pf8x00-regulator.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2017 NXP
  4. * Copyright (C) 2019 Boundary Devices
  5. * Copyright (C) 2020 Amarula Solutions(India)
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/err.h>
  9. #include <linux/gpio/consumer.h>
  10. #include <linux/i2c.h>
  11. #include <linux/module.h>
  12. #include <linux/regmap.h>
  13. #include <linux/regulator/driver.h>
  14. #include <linux/regulator/machine.h>
  15. /* registers */
  16. #define PF8X00_DEVICEID 0x00
  17. #define PF8X00_REVID 0x01
  18. #define PF8X00_EMREV 0x02
  19. #define PF8X00_PROGID 0x03
  20. #define PF8X00_IMS_INT 0x04
  21. #define PF8X00_IMS_THERM 0x07
  22. #define PF8X00_SW_MODE_INT 0x0a
  23. #define PF8X00_SW_MODE_MASK 0x0b
  24. #define PF8X00_IMS_SW_ILIM 0x12
  25. #define PF8X00_IMS_LDO_ILIM 0x15
  26. #define PF8X00_IMS_SW_UV 0x18
  27. #define PF8X00_IMS_SW_OV 0x1b
  28. #define PF8X00_IMS_LDO_UV 0x1e
  29. #define PF8X00_IMS_LDO_OV 0x21
  30. #define PF8X00_IMS_PWRON 0x24
  31. #define PF8X00_SYS_INT 0x27
  32. #define PF8X00_HARD_FAULT 0x29
  33. #define PF8X00_FSOB_FLAGS 0x2a
  34. #define PF8X00_FSOB_SELECT 0x2b
  35. #define PF8X00_ABIST_OV1 0x2c
  36. #define PF8X00_ABIST_OV2 0x2d
  37. #define PF8X00_ABIST_UV1 0x2e
  38. #define PF8X00_ABIST_UV2 0x2f
  39. #define PF8X00_TEST_FLAGS 0x30
  40. #define PF8X00_ABIST_RUN 0x31
  41. #define PF8X00_RANDOM_GEN 0x33
  42. #define PF8X00_RANDOM_CHK 0x34
  43. #define PF8X00_VMONEN1 0x35
  44. #define PF8X00_VMONEN2 0x36
  45. #define PF8X00_CTRL1 0x37
  46. #define PF8X00_CTRL2 0x38
  47. #define PF8X00_CTRL3 0x39
  48. #define PF8X00_PWRUP_CTRL 0x3a
  49. #define PF8X00_RESETBMCU 0x3c
  50. #define PF8X00_PGOOD 0x3d
  51. #define PF8X00_PWRDN_DLY1 0x3e
  52. #define PF8X00_PWRDN_DLY2 0x3f
  53. #define PF8X00_FREQ_CTRL 0x40
  54. #define PF8X00_COINCELL_CTRL 0x41
  55. #define PF8X00_PWRON 0x42
  56. #define PF8X00_WD_CONFIG 0x43
  57. #define PF8X00_WD_CLEAR 0x44
  58. #define PF8X00_WD_EXPIRE 0x45
  59. #define PF8X00_WD_COUNTER 0x46
  60. #define PF8X00_FAULT_COUNTER 0x47
  61. #define PF8X00_FSAFE_COUNTER 0x48
  62. #define PF8X00_FAULT_TIMER 0x49
  63. #define PF8X00_AMUX 0x4a
  64. #define PF8X00_SW1_CONFIG1 0x4d
  65. #define PF8X00_LDO1_CONFIG1 0x85
  66. #define PF8X00_VSNVS_CONFIG1 0x9d
  67. #define PF8X00_PAGE_SELECT 0x9f
  68. /* regulators */
  69. enum pf8x00_regulators {
  70. PF8X00_LDO1,
  71. PF8X00_LDO2,
  72. PF8X00_LDO3,
  73. PF8X00_LDO4,
  74. PF8X00_BUCK1,
  75. PF8X00_BUCK2,
  76. PF8X00_BUCK3,
  77. PF8X00_BUCK4,
  78. PF8X00_BUCK5,
  79. PF8X00_BUCK6,
  80. PF8X00_BUCK7,
  81. PF8X00_VSNVS,
  82. PF8X00_MAX_REGULATORS,
  83. };
  84. enum pf8x00_buck_states {
  85. SW_CONFIG1,
  86. SW_CONFIG2,
  87. SW_PWRUP,
  88. SW_MODE1,
  89. SW_RUN_VOLT,
  90. SW_STBY_VOLT,
  91. };
  92. #define PF8X00_SW_BASE(i) (8 * (i - PF8X00_BUCK1) + PF8X00_SW1_CONFIG1)
  93. enum pf8x00_ldo_states {
  94. LDO_CONFIG1,
  95. LDO_CONFIG2,
  96. LDO_PWRUP,
  97. LDO_RUN_VOLT,
  98. LDO_STBY_VOLT,
  99. };
  100. #define PF8X00_LDO_BASE(i) (6 * (i - PF8X00_LDO1) + PF8X00_LDO1_CONFIG1)
  101. enum swxilim_bits {
  102. SWXILIM_2100_MA,
  103. SWXILIM_2600_MA,
  104. SWXILIM_3000_MA,
  105. SWXILIM_4500_MA,
  106. };
  107. #define PF8X00_SWXILIM_SHIFT 3
  108. #define PF8X00_SWXILIM_MASK GENMASK(4, 3)
  109. #define PF8X00_SWXPHASE_MASK GENMASK(2, 0)
  110. #define PF8X00_SWXPHASE_SHIFT 7
  111. enum pf8x00_devid {
  112. PF8100 = 0x0,
  113. PF8121A = BIT(1),
  114. PF8200 = BIT(3),
  115. };
  116. #define PF8X00_FAM BIT(6)
  117. #define PF8X00_DEVICE_FAM_MASK GENMASK(7, 4)
  118. #define PF8X00_DEVICE_ID_MASK GENMASK(3, 0)
  119. struct pf8x00_regulator_data {
  120. struct regulator_desc desc;
  121. unsigned int suspend_enable_reg;
  122. unsigned int suspend_enable_mask;
  123. unsigned int suspend_voltage_reg;
  124. unsigned int suspend_voltage_cache;
  125. };
  126. struct pf8x00_chip {
  127. struct regmap *regmap;
  128. struct device *dev;
  129. };
  130. static const struct regmap_config pf8x00_regmap_config = {
  131. .reg_bits = 8,
  132. .val_bits = 8,
  133. .max_register = PF8X00_PAGE_SELECT,
  134. .cache_type = REGCACHE_RBTREE,
  135. };
  136. /* VLDOx output: 1.5V to 5.0V */
  137. static const int pf8x00_ldo_voltages[] = {
  138. 1500000, 1600000, 1800000, 1850000, 2150000, 2500000, 2800000, 3000000,
  139. 3100000, 3150000, 3200000, 3300000, 3350000, 1650000, 1700000, 5000000,
  140. };
  141. /* Output: 2.1A to 4.5A */
  142. static const unsigned int pf8x00_sw_current_table[] = {
  143. 2100000, 2600000, 3000000, 4500000,
  144. };
  145. /* Output: 0.4V to 1.8V */
  146. #define PF8XOO_SW1_6_VOLTAGE_NUM 0xB2
  147. static const struct linear_range pf8x00_sw1_to_6_voltages[] = {
  148. REGULATOR_LINEAR_RANGE(400000, 0x00, 0xB0, 6250),
  149. REGULATOR_LINEAR_RANGE(1800000, 0xB1, 0xB1, 0),
  150. };
  151. /* Output: 1.0V to 4.1V */
  152. static const int pf8x00_sw7_voltages[] = {
  153. 1000000, 1100000, 1200000, 1250000, 1300000, 1350000, 1500000, 1600000,
  154. 1800000, 1850000, 2000000, 2100000, 2150000, 2250000, 2300000, 2400000,
  155. 2500000, 2800000, 3150000, 3200000, 3250000, 3300000, 3350000, 3400000,
  156. 3500000, 3800000, 4000000, 4100000, 4100000, 4100000, 4100000, 4100000,
  157. };
  158. /* Output: 1.8V, 3.0V, or 3.3V */
  159. static const int pf8x00_vsnvs_voltages[] = {
  160. 0, 1800000, 3000000, 3300000,
  161. };
  162. static void swxilim_select(struct pf8x00_chip *chip, int id, int ilim)
  163. {
  164. u8 ilim_sel;
  165. u8 reg = PF8X00_SW_BASE(id) + SW_CONFIG2;
  166. switch (ilim) {
  167. case 2100:
  168. ilim_sel = SWXILIM_2100_MA;
  169. break;
  170. case 2600:
  171. ilim_sel = SWXILIM_2600_MA;
  172. break;
  173. case 3000:
  174. ilim_sel = SWXILIM_3000_MA;
  175. break;
  176. case 4500:
  177. ilim_sel = SWXILIM_4500_MA;
  178. break;
  179. default:
  180. ilim_sel = SWXILIM_2100_MA;
  181. break;
  182. }
  183. regmap_update_bits(chip->regmap, reg,
  184. PF8X00_SWXILIM_MASK,
  185. ilim_sel << PF8X00_SWXILIM_SHIFT);
  186. }
  187. static void handle_ilim_property(struct device_node *np,
  188. const struct regulator_desc *desc,
  189. struct regulator_config *config)
  190. {
  191. struct pf8x00_chip *chip = config->driver_data;
  192. int ret;
  193. int val;
  194. if ((desc->id >= PF8X00_BUCK1) && (desc->id <= PF8X00_BUCK7)) {
  195. ret = of_property_read_u32(np, "nxp,ilim-ma", &val);
  196. if (ret) {
  197. dev_dbg(chip->dev, "unspecified ilim for BUCK%d, use value stored in OTP\n",
  198. desc->id - PF8X00_LDO4);
  199. return;
  200. }
  201. dev_warn(chip->dev, "nxp,ilim-ma is deprecated, please use regulator-max-microamp\n");
  202. swxilim_select(chip, desc->id, val);
  203. } else
  204. dev_warn(chip->dev, "nxp,ilim-ma used with incorrect regulator (%d)\n", desc->id);
  205. }
  206. static void handle_shift_property(struct device_node *np,
  207. const struct regulator_desc *desc,
  208. struct regulator_config *config)
  209. {
  210. unsigned char id = desc->id - PF8X00_LDO4;
  211. unsigned char reg = PF8X00_SW_BASE(id) + SW_CONFIG2;
  212. struct pf8x00_chip *chip = config->driver_data;
  213. int phase;
  214. int val;
  215. int ret;
  216. if ((desc->id >= PF8X00_BUCK1) && (desc->id <= PF8X00_BUCK7)) {
  217. ret = of_property_read_u32(np, "nxp,phase-shift", &val);
  218. if (ret) {
  219. dev_dbg(chip->dev,
  220. "unspecified phase-shift for BUCK%d, using OTP configuration\n",
  221. id);
  222. return;
  223. }
  224. if (val < 0 || val > 315 || val % 45 != 0) {
  225. dev_warn(config->dev,
  226. "invalid phase_shift %d for BUCK%d, using OTP configuration\n",
  227. val, id);
  228. return;
  229. }
  230. phase = val / 45;
  231. if (phase >= 1)
  232. phase -= 1;
  233. else
  234. phase = PF8X00_SWXPHASE_SHIFT;
  235. regmap_update_bits(chip->regmap, reg,
  236. PF8X00_SWXPHASE_MASK,
  237. phase);
  238. } else
  239. dev_warn(chip->dev, "nxp,phase-shift used with incorrect regulator (%d)\n", id);
  240. }
  241. static int pf8x00_of_parse_cb(struct device_node *np,
  242. const struct regulator_desc *desc,
  243. struct regulator_config *config)
  244. {
  245. handle_ilim_property(np, desc, config);
  246. handle_shift_property(np, desc, config);
  247. return 0;
  248. }
  249. static int pf8x00_suspend_enable(struct regulator_dev *rdev)
  250. {
  251. struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
  252. struct regmap *rmap = rdev_get_regmap(rdev);
  253. return regmap_update_bits(rmap, regl->suspend_enable_reg,
  254. regl->suspend_enable_mask,
  255. regl->suspend_enable_mask);
  256. }
  257. static int pf8x00_suspend_disable(struct regulator_dev *rdev)
  258. {
  259. struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
  260. struct regmap *rmap = rdev_get_regmap(rdev);
  261. return regmap_update_bits(rmap, regl->suspend_enable_reg,
  262. regl->suspend_enable_mask, 0);
  263. }
  264. static int pf8x00_set_suspend_voltage(struct regulator_dev *rdev, int uV)
  265. {
  266. struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
  267. int ret;
  268. if (regl->suspend_voltage_cache == uV)
  269. return 0;
  270. ret = regulator_map_voltage_iterate(rdev, uV, uV);
  271. if (ret < 0) {
  272. dev_err(rdev_get_dev(rdev), "failed to map %i uV\n", uV);
  273. return ret;
  274. }
  275. dev_dbg(rdev_get_dev(rdev), "uV: %i, reg: 0x%x, msk: 0x%x, val: 0x%x\n",
  276. uV, regl->suspend_voltage_reg, regl->desc.vsel_mask, ret);
  277. ret = regmap_update_bits(rdev->regmap, regl->suspend_voltage_reg,
  278. regl->desc.vsel_mask, ret);
  279. if (ret < 0) {
  280. dev_err(rdev_get_dev(rdev), "failed to set %i uV\n", uV);
  281. return ret;
  282. }
  283. regl->suspend_voltage_cache = uV;
  284. return 0;
  285. }
  286. static const struct regulator_ops pf8x00_ldo_ops = {
  287. .enable = regulator_enable_regmap,
  288. .disable = regulator_disable_regmap,
  289. .is_enabled = regulator_is_enabled_regmap,
  290. .list_voltage = regulator_list_voltage_table,
  291. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  292. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  293. .set_suspend_enable = pf8x00_suspend_enable,
  294. .set_suspend_disable = pf8x00_suspend_disable,
  295. .set_suspend_voltage = pf8x00_set_suspend_voltage,
  296. };
  297. static const struct regulator_ops pf8x00_buck1_6_ops = {
  298. .enable = regulator_enable_regmap,
  299. .disable = regulator_disable_regmap,
  300. .is_enabled = regulator_is_enabled_regmap,
  301. .list_voltage = regulator_list_voltage_linear_range,
  302. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  303. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  304. .get_current_limit = regulator_get_current_limit_regmap,
  305. .set_current_limit = regulator_set_current_limit_regmap,
  306. .set_suspend_enable = pf8x00_suspend_enable,
  307. .set_suspend_disable = pf8x00_suspend_disable,
  308. .set_suspend_voltage = pf8x00_set_suspend_voltage,
  309. };
  310. static const struct regulator_ops pf8x00_buck7_ops = {
  311. .enable = regulator_enable_regmap,
  312. .disable = regulator_disable_regmap,
  313. .is_enabled = regulator_is_enabled_regmap,
  314. .list_voltage = regulator_list_voltage_table,
  315. .map_voltage = regulator_map_voltage_ascend,
  316. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  317. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  318. .get_current_limit = regulator_get_current_limit_regmap,
  319. .set_current_limit = regulator_set_current_limit_regmap,
  320. .set_suspend_enable = pf8x00_suspend_enable,
  321. .set_suspend_disable = pf8x00_suspend_disable,
  322. };
  323. static const struct regulator_ops pf8x00_vsnvs_ops = {
  324. .enable = regulator_enable_regmap,
  325. .disable = regulator_disable_regmap,
  326. .is_enabled = regulator_is_enabled_regmap,
  327. .list_voltage = regulator_list_voltage_table,
  328. .map_voltage = regulator_map_voltage_ascend,
  329. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  330. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  331. };
  332. #define PF8X00LDO(_id, _name, base, voltages) \
  333. [PF8X00_LDO ## _id] = { \
  334. .desc = { \
  335. .name = _name, \
  336. .of_match = _name, \
  337. .regulators_node = "regulators", \
  338. .n_voltages = ARRAY_SIZE(voltages), \
  339. .ops = &pf8x00_ldo_ops, \
  340. .type = REGULATOR_VOLTAGE, \
  341. .id = PF8X00_LDO ## _id, \
  342. .owner = THIS_MODULE, \
  343. .volt_table = voltages, \
  344. .vsel_reg = (base) + LDO_RUN_VOLT, \
  345. .vsel_mask = 0xff, \
  346. .enable_reg = (base) + LDO_CONFIG2, \
  347. .enable_val = 0x2, \
  348. .disable_val = 0x0, \
  349. .enable_mask = 2, \
  350. }, \
  351. .suspend_enable_reg = (base) + LDO_CONFIG2, \
  352. .suspend_enable_mask = 1, \
  353. .suspend_voltage_reg = (base) + LDO_STBY_VOLT, \
  354. }
  355. #define PF8X00BUCK(_id, _name, base, voltages) \
  356. [PF8X00_BUCK ## _id] = { \
  357. .desc = { \
  358. .name = _name, \
  359. .of_match = _name, \
  360. .regulators_node = "regulators", \
  361. .of_parse_cb = pf8x00_of_parse_cb, \
  362. .n_voltages = PF8XOO_SW1_6_VOLTAGE_NUM, \
  363. .ops = &pf8x00_buck1_6_ops, \
  364. .type = REGULATOR_VOLTAGE, \
  365. .id = PF8X00_BUCK ## _id, \
  366. .owner = THIS_MODULE, \
  367. .ramp_delay = 19000, \
  368. .linear_ranges = pf8x00_sw1_to_6_voltages, \
  369. .n_linear_ranges = \
  370. ARRAY_SIZE(pf8x00_sw1_to_6_voltages), \
  371. .vsel_reg = (base) + SW_RUN_VOLT, \
  372. .vsel_mask = 0xff, \
  373. .curr_table = pf8x00_sw_current_table, \
  374. .n_current_limits = \
  375. ARRAY_SIZE(pf8x00_sw_current_table), \
  376. .csel_reg = (base) + SW_CONFIG2, \
  377. .csel_mask = PF8X00_SWXILIM_MASK, \
  378. .enable_reg = (base) + SW_MODE1, \
  379. .enable_val = 0x3, \
  380. .disable_val = 0x0, \
  381. .enable_mask = 0x3, \
  382. .enable_time = 500, \
  383. }, \
  384. .suspend_enable_reg = (base) + SW_MODE1, \
  385. .suspend_enable_mask = 0xc, \
  386. .suspend_voltage_reg = (base) + SW_STBY_VOLT, \
  387. }
  388. #define PF8X00BUCK7(_name, base, voltages) \
  389. [PF8X00_BUCK7] = { \
  390. .desc = { \
  391. .name = _name, \
  392. .of_match = _name, \
  393. .regulators_node = "regulators", \
  394. .of_parse_cb = pf8x00_of_parse_cb, \
  395. .n_voltages = ARRAY_SIZE(voltages), \
  396. .ops = &pf8x00_buck7_ops, \
  397. .type = REGULATOR_VOLTAGE, \
  398. .id = PF8X00_BUCK7, \
  399. .owner = THIS_MODULE, \
  400. .ramp_delay = 19000, \
  401. .volt_table = voltages, \
  402. .vsel_reg = (base) + SW_RUN_VOLT, \
  403. .vsel_mask = 0xff, \
  404. .curr_table = pf8x00_sw_current_table, \
  405. .n_current_limits = \
  406. ARRAY_SIZE(pf8x00_sw_current_table), \
  407. .csel_reg = (base) + SW_CONFIG2, \
  408. .csel_mask = PF8X00_SWXILIM_MASK, \
  409. .enable_reg = (base) + SW_MODE1, \
  410. .enable_val = 0x3, \
  411. .disable_val = 0x0, \
  412. .enable_mask = 0x3, \
  413. .enable_time = 500, \
  414. }, \
  415. }
  416. #define PF8X00VSNVS(_name, base, voltages) \
  417. [PF8X00_VSNVS] = { \
  418. .desc = { \
  419. .name = _name, \
  420. .of_match = _name, \
  421. .regulators_node = "regulators", \
  422. .n_voltages = ARRAY_SIZE(voltages), \
  423. .ops = &pf8x00_vsnvs_ops, \
  424. .type = REGULATOR_VOLTAGE, \
  425. .id = PF8X00_VSNVS, \
  426. .owner = THIS_MODULE, \
  427. .volt_table = voltages, \
  428. .vsel_reg = (base), \
  429. .vsel_mask = 0x3, \
  430. }, \
  431. }
  432. static struct pf8x00_regulator_data pf8x00_regs_data[PF8X00_MAX_REGULATORS] = {
  433. PF8X00LDO(1, "ldo1", PF8X00_LDO_BASE(PF8X00_LDO1), pf8x00_ldo_voltages),
  434. PF8X00LDO(2, "ldo2", PF8X00_LDO_BASE(PF8X00_LDO2), pf8x00_ldo_voltages),
  435. PF8X00LDO(3, "ldo3", PF8X00_LDO_BASE(PF8X00_LDO3), pf8x00_ldo_voltages),
  436. PF8X00LDO(4, "ldo4", PF8X00_LDO_BASE(PF8X00_LDO4), pf8x00_ldo_voltages),
  437. PF8X00BUCK(1, "buck1", PF8X00_SW_BASE(PF8X00_BUCK1), pf8x00_sw1_to_6_voltages),
  438. PF8X00BUCK(2, "buck2", PF8X00_SW_BASE(PF8X00_BUCK2), pf8x00_sw1_to_6_voltages),
  439. PF8X00BUCK(3, "buck3", PF8X00_SW_BASE(PF8X00_BUCK3), pf8x00_sw1_to_6_voltages),
  440. PF8X00BUCK(4, "buck4", PF8X00_SW_BASE(PF8X00_BUCK4), pf8x00_sw1_to_6_voltages),
  441. PF8X00BUCK(5, "buck5", PF8X00_SW_BASE(PF8X00_BUCK5), pf8x00_sw1_to_6_voltages),
  442. PF8X00BUCK(6, "buck6", PF8X00_SW_BASE(PF8X00_BUCK6), pf8x00_sw1_to_6_voltages),
  443. PF8X00BUCK7("buck7", PF8X00_SW_BASE(PF8X00_BUCK7), pf8x00_sw7_voltages),
  444. PF8X00VSNVS("vsnvs", PF8X00_VSNVS_CONFIG1, pf8x00_vsnvs_voltages),
  445. };
  446. static int pf8x00_identify(struct pf8x00_chip *chip)
  447. {
  448. unsigned int value;
  449. u8 dev_fam, dev_id;
  450. const char *name = NULL;
  451. int ret;
  452. ret = regmap_read(chip->regmap, PF8X00_DEVICEID, &value);
  453. if (ret) {
  454. dev_err(chip->dev, "failed to read chip family\n");
  455. return ret;
  456. }
  457. dev_fam = value & PF8X00_DEVICE_FAM_MASK;
  458. switch (dev_fam) {
  459. case PF8X00_FAM:
  460. break;
  461. default:
  462. dev_err(chip->dev,
  463. "Chip 0x%x is not from PF8X00 family\n", dev_fam);
  464. return ret;
  465. }
  466. dev_id = value & PF8X00_DEVICE_ID_MASK;
  467. switch (dev_id) {
  468. case PF8100:
  469. name = "PF8100";
  470. break;
  471. case PF8121A:
  472. name = "PF8121A";
  473. break;
  474. case PF8200:
  475. name = "PF8200";
  476. break;
  477. default:
  478. dev_err(chip->dev, "Unknown pf8x00 device id 0x%x\n", dev_id);
  479. return -ENODEV;
  480. }
  481. dev_info(chip->dev, "%s PMIC found.\n", name);
  482. return 0;
  483. }
  484. static int pf8x00_i2c_probe(struct i2c_client *client)
  485. {
  486. struct regulator_config config = { NULL, };
  487. struct pf8x00_chip *chip;
  488. int id;
  489. int ret;
  490. chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
  491. if (!chip)
  492. return -ENOMEM;
  493. i2c_set_clientdata(client, chip);
  494. chip->dev = &client->dev;
  495. chip->regmap = devm_regmap_init_i2c(client, &pf8x00_regmap_config);
  496. if (IS_ERR(chip->regmap)) {
  497. ret = PTR_ERR(chip->regmap);
  498. dev_err(&client->dev,
  499. "regmap allocation failed with err %d\n", ret);
  500. return ret;
  501. }
  502. ret = pf8x00_identify(chip);
  503. if (ret)
  504. return ret;
  505. for (id = 0; id < ARRAY_SIZE(pf8x00_regs_data); id++) {
  506. struct pf8x00_regulator_data *data = &pf8x00_regs_data[id];
  507. struct regulator_dev *rdev;
  508. config.dev = chip->dev;
  509. config.driver_data = data;
  510. config.regmap = chip->regmap;
  511. rdev = devm_regulator_register(&client->dev, &data->desc, &config);
  512. if (IS_ERR(rdev)) {
  513. dev_err(&client->dev,
  514. "failed to register %s regulator\n", data->desc.name);
  515. return PTR_ERR(rdev);
  516. }
  517. }
  518. return 0;
  519. }
  520. static const struct of_device_id pf8x00_dt_ids[] = {
  521. { .compatible = "nxp,pf8100",},
  522. { .compatible = "nxp,pf8121a",},
  523. { .compatible = "nxp,pf8200",},
  524. { }
  525. };
  526. MODULE_DEVICE_TABLE(of, pf8x00_dt_ids);
  527. static const struct i2c_device_id pf8x00_i2c_id[] = {
  528. { "pf8100", 0 },
  529. { "pf8121a", 0 },
  530. { "pf8200", 0 },
  531. {},
  532. };
  533. MODULE_DEVICE_TABLE(i2c, pf8x00_i2c_id);
  534. static struct i2c_driver pf8x00_regulator_driver = {
  535. .id_table = pf8x00_i2c_id,
  536. .driver = {
  537. .name = "pf8x00",
  538. .of_match_table = pf8x00_dt_ids,
  539. },
  540. .probe_new = pf8x00_i2c_probe,
  541. };
  542. module_i2c_driver(pf8x00_regulator_driver);
  543. MODULE_AUTHOR("Jagan Teki <[email protected]>");
  544. MODULE_AUTHOR("Troy Kisky <[email protected]>");
  545. MODULE_DESCRIPTION("Regulator Driver for NXP's PF8100/PF8121A/PF8200 PMIC");
  546. MODULE_LICENSE("GPL v2");