1 /*
2  * Atmel SAMA5D2-Compatible Shutdown Controller (SHDWC) driver.
3  * Found on some SoCs as the sama5d2 (obviously).
4  *
5  * Copyright (C) 2015 Atmel Corporation,
6  *                    Nicolas Ferre <nicolas.ferre@atmel.com>
7  *
8  * Evolved from driver at91-poweroff.c.
9  *
10  * This file is licensed under the terms of the GNU General Public
11  * License version 2.  This program is licensed "as is" without any
12  * warranty of any kind, whether express or implied.
13  *
14  * TODO:
15  * - addition to status of other wake-up inputs [1 - 15]
16  * - Analog Comparator wake-up alarm
17  * - Serial RX wake-up alarm
18  * - low power debouncer
19  */
20 
21 #include <linux/clk.h>
22 #include <linux/clk/at91_pmc.h>
23 #include <linux/io.h>
24 #include <linux/module.h>
25 #include <linux/of.h>
26 #include <linux/of_address.h>
27 #include <linux/platform_device.h>
28 #include <linux/printk.h>
29 
30 #include <soc/at91/at91sam9_ddrsdr.h>
31 
32 #define SLOW_CLOCK_FREQ	32768
33 
34 #define AT91_SHDW_CR	0x00		/* Shut Down Control Register */
35 #define AT91_SHDW_SHDW		BIT(0)			/* Shut Down command */
36 #define AT91_SHDW_KEY		(0xa5UL << 24)		/* KEY Password */
37 
38 #define AT91_SHDW_MR	0x04		/* Shut Down Mode Register */
39 #define AT91_SHDW_WKUPDBC_SHIFT	24
40 #define AT91_SHDW_WKUPDBC_MASK	GENMASK(31, 16)
41 #define AT91_SHDW_WKUPDBC(x)	(((x) << AT91_SHDW_WKUPDBC_SHIFT) \
42 						& AT91_SHDW_WKUPDBC_MASK)
43 
44 #define AT91_SHDW_SR	0x08		/* Shut Down Status Register */
45 #define AT91_SHDW_WKUPIS_SHIFT	16
46 #define AT91_SHDW_WKUPIS_MASK	GENMASK(31, 16)
47 #define AT91_SHDW_WKUPIS(x)	((1 << (x)) << AT91_SHDW_WKUPIS_SHIFT \
48 						& AT91_SHDW_WKUPIS_MASK)
49 
50 #define AT91_SHDW_WUIR	0x0c		/* Shutdown Wake-up Inputs Register */
51 #define AT91_SHDW_WKUPEN_MASK	GENMASK(15, 0)
52 #define AT91_SHDW_WKUPEN(x)	((1 << (x)) & AT91_SHDW_WKUPEN_MASK)
53 #define AT91_SHDW_WKUPT_SHIFT	16
54 #define AT91_SHDW_WKUPT_MASK	GENMASK(31, 16)
55 #define AT91_SHDW_WKUPT(x)	((1 << (x)) << AT91_SHDW_WKUPT_SHIFT \
56 						& AT91_SHDW_WKUPT_MASK)
57 
58 #define SHDW_WK_PIN(reg, cfg)	((reg) & AT91_SHDW_WKUPIS((cfg)->wkup_pin_input))
59 #define SHDW_RTCWK(reg, cfg)	(((reg) >> ((cfg)->sr_rtcwk_shift)) & 0x1)
60 #define SHDW_RTTWK(reg, cfg)	(((reg) >> ((cfg)->sr_rttwk_shift)) & 0x1)
61 #define SHDW_RTCWKEN(cfg)	(1 << ((cfg)->mr_rtcwk_shift))
62 #define SHDW_RTTWKEN(cfg)	(1 << ((cfg)->mr_rttwk_shift))
63 
64 #define DBC_PERIOD_US(x)	DIV_ROUND_UP_ULL((1000000 * (x)), \
65 							SLOW_CLOCK_FREQ)
66 
67 #define SHDW_CFG_NOT_USED	(32)
68 
69 struct shdwc_reg_config {
70 	u8 wkup_pin_input;
71 	u8 mr_rtcwk_shift;
72 	u8 mr_rttwk_shift;
73 	u8 sr_rtcwk_shift;
74 	u8 sr_rttwk_shift;
75 };
76 
77 struct pmc_reg_config {
78 	u8 mckr;
79 };
80 
81 struct reg_config {
82 	struct shdwc_reg_config shdwc;
83 	struct pmc_reg_config pmc;
84 };
85 
86 struct shdwc {
87 	const struct reg_config *rcfg;
88 	struct clk *sclk;
89 	void __iomem *shdwc_base;
90 	void __iomem *mpddrc_base;
91 	void __iomem *pmc_base;
92 };
93 
94 /*
95  * Hold configuration here, cannot be more than one instance of the driver
96  * since pm_power_off itself is global.
97  */
98 static struct shdwc *at91_shdwc;
99 
100 static const unsigned long long sdwc_dbc_period[] = {
101 	0, 3, 32, 512, 4096, 32768,
102 };
103 
104 static void __init at91_wakeup_status(struct platform_device *pdev)
105 {
106 	struct shdwc *shdw = platform_get_drvdata(pdev);
107 	const struct reg_config *rcfg = shdw->rcfg;
108 	u32 reg;
109 	char *reason = "unknown";
110 
111 	reg = readl(shdw->shdwc_base + AT91_SHDW_SR);
112 
113 	dev_dbg(&pdev->dev, "%s: status = %#x\n", __func__, reg);
114 
115 	/* Simple power-on, just bail out */
116 	if (!reg)
117 		return;
118 
119 	if (SHDW_WK_PIN(reg, &rcfg->shdwc))
120 		reason = "WKUP pin";
121 	else if (SHDW_RTCWK(reg, &rcfg->shdwc))
122 		reason = "RTC";
123 	else if (SHDW_RTTWK(reg, &rcfg->shdwc))
124 		reason = "RTT";
125 
126 	pr_info("AT91: Wake-Up source: %s\n", reason);
127 }
128 
129 static void at91_poweroff(void)
130 {
131 	asm volatile(
132 		/* Align to cache lines */
133 		".balign 32\n\t"
134 
135 		/* Ensure AT91_SHDW_CR is in the TLB by reading it */
136 		"	ldr	r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
137 
138 		/* Power down SDRAM0 */
139 		"	tst	%0, #0\n\t"
140 		"	beq	1f\n\t"
141 		"	str	%1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
142 
143 		/* Switch the master clock source to slow clock. */
144 		"1:	ldr	r6, [%4, %5]\n\t"
145 		"	bic	r6, r6,  #" __stringify(AT91_PMC_CSS) "\n\t"
146 		"	str	r6, [%4, %5]\n\t"
147 		/* Wait for clock switch. */
148 		"2:	ldr	r6, [%4, #" __stringify(AT91_PMC_SR) "]\n\t"
149 		"	tst	r6, #"	    __stringify(AT91_PMC_MCKRDY) "\n\t"
150 		"	beq	2b\n\t"
151 
152 		/* Shutdown CPU */
153 		"	str	%3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
154 
155 		"	b	.\n\t"
156 		:
157 		: "r" (at91_shdwc->mpddrc_base),
158 		  "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF),
159 		  "r" (at91_shdwc->shdwc_base),
160 		  "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW),
161 		  "r" (at91_shdwc->pmc_base),
162 		  "r" (at91_shdwc->rcfg->pmc.mckr)
163 		: "r6");
164 }
165 
166 static u32 at91_shdwc_debouncer_value(struct platform_device *pdev,
167 				      u32 in_period_us)
168 {
169 	int i;
170 	int max_idx = ARRAY_SIZE(sdwc_dbc_period) - 1;
171 	unsigned long long period_us;
172 	unsigned long long max_period_us = DBC_PERIOD_US(sdwc_dbc_period[max_idx]);
173 
174 	if (in_period_us > max_period_us) {
175 		dev_warn(&pdev->dev,
176 			 "debouncer period %u too big, reduced to %llu us\n",
177 			 in_period_us, max_period_us);
178 		return max_idx;
179 	}
180 
181 	for (i = max_idx - 1; i > 0; i--) {
182 		period_us = DBC_PERIOD_US(sdwc_dbc_period[i]);
183 		dev_dbg(&pdev->dev, "%s: ref[%d] = %llu\n",
184 						__func__, i, period_us);
185 		if (in_period_us > period_us)
186 			break;
187 	}
188 
189 	return i + 1;
190 }
191 
192 static u32 at91_shdwc_get_wakeup_input(struct platform_device *pdev,
193 				       struct device_node *np)
194 {
195 	struct device_node *cnp;
196 	u32 wk_input_mask;
197 	u32 wuir = 0;
198 	u32 wk_input;
199 
200 	for_each_child_of_node(np, cnp) {
201 		if (of_property_read_u32(cnp, "reg", &wk_input)) {
202 			dev_warn(&pdev->dev, "reg property is missing for %pOF\n",
203 				 cnp);
204 			continue;
205 		}
206 
207 		wk_input_mask = 1 << wk_input;
208 		if (!(wk_input_mask & AT91_SHDW_WKUPEN_MASK)) {
209 			dev_warn(&pdev->dev,
210 				 "wake-up input %d out of bounds ignore\n",
211 				 wk_input);
212 			continue;
213 		}
214 		wuir |= wk_input_mask;
215 
216 		if (of_property_read_bool(cnp, "atmel,wakeup-active-high"))
217 			wuir |= AT91_SHDW_WKUPT(wk_input);
218 
219 		dev_dbg(&pdev->dev, "%s: (child %d) wuir = %#x\n",
220 						__func__, wk_input, wuir);
221 	}
222 
223 	return wuir;
224 }
225 
226 static void at91_shdwc_dt_configure(struct platform_device *pdev)
227 {
228 	struct shdwc *shdw = platform_get_drvdata(pdev);
229 	const struct reg_config *rcfg = shdw->rcfg;
230 	struct device_node *np = pdev->dev.of_node;
231 	u32 mode = 0, tmp, input;
232 
233 	if (!np) {
234 		dev_err(&pdev->dev, "device node not found\n");
235 		return;
236 	}
237 
238 	if (!of_property_read_u32(np, "debounce-delay-us", &tmp))
239 		mode |= AT91_SHDW_WKUPDBC(at91_shdwc_debouncer_value(pdev, tmp));
240 
241 	if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
242 		mode |= SHDW_RTCWKEN(&rcfg->shdwc);
243 
244 	if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
245 		mode |= SHDW_RTTWKEN(&rcfg->shdwc);
246 
247 	dev_dbg(&pdev->dev, "%s: mode = %#x\n", __func__, mode);
248 	writel(mode, shdw->shdwc_base + AT91_SHDW_MR);
249 
250 	input = at91_shdwc_get_wakeup_input(pdev, np);
251 	writel(input, shdw->shdwc_base + AT91_SHDW_WUIR);
252 }
253 
254 static const struct reg_config sama5d2_reg_config = {
255 	.shdwc = {
256 		.wkup_pin_input = 0,
257 		.mr_rtcwk_shift = 17,
258 		.mr_rttwk_shift	= SHDW_CFG_NOT_USED,
259 		.sr_rtcwk_shift = 5,
260 		.sr_rttwk_shift = SHDW_CFG_NOT_USED,
261 	},
262 	.pmc = {
263 		.mckr		= 0x30,
264 	},
265 };
266 
267 static const struct reg_config sam9x60_reg_config = {
268 	.shdwc = {
269 		.wkup_pin_input = 0,
270 		.mr_rtcwk_shift = 17,
271 		.mr_rttwk_shift = 16,
272 		.sr_rtcwk_shift = 5,
273 		.sr_rttwk_shift = 4,
274 	},
275 	.pmc = {
276 		.mckr		= 0x28,
277 	},
278 };
279 
280 static const struct of_device_id at91_shdwc_of_match[] = {
281 	{
282 		.compatible = "atmel,sama5d2-shdwc",
283 		.data = &sama5d2_reg_config,
284 	},
285 	{
286 		.compatible = "microchip,sam9x60-shdwc",
287 		.data = &sam9x60_reg_config,
288 	}, {
289 		/*sentinel*/
290 	}
291 };
292 MODULE_DEVICE_TABLE(of, at91_shdwc_of_match);
293 
294 static const struct of_device_id at91_pmc_ids[] = {
295 	{ .compatible = "atmel,sama5d2-pmc" },
296 	{ .compatible = "microchip,sam9x60-pmc" },
297 	{ /* Sentinel. */ }
298 };
299 
300 static int __init at91_shdwc_probe(struct platform_device *pdev)
301 {
302 	struct resource *res;
303 	const struct of_device_id *match;
304 	struct device_node *np;
305 	u32 ddr_type;
306 	int ret;
307 
308 	if (!pdev->dev.of_node)
309 		return -ENODEV;
310 
311 	if (at91_shdwc)
312 		return -EBUSY;
313 
314 	at91_shdwc = devm_kzalloc(&pdev->dev, sizeof(*at91_shdwc), GFP_KERNEL);
315 	if (!at91_shdwc)
316 		return -ENOMEM;
317 
318 	platform_set_drvdata(pdev, at91_shdwc);
319 
320 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
321 	at91_shdwc->shdwc_base = devm_ioremap_resource(&pdev->dev, res);
322 	if (IS_ERR(at91_shdwc->shdwc_base)) {
323 		dev_err(&pdev->dev, "Could not map reset controller address\n");
324 		return PTR_ERR(at91_shdwc->shdwc_base);
325 	}
326 
327 	match = of_match_node(at91_shdwc_of_match, pdev->dev.of_node);
328 	at91_shdwc->rcfg = match->data;
329 
330 	at91_shdwc->sclk = devm_clk_get(&pdev->dev, NULL);
331 	if (IS_ERR(at91_shdwc->sclk))
332 		return PTR_ERR(at91_shdwc->sclk);
333 
334 	ret = clk_prepare_enable(at91_shdwc->sclk);
335 	if (ret) {
336 		dev_err(&pdev->dev, "Could not enable slow clock\n");
337 		return ret;
338 	}
339 
340 	at91_wakeup_status(pdev);
341 
342 	at91_shdwc_dt_configure(pdev);
343 
344 	np = of_find_matching_node(NULL, at91_pmc_ids);
345 	if (!np) {
346 		ret = -ENODEV;
347 		goto clk_disable;
348 	}
349 
350 	at91_shdwc->pmc_base = of_iomap(np, 0);
351 	of_node_put(np);
352 
353 	if (!at91_shdwc->pmc_base) {
354 		ret = -ENOMEM;
355 		goto clk_disable;
356 	}
357 
358 	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc");
359 	if (!np) {
360 		ret = -ENODEV;
361 		goto unmap;
362 	}
363 
364 	at91_shdwc->mpddrc_base = of_iomap(np, 0);
365 	of_node_put(np);
366 
367 	if (!at91_shdwc->mpddrc_base) {
368 		ret = -ENOMEM;
369 		goto unmap;
370 	}
371 
372 	pm_power_off = at91_poweroff;
373 
374 	ddr_type = readl(at91_shdwc->mpddrc_base + AT91_DDRSDRC_MDR) &
375 			 AT91_DDRSDRC_MD;
376 	if (ddr_type != AT91_DDRSDRC_MD_LPDDR2 &&
377 	    ddr_type != AT91_DDRSDRC_MD_LPDDR3) {
378 		iounmap(at91_shdwc->mpddrc_base);
379 		at91_shdwc->mpddrc_base = NULL;
380 	}
381 
382 	return 0;
383 
384 unmap:
385 	iounmap(at91_shdwc->pmc_base);
386 clk_disable:
387 	clk_disable_unprepare(at91_shdwc->sclk);
388 
389 	return ret;
390 }
391 
392 static int __exit at91_shdwc_remove(struct platform_device *pdev)
393 {
394 	struct shdwc *shdw = platform_get_drvdata(pdev);
395 
396 	if (pm_power_off == at91_poweroff)
397 		pm_power_off = NULL;
398 
399 	/* Reset values to disable wake-up features  */
400 	writel(0, shdw->shdwc_base + AT91_SHDW_MR);
401 	writel(0, shdw->shdwc_base + AT91_SHDW_WUIR);
402 
403 	if (shdw->mpddrc_base)
404 		iounmap(shdw->mpddrc_base);
405 	iounmap(shdw->pmc_base);
406 
407 	clk_disable_unprepare(shdw->sclk);
408 
409 	return 0;
410 }
411 
412 static struct platform_driver at91_shdwc_driver = {
413 	.remove = __exit_p(at91_shdwc_remove),
414 	.driver = {
415 		.name = "at91-shdwc",
416 		.of_match_table = at91_shdwc_of_match,
417 	},
418 };
419 module_platform_driver_probe(at91_shdwc_driver, at91_shdwc_probe);
420 
421 MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
422 MODULE_DESCRIPTION("Atmel shutdown controller driver");
423 MODULE_LICENSE("GPL v2");
424