Lines Matching +full:io +full:- +full:domains

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Allwinner PCK-600 power domain support
5 * Copyright (c) 2025 Chen-Yu Tsai <wens@csie.org>
7 * The hardware is likely based on the Arm PCK-600 IP, since some of
12 * - "Arm CoreLink PCK-600 Power Control Kit" TRM
13 * - "Arm Power Policy Unit" architecture specification (DEN0051E)
22 #include <linux/io.h>
73 struct sunxi_pck600 *pck = pd->pck; in sunxi_pck600_pd_set_power()
74 struct generic_pm_domain *genpd = &pd->genpd; in sunxi_pck600_pd_set_power()
80 reg = readl(pd->base + PPU_PWPR); in sunxi_pck600_pd_set_power()
82 writel(reg, pd->base + PPU_PWPR); in sunxi_pck600_pd_set_power()
85 reg = readl(pd->base + PPU_PWPR); in sunxi_pck600_pd_set_power()
87 ret = readl_poll_timeout_atomic(pd->base + PPU_PWSR, reg, in sunxi_pck600_pd_set_power()
91 dev_err(pck->dev, "failed to turn domain \"%s\" %s: %d\n", in sunxi_pck600_pd_set_power()
92 genpd->name, str_on_off(on), ret); in sunxi_pck600_pd_set_power()
114 writel(desc->device_ctrl0_delay, pd->base + PPU_DCDR0); in sunxi_pck600_pd_setup()
115 writel(desc->device_ctrl1_delay, pd->base + PPU_DCDR1); in sunxi_pck600_pd_setup()
116 writel(desc->logic_power_switch0_delay, in sunxi_pck600_pd_setup()
117 pd->base + desc->logic_power_switch0_delay_offset); in sunxi_pck600_pd_setup()
118 writel(desc->logic_power_switch1_delay, in sunxi_pck600_pd_setup()
119 pd->base + desc->logic_power_switch1_delay_offset); in sunxi_pck600_pd_setup()
120 writel(desc->off2on_delay, pd->base + desc->off2on_delay_offset); in sunxi_pck600_pd_setup()
125 struct device *dev = &pdev->dev; in sunxi_pck600_probe()
136 pck = devm_kzalloc(dev, struct_size(pck, pds, desc->num_domains), GFP_KERNEL); in sunxi_pck600_probe()
138 return -ENOMEM; in sunxi_pck600_probe()
140 pck->dev = &pdev->dev; in sunxi_pck600_probe()
143 genpds = &pck->genpd_data; in sunxi_pck600_probe()
144 genpds->num_domains = desc->num_domains; in sunxi_pck600_probe()
145 genpds->domains = devm_kcalloc(dev, desc->num_domains, in sunxi_pck600_probe()
146 sizeof(*genpds->domains), GFP_KERNEL); in sunxi_pck600_probe()
147 if (!genpds->domains) in sunxi_pck600_probe()
148 return -ENOMEM; in sunxi_pck600_probe()
162 for (i = 0; i < desc->num_domains; i++) { in sunxi_pck600_probe()
163 struct sunxi_pck600_pd *pd = &pck->pds[i]; in sunxi_pck600_probe()
165 pd->genpd.name = desc->pd_names[i]; in sunxi_pck600_probe()
166 pd->genpd.power_off = sunxi_pck600_power_off; in sunxi_pck600_probe()
167 pd->genpd.power_on = sunxi_pck600_power_on; in sunxi_pck600_probe()
168 pd->base = base + PPU_REG_SIZE * i; in sunxi_pck600_probe()
171 ret = pm_genpd_init(&pd->genpd, NULL, false); in sunxi_pck600_probe()
177 genpds->domains[i] = &pd->genpd; in sunxi_pck600_probe()
189 for (i--; i >= 0; i--) in sunxi_pck600_probe()
190 pm_genpd_remove(genpds->domains[i]); in sunxi_pck600_probe()
214 .compatible = "allwinner,sun55i-a523-pck-600",
224 .name = "sunxi-pck-600",
226 /* Power domains cannot be removed if in use. */
232 MODULE_DESCRIPTION("Allwinner PCK-600 power domain driver");
233 MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");