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> 24c6c19332SMike Rapoport #include <linux/gpio.h> 25c6c19332SMike Rapoport #include <linux/i2c.h> 26c6c19332SMike Rapoport 27c6c19332SMike Rapoport #include <linux/mfd/core.h> 28c6c19332SMike Rapoport #include <linux/mfd/tps6586x.h> 29c6c19332SMike Rapoport 30c6c19332SMike Rapoport /* GPIO control registers */ 31c6c19332SMike Rapoport #define TPS6586X_GPIOSET1 0x5d 32c6c19332SMike Rapoport #define TPS6586X_GPIOSET2 0x5e 33c6c19332SMike Rapoport 34c26448c4SGary King /* interrupt control registers */ 35c26448c4SGary King #define TPS6586X_INT_ACK1 0xb5 36c26448c4SGary King #define TPS6586X_INT_ACK2 0xb6 37c26448c4SGary King #define TPS6586X_INT_ACK3 0xb7 38c26448c4SGary King #define TPS6586X_INT_ACK4 0xb8 39c26448c4SGary King 40c26448c4SGary King /* interrupt mask registers */ 41c26448c4SGary King #define TPS6586X_INT_MASK1 0xb0 42c26448c4SGary King #define TPS6586X_INT_MASK2 0xb1 43c26448c4SGary King #define TPS6586X_INT_MASK3 0xb2 44c26448c4SGary King #define TPS6586X_INT_MASK4 0xb3 45c26448c4SGary King #define TPS6586X_INT_MASK5 0xb4 46c26448c4SGary King 47c6c19332SMike Rapoport /* device id */ 48c6c19332SMike Rapoport #define TPS6586X_VERSIONCRC 0xcd 49c6c19332SMike Rapoport 50c26448c4SGary King struct tps6586x_irq_data { 51c26448c4SGary King u8 mask_reg; 52c26448c4SGary King u8 mask_mask; 53c26448c4SGary King }; 54c26448c4SGary King 55c26448c4SGary King #define TPS6586X_IRQ(_reg, _mask) \ 56c26448c4SGary King { \ 57c26448c4SGary King .mask_reg = (_reg) - TPS6586X_INT_MASK1, \ 58c26448c4SGary King .mask_mask = (_mask), \ 59c26448c4SGary King } 60c26448c4SGary King 61c26448c4SGary King static const struct tps6586x_irq_data tps6586x_irqs[] = { 62c26448c4SGary King [TPS6586X_INT_PLDO_0] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 0), 63c26448c4SGary King [TPS6586X_INT_PLDO_1] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 1), 64c26448c4SGary King [TPS6586X_INT_PLDO_2] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 2), 65c26448c4SGary King [TPS6586X_INT_PLDO_3] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 3), 66c26448c4SGary King [TPS6586X_INT_PLDO_4] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 4), 67c26448c4SGary King [TPS6586X_INT_PLDO_5] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 5), 68c26448c4SGary King [TPS6586X_INT_PLDO_6] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 6), 69c26448c4SGary King [TPS6586X_INT_PLDO_7] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 7), 70c26448c4SGary King [TPS6586X_INT_COMP_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 0), 71c26448c4SGary King [TPS6586X_INT_ADC] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 1), 72c26448c4SGary King [TPS6586X_INT_PLDO_8] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 2), 73c26448c4SGary King [TPS6586X_INT_PLDO_9] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 3), 74c26448c4SGary King [TPS6586X_INT_PSM_0] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 4), 75c26448c4SGary King [TPS6586X_INT_PSM_1] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 5), 76c26448c4SGary King [TPS6586X_INT_PSM_2] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 6), 77c26448c4SGary King [TPS6586X_INT_PSM_3] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 7), 78c26448c4SGary King [TPS6586X_INT_RTC_ALM1] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 4), 79c26448c4SGary King [TPS6586X_INT_ACUSB_OVP] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 0x03), 80c26448c4SGary King [TPS6586X_INT_USB_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 2), 81c26448c4SGary King [TPS6586X_INT_AC_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 3), 82c26448c4SGary King [TPS6586X_INT_BAT_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 1 << 0), 83c26448c4SGary King [TPS6586X_INT_CHG_STAT] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 0xfc), 84c26448c4SGary King [TPS6586X_INT_CHG_TEMP] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 0x06), 85c26448c4SGary King [TPS6586X_INT_PP] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 0xf0), 86c26448c4SGary King [TPS6586X_INT_RESUME] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 5), 87c26448c4SGary King [TPS6586X_INT_LOW_SYS] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 6), 88c26448c4SGary King [TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1), 89c26448c4SGary King }; 90c26448c4SGary King 91c6c19332SMike Rapoport struct tps6586x { 92c6c19332SMike Rapoport struct mutex lock; 93c6c19332SMike Rapoport struct device *dev; 94c6c19332SMike Rapoport struct i2c_client *client; 95c6c19332SMike Rapoport 96c6c19332SMike Rapoport struct gpio_chip gpio; 97c26448c4SGary King struct irq_chip irq_chip; 98c26448c4SGary King struct mutex irq_lock; 99c26448c4SGary King int irq_base; 100c26448c4SGary King u32 irq_en; 101c26448c4SGary King u8 mask_cache[5]; 102c26448c4SGary King u8 mask_reg[5]; 103c6c19332SMike Rapoport }; 104c6c19332SMike Rapoport 105c6c19332SMike Rapoport static inline int __tps6586x_read(struct i2c_client *client, 106c6c19332SMike Rapoport int reg, uint8_t *val) 107c6c19332SMike Rapoport { 108c6c19332SMike Rapoport int ret; 109c6c19332SMike Rapoport 110c6c19332SMike Rapoport ret = i2c_smbus_read_byte_data(client, reg); 111c6c19332SMike Rapoport if (ret < 0) { 112c6c19332SMike Rapoport dev_err(&client->dev, "failed reading at 0x%02x\n", reg); 113c6c19332SMike Rapoport return ret; 114c6c19332SMike Rapoport } 115c6c19332SMike Rapoport 116c6c19332SMike Rapoport *val = (uint8_t)ret; 117c6c19332SMike Rapoport 118c6c19332SMike Rapoport return 0; 119c6c19332SMike Rapoport } 120c6c19332SMike Rapoport 121c6c19332SMike Rapoport static inline int __tps6586x_reads(struct i2c_client *client, int reg, 122c6c19332SMike Rapoport int len, uint8_t *val) 123c6c19332SMike Rapoport { 124c6c19332SMike Rapoport int ret; 125c6c19332SMike Rapoport 126c6c19332SMike Rapoport ret = i2c_smbus_read_i2c_block_data(client, reg, len, val); 127c6c19332SMike Rapoport if (ret < 0) { 128c6c19332SMike Rapoport dev_err(&client->dev, "failed reading from 0x%02x\n", reg); 129c6c19332SMike Rapoport return ret; 130c6c19332SMike Rapoport } 131c6c19332SMike Rapoport 132c6c19332SMike Rapoport return 0; 133c6c19332SMike Rapoport } 134c6c19332SMike Rapoport 135c6c19332SMike Rapoport static inline int __tps6586x_write(struct i2c_client *client, 136c6c19332SMike Rapoport int reg, uint8_t val) 137c6c19332SMike Rapoport { 138c6c19332SMike Rapoport int ret; 139c6c19332SMike Rapoport 140c6c19332SMike Rapoport ret = i2c_smbus_write_byte_data(client, reg, val); 141c6c19332SMike Rapoport if (ret < 0) { 142c6c19332SMike Rapoport dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", 143c6c19332SMike Rapoport val, reg); 144c6c19332SMike Rapoport return ret; 145c6c19332SMike Rapoport } 146c6c19332SMike Rapoport 147c6c19332SMike Rapoport return 0; 148c6c19332SMike Rapoport } 149c6c19332SMike Rapoport 150c6c19332SMike Rapoport static inline int __tps6586x_writes(struct i2c_client *client, int reg, 151c6c19332SMike Rapoport int len, uint8_t *val) 152c6c19332SMike Rapoport { 1534b57018dSvwadekar@nvidia.com int ret, i; 154c6c19332SMike Rapoport 1554b57018dSvwadekar@nvidia.com for (i = 0; i < len; i++) { 1564b57018dSvwadekar@nvidia.com ret = __tps6586x_write(client, reg + i, *(val + i)); 1574b57018dSvwadekar@nvidia.com if (ret < 0) 158c6c19332SMike Rapoport return ret; 159c6c19332SMike Rapoport } 160c6c19332SMike Rapoport 161c6c19332SMike Rapoport return 0; 162c6c19332SMike Rapoport } 163c6c19332SMike Rapoport 164c6c19332SMike Rapoport int tps6586x_write(struct device *dev, int reg, uint8_t val) 165c6c19332SMike Rapoport { 166c6c19332SMike Rapoport return __tps6586x_write(to_i2c_client(dev), reg, val); 167c6c19332SMike Rapoport } 168c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_write); 169c6c19332SMike Rapoport 170c6c19332SMike Rapoport int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val) 171c6c19332SMike Rapoport { 172c6c19332SMike Rapoport return __tps6586x_writes(to_i2c_client(dev), reg, len, val); 173c6c19332SMike Rapoport } 174c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_writes); 175c6c19332SMike Rapoport 176c6c19332SMike Rapoport int tps6586x_read(struct device *dev, int reg, uint8_t *val) 177c6c19332SMike Rapoport { 178c6c19332SMike Rapoport return __tps6586x_read(to_i2c_client(dev), reg, val); 179c6c19332SMike Rapoport } 180c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_read); 181c6c19332SMike Rapoport 182c6c19332SMike Rapoport int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val) 183c6c19332SMike Rapoport { 184c6c19332SMike Rapoport return __tps6586x_reads(to_i2c_client(dev), reg, len, val); 185c6c19332SMike Rapoport } 186c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_reads); 187c6c19332SMike Rapoport 188c6c19332SMike Rapoport int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) 189c6c19332SMike Rapoport { 190c6c19332SMike Rapoport struct tps6586x *tps6586x = dev_get_drvdata(dev); 191c6c19332SMike Rapoport uint8_t reg_val; 192c6c19332SMike Rapoport int ret = 0; 193c6c19332SMike Rapoport 194c6c19332SMike Rapoport mutex_lock(&tps6586x->lock); 195c6c19332SMike Rapoport 196c6c19332SMike Rapoport ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); 197c6c19332SMike Rapoport if (ret) 198c6c19332SMike Rapoport goto out; 199c6c19332SMike Rapoport 200c6c19332SMike Rapoport if ((reg_val & bit_mask) == 0) { 201c6c19332SMike Rapoport reg_val |= bit_mask; 202c6c19332SMike Rapoport ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); 203c6c19332SMike Rapoport } 204c6c19332SMike Rapoport out: 205c6c19332SMike Rapoport mutex_unlock(&tps6586x->lock); 206c6c19332SMike Rapoport return ret; 207c6c19332SMike Rapoport } 208c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_set_bits); 209c6c19332SMike Rapoport 210c6c19332SMike Rapoport int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) 211c6c19332SMike Rapoport { 212c6c19332SMike Rapoport struct tps6586x *tps6586x = dev_get_drvdata(dev); 213c6c19332SMike Rapoport uint8_t reg_val; 214c6c19332SMike Rapoport int ret = 0; 215c6c19332SMike Rapoport 216c6c19332SMike Rapoport mutex_lock(&tps6586x->lock); 217c6c19332SMike Rapoport 218c6c19332SMike Rapoport ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); 219c6c19332SMike Rapoport if (ret) 220c6c19332SMike Rapoport goto out; 221c6c19332SMike Rapoport 222c6c19332SMike Rapoport if (reg_val & bit_mask) { 223c6c19332SMike Rapoport reg_val &= ~bit_mask; 224c6c19332SMike Rapoport ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); 225c6c19332SMike Rapoport } 226c6c19332SMike Rapoport out: 227c6c19332SMike Rapoport mutex_unlock(&tps6586x->lock); 228c6c19332SMike Rapoport return ret; 229c6c19332SMike Rapoport } 230c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_clr_bits); 231c6c19332SMike Rapoport 232c6c19332SMike Rapoport int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) 233c6c19332SMike Rapoport { 234c6c19332SMike Rapoport struct tps6586x *tps6586x = dev_get_drvdata(dev); 235c6c19332SMike Rapoport uint8_t reg_val; 236c6c19332SMike Rapoport int ret = 0; 237c6c19332SMike Rapoport 238c6c19332SMike Rapoport mutex_lock(&tps6586x->lock); 239c6c19332SMike Rapoport 240c6c19332SMike Rapoport ret = __tps6586x_read(tps6586x->client, reg, ®_val); 241c6c19332SMike Rapoport if (ret) 242c6c19332SMike Rapoport goto out; 243c6c19332SMike Rapoport 244c6c19332SMike Rapoport if ((reg_val & mask) != val) { 245c6c19332SMike Rapoport reg_val = (reg_val & ~mask) | val; 246c6c19332SMike Rapoport ret = __tps6586x_write(tps6586x->client, reg, reg_val); 247c6c19332SMike Rapoport } 248c6c19332SMike Rapoport out: 249c6c19332SMike Rapoport mutex_unlock(&tps6586x->lock); 250c6c19332SMike Rapoport return ret; 251c6c19332SMike Rapoport } 252c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_update); 253c6c19332SMike Rapoport 254c6c19332SMike Rapoport static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) 255c6c19332SMike Rapoport { 256c6c19332SMike Rapoport struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); 257c6c19332SMike Rapoport uint8_t val; 258c6c19332SMike Rapoport int ret; 259c6c19332SMike Rapoport 260c6c19332SMike Rapoport ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val); 261c6c19332SMike Rapoport if (ret) 262c6c19332SMike Rapoport return ret; 263c6c19332SMike Rapoport 264c6c19332SMike Rapoport return !!(val & (1 << offset)); 265c6c19332SMike Rapoport } 266c6c19332SMike Rapoport 267c6c19332SMike Rapoport 268c6c19332SMike Rapoport static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, 269c6c19332SMike Rapoport int value) 270c6c19332SMike Rapoport { 271c6c19332SMike Rapoport struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); 272c6c19332SMike Rapoport 273c6c19332SMike Rapoport __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2, 274c6c19332SMike Rapoport value << offset); 275c6c19332SMike Rapoport } 276c6c19332SMike Rapoport 277c6c19332SMike Rapoport static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, 278c6c19332SMike Rapoport int value) 279c6c19332SMike Rapoport { 280c6c19332SMike Rapoport struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); 281c6c19332SMike Rapoport uint8_t val, mask; 282c6c19332SMike Rapoport 283c6c19332SMike Rapoport tps6586x_gpio_set(gc, offset, value); 284c6c19332SMike Rapoport 285c6c19332SMike Rapoport val = 0x1 << (offset * 2); 286c6c19332SMike Rapoport mask = 0x3 << (offset * 2); 287c6c19332SMike Rapoport 288c6c19332SMike Rapoport return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); 289c6c19332SMike Rapoport } 290c6c19332SMike Rapoport 2916f9f13bfSVincent Palatin static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) 292c6c19332SMike Rapoport { 293c6c19332SMike Rapoport if (!gpio_base) 2946f9f13bfSVincent Palatin return 0; 295c6c19332SMike Rapoport 296c6c19332SMike Rapoport tps6586x->gpio.owner = THIS_MODULE; 297c6c19332SMike Rapoport tps6586x->gpio.label = tps6586x->client->name; 298c6c19332SMike Rapoport tps6586x->gpio.dev = tps6586x->dev; 299c6c19332SMike Rapoport tps6586x->gpio.base = gpio_base; 300c6c19332SMike Rapoport tps6586x->gpio.ngpio = 4; 301c6c19332SMike Rapoport tps6586x->gpio.can_sleep = 1; 302c6c19332SMike Rapoport 303c6c19332SMike Rapoport /* FIXME: add handling of GPIOs as dedicated inputs */ 304c6c19332SMike Rapoport tps6586x->gpio.direction_output = tps6586x_gpio_output; 305c6c19332SMike Rapoport tps6586x->gpio.set = tps6586x_gpio_set; 306c6c19332SMike Rapoport tps6586x->gpio.get = tps6586x_gpio_get; 307c6c19332SMike Rapoport 3086f9f13bfSVincent Palatin return gpiochip_add(&tps6586x->gpio); 309c6c19332SMike Rapoport } 310c6c19332SMike Rapoport 311c6c19332SMike Rapoport static int __remove_subdev(struct device *dev, void *unused) 312c6c19332SMike Rapoport { 313c6c19332SMike Rapoport platform_device_unregister(to_platform_device(dev)); 314c6c19332SMike Rapoport return 0; 315c6c19332SMike Rapoport } 316c6c19332SMike Rapoport 317c6c19332SMike Rapoport static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) 318c6c19332SMike Rapoport { 319c6c19332SMike Rapoport return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); 320c6c19332SMike Rapoport } 321c6c19332SMike Rapoport 32296e824bdSMark Brown static void tps6586x_irq_lock(struct irq_data *data) 323c26448c4SGary King { 32496e824bdSMark Brown struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data); 325c26448c4SGary King 326c26448c4SGary King mutex_lock(&tps6586x->irq_lock); 327c26448c4SGary King } 328c26448c4SGary King 32996e824bdSMark Brown static void tps6586x_irq_enable(struct irq_data *irq_data) 330c26448c4SGary King { 33196e824bdSMark Brown struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data); 33296e824bdSMark Brown unsigned int __irq = irq_data->irq - tps6586x->irq_base; 333c26448c4SGary King const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq]; 334c26448c4SGary King 335c26448c4SGary King tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask; 336c26448c4SGary King tps6586x->irq_en |= (1 << __irq); 337c26448c4SGary King } 338c26448c4SGary King 33996e824bdSMark Brown static void tps6586x_irq_disable(struct irq_data *irq_data) 340c26448c4SGary King { 34196e824bdSMark Brown struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data); 342c26448c4SGary King 34396e824bdSMark Brown unsigned int __irq = irq_data->irq - tps6586x->irq_base; 344c26448c4SGary King const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq]; 345c26448c4SGary King 346c26448c4SGary King tps6586x->mask_reg[data->mask_reg] |= data->mask_mask; 347c26448c4SGary King tps6586x->irq_en &= ~(1 << __irq); 348c26448c4SGary King } 349c26448c4SGary King 35096e824bdSMark Brown static void tps6586x_irq_sync_unlock(struct irq_data *data) 351c26448c4SGary King { 35296e824bdSMark Brown struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data); 353c26448c4SGary King int i; 354c26448c4SGary King 355c26448c4SGary King for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) { 356c26448c4SGary King if (tps6586x->mask_reg[i] != tps6586x->mask_cache[i]) { 357c26448c4SGary King if (!WARN_ON(tps6586x_write(tps6586x->dev, 358c26448c4SGary King TPS6586X_INT_MASK1 + i, 359c26448c4SGary King tps6586x->mask_reg[i]))) 360c26448c4SGary King tps6586x->mask_cache[i] = tps6586x->mask_reg[i]; 361c26448c4SGary King } 362c26448c4SGary King } 363c26448c4SGary King 364c26448c4SGary King mutex_unlock(&tps6586x->irq_lock); 365c26448c4SGary King } 366c26448c4SGary King 367c26448c4SGary King static irqreturn_t tps6586x_irq(int irq, void *data) 368c26448c4SGary King { 369c26448c4SGary King struct tps6586x *tps6586x = data; 370c26448c4SGary King u32 acks; 371c26448c4SGary King int ret = 0; 372c26448c4SGary King 373c26448c4SGary King ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, 374c26448c4SGary King sizeof(acks), (uint8_t *)&acks); 375c26448c4SGary King 376c26448c4SGary King if (ret < 0) { 377c26448c4SGary King dev_err(tps6586x->dev, "failed to read interrupt status\n"); 378c26448c4SGary King return IRQ_NONE; 379c26448c4SGary King } 380c26448c4SGary King 381c26448c4SGary King acks = le32_to_cpu(acks); 382c26448c4SGary King 383c26448c4SGary King while (acks) { 384c26448c4SGary King int i = __ffs(acks); 385c26448c4SGary King 386c26448c4SGary King if (tps6586x->irq_en & (1 << i)) 387c26448c4SGary King handle_nested_irq(tps6586x->irq_base + i); 388c26448c4SGary King 389c26448c4SGary King acks &= ~(1 << i); 390c26448c4SGary King } 391c26448c4SGary King 392c26448c4SGary King return IRQ_HANDLED; 393c26448c4SGary King } 394c26448c4SGary King 395c26448c4SGary King static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq, 396c26448c4SGary King int irq_base) 397c26448c4SGary King { 398c26448c4SGary King int i, ret; 399c26448c4SGary King u8 tmp[4]; 400c26448c4SGary King 401c26448c4SGary King if (!irq_base) { 402c26448c4SGary King dev_warn(tps6586x->dev, "No interrupt support on IRQ base\n"); 403c26448c4SGary King return -EINVAL; 404c26448c4SGary King } 405c26448c4SGary King 406c26448c4SGary King mutex_init(&tps6586x->irq_lock); 407c26448c4SGary King for (i = 0; i < 5; i++) { 408c26448c4SGary King tps6586x->mask_cache[i] = 0xff; 409c26448c4SGary King tps6586x->mask_reg[i] = 0xff; 410c26448c4SGary King tps6586x_write(tps6586x->dev, TPS6586X_INT_MASK1 + i, 0xff); 411c26448c4SGary King } 412c26448c4SGary King 413c26448c4SGary King tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, sizeof(tmp), tmp); 414c26448c4SGary King 415c26448c4SGary King tps6586x->irq_base = irq_base; 416c26448c4SGary King 417c26448c4SGary King tps6586x->irq_chip.name = "tps6586x"; 41896e824bdSMark Brown tps6586x->irq_chip.irq_enable = tps6586x_irq_enable; 41996e824bdSMark Brown tps6586x->irq_chip.irq_disable = tps6586x_irq_disable; 42096e824bdSMark Brown tps6586x->irq_chip.irq_bus_lock = tps6586x_irq_lock; 42196e824bdSMark Brown tps6586x->irq_chip.irq_bus_sync_unlock = tps6586x_irq_sync_unlock; 422c26448c4SGary King 423c26448c4SGary King for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) { 424c26448c4SGary King int __irq = i + tps6586x->irq_base; 425d5bb1221SThomas Gleixner irq_set_chip_data(__irq, tps6586x); 426d5bb1221SThomas Gleixner irq_set_chip_and_handler(__irq, &tps6586x->irq_chip, 427c26448c4SGary King handle_simple_irq); 428d5bb1221SThomas Gleixner irq_set_nested_thread(__irq, 1); 429c26448c4SGary King #ifdef CONFIG_ARM 430c26448c4SGary King set_irq_flags(__irq, IRQF_VALID); 431c26448c4SGary King #endif 432c26448c4SGary King } 433c26448c4SGary King 434c26448c4SGary King ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT, 435c26448c4SGary King "tps6586x", tps6586x); 436c26448c4SGary King 437c26448c4SGary King if (!ret) { 438c26448c4SGary King device_init_wakeup(tps6586x->dev, 1); 439c26448c4SGary King enable_irq_wake(irq); 440c26448c4SGary King } 441c26448c4SGary King 442c26448c4SGary King return ret; 443c26448c4SGary King } 444c26448c4SGary King 445c6c19332SMike Rapoport static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, 446c6c19332SMike Rapoport struct tps6586x_platform_data *pdata) 447c6c19332SMike Rapoport { 448c6c19332SMike Rapoport struct tps6586x_subdev_info *subdev; 449c6c19332SMike Rapoport struct platform_device *pdev; 450c6c19332SMike Rapoport int i, ret = 0; 451c6c19332SMike Rapoport 452c6c19332SMike Rapoport for (i = 0; i < pdata->num_subdevs; i++) { 453c6c19332SMike Rapoport subdev = &pdata->subdevs[i]; 454c6c19332SMike Rapoport 455c6c19332SMike Rapoport pdev = platform_device_alloc(subdev->name, subdev->id); 456929980abSAxel Lin if (!pdev) { 457929980abSAxel Lin ret = -ENOMEM; 458929980abSAxel Lin goto failed; 459929980abSAxel Lin } 460c6c19332SMike Rapoport 461c6c19332SMike Rapoport pdev->dev.parent = tps6586x->dev; 462c6c19332SMike Rapoport pdev->dev.platform_data = subdev->platform_data; 463c6c19332SMike Rapoport 464c6c19332SMike Rapoport ret = platform_device_add(pdev); 465929980abSAxel Lin if (ret) { 466929980abSAxel Lin platform_device_put(pdev); 467c6c19332SMike Rapoport goto failed; 468c6c19332SMike Rapoport } 469929980abSAxel Lin } 470c6c19332SMike Rapoport return 0; 471c6c19332SMike Rapoport 472c6c19332SMike Rapoport failed: 473c6c19332SMike Rapoport tps6586x_remove_subdevs(tps6586x); 474c6c19332SMike Rapoport return ret; 475c6c19332SMike Rapoport } 476c6c19332SMike Rapoport 477c6c19332SMike Rapoport static int __devinit tps6586x_i2c_probe(struct i2c_client *client, 478c6c19332SMike Rapoport const struct i2c_device_id *id) 479c6c19332SMike Rapoport { 480c6c19332SMike Rapoport struct tps6586x_platform_data *pdata = client->dev.platform_data; 481c6c19332SMike Rapoport struct tps6586x *tps6586x; 482c6c19332SMike Rapoport int ret; 483c6c19332SMike Rapoport 484c6c19332SMike Rapoport if (!pdata) { 485c6c19332SMike Rapoport dev_err(&client->dev, "tps6586x requires platform data\n"); 486c6c19332SMike Rapoport return -ENOTSUPP; 487c6c19332SMike Rapoport } 488c6c19332SMike Rapoport 489c6c19332SMike Rapoport ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); 490c6c19332SMike Rapoport if (ret < 0) { 491c6c19332SMike Rapoport dev_err(&client->dev, "Chip ID read failed: %d\n", ret); 492c6c19332SMike Rapoport return -EIO; 493c6c19332SMike Rapoport } 494c6c19332SMike Rapoport 4954d1cdbf6SStephen Warren dev_info(&client->dev, "VERSIONCRC is %02x\n", ret); 496c6c19332SMike Rapoport 497c6c19332SMike Rapoport tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL); 498c6c19332SMike Rapoport if (tps6586x == NULL) 499c6c19332SMike Rapoport return -ENOMEM; 500c6c19332SMike Rapoport 501c6c19332SMike Rapoport tps6586x->client = client; 502c6c19332SMike Rapoport tps6586x->dev = &client->dev; 503c6c19332SMike Rapoport i2c_set_clientdata(client, tps6586x); 504c6c19332SMike Rapoport 505c6c19332SMike Rapoport mutex_init(&tps6586x->lock); 506c6c19332SMike Rapoport 507c26448c4SGary King if (client->irq) { 508c26448c4SGary King ret = tps6586x_irq_init(tps6586x, client->irq, 509c26448c4SGary King pdata->irq_base); 510c26448c4SGary King if (ret) { 511c26448c4SGary King dev_err(&client->dev, "IRQ init failed: %d\n", ret); 512c26448c4SGary King goto err_irq_init; 513c26448c4SGary King } 514c26448c4SGary King } 515c26448c4SGary King 5166f9f13bfSVincent Palatin ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base); 5176f9f13bfSVincent Palatin if (ret) { 5186f9f13bfSVincent Palatin dev_err(&client->dev, "GPIO registration failed: %d\n", ret); 5196f9f13bfSVincent Palatin goto err_gpio_init; 5206f9f13bfSVincent Palatin } 5216f9f13bfSVincent Palatin 522c6c19332SMike Rapoport ret = tps6586x_add_subdevs(tps6586x, pdata); 523c6c19332SMike Rapoport if (ret) { 524c6c19332SMike Rapoport dev_err(&client->dev, "add devices failed: %d\n", ret); 525c6c19332SMike Rapoport goto err_add_devs; 526c6c19332SMike Rapoport } 527c6c19332SMike Rapoport 528c6c19332SMike Rapoport return 0; 529c6c19332SMike Rapoport 530c6c19332SMike Rapoport err_add_devs: 5316f9f13bfSVincent Palatin if (pdata->gpio_base) { 5326f9f13bfSVincent Palatin ret = gpiochip_remove(&tps6586x->gpio); 5336f9f13bfSVincent Palatin if (ret) 5346f9f13bfSVincent Palatin dev_err(&client->dev, "Can't remove gpio chip: %d\n", 5356f9f13bfSVincent Palatin ret); 5366f9f13bfSVincent Palatin } 5376f9f13bfSVincent Palatin err_gpio_init: 538c26448c4SGary King if (client->irq) 539c26448c4SGary King free_irq(client->irq, tps6586x); 540c26448c4SGary King err_irq_init: 541c6c19332SMike Rapoport kfree(tps6586x); 542c6c19332SMike Rapoport return ret; 543c6c19332SMike Rapoport } 544c6c19332SMike Rapoport 545c6c19332SMike Rapoport static int __devexit tps6586x_i2c_remove(struct i2c_client *client) 546c6c19332SMike Rapoport { 5474b751cf5SAxel Lin struct tps6586x *tps6586x = i2c_get_clientdata(client); 5484b751cf5SAxel Lin struct tps6586x_platform_data *pdata = client->dev.platform_data; 5494b751cf5SAxel Lin int ret; 5504b751cf5SAxel Lin 551c26448c4SGary King if (client->irq) 552c26448c4SGary King free_irq(client->irq, tps6586x); 553c26448c4SGary King 5544b751cf5SAxel Lin if (pdata->gpio_base) { 5554b751cf5SAxel Lin ret = gpiochip_remove(&tps6586x->gpio); 5564b751cf5SAxel Lin if (ret) 5574b751cf5SAxel Lin dev_err(&client->dev, "Can't remove gpio chip: %d\n", 5584b751cf5SAxel Lin ret); 5594b751cf5SAxel Lin } 5604b751cf5SAxel Lin 5614b751cf5SAxel Lin tps6586x_remove_subdevs(tps6586x); 5624b751cf5SAxel Lin kfree(tps6586x); 563c6c19332SMike Rapoport return 0; 564c6c19332SMike Rapoport } 565c6c19332SMike Rapoport 566c6c19332SMike Rapoport static const struct i2c_device_id tps6586x_id_table[] = { 567c6c19332SMike Rapoport { "tps6586x", 0 }, 568c6c19332SMike Rapoport { }, 569c6c19332SMike Rapoport }; 570c6c19332SMike Rapoport MODULE_DEVICE_TABLE(i2c, tps6586x_id_table); 571c6c19332SMike Rapoport 572c6c19332SMike Rapoport static struct i2c_driver tps6586x_driver = { 573c6c19332SMike Rapoport .driver = { 574c6c19332SMike Rapoport .name = "tps6586x", 575c6c19332SMike Rapoport .owner = THIS_MODULE, 576c6c19332SMike Rapoport }, 577c6c19332SMike Rapoport .probe = tps6586x_i2c_probe, 578c6c19332SMike Rapoport .remove = __devexit_p(tps6586x_i2c_remove), 579c6c19332SMike Rapoport .id_table = tps6586x_id_table, 580c6c19332SMike Rapoport }; 581c6c19332SMike Rapoport 582c6c19332SMike Rapoport static int __init tps6586x_init(void) 583c6c19332SMike Rapoport { 584c6c19332SMike Rapoport return i2c_add_driver(&tps6586x_driver); 585c6c19332SMike Rapoport } 586c6c19332SMike Rapoport subsys_initcall(tps6586x_init); 587c6c19332SMike Rapoport 588c6c19332SMike Rapoport static void __exit tps6586x_exit(void) 589c6c19332SMike Rapoport { 590c6c19332SMike Rapoport i2c_del_driver(&tps6586x_driver); 591c6c19332SMike Rapoport } 592c6c19332SMike Rapoport module_exit(tps6586x_exit); 593c6c19332SMike Rapoport 594c6c19332SMike Rapoport MODULE_DESCRIPTION("TPS6586X core driver"); 595c6c19332SMike Rapoport MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); 596c6c19332SMike Rapoport MODULE_LICENSE("GPL"); 597