board/BuR/common: add br resetcontoller implementation
authorHannes Schmelzer <hannes.schmelzer@br-automation.com>
Wed, 10 Apr 2019 12:13:14 +0000 (14:13 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 26 Apr 2019 21:51:51 +0000 (17:51 -0400)
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 <hannes.schmelzer@br-automation.com>
board/BuR/common/br_resetc.c [new file with mode: 0644]
board/BuR/common/br_resetc.h [new file with mode: 0644]

diff --git a/board/BuR/common/br_resetc.c b/board/BuR/common/br_resetc.c
new file mode 100644 (file)
index 0000000..190f141
--- /dev/null
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * common reset-controller functions for B&R boards
+ *
+ * Copyright (C) 2019 Hannes Schmelzer <oe5hpm@oevsv.at>
+ * B&R Industrial Automation GmbH - http://www.br-automation.com/ *
+ */
+#include <common.h>
+#include <errno.h>
+#include <i2c.h>
+#include <dm/uclass.h>
+#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 <lcd.h>
+#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 *)&regw, 2);
+
+       return dm_i2c_write(resetc.i2cdev, reg, (u8 *)&regw, 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, &regb, 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 *)&regw, 2);
+       else
+               rc = dm_i2c_write(resetc.i2cdev, RSTCTRL_SCRATCHREG0,
+                                 (u8 *)&regw, 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 (file)
index 0000000..ba0689b
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * common reset-controller functions for B&R boards
+ *
+ * Copyright (C) 2019 Hannes Schmelzer <oe5hpm@oevsv.at>
+ * B&R Industrial Automation GmbH - http://www.br-automation.com/ *
+ */
+#ifndef __CONFIG_BRRESETC_H__
+#define __CONFIG_BRRESETC_H__
+#include <common.h>
+
+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__ */