• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * OMAP2+ PRM driver
4  *
5  * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
6  *	Tero Kristo <t-kristo@ti.com>
7  */
8 
9 #include <linux/kernel.h>
10 #include <linux/device.h>
11 #include <linux/io.h>
12 #include <linux/iopoll.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/of_device.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_domain.h>
18 #include <linux/reset-controller.h>
19 #include <linux/delay.h>
20 
21 #include <linux/platform_data/ti-prm.h>
22 
23 enum omap_prm_domain_mode {
24 	OMAP_PRMD_OFF,
25 	OMAP_PRMD_RETENTION,
26 	OMAP_PRMD_ON_INACTIVE,
27 	OMAP_PRMD_ON_ACTIVE,
28 };
29 
30 struct omap_prm_domain_map {
31 	unsigned int usable_modes;	/* Mask of hardware supported modes */
32 	unsigned long statechange:1;	/* Optional low-power state change */
33 	unsigned long logicretstate:1;	/* Optional logic off mode */
34 };
35 
36 struct omap_prm_domain {
37 	struct device *dev;
38 	struct omap_prm *prm;
39 	struct generic_pm_domain pd;
40 	u16 pwrstctrl;
41 	u16 pwrstst;
42 	const struct omap_prm_domain_map *cap;
43 	u32 pwrstctrl_saved;
44 };
45 
46 struct omap_rst_map {
47 	s8 rst;
48 	s8 st;
49 };
50 
51 struct omap_prm_data {
52 	u32 base;
53 	const char *name;
54 	const char *clkdm_name;
55 	u16 pwrstctrl;
56 	u16 pwrstst;
57 	const struct omap_prm_domain_map *dmap;
58 	u16 rstctrl;
59 	u16 rstst;
60 	const struct omap_rst_map *rstmap;
61 	u8 flags;
62 };
63 
64 struct omap_prm {
65 	const struct omap_prm_data *data;
66 	void __iomem *base;
67 	struct omap_prm_domain *prmd;
68 };
69 
70 struct omap_reset_data {
71 	struct reset_controller_dev rcdev;
72 	struct omap_prm *prm;
73 	u32 mask;
74 	spinlock_t lock;
75 	struct clockdomain *clkdm;
76 	struct device *dev;
77 };
78 
79 #define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd)
80 #define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev)
81 
82 #define OMAP_MAX_RESETS		8
83 #define OMAP_RESET_MAX_WAIT	10000
84 
85 #define OMAP_PRM_HAS_RSTCTRL	BIT(0)
86 #define OMAP_PRM_HAS_RSTST	BIT(1)
87 #define OMAP_PRM_HAS_NO_CLKDM	BIT(2)
88 
89 #define OMAP_PRM_HAS_RESETS	(OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST)
90 
91 #define PRM_STATE_MAX_WAIT	10000
92 #define PRM_LOGICRETSTATE	BIT(2)
93 #define PRM_LOWPOWERSTATECHANGE	BIT(4)
94 #define PRM_POWERSTATE_MASK	OMAP_PRMD_ON_ACTIVE
95 
96 #define PRM_ST_INTRANSITION	BIT(20)
97 
98 static const struct omap_prm_domain_map omap_prm_all = {
99 	.usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
100 			BIT(OMAP_PRMD_RETENTION) | BIT(OMAP_PRMD_OFF),
101 	.statechange = 1,
102 	.logicretstate = 1,
103 };
104 
105 static const struct omap_prm_domain_map omap_prm_noinact = {
106 	.usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION) |
107 			BIT(OMAP_PRMD_OFF),
108 	.statechange = 1,
109 	.logicretstate = 1,
110 };
111 
112 static const struct omap_prm_domain_map omap_prm_nooff = {
113 	.usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
114 			BIT(OMAP_PRMD_RETENTION),
115 	.statechange = 1,
116 	.logicretstate = 1,
117 };
118 
119 static const struct omap_prm_domain_map omap_prm_onoff_noauto = {
120 	.usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_OFF),
121 	.statechange = 1,
122 };
123 
124 static const struct omap_rst_map rst_map_0[] = {
125 	{ .rst = 0, .st = 0 },
126 	{ .rst = -1 },
127 };
128 
129 static const struct omap_rst_map rst_map_01[] = {
130 	{ .rst = 0, .st = 0 },
131 	{ .rst = 1, .st = 1 },
132 	{ .rst = -1 },
133 };
134 
135 static const struct omap_rst_map rst_map_012[] = {
136 	{ .rst = 0, .st = 0 },
137 	{ .rst = 1, .st = 1 },
138 	{ .rst = 2, .st = 2 },
139 	{ .rst = -1 },
140 };
141 
142 static const struct omap_prm_data omap4_prm_data[] = {
143 	{ .name = "tesla", .base = 0x4a306400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 },
144 	{
145 		.name = "abe", .base = 0x4a306500,
146 		.pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_all,
147 	},
148 	{ .name = "core", .base = 0x4a306700, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati", .rstmap = rst_map_012 },
149 	{ .name = "ivahd", .base = 0x4a306f00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 },
150 	{ .name = "device", .base = 0x4a307b00, .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM },
151 	{ },
152 };
153 
154 static const struct omap_prm_data omap5_prm_data[] = {
155 	{ .name = "dsp", .base = 0x4ae06400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 },
156 	{
157 		.name = "abe", .base = 0x4ae06500,
158 		.pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_nooff,
159 	},
160 	{ .name = "core", .base = 0x4ae06700, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu", .rstmap = rst_map_012 },
161 	{ .name = "iva", .base = 0x4ae07200, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 },
162 	{ .name = "device", .base = 0x4ae07c00, .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM },
163 	{ },
164 };
165 
166 static const struct omap_prm_data dra7_prm_data[] = {
167 	{ .name = "dsp1", .base = 0x4ae06400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 },
168 	{ .name = "ipu", .base = 0x4ae06500, .rstctrl = 0x10, .rstst = 0x14, .clkdm_name = "ipu1", .rstmap = rst_map_012 },
169 	{ .name = "core", .base = 0x4ae06700, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu2", .rstmap = rst_map_012 },
170 	{ .name = "iva", .base = 0x4ae06f00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 },
171 	{ .name = "dsp2", .base = 0x4ae07b00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 },
172 	{ .name = "eve1", .base = 0x4ae07b40, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 },
173 	{ .name = "eve2", .base = 0x4ae07b80, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 },
174 	{ .name = "eve3", .base = 0x4ae07bc0, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 },
175 	{ .name = "eve4", .base = 0x4ae07c00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 },
176 	{ },
177 };
178 
179 static const struct omap_rst_map am3_per_rst_map[] = {
180 	{ .rst = 1 },
181 	{ .rst = -1 },
182 };
183 
184 static const struct omap_rst_map am3_wkup_rst_map[] = {
185 	{ .rst = 3, .st = 5 },
186 	{ .rst = -1 },
187 };
188 
189 static const struct omap_prm_data am3_prm_data[] = {
190 	{ .name = "per", .base = 0x44e00c00, .rstctrl = 0x0, .rstmap = am3_per_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp" },
191 	{ .name = "wkup", .base = 0x44e00d00, .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM },
192 	{ .name = "device", .base = 0x44e00f00, .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM },
193 	{
194 		.name = "gfx", .base = 0x44e01100,
195 		.pwrstctrl = 0, .pwrstst = 0x10, .dmap = &omap_prm_noinact,
196 		.rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
197 	},
198 	{ },
199 };
200 
201 static const struct omap_rst_map am4_per_rst_map[] = {
202 	{ .rst = 1, .st = 0 },
203 	{ .rst = -1 },
204 };
205 
206 static const struct omap_rst_map am4_device_rst_map[] = {
207 	{ .rst = 0, .st = 1 },
208 	{ .rst = 1, .st = 0 },
209 	{ .rst = -1 },
210 };
211 
212 static const struct omap_prm_data am4_prm_data[] = {
213 	{
214 		.name = "gfx", .base = 0x44df0400,
215 		.pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
216 		.rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
217 	},
218 	{ .name = "per", .base = 0x44df0800, .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map, .clkdm_name = "pruss_ocp" },
219 	{ .name = "wkup", .base = 0x44df2000, .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map, .flags = OMAP_PRM_HAS_NO_CLKDM },
220 	{ .name = "device", .base = 0x44df4000, .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM },
221 	{ },
222 };
223 
224 static const struct of_device_id omap_prm_id_table[] = {
225 	{ .compatible = "ti,omap4-prm-inst", .data = omap4_prm_data },
226 	{ .compatible = "ti,omap5-prm-inst", .data = omap5_prm_data },
227 	{ .compatible = "ti,dra7-prm-inst", .data = dra7_prm_data },
228 	{ .compatible = "ti,am3-prm-inst", .data = am3_prm_data },
229 	{ .compatible = "ti,am4-prm-inst", .data = am4_prm_data },
230 	{ },
231 };
232 
233 #ifdef DEBUG
omap_prm_domain_show_state(struct omap_prm_domain * prmd,const char * desc)234 static void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
235 				       const char *desc)
236 {
237 	dev_dbg(prmd->dev, "%s %s: %08x/%08x\n",
238 		prmd->pd.name, desc,
239 		readl_relaxed(prmd->prm->base + prmd->pwrstctrl),
240 		readl_relaxed(prmd->prm->base + prmd->pwrstst));
241 }
242 #else
omap_prm_domain_show_state(struct omap_prm_domain * prmd,const char * desc)243 static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
244 					      const char *desc)
245 {
246 }
247 #endif
248 
omap_prm_domain_power_on(struct generic_pm_domain * domain)249 static int omap_prm_domain_power_on(struct generic_pm_domain *domain)
250 {
251 	struct omap_prm_domain *prmd;
252 	int ret;
253 	u32 v;
254 
255 	prmd = genpd_to_prm_domain(domain);
256 	if (!prmd->cap)
257 		return 0;
258 
259 	omap_prm_domain_show_state(prmd, "on: previous state");
260 
261 	if (prmd->pwrstctrl_saved)
262 		v = prmd->pwrstctrl_saved;
263 	else
264 		v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
265 
266 	writel_relaxed(v | OMAP_PRMD_ON_ACTIVE,
267 		       prmd->prm->base + prmd->pwrstctrl);
268 
269 	/* wait for the transition bit to get cleared */
270 	ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
271 					 v, !(v & PRM_ST_INTRANSITION), 1,
272 					 PRM_STATE_MAX_WAIT);
273 	if (ret)
274 		dev_err(prmd->dev, "%s: %s timed out\n",
275 			prmd->pd.name, __func__);
276 
277 	omap_prm_domain_show_state(prmd, "on: new state");
278 
279 	return ret;
280 }
281 
282 /* No need to check for holes in the mask for the lowest mode */
omap_prm_domain_find_lowest(struct omap_prm_domain * prmd)283 static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd)
284 {
285 	return __ffs(prmd->cap->usable_modes);
286 }
287 
omap_prm_domain_power_off(struct generic_pm_domain * domain)288 static int omap_prm_domain_power_off(struct generic_pm_domain *domain)
289 {
290 	struct omap_prm_domain *prmd;
291 	int ret;
292 	u32 v;
293 
294 	prmd = genpd_to_prm_domain(domain);
295 	if (!prmd->cap)
296 		return 0;
297 
298 	omap_prm_domain_show_state(prmd, "off: previous state");
299 
300 	v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
301 	prmd->pwrstctrl_saved = v;
302 
303 	v &= ~PRM_POWERSTATE_MASK;
304 	v |= omap_prm_domain_find_lowest(prmd);
305 
306 	if (prmd->cap->statechange)
307 		v |= PRM_LOWPOWERSTATECHANGE;
308 	if (prmd->cap->logicretstate)
309 		v &= ~PRM_LOGICRETSTATE;
310 	else
311 		v |= PRM_LOGICRETSTATE;
312 
313 	writel_relaxed(v, prmd->prm->base + prmd->pwrstctrl);
314 
315 	/* wait for the transition bit to get cleared */
316 	ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
317 					 v, !(v & PRM_ST_INTRANSITION), 1,
318 					 PRM_STATE_MAX_WAIT);
319 	if (ret)
320 		dev_warn(prmd->dev, "%s: %s timed out\n",
321 			 __func__, prmd->pd.name);
322 
323 	omap_prm_domain_show_state(prmd, "off: new state");
324 
325 	return 0;
326 }
327 
omap_prm_domain_attach_dev(struct generic_pm_domain * domain,struct device * dev)328 static int omap_prm_domain_attach_dev(struct generic_pm_domain *domain,
329 				      struct device *dev)
330 {
331 	struct generic_pm_domain_data *genpd_data;
332 	struct of_phandle_args pd_args;
333 	struct omap_prm_domain *prmd;
334 	struct device_node *np;
335 	int ret;
336 
337 	prmd = genpd_to_prm_domain(domain);
338 	np = dev->of_node;
339 
340 	ret = of_parse_phandle_with_args(np, "power-domains",
341 					 "#power-domain-cells", 0, &pd_args);
342 	if (ret < 0)
343 		return ret;
344 
345 	if (pd_args.args_count != 0)
346 		dev_warn(dev, "%s: unusupported #power-domain-cells: %i\n",
347 			 prmd->pd.name, pd_args.args_count);
348 
349 	genpd_data = dev_gpd_data(dev);
350 	genpd_data->data = NULL;
351 
352 	return 0;
353 }
354 
omap_prm_domain_detach_dev(struct generic_pm_domain * domain,struct device * dev)355 static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain,
356 				       struct device *dev)
357 {
358 	struct generic_pm_domain_data *genpd_data;
359 
360 	genpd_data = dev_gpd_data(dev);
361 	genpd_data->data = NULL;
362 }
363 
omap_prm_domain_init(struct device * dev,struct omap_prm * prm)364 static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
365 {
366 	struct omap_prm_domain *prmd;
367 	struct device_node *np = dev->of_node;
368 	const struct omap_prm_data *data;
369 	const char *name;
370 	int error;
371 
372 	if (!of_find_property(dev->of_node, "#power-domain-cells", NULL))
373 		return 0;
374 
375 	of_node_put(dev->of_node);
376 
377 	prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL);
378 	if (!prmd)
379 		return -ENOMEM;
380 
381 	data = prm->data;
382 	name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s",
383 			      data->name);
384 
385 	prmd->dev = dev;
386 	prmd->prm = prm;
387 	prmd->cap = prmd->prm->data->dmap;
388 	prmd->pwrstctrl = prmd->prm->data->pwrstctrl;
389 	prmd->pwrstst = prmd->prm->data->pwrstst;
390 
391 	prmd->pd.name = name;
392 	prmd->pd.power_on = omap_prm_domain_power_on;
393 	prmd->pd.power_off = omap_prm_domain_power_off;
394 	prmd->pd.attach_dev = omap_prm_domain_attach_dev;
395 	prmd->pd.detach_dev = omap_prm_domain_detach_dev;
396 
397 	pm_genpd_init(&prmd->pd, NULL, true);
398 	error = of_genpd_add_provider_simple(np, &prmd->pd);
399 	if (error)
400 		pm_genpd_remove(&prmd->pd);
401 	else
402 		prm->prmd = prmd;
403 
404 	return error;
405 }
406 
_is_valid_reset(struct omap_reset_data * reset,unsigned long id)407 static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id)
408 {
409 	if (reset->mask & BIT(id))
410 		return true;
411 
412 	return false;
413 }
414 
omap_reset_get_st_bit(struct omap_reset_data * reset,unsigned long id)415 static int omap_reset_get_st_bit(struct omap_reset_data *reset,
416 				 unsigned long id)
417 {
418 	const struct omap_rst_map *map = reset->prm->data->rstmap;
419 
420 	while (map->rst >= 0) {
421 		if (map->rst == id)
422 			return map->st;
423 
424 		map++;
425 	}
426 
427 	return id;
428 }
429 
omap_reset_status(struct reset_controller_dev * rcdev,unsigned long id)430 static int omap_reset_status(struct reset_controller_dev *rcdev,
431 			     unsigned long id)
432 {
433 	struct omap_reset_data *reset = to_omap_reset_data(rcdev);
434 	u32 v;
435 	int st_bit = omap_reset_get_st_bit(reset, id);
436 	bool has_rstst = reset->prm->data->rstst ||
437 		(reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
438 
439 	/* Check if we have rstst */
440 	if (!has_rstst)
441 		return -ENOTSUPP;
442 
443 	/* Check if hw reset line is asserted */
444 	v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
445 	if (v & BIT(id))
446 		return 1;
447 
448 	/*
449 	 * Check reset status, high value means reset sequence has been
450 	 * completed successfully so we can return 0 here (reset deasserted)
451 	 */
452 	v = readl_relaxed(reset->prm->base + reset->prm->data->rstst);
453 	v >>= st_bit;
454 	v &= 1;
455 
456 	return !v;
457 }
458 
omap_reset_assert(struct reset_controller_dev * rcdev,unsigned long id)459 static int omap_reset_assert(struct reset_controller_dev *rcdev,
460 			     unsigned long id)
461 {
462 	struct omap_reset_data *reset = to_omap_reset_data(rcdev);
463 	u32 v;
464 	unsigned long flags;
465 
466 	/* assert the reset control line */
467 	spin_lock_irqsave(&reset->lock, flags);
468 	v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
469 	v |= 1 << id;
470 	writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
471 	spin_unlock_irqrestore(&reset->lock, flags);
472 
473 	return 0;
474 }
475 
omap_reset_deassert(struct reset_controller_dev * rcdev,unsigned long id)476 static int omap_reset_deassert(struct reset_controller_dev *rcdev,
477 			       unsigned long id)
478 {
479 	struct omap_reset_data *reset = to_omap_reset_data(rcdev);
480 	u32 v;
481 	int st_bit;
482 	bool has_rstst;
483 	unsigned long flags;
484 	struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev);
485 	int ret = 0;
486 
487 	/* Nothing to do if the reset is already deasserted */
488 	if (!omap_reset_status(rcdev, id))
489 		return 0;
490 
491 	has_rstst = reset->prm->data->rstst ||
492 		(reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
493 
494 	if (has_rstst) {
495 		st_bit = omap_reset_get_st_bit(reset, id);
496 
497 		/* Clear the reset status by writing 1 to the status bit */
498 		v = 1 << st_bit;
499 		writel_relaxed(v, reset->prm->base + reset->prm->data->rstst);
500 	}
501 
502 	if (reset->clkdm)
503 		pdata->clkdm_deny_idle(reset->clkdm);
504 
505 	/* de-assert the reset control line */
506 	spin_lock_irqsave(&reset->lock, flags);
507 	v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
508 	v &= ~(1 << id);
509 	writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
510 	spin_unlock_irqrestore(&reset->lock, flags);
511 
512 	/* wait for the reset bit to clear */
513 	ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
514 						reset->prm->data->rstctrl,
515 						v, !(v & BIT(id)), 1,
516 						OMAP_RESET_MAX_WAIT);
517 	if (ret)
518 		pr_err("%s: timedout waiting for %s:%lu\n", __func__,
519 		       reset->prm->data->name, id);
520 
521 	/* wait for the status to be set */
522 	if (has_rstst) {
523 		ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
524 						 reset->prm->data->rstst,
525 						 v, v & BIT(st_bit), 1,
526 						 OMAP_RESET_MAX_WAIT);
527 		if (ret)
528 			pr_err("%s: timedout waiting for %s:%lu\n", __func__,
529 			       reset->prm->data->name, id);
530 	}
531 
532 	if (reset->clkdm)
533 		pdata->clkdm_allow_idle(reset->clkdm);
534 
535 	return ret;
536 }
537 
538 static const struct reset_control_ops omap_reset_ops = {
539 	.assert		= omap_reset_assert,
540 	.deassert	= omap_reset_deassert,
541 	.status		= omap_reset_status,
542 };
543 
omap_prm_reset_xlate(struct reset_controller_dev * rcdev,const struct of_phandle_args * reset_spec)544 static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev,
545 				const struct of_phandle_args *reset_spec)
546 {
547 	struct omap_reset_data *reset = to_omap_reset_data(rcdev);
548 
549 	if (!_is_valid_reset(reset, reset_spec->args[0]))
550 		return -EINVAL;
551 
552 	return reset_spec->args[0];
553 }
554 
omap_prm_reset_init(struct platform_device * pdev,struct omap_prm * prm)555 static int omap_prm_reset_init(struct platform_device *pdev,
556 			       struct omap_prm *prm)
557 {
558 	struct omap_reset_data *reset;
559 	const struct omap_rst_map *map;
560 	struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev);
561 	char buf[32];
562 	u32 v;
563 
564 	/*
565 	 * Check if we have controllable resets. If either rstctrl is non-zero
566 	 * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register
567 	 * for the domain.
568 	 */
569 	if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL))
570 		return 0;
571 
572 	/* Check if we have the pdata callbacks in place */
573 	if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle ||
574 	    !pdata->clkdm_allow_idle)
575 		return -EINVAL;
576 
577 	map = prm->data->rstmap;
578 	if (!map)
579 		return -EINVAL;
580 
581 	reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
582 	if (!reset)
583 		return -ENOMEM;
584 
585 	reset->rcdev.owner = THIS_MODULE;
586 	reset->rcdev.ops = &omap_reset_ops;
587 	reset->rcdev.of_node = pdev->dev.of_node;
588 	reset->rcdev.nr_resets = OMAP_MAX_RESETS;
589 	reset->rcdev.of_xlate = omap_prm_reset_xlate;
590 	reset->rcdev.of_reset_n_cells = 1;
591 	reset->dev = &pdev->dev;
592 	spin_lock_init(&reset->lock);
593 
594 	reset->prm = prm;
595 
596 	sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name :
597 		prm->data->name);
598 
599 	if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) {
600 		reset->clkdm = pdata->clkdm_lookup(buf);
601 		if (!reset->clkdm)
602 			return -EINVAL;
603 	}
604 
605 	while (map->rst >= 0) {
606 		reset->mask |= BIT(map->rst);
607 		map++;
608 	}
609 
610 	/* Quirk handling to assert rst_map_012 bits on reset and avoid errors */
611 	if (prm->data->rstmap == rst_map_012) {
612 		v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
613 		if ((v & reset->mask) != reset->mask) {
614 			dev_dbg(&pdev->dev, "Asserting all resets: %08x\n", v);
615 			writel_relaxed(reset->mask, reset->prm->base +
616 				       reset->prm->data->rstctrl);
617 		}
618 	}
619 
620 	return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
621 }
622 
omap_prm_probe(struct platform_device * pdev)623 static int omap_prm_probe(struct platform_device *pdev)
624 {
625 	struct resource *res;
626 	const struct omap_prm_data *data;
627 	struct omap_prm *prm;
628 	const struct of_device_id *match;
629 	int ret;
630 
631 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
632 	if (!res)
633 		return -ENODEV;
634 
635 	match = of_match_device(omap_prm_id_table, &pdev->dev);
636 	if (!match)
637 		return -ENOTSUPP;
638 
639 	prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL);
640 	if (!prm)
641 		return -ENOMEM;
642 
643 	data = match->data;
644 
645 	while (data->base != res->start) {
646 		if (!data->base)
647 			return -EINVAL;
648 		data++;
649 	}
650 
651 	prm->data = data;
652 
653 	prm->base = devm_ioremap_resource(&pdev->dev, res);
654 	if (IS_ERR(prm->base))
655 		return PTR_ERR(prm->base);
656 
657 	ret = omap_prm_domain_init(&pdev->dev, prm);
658 	if (ret)
659 		return ret;
660 
661 	ret = omap_prm_reset_init(pdev, prm);
662 	if (ret)
663 		goto err_domain;
664 
665 	return 0;
666 
667 err_domain:
668 	of_genpd_del_provider(pdev->dev.of_node);
669 	pm_genpd_remove(&prm->prmd->pd);
670 
671 	return ret;
672 }
673 
674 static struct platform_driver omap_prm_driver = {
675 	.probe = omap_prm_probe,
676 	.driver = {
677 		.name		= KBUILD_MODNAME,
678 		.of_match_table	= omap_prm_id_table,
679 	},
680 };
681 builtin_platform_driver(omap_prm_driver);
682