act8865-regulator.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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 regmap *regmap;
  61. };
  62. static const struct regmap_config act8865_regmap_config = {
  63. .reg_bits = 8,
  64. .val_bits = 8,
  65. };
  66. static const struct regulator_linear_range act8865_volatge_ranges[] = {
  67. REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
  68. REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
  69. REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
  70. };
  71. static struct regulator_ops act8865_ops = {
  72. .list_voltage = regulator_list_voltage_linear_range,
  73. .map_voltage = regulator_map_voltage_linear_range,
  74. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  75. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  76. .enable = regulator_enable_regmap,
  77. .disable = regulator_disable_regmap,
  78. .is_enabled = regulator_is_enabled_regmap,
  79. };
  80. static const struct regulator_desc act8865_reg[] = {
  81. {
  82. .name = "DCDC_REG1",
  83. .id = ACT8865_ID_DCDC1,
  84. .ops = &act8865_ops,
  85. .type = REGULATOR_VOLTAGE,
  86. .n_voltages = ACT8865_VOLTAGE_NUM,
  87. .linear_ranges = act8865_volatge_ranges,
  88. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  89. .vsel_reg = ACT8865_DCDC1_VSET1,
  90. .vsel_mask = ACT8865_VSEL_MASK,
  91. .enable_reg = ACT8865_DCDC1_CTRL,
  92. .enable_mask = ACT8865_ENA,
  93. .owner = THIS_MODULE,
  94. },
  95. {
  96. .name = "DCDC_REG2",
  97. .id = ACT8865_ID_DCDC2,
  98. .ops = &act8865_ops,
  99. .type = REGULATOR_VOLTAGE,
  100. .n_voltages = ACT8865_VOLTAGE_NUM,
  101. .linear_ranges = act8865_volatge_ranges,
  102. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  103. .vsel_reg = ACT8865_DCDC2_VSET1,
  104. .vsel_mask = ACT8865_VSEL_MASK,
  105. .enable_reg = ACT8865_DCDC2_CTRL,
  106. .enable_mask = ACT8865_ENA,
  107. .owner = THIS_MODULE,
  108. },
  109. {
  110. .name = "DCDC_REG3",
  111. .id = ACT8865_ID_DCDC3,
  112. .ops = &act8865_ops,
  113. .type = REGULATOR_VOLTAGE,
  114. .n_voltages = ACT8865_VOLTAGE_NUM,
  115. .linear_ranges = act8865_volatge_ranges,
  116. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  117. .vsel_reg = ACT8865_DCDC3_VSET1,
  118. .vsel_mask = ACT8865_VSEL_MASK,
  119. .enable_reg = ACT8865_DCDC3_CTRL,
  120. .enable_mask = ACT8865_ENA,
  121. .owner = THIS_MODULE,
  122. },
  123. {
  124. .name = "LDO_REG1",
  125. .id = ACT8865_ID_LDO1,
  126. .ops = &act8865_ops,
  127. .type = REGULATOR_VOLTAGE,
  128. .n_voltages = ACT8865_VOLTAGE_NUM,
  129. .linear_ranges = act8865_volatge_ranges,
  130. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  131. .vsel_reg = ACT8865_LDO1_VSET,
  132. .vsel_mask = ACT8865_VSEL_MASK,
  133. .enable_reg = ACT8865_LDO1_CTRL,
  134. .enable_mask = ACT8865_ENA,
  135. .owner = THIS_MODULE,
  136. },
  137. {
  138. .name = "LDO_REG2",
  139. .id = ACT8865_ID_LDO2,
  140. .ops = &act8865_ops,
  141. .type = REGULATOR_VOLTAGE,
  142. .n_voltages = ACT8865_VOLTAGE_NUM,
  143. .linear_ranges = act8865_volatge_ranges,
  144. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  145. .vsel_reg = ACT8865_LDO2_VSET,
  146. .vsel_mask = ACT8865_VSEL_MASK,
  147. .enable_reg = ACT8865_LDO2_CTRL,
  148. .enable_mask = ACT8865_ENA,
  149. .owner = THIS_MODULE,
  150. },
  151. {
  152. .name = "LDO_REG3",
  153. .id = ACT8865_ID_LDO3,
  154. .ops = &act8865_ops,
  155. .type = REGULATOR_VOLTAGE,
  156. .n_voltages = ACT8865_VOLTAGE_NUM,
  157. .linear_ranges = act8865_volatge_ranges,
  158. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  159. .vsel_reg = ACT8865_LDO3_VSET,
  160. .vsel_mask = ACT8865_VSEL_MASK,
  161. .enable_reg = ACT8865_LDO3_CTRL,
  162. .enable_mask = ACT8865_ENA,
  163. .owner = THIS_MODULE,
  164. },
  165. {
  166. .name = "LDO_REG4",
  167. .id = ACT8865_ID_LDO4,
  168. .ops = &act8865_ops,
  169. .type = REGULATOR_VOLTAGE,
  170. .n_voltages = ACT8865_VOLTAGE_NUM,
  171. .linear_ranges = act8865_volatge_ranges,
  172. .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
  173. .vsel_reg = ACT8865_LDO4_VSET,
  174. .vsel_mask = ACT8865_VSEL_MASK,
  175. .enable_reg = ACT8865_LDO4_CTRL,
  176. .enable_mask = ACT8865_ENA,
  177. .owner = THIS_MODULE,
  178. },
  179. };
  180. #ifdef CONFIG_OF
  181. static const struct of_device_id act8865_dt_ids[] = {
  182. { .compatible = "active-semi,act8865" },
  183. { }
  184. };
  185. MODULE_DEVICE_TABLE(of, act8865_dt_ids);
  186. static struct of_regulator_match act8865_matches[] = {
  187. [ACT8865_ID_DCDC1] = { .name = "DCDC_REG1"},
  188. [ACT8865_ID_DCDC2] = { .name = "DCDC_REG2"},
  189. [ACT8865_ID_DCDC3] = { .name = "DCDC_REG3"},
  190. [ACT8865_ID_LDO1] = { .name = "LDO_REG1"},
  191. [ACT8865_ID_LDO2] = { .name = "LDO_REG2"},
  192. [ACT8865_ID_LDO3] = { .name = "LDO_REG3"},
  193. [ACT8865_ID_LDO4] = { .name = "LDO_REG4"},
  194. };
  195. static int act8865_pdata_from_dt(struct device *dev,
  196. struct device_node **of_node,
  197. struct act8865_platform_data *pdata)
  198. {
  199. int matched, i;
  200. struct device_node *np;
  201. struct act8865_regulator_data *regulator;
  202. np = of_get_child_by_name(dev->of_node, "regulators");
  203. if (!np) {
  204. dev_err(dev, "missing 'regulators' subnode in DT\n");
  205. return -EINVAL;
  206. }
  207. matched = of_regulator_match(dev, np,
  208. act8865_matches, ARRAY_SIZE(act8865_matches));
  209. of_node_put(np);
  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. return -ENOMEM;
  217. pdata->num_regulators = matched;
  218. regulator = pdata->regulators;
  219. for (i = 0; i < ARRAY_SIZE(act8865_matches); i++) {
  220. regulator->id = i;
  221. regulator->name = act8865_matches[i].name;
  222. regulator->platform_data = act8865_matches[i].init_data;
  223. of_node[i] = act8865_matches[i].of_node;
  224. regulator++;
  225. }
  226. return 0;
  227. }
  228. #else
  229. static inline int act8865_pdata_from_dt(struct device *dev,
  230. struct device_node **of_node,
  231. struct act8865_platform_data *pdata)
  232. {
  233. return 0;
  234. }
  235. #endif
  236. static int act8865_pmic_probe(struct i2c_client *client,
  237. const struct i2c_device_id *i2c_id)
  238. {
  239. struct regulator_dev *rdev;
  240. struct device *dev = &client->dev;
  241. struct act8865_platform_data *pdata = dev_get_platdata(dev);
  242. struct regulator_config config = { };
  243. struct act8865 *act8865;
  244. struct device_node *of_node[ACT8865_REG_NUM];
  245. int i, id;
  246. int ret = -EINVAL;
  247. int error;
  248. if (dev->of_node && !pdata) {
  249. const struct of_device_id *id;
  250. struct act8865_platform_data pdata_of;
  251. id = of_match_device(of_match_ptr(act8865_dt_ids), dev);
  252. if (!id)
  253. return -ENODEV;
  254. ret = act8865_pdata_from_dt(dev, of_node, &pdata_of);
  255. if (ret < 0)
  256. return ret;
  257. pdata = &pdata_of;
  258. }
  259. if (pdata->num_regulators > ACT8865_REG_NUM) {
  260. dev_err(dev, "Too many regulators found!\n");
  261. return -EINVAL;
  262. }
  263. act8865 = devm_kzalloc(dev, sizeof(struct act8865), GFP_KERNEL);
  264. if (!act8865)
  265. return -ENOMEM;
  266. act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config);
  267. if (IS_ERR(act8865->regmap)) {
  268. error = PTR_ERR(act8865->regmap);
  269. dev_err(&client->dev, "Failed to allocate register map: %d\n",
  270. error);
  271. return error;
  272. }
  273. /* Finally register devices */
  274. for (i = 0; i < ACT8865_REG_NUM; i++) {
  275. id = pdata->regulators[i].id;
  276. config.dev = dev;
  277. config.init_data = pdata->regulators[i].platform_data;
  278. config.of_node = of_node[i];
  279. config.driver_data = act8865;
  280. config.regmap = act8865->regmap;
  281. rdev = devm_regulator_register(&client->dev, &act8865_reg[i],
  282. &config);
  283. if (IS_ERR(rdev)) {
  284. dev_err(dev, "failed to register %s\n",
  285. act8865_reg[id].name);
  286. return PTR_ERR(rdev);
  287. }
  288. }
  289. i2c_set_clientdata(client, act8865);
  290. return 0;
  291. }
  292. static const struct i2c_device_id act8865_ids[] = {
  293. { "act8865", 0 },
  294. { },
  295. };
  296. MODULE_DEVICE_TABLE(i2c, act8865_ids);
  297. static struct i2c_driver act8865_pmic_driver = {
  298. .driver = {
  299. .name = "act8865",
  300. .owner = THIS_MODULE,
  301. },
  302. .probe = act8865_pmic_probe,
  303. .id_table = act8865_ids,
  304. };
  305. module_i2c_driver(act8865_pmic_driver);
  306. MODULE_DESCRIPTION("active-semi act8865 voltage regulator driver");
  307. MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
  308. MODULE_LICENSE("GPL v2");