exynos-pmu.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
  4. // http://www.samsung.com/
  5. //
  6. // Exynos - CPU PMU(Power Management Unit) support
  7. #include <linux/array_size.h>
  8. #include <linux/bitmap.h>
  9. #include <linux/cpuhotplug.h>
  10. #include <linux/cpu_pm.h>
  11. #include <linux/of.h>
  12. #include <linux/of_address.h>
  13. #include <linux/mfd/core.h>
  14. #include <linux/mfd/syscon.h>
  15. #include <linux/of_platform.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/delay.h>
  18. #include <linux/reboot.h>
  19. #include <linux/regmap.h>
  20. #include <linux/soc/samsung/exynos-regs-pmu.h>
  21. #include <linux/soc/samsung/exynos-pmu.h>
  22. #include "exynos-pmu.h"
  23. struct exynos_pmu_context {
  24. struct device *dev;
  25. const struct exynos_pmu_data *pmu_data;
  26. struct regmap *pmureg;
  27. struct regmap *pmuintrgen;
  28. /*
  29. * Serialization lock for CPU hot plug and cpuidle ACPM hint
  30. * programming. Also protects in_cpuhp, sys_insuspend & sys_inreboot
  31. * flags.
  32. */
  33. raw_spinlock_t cpupm_lock;
  34. unsigned long *in_cpuhp;
  35. bool sys_insuspend;
  36. bool sys_inreboot;
  37. };
  38. void __iomem *pmu_base_addr;
  39. static struct exynos_pmu_context *pmu_context;
  40. /* forward declaration */
  41. static struct platform_driver exynos_pmu_driver;
  42. void pmu_raw_writel(u32 val, u32 offset)
  43. {
  44. writel_relaxed(val, pmu_base_addr + offset);
  45. }
  46. u32 pmu_raw_readl(u32 offset)
  47. {
  48. return readl_relaxed(pmu_base_addr + offset);
  49. }
  50. void exynos_sys_powerdown_conf(enum sys_powerdown mode)
  51. {
  52. unsigned int i;
  53. const struct exynos_pmu_data *pmu_data;
  54. if (!pmu_context || !pmu_context->pmu_data)
  55. return;
  56. pmu_data = pmu_context->pmu_data;
  57. if (pmu_data->powerdown_conf)
  58. pmu_data->powerdown_conf(mode);
  59. if (pmu_data->pmu_config) {
  60. for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END); i++)
  61. pmu_raw_writel(pmu_data->pmu_config[i].val[mode],
  62. pmu_data->pmu_config[i].offset);
  63. }
  64. if (pmu_data->powerdown_conf_extra)
  65. pmu_data->powerdown_conf_extra(mode);
  66. if (pmu_data->pmu_config_extra) {
  67. for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
  68. pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode],
  69. pmu_data->pmu_config_extra[i].offset);
  70. }
  71. }
  72. /*
  73. * Split the data between ARM architectures because it is relatively big
  74. * and useless on other arch.
  75. */
  76. #ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
  77. #define exynos_pmu_data_arm_ptr(data) (&data)
  78. #else
  79. #define exynos_pmu_data_arm_ptr(data) NULL
  80. #endif
  81. static const struct regmap_config regmap_smccfg = {
  82. .name = "pmu_regs",
  83. .reg_bits = 32,
  84. .reg_stride = 4,
  85. .val_bits = 32,
  86. .fast_io = true,
  87. .use_single_read = true,
  88. .use_single_write = true,
  89. .reg_read = tensor_sec_reg_read,
  90. .reg_write = tensor_sec_reg_write,
  91. .reg_update_bits = tensor_sec_update_bits,
  92. .use_raw_spinlock = true,
  93. };
  94. static const struct regmap_config regmap_pmu_intr = {
  95. .name = "pmu_intr_gen",
  96. .reg_bits = 32,
  97. .reg_stride = 4,
  98. .val_bits = 32,
  99. .use_raw_spinlock = true,
  100. };
  101. /*
  102. * PMU platform driver and devicetree bindings.
  103. */
  104. static const struct of_device_id exynos_pmu_of_device_ids[] = {
  105. {
  106. .compatible = "google,gs101-pmu",
  107. .data = &gs101_pmu_data,
  108. }, {
  109. .compatible = "samsung,exynos3250-pmu",
  110. .data = exynos_pmu_data_arm_ptr(exynos3250_pmu_data),
  111. }, {
  112. .compatible = "samsung,exynos4210-pmu",
  113. .data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data),
  114. }, {
  115. .compatible = "samsung,exynos4212-pmu",
  116. .data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data),
  117. }, {
  118. .compatible = "samsung,exynos4412-pmu",
  119. .data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data),
  120. }, {
  121. .compatible = "samsung,exynos5250-pmu",
  122. .data = exynos_pmu_data_arm_ptr(exynos5250_pmu_data),
  123. }, {
  124. .compatible = "samsung,exynos5410-pmu",
  125. }, {
  126. .compatible = "samsung,exynos5420-pmu",
  127. .data = exynos_pmu_data_arm_ptr(exynos5420_pmu_data),
  128. }, {
  129. .compatible = "samsung,exynos5433-pmu",
  130. }, {
  131. .compatible = "samsung,exynos7-pmu",
  132. }, {
  133. .compatible = "samsung,exynos850-pmu",
  134. },
  135. { /*sentinel*/ },
  136. };
  137. static const struct mfd_cell exynos_pmu_devs[] = {
  138. { .name = "exynos-clkout", },
  139. };
  140. /**
  141. * exynos_get_pmu_regmap() - Obtain pmureg regmap
  142. *
  143. * Find the pmureg regmap previously configured in probe() and return regmap
  144. * pointer.
  145. *
  146. * Return: A pointer to regmap if found or ERR_PTR error value.
  147. */
  148. struct regmap *exynos_get_pmu_regmap(void)
  149. {
  150. struct device_node *np = of_find_matching_node(NULL,
  151. exynos_pmu_of_device_ids);
  152. if (np)
  153. return exynos_get_pmu_regmap_by_phandle(np, NULL);
  154. return ERR_PTR(-ENODEV);
  155. }
  156. EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap);
  157. /**
  158. * exynos_get_pmu_regmap_by_phandle() - Obtain pmureg regmap via phandle
  159. * @np: Device node holding PMU phandle property
  160. * @propname: Name of property holding phandle value
  161. *
  162. * Find the pmureg regmap previously configured in probe() and return regmap
  163. * pointer.
  164. *
  165. * Return: A pointer to regmap if found or ERR_PTR error value.
  166. */
  167. struct regmap *exynos_get_pmu_regmap_by_phandle(struct device_node *np,
  168. const char *propname)
  169. {
  170. struct device_node *pmu_np;
  171. struct device *dev;
  172. if (propname)
  173. pmu_np = of_parse_phandle(np, propname, 0);
  174. else
  175. pmu_np = np;
  176. if (!pmu_np)
  177. return ERR_PTR(-ENODEV);
  178. /*
  179. * Determine if exynos-pmu device has probed and therefore regmap
  180. * has been created and can be returned to the caller. Otherwise we
  181. * return -EPROBE_DEFER.
  182. */
  183. dev = driver_find_device_by_of_node(&exynos_pmu_driver.driver,
  184. (void *)pmu_np);
  185. if (propname)
  186. of_node_put(pmu_np);
  187. if (!dev)
  188. return ERR_PTR(-EPROBE_DEFER);
  189. put_device(dev);
  190. return syscon_node_to_regmap(pmu_np);
  191. }
  192. EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle);
  193. /*
  194. * CPU_INFORM register "hint" values are required to be programmed in addition to
  195. * the standard PSCI calls to have functional CPU hotplug and CPU idle states.
  196. * This is required to workaround limitations in the el3mon/ACPM firmware.
  197. */
  198. #define CPU_INFORM_CLEAR 0
  199. #define CPU_INFORM_C2 1
  200. /*
  201. * __gs101_cpu_pmu_ prefix functions are common code shared by CPU PM notifiers
  202. * (CPUIdle) and CPU hotplug callbacks. Functions should be called with IRQs
  203. * disabled and cpupm_lock held.
  204. */
  205. static int __gs101_cpu_pmu_online(unsigned int cpu)
  206. __must_hold(&pmu_context->cpupm_lock)
  207. {
  208. unsigned int cpuhint = smp_processor_id();
  209. u32 reg, mask;
  210. /* clear cpu inform hint */
  211. regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint),
  212. CPU_INFORM_CLEAR);
  213. mask = BIT(cpu);
  214. regmap_update_bits(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_ENABLE,
  215. mask, (0 << cpu));
  216. regmap_read(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_UPEND, &reg);
  217. regmap_write(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_CLEAR,
  218. reg & mask);
  219. return 0;
  220. }
  221. /* Called from CPU PM notifier (CPUIdle code path) with IRQs disabled */
  222. static int gs101_cpu_pmu_online(void)
  223. {
  224. int cpu;
  225. raw_spin_lock(&pmu_context->cpupm_lock);
  226. if (pmu_context->sys_inreboot) {
  227. raw_spin_unlock(&pmu_context->cpupm_lock);
  228. return NOTIFY_OK;
  229. }
  230. cpu = smp_processor_id();
  231. __gs101_cpu_pmu_online(cpu);
  232. raw_spin_unlock(&pmu_context->cpupm_lock);
  233. return NOTIFY_OK;
  234. }
  235. /* Called from CPU hot plug callback with IRQs enabled */
  236. static int gs101_cpuhp_pmu_online(unsigned int cpu)
  237. {
  238. unsigned long flags;
  239. raw_spin_lock_irqsave(&pmu_context->cpupm_lock, flags);
  240. __gs101_cpu_pmu_online(cpu);
  241. /*
  242. * Mark this CPU as having finished the hotplug.
  243. * This means this CPU can now enter C2 idle state.
  244. */
  245. clear_bit(cpu, pmu_context->in_cpuhp);
  246. raw_spin_unlock_irqrestore(&pmu_context->cpupm_lock, flags);
  247. return 0;
  248. }
  249. /* Common function shared by both CPU hot plug and CPUIdle */
  250. static int __gs101_cpu_pmu_offline(unsigned int cpu)
  251. __must_hold(&pmu_context->cpupm_lock)
  252. {
  253. unsigned int cpuhint = smp_processor_id();
  254. u32 reg, mask;
  255. /* set cpu inform hint */
  256. regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint),
  257. CPU_INFORM_C2);
  258. mask = BIT(cpu);
  259. regmap_update_bits(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_ENABLE,
  260. mask, BIT(cpu));
  261. regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, &reg);
  262. regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR,
  263. reg & mask);
  264. mask = (BIT(cpu + 8));
  265. regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, &reg);
  266. regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR,
  267. reg & mask);
  268. return 0;
  269. }
  270. /* Called from CPU PM notifier (CPUIdle code path) with IRQs disabled */
  271. static int gs101_cpu_pmu_offline(void)
  272. {
  273. int cpu;
  274. raw_spin_lock(&pmu_context->cpupm_lock);
  275. cpu = smp_processor_id();
  276. if (test_bit(cpu, pmu_context->in_cpuhp)) {
  277. raw_spin_unlock(&pmu_context->cpupm_lock);
  278. return NOTIFY_BAD;
  279. }
  280. /* Ignore CPU_PM_ENTER event in reboot or suspend sequence. */
  281. if (pmu_context->sys_insuspend || pmu_context->sys_inreboot) {
  282. raw_spin_unlock(&pmu_context->cpupm_lock);
  283. return NOTIFY_OK;
  284. }
  285. __gs101_cpu_pmu_offline(cpu);
  286. raw_spin_unlock(&pmu_context->cpupm_lock);
  287. return NOTIFY_OK;
  288. }
  289. /* Called from CPU hot plug callback with IRQs enabled */
  290. static int gs101_cpuhp_pmu_offline(unsigned int cpu)
  291. {
  292. unsigned long flags;
  293. raw_spin_lock_irqsave(&pmu_context->cpupm_lock, flags);
  294. /*
  295. * Mark this CPU as entering hotplug. So as not to confuse
  296. * ACPM the CPU entering hotplug should not enter C2 idle state.
  297. */
  298. set_bit(cpu, pmu_context->in_cpuhp);
  299. __gs101_cpu_pmu_offline(cpu);
  300. raw_spin_unlock_irqrestore(&pmu_context->cpupm_lock, flags);
  301. return 0;
  302. }
  303. static int gs101_cpu_pm_notify_callback(struct notifier_block *self,
  304. unsigned long action, void *v)
  305. {
  306. switch (action) {
  307. case CPU_PM_ENTER:
  308. return gs101_cpu_pmu_offline();
  309. case CPU_PM_EXIT:
  310. return gs101_cpu_pmu_online();
  311. }
  312. return NOTIFY_OK;
  313. }
  314. static struct notifier_block gs101_cpu_pm_notifier = {
  315. .notifier_call = gs101_cpu_pm_notify_callback,
  316. /*
  317. * We want to be called first, as the ACPM hint and handshake is what
  318. * puts the CPU into C2.
  319. */
  320. .priority = INT_MAX
  321. };
  322. static int exynos_cpupm_reboot_notifier(struct notifier_block *nb,
  323. unsigned long event, void *v)
  324. {
  325. unsigned long flags;
  326. switch (event) {
  327. case SYS_POWER_OFF:
  328. case SYS_RESTART:
  329. raw_spin_lock_irqsave(&pmu_context->cpupm_lock, flags);
  330. pmu_context->sys_inreboot = true;
  331. raw_spin_unlock_irqrestore(&pmu_context->cpupm_lock, flags);
  332. break;
  333. }
  334. return NOTIFY_OK;
  335. }
  336. static struct notifier_block exynos_cpupm_reboot_nb = {
  337. .priority = INT_MAX,
  338. .notifier_call = exynos_cpupm_reboot_notifier,
  339. };
  340. static int setup_cpuhp_and_cpuidle(struct device *dev)
  341. {
  342. struct device_node *intr_gen_node;
  343. struct resource intrgen_res;
  344. void __iomem *virt_addr;
  345. int ret, cpu;
  346. intr_gen_node = of_parse_phandle(dev->of_node,
  347. "google,pmu-intr-gen-syscon", 0);
  348. if (!intr_gen_node) {
  349. /*
  350. * To maintain support for older DTs that didn't specify syscon
  351. * phandle just issue a warning rather than fail to probe.
  352. */
  353. dev_warn(dev, "pmu-intr-gen syscon unavailable\n");
  354. return 0;
  355. }
  356. /*
  357. * To avoid lockdep issues (CPU PM notifiers use raw spinlocks) create
  358. * a mmio regmap for pmu-intr-gen that uses raw spinlocks instead of
  359. * syscon provided regmap.
  360. */
  361. ret = of_address_to_resource(intr_gen_node, 0, &intrgen_res);
  362. of_node_put(intr_gen_node);
  363. virt_addr = devm_ioremap(dev, intrgen_res.start,
  364. resource_size(&intrgen_res));
  365. if (!virt_addr)
  366. return -ENOMEM;
  367. pmu_context->pmuintrgen = devm_regmap_init_mmio(dev, virt_addr,
  368. &regmap_pmu_intr);
  369. if (IS_ERR(pmu_context->pmuintrgen)) {
  370. dev_err(dev, "failed to initialize pmu-intr-gen regmap\n");
  371. return PTR_ERR(pmu_context->pmuintrgen);
  372. }
  373. /* register custom mmio regmap with syscon */
  374. ret = of_syscon_register_regmap(intr_gen_node,
  375. pmu_context->pmuintrgen);
  376. if (ret)
  377. return ret;
  378. pmu_context->in_cpuhp = devm_bitmap_zalloc(dev, num_possible_cpus(),
  379. GFP_KERNEL);
  380. if (!pmu_context->in_cpuhp)
  381. return -ENOMEM;
  382. /* set PMU to power on */
  383. for_each_online_cpu(cpu)
  384. gs101_cpuhp_pmu_online(cpu);
  385. /* register CPU hotplug callbacks */
  386. cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare",
  387. gs101_cpuhp_pmu_online, NULL);
  388. cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online",
  389. NULL, gs101_cpuhp_pmu_offline);
  390. /* register CPU PM notifiers for cpuidle */
  391. cpu_pm_register_notifier(&gs101_cpu_pm_notifier);
  392. register_reboot_notifier(&exynos_cpupm_reboot_nb);
  393. return 0;
  394. }
  395. static int exynos_pmu_probe(struct platform_device *pdev)
  396. {
  397. struct device *dev = &pdev->dev;
  398. struct regmap_config pmu_regmcfg;
  399. struct regmap *regmap;
  400. struct resource *res;
  401. int ret;
  402. pmu_base_addr = devm_platform_ioremap_resource(pdev, 0);
  403. if (IS_ERR(pmu_base_addr))
  404. return PTR_ERR(pmu_base_addr);
  405. pmu_context = devm_kzalloc(&pdev->dev,
  406. sizeof(struct exynos_pmu_context),
  407. GFP_KERNEL);
  408. if (!pmu_context)
  409. return -ENOMEM;
  410. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  411. if (!res)
  412. return -ENODEV;
  413. pmu_context->pmu_data = of_device_get_match_data(dev);
  414. /* For SoCs that secure PMU register writes use custom regmap */
  415. if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_secure) {
  416. pmu_regmcfg = regmap_smccfg;
  417. pmu_regmcfg.max_register = resource_size(res) -
  418. pmu_regmcfg.reg_stride;
  419. pmu_regmcfg.wr_table = pmu_context->pmu_data->wr_table;
  420. pmu_regmcfg.rd_table = pmu_context->pmu_data->rd_table;
  421. /* Need physical address for SMC call */
  422. regmap = devm_regmap_init(dev, NULL,
  423. (void *)(uintptr_t)res->start,
  424. &pmu_regmcfg);
  425. if (IS_ERR(regmap))
  426. return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
  427. "regmap init failed\n");
  428. ret = of_syscon_register_regmap(dev->of_node, regmap);
  429. if (ret)
  430. return ret;
  431. } else {
  432. /* let syscon create mmio regmap */
  433. regmap = syscon_node_to_regmap(dev->of_node);
  434. if (IS_ERR(regmap))
  435. return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
  436. "syscon_node_to_regmap failed\n");
  437. }
  438. pmu_context->pmureg = regmap;
  439. pmu_context->dev = dev;
  440. raw_spin_lock_init(&pmu_context->cpupm_lock);
  441. pmu_context->sys_inreboot = false;
  442. pmu_context->sys_insuspend = false;
  443. if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) {
  444. ret = setup_cpuhp_and_cpuidle(dev);
  445. if (ret)
  446. return ret;
  447. }
  448. if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_init)
  449. pmu_context->pmu_data->pmu_init();
  450. platform_set_drvdata(pdev, pmu_context);
  451. ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, exynos_pmu_devs,
  452. ARRAY_SIZE(exynos_pmu_devs), NULL, 0, NULL);
  453. if (ret)
  454. return ret;
  455. if (devm_of_platform_populate(dev))
  456. dev_err(dev, "Error populating children, reboot and poweroff might not work properly\n");
  457. dev_dbg(dev, "Exynos PMU Driver probe done\n");
  458. return 0;
  459. }
  460. static int exynos_cpupm_suspend_noirq(struct device *dev)
  461. {
  462. raw_spin_lock(&pmu_context->cpupm_lock);
  463. pmu_context->sys_insuspend = true;
  464. raw_spin_unlock(&pmu_context->cpupm_lock);
  465. return 0;
  466. }
  467. static int exynos_cpupm_resume_noirq(struct device *dev)
  468. {
  469. raw_spin_lock(&pmu_context->cpupm_lock);
  470. pmu_context->sys_insuspend = false;
  471. raw_spin_unlock(&pmu_context->cpupm_lock);
  472. return 0;
  473. }
  474. static const struct dev_pm_ops cpupm_pm_ops = {
  475. NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos_cpupm_suspend_noirq,
  476. exynos_cpupm_resume_noirq)
  477. };
  478. static struct platform_driver exynos_pmu_driver = {
  479. .driver = {
  480. .name = "exynos-pmu",
  481. .of_match_table = exynos_pmu_of_device_ids,
  482. .pm = pm_sleep_ptr(&cpupm_pm_ops),
  483. },
  484. .probe = exynos_pmu_probe,
  485. };
  486. static int __init exynos_pmu_init(void)
  487. {
  488. return platform_driver_register(&exynos_pmu_driver);
  489. }
  490. postcore_initcall(exynos_pmu_init);