Loading drivers/bus/ti-sysc.c +22 −0 Original line number Diff line number Diff line Loading @@ -2864,6 +2864,24 @@ static int sysc_check_disabled_devices(struct sysc *ddata) return error; } /* * Ignore timers tagged with no-reset and no-idle. These are likely in use, * for example by drivers/clocksource/timer-ti-dm-systimer.c. If more checks * are needed, we could also look at the timer register configuration. */ static int sysc_check_active_timer(struct sysc *ddata) { if (ddata->cap->type != TI_SYSC_OMAP2_TIMER && ddata->cap->type != TI_SYSC_OMAP4_TIMER) return 0; if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) && (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE)) return -EBUSY; return 0; } static const struct of_device_id sysc_match_table[] = { { .compatible = "simple-bus", }, { /* sentinel */ }, Loading Loading @@ -2920,6 +2938,10 @@ static int sysc_probe(struct platform_device *pdev) if (error) return error; error = sysc_check_active_timer(ddata); if (error) return error; error = sysc_get_clocks(ddata); if (error) return error; Loading drivers/clocksource/timer-ti-dm-systimer.c +36 −10 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ /* For type1, set SYSC_OMAP2_CLOCKACTIVITY for fck off on idle, l4 clock on */ #define DMTIMER_TYPE1_ENABLE ((1 << 9) | (SYSC_IDLE_SMART << 3) | \ SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_AUTOIDLE) #define DMTIMER_TYPE1_DISABLE (SYSC_OMAP2_SOFTRESET | SYSC_OMAP2_AUTOIDLE) #define DMTIMER_TYPE2_ENABLE (SYSC_IDLE_SMART_WKUP << 2) #define DMTIMER_RESET_WAIT 100000 Loading @@ -44,6 +44,8 @@ struct dmtimer_systimer { u8 ctrl; u8 wakeup; u8 ifctrl; struct clk *fck; struct clk *ick; unsigned long rate; }; Loading Loading @@ -298,16 +300,20 @@ static void __init dmtimer_systimer_select_best(void) } /* Interface clocks are only available on some SoCs variants */ static int __init dmtimer_systimer_init_clock(struct device_node *np, static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t, struct device_node *np, const char *name, unsigned long *rate) { struct clk *clock; unsigned long r; bool is_ick = false; int error; is_ick = !strncmp(name, "ick", 3); clock = of_clk_get_by_name(np, name); if ((PTR_ERR(clock) == -EINVAL) && !strncmp(name, "ick", 3)) if ((PTR_ERR(clock) == -EINVAL) && is_ick) return 0; else if (IS_ERR(clock)) return PTR_ERR(clock); Loading @@ -320,6 +326,11 @@ static int __init dmtimer_systimer_init_clock(struct device_node *np, if (!r) return -ENODEV; if (is_ick) t->ick = clock; else t->fck = clock; *rate = r; return 0; Loading @@ -339,7 +350,10 @@ static void dmtimer_systimer_enable(struct dmtimer_systimer *t) static void dmtimer_systimer_disable(struct dmtimer_systimer *t) { writel_relaxed(0, t->base + t->sysc); if (!dmtimer_systimer_revision1(t)) return; writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc); } static int __init dmtimer_systimer_setup(struct device_node *np, Loading @@ -366,13 +380,13 @@ static int __init dmtimer_systimer_setup(struct device_node *np, pr_err("%s: clock source init failed: %i\n", __func__, error); /* For ti-sysc, we have timer clocks at the parent module level */ error = dmtimer_systimer_init_clock(np->parent, "fck", &rate); error = dmtimer_systimer_init_clock(t, np->parent, "fck", &rate); if (error) goto err_unmap; t->rate = rate; error = dmtimer_systimer_init_clock(np->parent, "ick", &rate); error = dmtimer_systimer_init_clock(t, np->parent, "ick", &rate); if (error) goto err_unmap; Loading Loading @@ -496,12 +510,18 @@ static void omap_clockevent_idle(struct clock_event_device *evt) struct dmtimer_systimer *t = &clkevt->t; dmtimer_systimer_disable(t); clk_disable(t->fck); } static void omap_clockevent_unidle(struct clock_event_device *evt) { struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt); struct dmtimer_systimer *t = &clkevt->t; int error; error = clk_enable(t->fck); if (error) pr_err("could not enable timer fck on resume: %i\n", error); dmtimer_systimer_enable(t); writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena); Loading Loading @@ -570,8 +590,8 @@ static int __init dmtimer_clockevent_init(struct device_node *np) 3, /* Timer internal resynch latency */ 0xffffffff); if (of_device_is_compatible(np, "ti,am33xx") || of_device_is_compatible(np, "ti,am43")) { if (of_machine_is_compatible("ti,am33xx") || of_machine_is_compatible("ti,am43")) { dev->suspend = omap_clockevent_idle; dev->resume = omap_clockevent_unidle; } Loading Loading @@ -616,12 +636,18 @@ static void dmtimer_clocksource_suspend(struct clocksource *cs) clksrc->loadval = readl_relaxed(t->base + t->counter); dmtimer_systimer_disable(t); clk_disable(t->fck); } static void dmtimer_clocksource_resume(struct clocksource *cs) { struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs); struct dmtimer_systimer *t = &clksrc->t; int error; error = clk_enable(t->fck); if (error) pr_err("could not enable timer fck on resume: %i\n", error); dmtimer_systimer_enable(t); writel_relaxed(clksrc->loadval, t->base + t->counter); Loading Loading @@ -653,8 +679,8 @@ static int __init dmtimer_clocksource_init(struct device_node *np) dev->mask = CLOCKSOURCE_MASK(32); dev->flags = CLOCK_SOURCE_IS_CONTINUOUS; if (of_device_is_compatible(np, "ti,am33xx") || of_device_is_compatible(np, "ti,am43")) { /* Unlike for clockevent, legacy code sets suspend only for am4 */ if (of_machine_is_compatible("ti,am43")) { dev->suspend = dmtimer_clocksource_suspend; dev->resume = dmtimer_clocksource_resume; } Loading Loading
drivers/bus/ti-sysc.c +22 −0 Original line number Diff line number Diff line Loading @@ -2864,6 +2864,24 @@ static int sysc_check_disabled_devices(struct sysc *ddata) return error; } /* * Ignore timers tagged with no-reset and no-idle. These are likely in use, * for example by drivers/clocksource/timer-ti-dm-systimer.c. If more checks * are needed, we could also look at the timer register configuration. */ static int sysc_check_active_timer(struct sysc *ddata) { if (ddata->cap->type != TI_SYSC_OMAP2_TIMER && ddata->cap->type != TI_SYSC_OMAP4_TIMER) return 0; if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) && (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE)) return -EBUSY; return 0; } static const struct of_device_id sysc_match_table[] = { { .compatible = "simple-bus", }, { /* sentinel */ }, Loading Loading @@ -2920,6 +2938,10 @@ static int sysc_probe(struct platform_device *pdev) if (error) return error; error = sysc_check_active_timer(ddata); if (error) return error; error = sysc_get_clocks(ddata); if (error) return error; Loading
drivers/clocksource/timer-ti-dm-systimer.c +36 −10 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ /* For type1, set SYSC_OMAP2_CLOCKACTIVITY for fck off on idle, l4 clock on */ #define DMTIMER_TYPE1_ENABLE ((1 << 9) | (SYSC_IDLE_SMART << 3) | \ SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_AUTOIDLE) #define DMTIMER_TYPE1_DISABLE (SYSC_OMAP2_SOFTRESET | SYSC_OMAP2_AUTOIDLE) #define DMTIMER_TYPE2_ENABLE (SYSC_IDLE_SMART_WKUP << 2) #define DMTIMER_RESET_WAIT 100000 Loading @@ -44,6 +44,8 @@ struct dmtimer_systimer { u8 ctrl; u8 wakeup; u8 ifctrl; struct clk *fck; struct clk *ick; unsigned long rate; }; Loading Loading @@ -298,16 +300,20 @@ static void __init dmtimer_systimer_select_best(void) } /* Interface clocks are only available on some SoCs variants */ static int __init dmtimer_systimer_init_clock(struct device_node *np, static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t, struct device_node *np, const char *name, unsigned long *rate) { struct clk *clock; unsigned long r; bool is_ick = false; int error; is_ick = !strncmp(name, "ick", 3); clock = of_clk_get_by_name(np, name); if ((PTR_ERR(clock) == -EINVAL) && !strncmp(name, "ick", 3)) if ((PTR_ERR(clock) == -EINVAL) && is_ick) return 0; else if (IS_ERR(clock)) return PTR_ERR(clock); Loading @@ -320,6 +326,11 @@ static int __init dmtimer_systimer_init_clock(struct device_node *np, if (!r) return -ENODEV; if (is_ick) t->ick = clock; else t->fck = clock; *rate = r; return 0; Loading @@ -339,7 +350,10 @@ static void dmtimer_systimer_enable(struct dmtimer_systimer *t) static void dmtimer_systimer_disable(struct dmtimer_systimer *t) { writel_relaxed(0, t->base + t->sysc); if (!dmtimer_systimer_revision1(t)) return; writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc); } static int __init dmtimer_systimer_setup(struct device_node *np, Loading @@ -366,13 +380,13 @@ static int __init dmtimer_systimer_setup(struct device_node *np, pr_err("%s: clock source init failed: %i\n", __func__, error); /* For ti-sysc, we have timer clocks at the parent module level */ error = dmtimer_systimer_init_clock(np->parent, "fck", &rate); error = dmtimer_systimer_init_clock(t, np->parent, "fck", &rate); if (error) goto err_unmap; t->rate = rate; error = dmtimer_systimer_init_clock(np->parent, "ick", &rate); error = dmtimer_systimer_init_clock(t, np->parent, "ick", &rate); if (error) goto err_unmap; Loading Loading @@ -496,12 +510,18 @@ static void omap_clockevent_idle(struct clock_event_device *evt) struct dmtimer_systimer *t = &clkevt->t; dmtimer_systimer_disable(t); clk_disable(t->fck); } static void omap_clockevent_unidle(struct clock_event_device *evt) { struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt); struct dmtimer_systimer *t = &clkevt->t; int error; error = clk_enable(t->fck); if (error) pr_err("could not enable timer fck on resume: %i\n", error); dmtimer_systimer_enable(t); writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena); Loading Loading @@ -570,8 +590,8 @@ static int __init dmtimer_clockevent_init(struct device_node *np) 3, /* Timer internal resynch latency */ 0xffffffff); if (of_device_is_compatible(np, "ti,am33xx") || of_device_is_compatible(np, "ti,am43")) { if (of_machine_is_compatible("ti,am33xx") || of_machine_is_compatible("ti,am43")) { dev->suspend = omap_clockevent_idle; dev->resume = omap_clockevent_unidle; } Loading Loading @@ -616,12 +636,18 @@ static void dmtimer_clocksource_suspend(struct clocksource *cs) clksrc->loadval = readl_relaxed(t->base + t->counter); dmtimer_systimer_disable(t); clk_disable(t->fck); } static void dmtimer_clocksource_resume(struct clocksource *cs) { struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs); struct dmtimer_systimer *t = &clksrc->t; int error; error = clk_enable(t->fck); if (error) pr_err("could not enable timer fck on resume: %i\n", error); dmtimer_systimer_enable(t); writel_relaxed(clksrc->loadval, t->base + t->counter); Loading Loading @@ -653,8 +679,8 @@ static int __init dmtimer_clocksource_init(struct device_node *np) dev->mask = CLOCKSOURCE_MASK(32); dev->flags = CLOCK_SOURCE_IS_CONTINUOUS; if (of_device_is_compatible(np, "ti,am33xx") || of_device_is_compatible(np, "ti,am43")) { /* Unlike for clockevent, legacy code sets suspend only for am4 */ if (of_machine_is_compatible("ti,am43")) { dev->suspend = dmtimer_clocksource_suspend; dev->resume = dmtimer_clocksource_resume; } Loading