]> Git Repo - u-boot.git/blob - board/toradex/colibri_imx6/pf0100.c
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot.git] / board / toradex / colibri_imx6 / pf0100.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2014-2016, 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 GPIO: EXT_IO1 to switch on VPGM, ON: 1 */
25 static __maybe_unused iomux_v3_cfg_t const pmic_prog_pads[] = {
26         MX6_PAD_NANDF_D3__GPIO2_IO03 | MUX_PAD_CTRL(NO_PAD_CTRL),
27 #       define PMIC_PROG_VOLTAGE IMX_GPIO_NR(2, 3)
28 };
29
30 unsigned pmic_init(void)
31 {
32         unsigned programmed = 0;
33         uchar bus = 1;
34         uchar devid, revid, val;
35
36         puts("PMIC: ");
37         if (!((0 == i2c_set_bus_num(bus)) &&
38               (0 == i2c_probe(PFUZE100_I2C_ADDR)))) {
39                 puts("i2c bus failed\n");
40                 return 0;
41         }
42         /* get device ident */
43         if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_DEVICEID, 1, &devid, 1) < 0) {
44                 puts("i2c pmic devid read failed\n");
45                 return 0;
46         }
47         if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_REVID, 1, &revid, 1) < 0) {
48                 puts("i2c pmic revid read failed\n");
49                 return 0;
50         }
51         printf("device id: 0x%.2x, revision id: 0x%.2x\n", devid, revid);
52
53 #ifdef DEBUG
54         {
55                 unsigned i, j;
56
57                 for (i = 0; i < 16; i++)
58                         printf("\t%x", i);
59                 for (j = 0; j < 0x80; ) {
60                         printf("\n%2x", j);
61                         for (i = 0; i < 16; i++) {
62                                 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
63                                 printf("\t%2x", val);
64                         }
65                         j += 0x10;
66                 }
67                 printf("\nEXT Page 1");
68
69                 val = PFUZE100_PAGE_REGISTER_PAGE1;
70                 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1,
71                               &val, 1)) {
72                         puts("i2c write failed\n");
73                         return 0;
74                 }
75
76                 for (j = 0x80; j < 0x100; ) {
77                         printf("\n%2x", j);
78                         for (i = 0; i < 16; i++) {
79                                 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
80                                 printf("\t%2x", val);
81                         }
82                         j += 0x10;
83                 }
84                 printf("\nEXT Page 2");
85
86                 val = PFUZE100_PAGE_REGISTER_PAGE2;
87                 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1,
88                               &val, 1)) {
89                         puts("i2c write failed\n");
90                         return 0;
91                 }
92
93                 for (j = 0x80; j < 0x100; ) {
94                         printf("\n%2x", j);
95                         for (i = 0; i < 16; i++) {
96                                 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
97                                 printf("\t%2x", val);
98                         }
99                         j += 0x10;
100                 }
101                 printf("\n");
102         }
103 #endif
104         /* get device programmed state */
105         val = PFUZE100_PAGE_REGISTER_PAGE1;
106         if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1, &val, 1)) {
107                 puts("i2c write failed\n");
108                 return 0;
109         }
110         if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR1, 1, &val, 1) < 0) {
111                 puts("i2c fuse_por read failed\n");
112                 return 0;
113         }
114         if (val & PFUZE100_FUSE_POR_M)
115                 programmed++;
116
117         if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR2, 1, &val, 1) < 0) {
118                 puts("i2c fuse_por read failed\n");
119                 return programmed;
120         }
121         if (val & PFUZE100_FUSE_POR_M)
122                 programmed++;
123
124         if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR3, 1, &val, 1) < 0) {
125                 puts("i2c fuse_por read failed\n");
126                 return programmed;
127         }
128         if (val & PFUZE100_FUSE_POR_M)
129                 programmed++;
130
131         switch (programmed) {
132         case 0:
133                 printf("PMIC: not programmed\n");
134                 break;
135         case 3:
136                 printf("PMIC: programmed\n");
137                 break;
138         default:
139                 printf("PMIC: undefined programming state\n");
140                 break;
141         }
142
143         return programmed;
144 }
145
146 #ifndef CONFIG_SPL_BUILD
147 static int pf0100_prog(void)
148 {
149         unsigned char bus = 1;
150         unsigned char val;
151         unsigned int i;
152
153         if (pmic_init() == 3) {
154                 puts("PMIC already programmed, exiting\n");
155                 return CMD_RET_FAILURE;
156         }
157         /* set up gpio to manipulate vprog, initially off */
158         imx_iomux_v3_setup_multiple_pads(pmic_prog_pads,
159                                          ARRAY_SIZE(pmic_prog_pads));
160         gpio_direction_output(PMIC_PROG_VOLTAGE, 0);
161
162         if (!((0 == i2c_set_bus_num(bus)) &&
163               (0 == i2c_probe(PFUZE100_I2C_ADDR)))) {
164                 puts("i2c bus failed\n");
165                 return CMD_RET_FAILURE;
166         }
167
168         for (i = 0; i < ARRAY_SIZE(pmic_otp_prog); i++) {
169                 switch (pmic_otp_prog[i].cmd) {
170                 case pmic_i2c:
171                         val = (unsigned char) (pmic_otp_prog[i].value & 0xff);
172                         if (i2c_write(PFUZE100_I2C_ADDR, pmic_otp_prog[i].reg,
173                                       1, &val, 1)) {
174                                 printf("i2c write failed, reg 0x%2x, value 0x%2x\n",
175                                        pmic_otp_prog[i].reg, val);
176                                 return CMD_RET_FAILURE;
177                         }
178                         break;
179                 case pmic_delay:
180                         udelay(pmic_otp_prog[i].value * 1000);
181                         break;
182                 case pmic_vpgm:
183                         gpio_direction_output(PMIC_PROG_VOLTAGE,
184                                               pmic_otp_prog[i].value);
185                         break;
186                 case pmic_pwr:
187                         /* TODO */
188                         break;
189                 }
190         }
191         return CMD_RET_SUCCESS;
192 }
193
194 static int do_pf0100_prog(cmd_tbl_t *cmdtp, int flag, int argc,
195                 char * const argv[])
196 {
197         int ret;
198         puts("Programming PMIC OTP...");
199         ret = pf0100_prog();
200         if (ret == CMD_RET_SUCCESS)
201                 puts("done.\n");
202         else
203                 puts("failed.\n");
204         return ret;
205 }
206
207 U_BOOT_CMD(
208         pf0100_otp_prog, 1, 0, do_pf0100_prog,
209         "Program the OTP fuses on the PMIC PF0100",
210         ""
211 );
212 #endif
This page took 0.03727 seconds and 4 git commands to generate.