From db4c4426daedffefcfd890d04a6ec9ed93268878 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 28 Jan 2016 12:52:33 +0530 Subject: ARC: [intc-compact] setup TIMER as percpu_dev This removes the quirk from arc_request_percpu_irq() and paves way for future simplifications Signed-off-by: Vineet Gupta --- arch/arc/kernel/intc-compact.c | 3 ++- arch/arc/kernel/irq.c | 12 ------------ 2 files changed, 2 insertions(+), 13 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c index 224d1c3aa9c4..4195eedeb6d1 100644 --- a/arch/arc/kernel/intc-compact.c +++ b/arch/arc/kernel/intc-compact.c @@ -79,8 +79,9 @@ static struct irq_chip onchip_intc = { static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { - switch (irq) { + switch (hw) { case TIMER0_IRQ: + irq_set_percpu_devid(irq); irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq); break; default: diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index ba17f85285cf..88074b50456b 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -72,18 +72,6 @@ void arc_request_percpu_irq(int irq, int cpu, if (!cpu) { int rc; -#ifdef CONFIG_ISA_ARCOMPACT - /* - * A subsequent request_percpu_irq() fails if percpu_devid is - * not set. That in turns sets NOAUTOEN, meaning each core needs - * to call enable_percpu_irq() - * - * For ARCv2, this is done in irq map function since we know - * which irqs are strictly per cpu - */ - irq_set_percpu_devid(irq); -#endif - rc = request_percpu_irq(irq, isr, irq_nm, percpu_dev); if (rc) panic("Percpu IRQ request failed for %d\n", irq); -- cgit v1.2.3 From 569579401ae1c9b9f317f38261e32135b153e9b3 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 28 Jan 2016 12:56:03 +0530 Subject: ARC: opencode arc_request_percpu_irq - The idea is to remove the API usage since it has a subltle design flaw - relies on being called on cpu0 first. This is true for some early per cpu irqs such as TIMER/IPI, but not for late probed per cpu peripherals such a perf. And it's usage in perf has already bitten us once: see c6317bc7c5ab ("ARCv2: perf: Ensure perf intr gets enabled on all cores") where we ended up open coding it anyways - The seeming duplication will go away once we start using cpu notifier for timer setup Signed-off-by: Vineet Gupta --- arch/arc/include/asm/irq.h | 3 --- arch/arc/kernel/irq.c | 29 ----------------------------- arch/arc/kernel/smp.c | 15 ++++++++++++++- arch/arc/kernel/time.c | 14 +++++++++++--- 4 files changed, 25 insertions(+), 36 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index 49014f0ef36d..f9c735ede4fc 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -26,8 +26,5 @@ extern void arc_init_IRQ(void); void arc_local_timer_setup(void); -void arc_request_percpu_irq(int irq, int cpu, - irqreturn_t (*isr)(int irq, void *dev), - const char *irq_nm, void *percpu_dev); #endif diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index 88074b50456b..fb6dede9d05f 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -50,32 +50,3 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs) irq_exit(); set_irq_regs(old_regs); } - -/* - * API called for requesting percpu interrupts - called by each CPU - * - For boot CPU, actually request the IRQ with genirq core + enables - * - For subsequent callers only enable called locally - * - * Relies on being called by boot cpu first (i.e. request called ahead) of - * any enable as expected by genirq. Hence Suitable only for TIMER, IPI - * which are guaranteed to be setup on boot core first. - * Late probed peripherals such as perf can't use this as there no guarantee - * of being called on boot CPU first. - */ - -void arc_request_percpu_irq(int irq, int cpu, - irqreturn_t (*isr)(int irq, void *dev), - const char *irq_nm, - void *percpu_dev) -{ - /* Boot cpu calls request, all call enable */ - if (!cpu) { - int rc; - - rc = request_percpu_irq(irq, isr, irq_nm, percpu_dev); - if (rc) - panic("Percpu IRQ request failed for %d\n", irq); - } - - enable_percpu_irq(irq, 0); -} diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 4cb3add77c75..ca83ebe15a64 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -346,6 +346,10 @@ irqreturn_t do_IPI(int irq, void *dev_id) /* * API called by platform code to hookup arch-common ISR to their IPI IRQ + * + * Note: If IPI is provided by platform (vs. say ARC MCIP), their intc setup/map + * function needs to call call irq_set_percpu_devid() for IPI IRQ, otherwise + * request_percpu_irq() below will fail */ static DEFINE_PER_CPU(int, ipi_dev); @@ -353,7 +357,16 @@ int smp_ipi_irq_setup(int cpu, int irq) { int *dev = per_cpu_ptr(&ipi_dev, cpu); - arc_request_percpu_irq(irq, cpu, do_IPI, "IPI Interrupt", dev); + /* Boot cpu calls request, all call enable */ + if (!cpu) { + int rc; + + rc = request_percpu_irq(irq, do_IPI, "IPI Interrupt", dev); + if (rc) + panic("Percpu IRQ request failed for %d\n", irq); + } + + enable_percpu_irq(irq, 0); return 0; } diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 7d9a736fc7e5..146da3cbcc99 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -251,14 +251,22 @@ void arc_local_timer_setup() { struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); int cpu = smp_processor_id(); + int irq = TIMER0_IRQ; evt->cpumask = cpumask_of(cpu); clockevents_config_and_register(evt, arc_get_core_freq(), 0, ARC_TIMER_MAX); - /* setup the per-cpu timer IRQ handler - for all cpus */ - arc_request_percpu_irq(TIMER0_IRQ, cpu, timer_irq_handler, - "Timer0 (per-cpu-tick)", evt); + if (!cpu) { + int rc; + + rc = request_percpu_irq(irq, timer_irq_handler, + "Timer0 (per-cpu-tick)", evt); + if (rc) + panic("Percpu IRQ request failed for TIMER\n"); + } + + enable_percpu_irq(irq, 0); } /* -- cgit v1.2.3 From eec3c58efa271d7dfa30c978dda2c88280212634 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Fri, 1 Jan 2016 15:48:49 +0530 Subject: ARC: clockevent: switch to cpu notifier for clockevent setup ARC Timers so far have been handled as "legacy" w/o explicit description in DT. This poses challenge for newer platforms wanting to use them. This series will eventually help move timers over to DT. This patch does a small change of using a CPU notifier to set clockevent on non-boot CPUs. So explicit setup is done only on boot CPU (which will later be done by DT) Signed-off-by: Noam Camus [vgupta: broken off from a bigger patch] Signed-off-by: Vineet Gupta --- arch/arc/include/asm/irq.h | 1 - arch/arc/kernel/smp.c | 2 -- arch/arc/kernel/time.c | 62 ++++++++++++++++++++++++++++++---------------- 3 files changed, 41 insertions(+), 24 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index f9c735ede4fc..5c0b5abda67a 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -25,6 +25,5 @@ #include extern void arc_init_IRQ(void); -void arc_local_timer_setup(void); #endif diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index ca83ebe15a64..6b1813456336 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -138,8 +138,6 @@ void start_kernel_secondary(void) if (machine_desc->init_per_cpu) machine_desc->init_per_cpu(cpu); - arc_local_timer_setup(); - local_irq_enable(); preempt_disable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 146da3cbcc99..e97be743d47b 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -29,17 +29,14 @@ * which however is currently broken */ -#include #include #include -#include #include #include #include -#include -#include #include #include +#include #include #include #include @@ -183,6 +180,8 @@ static struct clocksource arc_counter = { /********** Clock Event Device *********/ +static int arc_timer_irq = TIMER0_IRQ; + /* * Arm the timer to interrupt after @cycles * The distinction for oneshot/periodic is done in arc_event_timer_ack() below @@ -218,7 +217,6 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = { .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .rating = 300, - .irq = TIMER0_IRQ, /* hardwired, no need for resources */ .set_next_event = arc_clkevent_set_next_event, .set_state_periodic = arc_clkevent_set_periodic, }; @@ -244,29 +242,52 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static int arc_timer_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); + + evt->cpumask = cpumask_of(smp_processor_id()); + + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + clockevents_config_and_register(evt, arc_get_core_freq(), + 0, ULONG_MAX); + enable_percpu_irq(arc_timer_irq, 0); + break; + case CPU_DYING: + disable_percpu_irq(arc_timer_irq); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block arc_timer_cpu_nb = { + .notifier_call = arc_timer_cpu_notify, +}; + /* - * Setup the local event timer for @cpu + * clockevent setup for boot CPU */ -void arc_local_timer_setup() +static void __init arc_clockevent_setup(void) { struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); - int cpu = smp_processor_id(); - int irq = TIMER0_IRQ; + int ret; - evt->cpumask = cpumask_of(cpu); + register_cpu_notifier(&arc_timer_cpu_nb); + + evt->cpumask = cpumask_of(smp_processor_id()); clockevents_config_and_register(evt, arc_get_core_freq(), 0, ARC_TIMER_MAX); - if (!cpu) { - int rc; - - rc = request_percpu_irq(irq, timer_irq_handler, - "Timer0 (per-cpu-tick)", evt); - if (rc) - panic("Percpu IRQ request failed for TIMER\n"); - } + /* Needs apriori irq_set_percpu_devid() done in intc map function */ + ret = request_percpu_irq(arc_timer_irq, timer_irq_handler, + "Timer0 (per-cpu-tick)", evt); + if (ret) + pr_err("Unable to register interrupt\n"); - enable_percpu_irq(irq, 0); + enable_percpu_irq(arc_timer_irq, 0); } /* @@ -291,6 +312,5 @@ void __init time_init(void) */ clocksource_register_hz(&arc_counter, arc_get_core_freq()); - /* sets up the periodic event timer */ - arc_local_timer_setup(); + arc_clockevent_setup(); } -- cgit v1.2.3 From 69fbd09874ded099d445271d05681529dac4d00a Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Thu, 14 Jan 2016 12:20:08 +0530 Subject: ARC: clockevent: Prepare for DT based probe - call clocksource_probe() - This in turns needs of_clk_init() to be called earlier Cc: Daniel Lezcano Signed-off-by: Noam Camus [vgupta: broken off from a bigger patch] Signed-off-by: Vineet Gupta --- arch/arc/Kconfig | 3 ++- arch/arc/kernel/setup.c | 2 -- arch/arc/kernel/time.c | 5 +++++ 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index a8767430df7d..ae3943435abf 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -10,8 +10,9 @@ config ARC def_bool y select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC select BUILDTIME_EXTABLE_SORT - select COMMON_CLK + select CLKSRC_OF select CLONE_BACKWARDS + select COMMON_CLK select GENERIC_ATOMIC64 select GENERIC_CLOCKEVENTS select GENERIC_FIND_FIRST_BIT diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 151acf0c9383..507ec523112a 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -444,7 +443,6 @@ void __init setup_arch(char **cmdline_p) static int __init customize_machine(void) { - of_clk_init(NULL); /* * Traverses flattened DeviceTree - registering platform devices * (if any) complete with their resources diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index e97be743d47b..848353a27ac8 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include #include @@ -301,6 +303,9 @@ static void __init arc_clockevent_setup(void) */ void __init time_init(void) { + of_clk_init(NULL); + clocksource_probe(); + /* * sets up the timekeeping free-flowing counter which also returns * whether the counter is usable as clocksource -- cgit v1.2.3 From 77c8d0d6b3f4ea0989b9ca42fb368cc2aac02495 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 1 Jan 2016 17:58:45 +0530 Subject: ARC: clockevent: DT based probe - timer frequency is derived from DT (no longer rely on top level DT "clock-frequency" probed early and exported by asm/clk.h) - TIMER0_IRQ need not be exported across arch code, confined to intc as it is property of same - Any failures in clockevent setup are considered pedantic and system panic()'s as there is no generic fallback (unlike clocksource where a jiffies based soft clocksource always exists) Acked-by: Daniel Lezcano Signed-off-by: Vineet Gupta --- arch/arc/include/asm/irq.h | 9 ------- arch/arc/kernel/intc-compact.c | 2 ++ arch/arc/kernel/time.c | 59 ++++++++++++++++++++++++++++++------------ 3 files changed, 45 insertions(+), 25 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index 5c0b5abda67a..a6ac89dc228f 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -12,15 +12,6 @@ #define NR_CPU_IRQS 32 /* number of interrupt lines of ARC770 CPU */ #define NR_IRQS 128 /* allow some CPU external IRQ handling */ -/* Platform Independent IRQs */ -#ifdef CONFIG_ISA_ARCOMPACT -#define TIMER0_IRQ 3 -#define TIMER1_IRQ 4 -#else -#define TIMER0_IRQ 16 -#define TIMER1_IRQ 17 -#endif - #include #include diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c index 4195eedeb6d1..d31bc647146d 100644 --- a/arch/arc/kernel/intc-compact.c +++ b/arch/arc/kernel/intc-compact.c @@ -14,6 +14,8 @@ #include #include +#define TIMER0_IRQ 3 /* Fixed by ISA */ + /* * Early Hardware specific Interrupt setup * -Platform independent, needed for each CPU (not foldable into init_IRQ) diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 848353a27ac8..01ec30d83590 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -30,19 +30,15 @@ */ #include -#include -#include -#include -#include #include #include #include #include #include +#include +#include #include #include -#include -#include #include @@ -59,6 +55,30 @@ #define ARC_TIMER_MAX 0xFFFFFFFF +static unsigned long arc_timer_freq; + +static int noinline arc_get_timer_clk(struct device_node *node) +{ + struct clk *clk; + int ret; + + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) { + pr_err("timer missing clk"); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("Couldn't enable parent clk\n"); + return ret; + } + + arc_timer_freq = clk_get_rate(clk); + + return 0; +} + /********** Clock Source Device *********/ #ifdef CONFIG_ARC_HAS_GFRC @@ -182,7 +202,7 @@ static struct clocksource arc_counter = { /********** Clock Event Device *********/ -static int arc_timer_irq = TIMER0_IRQ; +static int arc_timer_irq; /* * Arm the timer to interrupt after @cycles @@ -210,7 +230,7 @@ static int arc_clkevent_set_periodic(struct clock_event_device *dev) * At X Hz, 1 sec = 1000ms -> X cycles; * 10ms -> X / 100 cycles */ - arc_timer_event_setup(arc_get_core_freq() / HZ); + arc_timer_event_setup(arc_timer_freq / HZ); return 0; } @@ -253,7 +273,7 @@ static int arc_timer_cpu_notify(struct notifier_block *self, switch (action & ~CPU_TASKS_FROZEN) { case CPU_STARTING: - clockevents_config_and_register(evt, arc_get_core_freq(), + clockevents_config_and_register(evt, arc_timer_freq, 0, ULONG_MAX); enable_percpu_irq(arc_timer_irq, 0); break; @@ -272,25 +292,35 @@ static struct notifier_block arc_timer_cpu_nb = { /* * clockevent setup for boot CPU */ -static void __init arc_clockevent_setup(void) +static void __init arc_clockevent_setup(struct device_node *node) { struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); int ret; register_cpu_notifier(&arc_timer_cpu_nb); + arc_timer_irq = irq_of_parse_and_map(node, 0); + if (arc_timer_irq <= 0) + panic("clockevent: missing irq"); + + ret = arc_get_timer_clk(node); + if (ret) + panic("clockevent: missing clk"); + + evt->irq = arc_timer_irq; evt->cpumask = cpumask_of(smp_processor_id()); - clockevents_config_and_register(evt, arc_get_core_freq(), + clockevents_config_and_register(evt, arc_timer_freq, 0, ARC_TIMER_MAX); /* Needs apriori irq_set_percpu_devid() done in intc map function */ ret = request_percpu_irq(arc_timer_irq, timer_irq_handler, "Timer0 (per-cpu-tick)", evt); if (ret) - pr_err("Unable to register interrupt\n"); + panic("clockevent: unable to request irq\n"); enable_percpu_irq(arc_timer_irq, 0); } +CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_clockevent_setup); /* * Called from start_kernel() - boot CPU only @@ -299,7 +329,6 @@ static void __init arc_clockevent_setup(void) * -Also sets up any global state needed for timer subsystem: * - for "counting" timer, registers a clocksource, usable across CPUs * (provided that underlying counter h/w is synchronized across cores) - * - for "event" timer, sets up TIMER0 IRQ (as that is platform agnostic) */ void __init time_init(void) { @@ -315,7 +344,5 @@ void __init time_init(void) * CLK upto 4.29 GHz can be safely represented in 32 bits * because Max 32 bit number is 4,294,967,295 */ - clocksource_register_hz(&arc_counter, arc_get_core_freq()); - - arc_clockevent_setup(); + clocksource_register_hz(&arc_counter, arc_timer_freq); } -- cgit v1.2.3 From e608b53ea863a92eb458cb1ec7c2fcf3ca2b043a Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 1 Jan 2016 18:05:48 +0530 Subject: ARC: clocksource: DT based probe - Remove explicit clocksource setup and let it be done by OF framework by defining CLOCKSOURCE_OF_DECLARE() for various timers - This allows multiple clocksources to be potentially registered simultaneouly: previously we could only do one - as all of them had same arc_counter_setup() routine for registration - Setup routines also ensure that the underlying timer actually exists. - Remove some of the panic() calls if underlying timer is NOT detected as fallback clocksource might still be available 1. If GRFC doesn't exist, jiffies clocksource gets registered anyways 2. if RTC doesn't exist, TIMER1 can take over (as it is always present) Cc: Daniel Lezcano Signed-off-by: Vineet Gupta --- arch/arc/kernel/mcip.c | 4 +- arch/arc/kernel/setup.c | 3 -- arch/arc/kernel/time.c | 134 +++++++++++++++++++++++++++++------------------- 3 files changed, 82 insertions(+), 59 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index c41c364b926c..262d9c3771e6 100644 --- a/arch/arc/kernel/mcip.c +++ b/arch/arc/kernel/mcip.c @@ -116,15 +116,13 @@ static void mcip_probe_n_setup(void) IS_AVAIL1(mp.dbg, "DEBUG "), IS_AVAIL1(mp.gfrc, "GFRC")); + cpuinfo_arc700[0].extn.gfrc = mp.gfrc; idu_detected = mp.idu; if (mp.dbg) { __mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf); __mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xf, 0xf); } - - if (IS_ENABLED(CONFIG_ARC_HAS_GFRC) && !mp.gfrc) - panic("kernel trying to use non-existent GFRC\n"); } struct plat_smp_ops plat_smp_ops = { diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 507ec523112a..91f79fa447bc 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -313,9 +313,6 @@ static void arc_chk_core_config(void) if (!cpu->extn.timer1) panic("Timer1 is not present!\n"); - if (IS_ENABLED(CONFIG_ARC_HAS_RTC) && !cpu->extn.rtc) - panic("RTC is not present\n"); - #ifdef CONFIG_ARC_HAS_DCCM /* * DCCM can be arbit placed in hardware. diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 01ec30d83590..4549ab255dd1 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -83,12 +83,7 @@ static int noinline arc_get_timer_clk(struct device_node *node) #ifdef CONFIG_ARC_HAS_GFRC -static int arc_counter_setup(void) -{ - return 1; -} - -static cycle_t arc_counter_read(struct clocksource *cs) +static cycle_t arc_read_gfrc(struct clocksource *cs) { unsigned long flags; union { @@ -113,15 +108,31 @@ static cycle_t arc_counter_read(struct clocksource *cs) return stamp.full; } -static struct clocksource arc_counter = { +static struct clocksource arc_counter_gfrc = { .name = "ARConnect GFRC", .rating = 400, - .read = arc_counter_read, + .read = arc_read_gfrc, .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -#else +static void __init arc_cs_setup_gfrc(struct device_node *node) +{ + int exists = cpuinfo_arc700[0].extn.gfrc; + int ret; + + if (WARN(!exists, "Global-64-bit-Ctr clocksource not detected")) + return; + + ret = arc_get_timer_clk(node); + if (ret) + return; + + clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq); +} +CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc); + +#endif #ifdef CONFIG_ARC_HAS_RTC @@ -129,15 +140,7 @@ static struct clocksource arc_counter = { #define AUX_RTC_LOW 0x104 #define AUX_RTC_HIGH 0x105 -int arc_counter_setup(void) -{ - write_aux_reg(AUX_RTC_CTRL, 1); - - /* Not usable in SMP */ - return !IS_ENABLED(CONFIG_SMP); -} - -static cycle_t arc_counter_read(struct clocksource *cs) +static cycle_t arc_read_rtc(struct clocksource *cs) { unsigned long status; union { @@ -161,44 +164,73 @@ static cycle_t arc_counter_read(struct clocksource *cs) return stamp.full; } -static struct clocksource arc_counter = { +static struct clocksource arc_counter_rtc = { .name = "ARCv2 RTC", .rating = 350, - .read = arc_counter_read, + .read = arc_read_rtc, .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -#else /* !CONFIG_ARC_HAS_RTC */ - -/* - * set 32bit TIMER1 to keep counting monotonically and wraparound - */ -int arc_counter_setup(void) +static void __init arc_cs_setup_rtc(struct device_node *node) { - write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX); - write_aux_reg(ARC_REG_TIMER1_CNT, 0); - write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH); + int exists = cpuinfo_arc700[smp_processor_id()].extn.rtc; + int ret; + + if (WARN(!exists, "Local-64-bit-Ctr clocksource not detected")) + return; + + /* Local to CPU hence not usable in SMP */ + if (WARN(IS_ENABLED(CONFIG_SMP), "Local-64-bit-Ctr not usable in SMP")) + return; + + ret = arc_get_timer_clk(node); + if (ret) + return; - /* Not usable in SMP */ - return !IS_ENABLED(CONFIG_SMP); + write_aux_reg(AUX_RTC_CTRL, 1); + + clocksource_register_hz(&arc_counter_rtc, arc_timer_freq); } +CLOCKSOURCE_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc); + +#endif -static cycle_t arc_counter_read(struct clocksource *cs) +/* + * 32bit TIMER1 to keep counting monotonically and wraparound + */ + +static cycle_t arc_read_timer1(struct clocksource *cs) { return (cycle_t) read_aux_reg(ARC_REG_TIMER1_CNT); } -static struct clocksource arc_counter = { +static struct clocksource arc_counter_timer1 = { .name = "ARC Timer1", .rating = 300, - .read = arc_counter_read, + .read = arc_read_timer1, .mask = CLOCKSOURCE_MASK(32), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -#endif -#endif +static void __init arc_cs_setup_timer1(struct device_node *node) +{ + int ret; + + /* Local to CPU hence not usable in SMP */ + if (IS_ENABLED(CONFIG_SMP)) + return; + + ret = arc_get_timer_clk(node); + if (ret) + return; + + write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX); + write_aux_reg(ARC_REG_TIMER1_CNT, 0); + write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH); + + clocksource_register_hz(&arc_counter_timer1, arc_timer_freq); +} /********** Clock Event Device *********/ @@ -320,29 +352,25 @@ static void __init arc_clockevent_setup(struct device_node *node) enable_percpu_irq(arc_timer_irq, 0); } -CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_clockevent_setup); + +static void __init arc_of_timer_init(struct device_node *np) +{ + static int init_count = 0; + + if (!init_count) { + init_count = 1; + arc_clockevent_setup(np); + } else { + arc_cs_setup_timer1(np); + } +} +CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init); /* * Called from start_kernel() - boot CPU only - * - * -Sets up h/w timers as applicable on boot cpu - * -Also sets up any global state needed for timer subsystem: - * - for "counting" timer, registers a clocksource, usable across CPUs - * (provided that underlying counter h/w is synchronized across cores) */ void __init time_init(void) { of_clk_init(NULL); clocksource_probe(); - - /* - * sets up the timekeeping free-flowing counter which also returns - * whether the counter is usable as clocksource - */ - if (arc_counter_setup()) - /* - * CLK upto 4.29 GHz can be safely represented in 32 bits - * because Max 32 bit number is 4,294,967,295 - */ - clocksource_register_hz(&arc_counter, arc_timer_freq); } -- cgit v1.2.3 From 88555cc584d93e658722f090d3f8fb84d5fa15a5 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 30 Mar 2016 18:35:28 +0530 Subject: ARC: irq: export some IRQs again This will be needed for switching to linear irq domain as irq_create_mapping() called by intr code needs the IRQ numbers in addition to existing usage in mcip.c for requesting the irq Signed-off-by: Vineet Gupta --- arch/arc/include/asm/irq.h | 6 ++++++ arch/arc/kernel/mcip.c | 3 --- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index a6ac89dc228f..c0fa0d2de400 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -12,6 +12,12 @@ #define NR_CPU_IRQS 32 /* number of interrupt lines of ARC770 CPU */ #define NR_IRQS 128 /* allow some CPU external IRQ handling */ +/* Platform Independent IRQs */ +#ifdef CONFIG_ISA_ARCV2 +#define IPI_IRQ 19 +#define SOFTIRQ_IRQ 21 +#endif + #include #include diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index 262d9c3771e6..72f9179b1a24 100644 --- a/arch/arc/kernel/mcip.c +++ b/arch/arc/kernel/mcip.c @@ -15,9 +15,6 @@ #include #include -#define IPI_IRQ 19 -#define SOFTIRQ_IRQ 21 - static char smp_cpuinfo_buf[128]; static int idu_detected; -- cgit v1.2.3 From 1b0ccb8a4eee2d8c14adc996e07335cb7aa9e2ac Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 1 Jan 2016 15:12:54 +0530 Subject: ARC: [intc-*] Do a domain lookup in primary handler for hwirq -> linux virq The primary interrupt handler arch_do_IRQ() was passing hwirq as linux virq to core code. This was fragile and worked so far as we only had legacy/linear domains. This came out of a rant by Marc Zyngier. http://lists.infradead.org/pipermail/linux-snps-arc/2015-December/000298.html Cc: Marc Zyngier Cc: Thomas Gleixner Cc: Noam Camus Signed-off-by: Vineet Gupta --- arch/arc/Kconfig | 1 + arch/arc/kernel/intc-arcv2.c | 9 ++++++--- arch/arc/kernel/intc-compact.c | 10 ++++++---- arch/arc/kernel/irq.c | 9 ++------- 4 files changed, 15 insertions(+), 14 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index ae3943435abf..4f1482aa8823 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -31,6 +31,7 @@ config ARC select HAVE_MOD_ARCH_SPECIFIC if ARC_DW2_UNWIND select HAVE_OPROFILE select HAVE_PERF_EVENTS + select HANDLE_DOMAIN_IRQ select IRQ_DOMAIN select MODULES_USE_ELF_RELA select NO_BOOTMEM diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index 942526322ae7..592cc977151e 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c @@ -137,21 +137,24 @@ static const struct irq_domain_ops arcv2_irq_ops = { .map = arcv2_irq_map, }; -static struct irq_domain *root_domain; static int __init init_onchip_IRQ(struct device_node *intc, struct device_node *parent) { + struct irq_domain *root_domain; + if (parent) panic("DeviceTree incore intc not a root irq controller\n"); root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0, &arcv2_irq_ops, NULL); - if (!root_domain) panic("root irq domain not avail\n"); - /* with this we don't need to export root_domain */ + /* + * Needed for primary domain lookup to succeed + * This is a primary irqchip, and can never have a parent + */ irq_set_default_host(root_domain); return 0; diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c index d31bc647146d..48a8b24de23e 100644 --- a/arch/arc/kernel/intc-compact.c +++ b/arch/arc/kernel/intc-compact.c @@ -97,21 +97,23 @@ static const struct irq_domain_ops arc_intc_domain_ops = { .map = arc_intc_domain_map, }; -static struct irq_domain *root_domain; - static int __init init_onchip_IRQ(struct device_node *intc, struct device_node *parent) { + struct irq_domain *root_domain; + if (parent) panic("DeviceTree incore intc not a root irq controller\n"); root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0, &arc_intc_domain_ops, NULL); - if (!root_domain) panic("root irq domain not avail\n"); - /* with this we don't need to export root_domain */ + /* + * Needed for primary domain lookup to succeed + * This is a primary irqchip, and can never have a parent + */ irq_set_default_host(root_domain); return 0; diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index fb6dede9d05f..538b36afe89e 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -41,12 +41,7 @@ void __init init_IRQ(void) * "C" Entry point for any ARC ISR, called from low level vector handler * @irq is the vector number read from ICAUSE reg of on-chip intc */ -void arch_do_IRQ(unsigned int irq, struct pt_regs *regs) +void arch_do_IRQ(unsigned int hwirq, struct pt_regs *regs) { - struct pt_regs *old_regs = set_irq_regs(regs); - - irq_enter(); - generic_handle_irq(irq); - irq_exit(); - set_irq_regs(old_regs); + handle_domain_irq(NULL, hwirq, regs); } -- cgit v1.2.3 From d21beffb0b9181c8823f71a5a7fabce6a0d4cf29 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 28 Jan 2016 09:40:10 +0530 Subject: ARC: [intc-*] switch to linear domain Now that we have Timers probed from DT, don't need legacy domain This however requires mapping to be called explicitly for the IRQ which still can't (and probably never) be probed from DT such as IPI and SOFTIRQ Acked-by: Marc Zyngier Signed-off-by: Vineet Gupta --- arch/arc/kernel/intc-arcv2.c | 8 ++++++-- arch/arc/kernel/intc-compact.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index 592cc977151e..6c24faf48b16 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c @@ -146,8 +146,7 @@ init_onchip_IRQ(struct device_node *intc, struct device_node *parent) if (parent) panic("DeviceTree incore intc not a root irq controller\n"); - root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0, - &arcv2_irq_ops, NULL); + root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS, &arcv2_irq_ops, NULL); if (!root_domain) panic("root irq domain not avail\n"); @@ -157,6 +156,11 @@ init_onchip_IRQ(struct device_node *intc, struct device_node *parent) */ irq_set_default_host(root_domain); +#ifdef CONFIG_SMP + irq_create_mapping(root_domain, IPI_IRQ); +#endif + irq_create_mapping(root_domain, SOFTIRQ_IRQ); + return 0; } diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c index 48a8b24de23e..c5cceca36118 100644 --- a/arch/arc/kernel/intc-compact.c +++ b/arch/arc/kernel/intc-compact.c @@ -105,7 +105,7 @@ init_onchip_IRQ(struct device_node *intc, struct device_node *parent) if (parent) panic("DeviceTree incore intc not a root irq controller\n"); - root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0, + root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS, &arc_intc_domain_ops, NULL); if (!root_domain) panic("root irq domain not avail\n"); -- cgit v1.2.3 From 0e6e9b648d802fe6641fe543b6dc4828baded159 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Mon, 1 Feb 2016 16:31:14 +0300 Subject: ARC: use fixed frequencies in arc_set_early_base_baud() UARTs usually have fixed clock so we're switching to use of constant values instead of something derived from core clock frequency. Among other things this will allow us to get rid of arc_{get|set}_core_freq() and switch to generic clock framework later on. Acked-by: Christian Ruppert Signed-off-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/kernel/devtree.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index 7e844fd8213f..fecbc96df828 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -28,14 +28,12 @@ unsigned int __init arc_early_base_baud(void) static void __init arc_set_early_base_baud(unsigned long dt_root) { - unsigned int core_clk = arc_get_core_freq(); - if (of_flat_dt_is_compatible(dt_root, "abilis,arc-tb10x")) - arc_base_baud = core_clk/3; + arc_base_baud = 166666666; /* Fixed 166.6MHz clk (TB10x) */ else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp")) arc_base_baud = 33333333; /* Fixed 33MHz clk (AXS10x) */ else - arc_base_baud = core_clk; + arc_base_baud = 50000000; /* Fixed default 50MHz */ } #else #define arc_set_early_base_baud(dt_root) -- cgit v1.2.3 From 20c7dbbdbe12db75f9e9ac3fd0d713ab95549623 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Mon, 1 Feb 2016 17:30:17 +0300 Subject: ARC: Don't try to use value of top level clock-frequency in DT We no longer use it and instead a real clk device such as fixed-clk instance is fed to timers etc. Signed-off-by: Alexey Brodkin [vgupta: broken out of a bigger patch, rewrote changelog] Signed-off-by: Vineet Gupta --- arch/arc/kernel/setup.c | 12 +++++++----- arch/arc/plat-axs10x/axs10x.c | 2 -- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 91f79fa447bc..f63b8bfefb0c 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -219,10 +218,6 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) if (tbl->info.id == 0) n += scnprintf(buf + n, len - n, "UNKNOWN ARC Processor\n"); - n += scnprintf(buf + n, len - n, "CPU speed\t: %u.%02u Mhz\n", - (unsigned int)(arc_get_core_freq() / 1000000), - (unsigned int)(arc_get_core_freq() / 10000) % 100); - n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ", IS_AVAIL1(cpu->extn.timer0, "Timer0 "), IS_AVAIL1(cpu->extn.timer1, "Timer1 "), @@ -472,6 +467,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) { char *str; int cpu_id = ptr_to_cpu(v); + struct device_node *core_clk = of_find_node_by_name(NULL, "core_clk"); + u32 freq = 0; if (!cpu_online(cpu_id)) { seq_printf(m, "processor [%d]\t: Offline\n", cpu_id); @@ -484,6 +481,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE)); + of_property_read_u32(core_clk, "clock-frequency", &freq); + if (freq) + seq_printf(m, "CPU speed\t: %u.%02u Mhz\n", + freq / 1000000, (freq / 10000) % 100); + seq_printf(m, "Bogo MIPS\t: %lu.%02lu\n", loops_per_jiffy / (500000 / HZ), (loops_per_jiffy / (5000 / HZ)) % 100); diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c index f90fac271d16..9701c93f315d 100644 --- a/arch/arc/plat-axs10x/axs10x.c +++ b/arch/arc/plat-axs10x/axs10x.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -448,7 +447,6 @@ static void __init axs103_early_init(void) /* Patching .dtb in-place with new core clock value */ if (freq != orig ) { - arc_set_core_freq(freq * 1000000); freq = cpu_to_be32(freq * 1000000); fdt_setprop_inplace(initial_boot_params, offset, "clock-frequency", &freq, sizeof(freq)); -- cgit v1.2.3 From 6e9318d1be83714e004a0ac795a936df4d2bed3e Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Mon, 1 Feb 2016 17:30:17 +0300 Subject: ARC: RIP arc_{get|set}_core_freq() clk API There are no more users of this - so RIP! Signed-off-by: Alexey Brodkin [vgupta: update changelog] Signed-off-by: Vineet Gupta --- arch/arc/include/asm/clk.h | 22 ---------------------- arch/arc/kernel/Makefile | 2 +- arch/arc/kernel/clk.c | 21 --------------------- arch/arc/kernel/devtree.c | 7 ------- 4 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 arch/arc/include/asm/clk.h delete mode 100644 arch/arc/kernel/clk.c (limited to 'arch/arc/kernel') diff --git a/arch/arc/include/asm/clk.h b/arch/arc/include/asm/clk.h deleted file mode 100644 index bf9d29f5bd53..000000000000 --- a/arch/arc/include/asm/clk.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _ASM_ARC_CLK_H -#define _ASM_ARC_CLK_H - -/* Although we can't really hide core_freq, the accessor is still better way */ -extern unsigned long core_freq; - -static inline unsigned long arc_get_core_freq(void) -{ - return core_freq; -} - -extern int arc_set_core_freq(unsigned long); - -#endif diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index 1bc2036b19d7..cfcdedf52ff8 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile @@ -9,7 +9,7 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' obj-y := arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o -obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o +obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o intc-compact.o obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o obj-$(CONFIG_PCI) += pcibios.o diff --git a/arch/arc/kernel/clk.c b/arch/arc/kernel/clk.c deleted file mode 100644 index 10c7b0b5a079..000000000000 --- a/arch/arc/kernel/clk.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include - -unsigned long core_freq = 80000000; - -/* - * As of now we default to device-tree provided clock - * In future we can determine this in early boot - */ -int arc_set_core_freq(unsigned long freq) -{ - core_freq = freq; - return 0; -} diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index fecbc96df828..f1e07c2344f8 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #ifdef CONFIG_SERIAL_EARLYCON @@ -63,8 +62,6 @@ const struct machine_desc * __init setup_machine_fdt(void *dt) { const struct machine_desc *mdesc; unsigned long dt_root; - const void *clk; - int len; if (!early_init_dt_scan(dt)) return NULL; @@ -74,10 +71,6 @@ const struct machine_desc * __init setup_machine_fdt(void *dt) machine_halt(); dt_root = of_get_flat_dt_root(); - clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len); - if (clk) - arc_set_core_freq(of_read_ulong(clk, len/4)); - arc_set_early_base_baud(dt_root); return mdesc; -- cgit v1.2.3 From 71f9cf8fdd72e5f5c3a60f632bd1534fc7996b81 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 7 Nov 2015 09:16:19 +0200 Subject: ARC: Mark secondary cpu online only after all HW setup is done In SMP setup, master loops for each_present_cpu calling cpu_up(). For ARC it returns as soon as new cpu's status becomes online, However secondary may still do HW initializing, machine or platform hook level. So turn secondary online only after all HW setup is done. Signed-off-by: Noam Camus Acked-by: Vineet Gupta --- arch/arc/kernel/smp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/arc/kernel') diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 6b1813456336..f183cc648851 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -126,11 +126,6 @@ void start_kernel_secondary(void) current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); - notify_cpu_starting(cpu); - set_cpu_online(cpu, true); - - pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu); - /* Some SMP H/w setup - for each cpu */ if (plat_smp_ops.init_per_cpu) plat_smp_ops.init_per_cpu(cpu); @@ -138,6 +133,11 @@ void start_kernel_secondary(void) if (machine_desc->init_per_cpu) machine_desc->init_per_cpu(cpu); + notify_cpu_starting(cpu); + set_cpu_online(cpu, true); + + pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu); + local_irq_enable(); preempt_disable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); -- cgit v1.2.3 From 86c25466f7414d6396f1aaa13e4b34f36ec272d5 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Mon, 3 Jun 2013 15:17:25 +0300 Subject: ARC: [plat-eznps] Use dedicated identity auxiliary register. With generic "identity" num of CPUs is limited to 256 (8 bit). We use our alternative AUX register GLOBAL_ID (12 bit). Now we can support up to 4096 CPUs. Signed-off-by: Noam Camus --- arch/arc/include/asm/entry-compact.h | 6 ++++++ arch/arc/kernel/ctx_sw.c | 13 +++++++++++++ arch/arc/plat-eznps/include/plat/ctop.h | 9 +++++++++ 3 files changed, 28 insertions(+) (limited to 'arch/arc/kernel') diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h index 1d8f57cd6057..e0e1faf03c50 100644 --- a/arch/arc/include/asm/entry-compact.h +++ b/arch/arc/include/asm/entry-compact.h @@ -36,6 +36,10 @@ #include #include /* For THREAD_SIZE */ +#ifdef CONFIG_ARC_PLAT_EZNPS +#include +#endif + /*-------------------------------------------------------------- * Switch to Kernel Mode stack if SP points to User Mode stack * @@ -296,11 +300,13 @@ bic \reg, sp, (THREAD_SIZE - 1) .endm +#ifndef CONFIG_ARC_PLAT_EZNPS /* Get CPU-ID of this core */ .macro GET_CPU_ID reg lr \reg, [identity] lsr \reg, \reg, 8 bmsk \reg, \reg, 7 .endm +#endif #endif /* __ASM_ARC_ENTRY_COMPACT_H */ diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c index 5d446df2c413..6f4cb0dab1b9 100644 --- a/arch/arc/kernel/ctx_sw.c +++ b/arch/arc/kernel/ctx_sw.c @@ -16,6 +16,9 @@ #include #include +#ifdef CONFIG_ARC_PLAT_EZNPS +#include +#endif #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) @@ -66,10 +69,17 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) */ #ifndef CONFIG_SMP "st %2, [@_current_task] \n\t" +#else +#ifdef CONFIG_ARC_PLAT_EZNPS + "lr r24, [%4] \n\t" +#ifndef CONFIG_EZNPS_MTM_EXT + "lsr r24, r24, 4 \n\t" +#endif #else "lr r24, [identity] \n\t" "lsr r24, r24, 8 \n\t" "bmsk r24, r24, 7 \n\t" +#endif "add2 r24, @_current_task, r24 \n\t" "st %2, [r24] \n\t" #endif @@ -107,6 +117,9 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) : "=r"(tmp) : "n"(KSP_WORD_OFF), "r"(next), "r"(prev) +#ifdef CONFIG_ARC_PLAT_EZNPS + , "i"(CTOP_AUX_LOGIC_GLOBAL_ID) +#endif : "blink" ); diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h index 91b25f3dd39a..9d6718c1a199 100644 --- a/arch/arc/plat-eznps/include/plat/ctop.h +++ b/arch/arc/plat-eznps/include/plat/ctop.h @@ -195,6 +195,15 @@ struct nps_host_reg_aux_lpc { #define REG_GIM_P_INT_DST_25 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x149) #define REG_GIM_P_INT_DST_26 nps_host_reg_non_cl(NPS_GIM_BLKID, 0x14A) +#else + +.macro GET_CPU_ID reg + lr \reg, [CTOP_AUX_LOGIC_GLOBAL_ID] +#ifndef CONFIG_EZNPS_MTM_EXT + lsr \reg, \reg, 4 +#endif +.endm + #endif /* __ASSEMBLY__ */ #endif /* _PLAT_EZNPS_CTOP_H */ -- cgit v1.2.3