blob: 5006687fbf0d7800442b4df3aaa12aa85bf2b6ce [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>
Simon Glassdbd79542020-05-10 11:40:11 -060013#include <linux/delay.h>
Hannes Schmelzer44e37422019-04-10 14:13:14 +020014#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
Dario Binacchi90184bc2020-02-22 14:05:49 +010026#if CONFIG_IS_ENABLED(LCD) && !CONFIG_IS_ENABLED(DM_VIDEO)
Hannes Schmelzer44e37422019-04-10 14:13:14 +020027#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
35static 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
42struct br_reset_t {
43 struct udevice *i2cdev;
44 u8 is_psoc;
45};
46
47static struct br_reset_t resetc;
48
49__weak int board_boot_key(void)
50{
51 return 0;
52}
53
54__weak void board_boot_led(unsigned int on)
55{
56}
57
58static 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
Hannes Schmelzerdf381762019-05-10 11:22:00 +020069 resetc.is_psoc = 1;
Hannes Schmelzer44e37422019-04-10 14:13:14 +020070 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
84int 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
97int 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
114int 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}