From f4b9f0bdbacec5da0e54f486e960fdd2da0f5c0b Mon Sep 17 00:00:00 2001 From: Hannes Schmelzer Date: Wed, 10 Apr 2019 14:13:14 +0200 Subject: [PATCH] board/BuR/common: add br resetcontoller implementation On many B&R boards we have a reset-controller, responsible for very early board-bringup (voltages, clocks, ...) and bootmode selection. To be ready for adding more B&R boards to source tree while avoiding duplicate code, we add the resetcontroller implementation to the common part of B&R boards. Signed-off-by: Hannes Schmelzer --- board/BuR/common/br_resetc.c | 234 +++++++++++++++++++++++++++++++++++ board/BuR/common/br_resetc.h | 26 ++++ 2 files changed, 260 insertions(+) create mode 100644 board/BuR/common/br_resetc.c create mode 100644 board/BuR/common/br_resetc.h diff --git a/board/BuR/common/br_resetc.c b/board/BuR/common/br_resetc.c new file mode 100644 index 0000000000..190f141091 --- /dev/null +++ b/board/BuR/common/br_resetc.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * common reset-controller functions for B&R boards + * + * Copyright (C) 2019 Hannes Schmelzer + * B&R Industrial Automation GmbH - http://www.br-automation.com/ * + */ +#include +#include +#include +#include +#include "br_resetc.h" + +/* I2C Address of controller */ +#define RSTCTRL_ADDR_PSOC 0x75 +#define RSTCTRL_ADDR_STM32 0x60 + +#define BMODE_DEFAULTAR 0 +#define BMODE_SERVICE 2 +#define BMODE_RUN 4 +#define BMODE_PME 12 +#define BMODE_DIAG 15 + +#ifdef CONFIG_LCD +#include +#define LCD_SETCURSOR(x, y) lcd_position_cursor(x, y) +#define LCD_PUTS(x) lcd_puts(x) +#else +#define LCD_SETCURSOR(x, y) +#define LCD_PUTS(x) +#endif /* CONFIG_LCD */ + +static const char *bootmodeascii[16] = { + "BOOT", "reserved", "reserved", "reserved", + "RUN", "reserved", "reserved", "reserved", + "reserved", "reserved", "reserved", "reserved", + "PME", "reserved", "reserved", "DIAG", +}; + +struct br_reset_t { + struct udevice *i2cdev; + u8 is_psoc; +}; + +static struct br_reset_t resetc; + +__weak int board_boot_key(void) +{ + return 0; +} + +__weak void board_boot_led(unsigned int on) +{ +} + +static int resetc_init(void) +{ + struct udevice *i2cbus; + int rc; + + rc = uclass_get_device_by_seq(UCLASS_I2C, 0, &i2cbus); + if (rc) { + printf("Cannot find I2C bus #0!\n"); + return -1; + } + + rc = dm_i2c_probe(i2cbus, + RSTCTRL_ADDR_PSOC, 0, &resetc.i2cdev); + if (rc) { + resetc.is_psoc = 0; + rc = dm_i2c_probe(i2cbus, + RSTCTRL_ADDR_STM32, 0, &resetc.i2cdev); + } + + if (rc) + printf("Warning: cannot probe BuR resetcontroller!\n"); + + return rc; +} + +int br_resetc_regget(u8 reg, u8 *dst) +{ + int rc = 0; + + if (!resetc.i2cdev) + rc = resetc_init(); + + if (rc != 0) + return rc; + + return dm_i2c_read(resetc.i2cdev, reg, dst, 1); +} + +int br_resetc_regset(u8 reg, u8 val) +{ + int rc = 0; + u16 regw = (val << 8) | val; + + if (!resetc.i2cdev) + rc = resetc_init(); + + if (rc != 0) + return rc; + + if (resetc.is_psoc) + return dm_i2c_write(resetc.i2cdev, reg, (u8 *)®w, 2); + + return dm_i2c_write(resetc.i2cdev, reg, (u8 *)®w, 1); +} + +int br_resetc_bmode(void) +{ + int rc = 0; + u16 regw; + u8 regb, scr; + int cnt; + unsigned int bmode = 0; + + if (!resetc.i2cdev) + rc = resetc_init(); + + if (rc != 0) + return rc; + + rc = dm_i2c_read(resetc.i2cdev, RSTCTRL_ENHSTATUS, ®b, 1); + if (rc != 0) { + printf("WARN: cannot read ENHSTATUS from resetcontroller!\n"); + return -1; + } + + rc = dm_i2c_read(resetc.i2cdev, RSTCTRL_SCRATCHREG0, &scr, 1); + if (rc != 0) { + printf("WARN: cannot read SCRATCHREG from resetcontroller!\n"); + return -1; + } + + board_boot_led(1); + + /* special bootmode from resetcontroller */ + if (regb & 0x4) { + bmode = BMODE_DIAG; + } else if (regb & 0x8) { + bmode = BMODE_DEFAULTAR; + } else if (board_boot_key() != 0) { + cnt = 4; + do { + LCD_SETCURSOR(1, 8); + switch (cnt) { + case 4: + LCD_PUTS + ("release KEY to enter SERVICE-mode. "); + break; + case 3: + LCD_PUTS + ("release KEY to enter DIAGNOSE-mode. "); + break; + case 2: + LCD_PUTS + ("release KEY to enter BOOT-mode. "); + break; + } + mdelay(1000); + cnt--; + if (board_boot_key() == 0) + break; + } while (cnt); + + switch (cnt) { + case 0: + bmode = BMODE_PME; + break; + case 1: + bmode = BMODE_DEFAULTAR; + break; + case 2: + bmode = BMODE_DIAG; + break; + case 3: + bmode = BMODE_SERVICE; + break; + } + } else if ((regb & 0x1) || scr == 0xCC) { + bmode = BMODE_PME; + } else { + bmode = BMODE_RUN; + } + + LCD_SETCURSOR(1, 8); + + switch (bmode) { + case BMODE_PME: + LCD_PUTS("entering PME-Mode (netscript). "); + regw = 0x0C0C; + break; + case BMODE_DEFAULTAR: + LCD_PUTS("entering BOOT-mode. "); + regw = 0x0000; + break; + case BMODE_DIAG: + LCD_PUTS("entering DIAGNOSE-mode. "); + regw = 0x0F0F; + break; + case BMODE_SERVICE: + LCD_PUTS("entering SERVICE mode. "); + regw = 0xB4B4; + break; + case BMODE_RUN: + LCD_PUTS("loading OS... "); + regw = 0x0404; + break; + } + + board_boot_led(0); + + if (resetc.is_psoc) + rc = dm_i2c_write(resetc.i2cdev, RSTCTRL_SCRATCHREG0, + (u8 *)®w, 2); + else + rc = dm_i2c_write(resetc.i2cdev, RSTCTRL_SCRATCHREG0, + (u8 *)®w, 1); + + if (rc != 0) + printf("WARN: cannot write into resetcontroller!\n"); + + if (resetc.is_psoc) + printf("Reset: PSOC controller\n"); + else + printf("Reset: STM32 controller\n"); + + printf("Mode: %s\n", bootmodeascii[regw & 0x0F]); + env_set_ulong("b_mode", regw & 0x0F); + + return rc; +} diff --git a/board/BuR/common/br_resetc.h b/board/BuR/common/br_resetc.h new file mode 100644 index 0000000000..ba0689bf20 --- /dev/null +++ b/board/BuR/common/br_resetc.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * common reset-controller functions for B&R boards + * + * Copyright (C) 2019 Hannes Schmelzer + * B&R Industrial Automation GmbH - http://www.br-automation.com/ * + */ +#ifndef __CONFIG_BRRESETC_H__ +#define __CONFIG_BRRESETC_H__ +#include + +int br_resetc_regget(u8 reg, u8 *dst); +int br_resetc_regset(u8 reg, u8 val); +int br_resetc_bmode(void); + +/* reset controller register defines */ +#define RSTCTRL_CTRLREG 0x01 +#define RSTCTRL_SCRATCHREG0 0x04 +#define RSTCTRL_ENHSTATUS 0x07 +#define RSTCTRL_SCRATCHREG1 0x08 +#define RSTCTRL_RSTCAUSE 0x00 +#define RSTCTRL_ERSTCAUSE 0x09 +#define RSTCTRL_SPECGPIO_I 0x0A +#define RSTCTRL_SPECGPIO_O 0x0B + +#endif /* __CONFIG_BRRESETC_H__ */ -- 2.25.1