1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2014-2016, Toradex AG
7 * Helpers for Freescale PMIC PF0100
12 #include <asm/arch/imx-regs.h>
13 #include <asm/arch/iomux.h>
14 #include <asm/arch/mx6-pins.h>
16 #include <asm/mach-imx/iomux-v3.h>
18 #include "pf0100_otp.inc"
21 /* define for PMIC register dump */
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)
30 unsigned pmic_init(void)
32 unsigned programmed = 0;
34 uchar devid, revid, val;
37 if (!((0 == i2c_set_bus_num(bus)) &&
38 (0 == i2c_probe(PFUZE100_I2C_ADDR)))) {
39 puts("i2c bus failed\n");
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");
47 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_REVID, 1, &revid, 1) < 0) {
48 puts("i2c pmic revid read failed\n");
51 printf("device id: 0x%.2x, revision id: 0x%.2x\n", devid, revid);
57 for (i = 0; i < 16; i++)
59 for (j = 0; j < 0x80; ) {
61 for (i = 0; i < 16; i++) {
62 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
67 printf("\nEXT Page 1");
69 val = PFUZE100_PAGE_REGISTER_PAGE1;
70 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1,
72 puts("i2c write failed\n");
76 for (j = 0x80; j < 0x100; ) {
78 for (i = 0; i < 16; i++) {
79 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
84 printf("\nEXT Page 2");
86 val = PFUZE100_PAGE_REGISTER_PAGE2;
87 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1,
89 puts("i2c write failed\n");
93 for (j = 0x80; j < 0x100; ) {
95 for (i = 0; i < 16; i++) {
96 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
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");
110 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR1, 1, &val, 1) < 0) {
111 puts("i2c fuse_por read failed\n");
114 if (val & PFUZE100_FUSE_POR_M)
117 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR2, 1, &val, 1) < 0) {
118 puts("i2c fuse_por read failed\n");
121 if (val & PFUZE100_FUSE_POR_M)
124 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR3, 1, &val, 1) < 0) {
125 puts("i2c fuse_por read failed\n");
128 if (val & PFUZE100_FUSE_POR_M)
131 switch (programmed) {
133 printf("PMIC: not programmed\n");
136 printf("PMIC: programmed\n");
139 printf("PMIC: undefined programming state\n");
146 #ifndef CONFIG_SPL_BUILD
147 static int pf0100_prog(void)
149 unsigned char bus = 1;
153 if (pmic_init() == 3) {
154 puts("PMIC already programmed, exiting\n");
155 return CMD_RET_FAILURE;
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);
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;
168 for (i = 0; i < ARRAY_SIZE(pmic_otp_prog); i++) {
169 switch (pmic_otp_prog[i].cmd) {
171 val = (unsigned char) (pmic_otp_prog[i].value & 0xff);
172 if (i2c_write(PFUZE100_I2C_ADDR, pmic_otp_prog[i].reg,
174 printf("i2c write failed, reg 0x%2x, value 0x%2x\n",
175 pmic_otp_prog[i].reg, val);
176 return CMD_RET_FAILURE;
180 udelay(pmic_otp_prog[i].value * 1000);
183 gpio_direction_output(PMIC_PROG_VOLTAGE,
184 pmic_otp_prog[i].value);
191 return CMD_RET_SUCCESS;
194 static int do_pf0100_prog(cmd_tbl_t *cmdtp, int flag, int argc,
198 puts("Programming PMIC OTP...");
200 if (ret == CMD_RET_SUCCESS)
208 pf0100_otp_prog, 1, 0, do_pf0100_prog,
209 "Program the OTP fuses on the PMIC PF0100",