uboot/drivers/power/pmic/rk8xx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2015 Google, Inc
   4 * Written by Simon Glass <sjg@chromium.org>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <log.h>
  11#include <power/rk8xx_pmic.h>
  12#include <power/pmic.h>
  13
  14static struct reg_data rk817_init_reg[] = {
  15/* enable the under-voltage protection,
  16 * the under-voltage protection will shutdown the LDO3 and reset the PMIC
  17 */
  18        { RK817_BUCK4_CMIN, 0x60, 0x60},
  19};
  20
  21static const struct pmic_child_info pmic_children_info[] = {
  22        { .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
  23        { .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
  24        { .prefix = "SWITCH_REG", .driver = "rk8xx_switch"},
  25        { },
  26};
  27
  28static int rk8xx_reg_count(struct udevice *dev)
  29{
  30        return RK808_NUM_OF_REGS;
  31}
  32
  33static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
  34                          int len)
  35{
  36        int ret;
  37
  38        ret = dm_i2c_write(dev, reg, buff, len);
  39        if (ret) {
  40                debug("write error to device: %p register: %#x!\n", dev, reg);
  41                return ret;
  42        }
  43
  44        return 0;
  45}
  46
  47static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
  48{
  49        int ret;
  50
  51        ret = dm_i2c_read(dev, reg, buff, len);
  52        if (ret) {
  53                debug("read error from device: %p register: %#x!\n", dev, reg);
  54                return ret;
  55        }
  56
  57        return 0;
  58}
  59
  60#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
  61static int rk8xx_bind(struct udevice *dev)
  62{
  63        ofnode regulators_node;
  64        int children;
  65
  66        regulators_node = dev_read_subnode(dev, "regulators");
  67        if (!ofnode_valid(regulators_node)) {
  68                debug("%s: %s regulators subnode not found!\n", __func__,
  69                      dev->name);
  70                return -ENXIO;
  71        }
  72
  73        debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
  74
  75        children = pmic_bind_children(dev, regulators_node, pmic_children_info);
  76        if (!children)
  77                debug("%s: %s - no child found\n", __func__, dev->name);
  78
  79        /* Always return success for this device */
  80        return 0;
  81}
  82#endif
  83
  84static int rk8xx_probe(struct udevice *dev)
  85{
  86        struct rk8xx_priv *priv = dev_get_priv(dev);
  87        struct reg_data *init_data = NULL;
  88        int init_data_num = 0;
  89        int ret = 0, i, show_variant;
  90        u8 msb, lsb, id_msb, id_lsb;
  91        u8 on_source = 0, off_source = 0;
  92        u8 power_en0, power_en1, power_en2, power_en3;
  93        u8 value;
  94
  95        /* read Chip variant */
  96        if (device_is_compatible(dev, "rockchip,rk817") ||
  97            device_is_compatible(dev, "rockchip,rk809")) {
  98                id_msb = RK817_ID_MSB;
  99                id_lsb = RK817_ID_LSB;
 100        } else {
 101                id_msb = ID_MSB;
 102                id_lsb = ID_LSB;
 103        }
 104
 105        ret = rk8xx_read(dev, id_msb, &msb, 1);
 106        if (ret)
 107                return ret;
 108        ret = rk8xx_read(dev, id_lsb, &lsb, 1);
 109        if (ret)
 110                return ret;
 111
 112        priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
 113        show_variant = priv->variant;
 114        switch (priv->variant) {
 115        case RK808_ID:
 116                show_variant = 0x808;   /* RK808 hardware ID is 0 */
 117                break;
 118        case RK805_ID:
 119        case RK816_ID:
 120        case RK818_ID:
 121                on_source = RK8XX_ON_SOURCE;
 122                off_source = RK8XX_OFF_SOURCE;
 123                break;
 124        case RK809_ID:
 125        case RK817_ID:
 126                on_source = RK817_ON_SOURCE;
 127                off_source = RK817_OFF_SOURCE;
 128                init_data = rk817_init_reg;
 129                init_data_num = ARRAY_SIZE(rk817_init_reg);
 130                power_en0 = pmic_reg_read(dev, RK817_POWER_EN0);
 131                power_en1 = pmic_reg_read(dev, RK817_POWER_EN1);
 132                power_en2 = pmic_reg_read(dev, RK817_POWER_EN2);
 133                power_en3 = pmic_reg_read(dev, RK817_POWER_EN3);
 134
 135                value = (power_en0 & 0x0f) | ((power_en1 & 0x0f) << 4);
 136                pmic_reg_write(dev, RK817_POWER_EN_SAVE0, value);
 137                value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);
 138                pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value);
 139                break;
 140        default:
 141                printf("Unknown PMIC: RK%x!!\n", priv->variant);
 142                return -EINVAL;
 143        }
 144
 145        for (i = 0; i < init_data_num; i++) {
 146                ret = pmic_clrsetbits(dev,
 147                                      init_data[i].reg,
 148                                      init_data[i].mask,
 149                                      init_data[i].val);
 150                if (ret < 0) {
 151                        printf("%s: i2c set reg 0x%x failed, ret=%d\n",
 152                               __func__, init_data[i].reg, ret);
 153                }
 154
 155                debug("%s: reg[0x%x] = 0x%x\n", __func__, init_data[i].reg,
 156                      pmic_reg_read(dev, init_data[i].reg));
 157        }
 158
 159        printf("PMIC:  RK%x ", show_variant);
 160
 161        if (on_source && off_source)
 162                printf("(on=0x%02x, off=0x%02x)",
 163                       pmic_reg_read(dev, on_source),
 164                       pmic_reg_read(dev, off_source));
 165        printf("\n");
 166
 167        return 0;
 168}
 169
 170static struct dm_pmic_ops rk8xx_ops = {
 171        .reg_count = rk8xx_reg_count,
 172        .read = rk8xx_read,
 173        .write = rk8xx_write,
 174};
 175
 176static const struct udevice_id rk8xx_ids[] = {
 177        { .compatible = "rockchip,rk805" },
 178        { .compatible = "rockchip,rk808" },
 179        { .compatible = "rockchip,rk809" },
 180        { .compatible = "rockchip,rk816" },
 181        { .compatible = "rockchip,rk817" },
 182        { .compatible = "rockchip,rk818" },
 183        { }
 184};
 185
 186U_BOOT_DRIVER(rockchip_rk805) = {
 187        .name = "rockchip_rk805",
 188        .id = UCLASS_PMIC,
 189        .of_match = rk8xx_ids,
 190#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
 191        .bind = rk8xx_bind,
 192#endif
 193        .priv_auto        = sizeof(struct rk8xx_priv),
 194        .probe = rk8xx_probe,
 195        .ops = &rk8xx_ops,
 196};
 197
 198DM_DRIVER_ALIAS(rockchip_rk805, rockchip_rk808)
 199