1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * common reset-controller functions for B&R boards 4 * 5 * Copyright (C) 2019 Hannes Schmelzer <oe5hpm@oevsv.at> 6 * B&R Industrial Automation GmbH - http://www.br-automation.com/ * 7 */ 8#include <common.h> 9#include <env.h> 10#include <errno.h> 11#include <i2c.h> 12#include <dm/uclass.h> 13#include <linux/delay.h> 14#include "br_resetc.h" 15 16/* I2C Address of controller */ 17#define RSTCTRL_ADDR_PSOC 0x75 18#define RSTCTRL_ADDR_STM32 0x60 19 20#define BMODE_DEFAULTAR 0 21#define BMODE_SERVICE 2 22#define BMODE_RUN 4 23#define BMODE_PME 12 24#define BMODE_DIAG 15 25 26#define LCD_SETCURSOR(x, y) 27#define LCD_PUTS(x) 28 29static const char *bootmodeascii[16] = { 30 "BOOT", "reserved", "reserved", "reserved", 31 "RUN", "reserved", "reserved", "reserved", 32 "reserved", "reserved", "reserved", "reserved", 33 "PME", "reserved", "reserved", "DIAG", 34}; 35 36struct br_reset_t { 37 struct udevice *i2cdev; 38 u8 is_psoc; 39}; 40 41static struct br_reset_t resetc; 42 43__weak int board_boot_key(void) 44{ 45 return 0; 46} 47 48__weak void board_boot_led(unsigned int on) 49{ 50} 51 52static int resetc_init(void) 53{ 54 struct udevice *i2cbus; 55 int rc; 56 57 rc = uclass_get_device_by_seq(UCLASS_I2C, 0, &i2cbus); 58 if (rc) { 59 printf("Cannot find I2C bus #0!\n"); 60 return -1; 61 } 62 63 resetc.is_psoc = 1; 64 rc = dm_i2c_probe(i2cbus, 65 RSTCTRL_ADDR_PSOC, 0, &resetc.i2cdev); 66 if (rc) { 67 resetc.is_psoc = 0; 68 rc = dm_i2c_probe(i2cbus, 69 RSTCTRL_ADDR_STM32, 0, &resetc.i2cdev); 70 } 71 72 if (rc) 73 printf("Warning: cannot probe BuR resetcontroller!\n"); 74 75 return rc; 76} 77 78int br_resetc_regget(u8 reg, u8 *dst) 79{ 80 int rc = 0; 81 82 if (!resetc.i2cdev) 83 rc = resetc_init(); 84 85 if (rc != 0) 86 return rc; 87 88 return dm_i2c_read(resetc.i2cdev, reg, dst, 1); 89} 90 91int br_resetc_regset(u8 reg, u8 val) 92{ 93 int rc = 0; 94 u16 regw = (val << 8) | val; 95 96 if (!resetc.i2cdev) 97 rc = resetc_init(); 98 99 if (rc != 0) 100 return rc; 101 102 if (resetc.is_psoc) 103 return dm_i2c_write(resetc.i2cdev, reg, (u8 *)®w, 2); 104 105 return dm_i2c_write(resetc.i2cdev, reg, (u8 *)®w, 1); 106} 107 108int br_resetc_bmode(void) 109{ 110 int rc = 0; 111 u16 regw; 112 u8 regb, scr; 113 int cnt; 114 unsigned int bmode = 0; 115 116 if (!resetc.i2cdev) 117 rc = resetc_init(); 118 119 if (rc != 0) 120 return rc; 121 122 rc = dm_i2c_read(resetc.i2cdev, RSTCTRL_ENHSTATUS, ®b, 1); 123 if (rc != 0) { 124 printf("WARN: cannot read ENHSTATUS from resetcontroller!\n"); 125 return -1; 126 } 127 128 rc = dm_i2c_read(resetc.i2cdev, RSTCTRL_SCRATCHREG0, &scr, 1); 129 if (rc != 0) { 130 printf("WARN: cannot read SCRATCHREG from resetcontroller!\n"); 131 return -1; 132 } 133 134 board_boot_led(1); 135 136 /* special bootmode from resetcontroller */ 137 if (regb & 0x4) { 138 bmode = BMODE_DIAG; 139 } else if (regb & 0x8) { 140 bmode = BMODE_DEFAULTAR; 141 } else if (board_boot_key() != 0) { 142 cnt = 4; 143 do { 144 LCD_SETCURSOR(1, 8); 145 switch (cnt) { 146 case 4: 147 LCD_PUTS 148 ("release KEY to enter SERVICE-mode. "); 149 break; 150 case 3: 151 LCD_PUTS 152 ("release KEY to enter DIAGNOSE-mode. "); 153 break; 154 case 2: 155 LCD_PUTS 156 ("release KEY to enter BOOT-mode. "); 157 break; 158 } 159 mdelay(1000); 160 cnt--; 161 if (board_boot_key() == 0) 162 break; 163 } while (cnt); 164 165 switch (cnt) { 166 case 0: 167 bmode = BMODE_PME; 168 break; 169 case 1: 170 bmode = BMODE_DEFAULTAR; 171 break; 172 case 2: 173 bmode = BMODE_DIAG; 174 break; 175 case 3: 176 bmode = BMODE_SERVICE; 177 break; 178 } 179 } else if ((regb & 0x1) || scr == 0xCC) { 180 bmode = BMODE_PME; 181 } else { 182 bmode = BMODE_RUN; 183 } 184 185 LCD_SETCURSOR(1, 8); 186 187 switch (bmode) { 188 case BMODE_PME: 189 LCD_PUTS("entering PME-Mode (netscript). "); 190 regw = 0x0C0C; 191 break; 192 case BMODE_DEFAULTAR: 193 LCD_PUTS("entering BOOT-mode. "); 194 regw = 0x0000; 195 break; 196 case BMODE_DIAG: 197 LCD_PUTS("entering DIAGNOSE-mode. "); 198 regw = 0x0F0F; 199 break; 200 case BMODE_SERVICE: 201 LCD_PUTS("entering SERVICE mode. "); 202 regw = 0xB4B4; 203 break; 204 case BMODE_RUN: 205 LCD_PUTS("loading OS... "); 206 regw = 0x0404; 207 break; 208 } 209 210 board_boot_led(0); 211 212 if (resetc.is_psoc) 213 rc = dm_i2c_write(resetc.i2cdev, RSTCTRL_SCRATCHREG0, 214 (u8 *)®w, 2); 215 else 216 rc = dm_i2c_write(resetc.i2cdev, RSTCTRL_SCRATCHREG0, 217 (u8 *)®w, 1); 218 219 if (rc != 0) 220 printf("WARN: cannot write into resetcontroller!\n"); 221 222 if (resetc.is_psoc) 223 printf("Reset: PSOC controller\n"); 224 else 225 printf("Reset: STM32 controller\n"); 226 227 printf("Mode: %s\n", bootmodeascii[regw & 0x0F]); 228 env_set_ulong("b_mode", regw & 0x0F); 229 230 return rc; 231} 232