rockchip-io-domain.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * Rockchip IO Voltage Domain driver
  3. *
  4. * Copyright 2014 MundoReader S.L.
  5. * Copyright 2014 Google, Inc.
  6. *
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/err.h>
  19. #include <linux/mfd/syscon.h>
  20. #include <linux/of.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/regmap.h>
  23. #include <linux/regulator/consumer.h>
  24. #define MAX_SUPPLIES 16
  25. /*
  26. * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
  27. * "Recommended Operating Conditions" for "Digital GPIO". When the typical
  28. * is 3.3V the max is 3.6V. When the typical is 1.8V the max is 1.98V.
  29. *
  30. * They are used like this:
  31. * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
  32. * SoC we're at 3.3.
  33. * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
  34. * that to be an error.
  35. */
  36. #define MAX_VOLTAGE_1_8 1980000
  37. #define MAX_VOLTAGE_3_3 3600000
  38. #define RK3288_SOC_CON2 0x24c
  39. #define RK3288_SOC_CON2_FLASH0 BIT(7)
  40. #define RK3288_SOC_FLASH_SUPPLY_NUM 2
  41. #define RK3368_SOC_CON15 0x43c
  42. #define RK3368_SOC_CON15_FLASH0 BIT(14)
  43. #define RK3368_SOC_FLASH_SUPPLY_NUM 2
  44. struct rockchip_iodomain;
  45. /**
  46. * @supplies: voltage settings matching the register bits.
  47. */
  48. struct rockchip_iodomain_soc_data {
  49. int grf_offset;
  50. const char *supply_names[MAX_SUPPLIES];
  51. void (*init)(struct rockchip_iodomain *iod);
  52. };
  53. struct rockchip_iodomain_supply {
  54. struct rockchip_iodomain *iod;
  55. struct regulator *reg;
  56. struct notifier_block nb;
  57. int idx;
  58. };
  59. struct rockchip_iodomain {
  60. struct device *dev;
  61. struct regmap *grf;
  62. struct rockchip_iodomain_soc_data *soc_data;
  63. struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
  64. };
  65. static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
  66. int uV)
  67. {
  68. struct rockchip_iodomain *iod = supply->iod;
  69. u32 val;
  70. int ret;
  71. /* set value bit */
  72. val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
  73. val <<= supply->idx;
  74. /* apply hiword-mask */
  75. val |= (BIT(supply->idx) << 16);
  76. ret = regmap_write(iod->grf, iod->soc_data->grf_offset, val);
  77. if (ret)
  78. dev_err(iod->dev, "Couldn't write to GRF\n");
  79. return ret;
  80. }
  81. static int rockchip_iodomain_notify(struct notifier_block *nb,
  82. unsigned long event,
  83. void *data)
  84. {
  85. struct rockchip_iodomain_supply *supply =
  86. container_of(nb, struct rockchip_iodomain_supply, nb);
  87. int uV;
  88. int ret;
  89. /*
  90. * According to Rockchip it's important to keep the SoC IO domain
  91. * higher than (or equal to) the external voltage. That means we need
  92. * to change it before external voltage changes happen in the case
  93. * of an increase.
  94. *
  95. * Note that in the "pre" change we pick the max possible voltage that
  96. * the regulator might end up at (the client requests a range and we
  97. * don't know for certain the exact voltage). Right now we rely on the
  98. * slop in MAX_VOLTAGE_1_8 and MAX_VOLTAGE_3_3 to save us if clients
  99. * request something like a max of 3.6V when they really want 3.3V.
  100. * We could attempt to come up with better rules if this fails.
  101. */
  102. if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
  103. struct pre_voltage_change_data *pvc_data = data;
  104. uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV);
  105. } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE |
  106. REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) {
  107. uV = (unsigned long)data;
  108. } else {
  109. return NOTIFY_OK;
  110. }
  111. dev_dbg(supply->iod->dev, "Setting to %d\n", uV);
  112. if (uV > MAX_VOLTAGE_3_3) {
  113. dev_err(supply->iod->dev, "Voltage too high: %d\n", uV);
  114. if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
  115. return NOTIFY_BAD;
  116. }
  117. ret = rockchip_iodomain_write(supply, uV);
  118. if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
  119. return NOTIFY_BAD;
  120. dev_info(supply->iod->dev, "Setting to %d done\n", uV);
  121. return NOTIFY_OK;
  122. }
  123. static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
  124. {
  125. int ret;
  126. u32 val;
  127. /* if no flash supply we should leave things alone */
  128. if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
  129. return;
  130. /*
  131. * set flash0 iodomain to also use this framework
  132. * instead of a special gpio.
  133. */
  134. val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
  135. ret = regmap_write(iod->grf, RK3288_SOC_CON2, val);
  136. if (ret < 0)
  137. dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
  138. }
  139. static void rk3368_iodomain_init(struct rockchip_iodomain *iod)
  140. {
  141. int ret;
  142. u32 val;
  143. /* if no flash supply we should leave things alone */
  144. if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
  145. return;
  146. /*
  147. * set flash0 iodomain to also use this framework
  148. * instead of a special gpio.
  149. */
  150. val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
  151. ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
  152. if (ret < 0)
  153. dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
  154. }
  155. /*
  156. * On the rk3188 the io-domains are handled by a shared register with the
  157. * lower 8 bits being still being continuing drive-strength settings.
  158. */
  159. static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
  160. .grf_offset = 0x104,
  161. .supply_names = {
  162. NULL,
  163. NULL,
  164. NULL,
  165. NULL,
  166. NULL,
  167. NULL,
  168. NULL,
  169. NULL,
  170. "ap0",
  171. "ap1",
  172. "cif",
  173. "flash",
  174. "vccio0",
  175. "vccio1",
  176. "lcdc0",
  177. "lcdc1",
  178. },
  179. };
  180. static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
  181. .grf_offset = 0x380,
  182. .supply_names = {
  183. "lcdc", /* LCDC_VDD */
  184. "dvp", /* DVPIO_VDD */
  185. "flash0", /* FLASH0_VDD (emmc) */
  186. "flash1", /* FLASH1_VDD (sdio1) */
  187. "wifi", /* APIO3_VDD (sdio0) */
  188. "bb", /* APIO5_VDD */
  189. "audio", /* APIO4_VDD */
  190. "sdcard", /* SDMMC0_VDD (sdmmc) */
  191. "gpio30", /* APIO1_VDD */
  192. "gpio1830", /* APIO2_VDD */
  193. },
  194. .init = rk3288_iodomain_init,
  195. };
  196. static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
  197. .grf_offset = 0x900,
  198. .supply_names = {
  199. NULL, /* reserved */
  200. "dvp", /* DVPIO_VDD */
  201. "flash0", /* FLASH0_VDD (emmc) */
  202. "wifi", /* APIO2_VDD (sdio0) */
  203. NULL,
  204. "audio", /* APIO3_VDD */
  205. "sdcard", /* SDMMC0_VDD (sdmmc) */
  206. "gpio30", /* APIO1_VDD */
  207. "gpio1830", /* APIO4_VDD (gpujtag) */
  208. },
  209. .init = rk3368_iodomain_init,
  210. };
  211. static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
  212. .grf_offset = 0x100,
  213. .supply_names = {
  214. NULL,
  215. NULL,
  216. NULL,
  217. NULL,
  218. "pmu", /*PMU IO domain*/
  219. "vop", /*LCDC IO domain*/
  220. },
  221. };
  222. static const struct of_device_id rockchip_iodomain_match[] = {
  223. {
  224. .compatible = "rockchip,rk3188-io-voltage-domain",
  225. .data = (void *)&soc_data_rk3188
  226. },
  227. {
  228. .compatible = "rockchip,rk3288-io-voltage-domain",
  229. .data = (void *)&soc_data_rk3288
  230. },
  231. {
  232. .compatible = "rockchip,rk3368-io-voltage-domain",
  233. .data = (void *)&soc_data_rk3368
  234. },
  235. {
  236. .compatible = "rockchip,rk3368-pmu-io-voltage-domain",
  237. .data = (void *)&soc_data_rk3368_pmu
  238. },
  239. { /* sentinel */ },
  240. };
  241. static int rockchip_iodomain_probe(struct platform_device *pdev)
  242. {
  243. struct device_node *np = pdev->dev.of_node;
  244. const struct of_device_id *match;
  245. struct rockchip_iodomain *iod;
  246. int i, ret = 0;
  247. if (!np)
  248. return -ENODEV;
  249. iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
  250. if (!iod)
  251. return -ENOMEM;
  252. iod->dev = &pdev->dev;
  253. platform_set_drvdata(pdev, iod);
  254. match = of_match_node(rockchip_iodomain_match, np);
  255. iod->soc_data = (struct rockchip_iodomain_soc_data *)match->data;
  256. iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
  257. if (IS_ERR(iod->grf)) {
  258. dev_err(&pdev->dev, "couldn't find grf regmap\n");
  259. return PTR_ERR(iod->grf);
  260. }
  261. for (i = 0; i < MAX_SUPPLIES; i++) {
  262. const char *supply_name = iod->soc_data->supply_names[i];
  263. struct rockchip_iodomain_supply *supply = &iod->supplies[i];
  264. struct regulator *reg;
  265. int uV;
  266. if (!supply_name)
  267. continue;
  268. reg = devm_regulator_get_optional(iod->dev, supply_name);
  269. if (IS_ERR(reg)) {
  270. ret = PTR_ERR(reg);
  271. /* If a supply wasn't specified, that's OK */
  272. if (ret == -ENODEV)
  273. continue;
  274. else if (ret != -EPROBE_DEFER)
  275. dev_err(iod->dev, "couldn't get regulator %s\n",
  276. supply_name);
  277. goto unreg_notify;
  278. }
  279. /* set initial correct value */
  280. uV = regulator_get_voltage(reg);
  281. /* must be a regulator we can get the voltage of */
  282. if (uV < 0) {
  283. dev_err(iod->dev, "Can't determine voltage: %s\n",
  284. supply_name);
  285. goto unreg_notify;
  286. }
  287. if (uV > MAX_VOLTAGE_3_3) {
  288. dev_crit(iod->dev,
  289. "%d uV is too high. May damage SoC!\n",
  290. uV);
  291. ret = -EINVAL;
  292. goto unreg_notify;
  293. }
  294. /* setup our supply */
  295. supply->idx = i;
  296. supply->iod = iod;
  297. supply->reg = reg;
  298. supply->nb.notifier_call = rockchip_iodomain_notify;
  299. ret = rockchip_iodomain_write(supply, uV);
  300. if (ret) {
  301. supply->reg = NULL;
  302. goto unreg_notify;
  303. }
  304. /* register regulator notifier */
  305. ret = regulator_register_notifier(reg, &supply->nb);
  306. if (ret) {
  307. dev_err(&pdev->dev,
  308. "regulator notifier request failed\n");
  309. supply->reg = NULL;
  310. goto unreg_notify;
  311. }
  312. }
  313. if (iod->soc_data->init)
  314. iod->soc_data->init(iod);
  315. return 0;
  316. unreg_notify:
  317. for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
  318. struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
  319. if (io_supply->reg)
  320. regulator_unregister_notifier(io_supply->reg,
  321. &io_supply->nb);
  322. }
  323. return ret;
  324. }
  325. static int rockchip_iodomain_remove(struct platform_device *pdev)
  326. {
  327. struct rockchip_iodomain *iod = platform_get_drvdata(pdev);
  328. int i;
  329. for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
  330. struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
  331. if (io_supply->reg)
  332. regulator_unregister_notifier(io_supply->reg,
  333. &io_supply->nb);
  334. }
  335. return 0;
  336. }
  337. static struct platform_driver rockchip_iodomain_driver = {
  338. .probe = rockchip_iodomain_probe,
  339. .remove = rockchip_iodomain_remove,
  340. .driver = {
  341. .name = "rockchip-iodomain",
  342. .of_match_table = rockchip_iodomain_match,
  343. },
  344. };
  345. module_platform_driver(rockchip_iodomain_driver);
  346. MODULE_DESCRIPTION("Rockchip IO-domain driver");
  347. MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
  348. MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
  349. MODULE_LICENSE("GPL v2");