1 /* 2 * Copyright (C) 2014-2016, Toradex AG 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 /* 8 * Helpers for Freescale PMIC PF0100 9 */ 10 11 #include <common.h> 12 #include <i2c.h> 13 #include <linux/compiler.h> 14 #include <asm/arch/imx-regs.h> 15 #include <asm/arch/iomux.h> 16 #include <asm/arch/mx6-pins.h> 17 #include <asm/gpio.h> 18 #include <asm/mach-imx/iomux-v3.h> 19 20 #include "pf0100_otp.inc" 21 #include "pf0100.h" 22 23 /* define for PMIC register dump */ 24 /*#define DEBUG */ 25 26 /* use Apalis GPIO1 to switch on VPGM, ON: 1 */ 27 static __maybe_unused iomux_v3_cfg_t const pmic_prog_pads[] = { 28 MX6_PAD_NANDF_D4__GPIO2_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL), 29 # define PMIC_PROG_VOLTAGE IMX_GPIO_NR(2, 4) 30 }; 31 32 unsigned pmic_init(void) 33 { 34 unsigned programmed = 0; 35 uchar bus = 1; 36 uchar devid, revid, val; 37 38 puts("PMIC: "); 39 if (!((0 == i2c_set_bus_num(bus)) && 40 (0 == i2c_probe(PFUZE100_I2C_ADDR)))) { 41 puts("i2c bus failed\n"); 42 return 0; 43 } 44 /* get device ident */ 45 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_DEVICEID, 1, &devid, 1) < 0) { 46 puts("i2c pmic devid read failed\n"); 47 return 0; 48 } 49 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_REVID, 1, &revid, 1) < 0) { 50 puts("i2c pmic revid read failed\n"); 51 return 0; 52 } 53 printf("device id: 0x%.2x, revision id: 0x%.2x\n", devid, revid); 54 55 #ifdef DEBUG 56 { 57 unsigned i, j; 58 59 for (i = 0; i < 16; i++) 60 printf("\t%x", i); 61 for (j = 0; j < 0x80; ) { 62 printf("\n%2x", j); 63 for (i = 0; i < 16; i++) { 64 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1); 65 printf("\t%2x", val); 66 } 67 j += 0x10; 68 } 69 printf("\nEXT Page 1"); 70 71 val = PFUZE100_PAGE_REGISTER_PAGE1; 72 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1, 73 &val, 1)) { 74 puts("i2c write failed\n"); 75 return 0; 76 } 77 78 for (j = 0x80; j < 0x100; ) { 79 printf("\n%2x", j); 80 for (i = 0; i < 16; i++) { 81 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1); 82 printf("\t%2x", val); 83 } 84 j += 0x10; 85 } 86 printf("\nEXT Page 2"); 87 88 val = PFUZE100_PAGE_REGISTER_PAGE2; 89 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1, 90 &val, 1)) { 91 puts("i2c write failed\n"); 92 return 0; 93 } 94 95 for (j = 0x80; j < 0x100; ) { 96 printf("\n%2x", j); 97 for (i = 0; i < 16; i++) { 98 i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1); 99 printf("\t%2x", val); 100 } 101 j += 0x10; 102 } 103 printf("\n"); 104 } 105 #endif 106 /* get device programmed state */ 107 val = PFUZE100_PAGE_REGISTER_PAGE1; 108 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1, &val, 1)) { 109 puts("i2c write failed\n"); 110 return 0; 111 } 112 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR1, 1, &val, 1) < 0) { 113 puts("i2c fuse_por read failed\n"); 114 return 0; 115 } 116 if (val & PFUZE100_FUSE_POR_M) 117 programmed++; 118 119 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR2, 1, &val, 1) < 0) { 120 puts("i2c fuse_por read failed\n"); 121 return programmed; 122 } 123 if (val & PFUZE100_FUSE_POR_M) 124 programmed++; 125 126 if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR3, 1, &val, 1) < 0) { 127 puts("i2c fuse_por read failed\n"); 128 return programmed; 129 } 130 if (val & PFUZE100_FUSE_POR_M) 131 programmed++; 132 133 switch (programmed) { 134 case 0: 135 printf("PMIC: not programmed\n"); 136 break; 137 case 3: 138 printf("PMIC: programmed\n"); 139 break; 140 default: 141 printf("PMIC: undefined programming state\n"); 142 break; 143 } 144 145 /* The following is needed during production */ 146 if (programmed != 3) { 147 /* set VGEN1 to 1.2V */ 148 val = PFUZE100_VGEN1_VAL; 149 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_VGEN1CTL, 1, 150 &val, 1)) { 151 puts("i2c write failed\n"); 152 return programmed; 153 } 154 155 /* set SWBST to 5.0V */ 156 val = PFUZE100_SWBST_VAL; 157 if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_SWBSTCTL, 1, 158 &val, 1)) { 159 puts("i2c write failed\n"); 160 } 161 } 162 return programmed; 163 } 164 165 #ifndef CONFIG_SPL_BUILD 166 static int pf0100_prog(void) 167 { 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 if (!((0 == i2c_set_bus_num(bus)) && 182 (0 == i2c_probe(PFUZE100_I2C_ADDR)))) { 183 puts("i2c bus failed\n"); 184 return CMD_RET_FAILURE; 185 } 186 187 for (i = 0; i < ARRAY_SIZE(pmic_otp_prog); i++) { 188 switch (pmic_otp_prog[i].cmd) { 189 case pmic_i2c: 190 val = (unsigned char) (pmic_otp_prog[i].value & 0xff); 191 if (i2c_write(PFUZE100_I2C_ADDR, pmic_otp_prog[i].reg, 192 1, &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 232