1919 */
2020
2121#include <linux/clk.h>
22+ #include <linux/clk/at91_pmc.h>
2223#include <linux/io.h>
2324#include <linux/module.h>
2425#include <linux/of.h>
@@ -69,16 +70,17 @@ struct shdwc_config {
6970
7071struct shdwc {
7172 const struct shdwc_config * cfg ;
72- void __iomem * at91_shdwc_base ;
73+ struct clk * sclk ;
74+ void __iomem * shdwc_base ;
75+ void __iomem * mpddrc_base ;
76+ void __iomem * pmc_base ;
7377};
7478
7579/*
7680 * Hold configuration here, cannot be more than one instance of the driver
7781 * since pm_power_off itself is global.
7882 */
7983static struct shdwc * at91_shdwc ;
80- static struct clk * sclk ;
81- static void __iomem * mpddrc_base ;
8284
8385static const unsigned long long sdwc_dbc_period [] = {
8486 0 , 3 , 32 , 512 , 4096 , 32768 ,
@@ -90,7 +92,7 @@ static void __init at91_wakeup_status(struct platform_device *pdev)
9092 u32 reg ;
9193 char * reason = "unknown" ;
9294
93- reg = readl (shdw -> at91_shdwc_base + AT91_SHDW_SR );
95+ reg = readl (shdw -> shdwc_base + AT91_SHDW_SR );
9496
9597 dev_dbg (& pdev -> dev , "%s: status = %#x\n" , __func__ , reg );
9698
@@ -107,12 +109,6 @@ static void __init at91_wakeup_status(struct platform_device *pdev)
107109}
108110
109111static void at91_poweroff (void )
110- {
111- writel (AT91_SHDW_KEY | AT91_SHDW_SHDW ,
112- at91_shdwc -> at91_shdwc_base + AT91_SHDW_CR );
113- }
114-
115- static void at91_lpddr_poweroff (void )
116112{
117113 asm volatile (
118114 /* Align to cache lines */
@@ -122,16 +118,29 @@ static void at91_lpddr_poweroff(void)
122118 " ldr r6, [%2, #" __stringify (AT91_SHDW_CR ) "]\n\t"
123119
124120 /* Power down SDRAM0 */
121+ " tst %0, #0\n\t"
122+ " beq 1f\n\t"
125123 " str %1, [%0, #" __stringify (AT91_DDRSDRC_LPR ) "]\n\t"
124+
125+ /* Switch the master clock source to slow clock. */
126+ "1: ldr r6, [%4, #" __stringify (AT91_PMC_MCKR ) "]\n\t"
127+ " bic r6, r6, #" __stringify (AT91_PMC_CSS ) "\n\t"
128+ " str r6, [%4, #" __stringify (AT91_PMC_MCKR ) "]\n\t"
129+ /* Wait for clock switch. */
130+ "2: ldr r6, [%4, #" __stringify (AT91_PMC_SR ) "]\n\t"
131+ " tst r6, #" __stringify (AT91_PMC_MCKRDY ) "\n\t"
132+ " beq 2b\n\t"
133+
126134 /* Shutdown CPU */
127135 " str %3, [%2, #" __stringify (AT91_SHDW_CR ) "]\n\t"
128136
129137 " b .\n\t"
130138 :
131- : "r" (mpddrc_base ),
139+ : "r" (at91_shdwc -> mpddrc_base ),
132140 "r" cpu_to_le32 (AT91_DDRSDRC_LPDDR2_PWOFF ),
133- "r" (at91_shdwc -> at91_shdwc_base ),
134- "r" cpu_to_le32 (AT91_SHDW_KEY | AT91_SHDW_SHDW )
141+ "r" (at91_shdwc -> shdwc_base ),
142+ "r" cpu_to_le32 (AT91_SHDW_KEY | AT91_SHDW_SHDW ),
143+ "r" (at91_shdwc -> pmc_base )
135144 : "r6" );
136145}
137146
@@ -213,10 +222,10 @@ static void at91_shdwc_dt_configure(struct platform_device *pdev)
213222 mode |= SHDW_RTCWKEN (shdw -> cfg );
214223
215224 dev_dbg (& pdev -> dev , "%s: mode = %#x\n" , __func__ , mode );
216- writel (mode , shdw -> at91_shdwc_base + AT91_SHDW_MR );
225+ writel (mode , shdw -> shdwc_base + AT91_SHDW_MR );
217226
218227 input = at91_shdwc_get_wakeup_input (pdev , np );
219- writel (input , shdw -> at91_shdwc_base + AT91_SHDW_WUIR );
228+ writel (input , shdw -> shdwc_base + AT91_SHDW_WUIR );
220229}
221230
222231static const struct shdwc_config sama5d2_shdwc_config = {
@@ -246,27 +255,30 @@ static int __init at91_shdwc_probe(struct platform_device *pdev)
246255 if (!pdev -> dev .of_node )
247256 return - ENODEV ;
248257
258+ if (at91_shdwc )
259+ return - EBUSY ;
260+
249261 at91_shdwc = devm_kzalloc (& pdev -> dev , sizeof (* at91_shdwc ), GFP_KERNEL );
250262 if (!at91_shdwc )
251263 return - ENOMEM ;
252264
253265 platform_set_drvdata (pdev , at91_shdwc );
254266
255267 res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
256- at91_shdwc -> at91_shdwc_base = devm_ioremap_resource (& pdev -> dev , res );
257- if (IS_ERR (at91_shdwc -> at91_shdwc_base )) {
268+ at91_shdwc -> shdwc_base = devm_ioremap_resource (& pdev -> dev , res );
269+ if (IS_ERR (at91_shdwc -> shdwc_base )) {
258270 dev_err (& pdev -> dev , "Could not map reset controller address\n" );
259- return PTR_ERR (at91_shdwc -> at91_shdwc_base );
271+ return PTR_ERR (at91_shdwc -> shdwc_base );
260272 }
261273
262274 match = of_match_node (at91_shdwc_of_match , pdev -> dev .of_node );
263275 at91_shdwc -> cfg = match -> data ;
264276
265- sclk = devm_clk_get (& pdev -> dev , NULL );
266- if (IS_ERR (sclk ))
267- return PTR_ERR (sclk );
277+ at91_shdwc -> sclk = devm_clk_get (& pdev -> dev , NULL );
278+ if (IS_ERR (at91_shdwc -> sclk ))
279+ return PTR_ERR (at91_shdwc -> sclk );
268280
269- ret = clk_prepare_enable (sclk );
281+ ret = clk_prepare_enable (at91_shdwc -> sclk );
270282 if (ret ) {
271283 dev_err (& pdev -> dev , "Could not enable slow clock\n" );
272284 return ret ;
@@ -276,41 +288,70 @@ static int __init at91_shdwc_probe(struct platform_device *pdev)
276288
277289 at91_shdwc_dt_configure (pdev );
278290
279- pm_power_off = at91_poweroff ;
291+ np = of_find_compatible_node (NULL , NULL , "atmel,sama5d2-pmc" );
292+ if (!np ) {
293+ ret = - ENODEV ;
294+ goto clk_disable ;
295+ }
296+
297+ at91_shdwc -> pmc_base = of_iomap (np , 0 );
298+ of_node_put (np );
299+
300+ if (!at91_shdwc -> pmc_base ) {
301+ ret = - ENOMEM ;
302+ goto clk_disable ;
303+ }
280304
281305 np = of_find_compatible_node (NULL , NULL , "atmel,sama5d3-ddramc" );
282- if (!np )
283- return 0 ;
306+ if (!np ) {
307+ ret = - ENODEV ;
308+ goto unmap ;
309+ }
284310
285- mpddrc_base = of_iomap (np , 0 );
311+ at91_shdwc -> mpddrc_base = of_iomap (np , 0 );
286312 of_node_put (np );
287313
288- if (!mpddrc_base )
289- return 0 ;
314+ if (!at91_shdwc -> mpddrc_base ) {
315+ ret = - ENOMEM ;
316+ goto unmap ;
317+ }
290318
291- ddr_type = readl (mpddrc_base + AT91_DDRSDRC_MDR ) & AT91_DDRSDRC_MD ;
292- if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2 ) ||
293- (ddr_type == AT91_DDRSDRC_MD_LPDDR3 ))
294- pm_power_off = at91_lpddr_poweroff ;
295- else
296- iounmap (mpddrc_base );
319+ pm_power_off = at91_poweroff ;
320+
321+ ddr_type = readl (at91_shdwc -> mpddrc_base + AT91_DDRSDRC_MDR ) &
322+ AT91_DDRSDRC_MD ;
323+ if (ddr_type != AT91_DDRSDRC_MD_LPDDR2 &&
324+ ddr_type != AT91_DDRSDRC_MD_LPDDR3 ) {
325+ iounmap (at91_shdwc -> mpddrc_base );
326+ at91_shdwc -> mpddrc_base = NULL ;
327+ }
297328
298329 return 0 ;
330+
331+ unmap :
332+ iounmap (at91_shdwc -> pmc_base );
333+ clk_disable :
334+ clk_disable_unprepare (at91_shdwc -> sclk );
335+
336+ return ret ;
299337}
300338
301339static int __exit at91_shdwc_remove (struct platform_device * pdev )
302340{
303341 struct shdwc * shdw = platform_get_drvdata (pdev );
304342
305- if (pm_power_off == at91_poweroff ||
306- pm_power_off == at91_lpddr_poweroff )
343+ if (pm_power_off == at91_poweroff )
307344 pm_power_off = NULL ;
308345
309346 /* Reset values to disable wake-up features */
310- writel (0 , shdw -> at91_shdwc_base + AT91_SHDW_MR );
311- writel (0 , shdw -> at91_shdwc_base + AT91_SHDW_WUIR );
347+ writel (0 , shdw -> shdwc_base + AT91_SHDW_MR );
348+ writel (0 , shdw -> shdwc_base + AT91_SHDW_WUIR );
349+
350+ if (shdw -> mpddrc_base )
351+ iounmap (shdw -> mpddrc_base );
352+ iounmap (shdw -> pmc_base );
312353
313- clk_disable_unprepare (sclk );
354+ clk_disable_unprepare (shdw -> sclk );
314355
315356 return 0 ;
316357}
0 commit comments