diff options
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r-- | arch/blackfin/mach-common/Makefile | 5 | ||||
-rw-r--r-- | arch/blackfin/mach-common/clock.h | 27 | ||||
-rw-r--r-- | arch/blackfin/mach-common/clocks-init.c | 153 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cpufreq.c | 46 | ||||
-rw-r--r-- | arch/blackfin/mach-common/dpmc_modes.S | 606 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 5 | ||||
-rw-r--r-- | arch/blackfin/mach-common/head.S | 2 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 423 | ||||
-rw-r--r-- | arch/blackfin/mach-common/pm.c | 62 | ||||
-rw-r--r-- | arch/blackfin/mach-common/smp.c | 19 |
10 files changed, 688 insertions, 660 deletions
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index ff299f24aba0..75f0ba29ebb9 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -6,7 +6,10 @@ obj-y := \ cache.o cache-c.o entry.o head.o \ interrupt.o arch_checks.o ints-priority.o -obj-$(CONFIG_PM) += pm.o dpmc_modes.o +obj-$(CONFIG_PM) += pm.o +ifneq ($(CONFIG_BF60x),y) +obj-$(CONFIG_PM) += dpmc_modes.o +endif obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/blackfin/mach-common/clock.h b/arch/blackfin/mach-common/clock.h new file mode 100644 index 000000000000..645ff460a1f2 --- /dev/null +++ b/arch/blackfin/mach-common/clock.h @@ -0,0 +1,27 @@ +#ifndef __MACH_COMMON_CLKDEV_H +#define __MACH_COMMON_CLKDEV_H + +#include <linux/clk.h> + +struct clk_ops { + unsigned long (*get_rate)(struct clk *clk); + unsigned long (*round_rate)(struct clk *clk, unsigned long rate); + int (*set_rate)(struct clk *clk, unsigned long rate); + int (*enable)(struct clk *clk); + int (*disable)(struct clk *clk); +}; + +struct clk { + const char *name; + unsigned long rate; + spinlock_t lock; + u32 flags; + const struct clk_ops *ops; + const struct params *params; + void __iomem *reg; + u32 mask; + u32 shift; +}; + +#endif + diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c index d5cfe611b778..7ad2407d1571 100644 --- a/arch/blackfin/mach-common/clocks-init.c +++ b/arch/blackfin/mach-common/clocks-init.c @@ -15,10 +15,121 @@ #include <asm/mem_init.h> #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)) + +#define CONFIG_BFIN_DCLK (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_DCLK_DIV) / 1000000) +#if ((CONFIG_BFIN_DCLK != 125) && \ + (CONFIG_BFIN_DCLK != 133) && (CONFIG_BFIN_DCLK != 150) && \ + (CONFIG_BFIN_DCLK != 166) && (CONFIG_BFIN_DCLK != 200) && \ + (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 \ (((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \ - (PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000)) + (PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000)) +#endif __attribute__((l1_text)) static void do_sync(void) @@ -33,6 +144,44 @@ 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; +#else size_t i; for (i = 0; i < MAX_DMA_CHANNELS; ++i) { struct dma_register *dma = dma_io_base_addr[i]; @@ -91,6 +240,8 @@ void init_clocks(void) bfin_write_EBIU_DDRQUE(CONFIG_MEM_EBIU_DDRQUE); #endif #endif +#endif do_sync(); bfin_read16(0); + } diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index 2e6eefd812f4..6e87dc13f6bf 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -10,6 +10,7 @@ #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> @@ -17,6 +18,7 @@ #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[] = { @@ -67,12 +69,22 @@ static void __init bfin_init_tables(unsigned long cclk, unsigned long sclk) #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++, csel++) { bfin_freq_table[index].frequency = cclk >> index; +#ifndef CONFIG_BF60x dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */ dpm_state_table[index].tscale = (TIME_SCALE / (1 << csel)) - 1; +#else + dpm_state_table[index].csel = csel; + dpm_state_table[index].tscale = TIME_SCALE >> index; +#endif pr_debug("cpufreq: freq:%d csel:0x%x tscale:%d\n", bfin_freq_table[index].frequency, @@ -99,14 +111,34 @@ static unsigned int bfin_getfreq_khz(unsigned int cpu) 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) { - unsigned int index, plldiv, cpu; +#ifndef CONFIG_BF60x + unsigned int plldiv; +#endif + unsigned int index, cpu; unsigned long flags, 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; @@ -134,9 +166,17 @@ static int bfin_target(struct cpufreq_policy *poli, cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); if (cpu == CPUFREQ_CPU) { flags = hard_local_irq_save(); +#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) { + pr_debug("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(); @@ -161,7 +201,7 @@ static int bfin_target(struct cpufreq_policy *poli, } pr_debug("cpufreq: done\n"); - return 0; + return ret; } static int bfin_verify_speed(struct cpufreq_policy *policy) @@ -169,7 +209,7 @@ static int bfin_verify_speed(struct cpufreq_policy *policy) return cpufreq_frequency_table_verify(policy, bfin_freq_table); } -static int __init __bfin_cpu_init(struct cpufreq_policy *policy) +static int __bfin_cpu_init(struct cpufreq_policy *policy) { unsigned long cclk, sclk; diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S index 1c534d298de4..de99f3aac2c5 100644 --- a/arch/blackfin/mach-common/dpmc_modes.S +++ b/arch/blackfin/mach-common/dpmc_modes.S @@ -10,7 +10,6 @@ #include <asm/dpmc.h> .section .l1.text - ENTRY(_sleep_mode) [--SP] = (R7:4, P5:3); [--SP] = RETS; @@ -43,6 +42,9 @@ ENTRY(_sleep_mode) BITCLR (R7, 5); w[p0] = R7.L; IDLE; + + bfin_init_pm_bench_cycles; + call _test_pll_locked; RETS = [SP++]; @@ -58,12 +60,13 @@ ENDPROC(_sleep_mode) * * We accept just one argument -- the value to write to VR_CTL. */ + ENTRY(_hibernate_mode) /* Save/setup the regs we need early for minor pipeline optimization */ R4 = R0; + P3.H = hi(VR_CTL); P3.L = lo(VR_CTL); - /* Disable all wakeup sources */ R0 = IWR_DISABLE_ALL; R1 = IWR_DISABLE_ALL; @@ -74,6 +77,9 @@ ENTRY(_hibernate_mode) /* Finally, we climb into our cave to hibernate */ W[P3] = R4.L; + + bfin_init_pm_bench_cycles; + CLI R2; IDLE; .Lforever: @@ -158,6 +164,8 @@ ENTRY(_sleep_deeper) SSYNC; IDLE; + bfin_init_pm_bench_cycles; + call _test_pll_locked; P0.H = hi(PLL_DIV); @@ -276,327 +284,10 @@ ENTRY(_test_pll_locked) ENDPROC(_test_pll_locked) .section .text - -#define PM_REG0 R7 -#define PM_REG1 R6 -#define PM_REG2 R5 -#define PM_REG3 R4 -#define PM_REG4 R3 -#define PM_REG5 R2 -#define PM_REG6 R1 -#define PM_REG7 R0 -#define PM_REG8 P5 -#define PM_REG9 P4 -#define PM_REG10 P3 -#define PM_REG11 P2 -#define PM_REG12 P1 -#define PM_REG13 P0 - -#define PM_REGSET0 R7:7 -#define PM_REGSET1 R7:6 -#define PM_REGSET2 R7:5 -#define PM_REGSET3 R7:4 -#define PM_REGSET4 R7:3 -#define PM_REGSET5 R7:2 -#define PM_REGSET6 R7:1 -#define PM_REGSET7 R7:0 -#define PM_REGSET8 R7:0, P5:5 -#define PM_REGSET9 R7:0, P5:4 -#define PM_REGSET10 R7:0, P5:3 -#define PM_REGSET11 R7:0, P5:2 -#define PM_REGSET12 R7:0, P5:1 -#define PM_REGSET13 R7:0, P5:0 - -#define _PM_PUSH(n, x, w, base) PM_REG##n = w[FP + ((x) - (base))]; -#define _PM_POP(n, x, w, base) w[FP + ((x) - (base))] = PM_REG##n; -#define PM_PUSH_SYNC(n) [--sp] = (PM_REGSET##n); -#define PM_POP_SYNC(n) (PM_REGSET##n) = [sp++]; -#define PM_PUSH(n, x) PM_REG##n = [FP++]; -#define PM_POP(n, x) [FP--] = PM_REG##n; -#define PM_CORE_PUSH(n, x) _PM_PUSH(n, x, , COREMMR_BASE) -#define PM_CORE_POP(n, x) _PM_POP(n, x, , COREMMR_BASE) -#define PM_SYS_PUSH(n, x) _PM_PUSH(n, x, , SYSMMR_BASE) -#define PM_SYS_POP(n, x) _PM_POP(n, x, , SYSMMR_BASE) -#define PM_SYS_PUSH16(n, x) _PM_PUSH(n, x, w, SYSMMR_BASE) -#define PM_SYS_POP16(n, x) _PM_POP(n, x, w, SYSMMR_BASE) - ENTRY(_do_hibernate) - /* - * Save the core regs early so we can blow them away when - * saving/restoring MMR states - */ - [--sp] = (R7:0, P5:0); - [--sp] = fp; - [--sp] = usp; - - [--sp] = i0; - [--sp] = i1; - [--sp] = i2; - [--sp] = i3; - - [--sp] = m0; - [--sp] = m1; - [--sp] = m2; - [--sp] = m3; - - [--sp] = l0; - [--sp] = l1; - [--sp] = l2; - [--sp] = l3; - - [--sp] = b0; - [--sp] = b1; - [--sp] = b2; - [--sp] = b3; - [--sp] = a0.x; - [--sp] = a0.w; - [--sp] = a1.x; - [--sp] = a1.w; - - [--sp] = LC0; - [--sp] = LC1; - [--sp] = LT0; - [--sp] = LT1; - [--sp] = LB0; - [--sp] = LB1; - - /* We can't push RETI directly as that'll change IPEND[4] */ - r7 = RETI; - [--sp] = RETS; - [--sp] = ASTAT; - [--sp] = CYCLES; - [--sp] = CYCLES2; - [--sp] = SYSCFG; - [--sp] = RETX; - [--sp] = SEQSTAT; - [--sp] = r7; - - /* Save first func arg in M3 */ - M3 = R0; - - /* Save system MMRs */ - FP.H = hi(SYSMMR_BASE); - FP.L = lo(SYSMMR_BASE); - -#ifdef SIC_IMASK0 - PM_SYS_PUSH(0, SIC_IMASK0) - PM_SYS_PUSH(1, SIC_IMASK1) -# ifdef SIC_IMASK2 - PM_SYS_PUSH(2, SIC_IMASK2) -# endif -#else - PM_SYS_PUSH(0, SIC_IMASK) -#endif -#ifdef SIC_IAR0 - PM_SYS_PUSH(3, SIC_IAR0) - PM_SYS_PUSH(4, SIC_IAR1) - PM_SYS_PUSH(5, SIC_IAR2) -#endif -#ifdef SIC_IAR3 - PM_SYS_PUSH(6, SIC_IAR3) -#endif -#ifdef SIC_IAR4 - PM_SYS_PUSH(7, SIC_IAR4) - PM_SYS_PUSH(8, SIC_IAR5) - PM_SYS_PUSH(9, SIC_IAR6) -#endif -#ifdef SIC_IAR7 - PM_SYS_PUSH(10, SIC_IAR7) -#endif -#ifdef SIC_IAR8 - PM_SYS_PUSH(11, SIC_IAR8) - PM_SYS_PUSH(12, SIC_IAR9) - PM_SYS_PUSH(13, SIC_IAR10) -#endif - PM_PUSH_SYNC(13) -#ifdef SIC_IAR11 - PM_SYS_PUSH(0, SIC_IAR11) -#endif - -#ifdef SIC_IWR - PM_SYS_PUSH(1, SIC_IWR) -#endif -#ifdef SIC_IWR0 - PM_SYS_PUSH(1, SIC_IWR0) -#endif -#ifdef SIC_IWR1 - PM_SYS_PUSH(2, SIC_IWR1) -#endif -#ifdef SIC_IWR2 - PM_SYS_PUSH(3, SIC_IWR2) -#endif - -#ifdef PINT0_ASSIGN - PM_SYS_PUSH(4, PINT0_MASK_SET) - PM_SYS_PUSH(5, PINT1_MASK_SET) - PM_SYS_PUSH(6, PINT2_MASK_SET) - PM_SYS_PUSH(7, PINT3_MASK_SET) - PM_SYS_PUSH(8, PINT0_ASSIGN) - PM_SYS_PUSH(9, PINT1_ASSIGN) - PM_SYS_PUSH(10, PINT2_ASSIGN) - PM_SYS_PUSH(11, PINT3_ASSIGN) - PM_SYS_PUSH(12, PINT0_INVERT_SET) - PM_SYS_PUSH(13, PINT1_INVERT_SET) - PM_PUSH_SYNC(13) - PM_SYS_PUSH(0, PINT2_INVERT_SET) - PM_SYS_PUSH(1, PINT3_INVERT_SET) - PM_SYS_PUSH(2, PINT0_EDGE_SET) - PM_SYS_PUSH(3, PINT1_EDGE_SET) - PM_SYS_PUSH(4, PINT2_EDGE_SET) - PM_SYS_PUSH(5, PINT3_EDGE_SET) -#endif - - PM_SYS_PUSH16(6, SYSCR) - - PM_SYS_PUSH16(7, EBIU_AMGCTL) - PM_SYS_PUSH(8, EBIU_AMBCTL0) - PM_SYS_PUSH(9, EBIU_AMBCTL1) -#ifdef EBIU_FCTL - PM_SYS_PUSH(10, EBIU_MBSCTL) - PM_SYS_PUSH(11, EBIU_MODE) - PM_SYS_PUSH(12, EBIU_FCTL) - PM_PUSH_SYNC(12) -#else - PM_PUSH_SYNC(9) -#endif - - /* Save Core MMRs */ - I0.H = hi(COREMMR_BASE); - I0.L = lo(COREMMR_BASE); - I1 = I0; - I2 = I0; - I3 = I0; - B0 = I0; - B1 = I0; - B2 = I0; - B3 = I0; - I1.L = lo(DCPLB_ADDR0); - I2.L = lo(DCPLB_DATA0); - I3.L = lo(ICPLB_ADDR0); - B0.L = lo(ICPLB_DATA0); - B1.L = lo(EVT2); - B2.L = lo(IMASK); - B3.L = lo(TCNTL); - - /* DCPLB Addr */ - FP = I1; - PM_PUSH(0, DCPLB_ADDR0) - PM_PUSH(1, DCPLB_ADDR1) - PM_PUSH(2, DCPLB_ADDR2) - PM_PUSH(3, DCPLB_ADDR3) - PM_PUSH(4, DCPLB_ADDR4) - PM_PUSH(5, DCPLB_ADDR5) - PM_PUSH(6, DCPLB_ADDR6) - PM_PUSH(7, DCPLB_ADDR7) - PM_PUSH(8, DCPLB_ADDR8) - PM_PUSH(9, DCPLB_ADDR9) - PM_PUSH(10, DCPLB_ADDR10) - PM_PUSH(11, DCPLB_ADDR11) - PM_PUSH(12, DCPLB_ADDR12) - PM_PUSH(13, DCPLB_ADDR13) - PM_PUSH_SYNC(13) - PM_PUSH(0, DCPLB_ADDR14) - PM_PUSH(1, DCPLB_ADDR15) - - /* DCPLB Data */ - FP = I2; - PM_PUSH(2, DCPLB_DATA0) - PM_PUSH(3, DCPLB_DATA1) - PM_PUSH(4, DCPLB_DATA2) - PM_PUSH(5, DCPLB_DATA3) - PM_PUSH(6, DCPLB_DATA4) - PM_PUSH(7, DCPLB_DATA5) - PM_PUSH(8, DCPLB_DATA6) - PM_PUSH(9, DCPLB_DATA7) - PM_PUSH(10, DCPLB_DATA8) - PM_PUSH(11, DCPLB_DATA9) - PM_PUSH(12, DCPLB_DATA10) - PM_PUSH(13, DCPLB_DATA11) - PM_PUSH_SYNC(13) - PM_PUSH(0, DCPLB_DATA12) - PM_PUSH(1, DCPLB_DATA13) - PM_PUSH(2, DCPLB_DATA14) - PM_PUSH(3, DCPLB_DATA15) - - /* ICPLB Addr */ - FP = I3; - PM_PUSH(4, ICPLB_ADDR0) - PM_PUSH(5, ICPLB_ADDR1) - PM_PUSH(6, ICPLB_ADDR2) - PM_PUSH(7, ICPLB_ADDR3) - PM_PUSH(8, ICPLB_ADDR4) - PM_PUSH(9, ICPLB_ADDR5) - PM_PUSH(10, ICPLB_ADDR6) - PM_PUSH(11, ICPLB_ADDR7) - PM_PUSH(12, ICPLB_ADDR8) - PM_PUSH(13, ICPLB_ADDR9) - PM_PUSH_SYNC(13) - PM_PUSH(0, ICPLB_ADDR10) - PM_PUSH(1, ICPLB_ADDR11) - PM_PUSH(2, ICPLB_ADDR12) - PM_PUSH(3, ICPLB_ADDR13) - PM_PUSH(4, ICPLB_ADDR14) - PM_PUSH(5, ICPLB_ADDR15) - - /* ICPLB Data */ - FP = B0; - PM_PUSH(6, ICPLB_DATA0) - PM_PUSH(7, ICPLB_DATA1) - PM_PUSH(8, ICPLB_DATA2) - PM_PUSH(9, ICPLB_DATA3) - PM_PUSH(10, ICPLB_DATA4) - PM_PUSH(11, ICPLB_DATA5) - PM_PUSH(12, ICPLB_DATA6) - PM_PUSH(13, ICPLB_DATA7) - PM_PUSH_SYNC(13) - PM_PUSH(0, ICPLB_DATA8) - PM_PUSH(1, ICPLB_DATA9) - PM_PUSH(2, ICPLB_DATA10) - PM_PUSH(3, ICPLB_DATA11) - PM_PUSH(4, ICPLB_DATA12) - PM_PUSH(5, ICPLB_DATA13) - PM_PUSH(6, ICPLB_DATA14) - PM_PUSH(7, ICPLB_DATA15) - - /* Event Vectors */ - FP = B1; - PM_PUSH(8, EVT2) - PM_PUSH(9, EVT3) - FP += 4; /* EVT4 */ - PM_PUSH(10, EVT5) - PM_PUSH(11, EVT6) - PM_PUSH(12, EVT7) - PM_PUSH(13, EVT8) - PM_PUSH_SYNC(13) - PM_PUSH(0, EVT9) - PM_PUSH(1, EVT10) - PM_PUSH(2, EVT11) - PM_PUSH(3, EVT12) - PM_PUSH(4, EVT13) - PM_PUSH(5, EVT14) - PM_PUSH(6, EVT15) - - /* CEC */ - FP = B2; - PM_PUSH(7, IMASK) - FP += 4; /* IPEND */ - PM_PUSH(8, ILAT) - PM_PUSH(9, IPRIO) - - /* Core Timer */ - FP = B3; - PM_PUSH(10, TCNTL) - PM_PUSH(11, TPERIOD) - PM_PUSH(12, TSCALE) - PM_PUSH(13, TCOUNT) - PM_PUSH_SYNC(13) - - /* Misc non-contiguous registers */ - FP = I0; - PM_CORE_PUSH(0, DMEM_CONTROL); - PM_CORE_PUSH(1, IMEM_CONTROL); - PM_CORE_PUSH(2, TBUFCTL); - PM_PUSH_SYNC(2) + bfin_cpu_reg_save; + bfin_sys_mmr_save; + bfin_core_mmr_save; /* Setup args to hibernate mode early for pipeline optimization */ R0 = M3; @@ -618,274 +309,9 @@ ENTRY(_do_hibernate) .Lpm_resume_here: - /* Restore Core MMRs */ - I0.H = hi(COREMMR_BASE); - I0.L = lo(COREMMR_BASE); - I1 = I0; - I2 = I0; - I3 = I0; - B0 = I0; - B1 = I0; - B2 = I0; - B3 = I0; - I1.L = lo(DCPLB_ADDR15); - I2.L = lo(DCPLB_DATA15); - I3.L = lo(ICPLB_ADDR15); - B0.L = lo(ICPLB_DATA15); - B1.L = lo(EVT15); - B2.L = lo(IPRIO); - B3.L = lo(TCOUNT); - - /* Misc non-contiguous registers */ - FP = I0; - PM_POP_SYNC(2) - PM_CORE_POP(2, TBUFCTL) - PM_CORE_POP(1, IMEM_CONTROL) - PM_CORE_POP(0, DMEM_CONTROL) - - /* Core Timer */ - PM_POP_SYNC(13) - FP = B3; - PM_POP(13, TCOUNT) - PM_POP(12, TSCALE) - PM_POP(11, TPERIOD) - PM_POP(10, TCNTL) - - /* CEC */ - FP = B2; - PM_POP(9, IPRIO) - PM_POP(8, ILAT) - FP += -4; /* IPEND */ - PM_POP(7, IMASK) - - /* Event Vectors */ - FP = B1; - PM_POP(6, EVT15) - PM_POP(5, EVT14) - PM_POP(4, EVT13) - PM_POP(3, EVT12) - PM_POP(2, EVT11) - PM_POP(1, EVT10) - PM_POP(0, EVT9) - PM_POP_SYNC(13) - PM_POP(13, EVT8) - PM_POP(12, EVT7) - PM_POP(11, EVT6) - PM_POP(10, EVT5) - FP += -4; /* EVT4 */ - PM_POP(9, EVT3) - PM_POP(8, EVT2) - - /* ICPLB Data */ - FP = B0; - PM_POP(7, ICPLB_DATA15) - PM_POP(6, ICPLB_DATA14) - PM_POP(5, ICPLB_DATA13) - PM_POP(4, ICPLB_DATA12) - PM_POP(3, ICPLB_DATA11) - PM_POP(2, ICPLB_DATA10) - PM_POP(1, ICPLB_DATA9) - PM_POP(0, ICPLB_DATA8) - PM_POP_SYNC(13) - PM_POP(13, ICPLB_DATA7) - PM_POP(12, ICPLB_DATA6) - PM_POP(11, ICPLB_DATA5) - PM_POP(10, ICPLB_DATA4) - PM_POP(9, ICPLB_DATA3) - PM_POP(8, ICPLB_DATA2) - PM_POP(7, ICPLB_DATA1) - PM_POP(6, ICPLB_DATA0) - - /* ICPLB Addr */ - FP = I3; - PM_POP(5, ICPLB_ADDR15) - PM_POP(4, ICPLB_ADDR14) - PM_POP(3, ICPLB_ADDR13) - PM_POP(2, ICPLB_ADDR12) - PM_POP(1, ICPLB_ADDR11) - PM_POP(0, ICPLB_ADDR10) - PM_POP_SYNC(13) - PM_POP(13, ICPLB_ADDR9) - PM_POP(12, ICPLB_ADDR8) - PM_POP(11, ICPLB_ADDR7) - PM_POP(10, ICPLB_ADDR6) - PM_POP(9, ICPLB_ADDR5) - PM_POP(8, ICPLB_ADDR4) - PM_POP(7, ICPLB_ADDR3) - PM_POP(6, ICPLB_ADDR2) - PM_POP(5, ICPLB_ADDR1) - PM_POP(4, ICPLB_ADDR0) - - /* DCPLB Data */ - FP = I2; - PM_POP(3, DCPLB_DATA15) - PM_POP(2, DCPLB_DATA14) - PM_POP(1, DCPLB_DATA13) - PM_POP(0, DCPLB_DATA12) - PM_POP_SYNC(13) - PM_POP(13, DCPLB_DATA11) - PM_POP(12, DCPLB_DATA10) - PM_POP(11, DCPLB_DATA9) - PM_POP(10, DCPLB_DATA8) - PM_POP(9, DCPLB_DATA7) - PM_POP(8, DCPLB_DATA6) - PM_POP(7, DCPLB_DATA5) - PM_POP(6, DCPLB_DATA4) - PM_POP(5, DCPLB_DATA3) - PM_POP(4, DCPLB_DATA2) - PM_POP(3, DCPLB_DATA1) - PM_POP(2, DCPLB_DATA0) - - /* DCPLB Addr */ - FP = I1; - PM_POP(1, DCPLB_ADDR15) - PM_POP(0, DCPLB_ADDR14) - PM_POP_SYNC(13) - PM_POP(13, DCPLB_ADDR13) - PM_POP(12, DCPLB_ADDR12) - PM_POP(11, DCPLB_ADDR11) - PM_POP(10, DCPLB_ADDR10) - PM_POP(9, DCPLB_ADDR9) - PM_POP(8, DCPLB_ADDR8) - PM_POP(7, DCPLB_ADDR7) - PM_POP(6, DCPLB_ADDR6) - PM_POP(5, DCPLB_ADDR5) - PM_POP(4, DCPLB_ADDR4) - PM_POP(3, DCPLB_ADDR3) - PM_POP(2, DCPLB_ADDR2) - PM_POP(1, DCPLB_ADDR1) - PM_POP(0, DCPLB_ADDR0) - - /* Restore System MMRs */ - FP.H = hi(SYSMMR_BASE); - FP.L = lo(SYSMMR_BASE); - -#ifdef EBIU_FCTL - PM_POP_SYNC(12) - PM_SYS_POP(12, EBIU_FCTL) - PM_SYS_POP(11, EBIU_MODE) - PM_SYS_POP(10, EBIU_MBSCTL) -#else - PM_POP_SYNC(9) -#endif - PM_SYS_POP(9, EBIU_AMBCTL1) - PM_SYS_POP(8, EBIU_AMBCTL0) - PM_SYS_POP16(7, EBIU_AMGCTL) - - PM_SYS_POP16(6, SYSCR) - -#ifdef PINT0_ASSIGN - PM_SYS_POP(5, PINT3_EDGE_SET) - PM_SYS_POP(4, PINT2_EDGE_SET) - PM_SYS_POP(3, PINT1_EDGE_SET) - PM_SYS_POP(2, PINT0_EDGE_SET) - PM_SYS_POP(1, PINT3_INVERT_SET) - PM_SYS_POP(0, PINT2_INVERT_SET) - PM_POP_SYNC(13) - PM_SYS_POP(13, PINT1_INVERT_SET) - PM_SYS_POP(12, PINT0_INVERT_SET) - PM_SYS_POP(11, PINT3_ASSIGN) - PM_SYS_POP(10, PINT2_ASSIGN) - PM_SYS_POP(9, PINT1_ASSIGN) - PM_SYS_POP(8, PINT0_ASSIGN) - PM_SYS_POP(7, PINT3_MASK_SET) - PM_SYS_POP(6, PINT2_MASK_SET) - PM_SYS_POP(5, PINT1_MASK_SET) - PM_SYS_POP(4, PINT0_MASK_SET) -#endif - -#ifdef SIC_IWR2 - PM_SYS_POP(3, SIC_IWR2) -#endif -#ifdef SIC_IWR1 - PM_SYS_POP(2, SIC_IWR1) -#endif -#ifdef SIC_IWR0 - PM_SYS_POP(1, SIC_IWR0) -#endif -#ifdef SIC_IWR - PM_SYS_POP(1, SIC_IWR) -#endif - -#ifdef SIC_IAR11 - PM_SYS_POP(0, SIC_IAR11) -#endif - PM_POP_SYNC(13) -#ifdef SIC_IAR8 - PM_SYS_POP(13, SIC_IAR10) - PM_SYS_POP(12, SIC_IAR9) - PM_SYS_POP(11, SIC_IAR8) -#endif -#ifdef SIC_IAR7 - PM_SYS_POP(10, SIC_IAR7) -#endif -#ifdef SIC_IAR6 - PM_SYS_POP(9, SIC_IAR6) - PM_SYS_POP(8, SIC_IAR5) - PM_SYS_POP(7, SIC_IAR4) -#endif -#ifdef SIC_IAR3 - PM_SYS_POP(6, SIC_IAR3) -#endif -#ifdef SIC_IAR0 - PM_SYS_POP(5, SIC_IAR2) - PM_SYS_POP(4, SIC_IAR1) - PM_SYS_POP(3, SIC_IAR0) -#endif -#ifdef SIC_IMASK0 -# ifdef SIC_IMASK2 - PM_SYS_POP(2, SIC_IMASK2) -# endif - PM_SYS_POP(1, SIC_IMASK1) - PM_SYS_POP(0, SIC_IMASK0) -#else - PM_SYS_POP(0, SIC_IMASK) -#endif - - /* Restore Core Registers */ - RETI = [sp++]; - SEQSTAT = [sp++]; - RETX = [sp++]; - SYSCFG = [sp++]; - CYCLES2 = [sp++]; - CYCLES = [sp++]; - ASTAT = [sp++]; - RETS = [sp++]; - - LB1 = [sp++]; - LB0 = [sp++]; - LT1 = [sp++]; - LT0 = [sp++]; - LC1 = [sp++]; - LC0 = [sp++]; - - a1.w = [sp++]; - a1.x = [sp++]; - a0.w = [sp++]; - a0.x = [sp++]; - b3 = [sp++]; - b2 = [sp++]; - b1 = [sp++]; - b0 = [sp++]; - - l3 = [sp++]; - l2 = [sp++]; - l1 = [sp++]; - l0 = [sp++]; - - m3 = [sp++]; - m2 = [sp++]; - m1 = [sp++]; - m0 = [sp++]; - - i3 = [sp++]; - i2 = [sp++]; - i1 = [sp++]; - i0 = [sp++]; - - usp = [sp++]; - fp = [sp++]; - (R7:0, P5:0) = [sp++]; + bfin_core_mmr_restore; + bfin_sys_mmr_restore; + bfin_cpu_reg_restore; [--sp] = RETI; /* Clear Global Interrupt Disable */ SP += 4; diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 4698a9800522..80aa2535e2c9 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1141,7 +1141,8 @@ ENTRY(_schedule_and_signal_from_int) sti r0; /* finish the userspace "atomic" functions for it */ - r1 = FIXED_CODE_END; + r1.l = lo(FIXED_CODE_END); + r1.h = hi(FIXED_CODE_END); r2 = [sp + PT_PC]; cc = r1 <= r2; if cc jump .Lresume_userspace (bp); @@ -1376,7 +1377,7 @@ END(_ex_table) ENTRY(_sys_call_table) .long _sys_restart_syscall /* 0 */ .long _sys_exit - .long _sys_fork + .long _sys_ni_syscall /* fork */ .long _sys_read .long _sys_write .long _sys_open /* 5 */ diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 8b4d98854403..31515f0146f9 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -210,14 +210,12 @@ ENDPROC(__start) ENTRY(_real_start) /* Enable nested interrupts */ [--sp] = reti; - /* watchdog off for now */ p0.l = lo(WDOG_CTL); p0.h = hi(WDOG_CTL); r0 = 0xAD6(z); w[p0] = r0; ssync; - /* Pass the u-boot arguments to the global value command line */ R0 = R7; call _cmdline_init; diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 332dace6af34..2729cba715b0 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -16,6 +16,8 @@ #include <linux/seq_file.h> #include <linux/irq.h> #include <linux/sched.h> +#include <linux/syscore_ops.h> +#include <asm/delay.h> #ifdef CONFIG_IPIPE #include <linux/ipipe.h> #endif @@ -25,7 +27,11 @@ #include <asm/irq_handler.h> #include <asm/dpmc.h> -#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) +#ifndef CONFIG_BF60x +# define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) +#else +# define SIC_SYSIRQ(irq) ((irq) - IVG15) +#endif /* * NOTES: @@ -50,6 +56,7 @@ unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */ unsigned vr_wakeup; #endif +#ifndef CONFIG_BF60x static struct ivgx { /* irq number for request_irq, available in mach-bf5xx/irq.h */ unsigned int irqno; @@ -78,7 +85,8 @@ static void __init search_IAR(void) for (irqN = 0; irqN < NR_PERI_INTS; irqN += 4) { int irqn; - u32 iar = bfin_read32((unsigned long *)SIC_IAR0 + + u32 iar = + bfin_read32((unsigned long *)SIC_IAR0 + #if defined(CONFIG_BF51x) || defined(CONFIG_BF52x) || \ defined(CONFIG_BF538) || defined(CONFIG_BF539) ((irqN % 32) >> 3) + ((irqN / 32) * ((SIC_IAR4 - SIC_IAR0) / 4)) @@ -86,7 +94,6 @@ static void __init search_IAR(void) (irqN >> 3) #endif ); - for (irqn = irqN; irqn < irqN + 4; ++irqn) { int iar_shift = (irqn & 7) * 4; if (ivg == (0xf & (iar >> iar_shift))) { @@ -99,11 +106,11 @@ static void __init search_IAR(void) } } } +#endif /* * This is for core internal IRQs */ - void bfin_ack_noop(struct irq_data *d) { /* Dummy function. */ @@ -136,21 +143,21 @@ 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 #ifdef SIC_IMASK0 unsigned mask_bank = SIC_SYSIRQ(irq) / 32; unsigned mask_bit = SIC_SYSIRQ(irq) % 32; bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & - ~(1 << mask_bit)); -# ifdef CONFIG_SMP + ~(1 << mask_bit)); +# if defined(CONFIG_SMP) || defined(CONFIG_ICC) bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) & - ~(1 << mask_bit)); + ~(1 << mask_bit)); # endif #else bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & - ~(1 << SIC_SYSIRQ(irq))); + ~(1 << SIC_SYSIRQ(irq))); +#endif /* end of SIC_IMASK0 */ #endif - hard_local_irq_restore(flags); } @@ -160,7 +167,7 @@ static void bfin_internal_mask_irq_chip(struct irq_data *d) } #ifdef CONFIG_SMP -static void bfin_internal_unmask_irq_affinity(unsigned int irq, +void bfin_internal_unmask_irq_affinity(unsigned int irq, const struct cpumask *affinity) #else void bfin_internal_unmask_irq(unsigned int irq) @@ -168,6 +175,7 @@ void bfin_internal_unmask_irq(unsigned int irq) { unsigned long flags = hard_local_irq_save(); +#ifndef CONFIG_BF60x #ifdef SIC_IMASK0 unsigned mask_bank = SIC_SYSIRQ(irq) / 32; unsigned mask_bit = SIC_SYSIRQ(irq) % 32; @@ -175,22 +183,239 @@ void bfin_internal_unmask_irq(unsigned int irq) if (cpumask_test_cpu(0, affinity)) # endif bfin_write_SIC_IMASK(mask_bank, - bfin_read_SIC_IMASK(mask_bank) | - (1 << mask_bit)); + bfin_read_SIC_IMASK(mask_bank) | + (1 << mask_bit)); # ifdef CONFIG_SMP if (cpumask_test_cpu(1, affinity)) bfin_write_SICB_IMASK(mask_bank, - bfin_read_SICB_IMASK(mask_bank) | - (1 << mask_bit)); + bfin_read_SICB_IMASK(mask_bank) | + (1 << mask_bit)); # endif #else bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | - (1 << SIC_SYSIRQ(irq))); + (1 << SIC_SYSIRQ(irq))); +#endif #endif + hard_local_irq_restore(flags); +} + +#ifdef CONFIG_BF60x +static void bfin_sec_preflow_handler(struct irq_data *d) +{ + unsigned long flags = hard_local_irq_save(); + unsigned int sid = SIC_SYSIRQ(d->irq); + + bfin_write_SEC_SCI(0, SEC_CSID, sid); + + hard_local_irq_restore(flags); +} + +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); + + bfin_write_SEC_SCI(0, SEC_CSID, sid); hard_local_irq_restore(flags); } +static void bfin_sec_unmask_irq(struct irq_data *d) +{ + unsigned long flags = hard_local_irq_save(); + unsigned int sid = SIC_SYSIRQ(d->irq); + + bfin_write32(SEC_END, sid); + + hard_local_irq_restore(flags); +} + +static void bfin_sec_enable_ssi(unsigned int sid) +{ + unsigned long flags = hard_local_irq_save(); + uint32_t reg_sctl = bfin_read_SEC_SCTL(sid); + + reg_sctl |= SEC_SCTL_SRC_EN; + bfin_write_SEC_SCTL(sid, reg_sctl); + + hard_local_irq_restore(flags); +} + +static void bfin_sec_disable_ssi(unsigned int sid) +{ + unsigned long flags = hard_local_irq_save(); + uint32_t reg_sctl = bfin_read_SEC_SCTL(sid); + + reg_sctl &= ((uint32_t)~SEC_SCTL_SRC_EN); + bfin_write_SEC_SCTL(sid, reg_sctl); + + hard_local_irq_restore(flags); +} + +static void bfin_sec_set_ssi_coreid(unsigned int sid, unsigned int coreid) +{ + unsigned long flags = hard_local_irq_save(); + uint32_t reg_sctl = bfin_read_SEC_SCTL(sid); + + reg_sctl &= ((uint32_t)~SEC_SCTL_CTG); + bfin_write_SEC_SCTL(sid, reg_sctl | ((coreid << 20) & SEC_SCTL_CTG)); + + hard_local_irq_restore(flags); +} + +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)) + reg_sctl |= SEC_SCTL_FAULT_EN; + else + reg_sctl |= SEC_SCTL_INT_EN; + bfin_write_SEC_SCTL(sid, reg_sctl); + + hard_local_irq_restore(flags); +} + +static void bfin_sec_disable_sci(unsigned int sid) +{ + unsigned long flags = hard_local_irq_save(); + uint32_t reg_sctl = bfin_read_SEC_SCTL(sid); + + reg_sctl &= ((uint32_t)~SEC_SCTL_INT_EN); + bfin_write_SEC_SCTL(sid, reg_sctl); + + hard_local_irq_restore(flags); +} + +static void bfin_sec_enable(struct irq_data *d) +{ + unsigned long flags = hard_local_irq_save(); + unsigned int sid = SIC_SYSIRQ(d->irq); + + bfin_sec_enable_sci(sid); + bfin_sec_enable_ssi(sid); + + hard_local_irq_restore(flags); +} + +static void bfin_sec_disable(struct irq_data *d) +{ + unsigned long flags = hard_local_irq_save(); + unsigned int sid = SIC_SYSIRQ(d->irq); + + bfin_sec_disable_sci(sid); + bfin_sec_disable_ssi(sid); + + hard_local_irq_restore(flags); +} + +static void bfin_sec_raise_irq(unsigned int sid) +{ + unsigned long flags = hard_local_irq_save(); + + bfin_write32(SEC_RAISE, sid); + + hard_local_irq_restore(flags); +} + +static void init_software_driven_irq(void) +{ + bfin_sec_set_ssi_coreid(34, 0); + bfin_sec_set_ssi_coreid(35, 1); + bfin_sec_set_ssi_coreid(36, 0); + bfin_sec_set_ssi_coreid(37, 1); +} + +void bfin_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); +} + +void handle_sec_sfi_fault(uint32_t gstat) +{ + +} + +void handle_sec_sci_fault(uint32_t gstat) +{ + uint32_t core_id; + uint32_t cstat; + + core_id = gstat & SEC_GSTAT_SCI; + cstat = bfin_read_SEC_SCI(core_id, SEC_CSTAT); + if (cstat & SEC_CSTAT_ERR) { + switch (cstat & SEC_CSTAT_ERRC) { + case SEC_CSTAT_ACKERR: + printk(KERN_DEBUG "sec ack err\n"); + break; + default: + printk(KERN_DEBUG "sec sci unknow err\n"); + } + } + +} + +void handle_sec_ssi_fault(uint32_t gstat) +{ + uint32_t sid; + uint32_t sstat; + + sid = gstat & SEC_GSTAT_SID; + sstat = bfin_read_SEC_SSTAT(sid); + +} + +void handle_sec_fault(unsigned int irq, struct irq_desc *desc) +{ + 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) { + case 0: + handle_sec_sfi_fault(sec_gstat); + break; + case SEC_GSTAT_SCIERR: + handle_sec_sci_fault(sec_gstat); + break; + case SEC_GSTAT_SSIERR: + handle_sec_ssi_fault(sec_gstat); + break; + } + + + } + + raw_spin_unlock(&desc->lock); +} + +static int sec_suspend(void) +{ + return 0; +} + +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); +} + +static struct syscore_ops sec_pm_syscore_ops = { + .suspend = sec_suspend, + .resume = sec_resume, +}; + +#endif + #ifdef CONFIG_SMP static void bfin_internal_unmask_irq_chip(struct irq_data *d) { @@ -212,7 +437,7 @@ static void bfin_internal_unmask_irq_chip(struct irq_data *d) } #endif -#ifdef CONFIG_PM +#if defined(CONFIG_PM) && !defined(CONFIG_BF60x) int bfin_internal_set_wake(unsigned int irq, unsigned int state) { u32 bank, bit, wakeup = 0; @@ -271,22 +496,20 @@ 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) # define bfin_internal_set_wake_chip NULL #endif static struct irq_chip bfin_core_irqchip = { .name = "CORE", - .irq_ack = bfin_ack_noop, .irq_mask = bfin_core_mask_irq, .irq_unmask = bfin_core_unmask_irq, }; static struct irq_chip bfin_internal_irqchip = { .name = "INTN", - .irq_ack = bfin_ack_noop, .irq_mask = bfin_internal_mask_irq_chip, .irq_unmask = bfin_internal_unmask_irq_chip, - .irq_mask_ack = bfin_internal_mask_irq_chip, .irq_disable = bfin_internal_mask_irq_chip, .irq_enable = bfin_internal_unmask_irq_chip, #ifdef CONFIG_SMP @@ -295,6 +518,18 @@ static struct irq_chip bfin_internal_irqchip = { .irq_set_wake = bfin_internal_set_wake_chip, }; +#ifdef CONFIG_BF60x +static struct irq_chip bfin_sec_irqchip = { + .name = "SEC", + .irq_mask_ack = bfin_sec_mask_ack_irq, + .irq_mask = bfin_sec_mask_ack_irq, + .irq_unmask = bfin_sec_unmask_irq, + .irq_eoi = bfin_sec_unmask_irq, + .irq_disable = bfin_sec_disable, + .irq_enable = bfin_sec_enable, +}; +#endif + void bfin_handle_irq(unsigned irq) { #ifdef CONFIG_IPIPE @@ -396,8 +631,6 @@ int bfin_mac_status_set_wake(struct irq_data *d, unsigned int state) static struct irq_chip bfin_mac_status_irqchip = { .name = "MACST", - .irq_ack = bfin_ack_noop, - .irq_mask_ack = bfin_mac_status_mask_irq, .irq_mask = bfin_mac_status_mask_irq, .irq_unmask = bfin_mac_status_unmask_irq, .irq_set_wake = bfin_mac_status_set_wake, @@ -421,15 +654,15 @@ void bfin_demux_mac_status_irq(unsigned int int_err_irq, } else { bfin_mac_status_ack_irq(irq); pr_debug("IRQ %d:" - " MASKED MAC ERROR INTERRUPT ASSERTED\n", - irq); + " MASKED MAC ERROR INTERRUPT ASSERTED\n", + irq); } } else printk(KERN_ERR - "%s : %s : LINE %d :\nIRQ ?: MAC ERROR" - " INTERRUPT ASSERTED BUT NO SOURCE FOUND" - "(EMAC_SYSTAT=0x%X)\n", - __func__, __FILE__, __LINE__, status); + "%s : %s : LINE %d :\nIRQ ?: MAC ERROR" + " INTERRUPT ASSERTED BUT NO SOURCE FOUND" + "(EMAC_SYSTAT=0x%X)\n", + __func__, __FILE__, __LINE__, status); } #endif @@ -583,7 +816,7 @@ static void bfin_demux_gpio_block(unsigned int irq) } void bfin_demux_gpio_irq(unsigned int inta_irq, - struct irq_desc *desc) + struct irq_desc *desc) { unsigned int irq; @@ -635,9 +868,15 @@ void bfin_demux_gpio_irq(unsigned int inta_irq, #else +# ifndef CONFIG_BF60x #define NR_PINT_SYS_IRQS 4 -#define NR_PINT_BITS 32 #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 #define PINT_2_BANK(x) ((x) >> 5) @@ -652,8 +891,13 @@ static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = { (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 }; +#ifndef CONFIG_BF60x inline unsigned int get_irq_base(u32 bank, u8 bmap) { unsigned int irq_base; @@ -666,6 +910,16 @@ inline unsigned int get_irq_base(u32 bank, u8 bmap) 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; + + return irq_base; +} +#endif /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ void init_pint_lut(void) @@ -854,6 +1108,14 @@ static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) 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; } @@ -867,10 +1129,21 @@ static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) #endif void bfin_demux_gpio_irq(unsigned int inta_irq, - struct irq_desc *desc) + 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: @@ -885,6 +1158,14 @@ void bfin_demux_gpio_irq(unsigned int inta_irq, case IRQ_PINT1: bank = 1; break; +#ifdef CONFIG_BF60x + case IRQ_PINT4: + bank = 4; + break; + case IRQ_PINT5: + bank = 5; + break; +#endif default: return; } @@ -893,15 +1174,23 @@ void bfin_demux_gpio_irq(unsigned int inta_irq, 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 @@ -951,6 +1240,7 @@ 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); @@ -958,13 +1248,16 @@ int __init init_arch_irq(void) # ifdef SIC_IMASK2 bfin_write_SIC_IMASK2(SIC_UNMASK_ALL); # endif -# ifdef CONFIG_SMP +# if defined(CONFIG_SMP) || defined(CONFIG_ICC) bfin_write_SICB_IMASK0(SIC_UNMASK_ALL); bfin_write_SICB_IMASK1(SIC_UNMASK_ALL); # endif #else bfin_write_SIC_IMASK(SIC_UNMASK_ALL); #endif +#else /* CONFIG_BF60x */ + bfin_write_SEC_GCTL(SEC_GCTL_RESET); +#endif local_irq_disable(); @@ -974,6 +1267,10 @@ 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(); @@ -986,6 +1283,7 @@ 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: @@ -1015,12 +1313,13 @@ int __init init_arch_irq(void) bfin_demux_mac_status_irq); break; #endif -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_ICC) case IRQ_SUPPLE_0: case IRQ_SUPPLE_1: irq_set_handler(irq, handle_percpu_irq); break; #endif +#endif #ifdef CONFIG_TICKSOURCE_CORETMR case IRQ_CORETMR: @@ -1050,7 +1349,8 @@ int __init init_arch_irq(void) init_mach_irq(); -#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +#ifndef CONFIG_BF60x +#if (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) && !defined(CONFIG_BF60x) for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++) irq_set_chip_and_handler(irq, &bfin_mac_status_irqchip, handle_level_irq); @@ -1060,7 +1360,28 @@ 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(); @@ -1072,14 +1393,17 @@ 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(); /* 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; + IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | + IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; + + bfin_sti(bfin_irq_flags); /* This implicitly covers ANOMALY_05000171 * Boot-ROM code modifies SICA_IWRx wakeup registers @@ -1103,7 +1427,23 @@ 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; } @@ -1112,13 +1452,14 @@ __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 @@ -1147,6 +1488,10 @@ static int vec_to_irq(int vec) #endif return ivg->irqno; } +#else + /* for bf60x read */ + return BFIN_IRQ(bfin_read_SEC_SCI(0, SEC_CSID)); +#endif /* end of CONFIG_BF60x */ } #ifdef CONFIG_DO_IRQ_L1 diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index 3c648a077e75..ca6655e0d653 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -19,20 +19,33 @@ #include <asm/gpio.h> #include <asm/dma.h> #include <asm/dpmc.h> +#include <asm/pm.h> +#ifdef CONFIG_BF60x +struct bfin_cpu_pm_fns *bfin_cpu_pm; +#endif void bfin_pm_suspend_standby_enter(void) { +#ifndef CONFIG_BF60x bfin_pm_standby_setup(); +#endif -#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER - sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); +#ifdef CONFIG_BF60x + bfin_cpu_pm->enter(PM_SUSPEND_STANDBY); #else +# ifdef CONFIG_PM_BFIN_SLEEP_DEEPER + sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); +# else sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); +# endif #endif +#ifndef CONFIG_BF60x bfin_pm_standby_restore(); +#endif +#ifndef CONFIG_BF60x #ifdef SIC_IWR0 bfin_write_SIC_IWR0(IWR_DISABLE_ALL); # ifdef SIC_IWR1 @@ -52,6 +65,8 @@ void bfin_pm_suspend_standby_enter(void) #else bfin_write_SIC_IWR(IWR_DISABLE_ALL); #endif + +#endif } int bf53x_suspend_l1_mem(unsigned char *memptr) @@ -83,10 +98,13 @@ int bf53x_resume_l1_mem(unsigned char *memptr) } #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) +# ifdef CONFIG_BF60x +__attribute__((l1_text)) +# endif static void flushinv_all_dcache(void) { - u32 way, bank, subbank, set; - u32 status, addr; + register u32 way, bank, subbank, set; + register u32 status, addr; u32 dmem_ctl = bfin_read_DMEM_CONTROL(); for (bank = 0; bank < 2; ++bank) { @@ -133,6 +151,7 @@ int bfin_pm_suspend_mem_enter(void) return -ENOMEM; } +#ifndef CONFIG_BF60x wakeup = bfin_read_VR_CTL() & ~FREQ; wakeup |= SCKELOW; @@ -142,6 +161,7 @@ int bfin_pm_suspend_mem_enter(void) #ifdef CONFIG_PM_BFIN_WAKE_GP wakeup |= GPWE; #endif +#endif ret = blackfin_dma_suspend(); @@ -159,7 +179,11 @@ int bfin_pm_suspend_mem_enter(void) _disable_icplb(); bf53x_suspend_l1_mem(memptr); +#ifndef CONFIG_BF60x do_hibernate(wakeup | vr_wakeup); /* See you later! */ +#else + bfin_cpu_pm->enter(PM_SUSPEND_MEM); +#endif bf53x_resume_l1_mem(memptr); @@ -223,9 +247,39 @@ static int bfin_pm_enter(suspend_state_t state) return 0; } +#ifdef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH +void bfin_pm_end(void) +{ + u32 cycle, cycle2; + u64 usec64; + u32 usec; + + __asm__ __volatile__ ( + "1: %0 = CYCLES2\n" + "%1 = CYCLES\n" + "%2 = CYCLES2\n" + "CC = %2 == %0\n" + "if ! CC jump 1b\n" + : "=d,a" (cycle2), "=d,a" (cycle), "=d,a" (usec) : : "CC" + ); + + usec64 = ((u64)cycle2 << 32) + cycle; + do_div(usec64, get_cclk() / USEC_PER_SEC); + usec = usec64; + if (usec == 0) + usec = 1; + + pr_info("PM: resume of kernel completes after %ld msec %03ld usec\n", + usec / USEC_PER_MSEC, usec % USEC_PER_MSEC); +} +#endif + static const struct platform_suspend_ops bfin_pm_ops = { .enter = bfin_pm_enter, .valid = bfin_pm_valid, +#ifdef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH + .end = bfin_pm_end, +#endif }; static int __init bfin_pm_init(void) diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index ac8f8a43158c..00bbe672b3b3 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -340,27 +340,10 @@ void smp_send_stop(void) return; } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) { int ret; - struct blackfin_cpudata *ci = &per_cpu(cpu_data, cpu); - struct task_struct *idle = ci->idle; - if (idle) { - free_task(idle); - idle = NULL; - } - - if (!idle) { - idle = fork_idle(cpu); - if (IS_ERR(idle)) { - printk(KERN_ERR "CPU%u: fork() failed\n", cpu); - return PTR_ERR(idle); - } - ci->idle = idle; - } else { - init_idle(idle, cpu); - } secondary_stack = task_stack_page(idle) + THREAD_SIZE; ret = platform_boot_secondary(cpu, idle); |