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> 12*15e27b10SLee Jones #include <linux/irqdomain.h> 13f4e8afdcSSundar Iyer #include <linux/slab.h> 14f4e8afdcSSundar Iyer #include <linux/i2c.h> 15f4e8afdcSSundar Iyer #include <linux/mfd/core.h> 16f4e8afdcSSundar Iyer #include <linux/mfd/tc3589x.h> 17f4e8afdcSSundar Iyer 18593e9d70SSundar Iyer #define TC3589x_CLKMODE_MODCTL_SLEEP 0x0 19593e9d70SSundar Iyer #define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0) 20593e9d70SSundar Iyer 21f4e8afdcSSundar Iyer /** 2220406ebfSSundar Iyer * tc3589x_reg_read() - read a single TC3589x register 2320406ebfSSundar Iyer * @tc3589x: Device to read from 24f4e8afdcSSundar Iyer * @reg: Register to read 25f4e8afdcSSundar Iyer */ 2620406ebfSSundar Iyer int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg) 27f4e8afdcSSundar Iyer { 28f4e8afdcSSundar Iyer int ret; 29f4e8afdcSSundar Iyer 3020406ebfSSundar Iyer ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg); 31f4e8afdcSSundar Iyer if (ret < 0) 3220406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to read reg %#x: %d\n", 33f4e8afdcSSundar Iyer reg, ret); 34f4e8afdcSSundar Iyer 35f4e8afdcSSundar Iyer return ret; 36f4e8afdcSSundar Iyer } 3720406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_reg_read); 38f4e8afdcSSundar Iyer 39f4e8afdcSSundar Iyer /** 4020406ebfSSundar Iyer * tc3589x_reg_read() - write a single TC3589x register 4120406ebfSSundar Iyer * @tc3589x: Device to write to 42f4e8afdcSSundar Iyer * @reg: Register to read 43f4e8afdcSSundar Iyer * @data: Value to write 44f4e8afdcSSundar Iyer */ 4520406ebfSSundar Iyer int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data) 46f4e8afdcSSundar Iyer { 47f4e8afdcSSundar Iyer int ret; 48f4e8afdcSSundar Iyer 4920406ebfSSundar Iyer ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data); 50f4e8afdcSSundar Iyer if (ret < 0) 5120406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to write reg %#x: %d\n", 52f4e8afdcSSundar Iyer reg, ret); 53f4e8afdcSSundar Iyer 54f4e8afdcSSundar Iyer return ret; 55f4e8afdcSSundar Iyer } 5620406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_reg_write); 57f4e8afdcSSundar Iyer 58f4e8afdcSSundar Iyer /** 5920406ebfSSundar Iyer * tc3589x_block_read() - read multiple TC3589x registers 6020406ebfSSundar Iyer * @tc3589x: Device to read from 61f4e8afdcSSundar Iyer * @reg: First register 62f4e8afdcSSundar Iyer * @length: Number of registers 63f4e8afdcSSundar Iyer * @values: Buffer to write to 64f4e8afdcSSundar Iyer */ 6520406ebfSSundar Iyer int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values) 66f4e8afdcSSundar Iyer { 67f4e8afdcSSundar Iyer int ret; 68f4e8afdcSSundar Iyer 6920406ebfSSundar Iyer ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values); 70f4e8afdcSSundar Iyer if (ret < 0) 7120406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to read regs %#x: %d\n", 72f4e8afdcSSundar Iyer reg, ret); 73f4e8afdcSSundar Iyer 74f4e8afdcSSundar Iyer return ret; 75f4e8afdcSSundar Iyer } 7620406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_block_read); 77f4e8afdcSSundar Iyer 78f4e8afdcSSundar Iyer /** 7920406ebfSSundar Iyer * tc3589x_block_write() - write multiple TC3589x registers 8020406ebfSSundar Iyer * @tc3589x: Device to write to 81f4e8afdcSSundar Iyer * @reg: First register 82f4e8afdcSSundar Iyer * @length: Number of registers 83f4e8afdcSSundar Iyer * @values: Values to write 84f4e8afdcSSundar Iyer */ 8520406ebfSSundar Iyer int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, 86f4e8afdcSSundar Iyer const u8 *values) 87f4e8afdcSSundar Iyer { 88f4e8afdcSSundar Iyer int ret; 89f4e8afdcSSundar Iyer 9020406ebfSSundar Iyer ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length, 91f4e8afdcSSundar Iyer values); 92f4e8afdcSSundar Iyer if (ret < 0) 9320406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to write regs %#x: %d\n", 94f4e8afdcSSundar Iyer reg, ret); 95f4e8afdcSSundar Iyer 96f4e8afdcSSundar Iyer return ret; 97f4e8afdcSSundar Iyer } 9820406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_block_write); 99f4e8afdcSSundar Iyer 100f4e8afdcSSundar Iyer /** 10120406ebfSSundar Iyer * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register 10220406ebfSSundar Iyer * @tc3589x: Device to write to 103f4e8afdcSSundar Iyer * @reg: Register to write 104f4e8afdcSSundar Iyer * @mask: Mask of bits to set 105f4e8afdcSSundar Iyer * @values: Value to set 106f4e8afdcSSundar Iyer */ 10720406ebfSSundar Iyer int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val) 108f4e8afdcSSundar Iyer { 109f4e8afdcSSundar Iyer int ret; 110f4e8afdcSSundar Iyer 11120406ebfSSundar Iyer mutex_lock(&tc3589x->lock); 112f4e8afdcSSundar Iyer 11320406ebfSSundar Iyer ret = tc3589x_reg_read(tc3589x, reg); 114f4e8afdcSSundar Iyer if (ret < 0) 115f4e8afdcSSundar Iyer goto out; 116f4e8afdcSSundar Iyer 117f4e8afdcSSundar Iyer ret &= ~mask; 118f4e8afdcSSundar Iyer ret |= val; 119f4e8afdcSSundar Iyer 12020406ebfSSundar Iyer ret = tc3589x_reg_write(tc3589x, reg, ret); 121f4e8afdcSSundar Iyer 122f4e8afdcSSundar Iyer out: 12320406ebfSSundar Iyer mutex_unlock(&tc3589x->lock); 124f4e8afdcSSundar Iyer return ret; 125f4e8afdcSSundar Iyer } 12620406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_set_bits); 127f4e8afdcSSundar Iyer 128f4e8afdcSSundar Iyer static struct resource gpio_resources[] = { 129f4e8afdcSSundar Iyer { 13020406ebfSSundar Iyer .start = TC3589x_INT_GPIIRQ, 13120406ebfSSundar Iyer .end = TC3589x_INT_GPIIRQ, 132f4e8afdcSSundar Iyer .flags = IORESOURCE_IRQ, 133f4e8afdcSSundar Iyer }, 134f4e8afdcSSundar Iyer }; 135f4e8afdcSSundar Iyer 13609c730a4SSundar Iyer static struct resource keypad_resources[] = { 13709c730a4SSundar Iyer { 13809c730a4SSundar Iyer .start = TC3589x_INT_KBDIRQ, 13909c730a4SSundar Iyer .end = TC3589x_INT_KBDIRQ, 14009c730a4SSundar Iyer .flags = IORESOURCE_IRQ, 14109c730a4SSundar Iyer }, 14209c730a4SSundar Iyer }; 14309c730a4SSundar Iyer 144611b7590SSundar Iyer static struct mfd_cell tc3589x_dev_gpio[] = { 145f4e8afdcSSundar Iyer { 14620406ebfSSundar Iyer .name = "tc3589x-gpio", 147f4e8afdcSSundar Iyer .num_resources = ARRAY_SIZE(gpio_resources), 148f4e8afdcSSundar Iyer .resources = &gpio_resources[0], 149f4e8afdcSSundar Iyer }, 150f4e8afdcSSundar Iyer }; 151f4e8afdcSSundar Iyer 15209c730a4SSundar Iyer static struct mfd_cell tc3589x_dev_keypad[] = { 15309c730a4SSundar Iyer { 15409c730a4SSundar Iyer .name = "tc3589x-keypad", 15509c730a4SSundar Iyer .num_resources = ARRAY_SIZE(keypad_resources), 15609c730a4SSundar Iyer .resources = &keypad_resources[0], 15709c730a4SSundar Iyer }, 15809c730a4SSundar Iyer }; 15909c730a4SSundar Iyer 16020406ebfSSundar Iyer static irqreturn_t tc3589x_irq(int irq, void *data) 161f4e8afdcSSundar Iyer { 16220406ebfSSundar Iyer struct tc3589x *tc3589x = data; 163f4e8afdcSSundar Iyer int status; 164f4e8afdcSSundar Iyer 165bd77efd0SSundar Iyer again: 16620406ebfSSundar Iyer status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); 167f4e8afdcSSundar Iyer if (status < 0) 168f4e8afdcSSundar Iyer return IRQ_NONE; 169f4e8afdcSSundar Iyer 170f4e8afdcSSundar Iyer while (status) { 171f4e8afdcSSundar Iyer int bit = __ffs(status); 172*15e27b10SLee Jones int virq = irq_create_mapping(tc3589x->domain, bit); 173f4e8afdcSSundar Iyer 174*15e27b10SLee Jones handle_nested_irq(virq); 175f4e8afdcSSundar Iyer status &= ~(1 << bit); 176f4e8afdcSSundar Iyer } 177f4e8afdcSSundar Iyer 178f4e8afdcSSundar Iyer /* 179f4e8afdcSSundar Iyer * A dummy read or write (to any register) appears to be necessary to 180f4e8afdcSSundar Iyer * have the last interrupt clear (for example, GPIO IC write) take 181bd77efd0SSundar Iyer * effect. In such a case, recheck for any interrupt which is still 182bd77efd0SSundar Iyer * pending. 183f4e8afdcSSundar Iyer */ 184bd77efd0SSundar Iyer status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); 185bd77efd0SSundar Iyer if (status) 186bd77efd0SSundar Iyer goto again; 187f4e8afdcSSundar Iyer 188f4e8afdcSSundar Iyer return IRQ_HANDLED; 189f4e8afdcSSundar Iyer } 190f4e8afdcSSundar Iyer 191*15e27b10SLee Jones static int tc3589x_irq_map(struct irq_domain *d, unsigned int virq, 192*15e27b10SLee Jones irq_hw_number_t hwirq) 193f4e8afdcSSundar Iyer { 194*15e27b10SLee Jones struct tc3589x *tc3589x = d->host_data; 195f4e8afdcSSundar Iyer 196*15e27b10SLee Jones irq_set_chip_data(virq, tc3589x); 197*15e27b10SLee Jones irq_set_chip_and_handler(virq, &dummy_irq_chip, 198f4e8afdcSSundar Iyer handle_edge_irq); 199*15e27b10SLee Jones irq_set_nested_thread(virq, 1); 200f4e8afdcSSundar Iyer #ifdef CONFIG_ARM 201*15e27b10SLee Jones set_irq_flags(virq, IRQF_VALID); 202f4e8afdcSSundar Iyer #else 203*15e27b10SLee Jones irq_set_noprobe(virq); 204f4e8afdcSSundar Iyer #endif 205f4e8afdcSSundar Iyer 206f4e8afdcSSundar Iyer return 0; 207f4e8afdcSSundar Iyer } 208f4e8afdcSSundar Iyer 209*15e27b10SLee Jones static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq) 210*15e27b10SLee Jones { 211*15e27b10SLee Jones #ifdef CONFIG_ARM 212*15e27b10SLee Jones set_irq_flags(virq, 0); 213*15e27b10SLee Jones #endif 214*15e27b10SLee Jones irq_set_chip_and_handler(virq, NULL, NULL); 215*15e27b10SLee Jones irq_set_chip_data(virq, NULL); 216*15e27b10SLee Jones } 217*15e27b10SLee Jones 218*15e27b10SLee Jones static struct irq_domain_ops tc3589x_irq_ops = { 219*15e27b10SLee Jones .map = tc3589x_irq_map, 220*15e27b10SLee Jones .unmap = tc3589x_irq_unmap, 221*15e27b10SLee Jones .xlate = irq_domain_xlate_twocell, 222*15e27b10SLee Jones }; 223*15e27b10SLee Jones 224*15e27b10SLee Jones static int tc3589x_irq_init(struct tc3589x *tc3589x) 225f4e8afdcSSundar Iyer { 22620406ebfSSundar Iyer int base = tc3589x->irq_base; 227f4e8afdcSSundar Iyer 228*15e27b10SLee Jones if (base) { 229*15e27b10SLee Jones tc3589x->domain = irq_domain_add_legacy( 230*15e27b10SLee Jones NULL, TC3589x_NR_INTERNAL_IRQS, base, 231*15e27b10SLee Jones 0, &tc3589x_irq_ops, tc3589x); 232f4e8afdcSSundar Iyer } 233*15e27b10SLee Jones else { 234*15e27b10SLee Jones tc3589x->domain = irq_domain_add_linear( 235*15e27b10SLee Jones NULL, TC3589x_NR_INTERNAL_IRQS, 236*15e27b10SLee Jones &tc3589x_irq_ops, tc3589x); 237*15e27b10SLee Jones } 238*15e27b10SLee Jones 239*15e27b10SLee Jones if (!tc3589x->domain) { 240*15e27b10SLee Jones dev_err(tc3589x->dev, "Failed to create irqdomain\n"); 241*15e27b10SLee Jones return -ENOSYS; 242*15e27b10SLee Jones } 243*15e27b10SLee Jones 244*15e27b10SLee Jones return 0; 245f4e8afdcSSundar Iyer } 246f4e8afdcSSundar Iyer 24720406ebfSSundar Iyer static int tc3589x_chip_init(struct tc3589x *tc3589x) 248f4e8afdcSSundar Iyer { 249f4e8afdcSSundar Iyer int manf, ver, ret; 250f4e8afdcSSundar Iyer 25120406ebfSSundar Iyer manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE); 252f4e8afdcSSundar Iyer if (manf < 0) 253f4e8afdcSSundar Iyer return manf; 254f4e8afdcSSundar Iyer 25520406ebfSSundar Iyer ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION); 256f4e8afdcSSundar Iyer if (ver < 0) 257f4e8afdcSSundar Iyer return ver; 258f4e8afdcSSundar Iyer 25920406ebfSSundar Iyer if (manf != TC3589x_MANFCODE_MAGIC) { 26020406ebfSSundar Iyer dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf); 261f4e8afdcSSundar Iyer return -EINVAL; 262f4e8afdcSSundar Iyer } 263f4e8afdcSSundar Iyer 26420406ebfSSundar Iyer dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver); 265f4e8afdcSSundar Iyer 266523bc382SSundar Iyer /* 267523bc382SSundar Iyer * Put everything except the IRQ module into reset; 268523bc382SSundar Iyer * also spare the GPIO module for any pin initialization 269523bc382SSundar Iyer * done during pre-kernel boot 270523bc382SSundar Iyer */ 27120406ebfSSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL, 27220406ebfSSundar Iyer TC3589x_RSTCTRL_TIMRST 27320406ebfSSundar Iyer | TC3589x_RSTCTRL_ROTRST 274523bc382SSundar Iyer | TC3589x_RSTCTRL_KBDRST); 275f4e8afdcSSundar Iyer if (ret < 0) 276f4e8afdcSSundar Iyer return ret; 277f4e8afdcSSundar Iyer 278f4e8afdcSSundar Iyer /* Clear the reset interrupt. */ 27920406ebfSSundar Iyer return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1); 280f4e8afdcSSundar Iyer } 281f4e8afdcSSundar Iyer 282611b7590SSundar Iyer static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) 283611b7590SSundar Iyer { 284611b7590SSundar Iyer int ret = 0; 285611b7590SSundar Iyer unsigned int blocks = tc3589x->pdata->block; 286611b7590SSundar Iyer 287611b7590SSundar Iyer if (blocks & TC3589x_BLOCK_GPIO) { 288611b7590SSundar Iyer ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, 289611b7590SSundar Iyer ARRAY_SIZE(tc3589x_dev_gpio), NULL, 290*15e27b10SLee Jones tc3589x->irq_base, tc3589x->domain); 291611b7590SSundar Iyer if (ret) { 292611b7590SSundar Iyer dev_err(tc3589x->dev, "failed to add gpio child\n"); 293611b7590SSundar Iyer return ret; 294611b7590SSundar Iyer } 295611b7590SSundar Iyer dev_info(tc3589x->dev, "added gpio block\n"); 296611b7590SSundar Iyer } 297611b7590SSundar Iyer 29809c730a4SSundar Iyer if (blocks & TC3589x_BLOCK_KEYPAD) { 29909c730a4SSundar Iyer ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, 30009c730a4SSundar Iyer ARRAY_SIZE(tc3589x_dev_keypad), NULL, 301*15e27b10SLee Jones tc3589x->irq_base, tc3589x->domain); 30209c730a4SSundar Iyer if (ret) { 30309c730a4SSundar Iyer dev_err(tc3589x->dev, "failed to keypad child\n"); 304611b7590SSundar Iyer return ret; 30509c730a4SSundar Iyer } 30609c730a4SSundar Iyer dev_info(tc3589x->dev, "added keypad block\n"); 30709c730a4SSundar Iyer } 308611b7590SSundar Iyer 30909c730a4SSundar Iyer return ret; 310611b7590SSundar Iyer } 311611b7590SSundar Iyer 31220406ebfSSundar Iyer static int __devinit tc3589x_probe(struct i2c_client *i2c, 313f4e8afdcSSundar Iyer const struct i2c_device_id *id) 314f4e8afdcSSundar Iyer { 31520406ebfSSundar Iyer struct tc3589x_platform_data *pdata = i2c->dev.platform_data; 31620406ebfSSundar Iyer struct tc3589x *tc3589x; 317f4e8afdcSSundar Iyer int ret; 318f4e8afdcSSundar Iyer 319f4e8afdcSSundar Iyer if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA 320f4e8afdcSSundar Iyer | I2C_FUNC_SMBUS_I2C_BLOCK)) 321f4e8afdcSSundar Iyer return -EIO; 322f4e8afdcSSundar Iyer 32320406ebfSSundar Iyer tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL); 32420406ebfSSundar Iyer if (!tc3589x) 325f4e8afdcSSundar Iyer return -ENOMEM; 326f4e8afdcSSundar Iyer 32720406ebfSSundar Iyer mutex_init(&tc3589x->lock); 328f4e8afdcSSundar Iyer 32920406ebfSSundar Iyer tc3589x->dev = &i2c->dev; 33020406ebfSSundar Iyer tc3589x->i2c = i2c; 33120406ebfSSundar Iyer tc3589x->pdata = pdata; 33220406ebfSSundar Iyer tc3589x->irq_base = pdata->irq_base; 33320406ebfSSundar Iyer tc3589x->num_gpio = id->driver_data; 334f4e8afdcSSundar Iyer 33520406ebfSSundar Iyer i2c_set_clientdata(i2c, tc3589x); 336f4e8afdcSSundar Iyer 33720406ebfSSundar Iyer ret = tc3589x_chip_init(tc3589x); 338f4e8afdcSSundar Iyer if (ret) 339f4e8afdcSSundar Iyer goto out_free; 340f4e8afdcSSundar Iyer 34120406ebfSSundar Iyer ret = tc3589x_irq_init(tc3589x); 342f4e8afdcSSundar Iyer if (ret) 343f4e8afdcSSundar Iyer goto out_free; 344f4e8afdcSSundar Iyer 34520406ebfSSundar Iyer ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq, 346f4e8afdcSSundar Iyer IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 34720406ebfSSundar Iyer "tc3589x", tc3589x); 348f4e8afdcSSundar Iyer if (ret) { 34920406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret); 350*15e27b10SLee Jones goto out_free; 351f4e8afdcSSundar Iyer } 352f4e8afdcSSundar Iyer 353611b7590SSundar Iyer ret = tc3589x_device_init(tc3589x); 354f4e8afdcSSundar Iyer if (ret) { 355611b7590SSundar Iyer dev_err(tc3589x->dev, "failed to add child devices\n"); 356f4e8afdcSSundar Iyer goto out_freeirq; 357f4e8afdcSSundar Iyer } 358f4e8afdcSSundar Iyer 359f4e8afdcSSundar Iyer return 0; 360f4e8afdcSSundar Iyer 361f4e8afdcSSundar Iyer out_freeirq: 36220406ebfSSundar Iyer free_irq(tc3589x->i2c->irq, tc3589x); 363f4e8afdcSSundar Iyer out_free: 36420406ebfSSundar Iyer kfree(tc3589x); 365f4e8afdcSSundar Iyer return ret; 366f4e8afdcSSundar Iyer } 367f4e8afdcSSundar Iyer 36820406ebfSSundar Iyer static int __devexit tc3589x_remove(struct i2c_client *client) 369f4e8afdcSSundar Iyer { 37020406ebfSSundar Iyer struct tc3589x *tc3589x = i2c_get_clientdata(client); 371f4e8afdcSSundar Iyer 37220406ebfSSundar Iyer mfd_remove_devices(tc3589x->dev); 373f4e8afdcSSundar Iyer 37420406ebfSSundar Iyer free_irq(tc3589x->i2c->irq, tc3589x); 375f4e8afdcSSundar Iyer 37620406ebfSSundar Iyer kfree(tc3589x); 377f4e8afdcSSundar Iyer 378f4e8afdcSSundar Iyer return 0; 379f4e8afdcSSundar Iyer } 380f4e8afdcSSundar Iyer 381930bf022SAxel Lin #ifdef CONFIG_PM_SLEEP 382593e9d70SSundar Iyer static int tc3589x_suspend(struct device *dev) 383593e9d70SSundar Iyer { 384593e9d70SSundar Iyer struct tc3589x *tc3589x = dev_get_drvdata(dev); 385593e9d70SSundar Iyer struct i2c_client *client = tc3589x->i2c; 386593e9d70SSundar Iyer int ret = 0; 387593e9d70SSundar Iyer 388593e9d70SSundar Iyer /* put the system to sleep mode */ 389593e9d70SSundar Iyer if (!device_may_wakeup(&client->dev)) 390593e9d70SSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, 391593e9d70SSundar Iyer TC3589x_CLKMODE_MODCTL_SLEEP); 392593e9d70SSundar Iyer 393593e9d70SSundar Iyer return ret; 394593e9d70SSundar Iyer } 395593e9d70SSundar Iyer 396593e9d70SSundar Iyer static int tc3589x_resume(struct device *dev) 397593e9d70SSundar Iyer { 398593e9d70SSundar Iyer struct tc3589x *tc3589x = dev_get_drvdata(dev); 399593e9d70SSundar Iyer struct i2c_client *client = tc3589x->i2c; 400593e9d70SSundar Iyer int ret = 0; 401593e9d70SSundar Iyer 402593e9d70SSundar Iyer /* enable the system into operation */ 403593e9d70SSundar Iyer if (!device_may_wakeup(&client->dev)) 404593e9d70SSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, 405593e9d70SSundar Iyer TC3589x_CLKMODE_MODCTL_OPERATION); 406593e9d70SSundar Iyer 407593e9d70SSundar Iyer return ret; 408593e9d70SSundar Iyer } 40954d8e2c3SLinus Walleij #endif 410593e9d70SSundar Iyer 411930bf022SAxel Lin static SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, tc3589x_resume); 412930bf022SAxel Lin 41320406ebfSSundar Iyer static const struct i2c_device_id tc3589x_id[] = { 41420406ebfSSundar Iyer { "tc3589x", 24 }, 415f4e8afdcSSundar Iyer { } 416f4e8afdcSSundar Iyer }; 41720406ebfSSundar Iyer MODULE_DEVICE_TABLE(i2c, tc3589x_id); 418f4e8afdcSSundar Iyer 41920406ebfSSundar Iyer static struct i2c_driver tc3589x_driver = { 42020406ebfSSundar Iyer .driver.name = "tc3589x", 421f4e8afdcSSundar Iyer .driver.owner = THIS_MODULE, 422593e9d70SSundar Iyer .driver.pm = &tc3589x_dev_pm_ops, 42320406ebfSSundar Iyer .probe = tc3589x_probe, 42420406ebfSSundar Iyer .remove = __devexit_p(tc3589x_remove), 42520406ebfSSundar Iyer .id_table = tc3589x_id, 426f4e8afdcSSundar Iyer }; 427f4e8afdcSSundar Iyer 42820406ebfSSundar Iyer static int __init tc3589x_init(void) 429f4e8afdcSSundar Iyer { 43020406ebfSSundar Iyer return i2c_add_driver(&tc3589x_driver); 431f4e8afdcSSundar Iyer } 43220406ebfSSundar Iyer subsys_initcall(tc3589x_init); 433f4e8afdcSSundar Iyer 43420406ebfSSundar Iyer static void __exit tc3589x_exit(void) 435f4e8afdcSSundar Iyer { 43620406ebfSSundar Iyer i2c_del_driver(&tc3589x_driver); 437f4e8afdcSSundar Iyer } 43820406ebfSSundar Iyer module_exit(tc3589x_exit); 439f4e8afdcSSundar Iyer 440f4e8afdcSSundar Iyer MODULE_LICENSE("GPL v2"); 44120406ebfSSundar Iyer MODULE_DESCRIPTION("TC3589x MFD core driver"); 442f4e8afdcSSundar Iyer MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); 443