common: Drop linux/delay.h from common header
[oweals/u-boot.git] / board / gateworks / gw_ventana / gsc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2013 Gateworks Corporation
4  *
5  * Author: Tim Harvey <tharvey@gateworks.com>
6  */
7
8 #include <common.h>
9 #include <command.h>
10 #include <log.h>
11 #include <linux/delay.h>
12 #include <linux/errno.h>
13 #include <common.h>
14 #include <i2c.h>
15 #include <linux/ctype.h>
16
17 #include "ventana_eeprom.h"
18 #include "gsc.h"
19
20 /*
21  * The Gateworks System Controller will fail to ACK a master transaction if
22  * it is busy, which can occur during its 1HZ timer tick while reading ADC's.
23  * When this does occur, it will never be busy long enough to fail more than
24  * 2 back-to-back transfers.  Thus we wrap i2c_read and i2c_write with
25  * 3 retries.
26  */
27 int gsc_i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
28 {
29         int retry = 3;
30         int n = 0;
31         int ret;
32
33         while (n++ < retry) {
34                 ret = i2c_read(chip, addr, alen, buf, len);
35                 if (!ret)
36                         break;
37                 debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
38                       n, ret);
39                 if (ret != -ENODEV)
40                         break;
41                 mdelay(10);
42         }
43         return ret;
44 }
45
46 int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
47 {
48         int retry = 3;
49         int n = 0;
50         int ret;
51
52         while (n++ < retry) {
53                 ret = i2c_write(chip, addr, alen, buf, len);
54                 if (!ret)
55                         break;
56                 debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
57                       n, ret);
58                 if (ret != -ENODEV)
59                         break;
60                 mdelay(10);
61         }
62         mdelay(100);
63         return ret;
64 }
65
66 static void read_hwmon(const char *name, uint reg, uint size)
67 {
68         unsigned char buf[3];
69         uint ui;
70
71         printf("%-8s:", name);
72         memset(buf, 0, sizeof(buf));
73         if (gsc_i2c_read(GSC_HWMON_ADDR, reg, 1, buf, size)) {
74                 puts("fRD\n");
75         } else {
76                 ui = buf[0] | (buf[1]<<8) | (buf[2]<<16);
77                 if (size == 2 && ui > 0x8000)
78                         ui -= 0xffff;
79                 if (ui == 0xffffff)
80                         puts("invalid\n");
81                 else
82                         printf("%d\n", ui);
83         }
84 }
85
86 int gsc_info(int verbose)
87 {
88         unsigned char buf[16];
89
90         i2c_set_bus_num(0);
91         if (gsc_i2c_read(GSC_SC_ADDR, 0, 1, buf, 16))
92                 return CMD_RET_FAILURE;
93
94         printf("GSC:   v%d", buf[GSC_SC_FWVER]);
95         printf(" 0x%04x", buf[GSC_SC_FWCRC] | buf[GSC_SC_FWCRC+1]<<8);
96         printf(" WDT:%sabled", (buf[GSC_SC_CTRL1] & (1<<GSC_SC_CTRL1_WDEN))
97                 ? "en" : "dis");
98         if (buf[GSC_SC_STATUS] & (1 << GSC_SC_IRQ_WATCHDOG)) {
99                 buf[GSC_SC_STATUS] &= ~(1 << GSC_SC_IRQ_WATCHDOG);
100                 puts(" WDT_RESET");
101                 gsc_i2c_write(GSC_SC_ADDR, GSC_SC_STATUS, 1,
102                               &buf[GSC_SC_STATUS], 1);
103         }
104         if (!gsc_i2c_read(GSC_HWMON_ADDR, GSC_HWMON_TEMP, 1, buf, 2)) {
105                 int ui = buf[0] | buf[1]<<8;
106                 if (ui > 0x8000)
107                         ui -= 0xffff;
108                 printf(" board temp at %dC", ui / 10);
109         }
110         puts("\n");
111         if (!verbose)
112                 return CMD_RET_SUCCESS;
113
114         read_hwmon("Temp",     GSC_HWMON_TEMP, 2);
115         read_hwmon("VIN",      GSC_HWMON_VIN, 3);
116         read_hwmon("VBATT",    GSC_HWMON_VBATT, 3);
117         read_hwmon("VDD_3P3",  GSC_HWMON_VDD_3P3, 3);
118         read_hwmon("VDD_ARM",  GSC_HWMON_VDD_CORE, 3);
119         read_hwmon("VDD_SOC",  GSC_HWMON_VDD_SOC, 3);
120         read_hwmon("VDD_HIGH", GSC_HWMON_VDD_HIGH, 3);
121         read_hwmon("VDD_DDR",  GSC_HWMON_VDD_DDR, 3);
122         read_hwmon("VDD_5P0",  GSC_HWMON_VDD_5P0, 3);
123         if (strncasecmp((const char*) ventana_info.model, "GW553", 5))
124                 read_hwmon("VDD_2P5",  GSC_HWMON_VDD_2P5, 3);
125         read_hwmon("VDD_1P8",  GSC_HWMON_VDD_1P8, 3);
126         read_hwmon("VDD_IO2",  GSC_HWMON_VDD_IO2, 3);
127         switch (ventana_info.model[3]) {
128         case '1': /* GW51xx */
129                 read_hwmon("VDD_IO3",  GSC_HWMON_VDD_IO4, 3); /* -C rev */
130                 break;
131         case '2': /* GW52xx */
132                 break;
133         case '3': /* GW53xx */
134                 read_hwmon("VDD_IO4",  GSC_HWMON_VDD_IO4, 3); /* -C rev */
135                 read_hwmon("VDD_GPS",  GSC_HWMON_VDD_IO3, 3);
136                 break;
137         case '4': /* GW54xx */
138                 read_hwmon("VDD_IO3",  GSC_HWMON_VDD_IO4, 3); /* -C rev */
139                 read_hwmon("VDD_GPS",  GSC_HWMON_VDD_IO3, 3);
140                 break;
141         case '5': /* GW55xx */
142                 break;
143         case '6': /* GW560x */
144                 read_hwmon("VDD_IO4",  GSC_HWMON_VDD_IO4, 3);
145                 read_hwmon("VDD_GPS",  GSC_HWMON_VDD_IO3, 3);
146                 break;
147         case '9': /* GW590x */
148                 read_hwmon("AMONBMON",  GSC_HWMON_VDD_IO3, 3);
149                 read_hwmon("BAT_VOLT",  GSC_HWMON_VDD_EXT, 3);
150                 read_hwmon("BAT_TEMP",  GSC_HWMON_VDD_IO4, 2);
151         }
152         return 0;
153 }
154
155 /*
156  *  The Gateworks System Controller implements a boot
157  *  watchdog (always enabled) as a workaround for IMX6 boot related
158  *  errata such as:
159  *    ERR005768 - no fix scheduled
160  *    ERR006282 - fixed in silicon r1.2
161  *    ERR007117 - fixed in silicon r1.3
162  *    ERR007220 - fixed in silicon r1.3
163  *    ERR007926 - no fix scheduled
164  *  see http://cache.freescale.com/files/32bit/doc/errata/IMX6DQCE.pdf
165  *
166  * Disable the boot watchdog
167  */
168 int gsc_boot_wd_disable(void)
169 {
170         u8 reg;
171
172         i2c_set_bus_num(CONFIG_I2C_GSC);
173         if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1)) {
174                 reg |= (1 << GSC_SC_CTRL1_WDDIS);
175                 if (!gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
176                         return 0;
177         }
178         puts("Error: could not disable GSC Watchdog\n");
179         return 1;
180 }
181
182 #if defined(CONFIG_CMD_GSC) && !defined(CONFIG_SPL_BUILD)
183 static int do_gsc_sleep(struct cmd_tbl *cmdtp, int flag, int argc,
184                         char *const argv[])
185 {
186         unsigned char reg;
187         unsigned long secs = 0;
188
189         if (argc < 2)
190                 return CMD_RET_USAGE;
191
192         secs = simple_strtoul(argv[1], NULL, 10);
193         printf("GSC Sleeping for %ld seconds\n", secs);
194
195         i2c_set_bus_num(0);
196         reg = (secs >> 24) & 0xff;
197         if (gsc_i2c_write(GSC_SC_ADDR, 9, 1, &reg, 1))
198                 goto error;
199         reg = (secs >> 16) & 0xff;
200         if (gsc_i2c_write(GSC_SC_ADDR, 8, 1, &reg, 1))
201                 goto error;
202         reg = (secs >> 8) & 0xff;
203         if (gsc_i2c_write(GSC_SC_ADDR, 7, 1, &reg, 1))
204                 goto error;
205         reg = secs & 0xff;
206         if (gsc_i2c_write(GSC_SC_ADDR, 6, 1, &reg, 1))
207                 goto error;
208         if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
209                 goto error;
210         reg |= (1 << 2);
211         if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
212                 goto error;
213         reg &= ~(1 << 2);
214         reg |= 0x3;
215         if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
216                 goto error;
217
218         return CMD_RET_SUCCESS;
219
220 error:
221         printf("i2c error\n");
222         return CMD_RET_FAILURE;
223 }
224
225 static int do_gsc_wd(struct cmd_tbl *cmdtp, int flag, int argc,
226                      char *const argv[])
227 {
228         unsigned char reg;
229
230         if (argc < 2)
231                 return CMD_RET_USAGE;
232
233         if (strcasecmp(argv[1], "enable") == 0) {
234                 int timeout = 0;
235
236                 if (argc > 2)
237                         timeout = simple_strtoul(argv[2], NULL, 10);
238                 i2c_set_bus_num(0);
239                 if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
240                         return CMD_RET_FAILURE;
241                 reg &= ~((1 << GSC_SC_CTRL1_WDEN) | (1 << GSC_SC_CTRL1_WDTIME));
242                 if (timeout == 60)
243                         reg |= (1 << GSC_SC_CTRL1_WDTIME);
244                 else
245                         timeout = 30;
246                 reg |= (1 << GSC_SC_CTRL1_WDEN);
247                 if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
248                         return CMD_RET_FAILURE;
249                 printf("GSC Watchdog enabled with timeout=%d seconds\n",
250                        timeout);
251         } else if (strcasecmp(argv[1], "disable") == 0) {
252                 i2c_set_bus_num(0);
253                 if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
254                         return CMD_RET_FAILURE;
255                 reg &= ~((1 << GSC_SC_CTRL1_WDEN) | (1 << GSC_SC_CTRL1_WDTIME));
256                 if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
257                         return CMD_RET_FAILURE;
258                 printf("GSC Watchdog disabled\n");
259         } else {
260                 return CMD_RET_USAGE;
261         }
262         return CMD_RET_SUCCESS;
263 }
264
265 static int do_gsc(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
266 {
267         if (argc < 2)
268                 return gsc_info(1);
269
270         if (strcasecmp(argv[1], "wd") == 0)
271                 return do_gsc_wd(cmdtp, flag, --argc, ++argv);
272         else if (strcasecmp(argv[1], "sleep") == 0)
273                 return do_gsc_sleep(cmdtp, flag, --argc, ++argv);
274
275         return CMD_RET_USAGE;
276 }
277
278 U_BOOT_CMD(
279         gsc, 4, 1, do_gsc, "GSC configuration",
280         "[wd enable [30|60]]|[wd disable]|[sleep <secs>]\n"
281         );
282
283 #endif /* CONFIG_CMD_GSC */