|
@@ -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 *)®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;
|
|
|
+}
|