883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. From e0f8ad2a705367518b5c56bf9d6da89681467c02 Mon Sep 17 00:00:00 2001
  2. From: Shengyu Qu <[email protected]>
  3. Date: Fri, 21 Apr 2023 23:08:15 +0800
  4. Subject: [PATCH] mfd: axp20x: Add support for AXP15060 PMIC
  5. The AXP15060 is a PMIC chip produced by X-Powers, and could be connected
  6. via an I2C bus.
  7. Describe the regmap and the MFD bits, along with the registers exposed
  8. via I2C. Eventually advertise the device using a new compatible string
  9. and add support for power off the system.
  10. The driver would disable PEK function if IRQ is not configured in device
  11. tree, since some boards (For example, Starfive Visionfive 2) didn't
  12. connect IRQ line of PMIC to SOC.
  13. GPIO function isn't enabled in this commit, since its configuration
  14. operation is different from any existing AXP PMICs and needs
  15. logic modification on existing driver. GPIO support might come in later
  16. patches.
  17. Signed-off-by: Shengyu Qu <[email protected]>
  18. Reviewed-by: Krzysztof Kozlowski <[email protected]>
  19. Signed-off-by: Lee Jones <[email protected]>
  20. Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB2611.JPNP286.PROD.OUTLOOK.COM
  21. ---
  22. drivers/mfd/axp20x-i2c.c | 2 +
  23. drivers/mfd/axp20x.c | 107 +++++++++++++++++++++++++++++++++++++
  24. include/linux/mfd/axp20x.h | 85 +++++++++++++++++++++++++++++
  25. 3 files changed, 194 insertions(+)
  26. --- a/drivers/mfd/axp20x-i2c.c
  27. +++ b/drivers/mfd/axp20x-i2c.c
  28. @@ -66,6 +66,7 @@ static const struct of_device_id axp20x_
  29. { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
  30. { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
  31. { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
  32. + { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
  33. { },
  34. };
  35. MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
  36. @@ -79,6 +80,7 @@ static const struct i2c_device_id axp20x
  37. { "axp223", 0 },
  38. { "axp803", 0 },
  39. { "axp806", 0 },
  40. + { "axp15060", 0 },
  41. { },
  42. };
  43. MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
  44. --- a/drivers/mfd/axp20x.c
  45. +++ b/drivers/mfd/axp20x.c
  46. @@ -43,6 +43,7 @@ static const char * const axp20x_model_n
  47. "AXP806",
  48. "AXP809",
  49. "AXP813",
  50. + "AXP15060",
  51. };
  52. static const struct regmap_range axp152_writeable_ranges[] = {
  53. @@ -169,6 +170,31 @@ static const struct regmap_access_table
  54. .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
  55. };
  56. +static const struct regmap_range axp15060_writeable_ranges[] = {
  57. + regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2),
  58. + regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL),
  59. + regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
  60. + regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY),
  61. + regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN),
  62. + regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
  63. +};
  64. +
  65. +static const struct regmap_range axp15060_volatile_ranges[] = {
  66. + regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC),
  67. + regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
  68. + regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
  69. +};
  70. +
  71. +static const struct regmap_access_table axp15060_writeable_table = {
  72. + .yes_ranges = axp15060_writeable_ranges,
  73. + .n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges),
  74. +};
  75. +
  76. +static const struct regmap_access_table axp15060_volatile_table = {
  77. + .yes_ranges = axp15060_volatile_ranges,
  78. + .n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges),
  79. +};
  80. +
  81. static const struct resource axp152_pek_resources[] = {
  82. DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
  83. DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
  84. @@ -237,6 +263,11 @@ static const struct resource axp809_pek_
  85. DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
  86. };
  87. +static const struct resource axp15060_pek_resources[] = {
  88. + DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
  89. + DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
  90. +};
  91. +
  92. static const struct regmap_config axp152_regmap_config = {
  93. .reg_bits = 8,
  94. .val_bits = 8,
  95. @@ -282,6 +313,15 @@ static const struct regmap_config axp806
  96. .cache_type = REGCACHE_RBTREE,
  97. };
  98. +static const struct regmap_config axp15060_regmap_config = {
  99. + .reg_bits = 8,
  100. + .val_bits = 8,
  101. + .wr_table = &axp15060_writeable_table,
  102. + .volatile_table = &axp15060_volatile_table,
  103. + .max_register = AXP15060_IRQ2_STATE,
  104. + .cache_type = REGCACHE_RBTREE,
  105. +};
  106. +
  107. #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
  108. [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
  109. @@ -503,6 +543,23 @@ static const struct regmap_irq axp809_re
  110. INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0),
  111. };
  112. +static const struct regmap_irq axp15060_regmap_irqs[] = {
  113. + INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0),
  114. + INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1),
  115. + INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2),
  116. + INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3),
  117. + INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4),
  118. + INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5),
  119. + INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6),
  120. + INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7),
  121. + INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0),
  122. + INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1),
  123. + INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2),
  124. + INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3),
  125. + INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4),
  126. + INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5),
  127. +};
  128. +
  129. static const struct regmap_irq_chip axp152_regmap_irq_chip = {
  130. .name = "axp152_irq_chip",
  131. .status_base = AXP152_IRQ1_STATE,
  132. @@ -589,6 +646,17 @@ static const struct regmap_irq_chip axp8
  133. .num_regs = 5,
  134. };
  135. +static const struct regmap_irq_chip axp15060_regmap_irq_chip = {
  136. + .name = "axp15060",
  137. + .status_base = AXP15060_IRQ1_STATE,
  138. + .ack_base = AXP15060_IRQ1_STATE,
  139. + .unmask_base = AXP15060_IRQ1_EN,
  140. + .init_ack_masked = true,
  141. + .irqs = axp15060_regmap_irqs,
  142. + .num_irqs = ARRAY_SIZE(axp15060_regmap_irqs),
  143. + .num_regs = 2,
  144. +};
  145. +
  146. static const struct mfd_cell axp20x_cells[] = {
  147. {
  148. .name = "axp20x-gpio",
  149. @@ -833,6 +901,23 @@ static const struct mfd_cell axp813_cell
  150. },
  151. };
  152. +static const struct mfd_cell axp15060_cells[] = {
  153. + {
  154. + .name = "axp221-pek",
  155. + .num_resources = ARRAY_SIZE(axp15060_pek_resources),
  156. + .resources = axp15060_pek_resources,
  157. + }, {
  158. + .name = "axp20x-regulator",
  159. + },
  160. +};
  161. +
  162. +/* For boards that don't have IRQ line connected to SOC. */
  163. +static const struct mfd_cell axp_regulator_only_cells[] = {
  164. + {
  165. + .name = "axp20x-regulator",
  166. + },
  167. +};
  168. +
  169. static int axp20x_power_off(struct sys_off_data *data)
  170. {
  171. struct axp20x_dev *axp20x = data->cb_data;
  172. @@ -942,6 +1027,28 @@ int axp20x_match_device(struct axp20x_de
  173. */
  174. axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
  175. break;
  176. + case AXP15060_ID:
  177. + /*
  178. + * Don't register the power key part if there is no interrupt
  179. + * line.
  180. + *
  181. + * Since most use cases of AXP PMICs are Allwinner SOCs, board
  182. + * designers follow Allwinner's reference design and connects
  183. + * IRQ line to SOC, there's no need for those variants to deal
  184. + * with cases that IRQ isn't connected. However, AXP15660 is
  185. + * used by some other vendors' SOCs that didn't connect IRQ
  186. + * line, we need to deal with this case.
  187. + */
  188. + if (axp20x->irq > 0) {
  189. + axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
  190. + axp20x->cells = axp15060_cells;
  191. + } else {
  192. + axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
  193. + axp20x->cells = axp_regulator_only_cells;
  194. + }
  195. + axp20x->regmap_cfg = &axp15060_regmap_config;
  196. + axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
  197. + break;
  198. default:
  199. dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
  200. return -EINVAL;
  201. --- a/include/linux/mfd/axp20x.h
  202. +++ b/include/linux/mfd/axp20x.h
  203. @@ -21,6 +21,7 @@ enum axp20x_variants {
  204. AXP806_ID,
  205. AXP809_ID,
  206. AXP813_ID,
  207. + AXP15060_ID,
  208. NR_AXP20X_VARIANTS,
  209. };
  210. @@ -131,6 +132,39 @@ enum axp20x_variants {
  211. /* Other DCDC regulator control registers are the same as AXP803 */
  212. #define AXP813_DCDC7_V_OUT 0x26
  213. +#define AXP15060_STARTUP_SRC 0x00
  214. +#define AXP15060_PWR_OUT_CTRL1 0x10
  215. +#define AXP15060_PWR_OUT_CTRL2 0x11
  216. +#define AXP15060_PWR_OUT_CTRL3 0x12
  217. +#define AXP15060_DCDC1_V_CTRL 0x13
  218. +#define AXP15060_DCDC2_V_CTRL 0x14
  219. +#define AXP15060_DCDC3_V_CTRL 0x15
  220. +#define AXP15060_DCDC4_V_CTRL 0x16
  221. +#define AXP15060_DCDC5_V_CTRL 0x17
  222. +#define AXP15060_DCDC6_V_CTRL 0x18
  223. +#define AXP15060_ALDO1_V_CTRL 0x19
  224. +#define AXP15060_DCDC_MODE_CTRL1 0x1a
  225. +#define AXP15060_DCDC_MODE_CTRL2 0x1b
  226. +#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e
  227. +#define AXP15060_IRQ_PWROK_VOFF 0x1f
  228. +#define AXP15060_ALDO2_V_CTRL 0x20
  229. +#define AXP15060_ALDO3_V_CTRL 0x21
  230. +#define AXP15060_ALDO4_V_CTRL 0x22
  231. +#define AXP15060_ALDO5_V_CTRL 0x23
  232. +#define AXP15060_BLDO1_V_CTRL 0x24
  233. +#define AXP15060_BLDO2_V_CTRL 0x25
  234. +#define AXP15060_BLDO3_V_CTRL 0x26
  235. +#define AXP15060_BLDO4_V_CTRL 0x27
  236. +#define AXP15060_BLDO5_V_CTRL 0x28
  237. +#define AXP15060_CLDO1_V_CTRL 0x29
  238. +#define AXP15060_CLDO2_V_CTRL 0x2a
  239. +#define AXP15060_CLDO3_V_CTRL 0x2b
  240. +#define AXP15060_CLDO4_V_CTRL 0x2d
  241. +#define AXP15060_CPUSLDO_V_CTRL 0x2e
  242. +#define AXP15060_PWR_WAKEUP_CTRL 0x31
  243. +#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32
  244. +#define AXP15060_PEK_KEY 0x36
  245. +
  246. /* Interrupt */
  247. #define AXP152_IRQ1_EN 0x40
  248. #define AXP152_IRQ2_EN 0x41
  249. @@ -152,6 +186,11 @@ enum axp20x_variants {
  250. #define AXP20X_IRQ5_STATE 0x4c
  251. #define AXP20X_IRQ6_STATE 0x4d
  252. +#define AXP15060_IRQ1_EN 0x40
  253. +#define AXP15060_IRQ2_EN 0x41
  254. +#define AXP15060_IRQ1_STATE 0x48
  255. +#define AXP15060_IRQ2_STATE 0x49
  256. +
  257. /* ADC */
  258. #define AXP20X_ACIN_V_ADC_H 0x56
  259. #define AXP20X_ACIN_V_ADC_L 0x57
  260. @@ -222,6 +261,8 @@ enum axp20x_variants {
  261. #define AXP22X_GPIO_STATE 0x94
  262. #define AXP22X_GPIO_PULL_DOWN 0x95
  263. +#define AXP15060_CLDO4_GPIO2_MODESET 0x2c
  264. +
  265. /* Battery */
  266. #define AXP20X_CHRG_CC_31_24 0xb0
  267. #define AXP20X_CHRG_CC_23_16 0xb1
  268. @@ -419,6 +460,33 @@ enum {
  269. AXP813_REG_ID_MAX,
  270. };
  271. +enum {
  272. + AXP15060_DCDC1 = 0,
  273. + AXP15060_DCDC2,
  274. + AXP15060_DCDC3,
  275. + AXP15060_DCDC4,
  276. + AXP15060_DCDC5,
  277. + AXP15060_DCDC6,
  278. + AXP15060_ALDO1,
  279. + AXP15060_ALDO2,
  280. + AXP15060_ALDO3,
  281. + AXP15060_ALDO4,
  282. + AXP15060_ALDO5,
  283. + AXP15060_BLDO1,
  284. + AXP15060_BLDO2,
  285. + AXP15060_BLDO3,
  286. + AXP15060_BLDO4,
  287. + AXP15060_BLDO5,
  288. + AXP15060_CLDO1,
  289. + AXP15060_CLDO2,
  290. + AXP15060_CLDO3,
  291. + AXP15060_CLDO4,
  292. + AXP15060_CPUSLDO,
  293. + AXP15060_SW,
  294. + AXP15060_RTC_LDO,
  295. + AXP15060_REG_ID_MAX,
  296. +};
  297. +
  298. /* IRQs */
  299. enum {
  300. AXP152_IRQ_LDO0IN_CONNECT = 1,
  301. @@ -637,6 +705,23 @@ enum axp809_irqs {
  302. AXP809_IRQ_GPIO0_INPUT,
  303. };
  304. +enum axp15060_irqs {
  305. + AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1,
  306. + AXP15060_IRQ_DIE_TEMP_HIGH_LV2,
  307. + AXP15060_IRQ_DCDC1_V_LOW,
  308. + AXP15060_IRQ_DCDC2_V_LOW,
  309. + AXP15060_IRQ_DCDC3_V_LOW,
  310. + AXP15060_IRQ_DCDC4_V_LOW,
  311. + AXP15060_IRQ_DCDC5_V_LOW,
  312. + AXP15060_IRQ_DCDC6_V_LOW,
  313. + AXP15060_IRQ_PEK_LONG,
  314. + AXP15060_IRQ_PEK_SHORT,
  315. + AXP15060_IRQ_GPIO1_INPUT,
  316. + AXP15060_IRQ_PEK_FAL_EDGE,
  317. + AXP15060_IRQ_PEK_RIS_EDGE,
  318. + AXP15060_IRQ_GPIO2_INPUT,
  319. +};
  320. +
  321. struct axp20x_dev {
  322. struct device *dev;
  323. int irq;