gsc.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2013 Gateworks Corporation
  4. *
  5. * Author: Tim Harvey <tharvey@gateworks.com>
  6. */
  7. #include <common.h>
  8. #include <command.h>
  9. #include <log.h>
  10. #include <linux/delay.h>
  11. #include <linux/errno.h>
  12. #include <common.h>
  13. #include <i2c.h>
  14. #include <linux/ctype.h>
  15. #include <asm/arch/sys_proto.h>
  16. #include <asm/global_data.h>
  17. #include "ventana_eeprom.h"
  18. #include "gsc.h"
  19. DECLARE_GLOBAL_DATA_PTR;
  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. while (n++ < retry) {
  33. ret = i2c_read(chip, addr, alen, buf, len);
  34. if (!ret)
  35. break;
  36. debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
  37. n, ret);
  38. if (ret != -ENODEV)
  39. break;
  40. mdelay(10);
  41. }
  42. return ret;
  43. }
  44. int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
  45. {
  46. int retry = 3;
  47. int n = 0;
  48. int ret;
  49. while (n++ < retry) {
  50. ret = i2c_write(chip, addr, alen, buf, len);
  51. if (!ret)
  52. break;
  53. debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
  54. n, ret);
  55. if (ret != -ENODEV)
  56. break;
  57. mdelay(10);
  58. }
  59. mdelay(100);
  60. return ret;
  61. }
  62. int gsc_get_board_temp(void)
  63. {
  64. const void *fdt = gd->fdt_blob;
  65. int node, reg, mode, val;
  66. const char *label;
  67. u8 buf[2];
  68. int ret;
  69. node = fdt_node_offset_by_compatible(fdt, -1, "gw,gsc-adc");
  70. if (node <= 0)
  71. return node;
  72. i2c_set_bus_num(0);
  73. /* iterate over hwmon nodes */
  74. node = fdt_first_subnode(fdt, node);
  75. while (node > 0) {
  76. reg = fdtdec_get_int(fdt, node, "reg", -1);
  77. mode = fdtdec_get_int(fdt, node, "gw,mode", -1);
  78. label = fdt_stringlist_get(fdt, node, "label", 0, NULL);
  79. if ((reg == -1) || (mode == -1) || !label) {
  80. printf("invalid dt:%s\n", fdt_get_name(fdt, node, NULL));
  81. continue;
  82. }
  83. if ((mode != 0) || strcmp(label, "temp"))
  84. continue;
  85. memset(buf, 0, sizeof(buf));
  86. ret = gsc_i2c_read(GSC_HWMON_ADDR, reg, 1, buf, sizeof(buf));
  87. val = buf[0] | buf[1] << 8;
  88. if (val >= 0) {
  89. if (val > 0x8000)
  90. val -= 0xffff;
  91. return val;
  92. }
  93. node = fdt_next_subnode(fdt, node);
  94. }
  95. return 0;
  96. }
  97. /* display hardware monitor ADC channels */
  98. int gsc_hwmon(void)
  99. {
  100. const void *fdt = gd->fdt_blob;
  101. int node, reg, mode, len, val, offset;
  102. const char *label;
  103. u8 buf[2];
  104. int ret;
  105. node = fdt_node_offset_by_compatible(fdt, -1, "gw,gsc-adc");
  106. if (node <= 0)
  107. return node;
  108. i2c_set_bus_num(0);
  109. /* iterate over hwmon nodes */
  110. node = fdt_first_subnode(fdt, node);
  111. while (node > 0) {
  112. reg = fdtdec_get_int(fdt, node, "reg", -1);
  113. mode = fdtdec_get_int(fdt, node, "gw,mode", -1);
  114. offset = fdtdec_get_int(fdt, node, "gw,voltage-offset-microvolt", 0);
  115. label = fdt_stringlist_get(fdt, node, "label", 0, NULL);
  116. if ((reg == -1) || (mode == -1) || !label)
  117. printf("invalid dt:%s\n", fdt_get_name(fdt, node, NULL));
  118. memset(buf, 0, sizeof(buf));
  119. ret = gsc_i2c_read(GSC_HWMON_ADDR, reg, 1, buf, sizeof(buf));
  120. val = buf[0] | buf[1] << 8;
  121. if (val >= 0) {
  122. const u32 *div;
  123. int r[2];
  124. switch (mode) {
  125. case 0: /* temperature (C*10) */
  126. if (val > 0x8000)
  127. val -= 0xffff;
  128. printf("%-8s: %d.%ldC\n", label, val / 10, abs(val % 10));
  129. break;
  130. case 1: /* prescaled voltage */
  131. if (val != 0xffff)
  132. printf("%-8s: %d.%03dV\n", label, val / 1000, val % 1000);
  133. break;
  134. case 2: /* scaled based on ref volt and resolution */
  135. val *= 2500;
  136. val /= 1 << 12;
  137. /* apply pre-scaler voltage divider */
  138. div = fdt_getprop(fdt, node, "gw,voltage-divider-ohms", &len);
  139. if (div && (len == sizeof(uint32_t) * 2)) {
  140. r[0] = fdt32_to_cpu(div[0]);
  141. r[1] = fdt32_to_cpu(div[1]);
  142. if (r[0] && r[1]) {
  143. val *= (r[0] + r[1]);
  144. val /= r[1];
  145. }
  146. }
  147. /* adjust by offset */
  148. val += (offset / 1000);
  149. printf("%-8s: %d.%03dV\n", label, val / 1000, val % 1000);
  150. break;
  151. }
  152. }
  153. node = fdt_next_subnode(fdt, node);
  154. }
  155. return 0;
  156. }
  157. int gsc_info(int verbose)
  158. {
  159. unsigned char buf[16];
  160. i2c_set_bus_num(0);
  161. if (gsc_i2c_read(GSC_SC_ADDR, 0, 1, buf, 16))
  162. return CMD_RET_FAILURE;
  163. printf("GSC: v%d", buf[GSC_SC_FWVER]);
  164. printf(" 0x%04x", buf[GSC_SC_FWCRC] | buf[GSC_SC_FWCRC+1]<<8);
  165. printf(" WDT:%sabled", (buf[GSC_SC_CTRL1] & (1<<GSC_SC_CTRL1_WDEN))
  166. ? "en" : "dis");
  167. if (buf[GSC_SC_STATUS] & (1 << GSC_SC_IRQ_WATCHDOG)) {
  168. buf[GSC_SC_STATUS] &= ~(1 << GSC_SC_IRQ_WATCHDOG);
  169. puts(" WDT_RESET");
  170. gsc_i2c_write(GSC_SC_ADDR, GSC_SC_STATUS, 1,
  171. &buf[GSC_SC_STATUS], 1);
  172. }
  173. printf(" board temp at %dC", gsc_get_board_temp() / 10);
  174. puts("\n");
  175. if (!verbose)
  176. return CMD_RET_SUCCESS;
  177. gsc_hwmon();
  178. return 0;
  179. }
  180. /*
  181. * The Gateworks System Controller implements a boot
  182. * watchdog (always enabled) as a workaround for IMX6 boot related
  183. * errata such as:
  184. * ERR005768 - no fix scheduled
  185. * ERR006282 - fixed in silicon r1.2
  186. * ERR007117 - fixed in silicon r1.3
  187. * ERR007220 - fixed in silicon r1.3
  188. * ERR007926 - no fix scheduled
  189. * see http://cache.freescale.com/files/32bit/doc/errata/IMX6DQCE.pdf
  190. *
  191. * Disable the boot watchdog
  192. */
  193. int gsc_boot_wd_disable(void)
  194. {
  195. u8 reg;
  196. i2c_set_bus_num(CONFIG_I2C_GSC);
  197. if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1)) {
  198. reg |= (1 << GSC_SC_CTRL1_WDDIS);
  199. if (!gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
  200. return 0;
  201. }
  202. puts("Error: could not disable GSC Watchdog\n");
  203. return 1;
  204. }
  205. /* determine BOM revision from model */
  206. int get_bom_rev(const char *str)
  207. {
  208. int rev_bom = 0;
  209. int i;
  210. for (i = strlen(str) - 1; i > 0; i--) {
  211. if (str[i] == '-')
  212. break;
  213. if (str[i] >= '1' && str[i] <= '9') {
  214. rev_bom = str[i] - '0';
  215. break;
  216. }
  217. }
  218. return rev_bom;
  219. }
  220. /* determine PCB revision from model */
  221. char get_pcb_rev(const char *str)
  222. {
  223. char rev_pcb = 'A';
  224. int i;
  225. for (i = strlen(str) - 1; i > 0; i--) {
  226. if (str[i] == '-')
  227. break;
  228. if (str[i] >= 'A') {
  229. rev_pcb = str[i];
  230. break;
  231. }
  232. }
  233. return rev_pcb;
  234. }
  235. /*
  236. * get dt name based on model and detail level:
  237. */
  238. const char *gsc_get_dtb_name(int level, char *buf, int sz)
  239. {
  240. const char *model = (const char *)ventana_info.model;
  241. const char *pre = is_mx6dq() ? "imx6q-" : "imx6dl-";
  242. int modelno, rev_pcb, rev_bom;
  243. /* a few board models are dt equivalents to other models */
  244. if (strncasecmp(model, "gw5906", 6) == 0)
  245. model = "gw552x-d";
  246. else if (strncasecmp(model, "gw5908", 6) == 0)
  247. model = "gw53xx-f";
  248. else if (strncasecmp(model, "gw5905", 6) == 0)
  249. model = "gw5904-a";
  250. modelno = ((model[2] - '0') * 1000)
  251. + ((model[3] - '0') * 100)
  252. + ((model[4] - '0') * 10)
  253. + (model[5] - '0');
  254. rev_pcb = tolower(get_pcb_rev(model));
  255. rev_bom = get_bom_rev(model);
  256. /* compare model/rev/bom in order of most specific to least */
  257. snprintf(buf, sz, "%s%04d", pre, modelno);
  258. switch (level) {
  259. case 0: /* full model first (ie gw5400-a1) */
  260. if (rev_bom) {
  261. snprintf(buf, sz, "%sgw%04d-%c%d", pre, modelno, rev_pcb, rev_bom);
  262. break;
  263. }
  264. fallthrough;
  265. case 1: /* don't care about bom rev (ie gw5400-a) */
  266. snprintf(buf, sz, "%sgw%04d-%c", pre, modelno, rev_pcb);
  267. break;
  268. case 2: /* don't care about the pcb rev (ie gw5400) */
  269. snprintf(buf, sz, "%sgw%04d", pre, modelno);
  270. break;
  271. case 3: /* look for generic model (ie gw540x) */
  272. snprintf(buf, sz, "%sgw%03dx", pre, modelno / 10);
  273. break;
  274. case 4: /* look for more generic model (ie gw54xx) */
  275. snprintf(buf, sz, "%sgw%02dxx", pre, modelno / 100);
  276. break;
  277. default: /* give up */
  278. return NULL;
  279. }
  280. return buf;
  281. }
  282. #if defined(CONFIG_CMD_GSC) && !defined(CONFIG_SPL_BUILD)
  283. static int do_gsc_sleep(struct cmd_tbl *cmdtp, int flag, int argc,
  284. char *const argv[])
  285. {
  286. unsigned char reg;
  287. unsigned long secs = 0;
  288. if (argc < 2)
  289. return CMD_RET_USAGE;
  290. secs = dectoul(argv[1], NULL);
  291. printf("GSC Sleeping for %ld seconds\n", secs);
  292. i2c_set_bus_num(0);
  293. reg = (secs >> 24) & 0xff;
  294. if (gsc_i2c_write(GSC_SC_ADDR, 9, 1, &reg, 1))
  295. goto error;
  296. reg = (secs >> 16) & 0xff;
  297. if (gsc_i2c_write(GSC_SC_ADDR, 8, 1, &reg, 1))
  298. goto error;
  299. reg = (secs >> 8) & 0xff;
  300. if (gsc_i2c_write(GSC_SC_ADDR, 7, 1, &reg, 1))
  301. goto error;
  302. reg = secs & 0xff;
  303. if (gsc_i2c_write(GSC_SC_ADDR, 6, 1, &reg, 1))
  304. goto error;
  305. if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
  306. goto error;
  307. reg |= (1 << 2);
  308. if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
  309. goto error;
  310. reg &= ~(1 << 2);
  311. reg |= 0x3;
  312. if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
  313. goto error;
  314. return CMD_RET_SUCCESS;
  315. error:
  316. printf("i2c error\n");
  317. return CMD_RET_FAILURE;
  318. }
  319. static int do_gsc_wd(struct cmd_tbl *cmdtp, int flag, int argc,
  320. char *const argv[])
  321. {
  322. unsigned char reg;
  323. if (argc < 2)
  324. return CMD_RET_USAGE;
  325. if (strcasecmp(argv[1], "enable") == 0) {
  326. int timeout = 0;
  327. if (argc > 2)
  328. timeout = dectoul(argv[2], NULL);
  329. i2c_set_bus_num(0);
  330. if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
  331. return CMD_RET_FAILURE;
  332. reg &= ~((1 << GSC_SC_CTRL1_WDEN) | (1 << GSC_SC_CTRL1_WDTIME));
  333. if (timeout == 60)
  334. reg |= (1 << GSC_SC_CTRL1_WDTIME);
  335. else
  336. timeout = 30;
  337. reg |= (1 << GSC_SC_CTRL1_WDEN);
  338. if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
  339. return CMD_RET_FAILURE;
  340. printf("GSC Watchdog enabled with timeout=%d seconds\n",
  341. timeout);
  342. } else if (strcasecmp(argv[1], "disable") == 0) {
  343. i2c_set_bus_num(0);
  344. if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
  345. return CMD_RET_FAILURE;
  346. reg &= ~((1 << GSC_SC_CTRL1_WDEN) | (1 << GSC_SC_CTRL1_WDTIME));
  347. if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
  348. return CMD_RET_FAILURE;
  349. printf("GSC Watchdog disabled\n");
  350. } else {
  351. return CMD_RET_USAGE;
  352. }
  353. return CMD_RET_SUCCESS;
  354. }
  355. static int do_gsc(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  356. {
  357. if (argc < 2)
  358. return gsc_info(1);
  359. if (strcasecmp(argv[1], "wd") == 0)
  360. return do_gsc_wd(cmdtp, flag, --argc, ++argv);
  361. else if (strcasecmp(argv[1], "sleep") == 0)
  362. return do_gsc_sleep(cmdtp, flag, --argc, ++argv);
  363. return CMD_RET_USAGE;
  364. }
  365. U_BOOT_CMD(
  366. gsc, 4, 1, do_gsc, "GSC configuration",
  367. "[wd enable [30|60]]|[wd disable]|[sleep <secs>]\n"
  368. );
  369. #endif /* CONFIG_CMD_GSC */