xref: /linux/drivers/pmdomain/actions/owl-sps.c (revision d2c9a99135da931377240942d44f3dea104cedb8)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Actions Semi Owl Smart Power System (SPS)
4  *
5  * Copyright 2012 Actions Semi Inc.
6  * Author: Actions Semi, Inc.
7  *
8  * Copyright (c) 2017 Andreas Färber
9  */
10 
11 #include <linux/of_address.h>
12 #include <linux/platform_device.h>
13 #include <linux/property.h>
14 #include <linux/pm_domain.h>
15 #include <linux/soc/actions/owl-sps.h>
16 #include <dt-bindings/power/owl-s500-powergate.h>
17 #include <dt-bindings/power/owl-s700-powergate.h>
18 #include <dt-bindings/power/owl-s900-powergate.h>
19 
20 struct owl_sps_domain_info {
21 	const char *name;
22 	int pwr_bit;
23 	int ack_bit;
24 	unsigned int genpd_flags;
25 };
26 
27 struct owl_sps_info {
28 	unsigned num_domains;
29 	const struct owl_sps_domain_info *domains;
30 };
31 
32 struct owl_sps {
33 	struct device *dev;
34 	const struct owl_sps_info *info;
35 	void __iomem *base;
36 	struct genpd_onecell_data genpd_data;
37 	struct generic_pm_domain *domains[];
38 };
39 
40 #define to_owl_pd(gpd) container_of(gpd, struct owl_sps_domain, genpd)
41 
42 struct owl_sps_domain {
43 	struct generic_pm_domain genpd;
44 	const struct owl_sps_domain_info *info;
45 	struct owl_sps *sps;
46 };
47 
owl_sps_set_power(struct owl_sps_domain * pd,bool enable)48 static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable)
49 {
50 	u32 pwr_mask, ack_mask;
51 
52 	ack_mask = BIT(pd->info->ack_bit);
53 	pwr_mask = BIT(pd->info->pwr_bit);
54 
55 	return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable);
56 }
57 
owl_sps_power_on(struct generic_pm_domain * domain)58 static int owl_sps_power_on(struct generic_pm_domain *domain)
59 {
60 	struct owl_sps_domain *pd = to_owl_pd(domain);
61 
62 	dev_dbg(pd->sps->dev, "%s power on", pd->info->name);
63 
64 	return owl_sps_set_power(pd, true);
65 }
66 
owl_sps_power_off(struct generic_pm_domain * domain)67 static int owl_sps_power_off(struct generic_pm_domain *domain)
68 {
69 	struct owl_sps_domain *pd = to_owl_pd(domain);
70 
71 	dev_dbg(pd->sps->dev, "%s power off", pd->info->name);
72 
73 	return owl_sps_set_power(pd, false);
74 }
75 
owl_sps_init_domain(struct owl_sps * sps,int index)76 static int owl_sps_init_domain(struct owl_sps *sps, int index)
77 {
78 	struct owl_sps_domain *pd;
79 
80 	pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL);
81 	if (!pd)
82 		return -ENOMEM;
83 
84 	pd->info = &sps->info->domains[index];
85 	pd->sps = sps;
86 
87 	pd->genpd.name = pd->info->name;
88 	pd->genpd.power_on = owl_sps_power_on;
89 	pd->genpd.power_off = owl_sps_power_off;
90 	pd->genpd.flags = pd->info->genpd_flags;
91 	pm_genpd_init(&pd->genpd, NULL, false);
92 
93 	sps->genpd_data.domains[index] = &pd->genpd;
94 
95 	return 0;
96 }
97 
owl_sps_probe(struct platform_device * pdev)98 static int owl_sps_probe(struct platform_device *pdev)
99 {
100 	const struct owl_sps_info *sps_info;
101 	struct owl_sps *sps;
102 	int i, ret;
103 
104 	sps_info = device_get_match_data(&pdev->dev);
105 	if (!sps_info) {
106 		dev_err(&pdev->dev, "unknown compatible or missing data\n");
107 		return -EINVAL;
108 	}
109 
110 	sps = devm_kzalloc(&pdev->dev,
111 			   struct_size(sps, domains, sps_info->num_domains),
112 			   GFP_KERNEL);
113 	if (!sps)
114 		return -ENOMEM;
115 
116 	sps->base = of_io_request_and_map(pdev->dev.of_node, 0, "owl-sps");
117 	if (IS_ERR(sps->base)) {
118 		dev_err(&pdev->dev, "failed to map sps registers\n");
119 		return PTR_ERR(sps->base);
120 	}
121 
122 	sps->dev = &pdev->dev;
123 	sps->info = sps_info;
124 	sps->genpd_data.domains = sps->domains;
125 	sps->genpd_data.num_domains = sps_info->num_domains;
126 
127 	for (i = 0; i < sps_info->num_domains; i++) {
128 		ret = owl_sps_init_domain(sps, i);
129 		if (ret)
130 			return ret;
131 	}
132 
133 	ret = of_genpd_add_provider_onecell(pdev->dev.of_node, &sps->genpd_data);
134 	if (ret) {
135 		dev_err(&pdev->dev, "failed to add provider (%d)", ret);
136 		return ret;
137 	}
138 
139 	return 0;
140 }
141 
142 static const struct owl_sps_domain_info s500_sps_domains[] = {
143 	[S500_PD_VDE] = {
144 		.name = "VDE",
145 		.pwr_bit = 0,
146 		.ack_bit = 16,
147 	},
148 	[S500_PD_VCE_SI] = {
149 		.name = "VCE_SI",
150 		.pwr_bit = 1,
151 		.ack_bit = 17,
152 	},
153 	[S500_PD_USB2_1] = {
154 		.name = "USB2_1",
155 		.pwr_bit = 2,
156 		.ack_bit = 18,
157 	},
158 	[S500_PD_CPU2] = {
159 		.name = "CPU2",
160 		.pwr_bit = 5,
161 		.ack_bit = 21,
162 		.genpd_flags = GENPD_FLAG_ALWAYS_ON,
163 	},
164 	[S500_PD_CPU3] = {
165 		.name = "CPU3",
166 		.pwr_bit = 6,
167 		.ack_bit = 22,
168 		.genpd_flags = GENPD_FLAG_ALWAYS_ON,
169 	},
170 	[S500_PD_DMA] = {
171 		.name = "DMA",
172 		.pwr_bit = 8,
173 		.ack_bit = 12,
174 	},
175 	[S500_PD_DS] = {
176 		.name = "DS",
177 		.pwr_bit = 9,
178 		.ack_bit = 13,
179 	},
180 	[S500_PD_USB3] = {
181 		.name = "USB3",
182 		.pwr_bit = 10,
183 		.ack_bit = 14,
184 	},
185 	[S500_PD_USB2_0] = {
186 		.name = "USB2_0",
187 		.pwr_bit = 11,
188 		.ack_bit = 15,
189 	},
190 };
191 
192 static const struct owl_sps_info s500_sps_info = {
193 	.num_domains = ARRAY_SIZE(s500_sps_domains),
194 	.domains = s500_sps_domains,
195 };
196 
197 static const struct owl_sps_domain_info s700_sps_domains[] = {
198 	[S700_PD_VDE] = {
199 		.name = "VDE",
200 		.pwr_bit = 0,
201 	},
202 	[S700_PD_VCE_SI] = {
203 		.name = "VCE_SI",
204 		.pwr_bit = 1,
205 	},
206 	[S700_PD_USB2_1] = {
207 		.name = "USB2_1",
208 		.pwr_bit = 2,
209 	},
210 	[S700_PD_HDE] = {
211 		.name = "HDE",
212 		.pwr_bit = 7,
213 	},
214 	[S700_PD_DMA] = {
215 		.name = "DMA",
216 		.pwr_bit = 8,
217 	},
218 	[S700_PD_DS] = {
219 		.name = "DS",
220 		.pwr_bit = 9,
221 	},
222 	[S700_PD_USB3] = {
223 		.name = "USB3",
224 		.pwr_bit = 10,
225 	},
226 	[S700_PD_USB2_0] = {
227 		.name = "USB2_0",
228 		.pwr_bit = 11,
229 	},
230 };
231 
232 static const struct owl_sps_info s700_sps_info = {
233 	.num_domains = ARRAY_SIZE(s700_sps_domains),
234 	.domains = s700_sps_domains,
235 };
236 
237 static const struct owl_sps_domain_info s900_sps_domains[] = {
238 	[S900_PD_GPU_B] = {
239 		.name = "GPU_B",
240 		.pwr_bit = 3,
241 	},
242 	[S900_PD_VCE] = {
243 		.name = "VCE",
244 		.pwr_bit = 4,
245 	},
246 	[S900_PD_SENSOR] = {
247 		.name = "SENSOR",
248 		.pwr_bit = 5,
249 	},
250 	[S900_PD_VDE] = {
251 		.name = "VDE",
252 		.pwr_bit = 6,
253 	},
254 	[S900_PD_HDE] = {
255 		.name = "HDE",
256 		.pwr_bit = 7,
257 	},
258 	[S900_PD_USB3] = {
259 		.name = "USB3",
260 		.pwr_bit = 8,
261 	},
262 	[S900_PD_DDR0] = {
263 		.name = "DDR0",
264 		.pwr_bit = 9,
265 	},
266 	[S900_PD_DDR1] = {
267 		.name = "DDR1",
268 		.pwr_bit = 10,
269 	},
270 	[S900_PD_DE] = {
271 		.name = "DE",
272 		.pwr_bit = 13,
273 	},
274 	[S900_PD_NAND] = {
275 		.name = "NAND",
276 		.pwr_bit = 14,
277 	},
278 	[S900_PD_USB2_H0] = {
279 		.name = "USB2_H0",
280 		.pwr_bit = 15,
281 	},
282 	[S900_PD_USB2_H1] = {
283 		.name = "USB2_H1",
284 		.pwr_bit = 16,
285 	},
286 };
287 
288 static const struct owl_sps_info s900_sps_info = {
289 	.num_domains = ARRAY_SIZE(s900_sps_domains),
290 	.domains = s900_sps_domains,
291 };
292 
293 static const struct of_device_id owl_sps_of_matches[] = {
294 	{ .compatible = "actions,s500-sps", .data = &s500_sps_info },
295 	{ .compatible = "actions,s700-sps", .data = &s700_sps_info },
296 	{ .compatible = "actions,s900-sps", .data = &s900_sps_info },
297 	{ }
298 };
299 
300 static struct platform_driver owl_sps_platform_driver = {
301 	.probe = owl_sps_probe,
302 	.driver = {
303 		.name = "owl-sps",
304 		.of_match_table = owl_sps_of_matches,
305 		.suppress_bind_attrs = true,
306 	},
307 };
308 
owl_sps_init(void)309 static int __init owl_sps_init(void)
310 {
311 	return platform_driver_register(&owl_sps_platform_driver);
312 }
313 postcore_initcall(owl_sps_init);
314