Blame view

drivers/mfd/tc3589x.c 9.31 KB
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   * Copyright (C) ST-Ericsson SA 2010
   *
   * License Terms: GNU General Public License, version 2
   * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
   * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
   */
  
  #include <linux/module.h>
  #include <linux/interrupt.h>
  #include <linux/irq.h>
  #include <linux/slab.h>
  #include <linux/i2c.h>
  #include <linux/mfd/core.h>
c6eda6c5e   Sundar Iyer   mfd/tc35892: rena...
15
  #include <linux/mfd/tc3589x.h>
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
16

593e9d70f   Sundar Iyer   mfd/tc3589x: add ...
17
18
  #define TC3589x_CLKMODE_MODCTL_SLEEP		0x0
  #define TC3589x_CLKMODE_MODCTL_OPERATION	(1 << 0)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
19
  /**
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
20
21
   * tc3589x_reg_read() - read a single TC3589x register
   * @tc3589x:	Device to read from
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
22
23
   * @reg:	Register to read
   */
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
24
  int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
25
26
  {
  	int ret;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
27
  	ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
28
  	if (ret < 0)
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
29
30
  		dev_err(tc3589x->dev, "failed to read reg %#x: %d
  ",
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
31
32
33
34
  			reg, ret);
  
  	return ret;
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
35
  EXPORT_SYMBOL_GPL(tc3589x_reg_read);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
36
37
  
  /**
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
38
39
   * tc3589x_reg_read() - write a single TC3589x register
   * @tc3589x:	Device to write to
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
40
41
42
   * @reg:	Register to read
   * @data:	Value to write
   */
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
43
  int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
44
45
  {
  	int ret;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
46
  	ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
47
  	if (ret < 0)
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
48
49
  		dev_err(tc3589x->dev, "failed to write reg %#x: %d
  ",
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
50
51
52
53
  			reg, ret);
  
  	return ret;
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
54
  EXPORT_SYMBOL_GPL(tc3589x_reg_write);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
55
56
  
  /**
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
57
58
   * tc3589x_block_read() - read multiple TC3589x registers
   * @tc3589x:	Device to read from
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
59
60
61
62
   * @reg:	First register
   * @length:	Number of registers
   * @values:	Buffer to write to
   */
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
63
  int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
64
65
  {
  	int ret;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
66
  	ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
67
  	if (ret < 0)
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
68
69
  		dev_err(tc3589x->dev, "failed to read regs %#x: %d
  ",
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
70
71
72
73
  			reg, ret);
  
  	return ret;
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
74
  EXPORT_SYMBOL_GPL(tc3589x_block_read);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
75
76
  
  /**
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
77
78
   * tc3589x_block_write() - write multiple TC3589x registers
   * @tc3589x:	Device to write to
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
79
80
81
82
   * @reg:	First register
   * @length:	Number of registers
   * @values:	Values to write
   */
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
83
  int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
84
85
86
  			const u8 *values)
  {
  	int ret;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
87
  	ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length,
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
88
89
  					     values);
  	if (ret < 0)
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
90
91
  		dev_err(tc3589x->dev, "failed to write regs %#x: %d
  ",
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
92
93
94
95
  			reg, ret);
  
  	return ret;
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
96
  EXPORT_SYMBOL_GPL(tc3589x_block_write);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
97
98
  
  /**
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
99
100
   * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register
   * @tc3589x:	Device to write to
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
101
102
103
104
   * @reg:	Register to write
   * @mask:	Mask of bits to set
   * @values:	Value to set
   */
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
105
  int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
106
107
  {
  	int ret;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
108
  	mutex_lock(&tc3589x->lock);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
109

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
110
  	ret = tc3589x_reg_read(tc3589x, reg);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
111
112
113
114
115
  	if (ret < 0)
  		goto out;
  
  	ret &= ~mask;
  	ret |= val;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
116
  	ret = tc3589x_reg_write(tc3589x, reg, ret);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
117
118
  
  out:
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
119
  	mutex_unlock(&tc3589x->lock);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
120
121
  	return ret;
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
122
  EXPORT_SYMBOL_GPL(tc3589x_set_bits);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
123
124
125
  
  static struct resource gpio_resources[] = {
  	{
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
126
127
  		.start	= TC3589x_INT_GPIIRQ,
  		.end	= TC3589x_INT_GPIIRQ,
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
128
129
130
  		.flags	= IORESOURCE_IRQ,
  	},
  };
09c730a48   Sundar Iyer   input/tc3589x: ad...
131
132
133
134
135
136
137
  static struct resource keypad_resources[] = {
  	{
  		.start  = TC3589x_INT_KBDIRQ,
  		.end    = TC3589x_INT_KBDIRQ,
  		.flags  = IORESOURCE_IRQ,
  	},
  };
611b7590a   Sundar Iyer   mfd/tc3589x: add ...
138
  static struct mfd_cell tc3589x_dev_gpio[] = {
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
139
  	{
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
140
  		.name		= "tc3589x-gpio",
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
141
142
143
144
  		.num_resources	= ARRAY_SIZE(gpio_resources),
  		.resources	= &gpio_resources[0],
  	},
  };
09c730a48   Sundar Iyer   input/tc3589x: ad...
145
146
147
148
149
150
151
  static struct mfd_cell tc3589x_dev_keypad[] = {
  	{
  		.name           = "tc3589x-keypad",
  		.num_resources  = ARRAY_SIZE(keypad_resources),
  		.resources      = &keypad_resources[0],
  	},
  };
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
152
  static irqreturn_t tc3589x_irq(int irq, void *data)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
153
  {
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
154
  	struct tc3589x *tc3589x = data;
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
155
  	int status;
bd77efd0c   Sundar Iyer   mfd/tc3589x: fix ...
156
  again:
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
157
  	status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
158
159
160
161
162
  	if (status < 0)
  		return IRQ_NONE;
  
  	while (status) {
  		int bit = __ffs(status);
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
163
  		handle_nested_irq(tc3589x->irq_base + bit);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
164
165
166
167
168
169
  		status &= ~(1 << bit);
  	}
  
  	/*
  	 * A dummy read or write (to any register) appears to be necessary to
  	 * have the last interrupt clear (for example, GPIO IC write) take
bd77efd0c   Sundar Iyer   mfd/tc3589x: fix ...
170
171
  	 * effect. In such a case, recheck for any interrupt which is still
  	 * pending.
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
172
  	 */
bd77efd0c   Sundar Iyer   mfd/tc3589x: fix ...
173
174
175
  	status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
  	if (status)
  		goto again;
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
176
177
178
  
  	return IRQ_HANDLED;
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
179
  static int tc3589x_irq_init(struct tc3589x *tc3589x)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
180
  {
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
181
  	int base = tc3589x->irq_base;
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
182
  	int irq;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
183
  	for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
184
185
  		irq_set_chip_data(irq, tc3589x);
  		irq_set_chip_and_handler(irq, &dummy_irq_chip,
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
186
  					 handle_edge_irq);
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
187
  		irq_set_nested_thread(irq, 1);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
188
189
190
  #ifdef CONFIG_ARM
  		set_irq_flags(irq, IRQF_VALID);
  #else
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
191
  		irq_set_noprobe(irq);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
192
193
194
195
196
  #endif
  	}
  
  	return 0;
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
197
  static void tc3589x_irq_remove(struct tc3589x *tc3589x)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
198
  {
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
199
  	int base = tc3589x->irq_base;
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
200
  	int irq;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
201
  	for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
202
203
204
  #ifdef CONFIG_ARM
  		set_irq_flags(irq, 0);
  #endif
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
205
206
  		irq_set_chip_and_handler(irq, NULL, NULL);
  		irq_set_chip_data(irq, NULL);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
207
208
  	}
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
209
  static int tc3589x_chip_init(struct tc3589x *tc3589x)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
210
211
  {
  	int manf, ver, ret;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
212
  	manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
213
214
  	if (manf < 0)
  		return manf;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
215
  	ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
216
217
  	if (ver < 0)
  		return ver;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
218
219
220
  	if (manf != TC3589x_MANFCODE_MAGIC) {
  		dev_err(tc3589x->dev, "unknown manufacturer: %#x
  ", manf);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
221
222
  		return -EINVAL;
  	}
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
223
224
  	dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x
  ", manf, ver);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
225

523bc3820   Sundar Iyer   mfd/tc3589x: undo...
226
227
228
229
230
  	/*
  	 * Put everything except the IRQ module into reset;
  	 * also spare the GPIO module for any pin initialization
  	 * done during pre-kernel boot
  	 */
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
231
232
233
  	ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL,
  				TC3589x_RSTCTRL_TIMRST
  				| TC3589x_RSTCTRL_ROTRST
523bc3820   Sundar Iyer   mfd/tc3589x: undo...
234
  				| TC3589x_RSTCTRL_KBDRST);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
235
236
237
238
  	if (ret < 0)
  		return ret;
  
  	/* Clear the reset interrupt. */
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
239
  	return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
240
  }
611b7590a   Sundar Iyer   mfd/tc3589x: add ...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
  {
  	int ret = 0;
  	unsigned int blocks = tc3589x->pdata->block;
  
  	if (blocks & TC3589x_BLOCK_GPIO) {
  		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
  				ARRAY_SIZE(tc3589x_dev_gpio), NULL,
  				tc3589x->irq_base);
  		if (ret) {
  			dev_err(tc3589x->dev, "failed to add gpio child
  ");
  			return ret;
  		}
  		dev_info(tc3589x->dev, "added gpio block
  ");
  	}
09c730a48   Sundar Iyer   input/tc3589x: ad...
258
259
260
261
262
263
264
265
266
267
268
269
  	if (blocks & TC3589x_BLOCK_KEYPAD) {
  		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
  				ARRAY_SIZE(tc3589x_dev_keypad), NULL,
  				tc3589x->irq_base);
  		if (ret) {
  			dev_err(tc3589x->dev, "failed to keypad child
  ");
  			return ret;
  		}
  		dev_info(tc3589x->dev, "added keypad block
  ");
  	}
611b7590a   Sundar Iyer   mfd/tc3589x: add ...
270

09c730a48   Sundar Iyer   input/tc3589x: ad...
271
  	return ret;
611b7590a   Sundar Iyer   mfd/tc3589x: add ...
272
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
273
  static int __devinit tc3589x_probe(struct i2c_client *i2c,
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
274
275
  				   const struct i2c_device_id *id)
  {
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
276
277
  	struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
  	struct tc3589x *tc3589x;
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
278
279
280
281
282
  	int ret;
  
  	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
  				     | I2C_FUNC_SMBUS_I2C_BLOCK))
  		return -EIO;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
283
284
  	tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL);
  	if (!tc3589x)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
285
  		return -ENOMEM;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
286
  	mutex_init(&tc3589x->lock);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
287

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
288
289
290
291
292
  	tc3589x->dev = &i2c->dev;
  	tc3589x->i2c = i2c;
  	tc3589x->pdata = pdata;
  	tc3589x->irq_base = pdata->irq_base;
  	tc3589x->num_gpio = id->driver_data;
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
293

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
294
  	i2c_set_clientdata(i2c, tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
295

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
296
  	ret = tc3589x_chip_init(tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
297
298
  	if (ret)
  		goto out_free;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
299
  	ret = tc3589x_irq_init(tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
300
301
  	if (ret)
  		goto out_free;
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
302
  	ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq,
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
303
  				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
304
  				   "tc3589x", tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
305
  	if (ret) {
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
306
307
  		dev_err(tc3589x->dev, "failed to request IRQ: %d
  ", ret);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
308
309
  		goto out_removeirq;
  	}
611b7590a   Sundar Iyer   mfd/tc3589x: add ...
310
  	ret = tc3589x_device_init(tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
311
  	if (ret) {
611b7590a   Sundar Iyer   mfd/tc3589x: add ...
312
313
  		dev_err(tc3589x->dev, "failed to add child devices
  ");
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
314
315
316
317
318
319
  		goto out_freeirq;
  	}
  
  	return 0;
  
  out_freeirq:
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
320
  	free_irq(tc3589x->i2c->irq, tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
321
  out_removeirq:
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
322
  	tc3589x_irq_remove(tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
323
  out_free:
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
324
  	kfree(tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
325
326
  	return ret;
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
327
  static int __devexit tc3589x_remove(struct i2c_client *client)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
328
  {
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
329
  	struct tc3589x *tc3589x = i2c_get_clientdata(client);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
330

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
331
  	mfd_remove_devices(tc3589x->dev);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
332

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
333
334
  	free_irq(tc3589x->i2c->irq, tc3589x);
  	tc3589x_irq_remove(tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
335

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
336
  	kfree(tc3589x);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
337
338
339
  
  	return 0;
  }
54d8e2c32   Linus Walleij   mfd: Add missing ...
340
  #ifdef CONFIG_PM
593e9d70f   Sundar Iyer   mfd/tc3589x: add ...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
  static int tc3589x_suspend(struct device *dev)
  {
  	struct tc3589x *tc3589x = dev_get_drvdata(dev);
  	struct i2c_client *client = tc3589x->i2c;
  	int ret = 0;
  
  	/* put the system to sleep mode */
  	if (!device_may_wakeup(&client->dev))
  		ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
  				TC3589x_CLKMODE_MODCTL_SLEEP);
  
  	return ret;
  }
  
  static int tc3589x_resume(struct device *dev)
  {
  	struct tc3589x *tc3589x = dev_get_drvdata(dev);
  	struct i2c_client *client = tc3589x->i2c;
  	int ret = 0;
  
  	/* enable the system into operation */
  	if (!device_may_wakeup(&client->dev))
  		ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
  				TC3589x_CLKMODE_MODCTL_OPERATION);
  
  	return ret;
  }
  
  static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend,
  						tc3589x_resume);
54d8e2c32   Linus Walleij   mfd: Add missing ...
371
  #endif
593e9d70f   Sundar Iyer   mfd/tc3589x: add ...
372

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
373
374
  static const struct i2c_device_id tc3589x_id[] = {
  	{ "tc3589x", 24 },
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
375
376
  	{ }
  };
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
377
  MODULE_DEVICE_TABLE(i2c, tc3589x_id);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
378

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
379
380
  static struct i2c_driver tc3589x_driver = {
  	.driver.name	= "tc3589x",
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
381
  	.driver.owner	= THIS_MODULE,
593e9d70f   Sundar Iyer   mfd/tc3589x: add ...
382
383
384
  #ifdef CONFIG_PM
  	.driver.pm	= &tc3589x_dev_pm_ops,
  #endif
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
385
386
387
  	.probe		= tc3589x_probe,
  	.remove		= __devexit_p(tc3589x_remove),
  	.id_table	= tc3589x_id,
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
388
  };
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
389
  static int __init tc3589x_init(void)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
390
  {
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
391
  	return i2c_add_driver(&tc3589x_driver);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
392
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
393
  subsys_initcall(tc3589x_init);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
394

20406ebff   Sundar Iyer   mfd/tc3589x: rena...
395
  static void __exit tc3589x_exit(void)
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
396
  {
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
397
  	i2c_del_driver(&tc3589x_driver);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
398
  }
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
399
  module_exit(tc3589x_exit);
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
400
401
  
  MODULE_LICENSE("GPL v2");
20406ebff   Sundar Iyer   mfd/tc3589x: rena...
402
  MODULE_DESCRIPTION("TC3589x MFD core driver");
b4ecd326b   Rabin Vincent   mfd: Add Toshiba'...
403
  MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");