uboot/drivers/power/pmic/ab8500.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2019 Stephan Gerhold
   4 *
   5 * Adapted from old U-Boot and Linux kernel implementation:
   6 * Copyright (C) STMicroelectronics 2009
   7 * Copyright (C) ST-Ericsson SA 2010
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <regmap.h>
  13#include <syscon.h>
  14#include <linux/bitops.h>
  15#include <linux/err.h>
  16#include <power/ab8500.h>
  17#include <power/pmic.h>
  18
  19/* CPU mailbox registers */
  20#define PRCM_MBOX_CPU_VAL               0x0fc
  21#define PRCM_MBOX_CPU_SET               0x100
  22#define PRCM_MBOX_CPU_CLR               0x104
  23
  24#define PRCM_ARM_IT1_CLR                0x48C
  25#define PRCM_ARM_IT1_VAL                0x494
  26
  27#define PRCM_TCDM_RANGE                 2
  28#define PRCM_REQ_MB5                    0xE44
  29#define PRCM_ACK_MB5                    0xDF4
  30#define _PRCM_MBOX_HEADER               0xFE8
  31#define PRCM_MBOX_HEADER_REQ_MB5        (_PRCM_MBOX_HEADER + 0x5)
  32#define PRCMU_I2C_MBOX_BIT              BIT(5)
  33
  34/* Mailbox 5 Requests */
  35#define PRCM_REQ_MB5_I2C_SLAVE_OP       (PRCM_REQ_MB5 + 0x0)
  36#define PRCM_REQ_MB5_I2C_HW_BITS        (PRCM_REQ_MB5 + 0x1)
  37#define PRCM_REQ_MB5_I2C_REG            (PRCM_REQ_MB5 + 0x2)
  38#define PRCM_REQ_MB5_I2C_VAL            (PRCM_REQ_MB5 + 0x3)
  39#define PRCMU_I2C(bank)                 (((bank) << 1) | BIT(6))
  40#define PRCMU_I2C_WRITE                 0
  41#define PRCMU_I2C_READ                  1
  42#define PRCMU_I2C_STOP_EN               BIT(3)
  43
  44/* Mailbox 5 ACKs */
  45#define PRCM_ACK_MB5_I2C_STATUS         (PRCM_ACK_MB5 + 0x1)
  46#define PRCM_ACK_MB5_I2C_VAL            (PRCM_ACK_MB5 + 0x3)
  47#define PRCMU_I2C_WR_OK                 0x1
  48#define PRCMU_I2C_RD_OK                 0x2
  49
  50/* AB8500 version registers */
  51#define AB8500_MISC_REV_REG             AB8500_MISC(0x80)
  52#define AB8500_MISC_IC_NAME_REG         AB8500_MISC(0x82)
  53
  54struct ab8500_priv {
  55        struct ab8500 ab8500;
  56        struct regmap *regmap;
  57};
  58
  59static inline int prcmu_tcdm_readb(struct regmap *map, uint offset, u8 *valp)
  60{
  61        return regmap_raw_read_range(map, PRCM_TCDM_RANGE, offset,
  62                                     valp, sizeof(*valp));
  63}
  64
  65static inline int prcmu_tcdm_writeb(struct regmap *map, uint offset, u8 val)
  66{
  67        return regmap_raw_write_range(map, PRCM_TCDM_RANGE, offset,
  68                                      &val, sizeof(val));
  69}
  70
  71static int prcmu_wait_i2c_mbx_ready(struct ab8500_priv *priv)
  72{
  73        uint val;
  74        int ret;
  75
  76        ret = regmap_read(priv->regmap, PRCM_ARM_IT1_VAL, &val);
  77        if (ret)
  78                return ret;
  79
  80        if (val & PRCMU_I2C_MBOX_BIT) {
  81                printf("ab8500: warning: PRCMU i2c mailbox was not acked\n");
  82                /* clear mailbox 5 ack irq */
  83                ret = regmap_write(priv->regmap, PRCM_ARM_IT1_CLR,
  84                                   PRCMU_I2C_MBOX_BIT);
  85                if (ret)
  86                        return ret;
  87        }
  88
  89        /* wait for on-going transaction, use 1s timeout */
  90        return regmap_read_poll_timeout(priv->regmap, PRCM_MBOX_CPU_VAL, val,
  91                                        !(val & PRCMU_I2C_MBOX_BIT), 0, 1000);
  92}
  93
  94static int prcmu_wait_i2c_mbx_done(struct ab8500_priv *priv)
  95{
  96        uint val;
  97        int ret;
  98
  99        /* set interrupt to XP70 */
 100        ret = regmap_write(priv->regmap, PRCM_MBOX_CPU_SET, PRCMU_I2C_MBOX_BIT);
 101        if (ret)
 102                return ret;
 103
 104        /* wait for mailbox 5 (i2c) ack, use 1s timeout */
 105        return regmap_read_poll_timeout(priv->regmap, PRCM_ARM_IT1_VAL, val,
 106                                        (val & PRCMU_I2C_MBOX_BIT), 0, 1000);
 107}
 108
 109static int ab8500_transfer(struct udevice *dev, uint bank_reg, u8 *val,
 110                           u8 op, u8 expected_status)
 111{
 112        struct ab8500_priv *priv = dev_get_priv(dev);
 113        u8 reg = bank_reg & 0xff;
 114        u8 bank = bank_reg >> 8;
 115        u8 status;
 116        int ret;
 117
 118        ret = prcmu_wait_i2c_mbx_ready(priv);
 119        if (ret)
 120                return ret;
 121
 122        ret = prcmu_tcdm_writeb(priv->regmap, PRCM_MBOX_HEADER_REQ_MB5, 0);
 123        if (ret)
 124                return ret;
 125        ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_SLAVE_OP,
 126                                PRCMU_I2C(bank) | op);
 127        if (ret)
 128                return ret;
 129        ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_HW_BITS,
 130                                PRCMU_I2C_STOP_EN);
 131        if (ret)
 132                return ret;
 133        ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_REG, reg);
 134        if (ret)
 135                return ret;
 136        ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_VAL, *val);
 137        if (ret)
 138                return ret;
 139
 140        ret = prcmu_wait_i2c_mbx_done(priv);
 141        if (ret) {
 142                printf("%s: mailbox request timed out\n", __func__);
 143                return ret;
 144        }
 145
 146        /* read transfer result */
 147        ret = prcmu_tcdm_readb(priv->regmap, PRCM_ACK_MB5_I2C_STATUS, &status);
 148        if (ret)
 149                return ret;
 150        ret = prcmu_tcdm_readb(priv->regmap, PRCM_ACK_MB5_I2C_VAL, val);
 151        if (ret)
 152                return ret;
 153
 154        /*
 155         * Clear mailbox 5 ack irq. Note that the transfer is already complete
 156         * here so checking for errors does not make sense. Clearing the irq
 157         * will be retried in prcmu_wait_i2c_mbx_ready() on the next transfer.
 158         */
 159        regmap_write(priv->regmap, PRCM_ARM_IT1_CLR, PRCMU_I2C_MBOX_BIT);
 160
 161        if (status != expected_status) {
 162                /*
 163                 * AB8500 does not have the AB8500_MISC_IC_NAME_REG register,
 164                 * but we need to try reading it to detect AB8505.
 165                 * In case of an error, assume that we have AB8500.
 166                 */
 167                if (op == PRCMU_I2C_READ && bank_reg == AB8500_MISC_IC_NAME_REG) {
 168                        *val = AB8500_VERSION_AB8500;
 169                        return 0;
 170                }
 171
 172                printf("%s: return status %d\n", __func__, status);
 173                return -EIO;
 174        }
 175
 176        return 0;
 177}
 178
 179static int ab8500_reg_count(struct udevice *dev)
 180{
 181        return AB8500_NUM_REGISTERS;
 182}
 183
 184static int ab8500_read(struct udevice *dev, uint reg, uint8_t *buf, int len)
 185{
 186        int ret;
 187
 188        if (len != 1)
 189                return -EINVAL;
 190
 191        *buf = 0;
 192        ret = ab8500_transfer(dev, reg, buf, PRCMU_I2C_READ, PRCMU_I2C_RD_OK);
 193        if (ret) {
 194                printf("%s failed: %d\n", __func__, ret);
 195                return ret;
 196        }
 197
 198        return 0;
 199}
 200
 201static int ab8500_write(struct udevice *dev, uint reg, const uint8_t *buf, int len)
 202{
 203        int ret;
 204        u8 val;
 205
 206        if (len != 1)
 207                return -EINVAL;
 208
 209        val = *buf;
 210        ret = ab8500_transfer(dev, reg, &val, PRCMU_I2C_WRITE, PRCMU_I2C_WR_OK);
 211        if (ret) {
 212                printf("%s failed: %d\n", __func__, ret);
 213                return ret;
 214        }
 215
 216        return 0;
 217}
 218
 219static struct dm_pmic_ops ab8500_ops = {
 220        .reg_count = ab8500_reg_count,
 221        .read = ab8500_read,
 222        .write = ab8500_write,
 223};
 224
 225static int ab8500_probe(struct udevice *dev)
 226{
 227        struct ab8500_priv *priv = dev_get_priv(dev);
 228        int ret;
 229
 230        /* get regmap from the PRCMU parent device (syscon in U-Boot) */
 231        priv->regmap = syscon_get_regmap(dev->parent);
 232        if (IS_ERR(priv->regmap))
 233                return PTR_ERR(priv->regmap);
 234
 235        ret = pmic_reg_read(dev, AB8500_MISC_IC_NAME_REG);
 236        if (ret < 0) {
 237                printf("ab8500: failed to read chip version: %d\n", ret);
 238                return ret;
 239        }
 240        priv->ab8500.version = ret;
 241
 242        ret = pmic_reg_read(dev, AB8500_MISC_REV_REG);
 243        if (ret < 0) {
 244                printf("ab8500: failed to read chip id: %d\n", ret);
 245                return ret;
 246        }
 247        priv->ab8500.chip_id = ret;
 248
 249        debug("ab8500: version: %#x, chip id: %#x\n",
 250              priv->ab8500.version, priv->ab8500.chip_id);
 251
 252        return 0;
 253}
 254
 255static const struct udevice_id ab8500_ids[] = {
 256        { .compatible = "stericsson,ab8500" },
 257        { }
 258};
 259
 260U_BOOT_DRIVER(pmic_ab8500) = {
 261        .name           = "pmic_ab8500",
 262        .id             = UCLASS_PMIC,
 263        .of_match       = ab8500_ids,
 264        .bind           = dm_scan_fdt_dev,
 265        .probe          = ab8500_probe,
 266        .ops            = &ab8500_ops,
 267        .priv_auto      = sizeof(struct ab8500_priv),
 268};
 269