rohm-bd71828.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // Copyright (C) 2019 ROHM Semiconductors
  4. //
  5. // ROHM BD71828 PMIC driver
  6. #include <linux/gpio_keys.h>
  7. #include <linux/i2c.h>
  8. #include <linux/input.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/ioport.h>
  11. #include <linux/irq.h>
  12. #include <linux/mfd/core.h>
  13. #include <linux/mfd/rohm-bd71828.h>
  14. #include <linux/module.h>
  15. #include <linux/of_device.h>
  16. #include <linux/regmap.h>
  17. #include <linux/types.h>
  18. static struct gpio_keys_button button = {
  19. .code = KEY_POWER,
  20. .gpio = -1,
  21. .type = EV_KEY,
  22. };
  23. static struct gpio_keys_platform_data bd71828_powerkey_data = {
  24. .buttons = &button,
  25. .nbuttons = 1,
  26. .name = "bd71828-pwrkey",
  27. };
  28. static const struct resource rtc_irqs[] = {
  29. DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"),
  30. DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"),
  31. DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC2, "bd71828-rtc-alm-2"),
  32. };
  33. static struct mfd_cell bd71828_mfd_cells[] = {
  34. { .name = "bd71828-pmic", },
  35. { .name = "bd71828-gpio", },
  36. { .name = "bd71828-led", .of_compatible = "rohm,bd71828-leds" },
  37. /*
  38. * We use BD71837 driver to drive the clock block. Only differences to
  39. * BD70528 clock gate are the register address and mask.
  40. */
  41. { .name = "bd71828-clk", },
  42. { .name = "bd71827-power", },
  43. {
  44. .name = "bd71828-rtc",
  45. .resources = rtc_irqs,
  46. .num_resources = ARRAY_SIZE(rtc_irqs),
  47. }, {
  48. .name = "gpio-keys",
  49. .platform_data = &bd71828_powerkey_data,
  50. .pdata_size = sizeof(bd71828_powerkey_data),
  51. },
  52. };
  53. static const struct regmap_range volatile_ranges[] = {
  54. {
  55. .range_min = BD71828_REG_PS_CTRL_1,
  56. .range_max = BD71828_REG_PS_CTRL_1,
  57. }, {
  58. .range_min = BD71828_REG_PS_CTRL_3,
  59. .range_max = BD71828_REG_PS_CTRL_3,
  60. }, {
  61. .range_min = BD71828_REG_RTC_SEC,
  62. .range_max = BD71828_REG_RTC_YEAR,
  63. }, {
  64. /*
  65. * For now make all charger registers volatile because many
  66. * needs to be and because the charger block is not that
  67. * performance critical.
  68. */
  69. .range_min = BD71828_REG_CHG_STATE,
  70. .range_max = BD71828_REG_CHG_FULL,
  71. }, {
  72. .range_min = BD71828_REG_INT_MAIN,
  73. .range_max = BD71828_REG_IO_STAT,
  74. },
  75. };
  76. static const struct regmap_access_table volatile_regs = {
  77. .yes_ranges = &volatile_ranges[0],
  78. .n_yes_ranges = ARRAY_SIZE(volatile_ranges),
  79. };
  80. static struct regmap_config bd71828_regmap = {
  81. .reg_bits = 8,
  82. .val_bits = 8,
  83. .volatile_table = &volatile_regs,
  84. .max_register = BD71828_MAX_REGISTER,
  85. .cache_type = REGCACHE_RBTREE,
  86. };
  87. /*
  88. * Mapping of main IRQ register bits to sub-IRQ register offsets so that we can
  89. * access corect sub-IRQ registers based on bits that are set in main IRQ
  90. * register.
  91. */
  92. static unsigned int bit0_offsets[] = {11}; /* RTC IRQ */
  93. static unsigned int bit1_offsets[] = {10}; /* TEMP IRQ */
  94. static unsigned int bit2_offsets[] = {6, 7, 8, 9}; /* BAT MON IRQ */
  95. static unsigned int bit3_offsets[] = {5}; /* BAT IRQ */
  96. static unsigned int bit4_offsets[] = {4}; /* CHG IRQ */
  97. static unsigned int bit5_offsets[] = {3}; /* VSYS IRQ */
  98. static unsigned int bit6_offsets[] = {1, 2}; /* DCIN IRQ */
  99. static unsigned int bit7_offsets[] = {0}; /* BUCK IRQ */
  100. static struct regmap_irq_sub_irq_map bd71828_sub_irq_offsets[] = {
  101. REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
  102. REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
  103. REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),
  104. REGMAP_IRQ_MAIN_REG_OFFSET(bit3_offsets),
  105. REGMAP_IRQ_MAIN_REG_OFFSET(bit4_offsets),
  106. REGMAP_IRQ_MAIN_REG_OFFSET(bit5_offsets),
  107. REGMAP_IRQ_MAIN_REG_OFFSET(bit6_offsets),
  108. REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),
  109. };
  110. static struct regmap_irq bd71828_irqs[] = {
  111. REGMAP_IRQ_REG(BD71828_INT_BUCK1_OCP, 0, BD71828_INT_BUCK1_OCP_MASK),
  112. REGMAP_IRQ_REG(BD71828_INT_BUCK2_OCP, 0, BD71828_INT_BUCK2_OCP_MASK),
  113. REGMAP_IRQ_REG(BD71828_INT_BUCK3_OCP, 0, BD71828_INT_BUCK3_OCP_MASK),
  114. REGMAP_IRQ_REG(BD71828_INT_BUCK4_OCP, 0, BD71828_INT_BUCK4_OCP_MASK),
  115. REGMAP_IRQ_REG(BD71828_INT_BUCK5_OCP, 0, BD71828_INT_BUCK5_OCP_MASK),
  116. REGMAP_IRQ_REG(BD71828_INT_BUCK6_OCP, 0, BD71828_INT_BUCK6_OCP_MASK),
  117. REGMAP_IRQ_REG(BD71828_INT_BUCK7_OCP, 0, BD71828_INT_BUCK7_OCP_MASK),
  118. REGMAP_IRQ_REG(BD71828_INT_PGFAULT, 0, BD71828_INT_PGFAULT_MASK),
  119. /* DCIN1 interrupts */
  120. REGMAP_IRQ_REG(BD71828_INT_DCIN_DET, 1, BD71828_INT_DCIN_DET_MASK),
  121. REGMAP_IRQ_REG(BD71828_INT_DCIN_RMV, 1, BD71828_INT_DCIN_RMV_MASK),
  122. REGMAP_IRQ_REG(BD71828_INT_CLPS_OUT, 1, BD71828_INT_CLPS_OUT_MASK),
  123. REGMAP_IRQ_REG(BD71828_INT_CLPS_IN, 1, BD71828_INT_CLPS_IN_MASK),
  124. /* DCIN2 interrupts */
  125. REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_RES, 2,
  126. BD71828_INT_DCIN_MON_RES_MASK),
  127. REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_DET, 2,
  128. BD71828_INT_DCIN_MON_DET_MASK),
  129. REGMAP_IRQ_REG(BD71828_INT_LONGPUSH, 2, BD71828_INT_LONGPUSH_MASK),
  130. REGMAP_IRQ_REG(BD71828_INT_MIDPUSH, 2, BD71828_INT_MIDPUSH_MASK),
  131. REGMAP_IRQ_REG(BD71828_INT_SHORTPUSH, 2, BD71828_INT_SHORTPUSH_MASK),
  132. REGMAP_IRQ_REG(BD71828_INT_PUSH, 2, BD71828_INT_PUSH_MASK),
  133. REGMAP_IRQ_REG(BD71828_INT_WDOG, 2, BD71828_INT_WDOG_MASK),
  134. REGMAP_IRQ_REG(BD71828_INT_SWRESET, 2, BD71828_INT_SWRESET_MASK),
  135. /* Vsys */
  136. REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_RES, 3,
  137. BD71828_INT_VSYS_UV_RES_MASK),
  138. REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_DET, 3,
  139. BD71828_INT_VSYS_UV_DET_MASK),
  140. REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_RES, 3,
  141. BD71828_INT_VSYS_LOW_RES_MASK),
  142. REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_DET, 3,
  143. BD71828_INT_VSYS_LOW_DET_MASK),
  144. REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_IN, 3,
  145. BD71828_INT_VSYS_HALL_IN_MASK),
  146. REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_TOGGLE, 3,
  147. BD71828_INT_VSYS_HALL_TOGGLE_MASK),
  148. REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_RES, 3,
  149. BD71828_INT_VSYS_MON_RES_MASK),
  150. REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_DET, 3,
  151. BD71828_INT_VSYS_MON_DET_MASK),
  152. /* Charger */
  153. REGMAP_IRQ_REG(BD71828_INT_CHG_DCIN_ILIM, 4,
  154. BD71828_INT_CHG_DCIN_ILIM_MASK),
  155. REGMAP_IRQ_REG(BD71828_INT_CHG_TOPOFF_TO_DONE, 4,
  156. BD71828_INT_CHG_TOPOFF_TO_DONE_MASK),
  157. REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TEMP, 4,
  158. BD71828_INT_CHG_WDG_TEMP_MASK),
  159. REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TIME, 4,
  160. BD71828_INT_CHG_WDG_TIME_MASK),
  161. REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_RES, 4,
  162. BD71828_INT_CHG_RECHARGE_RES_MASK),
  163. REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_DET, 4,
  164. BD71828_INT_CHG_RECHARGE_DET_MASK),
  165. REGMAP_IRQ_REG(BD71828_INT_CHG_RANGED_TEMP_TRANSITION, 4,
  166. BD71828_INT_CHG_RANGED_TEMP_TRANSITION_MASK),
  167. REGMAP_IRQ_REG(BD71828_INT_CHG_STATE_TRANSITION, 4,
  168. BD71828_INT_CHG_STATE_TRANSITION_MASK),
  169. /* Battery */
  170. REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_NORMAL, 5,
  171. BD71828_INT_BAT_TEMP_NORMAL_MASK),
  172. REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_ERANGE, 5,
  173. BD71828_INT_BAT_TEMP_ERANGE_MASK),
  174. REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_WARN, 5,
  175. BD71828_INT_BAT_TEMP_WARN_MASK),
  176. REGMAP_IRQ_REG(BD71828_INT_BAT_REMOVED, 5,
  177. BD71828_INT_BAT_REMOVED_MASK),
  178. REGMAP_IRQ_REG(BD71828_INT_BAT_DETECTED, 5,
  179. BD71828_INT_BAT_DETECTED_MASK),
  180. REGMAP_IRQ_REG(BD71828_INT_THERM_REMOVED, 5,
  181. BD71828_INT_THERM_REMOVED_MASK),
  182. REGMAP_IRQ_REG(BD71828_INT_THERM_DETECTED, 5,
  183. BD71828_INT_THERM_DETECTED_MASK),
  184. /* Battery Mon 1 */
  185. REGMAP_IRQ_REG(BD71828_INT_BAT_DEAD, 6, BD71828_INT_BAT_DEAD_MASK),
  186. REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_RES, 6,
  187. BD71828_INT_BAT_SHORTC_RES_MASK),
  188. REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_DET, 6,
  189. BD71828_INT_BAT_SHORTC_DET_MASK),
  190. REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_RES, 6,
  191. BD71828_INT_BAT_LOW_VOLT_RES_MASK),
  192. REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_DET, 6,
  193. BD71828_INT_BAT_LOW_VOLT_DET_MASK),
  194. REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_RES, 6,
  195. BD71828_INT_BAT_OVER_VOLT_RES_MASK),
  196. REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_DET, 6,
  197. BD71828_INT_BAT_OVER_VOLT_DET_MASK),
  198. /* Battery Mon 2 */
  199. REGMAP_IRQ_REG(BD71828_INT_BAT_MON_RES, 7,
  200. BD71828_INT_BAT_MON_RES_MASK),
  201. REGMAP_IRQ_REG(BD71828_INT_BAT_MON_DET, 7,
  202. BD71828_INT_BAT_MON_DET_MASK),
  203. /* Battery Mon 3 (Coulomb counter) */
  204. REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON1, 8,
  205. BD71828_INT_BAT_CC_MON1_MASK),
  206. REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON2, 8,
  207. BD71828_INT_BAT_CC_MON2_MASK),
  208. REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON3, 8,
  209. BD71828_INT_BAT_CC_MON3_MASK),
  210. /* Battery Mon 4 */
  211. REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_RES, 9,
  212. BD71828_INT_BAT_OVER_CURR_1_RES_MASK),
  213. REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_DET, 9,
  214. BD71828_INT_BAT_OVER_CURR_1_DET_MASK),
  215. REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_RES, 9,
  216. BD71828_INT_BAT_OVER_CURR_2_RES_MASK),
  217. REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_DET, 9,
  218. BD71828_INT_BAT_OVER_CURR_2_DET_MASK),
  219. REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_RES, 9,
  220. BD71828_INT_BAT_OVER_CURR_3_RES_MASK),
  221. REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_DET, 9,
  222. BD71828_INT_BAT_OVER_CURR_3_DET_MASK),
  223. /* Temperature */
  224. REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_RES, 10,
  225. BD71828_INT_TEMP_BAT_LOW_RES_MASK),
  226. REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_DET, 10,
  227. BD71828_INT_TEMP_BAT_LOW_DET_MASK),
  228. REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_RES, 10,
  229. BD71828_INT_TEMP_BAT_HI_RES_MASK),
  230. REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_DET, 10,
  231. BD71828_INT_TEMP_BAT_HI_DET_MASK),
  232. REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_RES, 10,
  233. BD71828_INT_TEMP_CHIP_OVER_125_RES_MASK),
  234. REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_DET, 10,
  235. BD71828_INT_TEMP_CHIP_OVER_125_DET_MASK),
  236. REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_DET, 10,
  237. BD71828_INT_TEMP_CHIP_OVER_VF_DET_MASK),
  238. REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_RES, 10,
  239. BD71828_INT_TEMP_CHIP_OVER_VF_RES_MASK),
  240. /* RTC Alarm */
  241. REGMAP_IRQ_REG(BD71828_INT_RTC0, 11, BD71828_INT_RTC0_MASK),
  242. REGMAP_IRQ_REG(BD71828_INT_RTC1, 11, BD71828_INT_RTC1_MASK),
  243. REGMAP_IRQ_REG(BD71828_INT_RTC2, 11, BD71828_INT_RTC2_MASK),
  244. };
  245. static struct regmap_irq_chip bd71828_irq_chip = {
  246. .name = "bd71828_irq",
  247. .main_status = BD71828_REG_INT_MAIN,
  248. .irqs = &bd71828_irqs[0],
  249. .num_irqs = ARRAY_SIZE(bd71828_irqs),
  250. .status_base = BD71828_REG_INT_BUCK,
  251. .mask_base = BD71828_REG_INT_MASK_BUCK,
  252. .ack_base = BD71828_REG_INT_BUCK,
  253. .mask_invert = true,
  254. .init_ack_masked = true,
  255. .num_regs = 12,
  256. .num_main_regs = 1,
  257. .sub_reg_offsets = &bd71828_sub_irq_offsets[0],
  258. .num_main_status_bits = 8,
  259. .irq_reg_stride = 1,
  260. };
  261. static int bd71828_i2c_probe(struct i2c_client *i2c)
  262. {
  263. struct rohm_regmap_dev *chip;
  264. struct regmap_irq_chip_data *irq_data;
  265. int ret;
  266. if (!i2c->irq) {
  267. dev_err(&i2c->dev, "No IRQ configured\n");
  268. return -EINVAL;
  269. }
  270. chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL);
  271. if (!chip)
  272. return -ENOMEM;
  273. dev_set_drvdata(&i2c->dev, chip);
  274. chip->regmap = devm_regmap_init_i2c(i2c, &bd71828_regmap);
  275. if (IS_ERR(chip->regmap)) {
  276. dev_err(&i2c->dev, "Failed to initialize Regmap\n");
  277. return PTR_ERR(chip->regmap);
  278. }
  279. ret = devm_regmap_add_irq_chip(&i2c->dev, chip->regmap,
  280. i2c->irq, IRQF_ONESHOT, 0,
  281. &bd71828_irq_chip, &irq_data);
  282. if (ret) {
  283. dev_err(&i2c->dev, "Failed to add IRQ chip\n");
  284. return ret;
  285. }
  286. dev_dbg(&i2c->dev, "Registered %d IRQs for chip\n",
  287. bd71828_irq_chip.num_irqs);
  288. ret = regmap_irq_get_virq(irq_data, BD71828_INT_SHORTPUSH);
  289. if (ret < 0) {
  290. dev_err(&i2c->dev, "Failed to get the power-key IRQ\n");
  291. return ret;
  292. }
  293. button.irq = ret;
  294. ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
  295. bd71828_mfd_cells,
  296. ARRAY_SIZE(bd71828_mfd_cells), NULL, 0,
  297. regmap_irq_get_domain(irq_data));
  298. if (ret)
  299. dev_err(&i2c->dev, "Failed to create subdevices\n");
  300. return ret;
  301. }
  302. static const struct of_device_id bd71828_of_match[] = {
  303. { .compatible = "rohm,bd71828", },
  304. { },
  305. };
  306. MODULE_DEVICE_TABLE(of, bd71828_of_match);
  307. static struct i2c_driver bd71828_drv = {
  308. .driver = {
  309. .name = "rohm-bd71828",
  310. .of_match_table = bd71828_of_match,
  311. },
  312. .probe_new = &bd71828_i2c_probe,
  313. };
  314. module_i2c_driver(bd71828_drv);
  315. MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
  316. MODULE_DESCRIPTION("ROHM BD71828 Power Management IC driver");
  317. MODULE_LICENSE("GPL");