act8865-regulator.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. * act8865-regulator.c - Voltage regulation for the active-semi ACT8865
  3. * http://www.active-semi.com/sheets/ACT8865_Datasheet.pdf
  4. *
  5. * Copyright (C) 2013 Atmel Corporation
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/init.h>
  19. #include <linux/i2c.h>
  20. #include <linux/err.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/regulator/driver.h>
  23. #include <linux/regulator/act8865.h>
  24. #include <linux/of.h>
  25. #include <linux/of_device.h>
  26. #include <linux/regulator/of_regulator.h>
  27. #include <linux/regmap.h>
  28. /*
  29. * ACT8865 Global Register Map.
  30. */
  31. #define ACT8865_SYS_MODE 0x00
  32. #define ACT8865_SYS_CTRL 0x01
  33. #define ACT8865_DCDC1_VSET1 0x20
  34. #define ACT8865_DCDC1_VSET2 0x21
  35. #define ACT8865_DCDC1_CTRL 0x22
  36. #define ACT8865_DCDC2_VSET1 0x30
  37. #define ACT8865_DCDC2_VSET2 0x31
  38. #define ACT8865_DCDC2_CTRL 0x32
  39. #define ACT8865_DCDC3_VSET1 0x40
  40. #define ACT8865_DCDC3_VSET2 0x41
  41. #define ACT8865_DCDC3_CTRL 0x42
  42. #define ACT8865_LDO1_VSET 0x50
  43. #define ACT8865_LDO1_CTRL 0x51
  44. #define ACT8865_LDO2_VSET 0x54
  45. #define ACT8865_LDO2_CTRL 0x55
  46. #define ACT8865_LDO3_VSET 0x60
  47. #define ACT8865_LDO3_CTRL 0x61
  48. #define ACT8865_LDO4_VSET 0x64
  49. #define ACT8865_LDO4_CTRL 0x65
  50. /*
  51. * Field Definitions.
  52. */
  53. #define ACT8865_ENA 0x80 /* ON - [7] */
  54. #define ACT8865_VSEL_MASK 0x3F /* VSET - [5:0] */
  55. /*
  56. * ACT8865 voltage number
  57. */
  58. #define ACT8865_VOLTAGE_NUM 64
  59. struct act8865 {
  60. struct regulator_dev *rdev[ACT8865_REG_NUM];
  61. struct regmap *regmap;
  62. };
  63. static const struct regmap_config act8865_regmap_config = {
  64. .reg_bits = 8,
  65. .val_bits = 8,
  66. };
  67. static const struct regulator_linear_range act8865_volatge_ranges[] = {
  68. REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
  69. REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
  70. REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
  71. };
  72. static struct regulator_ops act8865_ops = {
  73. .list_voltage = regulator_list_voltage_linear_range,
  74. .map_voltage = regulator_map_voltage_linear_range,
  75. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  76. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  77. .enable = regulator_enable_regmap,
  78. .disable = regulator_disable_regmap,
  79. .is_enabled = regulator_is_enabled_regmap,
  80. };
  81. static const struct regulator_desc act8865_reg[] = {
  82. {
  83. .name = "DCDC_REG1",
  84. .id = ACT8865_ID_DCDC1,
  85. .ops = &act8865_ops,
  86. .type = REGULATOR_VOLTAGE,
  87. .n_voltages = ACT8865_VOLTAGE_NUM,
  88. .linear_ranges = act8865_volatge_ranges,
  89. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  90. .vsel_reg = ACT8865_DCDC1_VSET1,
  91. .vsel_mask = ACT8865_VSEL_MASK,
  92. .enable_reg = ACT8865_DCDC1_CTRL,
  93. .enable_mask = ACT8865_ENA,
  94. .owner = THIS_MODULE,
  95. },
  96. {
  97. .name = "DCDC_REG2",
  98. .id = ACT8865_ID_DCDC2,
  99. .ops = &act8865_ops,
  100. .type = REGULATOR_VOLTAGE,
  101. .n_voltages = ACT8865_VOLTAGE_NUM,
  102. .linear_ranges = act8865_volatge_ranges,
  103. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  104. .vsel_reg = ACT8865_DCDC2_VSET1,
  105. .vsel_mask = ACT8865_VSEL_MASK,
  106. .enable_reg = ACT8865_DCDC2_CTRL,
  107. .enable_mask = ACT8865_ENA,
  108. .owner = THIS_MODULE,
  109. },
  110. {
  111. .name = "DCDC_REG3",
  112. .id = ACT8865_ID_DCDC3,
  113. .ops = &act8865_ops,
  114. .type = REGULATOR_VOLTAGE,
  115. .n_voltages = ACT8865_VOLTAGE_NUM,
  116. .linear_ranges = act8865_volatge_ranges,
  117. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  118. .vsel_reg = ACT8865_DCDC3_VSET1,
  119. .vsel_mask = ACT8865_VSEL_MASK,
  120. .enable_reg = ACT8865_DCDC3_CTRL,
  121. .enable_mask = ACT8865_ENA,
  122. .owner = THIS_MODULE,
  123. },
  124. {
  125. .name = "LDO_REG1",
  126. .id = ACT8865_ID_LDO1,
  127. .ops = &act8865_ops,
  128. .type = REGULATOR_VOLTAGE,
  129. .n_voltages = ACT8865_VOLTAGE_NUM,
  130. .linear_ranges = act8865_volatge_ranges,
  131. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  132. .vsel_reg = ACT8865_LDO1_VSET,
  133. .vsel_mask = ACT8865_VSEL_MASK,
  134. .enable_reg = ACT8865_LDO1_CTRL,
  135. .enable_mask = ACT8865_ENA,
  136. .owner = THIS_MODULE,
  137. },
  138. {
  139. .name = "LDO_REG2",
  140. .id = ACT8865_ID_LDO2,
  141. .ops = &act8865_ops,
  142. .type = REGULATOR_VOLTAGE,
  143. .n_voltages = ACT8865_VOLTAGE_NUM,
  144. .linear_ranges = act8865_volatge_ranges,
  145. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  146. .vsel_reg = ACT8865_LDO2_VSET,
  147. .vsel_mask = ACT8865_VSEL_MASK,
  148. .enable_reg = ACT8865_LDO2_CTRL,
  149. .enable_mask = ACT8865_ENA,
  150. .owner = THIS_MODULE,
  151. },
  152. {
  153. .name = "LDO_REG3",
  154. .id = ACT8865_ID_LDO3,
  155. .ops = &act8865_ops,
  156. .type = REGULATOR_VOLTAGE,
  157. .n_voltages = ACT8865_VOLTAGE_NUM,
  158. .linear_ranges = act8865_volatge_ranges,
  159. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  160. .vsel_reg = ACT8865_LDO3_VSET,
  161. .vsel_mask = ACT8865_VSEL_MASK,
  162. .enable_reg = ACT8865_LDO3_CTRL,
  163. .enable_mask = ACT8865_ENA,
  164. .owner = THIS_MODULE,
  165. },
  166. {
  167. .name = "LDO_REG4",
  168. .id = ACT8865_ID_LDO4,
  169. .ops = &act8865_ops,
  170. .type = REGULATOR_VOLTAGE,
  171. .n_voltages = ACT8865_VOLTAGE_NUM,
  172. .linear_ranges = act8865_volatge_ranges,
  173. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  174. .vsel_reg = ACT8865_LDO4_VSET,
  175. .vsel_mask = ACT8865_VSEL_MASK,
  176. .enable_reg = ACT8865_LDO4_CTRL,
  177. .enable_mask = ACT8865_ENA,
  178. .owner = THIS_MODULE,
  179. },
  180. };
  181. #ifdef CONFIG_OF
  182. static const struct of_device_id act8865_dt_ids[] = {
  183. { .compatible = "active-semi,act8865" },
  184. { }
  185. };
  186. MODULE_DEVICE_TABLE(of, act8865_dt_ids);
  187. static struct of_regulator_match act8865_matches[] = {
  188. [ACT8865_ID_DCDC1] = { .name = "DCDC_REG1"},
  189. [ACT8865_ID_DCDC2] = { .name = "DCDC_REG2"},
  190. [ACT8865_ID_DCDC3] = { .name = "DCDC_REG3"},
  191. [ACT8865_ID_LDO1] = { .name = "LDO_REG1"},
  192. [ACT8865_ID_LDO2] = { .name = "LDO_REG2"},
  193. [ACT8865_ID_LDO3] = { .name = "LDO_REG3"},
  194. [ACT8865_ID_LDO4] = { .name = "LDO_REG4"},
  195. };
  196. static int act8865_pdata_from_dt(struct device *dev,
  197. struct device_node **of_node,
  198. struct act8865_platform_data *pdata)
  199. {
  200. int matched, i;
  201. struct device_node *np;
  202. struct act8865_regulator_data *regulator;
  203. np = of_find_node_by_name(dev->of_node, "regulators");
  204. if (!np) {
  205. dev_err(dev, "missing 'regulators' subnode in DT\n");
  206. return -EINVAL;
  207. }
  208. matched = of_regulator_match(dev, np,
  209. act8865_matches, ARRAY_SIZE(act8865_matches));
  210. if (matched <= 0)
  211. return matched;
  212. pdata->regulators = devm_kzalloc(dev,
  213. sizeof(struct act8865_regulator_data) *
  214. ARRAY_SIZE(act8865_matches), GFP_KERNEL);
  215. if (!pdata->regulators) {
  216. dev_err(dev, "%s: failed to allocate act8865 registor\n",
  217. __func__);
  218. return -ENOMEM;
  219. }
  220. pdata->num_regulators = matched;
  221. regulator = pdata->regulators;
  222. for (i = 0; i < ARRAY_SIZE(act8865_matches); i++) {
  223. regulator->id = i;
  224. regulator->name = act8865_matches[i].name;
  225. regulator->platform_data = act8865_matches[i].init_data;
  226. of_node[i] = act8865_matches[i].of_node;
  227. regulator++;
  228. }
  229. return 0;
  230. }
  231. #else
  232. static inline int act8865_pdata_from_dt(struct device *dev,
  233. struct device_node **of_node,
  234. struct act8865_platform_data *pdata)
  235. {
  236. return 0;
  237. }
  238. #endif
  239. static int act8865_pmic_probe(struct i2c_client *client,
  240. const struct i2c_device_id *i2c_id)
  241. {
  242. struct regulator_dev **rdev;
  243. struct device *dev = &client->dev;
  244. struct act8865_platform_data *pdata = dev_get_platdata(dev);
  245. struct regulator_config config = { };
  246. struct act8865 *act8865;
  247. struct device_node *of_node[ACT8865_REG_NUM];
  248. int i, id;
  249. int ret = -EINVAL;
  250. int error;
  251. if (dev->of_node && !pdata) {
  252. const struct of_device_id *id;
  253. struct act8865_platform_data pdata_of;
  254. id = of_match_device(of_match_ptr(act8865_dt_ids), dev);
  255. if (!id)
  256. return -ENODEV;
  257. ret = act8865_pdata_from_dt(dev, of_node, &pdata_of);
  258. if (ret < 0)
  259. return ret;
  260. pdata = &pdata_of;
  261. }
  262. if (pdata->num_regulators > ACT8865_REG_NUM) {
  263. dev_err(dev, "Too many regulators found!\n");
  264. return -EINVAL;
  265. }
  266. act8865 = devm_kzalloc(dev, sizeof(struct act8865), GFP_KERNEL);
  267. if (!act8865)
  268. return -ENOMEM;
  269. rdev = act8865->rdev;
  270. act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config);
  271. if (IS_ERR(act8865->regmap)) {
  272. error = PTR_ERR(act8865->regmap);
  273. dev_err(&client->dev, "Failed to allocate register map: %d\n",
  274. error);
  275. return error;
  276. }
  277. /* Finally register devices */
  278. for (i = 0; i < ACT8865_REG_NUM; i++) {
  279. id = pdata->regulators[i].id;
  280. config.dev = dev;
  281. config.init_data = pdata->regulators[i].platform_data;
  282. config.of_node = of_node[i];
  283. config.driver_data = act8865;
  284. config.regmap = act8865->regmap;
  285. rdev[i] = devm_regulator_register(&client->dev,
  286. &act8865_reg[i], &config);
  287. if (IS_ERR(rdev[i])) {
  288. dev_err(dev, "failed to register %s\n",
  289. act8865_reg[id].name);
  290. return PTR_ERR(rdev[i]);
  291. }
  292. }
  293. i2c_set_clientdata(client, act8865);
  294. return 0;
  295. }
  296. static const struct i2c_device_id act8865_ids[] = {
  297. { "act8865", 0 },
  298. { },
  299. };
  300. MODULE_DEVICE_TABLE(i2c, act8865_ids);
  301. static struct i2c_driver act8865_pmic_driver = {
  302. .driver = {
  303. .name = "act8865",
  304. .owner = THIS_MODULE,
  305. },
  306. .probe = act8865_pmic_probe,
  307. .id_table = act8865_ids,
  308. };
  309. module_i2c_driver(act8865_pmic_driver);
  310. MODULE_DESCRIPTION("active-semi act8865 voltage regulator driver");
  311. MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
  312. MODULE_LICENSE("GPL v2");