diff options
Diffstat (limited to 'arch/mips')
66 files changed, 808 insertions, 546 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 705a7a9170f..fd7620f025f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1,6 +1,7 @@ config MIPS bool default y + select HAVE_GENERIC_DMA_COHERENT select HAVE_IDE select HAVE_OPROFILE select HAVE_ARCH_KGDB @@ -357,7 +358,14 @@ config SGI_IP22 select SWAP_IO_SPACE select SYS_HAS_CPU_R4X00 select SYS_HAS_CPU_R5000 - select SYS_HAS_EARLY_PRINTK + # + # Disable EARLY_PRINTK for now since it leads to overwritten prom + # memory during early boot on some machines. + # + # See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com + # for a more details discussion + # + # select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN @@ -409,7 +417,14 @@ config SGI_IP28 select SGI_HAS_ZILOG select SWAP_IO_SPACE select SYS_HAS_CPU_R10000 - select SYS_HAS_EARLY_PRINTK + # + # Disable EARLY_PRINTK for now since it leads to overwritten prom + # memory during early boot on some machines. + # + # See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com + # for a more details discussion + # + # select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN help @@ -1012,9 +1027,9 @@ config BOOT_ELF32 config MIPS_L1_CACHE_SHIFT int - default "4" if MACH_DECSTATION || MIKROTIK_RB532 + default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL + default "6" if MIPS_CPU_SCACHE default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON - default "4" if PMC_MSP4200_EVAL default "5" config HAVE_STD_PC_SERIAL_PORT @@ -1438,6 +1453,7 @@ choice config PAGE_SIZE_4KB bool "4kB" + depends on !CPU_LOONGSON2 help This option select the standard 4kB Linux page size. On some R3000-family processors this is the only available page size. Using @@ -1762,7 +1778,7 @@ config SYS_SUPPORTS_SMARTMIPS config ARCH_FLATMEM_ENABLE def_bool y - depends on !NUMA + depends on !NUMA && !CPU_LOONGSON2 config ARCH_DISCONTIGMEM_ENABLE bool diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c index c88c821b4c3..d670928afcf 100644 --- a/arch/mips/alchemy/common/irq.c +++ b/arch/mips/alchemy/common/irq.c @@ -354,6 +354,28 @@ static void au1x_ic1_ack(unsigned int irq_nr) au_sync(); } +static void au1x_ic0_maskack(unsigned int irq_nr) +{ + unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; + + au_writel(1 << bit, IC0_WAKECLR); + au_writel(1 << bit, IC0_MASKCLR); + au_writel(1 << bit, IC0_RISINGCLR); + au_writel(1 << bit, IC0_FALLINGCLR); + au_sync(); +} + +static void au1x_ic1_maskack(unsigned int irq_nr) +{ + unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; + + au_writel(1 << bit, IC1_WAKECLR); + au_writel(1 << bit, IC1_MASKCLR); + au_writel(1 << bit, IC1_RISINGCLR); + au_writel(1 << bit, IC1_FALLINGCLR); + au_sync(); +} + static int au1x_ic1_setwake(unsigned int irq, unsigned int on) { unsigned int bit = irq - AU1000_INTC1_INT_BASE; @@ -379,25 +401,21 @@ static int au1x_ic1_setwake(unsigned int irq, unsigned int on) /* * irq_chips for both ICs; this way the mask handlers can be * as short as possible. - * - * NOTE: the ->ack() callback is used by the handle_edge_irq - * flowhandler only, the ->mask_ack() one by handle_level_irq, - * so no need for an irq_chip for each type of irq (level/edge). */ static struct irq_chip au1x_ic0_chip = { .name = "Alchemy-IC0", - .ack = au1x_ic0_ack, /* edge */ + .ack = au1x_ic0_ack, .mask = au1x_ic0_mask, - .mask_ack = au1x_ic0_mask, /* level */ + .mask_ack = au1x_ic0_maskack, .unmask = au1x_ic0_unmask, .set_type = au1x_ic_settype, }; static struct irq_chip au1x_ic1_chip = { .name = "Alchemy-IC1", - .ack = au1x_ic1_ack, /* edge */ + .ack = au1x_ic1_ack, .mask = au1x_ic1_mask, - .mask_ack = au1x_ic1_mask, /* level */ + .mask_ack = au1x_ic1_maskack, .unmask = au1x_ic1_unmask, .set_type = au1x_ic_settype, .set_wake = au1x_ic1_setwake, diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c index cc32c69a74a..45b61c9b82b 100644 --- a/arch/mips/alchemy/mtx-1/board_setup.c +++ b/arch/mips/alchemy/mtx-1/board_setup.c @@ -69,6 +69,7 @@ void __init board_setup(void) #else au_writel(0xf, Au1500_PCI_CFG); #endif + board_pci_idsel = mtx1_pci_idsel; #endif /* Initialize sys_pinfunc */ @@ -85,8 +86,6 @@ void __init board_setup(void) alchemy_gpio_direction_output(211, 1); /* green on */ alchemy_gpio_direction_output(212, 0); /* red off */ - board_pci_idsel = mtx1_pci_idsel; - printk(KERN_INFO "4G Systems MTX-1 Board\n"); } diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index e2278c04459..835f3f0319c 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -503,6 +503,7 @@ static int __init ar7_register_devices(void) { u16 chip_id; int res; + u32 *bootcr, val; #ifdef CONFIG_SERIAL_8250 static struct uart_port uart_port[2]; @@ -595,7 +596,13 @@ static int __init ar7_register_devices(void) ar7_wdt_res.end = ar7_wdt_res.start + 0x20; - res = platform_device_register(&ar7_wdt); + bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); + val = *bootcr; + iounmap(bootcr); + + /* Register watchdog only if enabled in hardware */ + if (val & AR7_WDT_HW_ENA) + res = platform_device_register(&ar7_wdt); return res; } diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c index 079e33d5278..fb284c3b2cf 100644 --- a/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c @@ -100,7 +100,7 @@ static __init void prom_init_console(void) static __init void prom_init_cmdline(void) { - char buf[CL_SIZE]; + static char buf[CL_SIZE] __initdata; /* Get the kernel command line from CFE */ if (cfe_getenv("LINUX_CMDLINE", buf, CL_SIZE) >= 0) { diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile index c146d1edede..00064b66080 100644 --- a/arch/mips/bcm63xx/Makefile +++ b/arch/mips/bcm63xx/Makefile @@ -1,5 +1,5 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ - dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o + dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += boards/ diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 78e155d21be..05a35cf5963 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -24,7 +24,6 @@ #include <bcm63xx_dev_enet.h> #include <bcm63xx_dev_dsp.h> #include <bcm63xx_dev_pcmcia.h> -#include <bcm63xx_dev_uart.h> #include <board_bcm963xx.h> #define PFX "board_bcm963xx: " @@ -794,8 +793,6 @@ int __init board_register_devices(void) { u32 val; - bcm63xx_uart_register(); - if (board.has_pccard) bcm63xx_pcmcia_register(); diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index 6dc43f0483e..70378bb5e3f 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/cpu.h> +#include <asm/cpu-info.h> #include <bcm63xx_cpu.h> #include <bcm63xx_regs.h> #include <bcm63xx_io.h> @@ -284,6 +285,7 @@ void __init bcm63xx_cpu_init(void) { unsigned int tmp, expected_cpu_id; struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int cpu = smp_processor_id(); /* soc registers location depends on cpu type */ expected_cpu_id = 0; @@ -293,6 +295,7 @@ void __init bcm63xx_cpu_init(void) * BCM6338 as the same PrId as BCM3302 see arch/mips/kernel/cpu-probe.c */ case CPU_BCM3302: + __cpu_name[cpu] = "Broadcom BCM6338"; expected_cpu_id = BCM6338_CPU_ID; bcm63xx_regs_base = bcm96338_regs_base; bcm63xx_irqs = bcm96338_irqs; diff --git a/arch/mips/bcm63xx/dev-uart.c b/arch/mips/bcm63xx/dev-uart.c index 5f3d89c4a98..b0519461ad9 100644 --- a/arch/mips/bcm63xx/dev-uart.c +++ b/arch/mips/bcm63xx/dev-uart.c @@ -10,7 +10,6 @@ #include <linux/kernel.h> #include <linux/platform_device.h> #include <bcm63xx_cpu.h> -#include <bcm63xx_dev_uart.h> static struct resource uart_resources[] = { { @@ -39,3 +38,4 @@ int __init bcm63xx_uart_register(void) uart_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0); return platform_device_register(&bcm63xx_uart_device); } +arch_initcall(bcm63xx_uart_register); diff --git a/arch/mips/bcm63xx/dev-wdt.c b/arch/mips/bcm63xx/dev-wdt.c new file mode 100644 index 00000000000..3e6c716a4c1 --- /dev/null +++ b/arch/mips/bcm63xx/dev-wdt.c @@ -0,0 +1,37 @@ +/* + * 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. + * + * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <bcm63xx_cpu.h> + +static struct resource wdt_resources[] = { + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device bcm63xx_wdt_device = { + .name = "bcm63xx-wdt", + .id = 0, + .num_resources = ARRAY_SIZE(wdt_resources), + .resource = wdt_resources, +}; + +int __init bcm63xx_wdt_register(void) +{ + wdt_resources[0].start = bcm63xx_regset_address(RSET_WDT); + wdt_resources[0].end = wdt_resources[0].start; + wdt_resources[0].end += RSET_WDT_SIZE - 1; + + return platform_device_register(&bcm63xx_wdt_device); +} +arch_initcall(bcm63xx_wdt_register); diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index b18a0ca926f..d0056598fbf 100644 --- a/arch/mips/bcm63xx/setup.c +++ b/arch/mips/bcm63xx/setup.c @@ -75,7 +75,9 @@ void bcm63xx_machine_reboot(void) bcm6348_a1_reboot(); printk(KERN_INFO "triggering watchdog soft-reset...\n"); - bcm_perf_writel(SYS_PLL_SOFT_RESET, PERF_SYS_PLL_CTL_REG); + reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG); + reg |= SYS_PLL_SOFT_RESET; + bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG); while (1) ; } diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 384f1842bfb..6f2acf09328 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -17,6 +17,15 @@ DEFINE_RWLOCK(octeon_irq_ciu0_rwlock); DEFINE_RWLOCK(octeon_irq_ciu1_rwlock); DEFINE_SPINLOCK(octeon_irq_msi_lock); +static int octeon_coreid_for_cpu(int cpu) +{ +#ifdef CONFIG_SMP + return cpu_logical_map(cpu); +#else + return cvmx_get_core_num(); +#endif +} + static void octeon_irq_core_ack(unsigned int irq) { unsigned int bit = irq - OCTEON_IRQ_SW0; @@ -152,11 +161,10 @@ static void octeon_irq_ciu0_disable(unsigned int irq) int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ unsigned long flags; uint64_t en0; -#ifdef CONFIG_SMP int cpu; write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags); for_each_online_cpu(cpu) { - int coreid = cpu_logical_map(cpu); + int coreid = octeon_coreid_for_cpu(cpu); en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); en0 &= ~(1ull << bit); cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); @@ -167,26 +175,57 @@ static void octeon_irq_ciu0_disable(unsigned int irq) */ cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2)); write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags); -#else - int coreid = cvmx_get_core_num(); - local_irq_save(flags); - en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); - en0 &= ~(1ull << bit); - cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); - cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); - local_irq_restore(flags); -#endif +} + +/* + * Enable the irq on the current core for chips that have the EN*_W1{S,C} + * registers. + */ +static void octeon_irq_ciu0_enable_v2(unsigned int irq) +{ + int index = cvmx_get_core_num() * 2; + u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); +} + +/* + * Disable the irq on the current core for chips that have the EN*_W1{S,C} + * registers. + */ +static void octeon_irq_ciu0_disable_v2(unsigned int irq) +{ + int index = cvmx_get_core_num() * 2; + u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); +} + +/* + * Disable the irq on the all cores for chips that have the EN*_W1{S,C} + * registers. + */ +static void octeon_irq_ciu0_disable_all_v2(unsigned int irq) +{ + u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + int index; + int cpu; + for_each_online_cpu(cpu) { + index = octeon_coreid_for_cpu(cpu) * 2; + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); + } } #ifdef CONFIG_SMP static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest) { int cpu; + unsigned long flags; int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ - write_lock(&octeon_irq_ciu0_rwlock); + write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags); for_each_online_cpu(cpu) { - int coreid = cpu_logical_map(cpu); + int coreid = octeon_coreid_for_cpu(cpu); uint64_t en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); if (cpumask_test_cpu(cpu, dest)) @@ -200,11 +239,45 @@ static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask * * of them are done. */ cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2)); - write_unlock(&octeon_irq_ciu0_rwlock); + write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags); return 0; } + +/* + * Set affinity for the irq for chips that have the EN*_W1{S,C} + * registers. + */ +static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq, + const struct cpumask *dest) +{ + int cpu; + int index; + u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + for_each_online_cpu(cpu) { + index = octeon_coreid_for_cpu(cpu) * 2; + if (cpumask_test_cpu(cpu, dest)) + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); + else + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); + } + return 0; +} +#endif + +/* + * Newer octeon chips have support for lockless CIU operation. + */ +static struct irq_chip octeon_irq_chip_ciu0_v2 = { + .name = "CIU0", + .enable = octeon_irq_ciu0_enable_v2, + .disable = octeon_irq_ciu0_disable_all_v2, + .ack = octeon_irq_ciu0_disable_v2, + .eoi = octeon_irq_ciu0_enable_v2, +#ifdef CONFIG_SMP + .set_affinity = octeon_irq_ciu0_set_affinity_v2, #endif +}; static struct irq_chip octeon_irq_chip_ciu0 = { .name = "CIU0", @@ -269,11 +342,10 @@ static void octeon_irq_ciu1_disable(unsigned int irq) int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ unsigned long flags; uint64_t en1; -#ifdef CONFIG_SMP int cpu; write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags); for_each_online_cpu(cpu) { - int coreid = cpu_logical_map(cpu); + int coreid = octeon_coreid_for_cpu(cpu); en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); en1 &= ~(1ull << bit); cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); @@ -284,26 +356,58 @@ static void octeon_irq_ciu1_disable(unsigned int irq) */ cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1)); write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags); -#else - int coreid = cvmx_get_core_num(); - local_irq_save(flags); - en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); - en1 &= ~(1ull << bit); - cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); - cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); - local_irq_restore(flags); -#endif +} + +/* + * Enable the irq on the current core for chips that have the EN*_W1{S,C} + * registers. + */ +static void octeon_irq_ciu1_enable_v2(unsigned int irq) +{ + int index = cvmx_get_core_num() * 2 + 1; + u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); + + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); +} + +/* + * Disable the irq on the current core for chips that have the EN*_W1{S,C} + * registers. + */ +static void octeon_irq_ciu1_disable_v2(unsigned int irq) +{ + int index = cvmx_get_core_num() * 2 + 1; + u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); + + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); +} + +/* + * Disable the irq on the all cores for chips that have the EN*_W1{S,C} + * registers. + */ +static void octeon_irq_ciu1_disable_all_v2(unsigned int irq) +{ + u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); + int index; + int cpu; + for_each_online_cpu(cpu) { + index = octeon_coreid_for_cpu(cpu) * 2 + 1; + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); + } } #ifdef CONFIG_SMP -static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest) +static int octeon_irq_ciu1_set_affinity(unsigned int irq, + const struct cpumask *dest) { int cpu; + unsigned long flags; int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ - write_lock(&octeon_irq_ciu1_rwlock); + write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags); for_each_online_cpu(cpu) { - int coreid = cpu_logical_map(cpu); + int coreid = octeon_coreid_for_cpu(cpu); uint64_t en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1 (coreid * 2 + 1)); @@ -318,12 +422,46 @@ static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask * * of them are done. */ cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1)); - write_unlock(&octeon_irq_ciu1_rwlock); + write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags); + + return 0; +} |