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