mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
clocksource/drivers/exynos_mct: Support local-timers property
If the device tree indicates that the hardware requires that the processor only use certain local timers, respect that. Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Link: https://lore.kernel.org/r/20220609112738.359385-4-vincent.whitchurch@axis.com Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
This commit is contained in:
parent
e8550f0e7b
commit
47dbe4eb98
@ -33,7 +33,7 @@
|
||||
#define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248)
|
||||
#define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C)
|
||||
#define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300)
|
||||
#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x))
|
||||
#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * (x)))
|
||||
#define EXYNOS4_MCT_L_MASK (0xffffff00)
|
||||
|
||||
#define MCT_L_TCNTB_OFFSET (0x00)
|
||||
@ -66,6 +66,8 @@
|
||||
#define MCT_L0_IRQ 4
|
||||
/* Max number of IRQ as per DT binding document */
|
||||
#define MCT_NR_IRQS 20
|
||||
/* Max number of local timers */
|
||||
#define MCT_NR_LOCAL (MCT_NR_IRQS - MCT_L0_IRQ)
|
||||
|
||||
enum {
|
||||
MCT_INT_SPI,
|
||||
@ -456,7 +458,6 @@ static int exynos4_mct_starting_cpu(unsigned int cpu)
|
||||
per_cpu_ptr(&percpu_mct_tick, cpu);
|
||||
struct clock_event_device *evt = &mevt->evt;
|
||||
|
||||
mevt->base = EXYNOS4_MCT_L_BASE(cpu);
|
||||
snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu);
|
||||
|
||||
evt->name = mevt->name;
|
||||
@ -527,8 +528,17 @@ static int __init exynos4_timer_resources(struct device_node *np)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* exynos4_timer_interrupts - initialize MCT interrupts
|
||||
* @np: device node for MCT
|
||||
* @int_type: interrupt type, MCT_INT_PPI or MCT_INT_SPI
|
||||
* @local_idx: array mapping CPU numbers to local timer indices
|
||||
* @nr_local: size of @local_idx array
|
||||
*/
|
||||
static int __init exynos4_timer_interrupts(struct device_node *np,
|
||||
unsigned int int_type)
|
||||
unsigned int int_type,
|
||||
const u32 *local_idx,
|
||||
size_t nr_local)
|
||||
{
|
||||
int nr_irqs, i, err, cpu;
|
||||
|
||||
@ -561,13 +571,21 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
|
||||
} else {
|
||||
for_each_possible_cpu(cpu) {
|
||||
int mct_irq;
|
||||
unsigned int irq_idx;
|
||||
struct mct_clock_event_device *pcpu_mevt =
|
||||
per_cpu_ptr(&percpu_mct_tick, cpu);
|
||||
|
||||
if (cpu >= nr_local) {
|
||||
err = -EINVAL;
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
irq_idx = MCT_L0_IRQ + local_idx[cpu];
|
||||
|
||||
pcpu_mevt->evt.irq = -1;
|
||||
if (MCT_L0_IRQ + cpu >= ARRAY_SIZE(mct_irqs))
|
||||
if (irq_idx >= ARRAY_SIZE(mct_irqs))
|
||||
break;
|
||||
mct_irq = mct_irqs[MCT_L0_IRQ + cpu];
|
||||
mct_irq = mct_irqs[irq_idx];
|
||||
|
||||
irq_set_status_flags(mct_irq, IRQ_NOAUTOEN);
|
||||
if (request_irq(mct_irq,
|
||||
@ -583,6 +601,17 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
|
||||
}
|
||||
}
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct mct_clock_event_device *mevt = per_cpu_ptr(&percpu_mct_tick, cpu);
|
||||
|
||||
if (cpu >= nr_local) {
|
||||
err = -EINVAL;
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
mevt->base = EXYNOS4_MCT_L_BASE(local_idx[cpu]);
|
||||
}
|
||||
|
||||
/* Install hotplug callbacks which configure the timer on this CPU */
|
||||
err = cpuhp_setup_state(CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING,
|
||||
"clockevents/exynos4/mct_timer:starting",
|
||||
@ -613,13 +642,34 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
|
||||
static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
|
||||
{
|
||||
bool frc_shared = of_property_read_bool(np, "samsung,frc-shared");
|
||||
u32 local_idx[MCT_NR_LOCAL] = {0};
|
||||
int nr_local;
|
||||
int ret;
|
||||
|
||||
nr_local = of_property_count_u32_elems(np, "samsung,local-timers");
|
||||
if (nr_local == 0)
|
||||
return -EINVAL;
|
||||
if (nr_local > 0) {
|
||||
if (nr_local > ARRAY_SIZE(local_idx))
|
||||
return -EINVAL;
|
||||
|
||||
ret = of_property_read_u32_array(np, "samsung,local-timers",
|
||||
local_idx, nr_local);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
int i;
|
||||
|
||||
nr_local = ARRAY_SIZE(local_idx);
|
||||
for (i = 0; i < nr_local; i++)
|
||||
local_idx[i] = i;
|
||||
}
|
||||
|
||||
ret = exynos4_timer_resources(np);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = exynos4_timer_interrupts(np, int_type);
|
||||
ret = exynos4_timer_interrupts(np, int_type, local_idx, nr_local);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user