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", .data = (void *)TPS65217 },
 315        { /* sentinel */ },
 316};
 317MODULE_DEVICE_TABLE(of, tps65217_of_match);
 318
 319static int tps65217_probe(struct i2c_client *client,
 320                                const struct i2c_device_id *ids)
 321{
 322        struct tps65217 *tps;
 323        unsigned int version;
 324        unsigned long chip_id = ids->driver_data;
 325        const struct of_device_id *match;
 326        bool status_off = false;
 327        int ret;
 328
 329        if (client->dev.of_node) {
 330                match = of_match_device(tps65217_of_match, &client->dev);
 331                if (!match) {
 332                        dev_err(&client->dev,
 333                                "Failed to find matching dt id\n");
 334                        return -EINVAL;
 335                }
 336                chip_id = (unsigned long)match->data;
 337                status_off = of_property_read_bool(client->dev.of_node,
 338                                        "ti,pmic-shutdown-controller");
 339        }
 340
 341        if (!chip_id) {
 342                dev_err(&client->dev, "id is null.\n");
 343                return -ENODEV;
 344        }
 345
 346        tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
 347        if (!tps)
 348                return -ENOMEM;
 349
 350        i2c_set_clientdata(client, tps);
 351        tps->dev = &client->dev;
 352        tps->id = chip_id;
 353
 354        tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config);
 355        if (IS_ERR(tps->regmap)) {
 356                ret = PTR_ERR(tps->regmap);
 357                dev_err(tps->dev, "Failed to allocate register map: %d\n",
 358                        ret);
 359                return ret;
 360        }
 361
 362        if (client->irq) {
 363                tps65217_irq_init(tps, client->irq);
 364        } else {
 365                int i;
 366
 367                /* Don't tell children about IRQ resources which won't fire */
 368                for (i = 0; i < ARRAY_SIZE(tps65217s); i++)
 369                        tps65217s[i].num_resources = 0;
 370        }
 371
 372        ret = devm_mfd_add_devices(tps->dev, -1, tps65217s,
 373                                   ARRAY_SIZE(tps65217s), NULL, 0,
 374                                   tps->irq_domain);
 375        if (ret < 0) {
 376                dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret);
 377                return ret;
 378        }
 379
 380        ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version);
 381        if (ret < 0) {
 382                dev_err(tps->dev, "Failed to read revision register: %d\n",
 383                        ret);
 384                return ret;
 385        }
 386
 387        /* Set the PMIC to shutdown on PWR_EN toggle */
 388        if (status_off) {
 389                ret = tps65217_set_bits(tps, TPS65217_REG_STATUS,
 390                                TPS65217_STATUS_OFF, TPS65217_STATUS_OFF,
 391                                TPS65217_PROTECT_NONE);
 392                if (ret)
 393                        dev_warn(tps->dev, "unable to set the status OFF\n");
 394        }
 395
 396        dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n",
 397                        (version & TPS65217_CHIPID_CHIP_MASK) >> 4,
 398                        version & TPS65217_CHIPID_REV_MASK);
 399
 400        return 0;
 401}
 402
 403static int tps65217_remove(struct i2c_client *client)
 404{
 405        struct tps65217 *tps = i2c_get_clientdata(client);
 406        unsigned int virq;
 407        int i;
 408
 409        for (i = 0; i < TPS65217_NUM_IRQ; i++) {
 410                virq = irq_find_mapping(tps->irq_domain, i);
 411                if (virq)
 412                        irq_dispose_mapping(virq);
 413        }
 414
 415        irq_domain_remove(tps->irq_domain);
 416        tps->irq_domain = NULL;
 417
 418        return 0;
 419}
 420
 421static const struct i2c_device_id tps65217_id_table[] = {
 422        {"tps65217", TPS65217},
 423        { /* sentinel */ }
 424};
 425MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
 426
 427static struct i2c_driver tps65217_driver = {
 428        .driver         = {
 429                .name   = "tps65217",
 430                .of_match_table = tps65217_of_match,
 431        },
 432        .id_table       = tps65217_id_table,
 433        .probe          = tps65217_probe,
 434        .remove         = tps65217_remove,
 435};
 436
 437static int __init tps65217_init(void)
 438{
 439        return i2c_add_driver(&tps65217_driver);
 440}
 441subsys_initcall(tps65217_init);
 442
 443static void __exit tps65217_exit(void)
 444{
 445        i2c_del_driver(&tps65217_driver);
 446}
 447module_exit(tps65217_exit);
 448
 449MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>");
 450MODULE_DESCRIPTION("TPS65217 chip family multi-function driver");
 451MODULE_LICENSE("GPL v2");
 452