linux/drivers/spmi/hisi-spmi-controller.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <linux/delay.h>
   4#include <linux/err.h>
   5#include <linux/interrupt.h>
   6#include <linux/io.h>
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/of.h>
  10#include <linux/platform_device.h>
  11#include <linux/seq_file.h>
  12#include <linux/slab.h>
  13#include <linux/spmi.h>
  14
  15/*
  16 * SPMI register addr
  17 */
  18#define SPMI_CHANNEL_OFFSET                             0x0300
  19#define SPMI_SLAVE_OFFSET                               0x20
  20
  21#define SPMI_APB_SPMI_CMD_BASE_ADDR                     0x0100
  22
  23#define SPMI_APB_SPMI_WDATA0_BASE_ADDR                  0x0104
  24#define SPMI_APB_SPMI_WDATA1_BASE_ADDR                  0x0108
  25#define SPMI_APB_SPMI_WDATA2_BASE_ADDR                  0x010c
  26#define SPMI_APB_SPMI_WDATA3_BASE_ADDR                  0x0110
  27
  28#define SPMI_APB_SPMI_STATUS_BASE_ADDR                  0x0200
  29
  30#define SPMI_APB_SPMI_RDATA0_BASE_ADDR                  0x0204
  31#define SPMI_APB_SPMI_RDATA1_BASE_ADDR                  0x0208
  32#define SPMI_APB_SPMI_RDATA2_BASE_ADDR                  0x020c
  33#define SPMI_APB_SPMI_RDATA3_BASE_ADDR                  0x0210
  34
  35#define SPMI_PER_DATAREG_BYTE                           4
  36/*
  37 * SPMI cmd register
  38 */
  39#define SPMI_APB_SPMI_CMD_EN                            BIT(31)
  40#define SPMI_APB_SPMI_CMD_TYPE_OFFSET                   24
  41#define SPMI_APB_SPMI_CMD_LENGTH_OFFSET                 20
  42#define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET                16
  43#define SPMI_APB_SPMI_CMD_ADDR_OFFSET                   0
  44
  45/* Command Opcodes */
  46
  47enum spmi_controller_cmd_op_code {
  48        SPMI_CMD_REG_ZERO_WRITE = 0,
  49        SPMI_CMD_REG_WRITE = 1,
  50        SPMI_CMD_REG_READ = 2,
  51        SPMI_CMD_EXT_REG_WRITE = 3,
  52        SPMI_CMD_EXT_REG_READ = 4,
  53        SPMI_CMD_EXT_REG_WRITE_L = 5,
  54        SPMI_CMD_EXT_REG_READ_L = 6,
  55        SPMI_CMD_REG_RESET = 7,
  56        SPMI_CMD_REG_SLEEP = 8,
  57        SPMI_CMD_REG_SHUTDOWN = 9,
  58        SPMI_CMD_REG_WAKEUP = 10,
  59};
  60
  61/*
  62 * SPMI status register
  63 */
  64#define SPMI_APB_TRANS_DONE                     BIT(0)
  65#define SPMI_APB_TRANS_FAIL                     BIT(2)
  66
  67/* Command register fields */
  68#define SPMI_CONTROLLER_CMD_MAX_BYTE_COUNT      16
  69
  70/* Maximum number of support PMIC peripherals */
  71#define SPMI_CONTROLLER_TIMEOUT_US              1000
  72#define SPMI_CONTROLLER_MAX_TRANS_BYTES         16
  73
  74struct spmi_controller_dev {
  75        struct spmi_controller  *controller;
  76        struct device           *dev;
  77        void __iomem            *base;
  78        spinlock_t              lock;
  79        u32                     channel;
  80};
  81
  82static int spmi_controller_wait_for_done(struct device *dev,
  83                                         struct spmi_controller_dev *ctrl_dev,
  84                                         void __iomem *base, u8 sid, u16 addr)
  85{
  86        u32 timeout = SPMI_CONTROLLER_TIMEOUT_US;
  87        u32 status, offset;
  88
  89        offset  = SPMI_APB_SPMI_STATUS_BASE_ADDR;
  90        offset += SPMI_CHANNEL_OFFSET * ctrl_dev->channel + SPMI_SLAVE_OFFSET * sid;
  91
  92        do {
  93                status = readl(base + offset);
  94
  95                if (status & SPMI_APB_TRANS_DONE) {
  96                        if (status & SPMI_APB_TRANS_FAIL) {
  97                                dev_err(dev, "%s: transaction failed (0x%x)\n",
  98                                        __func__, status);
  99                                return -EIO;
 100                        }
 101                        dev_dbg(dev, "%s: status 0x%x\n", __func__, status);
 102                        return 0;
 103                }
 104                udelay(1);
 105        } while (timeout--);
 106
 107        dev_err(dev, "%s: timeout, status 0x%x\n", __func__, status);
 108        return -ETIMEDOUT;
 109}
 110
 111static int spmi_read_cmd(struct spmi_controller *ctrl,
 112                         u8 opc, u8 slave_id, u16 slave_addr, u8 *__buf, size_t bc)
 113{
 114        struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev);
 115        u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel;
 116        unsigned long flags;
 117        u8 *buf = __buf;
 118        u32 cmd, data;
 119        int rc;
 120        u8 op_code, i;
 121
 122        if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
 123                dev_err(&ctrl->dev,
 124                        "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
 125                        SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
 126                return  -EINVAL;
 127        }
 128
 129        switch (opc) {
 130        case SPMI_CMD_READ:
 131                op_code = SPMI_CMD_REG_READ;
 132                break;
 133        case SPMI_CMD_EXT_READ:
 134                op_code = SPMI_CMD_EXT_REG_READ;
 135                break;
 136        case SPMI_CMD_EXT_READL:
 137                op_code = SPMI_CMD_EXT_REG_READ_L;
 138                break;
 139        default:
 140                dev_err(&ctrl->dev, "invalid read cmd 0x%x\n", opc);
 141                return -EINVAL;
 142        }
 143
 144        cmd = SPMI_APB_SPMI_CMD_EN |
 145             (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |
 146             ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |
 147             ((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) |  /* slvid */
 148             ((slave_addr & 0xffff)  << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */
 149
 150        spin_lock_irqsave(&spmi_controller->lock, flags);
 151
 152        writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR);
 153
 154        rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller,
 155                                           spmi_controller->base, slave_id, slave_addr);
 156        if (rc)
 157                goto done;
 158
 159        for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) {
 160                data = readl(spmi_controller->base + chnl_ofst +
 161                             SPMI_SLAVE_OFFSET * slave_id +
 162                             SPMI_APB_SPMI_RDATA0_BASE_ADDR +
 163                             i * SPMI_PER_DATAREG_BYTE);
 164                data = be32_to_cpu((__be32 __force)data);
 165                if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) {
 166                        memcpy(buf, &data, sizeof(data));
 167                        buf += sizeof(data);
 168                } else {
 169                        memcpy(buf, &data, bc % SPMI_PER_DATAREG_BYTE);
 170                        buf += (bc % SPMI_PER_DATAREG_BYTE);
 171                }
 172        }
 173
 174done:
 175        spin_unlock_irqrestore(&spmi_controller->lock, flags);
 176        if (rc)
 177                dev_err(&ctrl->dev,
 178                        "spmi read wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n",
 179                        opc, slave_id, slave_addr, bc + 1);
 180        else
 181                dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, read value: %*ph\n",
 182                        __func__, slave_id, slave_addr, (int)bc, __buf);
 183
 184        return rc;
 185}
 186
 187static int spmi_write_cmd(struct spmi_controller *ctrl,
 188                          u8 opc, u8 slave_id, u16 slave_addr, const u8 *__buf, size_t bc)
 189{
 190        struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev);
 191        u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel;
 192        const u8 *buf = __buf;
 193        unsigned long flags;
 194        u32 cmd, data;
 195        int rc;
 196        u8 op_code, i;
 197
 198        if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
 199                dev_err(&ctrl->dev,
 200                        "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
 201                        SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
 202                return  -EINVAL;
 203        }
 204
 205        switch (opc) {
 206        case SPMI_CMD_WRITE:
 207                op_code = SPMI_CMD_REG_WRITE;
 208                break;
 209        case SPMI_CMD_EXT_WRITE:
 210                op_code = SPMI_CMD_EXT_REG_WRITE;
 211                break;
 212        case SPMI_CMD_EXT_WRITEL:
 213                op_code = SPMI_CMD_EXT_REG_WRITE_L;
 214                break;
 215        default:
 216                dev_err(&ctrl->dev, "invalid write cmd 0x%x\n", opc);
 217                return -EINVAL;
 218        }
 219
 220        cmd = SPMI_APB_SPMI_CMD_EN |
 221              (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |
 222              ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |
 223              ((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) |
 224              ((slave_addr & 0xffff)  << SPMI_APB_SPMI_CMD_ADDR_OFFSET);
 225
 226        /* Write data to FIFOs */
 227        spin_lock_irqsave(&spmi_controller->lock, flags);
 228
 229        for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) {
 230                data = 0;
 231                if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) {
 232                        memcpy(&data, buf, sizeof(data));
 233                        buf += sizeof(data);
 234                } else {
 235                        memcpy(&data, buf, bc % SPMI_PER_DATAREG_BYTE);
 236                        buf += (bc % SPMI_PER_DATAREG_BYTE);
 237                }
 238
 239                writel((u32 __force)cpu_to_be32(data),
 240                       spmi_controller->base + chnl_ofst +
 241                       SPMI_APB_SPMI_WDATA0_BASE_ADDR +
 242                       SPMI_PER_DATAREG_BYTE * i);
 243        }
 244
 245        /* Start the transaction */
 246        writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR);
 247
 248        rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller,
 249                                           spmi_controller->base, slave_id,
 250                                           slave_addr);
 251        spin_unlock_irqrestore(&spmi_controller->lock, flags);
 252
 253        if (rc)
 254                dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n",
 255                        opc, slave_id, slave_addr, bc);
 256        else
 257                dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, wrote value: %*ph\n",
 258                        __func__, slave_id, slave_addr, (int)bc, __buf);
 259
 260        return rc;
 261}
 262
 263static int spmi_controller_probe(struct platform_device *pdev)
 264{
 265        struct spmi_controller_dev *spmi_controller;
 266        struct spmi_controller *ctrl;
 267        struct resource *iores;
 268        int ret;
 269
 270        ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller));
 271        if (!ctrl) {
 272                dev_err(&pdev->dev, "can not allocate spmi_controller data\n");
 273                return -ENOMEM;
 274        }
 275        spmi_controller = spmi_controller_get_drvdata(ctrl);
 276        spmi_controller->controller = ctrl;
 277
 278        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 279        if (!iores) {
 280                dev_err(&pdev->dev, "can not get resource!\n");
 281                ret = -EINVAL;
 282                goto err_put_controller;
 283        }
 284
 285        spmi_controller->base = devm_ioremap(&pdev->dev, iores->start,
 286                                             resource_size(iores));
 287        if (!spmi_controller->base) {
 288                dev_err(&pdev->dev, "can not remap base addr!\n");
 289                ret = -EADDRNOTAVAIL;
 290                goto err_put_controller;
 291        }
 292
 293        ret = of_property_read_u32(pdev->dev.of_node, "hisilicon,spmi-channel",
 294                                   &spmi_controller->channel);
 295        if (ret) {
 296                dev_err(&pdev->dev, "can not get channel\n");
 297                ret = -ENODEV;
 298                goto err_put_controller;
 299        }
 300
 301        platform_set_drvdata(pdev, spmi_controller);
 302        dev_set_drvdata(&ctrl->dev, spmi_controller);
 303
 304        spin_lock_init(&spmi_controller->lock);
 305
 306        ctrl->nr = spmi_controller->channel;
 307        ctrl->dev.parent = pdev->dev.parent;
 308        ctrl->dev.of_node = of_node_get(pdev->dev.of_node);
 309
 310        /* Callbacks */
 311        ctrl->read_cmd = spmi_read_cmd;
 312        ctrl->write_cmd = spmi_write_cmd;
 313
 314        ret = spmi_controller_add(ctrl);
 315        if (ret) {
 316                dev_err(&pdev->dev, "spmi_controller_add failed with error %d!\n", ret);
 317                goto err_put_controller;
 318        }
 319
 320        return 0;
 321
 322err_put_controller:
 323        spmi_controller_put(ctrl);
 324        return ret;
 325}
 326
 327static int spmi_del_controller(struct platform_device *pdev)
 328{
 329        struct spmi_controller *ctrl = platform_get_drvdata(pdev);
 330
 331        spmi_controller_remove(ctrl);
 332        spmi_controller_put(ctrl);
 333        return 0;
 334}
 335
 336static const struct of_device_id spmi_controller_match_table[] = {
 337        {
 338                .compatible = "hisilicon,kirin970-spmi-controller",
 339        },
 340        {}
 341};
 342MODULE_DEVICE_TABLE(of, spmi_controller_match_table);
 343
 344static struct platform_driver spmi_controller_driver = {
 345        .probe          = spmi_controller_probe,
 346        .remove         = spmi_del_controller,
 347        .driver         = {
 348                .name   = "hisi_spmi_controller",
 349                .of_match_table = spmi_controller_match_table,
 350        },
 351};
 352
 353static int __init spmi_controller_init(void)
 354{
 355        return platform_driver_register(&spmi_controller_driver);
 356}
 357postcore_initcall(spmi_controller_init);
 358
 359static void __exit spmi_controller_exit(void)
 360{
 361        platform_driver_unregister(&spmi_controller_driver);
 362}
 363module_exit(spmi_controller_exit);
 364
 365MODULE_LICENSE("GPL v2");
 366MODULE_VERSION("1.0");
 367MODULE_ALIAS("platform:spmi_controller");
 368