diff options
Diffstat (limited to 'arch')
93 files changed, 1545 insertions, 1374 deletions
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 795d0ac67c21..fd5708523f2e 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -832,6 +832,7 @@ config BANK_0 config BANK_1 hex "Bank 1" default 0x7BB0 + default 0x5558 if BF54x config BANK_2 hex "Bank 2" @@ -963,21 +964,22 @@ endchoice endmenu -if (BF537 || BF533 || BF54x) - menu "CPU Frequency scaling" source "drivers/cpufreq/Kconfig" -config CPU_FREQ - bool +config CPU_VOLTAGE + bool "CPU Voltage scaling" + depends on EXPERIMENTAL + depends on CPU_FREQ default n help - If you want to enable this option, you should select the - DPMC driver from Character Devices. -endmenu + Say Y here if you want CPU voltage scaling according to the CPU frequency. + This option violates the PLL BYPASS recommendation in the Blackfin Processor + manuals. There is a theoretical risk that during VDDINT transitions + the PLL may unlock. -endif +endmenu source "net/Kconfig" diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index 721f15f3cebf..881afe9082c7 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c @@ -56,9 +56,6 @@ int main(void) /* offsets into the thread struct */ DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); - DEFINE(THREAD_SR, offsetof(struct thread_struct, seqstat)); - DEFINE(PT_SR, offsetof(struct thread_struct, seqstat)); - DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); DEFINE(THREAD_PC, offsetof(struct thread_struct, pc)); DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); diff --git a/arch/blackfin/kernel/fixed_code.S b/arch/blackfin/kernel/fixed_code.S index 5ed47228a390..4b03ba025488 100644 --- a/arch/blackfin/kernel/fixed_code.S +++ b/arch/blackfin/kernel/fixed_code.S @@ -1,6 +1,6 @@ /* * This file contains sequences of code that will be copied to a - * fixed location, defined in <asm/atomic_seq.h>. The interrupt + * fixed location, defined in <asm/fixed_code.h>. The interrupt * handlers ensure that these sequences appear to be atomic when * executed from userspace. * These are aligned to 16 bytes, so that we have some space to replace diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c index 8b9fe29d03f4..14a42848f37f 100644 --- a/arch/blackfin/kernel/module.c +++ b/arch/blackfin/kernel/module.c @@ -160,6 +160,13 @@ int module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, char *secstrings, struct module *mod) { + /* + * XXX: sechdrs are vmalloced in kernel/module.c + * and would be vfreed just after module is loaded, + * so we hack to keep the only information we needed + * in mod->arch to correctly free L1 I/D sram later. + * NOTE: this breaks the semantic of mod->arch structure. + */ Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; void *dest = NULL; @@ -167,8 +174,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) || ((strcmp(".text", secstrings + s->sh_name) == 0) && (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) { - mod->arch.text_l1 = s; dest = l1_inst_sram_alloc(s->sh_size); + mod->arch.text_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 instruction memory allocation failed\n", @@ -182,8 +189,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) || ((strcmp(".data", secstrings + s->sh_name) == 0) && (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) { - mod->arch.data_a_l1 = s; dest = l1_data_sram_alloc(s->sh_size); + mod->arch.data_a_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 data memory allocation failed\n", @@ -197,8 +204,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 || ((strcmp(".bss", secstrings + s->sh_name) == 0) && (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) { - mod->arch.bss_a_l1 = s; dest = l1_data_sram_alloc(s->sh_size); + mod->arch.bss_a_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 data memory allocation failed\n", @@ -210,8 +217,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, s->sh_addr = (unsigned long)dest; } if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) { - mod->arch.data_b_l1 = s; dest = l1_data_B_sram_alloc(s->sh_size); + mod->arch.data_b_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 data memory allocation failed\n", @@ -223,8 +230,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, s->sh_addr = (unsigned long)dest; } if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) { - mod->arch.bss_b_l1 = s; dest = l1_data_B_sram_alloc(s->sh_size); + mod->arch.bss_b_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 data memory allocation failed\n", @@ -416,14 +423,14 @@ module_finalize(const Elf_Ehdr * hdr, void module_arch_cleanup(struct module *mod) { - if ((mod->arch.text_l1) && (mod->arch.text_l1->sh_addr)) - l1_inst_sram_free((void *)mod->arch.text_l1->sh_addr); - if ((mod->arch.data_a_l1) && (mod->arch.data_a_l1->sh_addr)) - l1_data_sram_free((void *)mod->arch.data_a_l1->sh_addr); - if ((mod->arch.bss_a_l1) && (mod->arch.bss_a_l1->sh_addr)) - l1_data_sram_free((void *)mod->arch.bss_a_l1->sh_addr); - if ((mod->arch.data_b_l1) && (mod->arch.data_b_l1->sh_addr)) - l1_data_B_sram_free((void *)mod->arch.data_b_l1->sh_addr); - if ((mod->arch.bss_b_l1) && (mod->arch.bss_b_l1->sh_addr)) - l1_data_B_sram_free((void *)mod->arch.bss_b_l1->sh_addr); + if (mod->arch.text_l1) + l1_inst_sram_free((void *)mod->arch.text_l1); + if (mod->arch.data_a_l1) + l1_data_sram_free((void *)mod->arch.data_a_l1); + if (mod->arch.bss_a_l1) + l1_data_sram_free((void *)mod->arch.bss_a_l1); + if (mod->arch.data_b_l1) + l1_data_B_sram_free((void *)mod->arch.data_b_l1); + if (mod->arch.bss_b_l1) + l1_data_B_sram_free((void *)mod->arch.bss_b_l1); } diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index be9fdd00d7cb..53c2cd255441 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -245,7 +245,7 @@ unsigned long get_wchan(struct task_struct *p) void finish_atomic_sections (struct pt_regs *regs) { - int __user *up0 = (int __user *)®s->p0; + int __user *up0 = (int __user *)regs->p0; if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END) return; diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index b4f062c172c6..f51ab088098e 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -185,8 +185,8 @@ void ptrace_disable(struct task_struct *child) { unsigned long tmp; /* make sure the single step bit is not set. */ - tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); - put_reg(child, PT_SR, tmp); + tmp = get_reg(child, PT_SYSCFG) & ~TRACE_BITS; + put_reg(child, PT_SYSCFG, tmp); } long arch_ptrace(struct task_struct *child, long request, long addr, long data) diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index cb9d883d493c..dbc3bbf846be 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c @@ -42,6 +42,9 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) +/* Location of the trace bit in SYSCFG. */ +#define TRACE_BITS 0x0001 + struct fdpic_func_descriptor { unsigned long text; unsigned long GOT; @@ -225,6 +228,16 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, regs->r1 = (unsigned long)(&frame->info); regs->r2 = (unsigned long)(&frame->uc); + /* + * Clear the trace flag when entering the signal handler, but + * notify any tracer that was single-stepping it. The tracer + * may want to single-step inside the handler too. + */ + if (regs->syscfg & TRACE_BITS) { + regs->syscfg &= ~TRACE_BITS; + ptrace_notify(SIGTRAP); + } + return 0; give_sigsegv: diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index 4482c47c09e5..e887efc86c29 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c @@ -60,7 +60,7 @@ static inline unsigned long long cycles_2_ns(cycle_t cyc) static cycle_t read_cycles(void) { - return get_cycles(); + return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod); } unsigned long long sched_clock(void) @@ -117,7 +117,7 @@ static void bfin_timer_set_mode(enum clock_event_mode mode, break; } case CLOCK_EVT_MODE_ONESHOT: - bfin_write_TSCALE(0); + bfin_write_TSCALE(TIME_SCALE - 1); bfin_write_TCOUNT(0); bfin_write_TCNTL(TMPWR | TMREN); CSYNC(); @@ -183,10 +183,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) static int __init bfin_clockevent_init(void) { + unsigned long timer_clk; + + timer_clk = get_cclk() / TIME_SCALE; + setup_irq(IRQ_CORETMR, &bfin_timer_irq); bfin_timer_init(); - clockevent_bfin.mult = div_sc(get_cclk(), NSEC_PER_SEC, clockevent_bfin.shift); + clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift); clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin); clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin); clockevents_register_device(&clockevent_bfin); diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 583d53811f03..8aa49f804228 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -32,12 +32,14 @@ #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) #include <linux/usb/isp1362.h> #endif #include <linux/ata_platform.h> +#include <linux/i2c.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/usb/sl811.h> @@ -50,6 +52,7 @@ #include <asm/reboot.h> #include <asm/nand.h> #include <asm/portmux.h> +#include <asm/dpmc.h> #include <linux/spi/ad7877.h> /* @@ -171,6 +174,46 @@ static struct platform_device bf52x_t350mcqb_device = { }; #endif +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) +static struct mtd_partition ezkit_partitions[] = { + { + .name = "Bootloader", + .size = 0x40000, + .offset = 0, + }, { + .name = "Kernel", + .size = 0x1C0000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "RootFS", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + } +}; + +static struct physmap_flash_data ezkit_flash_data = { + .width = 2, + .parts = ezkit_partitions, + .nr_parts = ARRAY_SIZE(ezkit_partitions), +}; + +static struct resource ezkit_flash_resource = { + .start = 0x20000000, + .end = 0x203fffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ezkit_flash_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ezkit_flash_data, + }, + .num_resources = 1, + .resource = &ezkit_flash_resource, +}; +#endif + #if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE) static struct mtd_partition partition_info[] = { { @@ -420,11 +463,7 @@ static struct mtd_partition bfin_spi_flash_partitions[] = { .offset = 0, .mask_flags = MTD_CAP_ROM }, { - .name = "kernel", - .size = 0xe0000, - .offset = MTDPART_OFS_APPEND, - }, { - .name = "file system", + .name = "linux kernel", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_APPEND, } @@ -434,7 +473,7 @@ static struct flash_platform_data bfin_spi_flash_data = { .name = "m25p80", .parts = bfin_spi_flash_partitions, .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions), - .type = "m25p64", + .type = "m25p16", }; /* SPI flash chip (m25p64) */ @@ -755,6 +794,24 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif +#ifdef CONFIG_I2C_BOARDINFO +static struct i2c_board_info __initdata bfin_i2c_board_info[] = { +#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) + { + I2C_BOARD_INFO("pcf8574_lcd", 0x22), + .type = "pcf8574_lcd", + }, +#endif +#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE) + { + I2C_BOARD_INFO("pcf8574_keypad", 0x27), + .type = "pcf8574_keypad", + .irq = IRQ_PF8, + }, +#endif +}; +#endif + #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { .name = "bfin-sport-uart", @@ -839,7 +896,32 @@ static struct platform_device bfin_gpios_device = { .resource = &bfin_gpios_resources, }; +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_100, 400000000), + VRPAIR(VLEV_105, 426000000), + VRPAIR(VLEV_110, 500000000), + VRPAIR(VLEV_115, 533000000), + VRPAIR(VLEV_120, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *stamp_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE) &bf5xx_nand_device, #endif @@ -921,12 +1003,22 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_device_gpiokeys, #endif +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) + &ezkit_flash_device, +#endif + &bfin_gpios_device, }; static int __init stamp_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); + +#ifdef CONFIG_I2C_BOARDINFO + i2c_register_board_info(0, bfin_i2c_board_info, + ARRAY_SIZE(bfin_i2c_board_info)); +#endif + platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) spi_register_board_info(bfin_spi_board_info, diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c index a03149c72681..ed2b0b8f5dc9 100644 --- a/arch/blackfin/mach-bf533/boards/cm_bf533.c +++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c @@ -33,12 +33,15 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) #include <linux/usb/isp1362.h> +#endif #include <linux/ata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -341,7 +344,37 @@ static struct platform_device bfin_pata_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 600000000), + VRPAIR(VLEV_125, 600000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *cm_bf533_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) &bfin_uart_device, #endif diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c index 08a7943949ae..9d28415163ea 100644 --- a/arch/blackfin/mach-bf533/boards/ezkit.c +++ b/arch/blackfin/mach-bf533/boards/ezkit.c @@ -42,6 +42,7 @@ #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -350,7 +351,37 @@ static struct platform_device i2c_gpio_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 600000000), + VRPAIR(VLEV_125, 600000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *ezkit_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) &smc91x_device, #endif diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index 024f418ae543..7fd35fb32fd5 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -45,6 +45,7 @@ #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -516,7 +517,37 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 600000000), + VRPAIR(VLEV_125, 600000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *stamp_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) &rtc_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c index d8a23cd9b9ed..73f2142875e2 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c @@ -35,12 +35,15 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) #include <linux/usb/isp1362.h> +#endif #include <linux/ata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -428,7 +431,37 @@ static struct platform_device bfin_pata_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 500000000), + VRPAIR(VLEV_125, 533000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *cm_bf537_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_FB_HITACHI_TX09) || defined(CONFIG_FB_HITACHI_TX09_MODULE) &hitachi_fb_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index d3727b7c2d7d..9a756d1f3d73 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -47,6 +47,7 @@ #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> #include <asm/portmux.h> +#include <asm/dpmc.h> #include <linux/spi/ad7877.h> /* @@ -817,7 +818,37 @@ static struct platform_device bfin_pata_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 500000000), + VRPAIR(VLEV_125, 533000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *stamp_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE) &bfin_pcmcia_cf_device, #endif diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c index e3e8479fffb5..3b74f96d3590 100644 --- a/arch/blackfin/mach-bf548/boards/cm_bf548.c +++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c @@ -36,7 +36,9 @@ #include <linux/spi/flash.h> #include <linux/irq.h> #include <linux/interrupt.h> +#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) #include <linux/usb/musb.h> +#endif #include <asm/bfin5xx_spi.h> #include <asm/cplb.h> #include <asm/dma.h> @@ -44,6 +46,7 @@ #include <asm/nand.h> #include <asm/portmux.h> #include <asm/mach/bf54x_keys.h> +#include <asm/dpmc.h> #include <linux/input.h> #include <linux/spi/ad7877.h> @@ -590,7 +593,38 @@ static struct platform_device bfin_device_gpiokeys = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ +/* + * Internal VLEV BF54XSBBC1533 + ****temporarily using these values until data sheet is updated + */ + VRPAIR(VLEV_085, 150000000), + VRPAIR(VLEV_090, 250000000), + VRPAIR(VLEV_110, 276000000), + VRPAIR(VLEV_115, 301000000), + VRPAIR(VLEV_120, 525000000), + VRPAIR(VLEV_125, 550000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *cm_bf548_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) &rtc_device, #endif diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index b00f68ac6bc9..d1682bb37509 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -46,6 +46,7 @@ #include <asm/dma.h> #include <asm/gpio.h> #include <asm/nand.h> +#include <asm/dpmc.h> #include <asm/portmux.h> #include <asm/mach/bf54x_keys.h> #include <linux/input.h> @@ -689,7 +690,38 @@ static struct platform_device bfin_gpios_device = { .resource = &bfin_gpios_resources, }; +static const unsigned int cclk_vlev_datasheet[] = +{ +/* + * Internal VLEV BF54XSBBC1533 + ****temporarily using these values until data sheet is updated + */ + VRPAIR(VLEV_085, 150000000), + VRPAIR(VLEV_090, 250000000), + VRPAIR(VLEV_110, 276000000), + VRPAIR(VLEV_115, 301000000), + VRPAIR(VLEV_120, 525000000), + VRPAIR(VLEV_125, 550000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *ezkit_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) &rtc_device, #endif diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c index 9fd580952fd8..466ef5929a25 100644 --- a/arch/blackfin/mach-bf561/boards/cm_bf561.c +++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c @@ -33,12 +33,15 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) #include <linux/usb/isp1362.h> +#endif #include <linux/ata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -339,8 +342,37 @@ static struct platform_device bfin_pata_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 300000000), + VRPAIR(VLEV_095, 313000000), + VRPAIR(VLEV_100, 350000000), + VRPAIR(VLEV_105, 400000000), + VRPAIR(VLEV_110, 444000000), + VRPAIR(VLEV_115, 450000000), + VRPAIR(VLEV_120, 475000000), + VRPAIR(VLEV_125, 500000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *cm_bf561_devices[] __initdata = { + &bfin_dpmc, + #if defined(CONFIG_FB_HITACHI_TX09) || defined(CONFIG_FB_HITACHI_TX09_MODULE) &hitachi_fb_device, #endif diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index 0d74b7d99209..61d8f7648b24 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c @@ -39,6 +39,7 @@ #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -443,7 +444,37 @@ static struct platform_device i2c_gpio_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 300000000), + VRPAIR(VLEV_095, 313000000), + VRPAIR(VLEV_100, 350000000), + VRPAIR(VLEV_105, 400000000), + VRPAIR(VLEV_110, 444000000), + VRPAIR(VLEV_115, 450000000), + VRPAIR(VLEV_120, 475000000), + VRPAIR(VLEV_125, 500000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *ezkit_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) &smc91x_device, #endif diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 393081e9b680..422bfee34adc 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -6,5 +6,6 @@ obj-y := \ cache.o cacheinit.o entry.o \ interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o -obj-$(CONFIG_PM) += pm.o dpmc.o -obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_PM) += pm.o dpmc_modes.o +obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index ed81e00d20e1..75cdad291e88 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -62,6 +62,14 @@ static struct bfin_dpm_state { unsigned int tscale; /* change the divider on the core timer interrupt */ } dpm_state_table[3]; +/* + normalized to maximum frequncy 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; + /**************************************************************************/ static unsigned int bfin_getfreq(unsigned int cpu) @@ -80,6 +88,7 @@ static int bfin_target(struct cpufreq_policy *policy, unsigned int index, plldiv, tscale; unsigned long flags, cclk_hz; struct cpufreq_freqs freqs; + cycles_t cycles; if (cpufreq_frequency_table_target(policy, bfin_freq_table, target_freq, relation, &index)) @@ -101,8 +110,14 @@ static int bfin_target(struct cpufreq_policy *policy, bfin_write_PLL_DIV(plldiv); /* we have to adjust the core timer, because it is using cclk */ bfin_write_TSCALE(tscale); + cycles = get_cycles(); SSYNC(); + cycles += 10; /* ~10 cycles we loose after get_cycles() */ + __bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index); + __bfin_cycles_mod = index; local_irq_restore(flags); + /* TODO: just test case for cycles clock source, remove later */ + pr_debug("cpufreq: done\n"); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; @@ -119,22 +134,13 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy) unsigned long cclk, sclk, csel, min_cclk; int index; -#ifdef CONFIG_CYCLES_CLOCKSOURCE -/* - * Clocksource CYCLES is still CONTINUOUS but not longer MONOTONIC in case we enable - * CPU frequency scaling, since CYCLES runs off Core Clock. - */ - printk(KERN_WARNING "CPU frequency scaling not supported: Clocksource not suitable\n" - return -ENODEV; -#endif - if (policy->cpu != 0) return -EINVAL; cclk = get_cclk(); sclk = get_sclk(); -#if ANOMALY_05000273 +#if ANOMALY_05000273 || (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_DCACHE)) min_cclk = sclk * 2; #else min_cclk = sclk; diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c new file mode 100644 index 000000000000..02c7efd1bcf4 --- /dev/null +++ b/arch/blackfin/mach-common/dpmc.c @@ -0,0 +1,137 @@ +/* + * Copyright 2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/cdev.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/cpufreq.h> + +#include <asm/delay.h> +#include <asm/dpmc.h> + +#define DRIVER_NAME "bfin dpmc" + +#define dprintk(msg...) \ + cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, DRIVER_NAME, msg) + +struct bfin_dpmc_platform_data *pdata; + +/** + * bfin_set_vlev - Update VLEV field in VR_CTL Reg. + * Avoid BYPASS sequence + */ +static void bfin_set_vlev(unsigned int vlev) +{ + unsigned pll_lcnt; + + pll_lcnt = bfin_read_PLL_LOCKCNT(); + + bfin_write_PLL_LOCKCNT(1); + bfin_write_VR_CTL((bfin_read_VR_CTL() & ~VLEV) | vlev); + bfin_write_PLL_LOCKCNT(pll_lcnt); +} + +/** + * bfin_get_vlev - Get CPU specific VLEV from platform device data + */ +static unsigned int bfin_get_vlev(unsigned int freq) +{ + int i; + + if (!pdata) + goto err_out; + + freq >>= 16; + + for (i = 0; i < pdata->tabsize; i++) + if (freq <= (pdata->tuple_tab[i] & 0xFFFF)) + return pdata->tuple_tab[i] >> 16; + +err_out: + printk(KERN_WARNING "DPMC: No suitable CCLK VDDINT voltage pair found\n"); + return VLEV_120; +} + +#ifdef CONFIG_CPU_FREQ +static int +vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + + if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) { + bfin_set_vlev(bfin_get_vlev(freq->new)); + udelay(pdata->vr_settling_time); /* Wait until Volatge settled */ + + } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) + bfin_set_vlev(bfin_get_vlev(freq->new)); + + return 0; +} + +static struct notifier_block vreg_cpufreq_notifier_block = { + .notifier_call = vreg_cpufreq_notifier +}; +#endif /* CONFIG_CPU_FREQ */ + +/** + * bfin_dpmc_probe - + * + */ +static int __devinit bfin_dpmc_probe(struct platform_device *pdev) +{ + if (pdev->dev.platform_data) + pdata = pdev->dev.platform_data; + else + return -EINVAL; + + return cpufreq_register_notifier(&vreg_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); +} + +/** + * bfin_dpmc_remove - + */ +static int __devexit bfin_dpmc_remove(struct platform_device *pdev) +{ + pdata = NULL; + return cpufreq_unregister_notifier(&vreg_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); +} + +struct platform_driver bfin_dpmc_device_driver = { + .probe = bfin_dpmc_probe, + .remove = __devexit_p(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_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("cpu power management driver for Blackfin"); +MODULE_LICENSE("GPL"); diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc_modes.S index 9d45aa3265b1..b7981d31c392 100644 --- a/arch/blackfin/mach-common/dpmc.S +++ b/arch/blackfin/mach-common/dpmc_modes.S @@ -1,30 +1,7 @@ /* - * File: arch/blackfin/mach-common/dpmc.S - * Based on: - * Author: LG Soft India + * Copyright 2004-2008 Analog Devices Inc. * - * Created: ? - * Description: Watchdog Timer APIs - * - * Modified: - * Copyright 2004-2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Licensed under the GPL-2 or later. */ #include <linux/linkage.h> diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index f2fb87e9a46e..038f70e0be65 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -151,26 +151,62 @@ ENTRY(_ex_soft_bp) ENDPROC(_ex_soft_bp) ENTRY(_ex_single_step) + /* If we just returned from an interrupt, the single step event is + for the RTI instruction. */ r7 = retx; r6 = reti; cc = r7 == r6; - if cc jump _bfin_return_from_exception - r7 = syscfg; - bitclr (r7, 0); - syscfg = R7; + if cc jump _bfin_return_from_exception; + /* If we were in user mode, do the single step normally. */ p5.l = lo(IPEND); p5.h = hi(IPEND); r6 = [p5]; - cc = bittst(r6, 5); - if !cc jump _ex_trap_c; - p4.l = lo(EVT5); - p4.h = hi(EVT5); - r6.h = _exception_to_level5; - r6.l = _exception_to_level5; - r7 = [p4]; - cc = r6 == r7; - if !cc jump _ex_trap_c; + r7 = 0xffe0 (z); + r7 = r7 & r6; + cc = r7 == 0; + if !cc jump 1f; + + /* Single stepping only a single instruction, so clear the trace + * bit here. */ + r7 = syscfg; + bitclr (r7, 0); + syscfg = R7; + jump _ex_trap_c; + +1: + /* + * We were in an interrupt handler. By convention, all of them save + * SYSCFG with their first instruction, so by checking whether our + * RETX points at the entry point, we can determine whether to allow + * a single step, or whether to clear SYSCFG. + * + * First, find out the interrupt level and the event vector for it. + */ + p5.l = lo(EVT0); + p5.h = hi(EVT0); + p5 += -4; +2: + r7 = rot r7 by -1; + p5 += 4; + if !cc jump 2b; + + /* What we actually do is test for the _second_ instruction in the + * IRQ handler. That way, if there are insns following the restore + * of SYSCFG after leaving the handler, we will not turn off SYSCFG + * for them. */ + + r7 = [p5]; + r7 += 2; + r6 = RETX; + cc = R7 == R6; + if !cc jump _bfin_return_from_exception; + + r7 = syscfg; + bitclr (r7, 0); + syscfg = R7; + + /* Fall through to _bfin_return_from_exception. */ ENDPROC(_ex_single_step) ENTRY(_bfin_return_from_exception) @@ -234,20 +270,26 @@ ENTRY(_ex_trap_c) p5.l = _saved_icplb_fault_addr; [p5] = r7; - p4.l = __retx; - p4.h = __retx; + p4.l = _excpt_saved_stuff; + p4.h = _excpt_saved_stuff; + r6 = retx; [p4] = r6; - p4.l = lo(SAFE_USER_INSTRUCTION); - p4.h = hi(SAFE_USER_INSTRUCTION); - retx = p4; + + r6 = SYSCFG; + [p4 + 4] = r6; + BITCLR(r6, 0); + SYSCFG = r6; /* Disable all interrupts, but make sure level 5 is enabled so * we can switch to that level. Save the old mask. */ cli r6; - p4.l = _excpt_saved_imask; - p4.h = _excpt_saved_imask; - [p4] = r6; + [p4 + 8] = r6; + + p4.l = lo(SAFE_USER_INSTRUCTION); + p4.h = hi(SAFE_USER_INSTRUCTION); + retx = p4; + r6 = 0x3f; sti r6; @@ -295,6 +337,11 @@ ENTRY(_double_fault) */ SAVE_ALL_SYS + /* The dumping functions expect the return address in the RETI + * slot. */ + r6 = retx; + [sp + PT_PC] = r6; + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ SP += -12; call _double_fault_c; @@ -307,16 +354,17 @@ ENDPROC(_double_fault) ENTRY(_exception_to_level5) SAVE_ALL_SYS - p4.l = __retx; - p4.h = __retx; + p4.l = _excpt_saved_stuff; + p4.h = _excpt_saved_stuff; r6 = [p4]; [sp + PT_PC] = r6; + r6 = [p4 + 4]; + [sp + PT_SYSCFG] = r6; + /* Restore interrupt mask. We haven't pushed RETI, so this * doesn't enable interrupts until we return from this handler. */ - p4.l = _excpt_saved_imask; - p4.h = _excpt_saved_imask; - r6 = [p4]; + r6 = [p4 + 8]; sti r6; /* Restore the hardware error vector. */ @@ -1344,7 +1392,14 @@ ENTRY(_sys_call_table) .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall .endr -_excpt_saved_imask: + + /* + * Used to save the real RETX, IMASK and SYSCFG when temporarily + * storing safe values across the transition from exception to IRQ5. + */ +_excpt_saved_stuff: + .long 0; + .long 0; .long 0; _exception_stack: @@ -1358,7 +1413,3 @@ _exception_stack_top: _last_cplb_fault_retx: .long 0; #endif - /* Used to save the real RETX when temporarily storing a safe - * return address. */ -__retx: - .long 0; diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c index d124066e1728..a79fbd87021b 100644 --- a/arch/cris/kernel/sys_cris.c +++ b/arch/cris/kernel/sys_cris.c @@ -27,28 +27,6 @@ #include <asm/uaccess.h> #include <asm/segment.h> -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long __user * fildes) -{ - int fd[2]; - int error; - - lock_kernel(); - error = do_pipe(fd); - unlock_kernel(); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) { - sys_close(fd[0]); - sys_close(fd[1]); - error = -EFAULT; - } - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index 319c79720b8a..305ac852bbed 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -76,29 +76,6 @@ asmlinkage int sys_tas(int __user *addr) return oldval; } -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage int -sys_pipe(unsigned long r0, unsigned long r1, unsigned long r2, - unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, struct pt_regs regs) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user((void __user *)r0, fd, 2*sizeof(int))) { - sys_close(fd[0]); - sys_close(fd[1]); - error = -EFAULT; - } - } - return error; -} - asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 6a6409adc564..e856218da90d 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -186,17 +186,6 @@ config PREEMPT Say Y here if you are building a kernel for a desktop, embedded or real-time system. Say N if you are unsure. -config PREEMPT_BKL - bool "Preempt The Big Kernel Lock" - depends on PREEMPT - default y - help - This option reduces the latency of the kernel by making the - big kernel lock preemptible. - - Say Y here if you are building a kernel for a desktop system. - Say N if you are unsure. - config MN10300_CURRENT_IN_E2 bool "Hold current task address in E2 register" default y diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts index a1ae4d6ec990..72d67564bdfc 100644 --- a/arch/powerpc/boot/dts/sequoia.dts +++ b/arch/powerpc/boot/dts/sequoia.dts @@ -342,9 +342,14 @@ /* Outbound ranges, one memory and one IO, * later cannot be changed. Chip supports a second * IO range but we don't use it for now + * From the 440EPx user manual: + * PCI 1 Memory 1 8000 0000 1 BFFF FFFF 1GB + * I/O 1 E800 0000 1 E800 FFFF 64KB + * I/O 1 E880 0000 1 EBFF FFFF 56MB */ - ranges = <02000000 0 80000000 1 80000000 0 10000000 - 01000000 0 00000000 1 e8000000 0 00100000>; + ranges = <02000000 0 80000000 1 80000000 0 40000000 + 01000000 0 00000000 1 e8000000 0 00010000 + 01000000 0 00000000 1 e8800000 0 03800000>; /* Inbound 2GB range starting at 0 */ dma-ranges = <42000000 0 0 0 0 0 80000000>; diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 9f9377745490..d8f0329b1344 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -16,7 +16,6 @@ #include <asm/mmu.h> #include <asm/pgtable.h> #include <asm/io.h> -#include <asm/prom.h> #include <asm/processor.h> #include <asm/udbg.h> diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 36080d4d1922..81738a4b3c3a 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1208,6 +1208,18 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_4xx, .platform = "ppc405", }, + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic 40x PPC)", + .cpu_features = CPU_FTRS_40X, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + .machine_check = machine_check_4xx, + .platform = "ppc405", + } #endif /* CONFIG_40x */ #ifdef CONFIG_44x @@ -1421,8 +1433,18 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_440A, .platform = "ppc440", }, + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic 44x PPC)", + .cpu_features = CPU_FTRS_44X, + .cpu_user_features = COMMON_USER_BOOKE, + .icache_bsize = 32, + .dcache_bsize = 32, + .machine_check = machine_check_4xx, + .platform = "ppc440", + } #endif /* CONFIG_44x */ -#ifdef CONFIG_FSL_BOOKE #ifdef CONFIG_E200 { /* e200z5 */ .pvr_mask = 0xfff00000, @@ -1451,7 +1473,19 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e200, .platform = "ppc5554", }, -#elif defined(CONFIG_E500) + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic E200 PPC)", + .cpu_features = CPU_FTRS_E200, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_EFP_SINGLE | + PPC_FEATURE_UNIFIED_CACHE, + .dcache_bsize = 32, + .machine_check = machine_check_e200, + .platform = "ppc5554", +#endif /* CONFIG_E200 */ +#ifdef CONFIG_E500 { /* e500 */ .pvr_mask = 0xffff0000, .pvr_value = 0x80200000, @@ -1487,20 +1521,19 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e500, .platform = "ppc8548", }, -#endif -#endif -#if !CLASSIC_PPC { /* default match */ .pvr_mask = 0x00000000, .pvr_value = 0x00000000, - .cpu_name = "(generic PPC)", - .cpu_features = CPU_FTRS_GENERIC_32, - .cpu_user_features = PPC_FEATURE_32, + .cpu_name = "(generic E500 PPC)", + .cpu_features = CPU_FTRS_E500, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_SPE_COMP | + PPC_FEATURE_HAS_EFP_SINGLE_COMP, .icache_bsize = 32, .dcache_bsize = 32, + .machine_check = machine_check_e500, .platform = "powerpc", - } -#endif /* !CLASSIC_PPC */ +#endif /* CONFIG_E500 */ #endif /* CONFIG_PPC32 */ }; diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index b84ec6a2fc94..c2b9dc4fce5d 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -653,7 +653,14 @@ finish_tlb_load: rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ - rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ + + /* + * Clear U0-U3 and WL1 IL1I IL1D IL2I IL2D bits which are added + * on newer 440 cores like the 440x6 used on AMCC 460EX/460GT (see + * include/asm-powerpc/pgtable-ppc32.h for details). + */ + rlwinm r12, r12, 0, 20, 10 + tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ /* Done...restore registers and get out of here. diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 024805e1747d..25e84c0e1166 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1517,10 +1517,6 @@ _INIT_STATIC(start_here_multiplatform) addi r2,r2,0x4000 add r2,r2,r26 - /* Set initial ptr to current */ - LOAD_REG_IMMEDIATE(r4, init_task) - std r4,PACACURRENT(r13) - /* Do very early kernel initializations, including initial hash table, * stab and slb setup before we turn on relocation. */ diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c index 289af348978d..4d5731b2429a 100644 --- a/arch/powerpc/kernel/isa-bridge.c +++ b/arch/powerpc/kernel/isa-bridge.c @@ -108,9 +108,6 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, if (size > 0x10000) size = 0x10000; - printk(KERN_ERR "no ISA IO ranges or unexpected isa range, " - "mapping 64k\n"); - __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, size, _PAGE_NO_CACHE|_PAGE_GUARDED); return; diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 25e3fd8606ab..098fd96a394a 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -170,6 +170,8 @@ void __init setup_paca(int cpu) void __init early_setup(unsigned long dt_ptr) { + /* -------- printk is _NOT_ safe to use here ! ------- */ + /* Fill in any unititialised pacas */ initialise_pacas(); @@ -179,12 +181,14 @@ void __init early_setup(unsigned long dt_ptr) /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ setup_paca(0); - /* Enable early debugging if any specified (see udbg.h) */ - udbg_early_init(); - /* Initialize lockdep early or else spinlocks will blow */ lockdep_init(); + /* -------- printk is now safe to use ------- */ + + /* Enable early debugging if any specified (see udbg.h) */ + udbg_early_init(); + DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr); /* diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 04f74f9f9ab6..5bf7df146022 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -35,6 +35,7 @@ #include <linux/percpu.h> #include <linux/types.h> #include <linux/ioport.h> +#include <linux/kernel_stat.h> #include <asm/io.h> #include <asm/pgtable.h> @@ -231,6 +232,54 @@ static int iic_host_match(struct irq_host *h, struct device_node *node) "IBM,CBEA-Internal-Interrupt-Controller"); } +extern int noirqdebug; + +static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) +{ + const unsigned int cpu = smp_processor_id(); + + spin_lock(&desc->lock); + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + + /* + * If we're currently running this IRQ, or its disabled, + * we shouldn't process the IRQ. Mark it pending, handle + * the necessary masking and go out + */ + if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || + !desc->action)) { + desc->status |= IRQ_PENDING; + goto out_eoi; + } + + kstat_cpu(cpu).irqs[irq]++; + + /* Mark the IRQ currently in progress.*/ + desc->status |= IRQ_INPROGRESS; + + do { + struct irqaction *action = desc->action; + irqreturn_t action_ret; + + if (unlikely(!action)) + goto out_eoi; + + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); + spin_lock(&desc->lock); + + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); + + desc->status &= ~IRQ_INPROGRESS; +out_eoi: + desc->chip->eoi(irq); + spin_unlock(&desc->lock); +} + static int iic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { @@ -240,10 +289,10 @@ static int iic_host_map(struct irq_host *h, unsigned int virq, break; case IIC_IRQ_TYPE_IOEXC: set_irq_chip_and_handler(virq, &iic_ioexc_chip, - handle_fasteoi_irq); + handle_iic_irq); break; default: - set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq); + set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq); } return 0; } diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 6bab44b7716b..70c660121ec4 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -141,6 +141,10 @@ static void spu_restart_dma(struct spu *spu) if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags)) out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); + else { + set_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags); + mb(); + } } static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb) @@ -226,11 +230,13 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) return 0; } - spu->class_0_pending = 0; - spu->dar = ea; - spu->dsisr = dsisr; + spu->class_1_dar = ea; + spu->class_1_dsisr = dsisr; + + spu->stop_callback(spu, 1); - spu->stop_callback(spu); + spu->class_1_dar = 0; + spu->class_1_dsisr = 0; return 0; } @@ -318,11 +324,15 @@ spu_irq_class_0(int irq, void *data) stat = spu_int_stat_get(spu, 0) & mask; spu->class_0_pending |= stat; - spu->dsisr = spu_mfc_dsisr_get(spu); - spu->dar = spu_mfc_dar_get(spu); + spu->class_0_dsisr = spu_mfc_dsisr_get(spu); + spu->class_0_dar = spu_mfc_dar_get(spu); spin_unlock(&spu->register_lock); - spu->stop_callback(spu); + spu->stop_callback(spu, 0); + + spu->class_0_pending = 0; + spu->class_0_dsisr = 0; + spu->class_0_dar = 0; spu_int_stat_clear(spu, 0, stat); @@ -363,6 +373,9 @@ spu_irq_class_1(int irq, void *data) if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR) ; + spu->class_1_dsisr = 0; + spu->class_1_dar = 0; + return stat ? IRQ_HANDLED : IRQ_NONE; } @@ -396,10 +409,10 @@ spu_irq_class_2(int irq, void *data) spu->ibox_callback(spu); if (stat & CLASS2_SPU_STOP_INTR) - spu->stop_callback(spu); + spu->stop_callback(spu, 2); if (stat & CLASS2_SPU_HALT_INTR) - spu->stop_callback(spu); + spu->stop_callback(spu, 2); if (stat & CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR) spu->mfc_callback(spu); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index 67fa7247b80a..906a0a2a9fe1 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -28,6 +28,7 @@ #include <linux/io.h> #include <linux/mutex.h> #include <linux/device.h> +#include <linux/sched.h> #include <asm/spu.h> #include <asm/spu_priv1.h> @@ -75,8 +76,19 @@ static u64 int_stat_get(struct spu *spu, int class) static void cpu_affinity_set(struct spu *spu, int cpu) { - u64 target = iic_get_target_id(cpu); - u64 route = target << 48 | target << 32 | target << 16; + u64 target; + u64 route; + + if (nr_cpus_node(spu->node)) { + cpumask_t spumask = node_to_cpumask(spu->node); + cpumask_t cpumask = node_to_cpumask(cpu_to_node(cpu)); + + if (!cpus_intersects(spumask, cpumask)) + return; + } + + target = iic_get_target_id(cpu); + route = target << 48 | target << 32 | target << 16; out_be64(&spu->priv1->int_route_RW, route); } diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c index e46d300e21a5..f093a581ac74 100644 --- a/arch/powerpc/platforms/cell/spufs/fault.c +++ b/arch/powerpc/platforms/cell/spufs/fault.c @@ -83,13 +83,18 @@ int spufs_handle_class0(struct spu_context *ctx) return 0; if (stat & CLASS0_DMA_ALIGNMENT_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_DMA_ALIGNMENT); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_DMA_ALIGNMENT); if (stat & CLASS0_INVALID_DMA_COMMAND_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_INVALID_DMA); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_INVALID_DMA); if (stat & CLASS0_SPU_ERROR_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_SPE_ERROR); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_SPE_ERROR); + + ctx->csa.class_0_pending = 0; return -EIO; } @@ -119,8 +124,8 @@ int spufs_handle_class1(struct spu_context *ctx) * in time, we can still expect to get the same fault * the immediately after the context restore. */ - ea = ctx->csa.dar; - dsisr = ctx->csa.dsisr; + ea = ctx->csa.class_1_dar; + dsisr = ctx->csa.class_1_dsisr; if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) return 0; @@ -158,7 +163,7 @@ int spufs_handle_class1(struct spu_context *ctx) * time slicing will not preempt the context while the page fault * handler is running. Context switch code removes mappings. */ - ctx->csa.dar = ctx->csa.dsisr = 0; + ctx->csa.class_1_dar = ctx->csa.class_1_dsisr = 0; /* * If we handled the fault successfully and are in runnable diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 0c32a05ab068..f407b2471855 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -23,6 +23,7 @@ #include <linux/file.h> #include <linux/fs.h> +#include <linux/fsnotify.h> #include <linux/backing-dev.h> #include <linux/init.h> #include <linux/ioctl.h> @@ -223,7 +224,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file) parent = dir->d_parent->d_inode; ctx = SPUFS_I(dir->d_inode)->i_ctx; - mutex_lock(&parent->i_mutex); + mutex_lock_nested(&parent->i_mutex, I_MUTEX_PARENT); ret = spufs_rmdir(parent, dir); mutex_unlock(&parent->i_mutex); WARN_ON(ret); @@ -618,12 +619,15 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, mode &= ~current->fs->umask; if (flags & SPU_CREATE_GANG) - return spufs_create_gang(nd->path.dentry->d_inode, + ret = spufs_create_gang(nd->path.dentry->d_inode, dentry, nd->path.mnt, mode); else - return spufs_create_context(nd->path.dentry->d_inode, + ret = spufs_create_context(nd->path.dentry->d_inode, dentry, nd->path.mnt, flags, mode, filp); + if (ret >= 0) + fsnotify_mkdir(nd->path.dentry->d_inode, dentry); + return ret; out_dput: dput(dentry); diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index a9c35b7b719f..b7493b865812 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -11,7 +11,7 @@ #include "spufs.h" /* interrupt-level stop callback function. */ -void spufs_stop_callback(struct spu *spu) +void spufs_stop_callback(struct spu *spu, int irq) { struct spu_context *ctx = spu->ctx; @@ -24,9 +24,19 @@ void spufs_stop_callback(struct spu *spu) */ if (ctx) { /* Copy exception arguments into module specific structure */ - ctx->csa.class_0_pending = spu->class_0_pending; - ctx->csa.dsisr = spu->dsisr; - ctx->csa.dar = spu->dar; + switch(irq) { + case 0 : + ctx->csa.class_0_pending = spu->class_0_pending; + ctx->csa.class_0_dsisr = spu->class_0_dsisr; + ctx->csa.class_0_dar = spu->class_0_dar; + break; + case 1 : + ctx->csa.class_1_dsisr = spu->class_1_dsisr; + ctx->csa.class_1_dar = spu->class_1_dar; + break; + case 2 : + break; + } /* ensure that the exception status has hit memory before a * thread waiting on the context's stop queue is woken */ @@ -34,11 +44,6 @@ void spufs_stop_callback(struct spu *spu) wake_up_all(&ctx->stop_wq); } - - /* Clear callback arguments from spu structure */ - spu->class_0_pending = 0; - spu->dsisr = 0; - spu->dar = 0; } int spu_stopped(struct spu_context *ctx, u32 *stat) @@ -56,7 +61,11 @@ int spu_stopped(struct spu_context *ctx, u32 *stat) if (!(*stat & SPU_STATUS_RUNNING) && (*stat & stopped)) return 1; - dsisr = ctx->csa.dsisr; + dsisr = ctx->csa.class_0_dsisr; + if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) + return 1; + + dsisr = ctx->csa.class_1_dsisr; if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) return 1; @@ -294,7 +303,7 @@ static int spu_process_callback(struct spu_context *ctx) u32 ls_pointer, npc; void __iomem *ls; long spu_ret; - int ret, ret2; + int ret; /* get syscall block from local store */ npc = ctx->ops->npc_read(ctx) & ~3; @@ -316,11 +325,9 @@ static int spu_process_callback(struct spu_context *ctx) if (spu_ret <= -ERESTARTSYS) { ret = spu_handle_restartsys(ctx, &spu_ret, &npc); } - ret2 = spu_acquire(ctx); + mutex_lock(&ctx->state_mutex); if (ret == -ERESTARTSYS) return ret; - if (ret2) - return -EINTR; } /* need to re-get the ls, as it may have changed when we released the @@ -343,13 +350,14 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) if (mutex_lock_interruptible(&ctx->run_mutex)) return -ERESTARTSYS; - spu_enable_spu(ctx); ctx->event_return = 0; ret = spu_acquire(ctx); if (ret) goto out_unlock; + spu_enable_spu(ctx); + spu_update_sched_info(ctx); ret = spu_run_init(ctx, npc); diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 7298e7db2c83..2e411f23462b 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -140,6 +140,9 @@ void __spu_update_sched_info(struct spu_context *ctx) * if it is timesliced or preempted. */ ctx->cpus_allowed = current->cpus_allowed; + + /* Save the current cpu id for spu interrupt routing. */ + ctx->last_ran = raw_smp_processor_id(); } void spu_update_sched_info(struct spu_context *ctx) @@ -243,7 +246,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0); spu_restore(&ctx->csa, spu); spu->timestamp = jiffies; - spu_cpu_affinity_set(spu, raw_smp_processor_id()); spu_switch_notify(spu, ctx); ctx->state = SPU_STATE_RUNNABLE; @@ -657,7 +659,8 @@ static struct spu *find_victim(struct spu_context *ctx) victim->stats.invol_ctx_switch++; spu->stats.invol_ctx_switch++; - spu_add_to_rq(victim); + if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags)) + spu_add_to_rq(victim); mutex_unlock(&victim->state_mutex); diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 7312745b7540..454c277c1457 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -121,6 +121,7 @@ struct spu_context { cpumask_t cpus_allowed; int policy; int prio; + int last_ran; /* statistics */ struct { @@ -331,7 +332,7 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data); /* irq callback funcs. */ void spufs_ibox_callback(struct spu *spu); void spufs_wbox_callback(struct spu *spu); -void spufs_stop_callback(struct spu *spu); +void spufs_stop_callback(struct spu *spu, int irq); void spufs_mfc_callback(struct spu *spu); void spufs_dma_callback(struct spu *spu, int type); diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index d2a1249d36dd..3df9a36eb2f5 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -132,6 +132,14 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu) spu_int_mask_set(spu, 2, 0ul); eieio(); spin_unlock_irq(&spu->register_lock); + + /* + * This flag needs to be set before calling synchronize_irq so + * that the update will be visible to the relevant handlers + * via a simple load. + */ + set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); + clear_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags); synchronize_irq(spu->irqs[0]); synchronize_irq(spu->irqs[1]); synchronize_irq(spu->irqs[2]); @@ -166,9 +174,8 @@ static inline void set_switch_pending(struct spu_state *csa, struct spu *spu) /* Save, Step 7: * Restore, Step 5: * Set a software context switch pending flag. + * Done above in Step 3 - disable_interrupts(). */ - set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); - mb(); } static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) @@ -186,20 +193,21 @@ static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) MFC_CNTL_SUSPEND_COMPLETE); /* fall through */ case MFC_CNTL_SUSPEND_COMPLETE: - if (csa) { + if (csa) csa->priv2.mfc_control_RW = - MFC_CNTL_SUSPEND_MASK | + in_be64(&priv2->mfc_control_RW) | MFC_CNTL_SUSPEND_DMA_QUEUE; - } break; case MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION: out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE); POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) & MFC_CNTL_SUSPEND_DMA_STATUS_MASK) == MFC_CNTL_SUSPEND_COMPLETE); - if (csa) { - csa->priv2.mfc_control_RW = 0; - } + if (csa) + csa->priv2.mfc_control_RW = + in_be64(&priv2->mfc_control_RW) & + ~MFC_CNTL_SUSPEND_DMA_QUEUE & + ~MFC_CNTL_SUSPEND_MASK; break; } } @@ -249,16 +257,21 @@ static inline void save_spu_status(struct spu_state *csa, struct spu *spu) } } -static inline void save_mfc_decr(struct spu_state *csa, struct spu *spu) +static inline void save_mfc_stopped_status(struct spu_state *csa, + struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; + const u64 mask = MFC_CNTL_DECREMENTER_RUNNING | + MFC_CNTL_DMA_QUEUES_EMPTY; /* Save, Step 12: * Read MFC_CNTL[Ds]. Update saved copy of * CSA.MFC_CNTL[Ds]. + * + * update: do the same with MFC_CNTL[Q]. */ - csa->priv2.mfc_control_RW |= - in_be64(&priv2->mfc_control_RW) & MFC_CNTL_DECREMENTER_RUNNING; + csa->priv2.mfc_control_RW &= ~mask; + csa->priv2.mfc_control_RW |= in_be64(&priv2->mfc_control_RW) & mask; } static inline void halt_mfc_decr(struct spu_state *csa, struct spu *spu) @@ -462,7 +475,9 @@ static inline void purge_mfc_queue(struct spu_state *csa, struct spu *spu) * Restore, Step 14. * Write MFC_CNTL[Pc]=1 (purge queue). */ - out_be64(&priv2->mfc_control_RW, MFC_CNTL_PURGE_DMA_REQUEST); + out_be64(&priv2->mfc_control_RW, + MFC_CNTL_PURGE_DMA_REQUEST | + MFC_CNTL_SUSPEND_MASK); eieio(); } @@ -725,10 +740,14 @@ static inline void set_switch_active(struct spu_state *csa, struct spu *spu) /* Save, Step 48: * Restore, Step 23. * Change the software context switch pending flag - * to context switch active. + * to context switch active. This implementation does + * not uses a switch active flag. * - * This implementation does not uses a switch active flag. + * Now that we have saved the mfc in the csa, we can add in the + * restart command if an exception occurred. */ + if (test_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags)) + csa->priv2.mfc_control_RW |= MFC_CNTL_RESTART_DMA_COMMAND; clear_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); mb(); } @@ -1690,6 +1709,13 @@ static inline void restore_mfc_sr1(struct spu_state *csa, struct spu *spu) eieio(); } +static inline void set_int_route(struct spu_state *csa, struct spu *spu) +{ + struct spu_context *ctx = spu->ctx; + + spu_cpu_affinity_set(spu, ctx->last_ran); +} + static inline void restore_other_spu_access(struct spu_state *csa, struct spu *spu) { @@ -1721,15 +1747,15 @@ static inline void restore_mfc_cntl(struct spu_state *csa, struct spu *spu) */ out_be64(&priv2->mfc_control_RW, csa->priv2.mfc_control_RW); eieio(); + /* - * FIXME: this is to restart a DMA that we were processing - * before the save. better remember the fault information - * in the csa instead. + * The queue is put back into the same state that was evident prior to + * the context switch. The suspend flag is added to the saved state in + * the csa, if the operational state was suspending or suspended. In + * this case, the code that suspended the mfc is responsible for + * continuing it. Note that SPE faults do not change the operational + * state of the spu. */ - if ((csa->priv2.mfc_control_RW & MFC_CNTL_SUSPEND_DMA_QUEUE_MASK)) { - out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); - eieio(); - } } static inline void enable_user_access(struct spu_state *csa, struct spu *spu) @@ -1788,7 +1814,7 @@ static int quiece_spu(struct spu_state *prev, struct spu *spu) save_spu_runcntl(prev, spu); /* Step 9. */ save_mfc_sr1(prev, spu); /* Step 10. */ save_spu_status(prev, spu); /* Step 11. */ - save_mfc_decr(prev, spu); /* Step 12. */ + save_mfc_stopped_status(prev, spu); /* Step 12. */ halt_mfc_decr(prev, spu); /* Step 13. */ save_timebase(prev, spu); /* Step 14. */ remove_other_spu_access(prev, spu); /* Step 15. */ @@ -2000,6 +2026,7 @@ static void restore_csa(struct spu_state *next, struct spu *spu) check_ppuint_mb_stat(next, spu); /* Step 67. */ spu_invalidate_slbs(spu); /* Modified Step 68. */ restore_mfc_sr1(next, spu); /* Step 69. */ + set_int_route(next, spu); /* NEW */ restore_other_spu_access(next, spu); /* Step 70. */ restore_spu_runcntl(next, spu); /* Step 71. */ restore_mfc_cntl(next, spu); /* Step 72. */ diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 1814adbd2236..b4a54c52e880 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -1387,28 +1387,59 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, resource_size_t size = res->end - res->start + 1; u64 sa; - /* Calculate window size */ - sa = (0xffffffffffffffffull << ilog2(size));; - if (res->flags & IORESOURCE_PREFETCH) - sa |= 0x8; + if (port->endpoint) { + resource_size_t ep_addr = 0; + resource_size_t ep_size = 32 << 20; + + /* Currently we map a fixed 64MByte window to PLB address + * 0 (SDRAM). This should probably be configurable via a dts + * property. + */ + + /* Calculate window size */ + sa = (0xffffffffffffffffull << ilog2(ep_size));; + + /* Setup BAR0 */ + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa) | + PCI_BASE_ADDRESS_MEM_TYPE_64); - out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); - out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); + /* Disable BAR1 & BAR2 */ + out_le32(mbase + PECFG_BAR1MPA, 0); + out_le32(mbase + PECFG_BAR2HMPA, 0); + out_le32(mbase + PECFG_BAR2LMPA, 0); - /* The setup of the split looks weird to me ... let's see if it works */ - out_le32(mbase + PECFG_PIM0LAL, 0x00000000); - out_le32(mbase + PECFG_PIM0LAH, 0x00000000); - out_le32(mbase + PECFG_PIM1LAL, 0x00000000); - out_le32(mbase + PECFG_PIM1LAH, 0x00000000); - out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); - out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + out_le32(mbase + PECFG_PIM01SAH, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_PIM01SAL, RES_TO_U32_LOW(sa)); + + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(ep_addr)); + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr)); + } else { + /* Calculate window size */ + sa = (0xffffffffffffffffull << ilog2(size));; + if (res->flags & IORESOURCE_PREFETCH) + sa |= 0x8; + + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); + + /* The setup of the split looks weird to me ... let's see + * if it works + */ + out_le32(mbase + PECFG_PIM0LAL, 0x00000000); + out_le32(mbase + PECFG_PIM0LAH, 0x00000000); + out_le32(mbase + PECFG_PIM1LAL, 0x00000000); + out_le32(mbase + PECFG_PIM1LAH, 0x00000000); + out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); + out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); + } /* Enable inbound mapping */ out_le32(mbase + PECFG_PIMEN, 0x1); - out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); - out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); - /* Enable I/O, Mem, and Busmaster cycles */ out_le16(mbase + PCI_COMMAND, in_le16(mbase + PCI_COMMAND) | @@ -1422,13 +1453,8 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) const int *bus_range; int primary = 0, busses; void __iomem *mbase = NULL, *cfg_data = NULL; - - /* XXX FIXME: Handle endpoint mode properly */ - if (port->endpoint) { - printk(KERN_WARNING "PCIE%d: Port in endpoint mode !\n", - port->index); - return; - } + const u32 *pval; + u32 val; /* Check if primary bridge */ if (of_get_property(port->node, "primary", NULL)) @@ -1462,21 +1488,30 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) hose->last_busno = hose->first_busno + busses; } - /* We map the external config space in cfg_data and the host config - * space in cfg_addr. External space is 1M per bus, internal space - * is 4K + if (!port->endpoint) { + /* Only map the external config space in cfg_data for + * PCIe root-complexes. External space is 1M per bus + */ + cfg_data = ioremap(port->cfg_space.start + + (hose->first_busno + 1) * 0x100000, + busses * 0x100000); + if (cfg_data == NULL) { + printk(KERN_ERR "%s: Can't map external config space !", + port->node->full_name); + goto fail; + } + hose->cfg_data = cfg_data; + } + + /* Always map the host config space in cfg_addr. + * Internal space is 4K */ - cfg_data = ioremap(port->cfg_space.start + - (hose->first_busno + 1) * 0x100000, - busses * 0x100000); mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); - if (cfg_data == NULL || mbase == NULL) { - printk(KERN_ERR "%s: Can't map config space !", + if (mbase == NULL) { + printk(KERN_ERR "%s: Can't map internal config space !", port->node->full_name); goto fail; } - - hose->cfg_data = cfg_data; hose->cfg_addr = mbase; pr_debug("PCIE %s, bus %d..%d\n", port->node->full_name, @@ -1489,12 +1524,14 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) port->hose = hose; mbase = (void __iomem *)hose->cfg_addr; - /* - * Set bus numbers on our root port - */ - out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); - out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); - out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); + if (!port->endpoint) { + /* + * Set bus numbers on our root port + */ + out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); + out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); + out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); + } /* * OMRs are already reset, also disable PIMs @@ -1515,17 +1552,49 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) ppc4xx_configure_pciex_PIMs(port, hose, mbase, &dma_window); /* The root complex doesn't show up if we don't set some vendor - * and device IDs into it. Those are the same bogus one that the - * initial code in arch/ppc add. We might want to change that. + * and device IDs into it. The defaults below are the same bogus + * one that the initial code in arch/ppc had. This can be + * overwritten by setting the "vendor-id/device-id" properties + * in the pciex node. */ - out_le16(mbase + 0x200, 0xaaa0 + port->index); - out_le16(mbase + 0x202, 0xbed0 + port->index); - /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ - out_le32(mbase + 0x208, 0x06040001); + /* Get the (optional) vendor-/device-id from the device-tree */ + pval = of_get_property(port->node, "vendor-id", NULL); + if (pval) { + val = *pval; + } else { + if (!port->endpoint) + val = 0xaaa0 + port->index; + else + val = 0xeee0 + port->index; + } + out_le16(mbase + 0x200, val); + + pval = of_get_property(port->node, "device-id", NULL); + if (pval) { + val = *pval; + } else { + if (!port->endpoint) + val = 0xbed0 + port->index; + else + val = 0xfed0 + port->index; + } + out_le16(mbase + 0x202, val); + + if (!port->endpoint) { + /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ + out_le32(mbase + 0x208, 0x06040001); + + printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", + port->index); + } else { + /* Set Class Code to Processor/PPC */ + out_le32(mbase + 0x208, 0x0b200001); + + printk(KERN_INFO "PCIE%d: successfully set as endpoint\n", + port->index); + } - printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", - port->index); return; fail: if (hose) @@ -1542,6 +1611,7 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) const u32 *pval; int portno; unsigned int dcrs; + const char *val; /* First, proceed to core initialization as we assume there's * only one PCIe core in the system @@ -1573,8 +1643,20 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) } port->sdr_base = *pval; - /* XXX Currently, we only support root complex mode */ - port->endpoint = 0; + /* Check if device_type property is set to "pci" or "pci-endpoint". + * Resulting from this setup this PCIe port will be configured + * as root-complex or as endpoint. + */ + val = of_get_property(port->node, "device_type", NULL); + if (!strcmp(val, "pci-endpoint")) { + port->endpoint = 1; + } else if (!strcmp(val, "pci")) { + port->endpoint = 0; + } else { + printk(KERN_ERR "PCIE: missing or incorrect device_type for %s\n", + np->full_name); + return; + } /* Fetch config space registers address */ if (of_address_to_resource(np, 0, &port->cfg_space)) { diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 52c74780f403..1702de9395ee 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2842,9 +2842,11 @@ static void dump_spu_fields(struct spu *spu) DUMP_FIELD(spu, "0x%lx", ls_size); DUMP_FIELD(spu, "0x%x", node); DUMP_FIELD(spu, "0x%lx", flags); - DUMP_FIELD(spu, "0x%lx", dar); - DUMP_FIELD(spu, "0x%lx", dsisr); DUMP_FIELD(spu, "%d", class_0_pending); + DUMP_FIELD(spu, "0x%lx", class_0_dar); + DUMP_FIELD(spu, "0x%lx", class_0_dsisr); + DUMP_FIELD(spu, "0x%lx", class_1_dar); + DUMP_FIELD(spu, "0x%lx", class_1_dsisr); DUMP_FIELD(spu, "0x%lx", irqs[0]); DUMP_FIELD(spu, "0x%lx", irqs[1]); DUMP_FIELD(spu, "0x%lx", irqs[2]); diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 6a679c3e15e8..8a68160079a9 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -448,14 +448,6 @@ config SH_DREAMCAST Select Dreamcast if configuring for a SEGA Dreamcast. More information at <http://www.linux-sh.org> -config SH_MPC1211 - bool "Interface MPC1211" - depends on CPU_SUBTYPE_SH7751 && BROKEN - help - CTP/PCI-SH02 is a CPU module computer that is produced - by Interface Corporation. - More information at <http://www.interface.co.jp> - config SH_SH03 bool "Interface CTP/PCI-SH03" depends on CPU_SUBTYPE_SH7751 @@ -657,8 +649,7 @@ source "arch/sh/drivers/Kconfig" endmenu config ISA_DMA_API - def_bool y - depends on SH_MPC1211 + bool menu "Kernel features" @@ -666,7 +657,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on SUPERH32 && EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot @@ -683,7 +674,7 @@ config KEXEC config CRASH_DUMP bool "kernel crash dumps (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on SUPERH32 && EXPERIMENTAL help Generate crash dump after being started by kexec. This should be normally only set in special crash dump kernels @@ -763,7 +754,7 @@ menu "Boot options" config ZERO_PAGE_OFFSET hex "Zero page offset" - default "0x00004000" if SH_MPC1211 || SH_SH03 + default "0x00004000" if SH_SH03 default "0x00010000" if PAGE_SIZE_64KB default "0x00002000" if PAGE_SIZE_8KB default "0x00001000" diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index d9d28f9dd0db..0d2ef1e9a6fd 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -7,6 +7,7 @@ source "lib/Kconfig.debug" config SH_STANDARD_BIOS bool "Use LinuxSH standard BIOS" + depends on SUPERH32 help Say Y here if your target has the gdb-sh-stub package from www.m17n.org (or any conforming standard LinuxSH BIOS) diff --git a/arch/sh/Makefile b/arch/sh/Makefile index bb06f83e6239..8050b03d51fc 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -110,7 +110,6 @@ machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE) += se/7343 machdir-$(CONFIG_SH_7721_SOLUTION_ENGINE) += se/7721 machdir-$(CONFIG_SH_HP6XX) += hp6xx machdir-$(CONFIG_SH_DREAMCAST) += dreamcast -machdir-$(CONFIG_SH_MPC1211) += mpc1211 machdir-$(CONFIG_SH_SH03) += sh03 machdir-$(CONFIG_SH_SECUREEDGE5410) += snapgear machdir-$(CONFIG_SH_RTS7751R2D) += renesas/rts7751r2d diff --git a/arch/sh/boards/mpc1211/Makefile b/arch/sh/boards/mpc1211/Makefile deleted file mode 100644 index 8cd31b5d200b..000000000000 --- a/arch/sh/boards/mpc1211/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel -# - -obj-y := setup.o rtc.o - -obj-$(CONFIG_PCI) += pci.o - diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c deleted file mode 100644 index 23849f70f133..000000000000 --- a/arch/sh/boards/mpc1211/pci.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Low-Level PCI Support for the MPC-1211(CTP/PCI/MPC-SH02) - * - * (c) 2002-2003 Saito.K & Jeanne - * - * Dustin McIntire (dustin@sensoria.com) - * Derived from arch/i386/kernel/pci-*.c which bore the message: - * (c) 1999--2000 Martin Mares <mj@ucw.cz> - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/pci.h> -#include <linux/sched.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/irq.h> -#include <linux/interrupt.h> - -#include <asm/machvec.h> -#include <asm/io.h> -#include <asm/mpc1211/pci.h> - -static struct resource mpcpci_io_resource = { - "MPCPCI IO", - 0x00000000, - 0xffffffff, - IORESOURCE_IO -}; - -static struct resource mpcpci_mem_resource = { - "MPCPCI mem", - 0x00000000, - 0xffffffff, - IORESOURCE_MEM -}; - -static struct pci_ops pci_direct_conf1; -struct pci_channel board_pci_channels[] = { - {&pci_direct_conf1, &mpcpci_io_resource, &mpcpci_mem_resource, 0, 256}, - {NULL, NULL, NULL, 0, 0}, -}; - -/* - * Direct access to PCI hardware... - */ - - -#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) - -/* - * Functions for accessing PCI configuration space with type 1 accesses - */ -static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - u32 word; - unsigned long flags; - - /* - * PCIPDR may only be accessed as 32 bit words, - * so we must do byte alignment by hand - */ - local_irq_save(flags); - writel(CONFIG_CMD(bus,devfn,where), PCIPAR); - word = readl(PCIPDR); - local_irq_restore(flags); - - switch (size) { - case 1: - switch (where & 0x3) { - case 3: - *value = (u8)(word >> 24); - break; - case 2: - *value = (u8)(word >> 16); - break; - case 1: - *value = (u8)(word >> 8); - break; - default: - *value = (u8)word; - break; - } - break; - case 2: - switch (where & 0x3) { - case 3: - *value = (u16)(word >> 24); - local_irq_save(flags); - writel(CONFIG_CMD(bus,devfn,(where+1)), PCIPAR); - word = readl(PCIPDR); - local_irq_restore(flags); - *value |= ((word & 0xff) << 8); - break; - case 2: - *value = (u16)(word >> 16); - break; - case 1: - *value = (u16)(word >> 8); - break; - default: - *value = (u16)word; - break; - } - break; - case 4: - *value = word; - break; - } - PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value); - return PCIBIOS_SUCCESSFUL; -} - -/* - * Since MPC-1211 only does 32bit access we'll have to do a read,mask,write operation. - * We'll allow an odd byte offset, though it should be illegal. - */ -static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - u32 word,mask = 0; - unsigned long flags; - u32 shift = (where & 3) * 8; - - if(size == 1) { - mask = ((1 << 8) - 1) << shift; // create the byte mask - } else if(size == 2){ - if(shift == 24) - return PCIBIOS_BAD_REGISTER_NUMBER; - mask = ((1 << 16) - 1) << shift; // create the word mask - } - local_irq_save(flags); - writel(CONFIG_CMD(bus,devfn,where), PCIPAR); - if(size == 4){ - writel(value, PCIPDR); - local_irq_restore(flags); - PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value); - return PCIBIOS_SUCCESSFUL; - } - word = readl(PCIPDR); - word &= ~mask; - word |= ((value << shift) & mask); - writel(word, PCIPDR); - local_irq_restore(flags); - PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word); - return PCIBIOS_SUCCESSFUL; -} - -#undef CONFIG_CMD - -static struct pci_ops pci_direct_conf1 = { - .read = pci_conf1_read, - .write = pci_conf1_write, -}; - -static void __devinit quirk_ali_ide_ports(struct pci_dev *dev) -{ - dev->resource[0].start = 0x1f0; - dev->resource[0].end = 0x1f7; - dev->resource[0].flags = IORESOURCE_IO; - dev->resource[1].start = 0x3f6; - dev->resource[1].end = 0x3f6; - dev->resource[1].flags = IORESOURCE_IO; - dev->resource[2].start = 0x170; - dev->resource[2].end = 0x177; - dev->resource[2].flags = IORESOURCE_IO; - dev->resource[3].start = 0x376; - dev->resource[3].end = 0x376; - dev->resource[3].flags = IORESOURCE_IO; - dev->resource[4].start = 0xf000; - dev->resource[4].end = 0xf00f; - dev->resource[4].flags = IORESOURCE_IO; -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports); - -char * __devinit pcibios_setup(char *str) -{ - return str; -} - -/* - * Called after each bus is probed, but before its children - * are examined. - */ - -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ - pci_read_bridge_bases(b); -} - -/* - * IRQ functions - */ -static inline u8 bridge_swizzle(u8 pin, u8 slot) -{ - return (((pin-1) + slot) % 4) + 1; -} - -static inline u8 bridge_swizzle_pci_1(u8 pin, u8 slot) -{ - return (((pin-1) - slot) & 3) + 1; -} - -static u8 __init mpc1211_swizzle(struct pci_dev *dev, u8 *pinp) -{ - unsigned long flags; - u8 pin = *pinp; - u32 word; - - for ( ; dev->bus->self; dev = dev->bus->self) { - if (!pin) - continue; - - if (dev->bus->number == 1) { - local_irq_save(flags); - writel(0x80000000 | 0x2c, PCIPAR); - word = readl(PCIPDR); - local_irq_restore(flags); - word >>= 16; - - if (word == 0x0001) - pin = bridge_swizzle_pci_1(pin, PCI_SLOT(dev->devfn)); - else - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - } else - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - } - - *pinp = pin; - - return PCI_SLOT(dev->devfn); -} - -static int __init map_mpc1211_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int irq = -1; - - /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ - if (dev->bus->number == 0) { - switch (slot) { - case 13: irq = 9; break; /* USB */ - case 22: irq = 10; break; /* LAN */ - default: irq = 0; break; - } - } else { - switch (pin) { - case 0: irq = 0; break; - case 1: irq = 7; break; - case 2: irq = 9; break; - case 3: irq = 10; break; - case 4: irq = 11; break; - } - } - - if( irq < 0 ) { - PCIDBG(3, "PCI: Error mapping IRQ on device %s\n", pci_name(dev)); - return irq; - } - - PCIDBG(2, "Setting IRQ for slot %s to %d\n", pci_name(dev), irq); - - return irq; -} - -void __init pcibios_fixup_irqs(void) -{ - pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq); -} - -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) -{ - resource_size_t start = res->start; - - if (res->flags & IORESOURCE_IO) { - if (start >= 0x10000UL) { - if ((start & 0xffffUL) < 0x4000UL) { - start = (start & 0xffff0000UL) + 0x4000UL; - } else if ((start & 0xffffUL) >= 0xf000UL) { - start = (start & 0xffff0000UL) + 0x10000UL; - } - res->start = start; - } else { - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } - } -} - diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c deleted file mode 100644 index 03b123a4bba4..000000000000 --- a/arch/sh/boards/mpc1211/rtc.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support - * - * Copyright (C) 2002 Saito.K & Jeanne - * - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/time.h> -#include <linux/bcd.h> -#include <linux/mc146818rtc.h> - -unsigned long get_cmos_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - - spin_lock(&rtc_lock); - - do { - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - - spin_unlock(&rtc_lock); - - year += 1900; - if (year < 1970) - year += 100; - - return mktime(year, mon, day, hour, min, sec); -} - -void mpc1211_rtc_gettimeofday(struct timeval *tv) -{ - - tv->tv_sec = get_cmos_time(); - tv->tv_usec = 0; -} - -/* arc/i386/kernel/time.c */ -/* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when - * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. - * - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you'll only notice that after reboot! - */ -static int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; - - /* gets recalled with irq locally disabled */ - spin_lock(&rtc_lock); - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - cmos_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(cmos_minutes); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock(&rtc_lock); - - return retval; -} - -int mpc1211_rtc_settimeofday(const struct timeval *tv) -{ - unsigned long nowtime = tv->tv_sec; - - return set_rtc_mmss(nowtime); -} - -void mpc1211_time_init(void) -{ - rtc_sh_get_time = mpc1211_rtc_gettimeofday; - rtc_sh_set_time = mpc1211_rtc_settimeofday; -} - diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c deleted file mode 100644 index fede36361dc7..000000000000 --- a/arch/sh/boards/mpc1211/setup.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * linux/arch/sh/boards/mpc1211/setup.c - * - * Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y - * - */ - -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/hdreg.h> -#include <linux/ide.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <asm/io.h> -#include <asm/machvec.h> -#include <asm/mpc1211/mpc1211.h> -#include <asm/mpc1211/pci.h> -#include <asm/mpc1211/m1543c.h> - -/* ALI15X3 SMBus address offsets */ -#define SMBHSTSTS (0 + 0x3100) -#define SMBHSTCNT (1 + 0x3100) -#define SMBHSTSTART (2 + 0x3100) -#define SMBHSTCMD (7 + 0x3100) -#define SMBHSTADD (3 + 0x3100) -#define SMBHSTDAT0 (4 + 0x3100) -#define SMBHSTDAT1 (5 + 0x3100) -#define SMBBLKDAT (6 + 0x3100) - -/* Other settings */ -#define MAX_TIMEOUT 500 /* times 1/100 sec */ - -/* ALI15X3 command constants */ -#define ALI15X3_ABORT 0x04 -#define ALI15X3_T_OUT 0x08 -#define ALI15X3_QUICK 0x00 -#define ALI15X3_BYTE 0x10 -#define ALI15X3_BYTE_DATA 0x20 -#define ALI15X3_WORD_DATA 0x30 -#define ALI15X3_BLOCK_DATA 0x40 -#define ALI15X3_BLOCK_CLR 0x80 - -/* ALI15X3 status register bits */ -#define ALI15X3_STS_IDLE 0x04 -#define ALI15X3_STS_BUSY 0x08 -#define ALI15X3_STS_DONE 0x10 -#define ALI15X3_STS_DEV 0x20 /* device error */ -#define ALI15X3_STS_COLL 0x40 /* collision or no response */ -#define ALI15X3_STS_TERM 0x80 /* terminated by abort */ -#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ - -static void __init pci_write_config(unsigned long busNo, - unsigned long devNo, - unsigned long fncNo, - unsigned long cnfAdd, - unsigned long cnfData) -{ - ctrl_outl((0x80000000 - + ((busNo & 0xff) << 16) - + ((devNo & 0x1f) << 11) - + ((fncNo & 0x07) << 8) - + (cnfAdd & 0xfc)), PCIPAR); - - ctrl_outl(cnfData, PCIPDR); -} - -/* - Initialize IRQ setting -*/ - -static unsigned char m_irq_mask = 0xfb; -static unsigned char s_irq_mask = 0xff; - -static void disable_mpc1211_irq(unsigned int irq) -{ - if( irq < 8) { - m_irq_mask |= (1 << irq); - outb(m_irq_mask,I8259_M_MR); - } else { - s_irq_mask |= (1 << (irq - 8)); - outb(s_irq_mask,I8259_S_MR); - } - -} - -static void enable_mpc1211_irq(unsigned int irq) -{ - if( irq < 8) { - m_irq_mask &= ~(1 << irq); - outb(m_irq_mask,I8259_M_MR); - } else { - s_irq_mask &= ~(1 << (irq - 8)); - outb(s_irq_mask,I8259_S_MR); - } -} - -static inline int mpc1211_irq_real(unsigned int irq) -{ - int value; - int irqmask; - - if ( irq < 8) { - irqmask = 1<<irq; - outb(0x0b,I8259_M_CR); /* ISR register */ - value = inb(I8259_M_CR) & irqmask; - outb(0x0a,I8259_M_CR); /* back ro the IPR reg */ - return value; - } - irqmask = 1<<(irq - 8); - outb(0x0b,I8259_S_CR); /* ISR register */ - value = inb(I8259_S_CR) & irqmask; - outb(0x0a,I8259_S_CR); /* back ro the IPR reg */ - return value; -} - -static void mask_and_ack_mpc1211(unsigned int irq) -{ - if(irq < 8) { - if(m_irq_mask & (1<<irq)){ - if(!mpc1211_irq_real(irq)){ - atomic_inc(&irq_err_count) - printk("spurious 8259A interrupt: IRQ %x\n",irq); - } - } else { - m_irq_mask |= (1<<irq); - } - inb(I8259_M_MR); /* DUMMY */ - outb(m_irq_mask,I8259_M_MR); /* disable */ - outb(0x60+irq,I8259_M_CR); /* EOI */ - - } else { - if(s_irq_mask & (1<<(irq - 8))){ - if(!mpc1211_irq_real(irq)){ - atomic_inc(&irq_err_count); - printk("spurious 8259A interrupt: IRQ %x\n",irq); - } - } else { - s_irq_mask |= (1<<(irq - 8)); - } - inb(I8259_S_MR); /* DUMMY */ - outb(s_irq_mask,I8259_S_MR); /* disable */ - outb(0x60+(irq-8),I8259_S_CR); /* EOI */ - outb(0x60+2,I8259_M_CR); - } -} - -static void end_mpc1211_irq(unsigned int irq) -{ - enable_mpc1211_irq(irq); -} - -static unsigned int startup_mpc1211_irq(unsigned int irq) -{ - enable_mpc1211_irq(irq); - return 0; -} - -static void shutdown_mpc1211_irq(unsigned int irq) -{ - disable_mpc1211_irq(irq); -} - -static struct hw_interrupt_type mpc1211_irq_type = { - .typename = "MPC1211-IRQ", - .startup = startup_mpc1211_irq, - .shutdown = shutdown_mpc1211_irq, - .enable = enable_mpc1211_irq, - .disable = disable_mpc1211_irq, - .ack = mask_and_ack_mpc1211, - .end = end_mpc1211_irq -}; - -static void make_mpc1211_irq(unsigned int irq) -{ - irq_desc[irq].chip = &mpc1211_irq_type; - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = 0; - irq_desc[irq].depth = 1; - disable_mpc1211_irq(irq); -} - -int mpc1211_irq_demux(int irq) -{ - unsigned int poll; - - if( irq == 2 ) { - outb(0x0c,I8259_M_CR); - poll = inb(I8259_M_CR); - if(poll & 0x80) { - irq = (poll & 0x07); - } - if( irq == 2) { - outb(0x0c,I8259_S_CR); - poll = inb(I8259_S_CR); - irq = (poll & 0x07) + 8; - } - } - return irq; -} - -static void __init init_mpc1211_IRQ(void) -{ - int i; - /* - * Super I/O (Just mimic PC): - * 1: keyboard - * 3: serial 1 - * 4: serial 0 - * 5: printer - * 6: floppy - * 8: rtc - * 10: lan - * 12: mouse - * 14: ide0 - * 15: ide1 - */ - - pci_write_config(0,0,0,0x54, 0xb0b0002d); - outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */ - outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */ - outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */ - outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */ - outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */ - outb(0x02, I8259_S_MR); /* s icw3 slave id */ - outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/ - outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/ - outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */ - outb(0xff, I8259_S_MR); /* disable irq8--irq15 */ - - for ( i=0; i < 16; i++) { - if(i != 2) { - make_mpc1211_irq(i); - } - } -} - -static void delay1000(void) -{ - int i; - - for (i=0; i<1000; i++) - ctrl_delay(); -} - -static int put_smb_blk(unsigned char *p, int address, int command, int no) -{ - int temp; - int timeout; - int i; - - outb(0xff, SMBHSTSTS); - temp = inb(SMBHSTSTS); - for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) { - delay1000(); - temp = inb(SMBHSTSTS); - } - if (timeout >= MAX_TIMEOUT){ - return -1; - } - - outb(((address & 0x7f) << 1), SMBHSTADD); - outb(0xc0, SMBHSTCNT); - outb(command & 0xff, SMBHSTCMD); - outb(no & 0x1f, SMBHSTDAT0); - - for(i = 1; i <= no; i++) { - outb(*p++, SMBBLKDAT); - } - outb(0xff, SMBHSTSTART); - - temp = inb(SMBHSTSTS); - for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) { - delay1000(); - temp = inb(SMBHSTSTS); - } - if (timeout >= MAX_TIMEOUT) { - return -2; - } - if ( temp & ALI15X3_STS_ERR ){ - return -3; - } - return 0; -} - -static struct resource heartbeat_resources[] = { - [0] = { - .start = 0xa2000000, - .end = 0xa2000000, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device heartbeat_device = { - .name = "heartbeat", - .id = -1, - .num_resources = ARRAY_SIZE(heartbeat_resources), - .resource = heartbeat_resources, -}; - -static struct platform_device *mpc1211_devices[] __initdata = { - &heartbeat_device, -}; - -static int __init mpc1211_devices_setup(void) -{ - return platform_add_devices(mpc1211_devices, - ARRAY_SIZE(mpc1211_devices)); -} -__initcall(mpc1211_devices_setup); - -/* arch/sh/boards/mpc1211/rtc.c */ -void mpc1211_time_init(void); - -static void __init mpc1211_setup(char **cmdline_p) -{ - unsigned char spd_buf[128]; - - __set_io_port_base(PA_PCI_IO); - - pci_write_config(0,0,0,0x54, 0xb0b00000); - - do { - outb(ALI15X3_ABORT, SMBHSTCNT); - spd_buf[0] = 0x0c; - spd_buf[1] = 0x43; - spd_buf[2] = 0x7f; - spd_buf[3] = 0x03; - spd_buf[4] = 0x00; - spd_buf[5] = 0x03; - spd_buf[6] = 0x00; - } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0); - - board_time_init = mpc1211_time_init; - - return 0; -} - -/* - * The Machine Vector - */ -static struct sh_machine_vector mv_mpc1211 __initmv = { - .mv_name = "Interface MPC-1211(CTP/PCI/MPC-SH02)", - .mv_setup = mpc1211_setup, - .mv_nr_irqs = 48, - .mv_irq_demux = mpc1211_irq_demux, - .mv_init_irq = init_mpc1211_IRQ, -}; diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c index e7c150d49702..01af44245b57 100644 --- a/arch/sh/boards/renesas/migor/setup.c +++ b/arch/sh/boards/renesas/migor/setup.c @@ -14,6 +14,7 @@ #include <linux/mtd/physmap.h> #include <linux/mtd/nand.h> #include <linux/i2c.h> +#include <linux/smc91x.h> #include <asm/machvec.h> #include <asm/io.h> #include <asm/sh_keysc.h> @@ -27,6 +28,11 @@ * 0x18000000 8GB 8 NAND Flash (K9K8G08U0A) */ +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT, + .irq_flags = IRQF_TRIGGER_HIGH, +}; + static struct resource smc91x_eth_resources[] = { [0] = { .name = "SMC91C111" , @@ -36,7 +42,7 @@ static struct resource smc91x_eth_resources[] = { }, [1] = { .start = 32, /* IRQ0 */ - .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, + .flags = IORESOURCE_IRQ, }, }; @@ -44,6 +50,9 @@ static struct platform_device smc91x_eth_device = { .name = "smc91x", .num_resources = ARRAY_SIZE(smc91x_eth_resources), .resource = smc91x_eth_resources, + .dev = { + .platform_data = &smc91x_info, + }, }; static struct sh_keysc_info sh_keysc_info = { diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c b/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c index 68f0ad1b637d..ae1cfcb29700 100644 --- a/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c +++ b/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c @@ -62,7 +62,7 @@ static unsigned char irl2irq[HL_NR_IRL] __initdata = { static DECLARE_INTC_DESC(intc_desc, "r7780mp", vectors, NULL, mask_registers, NULL, NULL); -unsigned char * __init highlander_init_irq_r7780mp(void) +unsigned char * __init highlander_plat_irq_setup(void) { if ((ctrl_inw(0xa4000700) & 0xf000) == 0x2000) { printk(KERN_INFO "Using r7780mp interrupt controller.\n"); diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c b/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c index bd34048ed0e1..9d3921fe27c0 100644 --- a/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c +++ b/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c @@ -55,7 +55,7 @@ static unsigned char irl2irq[HL_NR_IRL] __initdata = { static DECLARE_INTC_DESC(intc_desc, "r7780rp", vectors, NULL, mask_registers, NULL, NULL); -unsigned char * __init highlander_init_irq_r7780rp(void) +unsigned char * __init highlander_plat_irq_setup(void) { if (ctrl_inw(0xa5000600)) { printk(KERN_INFO "Using r7780rp interrupt controller.\n"); diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c b/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c index bf7ec107fbc6..896c045aa39d 100644 --- a/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c +++ b/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c @@ -64,7 +64,7 @@ static unsigned char irl2irq[HL_NR_IRL] __initdata = { static DECLARE_INTC_DESC(intc_desc, "r7785rp", vectors, NULL, mask_registers, NULL, NULL); -unsigned char * __init highlander_init_irq_r7785rp(void) +unsigned char * __init highlander_plat_irq_setup(void) { if ((ctrl_inw(0xa4000158) & 0xf000) != 0x1000) return NULL; diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c index ac0a96522e45..bc79afb6fc4c 100644 --- a/arch/sh/boards/renesas/r7780rp/setup.c +++ b/arch/sh/boards/renesas/r7780rp/setup.c @@ -316,7 +316,7 @@ static void __init highlander_setup(char **cmdline_p) static unsigned char irl2irq[HL_NR_IRL]; -int highlander_irq_demux(int irq) +static int highlander_irq_demux(int irq) { if (irq >= HL_NR_IRL || !irl2irq[irq]) return irq; @@ -324,27 +324,9 @@ int highlander_irq_demux(int irq) return irl2irq[irq]; } -void __init highlander_init_irq(void) +static void __init highlander_init_irq(void) { - unsigned char *ucp = NULL; - - do { -#ifdef CONFIG_SH_R7780MP - ucp = highlander_init_irq_r7780mp(); - if (ucp) - break; -#endif -#ifdef CONFIG_SH_R7785RP - ucp = highlander_init_irq_r7785rp(); - if (ucp) - break; -#endif -#ifdef CONFIG_SH_R7780RP - ucp = highlander_init_irq_r7780rp(); - if (ucp) - break; -#endif - } while (0); + unsigned char *ucp = highlander_plat_irq_setup(); if (ucp) { plat_irq_setup_pins(IRQ_MODE_IRL3210); diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c index f21ee49ef3a5..452d0d6459a4 100644 --- a/arch/sh/boards/renesas/rts7751r2d/setup.c +++ b/arch/sh/boards/renesas/rts7751r2d/setup.c @@ -109,7 +109,6 @@ static struct platform_device heartbeat_device = { .resource = heartbeat_resources, }; -#ifdef CONFIG_MFD_SM501 static struct plat_serial8250_port uart_platform_data[] = { { .membase = (void __iomem *)0xb3e30000, @@ -208,13 +207,9 @@ static struct platform_device sm501_device = { .resource = sm501_resources, }; -#endif /* CONFIG_MFD_SM501 */ - static struct platform_device *rts7751r2d_devices[] __initdata = { -#ifdef CONFIG_MFD_SM501 &uart_device, &sm501_device, -#endif &heartbeat_device, &spi_sh_sci_device, }; @@ -234,7 +229,9 @@ static int __init rts7751r2d_devices_setup(void) { if (register_trapped_io(&cf_trapped_io) == 0) platform_device_register(&cf_ide_device); + spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus)); + return platform_add_devices(rts7751r2d_devices, ARRAY_SIZE(rts7751r2d_devices)); } diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c index 5b3ee089d91d..4fe84cc08406 100644 --- a/arch/sh/boards/se/7206/setup.c +++ b/arch/sh/boards/se/7206/setup.c @@ -3,12 +3,13 @@ * linux/arch/sh/boards/se/7206/setup.c * * Copyright (C) 2006 Yoshinori Sato - * Copyright (C) 2007 Paul Mundt + * Copyright (C) 2007 - 2008 Paul Mundt * * Hitachi 7206 SolutionEngine Support. */ #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/smc91x.h> #include <asm/se7206.h> #include <asm/io.h> #include <asm/machvec.h> @@ -16,8 +17,9 @@ static struct resource smc91x_resources[] = { [0] = { - .start = 0x300, - .end = 0x300 + 0x020 - 1, + .name = "smc91x-regs", + .start = PA_SMSC + 0x300, + .end = PA_SMSC + 0x300 + 0x020 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -27,9 +29,18 @@ static struct resource smc91x_resources[] = { }, }; +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT, +}; + static struct platform_device smc91x_device = { .name = "smc91x", .id = -1, + .dev = { + .dma_mask = NULL, + .coherent_dma_mask = 0xffffffff, + .platform_data = &smc91x_info, + }, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c index 33f6ee71f848..ede3957fc14a 100644 --- a/arch/sh/boards/se/7722/setup.c +++ b/arch/sh/boards/se/7722/setup.c @@ -14,6 +14,7 @@ #include <linux/platform_device.h> #include <linux/ata_platform.h> #include <linux/input.h> +#include <linux/smc91x.h> #include <asm/machvec.h> #include <asm/se7722.h> #include <asm/io.h> @@ -44,6 +45,10 @@ static struct platform_device heartbeat_device = { }; /* SMC91x */ +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT, +}; + static struct resource smc91x_eth_resources[] = { [0] = { .name = "smc91x-regs" , @@ -64,6 +69,7 @@ static struct platform_device smc91x_eth_device = { .dev = { .dma_mask = NULL, /* don't use dma */ .coherent_dma_mask = 0xffffffff, + .platform_data = &smc91x_info, }, .num_resources = ARRAY_SIZE(smc91x_eth_resources), .resource = smc91x_eth_resources, diff --git a/arch/sh/boot/compressed/Makefile_32 b/arch/sh/boot/compressed/Makefile_32 index 6ac8d4a4ed1d..c0d25fb1aa60 100644 --- a/arch/sh/boot/compressed/Makefile_32 +++ b/arch/sh/boot/compressed/Makefile_32 @@ -6,7 +6,6 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \ head_32.o misc_32.o piggy.o -EXTRA_AFLAGS := -traditional OBJECTS = $(obj)/head_32.o $(obj)/misc_32.o diff --git a/arch/sh/boot/compressed/Makefile_64 b/arch/sh/boot/compressed/Makefile_64 index 4334f2b86d8f..912f3e205a0d 100644 --- a/arch/sh/boot/compressed/Makefile_64 +++ b/arch/sh/boot/compressed/Makefile_64 @@ -13,7 +13,6 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \ head_64.o misc_64.o cache.o piggy.o -EXTRA_AFLAGS := -traditional OBJECTS := $(obj)/vmlinux_64.lds $(obj)/head_64.o $(obj)/misc_64.o \ $(obj)/cache.o diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c index d6e0e2bdaad5..de45c6a3e33b 100644 --- a/arch/sh/kernel/cpu/irq/intc-sh5.c +++ b/arch/sh/kernel/cpu/irq/intc-sh5.c @@ -184,9 +184,8 @@ int intc_irq_describe(char* p, int irq) void __init plat_irq_setup(void) { - unsigned long long __dummy0, __dummy1=~0x00000000100000f0; + unsigned long long __dummy0, __dummy1=~0x00000000100000f0; unsigned long reg; - unsigned long data; int i; intc_virt = onchip_remap(INTC_BASE, 1024, "INTC"); @@ -196,11 +195,8 @@ void __init plat_irq_setup(void) /* Set default: per-line enable/disable, priority driven ack/eoi */ - for (i = 0; i < NR_INTC_IRQS; i++) { - if (platform_int_priority[i] != NO_PRIORITY) { - irq_desc[i].chip = &intc_irq_type; - } - } + for (i = 0; i < NR_INTC_IRQS; i++) + irq_desc[i].chip = &intc_irq_type; /* Disable all interrupts and set all priorities to 0 to avoid trouble */ @@ -211,35 +207,42 @@ void __init plat_irq_setup(void) ctrl_outl( NO_PRIORITY, reg); - /* Set IRLM */ - /* If all the priorities are set to 'no priority', then - * assume we are using encoded mode. - */ - irlm = platform_int_priority[IRQ_IRL0] + platform_int_priority[IRQ_IRL1] + \ - platform_int_priority[IRQ_IRL2] + platform_int_priority[IRQ_IRL3]; - - if (irlm == NO_PRIORITY) { - /* IRLM = 0 */ - reg = INTC_ICR_CLEAR; - i = IRQ_INTA; - printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); - } else { - /* IRLM = 1 */ - reg = INTC_ICR_SET; - i = IRQ_IRL0; - } - ctrl_outl(INTC_ICR_IRLM, reg); - - /* Set interrupt priorities according to platform description */ - for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { - data |= platform_int_priority[i] << ((i % INTC_INTPRI_PPREG) * 4); - if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { - /* Upon the 7th, set Priority Register */ - ctrl_outl(data, reg); - data = 0; - reg += 8; +#ifdef CONFIG_SH_CAYMAN + { + unsigned long data; + + /* Set IRLM */ + /* If all the priorities are set to 'no priority', then + * assume we are using encoded mode. + */ + irlm = platform_int_priority[IRQ_IRL0] + + platform_int_priority[IRQ_IRL1] + + platform_int_priority[IRQ_IRL2] + + platform_int_priority[IRQ_IRL3]; + if (irlm == NO_PRIORITY) { + /* IRLM = 0 */ + reg = INTC_ICR_CLEAR; + i = IRQ_INTA; + printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); + } else { + /* IRLM = 1 */ + reg = INTC_ICR_SET; + i = IRQ_IRL0; } - } + ctrl_outl(INTC_ICR_IRLM, reg); + + /* Set interrupt priorities according to platform description */ + for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { + data |= platform_int_priority[i] << + ((i % INTC_INTPRI_PPREG) * 4); + if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { + /* Upon the 7th, set Priority Register */ + ctrl_outl(data, reg); + data = 0; + reg += 8; + } + } +#endif /* * And now let interrupts come in. diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c index 84806b2027f8..da5dae787888 100644 --- a/arch/sh/kernel/cpu/irq/intc.c +++ b/arch/sh/kernel/cpu/irq/intc.c @@ -1,7 +1,7 @@ /* * Shared interrupt handling code for IPR and INTC2 types of IRQs. * - * Copyright (C) 2007 Magnus Damm + * Copyright (C) 2007, 2008 Magnus Damm * * Based on intc2.c and ipr.c * @@ -62,6 +62,9 @@ struct intc_desc_int { #endif static unsigned int intc_prio_level[NR_IRQS]; /* for now */ +#ifdef CONFIG_CPU_SH3 +static unsigned long ack_handle[NR_IRQS]; +#endif static inline struct intc_desc_int *get_intc_desc(unsigned int irq) { @@ -98,17 +101,26 @@ static void write_32(unsigned long addr, unsigned long h, unsigned long data) static void modify_8(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outb(set_field(ctrl_inb(addr), data, h), addr); + local_irq_restore(flags); } static void modify_16(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outw(set_field(ctrl_inw(addr), data, h), addr); + local_irq_restore(flags); } static void modify_32(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outl(set_field(ctrl_inl(addr), data, h), addr); + local_irq_restore(flags); } enum { REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 }; @@ -219,6 +231,25 @@ static void intc_disable(unsigned int irq) } } +#ifdef CONFIG_CPU_SH3 +static void intc_mask_ack(unsigned int irq) +{ + struct intc_desc_int *d = get_intc_desc(irq); + unsigned long handle = ack_handle[irq]; + unsigned long addr; + + intc_disable(irq); + + /* read register and write zero only to the assocaited bit */ + + if (handle) { + addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); + ctrl_inb(addr); + ctrl_outb(0x3f ^ set_field(0, 1, handle), addr); + } +} +#endif + static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, unsigned int nr_hp, unsigned int irq) @@ -280,7 +311,12 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { [IRQ_TYPE_EDGE_FALLING] = VALID(0), [IRQ_TYPE_EDGE_RISING] = VALID(1), [IRQ_TYPE_LEVEL_LOW] = VALID(2), + /* SH7706, SH7707 and SH7709 do not support high level triggered */ +#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \ + !defined(CONFIG_CPU_SUBTYPE_SH7707) && \ + !defined(CONFIG_CPU_SUBTYPE_SH7709) [IRQ_TYPE_LEVEL_HIGH] = VALID(3), +#endif }; static int intc_set_sense(unsigned int irq, unsigned int type) @@ -430,6 +466,40 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc, return 0; } +#ifdef CONFIG_CPU_SH3 +static unsigned int __init intc_ack_data(struct intc_desc *desc, + struct intc_desc_int *d, + intc_enum enum_id) +{ + struct intc_mask_reg *mr = desc->ack_regs; + unsigned int i, j, fn, mode; + unsigned long reg_e, reg_d; + + for (i = 0; mr && enum_id && i < desc->nr_ack_regs; i++) { + mr = desc->ack_regs + i; + + for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { + if (mr->enum_ids[j] != enum_id) + continue; + + fn = REG_FN_MODIFY_BASE; + mode = MODE_ENABLE_REG; + reg_e = mr->set_reg; + reg_d = mr->set_reg; + + fn += (mr->reg_width >> 3) - 1; + return _INTC_MK(fn, mode, + intc_get_reg(d, reg_e), + intc_get_reg(d, reg_d), + 1, + (mr->reg_width - 1) - j); + } + } + + return 0; +} +#endif + static unsigned int __init intc_sense_data(struct intc_desc *desc, struct intc_desc_int *d, intc_enum enum_id) @@ -530,6 +600,11 @@ static void __init intc_register_irq(struct intc_desc *desc, /* irq should be disabled by default */ d->chip.mask(irq); + +#ifdef CONFIG_CPU_SH3 + if (desc->ack_regs) + ack_handle[irq] = intc_ack_data(desc, d, enum_id); +#endif } static unsigned int __init save_reg(struct intc_desc_int *d, @@ -560,6 +635,9 @@ void __init register_intc_controller(struct intc_desc *desc) d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0; d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0; +#ifdef CONFIG_CPU_SH3 + d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0; +#endif d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg)); #ifdef CONFIG_SMP d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp)); @@ -592,14 +670,23 @@ void __init register_intc_controller(struct intc_desc *desc) } } - BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ - d->chip.name = desc->name; d->chip.mask = intc_disable; d->chip.unmask = intc_enable; d->chip.mask_ack = intc_disable; d->chip.set_type = intc_set_sense; +#ifdef CONFIG_CPU_SH3 + if (desc->ack_regs) { + for (i = 0; i < desc->nr_ack_regs; i++) + k += save_reg(d, k, desc->ack_regs[i].set_reg, 0); + + d->chip.mask_ack = intc_mask_ack; + } +#endif + + BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ + for (i = 0; i < desc->nr_vectors; i++) { struct intc_vect *vect = desc->vectors + i; diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c index 5627c0b3ffa8..6df2fb98eb30 100644 --- a/arch/sh/kernel/cpu/sh2a/fpu.c +++ b/arch/sh/kernel/cpu/sh2a/fpu.c @@ -300,7 +300,7 @@ static int denormal_addf(int hx, int hy) iy = hy & 0x7fffffff; if (iy < 0x00800000) { ix = denormal_subf1(ix, iy); - if (ix < 0) { + if ((int) ix < 0) { ix = -ix; sign ^= 0x80000000; } @@ -385,7 +385,7 @@ static long long denormal_addd(long long hx, long long hy) iy = hy & 0x7fffffffffffffffLL; if (iy < 0x0010000000000000LL) { ix = denormal_subd1(ix, iy); - if (ix < 0) { + if ((int) ix < 0) { ix = -ix; sign ^= 0x8000000000000000LL; } diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 3ae4d9111f19..511de55af832 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/SuperH SH-3 backends. # -obj-y := ex.o probe.o entry.o +obj-y := ex.o probe.o entry.o setup-sh3.o # CPU subtype setup obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o diff --git a/arch/sh/kernel/cpu/sh3/setup-sh3.c b/arch/sh/kernel/cpu/sh3/setup-sh3.c new file mode 100644 index 000000000000..c98846857855 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/setup-sh3.c @@ -0,0 +1,71 @@ +/* + * Shared SH3 Setup code + * + * Copyright (C) 2008 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/io.h> + +/* All SH3 devices are equipped with IRQ0->5 (except sh7708) */ + +enum { + UNUSED = 0, + + /* interrupt sources */ + IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, +}; + +static struct intc_vect vectors_irq0123[] __initdata = { + INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), + INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), +}; + +static struct intc_vect vectors_irq45[] __initdata = { + INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), +}; + +static struct intc_prio_reg prio_registers[] __initdata = { + { 0xa4000016, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } }, + { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } }, +}; + +static struct intc_mask_reg ack_registers[] __initdata = { + { 0xa4000004, 0, 8, /* IRR0 */ + { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } }, +}; + +static struct intc_sense_reg sense_registers[] __initdata = { + { 0xa4000010, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } }, +}; + +static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh3-irq0123", + vectors_irq0123, NULL, NULL, + prio_registers, sense_registers, ack_registers); + +static DECLARE_INTC_DESC_ACK(intc_desc_irq45, "sh3-irq45", + vectors_irq45, NULL, NULL, + prio_registers, sense_registers, ack_registers); + +#define INTC_ICR1 0xa4000010UL +#define INTC_ICR1_IRQLVL (1<<14) + +void __init plat_irq_setup_pins(int mode) +{ + if (mode == IRQ_MODE_IRQ) { + ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1); + register_intc_controller(&intc_desc_irq0123); + return; + } + BUG(); +} + +void __init plat_irq_setup_sh3(void) +{ + register_intc_controller(&intc_desc_irq45); +} diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index f581534cb732..6468ae86b944 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c @@ -37,7 +37,7 @@ enum { }; static struct intc_vect vectors[] __initdata = { - INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), + /* IRQ0->5 are handled in setup-sh3.c */ INTC_VECT(PINT07, 0x700), INTC_VECT(PINT815, 0x720), INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820), INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860), @@ -48,7 +48,7 @@ static struct intc_vect vectors[] __initdata = { INTC_VECT(ADC_ADI, 0x980), INTC_VECT(USB_USI0, 0xa20), INTC_VECT(USB_USI1, 0xa40), INTC_VECT(TPU0, 0xc00), INTC_VECT(TPU1, 0xc20), - INTC_VECT(TPU3, 0xc80), INTC_VECT(TPU1, 0xca0), + INTC_VECT(TPU2, 0xc80), INTC_VECT(TPU3, 0xca0), INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460), INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0), @@ -81,14 +81,6 @@ static struct intc_prio_reg prio_registers[] __initdata = { static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, groups, NULL, prio_registers, NULL); -static struct intc_vect vectors_irq[] __initdata = { - INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), - INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), -}; - -static DECLARE_INTC_DESC(intc_desc_irq, "sh7705-irq", vectors_irq, NULL, - NULL, prio_registers, NULL); - static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xa4410000, @@ -159,16 +151,8 @@ static int __init sh7705_devices_setup(void) } __initcall(sh7705_devices_setup); -void __init plat_irq_setup_pins(int mode) -{ - if (mode == IRQ_MODE_IRQ) { - register_intc_controller(&intc_desc_irq); - return; - } - BUG(); -} - void __init plat_irq_setup(void) { register_intc_controller(&intc_desc); + plat_irq_setup_sh3(); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c index d3733b13ea52..93c55e2ed952 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c @@ -52,7 +52,7 @@ static struct intc_vect vectors[] __initdata = { #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ defined(CONFIG_CPU_SUBTYPE_SH7707) || \ defined(CONFIG_CPU_SUBTYPE_SH7709) - INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), + /* IRQ0->5 are handled in setup-sh3.c */ INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820), INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860), INTC_VECT(ADC_ADI, 0x980), @@ -104,18 +104,6 @@ static struct intc_prio_reg prio_registers[] __initdata = { static DECLARE_INTC_DESC(intc_desc, "sh770x", vectors, groups, NULL, prio_registers, NULL); -#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -static struct intc_vect vectors_irq[] __initdata = { - INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), - INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), -}; - -static DECLARE_INTC_DESC(intc_desc_irq, "sh770x-irq", vectors_irq, NULL, - NULL, prio_registers, NULL); -#endif - static struct resource rtc_resources[] = { [0] = { .start = 0xfffffec0, @@ -194,24 +182,12 @@ static int __init sh770x_devices_setup(void) } __initcall(sh770x_devices_setup); -#define INTC_ICR1 0xa4000010UL -#define INTC_ICR1_IRQLVL (1<<14) - -void __init plat_irq_setup_pins(int mode) +void __init plat_irq_setup(void) { - if (mode == IRQ_MODE_IRQ) { + register_intc_controller(&intc_desc); #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ defined(CONFIG_CPU_SUBTYPE_SH7707) || \ defined(CONFIG_CPU_SUBTYPE_SH7709) - ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1); - register_intc_controller(&intc_desc_irq); - return; + plat_irq_setup_sh3(); #endif - } - BUG(); -} - -void __init plat_irq_setup(void) -{ - register_intc_controller(&intc_desc); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index 7406c9ad9259..77eee481de47 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c @@ -38,7 +38,7 @@ enum { }; static struct intc_vect vectors[] __initdata = { - INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), + /* IRQ0->5 are handled in setup-sh3.c */ INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820), INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860), INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0), @@ -79,10 +79,7 @@ static struct intc_prio_reg prio_registers[] __initdata = { { 0xa4000016, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } }, { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } }, { 0xa400001a, 0, 16, 4, /* IPRE */ { DMAC1, SCIF0, SCIF1 } }, - { 0xa4080000, 0, 16, 4, /* IPRF */ { 0, DMAC2 } }, -#ifdef CONFIG_CPU_SUBTYPE_SH7710 - { 0xa4080000, 0, 16, 4, /* IPRF */ { IPSEC } }, -#endif + { 0xa4080000, 0, 16, 4, /* IPRF */ { IPSEC, DMAC2 } }, { 0xa4080002, 0, 16, 4, /* IPRG */ { EDMAC0, EDMAC1, EDMAC2 } }, { 0xa4080004, 0, 16, 4, /* IPRH */ { 0, 0, 0, SIOF0 } }, { 0xa4080006, 0, 16, 4, /* IPRI */ { 0, 0, SIOF1 } }, @@ -91,14 +88,6 @@ static struct intc_prio_reg prio_registers[] __initdata = { static DECLARE_INTC_DESC(intc_desc, "sh7710", vectors, groups, NULL, prio_registers, NULL); -static struct intc_vect vectors_irq[] __initdata = { - INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), - INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), -}; - -static DECLARE_INTC_DESC(intc_desc_irq, "sh7710-irq", vectors_irq, NULL, - NULL, prio_registers, NULL); - static struct resource rtc_resources[] = { [0] = { .start = 0xa413fec0, @@ -170,16 +159,8 @@ static int __init sh7710_devices_setup(void) } __initcall(sh7710_devices_setup); -void __init plat_irq_setup_pins(int mode) -{ - if (mode == IRQ_MODE_IRQ) { - register_intc_controller(&intc_desc_irq); - return; - } - BUG(); -} - void __init plat_irq_setup(void) { register_intc_controller(&intc_desc); + plat_irq_setup_sh3(); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c index 8028082527c5..f807a21b066c 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c @@ -19,10 +19,6 @@ #include <linux/serial_sci.h> #include <asm/rtc.h> -#define INTC_ICR1 0xA4140010UL -#define INTC_ICR_IRLM 0x4000 -#define INTC_ICR_IRQ (~INTC_ICR_IRLM) - static struct resource rtc_resources[] = { [0] = { .start = 0xa413fec0, @@ -170,6 +166,7 @@ enum { }; static struct intc_vect vectors[] __initdata = { + /* IRQ0->5 are handled in setup-sh3.c */ INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), INTC_VECT(TMU2, 0x440), INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0), INTC_VECT(RTC_CUI, 0x4c0), @@ -214,11 +211,7 @@ static struct intc_prio_reg prio_registers[] __initdata = { { 0xA414FEE4UL, 0, 16, 4, /* IPRB */ { WDT, REF_RCMI, SIM, 0 } }, { 0xA4140016UL, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } }, { 0xA4140018UL, 0, 16, 4, /* IPRD */ { USBF_SPD, TMU_SUNI, IRQ5, IRQ4 } }, -#if defined(CONFIG_CPU_SUBTYPE_SH7720) { 0xA414001AUL, 0, 16, 4, /* IPRE */ { DMAC1, 0, LCDC, SSL } }, -#else - { 0xA414001AUL, 0, 16, 4, /* IPRE */ { DMAC1, 0, LCDC, 0 } }, -#endif { 0xA4080000UL, 0, 16, 4, /* IPRF */ { ADC, DMAC2, USBFI, CMT } }, { 0xA4080002UL, 0, 16, 4, /* IPRG */ { SCIF0, SCIF1, 0, 0 } }, { 0xA4080004UL, 0, 16, 4, /* IPRH */ { PINT07, PINT815, TPU, IIC } }, @@ -229,32 +222,8 @@ static struct intc_prio_reg prio_registers[] __initdata = { static DECLARE_INTC_DESC(intc_desc, "sh7720", vectors, groups, NULL, prio_registers, NULL); -static struct intc_sense_reg sense_registers[] __initdata = { - { INTC_ICR1, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } }, -}; - -static struct intc_vect vectors_irq[] __initdata = { - INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), - INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), - INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), -}; - -static DECLARE_INTC_DESC(intc_irq_desc, "sh7720-irq", vectors_irq, - NULL, NULL, prio_registers, sense_registers); - -void __init plat_irq_setup_pins(int mode) -{ - switch (mode) { - case IRQ_MODE_IRQ: - ctrl_outw(ctrl_inw(INTC_ICR1) & INTC_ICR_IRQ, INTC_ICR1); - register_intc_controller(&intc_irq_desc); - break; - default: - BUG(); - } -} - void __init plat_irq_setup(void) { register_intc_controller(&intc_desc); + plat_irq_setup_sh3(); } diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index ba8750176d91..05372ed6c568 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -143,12 +143,22 @@ resvec_save_area: trap_jtable: .long do_exception_error /* 0x000 */ .long do_exception_error /* 0x020 */ +#ifdef CONFIG_MMU .long tlb_miss_load /* 0x040 */ .long tlb_miss_store /* 0x060 */ +#else + .long do_exception_error + .long do_exception_error +#endif ! ARTIFICIAL pseudo-EXPEVT setting .long do_debug_interrupt /* 0x080 */ +#ifdef CONFIG_MMU .long tlb_miss_load /* 0x0A0 */ .long tlb_miss_store /* 0x0C0 */ +#else + .long do_exception_error + .long do_exception_error +#endif .long do_address_error_load /* 0x0E0 */ .long do_address_error_store /* 0x100 */ #ifdef CONFIG_SH_FPU @@ -185,10 +195,18 @@ trap_jtable: .endr .long do_IRQ /* 0xA00 */ .long do_IRQ /* 0xA20 */ +#ifdef CONFIG_MMU .long itlb_miss_or_IRQ /* 0xA40 */ +#else + .long do_IRQ +#endif .long do_IRQ /* 0xA60 */ .long do_IRQ /* 0xA80 */ +#ifdef CONFIG_MMU .long itlb_miss_or_IRQ /* 0xAA0 */ +#else + .long do_IRQ +#endif .long do_exception_error /* 0xAC0 */ .long do_address_error_exec /* 0xAE0 */ .rept 8 @@ -274,6 +292,7 @@ not_a_tlb_miss: * Instead of '.space 1024-TEXT_SIZE' place the RESVEC * block making sure the final alignment is correct. */ +#ifdef CONFIG_MMU tlb_miss: synco /* TAKum03020 (but probably a good idea anyway.) */ putcon SP, KCR1 @@ -377,6 +396,9 @@ fixup_to_invoke_general_handler: getcon KCR1, SP pta handle_exception, tr0 blink tr0, ZERO +#else /* CONFIG_MMU */ + .balign 256 +#endif /* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE DOES END UP AT VBR+0x600 */ @@ -1103,6 +1125,7 @@ restore_all: * fpu_error_or_IRQ? is a helper to deflect to the right cause. * */ +#ifdef CONFIG_MMU tlb_miss_load: or SP, ZERO, r2 or ZERO, ZERO, r3 /* Read */ @@ -1132,6 +1155,7 @@ call_do_page_fault: movi do_page_fault, r6 ptabs r6, tr0 blink tr0, ZERO +#endif /* CONFIG_MMU */ fpu_error_or_IRQA: pta its_IRQ, tr0 @@ -1481,6 +1505,7 @@ poke_real_address_q: ptabs LINK, tr0 blink tr0, r63 +#ifdef CONFIG_MMU /* * --- User Access Handling Section */ @@ -1604,6 +1629,7 @@ ___clear_user_exit: ptabs LINK, tr0 blink tr0, ZERO +#endif /* CONFIG_MMU */ /* * int __strncpy_from_user(unsigned long __dest, unsigned long __src, @@ -2014,9 +2040,11 @@ sa_default_restorer: .global asm_uaccess_start /* Just a marker */ asm_uaccess_start: +#ifdef CONFIG_MMU .long ___copy_user1, ___copy_user_exit .long ___copy_user2, ___copy_user_exit .long ___clear_user1, ___clear_user_exit +#endif .long ___strncpy_from_user1, ___strncpy_from_user_exit .long ___strnlen_user1, ___strnlen_user_exit .long ___get_user_asm_b1, ___get_user_asm_b_exit diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c index 31f8cb0f6374..92ad844b5c12 100644 --- a/arch/sh/kernel/cpu/sh5/probe.c +++ b/arch/sh/kernel/cpu/sh5/probe.c @@ -15,6 +15,7 @@ #include <linux/string.h> #include <asm/processor.h> #include <asm/cache.h> +#include <asm/tlb.h> int __init detect_cpu_and_cache_system(void) { @@ -67,5 +68,8 @@ int __init detect_cpu_and_cache_system(void) set_bit(SH_CACHE_MODE_WB, &(boot_cpu_data.dcache.flags)); #endif + /* Setup some I/D TLB defaults */ + sh64_tlb_init(); + return 0; } diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index 957f25611543..6b7d166694e2 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c @@ -141,7 +141,9 @@ static void scif_sercon_init(char *s) */ static void scif_sercon_init(char *s) { + struct uart_port *port = &scif_port; unsigned baud = DEFAULT_BAUD; + unsigned int status; char *e; if (*s == ',') @@ -160,19 +162,25 @@ static void scif_sercon_init(char *s) baud = DEFAULT_BAUD; } - ctrl_outw(0, scif_port.mapbase + 8); - ctrl_outw(0, scif_port.mapbase); + do { + status = sci_in(port, SCxSR); + } while (!(status & SCxSR_TEND(port))); + + sci_out(port, SCSCR, 0); /* TE=0, RE=0 */ + sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); + sci_out(port, SCSMR, 0); /* Set baud rate */ - ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) / - (32 * baud) - 1, scif_port.mapbase + 4); - - ctrl_outw(12, scif_port.mapbase + 24); - ctrl_outw(8, scif_port.mapbase + 24); - ctrl_outw(0, scif_port.mapbase + 32); - ctrl_outw(0x60, scif_port.mapbase + 16); - ctrl_outw(0, scif_port.mapbase + 36); - ctrl_outw(0x30, scif_port.mapbase + 8); + sci_out(port, SCBRR, (CONFIG_SH_PCLK_FREQ + 16 * baud) / + (32 * baud) - 1); + udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ + + sci_out(port, SCSPTR, 0); + sci_out(port, SCxSR, 0x60); + sci_out(port, SCLSR, 0); + + sci_out(port, SCFCR, 0); + sci_out(port, SCSCR, 0x30); /* TE=1, RE=1 */ } #endif /* defined(CONFIG_CPU_SUBTYPE_SH7720) */ #endif /* !defined(CONFIG_SH_STANDARD_BIOS) */ diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 284f66f1ebbe..516bde9c50fa 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -53,6 +53,7 @@ EXPORT_SYMBOL(cpu_data); * sh_mv= on the command line, prior to .machvec.init teardown. */ struct sh_machine_vector sh_mv = { .mv_name = "generic", }; +EXPORT_SYMBOL(sh_mv); #ifdef CONFIG_VT struct screen_info screen_info; @@ -76,11 +77,18 @@ static struct resource data_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_MEM, }; +static struct resource bss_resource = { + .name = "Kernel bss", + .flags = IORESOURCE_BUSY | IORESOURCE_MEM, +}; + unsigned long memory_start; EXPORT_SYMBOL(memory_start); unsigned long memory_end = 0; EXPORT_SYMBOL(memory_end); +static struct resource mem_resources[MAX_NUMNODES]; + int l1i_cache_shape, l1d_cache_shape, l2_cache_shape; static int __init early_parse_mem(char *p) @@ -169,6 +177,40 @@ static inline void __init reserve_crashkernel(void) {} #endif +void __init __add_active_range(unsigned int nid, unsigned long start_pfn, + unsigned long end_pfn) +{ + struct resource *res = &mem_resources[nid]; + + WARN_ON(res->name); /* max one active range per node for now */ + + res->name = "System RAM"; + res->start = start_pfn << PAGE_SHIFT; + res->end = (end_pfn << PAGE_SHIFT) - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&iomem_resource, res)) { + pr_err("unable to request memory_resource 0x%lx 0x%lx\n", + start_pfn, end_pfn); + return; + } + + /* + * We don't know which RAM region contains kernel data, + * so we try it repeatedly and let the resource manager + * test it. + */ + request_resource(res, &code_resource); + request_resource(res, &data_resource); + request_resource(res, &bss_resource); + +#ifdef CONFIG_KEXEC + if (crashk_res.start != crashk_res.end) + request_resource(res, &crashk_res); +#endif + + add_active_range(nid, start_pfn, end_pfn); +} + void __init setup_bootmem_allocator(unsigned long free_pfn) { unsigned long bootmap_size; @@ -181,7 +223,7 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn, min_low_pfn, max_low_pfn); - add_active_range(0, min_low_pfn, max_low_pfn); + __add_active_range(0, min_low_pfn, max_low_pfn); register_bootmem_low_pages(); node_set_online(0); @@ -267,6 +309,8 @@ void __init setup_arch(char **cmdline_p) code_resource.end = virt_to_phys(_etext)-1; data_resource.start = virt_to_phys(_etext); data_resource.end = virt_to_phys(_edata)-1; + bss_resource.start = virt_to_phys(__bss_start); + bss_resource.end = virt_to_phys(_ebss)-1; memory_start = (unsigned long)__va(__MEMORY_START); if (!memory_end) diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 6d405462cee8..8f916536719c 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -20,8 +20,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); extern struct hw_interrupt_type no_irq_type; -EXPORT_SYMBOL(sh_mv); - /* platform dependent support */ EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(kernel_thread); diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index a310c9707f03..9324d32adacc 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c @@ -16,6 +16,7 @@ #include <linux/in6.h> #include <linux/interrupt.h> #include <linux/screen_info.h> +#include <asm/cacheflush.h> #include <asm/processor.h> #include <asm/uaccess.h> #include <asm/checksum.h> @@ -29,25 +30,50 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(kernel_thread); +#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) +EXPORT_SYMBOL(clear_user_page); +#endif + +#ifndef CONFIG_CACHE_OFF +EXPORT_SYMBOL(flush_dcache_page); +#endif + /* Networking helper routines. */ +EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_nocheck); +#ifdef CONFIG_IPV6 +EXPORT_SYMBOL(csum_ipv6_magic); +#endif #ifdef CONFIG_VT EXPORT_SYMBOL(screen_info); #endif +EXPORT_SYMBOL(__put_user_asm_b); +EXPORT_SYMBOL(__put_user_asm_w); EXPORT_SYMBOL(__put_user_asm_l); +EXPORT_SYMBOL(__put_user_asm_q); +EXPORT_SYMBOL(__get_user_asm_b); +EXPORT_SYMBOL(__get_user_asm_w); EXPORT_SYMBOL(__get_user_asm_l); +EXPORT_SYMBOL(__get_user_asm_q); +EXPORT_SYMBOL(__strnlen_user); +EXPORT_SYMBOL(__strncpy_from_user); +EXPORT_SYMBOL(clear_page); +EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); +EXPORT_SYMBOL(__const_udelay); /* Ugh. These come in from libgcc.a at link time. */ #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) DECLARE_EXPORT(__sdivsi3); +DECLARE_EXPORT(__sdivsi3_2); DECLARE_EXPORT(__muldi3); DECLARE_EXPORT(__udivsi3); +DECLARE_EXPORT(__div_table); diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c index 898977ee2030..022a55f1c1d4 100644 --- a/arch/sh/kernel/time_64.c +++ b/arch/sh/kernel/time_64.c @@ -172,6 +172,7 @@ void do_gettimeofday(struct timeval *tv) tv->tv_sec = sec; tv->tv_usec = usec; } +EXPORT_SYMBOL(do_gettimeofday); int do_settimeofday(struct timespec *tv) { @@ -240,7 +241,7 @@ static inline void do_timer_interrupt(void) * the irq version of write_lock because as just said we have irq * locally disabled. -arca */ - write_lock(&xtime_lock); + write_seqlock(&xtime_lock); asm ("getcon cr62, %0" : "=r" (current_ctc)); ctc_last_interrupt = (unsigned long) current_ctc; @@ -266,7 +267,7 @@ static inline void do_timer_interrupt(void) /* do it again in 60 s */ last_rtc_update = xtime.tv_sec - 600; } - write_unlock(&xtime_lock); + write_sequnlock(&xtime_lock); #ifndef CONFIG_SMP update_process_times(user_mode(get_irq_regs())); diff --git a/arch/sh/lib64/dbg.c b/arch/sh/lib64/dbg.c index 75825ef6e084..2fb8eaf6de60 100644 --- a/arch/sh/lib64/dbg.c +++ b/arch/sh/lib64/dbg.c @@ -186,8 +186,8 @@ void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs) rr->pc = regs->pc; if (sp < stack_bottom + 3092) { - printk("evt_debug : stack underflow report\n"); int i, j; + printk("evt_debug : stack underflow report\n"); for (j=0, i = event_ptr; j<16; j++) { rr = event_ring + i; printk("evt=%08x event=%08x tra=%08x pid=%5d sp=%08lx pc=%08lx\n", diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64 index cbd6aa33c5ac..0d92a8a3ac9a 100644 --- a/arch/sh/mm/Makefile_64 +++ b/arch/sh/mm/Makefile_64 @@ -2,10 +2,11 @@ # Makefile for the Linux SuperH-specific parts of the memory manager. # -obj-y := init.o extable_64.o consistent.o +obj-y := init.o consistent.o -mmu-y := tlb-nommu.o pg-nommu.o -mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o +mmu-y := tlb-nommu.o pg-nommu.o extable_32.o +mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o \ + extable_64.o ifndef CONFIG_CACHE_OFF obj-y += cache-sh5.o diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c index 3877321fcede..9e277ec7d536 100644 --- a/arch/sh/mm/cache-sh5.c +++ b/arch/sh/mm/cache-sh5.c @@ -714,6 +714,7 @@ void flush_cache_sigtramp(unsigned long vaddr) sh64_icache_inv_current_user_range(vaddr, end); } +#ifdef CONFIG_MMU /* * These *MUST* lie in an area of virtual address space that's otherwise * unused. @@ -830,3 +831,4 @@ void clear_user_page(void *to, unsigned long address, struct page *page) else sh64_clear_user_page_coloured(to, address); } +#endif diff --git a/arch/sh/mm/ioremap_64.c b/arch/sh/mm/ioremap_64.c index cea224c3e49b..6e0be24d26e2 100644 --- a/arch/sh/mm/ioremap_64.c +++ b/arch/sh/mm/ioremap_64.c @@ -343,6 +343,7 @@ unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *n return shmedia_alloc_io(phys, size, name); } +EXPORT_SYMBOL(onchip_remap); void onchip_unmap(unsigned long vaddr) { @@ -370,6 +371,7 @@ void onchip_unmap(unsigned long vaddr) kfree(res); } } +EXPORT_SYMBOL(onchip_unmap); #ifdef CONFIG_PROC_FS static int diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c index 2de7302724fc..1663199ce888 100644 --- a/arch/sh/mm/numa.c +++ b/arch/sh/mm/numa.c @@ -59,7 +59,7 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end) free_pfn = start_pfn = start >> PAGE_SHIFT; end_pfn = end >> PAGE_SHIFT; - add_active_range(nid, start_pfn, end_pfn); + __add_active_range(nid, start_pfn, end_pfn); /* Node-local pgdat */ NODE_DATA(nid) = pfn_to_kaddr(free_pfn); diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 987c6682bf99..1bba7d36be90 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -28,7 +28,6 @@ HD64465 HD64465 7751SYSTEMH SH_7751_SYSTEMH HP6XX SH_HP6XX DREAMCAST SH_DREAMCAST -MPC1211 SH_MPC1211 SNAPGEAR SH_SECUREEDGE5410 EDOSK7705 SH_EDOSK7705 SH4202_MICRODEV SH_SH4202_MICRODEV diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bbcafaa160c0..fe361ae7ef2f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -335,6 +335,7 @@ config X86_RDC321X select GENERIC_GPIO select LEDS_CLASS select LEDS_GPIO + select NEW_LEDS help This option is needed for RDC R-321x system-on-chip, also known as R-8610-(G). @@ -1662,7 +1663,6 @@ config GEODE_MFGPT_TIMER config OLPC bool "One Laptop Per Child support" - depends on MGEODE_LX default n help Add support for detecting the unique features of the OLPC diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 238468ae1993..c2e1ce33c7cb 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -6,6 +6,7 @@ #include <linux/cpu.h> +#include <asm/pat.h> #include <asm/processor.h> struct cpuid_bit { @@ -48,3 +49,23 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) set_cpu_cap(c, cb->feature); } } + +#ifdef CONFIG_X86_PAT +void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) +{ + switch (c->x86_vendor) { + case X86_VENDOR_AMD: + if (c->x86 >= 0xf && c->x86 <= 0x11) + return; + break; + case X86_VENDOR_INTEL: + if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) + return; + break; + } + + pat_disable(cpu_has_pat ? + "PAT disabled. Not yet verified on this CPU type." : + "PAT not supported by CPU."); +} +#endif diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 35b4f6a9c8ef..d0463a946247 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -12,6 +12,7 @@ #include <asm/mmu_context.h> #include <asm/mtrr.h> #include <asm/mce.h> +#include <asm/pat.h> #ifdef CONFIG_X86_LOCAL_APIC #include <asm/mpspec.h> #include <asm/apic.h> @@ -308,19 +309,6 @@ static void __cpuinit early_get_cap(struct cpuinfo_x86 *c) } - clear_cpu_cap(c, X86_FEATURE_PAT); - - switch (c->x86_vendor) { - case X86_VENDOR_AMD: - if (c->x86 >= 0xf && c->x86 <= 0x11) - set_cpu_cap(c, X86_FEATURE_PAT); - break; - case X86_VENDOR_INTEL: - if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) - set_cpu_cap(c, X86_FEATURE_PAT); - break; - } - } /* @@ -409,18 +397,6 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) init_scattered_cpuid_features(c); } - clear_cpu_cap(c, X86_FEATURE_PAT); - - switch (c->x86_vendor) { - case X86_VENDOR_AMD: - if (c->x86 >= 0xf && c->x86 <= 0x11) - set_cpu_cap(c, X86_FEATURE_PAT); - break; - case X86_VENDOR_INTEL: - if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) - set_cpu_cap(c, X86_FEATURE_PAT); - break; - } } static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) @@ -651,6 +627,7 @@ void __init early_cpu_init(void) cpu_devs[cvdev->vendor] = cvdev->cpu_dev; early_cpu_detect(); + validate_pat_support(&boot_cpu_data); } /* Make sure %fs is initialized properly in idle threads */ diff --git a/arch/x86/kernel/geode_32.c b/arch/x86/kernel/geode_32.c index 9dad6ca6cd70..e8edd63ab000 100644 --- a/arch/x86/kernel/geode_32.c +++ b/arch/x86/kernel/geode_32.c @@ -161,6 +161,25 @@ void geode_gpio_setup_event(unsigned int gpio, int pair, int pme) } EXPORT_SYMBOL_GPL(geode_gpio_setup_event); +int geode_has_vsa2(void) +{ + static int has_vsa2 = -1; + + if (has_vsa2 == -1) { + /* + * The VSA has virtual registers that we can query for a + * signature. + */ + outw(VSA_VR_UNLOCK, VSA_VRC_INDEX); + outw(VSA_VR_SIGNATURE, VSA_VRC_INDEX); + + has_vsa2 = (inw(VSA_VRC_DATA) == VSA_SIG); + } + + return has_vsa2; +} +EXPORT_SYMBOL_GPL(geode_has_vsa2); + static int __init geode_southbridge_init(void) { if (!is_geode()) diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index db6839b53195..e03cc952f233 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -450,7 +450,6 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) { struct task_struct *tsk = current; - clear_fpu(tsk); return __copy_from_user(&tsk->thread.xstate->fsave, buf, sizeof(struct i387_fsave_struct)); } @@ -461,7 +460,6 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) struct user_i387_ia32_struct env; int err; - clear_fpu(tsk); err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], sizeof(struct i387_fxsave_struct)); /* mxcsr reserved bits must be masked to zero for security reasons */ @@ -478,6 +476,16 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf) int err; if (HAVE_HWFP) { + struct task_struct *tsk = current; + + clear_fpu(tsk); + + if (!used_math()) { + err = init_fpu(tsk); + if (err) + return err; + } + if (cpu_has_fxsr) err = restore_i387_fxsave(buf); else diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index cc6f5eb20b24..c0c68c18a788 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -95,7 +95,7 @@ void __init setup_per_cpu_areas(void) /* Copy section for each CPU (we discard the original) */ size = PERCPU_ENOUGH_ROOM; - printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n", + printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size); for_each_possible_cpu(i) { diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 2283422af794..2c5f8b213e86 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -127,7 +127,12 @@ static struct resource standard_io_resources[] = { { }, { .name = "keyboard", .start = 0x0060, - .end = 0x006f, + .end = 0x0060, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "keyboard", + .start = 0x0064, + .end = 0x0064, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "dma page reg", diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 22c14e21c97c..f2fc8feb727d 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -70,6 +70,7 @@ #include <asm/ds.h> #include <asm/topology.h> #include <asm/trampoline.h> +#include <asm/pat.h> #include <mach_apic.h> #ifdef CONFIG_PARAVIRT @@ -128,7 +129,9 @@ static struct resource standard_io_resources[] = { .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "timer1", .start = 0x50, .end = 0x53, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, - { .name = "keyboard", .start = 0x60, .end = 0x6f, + { .name = "keyboard", .start = 0x60, .end = 0x60, + .flags = IORESOURCE_BUSY | IORESOURCE_IO }, + { .name = "keyboard", .start = 0x64, .end = 0x64, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "dma page reg", .start = 0x80, .end = 0x8f, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, @@ -1063,25 +1066,19 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) if (c->extended_cpuid_level >= 0x80000007) c->x86_power = cpuid_edx(0x80000007); - - clear_cpu_cap(c, X86_FEATURE_PAT); - switch (c->x86_vendor) { case X86_VENDOR_AMD: early_init_amd(c); - if (c->x86 >= 0xf && c->x86 <= 0x11) - set_cpu_cap(c, X86_FEATURE_PAT); break; case X86_VENDOR_INTEL: early_init_intel(c); - if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) - set_cpu_cap(c, X86_FEATURE_PAT); break; case X86_VENDOR_CENTAUR: early_init_centaur(c); break; } + validate_pat_support(c); } /* diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 277446cd30b6..60adbe22efa0 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -25,31 +25,24 @@ #include <asm/mtrr.h> #include <asm/io.h> -int pat_wc_enabled = 1; +#ifdef CONFIG_X86_PAT +int __read_mostly pat_wc_enabled = 1; -static u64 __read_mostly boot_pat_state; - -static int nopat(char *str) +void __init pat_disable(char *reason) { pat_wc_enabled = 0; - printk(KERN_INFO "x86: PAT support disabled.\n"); - - return 0; + printk(KERN_INFO "%s\n", reason); } -early_param("nopat", nopat); -static int pat_known_cpu(void) +static int nopat(char *str) { - if (!pat_wc_enabled) - return 0; - - if (cpu_has_pat) - return 1; - - pat_wc_enabled = 0; - printk(KERN_INFO "CPU and/or kernel does not support PAT.\n"); + pat_disable("PAT support disabled."); return 0; } +early_param("nopat", nopat); +#endif + +static u64 __read_mostly boot_pat_state; enum { PAT_UC = 0, /* uncached */ @@ -66,17 +59,19 @@ void pat_init(void) { u64 pat; -#ifndef CONFIG_X86_PAT - nopat(NULL); -#endif - - /* Boot CPU enables PAT based on CPU feature */ - if (!smp_processor_id() && !pat_known_cpu()) + if (!pat_wc_enabled) return; - /* APs enable PAT iff boot CPU has enabled it before */ - if (smp_processor_id() && !pat_wc_enabled) - return; + /* Paranoia check. */ + if (!cpu_has_pat) { + printk(KERN_ERR "PAT enabled, but CPU feature cleared\n"); + /* + * Panic if this happens on the secondary CPU, and we + * switched to PAT on the boot CPU. We have no way to + * undo PAT. + */ + BUG_ON(boot_pat_state); + } /* Set PWT to Write-Combining. All other bits stay the same */ /* @@ -95,9 +90,8 @@ void pat_init(void) PAT(4,WB) | PAT(5,WC) | PAT(6,UC_MINUS) | PAT(7,UC); /* Boot CPU check */ - if (!smp_processor_id()) { + if (!boot_pat_state) rdmsrl(MSR_IA32_CR_PAT, boot_pat_state); - } wrmsrl(MSR_IA32_CR_PAT, pat); printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n", diff --git a/arch/x86/pci/k8-bus_64.c b/arch/x86/pci/k8-bus_64.c index ab6d4b18a88f..5c2799c20e47 100644 --- a/arch/x86/pci/k8-bus_64.c +++ b/arch/x86/pci/k8-bus_64.c @@ -504,14 +504,6 @@ static int __init early_fill_mp_bus_info(void) } } -#ifdef CONFIG_NUMA - for (i = 0; i < BUS_NR; i++) { - node = mp_bus_to_node[i]; - if (node >= 0) - printk(KERN_DEBUG "bus: %02x to node: %02x\n", i, node); - } -#endif - for (i = 0; i < pci_root_num; i++) { int res_num; int busnum; |