summaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r--arch/blackfin/mach-common/clocks-init.c139
-rw-r--r--arch/blackfin/mach-common/cpufreq.c5
-rw-r--r--arch/blackfin/mach-common/entry.S7
-rw-r--r--arch/blackfin/mach-common/ints-priority.c331
-rw-r--r--arch/blackfin/mach-common/pm.c8
-rw-r--r--arch/blackfin/mach-common/smp.c223
6 files changed, 314 insertions, 399 deletions
diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c
index 7ad2407d157..2308ce52f84 100644
--- a/arch/blackfin/mach-common/clocks-init.c
+++ b/arch/blackfin/mach-common/clocks-init.c
@@ -16,23 +16,14 @@
#include <asm/dpmc.h>
#ifdef CONFIG_BF60x
-#define CSEL_P 0
-#define S0SEL_P 5
-#define SYSSEL_P 8
-#define S1SEL_P 13
-#define DSEL_P 16
-#define OSEL_P 22
-#define ALGN_P 29
-#define UPDT_P 30
-#define LOCK_P 31
#define CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CLKIN_HALF)
#define CGU_DIV_VAL \
- ((CONFIG_CCLK_DIV << CSEL_P) | \
- (CONFIG_SCLK_DIV << SYSSEL_P) | \
- (CONFIG_SCLK0_DIV << S0SEL_P) | \
- (CONFIG_SCLK1_DIV << S1SEL_P) | \
- (CONFIG_DCLK_DIV << DSEL_P))
+ ((CONFIG_CCLK_DIV << CSEL_OFFSET) | \
+ (CONFIG_SCLK_DIV << SYSSEL_OFFSET) | \
+ (CONFIG_SCLK0_DIV << S0SEL_OFFSET) | \
+ (CONFIG_SCLK1_DIV << S1SEL_OFFSET) | \
+ (CONFIG_DCLK_DIV << DSEL_OFFSET))
#define CONFIG_BFIN_DCLK (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_DCLK_DIV) / 1000000)
#if ((CONFIG_BFIN_DCLK != 125) && \
@@ -41,89 +32,7 @@
(CONFIG_BFIN_DCLK != 225) && (CONFIG_BFIN_DCLK != 250))
#error "DCLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
#endif
-struct ddr_config {
- u32 ddr_clk;
- u32 dmc_ddrctl;
- u32 dmc_ddrcfg;
- u32 dmc_ddrtr0;
- u32 dmc_ddrtr1;
- u32 dmc_ddrtr2;
- u32 dmc_ddrmr;
- u32 dmc_ddrmr1;
-};
-struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = {
- [0] = {
- .ddr_clk = 125,
- .dmc_ddrctl = 0x00000904,
- .dmc_ddrcfg = 0x00000422,
- .dmc_ddrtr0 = 0x20705212,
- .dmc_ddrtr1 = 0x201003CF,
- .dmc_ddrtr2 = 0x00320107,
- .dmc_ddrmr = 0x00000422,
- .dmc_ddrmr1 = 0x4,
- },
- [1] = {
- .ddr_clk = 133,
- .dmc_ddrctl = 0x00000904,
- .dmc_ddrcfg = 0x00000422,
- .dmc_ddrtr0 = 0x20806313,
- .dmc_ddrtr1 = 0x2013040D,
- .dmc_ddrtr2 = 0x00320108,
- .dmc_ddrmr = 0x00000632,
- .dmc_ddrmr1 = 0x4,
- },
- [2] = {
- .ddr_clk = 150,
- .dmc_ddrctl = 0x00000904,
- .dmc_ddrcfg = 0x00000422,
- .dmc_ddrtr0 = 0x20A07323,
- .dmc_ddrtr1 = 0x20160492,
- .dmc_ddrtr2 = 0x00320209,
- .dmc_ddrmr = 0x00000632,
- .dmc_ddrmr1 = 0x4,
- },
- [3] = {
- .ddr_clk = 166,
- .dmc_ddrctl = 0x00000904,
- .dmc_ddrcfg = 0x00000422,
- .dmc_ddrtr0 = 0x20A07323,
- .dmc_ddrtr1 = 0x2016050E,
- .dmc_ddrtr2 = 0x00320209,
- .dmc_ddrmr = 0x00000632,
- .dmc_ddrmr1 = 0x4,
- },
- [4] = {
- .ddr_clk = 200,
- .dmc_ddrctl = 0x00000904,
- .dmc_ddrcfg = 0x00000422,
- .dmc_ddrtr0 = 0x20a07323,
- .dmc_ddrtr1 = 0x2016050f,
- .dmc_ddrtr2 = 0x00320509,
- .dmc_ddrmr = 0x00000632,
- .dmc_ddrmr1 = 0x4,
- },
- [5] = {
- .ddr_clk = 225,
- .dmc_ddrctl = 0x00000904,
- .dmc_ddrcfg = 0x00000422,
- .dmc_ddrtr0 = 0x20E0A424,
- .dmc_ddrtr1 = 0x302006DB,
- .dmc_ddrtr2 = 0x0032020D,
- .dmc_ddrmr = 0x00000842,
- .dmc_ddrmr1 = 0x4,
- },
- [6] = {
- .ddr_clk = 250,
- .dmc_ddrctl = 0x00000904,
- .dmc_ddrcfg = 0x00000422,
- .dmc_ddrtr0 = 0x20E0A424,
- .dmc_ddrtr1 = 0x3020079E,
- .dmc_ddrtr2 = 0x0032020D,
- .dmc_ddrmr = 0x00000842,
- .dmc_ddrmr1 = 0x4,
- },
-};
#else
#define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */
#define PLL_CTL_VAL \
@@ -144,43 +53,9 @@ void init_clocks(void)
* in the middle of reprogramming things, and that'll screw us up.
* For example, any automatic DMAs left by U-Boot for splash screens.
*/
-
#ifdef CONFIG_BF60x
- int i, dlldatacycle, dll_ctl;
- bfin_write32(CGU0_DIV, CGU_DIV_VAL);
- bfin_write32(CGU0_CTL, CGU_CTL_VAL);
- while ((bfin_read32(CGU0_STAT) & 0x8) || !(bfin_read32(CGU0_STAT) & 0x4))
- continue;
-
- bfin_write32(CGU0_DIV, CGU_DIV_VAL | (1 << UPDT_P));
- while (bfin_read32(CGU0_STAT) & (1 << 3))
- continue;
-
- for (i = 0; i < 7; i++) {
- if (ddr_config_table[i].ddr_clk == CONFIG_BFIN_DCLK) {
- bfin_write_DDR0_CFG(ddr_config_table[i].dmc_ddrcfg);
- bfin_write_DDR0_TR0(ddr_config_table[i].dmc_ddrtr0);
- bfin_write_DDR0_TR1(ddr_config_table[i].dmc_ddrtr1);
- bfin_write_DDR0_TR2(ddr_config_table[i].dmc_ddrtr2);
- bfin_write_DDR0_MR(ddr_config_table[i].dmc_ddrmr);
- bfin_write_DDR0_EMR1(ddr_config_table[i].dmc_ddrmr1);
- bfin_write_DDR0_CTL(ddr_config_table[i].dmc_ddrctl);
- break;
- }
- }
-
- do_sync();
- while (!(bfin_read_DDR0_STAT() & 0x4))
- continue;
-
- dlldatacycle = (bfin_read_DDR0_STAT() & 0x00f00000) >> 20;
- dll_ctl = bfin_read_DDR0_DLLCTL();
- dll_ctl &= 0x0ff;
- bfin_write_DDR0_DLLCTL(dll_ctl | (dlldatacycle << 8));
-
- do_sync();
- while (!(bfin_read_DDR0_STAT() & 0x2000))
- continue;
+ init_cgu(CGU_DIV_VAL, CGU_CTL_VAL);
+ init_dmc(CONFIG_BFIN_DCLK);
#else
size_t i;
for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index 6e87dc13f6b..c854a27cbea 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -64,7 +64,8 @@ static void __init bfin_init_tables(unsigned long cclk, unsigned long sclk)
/* Anomaly 273 seems to still exist on non-BF54x w/dcache turned on */
#if ANOMALY_05000273 || ANOMALY_05000274 || \
- (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE))
+ (!(defined(CONFIG_BF54x) || defined(CONFIG_BF60x)) \
+ && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE))
min_cclk = sclk * 2;
#else
min_cclk = sclk;
@@ -173,7 +174,7 @@ static int bfin_target(struct cpufreq_policy *poli,
#else
ret = cpu_set_cclk(cpu, freqs.new * 1000);
if (ret != 0) {
- pr_debug("cpufreq set freq failed %d\n", ret);
+ WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret);
break;
}
#endif
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 04c2fbe41a7..1c3d2c5bb0b 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -25,13 +25,6 @@
#include <asm/context.S>
-#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
-# define EX_SCRATCH_REG RETN
-#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
-# define EX_SCRATCH_REG RETE
-#else
-# define EX_SCRATCH_REG CYCLES
-#endif
#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
.section .l1.text
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 2729cba715b..7ca09ec2ca5 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -26,8 +26,9 @@
#include <asm/gpio.h>
#include <asm/irq_handler.h>
#include <asm/dpmc.h>
+#include <asm/traps.h>
-#ifndef CONFIG_BF60x
+#ifndef SEC_GCTL
# define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))
#else
# define SIC_SYSIRQ(irq) ((irq) - IVG15)
@@ -56,7 +57,7 @@ unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */
unsigned vr_wakeup;
#endif
-#ifndef CONFIG_BF60x
+#ifndef SEC_GCTL
static struct ivgx {
/* irq number for request_irq, available in mach-bf5xx/irq.h */
unsigned int irqno;
@@ -143,7 +144,7 @@ static void bfin_core_unmask_irq(struct irq_data *d)
void bfin_internal_mask_irq(unsigned int irq)
{
unsigned long flags = hard_local_irq_save();
-#ifndef CONFIG_BF60x
+#ifndef SEC_GCTL
#ifdef SIC_IMASK0
unsigned mask_bank = SIC_SYSIRQ(irq) / 32;
unsigned mask_bit = SIC_SYSIRQ(irq) % 32;
@@ -175,7 +176,7 @@ void bfin_internal_unmask_irq(unsigned int irq)
{
unsigned long flags = hard_local_irq_save();
-#ifndef CONFIG_BF60x
+#ifndef SEC_GCTL
#ifdef SIC_IMASK0
unsigned mask_bank = SIC_SYSIRQ(irq) / 32;
unsigned mask_bit = SIC_SYSIRQ(irq) % 32;
@@ -199,7 +200,7 @@ void bfin_internal_unmask_irq(unsigned int irq)
hard_local_irq_restore(flags);
}
-#ifdef CONFIG_BF60x
+#ifdef SEC_GCTL
static void bfin_sec_preflow_handler(struct irq_data *d)
{
unsigned long flags = hard_local_irq_save();
@@ -310,7 +311,24 @@ static void bfin_sec_disable(struct irq_data *d)
hard_local_irq_restore(flags);
}
-static void bfin_sec_raise_irq(unsigned int sid)
+static void bfin_sec_set_priority(unsigned int sec_int_levels, u8 *sec_int_priority)
+{
+ unsigned long flags = hard_local_irq_save();
+ uint32_t reg_sctl;
+ int i;
+
+ bfin_write_SEC_SCI(0, SEC_CPLVL, sec_int_levels);
+
+ for (i = 0; i < SYS_IRQS - BFIN_IRQ(0); i++) {
+ reg_sctl = bfin_read_SEC_SCTL(i) & ~SEC_SCTL_PRIO;
+ reg_sctl |= sec_int_priority[i] << SEC_SCTL_PRIO_OFFSET;
+ bfin_write_SEC_SCTL(i, reg_sctl);
+ }
+
+ hard_local_irq_restore(flags);
+}
+
+void bfin_sec_raise_irq(unsigned int sid)
{
unsigned long flags = hard_local_irq_save();
@@ -396,24 +414,34 @@ void handle_sec_fault(unsigned int irq, struct irq_desc *desc)
raw_spin_unlock(&desc->lock);
}
-static int sec_suspend(void)
+void handle_core_fault(unsigned int irq, struct irq_desc *desc)
{
- return 0;
-}
+ struct pt_regs *fp = get_irq_regs();
-static void sec_resume(void)
-{
- bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
- udelay(100);
- bfin_write_SEC_GCTL(SEC_GCTL_EN);
- bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
-}
+ raw_spin_lock(&desc->lock);
-static struct syscore_ops sec_pm_syscore_ops = {
- .suspend = sec_suspend,
- .resume = sec_resume,
-};
+ switch (irq) {
+ case IRQ_C0_DBL_FAULT:
+ double_fault_c(fp);
+ break;
+ case IRQ_C0_HW_ERR:
+ dump_bfin_process(fp);
+ dump_bfin_mem(fp);
+ show_regs(fp);
+ printk(KERN_NOTICE "Kernel Stack\n");
+ show_stack(current, NULL);
+ print_modules();
+ panic("Kernel core hardware error");
+ break;
+ case IRQ_C0_NMI_L1_PARITY_ERR:
+ panic("NMI occurs unexpectedly");
+ break;
+ default:
+ panic("Core 1 fault occurs unexpectedly");
+ }
+ raw_spin_unlock(&desc->lock);
+}
#endif
#ifdef CONFIG_SMP
@@ -437,7 +465,7 @@ static void bfin_internal_unmask_irq_chip(struct irq_data *d)
}
#endif
-#if defined(CONFIG_PM) && !defined(CONFIG_BF60x)
+#if defined(CONFIG_PM) && !defined(SEC_GCTL)
int bfin_internal_set_wake(unsigned int irq, unsigned int state)
{
u32 bank, bit, wakeup = 0;
@@ -496,7 +524,10 @@ static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state)
return bfin_internal_set_wake(d->irq, state);
}
#else
-# define bfin_internal_set_wake(irq, state)
+inline int bfin_internal_set_wake(unsigned int irq, unsigned int state)
+{
+ return 0;
+}
# define bfin_internal_set_wake_chip NULL
#endif
@@ -518,7 +549,7 @@ static struct irq_chip bfin_internal_irqchip = {
.irq_set_wake = bfin_internal_set_wake_chip,
};
-#ifdef CONFIG_BF60x
+#ifdef SEC_GCTL
static struct irq_chip bfin_sec_irqchip = {
.name = "SEC",
.irq_mask_ack = bfin_sec_mask_ack_irq,
@@ -868,14 +899,6 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
#else
-# ifndef CONFIG_BF60x
-#define NR_PINT_SYS_IRQS 4
-#define NR_PINTS 160
-# else
-#define NR_PINT_SYS_IRQS 6
-#define NR_PINTS 112
-#endif
-
#define NR_PINT_BITS 32
#define IRQ_NOT_AVAIL 0xFF
@@ -897,29 +920,21 @@ static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = {
#endif
};
-#ifndef CONFIG_BF60x
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;
}
-
- return irq_base;
-}
#else
-inline unsigned int get_irq_base(u32 bank, u8 bmap)
-{
- unsigned int irq_base;
-
irq_base = IRQ_PA0 + bank * 16 + bmap * 16;
-
+#endif
return irq_base;
}
-#endif
/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
void init_pint_lut(void)
@@ -1089,6 +1104,9 @@ static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
}
#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;
@@ -1124,6 +1142,59 @@ static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
return 0;
}
+
+void bfin_pint_suspend(void)
+{
+ u32 bank;
+
+ 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;
+ }
+}
+
+void bfin_pint_resume(void)
+{
+ u32 bank;
+
+ 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 SEC_GCTL
+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));
+ return 0;
+}
+
+static void sec_resume(void)
+{
+ u32 bank;
+
+ bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
+ udelay(100);
+ bfin_write_SEC_GCTL(SEC_GCTL_EN);
+ 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]);
+}
+
+static struct syscore_ops sec_pm_syscore_ops = {
+ .suspend = sec_suspend,
+ .resume = sec_resume,
+};
+#endif
#else
# define bfin_gpio_set_wake NULL
#endif
@@ -1230,6 +1301,7 @@ void __cpuinit init_exception_vectors(void)
CSYNC();
}
+#ifndef SEC_GCTL
/*
* This function should be called during kernel startup to initialize
* the BFin IRQ handling routines.
@@ -1240,7 +1312,6 @@ int __init init_arch_irq(void)
int irq;
unsigned long ilat = 0;
-#ifndef CONFIG_BF60x
/* Disable all the peripheral intrs - page 4-29 HW Ref manual */
#ifdef SIC_IMASK0
bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
@@ -1255,9 +1326,6 @@ int __init init_arch_irq(void)
#else
bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
#endif
-#else /* CONFIG_BF60x */
- bfin_write_SEC_GCTL(SEC_GCTL_RESET);
-#endif
local_irq_disable();
@@ -1267,10 +1335,6 @@ int __init init_arch_irq(void)
pint[1]->assign = CONFIG_PINT1_ASSIGN;
pint[2]->assign = CONFIG_PINT2_ASSIGN;
pint[3]->assign = CONFIG_PINT3_ASSIGN;
-# ifdef CONFIG_BF60x
- pint[4]->assign = CONFIG_PINT4_ASSIGN;
- pint[5]->assign = CONFIG_PINT5_ASSIGN;
-# endif
# endif
/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
init_pint_lut();
@@ -1283,7 +1347,6 @@ int __init init_arch_irq(void)
irq_set_chip(irq, &bfin_internal_irqchip);
switch (irq) {
-#ifndef CONFIG_BF60x
#if BFIN_GPIO_PINT
case IRQ_PINT0:
case IRQ_PINT1:
@@ -1319,7 +1382,6 @@ int __init init_arch_irq(void)
irq_set_handler(irq, handle_percpu_irq);
break;
#endif
-#endif
#ifdef CONFIG_TICKSOURCE_CORETMR
case IRQ_CORETMR:
@@ -1349,8 +1411,7 @@ int __init init_arch_irq(void)
init_mach_irq();
-#ifndef CONFIG_BF60x
-#if (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) && !defined(CONFIG_BF60x)
+#if (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++)
irq_set_chip_and_handler(irq, &bfin_mac_status_irqchip,
handle_level_irq);
@@ -1360,28 +1421,6 @@ int __init init_arch_irq(void)
irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,
handle_level_irq);
-#else
- for (irq = BFIN_IRQ(0); irq <= SYS_IRQS; irq++) {
- if (irq < CORE_IRQS) {
- irq_set_chip(irq, &bfin_sec_irqchip);
- __irq_set_handler(irq, handle_sec_fault, 0, NULL);
- } 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);
- __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);
-#endif
bfin_write_IMASK(0);
CSYNC();
ilat = bfin_read_ILAT();
@@ -1393,7 +1432,6 @@ int __init init_arch_irq(void)
/* IMASK=xxx is equivalent to STI xx or bfin_irq_flags=xx,
* local_irq_enable()
*/
-#ifndef CONFIG_BF60x
program_IAR();
/* Therefore it's better to setup IARs before interrupts enabled */
search_IAR();
@@ -1427,23 +1465,6 @@ int __init init_arch_irq(void)
#else
bfin_write_SIC_IWR(IWR_DISABLE_ALL);
#endif
-#else /* CONFIG_BF60x */
- /* Enable interrupts IVG7-15 */
- bfin_irq_flags |= IMASK_IVG15 |
- IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
- IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
-
-
- 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_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
- udelay(100);
- bfin_write_SEC_GCTL(SEC_GCTL_EN);
- bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
- init_software_driven_irq();
- register_syscore_ops(&sec_pm_syscore_ops);
-#endif
return 0;
}
@@ -1452,14 +1473,11 @@ __attribute__((l1_text))
#endif
static int vec_to_irq(int vec)
{
-#ifndef CONFIG_BF60x
struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
unsigned long sic_status[3];
-#endif
if (likely(vec == EVT_IVTMR_P))
return IRQ_CORETMR;
-#ifndef CONFIG_BF60x
#ifdef SIC_ISR
sic_status[0] = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
#else
@@ -1488,11 +1506,119 @@ static int vec_to_irq(int vec)
#endif
return ivg->irqno;
}
-#else
- /* for bf60x read */
+}
+
+#else /* SEC_GCTL */
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the BFin IRQ handling routines.
+ */
+
+int __init init_arch_irq(void)
+{
+ int irq;
+ unsigned long ilat = 0;
+
+ bfin_write_SEC_GCTL(SEC_GCTL_RESET);
+
+ 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
+ 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);
+ __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();
+ ilat = bfin_read_ILAT();
+ CSYNC();
+ bfin_write_ILAT(ilat);
+ CSYNC();
+
+ printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
+
+ 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 |
+ IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
+
+
+ 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_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
+ udelay(100);
+ bfin_write_SEC_GCTL(SEC_GCTL_EN);
+ bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+ bfin_write_SEC_SCI(1, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+
+ init_software_driven_irq();
+ register_syscore_ops(&sec_pm_syscore_ops);
+
+ return 0;
+}
+
+#ifdef CONFIG_DO_IRQ_L1
+__attribute__((l1_text))
+#endif
+static int vec_to_irq(int vec)
+{
+ if (likely(vec == EVT_IVTMR_P))
+ return IRQ_CORETMR;
+
return BFIN_IRQ(bfin_read_SEC_SCI(0, SEC_CSID));
-#endif /* end of CONFIG_BF60x */
}
+#endif /* SEC_GCTL */
#ifdef CONFIG_DO_IRQ_L1
__attribute__((l1_text))
@@ -1514,6 +1640,10 @@ int __ipipe_get_irq_priority(unsigned irq)
if (irq <= IRQ_CORETMR)
return irq;
+#ifdef SEC_GCTL
+ if (irq >= BFIN_IRQ(0))
+ return IVG11;
+#else
for (ient = 0; ient < NR_PERI_INTS; ient++) {
struct ivgx *ivg = ivg_table + ient;
if (ivg->irqno == irq) {
@@ -1524,6 +1654,7 @@ int __ipipe_get_irq_priority(unsigned irq)
}
}
}
+#endif
return IVG15;
}
@@ -1536,8 +1667,6 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
{
struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
struct ipipe_domain *this_domain = __ipipe_current_domain;
- struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
- struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
int irq, s = 0;
irq = vec_to_irq(vec);
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index ca6655e0d65..87bfe549ad3 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -172,6 +172,10 @@ int bfin_pm_suspend_mem_enter(void)
bfin_gpio_pm_hibernate_suspend();
+#if BFIN_GPIO_PINT
+ bfin_pint_suspend();
+#endif
+
#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
flushinv_all_dcache();
#endif
@@ -190,6 +194,10 @@ int bfin_pm_suspend_mem_enter(void)
_enable_icplb();
_enable_dcplb();
+#if BFIN_GPIO_PINT
+ bfin_pint_resume();
+#endif
+
bfin_gpio_pm_hibernate_restore();
blackfin_dma_resume();
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index 00bbe672b3b..a40151306b7 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -48,10 +48,13 @@ unsigned long blackfin_iflush_l1_entry[NR_CPUS];
struct blackfin_initial_pda __cpuinitdata initial_pda_coreb;
-#define BFIN_IPI_TIMER 0
-#define BFIN_IPI_RESCHEDULE 1
-#define BFIN_IPI_CALL_FUNC 2
-#define BFIN_IPI_CPU_STOP 3
+enum ipi_message_type {
+ BFIN_IPI_TIMER,
+ BFIN_IPI_RESCHEDULE,
+ BFIN_IPI_CALL_FUNC,
+ BFIN_IPI_CALL_FUNC_SINGLE,
+ BFIN_IPI_CPU_STOP,
+};
struct blackfin_flush_data {
unsigned long start;
@@ -60,35 +63,20 @@ struct blackfin_flush_data {
void *secondary_stack;
-
-struct smp_call_struct {
- void (*func)(void *info);
- void *info;
- int wait;
- cpumask_t *waitmask;
-};
-
static struct blackfin_flush_data smp_flush_data;
static DEFINE_SPINLOCK(stop_lock);
-struct ipi_message {
- unsigned long type;
- struct smp_call_struct call_struct;
-};
-
/* A magic number - stress test shows this is safe for common cases */
#define BFIN_IPI_MSGQ_LEN 5
/* Simple FIFO buffer, overflow leads to panic */
-struct ipi_message_queue {
- spinlock_t lock;
+struct ipi_data {
unsigned long count;
- unsigned long head; /* head of the queue */
- struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN];
+ unsigned long bits;
};
-static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue);
+static DEFINE_PER_CPU(struct ipi_data, bfin_ipi);
static void ipi_cpu_stop(unsigned int cpu)
{
@@ -129,28 +117,6 @@ static void ipi_flush_icache(void *info)
blackfin_icache_flush_range(fdata->start, fdata->end);
}
-static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
-{
- int wait;
- void (*func)(void *info);
- void *info;
- func = msg->call_struct.func;
- info = msg->call_struct.info;
- wait = msg->call_struct.wait;
- func(info);
- if (wait) {
-#ifdef __ARCH_SYNC_CORE_DCACHE
- /*
- * 'wait' usually means synchronization between CPUs.
- * Invalidate D cache in case shared data was changed
- * by func() to ensure cache coherence.
- */
- resync_core_dcache();
-#endif
- cpumask_clear_cpu(cpu, msg->call_struct.waitmask);
- }
-}
-
/* Use IRQ_SUPPLE_0 to request reschedule.
* When returning from interrupt to user space,
* there is chance to reschedule */
@@ -172,152 +138,95 @@ void ipi_timer(void)
static irqreturn_t ipi_handler_int1(int irq, void *dev_instance)
{
- struct ipi_message *msg;
- struct ipi_message_queue *msg_queue;
+ struct ipi_data *bfin_ipi_data;
unsigned int cpu = smp_processor_id();
- unsigned long flags;
+ unsigned long pending;
+ unsigned long msg;
platform_clear_ipi(cpu, IRQ_SUPPLE_1);
- msg_queue = &__get_cpu_var(ipi_msg_queue);
-
- spin_lock_irqsave(&msg_queue->lock, flags);
-
- while (msg_queue->count) {
- msg = &msg_queue->ipi_message[msg_queue->head];
- switch (msg->type) {
- case BFIN_IPI_TIMER:
- ipi_timer();
- break;
- case BFIN_IPI_RESCHEDULE:
- scheduler_ipi();
- break;
- case BFIN_IPI_CALL_FUNC:
- ipi_call_function(cpu, msg);
- break;
- case BFIN_IPI_CPU_STOP:
- ipi_cpu_stop(cpu);
- break;
- default:
- printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n",
- cpu, msg->type);
- break;
- }
- msg_queue->head++;
- msg_queue->head %= BFIN_IPI_MSGQ_LEN;
- msg_queue->count--;
+ bfin_ipi_data = &__get_cpu_var(bfin_ipi);
+
+ while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) {
+ msg = 0;
+ do {
+ msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1);
+ switch (msg) {
+ case BFIN_IPI_TIMER:
+ ipi_timer();
+ break;
+ case BFIN_IPI_RESCHEDULE:
+ scheduler_ipi();
+ break;
+ 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;
+ }
+ } while (msg < BITS_PER_LONG);
+
+ smp_mb();
}
- spin_unlock_irqrestore(&msg_queue->lock, flags);
return IRQ_HANDLED;
}
-static void ipi_queue_init(void)
+static void bfin_ipi_init(void)
{
unsigned int cpu;
- struct ipi_message_queue *msg_queue;
+ struct ipi_data *bfin_ipi_data;
for_each_possible_cpu(cpu) {
- msg_queue = &per_cpu(ipi_msg_queue, cpu);
- spin_lock_init(&msg_queue->lock);
- msg_queue->count = 0;
- msg_queue->head = 0;
+ bfin_ipi_data = &per_cpu(bfin_ipi, cpu);
+ bfin_ipi_data->bits = 0;
+ bfin_ipi_data->count = 0;
}
}
-static inline void smp_send_message(cpumask_t callmap, unsigned long type,
- void (*func) (void *info), void *info, int wait)
+void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg)
{
unsigned int cpu;
- struct ipi_message_queue *msg_queue;
- struct ipi_message *msg;
- unsigned long flags, next_msg;
- cpumask_t waitmask; /* waitmask is shared by all cpus */
-
- cpumask_copy(&waitmask, &callmap);
- for_each_cpu(cpu, &callmap) {
- msg_queue = &per_cpu(ipi_msg_queue, cpu);
- spin_lock_irqsave(&msg_queue->lock, flags);
- if (msg_queue->count < BFIN_IPI_MSGQ_LEN) {
- next_msg = (msg_queue->head + msg_queue->count)
- % BFIN_IPI_MSGQ_LEN;
- msg = &msg_queue->ipi_message[next_msg];
- msg->type = type;
- if (type == BFIN_IPI_CALL_FUNC) {
- msg->call_struct.func = func;
- msg->call_struct.info = info;
- msg->call_struct.wait = wait;
- msg->call_struct.waitmask = &waitmask;
- }
- msg_queue->count++;
- } else
- panic("IPI message queue overflow\n");
- spin_unlock_irqrestore(&msg_queue->lock, flags);
+ struct ipi_data *bfin_ipi_data;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ 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);
}
- if (wait) {
- while (!cpumask_empty(&waitmask))
- blackfin_dcache_invalidate_range(
- (unsigned long)(&waitmask),
- (unsigned long)(&waitmask));
-#ifdef __ARCH_SYNC_CORE_DCACHE
- /*
- * Invalidate D cache in case shared data was changed by
- * other processors to ensure cache coherence.
- */
- resync_core_dcache();
-#endif
- }
+ local_irq_restore(flags);
}
-int smp_call_function(void (*func)(void *info), void *info, int wait)
+void arch_send_call_function_single_ipi(int cpu)
{
- cpumask_t callmap;
-
- preempt_disable();
- cpumask_copy(&callmap, cpu_online_mask);
- cpumask_clear_cpu(smp_processor_id(), &callmap);
- if (!cpumask_empty(&callmap))
- smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
-
- preempt_enable();
-
- return 0;
+ send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC_SINGLE);
}
-EXPORT_SYMBOL_GPL(smp_call_function);
-int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
- int wait)
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
{
- unsigned int cpu = cpuid;
- cpumask_t callmap;
-
- if (cpu_is_offline(cpu))
- return 0;
- cpumask_clear(&callmap);
- cpumask_set_cpu(cpu, &callmap);
-
- smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
-
- return 0;
+ send_ipi(mask, BFIN_IPI_CALL_FUNC);
}
-EXPORT_SYMBOL_GPL(smp_call_function_single);
void smp_send_reschedule(int cpu)
{
- cpumask_t callmap;
- /* simply trigger an ipi */
-
- cpumask_clear(&callmap);
- cpumask_set_cpu(cpu, &callmap);
-
- smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0);
+ send_ipi(cpumask_of(cpu), BFIN_IPI_RESCHEDULE);
return;
}
void smp_send_msg(const struct cpumask *mask, unsigned long type)
{
- smp_send_message(*mask, type, NULL, NULL, 0);
+ send_ipi(mask, type);
}
void smp_timer_broadcast(const struct cpumask *mask)
@@ -333,7 +242,7 @@ void smp_send_stop(void)
cpumask_copy(&callmap, cpu_online_mask);
cpumask_clear_cpu(smp_processor_id(), &callmap);
if (!cpumask_empty(&callmap))
- smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
+ send_ipi(&callmap, BFIN_IPI_CPU_STOP);
preempt_enable();
@@ -436,7 +345,7 @@ void __init smp_prepare_boot_cpu(void)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
platform_prepare_cpus(max_cpus);
- ipi_queue_init();
+ bfin_ipi_init();
platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0);
platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1);
}