Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tc3589x.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) ST-Ericsson SA 2010
3  *
4  * License Terms: GNU General Public License, version 2
5  * Author: Hanumath Prasad <[email protected]> for ST-Ericsson
6  * Author: Rabin Vincent <[email protected]> for ST-Ericsson
7  */
8 
9 #include <linux/module.h>
10 #include <linux/interrupt.h>
11 #include <linux/irq.h>
12 #include <linux/irqdomain.h>
13 #include <linux/slab.h>
14 #include <linux/i2c.h>
15 #include <linux/of.h>
16 #include <linux/mfd/core.h>
17 #include <linux/mfd/tc3589x.h>
18 
19 #define TC3589x_CLKMODE_MODCTL_SLEEP 0x0
20 #define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0)
21 
28 {
29  int ret;
30 
31  ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg);
32  if (ret < 0)
33  dev_err(tc3589x->dev, "failed to read reg %#x: %d\n",
34  reg, ret);
35 
36  return ret;
37 }
39 
47 {
48  int ret;
49 
50  ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data);
51  if (ret < 0)
52  dev_err(tc3589x->dev, "failed to write reg %#x: %d\n",
53  reg, ret);
54 
55  return ret;
56 }
58 
67 {
68  int ret;
69 
70  ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values);
71  if (ret < 0)
72  dev_err(tc3589x->dev, "failed to read regs %#x: %d\n",
73  reg, ret);
74 
75  return ret;
76 }
78 
87  const u8 *values)
88 {
89  int ret;
90 
91  ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length,
92  values);
93  if (ret < 0)
94  dev_err(tc3589x->dev, "failed to write regs %#x: %d\n",
95  reg, ret);
96 
97  return ret;
98 }
100 
109 {
110  int ret;
111 
112  mutex_lock(&tc3589x->lock);
113 
114  ret = tc3589x_reg_read(tc3589x, reg);
115  if (ret < 0)
116  goto out;
117 
118  ret &= ~mask;
119  ret |= val;
120 
121  ret = tc3589x_reg_write(tc3589x, reg, ret);
122 
123 out:
124  mutex_unlock(&tc3589x->lock);
125  return ret;
126 }
128 
129 static struct resource gpio_resources[] = {
130  {
131  .start = TC3589x_INT_GPIIRQ,
132  .end = TC3589x_INT_GPIIRQ,
133  .flags = IORESOURCE_IRQ,
134  },
135 };
136 
137 static struct resource keypad_resources[] = {
138  {
139  .start = TC3589x_INT_KBDIRQ,
140  .end = TC3589x_INT_KBDIRQ,
141  .flags = IORESOURCE_IRQ,
142  },
143 };
144 
145 static struct mfd_cell tc3589x_dev_gpio[] = {
146  {
147  .name = "tc3589x-gpio",
148  .num_resources = ARRAY_SIZE(gpio_resources),
149  .resources = &gpio_resources[0],
150  .of_compatible = "tc3589x-gpio",
151  },
152 };
153 
154 static struct mfd_cell tc3589x_dev_keypad[] = {
155  {
156  .name = "tc3589x-keypad",
157  .num_resources = ARRAY_SIZE(keypad_resources),
158  .resources = &keypad_resources[0],
159  .of_compatible = "tc3589x-keypad",
160  },
161 };
162 
163 static irqreturn_t tc3589x_irq(int irq, void *data)
164 {
165  struct tc3589x *tc3589x = data;
166  int status;
167 
168 again:
169  status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
170  if (status < 0)
171  return IRQ_NONE;
172 
173  while (status) {
174  int bit = __ffs(status);
175  int virq = irq_create_mapping(tc3589x->domain, bit);
176 
177  handle_nested_irq(virq);
178  status &= ~(1 << bit);
179  }
180 
181  /*
182  * A dummy read or write (to any register) appears to be necessary to
183  * have the last interrupt clear (for example, GPIO IC write) take
184  * effect. In such a case, recheck for any interrupt which is still
185  * pending.
186  */
187  status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
188  if (status)
189  goto again;
190 
191  return IRQ_HANDLED;
192 }
193 
194 static int tc3589x_irq_map(struct irq_domain *d, unsigned int virq,
195  irq_hw_number_t hwirq)
196 {
197  struct tc3589x *tc3589x = d->host_data;
198 
199  irq_set_chip_data(virq, tc3589x);
200  irq_set_chip_and_handler(virq, &dummy_irq_chip,
202  irq_set_nested_thread(virq, 1);
203 #ifdef CONFIG_ARM
204  set_irq_flags(virq, IRQF_VALID);
205 #else
206  irq_set_noprobe(virq);
207 #endif
208 
209  return 0;
210 }
211 
212 static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
213 {
214 #ifdef CONFIG_ARM
215  set_irq_flags(virq, 0);
216 #endif
217  irq_set_chip_and_handler(virq, NULL, NULL);
218  irq_set_chip_data(virq, NULL);
219 }
220 
221 static struct irq_domain_ops tc3589x_irq_ops = {
222  .map = tc3589x_irq_map,
223  .unmap = tc3589x_irq_unmap,
224  .xlate = irq_domain_xlate_twocell,
225 };
226 
227 static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
228 {
229  int base = tc3589x->irq_base;
230 
231  if (base) {
232  tc3589x->domain = irq_domain_add_legacy(
234  0, &tc3589x_irq_ops, tc3589x);
235  }
236  else {
237  tc3589x->domain = irq_domain_add_linear(
239  &tc3589x_irq_ops, tc3589x);
240  }
241 
242  if (!tc3589x->domain) {
243  dev_err(tc3589x->dev, "Failed to create irqdomain\n");
244  return -ENOSYS;
245  }
246 
247  return 0;
248 }
249 
250 static int tc3589x_chip_init(struct tc3589x *tc3589x)
251 {
252  int manf, ver, ret;
253 
254  manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE);
255  if (manf < 0)
256  return manf;
257 
258  ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION);
259  if (ver < 0)
260  return ver;
261 
262  if (manf != TC3589x_MANFCODE_MAGIC) {
263  dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf);
264  return -EINVAL;
265  }
266 
267  dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
268 
269  /*
270  * Put everything except the IRQ module into reset;
271  * also spare the GPIO module for any pin initialization
272  * done during pre-kernel boot
273  */
274  ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL,
278  if (ret < 0)
279  return ret;
280 
281  /* Clear the reset interrupt. */
282  return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
283 }
284 
285 static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
286 {
287  int ret = 0;
288  unsigned int blocks = tc3589x->pdata->block;
289 
290  if (blocks & TC3589x_BLOCK_GPIO) {
291  ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
292  ARRAY_SIZE(tc3589x_dev_gpio), NULL,
293  tc3589x->irq_base, tc3589x->domain);
294  if (ret) {
295  dev_err(tc3589x->dev, "failed to add gpio child\n");
296  return ret;
297  }
298  dev_info(tc3589x->dev, "added gpio block\n");
299  }
300 
301  if (blocks & TC3589x_BLOCK_KEYPAD) {
302  ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
303  ARRAY_SIZE(tc3589x_dev_keypad), NULL,
304  tc3589x->irq_base, tc3589x->domain);
305  if (ret) {
306  dev_err(tc3589x->dev, "failed to keypad child\n");
307  return ret;
308  }
309  dev_info(tc3589x->dev, "added keypad block\n");
310  }
311 
312  return ret;
313 }
314 
315 static int tc3589x_of_probe(struct device_node *np,
317 {
318  struct device_node *child;
319 
320  for_each_child_of_node(np, child) {
321  if (!strcmp(child->name, "tc3589x_gpio")) {
322  pdata->block |= TC3589x_BLOCK_GPIO;
323  }
324  if (!strcmp(child->name, "tc3589x_keypad")) {
325  pdata->block |= TC3589x_BLOCK_KEYPAD;
326  }
327  }
328 
329  return 0;
330 }
331 
332 static int __devinit tc3589x_probe(struct i2c_client *i2c,
333  const struct i2c_device_id *id)
334 {
335  struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
336  struct device_node *np = i2c->dev.of_node;
337  struct tc3589x *tc3589x;
338  int ret;
339 
340  if (!pdata) {
341  if (np) {
342  pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
343  if (!pdata)
344  return -ENOMEM;
345 
346  ret = tc3589x_of_probe(np, pdata);
347  if (ret)
348  return ret;
349  }
350  else {
351  dev_err(&i2c->dev, "No platform data or DT found\n");
352  return -EINVAL;
353  }
354  }
355 
356  if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
358  return -EIO;
359 
360  tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL);
361  if (!tc3589x)
362  return -ENOMEM;
363 
364  mutex_init(&tc3589x->lock);
365 
366  tc3589x->dev = &i2c->dev;
367  tc3589x->i2c = i2c;
368  tc3589x->pdata = pdata;
369  tc3589x->irq_base = pdata->irq_base;
370  tc3589x->num_gpio = id->driver_data;
371 
372  i2c_set_clientdata(i2c, tc3589x);
373 
374  ret = tc3589x_chip_init(tc3589x);
375  if (ret)
376  goto out_free;
377 
378  ret = tc3589x_irq_init(tc3589x, np);
379  if (ret)
380  goto out_free;
381 
382  ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq,
384  "tc3589x", tc3589x);
385  if (ret) {
386  dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
387  goto out_free;
388  }
389 
390  ret = tc3589x_device_init(tc3589x);
391  if (ret) {
392  dev_err(tc3589x->dev, "failed to add child devices\n");
393  goto out_freeirq;
394  }
395 
396  return 0;
397 
398 out_freeirq:
399  free_irq(tc3589x->i2c->irq, tc3589x);
400 out_free:
401  kfree(tc3589x);
402  return ret;
403 }
404 
405 static int __devexit tc3589x_remove(struct i2c_client *client)
406 {
407  struct tc3589x *tc3589x = i2c_get_clientdata(client);
408 
409  mfd_remove_devices(tc3589x->dev);
410 
411  free_irq(tc3589x->i2c->irq, tc3589x);
412 
413  kfree(tc3589x);
414 
415  return 0;
416 }
417 
418 #ifdef CONFIG_PM_SLEEP
419 static int tc3589x_suspend(struct device *dev)
420 {
421  struct tc3589x *tc3589x = dev_get_drvdata(dev);
422  struct i2c_client *client = tc3589x->i2c;
423  int ret = 0;
424 
425  /* put the system to sleep mode */
426  if (!device_may_wakeup(&client->dev))
427  ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
429 
430  return ret;
431 }
432 
433 static int tc3589x_resume(struct device *dev)
434 {
435  struct tc3589x *tc3589x = dev_get_drvdata(dev);
436  struct i2c_client *client = tc3589x->i2c;
437  int ret = 0;
438 
439  /* enable the system into operation */
440  if (!device_may_wakeup(&client->dev))
441  ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
443 
444  return ret;
445 }
446 #endif
447 
448 static SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, tc3589x_resume);
449 
450 static const struct i2c_device_id tc3589x_id[] = {
451  { "tc3589x", 24 },
452  { }
453 };
454 MODULE_DEVICE_TABLE(i2c, tc3589x_id);
455 
456 static struct i2c_driver tc3589x_driver = {
457  .driver.name = "tc3589x",
458  .driver.owner = THIS_MODULE,
459  .driver.pm = &tc3589x_dev_pm_ops,
460  .probe = tc3589x_probe,
461  .remove = __devexit_p(tc3589x_remove),
462  .id_table = tc3589x_id,
463 };
464 
465 static int __init tc3589x_init(void)
466 {
467  return i2c_add_driver(&tc3589x_driver);
468 }
469 subsys_initcall(tc3589x_init);
470 
471 static void __exit tc3589x_exit(void)
472 {
473  i2c_del_driver(&tc3589x_driver);
474 }
475 module_exit(tc3589x_exit);
476 
477 MODULE_LICENSE("GPL v2");
478 MODULE_DESCRIPTION("TC3589x MFD core driver");
479 MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");