tc3589x.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /*
  2. * Copyright (C) ST-Ericsson SA 2010
  3. *
  4. * License Terms: GNU General Public License, version 2
  5. * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
  6. * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
  7. */
  8. #include <linux/module.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/irq.h>
  11. #include <linux/irqdomain.h>
  12. #include <linux/slab.h>
  13. #include <linux/i2c.h>
  14. #include <linux/of.h>
  15. #include <linux/mfd/core.h>
  16. #include <linux/mfd/tc3589x.h>
  17. #define TC3589x_CLKMODE_MODCTL_SLEEP 0x0
  18. #define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0)
  19. /**
  20. * tc3589x_reg_read() - read a single TC3589x register
  21. * @tc3589x: Device to read from
  22. * @reg: Register to read
  23. */
  24. int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg)
  25. {
  26. int ret;
  27. ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg);
  28. if (ret < 0)
  29. dev_err(tc3589x->dev, "failed to read reg %#x: %d\n",
  30. reg, ret);
  31. return ret;
  32. }
  33. EXPORT_SYMBOL_GPL(tc3589x_reg_read);
  34. /**
  35. * tc3589x_reg_read() - write a single TC3589x register
  36. * @tc3589x: Device to write to
  37. * @reg: Register to read
  38. * @data: Value to write
  39. */
  40. int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data)
  41. {
  42. int ret;
  43. ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data);
  44. if (ret < 0)
  45. dev_err(tc3589x->dev, "failed to write reg %#x: %d\n",
  46. reg, ret);
  47. return ret;
  48. }
  49. EXPORT_SYMBOL_GPL(tc3589x_reg_write);
  50. /**
  51. * tc3589x_block_read() - read multiple TC3589x registers
  52. * @tc3589x: Device to read from
  53. * @reg: First register
  54. * @length: Number of registers
  55. * @values: Buffer to write to
  56. */
  57. int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values)
  58. {
  59. int ret;
  60. ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values);
  61. if (ret < 0)
  62. dev_err(tc3589x->dev, "failed to read regs %#x: %d\n",
  63. reg, ret);
  64. return ret;
  65. }
  66. EXPORT_SYMBOL_GPL(tc3589x_block_read);
  67. /**
  68. * tc3589x_block_write() - write multiple TC3589x registers
  69. * @tc3589x: Device to write to
  70. * @reg: First register
  71. * @length: Number of registers
  72. * @values: Values to write
  73. */
  74. int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
  75. const u8 *values)
  76. {
  77. int ret;
  78. ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length,
  79. values);
  80. if (ret < 0)
  81. dev_err(tc3589x->dev, "failed to write regs %#x: %d\n",
  82. reg, ret);
  83. return ret;
  84. }
  85. EXPORT_SYMBOL_GPL(tc3589x_block_write);
  86. /**
  87. * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register
  88. * @tc3589x: Device to write to
  89. * @reg: Register to write
  90. * @mask: Mask of bits to set
  91. * @values: Value to set
  92. */
  93. int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val)
  94. {
  95. int ret;
  96. mutex_lock(&tc3589x->lock);
  97. ret = tc3589x_reg_read(tc3589x, reg);
  98. if (ret < 0)
  99. goto out;
  100. ret &= ~mask;
  101. ret |= val;
  102. ret = tc3589x_reg_write(tc3589x, reg, ret);
  103. out:
  104. mutex_unlock(&tc3589x->lock);
  105. return ret;
  106. }
  107. EXPORT_SYMBOL_GPL(tc3589x_set_bits);
  108. static struct resource gpio_resources[] = {
  109. {
  110. .start = TC3589x_INT_GPIIRQ,
  111. .end = TC3589x_INT_GPIIRQ,
  112. .flags = IORESOURCE_IRQ,
  113. },
  114. };
  115. static struct resource keypad_resources[] = {
  116. {
  117. .start = TC3589x_INT_KBDIRQ,
  118. .end = TC3589x_INT_KBDIRQ,
  119. .flags = IORESOURCE_IRQ,
  120. },
  121. };
  122. static struct mfd_cell tc3589x_dev_gpio[] = {
  123. {
  124. .name = "tc3589x-gpio",
  125. .num_resources = ARRAY_SIZE(gpio_resources),
  126. .resources = &gpio_resources[0],
  127. .of_compatible = "tc3589x-gpio",
  128. },
  129. };
  130. static struct mfd_cell tc3589x_dev_keypad[] = {
  131. {
  132. .name = "tc3589x-keypad",
  133. .num_resources = ARRAY_SIZE(keypad_resources),
  134. .resources = &keypad_resources[0],
  135. .of_compatible = "tc3589x-keypad",
  136. },
  137. };
  138. static irqreturn_t tc3589x_irq(int irq, void *data)
  139. {
  140. struct tc3589x *tc3589x = data;
  141. int status;
  142. again:
  143. status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
  144. if (status < 0)
  145. return IRQ_NONE;
  146. while (status) {
  147. int bit = __ffs(status);
  148. int virq = irq_create_mapping(tc3589x->domain, bit);
  149. handle_nested_irq(virq);
  150. status &= ~(1 << bit);
  151. }
  152. /*
  153. * A dummy read or write (to any register) appears to be necessary to
  154. * have the last interrupt clear (for example, GPIO IC write) take
  155. * effect. In such a case, recheck for any interrupt which is still
  156. * pending.
  157. */
  158. status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
  159. if (status)
  160. goto again;
  161. return IRQ_HANDLED;
  162. }
  163. static int tc3589x_irq_map(struct irq_domain *d, unsigned int virq,
  164. irq_hw_number_t hwirq)
  165. {
  166. struct tc3589x *tc3589x = d->host_data;
  167. irq_set_chip_data(virq, tc3589x);
  168. irq_set_chip_and_handler(virq, &dummy_irq_chip,
  169. handle_edge_irq);
  170. irq_set_nested_thread(virq, 1);
  171. #ifdef CONFIG_ARM
  172. set_irq_flags(virq, IRQF_VALID);
  173. #else
  174. irq_set_noprobe(virq);
  175. #endif
  176. return 0;
  177. }
  178. static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
  179. {
  180. #ifdef CONFIG_ARM
  181. set_irq_flags(virq, 0);
  182. #endif
  183. irq_set_chip_and_handler(virq, NULL, NULL);
  184. irq_set_chip_data(virq, NULL);
  185. }
  186. static struct irq_domain_ops tc3589x_irq_ops = {
  187. .map = tc3589x_irq_map,
  188. .unmap = tc3589x_irq_unmap,
  189. .xlate = irq_domain_xlate_twocell,
  190. };
  191. static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
  192. {
  193. int base = tc3589x->irq_base;
  194. if (base) {
  195. tc3589x->domain = irq_domain_add_legacy(
  196. NULL, TC3589x_NR_INTERNAL_IRQS, base,
  197. 0, &tc3589x_irq_ops, tc3589x);
  198. }
  199. else {
  200. tc3589x->domain = irq_domain_add_linear(
  201. np, TC3589x_NR_INTERNAL_IRQS,
  202. &tc3589x_irq_ops, tc3589x);
  203. }
  204. if (!tc3589x->domain) {
  205. dev_err(tc3589x->dev, "Failed to create irqdomain\n");
  206. return -ENOSYS;
  207. }
  208. return 0;
  209. }
  210. static int tc3589x_chip_init(struct tc3589x *tc3589x)
  211. {
  212. int manf, ver, ret;
  213. manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE);
  214. if (manf < 0)
  215. return manf;
  216. ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION);
  217. if (ver < 0)
  218. return ver;
  219. if (manf != TC3589x_MANFCODE_MAGIC) {
  220. dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf);
  221. return -EINVAL;
  222. }
  223. dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
  224. /*
  225. * Put everything except the IRQ module into reset;
  226. * also spare the GPIO module for any pin initialization
  227. * done during pre-kernel boot
  228. */
  229. ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL,
  230. TC3589x_RSTCTRL_TIMRST
  231. | TC3589x_RSTCTRL_ROTRST
  232. | TC3589x_RSTCTRL_KBDRST);
  233. if (ret < 0)
  234. return ret;
  235. /* Clear the reset interrupt. */
  236. return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
  237. }
  238. static int tc3589x_device_init(struct tc3589x *tc3589x)
  239. {
  240. int ret = 0;
  241. unsigned int blocks = tc3589x->pdata->block;
  242. if (blocks & TC3589x_BLOCK_GPIO) {
  243. ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
  244. ARRAY_SIZE(tc3589x_dev_gpio), NULL,
  245. tc3589x->irq_base, tc3589x->domain);
  246. if (ret) {
  247. dev_err(tc3589x->dev, "failed to add gpio child\n");
  248. return ret;
  249. }
  250. dev_info(tc3589x->dev, "added gpio block\n");
  251. }
  252. if (blocks & TC3589x_BLOCK_KEYPAD) {
  253. ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
  254. ARRAY_SIZE(tc3589x_dev_keypad), NULL,
  255. tc3589x->irq_base, tc3589x->domain);
  256. if (ret) {
  257. dev_err(tc3589x->dev, "failed to keypad child\n");
  258. return ret;
  259. }
  260. dev_info(tc3589x->dev, "added keypad block\n");
  261. }
  262. return ret;
  263. }
  264. static int tc3589x_of_probe(struct device_node *np,
  265. struct tc3589x_platform_data *pdata)
  266. {
  267. struct device_node *child;
  268. for_each_child_of_node(np, child) {
  269. if (!strcmp(child->name, "tc3589x_gpio")) {
  270. pdata->block |= TC3589x_BLOCK_GPIO;
  271. }
  272. if (!strcmp(child->name, "tc3589x_keypad")) {
  273. pdata->block |= TC3589x_BLOCK_KEYPAD;
  274. }
  275. }
  276. return 0;
  277. }
  278. static int tc3589x_probe(struct i2c_client *i2c,
  279. const struct i2c_device_id *id)
  280. {
  281. struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
  282. struct device_node *np = i2c->dev.of_node;
  283. struct tc3589x *tc3589x;
  284. int ret;
  285. if (!pdata) {
  286. if (np) {
  287. pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
  288. if (!pdata)
  289. return -ENOMEM;
  290. ret = tc3589x_of_probe(np, pdata);
  291. if (ret)
  292. return ret;
  293. }
  294. else {
  295. dev_err(&i2c->dev, "No platform data or DT found\n");
  296. return -EINVAL;
  297. }
  298. }
  299. if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
  300. | I2C_FUNC_SMBUS_I2C_BLOCK))
  301. return -EIO;
  302. tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL);
  303. if (!tc3589x)
  304. return -ENOMEM;
  305. mutex_init(&tc3589x->lock);
  306. tc3589x->dev = &i2c->dev;
  307. tc3589x->i2c = i2c;
  308. tc3589x->pdata = pdata;
  309. tc3589x->irq_base = pdata->irq_base;
  310. tc3589x->num_gpio = id->driver_data;
  311. i2c_set_clientdata(i2c, tc3589x);
  312. ret = tc3589x_chip_init(tc3589x);
  313. if (ret)
  314. goto out_free;
  315. ret = tc3589x_irq_init(tc3589x, np);
  316. if (ret)
  317. goto out_free;
  318. ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq,
  319. IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  320. "tc3589x", tc3589x);
  321. if (ret) {
  322. dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
  323. goto out_free;
  324. }
  325. ret = tc3589x_device_init(tc3589x);
  326. if (ret) {
  327. dev_err(tc3589x->dev, "failed to add child devices\n");
  328. goto out_freeirq;
  329. }
  330. return 0;
  331. out_freeirq:
  332. free_irq(tc3589x->i2c->irq, tc3589x);
  333. out_free:
  334. kfree(tc3589x);
  335. return ret;
  336. }
  337. static int tc3589x_remove(struct i2c_client *client)
  338. {
  339. struct tc3589x *tc3589x = i2c_get_clientdata(client);
  340. mfd_remove_devices(tc3589x->dev);
  341. free_irq(tc3589x->i2c->irq, tc3589x);
  342. kfree(tc3589x);
  343. return 0;
  344. }
  345. #ifdef CONFIG_PM_SLEEP
  346. static int tc3589x_suspend(struct device *dev)
  347. {
  348. struct tc3589x *tc3589x = dev_get_drvdata(dev);
  349. struct i2c_client *client = tc3589x->i2c;
  350. int ret = 0;
  351. /* put the system to sleep mode */
  352. if (!device_may_wakeup(&client->dev))
  353. ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
  354. TC3589x_CLKMODE_MODCTL_SLEEP);
  355. return ret;
  356. }
  357. static int tc3589x_resume(struct device *dev)
  358. {
  359. struct tc3589x *tc3589x = dev_get_drvdata(dev);
  360. struct i2c_client *client = tc3589x->i2c;
  361. int ret = 0;
  362. /* enable the system into operation */
  363. if (!device_may_wakeup(&client->dev))
  364. ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
  365. TC3589x_CLKMODE_MODCTL_OPERATION);
  366. return ret;
  367. }
  368. #endif
  369. static SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, tc3589x_resume);
  370. static const struct i2c_device_id tc3589x_id[] = {
  371. { "tc3589x", 24 },
  372. { }
  373. };
  374. MODULE_DEVICE_TABLE(i2c, tc3589x_id);
  375. static struct i2c_driver tc3589x_driver = {
  376. .driver.name = "tc3589x",
  377. .driver.owner = THIS_MODULE,
  378. .driver.pm = &tc3589x_dev_pm_ops,
  379. .probe = tc3589x_probe,
  380. .remove = tc3589x_remove,
  381. .id_table = tc3589x_id,
  382. };
  383. static int __init tc3589x_init(void)
  384. {
  385. return i2c_add_driver(&tc3589x_driver);
  386. }
  387. subsys_initcall(tc3589x_init);
  388. static void __exit tc3589x_exit(void)
  389. {
  390. i2c_del_driver(&tc3589x_driver);
  391. }
  392. module_exit(tc3589x_exit);
  393. MODULE_LICENSE("GPL v2");
  394. MODULE_DESCRIPTION("TC3589x MFD core driver");
  395. MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");