bd9571mwv.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * ROHM BD9571MWV-M and BD9574MVF-M core driver
  4. *
  5. * Copyright (C) 2017 Marek Vasut <[email protected]>
  6. * Copyright (C) 2020 Renesas Electronics Corporation
  7. *
  8. * Based on the TPS65086 driver
  9. */
  10. #include <linux/i2c.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/mfd/core.h>
  13. #include <linux/mfd/rohm-generic.h>
  14. #include <linux/module.h>
  15. #include <linux/mfd/bd9571mwv.h>
  16. static const struct mfd_cell bd9571mwv_cells[] = {
  17. { .name = "bd9571mwv-regulator", },
  18. { .name = "bd9571mwv-gpio", },
  19. };
  20. static const struct regmap_range bd9571mwv_readable_yes_ranges[] = {
  21. regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
  22. regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
  23. regmap_reg_range(BD9571MWV_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)),
  24. regmap_reg_range(BD9571MWV_VD18_VID, BD9571MWV_VD33_VID),
  25. regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_VINIT),
  26. regmap_reg_range(BD9571MWV_DVFS_SETVMAX, BD9571MWV_DVFS_MONIVDAC),
  27. regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
  28. regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK),
  29. regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
  30. };
  31. static const struct regmap_access_table bd9571mwv_readable_table = {
  32. .yes_ranges = bd9571mwv_readable_yes_ranges,
  33. .n_yes_ranges = ARRAY_SIZE(bd9571mwv_readable_yes_ranges),
  34. };
  35. static const struct regmap_range bd9571mwv_writable_yes_ranges[] = {
  36. regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
  37. regmap_reg_range(BD9571MWV_AVS_VD09_VID(0), BD9571MWV_AVS_VD09_VID(3)),
  38. regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
  39. regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
  40. regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK),
  41. regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
  42. };
  43. static const struct regmap_access_table bd9571mwv_writable_table = {
  44. .yes_ranges = bd9571mwv_writable_yes_ranges,
  45. .n_yes_ranges = ARRAY_SIZE(bd9571mwv_writable_yes_ranges),
  46. };
  47. static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
  48. regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
  49. regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
  50. regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
  51. regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
  52. };
  53. static const struct regmap_access_table bd9571mwv_volatile_table = {
  54. .yes_ranges = bd9571mwv_volatile_yes_ranges,
  55. .n_yes_ranges = ARRAY_SIZE(bd9571mwv_volatile_yes_ranges),
  56. };
  57. static const struct regmap_config bd9571mwv_regmap_config = {
  58. .reg_bits = 8,
  59. .val_bits = 8,
  60. .cache_type = REGCACHE_RBTREE,
  61. .rd_table = &bd9571mwv_readable_table,
  62. .wr_table = &bd9571mwv_writable_table,
  63. .volatile_table = &bd9571mwv_volatile_table,
  64. .max_register = 0xff,
  65. };
  66. static const struct regmap_irq bd9571mwv_irqs[] = {
  67. REGMAP_IRQ_REG(BD9571MWV_IRQ_MD1, 0,
  68. BD9571MWV_INT_INTREQ_MD1_INT),
  69. REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E1, 0,
  70. BD9571MWV_INT_INTREQ_MD2_E1_INT),
  71. REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E2, 0,
  72. BD9571MWV_INT_INTREQ_MD2_E2_INT),
  73. REGMAP_IRQ_REG(BD9571MWV_IRQ_PROT_ERR, 0,
  74. BD9571MWV_INT_INTREQ_PROT_ERR_INT),
  75. REGMAP_IRQ_REG(BD9571MWV_IRQ_GP, 0,
  76. BD9571MWV_INT_INTREQ_GP_INT),
  77. REGMAP_IRQ_REG(BD9571MWV_IRQ_128H_OF, 0,
  78. BD9571MWV_INT_INTREQ_128H_OF_INT),
  79. REGMAP_IRQ_REG(BD9571MWV_IRQ_WDT_OF, 0,
  80. BD9571MWV_INT_INTREQ_WDT_OF_INT),
  81. REGMAP_IRQ_REG(BD9571MWV_IRQ_BKUP_TRG, 0,
  82. BD9571MWV_INT_INTREQ_BKUP_TRG_INT),
  83. };
  84. static struct regmap_irq_chip bd9571mwv_irq_chip = {
  85. .name = "bd9571mwv",
  86. .status_base = BD9571MWV_INT_INTREQ,
  87. .mask_base = BD9571MWV_INT_INTMASK,
  88. .ack_base = BD9571MWV_INT_INTREQ,
  89. .init_ack_masked = true,
  90. .num_regs = 1,
  91. .irqs = bd9571mwv_irqs,
  92. .num_irqs = ARRAY_SIZE(bd9571mwv_irqs),
  93. };
  94. static const struct mfd_cell bd9574mwf_cells[] = {
  95. { .name = "bd9574mwf-regulator", },
  96. { .name = "bd9574mwf-gpio", },
  97. };
  98. static const struct regmap_range bd9574mwf_readable_yes_ranges[] = {
  99. regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
  100. regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
  101. regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_SETVMAX),
  102. regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_MONIVDAC),
  103. regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
  104. regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK),
  105. regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
  106. };
  107. static const struct regmap_access_table bd9574mwf_readable_table = {
  108. .yes_ranges = bd9574mwf_readable_yes_ranges,
  109. .n_yes_ranges = ARRAY_SIZE(bd9574mwf_readable_yes_ranges),
  110. };
  111. static const struct regmap_range bd9574mwf_writable_yes_ranges[] = {
  112. regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
  113. regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
  114. regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
  115. regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK),
  116. regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
  117. };
  118. static const struct regmap_access_table bd9574mwf_writable_table = {
  119. .yes_ranges = bd9574mwf_writable_yes_ranges,
  120. .n_yes_ranges = ARRAY_SIZE(bd9574mwf_writable_yes_ranges),
  121. };
  122. static const struct regmap_range bd9574mwf_volatile_yes_ranges[] = {
  123. regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
  124. regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
  125. regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
  126. regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
  127. };
  128. static const struct regmap_access_table bd9574mwf_volatile_table = {
  129. .yes_ranges = bd9574mwf_volatile_yes_ranges,
  130. .n_yes_ranges = ARRAY_SIZE(bd9574mwf_volatile_yes_ranges),
  131. };
  132. static const struct regmap_config bd9574mwf_regmap_config = {
  133. .reg_bits = 8,
  134. .val_bits = 8,
  135. .cache_type = REGCACHE_RBTREE,
  136. .rd_table = &bd9574mwf_readable_table,
  137. .wr_table = &bd9574mwf_writable_table,
  138. .volatile_table = &bd9574mwf_volatile_table,
  139. .max_register = 0xff,
  140. };
  141. static struct regmap_irq_chip bd9574mwf_irq_chip = {
  142. .name = "bd9574mwf",
  143. .status_base = BD9571MWV_INT_INTREQ,
  144. .mask_base = BD9571MWV_INT_INTMASK,
  145. .ack_base = BD9571MWV_INT_INTREQ,
  146. .init_ack_masked = true,
  147. .num_regs = 1,
  148. .irqs = bd9571mwv_irqs,
  149. .num_irqs = ARRAY_SIZE(bd9571mwv_irqs),
  150. };
  151. static int bd957x_identify(struct device *dev, struct regmap *regmap)
  152. {
  153. unsigned int value;
  154. int ret;
  155. ret = regmap_read(regmap, BD9571MWV_VENDOR_CODE, &value);
  156. if (ret) {
  157. dev_err(dev, "Failed to read vendor code register (ret=%i)\n",
  158. ret);
  159. return ret;
  160. }
  161. if (value != BD9571MWV_VENDOR_CODE_VAL) {
  162. dev_err(dev, "Invalid vendor code ID %02x (expected %02x)\n",
  163. value, BD9571MWV_VENDOR_CODE_VAL);
  164. return -EINVAL;
  165. }
  166. ret = regmap_read(regmap, BD9571MWV_PRODUCT_CODE, &value);
  167. if (ret) {
  168. dev_err(dev, "Failed to read product code register (ret=%i)\n",
  169. ret);
  170. return ret;
  171. }
  172. ret = regmap_read(regmap, BD9571MWV_PRODUCT_REVISION, &value);
  173. if (ret) {
  174. dev_err(dev, "Failed to read revision register (ret=%i)\n",
  175. ret);
  176. return ret;
  177. }
  178. return 0;
  179. }
  180. static int bd9571mwv_probe(struct i2c_client *client,
  181. const struct i2c_device_id *ids)
  182. {
  183. const struct regmap_config *regmap_config;
  184. const struct regmap_irq_chip *irq_chip;
  185. const struct mfd_cell *cells;
  186. struct device *dev = &client->dev;
  187. struct regmap *regmap;
  188. struct regmap_irq_chip_data *irq_data;
  189. int ret, num_cells, irq = client->irq;
  190. /* Read the PMIC product code */
  191. ret = i2c_smbus_read_byte_data(client, BD9571MWV_PRODUCT_CODE);
  192. if (ret < 0) {
  193. dev_err(dev, "Failed to read product code\n");
  194. return ret;
  195. }
  196. switch (ret) {
  197. case BD9571MWV_PRODUCT_CODE_BD9571MWV:
  198. regmap_config = &bd9571mwv_regmap_config;
  199. irq_chip = &bd9571mwv_irq_chip;
  200. cells = bd9571mwv_cells;
  201. num_cells = ARRAY_SIZE(bd9571mwv_cells);
  202. break;
  203. case BD9571MWV_PRODUCT_CODE_BD9574MWF:
  204. regmap_config = &bd9574mwf_regmap_config;
  205. irq_chip = &bd9574mwf_irq_chip;
  206. cells = bd9574mwf_cells;
  207. num_cells = ARRAY_SIZE(bd9574mwf_cells);
  208. break;
  209. default:
  210. dev_err(dev, "Unsupported device 0x%x\n", ret);
  211. return -ENODEV;
  212. }
  213. regmap = devm_regmap_init_i2c(client, regmap_config);
  214. if (IS_ERR(regmap)) {
  215. dev_err(dev, "Failed to initialize register map\n");
  216. return PTR_ERR(regmap);
  217. }
  218. ret = bd957x_identify(dev, regmap);
  219. if (ret)
  220. return ret;
  221. ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT, 0,
  222. irq_chip, &irq_data);
  223. if (ret) {
  224. dev_err(dev, "Failed to register IRQ chip\n");
  225. return ret;
  226. }
  227. return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, num_cells,
  228. NULL, 0, regmap_irq_get_domain(irq_data));
  229. }
  230. static const struct of_device_id bd9571mwv_of_match_table[] = {
  231. { .compatible = "rohm,bd9571mwv", },
  232. { .compatible = "rohm,bd9574mwf", },
  233. { /* sentinel */ }
  234. };
  235. MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table);
  236. static const struct i2c_device_id bd9571mwv_id_table[] = {
  237. { "bd9571mwv", 0 },
  238. { /* sentinel */ }
  239. };
  240. MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table);
  241. static struct i2c_driver bd9571mwv_driver = {
  242. .driver = {
  243. .name = "bd9571mwv",
  244. .of_match_table = bd9571mwv_of_match_table,
  245. },
  246. .probe = bd9571mwv_probe,
  247. .id_table = bd9571mwv_id_table,
  248. };
  249. module_i2c_driver(bd9571mwv_driver);
  250. MODULE_AUTHOR("Marek Vasut <[email protected]>");
  251. MODULE_DESCRIPTION("BD9571MWV PMIC Driver");
  252. MODULE_LICENSE("GPL v2");