Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'pmdomain-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm

Pull pmdomain updates from Ulf Hansson:
"pmdomain core:
- Leave powered-on genpds on until ->sync_state() or late_initcall_sync
- Export a common ->sync_state() helper for genpd providers
- Add generic ->sync_state() support
- Add a bus/driver for genpd provider-devices
- Introduce dev_pm_genpd_is_on() for consumers

pmdomain providers:
- cpuidle-psci: Drop redundant ->sync_state() support
- cpuidle-riscv-sbi: Drop redundant ->sync_state() support
- imx: Set ISI panic write for imx8m-blk-ctrl
- qcom: Add support for Glymur and Milos RPMh power-domains
- qcom: Use of_genpd_sync_state() for power-domains
- rockchip: Add support for the RK3528 variant
- samsung: Fix splash-screen handover by enforcing a ->sync_state()
- sunxi: Add support for Allwinner A523's PCK600 power-controller
- tegra: Opt-out from genpd's common ->sync_state() support for pmc
- thead: Instantiate a GPU power sequencer via the auxiliary bus
- renesas: Move init to postcore_initcalls
- xilinx: Move ->sync_state() support to firmware driver
- xilinx: Use of_genpd_sync_state() for power-domains

pmdomain consumers:
- remoteproc: imx_rproc: Fixup the detect/attach procedure for
pre-booted cores"

* tag 'pmdomain-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: (44 commits)
pmdomain: qcom: rpmhpd: Add Glymur RPMh Power Domains
dt-bindings: power: rpmpd: Add Glymur power domains
remoteproc: imx_rproc: detect and attach to pre-booted remote cores
remoteproc: imx_rproc: skip clock enable when M-core is managed by the SCU
pmdomain: core: introduce dev_pm_genpd_is_on()
pmdomain: ti: Select PM_GENERIC_DOMAINS
pmdomain: sunxi: sun20i-ppu: change to tristate and enable for ARCH_SUNXI
pmdomain: sunxi: add driver for Allwinner A523's PCK-600 power controller
pmdomain: sunxi: sun20i-ppu: add A523 support
pmdomain: samsung: Fix splash-screen handover by enforcing a sync_state
cpuidle: riscv-sbi: Drop redundant sync_state support
cpuidle: psci: Drop redundant sync_state support
pmdomain: core: Leave powered-on genpds on until sync_state
pmdomain: core: Leave powered-on genpds on until late_initcall_sync
pmdomain: core: Default to use of_genpd_sync_state() for genpd providers
driver core: Add dev_set_drv_sync_state()
pmdomain: core: Add common ->sync_state() support for genpd providers
driver core: Export get_dev_from_fwnode()
firmware: xilinx: Use of_genpd_sync_state()
firmware: xilinx: Don't share zynqmp_pm_init_finalize()
...

+882 -197
+1
Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
··· 17 17 compatible: 18 18 oneOf: 19 19 - enum: 20 + - qcom,glymur-rpmhpd 20 21 - qcom,mdm9607-rpmpd 21 22 - qcom,milos-rpmhpd 22 23 - qcom,msm8226-rpmpd
+6 -2
drivers/base/core.c
··· 1881 1881 device_links_write_unlock(); 1882 1882 } 1883 1883 1884 - #define get_dev_from_fwnode(fwnode) get_device((fwnode)->dev) 1885 - 1886 1884 static bool fwnode_init_without_drv(struct fwnode_handle *fwnode) 1887 1885 { 1888 1886 struct device *dev; ··· 5278 5280 dev->of_node = to_of_node(fwnode); 5279 5281 } 5280 5282 EXPORT_SYMBOL_GPL(device_set_node); 5283 + 5284 + struct device *get_dev_from_fwnode(struct fwnode_handle *fwnode) 5285 + { 5286 + return get_device((fwnode)->dev); 5287 + } 5288 + EXPORT_SYMBOL_GPL(get_dev_from_fwnode); 5281 5289 5282 5290 int device_match_name(struct device *dev, const void *name) 5283 5291 {
-14
drivers/cpuidle/cpuidle-psci-domain.c
··· 28 28 }; 29 29 30 30 static LIST_HEAD(psci_pd_providers); 31 - static bool psci_pd_allow_domain_state; 32 31 33 32 static int psci_pd_power_off(struct generic_pm_domain *pd) 34 33 { ··· 36 37 37 38 if (!state->data) 38 39 return 0; 39 - 40 - if (!psci_pd_allow_domain_state) 41 - return -EBUSY; 42 40 43 41 /* OSI mode is enabled, set the corresponding domain state. */ 44 42 pd_state = state->data; ··· 122 126 } 123 127 } 124 128 125 - static void psci_cpuidle_domain_sync_state(struct device *dev) 126 - { 127 - /* 128 - * All devices have now been attached/probed to the PM domain topology, 129 - * hence it's fine to allow domain states to be picked. 130 - */ 131 - psci_pd_allow_domain_state = true; 132 - } 133 - 134 129 static const struct of_device_id psci_of_match[] = { 135 130 { .compatible = "arm,psci-1.0" }, 136 131 {} ··· 182 195 .driver = { 183 196 .name = "psci-cpuidle-domain", 184 197 .of_match_table = psci_of_match, 185 - .sync_state = psci_cpuidle_domain_sync_state, 186 198 }, 187 199 }; 188 200
-14
drivers/cpuidle/cpuidle-riscv-sbi.c
··· 44 44 static DEFINE_PER_CPU(struct sbi_domain_state, domain_state); 45 45 static bool sbi_cpuidle_use_osi; 46 46 static bool sbi_cpuidle_use_cpuhp; 47 - static bool sbi_cpuidle_pd_allow_domain_state; 48 47 49 48 static inline void sbi_set_domain_state(u32 state) 50 49 { ··· 344 345 return ret; 345 346 } 346 347 347 - static void sbi_cpuidle_domain_sync_state(struct device *dev) 348 - { 349 - /* 350 - * All devices have now been attached/probed to the PM domain 351 - * topology, hence it's fine to allow domain states to be picked. 352 - */ 353 - sbi_cpuidle_pd_allow_domain_state = true; 354 - } 355 - 356 348 #ifdef CONFIG_DT_IDLE_GENPD 357 349 358 350 static int sbi_cpuidle_pd_power_off(struct generic_pm_domain *pd) ··· 353 363 354 364 if (!state->data) 355 365 return 0; 356 - 357 - if (!sbi_cpuidle_pd_allow_domain_state) 358 - return -EBUSY; 359 366 360 367 /* OSI mode is enabled, set the corresponding domain state. */ 361 368 pd_state = state->data; ··· 551 564 .probe = sbi_cpuidle_probe, 552 565 .driver = { 553 566 .name = "sbi-cpuidle", 554 - .sync_state = sbi_cpuidle_domain_sync_state, 555 567 }, 556 568 }; 557 569
+16 -2
drivers/firmware/xilinx/zynqmp.c
··· 20 20 #include <linux/of.h> 21 21 #include <linux/of_platform.h> 22 22 #include <linux/platform_device.h> 23 + #include <linux/pm_domain.h> 23 24 #include <linux/slab.h> 24 25 #include <linux/uaccess.h> 25 26 #include <linux/hashtable.h> ··· 1300 1299 * This API function is to be used for notify the power management controller 1301 1300 * about the completed power management initialization. 1302 1301 */ 1303 - int zynqmp_pm_init_finalize(void) 1302 + static int zynqmp_pm_init_finalize(void) 1304 1303 { 1305 1304 return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, NULL, 0); 1306 1305 } 1307 - EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize); 1308 1306 1309 1307 /** 1310 1308 * zynqmp_pm_set_suspend_mode() - Set system suspend mode ··· 2100 2100 platform_device_unregister(em_dev); 2101 2101 } 2102 2102 2103 + static void zynqmp_firmware_sync_state(struct device *dev) 2104 + { 2105 + struct device_node *np = dev->of_node; 2106 + 2107 + if (!of_device_is_compatible(np, "xlnx,zynqmp-firmware")) 2108 + return; 2109 + 2110 + of_genpd_sync_state(np); 2111 + 2112 + if (zynqmp_pm_init_finalize()) 2113 + dev_warn(dev, "failed to release power management to firmware\n"); 2114 + } 2115 + 2103 2116 static const struct of_device_id zynqmp_firmware_of_match[] = { 2104 2117 {.compatible = "xlnx,zynqmp-firmware"}, 2105 2118 {.compatible = "xlnx,versal-firmware"}, ··· 2125 2112 .name = "zynqmp_firmware", 2126 2113 .of_match_table = zynqmp_firmware_of_match, 2127 2114 .dev_groups = zynqmp_firmware_groups, 2115 + .sync_state = zynqmp_firmware_sync_state, 2128 2116 }, 2129 2117 .probe = zynqmp_firmware_probe, 2130 2118 .remove = zynqmp_firmware_remove,
+6 -6
drivers/pmdomain/amlogic/meson-secure-pwrc.c
··· 342 342 return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate); 343 343 } 344 344 345 - static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = { 345 + static const struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = { 346 346 .domains = a1_pwrc_domains, 347 347 .count = ARRAY_SIZE(a1_pwrc_domains), 348 348 }; 349 349 350 - static struct meson_secure_pwrc_domain_data amlogic_secure_a4_pwrc_data = { 350 + static const struct meson_secure_pwrc_domain_data amlogic_secure_a4_pwrc_data = { 351 351 .domains = a4_pwrc_domains, 352 352 .count = ARRAY_SIZE(a4_pwrc_domains), 353 353 }; 354 354 355 - static struct meson_secure_pwrc_domain_data amlogic_secure_a5_pwrc_data = { 355 + static const struct meson_secure_pwrc_domain_data amlogic_secure_a5_pwrc_data = { 356 356 .domains = a5_pwrc_domains, 357 357 .count = ARRAY_SIZE(a5_pwrc_domains), 358 358 }; 359 359 360 - static struct meson_secure_pwrc_domain_data amlogic_secure_c3_pwrc_data = { 360 + static const struct meson_secure_pwrc_domain_data amlogic_secure_c3_pwrc_data = { 361 361 .domains = c3_pwrc_domains, 362 362 .count = ARRAY_SIZE(c3_pwrc_domains), 363 363 }; 364 364 365 - static struct meson_secure_pwrc_domain_data meson_secure_s4_pwrc_data = { 365 + static const struct meson_secure_pwrc_domain_data meson_secure_s4_pwrc_data = { 366 366 .domains = s4_pwrc_domains, 367 367 .count = ARRAY_SIZE(s4_pwrc_domains), 368 368 }; 369 369 370 - static struct meson_secure_pwrc_domain_data amlogic_secure_t7_pwrc_data = { 370 + static const struct meson_secure_pwrc_domain_data amlogic_secure_t7_pwrc_data = { 371 371 .domains = t7_pwrc_domains, 372 372 .count = ARRAY_SIZE(t7_pwrc_domains), 373 373 };
-1
drivers/pmdomain/apple/Kconfig
··· 9 9 select MFD_SYSCON 10 10 select PM_GENERIC_DOMAINS 11 11 select RESET_CONTROLLER 12 - default ARCH_APPLE 13 12 help 14 13 The PMGR block in Apple SoCs provides high-level power state 15 14 controls for SoC devices. This driver manages them through the
+3 -9
drivers/pmdomain/arm/scmi_pm_domain.c
··· 22 22 23 23 #define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd) 24 24 25 - static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on) 25 + static int scmi_pd_power(struct generic_pm_domain *domain, u32 state) 26 26 { 27 - u32 state; 28 27 struct scmi_pm_domain *pd = to_scmi_pd(domain); 29 - 30 - if (power_on) 31 - state = SCMI_POWER_STATE_GENERIC_ON; 32 - else 33 - state = SCMI_POWER_STATE_GENERIC_OFF; 34 28 35 29 return power_ops->state_set(pd->ph, pd->domain, state); 36 30 } 37 31 38 32 static int scmi_pd_power_on(struct generic_pm_domain *domain) 39 33 { 40 - return scmi_pd_power(domain, true); 34 + return scmi_pd_power(domain, SCMI_POWER_STATE_GENERIC_ON); 41 35 } 42 36 43 37 static int scmi_pd_power_off(struct generic_pm_domain *domain) 44 38 { 45 - return scmi_pd_power(domain, false); 39 + return scmi_pd_power(domain, SCMI_POWER_STATE_GENERIC_OFF); 46 40 } 47 41 48 42 static int scmi_pm_domain_probe(struct scmi_device *sdev)
+234 -20
drivers/pmdomain/core.c
··· 27 27 /* Provides a unique ID for each genpd device */ 28 28 static DEFINE_IDA(genpd_ida); 29 29 30 + /* The bus for genpd_providers. */ 31 + static const struct bus_type genpd_provider_bus_type = { 32 + .name = "genpd_provider", 33 + }; 34 + 35 + /* The parent for genpd_provider devices. */ 36 + static struct device genpd_provider_bus = { 37 + .init_name = "genpd_provider", 38 + }; 39 + 30 40 #define GENPD_RETRY_MAX_MS 250 /* Approximate */ 31 41 32 42 #define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \ ··· 186 176 #define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON) 187 177 #define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW) 188 178 #define genpd_is_dev_name_fw(genpd) (genpd->flags & GENPD_FLAG_DEV_NAME_FW) 179 + #define genpd_is_no_sync_state(genpd) (genpd->flags & GENPD_FLAG_NO_SYNC_STATE) 189 180 190 181 static inline bool irq_safe_dev_in_sleep_domain(struct device *dev, 191 182 const struct generic_pm_domain *genpd) ··· 770 759 EXPORT_SYMBOL_GPL(dev_pm_genpd_rpm_always_on); 771 760 772 761 /** 762 + * dev_pm_genpd_is_on() - Get device's current power domain status 763 + * 764 + * @dev: Device to get the current power status 765 + * 766 + * This function checks whether the generic power domain associated with the 767 + * given device is on or not by verifying if genpd_status_on equals 768 + * GENPD_STATE_ON. 769 + * 770 + * Note: this function returns the power status of the genpd at the time of the 771 + * call. The power status may change after due to activity from other devices 772 + * sharing the same genpd. Therefore, this information should not be relied for 773 + * long-term decisions about the device power state. 774 + * 775 + * Return: 'true' if the device's power domain is on, 'false' otherwise. 776 + */ 777 + bool dev_pm_genpd_is_on(struct device *dev) 778 + { 779 + struct generic_pm_domain *genpd; 780 + bool is_on; 781 + 782 + genpd = dev_to_genpd_safe(dev); 783 + if (!genpd) 784 + return false; 785 + 786 + genpd_lock(genpd); 787 + is_on = genpd_status_on(genpd); 788 + genpd_unlock(genpd); 789 + 790 + return is_on; 791 + } 792 + EXPORT_SYMBOL_GPL(dev_pm_genpd_is_on); 793 + 794 + /** 773 795 * pm_genpd_inc_rejected() - Adjust the rejected/usage counts for an idle-state. 774 796 * 775 797 * @genpd: The PM domain the idle-state belongs to. ··· 964 920 * The domain is already in the "power off" state. 965 921 * System suspend is in progress. 966 922 * The domain is configured as always on. 923 + * The domain was on at boot and still need to stay on. 967 924 * The domain has a subdomain being powered on. 968 925 */ 969 926 if (!genpd_status_on(genpd) || genpd->prepared_count > 0 || 970 927 genpd_is_always_on(genpd) || genpd_is_rpm_always_on(genpd) || 971 - atomic_read(&genpd->sd_count) > 0) 928 + genpd->stay_on || atomic_read(&genpd->sd_count) > 0) 972 929 return; 973 930 974 931 /* ··· 1357 1312 return ret; 1358 1313 } 1359 1314 1315 + #ifndef CONFIG_PM_GENERIC_DOMAINS_OF 1360 1316 static bool pd_ignore_unused; 1361 1317 static int __init pd_ignore_unused_setup(char *__unused) 1362 1318 { ··· 1381 1335 pr_info("genpd: Disabling unused power domains\n"); 1382 1336 mutex_lock(&gpd_list_lock); 1383 1337 1384 - list_for_each_entry(genpd, &gpd_list, gpd_list_node) 1338 + list_for_each_entry(genpd, &gpd_list, gpd_list_node) { 1339 + genpd_lock(genpd); 1340 + genpd->stay_on = false; 1341 + genpd_unlock(genpd); 1385 1342 genpd_queue_power_off_work(genpd); 1343 + } 1386 1344 1387 1345 mutex_unlock(&gpd_list_lock); 1388 1346 1389 1347 return 0; 1390 1348 } 1391 1349 late_initcall_sync(genpd_power_off_unused); 1350 + #endif 1392 1351 1393 1352 #ifdef CONFIG_PM_SLEEP 1394 1353 ··· 2313 2262 genpd->gd = gd; 2314 2263 device_initialize(&genpd->dev); 2315 2264 genpd->dev.release = genpd_provider_release; 2265 + genpd->dev.bus = &genpd_provider_bus_type; 2266 + genpd->dev.parent = &genpd_provider_bus; 2316 2267 2317 2268 if (!genpd_is_dev_name_fw(genpd)) { 2318 2269 dev_set_name(&genpd->dev, "%s", genpd->name); ··· 2392 2339 INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn); 2393 2340 atomic_set(&genpd->sd_count, 0); 2394 2341 genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON; 2342 + genpd->stay_on = !is_off; 2343 + genpd->sync_state = GENPD_SYNC_STATE_OFF; 2395 2344 genpd->device_count = 0; 2396 2345 genpd->provider = NULL; 2397 2346 genpd->device_id = -ENXIO; ··· 2546 2491 static LIST_HEAD(of_genpd_providers); 2547 2492 /* Mutex to protect the list above. */ 2548 2493 static DEFINE_MUTEX(of_genpd_mutex); 2494 + /* Used to prevent registering devices before the bus. */ 2495 + static bool genpd_bus_registered; 2549 2496 2550 2497 /** 2551 2498 * genpd_xlate_simple() - Xlate function for direct node-domain mapping ··· 2614 2557 cp->node = of_node_get(np); 2615 2558 cp->data = data; 2616 2559 cp->xlate = xlate; 2617 - fwnode_dev_initialized(&np->fwnode, true); 2560 + fwnode_dev_initialized(of_fwnode_handle(np), true); 2618 2561 2619 2562 mutex_lock(&of_genpd_mutex); 2620 2563 list_add(&cp->link, &of_genpd_providers); ··· 2641 2584 return ret; 2642 2585 } 2643 2586 2587 + static void genpd_sync_state(struct device *dev) 2588 + { 2589 + return of_genpd_sync_state(dev->of_node); 2590 + } 2591 + 2644 2592 /** 2645 2593 * of_genpd_add_provider_simple() - Register a simple PM domain provider 2646 2594 * @np: Device node pointer associated with the PM domain provider. ··· 2654 2592 int of_genpd_add_provider_simple(struct device_node *np, 2655 2593 struct generic_pm_domain *genpd) 2656 2594 { 2595 + struct fwnode_handle *fwnode; 2596 + struct device *dev; 2657 2597 int ret; 2658 2598 2659 2599 if (!np || !genpd) 2660 2600 return -EINVAL; 2601 + 2602 + if (!genpd_bus_registered) 2603 + return -ENODEV; 2661 2604 2662 2605 if (!genpd_present(genpd)) 2663 2606 return -EINVAL; 2664 2607 2665 2608 genpd->dev.of_node = np; 2666 2609 2610 + fwnode = of_fwnode_handle(np); 2611 + dev = get_dev_from_fwnode(fwnode); 2612 + if (!dev && !genpd_is_no_sync_state(genpd)) { 2613 + genpd->sync_state = GENPD_SYNC_STATE_SIMPLE; 2614 + device_set_node(&genpd->dev, fwnode); 2615 + } else { 2616 + dev_set_drv_sync_state(dev, genpd_sync_state); 2617 + } 2618 + 2619 + put_device(dev); 2620 + 2621 + ret = device_add(&genpd->dev); 2622 + if (ret) 2623 + return ret; 2624 + 2667 2625 /* Parse genpd OPP table */ 2668 2626 if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) { 2669 2627 ret = dev_pm_opp_of_add_table(&genpd->dev); 2670 - if (ret) 2671 - return dev_err_probe(&genpd->dev, ret, "Failed to add OPP table\n"); 2628 + if (ret) { 2629 + dev_err_probe(&genpd->dev, ret, "Failed to add OPP table\n"); 2630 + goto err_del; 2631 + } 2672 2632 2673 2633 /* 2674 2634 * Save table for faster processing while setting performance ··· 2701 2617 } 2702 2618 2703 2619 ret = genpd_add_provider(np, genpd_xlate_simple, genpd); 2704 - if (ret) { 2705 - if (genpd->opp_table) { 2706 - dev_pm_opp_put_opp_table(genpd->opp_table); 2707 - dev_pm_opp_of_remove_table(&genpd->dev); 2708 - } 2620 + if (ret) 2621 + goto err_opp; 2709 2622 2710 - return ret; 2711 - } 2712 - 2713 - genpd->provider = &np->fwnode; 2623 + genpd->provider = fwnode; 2714 2624 genpd->has_provider = true; 2715 2625 2716 2626 return 0; 2627 + 2628 + err_opp: 2629 + if (genpd->opp_table) { 2630 + dev_pm_opp_put_opp_table(genpd->opp_table); 2631 + dev_pm_opp_of_remove_table(&genpd->dev); 2632 + } 2633 + err_del: 2634 + device_del(&genpd->dev); 2635 + return ret; 2717 2636 } 2718 2637 EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple); 2719 2638 ··· 2729 2642 struct genpd_onecell_data *data) 2730 2643 { 2731 2644 struct generic_pm_domain *genpd; 2645 + struct fwnode_handle *fwnode; 2646 + struct device *dev; 2732 2647 unsigned int i; 2733 2648 int ret = -EINVAL; 2649 + bool sync_state = false; 2734 2650 2735 2651 if (!np || !data) 2736 2652 return -EINVAL; 2737 2653 2654 + if (!genpd_bus_registered) 2655 + return -ENODEV; 2656 + 2738 2657 if (!data->xlate) 2739 2658 data->xlate = genpd_xlate_onecell; 2659 + 2660 + fwnode = of_fwnode_handle(np); 2661 + dev = get_dev_from_fwnode(fwnode); 2662 + if (!dev) 2663 + sync_state = true; 2664 + else 2665 + dev_set_drv_sync_state(dev, genpd_sync_state); 2666 + 2667 + put_device(dev); 2740 2668 2741 2669 for (i = 0; i < data->num_domains; i++) { 2742 2670 genpd = data->domains[i]; ··· 2763 2661 2764 2662 genpd->dev.of_node = np; 2765 2663 2664 + if (sync_state && !genpd_is_no_sync_state(genpd)) { 2665 + genpd->sync_state = GENPD_SYNC_STATE_ONECELL; 2666 + device_set_node(&genpd->dev, fwnode); 2667 + sync_state = false; 2668 + } 2669 + 2670 + ret = device_add(&genpd->dev); 2671 + if (ret) 2672 + goto error; 2673 + 2766 2674 /* Parse genpd OPP table */ 2767 2675 if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) { 2768 2676 ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i); 2769 2677 if (ret) { 2770 2678 dev_err_probe(&genpd->dev, ret, 2771 2679 "Failed to add OPP table for index %d\n", i); 2680 + device_del(&genpd->dev); 2772 2681 goto error; 2773 2682 } 2774 2683 ··· 2791 2678 WARN_ON(IS_ERR(genpd->opp_table)); 2792 2679 } 2793 2680 2794 - genpd->provider = &np->fwnode; 2681 + genpd->provider = fwnode; 2795 2682 genpd->has_provider = true; 2796 2683 } 2797 2684 ··· 2815 2702 dev_pm_opp_put_opp_table(genpd->opp_table); 2816 2703 dev_pm_opp_of_remove_table(&genpd->dev); 2817 2704 } 2705 + 2706 + device_del(&genpd->dev); 2818 2707 } 2819 2708 2820 2709 return ret; ··· 2842 2727 * so that the PM domain can be safely removed. 2843 2728 */ 2844 2729 list_for_each_entry(gpd, &gpd_list, gpd_list_node) { 2845 - if (gpd->provider == &np->fwnode) { 2730 + if (gpd->provider == of_fwnode_handle(np)) { 2846 2731 gpd->has_provider = false; 2847 2732 2848 2733 if (gpd->opp_table) { 2849 2734 dev_pm_opp_put_opp_table(gpd->opp_table); 2850 2735 dev_pm_opp_of_remove_table(&gpd->dev); 2851 2736 } 2737 + 2738 + device_del(&gpd->dev); 2852 2739 } 2853 2740 } 2854 2741 2855 - fwnode_dev_initialized(&cp->node->fwnode, false); 2742 + fwnode_dev_initialized(of_fwnode_handle(cp->node), false); 2856 2743 list_del(&cp->link); 2857 2744 of_node_put(cp->node); 2858 2745 kfree(cp); ··· 3033 2916 3034 2917 mutex_lock(&gpd_list_lock); 3035 2918 list_for_each_entry_safe(gpd, tmp, &gpd_list, gpd_list_node) { 3036 - if (gpd->provider == &np->fwnode) { 2919 + if (gpd->provider == of_fwnode_handle(np)) { 3037 2920 ret = genpd_remove(gpd); 3038 2921 genpd = ret ? ERR_PTR(ret) : gpd; 3039 2922 break; ··· 3296 3179 if (num_domains < 0 || index >= num_domains) 3297 3180 return NULL; 3298 3181 3182 + if (!genpd_bus_registered) 3183 + return ERR_PTR(-ENODEV); 3184 + 3299 3185 /* Allocate and register device on the genpd bus. */ 3300 3186 virt_dev = kzalloc(sizeof(*virt_dev), GFP_KERNEL); 3301 3187 if (!virt_dev) ··· 3389 3269 3390 3270 genpd_state->power_on_latency_ns = 1000LL * exit_latency; 3391 3271 genpd_state->power_off_latency_ns = 1000LL * entry_latency; 3392 - genpd_state->fwnode = &state_node->fwnode; 3272 + genpd_state->fwnode = of_fwnode_handle(state_node); 3393 3273 3394 3274 return 0; 3395 3275 } ··· 3475 3355 } 3476 3356 EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states); 3477 3357 3358 + /** 3359 + * of_genpd_sync_state() - A common sync_state function for genpd providers 3360 + * @np: The device node the genpd provider is associated with. 3361 + * 3362 + * The @np that corresponds to a genpd provider may provide one or multiple 3363 + * genpds. This function makes use @np to find the genpds that belongs to the 3364 + * provider. For each genpd we try a power-off. 3365 + */ 3366 + void of_genpd_sync_state(struct device_node *np) 3367 + { 3368 + struct generic_pm_domain *genpd; 3369 + 3370 + if (!np) 3371 + return; 3372 + 3373 + mutex_lock(&gpd_list_lock); 3374 + list_for_each_entry(genpd, &gpd_list, gpd_list_node) { 3375 + if (genpd->provider == of_fwnode_handle(np)) { 3376 + genpd_lock(genpd); 3377 + genpd->stay_on = false; 3378 + genpd_power_off(genpd, false, 0); 3379 + genpd_unlock(genpd); 3380 + } 3381 + } 3382 + mutex_unlock(&gpd_list_lock); 3383 + } 3384 + EXPORT_SYMBOL_GPL(of_genpd_sync_state); 3385 + 3386 + static int genpd_provider_probe(struct device *dev) 3387 + { 3388 + return 0; 3389 + } 3390 + 3391 + static void genpd_provider_sync_state(struct device *dev) 3392 + { 3393 + struct generic_pm_domain *genpd = container_of(dev, struct generic_pm_domain, dev); 3394 + 3395 + switch (genpd->sync_state) { 3396 + case GENPD_SYNC_STATE_OFF: 3397 + break; 3398 + 3399 + case GENPD_SYNC_STATE_ONECELL: 3400 + of_genpd_sync_state(dev->of_node); 3401 + break; 3402 + 3403 + case GENPD_SYNC_STATE_SIMPLE: 3404 + genpd_lock(genpd); 3405 + genpd->stay_on = false; 3406 + genpd_power_off(genpd, false, 0); 3407 + genpd_unlock(genpd); 3408 + break; 3409 + 3410 + default: 3411 + break; 3412 + } 3413 + } 3414 + 3415 + static struct device_driver genpd_provider_drv = { 3416 + .name = "genpd_provider", 3417 + .bus = &genpd_provider_bus_type, 3418 + .probe = genpd_provider_probe, 3419 + .sync_state = genpd_provider_sync_state, 3420 + .suppress_bind_attrs = true, 3421 + }; 3422 + 3478 3423 static int __init genpd_bus_init(void) 3479 3424 { 3480 - return bus_register(&genpd_bus_type); 3425 + int ret; 3426 + 3427 + ret = device_register(&genpd_provider_bus); 3428 + if (ret) { 3429 + put_device(&genpd_provider_bus); 3430 + return ret; 3431 + } 3432 + 3433 + ret = bus_register(&genpd_provider_bus_type); 3434 + if (ret) 3435 + goto err_dev; 3436 + 3437 + ret = bus_register(&genpd_bus_type); 3438 + if (ret) 3439 + goto err_prov_bus; 3440 + 3441 + ret = driver_register(&genpd_provider_drv); 3442 + if (ret) 3443 + goto err_bus; 3444 + 3445 + genpd_bus_registered = true; 3446 + return 0; 3447 + 3448 + err_bus: 3449 + bus_unregister(&genpd_bus_type); 3450 + err_prov_bus: 3451 + bus_unregister(&genpd_provider_bus_type); 3452 + err_dev: 3453 + device_unregister(&genpd_provider_bus); 3454 + return ret; 3481 3455 } 3482 3456 core_initcall(genpd_bus_init); 3483 3457
+10
drivers/pmdomain/imx/imx8m-blk-ctrl.c
··· 665 665 #define LCDIF_1_RD_HURRY GENMASK(15, 13) 666 666 #define LCDIF_0_RD_HURRY GENMASK(12, 10) 667 667 668 + #define ISI_CACHE_CTRL 0x50 669 + #define ISI_V_WR_HURRY GENMASK(28, 26) 670 + #define ISI_U_WR_HURRY GENMASK(25, 23) 671 + #define ISI_Y_WR_HURRY GENMASK(22, 20) 672 + 668 673 static int imx8mp_media_power_notifier(struct notifier_block *nb, 669 674 unsigned long action, void *data) 670 675 { ··· 699 694 regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL, 700 695 FIELD_PREP(LCDIF_1_RD_HURRY, 7) | 701 696 FIELD_PREP(LCDIF_0_RD_HURRY, 7)); 697 + /* Same here for ISI */ 698 + regmap_set_bits(bc->regmap, ISI_CACHE_CTRL, 699 + FIELD_PREP(ISI_V_WR_HURRY, 7) | 700 + FIELD_PREP(ISI_U_WR_HURRY, 7) | 701 + FIELD_PREP(ISI_Y_WR_HURRY, 7)); 702 702 } 703 703 704 704 return NOTIFY_OK;
+47
drivers/pmdomain/qcom/rpmhpd.c
··· 217 217 .res_name = "gmxc.lvl", 218 218 }; 219 219 220 + /* Milos RPMH powerdomains */ 221 + static struct rpmhpd *milos_rpmhpds[] = { 222 + [RPMHPD_CX] = &cx, 223 + [RPMHPD_CX_AO] = &cx_ao, 224 + [RPMHPD_EBI] = &ebi, 225 + [RPMHPD_GFX] = &gfx, 226 + [RPMHPD_LCX] = &lcx, 227 + [RPMHPD_LMX] = &lmx, 228 + [RPMHPD_MSS] = &mss, 229 + [RPMHPD_MX] = &mx, 230 + [RPMHPD_MX_AO] = &mx_ao, 231 + }; 232 + 233 + static const struct rpmhpd_desc milos_desc = { 234 + .rpmhpds = milos_rpmhpds, 235 + .num_pds = ARRAY_SIZE(milos_rpmhpds), 236 + }; 237 + 220 238 /* SA8540P RPMH powerdomains */ 221 239 static struct rpmhpd *sa8540p_rpmhpds[] = { 222 240 [SC8280XP_CX] = &cx, ··· 684 666 .num_pds = ARRAY_SIZE(sc8280xp_rpmhpds), 685 667 }; 686 668 669 + /* Glymur RPMH powerdomains */ 670 + static struct rpmhpd *glymur_rpmhpds[] = { 671 + [RPMHPD_CX] = &cx, 672 + [RPMHPD_CX_AO] = &cx_ao, 673 + [RPMHPD_EBI] = &ebi, 674 + [RPMHPD_GFX] = &gfx, 675 + [RPMHPD_LCX] = &lcx, 676 + [RPMHPD_LMX] = &lmx, 677 + [RPMHPD_MMCX] = &mmcx, 678 + [RPMHPD_MMCX_AO] = &mmcx_ao, 679 + [RPMHPD_MX] = &mx, 680 + [RPMHPD_MX_AO] = &mx_ao, 681 + [RPMHPD_MXC] = &mxc, 682 + [RPMHPD_MXC_AO] = &mxc_ao, 683 + [RPMHPD_MSS] = &mss, 684 + [RPMHPD_NSP] = &nsp, 685 + [RPMHPD_NSP2] = &nsp2, 686 + [RPMHPD_GMXC] = &gmxc, 687 + }; 688 + 689 + static const struct rpmhpd_desc glymur_desc = { 690 + .rpmhpds = glymur_rpmhpds, 691 + .num_pds = ARRAY_SIZE(glymur_rpmhpds), 692 + }; 693 + 687 694 /* X1E80100 RPMH powerdomains */ 688 695 static struct rpmhpd *x1e80100_rpmhpds[] = { 689 696 [RPMHPD_CX] = &cx, ··· 766 723 }; 767 724 768 725 static const struct of_device_id rpmhpd_match_table[] = { 726 + { .compatible = "qcom,glymur-rpmhpd", .data = &glymur_desc }, 727 + { .compatible = "qcom,milos-rpmhpd", .data = &milos_desc }, 769 728 { .compatible = "qcom,qcs615-rpmhpd", .data = &qcs615_desc }, 770 729 { .compatible = "qcom,qcs8300-rpmhpd", .data = &qcs8300_desc }, 771 730 { .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc }, ··· 1071 1026 struct rpmhpd *pd; 1072 1027 unsigned int i; 1073 1028 int ret; 1029 + 1030 + of_genpd_sync_state(dev->of_node); 1074 1031 1075 1032 mutex_lock(&rpmhpd_lock); 1076 1033 for (i = 0; i < desc->num_pds; i++) {
+2
drivers/pmdomain/qcom/rpmpd.c
··· 1144 1144 unsigned int i; 1145 1145 int ret; 1146 1146 1147 + of_genpd_sync_state(dev->of_node); 1148 + 1147 1149 mutex_lock(&rpmpd_lock); 1148 1150 for (i = 0; i < desc->num_pds; i++) { 1149 1151 pd = rpmpds[i];
+88 -84
drivers/pmdomain/renesas/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 if SOC_RENESAS 3 + menu "Renesas PM Domains" 3 4 5 + # SoC Family 4 6 config SYSC_RCAR 5 7 bool "System Controller support for R-Car" if COMPILE_TEST 6 8 7 9 config SYSC_RCAR_GEN4 8 10 bool "System Controller support for R-Car Gen4" if COMPILE_TEST 9 11 10 - config SYSC_R8A77995 11 - bool "System Controller support for R-Car D3" if COMPILE_TEST 12 - select SYSC_RCAR 13 - 14 - config SYSC_R8A7794 15 - bool "System Controller support for R-Car E2" if COMPILE_TEST 16 - select SYSC_RCAR 17 - 18 - config SYSC_R8A77990 19 - bool "System Controller support for R-Car E3" if COMPILE_TEST 20 - select SYSC_RCAR 21 - 22 - config SYSC_R8A7779 23 - bool "System Controller support for R-Car H1" if COMPILE_TEST 24 - select SYSC_RCAR 25 - 26 - config SYSC_R8A7790 27 - bool "System Controller support for R-Car H2" if COMPILE_TEST 28 - select SYSC_RCAR 29 - 30 - config SYSC_R8A7795 31 - bool "System Controller support for R-Car H3" if COMPILE_TEST 32 - select SYSC_RCAR 33 - 34 - config SYSC_R8A7791 35 - bool "System Controller support for R-Car M2-W/N" if COMPILE_TEST 36 - select SYSC_RCAR 37 - 38 - config SYSC_R8A77965 39 - bool "System Controller support for R-Car M3-N" if COMPILE_TEST 40 - select SYSC_RCAR 41 - 42 - config SYSC_R8A77960 43 - bool "System Controller support for R-Car M3-W" if COMPILE_TEST 44 - select SYSC_RCAR 45 - 46 - config SYSC_R8A77961 47 - bool "System Controller support for R-Car M3-W+" if COMPILE_TEST 48 - select SYSC_RCAR 49 - 50 - config SYSC_R8A779F0 51 - bool "System Controller support for R-Car S4-8" if COMPILE_TEST 52 - select SYSC_RCAR_GEN4 53 - 54 - config SYSC_R8A7792 55 - bool "System Controller support for R-Car V2H" if COMPILE_TEST 56 - select SYSC_RCAR 57 - 58 - config SYSC_R8A77980 59 - bool "System Controller support for R-Car V3H" if COMPILE_TEST 60 - select SYSC_RCAR 61 - 62 - config SYSC_R8A77970 63 - bool "System Controller support for R-Car V3M" if COMPILE_TEST 64 - select SYSC_RCAR 65 - 66 - config SYSC_R8A779A0 67 - bool "System Controller support for R-Car V3U" if COMPILE_TEST 68 - select SYSC_RCAR_GEN4 69 - 70 - config SYSC_R8A779G0 71 - bool "System Controller support for R-Car V4H" if COMPILE_TEST 72 - select SYSC_RCAR_GEN4 73 - 74 - config SYSC_R8A779H0 75 - bool "System Controller support for R-Car V4M" if COMPILE_TEST 76 - select SYSC_RCAR_GEN4 77 - 78 12 config SYSC_RMOBILE 79 13 bool "System Controller support for R-Mobile" if COMPILE_TEST 80 14 81 - config SYSC_R8A77470 82 - bool "System Controller support for RZ/G1C" if COMPILE_TEST 83 - select SYSC_RCAR 84 - 85 - config SYSC_R8A7745 86 - bool "System Controller support for RZ/G1E" if COMPILE_TEST 87 - select SYSC_RCAR 88 - 15 + # SoC 89 16 config SYSC_R8A7742 90 - bool "System Controller support for RZ/G1H" if COMPILE_TEST 17 + bool "System Controller support for R8A7742 (RZ/G1H)" if COMPILE_TEST 91 18 select SYSC_RCAR 92 19 93 20 config SYSC_R8A7743 94 - bool "System Controller support for RZ/G1M" if COMPILE_TEST 21 + bool "System Controller support for R8A7743 (RZ/G1M)" if COMPILE_TEST 95 22 select SYSC_RCAR 96 23 97 - config SYSC_R8A774C0 98 - bool "System Controller support for RZ/G2E" if COMPILE_TEST 24 + config SYSC_R8A7745 25 + bool "System Controller support for R8A7745 (RZ/G1E)" if COMPILE_TEST 99 26 select SYSC_RCAR 100 27 101 - config SYSC_R8A774E1 102 - bool "System Controller support for RZ/G2H" if COMPILE_TEST 28 + config SYSC_R8A77470 29 + bool "System Controller support for R8A77470 (RZ/G1C)" if COMPILE_TEST 103 30 select SYSC_RCAR 104 31 105 32 config SYSC_R8A774A1 106 - bool "System Controller support for RZ/G2M" if COMPILE_TEST 33 + bool "System Controller support for R8A774A1 (RZ/G2M)" if COMPILE_TEST 107 34 select SYSC_RCAR 108 35 109 36 config SYSC_R8A774B1 110 - bool "System Controller support for RZ/G2N" if COMPILE_TEST 37 + bool "System Controller support for R8A774B1 (RZ/G2N)" if COMPILE_TEST 111 38 select SYSC_RCAR 112 39 40 + config SYSC_R8A774C0 41 + bool "System Controller support for R8A774C0 (RZ/G2E)" if COMPILE_TEST 42 + select SYSC_RCAR 43 + 44 + config SYSC_R8A774E1 45 + bool "System Controller support for R8A774E1 (RZ/G2H)" if COMPILE_TEST 46 + select SYSC_RCAR 47 + 48 + config SYSC_R8A7779 49 + bool "System Controller support for R8A7779 (R-Car H1)" if COMPILE_TEST 50 + select SYSC_RCAR 51 + 52 + config SYSC_R8A7790 53 + bool "System Controller support for R8A7790 (R-Car H2)" if COMPILE_TEST 54 + select SYSC_RCAR 55 + 56 + config SYSC_R8A7791 57 + bool "System Controller support for R8A7791/R8A7793 (R-Car M2-W/N)" if COMPILE_TEST 58 + select SYSC_RCAR 59 + 60 + config SYSC_R8A7792 61 + bool "System Controller support for R8A7792 (R-Car V2H)" if COMPILE_TEST 62 + select SYSC_RCAR 63 + 64 + config SYSC_R8A7794 65 + bool "System Controller support for R8A7794 (R-Car E2)" if COMPILE_TEST 66 + select SYSC_RCAR 67 + 68 + config SYSC_R8A7795 69 + bool "System Controller support for R8A7795 (R-Car H3)" if COMPILE_TEST 70 + select SYSC_RCAR 71 + 72 + config SYSC_R8A77960 73 + bool "System Controller support for R8A77960 (R-Car M3-W)" if COMPILE_TEST 74 + select SYSC_RCAR 75 + 76 + config SYSC_R8A77961 77 + bool "System Controller support for R8A77961 (R-Car M3-W+)" if COMPILE_TEST 78 + select SYSC_RCAR 79 + 80 + config SYSC_R8A77965 81 + bool "System Controller support for R8A77965 (R-Car M3-N)" if COMPILE_TEST 82 + select SYSC_RCAR 83 + 84 + config SYSC_R8A77970 85 + bool "System Controller support for R8A77970 (R-Car V3M)" if COMPILE_TEST 86 + select SYSC_RCAR 87 + 88 + config SYSC_R8A77980 89 + bool "System Controller support for R8A77980 (R-Car V3H)" if COMPILE_TEST 90 + select SYSC_RCAR 91 + 92 + config SYSC_R8A77990 93 + bool "System Controller support for R8A77990 (R-Car E3)" if COMPILE_TEST 94 + select SYSC_RCAR 95 + 96 + config SYSC_R8A77995 97 + bool "System Controller support for R8A77995 (R-Car D3)" if COMPILE_TEST 98 + select SYSC_RCAR 99 + 100 + config SYSC_R8A779A0 101 + bool "System Controller support for R8A779A0 (R-Car V3U)" if COMPILE_TEST 102 + select SYSC_RCAR_GEN4 103 + 104 + config SYSC_R8A779F0 105 + bool "System Controller support for R8A779F0 (R-Car S4-8)" if COMPILE_TEST 106 + select SYSC_RCAR_GEN4 107 + 108 + config SYSC_R8A779G0 109 + bool "System Controller support for R8A779G0 (R-Car V4H)" if COMPILE_TEST 110 + select SYSC_RCAR_GEN4 111 + 112 + config SYSC_R8A779H0 113 + bool "System Controller support for R8A779H0 (R-Car V4M)" if COMPILE_TEST 114 + select SYSC_RCAR_GEN4 115 + 116 + endmenu 113 117 endif
+1 -1
drivers/pmdomain/renesas/rcar-gen4-sysc.c
··· 374 374 of_node_put(np); 375 375 return error; 376 376 } 377 - early_initcall(rcar_gen4_sysc_pd_init); 377 + postcore_initcall(rcar_gen4_sysc_pd_init);
+18 -1
drivers/pmdomain/renesas/rcar-sysc.c
··· 342 342 }; 343 343 344 344 static struct genpd_onecell_data *rcar_sysc_onecell_data; 345 + static struct device_node *rcar_sysc_onecell_np; 345 346 346 347 static int __init rcar_sysc_pd_init(void) 347 348 { ··· 429 428 } 430 429 } 431 430 432 - error = of_genpd_add_provider_onecell(np, &domains->onecell_data); 431 + rcar_sysc_onecell_np = np; 432 + return 0; 433 433 434 434 out_put: 435 435 of_node_put(np); 436 436 return error; 437 437 } 438 438 early_initcall(rcar_sysc_pd_init); 439 + 440 + static int __init rcar_sysc_pd_init_provider(void) 441 + { 442 + int error; 443 + 444 + if (!rcar_sysc_onecell_np) 445 + return -ENODEV; 446 + 447 + error = of_genpd_add_provider_onecell(rcar_sysc_onecell_np, 448 + rcar_sysc_onecell_data); 449 + 450 + of_node_put(rcar_sysc_onecell_np); 451 + return error; 452 + } 453 + postcore_initcall(rcar_sysc_pd_init_provider); 439 454 440 455 #ifdef CONFIG_ARCH_R8A7779 441 456 static int rcar_sysc_power_cpu(unsigned int idx, bool on)
+1 -2
drivers/pmdomain/renesas/rmobile-sysc.c
··· 335 335 336 336 return ret; 337 337 } 338 - 339 - core_initcall(rmobile_init_pm_domains); 338 + postcore_initcall(rmobile_init_pm_domains);
+27
drivers/pmdomain/rockchip/pm-domains.c
··· 35 35 #include <dt-bindings/power/rk3366-power.h> 36 36 #include <dt-bindings/power/rk3368-power.h> 37 37 #include <dt-bindings/power/rk3399-power.h> 38 + #include <dt-bindings/power/rockchip,rk3528-power.h> 38 39 #include <dt-bindings/power/rockchip,rk3562-power.h> 39 40 #include <dt-bindings/power/rk3568-power.h> 40 41 #include <dt-bindings/power/rockchip,rk3576-power.h> ··· 216 215 217 216 #define DOMAIN_RK3399(name, pwr, status, req, wakeup) \ 218 217 DOMAIN(name, pwr, status, req, req, req, wakeup) 218 + 219 + #define DOMAIN_RK3528(name, pwr, req) \ 220 + DOMAIN_M(name, pwr, pwr, req, req, req, false) 219 221 220 222 #define DOMAIN_RK3562(name, pwr, req, g_mask, mem, wakeup) \ 221 223 DOMAIN_M_G_SD(name, pwr, pwr, req, req, req, g_mask, mem, wakeup, false) ··· 1219 1215 [RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399("sdioaudio", BIT(31), BIT(31), BIT(29), true), 1220 1216 }; 1221 1217 1218 + static const struct rockchip_domain_info rk3528_pm_domains[] = { 1219 + [RK3528_PD_GPU] = DOMAIN_RK3528("gpu", BIT(0), BIT(4)), 1220 + [RK3528_PD_RKVDEC] = DOMAIN_RK3528("vdec", 0, BIT(5)), 1221 + [RK3528_PD_RKVENC] = DOMAIN_RK3528("venc", 0, BIT(6)), 1222 + [RK3528_PD_VO] = DOMAIN_RK3528("vo", 0, BIT(7)), 1223 + [RK3528_PD_VPU] = DOMAIN_RK3528("vpu", 0, BIT(8)), 1224 + }; 1225 + 1222 1226 static const struct rockchip_domain_info rk3562_pm_domains[] = { 1223 1227 /* name pwr req g_mask mem wakeup */ 1224 1228 [RK3562_PD_GPU] = DOMAIN_RK3562("gpu", BIT(0), BIT(1), BIT(1), 0, false), ··· 1440 1428 .domain_info = rk3399_pm_domains, 1441 1429 }; 1442 1430 1431 + static const struct rockchip_pmu_info rk3528_pmu = { 1432 + .pwr_offset = 0x1210, 1433 + .status_offset = 0x1230, 1434 + .req_offset = 0x1110, 1435 + .idle_offset = 0x1128, 1436 + .ack_offset = 0x1120, 1437 + 1438 + .num_domains = ARRAY_SIZE(rk3528_pm_domains), 1439 + .domain_info = rk3528_pm_domains, 1440 + }; 1441 + 1443 1442 static const struct rockchip_pmu_info rk3562_pmu = { 1444 1443 .pwr_offset = 0x210, 1445 1444 .status_offset = 0x230, ··· 1560 1537 { 1561 1538 .compatible = "rockchip,rk3399-power-controller", 1562 1539 .data = (void *)&rk3399_pmu, 1540 + }, 1541 + { 1542 + .compatible = "rockchip,rk3528-power-controller", 1543 + .data = (void *)&rk3528_pmu, 1563 1544 }, 1564 1545 { 1565 1546 .compatible = "rockchip,rk3562-power-controller",
+9
drivers/pmdomain/samsung/exynos-pm-domains.c
··· 147 147 parent.np, child.np); 148 148 } 149 149 150 + /* 151 + * Some Samsung platforms with bootloaders turning on the splash-screen 152 + * and handing it over to the kernel, requires the power-domains to be 153 + * reset during boot. As a temporary hack to manage this, let's enforce 154 + * a sync_state. 155 + */ 156 + if (!ret) 157 + of_genpd_sync_state(np); 158 + 150 159 pm_runtime_enable(dev); 151 160 return ret; 152 161 }
+16 -3
drivers/pmdomain/sunxi/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 3 3 config SUN20I_PPU 4 - bool "Allwinner D1 PPU power domain driver" 4 + tristate "Allwinner D1 PPU power domain driver" 5 5 depends on ARCH_SUNXI || COMPILE_TEST 6 6 depends on PM 7 + default ARCH_SUNXI 7 8 select PM_GENERIC_DOMAINS 8 9 help 9 - Say y to enable the PPU power domain driver. This saves power 10 - when certain peripherals, such as the video engine, are idle. 10 + Say y to enable the PPU power domain driver. This is required 11 + to enable power to certain peripherals, such as the display 12 + engine. 11 13 12 14 config SUN50I_H6_PRCM_PPU 13 15 tristate "Allwinner H6 PRCM power domain driver" ··· 20 18 Say y to enable the Allwinner H6/H616 PRCM power domain driver. 21 19 This is required to enable the Mali GPU in the H616 SoC, it is 22 20 optional for the H6. 21 + 22 + config SUN55I_PCK600 23 + tristate "Allwinner A523 PCK-600 power domain driver" 24 + depends on ARCH_SUNXI || COMPILE_TEST 25 + depends on PM 26 + default ARCH_SUNXI 27 + select PM_GENERIC_DOMAINS 28 + help 29 + Say y to enable the PCK-600 power domain driver. This is required 30 + to enable power to certain peripherals, such as the display and 31 + video engines.
+1
drivers/pmdomain/sunxi/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-$(CONFIG_SUN20I_PPU) += sun20i-ppu.o 3 3 obj-$(CONFIG_SUN50I_H6_PRCM_PPU) += sun50i-h6-prcm-ppu.o 4 + obj-$(CONFIG_SUN55I_PCK600) += sun55i-pck600.o
+17
drivers/pmdomain/sunxi/sun20i-ppu.c
··· 193 193 .num_domains = ARRAY_SIZE(sun8i_v853_ppu_pd_names), 194 194 }; 195 195 196 + static const char *const sun55i_a523_ppu_pd_names[] = { 197 + "DSP", 198 + "NPU", 199 + "AUDIO", 200 + "SRAM", 201 + "RISCV", 202 + }; 203 + 204 + static const struct sun20i_ppu_desc sun55i_a523_ppu_desc = { 205 + .names = sun55i_a523_ppu_pd_names, 206 + .num_domains = ARRAY_SIZE(sun55i_a523_ppu_pd_names), 207 + }; 208 + 196 209 static const struct of_device_id sun20i_ppu_of_match[] = { 197 210 { 198 211 .compatible = "allwinner,sun20i-d1-ppu", ··· 214 201 { 215 202 .compatible = "allwinner,sun8i-v853-ppu", 216 203 .data = &sun8i_v853_ppu_desc, 204 + }, 205 + { 206 + .compatible = "allwinner,sun55i-a523-ppu", 207 + .data = &sun55i_a523_ppu_desc, 217 208 }, 218 209 { } 219 210 };
+234
drivers/pmdomain/sunxi/sun55i-pck600.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Allwinner PCK-600 power domain support 4 + * 5 + * Copyright (c) 2025 Chen-Yu Tsai <wens@csie.org> 6 + * 7 + * The hardware is likely based on the Arm PCK-600 IP, since some of 8 + * the registers match Arm's documents, with additional delay controls 9 + * that are in registers listed as reserved. 10 + * 11 + * Documents include: 12 + * - "Arm CoreLink PCK-600 Power Control Kit" TRM 13 + * - "Arm Power Policy Unit" architecture specification (DEN0051E) 14 + */ 15 + 16 + #include <linux/bitfield.h> 17 + #include <linux/clk.h> 18 + #include <linux/container_of.h> 19 + #include <linux/device.h> 20 + #include <linux/dev_printk.h> 21 + #include <linux/err.h> 22 + #include <linux/io.h> 23 + #include <linux/iopoll.h> 24 + #include <linux/module.h> 25 + #include <linux/of.h> 26 + #include <linux/platform_device.h> 27 + #include <linux/pm_domain.h> 28 + #include <linux/reset.h> 29 + #include <linux/slab.h> 30 + #include <linux/string_choices.h> 31 + 32 + #define PPU_PWPR 0x0 33 + #define PPU_PWSR 0x8 34 + #define PPU_DCDR0 0x170 35 + #define PPU_DCDR1 0x174 36 + 37 + /* shared definition for PPU_PWPR and PPU_PWSR */ 38 + #define PPU_PWR_STATUS GENMASK(3, 0) 39 + #define PPU_POWER_MODE_ON 0x8 40 + #define PPU_POWER_MODE_OFF 0x0 41 + 42 + #define PPU_REG_SIZE 0x1000 43 + 44 + struct sunxi_pck600_desc { 45 + const char * const *pd_names; 46 + unsigned int num_domains; 47 + u32 logic_power_switch0_delay_offset; 48 + u32 logic_power_switch1_delay_offset; 49 + u32 off2on_delay_offset; 50 + u32 device_ctrl0_delay; 51 + u32 device_ctrl1_delay; 52 + u32 logic_power_switch0_delay; 53 + u32 logic_power_switch1_delay; 54 + u32 off2on_delay; 55 + }; 56 + 57 + struct sunxi_pck600_pd { 58 + struct generic_pm_domain genpd; 59 + struct sunxi_pck600 *pck; 60 + void __iomem *base; 61 + }; 62 + 63 + struct sunxi_pck600 { 64 + struct device *dev; 65 + struct genpd_onecell_data genpd_data; 66 + struct sunxi_pck600_pd pds[]; 67 + }; 68 + 69 + #define to_sunxi_pd(gpd) container_of(gpd, struct sunxi_pck600_pd, genpd) 70 + 71 + static int sunxi_pck600_pd_set_power(struct sunxi_pck600_pd *pd, bool on) 72 + { 73 + struct sunxi_pck600 *pck = pd->pck; 74 + struct generic_pm_domain *genpd = &pd->genpd; 75 + int ret; 76 + u32 val, reg; 77 + 78 + val = on ? PPU_POWER_MODE_ON : PPU_POWER_MODE_OFF; 79 + 80 + reg = readl(pd->base + PPU_PWPR); 81 + FIELD_MODIFY(PPU_PWR_STATUS, &reg, val); 82 + writel(reg, pd->base + PPU_PWPR); 83 + 84 + /* push write out to hardware */ 85 + reg = readl(pd->base + PPU_PWPR); 86 + 87 + ret = readl_poll_timeout_atomic(pd->base + PPU_PWSR, reg, 88 + FIELD_GET(PPU_PWR_STATUS, reg) == val, 89 + 0, 10000); 90 + if (ret) 91 + dev_err(pck->dev, "failed to turn domain \"%s\" %s: %d\n", 92 + genpd->name, str_on_off(on), ret); 93 + 94 + return ret; 95 + } 96 + 97 + static int sunxi_pck600_power_on(struct generic_pm_domain *domain) 98 + { 99 + struct sunxi_pck600_pd *pd = to_sunxi_pd(domain); 100 + 101 + return sunxi_pck600_pd_set_power(pd, true); 102 + } 103 + 104 + static int sunxi_pck600_power_off(struct generic_pm_domain *domain) 105 + { 106 + struct sunxi_pck600_pd *pd = to_sunxi_pd(domain); 107 + 108 + return sunxi_pck600_pd_set_power(pd, false); 109 + } 110 + 111 + static void sunxi_pck600_pd_setup(struct sunxi_pck600_pd *pd, 112 + const struct sunxi_pck600_desc *desc) 113 + { 114 + writel(desc->device_ctrl0_delay, pd->base + PPU_DCDR0); 115 + writel(desc->device_ctrl1_delay, pd->base + PPU_DCDR1); 116 + writel(desc->logic_power_switch0_delay, 117 + pd->base + desc->logic_power_switch0_delay_offset); 118 + writel(desc->logic_power_switch1_delay, 119 + pd->base + desc->logic_power_switch1_delay_offset); 120 + writel(desc->off2on_delay, pd->base + desc->off2on_delay_offset); 121 + } 122 + 123 + static int sunxi_pck600_probe(struct platform_device *pdev) 124 + { 125 + struct device *dev = &pdev->dev; 126 + const struct sunxi_pck600_desc *desc; 127 + struct genpd_onecell_data *genpds; 128 + struct sunxi_pck600 *pck; 129 + struct reset_control *rst; 130 + struct clk *clk; 131 + void __iomem *base; 132 + int i, ret; 133 + 134 + desc = of_device_get_match_data(dev); 135 + 136 + pck = devm_kzalloc(dev, struct_size(pck, pds, desc->num_domains), GFP_KERNEL); 137 + if (!pck) 138 + return -ENOMEM; 139 + 140 + pck->dev = &pdev->dev; 141 + platform_set_drvdata(pdev, pck); 142 + 143 + genpds = &pck->genpd_data; 144 + genpds->num_domains = desc->num_domains; 145 + genpds->domains = devm_kcalloc(dev, desc->num_domains, 146 + sizeof(*genpds->domains), GFP_KERNEL); 147 + if (!genpds->domains) 148 + return -ENOMEM; 149 + 150 + base = devm_platform_ioremap_resource(pdev, 0); 151 + if (IS_ERR(base)) 152 + return PTR_ERR(base); 153 + 154 + rst = devm_reset_control_get_exclusive_released(dev, NULL); 155 + if (IS_ERR(rst)) 156 + return dev_err_probe(dev, PTR_ERR(rst), "failed to get reset control\n"); 157 + 158 + clk = devm_clk_get_enabled(dev, NULL); 159 + if (IS_ERR(clk)) 160 + return dev_err_probe(dev, PTR_ERR(clk), "failed to get clock\n"); 161 + 162 + for (i = 0; i < desc->num_domains; i++) { 163 + struct sunxi_pck600_pd *pd = &pck->pds[i]; 164 + 165 + pd->genpd.name = desc->pd_names[i]; 166 + pd->genpd.power_off = sunxi_pck600_power_off; 167 + pd->genpd.power_on = sunxi_pck600_power_on; 168 + pd->base = base + PPU_REG_SIZE * i; 169 + 170 + sunxi_pck600_pd_setup(pd, desc); 171 + ret = pm_genpd_init(&pd->genpd, NULL, false); 172 + if (ret) { 173 + dev_err_probe(dev, ret, "failed to initialize power domain\n"); 174 + goto err_remove_pds; 175 + } 176 + 177 + genpds->domains[i] = &pd->genpd; 178 + } 179 + 180 + ret = of_genpd_add_provider_onecell(dev_of_node(dev), genpds); 181 + if (ret) { 182 + dev_err_probe(dev, ret, "failed to add PD provider\n"); 183 + goto err_remove_pds; 184 + } 185 + 186 + return 0; 187 + 188 + err_remove_pds: 189 + for (i--; i >= 0; i--) 190 + pm_genpd_remove(genpds->domains[i]); 191 + 192 + return ret; 193 + } 194 + 195 + static const char * const sun55i_a523_pck600_pd_names[] = { 196 + "VE", "GPU", "VI", "VO0", "VO1", "DE", "NAND", "PCIE" 197 + }; 198 + 199 + static const struct sunxi_pck600_desc sun55i_a523_pck600_desc = { 200 + .pd_names = sun55i_a523_pck600_pd_names, 201 + .num_domains = ARRAY_SIZE(sun55i_a523_pck600_pd_names), 202 + .logic_power_switch0_delay_offset = 0xc00, 203 + .logic_power_switch1_delay_offset = 0xc04, 204 + .off2on_delay_offset = 0xc10, 205 + .device_ctrl0_delay = 0xffffff, 206 + .device_ctrl1_delay = 0xffff, 207 + .logic_power_switch0_delay = 0x8080808, 208 + .logic_power_switch1_delay = 0x808, 209 + .off2on_delay = 0x8 210 + }; 211 + 212 + static const struct of_device_id sunxi_pck600_of_match[] = { 213 + { 214 + .compatible = "allwinner,sun55i-a523-pck-600", 215 + .data = &sun55i_a523_pck600_desc, 216 + }, 217 + {} 218 + }; 219 + MODULE_DEVICE_TABLE(of, sunxi_pck600_of_match); 220 + 221 + static struct platform_driver sunxi_pck600_driver = { 222 + .probe = sunxi_pck600_probe, 223 + .driver = { 224 + .name = "sunxi-pck-600", 225 + .of_match_table = sunxi_pck600_of_match, 226 + /* Power domains cannot be removed if in use. */ 227 + .suppress_bind_attrs = true, 228 + }, 229 + }; 230 + module_platform_driver(sunxi_pck600_driver); 231 + 232 + MODULE_DESCRIPTION("Allwinner PCK-600 power domain driver"); 233 + MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); 234 + MODULE_LICENSE("GPL");
+1
drivers/pmdomain/thead/Kconfig
··· 4 4 tristate "Support TH1520 Power Domains" 5 5 depends on TH1520_AON_PROTOCOL 6 6 select REGMAP_MMIO 7 + select AUXILIARY_BUS 7 8 help 8 9 This driver enables power domain management for the T-HEAD 9 10 TH-1520 SoC. On this SoC there are number of power domains,
+51
drivers/pmdomain/thead/th1520-pm-domains.c
··· 5 5 * Author: Michal Wilczynski <m.wilczynski@samsung.com> 6 6 */ 7 7 8 + #include <linux/auxiliary_bus.h> 8 9 #include <linux/firmware/thead/thead,th1520-aon.h> 9 10 #include <linux/slab.h> 10 11 #include <linux/platform_device.h> ··· 129 128 } 130 129 } 131 130 131 + static void th1520_pd_pwrseq_unregister_adev(void *adev) 132 + { 133 + auxiliary_device_delete(adev); 134 + auxiliary_device_uninit(adev); 135 + } 136 + 137 + static int th1520_pd_pwrseq_gpu_init(struct device *dev) 138 + { 139 + struct auxiliary_device *adev; 140 + int ret; 141 + 142 + /* 143 + * Correctly check only for the property's existence in the DT node. 144 + * We don't need to get/claim the reset here; that is the job of 145 + * the auxiliary driver that we are about to spawn. 146 + */ 147 + if (device_property_match_string(dev, "reset-names", "gpu-clkgen") < 0) 148 + /* 149 + * This is not an error. It simply means the optional sequencer 150 + * is not described in the device tree. 151 + */ 152 + return 0; 153 + 154 + adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL); 155 + if (!adev) 156 + return -ENOMEM; 157 + 158 + adev->name = "pwrseq-gpu"; 159 + adev->dev.parent = dev; 160 + 161 + ret = auxiliary_device_init(adev); 162 + if (ret) 163 + return ret; 164 + 165 + ret = auxiliary_device_add(adev); 166 + if (ret) { 167 + auxiliary_device_uninit(adev); 168 + return ret; 169 + } 170 + 171 + return devm_add_action_or_reset(dev, th1520_pd_pwrseq_unregister_adev, 172 + adev); 173 + } 174 + 132 175 static int th1520_pd_probe(struct platform_device *pdev) 133 176 { 134 177 struct generic_pm_domain **domains; ··· 231 186 if (ret) 232 187 goto err_clean_genpd; 233 188 189 + ret = th1520_pd_pwrseq_gpu_init(dev); 190 + if (ret) 191 + goto err_clean_provider; 192 + 234 193 return 0; 235 194 195 + err_clean_provider: 196 + of_genpd_del_provider(dev->of_node); 236 197 err_clean_genpd: 237 198 for (i--; i >= 0; i--) 238 199 pm_genpd_remove(domains[i]);
+1 -1
drivers/pmdomain/ti/Kconfig
··· 10 10 config TI_SCI_PM_DOMAINS 11 11 tristate "TI SCI PM Domains Driver" 12 12 depends on TI_SCI_PROTOCOL 13 - depends on PM_GENERIC_DOMAINS 13 + select PM_GENERIC_DOMAINS if PM 14 14 help 15 15 Generic power domain implementation for TI device implementing 16 16 the TI SCI protocol.
-16
drivers/pmdomain/xilinx/zynqmp-pm-domains.c
··· 153 153 struct device *dev) 154 154 { 155 155 struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); 156 - struct device_link *link; 157 156 int ret; 158 - 159 - link = device_link_add(dev, &domain->dev, DL_FLAG_SYNC_STATE_ONLY); 160 - if (!link) 161 - dev_dbg(&domain->dev, "failed to create device link for %s\n", 162 - dev_name(dev)); 163 157 164 158 /* If this is not the first device to attach there is nothing to do */ 165 159 if (domain->device_count) ··· 292 298 of_genpd_del_provider(pdev->dev.parent->of_node); 293 299 } 294 300 295 - static void zynqmp_gpd_sync_state(struct device *dev) 296 - { 297 - int ret; 298 - 299 - ret = zynqmp_pm_init_finalize(); 300 - if (ret) 301 - dev_warn(dev, "failed to release power management to firmware\n"); 302 - } 303 - 304 301 static struct platform_driver zynqmp_power_domain_driver = { 305 302 .driver = { 306 303 .name = "zynqmp_power_controller", 307 - .sync_state = zynqmp_gpd_sync_state, 308 304 }, 309 305 .probe = zynqmp_gpd_probe, 310 306 .remove = zynqmp_gpd_remove,
+37 -8
drivers/remoteproc/imx_rproc.c
··· 18 18 #include <linux/of_reserved_mem.h> 19 19 #include <linux/platform_device.h> 20 20 #include <linux/pm_domain.h> 21 + #include <linux/pm_runtime.h> 21 22 #include <linux/reboot.h> 22 23 #include <linux/regmap.h> 23 24 #include <linux/remoteproc.h> ··· 891 890 static int imx_rproc_attach_pd(struct imx_rproc *priv) 892 891 { 893 892 struct device *dev = priv->dev; 894 - int ret; 895 - struct dev_pm_domain_attach_data pd_data = { 896 - .pd_flags = PD_FLAG_DEV_LINK_ON, 897 - }; 893 + int ret, i; 894 + bool detached = true; 898 895 899 896 /* 900 897 * If there is only one power-domain entry, the platform driver framework ··· 901 902 if (dev->pm_domain) 902 903 return 0; 903 904 904 - ret = dev_pm_domain_attach_list(dev, &pd_data, &priv->pd_list); 905 - return ret < 0 ? ret : 0; 905 + ret = dev_pm_domain_attach_list(dev, NULL, &priv->pd_list); 906 + if (ret < 0) 907 + return ret; 908 + /* 909 + * If all the power domain devices are already turned on, the remote 910 + * core is already powered up and running when the kernel booted (e.g., 911 + * started by U-Boot's bootaux command). In this case attach to it. 912 + */ 913 + for (i = 0; i < ret; i++) { 914 + if (!dev_pm_genpd_is_on(priv->pd_list->pd_devs[i])) { 915 + detached = false; 916 + break; 917 + } 918 + } 919 + 920 + if (detached) 921 + priv->rproc->state = RPROC_DETACHED; 922 + 923 + return 0; 906 924 } 907 925 908 926 static int imx_rproc_detect_mode(struct imx_rproc *priv) ··· 1045 1029 struct device *dev = priv->dev; 1046 1030 int ret; 1047 1031 1048 - /* Remote core is not under control of Linux */ 1049 - if (dcfg->method == IMX_RPROC_NONE) 1032 + /* Remote core is not under control of Linux or it is managed by SCU API */ 1033 + if (dcfg->method == IMX_RPROC_NONE || dcfg->method == IMX_RPROC_SCU_API) 1050 1034 return 0; 1051 1035 1052 1036 priv->clk = devm_clk_get(dev, NULL); ··· 1162 1146 } 1163 1147 } 1164 1148 1149 + if (dcfg->method == IMX_RPROC_SCU_API) { 1150 + pm_runtime_enable(dev); 1151 + ret = pm_runtime_resume_and_get(dev); 1152 + if (ret) { 1153 + dev_err(dev, "pm_runtime get failed: %d\n", ret); 1154 + goto err_put_clk; 1155 + } 1156 + } 1157 + 1165 1158 ret = rproc_add(rproc); 1166 1159 if (ret) { 1167 1160 dev_err(dev, "rproc_add failed\n"); ··· 1196 1171 struct rproc *rproc = platform_get_drvdata(pdev); 1197 1172 struct imx_rproc *priv = rproc->priv; 1198 1173 1174 + if (priv->dcfg->method == IMX_RPROC_SCU_API) { 1175 + pm_runtime_disable(priv->dev); 1176 + pm_runtime_put(priv->dev); 1177 + } 1199 1178 clk_disable_unprepare(priv->clk); 1200 1179 rproc_del(rproc); 1201 1180 imx_rproc_put_scu(rproc);
+19 -7
drivers/soc/tegra/pmc.c
··· 418 418 * @irq: chip implementation for the IRQ domain 419 419 * @clk_nb: pclk clock changes handler 420 420 * @core_domain_state_synced: flag marking the core domain's state as synced 421 - * @core_domain_registered: flag marking the core domain as registered 422 421 * @wake_type_level_map: Bitmap indicating level type for non-dual edge wakes 423 422 * @wake_type_dual_edge_map: Bitmap indicating if a wake is dual-edge or not 424 423 * @wake_sw_status_map: Bitmap to hold raw status of wakes without mask ··· 461 462 struct notifier_block clk_nb; 462 463 463 464 bool core_domain_state_synced; 464 - bool core_domain_registered; 465 465 466 466 unsigned long *wake_type_level_map; 467 467 unsigned long *wake_type_dual_edge_map; ··· 1295 1297 1296 1298 pg->id = id; 1297 1299 pg->genpd.name = np->name; 1300 + pg->genpd.flags = GENPD_FLAG_NO_SYNC_STATE; 1298 1301 pg->genpd.power_off = tegra_genpd_power_off; 1299 1302 pg->genpd.power_on = tegra_genpd_power_on; 1300 1303 pg->pmc = pmc; ··· 1405 1406 return -ENOMEM; 1406 1407 1407 1408 genpd->name = "core"; 1409 + genpd->flags = GENPD_FLAG_NO_SYNC_STATE; 1408 1410 genpd->set_performance_state = tegra_pmc_core_pd_set_performance_state; 1409 1411 1410 1412 err = devm_pm_opp_set_regulators(pmc->dev, rname); ··· 1424 1424 dev_err(pmc->dev, "failed to add core genpd: %d\n", err); 1425 1425 goto remove_genpd; 1426 1426 } 1427 - 1428 - pmc->core_domain_registered = true; 1429 1427 1430 1428 return 0; 1431 1429 ··· 4381 4383 4382 4384 static void tegra_pmc_sync_state(struct device *dev) 4383 4385 { 4386 + struct device_node *np, *child; 4384 4387 int err; 4388 + 4389 + np = of_get_child_by_name(dev->of_node, "powergates"); 4390 + if (!np) 4391 + return; 4392 + 4393 + for_each_child_of_node(np, child) 4394 + of_genpd_sync_state(child); 4395 + 4396 + of_node_put(np); 4397 + 4398 + np = of_get_child_by_name(dev->of_node, "core-domain"); 4399 + if (!np) 4400 + return; 4401 + 4402 + of_genpd_sync_state(np); 4403 + of_node_put(np); 4385 4404 4386 4405 /* 4387 4406 * Newer device-trees have power domains, but we need to prepare all ··· 4413 4398 * no dependencies that will block the state syncing. We shouldn't 4414 4399 * mark the domain as synced in this case. 4415 4400 */ 4416 - if (!pmc->core_domain_registered) 4417 - return; 4418 - 4419 4401 pmc->core_domain_state_synced = true; 4420 4402 4421 4403 /* this is a no-op if core regulator isn't used */
+13
include/linux/device.h
··· 944 944 return false; 945 945 } 946 946 947 + static inline int dev_set_drv_sync_state(struct device *dev, 948 + void (*fn)(struct device *dev)) 949 + { 950 + if (!dev || !dev->driver) 951 + return 0; 952 + if (dev->driver->sync_state && dev->driver->sync_state != fn) 953 + return -EBUSY; 954 + if (!dev->driver->sync_state) 955 + dev->driver->sync_state = fn; 956 + return 0; 957 + } 958 + 947 959 static inline void dev_set_removable(struct device *dev, 948 960 enum device_removable removable) 949 961 { ··· 1087 1075 int device_add_of_node(struct device *dev, struct device_node *of_node); 1088 1076 void device_remove_of_node(struct device *dev); 1089 1077 void device_set_of_node_from_dev(struct device *dev, const struct device *dev2); 1078 + struct device *get_dev_from_fwnode(struct fwnode_handle *fwnode); 1090 1079 1091 1080 static inline struct device_node *dev_of_node(struct device *dev) 1092 1081 {
-6
include/linux/firmware/xlnx-zynqmp.h
··· 585 585 int zynqmp_pm_reset_get_status(const u32 reset, u32 *status); 586 586 unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode); 587 587 int zynqmp_pm_bootmode_write(u32 ps_mode); 588 - int zynqmp_pm_init_finalize(void); 589 588 int zynqmp_pm_set_suspend_mode(u32 mode); 590 589 int zynqmp_pm_request_node(const u32 node, const u32 capabilities, 591 590 const u32 qos, const enum zynqmp_pm_request_ack ack); ··· 741 742 } 742 743 743 744 static inline int zynqmp_pm_bootmode_write(u32 ps_mode) 744 - { 745 - return -ENODEV; 746 - } 747 - 748 - static inline int zynqmp_pm_init_finalize(void) 749 745 { 750 746 return -ENODEV; 751 747 }
+23
include/linux/pm_domain.h
··· 110 110 * GENPD_FLAG_DEV_NAME_FW: Instructs genpd to generate an unique device name 111 111 * using ida. It is used by genpd providers which 112 112 * get their genpd-names directly from FW. 113 + * 114 + * GENPD_FLAG_NO_SYNC_STATE: The ->sync_state() support is implemented in a 115 + * genpd provider specific way, likely through a 116 + * parent device node. This flag makes genpd to 117 + * skip its internal support for this. 113 118 */ 114 119 #define GENPD_FLAG_PM_CLK (1U << 0) 115 120 #define GENPD_FLAG_IRQ_SAFE (1U << 1) ··· 125 120 #define GENPD_FLAG_MIN_RESIDENCY (1U << 6) 126 121 #define GENPD_FLAG_OPP_TABLE_FW (1U << 7) 127 122 #define GENPD_FLAG_DEV_NAME_FW (1U << 8) 123 + #define GENPD_FLAG_NO_SYNC_STATE (1U << 9) 128 124 129 125 enum gpd_status { 130 126 GENPD_STATE_ON = 0, /* PM domain is on */ ··· 137 131 GENPD_NOTIFY_OFF, 138 132 GENPD_NOTIFY_PRE_ON, 139 133 GENPD_NOTIFY_ON, 134 + }; 135 + 136 + enum genpd_sync_state { 137 + GENPD_SYNC_STATE_OFF = 0, 138 + GENPD_SYNC_STATE_SIMPLE, 139 + GENPD_SYNC_STATE_ONECELL, 140 140 }; 141 141 142 142 struct dev_power_governor { ··· 205 193 unsigned int performance_state; /* Aggregated max performance state */ 206 194 cpumask_var_t cpus; /* A cpumask of the attached CPUs */ 207 195 bool synced_poweroff; /* A consumer needs a synced poweroff */ 196 + bool stay_on; /* Stay powered-on during boot. */ 197 + enum genpd_sync_state sync_state; /* How sync_state is managed. */ 208 198 int (*power_off)(struct generic_pm_domain *domain); 209 199 int (*power_on)(struct generic_pm_domain *domain); 210 200 struct raw_notifier_head power_notifiers; /* Power on/off notifiers */ ··· 321 307 int dev_pm_genpd_set_hwmode(struct device *dev, bool enable); 322 308 bool dev_pm_genpd_get_hwmode(struct device *dev); 323 309 int dev_pm_genpd_rpm_always_on(struct device *dev, bool on); 310 + bool dev_pm_genpd_is_on(struct device *dev); 324 311 325 312 extern struct dev_power_governor simple_qos_governor; 326 313 extern struct dev_power_governor pm_domain_always_on_gov; ··· 414 399 return -EOPNOTSUPP; 415 400 } 416 401 402 + static inline bool dev_pm_genpd_is_on(struct device *dev) 403 + { 404 + return false; 405 + } 406 + 417 407 #define simple_qos_governor (*(struct dev_power_governor *)(NULL)) 418 408 #define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL)) 419 409 #endif ··· 457 437 struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); 458 438 int of_genpd_parse_idle_states(struct device_node *dn, 459 439 struct genpd_power_state **states, int *n); 440 + void of_genpd_sync_state(struct device_node *np); 460 441 461 442 int genpd_dev_pm_attach(struct device *dev); 462 443 struct device *genpd_dev_pm_attach_by_id(struct device *dev, ··· 502 481 { 503 482 return -ENODEV; 504 483 } 484 + 485 + static inline void of_genpd_sync_state(struct device_node *np) {} 505 486 506 487 static inline int genpd_dev_pm_attach(struct device *dev) 507 488 {