apalis_imx6: pf0100: reorder and cleanup message printing
[oweals/u-boot.git] / board / toradex / apalis_imx6 / pf0100.c
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 /* use Apalis GPIO1 to switch on VPGM, ON: 1 */
25 static __maybe_unused iomux_v3_cfg_t const pmic_prog_pads[] = {
26         MX6_PAD_NANDF_D4__GPIO2_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL),
27 #       define PMIC_PROG_VOLTAGE IMX_GPIO_NR(2, 4)
28 };
29
30 unsigned pmic_init(void)
31 {
32         int rc;
33         struct udevice *dev = NULL;
34         unsigned programmed = 0;
35         uchar bus = 1;
36         uchar devid, revid, val;
37
38         puts("PMIC:  ");
39         rc = i2c_get_chip_for_busnum(bus, PFUZE100_I2C_ADDR, 1, &dev);
40         if (rc) {
41                 printf("failed to get device for PMIC at address 0x%x\n",
42                        PFUZE100_I2C_ADDR);
43                 return 0;
44         }
45         /* get device ident */
46         if (dm_i2c_read(dev, PFUZE100_DEVICEID, &devid, 1) < 0) {
47                 puts("i2c pmic devid read failed\n");
48                 return 0;
49         }
50         if (dm_i2c_read(dev, PFUZE100_REVID, &revid, 1) < 0) {
51                 puts("i2c pmic revid read failed\n");
52                 return 0;
53         }
54         printf("device id: 0x%.2x, revision id: 0x%.2x, ", devid, revid);
55
56         /* get device programmed state */
57         val = PFUZE100_PAGE_REGISTER_PAGE1;
58         if (dm_i2c_write(dev, PFUZE100_PAGE_REGISTER, &val, 1)) {
59                 puts("i2c write failed\n");
60                 return 0;
61         }
62         if (dm_i2c_read(dev, PFUZE100_FUSE_POR1, &val, 1) < 0) {
63                 puts("i2c fuse_por read failed\n");
64                 return 0;
65         }
66         if (val & PFUZE100_FUSE_POR_M)
67                 programmed++;
68
69         if (dm_i2c_read(dev, PFUZE100_FUSE_POR2, &val, 1) < 0) {
70                 puts("i2c fuse_por read failed\n");
71                 return programmed;
72         }
73         if (val & PFUZE100_FUSE_POR_M)
74                 programmed++;
75
76         if (dm_i2c_read(dev, PFUZE100_FUSE_POR3, &val, 1) < 0) {
77                 puts("i2c fuse_por read failed\n");
78                 return programmed;
79         }
80         if (val & PFUZE100_FUSE_POR_M)
81                 programmed++;
82
83         switch (programmed) {
84         case 0:
85                 puts("not programmed\n");
86                 break;
87         case 3:
88                 puts("programmed\n");
89                 break;
90         default:
91                 puts("undefined programming state\n");
92                 break;
93         }
94
95         /* The following is needed during production */
96         if (programmed != 3) {
97                 /* set VGEN1 to 1.2V */
98                 val = PFUZE100_VGEN1_VAL;
99                 if (dm_i2c_write(dev, PFUZE100_VGEN1CTL, &val, 1)) {
100                         puts("i2c write failed\n");
101                         return programmed;
102                 }
103
104                 /* set SWBST to 5.0V */
105                 val = PFUZE100_SWBST_VAL;
106                 if (dm_i2c_write(dev, PFUZE100_SWBSTCTL, &val, 1))
107                         puts("i2c write failed\n");
108         }
109
110 #ifdef DEBUG
111         {
112                 unsigned int i, j;
113
114                 for (i = 0; i < 16; i++)
115                         printf("\t%x", i);
116                 for (j = 0; j < 0x80; ) {
117                         printf("\n%2x", j);
118                         for (i = 0; i < 16; i++) {
119                                 dm_i2c_read(dev, j + i, &val, 1);
120                                 printf("\t%2x", val);
121                         }
122                         j += 0x10;
123                 }
124                 printf("\nEXT Page 1");
125
126                 val = PFUZE100_PAGE_REGISTER_PAGE1;
127                 if (dm_i2c_write(dev, PFUZE100_PAGE_REGISTER, &val, 1)) {
128                         puts("i2c write failed\n");
129                         return 0;
130                 }
131
132                 for (j = 0x80; j < 0x100; ) {
133                         printf("\n%2x", j);
134                         for (i = 0; i < 16; i++) {
135                                 dm_i2c_read(dev, j + i, &val, 1);
136                                 printf("\t%2x", val);
137                         }
138                         j += 0x10;
139                 }
140                 printf("\nEXT Page 2");
141
142                 val = PFUZE100_PAGE_REGISTER_PAGE2;
143                 if (dm_i2c_write(dev, PFUZE100_PAGE_REGISTER, &val, 1)) {
144                         puts("i2c write failed\n");
145                         return 0;
146                 }
147
148                 for (j = 0x80; j < 0x100; ) {
149                         printf("\n%2x", j);
150                         for (i = 0; i < 16; i++) {
151                                 dm_i2c_read(dev, j + i, &val, 1);
152                                 printf("\t%2x", val);
153                         }
154                         j += 0x10;
155                 }
156                 printf("\n");
157         }
158 #endif /* DEBUG */
159
160         return programmed;
161 }
162
163 #ifndef CONFIG_SPL_BUILD
164 static int pf0100_prog(void)
165 {
166         int rc;
167         struct udevice *dev = NULL;
168         unsigned char bus = 1;
169         unsigned char val;
170         unsigned int i;
171
172         if (pmic_init() == 3) {
173                 puts("PMIC already programmed, exiting\n");
174                 return CMD_RET_FAILURE;
175         }
176         /* set up gpio to manipulate vprog, initially off */
177         imx_iomux_v3_setup_multiple_pads(pmic_prog_pads,
178                                          ARRAY_SIZE(pmic_prog_pads));
179         gpio_direction_output(PMIC_PROG_VOLTAGE, 0);
180
181         rc = i2c_get_chip_for_busnum(bus, PFUZE100_I2C_ADDR, 1, &dev);
182         if (rc) {
183                 printf("failed to get device for PMIC at address 0x%x\n",
184                        PFUZE100_I2C_ADDR);
185                 return CMD_RET_FAILURE;
186         }
187
188         for (i = 0; i < ARRAY_SIZE(pmic_otp_prog); i++) {
189                 switch (pmic_otp_prog[i].cmd) {
190                 case pmic_i2c:
191                         val = (unsigned char) (pmic_otp_prog[i].value & 0xff);
192                         if (dm_i2c_write(dev, pmic_otp_prog[i].reg, &val, 1)) {
193                                 printf("i2c write failed, reg 0x%2x, value 0x%2x\n",
194                                        pmic_otp_prog[i].reg, val);
195                                 return CMD_RET_FAILURE;
196                         }
197                         break;
198                 case pmic_delay:
199                         udelay(pmic_otp_prog[i].value * 1000);
200                         break;
201                 case pmic_vpgm:
202                         gpio_direction_output(PMIC_PROG_VOLTAGE,
203                                               pmic_otp_prog[i].value);
204                         break;
205                 case pmic_pwr:
206                         /* TODO */
207                         break;
208                 }
209         }
210         return CMD_RET_SUCCESS;
211 }
212
213 static int do_pf0100_prog(cmd_tbl_t *cmdtp, int flag, int argc,
214                 char * const argv[])
215 {
216         int ret;
217         puts("Programming PMIC OTP...");
218         ret = pf0100_prog();
219         if (ret == CMD_RET_SUCCESS)
220                 puts("done.\n");
221         else
222                 puts("failed.\n");
223         return ret;
224 }
225
226 U_BOOT_CMD(
227         pf0100_otp_prog, 1, 0, do_pf0100_prog,
228         "Program the OTP fuses on the PMIC PF0100",
229         ""
230 );
231 #endif /* CONFIG_SPL_BUILD */