1f4e8afdcSSundar Iyer /* 2f4e8afdcSSundar Iyer * Copyright (C) ST-Ericsson SA 2010 3f4e8afdcSSundar Iyer * 4f4e8afdcSSundar Iyer * License Terms: GNU General Public License, version 2 5f4e8afdcSSundar Iyer * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson 6f4e8afdcSSundar Iyer * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson 7f4e8afdcSSundar Iyer */ 8f4e8afdcSSundar Iyer 9f4e8afdcSSundar Iyer #include <linux/module.h> 10f4e8afdcSSundar Iyer #include <linux/interrupt.h> 11f4e8afdcSSundar Iyer #include <linux/irq.h> 1215e27b10SLee Jones #include <linux/irqdomain.h> 13f4e8afdcSSundar Iyer #include <linux/slab.h> 14f4e8afdcSSundar Iyer #include <linux/i2c.h> 15*a435ae1dSLee Jones #include <linux/of.h> 16f4e8afdcSSundar Iyer #include <linux/mfd/core.h> 17f4e8afdcSSundar Iyer #include <linux/mfd/tc3589x.h> 18f4e8afdcSSundar Iyer 19593e9d70SSundar Iyer #define TC3589x_CLKMODE_MODCTL_SLEEP 0x0 20593e9d70SSundar Iyer #define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0) 21593e9d70SSundar Iyer 22f4e8afdcSSundar Iyer /** 2320406ebfSSundar Iyer * tc3589x_reg_read() - read a single TC3589x register 2420406ebfSSundar Iyer * @tc3589x: Device to read from 25f4e8afdcSSundar Iyer * @reg: Register to read 26f4e8afdcSSundar Iyer */ 2720406ebfSSundar Iyer int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg) 28f4e8afdcSSundar Iyer { 29f4e8afdcSSundar Iyer int ret; 30f4e8afdcSSundar Iyer 3120406ebfSSundar Iyer ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg); 32f4e8afdcSSundar Iyer if (ret < 0) 3320406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to read reg %#x: %d\n", 34f4e8afdcSSundar Iyer reg, ret); 35f4e8afdcSSundar Iyer 36f4e8afdcSSundar Iyer return ret; 37f4e8afdcSSundar Iyer } 3820406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_reg_read); 39f4e8afdcSSundar Iyer 40f4e8afdcSSundar Iyer /** 4120406ebfSSundar Iyer * tc3589x_reg_read() - write a single TC3589x register 4220406ebfSSundar Iyer * @tc3589x: Device to write to 43f4e8afdcSSundar Iyer * @reg: Register to read 44f4e8afdcSSundar Iyer * @data: Value to write 45f4e8afdcSSundar Iyer */ 4620406ebfSSundar Iyer int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data) 47f4e8afdcSSundar Iyer { 48f4e8afdcSSundar Iyer int ret; 49f4e8afdcSSundar Iyer 5020406ebfSSundar Iyer ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data); 51f4e8afdcSSundar Iyer if (ret < 0) 5220406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to write reg %#x: %d\n", 53f4e8afdcSSundar Iyer reg, ret); 54f4e8afdcSSundar Iyer 55f4e8afdcSSundar Iyer return ret; 56f4e8afdcSSundar Iyer } 5720406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_reg_write); 58f4e8afdcSSundar Iyer 59f4e8afdcSSundar Iyer /** 6020406ebfSSundar Iyer * tc3589x_block_read() - read multiple TC3589x registers 6120406ebfSSundar Iyer * @tc3589x: Device to read from 62f4e8afdcSSundar Iyer * @reg: First register 63f4e8afdcSSundar Iyer * @length: Number of registers 64f4e8afdcSSundar Iyer * @values: Buffer to write to 65f4e8afdcSSundar Iyer */ 6620406ebfSSundar Iyer int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values) 67f4e8afdcSSundar Iyer { 68f4e8afdcSSundar Iyer int ret; 69f4e8afdcSSundar Iyer 7020406ebfSSundar Iyer ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values); 71f4e8afdcSSundar Iyer if (ret < 0) 7220406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to read regs %#x: %d\n", 73f4e8afdcSSundar Iyer reg, ret); 74f4e8afdcSSundar Iyer 75f4e8afdcSSundar Iyer return ret; 76f4e8afdcSSundar Iyer } 7720406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_block_read); 78f4e8afdcSSundar Iyer 79f4e8afdcSSundar Iyer /** 8020406ebfSSundar Iyer * tc3589x_block_write() - write multiple TC3589x registers 8120406ebfSSundar Iyer * @tc3589x: Device to write to 82f4e8afdcSSundar Iyer * @reg: First register 83f4e8afdcSSundar Iyer * @length: Number of registers 84f4e8afdcSSundar Iyer * @values: Values to write 85f4e8afdcSSundar Iyer */ 8620406ebfSSundar Iyer int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, 87f4e8afdcSSundar Iyer const u8 *values) 88f4e8afdcSSundar Iyer { 89f4e8afdcSSundar Iyer int ret; 90f4e8afdcSSundar Iyer 9120406ebfSSundar Iyer ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length, 92f4e8afdcSSundar Iyer values); 93f4e8afdcSSundar Iyer if (ret < 0) 9420406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to write regs %#x: %d\n", 95f4e8afdcSSundar Iyer reg, ret); 96f4e8afdcSSundar Iyer 97f4e8afdcSSundar Iyer return ret; 98f4e8afdcSSundar Iyer } 9920406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_block_write); 100f4e8afdcSSundar Iyer 101f4e8afdcSSundar Iyer /** 10220406ebfSSundar Iyer * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register 10320406ebfSSundar Iyer * @tc3589x: Device to write to 104f4e8afdcSSundar Iyer * @reg: Register to write 105f4e8afdcSSundar Iyer * @mask: Mask of bits to set 106f4e8afdcSSundar Iyer * @values: Value to set 107f4e8afdcSSundar Iyer */ 10820406ebfSSundar Iyer int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val) 109f4e8afdcSSundar Iyer { 110f4e8afdcSSundar Iyer int ret; 111f4e8afdcSSundar Iyer 11220406ebfSSundar Iyer mutex_lock(&tc3589x->lock); 113f4e8afdcSSundar Iyer 11420406ebfSSundar Iyer ret = tc3589x_reg_read(tc3589x, reg); 115f4e8afdcSSundar Iyer if (ret < 0) 116f4e8afdcSSundar Iyer goto out; 117f4e8afdcSSundar Iyer 118f4e8afdcSSundar Iyer ret &= ~mask; 119f4e8afdcSSundar Iyer ret |= val; 120f4e8afdcSSundar Iyer 12120406ebfSSundar Iyer ret = tc3589x_reg_write(tc3589x, reg, ret); 122f4e8afdcSSundar Iyer 123f4e8afdcSSundar Iyer out: 12420406ebfSSundar Iyer mutex_unlock(&tc3589x->lock); 125f4e8afdcSSundar Iyer return ret; 126f4e8afdcSSundar Iyer } 12720406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_set_bits); 128f4e8afdcSSundar Iyer 129f4e8afdcSSundar Iyer static struct resource gpio_resources[] = { 130f4e8afdcSSundar Iyer { 13120406ebfSSundar Iyer .start = TC3589x_INT_GPIIRQ, 13220406ebfSSundar Iyer .end = TC3589x_INT_GPIIRQ, 133f4e8afdcSSundar Iyer .flags = IORESOURCE_IRQ, 134f4e8afdcSSundar Iyer }, 135f4e8afdcSSundar Iyer }; 136f4e8afdcSSundar Iyer 13709c730a4SSundar Iyer static struct resource keypad_resources[] = { 13809c730a4SSundar Iyer { 13909c730a4SSundar Iyer .start = TC3589x_INT_KBDIRQ, 14009c730a4SSundar Iyer .end = TC3589x_INT_KBDIRQ, 14109c730a4SSundar Iyer .flags = IORESOURCE_IRQ, 14209c730a4SSundar Iyer }, 14309c730a4SSundar Iyer }; 14409c730a4SSundar Iyer 145611b7590SSundar Iyer static struct mfd_cell tc3589x_dev_gpio[] = { 146f4e8afdcSSundar Iyer { 14720406ebfSSundar Iyer .name = "tc3589x-gpio", 148f4e8afdcSSundar Iyer .num_resources = ARRAY_SIZE(gpio_resources), 149f4e8afdcSSundar Iyer .resources = &gpio_resources[0], 150*a435ae1dSLee Jones .of_compatible = "tc3589x-gpio", 151f4e8afdcSSundar Iyer }, 152f4e8afdcSSundar Iyer }; 153f4e8afdcSSundar Iyer 15409c730a4SSundar Iyer static struct mfd_cell tc3589x_dev_keypad[] = { 15509c730a4SSundar Iyer { 15609c730a4SSundar Iyer .name = "tc3589x-keypad", 15709c730a4SSundar Iyer .num_resources = ARRAY_SIZE(keypad_resources), 15809c730a4SSundar Iyer .resources = &keypad_resources[0], 159*a435ae1dSLee Jones .of_compatible = "tc3589x-keypad", 16009c730a4SSundar Iyer }, 16109c730a4SSundar Iyer }; 16209c730a4SSundar Iyer 16320406ebfSSundar Iyer static irqreturn_t tc3589x_irq(int irq, void *data) 164f4e8afdcSSundar Iyer { 16520406ebfSSundar Iyer struct tc3589x *tc3589x = data; 166f4e8afdcSSundar Iyer int status; 167f4e8afdcSSundar Iyer 168bd77efd0SSundar Iyer again: 16920406ebfSSundar Iyer status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); 170f4e8afdcSSundar Iyer if (status < 0) 171f4e8afdcSSundar Iyer return IRQ_NONE; 172f4e8afdcSSundar Iyer 173f4e8afdcSSundar Iyer while (status) { 174f4e8afdcSSundar Iyer int bit = __ffs(status); 17515e27b10SLee Jones int virq = irq_create_mapping(tc3589x->domain, bit); 176f4e8afdcSSundar Iyer 17715e27b10SLee Jones handle_nested_irq(virq); 178f4e8afdcSSundar Iyer status &= ~(1 << bit); 179f4e8afdcSSundar Iyer } 180f4e8afdcSSundar Iyer 181f4e8afdcSSundar Iyer /* 182f4e8afdcSSundar Iyer * A dummy read or write (to any register) appears to be necessary to 183f4e8afdcSSundar Iyer * have the last interrupt clear (for example, GPIO IC write) take 184bd77efd0SSundar Iyer * effect. In such a case, recheck for any interrupt which is still 185bd77efd0SSundar Iyer * pending. 186f4e8afdcSSundar Iyer */ 187bd77efd0SSundar Iyer status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); 188bd77efd0SSundar Iyer if (status) 189bd77efd0SSundar Iyer goto again; 190f4e8afdcSSundar Iyer 191f4e8afdcSSundar Iyer return IRQ_HANDLED; 192f4e8afdcSSundar Iyer } 193f4e8afdcSSundar Iyer 19415e27b10SLee Jones static int tc3589x_irq_map(struct irq_domain *d, unsigned int virq, 19515e27b10SLee Jones irq_hw_number_t hwirq) 196f4e8afdcSSundar Iyer { 19715e27b10SLee Jones struct tc3589x *tc3589x = d->host_data; 198f4e8afdcSSundar Iyer 19915e27b10SLee Jones irq_set_chip_data(virq, tc3589x); 20015e27b10SLee Jones irq_set_chip_and_handler(virq, &dummy_irq_chip, 201f4e8afdcSSundar Iyer handle_edge_irq); 20215e27b10SLee Jones irq_set_nested_thread(virq, 1); 203f4e8afdcSSundar Iyer #ifdef CONFIG_ARM 20415e27b10SLee Jones set_irq_flags(virq, IRQF_VALID); 205f4e8afdcSSundar Iyer #else 20615e27b10SLee Jones irq_set_noprobe(virq); 207f4e8afdcSSundar Iyer #endif 208f4e8afdcSSundar Iyer 209f4e8afdcSSundar Iyer return 0; 210f4e8afdcSSundar Iyer } 211f4e8afdcSSundar Iyer 21215e27b10SLee Jones static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq) 21315e27b10SLee Jones { 21415e27b10SLee Jones #ifdef CONFIG_ARM 21515e27b10SLee Jones set_irq_flags(virq, 0); 21615e27b10SLee Jones #endif 21715e27b10SLee Jones irq_set_chip_and_handler(virq, NULL, NULL); 21815e27b10SLee Jones irq_set_chip_data(virq, NULL); 21915e27b10SLee Jones } 22015e27b10SLee Jones 22115e27b10SLee Jones static struct irq_domain_ops tc3589x_irq_ops = { 22215e27b10SLee Jones .map = tc3589x_irq_map, 22315e27b10SLee Jones .unmap = tc3589x_irq_unmap, 22415e27b10SLee Jones .xlate = irq_domain_xlate_twocell, 22515e27b10SLee Jones }; 22615e27b10SLee Jones 227*a435ae1dSLee Jones static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np) 228f4e8afdcSSundar Iyer { 22920406ebfSSundar Iyer int base = tc3589x->irq_base; 230f4e8afdcSSundar Iyer 23115e27b10SLee Jones if (base) { 23215e27b10SLee Jones tc3589x->domain = irq_domain_add_legacy( 23315e27b10SLee Jones NULL, TC3589x_NR_INTERNAL_IRQS, base, 23415e27b10SLee Jones 0, &tc3589x_irq_ops, tc3589x); 235f4e8afdcSSundar Iyer } 23615e27b10SLee Jones else { 23715e27b10SLee Jones tc3589x->domain = irq_domain_add_linear( 238*a435ae1dSLee Jones np, TC3589x_NR_INTERNAL_IRQS, 23915e27b10SLee Jones &tc3589x_irq_ops, tc3589x); 24015e27b10SLee Jones } 24115e27b10SLee Jones 24215e27b10SLee Jones if (!tc3589x->domain) { 24315e27b10SLee Jones dev_err(tc3589x->dev, "Failed to create irqdomain\n"); 24415e27b10SLee Jones return -ENOSYS; 24515e27b10SLee Jones } 24615e27b10SLee Jones 24715e27b10SLee Jones return 0; 248f4e8afdcSSundar Iyer } 249f4e8afdcSSundar Iyer 25020406ebfSSundar Iyer static int tc3589x_chip_init(struct tc3589x *tc3589x) 251f4e8afdcSSundar Iyer { 252f4e8afdcSSundar Iyer int manf, ver, ret; 253f4e8afdcSSundar Iyer 25420406ebfSSundar Iyer manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE); 255f4e8afdcSSundar Iyer if (manf < 0) 256f4e8afdcSSundar Iyer return manf; 257f4e8afdcSSundar Iyer 25820406ebfSSundar Iyer ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION); 259f4e8afdcSSundar Iyer if (ver < 0) 260f4e8afdcSSundar Iyer return ver; 261f4e8afdcSSundar Iyer 26220406ebfSSundar Iyer if (manf != TC3589x_MANFCODE_MAGIC) { 26320406ebfSSundar Iyer dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf); 264f4e8afdcSSundar Iyer return -EINVAL; 265f4e8afdcSSundar Iyer } 266f4e8afdcSSundar Iyer 26720406ebfSSundar Iyer dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver); 268f4e8afdcSSundar Iyer 269523bc382SSundar Iyer /* 270523bc382SSundar Iyer * Put everything except the IRQ module into reset; 271523bc382SSundar Iyer * also spare the GPIO module for any pin initialization 272523bc382SSundar Iyer * done during pre-kernel boot 273523bc382SSundar Iyer */ 27420406ebfSSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL, 27520406ebfSSundar Iyer TC3589x_RSTCTRL_TIMRST 27620406ebfSSundar Iyer | TC3589x_RSTCTRL_ROTRST 277523bc382SSundar Iyer | TC3589x_RSTCTRL_KBDRST); 278f4e8afdcSSundar Iyer if (ret < 0) 279f4e8afdcSSundar Iyer return ret; 280f4e8afdcSSundar Iyer 281f4e8afdcSSundar Iyer /* Clear the reset interrupt. */ 28220406ebfSSundar Iyer return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1); 283f4e8afdcSSundar Iyer } 284f4e8afdcSSundar Iyer 285611b7590SSundar Iyer static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) 286611b7590SSundar Iyer { 287611b7590SSundar Iyer int ret = 0; 288611b7590SSundar Iyer unsigned int blocks = tc3589x->pdata->block; 289611b7590SSundar Iyer 290611b7590SSundar Iyer if (blocks & TC3589x_BLOCK_GPIO) { 291611b7590SSundar Iyer ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, 292611b7590SSundar Iyer ARRAY_SIZE(tc3589x_dev_gpio), NULL, 29315e27b10SLee Jones tc3589x->irq_base, tc3589x->domain); 294611b7590SSundar Iyer if (ret) { 295611b7590SSundar Iyer dev_err(tc3589x->dev, "failed to add gpio child\n"); 296611b7590SSundar Iyer return ret; 297611b7590SSundar Iyer } 298611b7590SSundar Iyer dev_info(tc3589x->dev, "added gpio block\n"); 299611b7590SSundar Iyer } 300611b7590SSundar Iyer 30109c730a4SSundar Iyer if (blocks & TC3589x_BLOCK_KEYPAD) { 30209c730a4SSundar Iyer ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, 30309c730a4SSundar Iyer ARRAY_SIZE(tc3589x_dev_keypad), NULL, 30415e27b10SLee Jones tc3589x->irq_base, tc3589x->domain); 30509c730a4SSundar Iyer if (ret) { 30609c730a4SSundar Iyer dev_err(tc3589x->dev, "failed to keypad child\n"); 307611b7590SSundar Iyer return ret; 30809c730a4SSundar Iyer } 30909c730a4SSundar Iyer dev_info(tc3589x->dev, "added keypad block\n"); 31009c730a4SSundar Iyer } 311611b7590SSundar Iyer 31209c730a4SSundar Iyer return ret; 313611b7590SSundar Iyer } 314611b7590SSundar Iyer 315*a435ae1dSLee Jones static int tc3589x_of_probe(struct device_node *np, 316*a435ae1dSLee Jones struct tc3589x_platform_data *pdata) 317*a435ae1dSLee Jones { 318*a435ae1dSLee Jones struct device_node *child; 319*a435ae1dSLee Jones 320*a435ae1dSLee Jones for_each_child_of_node(np, child) { 321*a435ae1dSLee Jones if (!strcmp(child->name, "tc3589x_gpio")) { 322*a435ae1dSLee Jones pdata->block |= TC3589x_BLOCK_GPIO; 323*a435ae1dSLee Jones } 324*a435ae1dSLee Jones if (!strcmp(child->name, "tc3589x_keypad")) { 325*a435ae1dSLee Jones pdata->block |= TC3589x_BLOCK_KEYPAD; 326*a435ae1dSLee Jones } 327*a435ae1dSLee Jones } 328*a435ae1dSLee Jones 329*a435ae1dSLee Jones return 0; 330*a435ae1dSLee Jones } 331*a435ae1dSLee Jones 33220406ebfSSundar Iyer static int __devinit tc3589x_probe(struct i2c_client *i2c, 333f4e8afdcSSundar Iyer const struct i2c_device_id *id) 334f4e8afdcSSundar Iyer { 33520406ebfSSundar Iyer struct tc3589x_platform_data *pdata = i2c->dev.platform_data; 336*a435ae1dSLee Jones struct device_node *np = i2c->dev.of_node; 33720406ebfSSundar Iyer struct tc3589x *tc3589x; 338f4e8afdcSSundar Iyer int ret; 339f4e8afdcSSundar Iyer 340*a435ae1dSLee Jones if (!pdata) { 341*a435ae1dSLee Jones if (np) { 342*a435ae1dSLee Jones pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); 343*a435ae1dSLee Jones if (!pdata) 344*a435ae1dSLee Jones return -ENOMEM; 345*a435ae1dSLee Jones 346*a435ae1dSLee Jones ret = tc3589x_of_probe(np, pdata); 347*a435ae1dSLee Jones if (ret) 348*a435ae1dSLee Jones return ret; 349*a435ae1dSLee Jones } 350*a435ae1dSLee Jones else { 351*a435ae1dSLee Jones dev_err(&i2c->dev, "No platform data or DT found\n"); 352*a435ae1dSLee Jones return -EINVAL; 353*a435ae1dSLee Jones } 354*a435ae1dSLee Jones } 355*a435ae1dSLee Jones 356f4e8afdcSSundar Iyer if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA 357f4e8afdcSSundar Iyer | I2C_FUNC_SMBUS_I2C_BLOCK)) 358f4e8afdcSSundar Iyer return -EIO; 359f4e8afdcSSundar Iyer 36020406ebfSSundar Iyer tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL); 36120406ebfSSundar Iyer if (!tc3589x) 362f4e8afdcSSundar Iyer return -ENOMEM; 363f4e8afdcSSundar Iyer 36420406ebfSSundar Iyer mutex_init(&tc3589x->lock); 365f4e8afdcSSundar Iyer 36620406ebfSSundar Iyer tc3589x->dev = &i2c->dev; 36720406ebfSSundar Iyer tc3589x->i2c = i2c; 36820406ebfSSundar Iyer tc3589x->pdata = pdata; 36920406ebfSSundar Iyer tc3589x->irq_base = pdata->irq_base; 37020406ebfSSundar Iyer tc3589x->num_gpio = id->driver_data; 371f4e8afdcSSundar Iyer 37220406ebfSSundar Iyer i2c_set_clientdata(i2c, tc3589x); 373f4e8afdcSSundar Iyer 37420406ebfSSundar Iyer ret = tc3589x_chip_init(tc3589x); 375f4e8afdcSSundar Iyer if (ret) 376f4e8afdcSSundar Iyer goto out_free; 377f4e8afdcSSundar Iyer 378*a435ae1dSLee Jones ret = tc3589x_irq_init(tc3589x, np); 379f4e8afdcSSundar Iyer if (ret) 380f4e8afdcSSundar Iyer goto out_free; 381f4e8afdcSSundar Iyer 38220406ebfSSundar Iyer ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq, 383f4e8afdcSSundar Iyer IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 38420406ebfSSundar Iyer "tc3589x", tc3589x); 385f4e8afdcSSundar Iyer if (ret) { 38620406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret); 38715e27b10SLee Jones goto out_free; 388f4e8afdcSSundar Iyer } 389f4e8afdcSSundar Iyer 390611b7590SSundar Iyer ret = tc3589x_device_init(tc3589x); 391f4e8afdcSSundar Iyer if (ret) { 392611b7590SSundar Iyer dev_err(tc3589x->dev, "failed to add child devices\n"); 393f4e8afdcSSundar Iyer goto out_freeirq; 394f4e8afdcSSundar Iyer } 395f4e8afdcSSundar Iyer 396f4e8afdcSSundar Iyer return 0; 397f4e8afdcSSundar Iyer 398f4e8afdcSSundar Iyer out_freeirq: 39920406ebfSSundar Iyer free_irq(tc3589x->i2c->irq, tc3589x); 400f4e8afdcSSundar Iyer out_free: 40120406ebfSSundar Iyer kfree(tc3589x); 402f4e8afdcSSundar Iyer return ret; 403f4e8afdcSSundar Iyer } 404f4e8afdcSSundar Iyer 40520406ebfSSundar Iyer static int __devexit tc3589x_remove(struct i2c_client *client) 406f4e8afdcSSundar Iyer { 40720406ebfSSundar Iyer struct tc3589x *tc3589x = i2c_get_clientdata(client); 408f4e8afdcSSundar Iyer 40920406ebfSSundar Iyer mfd_remove_devices(tc3589x->dev); 410f4e8afdcSSundar Iyer 41120406ebfSSundar Iyer free_irq(tc3589x->i2c->irq, tc3589x); 412f4e8afdcSSundar Iyer 41320406ebfSSundar Iyer kfree(tc3589x); 414f4e8afdcSSundar Iyer 415f4e8afdcSSundar Iyer return 0; 416f4e8afdcSSundar Iyer } 417f4e8afdcSSundar Iyer 418930bf022SAxel Lin #ifdef CONFIG_PM_SLEEP 419593e9d70SSundar Iyer static int tc3589x_suspend(struct device *dev) 420593e9d70SSundar Iyer { 421593e9d70SSundar Iyer struct tc3589x *tc3589x = dev_get_drvdata(dev); 422593e9d70SSundar Iyer struct i2c_client *client = tc3589x->i2c; 423593e9d70SSundar Iyer int ret = 0; 424593e9d70SSundar Iyer 425593e9d70SSundar Iyer /* put the system to sleep mode */ 426593e9d70SSundar Iyer if (!device_may_wakeup(&client->dev)) 427593e9d70SSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, 428593e9d70SSundar Iyer TC3589x_CLKMODE_MODCTL_SLEEP); 429593e9d70SSundar Iyer 430593e9d70SSundar Iyer return ret; 431593e9d70SSundar Iyer } 432593e9d70SSundar Iyer 433593e9d70SSundar Iyer static int tc3589x_resume(struct device *dev) 434593e9d70SSundar Iyer { 435593e9d70SSundar Iyer struct tc3589x *tc3589x = dev_get_drvdata(dev); 436593e9d70SSundar Iyer struct i2c_client *client = tc3589x->i2c; 437593e9d70SSundar Iyer int ret = 0; 438593e9d70SSundar Iyer 439593e9d70SSundar Iyer /* enable the system into operation */ 440593e9d70SSundar Iyer if (!device_may_wakeup(&client->dev)) 441593e9d70SSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, 442593e9d70SSundar Iyer TC3589x_CLKMODE_MODCTL_OPERATION); 443593e9d70SSundar Iyer 444593e9d70SSundar Iyer return ret; 445593e9d70SSundar Iyer } 44654d8e2c3SLinus Walleij #endif 447593e9d70SSundar Iyer 448930bf022SAxel Lin static SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, tc3589x_resume); 449930bf022SAxel Lin 45020406ebfSSundar Iyer static const struct i2c_device_id tc3589x_id[] = { 45120406ebfSSundar Iyer { "tc3589x", 24 }, 452f4e8afdcSSundar Iyer { } 453f4e8afdcSSundar Iyer }; 45420406ebfSSundar Iyer MODULE_DEVICE_TABLE(i2c, tc3589x_id); 455f4e8afdcSSundar Iyer 45620406ebfSSundar Iyer static struct i2c_driver tc3589x_driver = { 45720406ebfSSundar Iyer .driver.name = "tc3589x", 458f4e8afdcSSundar Iyer .driver.owner = THIS_MODULE, 459593e9d70SSundar Iyer .driver.pm = &tc3589x_dev_pm_ops, 46020406ebfSSundar Iyer .probe = tc3589x_probe, 46120406ebfSSundar Iyer .remove = __devexit_p(tc3589x_remove), 46220406ebfSSundar Iyer .id_table = tc3589x_id, 463f4e8afdcSSundar Iyer }; 464f4e8afdcSSundar Iyer 46520406ebfSSundar Iyer static int __init tc3589x_init(void) 466f4e8afdcSSundar Iyer { 46720406ebfSSundar Iyer return i2c_add_driver(&tc3589x_driver); 468f4e8afdcSSundar Iyer } 46920406ebfSSundar Iyer subsys_initcall(tc3589x_init); 470f4e8afdcSSundar Iyer 47120406ebfSSundar Iyer static void __exit tc3589x_exit(void) 472f4e8afdcSSundar Iyer { 47320406ebfSSundar Iyer i2c_del_driver(&tc3589x_driver); 474f4e8afdcSSundar Iyer } 47520406ebfSSundar Iyer module_exit(tc3589x_exit); 476f4e8afdcSSundar Iyer 477f4e8afdcSSundar Iyer MODULE_LICENSE("GPL v2"); 47820406ebfSSundar Iyer MODULE_DESCRIPTION("TC3589x MFD core driver"); 479f4e8afdcSSundar Iyer MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); 480