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 *)&regw, 2);
104
105	return dm_i2c_write(resetc.i2cdev, reg, (u8 *)&regw, 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, &regb, 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 *)&regw, 2);
215	else
216		rc = dm_i2c_write(resetc.i2cdev, RSTCTRL_SCRATCHREG0,
217				  (u8 *)&regw, 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