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
  45static void tps65217_irq_lock(struct irq_data *data)
  46{
  47        struct tps65217 *tps = irq_data_get_irq_chip_data(data);
  48
  49        mutex_lock(&tps->irq_lock);
  50}
  51
  52static void tps65217_irq_sync_unlock(struct irq_data *data)
  53{
  54        struct tps65217 *tps = irq_data_get_irq_chip_data(data);
  55        int ret;
  56
  57        ret = tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK,
  58                                tps->irq_mask, TPS65217_PROTECT_NONE);
  59        if (ret != 0)
  60                dev_err(tps->dev, "Failed to sync IRQ masks\n");
  61
  62        mutex_unlock(&tps->irq_lock);
  63}
  64
  65static void tps65217_irq_enable(struct irq_data *data)
  66{
  67        struct tps65217 *tps = irq_data_get_irq_chip_data(data);
  68        u8 mask = BIT(data->hwirq) << TPS65217_INT_SHIFT;
  69
  70        tps->irq_mask &= ~mask;
  71}
  72
  73static void tps65217_irq_disable(struct irq_data *data)
  74{
  75        struct tps65217 *tps = irq_data_get_irq_chip_data(data);
  76        u8 mask = BIT(data->hwirq) << TPS65217_INT_SHIFT;
  77
  78        tps->irq_mask |= mask;
  79}
  80
  81static struct irq_chip tps65217_irq_chip = {
  82        .name                   = "tps65217",
  83        .irq_bus_lock           = tps65217_irq_lock,
  84        .irq_bus_sync_unlock    = tps65217_irq_sync_unlock,
  85        .irq_enable             = tps65217_irq_enable,
  86        .irq_disable            = tps65217_irq_disable,
  87};
  88
  89static struct mfd_cell tps65217s[] = {
  90        {
  91                .name = "tps65217-pmic",
  92                .of_compatible = "ti,tps65217-pmic",
  93        },
  94        {
  95                .name = "tps65217-bl",
  96                .of_compatible = "ti,tps65217-bl",
  97        },
  98        {
  99                .name = "tps65217-charger",
 100                .num_resources = ARRAY_SIZE(charger_resources),
 101                .resources = charger_resources,
 102                .of_compatible = "ti,tps65217-charger",
 103        },
 104        {
 105                .name = "tps65217-pwrbutton",
 106                .num_resources = ARRAY_SIZE(pb_resources),
 107                .resources = pb_resources,
 108                .of_compatible = "ti,tps65217-pwrbutton",
 109        },
 110};
 111
 112static irqreturn_t tps65217_irq_thread(int irq, void *data)
 113{
 114        struct tps65217 *tps = data;
 115        unsigned int status;
 116        bool handled = false;
 117        int i;
 118        int ret;
 119
 120        ret = tps65217_reg_read(tps, TPS65217_REG_INT, &status);
 121        if (ret < 0) {
 122                dev_err(tps->dev, "Failed to read IRQ status: %d\n",
 123                        ret);
 124                return IRQ_NONE;
 125        }
 126
 127        for (i = 0; i < TPS65217_NUM_IRQ; i++) {
 128                if (status & BIT(i)) {
 129                        handle_nested_irq(irq_find_mapping(tps->irq_domain, i));
 130                        handled = true;
 131                }
 132        }
 133
 134        if (handled)
 135                return IRQ_HANDLED;
 136
 137        return IRQ_NONE;
 138}
 139
 140static int tps65217_irq_map(struct irq_domain *h, unsigned int virq,
 141                        irq_hw_number_t hw)
 142{
 143        struct tps65217 *tps = h->host_data;
 144
 145        irq_set_chip_data(virq, tps);
 146        irq_set_chip_and_handler(virq, &tps65217_irq_chip, handle_edge_irq);
 147        irq_set_nested_thread(virq, 1);
 148        irq_set_parent(virq, tps->irq);
 149        irq_set_noprobe(virq);
 150
 151        return 0;
 152}
 153
 154static const struct irq_domain_ops tps65217_irq_domain_ops = {
 155        .map = tps65217_irq_map,
 156};
 157
 158static int tps65217_irq_init(struct tps65217 *tps, int irq)
 159{
 160        int ret;
 161
 162        mutex_init(&tps->irq_lock);
 163        tps->irq = irq;
 164
 165        /* Mask all interrupt sources */
 166        tps->irq_mask = TPS65217_INT_MASK;
 167        tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK,
 168                          TPS65217_INT_MASK, TPS65217_PROTECT_NONE);
 169
 170        tps->irq_domain = irq_domain_add_linear(tps->dev->of_node,
 171                TPS65217_NUM_IRQ, &tps65217_irq_domain_ops, tps);
 172        if (!tps->irq_domain) {
 173                dev_err(tps->dev, "Could not create IRQ domain\n");
 174                return -ENOMEM;
 175        }
 176
 177        ret = devm_request_threaded_irq(tps->dev, irq, NULL,
 178                                        tps65217_irq_thread, IRQF_ONESHOT,
 179                                        "tps65217-irq", tps);
 180        if (ret) {
 181                dev_err(tps->dev, "Failed to request IRQ %d: %d\n",
 182                        irq, ret);
 183                return ret;
 184        }
 185
 186        enable_irq_wake(irq);
 187
 188        return 0;
 189}
 190
 191/**
 192 * tps65217_reg_read: Read a single tps65217 register.
 193 *
 194 * @tps: Device to read from.
 195 * @reg: Register to read.
 196 * @val: Contians the value
 197 */
 198int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
 199                        unsigned int *val)
 200{
 201        return regmap_read(tps->regmap, reg, val);
 202}
 203EXPORT_SYMBOL_GPL(tps65217_reg_read);
 204
 205/**
 206 * tps65217_reg_write: Write a single tps65217 register.
 207 *
 208 * @tps65217: Device to write to.
 209 * @reg: Register to write to.
 210 * @val: Value to write.
 211 * @level: Password protected level
 212 */
 213int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,
 214                        unsigned int val, unsigned int level)
 215{
 216        int ret;
 217        unsigned int xor_reg_val;
 218
 219        switch (level) {
 220        case TPS65217_PROTECT_NONE:
 221                return regmap_write(tps->regmap, reg, val);
 222        case TPS65217_PROTECT_L1:
 223                xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK;
 224                ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
 225                                                        xor_reg_val);
 226                if (ret < 0)
 227                        return ret;
 228
 229                return regmap_write(tps->regmap, reg, val);
 230        case TPS65217_PROTECT_L2:
 231                xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK;
 232                ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
 233                                                        xor_reg_val);
 234                if (ret < 0)
 235                        return ret;
 236                ret = regmap_write(tps->regmap, reg, val);
 237                if (ret < 0)
 238                        return ret;
 239                ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
 240                                                        xor_reg_val);
 241                if (ret < 0)
 242                        return ret;
 243                return regmap_write(tps->regmap, reg, val);
 244        default:
 245                return -EINVAL;
 246        }
 247}
 248EXPORT_SYMBOL_GPL(tps65217_reg_write);
 249
 250/**
 251 * tps65217_update_bits: Modify bits w.r.t mask, val and level.
 252 *
 253 * @tps65217: Device to write to.
 254 * @reg: Register to read-write to.
 255 * @mask: Mask.
 256 * @val: Value to write.
 257 * @level: Password protected level
 258 */
 259static int tps65217_update_bits(struct tps65217 *tps, unsigned int reg,
 260                unsigned int mask, unsigned int val, unsigned int level)
 261{
 262        int ret;
 263        unsigned int data;
 264
 265        ret = tps65217_reg_read(tps, reg, &data);
 266        if (ret) {
 267                dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
 268                return ret;
 269        }
 270
 271        data &= ~mask;
 272        data |= val & mask;
 273
 274        ret = tps65217_reg_write(tps, reg, data, level);
 275        if (ret)
 276                dev_err(tps->dev, "Write for reg 0x%x failed\n", reg);
 277
 278        return ret;
 279}
 280
 281int tps65217_set_bits(struct tps65217 *tps, unsigned int reg,
 282                unsigned int mask, unsigned int val, unsigned int level)
 283{
 284        return tps65217_update_bits(tps, reg, mask, val, level);
 285}
 286EXPORT_SYMBOL_GPL(tps65217_set_bits);
 287
 288int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
 289                unsigned int mask, unsigned int level)
 290{
 291        return tps65217_update_bits(tps, reg, mask, 0, level);
 292}
 293EXPORT_SYMBOL_GPL(tps65217_clear_bits);
 294
 295static bool tps65217_volatile_reg(struct device *dev, unsigned int reg)
 296{
 297        switch (reg) {
 298        case TPS65217_REG_INT:
 299                return true;
 300        default:
 301                return false;
 302        }
 303}
 304
 305static const struct regmap_config tps65217_regmap_config = {
 306        .reg_bits = 8,
 307        .val_bits = 8,
 308
 309        .max_register = TPS65217_REG_MAX,
 310        .volatile_reg = tps65217_volatile_reg,
 311};
 312
 313static const struct of_device_id tps65217_of_match[] = {
 314        { .compatible = "ti,tps65217"},
 315        { /* sentinel */ },
 316};
 317MODULE_DEVICE_TABLE(of, tps65217_of_match);
 318
 319static int tps65217_probe(struct i2c_client *client)
 320{
 321        struct tps65217 *tps;
 322        unsigned int version;
 323        bool status_off = false;
 324        int ret;
 325
 326        status_off = of_property_read_bool(client->dev.of_node,
 327                                           "ti,pmic-shutdown-controller");
 328
 329        tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
 330        if (!tps)
 331                return -ENOMEM;
 332
 333        i2c_set_clientdata(client, tps);
 334        tps->dev = &client->dev;
 335
 336        tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config);
 337        if (IS_ERR(tps->regmap)) {
 338                ret = PTR_ERR(tps->regmap);
 339                dev_err(tps->dev, "Failed to allocate register map: %d\n",
 340                        ret);
 341                return ret;
 342        }
 343
 344        if (client->irq) {
 345                tps65217_irq_init(tps, client->irq);
 346        } else {
 347                int i;
 348
 349                /* Don't tell children about IRQ resources which won't fire */
 350                for (i = 0; i < ARRAY_SIZE(tps65217s); i++)
 351                        tps65217s[i].num_resources = 0;
 352        }
 353
 354        ret = devm_mfd_add_devices(tps->dev, -1, tps65217s,
 355                                   ARRAY_SIZE(tps65217s), NULL, 0,
 356                                   tps->irq_domain);
 357        if (ret < 0) {
 358                dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret);
 359                return ret;
 360        }
 361
 362        ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version);
 363        if (ret < 0) {
 364                dev_err(tps->dev, "Failed to read revision register: %d\n",
 365                        ret);
 366                return ret;
 367        }
 368
 369        /* Set the PMIC to shutdown on PWR_EN toggle */
 370        if (status_off) {
 371                ret = tps65217_set_bits(tps, TPS65217_REG_STATUS,
 372                                TPS65217_STATUS_OFF, TPS65217_STATUS_OFF,
 373                                TPS65217_PROTECT_NONE);
 374                if (ret)
 375                        dev_warn(tps->dev, "unable to set the status OFF\n");
 376        }
 377
 378        dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n",
 379                        (version & TPS65217_CHIPID_CHIP_MASK) >> 4,
 380                        version & TPS65217_CHIPID_REV_MASK);
 381
 382        return 0;
 383}
 384
 385static int tps65217_remove(struct i2c_client *client)
 386{
 387        struct tps65217 *tps = i2c_get_clientdata(client);
 388        unsigned int virq;
 389        int i;
 390
 391        for (i = 0; i < TPS65217_NUM_IRQ; i++) {
 392                virq = irq_find_mapping(tps->irq_domain, i);
 393                if (virq)
 394                        irq_dispose_mapping(virq);
 395        }
 396
 397        irq_domain_remove(tps->irq_domain);
 398        tps->irq_domain = NULL;
 399
 400        return 0;
 401}
 402
 403static const struct i2c_device_id tps65217_id_table[] = {
 404        {"tps65217", TPS65217},
 405        { /* sentinel */ }
 406};
 407MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
 408
 409static struct i2c_driver tps65217_driver = {
 410        .driver         = {
 411                .name   = "tps65217",
 412                .of_match_table = tps65217_of_match,
 413        },
 414        .id_table       = tps65217_id_table,
 415        .probe_new      = tps65217_probe,
 416        .remove         = tps65217_remove,
 417};
 418
 419static int __init tps65217_init(void)
 420{
 421        return i2c_add_driver(&tps65217_driver);
 422}
 423subsys_initcall(tps65217_init);
 424
 425static void __exit tps65217_exit(void)
 426{
 427        i2c_del_driver(&tps65217_driver);
 428}
 429module_exit(tps65217_exit);
 430
 431MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>");
 432MODULE_DESCRIPTION("TPS65217 chip family multi-function driver");
 433MODULE_LICENSE("GPL v2");
 434