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