Skip to content

Commit e2e1c4e

Browse files
committed
Merge branch 'at91-4.14-trunk/sys-reset' into linux-4.14-at91
Signed-off-by: Cristian Birsan <cristian.birsan@microchip.com>
2 parents 376cf59 + 14bfaa1 commit e2e1c4e

2 files changed

Lines changed: 88 additions & 39 deletions

File tree

arch/arm/mach-at91/pm_suspend.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ exit_suspend:
149149
ENDPROC(at91_pm_suspend_in_sram)
150150

151151
ENTRY(at91_backup_mode)
152+
/* Switch the master clock source to slow clock. */
153+
ldr pmc, .pmc_base
154+
ldr tmp1, [pmc, #AT91_PMC_MCKR]
155+
bic tmp1, tmp1, #AT91_PMC_CSS
156+
str tmp1, [pmc, #AT91_PMC_MCKR]
157+
158+
wait_mckrdy
159+
152160
/*BUMEN*/
153161
ldr r0, .sfr
154162
mov tmp1, #0x1

drivers/power/reset/at91-sama5d2_shdwc.c

Lines changed: 80 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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

7071
struct 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
*/
7983
static struct shdwc *at91_shdwc;
80-
static struct clk *sclk;
81-
static void __iomem *mpddrc_base;
8284

8385
static 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

109111
static 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

222231
static 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

301339
static 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

Comments
 (0)