mp8859.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Copyright (c) 2019 five technologies GmbH
  4. // Author: Markus Reichl <m.reichl@fivetechno.de>
  5. #include <linux/module.h>
  6. #include <linux/i2c.h>
  7. #include <linux/of.h>
  8. #include <linux/regulator/driver.h>
  9. #include <linux/regmap.h>
  10. #define VOL_MIN_IDX 0x00
  11. #define VOL_MAX_IDX 0x7ff
  12. /* Register definitions */
  13. #define MP8859_VOUT_L_REG 0 //3 lo Bits
  14. #define MP8859_VOUT_H_REG 1 //8 hi Bits
  15. #define MP8859_VOUT_GO_REG 2
  16. #define MP8859_IOUT_LIM_REG 3
  17. #define MP8859_CTL1_REG 4
  18. #define MP8859_CTL2_REG 5
  19. #define MP8859_RESERVED1_REG 6
  20. #define MP8859_RESERVED2_REG 7
  21. #define MP8859_RESERVED3_REG 8
  22. #define MP8859_STATUS_REG 9
  23. #define MP8859_INTERRUPT_REG 0x0A
  24. #define MP8859_MASK_REG 0x0B
  25. #define MP8859_ID1_REG 0x0C
  26. #define MP8859_MFR_ID_REG 0x27
  27. #define MP8859_DEV_ID_REG 0x28
  28. #define MP8859_IC_REV_REG 0x29
  29. #define MP8859_MAX_REG 0x29
  30. #define MP8859_GO_BIT 0x01
  31. #define MP8859_IOUT_LIM_MASK 0x7f
  32. #define MP8859_ENABLE_MASK 0x80
  33. #define MP8859_DISCHG_EN_MASK 0x10
  34. #define MP8859_MODE_MASK 0x08
  35. #define MP8859_PG_MASK 0x80
  36. #define MP8859_OTP_MASK 0x40
  37. #define MP8859_OTW_MASK 0x20
  38. #define MP8859_CC_CV_MASK 0x10
  39. static int mp8859_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
  40. {
  41. int ret;
  42. ret = regmap_write(rdev->regmap, MP8859_VOUT_L_REG, sel & 0x7);
  43. if (ret)
  44. return ret;
  45. ret = regmap_write(rdev->regmap, MP8859_VOUT_H_REG, sel >> 3);
  46. if (ret)
  47. return ret;
  48. ret = regmap_update_bits(rdev->regmap, MP8859_VOUT_GO_REG,
  49. MP8859_GO_BIT, 1);
  50. return ret;
  51. }
  52. static int mp8859_get_voltage_sel(struct regulator_dev *rdev)
  53. {
  54. unsigned int val_tmp;
  55. unsigned int val;
  56. int ret;
  57. ret = regmap_read(rdev->regmap, MP8859_VOUT_H_REG, &val_tmp);
  58. if (ret)
  59. return ret;
  60. val = val_tmp << 3;
  61. ret = regmap_read(rdev->regmap, MP8859_VOUT_L_REG, &val_tmp);
  62. if (ret)
  63. return ret;
  64. val |= val_tmp & 0x07;
  65. return val;
  66. }
  67. static int mp8859_set_voltage_time_sel(struct regulator_dev *rdev,
  68. unsigned int from, unsigned int to)
  69. {
  70. int change;
  71. /* The voltage ramps at 1mV/uS, selectors are 10mV */
  72. if (from > to)
  73. change = from - to;
  74. else
  75. change = to - from;
  76. return change * 10 * 1000;
  77. }
  78. static unsigned int mp8859_get_mode(struct regulator_dev *rdev)
  79. {
  80. unsigned int val;
  81. int ret;
  82. ret = regmap_read(rdev->regmap, MP8859_CTL1_REG, &val);
  83. if (ret != 0) {
  84. dev_err(&rdev->dev, "Failed to read mode: %d\n", ret);
  85. return 0;
  86. }
  87. if (val & MP8859_MODE_MASK)
  88. return REGULATOR_MODE_FAST;
  89. else
  90. return REGULATOR_MODE_NORMAL;
  91. }
  92. static int mp8859_set_mode(struct regulator_dev *rdev, unsigned int mode)
  93. {
  94. unsigned int val;
  95. switch (mode) {
  96. case REGULATOR_MODE_FAST:
  97. val = MP8859_MODE_MASK;
  98. break;
  99. case REGULATOR_MODE_NORMAL:
  100. val = 0;
  101. break;
  102. default:
  103. return -EINVAL;
  104. }
  105. return regmap_update_bits(rdev->regmap, MP8859_CTL1_REG,
  106. MP8859_MODE_MASK, val);
  107. }
  108. static int mp8859_set_current_limit(struct regulator_dev *rdev,
  109. int min_uA, int max_uA)
  110. {
  111. unsigned int cur_val, new_val;
  112. int ret, i;
  113. /* Steps of 50mA */
  114. new_val = max_uA / 50000;
  115. if (new_val > MP8859_IOUT_LIM_MASK)
  116. return -EINVAL;
  117. if (new_val == 0)
  118. return -EINVAL;
  119. /*
  120. * If the regulator is limiting then ramp gradually as per
  121. * datasheet, otherwise just set the value directly.
  122. */
  123. ret = regmap_read(rdev->regmap, MP8859_STATUS_REG, &cur_val);
  124. if (ret != 0)
  125. return ret;
  126. if (!(cur_val & MP8859_CC_CV_MASK)) {
  127. return regmap_update_bits(rdev->regmap, MP8859_IOUT_LIM_REG,
  128. MP8859_IOUT_LIM_MASK, new_val);
  129. }
  130. ret = regmap_read(rdev->regmap, MP8859_IOUT_LIM_REG, &cur_val);
  131. if (ret != 0)
  132. return ret;
  133. if (cur_val >= new_val) {
  134. for (i = cur_val; i >= new_val; i--) {
  135. ret = regmap_update_bits(rdev->regmap,
  136. MP8859_IOUT_LIM_REG,
  137. MP8859_IOUT_LIM_MASK,
  138. cur_val - i);
  139. if (ret != 0)
  140. return ret;
  141. }
  142. } else {
  143. for (i = cur_val; i <= new_val; i++) {
  144. ret = regmap_update_bits(rdev->regmap,
  145. MP8859_IOUT_LIM_REG,
  146. MP8859_IOUT_LIM_MASK,
  147. cur_val + i);
  148. if (ret != 0)
  149. return ret;
  150. }
  151. }
  152. return 0;
  153. }
  154. static int mp8859_get_status(struct regulator_dev *rdev)
  155. {
  156. unsigned int val;
  157. int ret;
  158. /* Output status is only meaingful when enabled */
  159. ret = regmap_read(rdev->regmap, MP8859_CTL1_REG, &val);
  160. if (ret != 0)
  161. return ret;
  162. if (!(val & MP8859_ENABLE_MASK))
  163. return REGULATOR_STATUS_UNDEFINED;
  164. ret = regmap_read(rdev->regmap, MP8859_STATUS_REG, &val);
  165. if (ret != 0)
  166. return ret;
  167. if (val & MP8859_PG_MASK)
  168. return REGULATOR_STATUS_ON;
  169. else
  170. return REGULATOR_STATUS_ERROR;
  171. }
  172. static int mp8859_get_error_flags(struct regulator_dev *rdev,
  173. unsigned int *flags)
  174. {
  175. unsigned int status, enabled;
  176. int ret;
  177. *flags = 0;
  178. /* Output status is only meaingful when enabled */
  179. ret = regmap_read(rdev->regmap, MP8859_CTL1_REG, &enabled);
  180. if (ret != 0)
  181. return ret;
  182. enabled &= MP8859_ENABLE_MASK;
  183. ret = regmap_read(rdev->regmap, MP8859_STATUS_REG, &status);
  184. if (ret != 0)
  185. return ret;
  186. if (enabled && !(status & MP8859_PG_MASK))
  187. status |= REGULATOR_ERROR_FAIL;
  188. if (status & MP8859_OTP_MASK)
  189. status |= REGULATOR_ERROR_OVER_TEMP;
  190. if (status & MP8859_OTW_MASK)
  191. status |= REGULATOR_ERROR_OVER_TEMP_WARN;
  192. if (status & MP8859_CC_CV_MASK)
  193. status |= REGULATOR_ERROR_OVER_CURRENT;
  194. return 0;
  195. }
  196. static const struct linear_range mp8859_dcdc_ranges[] = {
  197. REGULATOR_LINEAR_RANGE(0, VOL_MIN_IDX, VOL_MAX_IDX, 10000),
  198. };
  199. static bool mp8859_readable(struct device *dev, unsigned int reg)
  200. {
  201. switch (reg) {
  202. case MP8859_VOUT_L_REG:
  203. case MP8859_VOUT_H_REG:
  204. case MP8859_VOUT_GO_REG:
  205. case MP8859_IOUT_LIM_REG:
  206. case MP8859_CTL1_REG:
  207. case MP8859_CTL2_REG:
  208. case MP8859_STATUS_REG:
  209. case MP8859_INTERRUPT_REG:
  210. case MP8859_MASK_REG:
  211. case MP8859_ID1_REG:
  212. case MP8859_MFR_ID_REG:
  213. case MP8859_DEV_ID_REG:
  214. case MP8859_IC_REV_REG:
  215. return true;
  216. default:
  217. return false;
  218. }
  219. }
  220. static bool mp8859_volatile(struct device *dev, unsigned int reg)
  221. {
  222. switch (reg) {
  223. case MP8859_VOUT_GO_REG:
  224. case MP8859_STATUS_REG:
  225. case MP8859_INTERRUPT_REG:
  226. return true;
  227. default:
  228. return false;
  229. }
  230. }
  231. static const struct regmap_config mp8859_regmap = {
  232. .reg_bits = 8,
  233. .val_bits = 8,
  234. .max_register = MP8859_MAX_REG,
  235. .cache_type = REGCACHE_MAPLE,
  236. .readable_reg = mp8859_readable,
  237. .volatile_reg = mp8859_volatile,
  238. };
  239. static const struct regulator_ops mp8859_ops = {
  240. .set_voltage_sel = mp8859_set_voltage_sel,
  241. .get_voltage_sel = mp8859_get_voltage_sel,
  242. .list_voltage = regulator_list_voltage_linear_range,
  243. .set_voltage_time_sel = mp8859_set_voltage_time_sel,
  244. .enable = regulator_enable_regmap,
  245. .disable = regulator_disable_regmap,
  246. .is_enabled = regulator_is_enabled_regmap,
  247. .set_mode = mp8859_set_mode,
  248. .get_mode = mp8859_get_mode,
  249. .set_active_discharge = regulator_set_active_discharge_regmap,
  250. .set_current_limit = mp8859_set_current_limit,
  251. .get_status = mp8859_get_status,
  252. .get_error_flags = mp8859_get_error_flags,
  253. };
  254. static const struct regulator_desc mp8859_regulators[] = {
  255. {
  256. .id = 0,
  257. .type = REGULATOR_VOLTAGE,
  258. .name = "mp8859_dcdc",
  259. .supply_name = "vin",
  260. .of_match = of_match_ptr("mp8859_dcdc"),
  261. .n_voltages = VOL_MAX_IDX + 1,
  262. .linear_ranges = mp8859_dcdc_ranges,
  263. .n_linear_ranges = 1,
  264. .enable_reg = MP8859_CTL1_REG,
  265. .enable_mask = MP8859_ENABLE_MASK,
  266. .enable_val = MP8859_ENABLE_MASK,
  267. .active_discharge_reg = MP8859_CTL1_REG,
  268. .active_discharge_on = MP8859_DISCHG_EN_MASK,
  269. .active_discharge_mask = MP8859_DISCHG_EN_MASK,
  270. .ops = &mp8859_ops,
  271. .owner = THIS_MODULE,
  272. },
  273. };
  274. static int mp8859_i2c_probe(struct i2c_client *i2c)
  275. {
  276. int ret;
  277. struct regulator_config config = {.dev = &i2c->dev};
  278. struct regmap *regmap = devm_regmap_init_i2c(i2c, &mp8859_regmap);
  279. struct regulator_dev *rdev;
  280. unsigned int val, rev;
  281. if (IS_ERR(regmap)) {
  282. ret = PTR_ERR(regmap);
  283. dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
  284. return ret;
  285. }
  286. ret = regmap_read(regmap, MP8859_MFR_ID_REG, &val);
  287. if (ret != 0) {
  288. dev_err(&i2c->dev, "Failed to read manufacturer ID: %d\n", ret);
  289. return ret;
  290. }
  291. if (val != 0x9) {
  292. dev_err(&i2c->dev, "Manufacturer ID %x != 9\n", val);
  293. return -EINVAL;
  294. }
  295. ret = regmap_read(regmap, MP8859_DEV_ID_REG, &val);
  296. if (ret != 0) {
  297. dev_err(&i2c->dev, "Failed to read device ID: %d\n", ret);
  298. return ret;
  299. }
  300. if (val != 0x58) {
  301. dev_err(&i2c->dev, "Manufacturer ID %x != 0x58\n", val);
  302. return -EINVAL;
  303. }
  304. ret = regmap_read(regmap, MP8859_IC_REV_REG, &rev);
  305. if (ret != 0) {
  306. dev_err(&i2c->dev, "Failed to read device revision: %d\n", ret);
  307. return ret;
  308. }
  309. ret = regmap_read(regmap, MP8859_ID1_REG, &val);
  310. if (ret != 0) {
  311. dev_err(&i2c->dev, "Failed to read device ID1: %d\n", ret);
  312. return ret;
  313. }
  314. dev_info(&i2c->dev, "MP8859-%04d revision %d\n", val, rev);
  315. rdev = devm_regulator_register(&i2c->dev, &mp8859_regulators[0],
  316. &config);
  317. if (IS_ERR(rdev)) {
  318. ret = PTR_ERR(rdev);
  319. dev_err(&i2c->dev, "failed to register %s: %d\n",
  320. mp8859_regulators[0].name, ret);
  321. return ret;
  322. }
  323. return 0;
  324. }
  325. static const struct of_device_id mp8859_dt_id[] __maybe_unused = {
  326. {.compatible = "mps,mp8859"},
  327. {},
  328. };
  329. MODULE_DEVICE_TABLE(of, mp8859_dt_id);
  330. static const struct i2c_device_id mp8859_i2c_id[] = {
  331. { "mp8859", },
  332. { },
  333. };
  334. MODULE_DEVICE_TABLE(i2c, mp8859_i2c_id);
  335. static struct i2c_driver mp8859_regulator_driver = {
  336. .driver = {
  337. .name = "mp8859",
  338. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  339. .of_match_table = of_match_ptr(mp8859_dt_id),
  340. },
  341. .probe = mp8859_i2c_probe,
  342. .id_table = mp8859_i2c_id,
  343. };
  344. module_i2c_driver(mp8859_regulator_driver);
  345. MODULE_DESCRIPTION("Monolithic Power Systems MP8859 voltage regulator driver");
  346. MODULE_AUTHOR("Markus Reichl <m.reichl@fivetechno.de>");
  347. MODULE_LICENSE("GPL v2");