diff options
Diffstat (limited to 'arch/blackfin/mach-common')
| -rw-r--r-- | arch/blackfin/mach-common/Makefile | 2 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/cache-c.c | 15 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/clocks-init.c | 1 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/cpufreq.c | 258 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/dpmc.c | 25 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/entry.S | 57 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 718 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/pm.c | 22 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/scb-init.c | 52 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/smp.c | 54 |
10 files changed, 282 insertions, 922 deletions
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 75f0ba29ebb..f0997920404 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_PM) += pm.o ifneq ($(CONFIG_BF60x),y) obj-$(CONFIG_PM) += dpmc_modes.o endif -obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_SCB_PRIORITY) += scb-init.o obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o diff --git a/arch/blackfin/mach-common/cache-c.c b/arch/blackfin/mach-common/cache-c.c index a60a24f5035..f4adedc9289 100644 --- a/arch/blackfin/mach-common/cache-c.c +++ b/arch/blackfin/mach-common/cache-c.c @@ -6,7 +6,6 @@ * Licensed under the GPL-2 or later. */ -#include <linux/init.h> #include <asm/blackfin.h> #include <asm/cplbinit.h> @@ -42,6 +41,16 @@ bfin_cache_init(struct cplb_entry *cplb_tbl, unsigned long cplb_addr, unsigned long mem_mask) { int i; +#ifdef CONFIG_L1_PARITY_CHECK + u32 ctrl; + + if (cplb_addr == DCPLB_ADDR0) { + ctrl = bfin_read32(mem_control) | (1 << RDCHK); + CSYNC(); + bfin_write32(mem_control, ctrl); + SSYNC(); + } +#endif for (i = 0; i < MAX_CPLBS; i++) { bfin_write32(cplb_addr + i * 4, cplb_tbl[i].addr); @@ -52,7 +61,7 @@ bfin_cache_init(struct cplb_entry *cplb_tbl, unsigned long cplb_addr, } #ifdef CONFIG_BFIN_ICACHE -void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl) +void bfin_icache_init(struct cplb_entry *icplb_tbl) { bfin_cache_init(icplb_tbl, ICPLB_ADDR0, ICPLB_DATA0, IMEM_CONTROL, (IMC | ENICPLB)); @@ -60,7 +69,7 @@ void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl) #endif #ifdef CONFIG_BFIN_DCACHE -void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) +void bfin_dcache_init(struct cplb_entry *dcplb_tbl) { /* * Anomaly notes: diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c index 2308ce52f84..d436bd907fc 100644 --- a/arch/blackfin/mach-common/clocks-init.c +++ b/arch/blackfin/mach-common/clocks-init.c @@ -7,7 +7,6 @@ */ #include <linux/linkage.h> -#include <linux/init.h> #include <asm/blackfin.h> #include <asm/dma.h> diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c deleted file mode 100644 index d88bd31319e..00000000000 --- a/arch/blackfin/mach-common/cpufreq.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Blackfin core clock scaling - * - * Copyright 2008-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/init.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <asm/blackfin.h> -#include <asm/time.h> -#include <asm/dpmc.h> - - -/* this is the table of CCLK frequencies, in Hz */ -/* .index is the entry in the auxiliary dpm_state_table[] */ -static struct cpufreq_frequency_table bfin_freq_table[] = { - { - .frequency = CPUFREQ_TABLE_END, - .index = 0, - }, - { - .frequency = CPUFREQ_TABLE_END, - .index = 1, - }, - { - .frequency = CPUFREQ_TABLE_END, - .index = 2, - }, - { - .frequency = CPUFREQ_TABLE_END, - .index = 0, - }, -}; - -static struct bfin_dpm_state { - unsigned int csel; /* system clock divider */ - unsigned int tscale; /* change the divider on the core timer interrupt */ -} dpm_state_table[3]; - -#if defined(CONFIG_CYCLES_CLOCKSOURCE) -/* - * normalized to maximum frequency offset for CYCLES, - * used in time-ts cycles clock source, but could be used - * somewhere also. - */ -unsigned long long __bfin_cycles_off; -unsigned int __bfin_cycles_mod; -#endif - -/**************************************************************************/ -static void __init bfin_init_tables(unsigned long cclk, unsigned long sclk) -{ - - unsigned long csel, min_cclk; - int index; - - /* Anomaly 273 seems to still exist on non-BF54x w/dcache turned on */ -#if ANOMALY_05000273 || ANOMALY_05000274 || \ - (!(defined(CONFIG_BF54x) || defined(CONFIG_BF60x)) \ - && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE)) - min_cclk = sclk * 2; -#else - min_cclk = sclk; -#endif - -#ifndef CONFIG_BF60x - csel = ((bfin_read_PLL_DIV() & CSEL) >> 4); -#else - csel = bfin_read32(CGU0_DIV) & 0x1F; -#endif - - for (index = 0; (cclk >> index) >= min_cclk && csel <= 3 && index < 3; index++, csel++) { - bfin_freq_table[index].frequency = cclk >> index; -#ifndef CONFIG_BF60x - dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */ -#else - dpm_state_table[index].csel = csel; -#endif - dpm_state_table[index].tscale = (TIME_SCALE >> index) - 1; - - pr_debug("cpufreq: freq:%d csel:0x%x tscale:%d\n", - bfin_freq_table[index].frequency, - dpm_state_table[index].csel, - dpm_state_table[index].tscale); - } - return; -} - -static void bfin_adjust_core_timer(void *info) -{ - unsigned int tscale; - unsigned int index = *(unsigned int *)info; - - /* we have to adjust the core timer, because it is using cclk */ - tscale = dpm_state_table[index].tscale; - bfin_write_TSCALE(tscale); - return; -} - -static unsigned int bfin_getfreq_khz(unsigned int cpu) -{ - /* Both CoreA/B have the same core clock */ - return get_cclk() / 1000; -} - -#ifdef CONFIG_BF60x -unsigned long cpu_set_cclk(int cpu, unsigned long new) -{ - struct clk *clk; - int ret; - - clk = clk_get(NULL, "CCLK"); - if (IS_ERR(clk)) - return -ENODEV; - - ret = clk_set_rate(clk, new); - clk_put(clk); - return ret; -} -#endif - -static int bfin_target(struct cpufreq_policy *poli, - unsigned int target_freq, unsigned int relation) -{ -#ifndef CONFIG_BF60x - unsigned int plldiv; -#endif - unsigned int index, cpu; - unsigned long cclk_hz; - struct cpufreq_freqs freqs; - static unsigned long lpj_ref; - static unsigned int lpj_ref_freq; - int ret = 0; - -#if defined(CONFIG_CYCLES_CLOCKSOURCE) - cycles_t cycles; -#endif - - for_each_online_cpu(cpu) { - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - - if (!policy) - continue; - - if (cpufreq_frequency_table_target(policy, bfin_freq_table, - target_freq, relation, &index)) - return -EINVAL; - - cclk_hz = bfin_freq_table[index].frequency; - - freqs.old = bfin_getfreq_khz(0); - freqs.new = cclk_hz; - freqs.cpu = cpu; - - pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n", - cclk_hz, target_freq, freqs.old); - - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (cpu == CPUFREQ_CPU) { -#ifndef CONFIG_BF60x - plldiv = (bfin_read_PLL_DIV() & SSEL) | - dpm_state_table[index].csel; - bfin_write_PLL_DIV(plldiv); -#else - ret = cpu_set_cclk(cpu, freqs.new * 1000); - if (ret != 0) { - WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret); - break; - } -#endif - on_each_cpu(bfin_adjust_core_timer, &index, 1); -#if defined(CONFIG_CYCLES_CLOCKSOURCE) - cycles = get_cycles(); - SSYNC(); - cycles += 10; /* ~10 cycles we lose after get_cycles() */ - __bfin_cycles_off += - (cycles << __bfin_cycles_mod) - (cycles << index); - __bfin_cycles_mod = index; -#endif - if (!lpj_ref_freq) { - lpj_ref = loops_per_jiffy; - lpj_ref_freq = freqs.old; - } - if (freqs.new != freqs.old) { - loops_per_jiffy = cpufreq_scale(lpj_ref, - lpj_ref_freq, freqs.new); - } - } - /* TODO: just test case for cycles clock source, remove later */ - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - } - - pr_debug("cpufreq: done\n"); - return ret; -} - -static int bfin_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, bfin_freq_table); -} - -static int __bfin_cpu_init(struct cpufreq_policy *policy) -{ - - unsigned long cclk, sclk; - - cclk = get_cclk() / 1000; - sclk = get_sclk() / 1000; - - if (policy->cpu == CPUFREQ_CPU) - bfin_init_tables(cclk, sclk); - - policy->cpuinfo.transition_latency = 50000; /* 50us assumed */ - - policy->cur = cclk; - cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu); - return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table); -} - -static struct freq_attr *bfin_freq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - -static struct cpufreq_driver bfin_driver = { - .verify = bfin_verify_speed, - .target = bfin_target, - .get = bfin_getfreq_khz, - .init = __bfin_cpu_init, - .name = "bfin cpufreq", - .owner = THIS_MODULE, - .attr = bfin_freq_attr, -}; - -static int __init bfin_cpu_init(void) -{ - return cpufreq_register_driver(&bfin_driver); -} - -static void __exit bfin_cpu_exit(void) -{ - cpufreq_unregister_driver(&bfin_driver); -} - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("cpufreq driver for Blackfin"); -MODULE_LICENSE("GPL"); - -module_init(bfin_cpu_init); -module_exit(bfin_cpu_exit); diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c index f5685a496c5..724a8c5f557 100644 --- a/arch/blackfin/mach-common/dpmc.c +++ b/arch/blackfin/mach-common/dpmc.c @@ -129,7 +129,7 @@ static struct notifier_block vreg_cpufreq_notifier_block = { * bfin_dpmc_probe - * */ -static int __devinit bfin_dpmc_probe(struct platform_device *pdev) +static int bfin_dpmc_probe(struct platform_device *pdev) { if (pdev->dev.platform_data) pdata = pdev->dev.platform_data; @@ -143,7 +143,7 @@ static int __devinit bfin_dpmc_probe(struct platform_device *pdev) /** * bfin_dpmc_remove - */ -static int __devexit bfin_dpmc_remove(struct platform_device *pdev) +static int bfin_dpmc_remove(struct platform_device *pdev) { pdata = NULL; return cpufreq_unregister_notifier(&vreg_cpufreq_notifier_block, @@ -152,29 +152,12 @@ static int __devexit bfin_dpmc_remove(struct platform_device *pdev) struct platform_driver bfin_dpmc_device_driver = { .probe = bfin_dpmc_probe, - .remove = __devexit_p(bfin_dpmc_remove), + .remove = bfin_dpmc_remove, .driver = { .name = DRIVER_NAME, } }; - -/** - * bfin_dpmc_init - Init driver - */ -static int __init bfin_dpmc_init(void) -{ - return platform_driver_register(&bfin_dpmc_device_driver); -} -module_init(bfin_dpmc_init); - -/** - * bfin_dpmc_exit - break down driver - */ -static void __exit bfin_dpmc_exit(void) -{ - platform_driver_unregister(&bfin_dpmc_device_driver); -} -module_exit(bfin_dpmc_exit); +module_platform_driver(bfin_dpmc_device_driver); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); MODULE_DESCRIPTION("cpu power management driver for Blackfin"); diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 1c3d2c5bb0b..86b5a095c5a 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -530,61 +530,6 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ jump .Lsyscall_really_exit; ENDPROC(_trap) -ENTRY(_kernel_execve) - link SIZEOF_PTREGS; - p0 = sp; - r3 = SIZEOF_PTREGS / 4; - r4 = 0(x); -.Lclear_regs: - [p0++] = r4; - r3 += -1; - cc = r3 == 0; - if !cc jump .Lclear_regs (bp); - - p0 = sp; - sp += -16; - [sp + 12] = p0; - pseudo_long_call _do_execve, p5; - SP += 16; - cc = r0 == 0; - if ! cc jump .Lexecve_failed; - /* Success. Copy our temporary pt_regs to the top of the kernel - * stack and do a normal exception return. - */ - r1 = sp; - r0 = (-KERNEL_STACK_SIZE) (x); - r1 = r1 & r0; - p2 = r1; - p3 = [p2]; - r0 = KERNEL_STACK_SIZE - 4 (z); - p1 = r0; - p1 = p1 + p2; - - p0 = fp; - r4 = [p0--]; - r3 = SIZEOF_PTREGS / 4; -.Lcopy_regs: - r4 = [p0--]; - [p1--] = r4; - r3 += -1; - cc = r3 == 0; - if ! cc jump .Lcopy_regs (bp); - - r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); - p1 = r0; - p1 = p1 + p2; - sp = p1; - r0 = syscfg; - [SP + PT_SYSCFG] = r0; - [p3 + (TASK_THREAD + THREAD_KSP)] = sp; - - RESTORE_CONTEXT; - rti; -.Lexecve_failed: - unlink; - rts; -ENDPROC(_kernel_execve) - ENTRY(_system_call) /* Store IPEND */ p2.l = lo(IPEND); @@ -1486,7 +1431,7 @@ ENTRY(_sys_call_table) .long _sys_ni_syscall /* old sys_ipc */ .long _sys_fsync .long _sys_ni_syscall /* old sys_sigreturn */ - .long _sys_clone /* 120 */ + .long _bfin_clone /* 120 */ .long _sys_setdomainname .long _sys_newuname .long _sys_ni_syscall /* old sys_modify_ldt */ diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 902bebc434c..1f94784eab6 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -28,12 +28,6 @@ #include <asm/dpmc.h> #include <asm/traps.h> -#ifndef SEC_GCTL -# define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) -#else -# define SIC_SYSIRQ(irq) ((irq) - IVG15) -#endif - /* * NOTES: * - we have separated the physical Hardware interrupt from the @@ -141,13 +135,13 @@ static void bfin_core_unmask_irq(struct irq_data *d) return; } +#ifndef SEC_GCTL void bfin_internal_mask_irq(unsigned int irq) { unsigned long flags = hard_local_irq_save(); -#ifndef SEC_GCTL #ifdef SIC_IMASK0 - unsigned mask_bank = SIC_SYSIRQ(irq) / 32; - unsigned mask_bit = SIC_SYSIRQ(irq) % 32; + unsigned mask_bank = BFIN_SYSIRQ(irq) / 32; + unsigned mask_bit = BFIN_SYSIRQ(irq) % 32; bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & ~(1 << mask_bit)); # if defined(CONFIG_SMP) || defined(CONFIG_ICC) @@ -156,9 +150,8 @@ void bfin_internal_mask_irq(unsigned int irq) # endif #else bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & - ~(1 << SIC_SYSIRQ(irq))); + ~(1 << BFIN_SYSIRQ(irq))); #endif /* end of SIC_IMASK0 */ -#endif hard_local_irq_restore(flags); } @@ -176,10 +169,9 @@ void bfin_internal_unmask_irq(unsigned int irq) { unsigned long flags = hard_local_irq_save(); -#ifndef SEC_GCTL #ifdef SIC_IMASK0 - unsigned mask_bank = SIC_SYSIRQ(irq) / 32; - unsigned mask_bit = SIC_SYSIRQ(irq) % 32; + unsigned mask_bank = BFIN_SYSIRQ(irq) / 32; + unsigned mask_bit = BFIN_SYSIRQ(irq) % 32; # ifdef CONFIG_SMP if (cpumask_test_cpu(0, affinity)) # endif @@ -194,17 +186,103 @@ void bfin_internal_unmask_irq(unsigned int irq) # endif #else bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | - (1 << SIC_SYSIRQ(irq))); + (1 << BFIN_SYSIRQ(irq))); +#endif + hard_local_irq_restore(flags); +} + +#ifdef CONFIG_SMP +static void bfin_internal_unmask_irq_chip(struct irq_data *d) +{ + bfin_internal_unmask_irq_affinity(d->irq, d->affinity); +} + +static int bfin_internal_set_affinity(struct irq_data *d, + const struct cpumask *mask, bool force) +{ + bfin_internal_mask_irq(d->irq); + bfin_internal_unmask_irq_affinity(d->irq, mask); + + return 0; +} +#else +static void bfin_internal_unmask_irq_chip(struct irq_data *d) +{ + bfin_internal_unmask_irq(d->irq); +} +#endif + +#if defined(CONFIG_PM) +int bfin_internal_set_wake(unsigned int irq, unsigned int state) +{ + u32 bank, bit, wakeup = 0; + unsigned long flags; + bank = BFIN_SYSIRQ(irq) / 32; + bit = BFIN_SYSIRQ(irq) % 32; + + switch (irq) { +#ifdef IRQ_RTC + case IRQ_RTC: + wakeup |= WAKE; + break; +#endif +#ifdef IRQ_CAN0_RX + case IRQ_CAN0_RX: + wakeup |= CANWE; + break; +#endif +#ifdef IRQ_CAN1_RX + case IRQ_CAN1_RX: + wakeup |= CANWE; + break; +#endif +#ifdef IRQ_USB_INT0 + case IRQ_USB_INT0: + wakeup |= USBWE; + break; #endif +#ifdef CONFIG_BF54x + case IRQ_CNT: + wakeup |= ROTWE; + break; #endif + default: + break; + } + + flags = hard_local_irq_save(); + + if (state) { + bfin_sic_iwr[bank] |= (1 << bit); + vr_wakeup |= wakeup; + + } else { + bfin_sic_iwr[bank] &= ~(1 << bit); + vr_wakeup &= ~wakeup; + } + hard_local_irq_restore(flags); + + return 0; } -#ifdef SEC_GCTL +static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state) +{ + return bfin_internal_set_wake(d->irq, state); +} +#else +inline int bfin_internal_set_wake(unsigned int irq, unsigned int state) +{ + return 0; +} +# define bfin_internal_set_wake_chip NULL +#endif + +#else /* SEC_GCTL */ static void bfin_sec_preflow_handler(struct irq_data *d) { unsigned long flags = hard_local_irq_save(); - unsigned int sid = SIC_SYSIRQ(d->irq); + unsigned int sid = BFIN_SYSIRQ(d->irq); bfin_write_SEC_SCI(0, SEC_CSID, sid); @@ -214,7 +292,7 @@ static void bfin_sec_preflow_handler(struct irq_data *d) static void bfin_sec_mask_ack_irq(struct irq_data *d) { unsigned long flags = hard_local_irq_save(); - unsigned int sid = SIC_SYSIRQ(d->irq); + unsigned int sid = BFIN_SYSIRQ(d->irq); bfin_write_SEC_SCI(0, SEC_CSID, sid); @@ -224,7 +302,7 @@ static void bfin_sec_mask_ack_irq(struct irq_data *d) static void bfin_sec_unmask_irq(struct irq_data *d) { unsigned long flags = hard_local_irq_save(); - unsigned int sid = SIC_SYSIRQ(d->irq); + unsigned int sid = BFIN_SYSIRQ(d->irq); bfin_write32(SEC_END, sid); @@ -269,7 +347,7 @@ static void bfin_sec_enable_sci(unsigned int sid) unsigned long flags = hard_local_irq_save(); uint32_t reg_sctl = bfin_read_SEC_SCTL(sid); - if (sid == SIC_SYSIRQ(IRQ_WATCH0)) + if (sid == BFIN_SYSIRQ(IRQ_WATCH0)) reg_sctl |= SEC_SCTL_FAULT_EN; else reg_sctl |= SEC_SCTL_INT_EN; @@ -292,7 +370,7 @@ static void bfin_sec_disable_sci(unsigned int sid) static void bfin_sec_enable(struct irq_data *d) { unsigned long flags = hard_local_irq_save(); - unsigned int sid = SIC_SYSIRQ(d->irq); + unsigned int sid = BFIN_SYSIRQ(d->irq); bfin_sec_enable_sci(sid); bfin_sec_enable_ssi(sid); @@ -303,7 +381,7 @@ static void bfin_sec_enable(struct irq_data *d) static void bfin_sec_disable(struct irq_data *d) { unsigned long flags = hard_local_irq_save(); - unsigned int sid = SIC_SYSIRQ(d->irq); + unsigned int sid = BFIN_SYSIRQ(d->irq); bfin_sec_disable_sci(sid); bfin_sec_disable_ssi(sid); @@ -328,9 +406,10 @@ static void bfin_sec_set_priority(unsigned int sec_int_levels, u8 *sec_int_prior hard_local_irq_restore(flags); } -void bfin_sec_raise_irq(unsigned int sid) +void bfin_sec_raise_irq(unsigned int irq) { unsigned long flags = hard_local_irq_save(); + unsigned int sid = BFIN_SYSIRQ(irq); bfin_write32(SEC_RAISE, sid); @@ -341,8 +420,13 @@ static void init_software_driven_irq(void) { bfin_sec_set_ssi_coreid(34, 0); bfin_sec_set_ssi_coreid(35, 1); + + bfin_sec_enable_sci(35); + bfin_sec_enable_ssi(35); bfin_sec_set_ssi_coreid(36, 0); bfin_sec_set_ssi_coreid(37, 1); + bfin_sec_enable_sci(37); + bfin_sec_enable_ssi(37); } void bfin_sec_resume(void) @@ -387,13 +471,8 @@ void handle_sec_ssi_fault(uint32_t gstat) } -void handle_sec_fault(unsigned int irq, struct irq_desc *desc) +void handle_sec_fault(uint32_t sec_gstat) { - uint32_t sec_gstat; - - raw_spin_lock(&desc->lock); - - sec_gstat = bfin_read32(SEC_GSTAT); if (sec_gstat & SEC_GSTAT_ERR) { switch (sec_gstat & SEC_GSTAT_ERRC) { @@ -410,16 +489,16 @@ void handle_sec_fault(unsigned int irq, struct irq_desc *desc) } - - raw_spin_unlock(&desc->lock); } -void handle_core_fault(unsigned int irq, struct irq_desc *desc) +static struct irqaction bfin_fault_irq = { + .name = "Blackfin fault", +}; + +static irqreturn_t bfin_fault_routine(int irq, void *data) { struct pt_regs *fp = get_irq_regs(); - raw_spin_lock(&desc->lock); - switch (irq) { case IRQ_C0_DBL_FAULT: double_fault_c(fp); @@ -431,105 +510,22 @@ void handle_core_fault(unsigned int irq, struct irq_desc *desc) printk(KERN_NOTICE "Kernel Stack\n"); show_stack(current, NULL); print_modules(); - panic("Kernel core hardware error"); + panic("Core 0 hardware error"); break; case IRQ_C0_NMI_L1_PARITY_ERR: - panic("NMI occurs unexpectedly"); + panic("Core 0 NMI L1 parity error"); + break; + case IRQ_SEC_ERR: + pr_err("SEC error\n"); + handle_sec_fault(bfin_read32(SEC_GSTAT)); break; default: - panic("Core 1 fault occurs unexpectedly"); - } - - raw_spin_unlock(&desc->lock); -} -#endif - -#ifdef CONFIG_SMP -static void bfin_internal_unmask_irq_chip(struct irq_data *d) -{ - bfin_internal_unmask_irq_affinity(d->irq, d->affinity); -} - -static int bfin_internal_set_affinity(struct irq_data *d, - const struct cpumask *mask, bool force) -{ - bfin_internal_mask_irq(d->irq); - bfin_internal_unmask_irq_affinity(d->irq, mask); - - return 0; -} -#else -static void bfin_internal_unmask_irq_chip(struct irq_data *d) -{ - bfin_internal_unmask_irq(d->irq); -} -#endif - -#if defined(CONFIG_PM) && !defined(SEC_GCTL) -int bfin_internal_set_wake(unsigned int irq, unsigned int state) -{ - u32 bank, bit, wakeup = 0; - unsigned long flags; - bank = SIC_SYSIRQ(irq) / 32; - bit = SIC_SYSIRQ(irq) % 32; - - switch (irq) { -#ifdef IRQ_RTC - case IRQ_RTC: - wakeup |= WAKE; - break; -#endif -#ifdef IRQ_CAN0_RX - case IRQ_CAN0_RX: - wakeup |= CANWE; - break; -#endif -#ifdef IRQ_CAN1_RX - case IRQ_CAN1_RX: - wakeup |= CANWE; - break; -#endif -#ifdef IRQ_USB_INT0 - case IRQ_USB_INT0: - wakeup |= USBWE; - break; -#endif -#ifdef CONFIG_BF54x - case IRQ_CNT: - wakeup |= ROTWE; - break; -#endif - default: - break; - } - - flags = hard_local_irq_save(); - - if (state) { - bfin_sic_iwr[bank] |= (1 << bit); - vr_wakeup |= wakeup; - - } else { - bfin_sic_iwr[bank] &= ~(1 << bit); - vr_wakeup &= ~wakeup; + panic("Unknown fault %d", irq); } - hard_local_irq_restore(flags); - - return 0; -} - -static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state) -{ - return bfin_internal_set_wake(d->irq, state); -} -#else -inline int bfin_internal_set_wake(unsigned int irq, unsigned int state) -{ - return 0; + return IRQ_HANDLED; } -# define bfin_internal_set_wake_chip NULL -#endif +#endif /* SEC_GCTL */ static struct irq_chip bfin_core_irqchip = { .name = "CORE", @@ -537,6 +533,7 @@ static struct irq_chip bfin_core_irqchip = { .irq_unmask = bfin_core_unmask_irq, }; +#ifndef SEC_GCTL static struct irq_chip bfin_internal_irqchip = { .name = "INTN", .irq_mask = bfin_internal_mask_irq_chip, @@ -548,8 +545,7 @@ static struct irq_chip bfin_internal_irqchip = { #endif .irq_set_wake = bfin_internal_set_wake_chip, }; - -#ifdef SEC_GCTL +#else static struct irq_chip bfin_sec_irqchip = { .name = "SEC", .irq_mask_ack = bfin_sec_mask_ack_irq, @@ -705,10 +701,9 @@ static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) __irq_set_handler_locked(irq, handle); } -static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS); -extern void bfin_gpio_irq_prepare(unsigned gpio); +#ifdef CONFIG_GPIO_ADI -#if !BFIN_GPIO_PINT +static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS); static void bfin_gpio_ack_irq(struct irq_data *d) { @@ -822,15 +817,6 @@ static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) return 0; } -#ifdef CONFIG_PM -static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) -{ - return gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state); -} -#else -# define bfin_gpio_set_wake NULL -#endif - static void bfin_demux_gpio_block(unsigned int irq) { unsigned int gpio, mask; @@ -897,283 +883,46 @@ void bfin_demux_gpio_irq(unsigned int inta_irq, bfin_demux_gpio_block(irq); } -#else - -#define NR_PINT_BITS 32 -#define IRQ_NOT_AVAIL 0xFF - -#define PINT_2_BANK(x) ((x) >> 5) -#define PINT_2_BIT(x) ((x) & 0x1F) -#define PINT_BIT(x) (1 << (PINT_2_BIT(x))) - -static unsigned char irq2pint_lut[NR_PINTS]; -static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; - -static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = { - (struct bfin_pint_regs *)PINT0_MASK_SET, - (struct bfin_pint_regs *)PINT1_MASK_SET, - (struct bfin_pint_regs *)PINT2_MASK_SET, - (struct bfin_pint_regs *)PINT3_MASK_SET, -#ifdef CONFIG_BF60x - (struct bfin_pint_regs *)PINT4_MASK_SET, - (struct bfin_pint_regs *)PINT5_MASK_SET, -#endif -}; - -inline unsigned int get_irq_base(u32 bank, u8 bmap) -{ - unsigned int irq_base; - -#ifndef CONFIG_BF60x - if (bank < 2) { /*PA-PB */ - irq_base = IRQ_PA0 + bmap * 16; - } else { /*PC-PJ */ - irq_base = IRQ_PC0 + bmap * 16; - } -#else - irq_base = IRQ_PA0 + bank * 16 + bmap * 16; -#endif - return irq_base; -} - - /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ -void init_pint_lut(void) -{ - u16 bank, bit, irq_base, bit_pos; - u32 pint_assign; - u8 bmap; - - memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut)); - - for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { - - pint_assign = pint[bank]->assign; - - for (bit = 0; bit < NR_PINT_BITS; bit++) { - - bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF; - - irq_base = get_irq_base(bank, bmap); - - irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0); - bit_pos = bit + bank * NR_PINT_BITS; - - pint2irq_lut[bit_pos] = irq_base - SYS_IRQS; - irq2pint_lut[irq_base - SYS_IRQS] = bit_pos; - } - } -} - -static void bfin_gpio_ack_irq(struct irq_data *d) -{ - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - u32 pintbit = PINT_BIT(pint_val); - u32 bank = PINT_2_BANK(pint_val); - - if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { - if (pint[bank]->invert_set & pintbit) - pint[bank]->invert_clear = pintbit; - else - pint[bank]->invert_set = pintbit; - } - pint[bank]->request = pintbit; - -} - -static void bfin_gpio_mask_ack_irq(struct irq_data *d) -{ - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - u32 pintbit = PINT_BIT(pint_val); - u32 bank = PINT_2_BANK(pint_val); - - if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { - if (pint[bank]->invert_set & pintbit) - pint[bank]->invert_clear = pintbit; - else - pint[bank]->invert_set = pintbit; - } - - pint[bank]->request = pintbit; - pint[bank]->mask_clear = pintbit; -} - -static void bfin_gpio_mask_irq(struct irq_data *d) -{ - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - - pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val); -} - -static void bfin_gpio_unmask_irq(struct irq_data *d) -{ - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - u32 pintbit = PINT_BIT(pint_val); - u32 bank = PINT_2_BANK(pint_val); - - pint[bank]->mask_set = pintbit; -} - -static unsigned int bfin_gpio_irq_startup(struct irq_data *d) -{ - unsigned int irq = d->irq; - u32 gpionr = irq_to_gpio(irq); - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; - - if (pint_val == IRQ_NOT_AVAIL) { - printk(KERN_ERR - "GPIO IRQ %d :Not in PINT Assign table " - "Reconfigure Interrupt to Port Assignemt\n", irq); - return -ENODEV; - } - - if (__test_and_set_bit(gpionr, gpio_enabled)) - bfin_gpio_irq_prepare(gpionr); - - bfin_gpio_unmask_irq(d); - - return 0; -} - -static void bfin_gpio_irq_shutdown(struct irq_data *d) -{ - u32 gpionr = irq_to_gpio(d->irq); - - bfin_gpio_mask_irq(d); - __clear_bit(gpionr, gpio_enabled); - bfin_gpio_irq_free(gpionr); -} - -static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) -{ - unsigned int irq = d->irq; - int ret; - char buf[16]; - u32 gpionr = irq_to_gpio(irq); - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; - u32 pintbit = PINT_BIT(pint_val); - u32 bank = PINT_2_BANK(pint_val); - - if (pint_val == IRQ_NOT_AVAIL) - return -ENODEV; - - if (type == IRQ_TYPE_PROBE) { - /* only probe unenabled GPIO interrupt lines */ - if (test_bit(gpionr, gpio_enabled)) - return 0; - type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; - } - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | - IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - - snprintf(buf, 16, "gpio-irq%d", irq); - ret = bfin_gpio_irq_request(gpionr, buf); - if (ret) - return ret; - - if (__test_and_set_bit(gpionr, gpio_enabled)) - bfin_gpio_irq_prepare(gpionr); - - } else { - __clear_bit(gpionr, gpio_enabled); - return 0; - } - - if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) - pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ - else - pint[bank]->invert_clear = pintbit; /* high or rising edge denoted by zero */ - - if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - if (gpio_get_value(gpionr)) - pint[bank]->invert_set = pintbit; - else - pint[bank]->invert_clear = pintbit; - } - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - pint[bank]->edge_set = pintbit; - bfin_set_irq_handler(irq, handle_edge_irq); - } else { - pint[bank]->edge_clear = pintbit; - bfin_set_irq_handler(irq, handle_level_irq); - } - - return 0; -} - #ifdef CONFIG_PM -static struct bfin_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS]; -static u32 save_pint_sec_ctl[NR_PINT_SYS_IRQS]; static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) { - u32 pint_irq; - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - u32 bank = PINT_2_BANK(pint_val); - - switch (bank) { - case 0: - pint_irq = IRQ_PINT0; - break; - case 2: - pint_irq = IRQ_PINT2; - break; - case 3: - pint_irq = IRQ_PINT3; - break; - case 1: - pint_irq = IRQ_PINT1; - break; -#ifdef CONFIG_BF60x - case 4: - pint_irq = IRQ_PINT4; - break; - case 5: - pint_irq = IRQ_PINT5; - break; -#endif - default: - return -EINVAL; - } + return bfin_gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state); +} - bfin_internal_set_wake(pint_irq, state); +#else - return 0; -} +# define bfin_gpio_set_wake NULL -void bfin_pint_suspend(void) -{ - u32 bank; +#endif - for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { - save_pint_reg[bank].mask_set = pint[bank]->mask_set; - save_pint_reg[bank].assign = pint[bank]->assign; - save_pint_reg[bank].edge_set = pint[bank]->edge_set; - save_pint_reg[bank].invert_set = pint[bank]->invert_set; - } -} +static struct irq_chip bfin_gpio_irqchip = { + .name = "GPIO", + .irq_ack = bfin_gpio_ack_irq, + .irq_mask = bfin_gpio_mask_irq, + .irq_mask_ack = bfin_gpio_mask_ack_irq, + .irq_unmask = bfin_gpio_unmask_irq, + .irq_disable = bfin_gpio_mask_irq, + .irq_enable = bfin_gpio_unmask_irq, + .irq_set_type = bfin_gpio_irq_type, + .irq_startup = bfin_gpio_irq_startup, + .irq_shutdown = bfin_gpio_irq_shutdown, + .irq_set_wake = bfin_gpio_set_wake, +}; -void bfin_pint_resume(void) -{ - u32 bank; +#endif - for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { - pint[bank]->mask_set = save_pint_reg[bank].mask_set; - pint[bank]->assign = save_pint_reg[bank].assign; - pint[bank]->edge_set = save_pint_reg[bank].edge_set; - pint[bank]->invert_set = save_pint_reg[bank].invert_set; - } -} +#ifdef CONFIG_PM #ifdef SEC_GCTL +static u32 save_pint_sec_ctl[NR_PINT_SYS_IRQS]; + static int sec_suspend(void) { u32 bank; for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) - save_pint_sec_ctl[bank] = bfin_read_SEC_SCTL(bank + SIC_SYSIRQ(IRQ_PINT0)); + save_pint_sec_ctl[bank] = bfin_read_SEC_SCTL(bank + BFIN_SYSIRQ(IRQ_PINT0)); return 0; } @@ -1187,7 +936,7 @@ static void sec_resume(void) bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN); for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) - bfin_write_SEC_SCTL(bank + SIC_SYSIRQ(IRQ_PINT0), save_pint_sec_ctl[bank]); + bfin_write_SEC_SCTL(bank + BFIN_SYSIRQ(IRQ_PINT0), save_pint_sec_ctl[bank]); } static struct syscore_ops sec_pm_syscore_ops = { @@ -1195,91 +944,10 @@ static struct syscore_ops sec_pm_syscore_ops = { .resume = sec_resume, }; #endif -#else -# define bfin_gpio_set_wake NULL -#endif - -void bfin_demux_gpio_irq(unsigned int inta_irq, - struct irq_desc *desc) -{ - u32 bank, pint_val; - u32 request, irq; - u32 level_mask; - int umask = 0; - struct irq_chip *chip = irq_desc_get_chip(desc); - - if (chip->irq_mask_ack) { - chip->irq_mask_ack(&desc->irq_data); - } else { - chip->irq_mask(&desc->irq_data); - if (chip->irq_ack) - chip->irq_ack(&desc->irq_data); - } - switch (inta_irq) { - case IRQ_PINT0: - bank = 0; - break; - case IRQ_PINT2: - bank = 2; - break; - case IRQ_PINT3: - bank = 3; - break; - case IRQ_PINT1: - bank = 1; - break; -#ifdef CONFIG_BF60x - case IRQ_PINT4: - bank = 4; - break; - case IRQ_PINT5: - bank = 5; - break; #endif - default: - return; - } - - pint_val = bank * NR_PINT_BITS; - request = pint[bank]->request; - - level_mask = pint[bank]->edge_set & request; - - while (request) { - if (request & 1) { - irq = pint2irq_lut[pint_val] + SYS_IRQS; - if (level_mask & PINT_BIT(pint_val)) { - umask = 1; - chip->irq_unmask(&desc->irq_data); - } - bfin_handle_irq(irq); - } - pint_val++; - request >>= 1; - } - - if (!umask) - chip->irq_unmask(&desc->irq_data); -} -#endif - -static struct irq_chip bfin_gpio_irqchip = { - .name = "GPIO", - .irq_ack = bfin_gpio_ack_irq, - .irq_mask = bfin_gpio_mask_irq, - .irq_mask_ack = bfin_gpio_mask_ack_irq, - .irq_unmask = bfin_gpio_unmask_irq, - .irq_disable = bfin_gpio_mask_irq, - .irq_enable = bfin_gpio_unmask_irq, - .irq_set_type = bfin_gpio_irq_type, - .irq_startup = bfin_gpio_irq_startup, - .irq_shutdown = bfin_gpio_irq_shutdown, - .irq_set_wake = bfin_gpio_set_wake, -}; - -void __cpuinit init_exception_vectors(void) +void init_exception_vectors(void) { /* cannot program in software: * evt0 - emulation (jtag) @@ -1329,17 +997,6 @@ int __init init_arch_irq(void) local_irq_disable(); -#if BFIN_GPIO_PINT -# ifdef CONFIG_PINTx_REASSIGN - pint[0]->assign = CONFIG_PINT0_ASSIGN; - pint[1]->assign = CONFIG_PINT1_ASSIGN; - pint[2]->assign = CONFIG_PINT2_ASSIGN; - pint[3]->assign = CONFIG_PINT3_ASSIGN; -# endif - /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ - init_pint_lut(); -#endif - for (irq = 0; irq <= SYS_IRQS; irq++) { if (irq <= IRQ_CORETMR) irq_set_chip(irq, &bfin_core_irqchip); @@ -1347,12 +1004,8 @@ int __init init_arch_irq(void) irq_set_chip(irq, &bfin_internal_irqchip); switch (irq) { -#if BFIN_GPIO_PINT - case IRQ_PINT0: - case IRQ_PINT1: - case IRQ_PINT2: - case IRQ_PINT3: -#elif defined(BF537_FAMILY) +#if !BFIN_GPIO_PINT +#if defined(BF537_FAMILY) case IRQ_PH_INTA_MAC_RX: case IRQ_PF_INTA_PG_INTA: #elif defined(BF533_FAMILY) @@ -1370,6 +1023,7 @@ int __init init_arch_irq(void) #endif irq_set_chained_handler(irq, bfin_demux_gpio_irq); break; +#endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) case IRQ_MAC_ERROR: irq_set_chained_handler(irq, @@ -1417,10 +1071,12 @@ int __init init_arch_irq(void) handle_level_irq); #endif /* if configured as edge, then will be changed to do_edge_IRQ */ +#ifdef CONFIG_GPIO_ADI for (irq = GPIO_IRQ_BASE; irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++) irq_set_chip_and_handler(irq, &bfin_gpio_irqchip, handle_level_irq); +#endif bfin_write_IMASK(0); CSYNC(); ilat = bfin_read_ILAT(); @@ -1523,55 +1179,23 @@ int __init init_arch_irq(void) local_irq_disable(); -#if BFIN_GPIO_PINT -# ifdef CONFIG_PINTx_REASSIGN - pint[0]->assign = CONFIG_PINT0_ASSIGN; - pint[1]->assign = CONFIG_PINT1_ASSIGN; - pint[2]->assign = CONFIG_PINT2_ASSIGN; - pint[3]->assign = CONFIG_PINT3_ASSIGN; - pint[4]->assign = CONFIG_PINT4_ASSIGN; - pint[5]->assign = CONFIG_PINT5_ASSIGN; -# endif - /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ - init_pint_lut(); -#endif - for (irq = 0; irq <= SYS_IRQS; irq++) { if (irq <= IRQ_CORETMR) { - irq_set_chip(irq, &bfin_core_irqchip); -#ifdef CONFIG_TICKSOURCE_CORETMR + irq_set_chip_and_handler(irq, &bfin_core_irqchip, + handle_simple_irq); +#if defined(CONFIG_TICKSOURCE_CORETMR) && defined(CONFIG_SMP) if (irq == IRQ_CORETMR) -# ifdef CONFIG_SMP irq_set_handler(irq, handle_percpu_irq); -# else - irq_set_handler(irq, handle_simple_irq); -# endif #endif - } else if (irq < BFIN_IRQ(0)) { - irq_set_chip_and_handler(irq, &bfin_internal_irqchip, - handle_simple_irq); - } else if (irq == IRQ_SEC_ERR) { - irq_set_chip_and_handler(irq, &bfin_sec_irqchip, - handle_sec_fault); - } else if (irq < CORE_IRQS && irq >= IRQ_C0_DBL_FAULT) { - irq_set_chip_and_handler(irq, &bfin_sec_irqchip, - handle_core_fault); - } else if (irq >= BFIN_IRQ(21) && irq <= BFIN_IRQ(26)) { - irq_set_chip(irq, &bfin_sec_irqchip); - irq_set_chained_handler(irq, bfin_demux_gpio_irq); } else if (irq >= BFIN_IRQ(34) && irq <= BFIN_IRQ(37)) { - irq_set_chip(irq, &bfin_sec_irqchip); - irq_set_handler(irq, handle_percpu_irq); - } else { irq_set_chip_and_handler(irq, &bfin_sec_irqchip, - handle_fasteoi_irq); + handle_percpu_irq); + } else { + irq_set_chip(irq, &bfin_sec_irqchip); + irq_set_handler(irq, handle_fasteoi_irq); __irq_set_preflow_handler(irq, bfin_sec_preflow_handler); } } - for (irq = GPIO_IRQ_BASE; - irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++) - irq_set_chip_and_handler(irq, &bfin_gpio_irqchip, - handle_level_irq); bfin_write_IMASK(0); CSYNC(); @@ -1584,8 +1208,6 @@ int __init init_arch_irq(void) bfin_sec_set_priority(CONFIG_SEC_IRQ_PRIORITY_LEVELS, sec_int_priority); - bfin_sec_set_priority(CONFIG_SEC_IRQ_PRIORITY_LEVELS, sec_int_priority); - /* Enable interrupts IVG7-15 */ bfin_irq_flags |= IMASK_IVG15 | IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | @@ -1593,8 +1215,8 @@ int __init init_arch_irq(void) bfin_write_SEC_FCTL(SEC_FCTL_EN | SEC_FCTL_SYSRST_EN | SEC_FCTL_FLTIN_EN); - bfin_sec_enable_sci(SIC_SYSIRQ(IRQ_WATCH0)); - bfin_sec_enable_ssi(SIC_SYSIRQ(IRQ_WATCH0)); + bfin_sec_enable_sci(BFIN_SYSIRQ(IRQ_WATCH0)); + bfin_sec_enable_ssi(BFIN_SYSIRQ(IRQ_WATCH0)); bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET); udelay(100); bfin_write_SEC_GCTL(SEC_GCTL_EN); @@ -1602,7 +1224,17 @@ int __init init_arch_irq(void) bfin_write_SEC_SCI(1, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN); init_software_driven_irq(); + +#ifdef CONFIG_PM register_syscore_ops(&sec_pm_syscore_ops); +#endif + + bfin_fault_irq.handler = bfin_fault_routine; +#ifdef CONFIG_L1_PARITY_CHECK + setup_irq(IRQ_C0_NMI_L1_PARITY_ERR, &bfin_fault_irq); +#endif + setup_irq(IRQ_C0_DBL_FAULT, &bfin_fault_irq); + setup_irq(IRQ_SEC_ERR, &bfin_fault_irq); return 0; } diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index 87bfe549ad3..1387a94bcfd 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -27,7 +27,7 @@ struct bfin_cpu_pm_fns *bfin_cpu_pm; void bfin_pm_suspend_standby_enter(void) { -#ifndef CONFIG_BF60x +#if !BFIN_GPIO_PINT bfin_pm_standby_setup(); #endif @@ -41,7 +41,7 @@ void bfin_pm_suspend_standby_enter(void) # endif #endif -#ifndef CONFIG_BF60x +#if !BFIN_GPIO_PINT bfin_pm_standby_restore(); #endif @@ -128,6 +128,7 @@ static void flushinv_all_dcache(void) if ((status & 0x3) != 0x3) continue; + /* construct the address using the tag */ addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5); @@ -140,11 +141,14 @@ static void flushinv_all_dcache(void) int bfin_pm_suspend_mem_enter(void) { - int wakeup, ret; + int ret; +#ifndef CONFIG_BF60x + int wakeup; +#endif unsigned char *memptr = kmalloc(L1_CODE_LENGTH + L1_DATA_A_LENGTH + L1_DATA_B_LENGTH + L1_SCRATCH_LENGTH, - GFP_KERNEL); + GFP_ATOMIC); if (memptr == NULL) { panic("bf53x_suspend_l1_mem malloc failed"); @@ -170,10 +174,8 @@ int bfin_pm_suspend_mem_enter(void) return ret; } +#ifdef CONFIG_GPIO_ADI bfin_gpio_pm_hibernate_suspend(); - -#if BFIN_GPIO_PINT - bfin_pint_suspend(); #endif #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) @@ -194,11 +196,9 @@ int bfin_pm_suspend_mem_enter(void) _enable_icplb(); _enable_dcplb(); -#if BFIN_GPIO_PINT - bfin_pint_resume(); -#endif - +#ifdef CONFIG_GPIO_ADI bfin_gpio_pm_hibernate_restore(); +#endif blackfin_dma_resume(); kfree(memptr); diff --git a/arch/blackfin/mach-common/scb-init.c b/arch/blackfin/mach-common/scb-init.c new file mode 100644 index 00000000000..8923398db66 --- /dev/null +++ b/arch/blackfin/mach-common/scb-init.c @@ -0,0 +1,52 @@ +/* + * arch/blackfin/mach-common/scb-init.c - reprogram system cross bar priority + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <asm/scb.h> + +__attribute__((l1_text)) +inline void scb_mi_write(unsigned long scb_mi_arbw, unsigned int slots, + unsigned char *scb_mi_prio) +{ + unsigned int i; + + for (i = 0; i < slots; ++i) + bfin_write32(scb_mi_arbw, (i << SCB_SLOT_OFFSET) | scb_mi_prio[i]); +} + +__attribute__((l1_text)) +inline void scb_mi_read(unsigned long scb_mi_arbw, unsigned int slots, + unsigned char *scb_mi_prio) +{ + unsigned int i; + + for (i = 0; i < slots; ++i) { + bfin_write32(scb_mi_arbw, (0xFF << SCB_SLOT_OFFSET) | i); + scb_mi_prio[i] = bfin_read32(scb_mi_arbw); + } +} + +__attribute__((l1_text)) +void init_scb(void) +{ + unsigned int i, j; + unsigned char scb_tmp_prio[32]; + + pr_info("Init System Crossbar\n"); + for (i = 0; scb_data[i].scb_mi_arbr > 0; ++i) { + + scb_mi_write(scb_data[i].scb_mi_arbw, scb_data[i].scb_mi_slots, scb_data[i].scb_mi_prio); + + pr_debug("scb priority at 0x%lx:\n", scb_data[i].scb_mi_arbr); + scb_mi_read(scb_data[i].scb_mi_arbw, scb_data[i].scb_mi_slots, scb_tmp_prio); + for (j = 0; j < scb_data[i].scb_mi_slots; ++j) + pr_debug("slot %d = %d\n", j, scb_tmp_prio[j]); + } + +} diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index bb61ae4986e..ba6c30d8534 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -46,13 +46,13 @@ struct corelock_slot corelock __attribute__ ((__section__(".l2.bss"))); unsigned long blackfin_iflush_l1_entry[NR_CPUS]; #endif -struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; +struct blackfin_initial_pda initial_pda_coreb; enum ipi_message_type { + BFIN_IPI_NONE, BFIN_IPI_TIMER, BFIN_IPI_RESCHEDULE, BFIN_IPI_CALL_FUNC, - BFIN_IPI_CALL_FUNC_SINGLE, BFIN_IPI_CPU_STOP, }; @@ -72,8 +72,8 @@ static DEFINE_SPINLOCK(stop_lock); /* Simple FIFO buffer, overflow leads to panic */ struct ipi_data { - unsigned long count; - unsigned long bits; + atomic_t count; + atomic_t bits; }; static DEFINE_PER_CPU(struct ipi_data, bfin_ipi); @@ -145,9 +145,9 @@ static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) platform_clear_ipi(cpu, IRQ_SUPPLE_1); + smp_rmb(); bfin_ipi_data = &__get_cpu_var(bfin_ipi); - smp_mb(); - while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) { + while ((pending = atomic_xchg(&bfin_ipi_data->bits, 0)) != 0) { msg = 0; do { msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1); @@ -161,19 +161,17 @@ static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) case BFIN_IPI_CALL_FUNC: generic_smp_call_function_interrupt(); break; - - case BFIN_IPI_CALL_FUNC_SINGLE: - generic_smp_call_function_single_interrupt(); - break; - case BFIN_IPI_CPU_STOP: ipi_cpu_stop(cpu); break; + default: + goto out; } + atomic_dec(&bfin_ipi_data->count); } while (msg < BITS_PER_LONG); - smp_mb(); } +out: return IRQ_HANDLED; } @@ -183,8 +181,8 @@ static void bfin_ipi_init(void) struct ipi_data *bfin_ipi_data; for_each_possible_cpu(cpu) { bfin_ipi_data = &per_cpu(bfin_ipi, cpu); - bfin_ipi_data->bits = 0; - bfin_ipi_data->count = 0; + atomic_set(&bfin_ipi_data->bits, 0); + atomic_set(&bfin_ipi_data->count, 0); } } @@ -195,21 +193,20 @@ void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg) unsigned long flags; local_irq_save(flags); - smp_mb(); for_each_cpu(cpu, cpumask) { bfin_ipi_data = &per_cpu(bfin_ipi, cpu); - smp_mb(); - set_bit(msg, &bfin_ipi_data->bits); - bfin_ipi_data->count++; - platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1); + atomic_set_mask((1 << msg), &bfin_ipi_data->bits); + atomic_inc(&bfin_ipi_data->count); } - local_irq_restore(flags); + smp_wmb(); + for_each_cpu(cpu, cpumask) + platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1); } void arch_send_call_function_single_ipi(int cpu) { - send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC_SINGLE); + send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC); } void arch_send_call_function_ipi_mask(const struct cpumask *mask) @@ -249,7 +246,7 @@ void smp_send_stop(void) return; } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) +int __cpu_up(unsigned int cpu, struct task_struct *idle) { int ret; @@ -262,7 +259,7 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) return ret; } -static void __cpuinit setup_secondary(unsigned int cpu) +static void setup_secondary(unsigned int cpu) { unsigned long ilat; @@ -280,7 +277,7 @@ static void __cpuinit setup_secondary(unsigned int cpu) IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; } -void __cpuinit secondary_start_kernel(void) +void secondary_start_kernel(void) { unsigned int cpu = smp_processor_id(); struct mm_struct *mm = &init_mm; @@ -319,7 +316,6 @@ void __cpuinit secondary_start_kernel(void) setup_secondary(cpu); platform_secondary_init(cpu); - /* setup local core timer */ bfin_local_timer_setup(); @@ -335,7 +331,9 @@ void __cpuinit secondary_start_kernel(void) */ calibrate_delay(); - cpu_idle(); + /* We are done with local CPU inits, unblock the boot CPU. */ + set_cpu_online(cpu, true); + cpu_startup_entry(CPUHP_ONLINE); } void __init smp_prepare_boot_cpu(void) @@ -404,7 +402,7 @@ EXPORT_SYMBOL(resync_core_dcache); #endif #ifdef CONFIG_HOTPLUG_CPU -int __cpuexit __cpu_disable(void) +int __cpu_disable(void) { unsigned int cpu = smp_processor_id(); @@ -417,7 +415,7 @@ int __cpuexit __cpu_disable(void) static DECLARE_COMPLETION(cpu_killed); -int __cpuexit __cpu_die(unsigned int cpu) +int __cpu_die(unsigned int cpu) { return wait_for_completion_timeout(&cpu_killed, 5000); } |
