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