axp20x.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. /*
  2. * MFD core driver for the X-Powers' Power Management ICs
  3. *
  4. * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
  5. * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
  6. * as well as configurable GPIOs.
  7. *
  8. * This file contains the interface independent core functions.
  9. *
  10. * Copyright (C) 2014 Carlo Caione
  11. *
  12. * Author: Carlo Caione <carlo@caione.org>
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License version 2 as
  16. * published by the Free Software Foundation.
  17. */
  18. #include <linux/err.h>
  19. #include <linux/delay.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/kernel.h>
  22. #include <linux/module.h>
  23. #include <linux/pm_runtime.h>
  24. #include <linux/regmap.h>
  25. #include <linux/regulator/consumer.h>
  26. #include <linux/mfd/axp20x.h>
  27. #include <linux/mfd/core.h>
  28. #include <linux/of_device.h>
  29. #include <linux/acpi.h>
  30. #define AXP20X_OFF 0x80
  31. static const char * const axp20x_model_names[] = {
  32. "AXP152",
  33. "AXP202",
  34. "AXP209",
  35. "AXP221",
  36. "AXP223",
  37. "AXP288",
  38. "AXP806",
  39. "AXP809",
  40. };
  41. static const struct regmap_range axp152_writeable_ranges[] = {
  42. regmap_reg_range(AXP152_LDO3456_DC1234_CTRL, AXP152_IRQ3_STATE),
  43. regmap_reg_range(AXP152_DCDC_MODE, AXP152_PWM1_DUTY_CYCLE),
  44. };
  45. static const struct regmap_range axp152_volatile_ranges[] = {
  46. regmap_reg_range(AXP152_PWR_OP_MODE, AXP152_PWR_OP_MODE),
  47. regmap_reg_range(AXP152_IRQ1_EN, AXP152_IRQ3_STATE),
  48. regmap_reg_range(AXP152_GPIO_INPUT, AXP152_GPIO_INPUT),
  49. };
  50. static const struct regmap_access_table axp152_writeable_table = {
  51. .yes_ranges = axp152_writeable_ranges,
  52. .n_yes_ranges = ARRAY_SIZE(axp152_writeable_ranges),
  53. };
  54. static const struct regmap_access_table axp152_volatile_table = {
  55. .yes_ranges = axp152_volatile_ranges,
  56. .n_yes_ranges = ARRAY_SIZE(axp152_volatile_ranges),
  57. };
  58. static const struct regmap_range axp20x_writeable_ranges[] = {
  59. regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
  60. regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
  61. regmap_reg_range(AXP20X_RDC_H, AXP20X_OCV(AXP20X_OCV_MAX)),
  62. };
  63. static const struct regmap_range axp20x_volatile_ranges[] = {
  64. regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_USB_OTG_STATUS),
  65. regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL2),
  66. regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
  67. regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
  68. regmap_reg_range(AXP20X_GPIO20_SS, AXP20X_GPIO3_CTRL),
  69. regmap_reg_range(AXP20X_FG_RES, AXP20X_RDC_L),
  70. };
  71. static const struct regmap_access_table axp20x_writeable_table = {
  72. .yes_ranges = axp20x_writeable_ranges,
  73. .n_yes_ranges = ARRAY_SIZE(axp20x_writeable_ranges),
  74. };
  75. static const struct regmap_access_table axp20x_volatile_table = {
  76. .yes_ranges = axp20x_volatile_ranges,
  77. .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
  78. };
  79. /* AXP22x ranges are shared with the AXP809, as they cover the same range */
  80. static const struct regmap_range axp22x_writeable_ranges[] = {
  81. regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
  82. regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
  83. };
  84. static const struct regmap_range axp22x_volatile_ranges[] = {
  85. regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
  86. regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
  87. regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
  88. regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
  89. };
  90. static const struct regmap_access_table axp22x_writeable_table = {
  91. .yes_ranges = axp22x_writeable_ranges,
  92. .n_yes_ranges = ARRAY_SIZE(axp22x_writeable_ranges),
  93. };
  94. static const struct regmap_access_table axp22x_volatile_table = {
  95. .yes_ranges = axp22x_volatile_ranges,
  96. .n_yes_ranges = ARRAY_SIZE(axp22x_volatile_ranges),
  97. };
  98. static const struct regmap_range axp288_writeable_ranges[] = {
  99. regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
  100. regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
  101. };
  102. static const struct regmap_range axp288_volatile_ranges[] = {
  103. regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
  104. };
  105. static const struct regmap_access_table axp288_writeable_table = {
  106. .yes_ranges = axp288_writeable_ranges,
  107. .n_yes_ranges = ARRAY_SIZE(axp288_writeable_ranges),
  108. };
  109. static const struct regmap_access_table axp288_volatile_table = {
  110. .yes_ranges = axp288_volatile_ranges,
  111. .n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges),
  112. };
  113. static const struct regmap_range axp806_writeable_ranges[] = {
  114. regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)),
  115. regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
  116. regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN),
  117. regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
  118. };
  119. static const struct regmap_range axp806_volatile_ranges[] = {
  120. regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
  121. };
  122. static const struct regmap_access_table axp806_writeable_table = {
  123. .yes_ranges = axp806_writeable_ranges,
  124. .n_yes_ranges = ARRAY_SIZE(axp806_writeable_ranges),
  125. };
  126. static const struct regmap_access_table axp806_volatile_table = {
  127. .yes_ranges = axp806_volatile_ranges,
  128. .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
  129. };
  130. static struct resource axp152_pek_resources[] = {
  131. DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
  132. DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
  133. };
  134. static struct resource axp20x_ac_power_supply_resources[] = {
  135. DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
  136. DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
  137. DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
  138. };
  139. static struct resource axp20x_pek_resources[] = {
  140. {
  141. .name = "PEK_DBR",
  142. .start = AXP20X_IRQ_PEK_RIS_EDGE,
  143. .end = AXP20X_IRQ_PEK_RIS_EDGE,
  144. .flags = IORESOURCE_IRQ,
  145. }, {
  146. .name = "PEK_DBF",
  147. .start = AXP20X_IRQ_PEK_FAL_EDGE,
  148. .end = AXP20X_IRQ_PEK_FAL_EDGE,
  149. .flags = IORESOURCE_IRQ,
  150. },
  151. };
  152. static struct resource axp20x_usb_power_supply_resources[] = {
  153. DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
  154. DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
  155. DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_VALID, "VBUS_VALID"),
  156. DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
  157. };
  158. static struct resource axp22x_usb_power_supply_resources[] = {
  159. DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
  160. DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
  161. };
  162. static struct resource axp22x_pek_resources[] = {
  163. {
  164. .name = "PEK_DBR",
  165. .start = AXP22X_IRQ_PEK_RIS_EDGE,
  166. .end = AXP22X_IRQ_PEK_RIS_EDGE,
  167. .flags = IORESOURCE_IRQ,
  168. }, {
  169. .name = "PEK_DBF",
  170. .start = AXP22X_IRQ_PEK_FAL_EDGE,
  171. .end = AXP22X_IRQ_PEK_FAL_EDGE,
  172. .flags = IORESOURCE_IRQ,
  173. },
  174. };
  175. static struct resource axp288_power_button_resources[] = {
  176. {
  177. .name = "PEK_DBR",
  178. .start = AXP288_IRQ_POKP,
  179. .end = AXP288_IRQ_POKP,
  180. .flags = IORESOURCE_IRQ,
  181. },
  182. {
  183. .name = "PEK_DBF",
  184. .start = AXP288_IRQ_POKN,
  185. .end = AXP288_IRQ_POKN,
  186. .flags = IORESOURCE_IRQ,
  187. },
  188. };
  189. static struct resource axp288_fuel_gauge_resources[] = {
  190. {
  191. .start = AXP288_IRQ_QWBTU,
  192. .end = AXP288_IRQ_QWBTU,
  193. .flags = IORESOURCE_IRQ,
  194. },
  195. {
  196. .start = AXP288_IRQ_WBTU,
  197. .end = AXP288_IRQ_WBTU,
  198. .flags = IORESOURCE_IRQ,
  199. },
  200. {
  201. .start = AXP288_IRQ_QWBTO,
  202. .end = AXP288_IRQ_QWBTO,
  203. .flags = IORESOURCE_IRQ,
  204. },
  205. {
  206. .start = AXP288_IRQ_WBTO,
  207. .end = AXP288_IRQ_WBTO,
  208. .flags = IORESOURCE_IRQ,
  209. },
  210. {
  211. .start = AXP288_IRQ_WL2,
  212. .end = AXP288_IRQ_WL2,
  213. .flags = IORESOURCE_IRQ,
  214. },
  215. {
  216. .start = AXP288_IRQ_WL1,
  217. .end = AXP288_IRQ_WL1,
  218. .flags = IORESOURCE_IRQ,
  219. },
  220. };
  221. static struct resource axp809_pek_resources[] = {
  222. {
  223. .name = "PEK_DBR",
  224. .start = AXP809_IRQ_PEK_RIS_EDGE,
  225. .end = AXP809_IRQ_PEK_RIS_EDGE,
  226. .flags = IORESOURCE_IRQ,
  227. }, {
  228. .name = "PEK_DBF",
  229. .start = AXP809_IRQ_PEK_FAL_EDGE,
  230. .end = AXP809_IRQ_PEK_FAL_EDGE,
  231. .flags = IORESOURCE_IRQ,
  232. },
  233. };
  234. static const struct regmap_config axp152_regmap_config = {
  235. .reg_bits = 8,
  236. .val_bits = 8,
  237. .wr_table = &axp152_writeable_table,
  238. .volatile_table = &axp152_volatile_table,
  239. .max_register = AXP152_PWM1_DUTY_CYCLE,
  240. .cache_type = REGCACHE_RBTREE,
  241. };
  242. static const struct regmap_config axp20x_regmap_config = {
  243. .reg_bits = 8,
  244. .val_bits = 8,
  245. .wr_table = &axp20x_writeable_table,
  246. .volatile_table = &axp20x_volatile_table,
  247. .max_register = AXP20X_OCV(AXP20X_OCV_MAX),
  248. .cache_type = REGCACHE_RBTREE,
  249. };
  250. static const struct regmap_config axp22x_regmap_config = {
  251. .reg_bits = 8,
  252. .val_bits = 8,
  253. .wr_table = &axp22x_writeable_table,
  254. .volatile_table = &axp22x_volatile_table,
  255. .max_register = AXP22X_BATLOW_THRES1,
  256. .cache_type = REGCACHE_RBTREE,
  257. };
  258. static const struct regmap_config axp288_regmap_config = {
  259. .reg_bits = 8,
  260. .val_bits = 8,
  261. .wr_table = &axp288_writeable_table,
  262. .volatile_table = &axp288_volatile_table,
  263. .max_register = AXP288_FG_TUNE5,
  264. .cache_type = REGCACHE_RBTREE,
  265. };
  266. static const struct regmap_config axp806_regmap_config = {
  267. .reg_bits = 8,
  268. .val_bits = 8,
  269. .wr_table = &axp806_writeable_table,
  270. .volatile_table = &axp806_volatile_table,
  271. .max_register = AXP806_VREF_TEMP_WARN_L,
  272. .cache_type = REGCACHE_RBTREE,
  273. };
  274. #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
  275. [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
  276. static const struct regmap_irq axp152_regmap_irqs[] = {
  277. INIT_REGMAP_IRQ(AXP152, LDO0IN_CONNECT, 0, 6),
  278. INIT_REGMAP_IRQ(AXP152, LDO0IN_REMOVAL, 0, 5),
  279. INIT_REGMAP_IRQ(AXP152, ALDO0IN_CONNECT, 0, 3),
  280. INIT_REGMAP_IRQ(AXP152, ALDO0IN_REMOVAL, 0, 2),
  281. INIT_REGMAP_IRQ(AXP152, DCDC1_V_LOW, 1, 5),
  282. INIT_REGMAP_IRQ(AXP152, DCDC2_V_LOW, 1, 4),
  283. INIT_REGMAP_IRQ(AXP152, DCDC3_V_LOW, 1, 3),
  284. INIT_REGMAP_IRQ(AXP152, DCDC4_V_LOW, 1, 2),
  285. INIT_REGMAP_IRQ(AXP152, PEK_SHORT, 1, 1),
  286. INIT_REGMAP_IRQ(AXP152, PEK_LONG, 1, 0),
  287. INIT_REGMAP_IRQ(AXP152, TIMER, 2, 7),
  288. INIT_REGMAP_IRQ(AXP152, PEK_RIS_EDGE, 2, 6),
  289. INIT_REGMAP_IRQ(AXP152, PEK_FAL_EDGE, 2, 5),
  290. INIT_REGMAP_IRQ(AXP152, GPIO3_INPUT, 2, 3),
  291. INIT_REGMAP_IRQ(AXP152, GPIO2_INPUT, 2, 2),
  292. INIT_REGMAP_IRQ(AXP152, GPIO1_INPUT, 2, 1),
  293. INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0),
  294. };
  295. static const struct regmap_irq axp20x_regmap_irqs[] = {
  296. INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7),
  297. INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6),
  298. INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL, 0, 5),
  299. INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V, 0, 4),
  300. INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN, 0, 3),
  301. INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL, 0, 2),
  302. INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW, 0, 1),
  303. INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN, 1, 7),
  304. INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL, 1, 6),
  305. INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE, 1, 5),
  306. INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE, 1, 4),
  307. INIT_REGMAP_IRQ(AXP20X, CHARG, 1, 3),
  308. INIT_REGMAP_IRQ(AXP20X, CHARG_DONE, 1, 2),
  309. INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH, 1, 1),
  310. INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW, 1, 0),
  311. INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH, 2, 7),
  312. INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW, 2, 6),
  313. INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG, 2, 5),
  314. INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG, 2, 4),
  315. INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG, 2, 3),
  316. INIT_REGMAP_IRQ(AXP20X, PEK_SHORT, 2, 1),
  317. INIT_REGMAP_IRQ(AXP20X, PEK_LONG, 2, 0),
  318. INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON, 3, 7),
  319. INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF, 3, 6),
  320. INIT_REGMAP_IRQ(AXP20X, VBUS_VALID, 3, 5),
  321. INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID, 3, 4),
  322. INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID, 3, 3),
  323. INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END, 3, 2),
  324. INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1, 3, 1),
  325. INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2, 3, 0),
  326. INIT_REGMAP_IRQ(AXP20X, TIMER, 4, 7),
  327. INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE, 4, 6),
  328. INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE, 4, 5),
  329. INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT, 4, 3),
  330. INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT, 4, 2),
  331. INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT, 4, 1),
  332. INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT, 4, 0),
  333. };
  334. static const struct regmap_irq axp22x_regmap_irqs[] = {
  335. INIT_REGMAP_IRQ(AXP22X, ACIN_OVER_V, 0, 7),
  336. INIT_REGMAP_IRQ(AXP22X, ACIN_PLUGIN, 0, 6),
  337. INIT_REGMAP_IRQ(AXP22X, ACIN_REMOVAL, 0, 5),
  338. INIT_REGMAP_IRQ(AXP22X, VBUS_OVER_V, 0, 4),
  339. INIT_REGMAP_IRQ(AXP22X, VBUS_PLUGIN, 0, 3),
  340. INIT_REGMAP_IRQ(AXP22X, VBUS_REMOVAL, 0, 2),
  341. INIT_REGMAP_IRQ(AXP22X, VBUS_V_LOW, 0, 1),
  342. INIT_REGMAP_IRQ(AXP22X, BATT_PLUGIN, 1, 7),
  343. INIT_REGMAP_IRQ(AXP22X, BATT_REMOVAL, 1, 6),
  344. INIT_REGMAP_IRQ(AXP22X, BATT_ENT_ACT_MODE, 1, 5),
  345. INIT_REGMAP_IRQ(AXP22X, BATT_EXIT_ACT_MODE, 1, 4),
  346. INIT_REGMAP_IRQ(AXP22X, CHARG, 1, 3),
  347. INIT_REGMAP_IRQ(AXP22X, CHARG_DONE, 1, 2),
  348. INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_HIGH, 1, 1),
  349. INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_LOW, 1, 0),
  350. INIT_REGMAP_IRQ(AXP22X, DIE_TEMP_HIGH, 2, 7),
  351. INIT_REGMAP_IRQ(AXP22X, PEK_SHORT, 2, 1),
  352. INIT_REGMAP_IRQ(AXP22X, PEK_LONG, 2, 0),
  353. INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL1, 3, 1),
  354. INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL2, 3, 0),
  355. INIT_REGMAP_IRQ(AXP22X, TIMER, 4, 7),
  356. INIT_REGMAP_IRQ(AXP22X, PEK_RIS_EDGE, 4, 6),
  357. INIT_REGMAP_IRQ(AXP22X, PEK_FAL_EDGE, 4, 5),
  358. INIT_REGMAP_IRQ(AXP22X, GPIO1_INPUT, 4, 1),
  359. INIT_REGMAP_IRQ(AXP22X, GPIO0_INPUT, 4, 0),
  360. };
  361. /* some IRQs are compatible with axp20x models */
  362. static const struct regmap_irq axp288_regmap_irqs[] = {
  363. INIT_REGMAP_IRQ(AXP288, VBUS_FALL, 0, 2),
  364. INIT_REGMAP_IRQ(AXP288, VBUS_RISE, 0, 3),
  365. INIT_REGMAP_IRQ(AXP288, OV, 0, 4),
  366. INIT_REGMAP_IRQ(AXP288, DONE, 1, 2),
  367. INIT_REGMAP_IRQ(AXP288, CHARGING, 1, 3),
  368. INIT_REGMAP_IRQ(AXP288, SAFE_QUIT, 1, 4),
  369. INIT_REGMAP_IRQ(AXP288, SAFE_ENTER, 1, 5),
  370. INIT_REGMAP_IRQ(AXP288, ABSENT, 1, 6),
  371. INIT_REGMAP_IRQ(AXP288, APPEND, 1, 7),
  372. INIT_REGMAP_IRQ(AXP288, QWBTU, 2, 0),
  373. INIT_REGMAP_IRQ(AXP288, WBTU, 2, 1),
  374. INIT_REGMAP_IRQ(AXP288, QWBTO, 2, 2),
  375. INIT_REGMAP_IRQ(AXP288, WBTO, 2, 3),
  376. INIT_REGMAP_IRQ(AXP288, QCBTU, 2, 4),
  377. INIT_REGMAP_IRQ(AXP288, CBTU, 2, 5),
  378. INIT_REGMAP_IRQ(AXP288, QCBTO, 2, 6),
  379. INIT_REGMAP_IRQ(AXP288, CBTO, 2, 7),
  380. INIT_REGMAP_IRQ(AXP288, WL2, 3, 0),
  381. INIT_REGMAP_IRQ(AXP288, WL1, 3, 1),
  382. INIT_REGMAP_IRQ(AXP288, GPADC, 3, 2),
  383. INIT_REGMAP_IRQ(AXP288, OT, 3, 7),
  384. INIT_REGMAP_IRQ(AXP288, GPIO0, 4, 0),
  385. INIT_REGMAP_IRQ(AXP288, GPIO1, 4, 1),
  386. INIT_REGMAP_IRQ(AXP288, POKO, 4, 2),
  387. INIT_REGMAP_IRQ(AXP288, POKL, 4, 3),
  388. INIT_REGMAP_IRQ(AXP288, POKS, 4, 4),
  389. INIT_REGMAP_IRQ(AXP288, POKN, 4, 5),
  390. INIT_REGMAP_IRQ(AXP288, POKP, 4, 6),
  391. INIT_REGMAP_IRQ(AXP288, TIMER, 4, 7),
  392. INIT_REGMAP_IRQ(AXP288, MV_CHNG, 5, 0),
  393. INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1),
  394. };
  395. static const struct regmap_irq axp806_regmap_irqs[] = {
  396. INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV1, 0, 0),
  397. INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV2, 0, 1),
  398. INIT_REGMAP_IRQ(AXP806, DCDCA_V_LOW, 0, 3),
  399. INIT_REGMAP_IRQ(AXP806, DCDCB_V_LOW, 0, 4),
  400. INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW, 0, 5),
  401. INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW, 0, 6),
  402. INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW, 0, 7),
  403. INIT_REGMAP_IRQ(AXP806, PWROK_LONG, 1, 0),
  404. INIT_REGMAP_IRQ(AXP806, PWROK_SHORT, 1, 1),
  405. INIT_REGMAP_IRQ(AXP806, WAKEUP, 1, 4),
  406. INIT_REGMAP_IRQ(AXP806, PWROK_FALL, 1, 5),
  407. INIT_REGMAP_IRQ(AXP806, PWROK_RISE, 1, 6),
  408. };
  409. static const struct regmap_irq axp809_regmap_irqs[] = {
  410. INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7),
  411. INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6),
  412. INIT_REGMAP_IRQ(AXP809, ACIN_REMOVAL, 0, 5),
  413. INIT_REGMAP_IRQ(AXP809, VBUS_OVER_V, 0, 4),
  414. INIT_REGMAP_IRQ(AXP809, VBUS_PLUGIN, 0, 3),
  415. INIT_REGMAP_IRQ(AXP809, VBUS_REMOVAL, 0, 2),
  416. INIT_REGMAP_IRQ(AXP809, VBUS_V_LOW, 0, 1),
  417. INIT_REGMAP_IRQ(AXP809, BATT_PLUGIN, 1, 7),
  418. INIT_REGMAP_IRQ(AXP809, BATT_REMOVAL, 1, 6),
  419. INIT_REGMAP_IRQ(AXP809, BATT_ENT_ACT_MODE, 1, 5),
  420. INIT_REGMAP_IRQ(AXP809, BATT_EXIT_ACT_MODE, 1, 4),
  421. INIT_REGMAP_IRQ(AXP809, CHARG, 1, 3),
  422. INIT_REGMAP_IRQ(AXP809, CHARG_DONE, 1, 2),
  423. INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH, 2, 7),
  424. INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH_END, 2, 6),
  425. INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW, 2, 5),
  426. INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW_END, 2, 4),
  427. INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH, 2, 3),
  428. INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH_END, 2, 2),
  429. INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW, 2, 1),
  430. INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW_END, 2, 0),
  431. INIT_REGMAP_IRQ(AXP809, DIE_TEMP_HIGH, 3, 7),
  432. INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL1, 3, 1),
  433. INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL2, 3, 0),
  434. INIT_REGMAP_IRQ(AXP809, TIMER, 4, 7),
  435. INIT_REGMAP_IRQ(AXP809, PEK_RIS_EDGE, 4, 6),
  436. INIT_REGMAP_IRQ(AXP809, PEK_FAL_EDGE, 4, 5),
  437. INIT_REGMAP_IRQ(AXP809, PEK_SHORT, 4, 4),
  438. INIT_REGMAP_IRQ(AXP809, PEK_LONG, 4, 3),
  439. INIT_REGMAP_IRQ(AXP809, PEK_OVER_OFF, 4, 2),
  440. INIT_REGMAP_IRQ(AXP809, GPIO1_INPUT, 4, 1),
  441. INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0),
  442. };
  443. static const struct regmap_irq_chip axp152_regmap_irq_chip = {
  444. .name = "axp152_irq_chip",
  445. .status_base = AXP152_IRQ1_STATE,
  446. .ack_base = AXP152_IRQ1_STATE,
  447. .mask_base = AXP152_IRQ1_EN,
  448. .mask_invert = true,
  449. .init_ack_masked = true,
  450. .irqs = axp152_regmap_irqs,
  451. .num_irqs = ARRAY_SIZE(axp152_regmap_irqs),
  452. .num_regs = 3,
  453. };
  454. static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
  455. .name = "axp20x_irq_chip",
  456. .status_base = AXP20X_IRQ1_STATE,
  457. .ack_base = AXP20X_IRQ1_STATE,
  458. .mask_base = AXP20X_IRQ1_EN,
  459. .mask_invert = true,
  460. .init_ack_masked = true,
  461. .irqs = axp20x_regmap_irqs,
  462. .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs),
  463. .num_regs = 5,
  464. };
  465. static const struct regmap_irq_chip axp22x_regmap_irq_chip = {
  466. .name = "axp22x_irq_chip",
  467. .status_base = AXP20X_IRQ1_STATE,
  468. .ack_base = AXP20X_IRQ1_STATE,
  469. .mask_base = AXP20X_IRQ1_EN,
  470. .mask_invert = true,
  471. .init_ack_masked = true,
  472. .irqs = axp22x_regmap_irqs,
  473. .num_irqs = ARRAY_SIZE(axp22x_regmap_irqs),
  474. .num_regs = 5,
  475. };
  476. static const struct regmap_irq_chip axp288_regmap_irq_chip = {
  477. .name = "axp288_irq_chip",
  478. .status_base = AXP20X_IRQ1_STATE,
  479. .ack_base = AXP20X_IRQ1_STATE,
  480. .mask_base = AXP20X_IRQ1_EN,
  481. .mask_invert = true,
  482. .init_ack_masked = true,
  483. .irqs = axp288_regmap_irqs,
  484. .num_irqs = ARRAY_SIZE(axp288_regmap_irqs),
  485. .num_regs = 6,
  486. };
  487. static const struct regmap_irq_chip axp806_regmap_irq_chip = {
  488. .name = "axp806",
  489. .status_base = AXP20X_IRQ1_STATE,
  490. .ack_base = AXP20X_IRQ1_STATE,
  491. .mask_base = AXP20X_IRQ1_EN,
  492. .mask_invert = true,
  493. .init_ack_masked = true,
  494. .irqs = axp806_regmap_irqs,
  495. .num_irqs = ARRAY_SIZE(axp806_regmap_irqs),
  496. .num_regs = 2,
  497. };
  498. static const struct regmap_irq_chip axp809_regmap_irq_chip = {
  499. .name = "axp809",
  500. .status_base = AXP20X_IRQ1_STATE,
  501. .ack_base = AXP20X_IRQ1_STATE,
  502. .mask_base = AXP20X_IRQ1_EN,
  503. .mask_invert = true,
  504. .init_ack_masked = true,
  505. .irqs = axp809_regmap_irqs,
  506. .num_irqs = ARRAY_SIZE(axp809_regmap_irqs),
  507. .num_regs = 5,
  508. };
  509. static struct mfd_cell axp20x_cells[] = {
  510. {
  511. .name = "axp20x-gpio",
  512. .of_compatible = "x-powers,axp209-gpio",
  513. }, {
  514. .name = "axp20x-pek",
  515. .num_resources = ARRAY_SIZE(axp20x_pek_resources),
  516. .resources = axp20x_pek_resources,
  517. }, {
  518. .name = "axp20x-regulator",
  519. }, {
  520. .name = "axp20x-ac-power-supply",
  521. .of_compatible = "x-powers,axp202-ac-power-supply",
  522. .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources),
  523. .resources = axp20x_ac_power_supply_resources,
  524. }, {
  525. .name = "axp20x-usb-power-supply",
  526. .of_compatible = "x-powers,axp202-usb-power-supply",
  527. .num_resources = ARRAY_SIZE(axp20x_usb_power_supply_resources),
  528. .resources = axp20x_usb_power_supply_resources,
  529. },
  530. };
  531. static struct mfd_cell axp22x_cells[] = {
  532. {
  533. .name = "axp20x-pek",
  534. .num_resources = ARRAY_SIZE(axp22x_pek_resources),
  535. .resources = axp22x_pek_resources,
  536. }, {
  537. .name = "axp20x-regulator",
  538. }, {
  539. .name = "axp20x-usb-power-supply",
  540. .of_compatible = "x-powers,axp221-usb-power-supply",
  541. .num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),
  542. .resources = axp22x_usb_power_supply_resources,
  543. },
  544. };
  545. static struct mfd_cell axp152_cells[] = {
  546. {
  547. .name = "axp20x-pek",
  548. .num_resources = ARRAY_SIZE(axp152_pek_resources),
  549. .resources = axp152_pek_resources,
  550. },
  551. };
  552. static struct resource axp288_adc_resources[] = {
  553. {
  554. .name = "GPADC",
  555. .start = AXP288_IRQ_GPADC,
  556. .end = AXP288_IRQ_GPADC,
  557. .flags = IORESOURCE_IRQ,
  558. },
  559. };
  560. static struct resource axp288_extcon_resources[] = {
  561. {
  562. .start = AXP288_IRQ_VBUS_FALL,
  563. .end = AXP288_IRQ_VBUS_FALL,
  564. .flags = IORESOURCE_IRQ,
  565. },
  566. {
  567. .start = AXP288_IRQ_VBUS_RISE,
  568. .end = AXP288_IRQ_VBUS_RISE,
  569. .flags = IORESOURCE_IRQ,
  570. },
  571. {
  572. .start = AXP288_IRQ_MV_CHNG,
  573. .end = AXP288_IRQ_MV_CHNG,
  574. .flags = IORESOURCE_IRQ,
  575. },
  576. {
  577. .start = AXP288_IRQ_BC_USB_CHNG,
  578. .end = AXP288_IRQ_BC_USB_CHNG,
  579. .flags = IORESOURCE_IRQ,
  580. },
  581. };
  582. static struct resource axp288_charger_resources[] = {
  583. {
  584. .start = AXP288_IRQ_OV,
  585. .end = AXP288_IRQ_OV,
  586. .flags = IORESOURCE_IRQ,
  587. },
  588. {
  589. .start = AXP288_IRQ_DONE,
  590. .end = AXP288_IRQ_DONE,
  591. .flags = IORESOURCE_IRQ,
  592. },
  593. {
  594. .start = AXP288_IRQ_CHARGING,
  595. .end = AXP288_IRQ_CHARGING,
  596. .flags = IORESOURCE_IRQ,
  597. },
  598. {
  599. .start = AXP288_IRQ_SAFE_QUIT,
  600. .end = AXP288_IRQ_SAFE_QUIT,
  601. .flags = IORESOURCE_IRQ,
  602. },
  603. {
  604. .start = AXP288_IRQ_SAFE_ENTER,
  605. .end = AXP288_IRQ_SAFE_ENTER,
  606. .flags = IORESOURCE_IRQ,
  607. },
  608. {
  609. .start = AXP288_IRQ_QCBTU,
  610. .end = AXP288_IRQ_QCBTU,
  611. .flags = IORESOURCE_IRQ,
  612. },
  613. {
  614. .start = AXP288_IRQ_CBTU,
  615. .end = AXP288_IRQ_CBTU,
  616. .flags = IORESOURCE_IRQ,
  617. },
  618. {
  619. .start = AXP288_IRQ_QCBTO,
  620. .end = AXP288_IRQ_QCBTO,
  621. .flags = IORESOURCE_IRQ,
  622. },
  623. {
  624. .start = AXP288_IRQ_CBTO,
  625. .end = AXP288_IRQ_CBTO,
  626. .flags = IORESOURCE_IRQ,
  627. },
  628. };
  629. static struct mfd_cell axp288_cells[] = {
  630. {
  631. .name = "axp288_adc",
  632. .num_resources = ARRAY_SIZE(axp288_adc_resources),
  633. .resources = axp288_adc_resources,
  634. },
  635. {
  636. .name = "axp288_extcon",
  637. .num_resources = ARRAY_SIZE(axp288_extcon_resources),
  638. .resources = axp288_extcon_resources,
  639. },
  640. {
  641. .name = "axp288_charger",
  642. .num_resources = ARRAY_SIZE(axp288_charger_resources),
  643. .resources = axp288_charger_resources,
  644. },
  645. {
  646. .name = "axp288_fuel_gauge",
  647. .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
  648. .resources = axp288_fuel_gauge_resources,
  649. },
  650. {
  651. .name = "axp20x-pek",
  652. .num_resources = ARRAY_SIZE(axp288_power_button_resources),
  653. .resources = axp288_power_button_resources,
  654. },
  655. {
  656. .name = "axp288_pmic_acpi",
  657. },
  658. };
  659. static struct mfd_cell axp806_cells[] = {
  660. {
  661. .id = 2,
  662. .name = "axp20x-regulator",
  663. },
  664. };
  665. static struct mfd_cell axp809_cells[] = {
  666. {
  667. .name = "axp20x-pek",
  668. .num_resources = ARRAY_SIZE(axp809_pek_resources),
  669. .resources = axp809_pek_resources,
  670. }, {
  671. .id = 1,
  672. .name = "axp20x-regulator",
  673. },
  674. };
  675. static struct axp20x_dev *axp20x_pm_power_off;
  676. static void axp20x_power_off(void)
  677. {
  678. if (axp20x_pm_power_off->variant == AXP288_ID)
  679. return;
  680. regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
  681. AXP20X_OFF);
  682. /* Give capacitors etc. time to drain to avoid kernel panic msg. */
  683. msleep(500);
  684. }
  685. int axp20x_match_device(struct axp20x_dev *axp20x)
  686. {
  687. struct device *dev = axp20x->dev;
  688. const struct acpi_device_id *acpi_id;
  689. const struct of_device_id *of_id;
  690. if (dev->of_node) {
  691. of_id = of_match_device(dev->driver->of_match_table, dev);
  692. if (!of_id) {
  693. dev_err(dev, "Unable to match OF ID\n");
  694. return -ENODEV;
  695. }
  696. axp20x->variant = (long)of_id->data;
  697. } else {
  698. acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
  699. if (!acpi_id || !acpi_id->driver_data) {
  700. dev_err(dev, "Unable to match ACPI ID and data\n");
  701. return -ENODEV;
  702. }
  703. axp20x->variant = (long)acpi_id->driver_data;
  704. }
  705. switch (axp20x->variant) {
  706. case AXP152_ID:
  707. axp20x->nr_cells = ARRAY_SIZE(axp152_cells);
  708. axp20x->cells = axp152_cells;
  709. axp20x->regmap_cfg = &axp152_regmap_config;
  710. axp20x->regmap_irq_chip = &axp152_regmap_irq_chip;
  711. break;
  712. case AXP202_ID:
  713. case AXP209_ID:
  714. axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
  715. axp20x->cells = axp20x_cells;
  716. axp20x->regmap_cfg = &axp20x_regmap_config;
  717. axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
  718. break;
  719. case AXP221_ID:
  720. case AXP223_ID:
  721. axp20x->nr_cells = ARRAY_SIZE(axp22x_cells);
  722. axp20x->cells = axp22x_cells;
  723. axp20x->regmap_cfg = &axp22x_regmap_config;
  724. axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip;
  725. break;
  726. case AXP288_ID:
  727. axp20x->cells = axp288_cells;
  728. axp20x->nr_cells = ARRAY_SIZE(axp288_cells);
  729. axp20x->regmap_cfg = &axp288_regmap_config;
  730. axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
  731. break;
  732. case AXP806_ID:
  733. axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
  734. axp20x->cells = axp806_cells;
  735. axp20x->regmap_cfg = &axp806_regmap_config;
  736. axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
  737. break;
  738. case AXP809_ID:
  739. axp20x->nr_cells = ARRAY_SIZE(axp809_cells);
  740. axp20x->cells = axp809_cells;
  741. axp20x->regmap_cfg = &axp22x_regmap_config;
  742. axp20x->regmap_irq_chip = &axp809_regmap_irq_chip;
  743. break;
  744. default:
  745. dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
  746. return -EINVAL;
  747. }
  748. dev_info(dev, "AXP20x variant %s found\n",
  749. axp20x_model_names[axp20x->variant]);
  750. return 0;
  751. }
  752. EXPORT_SYMBOL(axp20x_match_device);
  753. int axp20x_device_probe(struct axp20x_dev *axp20x)
  754. {
  755. int ret;
  756. ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
  757. IRQF_ONESHOT | IRQF_SHARED, -1,
  758. axp20x->regmap_irq_chip,
  759. &axp20x->regmap_irqc);
  760. if (ret) {
  761. dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret);
  762. return ret;
  763. }
  764. ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
  765. axp20x->nr_cells, NULL, 0, NULL);
  766. if (ret) {
  767. dev_err(axp20x->dev, "failed to add MFD devices: %d\n", ret);
  768. regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
  769. return ret;
  770. }
  771. if (!pm_power_off) {
  772. axp20x_pm_power_off = axp20x;
  773. pm_power_off = axp20x_power_off;
  774. }
  775. dev_info(axp20x->dev, "AXP20X driver loaded\n");
  776. return 0;
  777. }
  778. EXPORT_SYMBOL(axp20x_device_probe);
  779. int axp20x_device_remove(struct axp20x_dev *axp20x)
  780. {
  781. if (axp20x == axp20x_pm_power_off) {
  782. axp20x_pm_power_off = NULL;
  783. pm_power_off = NULL;
  784. }
  785. mfd_remove_devices(axp20x->dev);
  786. regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
  787. return 0;
  788. }
  789. EXPORT_SYMBOL(axp20x_device_remove);
  790. MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X");
  791. MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
  792. MODULE_LICENSE("GPL");