1c6c19332SMike Rapoport /* 2c6c19332SMike Rapoport * Core driver for TI TPS6586x PMIC family 3c6c19332SMike Rapoport * 4c6c19332SMike Rapoport * Copyright (c) 2010 CompuLab Ltd. 5c6c19332SMike Rapoport * Mike Rapoport <mike@compulab.co.il> 6c6c19332SMike Rapoport * 7c6c19332SMike Rapoport * Based on da903x.c. 8c6c19332SMike Rapoport * Copyright (C) 2008 Compulab, Ltd. 9c6c19332SMike Rapoport * Mike Rapoport <mike@compulab.co.il> 10c6c19332SMike Rapoport * Copyright (C) 2006-2008 Marvell International Ltd. 11c6c19332SMike Rapoport * Eric Miao <eric.miao@marvell.com> 12c6c19332SMike Rapoport * 13c6c19332SMike Rapoport * This program is free software; you can redistribute it and/or modify 14c6c19332SMike Rapoport * it under the terms of the GNU General Public License version 2 as 15c6c19332SMike Rapoport * published by the Free Software Foundation. 16c6c19332SMike Rapoport */ 17c6c19332SMike Rapoport 18c26448c4SGary King #include <linux/interrupt.h> 19c26448c4SGary King #include <linux/irq.h> 20c6c19332SMike Rapoport #include <linux/kernel.h> 21c6c19332SMike Rapoport #include <linux/module.h> 22c6c19332SMike Rapoport #include <linux/mutex.h> 23c6c19332SMike Rapoport #include <linux/slab.h> 241176b5beSLaxman Dewangan #include <linux/err.h> 25c6c19332SMike Rapoport #include <linux/gpio.h> 26c6c19332SMike Rapoport #include <linux/i2c.h> 271176b5beSLaxman Dewangan #include <linux/regmap.h> 2862f6b087SThierry Reding #include <linux/regulator/of_regulator.h> 29c6c19332SMike Rapoport 30c6c19332SMike Rapoport #include <linux/mfd/core.h> 31c6c19332SMike Rapoport #include <linux/mfd/tps6586x.h> 32c6c19332SMike Rapoport 33c6c19332SMike Rapoport /* GPIO control registers */ 34c6c19332SMike Rapoport #define TPS6586X_GPIOSET1 0x5d 35c6c19332SMike Rapoport #define TPS6586X_GPIOSET2 0x5e 36c6c19332SMike Rapoport 37c26448c4SGary King /* interrupt control registers */ 38c26448c4SGary King #define TPS6586X_INT_ACK1 0xb5 39c26448c4SGary King #define TPS6586X_INT_ACK2 0xb6 40c26448c4SGary King #define TPS6586X_INT_ACK3 0xb7 41c26448c4SGary King #define TPS6586X_INT_ACK4 0xb8 42c26448c4SGary King 43c26448c4SGary King /* interrupt mask registers */ 44c26448c4SGary King #define TPS6586X_INT_MASK1 0xb0 45c26448c4SGary King #define TPS6586X_INT_MASK2 0xb1 46c26448c4SGary King #define TPS6586X_INT_MASK3 0xb2 47c26448c4SGary King #define TPS6586X_INT_MASK4 0xb3 48c26448c4SGary King #define TPS6586X_INT_MASK5 0xb4 49c26448c4SGary King 50c6c19332SMike Rapoport /* device id */ 51c6c19332SMike Rapoport #define TPS6586X_VERSIONCRC 0xcd 52c6c19332SMike Rapoport 531176b5beSLaxman Dewangan /* Maximum register */ 541176b5beSLaxman Dewangan #define TPS6586X_MAX_REGISTER (TPS6586X_VERSIONCRC + 1) 551176b5beSLaxman Dewangan 56c26448c4SGary King struct tps6586x_irq_data { 57c26448c4SGary King u8 mask_reg; 58c26448c4SGary King u8 mask_mask; 59c26448c4SGary King }; 60c26448c4SGary King 61c26448c4SGary King #define TPS6586X_IRQ(_reg, _mask) \ 62c26448c4SGary King { \ 63c26448c4SGary King .mask_reg = (_reg) - TPS6586X_INT_MASK1, \ 64c26448c4SGary King .mask_mask = (_mask), \ 65c26448c4SGary King } 66c26448c4SGary King 67c26448c4SGary King static const struct tps6586x_irq_data tps6586x_irqs[] = { 68c26448c4SGary King [TPS6586X_INT_PLDO_0] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 0), 69c26448c4SGary King [TPS6586X_INT_PLDO_1] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 1), 70c26448c4SGary King [TPS6586X_INT_PLDO_2] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 2), 71c26448c4SGary King [TPS6586X_INT_PLDO_3] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 3), 72c26448c4SGary King [TPS6586X_INT_PLDO_4] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 4), 73c26448c4SGary King [TPS6586X_INT_PLDO_5] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 5), 74c26448c4SGary King [TPS6586X_INT_PLDO_6] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 6), 75c26448c4SGary King [TPS6586X_INT_PLDO_7] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 7), 76c26448c4SGary King [TPS6586X_INT_COMP_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 0), 77c26448c4SGary King [TPS6586X_INT_ADC] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 1), 78c26448c4SGary King [TPS6586X_INT_PLDO_8] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 2), 79c26448c4SGary King [TPS6586X_INT_PLDO_9] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 3), 80c26448c4SGary King [TPS6586X_INT_PSM_0] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 4), 81c26448c4SGary King [TPS6586X_INT_PSM_1] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 5), 82c26448c4SGary King [TPS6586X_INT_PSM_2] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 6), 83c26448c4SGary King [TPS6586X_INT_PSM_3] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 7), 84c26448c4SGary King [TPS6586X_INT_RTC_ALM1] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 4), 85c26448c4SGary King [TPS6586X_INT_ACUSB_OVP] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 0x03), 86c26448c4SGary King [TPS6586X_INT_USB_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 2), 87c26448c4SGary King [TPS6586X_INT_AC_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 3), 88c26448c4SGary King [TPS6586X_INT_BAT_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 1 << 0), 89c26448c4SGary King [TPS6586X_INT_CHG_STAT] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 0xfc), 90c26448c4SGary King [TPS6586X_INT_CHG_TEMP] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 0x06), 91c26448c4SGary King [TPS6586X_INT_PP] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 0xf0), 92c26448c4SGary King [TPS6586X_INT_RESUME] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 5), 93c26448c4SGary King [TPS6586X_INT_LOW_SYS] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 6), 94c26448c4SGary King [TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1), 95c26448c4SGary King }; 96c26448c4SGary King 97c6c19332SMike Rapoport struct tps6586x { 98c6c19332SMike Rapoport struct device *dev; 99c6c19332SMike Rapoport struct i2c_client *client; 1001176b5beSLaxman Dewangan struct regmap *regmap; 101c6c19332SMike Rapoport 102c6c19332SMike Rapoport struct gpio_chip gpio; 103c26448c4SGary King struct irq_chip irq_chip; 104c26448c4SGary King struct mutex irq_lock; 105c26448c4SGary King int irq_base; 106c26448c4SGary King u32 irq_en; 107c26448c4SGary King u8 mask_reg[5]; 108c6c19332SMike Rapoport }; 109c6c19332SMike Rapoport 1101176b5beSLaxman Dewangan static inline struct tps6586x *dev_to_tps6586x(struct device *dev) 111c6c19332SMike Rapoport { 1121176b5beSLaxman Dewangan return i2c_get_clientdata(to_i2c_client(dev)); 113c6c19332SMike Rapoport } 114c6c19332SMike Rapoport 115c6c19332SMike Rapoport int tps6586x_write(struct device *dev, int reg, uint8_t val) 116c6c19332SMike Rapoport { 1171176b5beSLaxman Dewangan struct tps6586x *tps6586x = dev_to_tps6586x(dev); 1181176b5beSLaxman Dewangan 1191176b5beSLaxman Dewangan return regmap_write(tps6586x->regmap, reg, val); 120c6c19332SMike Rapoport } 121c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_write); 122c6c19332SMike Rapoport 123c6c19332SMike Rapoport int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val) 124c6c19332SMike Rapoport { 1251176b5beSLaxman Dewangan struct tps6586x *tps6586x = dev_to_tps6586x(dev); 1261176b5beSLaxman Dewangan 1271176b5beSLaxman Dewangan return regmap_bulk_write(tps6586x->regmap, reg, val, len); 128c6c19332SMike Rapoport } 129c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_writes); 130c6c19332SMike Rapoport 131c6c19332SMike Rapoport int tps6586x_read(struct device *dev, int reg, uint8_t *val) 132c6c19332SMike Rapoport { 1331176b5beSLaxman Dewangan struct tps6586x *tps6586x = dev_to_tps6586x(dev); 1341176b5beSLaxman Dewangan unsigned int rval; 1351176b5beSLaxman Dewangan int ret; 1361176b5beSLaxman Dewangan 1371176b5beSLaxman Dewangan ret = regmap_read(tps6586x->regmap, reg, &rval); 1381176b5beSLaxman Dewangan if (!ret) 1391176b5beSLaxman Dewangan *val = rval; 1401176b5beSLaxman Dewangan return ret; 141c6c19332SMike Rapoport } 142c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_read); 143c6c19332SMike Rapoport 144c6c19332SMike Rapoport int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val) 145c6c19332SMike Rapoport { 1461176b5beSLaxman Dewangan struct tps6586x *tps6586x = dev_to_tps6586x(dev); 1471176b5beSLaxman Dewangan 1481176b5beSLaxman Dewangan return regmap_bulk_read(tps6586x->regmap, reg, val, len); 149c6c19332SMike Rapoport } 150c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_reads); 151c6c19332SMike Rapoport 152c6c19332SMike Rapoport int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) 153c6c19332SMike Rapoport { 1541176b5beSLaxman Dewangan struct tps6586x *tps6586x = dev_to_tps6586x(dev); 155c6c19332SMike Rapoport 1561176b5beSLaxman Dewangan return regmap_update_bits(tps6586x->regmap, reg, bit_mask, bit_mask); 157c6c19332SMike Rapoport } 158c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_set_bits); 159c6c19332SMike Rapoport 160c6c19332SMike Rapoport int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) 161c6c19332SMike Rapoport { 1621176b5beSLaxman Dewangan struct tps6586x *tps6586x = dev_to_tps6586x(dev); 163c6c19332SMike Rapoport 1641176b5beSLaxman Dewangan return regmap_update_bits(tps6586x->regmap, reg, bit_mask, 0); 165c6c19332SMike Rapoport } 166c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_clr_bits); 167c6c19332SMike Rapoport 168c6c19332SMike Rapoport int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) 169c6c19332SMike Rapoport { 1701176b5beSLaxman Dewangan struct tps6586x *tps6586x = dev_to_tps6586x(dev); 171c6c19332SMike Rapoport 1721176b5beSLaxman Dewangan return regmap_update_bits(tps6586x->regmap, reg, mask, val); 173c6c19332SMike Rapoport } 174c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_update); 175c6c19332SMike Rapoport 176c6c19332SMike Rapoport static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) 177c6c19332SMike Rapoport { 178c6c19332SMike Rapoport struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); 179c6c19332SMike Rapoport uint8_t val; 180c6c19332SMike Rapoport int ret; 181c6c19332SMike Rapoport 1821176b5beSLaxman Dewangan ret = tps6586x_read(tps6586x->dev, TPS6586X_GPIOSET2, &val); 183c6c19332SMike Rapoport if (ret) 184c6c19332SMike Rapoport return ret; 185c6c19332SMike Rapoport 186c6c19332SMike Rapoport return !!(val & (1 << offset)); 187c6c19332SMike Rapoport } 188c6c19332SMike Rapoport 189c6c19332SMike Rapoport 190c6c19332SMike Rapoport static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, 191c6c19332SMike Rapoport int value) 192c6c19332SMike Rapoport { 193c6c19332SMike Rapoport struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); 194c6c19332SMike Rapoport 195e6f1945bSVincent Palatin tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2, 196e6f1945bSVincent Palatin value << offset, 1 << offset); 197c6c19332SMike Rapoport } 198c6c19332SMike Rapoport 199c6c19332SMike Rapoport static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, 200c6c19332SMike Rapoport int value) 201c6c19332SMike Rapoport { 202c6c19332SMike Rapoport struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); 203c6c19332SMike Rapoport uint8_t val, mask; 204c6c19332SMike Rapoport 205c6c19332SMike Rapoport tps6586x_gpio_set(gc, offset, value); 206c6c19332SMike Rapoport 207c6c19332SMike Rapoport val = 0x1 << (offset * 2); 208c6c19332SMike Rapoport mask = 0x3 << (offset * 2); 209c6c19332SMike Rapoport 210c6c19332SMike Rapoport return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); 211c6c19332SMike Rapoport } 212c6c19332SMike Rapoport 2136f9f13bfSVincent Palatin static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) 214c6c19332SMike Rapoport { 215c6c19332SMike Rapoport if (!gpio_base) 2166f9f13bfSVincent Palatin return 0; 217c6c19332SMike Rapoport 218c6c19332SMike Rapoport tps6586x->gpio.owner = THIS_MODULE; 219c6c19332SMike Rapoport tps6586x->gpio.label = tps6586x->client->name; 220c6c19332SMike Rapoport tps6586x->gpio.dev = tps6586x->dev; 221c6c19332SMike Rapoport tps6586x->gpio.base = gpio_base; 222c6c19332SMike Rapoport tps6586x->gpio.ngpio = 4; 223c6c19332SMike Rapoport tps6586x->gpio.can_sleep = 1; 224c6c19332SMike Rapoport 225c6c19332SMike Rapoport /* FIXME: add handling of GPIOs as dedicated inputs */ 226c6c19332SMike Rapoport tps6586x->gpio.direction_output = tps6586x_gpio_output; 227c6c19332SMike Rapoport tps6586x->gpio.set = tps6586x_gpio_set; 228c6c19332SMike Rapoport tps6586x->gpio.get = tps6586x_gpio_get; 229c6c19332SMike Rapoport 2306f9f13bfSVincent Palatin return gpiochip_add(&tps6586x->gpio); 231c6c19332SMike Rapoport } 232c6c19332SMike Rapoport 233c6c19332SMike Rapoport static int __remove_subdev(struct device *dev, void *unused) 234c6c19332SMike Rapoport { 235c6c19332SMike Rapoport platform_device_unregister(to_platform_device(dev)); 236c6c19332SMike Rapoport return 0; 237c6c19332SMike Rapoport } 238c6c19332SMike Rapoport 239c6c19332SMike Rapoport static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) 240c6c19332SMike Rapoport { 241c6c19332SMike Rapoport return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); 242c6c19332SMike Rapoport } 243c6c19332SMike Rapoport 24496e824bdSMark Brown static void tps6586x_irq_lock(struct irq_data *data) 245c26448c4SGary King { 24696e824bdSMark Brown struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data); 247c26448c4SGary King 248c26448c4SGary King mutex_lock(&tps6586x->irq_lock); 249c26448c4SGary King } 250c26448c4SGary King 25196e824bdSMark Brown static void tps6586x_irq_enable(struct irq_data *irq_data) 252c26448c4SGary King { 25396e824bdSMark Brown struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data); 25496e824bdSMark Brown unsigned int __irq = irq_data->irq - tps6586x->irq_base; 255c26448c4SGary King const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq]; 256c26448c4SGary King 257c26448c4SGary King tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask; 258c26448c4SGary King tps6586x->irq_en |= (1 << __irq); 259c26448c4SGary King } 260c26448c4SGary King 26196e824bdSMark Brown static void tps6586x_irq_disable(struct irq_data *irq_data) 262c26448c4SGary King { 26396e824bdSMark Brown struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data); 264c26448c4SGary King 26596e824bdSMark Brown unsigned int __irq = irq_data->irq - tps6586x->irq_base; 266c26448c4SGary King const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq]; 267c26448c4SGary King 268c26448c4SGary King tps6586x->mask_reg[data->mask_reg] |= data->mask_mask; 269c26448c4SGary King tps6586x->irq_en &= ~(1 << __irq); 270c26448c4SGary King } 271c26448c4SGary King 27296e824bdSMark Brown static void tps6586x_irq_sync_unlock(struct irq_data *data) 273c26448c4SGary King { 27496e824bdSMark Brown struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data); 275c26448c4SGary King int i; 276c26448c4SGary King 277c26448c4SGary King for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) { 27875edd5afSLaxman Dewangan int ret; 27975edd5afSLaxman Dewangan ret = tps6586x_write(tps6586x->dev, 280c26448c4SGary King TPS6586X_INT_MASK1 + i, 28175edd5afSLaxman Dewangan tps6586x->mask_reg[i]); 28275edd5afSLaxman Dewangan WARN_ON(ret); 283c26448c4SGary King } 284c26448c4SGary King 285c26448c4SGary King mutex_unlock(&tps6586x->irq_lock); 286c26448c4SGary King } 287c26448c4SGary King 288c26448c4SGary King static irqreturn_t tps6586x_irq(int irq, void *data) 289c26448c4SGary King { 290c26448c4SGary King struct tps6586x *tps6586x = data; 291c26448c4SGary King u32 acks; 292c26448c4SGary King int ret = 0; 293c26448c4SGary King 294c26448c4SGary King ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, 295c26448c4SGary King sizeof(acks), (uint8_t *)&acks); 296c26448c4SGary King 297c26448c4SGary King if (ret < 0) { 298c26448c4SGary King dev_err(tps6586x->dev, "failed to read interrupt status\n"); 299c26448c4SGary King return IRQ_NONE; 300c26448c4SGary King } 301c26448c4SGary King 302c26448c4SGary King acks = le32_to_cpu(acks); 303c26448c4SGary King 304c26448c4SGary King while (acks) { 305c26448c4SGary King int i = __ffs(acks); 306c26448c4SGary King 307c26448c4SGary King if (tps6586x->irq_en & (1 << i)) 308c26448c4SGary King handle_nested_irq(tps6586x->irq_base + i); 309c26448c4SGary King 310c26448c4SGary King acks &= ~(1 << i); 311c26448c4SGary King } 312c26448c4SGary King 313c26448c4SGary King return IRQ_HANDLED; 314c26448c4SGary King } 315c26448c4SGary King 316c26448c4SGary King static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq, 317c26448c4SGary King int irq_base) 318c26448c4SGary King { 319c26448c4SGary King int i, ret; 320c26448c4SGary King u8 tmp[4]; 321c26448c4SGary King 322c26448c4SGary King if (!irq_base) { 323c26448c4SGary King dev_warn(tps6586x->dev, "No interrupt support on IRQ base\n"); 324c26448c4SGary King return -EINVAL; 325c26448c4SGary King } 326c26448c4SGary King 327c26448c4SGary King mutex_init(&tps6586x->irq_lock); 328c26448c4SGary King for (i = 0; i < 5; i++) { 329c26448c4SGary King tps6586x->mask_reg[i] = 0xff; 330c26448c4SGary King tps6586x_write(tps6586x->dev, TPS6586X_INT_MASK1 + i, 0xff); 331c26448c4SGary King } 332c26448c4SGary King 333c26448c4SGary King tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, sizeof(tmp), tmp); 334c26448c4SGary King 335c26448c4SGary King tps6586x->irq_base = irq_base; 336c26448c4SGary King 337c26448c4SGary King tps6586x->irq_chip.name = "tps6586x"; 33896e824bdSMark Brown tps6586x->irq_chip.irq_enable = tps6586x_irq_enable; 33996e824bdSMark Brown tps6586x->irq_chip.irq_disable = tps6586x_irq_disable; 34096e824bdSMark Brown tps6586x->irq_chip.irq_bus_lock = tps6586x_irq_lock; 34196e824bdSMark Brown tps6586x->irq_chip.irq_bus_sync_unlock = tps6586x_irq_sync_unlock; 342c26448c4SGary King 343c26448c4SGary King for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) { 344c26448c4SGary King int __irq = i + tps6586x->irq_base; 345d5bb1221SThomas Gleixner irq_set_chip_data(__irq, tps6586x); 346d5bb1221SThomas Gleixner irq_set_chip_and_handler(__irq, &tps6586x->irq_chip, 347c26448c4SGary King handle_simple_irq); 348d5bb1221SThomas Gleixner irq_set_nested_thread(__irq, 1); 349c26448c4SGary King #ifdef CONFIG_ARM 350c26448c4SGary King set_irq_flags(__irq, IRQF_VALID); 351c26448c4SGary King #endif 352c26448c4SGary King } 353c26448c4SGary King 354c26448c4SGary King ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT, 355c26448c4SGary King "tps6586x", tps6586x); 356c26448c4SGary King 357c26448c4SGary King if (!ret) { 358c26448c4SGary King device_init_wakeup(tps6586x->dev, 1); 359c26448c4SGary King enable_irq_wake(irq); 360c26448c4SGary King } 361c26448c4SGary King 362c26448c4SGary King return ret; 363c26448c4SGary King } 364c26448c4SGary King 365c6c19332SMike Rapoport static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, 366c6c19332SMike Rapoport struct tps6586x_platform_data *pdata) 367c6c19332SMike Rapoport { 368c6c19332SMike Rapoport struct tps6586x_subdev_info *subdev; 369c6c19332SMike Rapoport struct platform_device *pdev; 370c6c19332SMike Rapoport int i, ret = 0; 371c6c19332SMike Rapoport 372c6c19332SMike Rapoport for (i = 0; i < pdata->num_subdevs; i++) { 373c6c19332SMike Rapoport subdev = &pdata->subdevs[i]; 374c6c19332SMike Rapoport 375c6c19332SMike Rapoport pdev = platform_device_alloc(subdev->name, subdev->id); 376929980abSAxel Lin if (!pdev) { 377929980abSAxel Lin ret = -ENOMEM; 378929980abSAxel Lin goto failed; 379929980abSAxel Lin } 380c6c19332SMike Rapoport 381c6c19332SMike Rapoport pdev->dev.parent = tps6586x->dev; 382c6c19332SMike Rapoport pdev->dev.platform_data = subdev->platform_data; 38362f6b087SThierry Reding pdev->dev.of_node = subdev->of_node; 384c6c19332SMike Rapoport 385c6c19332SMike Rapoport ret = platform_device_add(pdev); 386929980abSAxel Lin if (ret) { 387929980abSAxel Lin platform_device_put(pdev); 388c6c19332SMike Rapoport goto failed; 389c6c19332SMike Rapoport } 390929980abSAxel Lin } 391c6c19332SMike Rapoport return 0; 392c6c19332SMike Rapoport 393c6c19332SMike Rapoport failed: 394c6c19332SMike Rapoport tps6586x_remove_subdevs(tps6586x); 395c6c19332SMike Rapoport return ret; 396c6c19332SMike Rapoport } 397c6c19332SMike Rapoport 39862f6b087SThierry Reding #ifdef CONFIG_OF 39962f6b087SThierry Reding static struct of_regulator_match tps6586x_matches[] = { 40062f6b087SThierry Reding { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 }, 40162f6b087SThierry Reding { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 }, 40262f6b087SThierry Reding { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 }, 40362f6b087SThierry Reding { .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 }, 40462f6b087SThierry Reding { .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 }, 40562f6b087SThierry Reding { .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 }, 40662f6b087SThierry Reding { .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 }, 40762f6b087SThierry Reding { .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 }, 40862f6b087SThierry Reding { .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 }, 40962f6b087SThierry Reding { .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 }, 41062f6b087SThierry Reding { .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 }, 41162f6b087SThierry Reding { .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 }, 41262f6b087SThierry Reding { .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 }, 41362f6b087SThierry Reding { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC }, 41462f6b087SThierry Reding }; 41562f6b087SThierry Reding 41662f6b087SThierry Reding static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client) 41762f6b087SThierry Reding { 41862f6b087SThierry Reding const unsigned int num = ARRAY_SIZE(tps6586x_matches); 41962f6b087SThierry Reding struct device_node *np = client->dev.of_node; 42062f6b087SThierry Reding struct tps6586x_platform_data *pdata; 42162f6b087SThierry Reding struct tps6586x_subdev_info *devs; 42262f6b087SThierry Reding struct device_node *regs; 42362f6b087SThierry Reding unsigned int count; 42462f6b087SThierry Reding unsigned int i, j; 42562f6b087SThierry Reding int err; 42662f6b087SThierry Reding 42762f6b087SThierry Reding regs = of_find_node_by_name(np, "regulators"); 42862f6b087SThierry Reding if (!regs) 42962f6b087SThierry Reding return NULL; 43062f6b087SThierry Reding 43162f6b087SThierry Reding err = of_regulator_match(&client->dev, regs, tps6586x_matches, num); 43262f6b087SThierry Reding if (err < 0) { 43362f6b087SThierry Reding of_node_put(regs); 43462f6b087SThierry Reding return NULL; 43562f6b087SThierry Reding } 43662f6b087SThierry Reding 43762f6b087SThierry Reding of_node_put(regs); 43862f6b087SThierry Reding count = err; 43962f6b087SThierry Reding 44062f6b087SThierry Reding devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL); 44162f6b087SThierry Reding if (!devs) 44262f6b087SThierry Reding return NULL; 44362f6b087SThierry Reding 44462f6b087SThierry Reding for (i = 0, j = 0; i < num && j < count; i++) { 44562f6b087SThierry Reding if (!tps6586x_matches[i].init_data) 44662f6b087SThierry Reding continue; 44762f6b087SThierry Reding 44862f6b087SThierry Reding devs[j].name = "tps6586x-regulator"; 44962f6b087SThierry Reding devs[j].platform_data = tps6586x_matches[i].init_data; 45062f6b087SThierry Reding devs[j].id = (int)tps6586x_matches[i].driver_data; 45162f6b087SThierry Reding devs[j].of_node = tps6586x_matches[i].of_node; 45262f6b087SThierry Reding j++; 45362f6b087SThierry Reding } 45462f6b087SThierry Reding 45562f6b087SThierry Reding pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); 45662f6b087SThierry Reding if (!pdata) 45762f6b087SThierry Reding return NULL; 45862f6b087SThierry Reding 45962f6b087SThierry Reding pdata->num_subdevs = count; 46062f6b087SThierry Reding pdata->subdevs = devs; 46162f6b087SThierry Reding pdata->gpio_base = -1; 46262f6b087SThierry Reding pdata->irq_base = -1; 46362f6b087SThierry Reding 46462f6b087SThierry Reding return pdata; 46562f6b087SThierry Reding } 46662f6b087SThierry Reding 46762f6b087SThierry Reding static struct of_device_id tps6586x_of_match[] = { 46862f6b087SThierry Reding { .compatible = "ti,tps6586x", }, 46962f6b087SThierry Reding { }, 47062f6b087SThierry Reding }; 47162f6b087SThierry Reding #else 47262f6b087SThierry Reding static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client) 47362f6b087SThierry Reding { 47462f6b087SThierry Reding return NULL; 47562f6b087SThierry Reding } 47662f6b087SThierry Reding #endif 47762f6b087SThierry Reding 47875edd5afSLaxman Dewangan static bool is_volatile_reg(struct device *dev, unsigned int reg) 47975edd5afSLaxman Dewangan { 48075edd5afSLaxman Dewangan /* Cache all interrupt mask register */ 48175edd5afSLaxman Dewangan if ((reg >= TPS6586X_INT_MASK1) && (reg <= TPS6586X_INT_MASK5)) 48275edd5afSLaxman Dewangan return false; 48375edd5afSLaxman Dewangan 48475edd5afSLaxman Dewangan return true; 48575edd5afSLaxman Dewangan } 48675edd5afSLaxman Dewangan 4871176b5beSLaxman Dewangan static const struct regmap_config tps6586x_regmap_config = { 4881176b5beSLaxman Dewangan .reg_bits = 8, 4891176b5beSLaxman Dewangan .val_bits = 8, 4901176b5beSLaxman Dewangan .max_register = TPS6586X_MAX_REGISTER - 1, 49175edd5afSLaxman Dewangan .volatile_reg = is_volatile_reg, 49275edd5afSLaxman Dewangan .cache_type = REGCACHE_RBTREE, 4931176b5beSLaxman Dewangan }; 4941176b5beSLaxman Dewangan 495c6c19332SMike Rapoport static int __devinit tps6586x_i2c_probe(struct i2c_client *client, 496c6c19332SMike Rapoport const struct i2c_device_id *id) 497c6c19332SMike Rapoport { 498c6c19332SMike Rapoport struct tps6586x_platform_data *pdata = client->dev.platform_data; 499c6c19332SMike Rapoport struct tps6586x *tps6586x; 500c6c19332SMike Rapoport int ret; 501c6c19332SMike Rapoport 50262f6b087SThierry Reding if (!pdata && client->dev.of_node) 50362f6b087SThierry Reding pdata = tps6586x_parse_dt(client); 50462f6b087SThierry Reding 505c6c19332SMike Rapoport if (!pdata) { 506c6c19332SMike Rapoport dev_err(&client->dev, "tps6586x requires platform data\n"); 507c6c19332SMike Rapoport return -ENOTSUPP; 508c6c19332SMike Rapoport } 509c6c19332SMike Rapoport 510c6c19332SMike Rapoport ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); 511c6c19332SMike Rapoport if (ret < 0) { 512c6c19332SMike Rapoport dev_err(&client->dev, "Chip ID read failed: %d\n", ret); 513c6c19332SMike Rapoport return -EIO; 514c6c19332SMike Rapoport } 515c6c19332SMike Rapoport 5164d1cdbf6SStephen Warren dev_info(&client->dev, "VERSIONCRC is %02x\n", ret); 517c6c19332SMike Rapoport 518b6719412SLaxman Dewangan tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL); 519b6719412SLaxman Dewangan if (tps6586x == NULL) { 520b6719412SLaxman Dewangan dev_err(&client->dev, "memory for tps6586x alloc failed\n"); 521c6c19332SMike Rapoport return -ENOMEM; 522b6719412SLaxman Dewangan } 523c6c19332SMike Rapoport 524c6c19332SMike Rapoport tps6586x->client = client; 525c6c19332SMike Rapoport tps6586x->dev = &client->dev; 526c6c19332SMike Rapoport i2c_set_clientdata(client, tps6586x); 527c6c19332SMike Rapoport 5281176b5beSLaxman Dewangan tps6586x->regmap = devm_regmap_init_i2c(client, 5291176b5beSLaxman Dewangan &tps6586x_regmap_config); 5301176b5beSLaxman Dewangan if (IS_ERR(tps6586x->regmap)) { 5311176b5beSLaxman Dewangan ret = PTR_ERR(tps6586x->regmap); 5321176b5beSLaxman Dewangan dev_err(&client->dev, "regmap init failed: %d\n", ret); 5331176b5beSLaxman Dewangan return ret; 5341176b5beSLaxman Dewangan } 5351176b5beSLaxman Dewangan 536c6c19332SMike Rapoport 537c26448c4SGary King if (client->irq) { 538c26448c4SGary King ret = tps6586x_irq_init(tps6586x, client->irq, 539c26448c4SGary King pdata->irq_base); 540c26448c4SGary King if (ret) { 541c26448c4SGary King dev_err(&client->dev, "IRQ init failed: %d\n", ret); 542b6719412SLaxman Dewangan return ret; 543c26448c4SGary King } 544c26448c4SGary King } 545c26448c4SGary King 5466f9f13bfSVincent Palatin ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base); 5476f9f13bfSVincent Palatin if (ret) { 5486f9f13bfSVincent Palatin dev_err(&client->dev, "GPIO registration failed: %d\n", ret); 5496f9f13bfSVincent Palatin goto err_gpio_init; 5506f9f13bfSVincent Palatin } 5516f9f13bfSVincent Palatin 552c6c19332SMike Rapoport ret = tps6586x_add_subdevs(tps6586x, pdata); 553c6c19332SMike Rapoport if (ret) { 554c6c19332SMike Rapoport dev_err(&client->dev, "add devices failed: %d\n", ret); 555c6c19332SMike Rapoport goto err_add_devs; 556c6c19332SMike Rapoport } 557c6c19332SMike Rapoport 558c6c19332SMike Rapoport return 0; 559c6c19332SMike Rapoport 560c6c19332SMike Rapoport err_add_devs: 5616f9f13bfSVincent Palatin if (pdata->gpio_base) { 5626f9f13bfSVincent Palatin ret = gpiochip_remove(&tps6586x->gpio); 5636f9f13bfSVincent Palatin if (ret) 5646f9f13bfSVincent Palatin dev_err(&client->dev, "Can't remove gpio chip: %d\n", 5656f9f13bfSVincent Palatin ret); 5666f9f13bfSVincent Palatin } 5676f9f13bfSVincent Palatin err_gpio_init: 568c26448c4SGary King if (client->irq) 569c26448c4SGary King free_irq(client->irq, tps6586x); 570b6719412SLaxman Dewangan 571c6c19332SMike Rapoport return ret; 572c6c19332SMike Rapoport } 573c6c19332SMike Rapoport 574c6c19332SMike Rapoport static int __devexit tps6586x_i2c_remove(struct i2c_client *client) 575c6c19332SMike Rapoport { 5764b751cf5SAxel Lin struct tps6586x *tps6586x = i2c_get_clientdata(client); 5774b751cf5SAxel Lin struct tps6586x_platform_data *pdata = client->dev.platform_data; 5784b751cf5SAxel Lin int ret; 5794b751cf5SAxel Lin 580c26448c4SGary King if (client->irq) 581c26448c4SGary King free_irq(client->irq, tps6586x); 582c26448c4SGary King 5834b751cf5SAxel Lin if (pdata->gpio_base) { 5844b751cf5SAxel Lin ret = gpiochip_remove(&tps6586x->gpio); 5854b751cf5SAxel Lin if (ret) 5864b751cf5SAxel Lin dev_err(&client->dev, "Can't remove gpio chip: %d\n", 5874b751cf5SAxel Lin ret); 5884b751cf5SAxel Lin } 5894b751cf5SAxel Lin 5904b751cf5SAxel Lin tps6586x_remove_subdevs(tps6586x); 591c6c19332SMike Rapoport return 0; 592c6c19332SMike Rapoport } 593c6c19332SMike Rapoport 594c6c19332SMike Rapoport static const struct i2c_device_id tps6586x_id_table[] = { 595c6c19332SMike Rapoport { "tps6586x", 0 }, 596c6c19332SMike Rapoport { }, 597c6c19332SMike Rapoport }; 598c6c19332SMike Rapoport MODULE_DEVICE_TABLE(i2c, tps6586x_id_table); 599c6c19332SMike Rapoport 600c6c19332SMike Rapoport static struct i2c_driver tps6586x_driver = { 601c6c19332SMike Rapoport .driver = { 602c6c19332SMike Rapoport .name = "tps6586x", 603c6c19332SMike Rapoport .owner = THIS_MODULE, 60462f6b087SThierry Reding .of_match_table = of_match_ptr(tps6586x_of_match), 605c6c19332SMike Rapoport }, 606c6c19332SMike Rapoport .probe = tps6586x_i2c_probe, 607c6c19332SMike Rapoport .remove = __devexit_p(tps6586x_i2c_remove), 608c6c19332SMike Rapoport .id_table = tps6586x_id_table, 609c6c19332SMike Rapoport }; 610c6c19332SMike Rapoport 611c6c19332SMike Rapoport static int __init tps6586x_init(void) 612c6c19332SMike Rapoport { 613c6c19332SMike Rapoport return i2c_add_driver(&tps6586x_driver); 614c6c19332SMike Rapoport } 615c6c19332SMike Rapoport subsys_initcall(tps6586x_init); 616c6c19332SMike Rapoport 617c6c19332SMike Rapoport static void __exit tps6586x_exit(void) 618c6c19332SMike Rapoport { 619c6c19332SMike Rapoport i2c_del_driver(&tps6586x_driver); 620c6c19332SMike Rapoport } 621c6c19332SMike Rapoport module_exit(tps6586x_exit); 622c6c19332SMike Rapoport 623c6c19332SMike Rapoport MODULE_DESCRIPTION("TPS6586X core driver"); 624c6c19332SMike Rapoport MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); 625c6c19332SMike Rapoport MODULE_LICENSE("GPL"); 626