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> 12f4e8afdcSSundar Iyer #include <linux/slab.h> 13f4e8afdcSSundar Iyer #include <linux/i2c.h> 14f4e8afdcSSundar Iyer #include <linux/mfd/core.h> 15f4e8afdcSSundar Iyer #include <linux/mfd/tc3589x.h> 16f4e8afdcSSundar Iyer 17593e9d70SSundar Iyer #define TC3589x_CLKMODE_MODCTL_SLEEP 0x0 18593e9d70SSundar Iyer #define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0) 19593e9d70SSundar Iyer 20f4e8afdcSSundar Iyer /** 2120406ebfSSundar Iyer * tc3589x_reg_read() - read a single TC3589x register 2220406ebfSSundar Iyer * @tc3589x: Device to read from 23f4e8afdcSSundar Iyer * @reg: Register to read 24f4e8afdcSSundar Iyer */ 2520406ebfSSundar Iyer int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg) 26f4e8afdcSSundar Iyer { 27f4e8afdcSSundar Iyer int ret; 28f4e8afdcSSundar Iyer 2920406ebfSSundar Iyer ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg); 30f4e8afdcSSundar Iyer if (ret < 0) 3120406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to read reg %#x: %d\n", 32f4e8afdcSSundar Iyer reg, ret); 33f4e8afdcSSundar Iyer 34f4e8afdcSSundar Iyer return ret; 35f4e8afdcSSundar Iyer } 3620406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_reg_read); 37f4e8afdcSSundar Iyer 38f4e8afdcSSundar Iyer /** 3920406ebfSSundar Iyer * tc3589x_reg_read() - write a single TC3589x register 4020406ebfSSundar Iyer * @tc3589x: Device to write to 41f4e8afdcSSundar Iyer * @reg: Register to read 42f4e8afdcSSundar Iyer * @data: Value to write 43f4e8afdcSSundar Iyer */ 4420406ebfSSundar Iyer int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data) 45f4e8afdcSSundar Iyer { 46f4e8afdcSSundar Iyer int ret; 47f4e8afdcSSundar Iyer 4820406ebfSSundar Iyer ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data); 49f4e8afdcSSundar Iyer if (ret < 0) 5020406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to write reg %#x: %d\n", 51f4e8afdcSSundar Iyer reg, ret); 52f4e8afdcSSundar Iyer 53f4e8afdcSSundar Iyer return ret; 54f4e8afdcSSundar Iyer } 5520406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_reg_write); 56f4e8afdcSSundar Iyer 57f4e8afdcSSundar Iyer /** 5820406ebfSSundar Iyer * tc3589x_block_read() - read multiple TC3589x registers 5920406ebfSSundar Iyer * @tc3589x: Device to read from 60f4e8afdcSSundar Iyer * @reg: First register 61f4e8afdcSSundar Iyer * @length: Number of registers 62f4e8afdcSSundar Iyer * @values: Buffer to write to 63f4e8afdcSSundar Iyer */ 6420406ebfSSundar Iyer int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values) 65f4e8afdcSSundar Iyer { 66f4e8afdcSSundar Iyer int ret; 67f4e8afdcSSundar Iyer 6820406ebfSSundar Iyer ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values); 69f4e8afdcSSundar Iyer if (ret < 0) 7020406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to read regs %#x: %d\n", 71f4e8afdcSSundar Iyer reg, ret); 72f4e8afdcSSundar Iyer 73f4e8afdcSSundar Iyer return ret; 74f4e8afdcSSundar Iyer } 7520406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_block_read); 76f4e8afdcSSundar Iyer 77f4e8afdcSSundar Iyer /** 7820406ebfSSundar Iyer * tc3589x_block_write() - write multiple TC3589x registers 7920406ebfSSundar Iyer * @tc3589x: Device to write to 80f4e8afdcSSundar Iyer * @reg: First register 81f4e8afdcSSundar Iyer * @length: Number of registers 82f4e8afdcSSundar Iyer * @values: Values to write 83f4e8afdcSSundar Iyer */ 8420406ebfSSundar Iyer int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, 85f4e8afdcSSundar Iyer const u8 *values) 86f4e8afdcSSundar Iyer { 87f4e8afdcSSundar Iyer int ret; 88f4e8afdcSSundar Iyer 8920406ebfSSundar Iyer ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length, 90f4e8afdcSSundar Iyer values); 91f4e8afdcSSundar Iyer if (ret < 0) 9220406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to write regs %#x: %d\n", 93f4e8afdcSSundar Iyer reg, ret); 94f4e8afdcSSundar Iyer 95f4e8afdcSSundar Iyer return ret; 96f4e8afdcSSundar Iyer } 9720406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_block_write); 98f4e8afdcSSundar Iyer 99f4e8afdcSSundar Iyer /** 10020406ebfSSundar Iyer * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register 10120406ebfSSundar Iyer * @tc3589x: Device to write to 102f4e8afdcSSundar Iyer * @reg: Register to write 103f4e8afdcSSundar Iyer * @mask: Mask of bits to set 104f4e8afdcSSundar Iyer * @values: Value to set 105f4e8afdcSSundar Iyer */ 10620406ebfSSundar Iyer int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val) 107f4e8afdcSSundar Iyer { 108f4e8afdcSSundar Iyer int ret; 109f4e8afdcSSundar Iyer 11020406ebfSSundar Iyer mutex_lock(&tc3589x->lock); 111f4e8afdcSSundar Iyer 11220406ebfSSundar Iyer ret = tc3589x_reg_read(tc3589x, reg); 113f4e8afdcSSundar Iyer if (ret < 0) 114f4e8afdcSSundar Iyer goto out; 115f4e8afdcSSundar Iyer 116f4e8afdcSSundar Iyer ret &= ~mask; 117f4e8afdcSSundar Iyer ret |= val; 118f4e8afdcSSundar Iyer 11920406ebfSSundar Iyer ret = tc3589x_reg_write(tc3589x, reg, ret); 120f4e8afdcSSundar Iyer 121f4e8afdcSSundar Iyer out: 12220406ebfSSundar Iyer mutex_unlock(&tc3589x->lock); 123f4e8afdcSSundar Iyer return ret; 124f4e8afdcSSundar Iyer } 12520406ebfSSundar Iyer EXPORT_SYMBOL_GPL(tc3589x_set_bits); 126f4e8afdcSSundar Iyer 127f4e8afdcSSundar Iyer static struct resource gpio_resources[] = { 128f4e8afdcSSundar Iyer { 12920406ebfSSundar Iyer .start = TC3589x_INT_GPIIRQ, 13020406ebfSSundar Iyer .end = TC3589x_INT_GPIIRQ, 131f4e8afdcSSundar Iyer .flags = IORESOURCE_IRQ, 132f4e8afdcSSundar Iyer }, 133f4e8afdcSSundar Iyer }; 134f4e8afdcSSundar Iyer 13509c730a4SSundar Iyer static struct resource keypad_resources[] = { 13609c730a4SSundar Iyer { 13709c730a4SSundar Iyer .start = TC3589x_INT_KBDIRQ, 13809c730a4SSundar Iyer .end = TC3589x_INT_KBDIRQ, 13909c730a4SSundar Iyer .flags = IORESOURCE_IRQ, 14009c730a4SSundar Iyer }, 14109c730a4SSundar Iyer }; 14209c730a4SSundar Iyer 143611b7590SSundar Iyer static struct mfd_cell tc3589x_dev_gpio[] = { 144f4e8afdcSSundar Iyer { 14520406ebfSSundar Iyer .name = "tc3589x-gpio", 146f4e8afdcSSundar Iyer .num_resources = ARRAY_SIZE(gpio_resources), 147f4e8afdcSSundar Iyer .resources = &gpio_resources[0], 148f4e8afdcSSundar Iyer }, 149f4e8afdcSSundar Iyer }; 150f4e8afdcSSundar Iyer 15109c730a4SSundar Iyer static struct mfd_cell tc3589x_dev_keypad[] = { 15209c730a4SSundar Iyer { 15309c730a4SSundar Iyer .name = "tc3589x-keypad", 15409c730a4SSundar Iyer .num_resources = ARRAY_SIZE(keypad_resources), 15509c730a4SSundar Iyer .resources = &keypad_resources[0], 15609c730a4SSundar Iyer }, 15709c730a4SSundar Iyer }; 15809c730a4SSundar Iyer 15920406ebfSSundar Iyer static irqreturn_t tc3589x_irq(int irq, void *data) 160f4e8afdcSSundar Iyer { 16120406ebfSSundar Iyer struct tc3589x *tc3589x = data; 162f4e8afdcSSundar Iyer int status; 163f4e8afdcSSundar Iyer 164bd77efd0SSundar Iyer again: 16520406ebfSSundar Iyer status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); 166f4e8afdcSSundar Iyer if (status < 0) 167f4e8afdcSSundar Iyer return IRQ_NONE; 168f4e8afdcSSundar Iyer 169f4e8afdcSSundar Iyer while (status) { 170f4e8afdcSSundar Iyer int bit = __ffs(status); 171f4e8afdcSSundar Iyer 17220406ebfSSundar Iyer handle_nested_irq(tc3589x->irq_base + bit); 173f4e8afdcSSundar Iyer status &= ~(1 << bit); 174f4e8afdcSSundar Iyer } 175f4e8afdcSSundar Iyer 176f4e8afdcSSundar Iyer /* 177f4e8afdcSSundar Iyer * A dummy read or write (to any register) appears to be necessary to 178f4e8afdcSSundar Iyer * have the last interrupt clear (for example, GPIO IC write) take 179bd77efd0SSundar Iyer * effect. In such a case, recheck for any interrupt which is still 180bd77efd0SSundar Iyer * pending. 181f4e8afdcSSundar Iyer */ 182bd77efd0SSundar Iyer status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); 183bd77efd0SSundar Iyer if (status) 184bd77efd0SSundar Iyer goto again; 185f4e8afdcSSundar Iyer 186f4e8afdcSSundar Iyer return IRQ_HANDLED; 187f4e8afdcSSundar Iyer } 188f4e8afdcSSundar Iyer 18920406ebfSSundar Iyer static int tc3589x_irq_init(struct tc3589x *tc3589x) 190f4e8afdcSSundar Iyer { 19120406ebfSSundar Iyer int base = tc3589x->irq_base; 192f4e8afdcSSundar Iyer int irq; 193f4e8afdcSSundar Iyer 19420406ebfSSundar Iyer for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { 195d5bb1221SThomas Gleixner irq_set_chip_data(irq, tc3589x); 196d5bb1221SThomas Gleixner irq_set_chip_and_handler(irq, &dummy_irq_chip, 197f4e8afdcSSundar Iyer handle_edge_irq); 198d5bb1221SThomas Gleixner irq_set_nested_thread(irq, 1); 199f4e8afdcSSundar Iyer #ifdef CONFIG_ARM 200f4e8afdcSSundar Iyer set_irq_flags(irq, IRQF_VALID); 201f4e8afdcSSundar Iyer #else 202d5bb1221SThomas Gleixner irq_set_noprobe(irq); 203f4e8afdcSSundar Iyer #endif 204f4e8afdcSSundar Iyer } 205f4e8afdcSSundar Iyer 206f4e8afdcSSundar Iyer return 0; 207f4e8afdcSSundar Iyer } 208f4e8afdcSSundar Iyer 20920406ebfSSundar Iyer static void tc3589x_irq_remove(struct tc3589x *tc3589x) 210f4e8afdcSSundar Iyer { 21120406ebfSSundar Iyer int base = tc3589x->irq_base; 212f4e8afdcSSundar Iyer int irq; 213f4e8afdcSSundar Iyer 21420406ebfSSundar Iyer for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { 215f4e8afdcSSundar Iyer #ifdef CONFIG_ARM 216f4e8afdcSSundar Iyer set_irq_flags(irq, 0); 217f4e8afdcSSundar Iyer #endif 218d5bb1221SThomas Gleixner irq_set_chip_and_handler(irq, NULL, NULL); 219d5bb1221SThomas Gleixner irq_set_chip_data(irq, NULL); 220f4e8afdcSSundar Iyer } 221f4e8afdcSSundar Iyer } 222f4e8afdcSSundar Iyer 22320406ebfSSundar Iyer static int tc3589x_chip_init(struct tc3589x *tc3589x) 224f4e8afdcSSundar Iyer { 225f4e8afdcSSundar Iyer int manf, ver, ret; 226f4e8afdcSSundar Iyer 22720406ebfSSundar Iyer manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE); 228f4e8afdcSSundar Iyer if (manf < 0) 229f4e8afdcSSundar Iyer return manf; 230f4e8afdcSSundar Iyer 23120406ebfSSundar Iyer ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION); 232f4e8afdcSSundar Iyer if (ver < 0) 233f4e8afdcSSundar Iyer return ver; 234f4e8afdcSSundar Iyer 23520406ebfSSundar Iyer if (manf != TC3589x_MANFCODE_MAGIC) { 23620406ebfSSundar Iyer dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf); 237f4e8afdcSSundar Iyer return -EINVAL; 238f4e8afdcSSundar Iyer } 239f4e8afdcSSundar Iyer 24020406ebfSSundar Iyer dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver); 241f4e8afdcSSundar Iyer 242523bc382SSundar Iyer /* 243523bc382SSundar Iyer * Put everything except the IRQ module into reset; 244523bc382SSundar Iyer * also spare the GPIO module for any pin initialization 245523bc382SSundar Iyer * done during pre-kernel boot 246523bc382SSundar Iyer */ 24720406ebfSSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL, 24820406ebfSSundar Iyer TC3589x_RSTCTRL_TIMRST 24920406ebfSSundar Iyer | TC3589x_RSTCTRL_ROTRST 250523bc382SSundar Iyer | TC3589x_RSTCTRL_KBDRST); 251f4e8afdcSSundar Iyer if (ret < 0) 252f4e8afdcSSundar Iyer return ret; 253f4e8afdcSSundar Iyer 254f4e8afdcSSundar Iyer /* Clear the reset interrupt. */ 25520406ebfSSundar Iyer return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1); 256f4e8afdcSSundar Iyer } 257f4e8afdcSSundar Iyer 258611b7590SSundar Iyer static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) 259611b7590SSundar Iyer { 260611b7590SSundar Iyer int ret = 0; 261611b7590SSundar Iyer unsigned int blocks = tc3589x->pdata->block; 262611b7590SSundar Iyer 263611b7590SSundar Iyer if (blocks & TC3589x_BLOCK_GPIO) { 264611b7590SSundar Iyer ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, 265611b7590SSundar Iyer ARRAY_SIZE(tc3589x_dev_gpio), NULL, 266611b7590SSundar Iyer tc3589x->irq_base); 267611b7590SSundar Iyer if (ret) { 268611b7590SSundar Iyer dev_err(tc3589x->dev, "failed to add gpio child\n"); 269611b7590SSundar Iyer return ret; 270611b7590SSundar Iyer } 271611b7590SSundar Iyer dev_info(tc3589x->dev, "added gpio block\n"); 272611b7590SSundar Iyer } 273611b7590SSundar Iyer 27409c730a4SSundar Iyer if (blocks & TC3589x_BLOCK_KEYPAD) { 27509c730a4SSundar Iyer ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, 27609c730a4SSundar Iyer ARRAY_SIZE(tc3589x_dev_keypad), NULL, 27709c730a4SSundar Iyer tc3589x->irq_base); 27809c730a4SSundar Iyer if (ret) { 27909c730a4SSundar Iyer dev_err(tc3589x->dev, "failed to keypad child\n"); 280611b7590SSundar Iyer return ret; 28109c730a4SSundar Iyer } 28209c730a4SSundar Iyer dev_info(tc3589x->dev, "added keypad block\n"); 28309c730a4SSundar Iyer } 284611b7590SSundar Iyer 28509c730a4SSundar Iyer return ret; 286611b7590SSundar Iyer } 287611b7590SSundar Iyer 28820406ebfSSundar Iyer static int __devinit tc3589x_probe(struct i2c_client *i2c, 289f4e8afdcSSundar Iyer const struct i2c_device_id *id) 290f4e8afdcSSundar Iyer { 29120406ebfSSundar Iyer struct tc3589x_platform_data *pdata = i2c->dev.platform_data; 29220406ebfSSundar Iyer struct tc3589x *tc3589x; 293f4e8afdcSSundar Iyer int ret; 294f4e8afdcSSundar Iyer 295f4e8afdcSSundar Iyer if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA 296f4e8afdcSSundar Iyer | I2C_FUNC_SMBUS_I2C_BLOCK)) 297f4e8afdcSSundar Iyer return -EIO; 298f4e8afdcSSundar Iyer 29920406ebfSSundar Iyer tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL); 30020406ebfSSundar Iyer if (!tc3589x) 301f4e8afdcSSundar Iyer return -ENOMEM; 302f4e8afdcSSundar Iyer 30320406ebfSSundar Iyer mutex_init(&tc3589x->lock); 304f4e8afdcSSundar Iyer 30520406ebfSSundar Iyer tc3589x->dev = &i2c->dev; 30620406ebfSSundar Iyer tc3589x->i2c = i2c; 30720406ebfSSundar Iyer tc3589x->pdata = pdata; 30820406ebfSSundar Iyer tc3589x->irq_base = pdata->irq_base; 30920406ebfSSundar Iyer tc3589x->num_gpio = id->driver_data; 310f4e8afdcSSundar Iyer 31120406ebfSSundar Iyer i2c_set_clientdata(i2c, tc3589x); 312f4e8afdcSSundar Iyer 31320406ebfSSundar Iyer ret = tc3589x_chip_init(tc3589x); 314f4e8afdcSSundar Iyer if (ret) 315f4e8afdcSSundar Iyer goto out_free; 316f4e8afdcSSundar Iyer 31720406ebfSSundar Iyer ret = tc3589x_irq_init(tc3589x); 318f4e8afdcSSundar Iyer if (ret) 319f4e8afdcSSundar Iyer goto out_free; 320f4e8afdcSSundar Iyer 32120406ebfSSundar Iyer ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq, 322f4e8afdcSSundar Iyer IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 32320406ebfSSundar Iyer "tc3589x", tc3589x); 324f4e8afdcSSundar Iyer if (ret) { 32520406ebfSSundar Iyer dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret); 326f4e8afdcSSundar Iyer goto out_removeirq; 327f4e8afdcSSundar Iyer } 328f4e8afdcSSundar Iyer 329611b7590SSundar Iyer ret = tc3589x_device_init(tc3589x); 330f4e8afdcSSundar Iyer if (ret) { 331611b7590SSundar Iyer dev_err(tc3589x->dev, "failed to add child devices\n"); 332f4e8afdcSSundar Iyer goto out_freeirq; 333f4e8afdcSSundar Iyer } 334f4e8afdcSSundar Iyer 335f4e8afdcSSundar Iyer return 0; 336f4e8afdcSSundar Iyer 337f4e8afdcSSundar Iyer out_freeirq: 33820406ebfSSundar Iyer free_irq(tc3589x->i2c->irq, tc3589x); 339f4e8afdcSSundar Iyer out_removeirq: 34020406ebfSSundar Iyer tc3589x_irq_remove(tc3589x); 341f4e8afdcSSundar Iyer out_free: 34220406ebfSSundar Iyer kfree(tc3589x); 343f4e8afdcSSundar Iyer return ret; 344f4e8afdcSSundar Iyer } 345f4e8afdcSSundar Iyer 34620406ebfSSundar Iyer static int __devexit tc3589x_remove(struct i2c_client *client) 347f4e8afdcSSundar Iyer { 34820406ebfSSundar Iyer struct tc3589x *tc3589x = i2c_get_clientdata(client); 349f4e8afdcSSundar Iyer 35020406ebfSSundar Iyer mfd_remove_devices(tc3589x->dev); 351f4e8afdcSSundar Iyer 35220406ebfSSundar Iyer free_irq(tc3589x->i2c->irq, tc3589x); 35320406ebfSSundar Iyer tc3589x_irq_remove(tc3589x); 354f4e8afdcSSundar Iyer 35520406ebfSSundar Iyer kfree(tc3589x); 356f4e8afdcSSundar Iyer 357f4e8afdcSSundar Iyer return 0; 358f4e8afdcSSundar Iyer } 359f4e8afdcSSundar Iyer 360*54d8e2c3SLinus Walleij #ifdef CONFIG_PM 361593e9d70SSundar Iyer static int tc3589x_suspend(struct device *dev) 362593e9d70SSundar Iyer { 363593e9d70SSundar Iyer struct tc3589x *tc3589x = dev_get_drvdata(dev); 364593e9d70SSundar Iyer struct i2c_client *client = tc3589x->i2c; 365593e9d70SSundar Iyer int ret = 0; 366593e9d70SSundar Iyer 367593e9d70SSundar Iyer /* put the system to sleep mode */ 368593e9d70SSundar Iyer if (!device_may_wakeup(&client->dev)) 369593e9d70SSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, 370593e9d70SSundar Iyer TC3589x_CLKMODE_MODCTL_SLEEP); 371593e9d70SSundar Iyer 372593e9d70SSundar Iyer return ret; 373593e9d70SSundar Iyer } 374593e9d70SSundar Iyer 375593e9d70SSundar Iyer static int tc3589x_resume(struct device *dev) 376593e9d70SSundar Iyer { 377593e9d70SSundar Iyer struct tc3589x *tc3589x = dev_get_drvdata(dev); 378593e9d70SSundar Iyer struct i2c_client *client = tc3589x->i2c; 379593e9d70SSundar Iyer int ret = 0; 380593e9d70SSundar Iyer 381593e9d70SSundar Iyer /* enable the system into operation */ 382593e9d70SSundar Iyer if (!device_may_wakeup(&client->dev)) 383593e9d70SSundar Iyer ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, 384593e9d70SSundar Iyer TC3589x_CLKMODE_MODCTL_OPERATION); 385593e9d70SSundar Iyer 386593e9d70SSundar Iyer return ret; 387593e9d70SSundar Iyer } 388593e9d70SSundar Iyer 389593e9d70SSundar Iyer static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, 390593e9d70SSundar Iyer tc3589x_resume); 391*54d8e2c3SLinus Walleij #endif 392593e9d70SSundar Iyer 39320406ebfSSundar Iyer static const struct i2c_device_id tc3589x_id[] = { 39420406ebfSSundar Iyer { "tc3589x", 24 }, 395f4e8afdcSSundar Iyer { } 396f4e8afdcSSundar Iyer }; 39720406ebfSSundar Iyer MODULE_DEVICE_TABLE(i2c, tc3589x_id); 398f4e8afdcSSundar Iyer 39920406ebfSSundar Iyer static struct i2c_driver tc3589x_driver = { 40020406ebfSSundar Iyer .driver.name = "tc3589x", 401f4e8afdcSSundar Iyer .driver.owner = THIS_MODULE, 402593e9d70SSundar Iyer #ifdef CONFIG_PM 403593e9d70SSundar Iyer .driver.pm = &tc3589x_dev_pm_ops, 404593e9d70SSundar Iyer #endif 40520406ebfSSundar Iyer .probe = tc3589x_probe, 40620406ebfSSundar Iyer .remove = __devexit_p(tc3589x_remove), 40720406ebfSSundar Iyer .id_table = tc3589x_id, 408f4e8afdcSSundar Iyer }; 409f4e8afdcSSundar Iyer 41020406ebfSSundar Iyer static int __init tc3589x_init(void) 411f4e8afdcSSundar Iyer { 41220406ebfSSundar Iyer return i2c_add_driver(&tc3589x_driver); 413f4e8afdcSSundar Iyer } 41420406ebfSSundar Iyer subsys_initcall(tc3589x_init); 415f4e8afdcSSundar Iyer 41620406ebfSSundar Iyer static void __exit tc3589x_exit(void) 417f4e8afdcSSundar Iyer { 41820406ebfSSundar Iyer i2c_del_driver(&tc3589x_driver); 419f4e8afdcSSundar Iyer } 42020406ebfSSundar Iyer module_exit(tc3589x_exit); 421f4e8afdcSSundar Iyer 422f4e8afdcSSundar Iyer MODULE_LICENSE("GPL v2"); 42320406ebfSSundar Iyer MODULE_DESCRIPTION("TC3589x MFD core driver"); 424f4e8afdcSSundar Iyer MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); 425