uboot/board/toradex/colibri_imx6/pf0100.c
<<
>>
Prefs
   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 <asm/arch/imx-regs.h>
  14#include <asm/arch/iomux.h>
  15#include <asm/arch/mx6-pins.h>
  16#include <asm/gpio.h>
  17#include <asm/mach-imx/iomux-v3.h>
  18
  19#include "pf0100_otp.inc"
  20#include "pf0100.h"
  21
  22/* define for PMIC register dump */
  23/*#define DEBUG */
  24
  25/* use GPIO: EXT_IO1 to switch on VPGM, ON: 1 */
  26static iomux_v3_cfg_t const pmic_prog_pads[] = {
  27        MX6_PAD_NANDF_D3__GPIO2_IO03 | MUX_PAD_CTRL(NO_PAD_CTRL),
  28#       define PMIC_PROG_VOLTAGE IMX_GPIO_NR(2, 3)
  29};
  30
  31unsigned pmic_init(void)
  32{
  33        unsigned programmed = 0;
  34        uchar bus = 1;
  35        uchar devid, revid, val;
  36
  37        puts("PMIC: ");
  38        if (!((0 == i2c_set_bus_num(bus)) &&
  39              (0 == i2c_probe(PFUZE100_I2C_ADDR)))) {
  40                puts("i2c bus failed\n");
  41                return 0;
  42        }
  43        /* get device ident */
  44        if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_DEVICEID, 1, &devid, 1) < 0) {
  45                puts("i2c pmic devid read failed\n");
  46                return 0;
  47        }
  48        if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_REVID, 1, &revid, 1) < 0) {
  49                puts("i2c pmic revid read failed\n");
  50                return 0;
  51        }
  52        printf("device id: 0x%.2x, revision id: 0x%.2x\n", devid, revid);
  53
  54#ifdef DEBUG
  55        {
  56                unsigned i, j;
  57
  58                for (i = 0; i < 16; i++)
  59                        printf("\t%x", i);
  60                for (j = 0; j < 0x80; ) {
  61                        printf("\n%2x", j);
  62                        for (i = 0; i < 16; i++) {
  63                                i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
  64                                printf("\t%2x", val);
  65                        }
  66                        j += 0x10;
  67                }
  68                printf("\nEXT Page 1");
  69
  70                val = PFUZE100_PAGE_REGISTER_PAGE1;
  71                if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1,
  72                              &val, 1)) {
  73                        puts("i2c write failed\n");
  74                        return 0;
  75                }
  76
  77                for (j = 0x80; j < 0x100; ) {
  78                        printf("\n%2x", j);
  79                        for (i = 0; i < 16; i++) {
  80                                i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
  81                                printf("\t%2x", val);
  82                        }
  83                        j += 0x10;
  84                }
  85                printf("\nEXT Page 2");
  86
  87                val = PFUZE100_PAGE_REGISTER_PAGE2;
  88                if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1,
  89                              &val, 1)) {
  90                        puts("i2c write failed\n");
  91                        return 0;
  92                }
  93
  94                for (j = 0x80; j < 0x100; ) {
  95                        printf("\n%2x", j);
  96                        for (i = 0; i < 16; i++) {
  97                                i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
  98                                printf("\t%2x", val);
  99                        }
 100                        j += 0x10;
 101                }
 102                printf("\n");
 103        }
 104#endif
 105        /* get device programmed state */
 106        val = PFUZE100_PAGE_REGISTER_PAGE1;
 107        if (i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1, &val, 1)) {
 108                puts("i2c write failed\n");
 109                return 0;
 110        }
 111        if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR1, 1, &val, 1) < 0) {
 112                puts("i2c fuse_por read failed\n");
 113                return 0;
 114        }
 115        if (val & PFUZE100_FUSE_POR_M)
 116                programmed++;
 117
 118        if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR2, 1, &val, 1) < 0) {
 119                puts("i2c fuse_por read failed\n");
 120                return programmed;
 121        }
 122        if (val & PFUZE100_FUSE_POR_M)
 123                programmed++;
 124
 125        if (i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR3, 1, &val, 1) < 0) {
 126                puts("i2c fuse_por read failed\n");
 127                return programmed;
 128        }
 129        if (val & PFUZE100_FUSE_POR_M)
 130                programmed++;
 131
 132        switch (programmed) {
 133        case 0:
 134                printf("PMIC: not programmed\n");
 135                break;
 136        case 3:
 137                printf("PMIC: programmed\n");
 138                break;
 139        default:
 140                printf("PMIC: undefined programming state\n");
 141                break;
 142        }
 143
 144        return programmed;
 145}
 146
 147int 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
 194int 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
 207U_BOOT_CMD(
 208        pf0100_otp_prog, 1, 0, do_pf0100_prog,
 209        "Program the OTP fuses on the PMIC PF0100",
 210        ""
 211);
 212