12aec85b2SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2d48f411cSAnilKumar Ch /* 3d48f411cSAnilKumar Ch * tps65217.c 4d48f411cSAnilKumar Ch * 5d48f411cSAnilKumar Ch * TPS65217 chip family multi-function driver 6d48f411cSAnilKumar Ch * 74f4ed454SAlexander A. Klimov * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/ 8d48f411cSAnilKumar Ch */ 9d48f411cSAnilKumar Ch 10d48f411cSAnilKumar Ch #include <linux/device.h> 11d48f411cSAnilKumar Ch #include <linux/err.h> 126556bdacSMarcin Niestroj #include <linux/init.h> 136556bdacSMarcin Niestroj #include <linux/interrupt.h> 146556bdacSMarcin Niestroj #include <linux/i2c.h> 156556bdacSMarcin Niestroj #include <linux/irq.h> 166556bdacSMarcin Niestroj #include <linux/irqdomain.h> 176556bdacSMarcin Niestroj #include <linux/kernel.h> 186556bdacSMarcin Niestroj #include <linux/module.h> 19817bb7fbSAnilKumar Ch #include <linux/of.h> 20817bb7fbSAnilKumar Ch #include <linux/of_device.h> 216556bdacSMarcin Niestroj #include <linux/platform_device.h> 226556bdacSMarcin Niestroj #include <linux/regmap.h> 236556bdacSMarcin Niestroj #include <linux/slab.h> 24d48f411cSAnilKumar Ch 25d48f411cSAnilKumar Ch #include <linux/mfd/core.h> 26d48f411cSAnilKumar Ch #include <linux/mfd/tps65217.h> 27d48f411cSAnilKumar Ch 280aefed0eSRikard Falkeborn static const struct resource charger_resources[] = { 296556bdacSMarcin Niestroj DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_AC, "AC"), 306556bdacSMarcin Niestroj DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_USB, "USB"), 316556bdacSMarcin Niestroj }; 326556bdacSMarcin Niestroj 330aefed0eSRikard Falkeborn static const struct resource pb_resources[] = { 34dea9c730SMarcin Niestroj DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_PB, "PB"), 35dea9c730SMarcin Niestroj }; 36dea9c730SMarcin Niestroj 376556bdacSMarcin Niestroj static void tps65217_irq_lock(struct irq_data *data) 386556bdacSMarcin Niestroj { 396556bdacSMarcin Niestroj struct tps65217 *tps = irq_data_get_irq_chip_data(data); 406556bdacSMarcin Niestroj 416556bdacSMarcin Niestroj mutex_lock(&tps->irq_lock); 426556bdacSMarcin Niestroj } 436556bdacSMarcin Niestroj 446556bdacSMarcin Niestroj static void tps65217_irq_sync_unlock(struct irq_data *data) 456556bdacSMarcin Niestroj { 466556bdacSMarcin Niestroj struct tps65217 *tps = irq_data_get_irq_chip_data(data); 476556bdacSMarcin Niestroj int ret; 486556bdacSMarcin Niestroj 49fa917052SMilo Kim ret = tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK, 50fa917052SMilo Kim tps->irq_mask, TPS65217_PROTECT_NONE); 516556bdacSMarcin Niestroj if (ret != 0) 526556bdacSMarcin Niestroj dev_err(tps->dev, "Failed to sync IRQ masks\n"); 536556bdacSMarcin Niestroj 546556bdacSMarcin Niestroj mutex_unlock(&tps->irq_lock); 556556bdacSMarcin Niestroj } 566556bdacSMarcin Niestroj 576556bdacSMarcin Niestroj static void tps65217_irq_enable(struct irq_data *data) 586556bdacSMarcin Niestroj { 596556bdacSMarcin Niestroj struct tps65217 *tps = irq_data_get_irq_chip_data(data); 60fa917052SMilo Kim u8 mask = BIT(data->hwirq) << TPS65217_INT_SHIFT; 616556bdacSMarcin Niestroj 62fa917052SMilo Kim tps->irq_mask &= ~mask; 636556bdacSMarcin Niestroj } 646556bdacSMarcin Niestroj 656556bdacSMarcin Niestroj static void tps65217_irq_disable(struct irq_data *data) 666556bdacSMarcin Niestroj { 676556bdacSMarcin Niestroj struct tps65217 *tps = irq_data_get_irq_chip_data(data); 68fa917052SMilo Kim u8 mask = BIT(data->hwirq) << TPS65217_INT_SHIFT; 696556bdacSMarcin Niestroj 70fa917052SMilo Kim tps->irq_mask |= mask; 716556bdacSMarcin Niestroj } 726556bdacSMarcin Niestroj 736556bdacSMarcin Niestroj static struct irq_chip tps65217_irq_chip = { 74f6602064SMilo Kim .name = "tps65217", 756556bdacSMarcin Niestroj .irq_bus_lock = tps65217_irq_lock, 766556bdacSMarcin Niestroj .irq_bus_sync_unlock = tps65217_irq_sync_unlock, 776556bdacSMarcin Niestroj .irq_enable = tps65217_irq_enable, 786556bdacSMarcin Niestroj .irq_disable = tps65217_irq_disable, 796556bdacSMarcin Niestroj }; 806556bdacSMarcin Niestroj 816556bdacSMarcin Niestroj static struct mfd_cell tps65217s[] = { 82817bb7fbSAnilKumar Ch { 83817bb7fbSAnilKumar Ch .name = "tps65217-pmic", 8411d0d300SJohannes Pointner .of_compatible = "ti,tps65217-pmic", 85817bb7fbSAnilKumar Ch }, 86b6290ffeSMatthias Kaehlcke { 87b6290ffeSMatthias Kaehlcke .name = "tps65217-bl", 8811d0d300SJohannes Pointner .of_compatible = "ti,tps65217-bl", 89b6290ffeSMatthias Kaehlcke }, 9055cec67aSEnric Balletbo i Serra { 9155cec67aSEnric Balletbo i Serra .name = "tps65217-charger", 926556bdacSMarcin Niestroj .num_resources = ARRAY_SIZE(charger_resources), 936556bdacSMarcin Niestroj .resources = charger_resources, 9455cec67aSEnric Balletbo i Serra .of_compatible = "ti,tps65217-charger", 9555cec67aSEnric Balletbo i Serra }, 96dea9c730SMarcin Niestroj { 97dea9c730SMarcin Niestroj .name = "tps65217-pwrbutton", 98dea9c730SMarcin Niestroj .num_resources = ARRAY_SIZE(pb_resources), 99dea9c730SMarcin Niestroj .resources = pb_resources, 100dea9c730SMarcin Niestroj .of_compatible = "ti,tps65217-pwrbutton", 101dea9c730SMarcin Niestroj }, 102817bb7fbSAnilKumar Ch }; 103817bb7fbSAnilKumar Ch 1046556bdacSMarcin Niestroj static irqreturn_t tps65217_irq_thread(int irq, void *data) 1056556bdacSMarcin Niestroj { 1066556bdacSMarcin Niestroj struct tps65217 *tps = data; 1076556bdacSMarcin Niestroj unsigned int status; 1086556bdacSMarcin Niestroj bool handled = false; 1096556bdacSMarcin Niestroj int i; 1106556bdacSMarcin Niestroj int ret; 1116556bdacSMarcin Niestroj 1126556bdacSMarcin Niestroj ret = tps65217_reg_read(tps, TPS65217_REG_INT, &status); 1136556bdacSMarcin Niestroj if (ret < 0) { 1146556bdacSMarcin Niestroj dev_err(tps->dev, "Failed to read IRQ status: %d\n", 1156556bdacSMarcin Niestroj ret); 1166556bdacSMarcin Niestroj return IRQ_NONE; 1176556bdacSMarcin Niestroj } 1186556bdacSMarcin Niestroj 119fa917052SMilo Kim for (i = 0; i < TPS65217_NUM_IRQ; i++) { 120fa917052SMilo Kim if (status & BIT(i)) { 1216556bdacSMarcin Niestroj handle_nested_irq(irq_find_mapping(tps->irq_domain, i)); 1226556bdacSMarcin Niestroj handled = true; 1236556bdacSMarcin Niestroj } 1246556bdacSMarcin Niestroj } 1256556bdacSMarcin Niestroj 1266556bdacSMarcin Niestroj if (handled) 1276556bdacSMarcin Niestroj return IRQ_HANDLED; 1286556bdacSMarcin Niestroj 1296556bdacSMarcin Niestroj return IRQ_NONE; 1306556bdacSMarcin Niestroj } 1316556bdacSMarcin Niestroj 1326556bdacSMarcin Niestroj static int tps65217_irq_map(struct irq_domain *h, unsigned int virq, 1336556bdacSMarcin Niestroj irq_hw_number_t hw) 1346556bdacSMarcin Niestroj { 1356556bdacSMarcin Niestroj struct tps65217 *tps = h->host_data; 1366556bdacSMarcin Niestroj 1376556bdacSMarcin Niestroj irq_set_chip_data(virq, tps); 1386556bdacSMarcin Niestroj irq_set_chip_and_handler(virq, &tps65217_irq_chip, handle_edge_irq); 1396556bdacSMarcin Niestroj irq_set_nested_thread(virq, 1); 1406556bdacSMarcin Niestroj irq_set_parent(virq, tps->irq); 1416556bdacSMarcin Niestroj irq_set_noprobe(virq); 1426556bdacSMarcin Niestroj 1436556bdacSMarcin Niestroj return 0; 1446556bdacSMarcin Niestroj } 1456556bdacSMarcin Niestroj 1466556bdacSMarcin Niestroj static const struct irq_domain_ops tps65217_irq_domain_ops = { 1476556bdacSMarcin Niestroj .map = tps65217_irq_map, 1486556bdacSMarcin Niestroj }; 1496556bdacSMarcin Niestroj 1506556bdacSMarcin Niestroj static int tps65217_irq_init(struct tps65217 *tps, int irq) 1516556bdacSMarcin Niestroj { 1526556bdacSMarcin Niestroj int ret; 1536556bdacSMarcin Niestroj 1546556bdacSMarcin Niestroj mutex_init(&tps->irq_lock); 1556556bdacSMarcin Niestroj tps->irq = irq; 1566556bdacSMarcin Niestroj 1576556bdacSMarcin Niestroj /* Mask all interrupt sources */ 1586d2c2b9fSMilo Kim tps->irq_mask = TPS65217_INT_MASK; 1596d2c2b9fSMilo Kim tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK, 1606d2c2b9fSMilo Kim TPS65217_INT_MASK, TPS65217_PROTECT_NONE); 1616556bdacSMarcin Niestroj 1626556bdacSMarcin Niestroj tps->irq_domain = irq_domain_add_linear(tps->dev->of_node, 1636556bdacSMarcin Niestroj TPS65217_NUM_IRQ, &tps65217_irq_domain_ops, tps); 1646556bdacSMarcin Niestroj if (!tps->irq_domain) { 1656556bdacSMarcin Niestroj dev_err(tps->dev, "Could not create IRQ domain\n"); 1666556bdacSMarcin Niestroj return -ENOMEM; 1676556bdacSMarcin Niestroj } 1686556bdacSMarcin Niestroj 1696556bdacSMarcin Niestroj ret = devm_request_threaded_irq(tps->dev, irq, NULL, 1706556bdacSMarcin Niestroj tps65217_irq_thread, IRQF_ONESHOT, 1716556bdacSMarcin Niestroj "tps65217-irq", tps); 1726556bdacSMarcin Niestroj if (ret) { 1736556bdacSMarcin Niestroj dev_err(tps->dev, "Failed to request IRQ %d: %d\n", 1746556bdacSMarcin Niestroj irq, ret); 1756556bdacSMarcin Niestroj return ret; 1766556bdacSMarcin Niestroj } 1776556bdacSMarcin Niestroj 17893559191SMilo Kim enable_irq_wake(irq); 17993559191SMilo Kim 1806556bdacSMarcin Niestroj return 0; 1816556bdacSMarcin Niestroj } 1826556bdacSMarcin Niestroj 183d48f411cSAnilKumar Ch /** 184d48f411cSAnilKumar Ch * tps65217_reg_read: Read a single tps65217 register. 185d48f411cSAnilKumar Ch * 186d48f411cSAnilKumar Ch * @tps: Device to read from. 187d48f411cSAnilKumar Ch * @reg: Register to read. 188d48f411cSAnilKumar Ch * @val: Contians the value 189d48f411cSAnilKumar Ch */ 190d48f411cSAnilKumar Ch int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, 191d48f411cSAnilKumar Ch unsigned int *val) 192d48f411cSAnilKumar Ch { 193d48f411cSAnilKumar Ch return regmap_read(tps->regmap, reg, val); 194d48f411cSAnilKumar Ch } 195d48f411cSAnilKumar Ch EXPORT_SYMBOL_GPL(tps65217_reg_read); 196d48f411cSAnilKumar Ch 197d48f411cSAnilKumar Ch /** 198d48f411cSAnilKumar Ch * tps65217_reg_write: Write a single tps65217 register. 199d48f411cSAnilKumar Ch * 2004976bfb8SLee Jones * @tps: Device to write to. 201d48f411cSAnilKumar Ch * @reg: Register to write to. 202d48f411cSAnilKumar Ch * @val: Value to write. 203d48f411cSAnilKumar Ch * @level: Password protected level 204d48f411cSAnilKumar Ch */ 205d48f411cSAnilKumar Ch int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, 206d48f411cSAnilKumar Ch unsigned int val, unsigned int level) 207d48f411cSAnilKumar Ch { 208d48f411cSAnilKumar Ch int ret; 209d48f411cSAnilKumar Ch unsigned int xor_reg_val; 210d48f411cSAnilKumar Ch 211d48f411cSAnilKumar Ch switch (level) { 212d48f411cSAnilKumar Ch case TPS65217_PROTECT_NONE: 213d48f411cSAnilKumar Ch return regmap_write(tps->regmap, reg, val); 214d48f411cSAnilKumar Ch case TPS65217_PROTECT_L1: 215d48f411cSAnilKumar Ch xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK; 216d48f411cSAnilKumar Ch ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, 217d48f411cSAnilKumar Ch xor_reg_val); 218d48f411cSAnilKumar Ch if (ret < 0) 219d48f411cSAnilKumar Ch return ret; 220d48f411cSAnilKumar Ch 221d48f411cSAnilKumar Ch return regmap_write(tps->regmap, reg, val); 222d48f411cSAnilKumar Ch case TPS65217_PROTECT_L2: 223d48f411cSAnilKumar Ch xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK; 224d48f411cSAnilKumar Ch ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, 225d48f411cSAnilKumar Ch xor_reg_val); 226d48f411cSAnilKumar Ch if (ret < 0) 227d48f411cSAnilKumar Ch return ret; 228d48f411cSAnilKumar Ch ret = regmap_write(tps->regmap, reg, val); 229d48f411cSAnilKumar Ch if (ret < 0) 230d48f411cSAnilKumar Ch return ret; 231d48f411cSAnilKumar Ch ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, 232d48f411cSAnilKumar Ch xor_reg_val); 233d48f411cSAnilKumar Ch if (ret < 0) 234d48f411cSAnilKumar Ch return ret; 235d48f411cSAnilKumar Ch return regmap_write(tps->regmap, reg, val); 236d48f411cSAnilKumar Ch default: 237d48f411cSAnilKumar Ch return -EINVAL; 238d48f411cSAnilKumar Ch } 239d48f411cSAnilKumar Ch } 240d48f411cSAnilKumar Ch EXPORT_SYMBOL_GPL(tps65217_reg_write); 241d48f411cSAnilKumar Ch 242d48f411cSAnilKumar Ch /** 243d48f411cSAnilKumar Ch * tps65217_update_bits: Modify bits w.r.t mask, val and level. 244d48f411cSAnilKumar Ch * 2454976bfb8SLee Jones * @tps: Device to write to. 246d48f411cSAnilKumar Ch * @reg: Register to read-write to. 247d48f411cSAnilKumar Ch * @mask: Mask. 248d48f411cSAnilKumar Ch * @val: Value to write. 249d48f411cSAnilKumar Ch * @level: Password protected level 250d48f411cSAnilKumar Ch */ 25127757e82SMark Brown static int tps65217_update_bits(struct tps65217 *tps, unsigned int reg, 252d48f411cSAnilKumar Ch unsigned int mask, unsigned int val, unsigned int level) 253d48f411cSAnilKumar Ch { 254d48f411cSAnilKumar Ch int ret; 255d48f411cSAnilKumar Ch unsigned int data; 256d48f411cSAnilKumar Ch 257d48f411cSAnilKumar Ch ret = tps65217_reg_read(tps, reg, &data); 258d48f411cSAnilKumar Ch if (ret) { 259d48f411cSAnilKumar Ch dev_err(tps->dev, "Read from reg 0x%x failed\n", reg); 260d48f411cSAnilKumar Ch return ret; 261d48f411cSAnilKumar Ch } 262d48f411cSAnilKumar Ch 263d48f411cSAnilKumar Ch data &= ~mask; 264d48f411cSAnilKumar Ch data |= val & mask; 265d48f411cSAnilKumar Ch 266d48f411cSAnilKumar Ch ret = tps65217_reg_write(tps, reg, data, level); 267d48f411cSAnilKumar Ch if (ret) 268d48f411cSAnilKumar Ch dev_err(tps->dev, "Write for reg 0x%x failed\n", reg); 269d48f411cSAnilKumar Ch 270d48f411cSAnilKumar Ch return ret; 271d48f411cSAnilKumar Ch } 272d48f411cSAnilKumar Ch 273d48f411cSAnilKumar Ch int tps65217_set_bits(struct tps65217 *tps, unsigned int reg, 274d48f411cSAnilKumar Ch unsigned int mask, unsigned int val, unsigned int level) 275d48f411cSAnilKumar Ch { 276d48f411cSAnilKumar Ch return tps65217_update_bits(tps, reg, mask, val, level); 277d48f411cSAnilKumar Ch } 278d48f411cSAnilKumar Ch EXPORT_SYMBOL_GPL(tps65217_set_bits); 279d48f411cSAnilKumar Ch 280d48f411cSAnilKumar Ch int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, 281d48f411cSAnilKumar Ch unsigned int mask, unsigned int level) 282d48f411cSAnilKumar Ch { 283d48f411cSAnilKumar Ch return tps65217_update_bits(tps, reg, mask, 0, level); 284d48f411cSAnilKumar Ch } 285d48f411cSAnilKumar Ch EXPORT_SYMBOL_GPL(tps65217_clear_bits); 286d48f411cSAnilKumar Ch 2876556bdacSMarcin Niestroj static bool tps65217_volatile_reg(struct device *dev, unsigned int reg) 2886556bdacSMarcin Niestroj { 2896556bdacSMarcin Niestroj switch (reg) { 2906556bdacSMarcin Niestroj case TPS65217_REG_INT: 2916556bdacSMarcin Niestroj return true; 2926556bdacSMarcin Niestroj default: 2936556bdacSMarcin Niestroj return false; 2946556bdacSMarcin Niestroj } 2956556bdacSMarcin Niestroj } 2966556bdacSMarcin Niestroj 297af0a837dSKrzysztof Kozlowski static const struct regmap_config tps65217_regmap_config = { 298d48f411cSAnilKumar Ch .reg_bits = 8, 299d48f411cSAnilKumar Ch .val_bits = 8, 3000b496b4cSMark Brown 3010b496b4cSMark Brown .max_register = TPS65217_REG_MAX, 3026556bdacSMarcin Niestroj .volatile_reg = tps65217_volatile_reg, 303d48f411cSAnilKumar Ch }; 304d48f411cSAnilKumar Ch 305817bb7fbSAnilKumar Ch static const struct of_device_id tps65217_of_match[] = { 306511cb174SKeerthy { .compatible = "ti,tps65217"}, 307817bb7fbSAnilKumar Ch { /* sentinel */ }, 308817bb7fbSAnilKumar Ch }; 3094895e493SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, tps65217_of_match); 310817bb7fbSAnilKumar Ch 311511cb174SKeerthy static int tps65217_probe(struct i2c_client *client) 312d48f411cSAnilKumar Ch { 313d48f411cSAnilKumar Ch struct tps65217 *tps; 314d48f411cSAnilKumar Ch unsigned int version; 315eb433dadSColin Foe-Parker bool status_off = false; 316817bb7fbSAnilKumar Ch int ret; 317d48f411cSAnilKumar Ch 318eb433dadSColin Foe-Parker status_off = of_property_read_bool(client->dev.of_node, 319eb433dadSColin Foe-Parker "ti,pmic-shutdown-controller"); 320a7f1b63eSAnilKumar Ch 321d48f411cSAnilKumar Ch tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); 322d48f411cSAnilKumar Ch if (!tps) 323d48f411cSAnilKumar Ch return -ENOMEM; 324d48f411cSAnilKumar Ch 325817bb7fbSAnilKumar Ch i2c_set_clientdata(client, tps); 326817bb7fbSAnilKumar Ch tps->dev = &client->dev; 327817bb7fbSAnilKumar Ch 3280ef4619cSAxel Lin tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config); 329d48f411cSAnilKumar Ch if (IS_ERR(tps->regmap)) { 330d48f411cSAnilKumar Ch ret = PTR_ERR(tps->regmap); 331d48f411cSAnilKumar Ch dev_err(tps->dev, "Failed to allocate register map: %d\n", 332d48f411cSAnilKumar Ch ret); 333d48f411cSAnilKumar Ch return ret; 334d48f411cSAnilKumar Ch } 335d48f411cSAnilKumar Ch 3366556bdacSMarcin Niestroj if (client->irq) { 3376556bdacSMarcin Niestroj tps65217_irq_init(tps, client->irq); 3386556bdacSMarcin Niestroj } else { 3396556bdacSMarcin Niestroj int i; 3406556bdacSMarcin Niestroj 3416556bdacSMarcin Niestroj /* Don't tell children about IRQ resources which won't fire */ 3426556bdacSMarcin Niestroj for (i = 0; i < ARRAY_SIZE(tps65217s); i++) 3436556bdacSMarcin Niestroj tps65217s[i].num_resources = 0; 3446556bdacSMarcin Niestroj } 3456556bdacSMarcin Niestroj 346b89b6b6bSLaxman Dewangan ret = devm_mfd_add_devices(tps->dev, -1, tps65217s, 3476556bdacSMarcin Niestroj ARRAY_SIZE(tps65217s), NULL, 0, 3486556bdacSMarcin Niestroj tps->irq_domain); 349817bb7fbSAnilKumar Ch if (ret < 0) { 350817bb7fbSAnilKumar Ch dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); 351817bb7fbSAnilKumar Ch return ret; 352817bb7fbSAnilKumar Ch } 353d48f411cSAnilKumar Ch 354d48f411cSAnilKumar Ch ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); 355d48f411cSAnilKumar Ch if (ret < 0) { 3560ef4619cSAxel Lin dev_err(tps->dev, "Failed to read revision register: %d\n", 3570ef4619cSAxel Lin ret); 3580ef4619cSAxel Lin return ret; 359d48f411cSAnilKumar Ch } 360d48f411cSAnilKumar Ch 361eb433dadSColin Foe-Parker /* Set the PMIC to shutdown on PWR_EN toggle */ 362eb433dadSColin Foe-Parker if (status_off) { 363eb433dadSColin Foe-Parker ret = tps65217_set_bits(tps, TPS65217_REG_STATUS, 364eb433dadSColin Foe-Parker TPS65217_STATUS_OFF, TPS65217_STATUS_OFF, 365eb433dadSColin Foe-Parker TPS65217_PROTECT_NONE); 366eb433dadSColin Foe-Parker if (ret) 367eb433dadSColin Foe-Parker dev_warn(tps->dev, "unable to set the status OFF\n"); 368eb433dadSColin Foe-Parker } 369eb433dadSColin Foe-Parker 370d48f411cSAnilKumar Ch dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n", 371d48f411cSAnilKumar Ch (version & TPS65217_CHIPID_CHIP_MASK) >> 4, 372d48f411cSAnilKumar Ch version & TPS65217_CHIPID_REV_MASK); 373d48f411cSAnilKumar Ch 374d48f411cSAnilKumar Ch return 0; 375d48f411cSAnilKumar Ch } 376d48f411cSAnilKumar Ch 377*ed5c2f5fSUwe Kleine-König static void tps65217_remove(struct i2c_client *client) 37840a50f8bSMilo Kim { 37940a50f8bSMilo Kim struct tps65217 *tps = i2c_get_clientdata(client); 38040a50f8bSMilo Kim unsigned int virq; 38140a50f8bSMilo Kim int i; 38240a50f8bSMilo Kim 383fa917052SMilo Kim for (i = 0; i < TPS65217_NUM_IRQ; i++) { 38440a50f8bSMilo Kim virq = irq_find_mapping(tps->irq_domain, i); 38540a50f8bSMilo Kim if (virq) 38640a50f8bSMilo Kim irq_dispose_mapping(virq); 38740a50f8bSMilo Kim } 38840a50f8bSMilo Kim 38940a50f8bSMilo Kim irq_domain_remove(tps->irq_domain); 39040a50f8bSMilo Kim tps->irq_domain = NULL; 39140a50f8bSMilo Kim } 39240a50f8bSMilo Kim 393d48f411cSAnilKumar Ch static const struct i2c_device_id tps65217_id_table[] = { 394817bb7fbSAnilKumar Ch {"tps65217", TPS65217}, 395817bb7fbSAnilKumar Ch { /* sentinel */ } 396d48f411cSAnilKumar Ch }; 397d48f411cSAnilKumar Ch MODULE_DEVICE_TABLE(i2c, tps65217_id_table); 398d48f411cSAnilKumar Ch 399d48f411cSAnilKumar Ch static struct i2c_driver tps65217_driver = { 400d48f411cSAnilKumar Ch .driver = { 401d48f411cSAnilKumar Ch .name = "tps65217", 402a351451aSSachin Kamat .of_match_table = tps65217_of_match, 403d48f411cSAnilKumar Ch }, 404d48f411cSAnilKumar Ch .id_table = tps65217_id_table, 405511cb174SKeerthy .probe_new = tps65217_probe, 40640a50f8bSMilo Kim .remove = tps65217_remove, 407d48f411cSAnilKumar Ch }; 408d48f411cSAnilKumar Ch 409d48f411cSAnilKumar Ch static int __init tps65217_init(void) 410d48f411cSAnilKumar Ch { 411d48f411cSAnilKumar Ch return i2c_add_driver(&tps65217_driver); 412d48f411cSAnilKumar Ch } 413d48f411cSAnilKumar Ch subsys_initcall(tps65217_init); 414d48f411cSAnilKumar Ch 415d48f411cSAnilKumar Ch static void __exit tps65217_exit(void) 416d48f411cSAnilKumar Ch { 417d48f411cSAnilKumar Ch i2c_del_driver(&tps65217_driver); 418d48f411cSAnilKumar Ch } 419d48f411cSAnilKumar Ch module_exit(tps65217_exit); 420d48f411cSAnilKumar Ch 421d48f411cSAnilKumar Ch MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>"); 422d48f411cSAnilKumar Ch MODULE_DESCRIPTION("TPS65217 chip family multi-function driver"); 423d48f411cSAnilKumar Ch MODULE_LICENSE("GPL v2"); 424