Skip to content

Commit b4a25fb

Browse files
committed
Merge tag 'timers-v5.8-rc7' of https://git.linaro.org/people/daniel.lezcano/linux into timers/urgent
Pull a timer chip fix from Daniel Lezcano: - Fix kernel panic at suspend / resume time on TI am3/am4 (Tony Lindgren)
2 parents e2a71bd + 6cfcd55 commit b4a25fb

File tree

2 files changed

+58
-10
lines changed

2 files changed

+58
-10
lines changed

drivers/bus/ti-sysc.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2864,6 +2864,24 @@ static int sysc_check_disabled_devices(struct sysc *ddata)
28642864
return error;
28652865
}
28662866

2867+
/*
2868+
* Ignore timers tagged with no-reset and no-idle. These are likely in use,
2869+
* for example by drivers/clocksource/timer-ti-dm-systimer.c. If more checks
2870+
* are needed, we could also look at the timer register configuration.
2871+
*/
2872+
static int sysc_check_active_timer(struct sysc *ddata)
2873+
{
2874+
if (ddata->cap->type != TI_SYSC_OMAP2_TIMER &&
2875+
ddata->cap->type != TI_SYSC_OMAP4_TIMER)
2876+
return 0;
2877+
2878+
if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) &&
2879+
(ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE))
2880+
return -EBUSY;
2881+
2882+
return 0;
2883+
}
2884+
28672885
static const struct of_device_id sysc_match_table[] = {
28682886
{ .compatible = "simple-bus", },
28692887
{ /* sentinel */ },
@@ -2920,6 +2938,10 @@ static int sysc_probe(struct platform_device *pdev)
29202938
if (error)
29212939
return error;
29222940

2941+
error = sysc_check_active_timer(ddata);
2942+
if (error)
2943+
return error;
2944+
29232945
error = sysc_get_clocks(ddata);
29242946
if (error)
29252947
return error;

drivers/clocksource/timer-ti-dm-systimer.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/* For type1, set SYSC_OMAP2_CLOCKACTIVITY for fck off on idle, l4 clock on */
2020
#define DMTIMER_TYPE1_ENABLE ((1 << 9) | (SYSC_IDLE_SMART << 3) | \
2121
SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_AUTOIDLE)
22-
22+
#define DMTIMER_TYPE1_DISABLE (SYSC_OMAP2_SOFTRESET | SYSC_OMAP2_AUTOIDLE)
2323
#define DMTIMER_TYPE2_ENABLE (SYSC_IDLE_SMART_WKUP << 2)
2424
#define DMTIMER_RESET_WAIT 100000
2525

@@ -44,6 +44,8 @@ struct dmtimer_systimer {
4444
u8 ctrl;
4545
u8 wakeup;
4646
u8 ifctrl;
47+
struct clk *fck;
48+
struct clk *ick;
4749
unsigned long rate;
4850
};
4951

@@ -298,16 +300,20 @@ static void __init dmtimer_systimer_select_best(void)
298300
}
299301

300302
/* Interface clocks are only available on some SoCs variants */
301-
static int __init dmtimer_systimer_init_clock(struct device_node *np,
303+
static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
304+
struct device_node *np,
302305
const char *name,
303306
unsigned long *rate)
304307
{
305308
struct clk *clock;
306309
unsigned long r;
310+
bool is_ick = false;
307311
int error;
308312

313+
is_ick = !strncmp(name, "ick", 3);
314+
309315
clock = of_clk_get_by_name(np, name);
310-
if ((PTR_ERR(clock) == -EINVAL) && !strncmp(name, "ick", 3))
316+
if ((PTR_ERR(clock) == -EINVAL) && is_ick)
311317
return 0;
312318
else if (IS_ERR(clock))
313319
return PTR_ERR(clock);
@@ -320,6 +326,11 @@ static int __init dmtimer_systimer_init_clock(struct device_node *np,
320326
if (!r)
321327
return -ENODEV;
322328

329+
if (is_ick)
330+
t->ick = clock;
331+
else
332+
t->fck = clock;
333+
323334
*rate = r;
324335

325336
return 0;
@@ -339,7 +350,10 @@ static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
339350

340351
static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
341352
{
342-
writel_relaxed(0, t->base + t->sysc);
353+
if (!dmtimer_systimer_revision1(t))
354+
return;
355+
356+
writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
343357
}
344358

345359
static int __init dmtimer_systimer_setup(struct device_node *np,
@@ -366,13 +380,13 @@ static int __init dmtimer_systimer_setup(struct device_node *np,
366380
pr_err("%s: clock source init failed: %i\n", __func__, error);
367381

368382
/* For ti-sysc, we have timer clocks at the parent module level */
369-
error = dmtimer_systimer_init_clock(np->parent, "fck", &rate);
383+
error = dmtimer_systimer_init_clock(t, np->parent, "fck", &rate);
370384
if (error)
371385
goto err_unmap;
372386

373387
t->rate = rate;
374388

375-
error = dmtimer_systimer_init_clock(np->parent, "ick", &rate);
389+
error = dmtimer_systimer_init_clock(t, np->parent, "ick", &rate);
376390
if (error)
377391
goto err_unmap;
378392

@@ -496,12 +510,18 @@ static void omap_clockevent_idle(struct clock_event_device *evt)
496510
struct dmtimer_systimer *t = &clkevt->t;
497511

498512
dmtimer_systimer_disable(t);
513+
clk_disable(t->fck);
499514
}
500515

501516
static void omap_clockevent_unidle(struct clock_event_device *evt)
502517
{
503518
struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
504519
struct dmtimer_systimer *t = &clkevt->t;
520+
int error;
521+
522+
error = clk_enable(t->fck);
523+
if (error)
524+
pr_err("could not enable timer fck on resume: %i\n", error);
505525

506526
dmtimer_systimer_enable(t);
507527
writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
@@ -570,8 +590,8 @@ static int __init dmtimer_clockevent_init(struct device_node *np)
570590
3, /* Timer internal resynch latency */
571591
0xffffffff);
572592

573-
if (of_device_is_compatible(np, "ti,am33xx") ||
574-
of_device_is_compatible(np, "ti,am43")) {
593+
if (of_machine_is_compatible("ti,am33xx") ||
594+
of_machine_is_compatible("ti,am43")) {
575595
dev->suspend = omap_clockevent_idle;
576596
dev->resume = omap_clockevent_unidle;
577597
}
@@ -616,12 +636,18 @@ static void dmtimer_clocksource_suspend(struct clocksource *cs)
616636

617637
clksrc->loadval = readl_relaxed(t->base + t->counter);
618638
dmtimer_systimer_disable(t);
639+
clk_disable(t->fck);
619640
}
620641

621642
static void dmtimer_clocksource_resume(struct clocksource *cs)
622643
{
623644
struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
624645
struct dmtimer_systimer *t = &clksrc->t;
646+
int error;
647+
648+
error = clk_enable(t->fck);
649+
if (error)
650+
pr_err("could not enable timer fck on resume: %i\n", error);
625651

626652
dmtimer_systimer_enable(t);
627653
writel_relaxed(clksrc->loadval, t->base + t->counter);
@@ -653,8 +679,8 @@ static int __init dmtimer_clocksource_init(struct device_node *np)
653679
dev->mask = CLOCKSOURCE_MASK(32);
654680
dev->flags = CLOCK_SOURCE_IS_CONTINUOUS;
655681

656-
if (of_device_is_compatible(np, "ti,am33xx") ||
657-
of_device_is_compatible(np, "ti,am43")) {
682+
/* Unlike for clockevent, legacy code sets suspend only for am4 */
683+
if (of_machine_is_compatible("ti,am43")) {
658684
dev->suspend = dmtimer_clocksource_suspend;
659685
dev->resume = dmtimer_clocksource_resume;
660686
}

0 commit comments

Comments
 (0)