• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2014-2019, Toradex AG
4  */
5 
6 /*
7  * Helpers for Freescale PMIC PF0100
8 */
9 
10 #include <common.h>
11 #include <i2c.h>
12 #include <asm/arch/imx-regs.h>
13 #include <asm/arch/iomux.h>
14 #include <asm/arch/mx6-pins.h>
15 #include <asm/gpio.h>
16 #include <asm/mach-imx/iomux-v3.h>
17 
18 #include "pf0100_otp.inc"
19 #include "pf0100.h"
20 
21 /* define for PMIC register dump */
22 /*#define DEBUG */
23 
24 #define WARNBAR "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
25 
26 /* use GPIO: EXT_IO1 to switch on VPGM, ON: 1 */
27 static __maybe_unused iomux_v3_cfg_t const pmic_prog_pads[] = {
28 	MX6_PAD_NANDF_D3__GPIO2_IO03 | MUX_PAD_CTRL(NO_PAD_CTRL),
29 #	define PMIC_PROG_VOLTAGE IMX_GPIO_NR(2, 3)
30 };
31 
pmic_init(void)32 unsigned pmic_init(void)
33 {
34 	int rc;
35 	struct udevice *dev = NULL;
36 	unsigned programmed = 0;
37 	uchar bus = 1;
38 	uchar devid, revid, val;
39 
40 	puts("PMIC:  ");
41 	rc = i2c_get_chip_for_busnum(bus, PFUZE100_I2C_ADDR, 1, &dev);
42 	if (rc) {
43 		printf("failed to get device for PMIC at address 0x%x\n",
44 		       PFUZE100_I2C_ADDR);
45 		return 0;
46 	}
47 
48 	/* check for errors in PMIC fuses */
49 	if (dm_i2c_read(dev, PFUZE100_INTSTAT3, &val, 1) < 0) {
50 		puts("i2c pmic INTSTAT3 register read failed\n");
51 		return 0;
52 	}
53 	if (val & PFUZE100_BIT_OTP_ECCI) {
54 		puts("\n" WARNBAR);
55 		puts("WARNING: ecc errors found in pmic fuse banks\n");
56 		puts(WARNBAR);
57 	}
58 	if (dm_i2c_read(dev, PFUZE100_OTP_ECC_SE1, &val, 1) < 0) {
59 		puts("i2c pmic ECC_SE1 register read failed\n");
60 		return 0;
61 	}
62 	if (val & PFUZE100_BITS_ECC_SE1) {
63 		puts(WARNBAR);
64 		puts("WARNING: ecc has made bit corrections in banks 1 to 5\n");
65 		puts(WARNBAR);
66 	}
67 	if (dm_i2c_read(dev, PFUZE100_OTP_ECC_SE2, &val, 1) < 0) {
68 		puts("i2c pmic ECC_SE2 register read failed\n");
69 		return 0;
70 	}
71 	if (val & PFUZE100_BITS_ECC_SE2) {
72 		puts(WARNBAR);
73 		puts("WARNING: ecc has made bit corrections in banks 6 to 10\n"
74 		    );
75 		puts(WARNBAR);
76 	}
77 	if (dm_i2c_read(dev, PFUZE100_OTP_ECC_DE1, &val, 1) < 0) {
78 		puts("i2c pmic ECC_DE register read failed\n");
79 		return 0;
80 	}
81 	if (val & PFUZE100_BITS_ECC_DE1) {
82 		puts(WARNBAR);
83 		puts("ERROR: banks 1 to 5 have uncorrectable bits\n");
84 		puts(WARNBAR);
85 	}
86 	if (dm_i2c_read(dev, PFUZE100_OTP_ECC_DE2, &val, 1) < 0) {
87 		puts("i2c pmic ECC_DE register read failed\n");
88 		return 0;
89 	}
90 	if (val & PFUZE100_BITS_ECC_DE2) {
91 		puts(WARNBAR);
92 		puts("ERROR: banks 6 to 10 have uncorrectable bits\n");
93 		puts(WARNBAR);
94 	}
95 
96 	/* get device ident */
97 	if (dm_i2c_read(dev, PFUZE100_DEVICEID, &devid, 1) < 0) {
98 		puts("i2c pmic devid read failed\n");
99 		return 0;
100 	}
101 	if (dm_i2c_read(dev, PFUZE100_REVID, &revid, 1) < 0) {
102 		puts("i2c pmic revid read failed\n");
103 		return 0;
104 	}
105 	printf("device id: 0x%.2x, revision id: 0x%.2x, ", devid, revid);
106 
107 	/* get device programmed state */
108 	val = PFUZE100_PAGE_REGISTER_PAGE1;
109 	if (dm_i2c_write(dev, PFUZE100_PAGE_REGISTER, &val, 1)) {
110 		puts("i2c write failed\n");
111 		return 0;
112 	}
113 	if (dm_i2c_read(dev, PFUZE100_FUSE_POR1, &val, 1) < 0) {
114 		puts("i2c fuse_por read failed\n");
115 		return 0;
116 	}
117 	if (val & PFUZE100_FUSE_POR_M)
118 		programmed++;
119 
120 	if (dm_i2c_read(dev, PFUZE100_FUSE_POR2, &val, 1) < 0) {
121 		puts("i2c fuse_por read failed\n");
122 		return programmed;
123 	}
124 	if (val & PFUZE100_FUSE_POR_M)
125 		programmed++;
126 
127 	if (dm_i2c_read(dev, PFUZE100_FUSE_POR3, &val, 1) < 0) {
128 		puts("i2c fuse_por read failed\n");
129 		return programmed;
130 	}
131 	if (val & PFUZE100_FUSE_POR_M)
132 		programmed++;
133 
134 	switch (programmed) {
135 	case 0:
136 		puts("not programmed\n");
137 		break;
138 	case 3:
139 		puts("programmed\n");
140 		break;
141 	default:
142 		puts("undefined programming state\n");
143 		break;
144 	}
145 
146 #ifdef DEBUG
147 	{
148 		unsigned int i, j;
149 
150 		for (i = 0; i < 16; i++)
151 			printf("\t%x", i);
152 		for (j = 0; j < 0x80; ) {
153 			printf("\n%2x", j);
154 			for (i = 0; i < 16; i++) {
155 				dm_i2c_read(dev, j + i, &val, 1);
156 				printf("\t%2x", val);
157 			}
158 			j += 0x10;
159 		}
160 		printf("\nEXT Page 1");
161 
162 		val = PFUZE100_PAGE_REGISTER_PAGE1;
163 		if (dm_i2c_write(dev, PFUZE100_PAGE_REGISTER, &val, 1)) {
164 			puts("i2c write failed\n");
165 			return 0;
166 		}
167 
168 		for (j = 0x80; j < 0x100; ) {
169 			printf("\n%2x", j);
170 			for (i = 0; i < 16; i++) {
171 				dm_i2c_read(dev, j + i, &val, 1);
172 				printf("\t%2x", val);
173 			}
174 			j += 0x10;
175 		}
176 		printf("\nEXT Page 2");
177 
178 		val = PFUZE100_PAGE_REGISTER_PAGE2;
179 		if (dm_i2c_write(dev, PFUZE100_PAGE_REGISTER, &val, 1)) {
180 			puts("i2c write failed\n");
181 			return 0;
182 		}
183 
184 		for (j = 0x80; j < 0x100; ) {
185 			printf("\n%2x", j);
186 			for (i = 0; i < 16; i++) {
187 				dm_i2c_read(dev, j + i, &val, 1);
188 				printf("\t%2x", val);
189 			}
190 			j += 0x10;
191 		}
192 		printf("\n");
193 	}
194 #endif /* DEBUG */
195 
196 	return programmed;
197 }
198 
199 #ifndef CONFIG_SPL_BUILD
pf0100_prog(void)200 static int pf0100_prog(void)
201 {
202 	int rc;
203 	struct udevice *dev = NULL;
204 	unsigned char bus = 1;
205 	unsigned char val;
206 	unsigned int i;
207 
208 	if (pmic_init() == 3) {
209 		puts("PMIC already programmed, exiting\n");
210 		return CMD_RET_FAILURE;
211 	}
212 	/* set up gpio to manipulate vprog, initially off */
213 	imx_iomux_v3_setup_multiple_pads(pmic_prog_pads,
214 					 ARRAY_SIZE(pmic_prog_pads));
215 	gpio_direction_output(PMIC_PROG_VOLTAGE, 0);
216 
217 	rc = i2c_get_chip_for_busnum(bus, PFUZE100_I2C_ADDR, 1, &dev);
218 	if (rc) {
219 		printf("failed to get device for PMIC at address 0x%x\n",
220 		       PFUZE100_I2C_ADDR);
221 		return CMD_RET_FAILURE;
222 	}
223 
224 	for (i = 0; i < ARRAY_SIZE(pmic_otp_prog); i++) {
225 		switch (pmic_otp_prog[i].cmd) {
226 		case pmic_i2c:
227 			val = (unsigned char) (pmic_otp_prog[i].value & 0xff);
228 			if (dm_i2c_write(dev, pmic_otp_prog[i].reg, &val, 1)) {
229 				printf("i2c write failed, reg 0x%2x, value 0x%2x\n",
230 				       pmic_otp_prog[i].reg, val);
231 				return CMD_RET_FAILURE;
232 			}
233 			break;
234 		case pmic_delay:
235 			udelay(pmic_otp_prog[i].value * 1000);
236 			break;
237 		case pmic_vpgm:
238 			gpio_direction_output(PMIC_PROG_VOLTAGE,
239 					      pmic_otp_prog[i].value);
240 			break;
241 		case pmic_pwr:
242 			/* TODO */
243 			break;
244 		}
245 	}
246 	return CMD_RET_SUCCESS;
247 }
248 
do_pf0100_prog(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])249 static int do_pf0100_prog(cmd_tbl_t *cmdtp, int flag, int argc,
250 		char * const argv[])
251 {
252 	int ret;
253 	puts("Programming PMIC OTP...");
254 	ret = pf0100_prog();
255 	if (ret == CMD_RET_SUCCESS)
256 		puts("done.\n");
257 	else
258 		puts("failed.\n");
259 	return ret;
260 }
261 
262 U_BOOT_CMD(
263 	pf0100_otp_prog, 1, 0, do_pf0100_prog,
264 	"Program the OTP fuses on the PMIC PF0100",
265 	""
266 );
267 #endif /* CONFIG_SPL_BUILD */
268