linux/drivers/mfd/tps65217.c
<<
>>
Prefs
   1/*
   2 * tps65217.c
   3 *
   4 * TPS65217 chip family multi-function driver
   5 *
   6 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation version 2.
  11 *
  12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  13 * kind, whether express or implied; without even the implied warranty
  14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 */
  17
  18#include <linux/device.h>
  19#include <linux/err.h>
  20#include <linux/init.h>
  21#include <linux/interrupt.h>
  22#include <linux/i2c.h>
  23#include <linux/irq.h>
  24#include <linux/irqdomain.h>
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/of.h>
  28#include <linux/of_device.h>
  29#include <linux/platform_device.h>
  30#include <linux/regmap.h>
  31#include <linux/slab.h>
  32
  33#include <linux/mfd/core.h>
  34#include <linux/mfd/tps65217.h>
  35
  36static struct resource charger_resources[] = {
  37        DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_AC, "AC"),
  38        DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_USB, "USB"),
  39};
  40
  41static struct resource pb_resources[] = {
  42        DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_PB, "PB"),
  43};
  44
  45struct tps65217_irq {
  46        int mask;
  47        int interrupt;
  48};
  49
  50static const struct tps65217_irq tps65217_irqs[] = {
  51        [TPS65217_IRQ_PB] = {
  52                .mask = TPS65217_INT_PBM,
  53                .interrupt = TPS65217_INT_PBI,
  54        },
  55        [TPS65217_IRQ_AC] = {
  56                .mask = TPS65217_INT_ACM,
  57                .interrupt = TPS65217_INT_ACI,
  58        },
  59        [TPS65217_IRQ_USB] = {
  60                .mask = TPS65217_INT_USBM,
  61                .interrupt = TPS65217_INT_USBI,
  62        },
  63};
  64
  65static void tps65217_irq_lock(struct irq_data *data)
  66{
  67        struct tps65217 *tps = irq_data_get_irq_chip_data(data);
  68
  69        mutex_lock(&tps->irq_lock);
  70}
  71
  72static void tps65217_irq_sync_unlock(struct irq_data *data)
  73{
  74        struct tps65217 *tps = irq_data_get_irq_chip_data(data);
  75        int ret;
  76
  77        ret = tps65217_reg_write(tps, TPS65217_REG_INT, tps->irq_mask,
  78                                TPS65217_PROTECT_NONE);
  79        if (ret != 0)
  80                dev_err(tps->dev, "Failed to sync IRQ masks\n");
  81
  82        mutex_unlock(&tps->irq_lock);
  83}
  84
  85static inline const struct tps65217_irq *
  86irq_to_tps65217_irq(struct tps65217 *tps, struct irq_data *data)
  87{
  88        return &tps65217_irqs[data->hwirq];
  89}
  90
  91static void tps65217_irq_enable(struct irq_data *data)
  92{
  93        struct tps65217 *tps = irq_data_get_irq_chip_data(data);
  94        const struct tps65217_irq *irq_data = irq_to_tps65217_irq(tps, data);
  95
  96        tps->irq_mask &= ~irq_data->mask;
  97}
  98
  99static void tps65217_irq_disable(struct irq_data *data)
 100{
 101        struct tps65217 *tps = irq_data_get_irq_chip_data(data);
 102        const struct tps65217_irq *irq_data = irq_to_tps65217_irq(tps, data);
 103
 104        tps->irq_mask |= irq_data->mask;
 105}
 106
 107static struct irq_chip tps65217_irq_chip = {
 108        .irq_bus_lock           = tps65217_irq_lock,
 109        .irq_bus_sync_unlock    = tps65217_irq_sync_unlock,
 110        .irq_enable             = tps65217_irq_enable,
 111        .irq_disable            = tps65217_irq_disable,
 112};
 113
 114static struct mfd_cell tps65217s[] = {
 115        {
 116                .name = "tps65217-pmic",
 117                .of_compatible = "ti,tps65217-pmic",
 118        },
 119        {
 120                .name = "tps65217-bl",
 121                .of_compatible = "ti,tps65217-bl",
 122        },
 123        {
 124                .name = "tps65217-charger",
 125                .num_resources = ARRAY_SIZE(charger_resources),
 126                .resources = charger_resources,
 127                .of_compatible = "ti,tps65217-charger",
 128        },
 129        {
 130                .name = "tps65217-pwrbutton",
 131                .num_resources = ARRAY_SIZE(pb_resources),
 132                .resources = pb_resources,
 133                .of_compatible = "ti,tps65217-pwrbutton",
 134        },
 135};
 136
 137static irqreturn_t tps65217_irq_thread(int irq, void *data)
 138{
 139        struct tps65217 *tps = data;
 140        unsigned int status;
 141        bool handled = false;
 142        int i;
 143        int ret;
 144
 145        ret = tps65217_reg_read(tps, TPS65217_REG_INT, &status);
 146        if (ret < 0) {
 147                dev_err(tps->dev, "Failed to read IRQ status: %d\n",
 148                        ret);
 149                return IRQ_NONE;
 150        }
 151
 152        for (i = 0; i < ARRAY_SIZE(tps65217_irqs); i++) {
 153                if (status & tps65217_irqs[i].interrupt) {
 154                        handle_nested_irq(irq_find_mapping(tps->irq_domain, i));
 155                        handled = true;
 156                }
 157        }
 158
 159        if (handled)
 160                return IRQ_HANDLED;
 161
 162        return IRQ_NONE;
 163}
 164
 165static int tps65217_irq_map(struct irq_domain *h, unsigned int virq,
 166                        irq_hw_number_t hw)
 167{
 168        struct tps65217 *tps = h->host_data;
 169
 170        irq_set_chip_data(virq, tps);
 171        irq_set_chip_and_handler(virq, &tps65217_irq_chip, handle_edge_irq);
 172        irq_set_nested_thread(virq, 1);
 173        irq_set_parent(virq, tps->irq);
 174        irq_set_noprobe(virq);
 175
 176        return 0;
 177}
 178
 179static const struct irq_domain_ops tps65217_irq_domain_ops = {
 180        .map = tps65217_irq_map,
 181};
 182
 183static int tps65217_irq_init(struct tps65217 *tps, int irq)
 184{
 185        int ret;
 186
 187        mutex_init(&tps->irq_lock);
 188        tps->irq = irq;
 189
 190        /* Mask all interrupt sources */
 191        tps->irq_mask = (TPS65217_INT_RESERVEDM | TPS65217_INT_PBM
 192                        | TPS65217_INT_ACM | TPS65217_INT_USBM);
 193        tps65217_reg_write(tps, TPS65217_REG_INT, tps->irq_mask,
 194                        TPS65217_PROTECT_NONE);
 195
 196        tps->irq_domain = irq_domain_add_linear(tps->dev->of_node,
 197                TPS65217_NUM_IRQ, &tps65217_irq_domain_ops, tps);
 198        if (!tps->irq_domain) {
 199                dev_err(tps->dev, "Could not create IRQ domain\n");
 200                return -ENOMEM;
 201        }
 202
 203        ret = devm_request_threaded_irq(tps->dev, irq, NULL,
 204                                        tps65217_irq_thread, IRQF_ONESHOT,
 205                                        "tps65217-irq", tps);
 206        if (ret) {
 207                dev_err(tps->dev, "Failed to request IRQ %d: %d\n",
 208                        irq, ret);
 209                return ret;
 210        }
 211
 212        return 0;
 213}
 214
 215/**
 216 * tps65217_reg_read: Read a single tps65217 register.
 217 *
 218 * @tps: Device to read from.
 219 * @reg: Register to read.
 220 * @val: Contians the value
 221 */
 222int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
 223                        unsigned int *val)
 224{
 225        return regmap_read(tps->regmap, reg, val);
 226}
 227EXPORT_SYMBOL_GPL(tps65217_reg_read);
 228
 229/**
 230 * tps65217_reg_write: Write a single tps65217 register.
 231 *
 232 * @tps65217: Device to write to.
 233 * @reg: Register to write to.
 234 * @val: Value to write.
 235 * @level: Password protected level
 236 */
 237int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,
 238                        unsigned int val, unsigned int level)
 239{
 240        int ret;
 241        unsigned int xor_reg_val;
 242
 243        switch (level) {
 244        case TPS65217_PROTECT_NONE:
 245                return regmap_write(tps->regmap, reg, val);
 246        case TPS65217_PROTECT_L1:
 247                xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK;
 248                ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
 249                                                        xor_reg_val);
 250                if (ret < 0)
 251                        return ret;
 252
 253                return regmap_write(tps->regmap, reg, val);
 254        case TPS65217_PROTECT_L2:
 255                xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK;
 256                ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
 257                                                        xor_reg_val);
 258                if (ret < 0)
 259                        return ret;
 260                ret = regmap_write(tps->regmap, reg, val);
 261                if (ret < 0)
 262                        return ret;
 263                ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
 264                                                        xor_reg_val);
 265                if (ret < 0)
 266                        return ret;
 267                return regmap_write(tps->regmap, reg, val);
 268        default:
 269                return -EINVAL;
 270        }
 271}
 272EXPORT_SYMBOL_GPL(tps65217_reg_write);
 273
 274/**
 275 * tps65217_update_bits: Modify bits w.r.t mask, val and level.
 276 *
 277 * @tps65217: Device to write to.
 278 * @reg: Register to read-write to.
 279 * @mask: Mask.
 280 * @val: Value to write.
 281 * @level: Password protected level
 282 */
 283static int tps65217_update_bits(struct tps65217 *tps, unsigned int reg,
 284                unsigned int mask, unsigned int val, unsigned int level)
 285{
 286        int ret;
 287        unsigned int data;
 288
 289        ret = tps65217_reg_read(tps, reg, &data);
 290        if (ret) {
 291                dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
 292                return ret;
 293        }
 294
 295        data &= ~mask;
 296        data |= val & mask;
 297
 298        ret = tps65217_reg_write(tps, reg, data, level);
 299        if (ret)
 300                dev_err(tps->dev, "Write for reg 0x%x failed\n", reg);
 301
 302        return ret;
 303}
 304
 305int tps65217_set_bits(struct tps65217 *tps, unsigned int reg,
 306                unsigned int mask, unsigned int val, unsigned int level)
 307{
 308        return tps65217_update_bits(tps, reg, mask, val, level);
 309}
 310EXPORT_SYMBOL_GPL(tps65217_set_bits);
 311
 312int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
 313                unsigned int mask, unsigned int level)
 314{
 315        return tps65217_update_bits(tps, reg, mask, 0, level);
 316}
 317EXPORT_SYMBOL_GPL(tps65217_clear_bits);
 318
 319static bool tps65217_volatile_reg(struct device *dev, unsigned int reg)
 320{
 321        switch (reg) {
 322        case TPS65217_REG_INT:
 323                return true;
 324        default:
 325                return false;
 326        }
 327}
 328
 329static const struct regmap_config tps65217_regmap_config = {
 330        .reg_bits = 8,
 331        .val_bits = 8,
 332
 333        .max_register = TPS65217_REG_MAX,
 334        .volatile_reg = tps65217_volatile_reg,
 335};
 336
 337static const struct of_device_id tps65217_of_match[] = {
 338        { .compatible = "ti,tps65217", .data = (void *)TPS65217 },
 339        { /* sentinel */ },
 340};
 341MODULE_DEVICE_TABLE(of, tps65217_of_match);
 342
 343static int tps65217_probe(struct i2c_client *client,
 344                                const struct i2c_device_id *ids)
 345{
 346        struct tps65217 *tps;
 347        unsigned int version;
 348        unsigned long chip_id = ids->driver_data;
 349        const struct of_device_id *match;
 350        bool status_off = false;
 351        int ret;
 352
 353        if (client->dev.of_node) {
 354                match = of_match_device(tps65217_of_match, &client->dev);
 355                if (!match) {
 356                        dev_err(&client->dev,
 357                                "Failed to find matching dt id\n");
 358                        return -EINVAL;
 359                }
 360                chip_id = (unsigned long)match->data;
 361                status_off = of_property_read_bool(client->dev.of_node,
 362                                        "ti,pmic-shutdown-controller");
 363        }
 364
 365        if (!chip_id) {
 366                dev_err(&client->dev, "id is null.\n");
 367                return -ENODEV;
 368        }
 369
 370        tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
 371        if (!tps)
 372                return -ENOMEM;
 373
 374        i2c_set_clientdata(client, tps);
 375        tps->dev = &client->dev;
 376        tps->id = chip_id;
 377
 378        tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config);
 379        if (IS_ERR(tps->regmap)) {
 380                ret = PTR_ERR(tps->regmap);
 381                dev_err(tps->dev, "Failed to allocate register map: %d\n",
 382                        ret);
 383                return ret;
 384        }
 385
 386        if (client->irq) {
 387                tps65217_irq_init(tps, client->irq);
 388        } else {
 389                int i;
 390
 391                /* Don't tell children about IRQ resources which won't fire */
 392                for (i = 0; i < ARRAY_SIZE(tps65217s); i++)
 393                        tps65217s[i].num_resources = 0;
 394        }
 395
 396        ret = devm_mfd_add_devices(tps->dev, -1, tps65217s,
 397                                   ARRAY_SIZE(tps65217s), NULL, 0,
 398                                   tps->irq_domain);
 399        if (ret < 0) {
 400                dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret);
 401                return ret;
 402        }
 403
 404        ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version);
 405        if (ret < 0) {
 406                dev_err(tps->dev, "Failed to read revision register: %d\n",
 407                        ret);
 408                return ret;
 409        }
 410
 411        /* Set the PMIC to shutdown on PWR_EN toggle */
 412        if (status_off) {
 413                ret = tps65217_set_bits(tps, TPS65217_REG_STATUS,
 414                                TPS65217_STATUS_OFF, TPS65217_STATUS_OFF,
 415                                TPS65217_PROTECT_NONE);
 416                if (ret)
 417                        dev_warn(tps->dev, "unable to set the status OFF\n");
 418        }
 419
 420        dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n",
 421                        (version & TPS65217_CHIPID_CHIP_MASK) >> 4,
 422                        version & TPS65217_CHIPID_REV_MASK);
 423
 424        return 0;
 425}
 426
 427static const struct i2c_device_id tps65217_id_table[] = {
 428        {"tps65217", TPS65217},
 429        { /* sentinel */ }
 430};
 431MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
 432
 433static struct i2c_driver tps65217_driver = {
 434        .driver         = {
 435                .name   = "tps65217",
 436                .of_match_table = tps65217_of_match,
 437        },
 438        .id_table       = tps65217_id_table,
 439        .probe          = tps65217_probe,
 440};
 441
 442static int __init tps65217_init(void)
 443{
 444        return i2c_add_driver(&tps65217_driver);
 445}
 446subsys_initcall(tps65217_init);
 447
 448static void __exit tps65217_exit(void)
 449{
 450        i2c_del_driver(&tps65217_driver);
 451}
 452module_exit(tps65217_exit);
 453
 454MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>");
 455MODULE_DESCRIPTION("TPS65217 chip family multi-function driver");
 456MODULE_LICENSE("GPL v2");
 457