sprd-sc27xx-spi.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * Copyright (C) 2017 Spreadtrum Communications Inc.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/interrupt.h>
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/mfd/core.h>
  17. #include <linux/of_device.h>
  18. #include <linux/regmap.h>
  19. #include <linux/spi/spi.h>
  20. #define SPRD_PMIC_INT_MASK_STATUS 0x0
  21. #define SPRD_PMIC_INT_RAW_STATUS 0x4
  22. #define SPRD_PMIC_INT_EN 0x8
  23. #define SPRD_SC2731_IRQ_BASE 0x140
  24. #define SPRD_SC2731_IRQ_NUMS 16
  25. struct sprd_pmic {
  26. struct regmap *regmap;
  27. struct device *dev;
  28. struct regmap_irq *irqs;
  29. struct regmap_irq_chip irq_chip;
  30. struct regmap_irq_chip_data *irq_data;
  31. int irq;
  32. };
  33. struct sprd_pmic_data {
  34. u32 irq_base;
  35. u32 num_irqs;
  36. };
  37. /*
  38. * Since different PMICs of SC27xx series can have different interrupt
  39. * base address and irq number, we should save irq number and irq base
  40. * in the device data structure.
  41. */
  42. static const struct sprd_pmic_data sc2731_data = {
  43. .irq_base = SPRD_SC2731_IRQ_BASE,
  44. .num_irqs = SPRD_SC2731_IRQ_NUMS,
  45. };
  46. static const struct mfd_cell sprd_pmic_devs[] = {
  47. {
  48. .name = "sc27xx-wdt",
  49. .of_compatible = "sprd,sc27xx-wdt",
  50. }, {
  51. .name = "sc27xx-rtc",
  52. .of_compatible = "sprd,sc27xx-rtc",
  53. }, {
  54. .name = "sc27xx-charger",
  55. .of_compatible = "sprd,sc27xx-charger",
  56. }, {
  57. .name = "sc27xx-chg-timer",
  58. .of_compatible = "sprd,sc27xx-chg-timer",
  59. }, {
  60. .name = "sc27xx-fast-chg",
  61. .of_compatible = "sprd,sc27xx-fast-chg",
  62. }, {
  63. .name = "sc27xx-chg-wdt",
  64. .of_compatible = "sprd,sc27xx-chg-wdt",
  65. }, {
  66. .name = "sc27xx-typec",
  67. .of_compatible = "sprd,sc27xx-typec",
  68. }, {
  69. .name = "sc27xx-flash",
  70. .of_compatible = "sprd,sc27xx-flash",
  71. }, {
  72. .name = "sc27xx-eic",
  73. .of_compatible = "sprd,sc27xx-eic",
  74. }, {
  75. .name = "sc27xx-efuse",
  76. .of_compatible = "sprd,sc27xx-efuse",
  77. }, {
  78. .name = "sc27xx-thermal",
  79. .of_compatible = "sprd,sc27xx-thermal",
  80. }, {
  81. .name = "sc27xx-adc",
  82. .of_compatible = "sprd,sc27xx-adc",
  83. }, {
  84. .name = "sc27xx-audio-codec",
  85. .of_compatible = "sprd,sc27xx-audio-codec",
  86. }, {
  87. .name = "sc27xx-regulator",
  88. .of_compatible = "sprd,sc27xx-regulator",
  89. }, {
  90. .name = "sc27xx-vibrator",
  91. .of_compatible = "sprd,sc27xx-vibrator",
  92. }, {
  93. .name = "sc27xx-keypad-led",
  94. .of_compatible = "sprd,sc27xx-keypad-led",
  95. }, {
  96. .name = "sc27xx-bltc",
  97. .of_compatible = "sprd,sc27xx-bltc",
  98. }, {
  99. .name = "sc27xx-fgu",
  100. .of_compatible = "sprd,sc27xx-fgu",
  101. }, {
  102. .name = "sc27xx-7sreset",
  103. .of_compatible = "sprd,sc27xx-7sreset",
  104. }, {
  105. .name = "sc27xx-poweroff",
  106. .of_compatible = "sprd,sc27xx-poweroff",
  107. }, {
  108. .name = "sc27xx-syscon",
  109. .of_compatible = "sprd,sc27xx-syscon",
  110. },
  111. };
  112. static int sprd_pmic_spi_write(void *context, const void *data, size_t count)
  113. {
  114. struct device *dev = context;
  115. struct spi_device *spi = to_spi_device(dev);
  116. return spi_write(spi, data, count);
  117. }
  118. static int sprd_pmic_spi_read(void *context,
  119. const void *reg, size_t reg_size,
  120. void *val, size_t val_size)
  121. {
  122. struct device *dev = context;
  123. struct spi_device *spi = to_spi_device(dev);
  124. u32 rx_buf[2] = { 0 };
  125. int ret;
  126. /* Now we only support one PMIC register to read every time. */
  127. if (reg_size != sizeof(u32) || val_size != sizeof(u32))
  128. return -EINVAL;
  129. /* Copy address to read from into first element of SPI buffer. */
  130. memcpy(rx_buf, reg, sizeof(u32));
  131. ret = spi_read(spi, rx_buf, 1);
  132. if (ret < 0)
  133. return ret;
  134. memcpy(val, rx_buf, val_size);
  135. return 0;
  136. }
  137. static struct regmap_bus sprd_pmic_regmap = {
  138. .write = sprd_pmic_spi_write,
  139. .read = sprd_pmic_spi_read,
  140. .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
  141. .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
  142. };
  143. static const struct regmap_config sprd_pmic_config = {
  144. .reg_bits = 32,
  145. .val_bits = 32,
  146. .reg_stride = 4,
  147. .max_register = 0xffff,
  148. };
  149. static int sprd_pmic_probe(struct spi_device *spi)
  150. {
  151. struct sprd_pmic *ddata;
  152. const struct sprd_pmic_data *pdata;
  153. int ret, i;
  154. pdata = of_device_get_match_data(&spi->dev);
  155. if (!pdata) {
  156. dev_err(&spi->dev, "No matching driver data found\n");
  157. return -EINVAL;
  158. }
  159. ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
  160. if (!ddata)
  161. return -ENOMEM;
  162. ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap,
  163. &spi->dev, &sprd_pmic_config);
  164. if (IS_ERR(ddata->regmap)) {
  165. ret = PTR_ERR(ddata->regmap);
  166. dev_err(&spi->dev, "Failed to allocate register map %d\n", ret);
  167. return ret;
  168. }
  169. spi_set_drvdata(spi, ddata);
  170. ddata->dev = &spi->dev;
  171. ddata->irq = spi->irq;
  172. ddata->irq_chip.name = dev_name(&spi->dev);
  173. ddata->irq_chip.status_base =
  174. pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS;
  175. ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN;
  176. ddata->irq_chip.ack_base = 0;
  177. ddata->irq_chip.num_regs = 1;
  178. ddata->irq_chip.num_irqs = pdata->num_irqs;
  179. ddata->irq_chip.mask_invert = true;
  180. ddata->irqs = devm_kcalloc(&spi->dev,
  181. pdata->num_irqs, sizeof(struct regmap_irq),
  182. GFP_KERNEL);
  183. if (!ddata->irqs)
  184. return -ENOMEM;
  185. ddata->irq_chip.irqs = ddata->irqs;
  186. for (i = 0; i < pdata->num_irqs; i++) {
  187. ddata->irqs[i].reg_offset = i / pdata->num_irqs;
  188. ddata->irqs[i].mask = BIT(i % pdata->num_irqs);
  189. }
  190. ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq,
  191. IRQF_ONESHOT | IRQF_NO_SUSPEND, 0,
  192. &ddata->irq_chip, &ddata->irq_data);
  193. if (ret) {
  194. dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret);
  195. return ret;
  196. }
  197. ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO,
  198. sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs),
  199. NULL, 0,
  200. regmap_irq_get_domain(ddata->irq_data));
  201. if (ret) {
  202. dev_err(&spi->dev, "Failed to register device %d\n", ret);
  203. return ret;
  204. }
  205. return 0;
  206. }
  207. static const struct of_device_id sprd_pmic_match[] = {
  208. { .compatible = "sprd,sc2731", .data = &sc2731_data },
  209. {},
  210. };
  211. MODULE_DEVICE_TABLE(of, sprd_pmic_match);
  212. static struct spi_driver sprd_pmic_driver = {
  213. .driver = {
  214. .name = "sc27xx-pmic",
  215. .bus = &spi_bus_type,
  216. .of_match_table = sprd_pmic_match,
  217. },
  218. .probe = sprd_pmic_probe,
  219. };
  220. static int __init sprd_pmic_init(void)
  221. {
  222. return spi_register_driver(&sprd_pmic_driver);
  223. }
  224. subsys_initcall(sprd_pmic_init);
  225. static void __exit sprd_pmic_exit(void)
  226. {
  227. spi_unregister_driver(&sprd_pmic_driver);
  228. }
  229. module_exit(sprd_pmic_exit);
  230. MODULE_LICENSE("GPL v2");
  231. MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver");
  232. MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>");