From 7ca5dc145bc7daddd8aed8bbda46b74af9cebefc Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 24 Jun 2009 11:12:57 +0200 Subject: MIPS: Add support for Texas Instruments AR7 System-on-a-Chip This patch adds support for the Texas Instruments AR7 System-on-a-Chip. It supports the TNETD7100, 7200 and 7300 versions of the SoC. Signed-off-by: Matteo Croce Signed-off-by: Felix Fietkau Signed-off-by: Eugene Konev Signed-off-by: Nicolas Thill Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 20 + arch/mips/Makefile | 7 + arch/mips/ar7/Makefile | 10 + arch/mips/ar7/clock.c | 440 ++++++++++++ arch/mips/ar7/gpio.c | 48 ++ arch/mips/ar7/irq.c | 176 +++++ arch/mips/ar7/memory.c | 72 ++ arch/mips/ar7/platform.c | 555 +++++++++++++++ arch/mips/ar7/prom.c | 297 ++++++++ arch/mips/ar7/setup.c | 94 +++ arch/mips/ar7/time.c | 30 + arch/mips/configs/ar7_defconfig | 1182 +++++++++++++++++++++++++++++++ arch/mips/include/asm/mach-ar7/ar7.h | 178 +++++ arch/mips/include/asm/mach-ar7/gpio.h | 110 +++ arch/mips/include/asm/mach-ar7/irq.h | 16 + arch/mips/include/asm/mach-ar7/prom.h | 25 + arch/mips/include/asm/mach-ar7/spaces.h | 22 + arch/mips/include/asm/mach-ar7/war.h | 25 + 18 files changed, 3307 insertions(+) create mode 100644 arch/mips/ar7/Makefile create mode 100644 arch/mips/ar7/clock.c create mode 100644 arch/mips/ar7/gpio.c create mode 100644 arch/mips/ar7/irq.c create mode 100644 arch/mips/ar7/memory.c create mode 100644 arch/mips/ar7/platform.c create mode 100644 arch/mips/ar7/prom.c create mode 100644 arch/mips/ar7/setup.c create mode 100644 arch/mips/ar7/time.c create mode 100644 arch/mips/configs/ar7_defconfig create mode 100644 arch/mips/include/asm/mach-ar7/ar7.h create mode 100644 arch/mips/include/asm/mach-ar7/gpio.h create mode 100644 arch/mips/include/asm/mach-ar7/irq.h create mode 100644 arch/mips/include/asm/mach-ar7/prom.h create mode 100644 arch/mips/include/asm/mach-ar7/spaces.h create mode 100644 arch/mips/include/asm/mach-ar7/war.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 8c4be1f301c..b0e55113633 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -22,6 +22,26 @@ choice config MACH_ALCHEMY bool "Alchemy processor based machines" +config AR7 + bool "Texas Instruments AR7" + select BOOT_ELF32 + select DMA_NONCOHERENT + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select NO_EXCEPT_FILL + select SWAP_IO_SPACE + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_GPIO + select GCD + select VLYNQ + help + Support for the Texas Instruments AR7 System-on-a-Chip + family: TNETD7100, 7200 and 7300. + config BASLER_EXCITE bool "Basler eXcite smart camera" select CEVT_R4K diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 807572a6a4d..861da514a46 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -172,6 +172,13 @@ libs-y += arch/mips/fw/lib/ # Board-dependent options and extra files # +# +# Texas Instruments AR7 +# +core-$(CONFIG_AR7) += arch/mips/ar7/ +cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 +load-$(CONFIG_AR7) += 0xffffffff94100000 + # # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile new file mode 100644 index 00000000000..7435e44b396 --- /dev/null +++ b/arch/mips/ar7/Makefile @@ -0,0 +1,10 @@ + +obj-y := \ + prom.o \ + setup.o \ + memory.o \ + irq.o \ + time.o \ + platform.o \ + gpio.o \ + clock.o diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c new file mode 100644 index 00000000000..27dc6663f2f --- /dev/null +++ b/arch/mips/ar7/clock.c @@ -0,0 +1,440 @@ +/* + * Copyright (C) 2007 Felix Fietkau + * Copyright (C) 2007 Eugene Konev + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define BOOT_PLL_SOURCE_MASK 0x3 +#define CPU_PLL_SOURCE_SHIFT 16 +#define BUS_PLL_SOURCE_SHIFT 14 +#define USB_PLL_SOURCE_SHIFT 18 +#define DSP_PLL_SOURCE_SHIFT 22 +#define BOOT_PLL_SOURCE_AFE 0 +#define BOOT_PLL_SOURCE_BUS 0 +#define BOOT_PLL_SOURCE_REF 1 +#define BOOT_PLL_SOURCE_XTAL 2 +#define BOOT_PLL_SOURCE_CPU 3 +#define BOOT_PLL_BYPASS 0x00000020 +#define BOOT_PLL_ASYNC_MODE 0x02000000 +#define BOOT_PLL_2TO1_MODE 0x00008000 + +#define TNETD7200_CLOCK_ID_CPU 0 +#define TNETD7200_CLOCK_ID_DSP 1 +#define TNETD7200_CLOCK_ID_USB 2 + +#define TNETD7200_DEF_CPU_CLK 211000000 +#define TNETD7200_DEF_DSP_CLK 125000000 +#define TNETD7200_DEF_USB_CLK 48000000 + +struct tnetd7300_clock { + u32 ctrl; +#define PREDIV_MASK 0x001f0000 +#define PREDIV_SHIFT 16 +#define POSTDIV_MASK 0x0000001f + u32 unused1[3]; + u32 pll; +#define MUL_MASK 0x0000f000 +#define MUL_SHIFT 12 +#define PLL_MODE_MASK 0x00000001 +#define PLL_NDIV 0x00000800 +#define PLL_DIV 0x00000002 +#define PLL_STATUS 0x00000001 + u32 unused2[3]; +}; + +struct tnetd7300_clocks { + struct tnetd7300_clock bus; + struct tnetd7300_clock cpu; + struct tnetd7300_clock usb; + struct tnetd7300_clock dsp; +}; + +struct tnetd7200_clock { + u32 ctrl; + u32 unused1[3]; +#define DIVISOR_ENABLE_MASK 0x00008000 + u32 mul; + u32 prediv; + u32 postdiv; + u32 postdiv2; + u32 unused2[6]; + u32 cmd; + u32 status; + u32 cmden; + u32 padding[15]; +}; + +struct tnetd7200_clocks { + struct tnetd7200_clock cpu; + struct tnetd7200_clock dsp; + struct tnetd7200_clock usb; +}; + +int ar7_cpu_clock = 150000000; +EXPORT_SYMBOL(ar7_cpu_clock); +int ar7_bus_clock = 125000000; +EXPORT_SYMBOL(ar7_bus_clock); +int ar7_dsp_clock; +EXPORT_SYMBOL(ar7_dsp_clock); + +static void approximate(int base, int target, int *prediv, + int *postdiv, int *mul) +{ + int i, j, k, freq, res = target; + for (i = 1; i <= 16; i++) + for (j = 1; j <= 32; j++) + for (k = 1; k <= 32; k++) { + freq = abs(base / j * i / k - target); + if (freq < res) { + res = freq; + *mul = i; + *prediv = j; + *postdiv = k; + } + } +} + +static void calculate(int base, int target, int *prediv, int *postdiv, + int *mul) +{ + int tmp_gcd, tmp_base, tmp_freq; + + for (*prediv = 1; *prediv <= 32; (*prediv)++) { + tmp_base = base / *prediv; + tmp_gcd = gcd(target, tmp_base); + *mul = target / tmp_gcd; + *postdiv = tmp_base / tmp_gcd; + if ((*mul < 1) || (*mul >= 16)) + continue; + if ((*postdiv > 0) & (*postdiv <= 32)) + break; + } + + if (base / *prediv * *mul / *postdiv != target) { + approximate(base, target, prediv, postdiv, mul); + tmp_freq = base / *prediv * *mul / *postdiv; + printk(KERN_WARNING + "Adjusted requested frequency %d to %d\n", + target, tmp_freq); + } + + printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n", + *prediv, *postdiv, *mul); +} + +static int tnetd7300_dsp_clock(void) +{ + u32 didr1, didr2; + u8 rev = ar7_chip_rev(); + didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18)); + didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c)); + if (didr2 & (1 << 23)) + return 0; + if ((rev >= 0x23) && (rev != 0x57)) + return 250000000; + if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22)) + > 4208000) + return 250000000; + return 0; +} + +static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock, + u32 *bootcr, u32 bus_clock) +{ + int product; + int base_clock = AR7_REF_CLOCK; + u32 ctrl = readl(&clock->ctrl); + u32 pll = readl(&clock->pll); + int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1; + int postdiv = (ctrl & POSTDIV_MASK) + 1; + int divisor = prediv * postdiv; + int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1; + + switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) { + case BOOT_PLL_SOURCE_BUS: + base_clock = bus_clock; + break; + case BOOT_PLL_SOURCE_REF: + base_clock = AR7_REF_CLOCK; + break; + case BOOT_PLL_SOURCE_XTAL: + base_clock = AR7_XTAL_CLOCK; + break; + case BOOT_PLL_SOURCE_CPU: + base_clock = ar7_cpu_clock; + break; + } + + if (*bootcr & BOOT_PLL_BYPASS) + return base_clock / divisor; + + if ((pll & PLL_MODE_MASK) == 0) + return (base_clock >> (mul / 16 + 1)) / divisor; + + if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) { + product = (mul & 1) ? + (base_clock * mul) >> 1 : + (base_clock * (mul - 1)) >> 2; + return product / divisor; + } + + if (mul == 16) + return base_clock / divisor; + + return base_clock * mul / divisor; +} + +static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock, + u32 *bootcr, u32 frequency) +{ + int prediv, postdiv, mul; + int base_clock = ar7_bus_clock; + + switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) { + case BOOT_PLL_SOURCE_BUS: + base_clock = ar7_bus_clock; + break; + case BOOT_PLL_SOURCE_REF: + base_clock = AR7_REF_CLOCK; + break; + case BOOT_PLL_SOURCE_XTAL: + base_clock = AR7_XTAL_CLOCK; + break; + case BOOT_PLL_SOURCE_CPU: + base_clock = ar7_cpu_clock; + break; + } + + calculate(base_clock, frequency, &prediv, &postdiv, &mul); + + writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl); + msleep(1); + writel(4, &clock->pll); + while (readl(&clock->pll) & PLL_STATUS) + ; + writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); + msleep(75); +} + +static void __init tnetd7300_init_clocks(void) +{ + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); + struct tnetd7300_clocks *clocks = + ioremap_nocache(UR8_REGS_CLOCKS, + sizeof(struct tnetd7300_clocks)); + + ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT, + &clocks->bus, bootcr, AR7_AFE_CLOCK); + + if (*bootcr & BOOT_PLL_ASYNC_MODE) + ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT, + &clocks->cpu, bootcr, AR7_AFE_CLOCK); + else + ar7_cpu_clock = ar7_bus_clock; + + if (ar7_dsp_clock == 250000000) + tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp, + bootcr, ar7_dsp_clock); + + iounmap(clocks); + iounmap(bootcr); +} + +static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock, + u32 *bootcr, u32 bus_clock) +{ + int divisor = ((readl(&clock->prediv) & 0x1f) + 1) * + ((readl(&clock->postdiv) & 0x1f) + 1); + + if (*bootcr & BOOT_PLL_BYPASS) + return base / divisor; + + return base * ((readl(&clock->mul) & 0xf) + 1) / divisor; +} + + +static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock, + int prediv, int postdiv, int postdiv2, int mul, u32 frequency) +{ + printk(KERN_INFO + "Clocks: base = %d, frequency = %u, prediv = %d, " + "postdiv = %d, postdiv2 = %d, mul = %d\n", + base, frequency, prediv, postdiv, postdiv2, mul); + + writel(0, &clock->ctrl); + writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv); + writel((mul - 1) & 0xF, &clock->mul); + + while (readl(&clock->status) & 0x1) + ; /* nop */ + + writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv); + + writel(readl(&clock->cmden) | 1, &clock->cmden); + writel(readl(&clock->cmd) | 1, &clock->cmd); + + while (readl(&clock->status) & 0x1) + ; /* nop */ + + writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2); + + writel(readl(&clock->cmden) | 1, &clock->cmden); + writel(readl(&clock->cmd) | 1, &clock->cmd); + + while (readl(&clock->status) & 0x1) + ; /* nop */ + + writel(readl(&clock->ctrl) | 1, &clock->ctrl); +} + +static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr) +{ + if (*bootcr & BOOT_PLL_ASYNC_MODE) + /* Async */ + switch (clock_id) { + case TNETD7200_CLOCK_ID_DSP: + return AR7_REF_CLOCK; + default: + return AR7_AFE_CLOCK; + } + else + /* Sync */ + if (*bootcr & BOOT_PLL_2TO1_MODE) + /* 2:1 */ + switch (clock_id) { + case TNETD7200_CLOCK_ID_DSP: + return AR7_REF_CLOCK; + default: + return AR7_AFE_CLOCK; + } + else + /* 1:1 */ + return AR7_REF_CLOCK; +} + + +static void __init tnetd7200_init_clocks(void) +{ + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); + struct tnetd7200_clocks *clocks = + ioremap_nocache(AR7_REGS_CLOCKS, + sizeof(struct tnetd7200_clocks)); + int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv; + int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv; + int usb_base, usb_mul, usb_prediv, usb_postdiv; + + cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr); + dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr); + + if (*bootcr & BOOT_PLL_ASYNC_MODE) { + printk(KERN_INFO "Clocks: Async mode\n"); + + printk(KERN_INFO "Clocks: Setting DSP clock\n"); + calculate(dsp_base, TNETD7200_DEF_DSP_CLK, + &dsp_prediv, &dsp_postdiv, &dsp_mul); + ar7_bus_clock = + ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv; + tnetd7200_set_clock(dsp_base, &clocks->dsp, + dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2, + ar7_bus_clock); + + printk(KERN_INFO "Clocks: Setting CPU clock\n"); + calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv, + &cpu_postdiv, &cpu_mul); + ar7_cpu_clock = + ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv; + tnetd7200_set_clock(cpu_base, &clocks->cpu, + cpu_prediv, cpu_postdiv, -1, cpu_mul, + ar7_cpu_clock); + + } else + if (*bootcr & BOOT_PLL_2TO1_MODE) { + printk(KERN_INFO "Clocks: Sync 2:1 mode\n"); + + printk(KERN_INFO "Clocks: Setting CPU clock\n"); + calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv, + &cpu_postdiv, &cpu_mul); + ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul) + / cpu_postdiv; + tnetd7200_set_clock(cpu_base, &clocks->cpu, + cpu_prediv, cpu_postdiv, -1, cpu_mul, + ar7_cpu_clock); + + printk(KERN_INFO "Clocks: Setting DSP clock\n"); + calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv, + &dsp_postdiv, &dsp_mul); + ar7_bus_clock = ar7_cpu_clock / 2; + tnetd7200_set_clock(dsp_base, &clocks->dsp, + dsp_prediv, dsp_postdiv * 2, dsp_postdiv, + dsp_mul * 2, ar7_bus_clock); + } else { + printk(KERN_INFO "Clocks: Sync 1:1 mode\n"); + + printk(KERN_INFO "Clocks: Setting DSP clock\n"); + calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv, + &dsp_postdiv, &dsp_mul); + ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul) + / dsp_postdiv; + tnetd7200_set_clock(dsp_base, &clocks->dsp, + dsp_prediv, dsp_postdiv * 2, dsp_postdiv, + dsp_mul * 2, ar7_bus_clock); + + ar7_cpu_clock = ar7_bus_clock; + } + + printk(KERN_INFO "Clocks: Setting USB clock\n"); + usb_base = ar7_bus_clock; + calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv, + &usb_postdiv, &usb_mul); + tnetd7200_set_clock(usb_base, &clocks->usb, + usb_prediv, usb_postdiv, -1, usb_mul, + TNETD7200_DEF_USB_CLK); + + ar7_dsp_clock = ar7_cpu_clock; + + iounmap(clocks); + iounmap(bootcr); +} + +int __init ar7_init_clocks(void) +{ + switch (ar7_chip_id()) { + case AR7_CHIP_7100: + case AR7_CHIP_7200: + tnetd7200_init_clocks(); + break; + case AR7_CHIP_7300: + ar7_dsp_clock = tnetd7300_dsp_clock(); + tnetd7300_init_clocks(); + break; + default: + break; + } + + return 0; +} +arch_initcall(ar7_init_clocks); diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c new file mode 100644 index 00000000000..74e14a3dbf4 --- /dev/null +++ b/arch/mips/ar7/gpio.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007 Felix Fietkau + * Copyright (C) 2007 Eugene Konev + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +static const char *ar7_gpio_list[AR7_GPIO_MAX]; + +int gpio_request(unsigned gpio, const char *label) +{ + if (gpio >= AR7_GPIO_MAX) + return -EINVAL; + + if (ar7_gpio_list[gpio]) + return -EBUSY; + + if (label) + ar7_gpio_list[gpio] = label; + else + ar7_gpio_list[gpio] = "busy"; + + return 0; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned gpio) +{ + BUG_ON(!ar7_gpio_list[gpio]); + ar7_gpio_list[gpio] = NULL; +} +EXPORT_SYMBOL(gpio_free); diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c new file mode 100644 index 00000000000..c781556c44e --- /dev/null +++ b/arch/mips/ar7/irq.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2006,2007 Felix Fietkau + * Copyright (C) 2006,2007 Eugene Konev + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include +#include +#include + +#define EXCEPT_OFFSET 0x80 +#define PACE_OFFSET 0xA0 +#define CHNLS_OFFSET 0x200 + +#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10) +#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8) +#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */ +#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */ +#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */ +#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */ +#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */ +#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */ +#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */ +#define PIR_OFFSET (0x40) +#define MSR_OFFSET (0x44) +#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */ +#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */ + +#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr)) + +#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4)) + +static int ar7_irq_base; + +static void ar7_unmask_irq(unsigned int irq) +{ + writel(1 << ((irq - ar7_irq_base) % 32), + REG(ESR_OFFSET(irq - ar7_irq_base))); +} + +static void ar7_mask_irq(unsigned int irq) +{ + writel(1 << ((irq - ar7_irq_base) % 32), + REG(ECR_OFFSET(irq - ar7_irq_base))); +} + +static void ar7_ack_irq(unsigned int irq) +{ + writel(1 << ((irq - ar7_irq_base) % 32), + REG(CR_OFFSET(irq - ar7_irq_base))); +} + +static void ar7_unmask_sec_irq(unsigned int irq) +{ + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET)); +} + +static void ar7_mask_sec_irq(unsigned int irq) +{ + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET)); +} + +static void ar7_ack_sec_irq(unsigned int irq) +{ + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET)); +} + +static struct irq_chip ar7_irq_type = { + .name = "AR7", + .unmask = ar7_unmask_irq, + .mask = ar7_mask_irq, + .ack = ar7_ack_irq +}; + +static struct irq_chip ar7_sec_irq_type = { + .name = "AR7", + .unmask = ar7_unmask_sec_irq, + .mask = ar7_mask_sec_irq, + .ack = ar7_ack_sec_irq, +}; + +static struct irqaction ar7_cascade_action = { + .handler = no_action, + .name = "AR7 cascade interrupt" +}; + +static void __init ar7_irq_init(int base) +{ + int i; + /* + * Disable interrupts and clear pending + */ + writel(0xffffffff, REG(ECR_OFFSET(0))); + writel(0xff, REG(ECR_OFFSET(32))); + writel(0xffffffff, REG(SEC_ECR_OFFSET)); + writel(0xffffffff, REG(CR_OFFSET(0))); + writel(0xff, REG(CR_OFFSET(32))); + writel(0xffffffff, REG(SEC_CR_OFFSET)); + + ar7_irq_base = base; + + for (i = 0; i < 40; i++) { + writel(i, REG(CHNL_OFFSET(i))); + /* Primary IRQ's */ + set_irq_chip_and_handler(base + i, &ar7_irq_type, + handle_level_irq); + /* Secondary IRQ's */ + if (i < 32) + set_irq_chip_and_handler(base + i + 40, + &ar7_sec_irq_type, + handle_level_irq); + } + + setup_irq(2, &ar7_cascade_action); + setup_irq(ar7_irq_base, &ar7_cascade_action); + set_c0_status(IE_IRQ0); +} + +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(); + ar7_irq_init(8); +} + +static void ar7_cascade(void) +{ + u32 status; + int i, irq; + + /* Primary IRQ's */ + irq = readl(REG(PIR_OFFSET)) & 0x3f; + if (irq) { + do_IRQ(ar7_irq_base + irq); + return; + } + + /* Secondary IRQ's are cascaded through primary '0' */ + writel(1, REG(CR_OFFSET(irq))); + status = readl(REG(SEC_SR_OFFSET)); + for (i = 0; i < 32; i++) { + if (status & 1) { + do_IRQ(ar7_irq_base + i + 40); + return; + } + status >>= 1; + } + + spurious_interrupt(); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + if (pending & STATUSF_IP7) /* cpu timer */ + do_IRQ(7); + else if (pending & STATUSF_IP2) /* int0 hardware line */ + ar7_cascade(); + else + spurious_interrupt(); +} diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c new file mode 100644 index 00000000000..46fed44825a --- /dev/null +++ b/arch/mips/ar7/memory.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007 Felix Fietkau + * Copyright (C) 2007 Eugene Konev + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static int __init memsize(void) +{ + u32 size = (64 << 20); + u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4); + u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end)); + u32 *tmpaddr = addr; + + while (tmpaddr > kernel_end) { + *tmpaddr = (u32)tmpaddr; + size >>= 1; + tmpaddr -= size >> 2; + } + + do { + tmpaddr += size >> 2; + if (*tmpaddr != (u32)tmpaddr) + break; + size <<= 1; + } while (size < (64 << 20)); + + writel(tmpaddr, &addr); + + return size; +} + +void __init prom_meminit(void) +{ + unsigned long pages; + + pages = memsize() >> PAGE_SHIFT; + add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT, + BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ + /* Nothing to free */ +} diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c new file mode 100644 index 00000000000..54224496178 --- /dev/null +++ b/arch/mips/ar7/platform.c @@ -0,0 +1,555 @@ +/* + * Copyright (C) 2006,2007 Felix Fietkau + * Copyright (C) 2006,2007 Eugene Konev + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct plat_vlynq_data { + struct plat_vlynq_ops ops; + int gpio_bit; + int reset_bit; +}; + + +static int vlynq_on(struct vlynq_device *dev) +{ + int result; + struct plat_vlynq_data *pdata = dev->dev.platform_data; + + result = gpio_request(pdata->gpio_bit, "vlynq"); + if (result) + goto out; + + ar7_device_reset(pdata->reset_bit); + + result = ar7_gpio_disable(pdata->gpio_bit); + if (result) + goto out_enabled; + + result = ar7_gpio_enable(pdata->gpio_bit); + if (result) + goto out_enabled; + + result = gpio_direction_output(pdata->gpio_bit, 0); + if (result) + goto out_gpio_enabled; + + msleep(50); + + gpio_set_value(pdata->gpio_bit, 1); + msleep(50); + + return 0; + +out_gpio_enabled: + ar7_gpio_disable(pdata->gpio_bit); +out_enabled: + ar7_device_disable(pdata->reset_bit); + gpio_free(pdata->gpio_bit); +out: + return result; +} + +static void vlynq_off(struct vlynq_device *dev) +{ + struct plat_vlynq_data *pdata = dev->dev.platform_data; + ar7_gpio_disable(pdata->gpio_bit); + gpio_free(pdata->gpio_bit); + ar7_device_disable(pdata->reset_bit); +} + +static struct resource physmap_flash_resource = { + .name = "mem", + .flags = IORESOURCE_MEM, + .start = 0x10000000, + .end = 0x107fffff, +}; + +static struct resource cpmac_low_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_MAC0, + .end = AR7_REGS_MAC0 + 0x7ff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 27, + .end = 27, + }, +}; + +static struct resource cpmac_high_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_MAC1, + .end = AR7_REGS_MAC1 + 0x7ff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 41, + .end = 41, + }, +}; + +static struct resource vlynq_low_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_VLYNQ0, + .end = AR7_REGS_VLYNQ0 + 0xff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 29, + .end = 29, + }, + { + .name = "mem", + .flags = IORESOURCE_MEM, + .start = 0x04000000, + .end = 0x04ffffff, + }, + { + .name = "devirq", + .flags = IORESOURCE_IRQ, + .start = 80, + .end = 111, + }, +}; + +static struct resource vlynq_high_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_VLYNQ1, + .end = AR7_REGS_VLYNQ1 + 0xff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 33, + .end = 33, + }, + { + .name = "mem", + .flags = IORESOURCE_MEM, + .start = 0x0c000000, + .end = 0x0cffffff, + }, + { + .name = "devirq", + .flags = IORESOURCE_IRQ, + .start = 112, + .end = 143, + }, +}; + +static struct resource usb_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_USB, + .end = AR7_REGS_USB + 0xff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 32, + .end = 32, + }, + { + .name = "mem", + .flags = IORESOURCE_MEM, + .start = 0x03400000, + .end = 0x034001fff, + }, +}; + +static struct physmap_flash_data physmap_flash_data = { + .width = 2, +}; + +static struct plat_cpmac_data cpmac_low_data = { + .reset_bit = 17, + .power_bit = 20, + .phy_mask = 0x80000000, +}; + +static struct plat_cpmac_data cpmac_high_data = { + .reset_bit = 21, + .power_bit = 22, + .phy_mask = 0x7fffffff, +}; + +static struct plat_vlynq_data vlynq_low_data = { + .ops.on = vlynq_on, + .ops.off = vlynq_off, + .reset_bit = 20, + .gpio_bit = 18, +}; + +static struct plat_vlynq_data vlynq_high_data = { + .ops.on = vlynq_on, + .ops.off = vlynq_off, + .reset_bit = 16, + .gpio_bit = 19, +}; + +static struct platform_device physmap_flash = { + .id = 0, + .name = "physmap-flash", + .dev.platform_data = &physmap_flash_data, + .resource = &physmap_flash_resource, + .num_resources = 1, +}; + +static u64 cpmac_dma_mask = DMA_32BIT_MASK; +static struct platform_device cpmac_low = { + .id = 0, + .name = "cpmac", + .dev = { + .dma_mask = &cpmac_dma_mask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = &cpmac_low_data, + }, + .resource = cpmac_low_res, + .num_resources = ARRAY_SIZE(cpmac_low_res), +}; + +static struct platform_device cpmac_high = { + .id = 1, + .name = "cpmac", + .dev = { + .dma_mask = &cpmac_dma_mask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = &cpmac_high_data, + }, + .resource = cpmac_high_res, + .num_resources = ARRAY_SIZE(cpmac_high_res), +}; + +static struct platform_device vlynq_low = { + .id = 0, + .name = "vlynq", + .dev.platform_data = &vlynq_low_data, + .resource = vlynq_low_res, + .num_resources = ARRAY_SIZE(vlynq_low_res), +}; + +static struct platform_device vlynq_high = { + .id = 1, + .name = "vlynq", + .dev.platform_data = &vlynq_high_data, + .resource = vlynq_high_res, + .num_resources = ARRAY_SIZE(vlynq_high_res), +}; + + +static struct gpio_led default_leds[] = { + { + .name = "status", + .gpio = 8, + .active_low = 1, + }, +}; + +static struct gpio_led dsl502t_leds[] = { + { + .name = "status", + .gpio = 9, + .active_low = 1, + }, + { + .name = "ethernet", + .gpio = 7, + .active_low = 1, + }, + { + .name = "usb", + .gpio = 12, + .active_low = 1, + }, +}; + +static struct gpio_led dg834g_leds[] = { + { + .name = "ppp", + .gpio = 6, + .active_low = 1, + }, + { + .name = "status", + .gpio = 7, + .active_low = 1, + }, + { + .name = "adsl", + .gpio = 8, + .active_low = 1, + }, + { + .name = "wifi", + .gpio = 12, + .active_low = 1, + }, + { + .name = "power", + .gpio = 14, + .active_low = 1, + .default_trigger = "default-on", + }, +}; + +static struct gpio_led fb_sl_leds[] = { + { + .name = "1", + .gpio = 7, + }, + { + .name = "2", + .gpio = 13, + .active_low = 1, + }, + { + .name = "3", + .gpio = 10, + .active_low = 1, + }, + { + .name = "4", + .gpio = 12, + .active_low = 1, + }, + { + .name = "5", + .gpio = 9, + .active_low = 1, + }, +}; + +static struct gpio_led fb_fon_leds[] = { + { + .name = "1", + .gpio = 8, + }, + { + .name = "2", + .gpio = 3, + .active_low = 1, + }, + { + .name = "3", + .gpio = 5, + }, + { + .name = "4", + .gpio = 4, + .active_low = 1, + }, + { + .name = "5", + .gpio = 11, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data ar7_led_data; + +static struct platform_device ar7_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &ar7_led_data, + } +}; + +static struct platform_device ar7_udc = { + .id = -1, + .name = "ar7_udc", + .resource = usb_res, + .num_resources = ARRAY_SIZE(usb_res), +}; + +static inline unsigned char char2hex(char h) +{ + switch (h) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return h - '0'; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return h - 'A' + 10; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return h - 'a' + 10; + default: + return 0; + } +} + +static void cpmac_get_mac(int instance, unsigned char *dev_addr) +{ + int i; + char name[5], default_mac[ETH_ALEN], *mac; + + mac = NULL; + sprintf(name, "mac%c", 'a' + instance); + mac = prom_getenv(name); + if (!mac) { + sprintf(name, "mac%c", 'a'); + mac = prom_getenv(name); + } + if (!mac) { + random_ether_addr(default_mac); + mac = default_mac; + } + for (i = 0; i < 6; i++) + dev_addr[i] = (char2hex(mac[i * 3]) << 4) + + char2hex(mac[i * 3 + 1]); +} + +static void __init detect_leds(void) +{ + char *prid, *usb_prod; + + /* Default LEDs */ + ar7_led_data.num_leds = ARRAY_SIZE(default_leds); + ar7_led_data.leds = default_leds; + + /* FIXME: the whole thing is unreliable */ + prid = prom_getenv("ProductID"); + usb_prod = prom_getenv("usb_prod"); + + /* If we can't get the product id from PROM, use the default LEDs */ + if (!prid) + return; + + if (strstr(prid, "Fritz_Box_FON")) { + ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds); + ar7_led_data.leds = fb_fon_leds; + } else if (strstr(prid, "Fritz_Box_")) { + ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds); + ar7_led_data.leds = fb_sl_leds; + } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB")) + && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) { + ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds); + ar7_led_data.leds = dsl502t_leds; + } else if (strstr(prid, "DG834")) { + ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds); + ar7_led_data.leds = dg834g_leds; + } +} + +static int __init ar7_register_devices(void) +{ + int res; + static struct uart_port uart_port[2]; + + memset(uart_port, 0, sizeof(struct uart_port) * 2); + + uart_port[0].type = PORT_16550A; + uart_port[0].line = 0; + uart_port[0].irq = AR7_IRQ_UART0; + uart_port[0].uartclk = ar7_bus_freq() / 2; + uart_port[0].iotype = UPIO_MEM32; + uart_port[0].mapbase = AR7_REGS_UART0; + uart_port[0].membase = ioremap(uart_port[0].mapbase, 256); + uart_port[0].regshift = 2; + res = early_serial_setup(&uart_port[0]); + if (res) + return res; + + + /* Only TNETD73xx have a second serial port */ + if (ar7_has_second_uart()) { + uart_port[1].type = PORT_16550A; + uart_port[1].line = 1; + uart_port[1].irq = AR7_IRQ_UART1; + uart_port[1].uartclk = ar7_bus_freq() / 2; + uart_port[1].iotype = UPIO_MEM32; + uart_port[1].mapbase = UR8_REGS_UART1; + uart_port[1].membase = ioremap(uart_port[1].mapbase, 256); + uart_port[1].regshift = 2; + res = early_serial_setup(&uart_port[1]); + if (res) + return res; + } + + res = platform_device_register(&physmap_flash); + if (res) + return res; + + ar7_device_disable(vlynq_low_data.reset_bit); + res = platform_device_register(&vlynq_low); + if (res) + return res; + + if (ar7_has_high_vlynq()) { + ar7_device_disable(vlynq_high_data.reset_bit); + res = platform_device_register(&vlynq_high); + if (res) + return res; + } + + if (ar7_has_high_cpmac()) { + cpmac_get_mac(1, cpmac_high_data.dev_addr); + res = platform_device_register(&cpmac_high); + if (res) + return res; + } else { + cpmac_low_data.phy_mask = 0xffffffff; + } + + cpmac_get_mac(0, cpmac_low_data.dev_addr); + res = platform_device_register(&cpmac_low); + if (res) + return res; + + detect_leds(); + res = platform_device_register(&ar7_gpio_leds); + if (res) + return res; + + res = platform_device_register(&ar7_udc); + + return res; +} +arch_initcall(ar7_register_devices); diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c new file mode 100644 index 00000000000..a320bceb2f9 --- /dev/null +++ b/arch/mips/ar7/prom.c @@ -0,0 +1,297 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Putting things on the screen/serial line using YAMONs facilities. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MAX_ENTRY 80 + +struct env_var { + char *name; + char *value; +}; + +static struct env_var adam2_env[MAX_ENTRY]; + +char *prom_getenv(const char *name) +{ + int i; + for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++) + if (!strcmp(name, adam2_env[i].name)) + return adam2_env[i].value; + + return NULL; +} +EXPORT_SYMBOL(prom_getenv); + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +static void __init ar7_init_cmdline(int argc, char *argv[]) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while (actr < argc) { + strcpy(cp, argv[actr]); + cp += strlen(argv[actr]); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) { + /* get rid of trailing space */ + --cp; + *cp = '\0'; + } +} + +struct psbl_rec { + u32 psbl_size; + u32 env_base; + u32 env_size; + u32 ffs_base; + u32 ffs_size; +}; + +static __initdata char psp_env_version[] = "TIENV0.8"; + +struct psp_env_chunk { + u8 num; + u8 ctrl; + u16 csum; + u8 len; + char data[11]; +} __attribute__ ((packed)); + +struct psp_var_map_entry { + u8 num; + char *value; +}; + +static struct psp_var_map_entry psp_var_map[] = { + { 1, "cpufrequency" }, + { 2, "memsize" }, + { 3, "flashsize" }, + { 4, "modetty0" }, + { 5, "modetty1" }, + { 8, "maca" }, + { 9, "macb" }, + { 28, "sysfrequency" }, + { 38, "mipsfrequency" }, +}; + +/* + +Well-known variable (num is looked up in table above for matching variable name) +Example: cpufrequency=211968000 ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- +| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- + +Name=Value pair in a single chunk +Example: NAME=VALUE ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- +| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0 ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- + +Name=Value pair in 2 chunks (len is the number of chunks) +Example: bootloaderVersion=1.3.7.15 ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- +| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- +| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0 ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- + +Data is padded with 0xFF + +*/ + +#define PSP_ENV_SIZE 4096 + +static char psp_env_data[PSP_ENV_SIZE] = { 0, }; + +static char * __init lookup_psp_var_map(u8 num) +{ + int i; + + for (i = 0; i < sizeof(psp_var_map); i++) + if (psp_var_map[i].num == num) + return psp_var_map[i].value; + + return NULL; +} + +static void __init add_adam2_var(char *name, char *value) +{ + int i; + for (i = 0; i < MAX_ENTRY; i++) { + if (!adam2_env[i].name) { + adam2_env[i].name = name; + adam2_env[i].value = value; + return; + } else if (!strcmp(adam2_env[i].name, name)) { + adam2_env[i].value = value; + return; + } + } +} + +static int __init parse_psp_env(void *psp_env_base) +{ + int i, n; + char *name, *value; + struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data; + + memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE); + + i = 1; + n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk); + while (i < n) { + if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n)) + break; + value = chunks[i].data; + if (chunks[i].num) { + name = lookup_psp_var_map(chunks[i].num); + } else { + name = value; + value += strlen(name) + 1; + } + if (name) + add_adam2_var(name, value); + i += chunks[i].len; + } + return 0; +} + +static void __init ar7_init_env(struct env_var *env) +{ + int i; + struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300)); + void *psp_env = (void *)KSEG1ADDR(psbl->env_base); + + if (strcmp(psp_env, psp_env_version) == 0) { + parse_psp_env(psp_env); + } else { + for (i = 0; i < MAX_ENTRY; i++, env++) + if (env->name) + add_adam2_var(env->name, env->value); + } +} + +static void __init console_config(void) +{ +#ifdef CONFIG_SERIAL_8250_CONSOLE + char console_string[40]; + int baud = 0; + char parity = '\0', bits = '\0', flow = '\0'; + char *s, *p; + + if (strstr(prom_getcmdline(), "console=")) + return; + +#ifdef CONFIG_KGDB + if (!strstr(prom_getcmdline(), "nokgdb")) { + strcat(prom_getcmdline(), " console=kgdb"); + kgdb_enabled = 1; + return; + } +#endif + + s = prom_getenv("modetty0"); + if (s) { + baud = simple_strtoul(s, &p, 10); + s = p; + if (*s == ',') + s++; + if (*s) + parity = *s++; + if (*s == ',') + s++; + if (*s) + bits = *s++; + if (*s == ',') + s++; + if (*s == 'h') + flow = 'r'; + } + + if (baud == 0) + baud = 38400; + if (parity != 'n' && parity != 'o' && parity != 'e') + parity = 'n'; + if (bits != '7' && bits != '8') + bits = '8'; + + if (flow == 'r') + sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, + parity, bits, flow); + else + sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity, + bits); + strcat(prom_getcmdline(), console_string); +#endif +} + +void __init prom_init(void) +{ + ar7_init_cmdline(fw_arg0, (char **)fw_arg1); + ar7_init_env((struct env_var *)fw_arg2); + console_config(); +} + +#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4))) +static inline unsigned int serial_in(int offset) +{ + return readl((void *)PORT(offset)); +} + +static inline void serial_out(int offset, int value) +{ + writel(value, (void *)PORT(offset)); +} + +char prom_getchar(void) +{ + while (!(serial_in(UART_LSR) & UART_LSR_DR)) + ; + return serial_in(UART_RX); +} + +int prom_putchar(char c) +{ + while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0) + ; + serial_out(UART_TX, c); + return 1; +} + diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c new file mode 100644 index 00000000000..6ebb5f16d96 --- /dev/null +++ b/arch/mips/ar7/setup.c @@ -0,0 +1,94 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +static void ar7_machine_restart(char *command) +{ + u32 *softres_reg = ioremap(AR7_REGS_RESET + + AR7_RESET_SOFTWARE, 1); + writel(1, softres_reg); +} + +static void ar7_machine_halt(void) +{ + while (1) + ; +} + +static void ar7_machine_power_off(void) +{ + u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1); + u32 power_state = readl(power_reg) | (3 << 30); + writel(power_state, power_reg); + ar7_machine_halt(); +} + +const char *get_system_type(void) +{ + u16 chip_id = ar7_chip_id(); + switch (chip_id) { + case AR7_CHIP_7300: + return "TI AR7 (TNETD7300)"; + case AR7_CHIP_7100: + return "TI AR7 (TNETD7100)"; + case AR7_CHIP_7200: + return "TI AR7 (TNETD7200)"; + default: + return "TI AR7 (Unknown)"; + } +} + +static int __init ar7_init_console(void) +{ + return 0; +} +console_initcall(ar7_init_console); + +/* + * Initializes basic routines and structures pointers, memory size (as + * given by the bios and saves the command line. + */ + +void __init plat_mem_setup(void) +{ + unsigned long io_base; + + _machine_restart = ar7_machine_restart; + _machine_halt = ar7_machine_halt; + pm_power_off = ar7_machine_power_off; + panic_timeout = 3; + + io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000); + if (!io_base) + panic("Can't remap IO base!\n"); + set_io_port_base(io_base); + + prom_meminit(); + + printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n", + get_system_type(), + ar7_chip_id(), ar7_chip_rev()); +} diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c new file mode 100644 index 00000000000..a1fba894daa --- /dev/null +++ b/arch/mips/ar7/time.c @@ -0,0 +1,30 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Setting up the clock on the MIPS boards. + */ + +#include +#include + +#include +#include + +void __init plat_time_init(void) +{ + mips_hpt_frequency = ar7_cpu_freq() / 2; +} diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig new file mode 100644 index 00000000000..dad5b6769d7 --- /dev/null +++ b/arch/mips/configs/ar7_defconfig @@ -0,0 +1,1182 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.30 +# Wed Jun 24 14:08:59 2009 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MACH_ALCHEMY is not set +CONFIG_AR7=y +# CONFIG_BASLER_EXCITE is not set +# CONFIG_BCM47XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_NEC_MARKEINS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SNI_RM is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_WR_PPMC is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_CEVT_R4K_LIB=y +CONFIG_CEVT_R4K=y +CONFIG_CSRC_R4K_LIB=y +CONFIG_CSRC_R4K=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +# CONFIG_HOTPLUG_CPU is not set +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_GPIO=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_NO_EXCEPT_FILL=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_LOONGSON2 is not set +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R5500 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_CAVIUM_OCTEON is not set +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_HARDWARE_WATCHPOINTS=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_32KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_48 is not set +CONFIG_HZ_100=y +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=100 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_KEXEC=y +# CONFIG_SECCOMP is not set +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_RELAY=y +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +# CONFIG_PCSPKR_PLATFORM is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Performance Counters +# +# CONFIG_VM_EVENT_COUNTERS is not set +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_SLOW_WORK is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_PROBE_INITRD_HEADER=y +# CONFIG_FREEZER is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_MMU=y +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Power management options +# +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_PM is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_CUBIC is not set +CONFIG_TCP_CONG_WESTWOOD=y +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_DEFAULT_BIC is not set +# CONFIG_DEFAULT_CUBIC is not set +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_VEGAS is not set +CONFIG_DEFAULT_WESTWOOD=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="westwood" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +# CONFIG_BRIDGE_NETFILTER is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +CONFIG_NF_CONNTRACK=m +# CONFIG_NF_CT_ACCT is not set +CONFIG_NF_CONNTRACK_MARK=y +# CONFIG_NF_CONNTRACK_EVENTS is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +# CONFIG_NF_CT_PROTO_UDPLITE is not set +# CONFIG_NF_CONNTRACK_AMANDA is not set +CONFIG_NF_CONNTRACK_FTP=m +# CONFIG_NF_CONNTRACK_H323 is not set +CONFIG_NF_CONNTRACK_IRC=m +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SIP is not set +CONFIG_NF_CONNTRACK_TFTP=m +# CONFIG_NF_CT_NETLINK is not set +# CONFIG_NETFILTER_TPROXY is not set +CONFIG_NETFILTER_XTABLES=m +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set +# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_STATE=m +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=m +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_TTL is not set +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +# CONFIG_IP_NF_TARGET_ULOG is not set +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_REDIRECT is not set +# CONFIG_NF_NAT_SNMP_BASIC is not set +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +# CONFIG_NF_NAT_AMANDA is not set +# CONFIG_NF_NAT_PPTP is not set +# CONFIG_NF_NAT_H323 is not set +# CONFIG_NF_NAT_SIP is not set +CONFIG_IP_NF_MANGLE=m +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=m +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +CONFIG_ATM=m +# CONFIG_ATM_CLIP is not set +# CONFIG_ATM_LANE is not set +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_STP=y +CONFIG_BRIDGE=y +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_ATM is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_INGRESS is not set + +# +# Classification +# +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_EMATCH is not set +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +# CONFIG_AX25 is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_CFG80211=m +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_WIRELESS_OLD_REGULATORY is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_DEFAULT_PS=y +CONFIG_MAC80211_DEFAULT_PS_VALUE=1 + +# +# Rate control algorithm selection +# +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT="pid" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_IFB is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +CONFIG_CPMAC=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_P54_COMMON is not set +# CONFIG_HOSTAP is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_RT2X00 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +# CONFIG_ATM_TCP is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_MPPE is not set +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=m +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AR7_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=y +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_SERIAL=y +CONFIG_SSB_DRIVER_MIPS=y +CONFIG_SSB_EMBEDDED=y +CONFIG_SSB_DRIVER_EXTIF=y + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_GPIO is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +CONFIG_VLYNQ=y +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m +CONFIG_CRYPTO_PCOMP=m +CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=m +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h new file mode 100644 index 00000000000..de71694614d --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/ar7.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2006,2007 Felix Fietkau + * Copyright (C) 2006,2007 Eugene Konev + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __AR7_H__ +#define __AR7_H__ + +#include +#include +#include + +#include + +#define AR7_SDRAM_BASE 0x14000000 + +#define AR7_REGS_BASE 0x08610000 + +#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000) +#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900) +/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */ +#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00) +#define AR7_REGS_CLOCKS (AR7_REGS_POWER + 0x80) +#define UR8_REGS_CLOCKS (AR7_REGS_POWER + 0x20) +#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00) +#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200) +#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600) +#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800) +#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00) +#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00) +#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00) +#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400) +#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800) + +#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00) +#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00) +#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00) + +#define AR7_RESET_PEREPHERIAL 0x0 +#define AR7_RESET_SOFTWARE 0x4 +#define AR7_RESET_STATUS 0x8 + +#define AR7_RESET_BIT_CPMAC_LO 17 +#define AR7_RESET_BIT_CPMAC_HI 21 +#define AR7_RESET_BIT_MDIO 22 +#define AR7_RESET_BIT_EPHY 26 + +/* GPIO control registers */ +#define AR7_GPIO_INPUT 0x0 +#define AR7_GPIO_OUTPUT 0x4 +#define AR7_GPIO_DIR 0x8 +#define AR7_GPIO_ENABLE 0xc + +#define AR7_CHIP_7100 0x18 +#define AR7_CHIP_7200 0x2b +#define AR7_CHIP_7300 0x05 + +/* Interrupts */ +#define AR7_IRQ_UART0 15 +#define AR7_IRQ_UART1 16 + +/* Clocks */ +#define AR7_AFE_CLOCK 35328000 +#define AR7_REF_CLOCK 25000000 +#define AR7_XTAL_CLOCK 24000000 + +struct plat_cpmac_data { + int reset_bit; + int power_bit; + u32 phy_mask; + char dev_addr[6]; +}; + +struct plat_dsl_data { + int reset_bit_dsl; + int reset_bit_sar; +}; + +extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock; + +static inline u16 ar7_chip_id(void) +{ + return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff; +} + +static inline u8 ar7_chip_rev(void) +{ + return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff; +} + +static inline int ar7_cpu_freq(void) +{ + return ar7_cpu_clock; +} + +static inline int ar7_bus_freq(void) +{ + return ar7_bus_clock; +} + +static inline int ar7_vbus_freq(void) +{ + return ar7_bus_clock / 2; +} +#define ar7_cpmac_freq ar7_vbus_freq + +static inline int ar7_dsp_freq(void) +{ + return ar7_dsp_clock; +} + +static inline int ar7_has_high_cpmac(void) +{ + u16 chip_id = ar7_chip_id(); + switch (chip_id) { + case AR7_CHIP_7100: + case AR7_CHIP_7200: + return 0; + case AR7_CHIP_7300: + return 1; + default: + return -ENXIO; + } +} +#define ar7_has_high_vlynq ar7_has_high_cpmac +#define ar7_has_second_uart ar7_has_high_cpmac + +static inline void ar7_device_enable(u32 bit) +{ + void *reset_reg = + (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); + writel(readl(reset_reg) | (1 << bit), reset_reg); + msleep(20); +} + +static inline void ar7_device_disable(u32 bit) +{ + void *reset_reg = + (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); + writel(readl(reset_reg) & ~(1 << bit), reset_reg); + msleep(20); +} + +static inline void ar7_device_reset(u32 bit) +{ + ar7_device_disable(bit); + ar7_device_enable(bit); +} + +static inline void ar7_device_on(u32 bit) +{ + void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER); + writel(readl(power_reg) | (1 << bit), power_reg); + msleep(20); +} + +static inline void ar7_device_off(u32 bit) +{ + void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER); + writel(readl(power_reg) & ~(1 << bit), power_reg); + msleep(20); +} + +#endif /* __AR7_H__ */ diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h new file mode 100644 index 00000000000..cbe9c4f126d --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/gpio.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007 Florian Fainelli + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __AR7_GPIO_H__ +#define __AR7_GPIO_H__ + +#include + +#define AR7_GPIO_MAX 32 + +extern int gpio_request(unsigned gpio, const char *label); +extern void gpio_free(unsigned gpio); + +/* Common GPIO layer */ +static inline int gpio_get_value(unsigned gpio) +{ + void __iomem *gpio_in = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT); + + return readl(gpio_in) & (1 << gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + void __iomem *gpio_out = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT); + unsigned tmp; + + tmp = readl(gpio_out) & ~(1 << gpio); + if (value) + tmp |= 1 << gpio; + writel(tmp, gpio_out); +} + +static inline int gpio_direction_input(unsigned gpio) +{ + void __iomem *gpio_dir = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); + + if (gpio >= AR7_GPIO_MAX) + return -EINVAL; + + writel(readl(gpio_dir) | (1 << gpio), gpio_dir); + + return 0; +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + void __iomem *gpio_dir = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); + + if (gpio >= AR7_GPIO_MAX) + return -EINVAL; + + gpio_set_value(gpio, value); + writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir); + + return 0; +} + +static inline int gpio_to_irq(unsigned gpio) +{ + return -EINVAL; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return -EINVAL; +} + +/* Board specific GPIO functions */ +static inline int ar7_gpio_enable(unsigned gpio) +{ + void __iomem *gpio_en = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); + + writel(readl(gpio_en) | (1 << gpio), gpio_en); + + return 0; +} + +static inline int ar7_gpio_disable(unsigned gpio) +{ + void __iomem *gpio_en = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); + + writel(readl(gpio_en) & ~(1 << gpio), gpio_en); + + return 0; +} + +#include + +#endif diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h new file mode 100644 index 00000000000..39e9757e3d9 --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/irq.h @@ -0,0 +1,16 @@ +/* + * 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. + * + * Shamelessly copied from asm-mips/mach-emma2rh/ + * Copyright (C) 2003 by Ralf Baechle + */ +#ifndef __ASM_AR7_IRQ_H +#define __ASM_AR7_IRQ_H + +#define NR_IRQS 256 + +#include_next + +#endif /* __ASM_AR7_IRQ_H */ diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h new file mode 100644 index 00000000000..088f61fe85e --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/prom.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2006, 2007 Florian Fainelli + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __PROM_H__ +#define __PROM_H__ + +extern char *prom_getenv(const char *name); +extern void prom_meminit(void); + +#endif /* __PROM_H__ */ diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h new file mode 100644 index 00000000000..ac28f273449 --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/spaces.h @@ -0,0 +1,22 @@ +/* + * 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) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_AR7_SPACES_H +#define _ASM_AR7_SPACES_H + +/* + * This handles the memory map. + * We handle pages at KSEG0 for kernels with 32 bit address space. + */ +#define PAGE_OFFSET 0x94000000UL +#define PHYS_OFFSET 0x14000000UL + +#include + +#endif /* __ASM_AR7_SPACES_H */ diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h new file mode 100644 index 00000000000..f4862b56308 --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/war.h @@ -0,0 +1,25 @@ +/* + * 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) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_AR7_WAR_H +#define __ASM_MIPS_MACH_AR7_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_AR7_WAR_H */ -- cgit v1.2.3 From 52a7a27cd8f6c57817da99fef019e37b9c303c4e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 28 Jun 2009 09:26:09 -0700 Subject: MIPS: MT: Remove unnecessary semicolons Signed-off-by: Joe Perches Signed-off-by: Ralf Baechle --- arch/mips/kernel/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 3ca5f42e819..07b9ec2c6e3 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1387,7 +1387,7 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr, return len; out_einval: - return -EINVAL;; + return -EINVAL; } static struct device_attribute vpe_class_attributes[] = { -- cgit v1.2.3 From d7e014db374d987c6bcff0b9abab2c6796f8e793 Mon Sep 17 00:00:00 2001 From: Dmitri Vorobiev Date: Fri, 26 Jun 2009 19:59:25 +0300 Subject: MIPS: Malta: Remove unnecessary function prototypes Signed-off-by: Dmitri Vorobiev Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/malta-reset.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/mips/mti-malta/malta-reset.c b/arch/mips/mti-malta/malta-reset.c index 42dee4da37b..f48d60e8429 100644 --- a/arch/mips/mti-malta/malta-reset.c +++ b/arch/mips/mti-malta/malta-reset.c @@ -28,9 +28,6 @@ #include #include -static void mips_machine_restart(char *command); -static void mips_machine_halt(void); - static void mips_machine_restart(char *command) { unsigned int __iomem *softres_reg = -- cgit v1.2.3 From 69f16c9a8630edc64cb1d6f1bfca4ee7bc16279f Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 26 Jun 2009 09:53:57 -0700 Subject: MIPS: Hookup new syscalls sys_rt_tgsigqueueinfo and sys_perf_counter_open. [Ralf: I fixed up the numbering in the comment in scall64-n32.S.] Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/include/asm/unistd.h | 18 ++++++++++++------ arch/mips/kernel/scall32-o32.S | 2 ++ arch/mips/kernel/scall64-64.S | 2 ++ arch/mips/kernel/scall64-n32.S | 2 ++ arch/mips/kernel/scall64-o32.S | 2 ++ 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index 40005010827..b70c49fdda2 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -352,16 +352,18 @@ #define __NR_inotify_init1 (__NR_Linux + 329) #define __NR_preadv (__NR_Linux + 330) #define __NR_pwritev (__NR_Linux + 331) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332) +#define __NR_perf_counter_open (__NR_Linux + 333) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 331 +#define __NR_Linux_syscalls 333 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 331 +#define __NR_O32_Linux_syscalls 333 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -660,16 +662,18 @@ #define __NR_inotify_init1 (__NR_Linux + 288) #define __NR_preadv (__NR_Linux + 289) #define __NR_pwritev (__NR_Linux + 290) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291) +#define __NR_perf_counter_open (__NR_Linux + 292) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 290 +#define __NR_Linux_syscalls 292 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 290 +#define __NR_64_Linux_syscalls 292 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -972,16 +976,18 @@ #define __NR_inotify_init1 (__NR_Linux + 292) #define __NR_preadv (__NR_Linux + 293) #define __NR_pwritev (__NR_Linux + 294) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295) +#define __NR_perf_counter_open (__NR_Linux + 296) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 294 +#define __NR_Linux_syscalls 296 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 294 +#define __NR_N32_Linux_syscalls 296 #ifdef __KERNEL__ diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 0b31b9bda04..20a86e08fd5 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -652,6 +652,8 @@ einval: li v0, -ENOSYS sys sys_inotify_init1 1 sys sys_preadv 6 /* 4330 */ sys sys_pwritev 6 + sys sys_rt_tgsigqueueinfo 4 + sys sys_perf_counter_open 5 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index c647fd6e722..b046130d4c5 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -489,4 +489,6 @@ sys_call_table: PTR sys_inotify_init1 PTR sys_preadv PTR sys_pwritev /* 5390 */ + PTR sys_rt_tgsigqueueinfo + PTR sys_perf_counter_open .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 93cc672f452..15874f9812c 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -415,4 +415,6 @@ EXPORT(sysn32_call_table) PTR sys_inotify_init1 PTR sys_preadv PTR sys_pwritev + PTR compat_sys_rt_tgsigqueueinfo /* 5295 */ + PTR sys_perf_counter_open .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index a5598b2339d..781e0f1e953 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -535,4 +535,6 @@ sys_call_table: PTR sys_inotify_init1 PTR compat_sys_preadv /* 4330 */ PTR compat_sys_pwritev + PTR compat_sys_rt_tgsigqueueinfo + PTR sys_perf_counter_open .size sys_call_table,.-sys_call_table -- cgit v1.2.3 From 27fdd325dace4a1ebfa10e93ba6f3d25f25df674 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Mon, 29 Jun 2009 11:11:05 +0900 Subject: MIPS: Update VR41xx GPIO driver to use gpiolib Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/include/asm/vr41xx/giu.h | 22 +- drivers/char/Kconfig | 4 - drivers/char/Makefile | 1 - drivers/char/vr41xx_giu.c | 680 ------------------------------------- drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/vr41xx_giu.c | 586 ++++++++++++++++++++++++++++++++ 8 files changed, 597 insertions(+), 704 deletions(-) create mode 100644 drivers/gpio/vr41xx_giu.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b0e55113633..64891f74019 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -267,6 +267,7 @@ config MACH_VR41XX select CEVT_R4K select CSRC_R4K select SYS_HAS_CPU_VR41XX + select ARCH_REQUIRE_GPIOLIB config NXP_STB220 bool "NXP STB220 board" diff --git a/arch/mips/include/asm/vr41xx/giu.h b/arch/mips/include/asm/vr41xx/giu.h index 0bcdd3a5c25..b369c091b0e 100644 --- a/arch/mips/include/asm/vr41xx/giu.h +++ b/arch/mips/include/asm/vr41xx/giu.h @@ -1,7 +1,7 @@ /* * Include file for NEC VR4100 series General-purpose I/O Unit. * - * Copyright (C) 2005 Yoichi Yuasa + * Copyright (C) 2005-2009 Yoichi Yuasa * * 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 @@ -41,7 +41,8 @@ typedef enum { IRQ_SIGNAL_HOLD, } irq_signal_t; -extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal); +extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, + irq_signal_t signal); typedef enum { IRQ_LEVEL_LOW, @@ -50,23 +51,6 @@ typedef enum { extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level); -typedef enum { - GPIO_DATA_LOW, - GPIO_DATA_HIGH, - GPIO_DATA_INVAL, -} gpio_data_t; - -extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin); -extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data); - -typedef enum { - GPIO_INPUT, - GPIO_OUTPUT, - GPIO_OUTPUT_DISABLE, -} gpio_direction_t; - -extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir); - typedef enum { GPIO_PULL_DOWN, GPIO_PULL_UP, diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0bd01f49cfd..6a06913b01d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -1029,10 +1029,6 @@ config CS5535_GPIO If compiled as a module, it will be called cs5535_gpio. -config GPIO_VR41XX - tristate "NEC VR4100 series General-purpose I/O Unit support" - depends on CPU_VR41XX - config RAW_DRIVER tristate "RAW driver (/dev/raw/rawN)" depends on BLOCK diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 189efcff08c..66f779ad4f4 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -95,7 +95,6 @@ obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o -obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o obj-$(CONFIG_GPIO_TB0219) += tb0219.o obj-$(CONFIG_TELCLOCK) += tlclk.o diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 54c837288d1..e69de29bb2d 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c @@ -1,680 +0,0 @@ -/* - * Driver for NEC VR4100 series General-purpose I/O Unit. - * - * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa - * Copyright (C) 2003-2007 Yoichi Yuasa - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -MODULE_AUTHOR("Yoichi Yuasa "); -MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); -MODULE_LICENSE("GPL"); - -static int major; /* default is dynamic major device number */ -module_param(major, int, 0); -MODULE_PARM_DESC(major, "Major device number"); - -#define GIUIOSELL 0x00 -#define GIUIOSELH 0x02 -#define GIUPIODL 0x04 -#define GIUPIODH 0x06 -#define GIUINTSTATL 0x08 -#define GIUINTSTATH 0x0a -#define GIUINTENL 0x0c -#define GIUINTENH 0x0e -#define GIUINTTYPL 0x10 -#define GIUINTTYPH 0x12 -#define GIUINTALSELL 0x14 -#define GIUINTALSELH 0x16 -#define GIUINTHTSELL 0x18 -#define GIUINTHTSELH 0x1a -#define GIUPODATL 0x1c -#define GIUPODATEN 0x1c -#define GIUPODATH 0x1e - #define PIOEN0 0x0100 - #define PIOEN1 0x0200 -#define GIUPODAT 0x1e -#define GIUFEDGEINHL 0x20 -#define GIUFEDGEINHH 0x22 -#define GIUREDGEINHL 0x24 -#define GIUREDGEINHH 0x26 - -#define GIUUSEUPDN 0x1e0 -#define GIUTERMUPDN 0x1e2 - -#define GPIO_HAS_PULLUPDOWN_IO 0x0001 -#define GPIO_HAS_OUTPUT_ENABLE 0x0002 -#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 - -static spinlock_t giu_lock; -static unsigned long giu_flags; -static unsigned int giu_nr_pins; - -static void __iomem *giu_base; - -#define giu_read(offset) readw(giu_base + (offset)) -#define giu_write(offset, value) writew((value), giu_base + (offset)) - -#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) -#define GIUINT_HIGH_OFFSET 16 -#define GIUINT_HIGH_MAX 32 - -static inline uint16_t giu_set(uint16_t offset, uint16_t set) -{ - uint16_t data; - - data = giu_read(offset); - data |= set; - giu_write(offset, data); - - return data; -} - -static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) -{ - uint16_t data; - - data = giu_read(offset); - data &= ~clear; - giu_write(offset, data); - - return data; -} - -static void ack_giuint_low(unsigned int irq) -{ - giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); -} - -static void mask_giuint_low(unsigned int irq) -{ - giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); -} - -static void mask_ack_giuint_low(unsigned int irq) -{ - unsigned int pin; - - pin = GPIO_PIN_OF_IRQ(irq); - giu_clear(GIUINTENL, 1 << pin); - giu_write(GIUINTSTATL, 1 << pin); -} - -static void unmask_giuint_low(unsigned int irq) -{ - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); -} - -static struct irq_chip giuint_low_irq_chip = { - .name = "GIUINTL", - .ack = ack_giuint_low, - .mask = mask_giuint_low, - .mask_ack = mask_ack_giuint_low, - .unmask = unmask_giuint_low, -}; - -static void ack_giuint_high(unsigned int irq) -{ - giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); -} - -static void mask_giuint_high(unsigned int irq) -{ - giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); -} - -static void mask_ack_giuint_high(unsigned int irq) -{ - unsigned int pin; - - pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; - giu_clear(GIUINTENH, 1 << pin); - giu_write(GIUINTSTATH, 1 << pin); -} - -static void unmask_giuint_high(unsigned int irq) -{ - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); -} - -static struct irq_chip giuint_high_irq_chip = { - .name = "GIUINTH", - .ack = ack_giuint_high, - .mask = mask_giuint_high, - .mask_ack = mask_ack_giuint_high, - .unmask = unmask_giuint_high, -}; - -static int giu_get_irq(unsigned int irq) -{ - uint16_t pendl, pendh, maskl, maskh; - int i; - - pendl = giu_read(GIUINTSTATL); - pendh = giu_read(GIUINTSTATH); - maskl = giu_read(GIUINTENL); - maskh = giu_read(GIUINTENH); - - maskl &= pendl; - maskh &= pendh; - - if (maskl) { - for (i = 0; i < 16; i++) { - if (maskl & (1 << i)) - return GIU_IRQ(i); - } - } else if (maskh) { - for (i = 0; i < 16; i++) { - if (maskh & (1 << i)) - return GIU_IRQ(i + GIUINT_HIGH_OFFSET); - } - } - - printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", - maskl, pendl, maskh, pendh); - - atomic_inc(&irq_err_count); - - return -EINVAL; -} - -void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal) -{ - uint16_t mask; - - if (pin < GIUINT_HIGH_OFFSET) { - mask = 1 << pin; - if (trigger != IRQ_TRIGGER_LEVEL) { - giu_set(GIUINTTYPL, mask); - if (signal == IRQ_SIGNAL_HOLD) - giu_set(GIUINTHTSELL, mask); - else - giu_clear(GIUINTHTSELL, mask); - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { - switch (trigger) { - case IRQ_TRIGGER_EDGE_FALLING: - giu_set(GIUFEDGEINHL, mask); - giu_clear(GIUREDGEINHL, mask); - break; - case IRQ_TRIGGER_EDGE_RISING: - giu_clear(GIUFEDGEINHL, mask); - giu_set(GIUREDGEINHL, mask); - break; - default: - giu_set(GIUFEDGEINHL, mask); - giu_set(GIUREDGEINHL, mask); - break; - } - } - set_irq_chip_and_handler(GIU_IRQ(pin), - &giuint_low_irq_chip, - handle_edge_irq); - } else { - giu_clear(GIUINTTYPL, mask); - giu_clear(GIUINTHTSELL, mask); - set_irq_chip_and_handler(GIU_IRQ(pin), - &giuint_low_irq_chip, - handle_level_irq); - } - giu_write(GIUINTSTATL, mask); - } else if (pin < GIUINT_HIGH_MAX) { - mask = 1 << (pin - GIUINT_HIGH_OFFSET); - if (trigger != IRQ_TRIGGER_LEVEL) { - giu_set(GIUINTTYPH, mask); - if (signal == IRQ_SIGNAL_HOLD) - giu_set(GIUINTHTSELH, mask); - else - giu_clear(GIUINTHTSELH, mask); - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { - switch (trigger) { - case IRQ_TRIGGER_EDGE_FALLING: - giu_set(GIUFEDGEINHH, mask); - giu_clear(GIUREDGEINHH, mask); - break; - case IRQ_TRIGGER_EDGE_RISING: - giu_clear(GIUFEDGEINHH, mask); - giu_set(GIUREDGEINHH, mask); - break; - default: - giu_set(GIUFEDGEINHH, mask); - giu_set(GIUREDGEINHH, mask); - break; - } - } - set_irq_chip_and_handler(GIU_IRQ(pin), - &giuint_high_irq_chip, - handle_edge_irq); - } else { - giu_clear(GIUINTTYPH, mask); - giu_clear(GIUINTHTSELH, mask); - set_irq_chip_and_handler(GIU_IRQ(pin), - &giuint_high_irq_chip, - handle_level_irq); - } - giu_write(GIUINTSTATH, mask); - } -} -EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); - -void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) -{ - uint16_t mask; - - if (pin < GIUINT_HIGH_OFFSET) { - mask = 1 << pin; - if (level == IRQ_LEVEL_HIGH) - giu_set(GIUINTALSELL, mask); - else - giu_clear(GIUINTALSELL, mask); - giu_write(GIUINTSTATL, mask); - } else if (pin < GIUINT_HIGH_MAX) { - mask = 1 << (pin - GIUINT_HIGH_OFFSET); - if (level == IRQ_LEVEL_HIGH) - giu_set(GIUINTALSELH, mask); - else - giu_clear(GIUINTALSELH, mask); - giu_write(GIUINTSTATH, mask); - } -} -EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); - -gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) -{ - uint16_t reg, mask; - - if (pin >= giu_nr_pins) - return GPIO_DATA_INVAL; - - if (pin < 16) { - reg = giu_read(GIUPIODL); - mask = (uint16_t)1 << pin; - } else if (pin < 32) { - reg = giu_read(GIUPIODH); - mask = (uint16_t)1 << (pin - 16); - } else if (pin < 48) { - reg = giu_read(GIUPODATL); - mask = (uint16_t)1 << (pin - 32); - } else { - reg = giu_read(GIUPODATH); - mask = (uint16_t)1 << (pin - 48); - } - - if (reg & mask) - return GPIO_DATA_HIGH; - - return GPIO_DATA_LOW; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); - -int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) -{ - uint16_t offset, mask, reg; - unsigned long flags; - - if (pin >= giu_nr_pins) - return -EINVAL; - - if (pin < 16) { - offset = GIUPIODL; - mask = (uint16_t)1 << pin; - } else if (pin < 32) { - offset = GIUPIODH; - mask = (uint16_t)1 << (pin - 16); - } else if (pin < 48) { - offset = GIUPODATL; - mask = (uint16_t)1 << (pin - 32); - } else { - offset = GIUPODATH; - mask = (uint16_t)1 << (pin - 48); - } - - spin_lock_irqsave(&giu_lock, flags); - - reg = giu_read(offset); - if (data == GPIO_DATA_HIGH) - reg |= mask; - else - reg &= ~mask; - giu_write(offset, reg); - - spin_unlock_irqrestore(&giu_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); - -int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) -{ - uint16_t offset, mask, reg; - unsigned long flags; - - if (pin >= giu_nr_pins) - return -EINVAL; - - if (pin < 16) { - offset = GIUIOSELL; - mask = (uint16_t)1 << pin; - } else if (pin < 32) { - offset = GIUIOSELH; - mask = (uint16_t)1 << (pin - 16); - } else { - if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { - offset = GIUPODATEN; - mask = (uint16_t)1 << (pin - 32); - } else { - switch (pin) { - case 48: - offset = GIUPODATH; - mask = PIOEN0; - break; - case 49: - offset = GIUPODATH; - mask = PIOEN1; - break; - default: - return -EINVAL; - } - } - } - - spin_lock_irqsave(&giu_lock, flags); - - reg = giu_read(offset); - if (dir == GPIO_OUTPUT) - reg |= mask; - else - reg &= ~mask; - giu_write(offset, reg); - - spin_unlock_irqrestore(&giu_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); - -int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) -{ - uint16_t reg, mask; - unsigned long flags; - - if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) - return -EPERM; - - if (pin >= 15) - return -EINVAL; - - mask = (uint16_t)1 << pin; - - spin_lock_irqsave(&giu_lock, flags); - - if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { - reg = giu_read(GIUTERMUPDN); - if (pull == GPIO_PULL_UP) - reg |= mask; - else - reg &= ~mask; - giu_write(GIUTERMUPDN, reg); - - reg = giu_read(GIUUSEUPDN); - reg |= mask; - giu_write(GIUUSEUPDN, reg); - } else { - reg = giu_read(GIUUSEUPDN); - reg &= ~mask; - giu_write(GIUUSEUPDN, reg); - } - - spin_unlock_irqrestore(&giu_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); - -static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, - loff_t *ppos) -{ - unsigned int pin; - char value = '0'; - - pin = iminor(file->f_path.dentry->d_inode); - if (pin >= giu_nr_pins) - return -EBADF; - - if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH) - value = '1'; - - if (len <= 0) - return -EFAULT; - - if (put_user(value, buf)) - return -EFAULT; - - return 1; -} - -static ssize_t gpio_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - unsigned int pin; - size_t i; - char c; - int retval = 0; - - pin = iminor(file->f_path.dentry->d_inode); - if (pin >= giu_nr_pins) - return -EBADF; - - for (i = 0; i < len; i++) { - if (get_user(c, data + i)) - return -EFAULT; - - switch (c) { - case '0': - retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW); - break; - case '1': - retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH); - break; - case 'D': - printk(KERN_INFO "GPIO%d: pull down\n", pin); - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN); - break; - case 'd': - printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); - break; - case 'I': - printk(KERN_INFO "GPIO%d: input\n", pin); - retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT); - break; - case 'O': - printk(KERN_INFO "GPIO%d: output\n", pin); - retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT); - break; - case 'o': - printk(KERN_INFO "GPIO%d: output disable\n", pin); - retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE); - break; - case 'P': - printk(KERN_INFO "GPIO%d: pull up\n", pin); - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP); - break; - case 'p': - printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); - break; - default: - break; - } - - if (retval < 0) - break; - } - - return i; -} - -static int gpio_open(struct inode *inode, struct file *file) -{ - unsigned int pin; - - cycle_kernel_lock(); - pin = iminor(inode); - if (pin >= giu_nr_pins) - return -EBADF; - - return nonseekable_open(inode, file); -} - -static int gpio_release(struct inode *inode, struct file *file) -{ - unsigned int pin; - - pin = iminor(inode); - if (pin >= giu_nr_pins) - return -EBADF; - - return 0; -} - -static const struct file_operations gpio_fops = { - .owner = THIS_MODULE, - .read = gpio_read, - .write = gpio_write, - .open = gpio_open, - .release = gpio_release, -}; - -static int __devinit giu_probe(struct platform_device *dev) -{ - struct resource *res; - unsigned int trigger, i, pin; - struct irq_chip *chip; - int irq, retval; - - switch (dev->id) { - case GPIO_50PINS_PULLUPDOWN: - giu_flags = GPIO_HAS_PULLUPDOWN_IO; - giu_nr_pins = 50; - break; - case GPIO_36PINS: - giu_nr_pins = 36; - break; - case GPIO_48PINS_EDGE_SELECT: - giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; - giu_nr_pins = 48; - break; - default: - printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); - return -ENODEV; - } - - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!res) - return -EBUSY; - - giu_base = ioremap(res->start, res->end - res->start + 1); - if (!giu_base) - return -ENOMEM; - - retval = register_chrdev(major, "GIU", &gpio_fops); - if (retval < 0) { - iounmap(giu_base); - giu_base = NULL; - return retval; - } - - if (major == 0) { - major = retval; - printk(KERN_INFO "GIU: major number %d\n", major); - } - - spin_lock_init(&giu_lock); - - giu_write(GIUINTENL, 0); - giu_write(GIUINTENH, 0); - - trigger = giu_read(GIUINTTYPH) << 16; - trigger |= giu_read(GIUINTTYPL); - for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { - pin = GPIO_PIN_OF_IRQ(i); - if (pin < GIUINT_HIGH_OFFSET) - chip = &giuint_low_irq_chip; - else - chip = &giuint_high_irq_chip; - - if (trigger & (1 << pin)) - set_irq_chip_and_handler(i, chip, handle_edge_irq); - else - set_irq_chip_and_handler(i, chip, handle_level_irq); - - } - - irq = platform_get_irq(dev, 0); - if (irq < 0 || irq >= nr_irqs) - return -EBUSY; - - return cascade_irq(irq, giu_get_irq); -} - -static int __devexit giu_remove(struct platform_device *dev) -{ - if (giu_base) { - iounmap(giu_base); - giu_base = NULL; - } - - return 0; -} - -static struct platform_driver giu_device_driver = { - .probe = giu_probe, - .remove = __devexit_p(giu_remove), - .driver = { - .name = "GIU", - .owner = THIS_MODULE, - }, -}; - -static int __init vr41xx_giu_init(void) -{ - return platform_driver_register(&giu_device_driver); -} - -static void __exit vr41xx_giu_exit(void) -{ - platform_driver_unregister(&giu_device_driver); -} - -module_init(vr41xx_giu_init); -module_exit(vr41xx_giu_exit); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3582c39f972..96dda81c922 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -79,6 +79,12 @@ config GPIO_XILINX help Say yes here to support the Xilinx FPGA GPIO device +config GPIO_VR41XX + tristate "NEC VR4100 series General-purpose I/O Uint support" + depends on CPU_VR41XX + help + Say yes here to support the NEC VR4100 series General-purpose I/O Uint + comment "I2C GPIO expanders:" config GPIO_MAX732X diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ef90203e8f3..9244c6fcd8b 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_GPIO_PL061) += pl061.o obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o +obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c new file mode 100644 index 00000000000..f691ffa95fb --- /dev/null +++ b/drivers/gpio/vr41xx_giu.c @@ -0,0 +1,586 @@ +/* + * Driver for NEC VR4100 series General-purpose I/O Unit. + * + * Copyright (C) 2002 MontaVista Software Inc. + * Author: Yoichi Yuasa + * Copyright (C) 2003-2009 Yoichi Yuasa + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); +MODULE_LICENSE("GPL"); + +#define GIUIOSELL 0x00 +#define GIUIOSELH 0x02 +#define GIUPIODL 0x04 +#define GIUPIODH 0x06 +#define GIUINTSTATL 0x08 +#define GIUINTSTATH 0x0a +#define GIUINTENL 0x0c +#define GIUINTENH 0x0e +#define GIUINTTYPL 0x10 +#define GIUINTTYPH 0x12 +#define GIUINTALSELL 0x14 +#define GIUINTALSELH 0x16 +#define GIUINTHTSELL 0x18 +#define GIUINTHTSELH 0x1a +#define GIUPODATL 0x1c +#define GIUPODATEN 0x1c +#define GIUPODATH 0x1e + #define PIOEN0 0x0100 + #define PIOEN1 0x0200 +#define GIUPODAT 0x1e +#define GIUFEDGEINHL 0x20 +#define GIUFEDGEINHH 0x22 +#define GIUREDGEINHL 0x24 +#define GIUREDGEINHH 0x26 + +#define GIUUSEUPDN 0x1e0 +#define GIUTERMUPDN 0x1e2 + +#define GPIO_HAS_PULLUPDOWN_IO 0x0001 +#define GPIO_HAS_OUTPUT_ENABLE 0x0002 +#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 + +enum { + GPIO_INPUT, + GPIO_OUTPUT, +}; + +static DEFINE_SPINLOCK(giu_lock); +static unsigned long giu_flags; + +static void __iomem *giu_base; + +#define giu_read(offset) readw(giu_base + (offset)) +#define giu_write(offset, value) writew((value), giu_base + (offset)) + +#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) +#define GIUINT_HIGH_OFFSET 16 +#define GIUINT_HIGH_MAX 32 + +static inline u16 giu_set(u16 offset, u16 set) +{ + u16 data; + + data = giu_read(offset); + data |= set; + giu_write(offset, data); + + return data; +} + +static inline u16 giu_clear(u16 offset, u16 clear) +{ + u16 data; + + data = giu_read(offset); + data &= ~clear; + giu_write(offset, data); + + return data; +} + +static void ack_giuint_low(unsigned int irq) +{ + giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); +} + +static void mask_giuint_low(unsigned int irq) +{ + giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); +} + +static void mask_ack_giuint_low(unsigned int irq) +{ + unsigned int pin; + + pin = GPIO_PIN_OF_IRQ(irq); + giu_clear(GIUINTENL, 1 << pin); + giu_write(GIUINTSTATL, 1 << pin); +} + +static void unmask_giuint_low(unsigned int irq) +{ + giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); +} + +static struct irq_chip giuint_low_irq_chip = { + .name = "GIUINTL", + .ack = ack_giuint_low, + .mask = mask_giuint_low, + .mask_ack = mask_ack_giuint_low, + .unmask = unmask_giuint_low, +}; + +static void ack_giuint_high(unsigned int irq) +{ + giu_write(GIUINTSTATH, + 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); +} + +static void mask_giuint_high(unsigned int irq) +{ + giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); +} + +static void mask_ack_giuint_high(unsigned int irq) +{ + unsigned int pin; + + pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; + giu_clear(GIUINTENH, 1 << pin); + giu_write(GIUINTSTATH, 1 << pin); +} + +static void unmask_giuint_high(unsigned int irq) +{ + giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); +} + +static struct irq_chip giuint_high_irq_chip = { + .name = "GIUINTH", + .ack = ack_giuint_high, + .mask = mask_giuint_high, + .mask_ack = mask_ack_giuint_high, + .unmask = unmask_giuint_high, +}; + +static int giu_get_irq(unsigned int irq) +{ + u16 pendl, pendh, maskl, maskh; + int i; + + pendl = giu_read(GIUINTSTATL); + pendh = giu_read(GIUINTSTATH); + maskl = giu_read(GIUINTENL); + maskh = giu_read(GIUINTENH); + + maskl &= pendl; + maskh &= pendh; + + if (maskl) { + for (i = 0; i < 16; i++) { + if (maskl & (1 << i)) + return GIU_IRQ(i); + } + } else if (maskh) { + for (i = 0; i < 16; i++) { + if (maskh & (1 << i)) + return GIU_IRQ(i + GIUINT_HIGH_OFFSET); + } + } + + printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", + maskl, pendl, maskh, pendh); + + atomic_inc(&irq_err_count); + + return -EINVAL; +} + +void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, + irq_signal_t signal) +{ + u16 mask; + + if (pin < GIUINT_HIGH_OFFSET) { + mask = 1 << pin; + if (trigger != IRQ_TRIGGER_LEVEL) { + giu_set(GIUINTTYPL, mask); + if (signal == IRQ_SIGNAL_HOLD) + giu_set(GIUINTHTSELL, mask); + else + giu_clear(GIUINTHTSELL, mask); + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { + switch (trigger) { + case IRQ_TRIGGER_EDGE_FALLING: + giu_set(GIUFEDGEINHL, mask); + giu_clear(GIUREDGEINHL, mask); + break; + case IRQ_TRIGGER_EDGE_RISING: + giu_clear(GIUFEDGEINHL, mask); + giu_set(GIUREDGEINHL, mask); + break; + default: + giu_set(GIUFEDGEINHL, mask); + giu_set(GIUREDGEINHL, mask); + break; + } + } + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_low_irq_chip, + handle_edge_irq); + } else { + giu_clear(GIUINTTYPL, mask); + giu_clear(GIUINTHTSELL, mask); + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_low_irq_chip, + handle_level_irq); + } + giu_write(GIUINTSTATL, mask); + } else if (pin < GIUINT_HIGH_MAX) { + mask = 1 << (pin - GIUINT_HIGH_OFFSET); + if (trigger != IRQ_TRIGGER_LEVEL) { + giu_set(GIUINTTYPH, mask); + if (signal == IRQ_SIGNAL_HOLD) + giu_set(GIUINTHTSELH, mask); + else + giu_clear(GIUINTHTSELH, mask); + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { + switch (trigger) { + case IRQ_TRIGGER_EDGE_FALLING: + giu_set(GIUFEDGEINHH, mask); + giu_clear(GIUREDGEINHH, mask); + break; + case IRQ_TRIGGER_EDGE_RISING: + giu_clear(GIUFEDGEINHH, mask); + giu_set(GIUREDGEINHH, mask); + break; + default: + giu_set(GIUFEDGEINHH, mask); + giu_set(GIUREDGEINHH, mask); + break; + } + } + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_high_irq_chip, + handle_edge_irq); + } else { + giu_clear(GIUINTTYPH, mask); + giu_clear(GIUINTHTSELH, mask); + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_high_irq_chip, + handle_level_irq); + } + giu_write(GIUINTSTATH, mask); + } +} +EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); + +void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) +{ + u16 mask; + + if (pin < GIUINT_HIGH_OFFSET) { + mask = 1 << pin; + if (level == IRQ_LEVEL_HIGH) + giu_set(GIUINTALSELL, mask); + else + giu_clear(GIUINTALSELL, mask); + giu_write(GIUINTSTATL, mask); + } else if (pin < GIUINT_HIGH_MAX) { + mask = 1 << (pin - GIUINT_HIGH_OFFSET); + if (level == IRQ_LEVEL_HIGH) + giu_set(GIUINTALSELH, mask); + else + giu_clear(GIUINTALSELH, mask); + giu_write(GIUINTSTATH, mask); + } +} +EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); + +static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) +{ + u16 offset, mask, reg; + unsigned long flags; + + if (pin >= chip->ngpio) + return -EINVAL; + + if (pin < 16) { + offset = GIUIOSELL; + mask = 1 << pin; + } else if (pin < 32) { + offset = GIUIOSELH; + mask = 1 << (pin - 16); + } else { + if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { + offset = GIUPODATEN; + mask = 1 << (pin - 32); + } else { + switch (pin) { + case 48: + offset = GIUPODATH; + mask = PIOEN0; + break; + case 49: + offset = GIUPODATH; + mask = PIOEN1; + break; + default: + return -EINVAL; + } + } + } + + spin_lock_irqsave(&giu_lock, flags); + + reg = giu_read(offset); + if (dir == GPIO_OUTPUT) + reg |= mask; + else + reg &= ~mask; + giu_write(offset, reg); + + spin_unlock_irqrestore(&giu_lock, flags); + + return 0; +} + +int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) +{ + u16 reg, mask; + unsigned long flags; + + if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) + return -EPERM; + + if (pin >= 15) + return -EINVAL; + + mask = 1 << pin; + + spin_lock_irqsave(&giu_lock, flags); + + if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { + reg = giu_read(GIUTERMUPDN); + if (pull == GPIO_PULL_UP) + reg |= mask; + else + reg &= ~mask; + giu_write(GIUTERMUPDN, reg); + + reg = giu_read(GIUUSEUPDN); + reg |= mask; + giu_write(GIUUSEUPDN, reg); + } else { + reg = giu_read(GIUUSEUPDN); + reg &= ~mask; + giu_write(GIUUSEUPDN, reg); + } + + spin_unlock_irqrestore(&giu_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); + +static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) +{ + u16 reg, mask; + + if (pin >= chip->ngpio) + return -EINVAL; + + if (pin < 16) { + reg = giu_read(GIUPIODL); + mask = 1 << pin; + } else if (pin < 32) { + reg = giu_read(GIUPIODH); + mask = 1 << (pin - 16); + } else if (pin < 48) { + reg = giu_read(GIUPODATL); + mask = 1 << (pin - 32); + } else { + reg = giu_read(GIUPODATH); + mask = 1 << (pin - 48); + } + + if (reg & mask) + return 1; + + return 0; +} + +static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, + int value) +{ + u16 offset, mask, reg; + unsigned long flags; + + if (pin >= chip->ngpio) + return; + + if (pin < 16) { + offset = GIUPIODL; + mask = 1 << pin; + } else if (pin < 32) { + offset = GIUPIODH; + mask = 1 << (pin - 16); + } else if (pin < 48) { + offset = GIUPODATL; + mask = 1 << (pin - 32); + } else { + offset = GIUPODATH; + mask = 1 << (pin - 48); + } + + spin_lock_irqsave(&giu_lock, flags); + + reg = giu_read(offset); + if (value) + reg |= mask; + else + reg &= ~mask; + giu_write(offset, reg); + + spin_unlock_irqrestore(&giu_lock, flags); +} + + +static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return giu_set_direction(chip, offset, GPIO_INPUT); +} + +static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + vr41xx_gpio_set(chip, offset, value); + + return giu_set_direction(chip, offset, GPIO_OUTPUT); +} + +static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + if (offset >= chip->ngpio) + return -EINVAL; + + return GIU_IRQ_BASE + offset; +} + +static struct gpio_chip vr41xx_gpio_chip = { + .label = "vr41xx", + .owner = THIS_MODULE, + .direction_input = vr41xx_gpio_direction_input, + .get = vr41xx_gpio_get, + .direction_output = vr41xx_gpio_direction_output, + .set = vr41xx_gpio_set, + .to_irq = vr41xx_gpio_to_irq, +}; + +static int __devinit giu_probe(struct platform_device *pdev) +{ + struct resource *res; + unsigned int trigger, i, pin; + struct irq_chip *chip; + int irq, retval; + + switch (pdev->id) { + case GPIO_50PINS_PULLUPDOWN: + giu_flags = GPIO_HAS_PULLUPDOWN_IO; + vr41xx_gpio_chip.ngpio = 50; + break; + case GPIO_36PINS: + vr41xx_gpio_chip.ngpio = 36; + break; + case GPIO_48PINS_EDGE_SELECT: + giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; + vr41xx_gpio_chip.ngpio = 48; + break; + default: + dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EBUSY; + + giu_base = ioremap(res->start, res->end - res->start + 1); + if (!giu_base) + return -ENOMEM; + + vr41xx_gpio_chip.dev = &pdev->dev; + + retval = gpiochip_add(&vr41xx_gpio_chip); + + giu_write(GIUINTENL, 0); + giu_write(GIUINTENH, 0); + + trigger = giu_read(GIUINTTYPH) << 16; + trigger |= giu_read(GIUINTTYPL); + for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { + pin = GPIO_PIN_OF_IRQ(i); + if (pin < GIUINT_HIGH_OFFSET) + chip = &giuint_low_irq_chip; + else + chip = &giuint_high_irq_chip; + + if (trigger & (1 << pin)) + set_irq_chip_and_handler(i, chip, handle_edge_irq); + else + set_irq_chip_and_handler(i, chip, handle_level_irq); + + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0 || irq >= nr_irqs) + return -EBUSY; + + return cascade_irq(irq, giu_get_irq); +} + +static int __devexit giu_remove(struct platform_device *pdev) +{ + if (giu_base) { + iounmap(giu_base); + giu_base = NULL; + } + + return 0; +} + +static struct platform_driver giu_device_driver = { + .probe = giu_probe, + .remove = __devexit_p(giu_remove), + .driver = { + .name = "GIU", + .owner = THIS_MODULE, + }, +}; + +static int __init vr41xx_giu_init(void) +{ + return platform_driver_register(&giu_device_driver); +} + +static void __exit vr41xx_giu_exit(void) +{ + platform_driver_unregister(&giu_device_driver); +} + +module_init(vr41xx_giu_init); +module_exit(vr41xx_giu_exit); -- cgit v1.2.3 From b53d4d1f8d522342e66f79b8b49a19835071fed4 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 29 Jun 2009 09:54:15 -0700 Subject: MIPS: Define __arch_swab64 for all mips r2 cpus Some CPUs implement mipsr2, but because they are a super-set of mips64r2 do not define CONFIG_CPU_MIPS64_R2. Cavium OCTEON falls into this category. We would still like to use the optimized implementation, so since we have already checked for CONFIG_CPU_MIPSR2, checking for CONFIG_64BIT instead of CONFIG_CPU_MIPS64_R2 is sufficient. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/include/asm/swab.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/swab.h b/arch/mips/include/asm/swab.h index 99993c0d6c1..97c2f81b4b4 100644 --- a/arch/mips/include/asm/swab.h +++ b/arch/mips/include/asm/swab.h @@ -38,7 +38,11 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x) } #define __arch_swab32 __arch_swab32 -#ifdef CONFIG_CPU_MIPS64_R2 +/* + * Having already checked for CONFIG_CPU_MIPSR2, enable the + * optimized version for 64-bit kernel on r2 CPUs. + */ +#ifdef CONFIG_64BIT static inline __attribute_const__ __u64 __arch_swab64(__u64 x) { __asm__( @@ -50,6 +54,6 @@ static inline __attribute_const__ __u64 __arch_swab64(__u64 x) return x; } #define __arch_swab64 __arch_swab64 -#endif /* CONFIG_CPU_MIPS64_R2 */ +#endif /* CONFIG_64BIT */ #endif /* CONFIG_CPU_MIPSR2 */ #endif /* _ASM_SWAB_H */ -- cgit v1.2.3 From 9306c8def6abc2dbde4ac75eb6c631606b8fc1dd Mon Sep 17 00:00:00 2001 From: Tim Anderson Date: Wed, 17 Jun 2009 16:21:19 -0700 Subject: MIPS: CMP: Extend the GIC IPI interrupts beyond 32 This patch extends the GIC interrupt handling beyond the current 32 bit range as well as extending the number of interrupts based on the number of CPUs. Signed-off-by: Tim Anderson Signed-off-by: Ralf Baechle --- arch/mips/include/asm/gic.h | 4 ++++ arch/mips/kernel/irq-gic.c | 15 ++++----------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 954807d9d66..e8fdd92c52c 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -20,7 +20,11 @@ #define GIC_TRIG_EDGE 1 #define GIC_TRIG_LEVEL 0 +#if CONFIG_SMP +#define GIC_NUM_INTRS (24 + NR_CPUS * 2) +#else #define GIC_NUM_INTRS 32 +#endif #define MSK(n) ((1 << (n)) - 1) #define REG32(addr) (*(volatile unsigned int *) (addr)) diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 39000f103f2..5c85e1ce049 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -107,9 +107,7 @@ static unsigned int gic_irq_startup(unsigned int irq) { pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; - /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */ - GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))), - 1 << (irq % 32)); + GIC_SET_INTR_MASK(irq, 1); return 0; } @@ -120,8 +118,7 @@ static void gic_irq_ack(unsigned int irq) #endif pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; - GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))), - 1 << (irq % 32)); + GIC_CLR_INTR_MASK(irq, 1); if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) { if (!gic_wedgeb2bok) @@ -138,18 +135,14 @@ static void gic_mask_irq(unsigned int irq) { pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; - /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */ - GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))), - 1 << (irq % 32)); + GIC_CLR_INTR_MASK(irq, 1); } static void gic_unmask_irq(unsigned int irq) { pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; - /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */ - GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))), - 1 << (irq % 32)); + GIC_SET_INTR_MASK(irq, 1); } #ifdef CONFIG_SMP -- cgit v1.2.3 From a214cef9a5d06894785dca1f967c9c324cc84c17 Mon Sep 17 00:00:00 2001 From: Tim Anderson Date: Wed, 17 Jun 2009 16:22:25 -0700 Subject: MIPS: CMP: Extend IPI handling to CPU number This takes the current IPI interrupt assignment from the fix number of 4 to the number of CPUs defined in the system. Signed-off-by: Tim Anderson Signed-off-by: Ralf Baechle --- arch/mips/kernel/irq-gic.c | 4 +++ arch/mips/mti-malta/malta-int.c | 74 ++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 5c85e1ce049..d2072cd3859 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -247,6 +247,10 @@ static void __init gic_basic_init(void) if (cpu == X) continue; + if (cpu == 0 && i != 0 && _intrmap[i].intrnum == 0 && + _intrmap[i].ipiflag == 0) + continue; + setup_intr(_intrmap[i].intrnum, _intrmap[i].cpunum, _intrmap[i].pin, diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index b4eaf137e4a..4e14972dcfc 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -331,6 +331,11 @@ static struct irqaction irq_call = { .flags = IRQF_DISABLED|IRQF_PERCPU, .name = "IPI_call" }; + +static int gic_resched_int_base; +static int gic_call_int_base; +#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) +#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) #endif /* CONFIG_MIPS_MT_SMP */ static struct irqaction i8259irq = { @@ -370,7 +375,7 @@ static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); * Interrupts and CPUs/Core Interrupts. The nature of the External * Interrupts is also defined here - polarity/trigger. */ -static struct gic_intr_map gic_intr_map[] = { +static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { { GIC_EXT_INTR(0), X, X, X, X, 0 }, { GIC_EXT_INTR(1), X, X, X, X, 0 }, { GIC_EXT_INTR(2), X, X, X, X, 0 }, @@ -387,14 +392,7 @@ static struct gic_intr_map gic_intr_map[] = { { GIC_EXT_INTR(13), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, { GIC_EXT_INTR(14), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, { GIC_EXT_INTR(15), X, X, X, X, 0 }, - { GIC_EXT_INTR(16), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(17), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(18), 1, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(19), 1, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(20), 2, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(21), 2, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(22), 3, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(23), 3, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, +/* This is the end of the general interrupts now we do IPI ones */ }; #endif @@ -416,14 +414,25 @@ static int __init gcmp_probe(unsigned long addr, unsigned long size) } #if defined(CONFIG_MIPS_MT_SMP) +static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin) +{ + int intr = baseintr + cpu; + gic_intr_map[intr].intrnum = GIC_EXT_INTR(intr); + gic_intr_map[intr].cpunum = cpu; + gic_intr_map[intr].pin = cpupin; + gic_intr_map[intr].polarity = GIC_POL_POS; + gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; + gic_intr_map[intr].ipiflag = 1; + ipi_map[cpu] |= (1 << (cpupin + 2)); +} + static void __init fill_ipi_map(void) { - int i; + int cpu; - for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) { - if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X)) - ipi_map[gic_intr_map[i].cpunum] |= - (1 << (gic_intr_map[i].pin + 2)); + for (cpu = 0; cpu < NR_CPUS; cpu++) { + fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1); + fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2); } } #endif @@ -514,24 +523,10 @@ void __init arch_init_irq(void) if (gic_present) { /* FIXME */ int i; - struct { - unsigned int resched; - unsigned int call; - } ipiirq[] = { - { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE0, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE0}, - { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE1, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE1 - }, { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE2, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE2 - }, { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE3, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE3 - } - }; + + gic_call_int_base = GIC_NUM_INTRS - NR_CPUS; + gic_resched_int_base = gic_call_int_base - NR_CPUS; + fill_ipi_map(); gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); if (!gcmp_present) { @@ -553,12 +548,15 @@ void __init arch_init_irq(void) printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status()); write_c0_status(0x1100dc00); printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status()); - for (i = 0; i < ARRAY_SIZE(ipiirq); i++) { - setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched); - setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call); - - set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq); - set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq); + for (i = 0; i < NR_CPUS; i++) { + setup_irq(MIPS_GIC_IRQ_BASE + + GIC_RESCHED_INT(i), &irq_resched); + setup_irq(MIPS_GIC_IRQ_BASE + + GIC_CALL_INT(i), &irq_call); + set_irq_handler(MIPS_GIC_IRQ_BASE + + GIC_RESCHED_INT(i), handle_percpu_irq); + set_irq_handler(MIPS_GIC_IRQ_BASE + + GIC_CALL_INT(i), handle_percpu_irq); } } else { /* set up ipi interrupts */ -- cgit v1.2.3 From 0365070f05f12f1648b4adf22cfb52ec7a8a371c Mon Sep 17 00:00:00 2001 From: Tim Anderson Date: Wed, 17 Jun 2009 16:22:53 -0700 Subject: MIPS: CMP: activate CMP support Most of the CMP support was added before, this mostly correct compile problems but adds a platform specific translation for the interrupt number based on cpu number. Signed-off-by: Tim Anderson Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/include/asm/amon.h | 7 +++++ arch/mips/include/asm/gic.h | 2 ++ arch/mips/kernel/smp-cmp.c | 66 ++++------------------------------------- arch/mips/mti-malta/malta-int.c | 10 +++++++ 5 files changed, 25 insertions(+), 62 deletions(-) create mode 100644 arch/mips/include/asm/amon.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 64891f74019..4368a723e2d 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -229,7 +229,7 @@ config MIPS_MALTA select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN - select SYS_SUPPORTS_MIPS_CMP if BROKEN # because SYNC_R4K is broken + select SYS_SUPPORTS_MIPS_CMP select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_SMARTMIPS help diff --git a/arch/mips/include/asm/amon.h b/arch/mips/include/asm/amon.h new file mode 100644 index 00000000000..c3dc1a68dd8 --- /dev/null +++ b/arch/mips/include/asm/amon.h @@ -0,0 +1,7 @@ +/* + * Amon support + */ + +int amon_cpu_avail(int); +void amon_cpu_start(int, unsigned long, unsigned long, + unsigned long, unsigned long); diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index e8fdd92c52c..10292e37c1f 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -487,5 +487,7 @@ extern void gic_init(unsigned long gic_base_addr, extern unsigned int gic_get_int(void); extern void gic_send_ipi(unsigned int intr); +extern unsigned int plat_ipi_call_int_xlate(unsigned int); +extern unsigned int plat_ipi_resched_int_xlate(unsigned int); #endif /* _ASM_GICREGS_H */ diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index 653be061b9e..ad0ff5dc4d5 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c @@ -37,80 +37,24 @@ #include #include #include - -/* - * Crude manipulation of the CPU masks to control which - * which CPU's are brought online during initialisation - * - * Beware... this needs to be called after CPU discovery - * but before CPU bringup - */ -static int __init allowcpus(char *str) -{ - cpumask_t cpu_allow_map; - char buf[256]; - int len; - - cpus_clear(cpu_allow_map); - if (cpulist_parse(str, &cpu_allow_map) == 0) { - cpu_set(0, cpu_allow_map); - cpus_and(cpu_possible_map, cpu_possible_map, cpu_allow_map); - len = cpulist_scnprintf(buf, sizeof(buf)-1, &cpu_possible_map); - buf[len] = '\0'; - pr_debug("Allowable CPUs: %s\n", buf); - return 1; - } else - return 0; -} -__setup("allowcpus=", allowcpus); +#include +#include static void ipi_call_function(unsigned int cpu) { - unsigned int action = 0; - pr_debug("CPU%d: %s cpu %d status %08x\n", smp_processor_id(), __func__, cpu, read_c0_status()); - switch (cpu) { - case 0: - action = GIC_IPI_EXT_INTR_CALLFNC_VPE0; - break; - case 1: - action = GIC_IPI_EXT_INTR_CALLFNC_VPE1; - break; - case 2: - action = GIC_IPI_EXT_INTR_CALLFNC_VPE2; - break; - case 3: - action = GIC_IPI_EXT_INTR_CALLFNC_VPE3; - break; - } - gic_send_ipi(action); + gic_send_ipi(plat_ipi_call_int_xlate(cpu)); } static void ipi_resched(unsigned int cpu) { - unsigned int action = 0; - pr_debug("CPU%d: %s cpu %d status %08x\n", smp_processor_id(), __func__, cpu, read_c0_status()); - switch (cpu) { - case 0: - action = GIC_IPI_EXT_INTR_RESCHED_VPE0; - break; - case 1: - action = GIC_IPI_EXT_INTR_RESCHED_VPE1; - break; - case 2: - action = GIC_IPI_EXT_INTR_RESCHED_VPE2; - break; - case 3: - action = GIC_IPI_EXT_INTR_RESCHED_VPE3; - break; - } - gic_send_ipi(action); + gic_send_ipi(plat_ipi_resched_int_xlate(cpu)); } /* @@ -206,7 +150,7 @@ static void cmp_boot_secondary(int cpu, struct task_struct *idle) (unsigned long)(gp + sizeof(struct thread_info))); #endif - amon_cpu_start(cpu, pc, sp, gp, a0); + amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0); } /* diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 4e14972dcfc..bc0ba58acfd 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -336,6 +336,16 @@ static int gic_resched_int_base; static int gic_call_int_base; #define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) #define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) + +unsigned int plat_ipi_call_int_xlate(unsigned int cpu) +{ + return GIC_CALL_INT(cpu); +} + +unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) +{ + return GIC_RESCHED_INT(cpu); +} #endif /* CONFIG_MIPS_MT_SMP */ static struct irqaction i8259irq = { -- cgit v1.2.3 From 47b178bb69ea4d0043f2df509c714bc5b287f375 Mon Sep 17 00:00:00 2001 From: Tim Anderson Date: Wed, 17 Jun 2009 16:25:18 -0700 Subject: MIPS: CMP: Move gcmp_probe to before the SMP ops This is to move the gcmp_probe call to before the use of and selection of the smp_ops functions. This allows malta with 1004K to work. Signed-off-by: Tim Anderson Signed-off-by: Ralf Baechle --- arch/mips/include/asm/gcmpregs.h | 2 ++ arch/mips/mti-malta/malta-init.c | 14 +++++++++++++- arch/mips/mti-malta/malta-int.c | 5 +---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/arch/mips/include/asm/gcmpregs.h b/arch/mips/include/asm/gcmpregs.h index d74a8a4ca86..36fd969d64d 100644 --- a/arch/mips/include/asm/gcmpregs.h +++ b/arch/mips/include/asm/gcmpregs.h @@ -114,4 +114,6 @@ #define GCMP_CCB_DINTGROUP_OFS 0x0030 /* DINT Group Participate */ #define GCMP_CCB_DBGGROUP_OFS 0x0100 /* DebugBreak Group */ +extern int __init gcmp_probe(unsigned long, unsigned long); + #endif /* _ASM_GCMPREGS_H */ diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c index 475038a141a..27c807b67fe 100644 --- a/arch/mips/mti-malta/malta-init.c +++ b/arch/mips/mti-malta/malta-init.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -192,6 +193,8 @@ extern struct plat_smp_ops msmtc_smp_ops; void __init prom_init(void) { + int result; + prom_argc = fw_arg0; _prom_argv = (int *) fw_arg1; _prom_envp = (int *) fw_arg2; @@ -358,12 +361,21 @@ void __init prom_init(void) #ifdef CONFIG_SERIAL_8250_CONSOLE console_config(); #endif + /* Early detection of CMP support */ + result = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); + #ifdef CONFIG_MIPS_CMP - register_smp_ops(&cmp_smp_ops); + if (result) + register_smp_ops(&cmp_smp_ops); #endif #ifdef CONFIG_MIPS_MT_SMP +#ifdef CONFIG_MIPS_CMP + if (!result) + register_smp_ops(&vsmp_smp_ops); +#else register_smp_ops(&vsmp_smp_ops); #endif +#endif #ifdef CONFIG_MIPS_MT_SMTC register_smp_ops(&msmtc_smp_ops); #endif diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index bc0ba58acfd..a8756f82c31 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -409,7 +409,7 @@ static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { /* * GCMP needs to be detected before any SMP initialisation */ -static int __init gcmp_probe(unsigned long addr, unsigned long size) +int __init gcmp_probe(unsigned long addr, unsigned long size) { if (gcmp_present >= 0) return gcmp_present; @@ -449,14 +449,11 @@ static void __init fill_ipi_map(void) void __init arch_init_irq(void) { - int gic_present, gcmp_present; - init_i8259_irqs(); if (!cpu_has_veic) mips_cpu_irq_init(); - gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); if (gcmp_present) { GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK; gic_present = 1; -- cgit v1.2.3 From eb9b5141a9815ef898ef6b6441f733e81c272600 Mon Sep 17 00:00:00 2001 From: Tim Anderson Date: Wed, 17 Jun 2009 16:40:34 -0700 Subject: MIPS: CMP: Update sync-r4k for current kernel This revises the sync-4k so it will boot and operate since the removal of expirelo from the timer code. Signed-off-by: Tim Anderson Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/kernel/sync-r4k.c | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4368a723e2d..df1a92afa56 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1656,7 +1656,7 @@ config MIPS_APSP_KSPD config MIPS_CMP bool "MIPS CMP framework support" depends on SYS_SUPPORTS_MIPS_CMP - select SYNC_R4K if BROKEN + select SYNC_R4K select SYS_SUPPORTS_SMP select SYS_SUPPORTS_SCHED_SMT if SMP select WEAK_ORDERING diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c index 9021108eb9c..05dd170a83f 100644 --- a/arch/mips/kernel/sync-r4k.c +++ b/arch/mips/kernel/sync-r4k.c @@ -1,7 +1,7 @@ /* * Count register synchronisation. * - * All CPUs will have their count registers synchronised to the CPU0 expirelo + * All CPUs will have their count registers synchronised to the CPU0 next time * value. This can cause a small timewarp for CPU0. All other CPU's should * not have done anything significant (but they may have had interrupts * enabled briefly - prom_smp_finish() should not be responsible for enabling @@ -13,21 +13,22 @@ #include #include #include -#include +#include +#include #include #include -#include #include -static atomic_t __initdata count_start_flag = ATOMIC_INIT(0); -static atomic_t __initdata count_count_start = ATOMIC_INIT(0); -static atomic_t __initdata count_count_stop = ATOMIC_INIT(0); +static atomic_t __cpuinitdata count_start_flag = ATOMIC_INIT(0); +static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0); +static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0); +static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0); #define COUNTON 100 #define NR_LOOPS 5 -void __init synchronise_count_master(void) +void __cpuinit synchronise_count_master(void) { int i; unsigned long flags; @@ -42,19 +43,20 @@ void __init synchronise_count_master(void) return; #endif - pr_info("Checking COUNT synchronization across %u CPUs: ", - num_online_cpus()); + printk(KERN_INFO "Synchronize counters across %u CPUs: ", + num_online_cpus()); local_irq_save(flags); /* * Notify the slaves that it's time to start */ + atomic_set(&count_reference, read_c0_count()); atomic_set(&count_start_flag, 1); smp_wmb(); - /* Count will be initialised to expirelo for all CPU's */ - initcount = expirelo; + /* Count will be initialised to current timer for all CPU's */ + initcount = read_c0_count(); /* * We loop a few times to get a primed instruction cache, @@ -106,7 +108,7 @@ void __init synchronise_count_master(void) printk("done.\n"); } -void __init synchronise_count_slave(void) +void __cpuinit synchronise_count_slave(void) { int i; unsigned long flags; @@ -131,8 +133,8 @@ void __init synchronise_count_slave(void) while (!atomic_read(&count_start_flag)) mb(); - /* Count will be initialised to expirelo for all CPU's */ - initcount = expirelo; + /* Count will be initialised to next expire for all CPU's */ + initcount = atomic_read(&count_reference); ncpus = num_online_cpus(); for (i = 0; i < NR_LOOPS; i++) { @@ -156,4 +158,3 @@ void __init synchronise_count_slave(void) local_irq_restore(flags); } #undef NR_LOOPS -#endif -- cgit v1.2.3 From ea4bbfd0048c53c24f72ef668b39f1247bc243c0 Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Tue, 30 Jun 2009 23:04:55 +0200 Subject: MIPS: BC47xx: Fix SSB irq setup The current ssb irq setup in ssb_mipscore_init has the problem that it configures some device on some irq without checking that the irq is not taken by an other device. For example in my case PCI host is on irq 0 and IPSEC on irq 3. The current code: - store in dev->irq that IPSEC irq is 3 + 2 - do a set_irq 0->3 on PCI host But now IPSEC irq is not routed anymore to the mips code and dev->irq is wrong. This causes a problem described in [1]. This patch tries to solve the problem by making set_irq configure the device we want to take the irq on the shared irq0. The previous example becomes: - store in dev->irq that IPSEC irq is 3 + 2 - do a set_irq 0->3 on PCI host: - irq 3 is already taken by IPSEC. do a set_irq 3->0 on IPSEC I also added some code to print the irq configuration after irq setup to allow easier debugging. And I add extra checking in ssb_mips_irq to report device without irq or device with not routed irq. [1] http://www.danm.de/files/src/bcm5365p/REPORTED_DEVICES Signed-off-by: Matthieu CASTET Acked-by : Michael Buesch Tested-by: Florian Fainelli Signed-off-by: Ralf Baechle --- drivers/ssb/driver_mipscore.c | 85 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3fd3e3b412b..3c6feed46f6 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = { static inline u32 ssb_irqflag(struct ssb_device *dev) { - return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; + u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); + if (tpsflag) + return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; + else + /* not irq supported */ + return 0x3f; +} + +static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) +{ + struct ssb_bus *bus = rdev->bus; + int i; + for (i = 0; i < bus->nr_devices; i++) { + struct ssb_device *dev; + dev = &(bus->devices[i]); + if (ssb_irqflag(dev) == irqflag) + return dev; + } + return NULL; } /* Get the MIPS IRQ assignment for a specified device. * If unassigned, 0 is returned. + * If disabled, 5 is returned. + * If not supported, 6 is returned. */ unsigned int ssb_mips_irq(struct ssb_device *dev) { struct ssb_bus *bus = dev->bus; + struct ssb_device *mdev = bus->mipscore.dev; u32 irqflag; u32 ipsflag; u32 tmp; unsigned int irq; irqflag = ssb_irqflag(dev); + if (irqflag == 0x3f) + return 6; ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); for (irq = 1; irq <= 4; irq++) { tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); if (tmp == irqflag) break; } - if (irq == 5) - irq = 0; + if (irq == 5) { + if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) + irq = 0; + } return irq; } @@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) struct ssb_device *mdev = bus->mipscore.dev; u32 irqflag = ssb_irqflag(dev); + BUG_ON(oldirq == 6); + dev->irq = irq + 2; - ssb_dprintk(KERN_INFO PFX - "set_irq: core 0x%04x, irq %d => %d\n", - dev->id.coreid, oldirq, irq); /* clear the old irq */ if (oldirq == 0) ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); - else + else if (oldirq != 5) clear_irq(bus, oldirq); /* assign the new one */ if (irq == 0) { ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); } else { + u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); + if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { + u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; + struct ssb_device *olddev = find_device(dev, oldipsflag); + if (olddev) + set_irq(olddev, 0); + } irqflag <<= ipsflag_irq_shift[irq]; - irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); + irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); ssb_write32(mdev, SSB_IPSFLAG, irqflag); } + ssb_dprintk(KERN_INFO PFX + "set_irq: core 0x%04x, irq %d => %d\n", + dev->id.coreid, oldirq+2, irq+2); +} + +static void print_irq(struct ssb_device *dev, unsigned int irq) +{ + int i; + static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; + ssb_dprintk(KERN_INFO PFX + "core 0x%04x, irq :", dev->id.coreid); + for (i = 0; i <= 6; i++) { + ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); + } + ssb_dprintk("\n"); +} + +static void dump_irq(struct ssb_bus *bus) +{ + int i; + for (i = 0; i < bus->nr_devices; i++) { + struct ssb_device *dev; + dev = &(bus->devices[i]); + print_irq(dev, ssb_mips_irq(dev)); + } } static void ssb_mips_serial_init(struct ssb_mipscore *mcore) @@ -197,16 +253,23 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ for (irq = 2, i = 0; i < bus->nr_devices; i++) { + int mips_irq; dev = &(bus->devices[i]); - dev->irq = ssb_mips_irq(dev) + 2; + mips_irq = ssb_mips_irq(dev); + if (mips_irq > 4) + dev->irq = 0; + else + dev->irq = mips_irq + 2; + if (dev->irq > 5) + continue; switch (dev->id.coreid) { case SSB_DEV_USB11_HOST: /* shouldn't need a separate irq line for non-4710, most of them have a proper * external usb controller on the pci */ if ((bus->chip_id == 0x4710) && (irq <= 4)) { set_irq(dev, irq++); - break; } + break; /* fallthrough */ case SSB_DEV_PCI: case SSB_DEV_ETHERNET: @@ -220,6 +283,8 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) } } } + ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); + dump_irq(bus); ssb_mips_serial_init(mcore); ssb_mips_flash_detect(mcore); -- cgit v1.2.3 From cad9bc69048b073023366ebb0878c1dd64a2c4d9 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Wed, 1 Jul 2009 09:35:39 +0800 Subject: MIPS: 64-bit: Fix o32 core dump If an o32 process generates a core dump on a 64 bit kernel, the core file will not be correctly recognized. This is because ELF_CORE_COPY_REGS and ELF_CORE_COPY_TASK_REGS are not correctly defined for o32 and will use the default register set which would be CONFIG_64BIT in asm/elf.h. So we'll switch to use the right register defines in this situation by checking for WANT_COMPAT_REG_H and use the right defines of ELF_CORE_COPY_REGS and ELF_CORE_COPY_TASK_REGS. [Ralf: made ELF_CORE_COPY_TASK_REGS() bullet-proof against funny arguments.] Signed-off-by: Yong Zhang Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 4 ++++ arch/mips/include/asm/reg.h | 2 +- arch/mips/kernel/binfmt_elfo32.c | 20 +++++++++++++++++--- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index d58f128aa74..7990694cda2 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -316,9 +316,13 @@ extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs); extern int dump_task_regs(struct task_struct *, elf_gregset_t *); extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); +#ifndef ELF_CORE_COPY_REGS #define ELF_CORE_COPY_REGS(elf_regs, regs) \ elf_dump_regs((elf_greg_t *)&(elf_regs), regs); +#endif +#ifndef ELF_CORE_COPY_TASK_REGS #define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) +#endif #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) \ dump_task_fpu(tsk, elf_fpregs) diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h index 634b55d7e7f..910e71a1246 100644 --- a/arch/mips/include/asm/reg.h +++ b/arch/mips/include/asm/reg.h @@ -69,7 +69,7 @@ #endif -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H) #define EF_R0 0 #define EF_R1 1 diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index e1333d7319e..ff448233dab 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -53,6 +53,23 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) #include + +/* + * When this file is selected, we are definitely running a 64bit kernel. + * So using the right regs define in asm/reg.h + */ +#define WANT_COMPAT_REG_H + +/* These MUST be defined before elf.h gets included */ +extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs); +#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs); +#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest) \ +({ \ + int __res = 1; \ + elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk)); \ + __res; \ +}) + #include #include #include @@ -110,9 +127,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) value->tv_usec = rem / NSEC_PER_USEC; } -#undef ELF_CORE_COPY_REGS -#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs); - void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs) { int i; -- cgit v1.2.3 From 3f5b3e17f791ba27f91fc4fdc514e7704d4d6273 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 2 Jul 2009 11:48:07 +0100 Subject: MIPS: Allow suspend and hibernation again on uniprocessor kernels. Signed-off-by: Ralf Baechle Acked-by: Pavel Machek --- arch/mips/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index df1a92afa56..3ca0fe1a912 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2168,11 +2168,11 @@ menu "Power management options" config ARCH_HIBERNATION_POSSIBLE def_bool y - depends on SYS_SUPPORTS_HOTPLUG_CPU + depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP config ARCH_SUSPEND_POSSIBLE def_bool y - depends on SYS_SUPPORTS_HOTPLUG_CPU + depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP source "kernel/power/Kconfig" -- cgit v1.2.3 From ada8e9514b5880f81cdbbd212d121380ceef7acc Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Fri, 3 Jul 2009 00:39:38 +0900 Subject: Update Yoichi Yuasa's e-mail address Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle --- arch/mips/cobalt/buttons.c | 2 +- arch/mips/cobalt/lcd.c | 2 +- arch/mips/cobalt/led.c | 2 +- arch/mips/cobalt/mtd.c | 2 +- arch/mips/cobalt/rtc.c | 2 +- arch/mips/cobalt/serial.c | 2 +- arch/mips/cobalt/time.c | 2 +- arch/mips/gt64120/wrppmc/serial.c | 2 +- arch/mips/include/asm/ds1287.h | 2 +- arch/mips/include/asm/irq_gt641xx.h | 2 +- arch/mips/include/asm/mach-cobalt/irq.h | 2 +- arch/mips/include/asm/mach-cobalt/mach-gt64120.h | 2 +- arch/mips/include/asm/vr41xx/capcella.h | 2 +- arch/mips/include/asm/vr41xx/giu.h | 2 +- arch/mips/include/asm/vr41xx/irq.h | 2 +- arch/mips/include/asm/vr41xx/mpc30x.h | 2 +- arch/mips/include/asm/vr41xx/pci.h | 2 +- arch/mips/include/asm/vr41xx/siu.h | 2 +- arch/mips/include/asm/vr41xx/tb0219.h | 2 +- arch/mips/include/asm/vr41xx/tb0226.h | 2 +- arch/mips/include/asm/vr41xx/vr41xx.h | 2 +- arch/mips/kernel/cevt-ds1287.c | 2 +- arch/mips/kernel/cevt-gt641xx.c | 2 +- arch/mips/kernel/csrc-ioasic.c | 2 +- arch/mips/kernel/irq-gt641xx.c | 2 +- arch/mips/pci/fixup-capcella.c | 2 +- arch/mips/pci/fixup-mpc30x.c | 2 +- arch/mips/pci/fixup-tb0219.c | 2 +- arch/mips/pci/fixup-tb0226.c | 2 +- arch/mips/pci/fixup-tb0287.c | 2 +- arch/mips/pci/ops-vr41xx.c | 6 +++--- arch/mips/pci/pci-vr41xx.c | 6 +++--- arch/mips/pci/pci-vr41xx.h | 4 ++-- arch/mips/vr41xx/casio-e55/setup.c | 2 +- arch/mips/vr41xx/common/bcu.c | 8 ++++---- arch/mips/vr41xx/common/cmu.c | 8 ++++---- arch/mips/vr41xx/common/giu.c | 2 +- arch/mips/vr41xx/common/icu.c | 8 ++++---- arch/mips/vr41xx/common/init.c | 2 +- arch/mips/vr41xx/common/irq.c | 2 +- arch/mips/vr41xx/common/pmu.c | 2 +- arch/mips/vr41xx/common/rtc.c | 2 +- arch/mips/vr41xx/common/siu.c | 2 +- arch/mips/vr41xx/common/type.c | 2 +- arch/mips/vr41xx/ibm-workpad/setup.c | 2 +- drivers/char/tb0219.c | 4 ++-- drivers/gpio/vr41xx_giu.c | 6 +++--- drivers/input/misc/cobalt_btns.c | 4 ++-- drivers/leds/leds-cobalt-raq.c | 2 +- drivers/pcmcia/vrc4171_card.c | 4 ++-- drivers/pcmcia/vrc4173_cardu.c | 4 ++-- drivers/pcmcia/vrc4173_cardu.h | 2 +- drivers/rtc/rtc-vr41xx.c | 4 ++-- drivers/serial/vr41xx_siu.c | 2 +- drivers/video/cobalt_lcdfb.c | 2 +- 55 files changed, 76 insertions(+), 76 deletions(-) diff --git a/arch/mips/cobalt/buttons.c b/arch/mips/cobalt/buttons.c index 9e143989c7b..4eaec8b46e0 100644 --- a/arch/mips/cobalt/buttons.c +++ b/arch/mips/cobalt/buttons.c @@ -1,7 +1,7 @@ /* * Cobalt buttons platform device. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/cobalt/lcd.c b/arch/mips/cobalt/lcd.c index 0720e4fae31..0f1cd90f37e 100644 --- a/arch/mips/cobalt/lcd.c +++ b/arch/mips/cobalt/lcd.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt LCD platform device. * - * Copyright (C) 2008 Yoichi Yuasa + * Copyright (C) 2008 Yoichi Yuasa * * 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 diff --git a/arch/mips/cobalt/led.c b/arch/mips/cobalt/led.c index 1c6ebd468b0..d3ce6fa1dc7 100644 --- a/arch/mips/cobalt/led.c +++ b/arch/mips/cobalt/led.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt LED platform device. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/cobalt/mtd.c b/arch/mips/cobalt/mtd.c index 2b088ef3839..691d620b676 100644 --- a/arch/mips/cobalt/mtd.c +++ b/arch/mips/cobalt/mtd.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt MTD device. * - * Copyright (C) 2006 Yoichi Yuasa + * Copyright (C) 2006 Yoichi Yuasa * * 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 diff --git a/arch/mips/cobalt/rtc.c b/arch/mips/cobalt/rtc.c index e70794b8bcb..3ab39898b4e 100644 --- a/arch/mips/cobalt/rtc.c +++ b/arch/mips/cobalt/rtc.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt RTC platform device. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/cobalt/serial.c b/arch/mips/cobalt/serial.c index 53b8d0d6da9..7cb51f57275 100644 --- a/arch/mips/cobalt/serial.c +++ b/arch/mips/cobalt/serial.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt UART platform device. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/cobalt/time.c b/arch/mips/cobalt/time.c index 4a570e7145f..0162f9edc69 100644 --- a/arch/mips/cobalt/time.c +++ b/arch/mips/cobalt/time.c @@ -1,7 +1,7 @@ /* * Cobalt time initialization. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/gt64120/wrppmc/serial.c b/arch/mips/gt64120/wrppmc/serial.c index 5ec1c2ffd3a..6f9d0858f59 100644 --- a/arch/mips/gt64120/wrppmc/serial.c +++ b/arch/mips/gt64120/wrppmc/serial.c @@ -1,7 +1,7 @@ /* * Registration of WRPPMC UART platform device. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/ds1287.h b/arch/mips/include/asm/ds1287.h index ba1702e8693..3af0b8fb3b8 100644 --- a/arch/mips/include/asm/ds1287.h +++ b/arch/mips/include/asm/ds1287.h @@ -1,7 +1,7 @@ /* * DS1287 timer functions. * - * Copyright (C) 2008 Yoichi Yuasa + * Copyright (C) 2008 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/irq_gt641xx.h b/arch/mips/include/asm/irq_gt641xx.h index f9a7c3ac2e6..250a2407b59 100644 --- a/arch/mips/include/asm/irq_gt641xx.h +++ b/arch/mips/include/asm/irq_gt641xx.h @@ -1,7 +1,7 @@ /* * Galileo/Marvell GT641xx IRQ definitions. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/mach-cobalt/irq.h b/arch/mips/include/asm/mach-cobalt/irq.h index 57c8c9ac585..9da9acf5dcb 100644 --- a/arch/mips/include/asm/mach-cobalt/irq.h +++ b/arch/mips/include/asm/mach-cobalt/irq.h @@ -8,7 +8,7 @@ * Copyright (C) 1997 Cobalt Microserver * Copyright (C) 1997, 2003 Ralf Baechle * Copyright (C) 2001-2003 Liam Davies (ldavies@agile.tv) - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa */ #ifndef _ASM_COBALT_IRQ_H #define _ASM_COBALT_IRQ_H diff --git a/arch/mips/include/asm/mach-cobalt/mach-gt64120.h b/arch/mips/include/asm/mach-cobalt/mach-gt64120.h index ae9c5523c7e..f8afec3f294 100644 --- a/arch/mips/include/asm/mach-cobalt/mach-gt64120.h +++ b/arch/mips/include/asm/mach-cobalt/mach-gt64120.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Yoichi Yuasa + * Copyright (C) 2006 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/vr41xx/capcella.h b/arch/mips/include/asm/vr41xx/capcella.h index e0ee05a3dfc..fcc6569414f 100644 --- a/arch/mips/include/asm/vr41xx/capcella.h +++ b/arch/mips/include/asm/vr41xx/capcella.h @@ -1,7 +1,7 @@ /* * capcella.h, Include file for ZAO Networks Capcella. * - * Copyright (C) 2002-2004 Yoichi Yuasa + * Copyright (C) 2002-2004 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/vr41xx/giu.h b/arch/mips/include/asm/vr41xx/giu.h index b369c091b0e..6a90bc1d916 100644 --- a/arch/mips/include/asm/vr41xx/giu.h +++ b/arch/mips/include/asm/vr41xx/giu.h @@ -1,7 +1,7 @@ /* * Include file for NEC VR4100 series General-purpose I/O Unit. * - * Copyright (C) 2005-2009 Yoichi Yuasa + * Copyright (C) 2005-2009 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/vr41xx/irq.h b/arch/mips/include/asm/vr41xx/irq.h index d315dfbc08f..b07f7321751 100644 --- a/arch/mips/include/asm/vr41xx/irq.h +++ b/arch/mips/include/asm/vr41xx/irq.h @@ -7,7 +7,7 @@ * Copyright (C) 2001, 2002 Paul Mundt * Copyright (C) 2002 MontaVista Software, Inc. * Copyright (C) 2002 TimeSys Corp. - * Copyright (C) 2003-2006 Yoichi Yuasa + * Copyright (C) 2003-2006 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/vr41xx/mpc30x.h b/arch/mips/include/asm/vr41xx/mpc30x.h index 1d67df843dc..130d09d8c8c 100644 --- a/arch/mips/include/asm/vr41xx/mpc30x.h +++ b/arch/mips/include/asm/vr41xx/mpc30x.h @@ -1,7 +1,7 @@ /* * mpc30x.h, Include file for Victor MP-C303/304. * - * Copyright (C) 2002-2004 Yoichi Yuasa + * Copyright (C) 2002-2004 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/vr41xx/pci.h b/arch/mips/include/asm/vr41xx/pci.h index 6fc01ce1977..c231a3d6cfd 100644 --- a/arch/mips/include/asm/vr41xx/pci.h +++ b/arch/mips/include/asm/vr41xx/pci.h @@ -1,7 +1,7 @@ /* * Include file for NEC VR4100 series PCI Control Unit. * - * Copyright (C) 2004-2005 Yoichi Yuasa + * Copyright (C) 2004-2005 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/vr41xx/siu.h b/arch/mips/include/asm/vr41xx/siu.h index da9f6e37340..ca806bc4ddc 100644 --- a/arch/mips/include/asm/vr41xx/siu.h +++ b/arch/mips/include/asm/vr41xx/siu.h @@ -1,7 +1,7 @@ /* * Include file for NEC VR4100 series Serial Interface Unit. * - * Copyright (C) 2005-2008 Yoichi Yuasa + * Copyright (C) 2005-2008 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/vr41xx/tb0219.h b/arch/mips/include/asm/vr41xx/tb0219.h index dc981b4be0a..c78e8243b44 100644 --- a/arch/mips/include/asm/vr41xx/tb0219.h +++ b/arch/mips/include/asm/vr41xx/tb0219.h @@ -1,7 +1,7 @@ /* * tb0219.h, Include file for TANBAC TB0219. * - * Copyright (C) 2002-2004 Yoichi Yuasa + * Copyright (C) 2002-2004 Yoichi Yuasa * * Modified for TANBAC TB0219: * Copyright (C) 2003 Megasolution Inc. diff --git a/arch/mips/include/asm/vr41xx/tb0226.h b/arch/mips/include/asm/vr41xx/tb0226.h index de527dcfa5f..36f5f798e41 100644 --- a/arch/mips/include/asm/vr41xx/tb0226.h +++ b/arch/mips/include/asm/vr41xx/tb0226.h @@ -1,7 +1,7 @@ /* * tb0226.h, Include file for TANBAC TB0226. * - * Copyright (C) 2002-2004 Yoichi Yuasa + * Copyright (C) 2002-2004 Yoichi Yuasa * * 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 diff --git a/arch/mips/include/asm/vr41xx/vr41xx.h b/arch/mips/include/asm/vr41xx/vr41xx.h index 22be64971cc..7b96a43b72b 100644 --- a/arch/mips/include/asm/vr41xx/vr41xx.h +++ b/arch/mips/include/asm/vr41xx/vr41xx.h @@ -7,7 +7,7 @@ * Copyright (C) 2001, 2002 Paul Mundt * Copyright (C) 2002 MontaVista Software, Inc. * Copyright (C) 2002 TimeSys Corp. - * Copyright (C) 2003-2008 Yoichi Yuasa + * Copyright (C) 2003-2008 Yoichi Yuasa * * 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 diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c index 1ada45ea070..6996da4d74a 100644 --- a/arch/mips/kernel/cevt-ds1287.c +++ b/arch/mips/kernel/cevt-ds1287.c @@ -1,7 +1,7 @@ /* * DS1287 clockevent driver * - * Copyright (C) 2008 Yoichi Yuasa + * Copyright (C) 2008 Yoichi Yuasa * * 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 diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c index e9b787feedc..92351e00ae0 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -1,7 +1,7 @@ /* * GT641xx clockevent routines. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c index b551f48d3a0..23da108506b 100644 --- a/arch/mips/kernel/csrc-ioasic.c +++ b/arch/mips/kernel/csrc-ioasic.c @@ -1,7 +1,7 @@ /* * DEC I/O ASIC's counter clocksource * - * Copyright (C) 2008 Yoichi Yuasa + * Copyright (C) 2008 Yoichi Yuasa * * 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 diff --git a/arch/mips/kernel/irq-gt641xx.c b/arch/mips/kernel/irq-gt641xx.c index 1b81b131f43..ebcc5f7ad9c 100644 --- a/arch/mips/kernel/irq-gt641xx.c +++ b/arch/mips/kernel/irq-gt641xx.c @@ -1,7 +1,7 @@ /* * GT641xx IRQ routines. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c index 1416bca6d1a..1c02f573736 100644 --- a/arch/mips/pci/fixup-capcella.c +++ b/arch/mips/pci/fixup-capcella.c @@ -1,7 +1,7 @@ /* * fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups. * - * Copyright (C) 2002,2004 Yoichi Yuasa + * Copyright (C) 2002,2004 Yoichi Yuasa * * 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 diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c index 59115962572..e08f49cb687 100644 --- a/arch/mips/pci/fixup-mpc30x.c +++ b/arch/mips/pci/fixup-mpc30x.c @@ -1,7 +1,7 @@ /* * fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups. * - * Copyright (C) 2002,2004 Yoichi Yuasa + * Copyright (C) 2002,2004 Yoichi Yuasa * * 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 diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c index ed87733f679..8084b17d440 100644 --- a/arch/mips/pci/fixup-tb0219.c +++ b/arch/mips/pci/fixup-tb0219.c @@ -2,7 +2,7 @@ * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups. * * Copyright (C) 2003 Megasolution Inc. - * Copyright (C) 2004-2005 Yoichi Yuasa + * Copyright (C) 2004-2005 Yoichi Yuasa * * 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 diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c index e3eedf4bf9b..4196ccf3ea3 100644 --- a/arch/mips/pci/fixup-tb0226.c +++ b/arch/mips/pci/fixup-tb0226.c @@ -1,7 +1,7 @@ /* * fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups. * - * Copyright (C) 2002-2005 Yoichi Yuasa + * Copyright (C) 2002-2005 Yoichi Yuasa * * 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 diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c index 267ab3dc3d4..2fe29db4372 100644 --- a/arch/mips/pci/fixup-tb0287.c +++ b/arch/mips/pci/fixup-tb0287.c @@ -1,7 +1,7 @@ /* * fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups. * - * Copyright (C) 2005 Yoichi Yuasa + * Copyright (C) 2005 Yoichi Yuasa * * 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 diff --git a/arch/mips/pci/ops-vr41xx.c b/arch/mips/pci/ops-vr41xx.c index 900c6b32576..28962a7c660 100644 --- a/arch/mips/pci/ops-vr41xx.c +++ b/arch/mips/pci/ops-vr41xx.c @@ -2,8 +2,8 @@ * ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series. * * Copyright (C) 2001-2003 MontaVista Software Inc. - * Author: Yoichi Yuasa - * Copyright (C) 2004-2005 Yoichi Yuasa + * Author: Yoichi Yuasa + * Copyright (C) 2004-2005 Yoichi Yuasa * * 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 @@ -21,7 +21,7 @@ */ /* * Changes: - * MontaVista Software Inc. or + * MontaVista Software Inc. * - New creation, NEC VR4122 and VR4131 are supported. */ #include diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c index d1e049b55f3..56525711f8b 100644 --- a/arch/mips/pci/pci-vr41xx.c +++ b/arch/mips/pci/pci-vr41xx.c @@ -2,8 +2,8 @@ * pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series. * * Copyright (C) 2001-2003 MontaVista Software Inc. - * Author: Yoichi Yuasa - * Copyright (C) 2004-2008 Yoichi Yuasa + * Author: Yoichi Yuasa + * Copyright (C) 2004-2008 Yoichi Yuasa * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,7 @@ */ /* * Changes: - * MontaVista Software Inc. or + * MontaVista Software Inc. * - New creation, NEC VR4122 and VR4131 are supported. */ #include diff --git a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h index 8a35e32b837..6b1ae2eb1c0 100644 --- a/arch/mips/pci/pci-vr41xx.h +++ b/arch/mips/pci/pci-vr41xx.h @@ -2,8 +2,8 @@ * pci-vr41xx.h, Include file for PCI Control Unit of the NEC VR4100 series. * * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa - * Copyright (C) 2004-2005 Yoichi Yuasa + * Author: Yoichi Yuasa + * Copyright (C) 2004-2005 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c index 6d9bab89058..719f4a5b984 100644 --- a/arch/mips/vr41xx/casio-e55/setup.c +++ b/arch/mips/vr41xx/casio-e55/setup.c @@ -1,7 +1,7 @@ /* * setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65. * - * Copyright (C) 2002-2006 Yoichi Yuasa + * Copyright (C) 2002-2006 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c index d77c330a0d5..6346c59c9f9 100644 --- a/arch/mips/vr41xx/common/bcu.c +++ b/arch/mips/vr41xx/common/bcu.c @@ -2,8 +2,8 @@ * bcu.c, Bus Control Unit routines for the NEC VR4100 series. * * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa - * Copyright (C) 2003-2005 Yoichi Yuasa + * Author: Yoichi Yuasa + * Copyright (C) 2003-2005 Yoichi Yuasa * * 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 @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. or + * MontaVista Software Inc. * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa + * Yoichi Yuasa * - Added support for NEC VR4133. */ #include diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c index ad0e8e3409d..8ba7d04a5ec 100644 --- a/arch/mips/vr41xx/common/cmu.c +++ b/arch/mips/vr41xx/common/cmu.c @@ -2,8 +2,8 @@ * cmu.c, Clock Mask Unit routines for the NEC VR4100 series. * * Copyright (C) 2001-2002 MontaVista Software Inc. - * Author: Yoichi Yuasa - * Copuright (C) 2003-2005 Yoichi Yuasa + * Author: Yoichi Yuasa + * Copuright (C) 2003-2005 Yoichi Yuasa * * 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 @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. or + * MontaVista Software Inc. * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa + * Yoichi Yuasa * - Added support for NEC VR4133. */ #include diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c index 2b272f1496f..22cc6f2100a 100644 --- a/arch/mips/vr41xx/common/giu.c +++ b/arch/mips/vr41xx/common/giu.c @@ -1,7 +1,7 @@ /* * NEC VR4100 series GIU platform device. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 3f23d9fda66..6d39e222b17 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -2,8 +2,8 @@ * icu.c, Interrupt Control Unit routines for the NEC VR4100 series. * * Copyright (C) 2001-2002 MontaVista Software Inc. - * Author: Yoichi Yuasa - * Copyright (C) 2003-2006 Yoichi Yuasa + * Author: Yoichi Yuasa + * Copyright (C) 2003-2006 Yoichi Yuasa * * 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 @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. or + * MontaVista Software Inc. * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa + * Yoichi Yuasa * - Coped with INTASSIGN of NEC VR4133. */ #include diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c index c64995342ba..1386e6f081c 100644 --- a/arch/mips/vr41xx/common/init.c +++ b/arch/mips/vr41xx/common/init.c @@ -1,7 +1,7 @@ /* * init.c, Common initialization routines for NEC VR4100 series. * - * Copyright (C) 2003-2008 Yoichi Yuasa + * Copyright (C) 2003-2008 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 9cc389109b1..bef06872f01 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -1,7 +1,7 @@ /* * Interrupt handing routines for NEC VR4100 series. * - * Copyright (C) 2005-2007 Yoichi Yuasa + * Copyright (C) 2005-2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c index 028aaf75eb2..692b4e85b7f 100644 --- a/arch/mips/vr41xx/common/pmu.c +++ b/arch/mips/vr41xx/common/pmu.c @@ -1,7 +1,7 @@ /* * pmu.c, Power Management Unit routines for NEC VR4100 series. * - * Copyright (C) 2003-2007 Yoichi Yuasa + * Copyright (C) 2003-2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c index 9f26c14edca..ebc5dcf0ed8 100644 --- a/arch/mips/vr41xx/common/rtc.c +++ b/arch/mips/vr41xx/common/rtc.c @@ -1,7 +1,7 @@ /* * NEC VR4100 series RTC platform device. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c index 654dee6208b..54eae56108f 100644 --- a/arch/mips/vr41xx/common/siu.c +++ b/arch/mips/vr41xx/common/siu.c @@ -1,7 +1,7 @@ /* * NEC VR4100 series SIU platform device. * - * Copyright (C) 2007-2008 Yoichi Yuasa + * Copyright (C) 2007-2008 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/common/type.c b/arch/mips/vr41xx/common/type.c index e0c1ac5e988..ff841422b63 100644 --- a/arch/mips/vr41xx/common/type.c +++ b/arch/mips/vr41xx/common/type.c @@ -1,7 +1,7 @@ /* * type.c, System type for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa + * Copyright (C) 2005 Yoichi Yuasa * * 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 diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c index 9eef297eca1..3982f378a3e 100644 --- a/arch/mips/vr41xx/ibm-workpad/setup.c +++ b/arch/mips/vr41xx/ibm-workpad/setup.c @@ -1,7 +1,7 @@ /* * setup.c, Setup for the IBM WorkPad z50. * - * Copyright (C) 2002-2006 Yoichi Yuasa + * Copyright (C) 2002-2006 Yoichi Yuasa * * 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 diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index 6062b62800f..b3ec9b10e29 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c @@ -1,7 +1,7 @@ /* * Driver for TANBAC TB0219 base board. * - * Copyright (C) 2005 Yoichi Yuasa + * Copyright (C) 2005 Yoichi Yuasa * * 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 @@ -28,7 +28,7 @@ #include #include -MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_AUTHOR("Yoichi Yuasa "); MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c index f691ffa95fb..b70e06133e7 100644 --- a/drivers/gpio/vr41xx_giu.c +++ b/drivers/gpio/vr41xx_giu.c @@ -2,8 +2,8 @@ * Driver for NEC VR4100 series General-purpose I/O Unit. * * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa - * Copyright (C) 2003-2009 Yoichi Yuasa + * Author: Yoichi Yuasa + * Copyright (C) 2003-2009 Yoichi Yuasa * * 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 @@ -37,7 +37,7 @@ #include #include -MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_AUTHOR("Yoichi Yuasa "); MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 2adf9cb265d..d114d3a9e1e 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -1,7 +1,7 @@ /* * Cobalt button interface driver. * - * Copyright (C) 2007-2008 Yoichi Yuasa + * Copyright (C) 2007-2008 Yoichi Yuasa * * 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 @@ -148,7 +148,7 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev) return 0; } -MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_AUTHOR("Yoichi Yuasa "); MODULE_DESCRIPTION("Cobalt button interface driver"); MODULE_LICENSE("GPL"); /* work with hotplug and coldplug */ diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c index ff0e8c3fbf9..5f1ce810815 100644 --- a/drivers/leds/leds-cobalt-raq.c +++ b/drivers/leds/leds-cobalt-raq.c @@ -1,7 +1,7 @@ /* * LEDs driver for the Cobalt Raq series. * - * Copyright (C) 2007 Yoichi Yuasa + * Copyright (C) 2007 Yoichi Yuasa * * 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 diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 659421d0ca4..d4ad50d737b 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -1,7 +1,7 @@ /* * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services. * - * Copyright (C) 2003-2005 Yoichi Yuasa + * Copyright (C) 2003-2005 Yoichi Yuasa * * 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 @@ -32,7 +32,7 @@ #include "i82365.h" MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services"); -MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_AUTHOR("Yoichi Yuasa "); MODULE_LICENSE("GPL"); #define CARD_MAX_SLOTS 2 diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 812f038e9bd..9b3c15827e5 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c @@ -6,7 +6,7 @@ * NEC VRC4173 CARDU driver for Socket Services * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) * - * Copyright 2002,2003 Yoichi Yuasa + * Copyright 2002,2003 Yoichi Yuasa * * 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 @@ -41,7 +41,7 @@ #include "vrc4173_cardu.h" MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); -MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_AUTHOR("Yoichi Yuasa "); MODULE_LICENSE("GPL"); static int vrc4173_cardu_slots; diff --git a/drivers/pcmcia/vrc4173_cardu.h b/drivers/pcmcia/vrc4173_cardu.h index 7d77c74120c..a7d96018ed8 100644 --- a/drivers/pcmcia/vrc4173_cardu.h +++ b/drivers/pcmcia/vrc4173_cardu.h @@ -5,7 +5,7 @@ * BRIEF MODULE DESCRIPTION * Include file for NEC VRC4173 CARDU. * - * Copyright 2002 Yoichi Yuasa + * Copyright 2002 Yoichi Yuasa * * 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 diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index f11297aff85..2c839d0d21b 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -1,7 +1,7 @@ /* * Driver for NEC VR4100 series Real Time Clock unit. * - * Copyright (C) 2003-2008 Yoichi Yuasa + * Copyright (C) 2003-2008 Yoichi Yuasa * * 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 @@ -33,7 +33,7 @@ #include #include -MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_AUTHOR("Yoichi Yuasa "); MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 0573f3b5175..dac550e57c2 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -1,7 +1,7 @@ /* * Driver for NEC VR4100 series Serial Interface Unit. * - * Copyright (C) 2004-2008 Yoichi Yuasa + * Copyright (C) 2004-2008 Yoichi Yuasa * * Based on drivers/serial/8250.c, by Russell King. * diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 7bad24ed04e..108b89e09a8 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c @@ -1,7 +1,7 @@ /* * Cobalt server LCD frame buffer driver. * - * Copyright (C) 2008 Yoichi Yuasa + * Copyright (C) 2008 Yoichi Yuasa * * 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 -- cgit v1.2.3 From 01a6221a6a51ec47b9ae3ed42c396f98dd488c7e Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 29 Jun 2009 17:18:51 -0700 Subject: MIPS: Reorganize Cavium OCTEON PCI support. Move the cavium PCI files to the arch/mips/pci directory. Also cleanup comment formatting and code layout. Code from pci-common.c, was moved into other files. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/Makefile | 4 - arch/mips/cavium-octeon/dma-octeon.c | 2 +- arch/mips/cavium-octeon/msi.c | 288 ------ arch/mips/cavium-octeon/pci-common.c | 137 --- arch/mips/cavium-octeon/pci-common.h | 39 - arch/mips/cavium-octeon/pci.c | 568 ------------ arch/mips/cavium-octeon/pcie.c | 1370 ----------------------------- arch/mips/include/asm/octeon/pci-octeon.h | 45 + arch/mips/pci/Makefile | 5 + arch/mips/pci/msi-octeon.c | 288 ++++++ arch/mips/pci/pci-octeon.c | 675 ++++++++++++++ arch/mips/pci/pcie-octeon.c | 1369 ++++++++++++++++++++++++++++ 12 files changed, 2383 insertions(+), 2407 deletions(-) delete mode 100644 arch/mips/cavium-octeon/msi.c delete mode 100644 arch/mips/cavium-octeon/pci-common.c delete mode 100644 arch/mips/cavium-octeon/pci-common.h delete mode 100644 arch/mips/cavium-octeon/pci.c delete mode 100644 arch/mips/cavium-octeon/pcie.c create mode 100644 arch/mips/include/asm/octeon/pci-octeon.h create mode 100644 arch/mips/pci/msi-octeon.c create mode 100644 arch/mips/pci/pci-octeon.c create mode 100644 arch/mips/pci/pcie-octeon.c diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 7c0528b0e34..d6903c3f3d5 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -14,9 +14,5 @@ obj-y += dma-octeon.o flash_setup.o obj-y += octeon-memcpy.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_PCI) += pci-common.o -obj-$(CONFIG_PCI) += pci.o -obj-$(CONFIG_PCI) += pcie.o -obj-$(CONFIG_PCI_MSI) += msi.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index 627c162a615..4b92bfc662d 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -29,7 +29,7 @@ #include #ifdef CONFIG_PCI -#include "pci-common.h" +#include #endif #define BAR2_PCI_ADDRESS 0x8000000000ul diff --git a/arch/mips/cavium-octeon/msi.c b/arch/mips/cavium-octeon/msi.c deleted file mode 100644 index 964b03b75a8..00000000000 --- a/arch/mips/cavium-octeon/msi.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * 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) 2005-2007 Cavium Networks - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "pci-common.h" - -/* - * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is - * in use. - */ -static uint64_t msi_free_irq_bitmask; - -/* - * Each bit in msi_multiple_irq_bitmask tells that the device using - * this bit in msi_free_irq_bitmask is also using the next bit. This - * is used so we can disable all of the MSI interrupts when a device - * uses multiple. - */ -static uint64_t msi_multiple_irq_bitmask; - -/* - * This lock controls updates to msi_free_irq_bitmask and - * msi_multiple_irq_bitmask. - */ -static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); - - -/** - * Called when a driver request MSI interrupts instead of the - * legacy INT A-D. This routine will allocate multiple interrupts - * for MSI devices that support them. A device can override this by - * programming the MSI control bits [6:4] before calling - * pci_enable_msi(). - * - * @param dev Device requesting MSI interrupts - * @param desc MSI descriptor - * - * Returns 0 on success. - */ -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) -{ - struct msi_msg msg; - uint16_t control; - int configured_private_bits; - int request_private_bits; - int irq; - int irq_step; - uint64_t search_mask; - - /* - * Read the MSI config to figure out how many IRQs this device - * wants. Most devices only want 1, which will give - * configured_private_bits and request_private_bits equal 0. - */ - pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, - &control); - - /* - * If the number of private bits has been configured then use - * that value instead of the requested number. This gives the - * driver the chance to override the number of interrupts - * before calling pci_enable_msi(). - */ - configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4; - if (configured_private_bits == 0) { - /* Nothing is configured, so use the hardware requested size */ - request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1; - } else { - /* - * Use the number of configured bits, assuming the - * driver wanted to override the hardware request - * value. - */ - request_private_bits = configured_private_bits; - } - - /* - * The PCI 2.3 spec mandates that there are at most 32 - * interrupts. If this device asks for more, only give it one. - */ - if (request_private_bits > 5) - request_private_bits = 0; - -try_only_one: - /* - * The IRQs have to be aligned on a power of two based on the - * number being requested. - */ - irq_step = 1 << request_private_bits; - - /* Mask with one bit for each IRQ */ - search_mask = (1 << irq_step) - 1; - - /* - * We're going to search msi_free_irq_bitmask_lock for zero - * bits. This represents an MSI interrupt number that isn't in - * use. - */ - spin_lock(&msi_free_irq_bitmask_lock); - for (irq = 0; irq < 64; irq += irq_step) { - if ((msi_free_irq_bitmask & (search_mask << irq)) == 0) { - msi_free_irq_bitmask |= search_mask << irq; - msi_multiple_irq_bitmask |= (search_mask >> 1) << irq; - break; - } - } - spin_unlock(&msi_free_irq_bitmask_lock); - - /* Make sure the search for available interrupts didn't fail */ - if (irq >= 64) { - if (request_private_bits) { - pr_err("arch_setup_msi_irq: Unable to find %d free " - "interrupts, trying just one", - 1 << request_private_bits); - request_private_bits = 0; - goto try_only_one; - } else - panic("arch_setup_msi_irq: Unable to find a free MSI " - "interrupt"); - } - - /* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */ - irq += OCTEON_IRQ_MSI_BIT0; - - switch (octeon_dma_bar_type) { - case OCTEON_DMA_BAR_TYPE_SMALL: - /* When not using big bar, Bar 0 is based at 128MB */ - msg.address_lo = - ((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff; - msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32; - case OCTEON_DMA_BAR_TYPE_BIG: - /* When using big bar, Bar 0 is based at 0 */ - msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff; - msg.address_hi = (0 + CVMX_PCI_MSI_RCV) >> 32; - break; - case OCTEON_DMA_BAR_TYPE_PCIE: - /* When using PCIe, Bar 0 is based at 0 */ - /* FIXME CVMX_NPEI_MSI_RCV* other than 0? */ - msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff; - msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32; - break; - default: - panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type\n"); - } - msg.data = irq - OCTEON_IRQ_MSI_BIT0; - - /* Update the number of IRQs the device has available to it */ - control &= ~PCI_MSI_FLAGS_QSIZE; - control |= request_private_bits << 4; - pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, - control); - - set_irq_msi(irq, desc); - write_msi_msg(irq, &msg); - return 0; -} - - -/** - * Called when a device no longer needs its MSI interrupts. All - * MSI interrupts for the device are freed. - * - * @irq: The devices first irq number. There may be multple in sequence. - */ -void arch_teardown_msi_irq(unsigned int irq) -{ - int number_irqs; - uint64_t bitmask; - - if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_BIT63)) - panic("arch_teardown_msi_irq: Attempted to teardown illegal " - "MSI interrupt (%d)", irq); - irq -= OCTEON_IRQ_MSI_BIT0; - - /* - * Count the number of IRQs we need to free by looking at the - * msi_multiple_irq_bitmask. Each bit set means that the next - * IRQ is also owned by this device. - */ - number_irqs = 0; - while ((irq+number_irqs < 64) && - (msi_multiple_irq_bitmask & (1ull << (irq + number_irqs)))) - number_irqs++; - number_irqs++; - /* Mask with one bit for each IRQ */ - bitmask = (1 << number_irqs) - 1; - /* Shift the mask to the correct bit location */ - bitmask <<= irq; - if ((msi_free_irq_bitmask & bitmask) != bitmask) - panic("arch_teardown_msi_irq: Attempted to teardown MSI " - "interrupt (%d) not in use", irq); - - /* Checks are done, update the in use bitmask */ - spin_lock(&msi_free_irq_bitmask_lock); - msi_free_irq_bitmask &= ~bitmask; - msi_multiple_irq_bitmask &= ~bitmask; - spin_unlock(&msi_free_irq_bitmask_lock); -} - - -/** - * Called by the interrupt handling code when an MSI interrupt - * occurs. - * - * @param cpl - * @param dev_id - * - * @return - */ -static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) -{ - uint64_t msi_bits; - int irq; - - if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) - msi_bits = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_RCV0); - else - msi_bits = cvmx_read_csr(CVMX_NPI_NPI_MSI_RCV); - irq = fls64(msi_bits); - if (irq) { - irq += OCTEON_IRQ_MSI_BIT0 - 1; - if (irq_desc[irq].action) { - do_IRQ(irq); - return IRQ_HANDLED; - } else { - pr_err("Spurious MSI interrupt %d\n", irq); - if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* These chips have PCIe */ - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, - 1ull << (irq - - OCTEON_IRQ_MSI_BIT0)); - } else { - /* These chips have PCI */ - cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, - 1ull << (irq - - OCTEON_IRQ_MSI_BIT0)); - } - } - } - return IRQ_NONE; -} - - -/** - * Initializes the MSI interrupt handling code - * - * @return - */ -int octeon_msi_initialize(void) -{ - int r; - if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { - r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[0:63]", octeon_msi_interrupt); - } else if (octeon_is_pci_host()) { - r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[0:15]", octeon_msi_interrupt); - r += request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[16:31]", octeon_msi_interrupt); - r += request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[32:47]", octeon_msi_interrupt); - r += request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[48:63]", octeon_msi_interrupt); - } - return 0; -} - -subsys_initcall(octeon_msi_initialize); diff --git a/arch/mips/cavium-octeon/pci-common.c b/arch/mips/cavium-octeon/pci-common.c deleted file mode 100644 index cd029f88da7..00000000000 --- a/arch/mips/cavium-octeon/pci-common.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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) 2005-2007 Cavium Networks - */ -#include -#include -#include -#include -#include -#include -#include "pci-common.h" - -typeof(pcibios_map_irq) *octeon_pcibios_map_irq; -enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID; - -/** - * Map a PCI device to the appropriate interrupt line - * - * @param dev The Linux PCI device structure for the device to map - * @param slot The slot number for this device on __BUS 0__. Linux - * enumerates through all the bridges and figures out the - * slot on Bus 0 where this device eventually hooks to. - * @param pin The PCI interrupt pin read from the device, then swizzled - * as it goes through each bridge. - * @return Interrupt number for the device - */ -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - if (octeon_pcibios_map_irq) - return octeon_pcibios_map_irq(dev, slot, pin); - else - panic("octeon_pcibios_map_irq doesn't point to a " - "pcibios_map_irq() function"); -} - - -/** - * Called to perform platform specific PCI setup - * - * @param dev - * @return - */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - uint16_t config; - uint32_t dconfig; - int pos; - /* - * Force the Cache line setting to 64 bytes. The standard - * Linux bus scan doesn't seem to set it. Octeon really has - * 128 byte lines, but Intel bridges get really upset if you - * try and set values above 64 bytes. Value is specified in - * 32bit words. - */ - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4); - /* Set latency timers for all devices */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48); - - /* Enable reporting System errors and parity errors on all devices */ - /* Enable parity checking and error reporting */ - pci_read_config_word(dev, PCI_COMMAND, &config); - config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; - pci_write_config_word(dev, PCI_COMMAND, config); - - if (dev->subordinate) { - /* Set latency timers on sub bridges */ - pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48); - /* More bridge error detection */ - pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config); - config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config); - } - - /* Enable the PCIe normal error reporting */ - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - if (pos) { - /* Update Device Control */ - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config); - /* Correctable Error Reporting */ - config |= PCI_EXP_DEVCTL_CERE; - /* Non-Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_NFERE; - /* Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_FERE; - /* Unsupported Request */ - config |= PCI_EXP_DEVCTL_URRE; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config); - } - - /* Find the Advanced Error Reporting capability */ - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); - if (pos) { - /* Clear Uncorrectable Error Status */ - pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, - &dconfig); - pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, - dconfig); - /* Enable reporting of all uncorrectable errors */ - /* Uncorrectable Error Mask - turned on bits disable errors */ - pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0); - /* - * Leave severity at HW default. This only controls if - * errors are reported as uncorrectable or - * correctable, not if the error is reported. - */ - /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */ - /* Clear Correctable Error Status */ - pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig); - pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig); - /* Enable reporting of all correctable errors */ - /* Correctable Error Mask - turned on bits disable errors */ - pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0); - /* Advanced Error Capabilities */ - pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig); - /* ECRC Generation Enable */ - if (config & PCI_ERR_CAP_ECRC_GENC) - config |= PCI_ERR_CAP_ECRC_GENE; - /* ECRC Check Enable */ - if (config & PCI_ERR_CAP_ECRC_CHKC) - config |= PCI_ERR_CAP_ECRC_CHKE; - pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig); - /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */ - /* Report all errors to the root complex */ - pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, - PCI_ERR_ROOT_CMD_COR_EN | - PCI_ERR_ROOT_CMD_NONFATAL_EN | - PCI_ERR_ROOT_CMD_FATAL_EN); - /* Clear the Root status register */ - pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig); - pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig); - } - - return 0; -} diff --git a/arch/mips/cavium-octeon/pci-common.h b/arch/mips/cavium-octeon/pci-common.h deleted file mode 100644 index 74ae79991e4..00000000000 --- a/arch/mips/cavium-octeon/pci-common.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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) 2005-2007 Cavium Networks - */ -#ifndef __OCTEON_PCI_COMMON_H__ -#define __OCTEON_PCI_COMMON_H__ - -#include - -/* Some PCI cards require delays when accessing config space. */ -#define PCI_CONFIG_SPACE_DELAY 10000 - -/* pcibios_map_irq() is defined inside pci-common.c. All it does is call the - Octeon specific version pointed to by this variable. This function needs to - change for PCI or PCIe based hosts */ -extern typeof(pcibios_map_irq) *octeon_pcibios_map_irq; - -/* The following defines are only used when octeon_dma_bar_type = - OCTEON_DMA_BAR_TYPE_BIG */ -#define OCTEON_PCI_BAR1_HOLE_BITS 5 -#define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3)) - -enum octeon_dma_bar_type { - OCTEON_DMA_BAR_TYPE_INVALID, - OCTEON_DMA_BAR_TYPE_SMALL, - OCTEON_DMA_BAR_TYPE_BIG, - OCTEON_DMA_BAR_TYPE_PCIE -}; - -/** - * This is a variable to tell the DMA mapping system in dma-octeon.c - * how to map PCI DMA addresses. - */ -extern enum octeon_dma_bar_type octeon_dma_bar_type; - -#endif diff --git a/arch/mips/cavium-octeon/pci.c b/arch/mips/cavium-octeon/pci.c deleted file mode 100644 index 67c0ff5e92f..00000000000 --- a/arch/mips/cavium-octeon/pci.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * 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) 2005-2007 Cavium Networks - */ -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "pci-common.h" - -#define USE_OCTEON_INTERNAL_ARBITER - -/* - * Octeon's PCI controller uses did=3, subdid=2 for PCI IO - * addresses. Use PCI endian swapping 1 so no address swapping is - * necessary. The Linux io routines will endian swap the data. - */ -#define OCTEON_PCI_IOSPACE_BASE 0x80011a0400000000ull -#define OCTEON_PCI_IOSPACE_SIZE (1ull<<32) - -/* Octeon't PCI controller uses did=3, subdid=3 for PCI memory. */ -#define OCTEON_PCI_MEMSPACE_OFFSET (0x00011b0000000000ull) - -/** - * This is the bit decoding used for the Octeon PCI controller addresses - */ -union octeon_pci_address { - uint64_t u64; - struct { - uint64_t upper:2; - uint64_t reserved:13; - uint64_t io:1; - uint64_t did:5; - uint64_t subdid:3; - uint64_t reserved2:4; - uint64_t endian_swap:2; - uint64_t reserved3:10; - uint64_t bus:8; - uint64_t dev:5; - uint64_t func:3; - uint64_t reg:8; - } s; -}; - -/** - * Return the mapping of PCI device number to IRQ line. Each - * character in the return string represents the interrupt - * line for the device at that position. Device 1 maps to the - * first character, etc. The characters A-D are used for PCI - * interrupts. - * - * Returns PCI interrupt mapping - */ -const char *octeon_get_pci_interrupts(void) -{ - /* - * Returning an empty string causes the interrupts to be - * routed based on the PCI specification. From the PCI spec: - * - * INTA# of Device Number 0 is connected to IRQW on the system - * board. (Device Number has no significance regarding being - * located on the system board or in a connector.) INTA# of - * Device Number 1 is connected to IRQX on the system - * board. INTA# of Device Number 2 is connected to IRQY on the - * system board. INTA# of Device Number 3 is connected to IRQZ - * on the system board. The table below describes how each - * agent's INTx# lines are connected to the system board - * interrupt lines. The following equation can be used to - * determine to which INTx# signal on the system board a given - * device's INTx# line(s) is connected. - * - * MB = (D + I) MOD 4 MB = System board Interrupt (IRQW = 0, - * IRQX = 1, IRQY = 2, and IRQZ = 3) D = Device Number I = - * Interrupt Number (INTA# = 0, INTB# = 1, INTC# = 2, and - * INTD# = 3) - */ - switch (octeon_bootinfo->board_type) { - case CVMX_BOARD_TYPE_NAO38: - /* This is really the NAC38 */ - return "AAAAADABAAAAAAAAAAAAAAAAAAAAAAAA"; - case CVMX_BOARD_TYPE_THUNDER: - return ""; - case CVMX_BOARD_TYPE_EBH3000: - return ""; - case CVMX_BOARD_TYPE_EBH3100: - case CVMX_BOARD_TYPE_CN3010_EVB_HS5: - case CVMX_BOARD_TYPE_CN3005_EVB_HS5: - return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - case CVMX_BOARD_TYPE_BBGW_REF: - return "AABCD"; - default: - return ""; - } -} - -/** - * Map a PCI device to the appropriate interrupt line - * - * @dev: The Linux PCI device structure for the device to map - * @slot: The slot number for this device on __BUS 0__. Linux - * enumerates through all the bridges and figures out the - * slot on Bus 0 where this device eventually hooks to. - * @pin: The PCI interrupt pin read from the device, then swizzled - * as it goes through each bridge. - * Returns Interrupt number for the device - */ -int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev, - u8 slot, u8 pin) -{ - int irq_num; - const char *interrupts; - int dev_num; - - /* Get the board specific interrupt mapping */ - interrupts = octeon_get_pci_interrupts(); - - dev_num = dev->devfn >> 3; - if (dev_num < strlen(interrupts)) - irq_num = ((interrupts[dev_num] - 'A' + pin - 1) & 3) + - OCTEON_IRQ_PCI_INT0; - else - irq_num = ((slot + pin - 3) & 3) + OCTEON_IRQ_PCI_INT0; - return irq_num; -} - - -/** - * Read a value from configuration space - * - */ -static int octeon_read_config(struct pci_bus *bus, unsigned int devfn, - int reg, int size, u32 *val) -{ - union octeon_pci_address pci_addr; - - pci_addr.u64 = 0; - pci_addr.s.upper = 2; - pci_addr.s.io = 1; - pci_addr.s.did = 3; - pci_addr.s.subdid = 1; - pci_addr.s.endian_swap = 1; - pci_addr.s.bus = bus->number; - pci_addr.s.dev = devfn >> 3; - pci_addr.s.func = devfn & 0x7; - pci_addr.s.reg = reg; - -#if PCI_CONFIG_SPACE_DELAY - udelay(PCI_CONFIG_SPACE_DELAY); -#endif - switch (size) { - case 4: - *val = le32_to_cpu(cvmx_read64_uint32(pci_addr.u64)); - return PCIBIOS_SUCCESSFUL; - case 2: - *val = le16_to_cpu(cvmx_read64_uint16(pci_addr.u64)); - return PCIBIOS_SUCCESSFUL; - case 1: - *val = cvmx_read64_uint8(pci_addr.u64); - return PCIBIOS_SUCCESSFUL; - } - return PCIBIOS_FUNC_NOT_SUPPORTED; -} - - -/** - * Write a value to PCI configuration space - * - * @bus: - * @devfn: - * @reg: - * @size: - * @val: - * Returns - */ -static int octeon_write_config(struct pci_bus *bus, unsigned int devfn, - int reg, int size, u32 val) -{ - union octeon_pci_address pci_addr; - - pci_addr.u64 = 0; - pci_addr.s.upper = 2; - pci_addr.s.io = 1; - pci_addr.s.did = 3; - pci_addr.s.subdid = 1; - pci_addr.s.endian_swap = 1; - pci_addr.s.bus = bus->number; - pci_addr.s.dev = devfn >> 3; - pci_addr.s.func = devfn & 0x7; - pci_addr.s.reg = reg; - -#if PCI_CONFIG_SPACE_DELAY - udelay(PCI_CONFIG_SPACE_DELAY); -#endif - switch (size) { - case 4: - cvmx_write64_uint32(pci_addr.u64, cpu_to_le32(val)); - return PCIBIOS_SUCCESSFUL; - case 2: - cvmx_write64_uint16(pci_addr.u64, cpu_to_le16(val)); - return PCIBIOS_SUCCESSFUL; - case 1: - cvmx_write64_uint8(pci_addr.u64, val); - return PCIBIOS_SUCCESSFUL; - } - return PCIBIOS_FUNC_NOT_SUPPORTED; -} - - -static struct pci_ops octeon_pci_ops = { - octeon_read_config, - octeon_write_config, -}; - -static struct resource octeon_pci_mem_resource = { - .start = 0, - .end = 0, - .name = "Octeon PCI MEM", - .flags = IORESOURCE_MEM, -}; - -/* - * PCI ports must be above 16KB so the ISA bus filtering in the PCI-X to PCI - * bridge - */ -static struct resource octeon_pci_io_resource = { - .start = 0x4000, - .end = OCTEON_PCI_IOSPACE_SIZE - 1, - .name = "Octeon PCI IO", - .flags = IORESOURCE_IO, -}; - -static struct pci_controller octeon_pci_controller = { - .pci_ops = &octeon_pci_ops, - .mem_resource = &octeon_pci_mem_resource, - .mem_offset = OCTEON_PCI_MEMSPACE_OFFSET, - .io_resource = &octeon_pci_io_resource, - .io_offset = 0, - .io_map_base = OCTEON_PCI_IOSPACE_BASE, -}; - - -/** - * Low level initialize the Octeon PCI controller - * - * Returns - */ -static void octeon_pci_initialize(void) -{ - union cvmx_pci_cfg01 cfg01; - union cvmx_npi_ctl_status ctl_status; - union cvmx_pci_ctl_status_2 ctl_status_2; - union cvmx_pci_cfg19 cfg19; - union cvmx_pci_cfg16 cfg16; - union cvmx_pci_cfg22 cfg22; - union cvmx_pci_cfg56 cfg56; - - /* Reset the PCI Bus */ - cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1); - cvmx_read_csr(CVMX_CIU_SOFT_PRST); - - udelay(2000); /* Hold PCI reset for 2 ms */ - - ctl_status.u64 = 0; /* cvmx_read_csr(CVMX_NPI_CTL_STATUS); */ - ctl_status.s.max_word = 1; - ctl_status.s.timer = 1; - cvmx_write_csr(CVMX_NPI_CTL_STATUS, ctl_status.u64); - - /* Deassert PCI reset and advertize PCX Host Mode Device Capability - (64b) */ - cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4); - cvmx_read_csr(CVMX_CIU_SOFT_PRST); - - udelay(2000); /* Wait 2 ms after deasserting PCI reset */ - - ctl_status_2.u32 = 0; - ctl_status_2.s.tsr_hwm = 1; /* Initializes to 0. Must be set - before any PCI reads. */ - ctl_status_2.s.bar2pres = 1; /* Enable BAR2 */ - ctl_status_2.s.bar2_enb = 1; - ctl_status_2.s.bar2_cax = 1; /* Don't use L2 */ - ctl_status_2.s.bar2_esx = 1; - ctl_status_2.s.pmo_amod = 1; /* Round robin priority */ - if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) { - /* BAR1 hole */ - ctl_status_2.s.bb1_hole = OCTEON_PCI_BAR1_HOLE_BITS; - ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */ - ctl_status_2.s.bb_ca = 1; /* Don't use L2 with big bars */ - ctl_status_2.s.bb_es = 1; /* Big bar in byte swap mode */ - ctl_status_2.s.bb1 = 1; /* BAR1 is big */ - ctl_status_2.s.bb0 = 1; /* BAR0 is big */ - } - - octeon_npi_write32(CVMX_NPI_PCI_CTL_STATUS_2, ctl_status_2.u32); - udelay(2000); /* Wait 2 ms before doing PCI reads */ - - ctl_status_2.u32 = octeon_npi_read32(CVMX_NPI_PCI_CTL_STATUS_2); - pr_notice("PCI Status: %s %s-bit\n", - ctl_status_2.s.ap_pcix ? "PCI-X" : "PCI", - ctl_status_2.s.ap_64ad ? "64" : "32"); - - if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) { - union cvmx_pci_cnt_reg cnt_reg_start; - union cvmx_pci_cnt_reg cnt_reg_end; - unsigned long cycles, pci_clock; - - cnt_reg_start.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG); - cycles = read_c0_cvmcount(); - udelay(1000); - cnt_reg_end.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG); - cycles = read_c0_cvmcount() - cycles; - pci_clock = (cnt_reg_end.s.pcicnt - cnt_reg_start.s.pcicnt) / - (cycles / (mips_hpt_frequency / 1000000)); - pr_notice("PCI Clock: %lu MHz\n", pci_clock); - } - - /* - * TDOMC must be set to one in PCI mode. TDOMC should be set to 4 - * in PCI-X mode to allow four oustanding splits. Otherwise, - * should not change from its reset value. Don't write PCI_CFG19 - * in PCI mode (0x82000001 reset value), write it to 0x82000004 - * after PCI-X mode is known. MRBCI,MDWE,MDRE -> must be zero. - * MRBCM -> must be one. - */ - if (ctl_status_2.s.ap_pcix) { - cfg19.u32 = 0; - /* - * Target Delayed/Split request outstanding maximum - * count. [1..31] and 0=32. NOTE: If the user - * programs these bits beyond the Designed Maximum - * outstanding count, then the designed maximum table - * depth will be used instead. No additional - * Deferred/Split transactions will be accepted if - * this outstanding maximum count is - * reached. Furthermore, no additional deferred/split - * transactions will be accepted if the I/O delay/ I/O - * Split Request outstanding maximum is reached. - */ - cfg19.s.tdomc = 4; - /* - * Master Deferred Read Request Outstanding Max Count - * (PCI only). CR4C[26:24] Max SAC cycles MAX DAC - * cycles 000 8 4 001 1 0 010 2 1 011 3 1 100 4 2 101 - * 5 2 110 6 3 111 7 3 For example, if these bits are - * programmed to 100, the core can support 2 DAC - * cycles, 4 SAC cycles or a combination of 1 DAC and - * 2 SAC cycles. NOTE: For the PCI-X maximum - * outstanding split transactions, refer to - * CRE0[22:20]. - */ - cfg19.s.mdrrmc = 2; - /* - * Master Request (Memory Read) Byte Count/Byte Enable - * select. 0 = Byte Enables valid. In PCI mode, a - * burst transaction cannot be performed using Memory - * Read command=4?h6. 1 = DWORD Byte Count valid - * (default). In PCI Mode, the memory read byte - * enables are automatically generated by the - * core. Note: N3 Master Request transaction sizes are - * always determined through the - * am_attr[<35:32>|<7:0>] field. - */ - cfg19.s.mrbcm = 1; - octeon_npi_write32(CVMX_NPI_PCI_CFG19, cfg19.u32); - } - - - cfg01.u32 = 0; - cfg01.s.msae = 1; /* Memory Space Access Enable */ - cfg01.s.me = 1; /* Master Enable */ - cfg01.s.pee = 1; /* PERR# Enable */ - cfg01.s.see = 1; /* System Error Enable */ - cfg01.s.fbbe = 1; /* Fast Back to Back Transaction Enable */ - - octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); - -#ifdef USE_OCTEON_INTERNAL_ARBITER - /* - * When OCTEON is a PCI host, most systems will use OCTEON's - * internal arbiter, so must enable it before any PCI/PCI-X - * traffic can occur. - */ - { - union cvmx_npi_pci_int_arb_cfg pci_int_arb_cfg; - - pci_int_arb_cfg.u64 = 0; - pci_int_arb_cfg.s.en = 1; /* Internal arbiter enable */ - cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64); - } -#endif /* USE_OCTEON_INTERNAL_ARBITER */ - - /* - * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE, - * TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to - * 1..7. - */ - cfg16.u32 = 0; - cfg16.s.mltd = 1; /* Master Latency Timer Disable */ - octeon_npi_write32(CVMX_NPI_PCI_CFG16, cfg16.u32); - - /* - * Should be written to 0x4ff00. MTTV -> must be zero. - * FLUSH -> must be 1. MRV -> should be 0xFF. - */ - cfg22.u32 = 0; - /* Master Retry Value [1..255] and 0=infinite */ - cfg22.s.mrv = 0xff; - /* - * AM_DO_FLUSH_I control NOTE: This bit MUST BE ONE for proper - * N3K operation. - */ - cfg22.s.flush = 1; - octeon_npi_write32(CVMX_NPI_PCI_CFG22, cfg22.u32); - - /* - * MOST Indicates the maximum number of outstanding splits (in -1 - * notation) when OCTEON is in PCI-X mode. PCI-X performance is - * affected by the MOST selection. Should generally be written - * with one of 0x3be807, 0x2be807, 0x1be807, or 0x0be807, - * depending on the desired MOST of 3, 2, 1, or 0, respectively. - */ - cfg56.u32 = 0; - cfg56.s.pxcid = 7; /* RO - PCI-X Capability ID */ - cfg56.s.ncp = 0xe8; /* RO - Next Capability Pointer */ - cfg56.s.dpere = 1; /* Data Parity Error Recovery Enable */ - cfg56.s.roe = 1; /* Relaxed Ordering Enable */ - cfg56.s.mmbc = 1; /* Maximum Memory Byte Count - [0=512B,1=1024B,2=2048B,3=4096B] */ - cfg56.s.most = 3; /* Maximum outstanding Split transactions [0=1 - .. 7=32] */ - - octeon_npi_write32(CVMX_NPI_PCI_CFG56, cfg56.u32); - - /* - * Affects PCI performance when OCTEON services reads to its - * BAR1/BAR2. Refer to Section 10.6.1. The recommended values are - * 0x22, 0x33, and 0x33 for PCI_READ_CMD_6, PCI_READ_CMD_C, and - * PCI_READ_CMD_E, respectively. Unfortunately due to errata DDR-700, - * these values need to be changed so they won't possibly prefetch off - * of the end of memory if PCI is DMAing a buffer at the end of - * memory. Note that these values differ from their reset values. - */ - octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_6, 0x21); - octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_C, 0x31); - octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_E, 0x31); -} - - -/** - * Initialize the Octeon PCI controller - * - * Returns - */ -static int __init octeon_pci_setup(void) -{ - union cvmx_npi_mem_access_subidx mem_access; - int index; - - /* Only these chips have PCI */ - if (octeon_has_feature(OCTEON_FEATURE_PCIE)) - return 0; - - /* Point pcibios_map_irq() to the PCI version of it */ - octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq; - - /* Only use the big bars on chips that support it */ - if (OCTEON_IS_MODEL(OCTEON_CN31XX) || - OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) || - OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)) - octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_SMALL; - else - octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG; - - /* PCI I/O and PCI MEM values */ - set_io_port_base(OCTEON_PCI_IOSPACE_BASE); - ioport_resource.start = 0; - ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1; - if (!octeon_is_pci_host()) { - pr_notice("Not in host mode, PCI Controller not initialized\n"); - return 0; - } - - pr_notice("%s Octeon big bar support\n", - (octeon_dma_bar_type == - OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling"); - - octeon_pci_initialize(); - - mem_access.u64 = 0; - mem_access.s.esr = 1; /* Endian-Swap on read. */ - mem_access.s.esw = 1; /* Endian-Swap on write. */ - mem_access.s.nsr = 0; /* No-Snoop on read. */ - mem_access.s.nsw = 0; /* No-Snoop on write. */ - mem_access.s.ror = 0; /* Relax Read on read. */ - mem_access.s.row = 0; /* Relax Order on write. */ - mem_access.s.ba = 0; /* PCI Address bits [63:36]. */ - cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, mem_access.u64); - - /* - * Remap the Octeon BAR 2 above all 32 bit devices - * (0x8000000000ul). This is done here so it is remapped - * before the readl()'s below. We don't want BAR2 overlapping - * with BAR0/BAR1 during these reads. - */ - octeon_npi_write32(CVMX_NPI_PCI_CFG08, 0); - octeon_npi_write32(CVMX_NPI_PCI_CFG09, 0x80); - - /* Disable the BAR1 movable mappings */ - for (index = 0; index < 32; index++) - octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0); - - if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) { - /* Remap the Octeon BAR 0 to 0-2GB */ - octeon_npi_write32(CVMX_NPI_PCI_CFG04, 0); - octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0); - - /* - * Remap the Octeon BAR 1 to map 2GB-4GB (minus the - * BAR 1 hole). - */ - octeon_npi_write32(CVMX_NPI_PCI_CFG06, 2ul << 30); - octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0); - - /* Devices go after BAR1 */ - octeon_pci_mem_resource.start = - OCTEON_PCI_MEMSPACE_OFFSET + (4ul << 30) - - (OCTEON_PCI_BAR1_HOLE_SIZE << 20); - octeon_pci_mem_resource.end = - octeon_pci_mem_resource.start + (1ul << 30); - } else { - /* Remap the Octeon BAR 0 to map 128MB-(128MB+4KB) */ - octeon_npi_write32(CVMX_NPI_PCI_CFG04, 128ul << 20); - octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0); - - /* Remap the Octeon BAR 1 to map 0-128MB */ - octeon_npi_write32(CVMX_NPI_PCI_CFG06, 0); - octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0); - - /* Devices go after BAR0 */ - octeon_pci_mem_resource.start = - OCTEON_PCI_MEMSPACE_OFFSET + (128ul << 20) + - (4ul << 10); - octeon_pci_mem_resource.end = - octeon_pci_mem_resource.start + (1ul << 30); - } - - register_pci_controller(&octeon_pci_controller); - - /* - * Clear any errors that might be pending from before the bus - * was setup properly. - */ - cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1); - return 0; -} - -arch_initcall(octeon_pci_setup); diff --git a/arch/mips/cavium-octeon/pcie.c b/arch/mips/cavium-octeon/pcie.c deleted file mode 100644 index 49d14081b3b..00000000000 --- a/arch/mips/cavium-octeon/pcie.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - * 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) 2007, 2008 Cavium Networks - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "pci-common.h" - -union cvmx_pcie_address { - uint64_t u64; - struct { - uint64_t upper:2; /* Normally 2 for XKPHYS */ - uint64_t reserved_49_61:13; /* Must be zero */ - uint64_t io:1; /* 1 for IO space access */ - uint64_t did:5; /* PCIe DID = 3 */ - uint64_t subdid:3; /* PCIe SubDID = 1 */ - uint64_t reserved_36_39:4; /* Must be zero */ - uint64_t es:2; /* Endian swap = 1 */ - uint64_t port:2; /* PCIe port 0,1 */ - uint64_t reserved_29_31:3; /* Must be zero */ - /* - * Selects the type of the configuration request (0 = type 0, - * 1 = type 1). - */ - uint64_t ty:1; - /* Target bus number sent in the ID in the request. */ - uint64_t bus:8; - /* - * Target device number sent in the ID in the - * request. Note that Dev must be zero for type 0 - * configuration requests. - */ - uint64_t dev:5; - /* Target function number sent in the ID in the request. */ - uint64_t func:3; - /* - * Selects a register in the configuration space of - * the target. - */ - uint64_t reg:12; - } config; - struct { - uint64_t upper:2; /* Normally 2 for XKPHYS */ - uint64_t reserved_49_61:13; /* Must be zero */ - uint64_t io:1; /* 1 for IO space access */ - uint64_t did:5; /* PCIe DID = 3 */ - uint64_t subdid:3; /* PCIe SubDID = 2 */ - uint64_t reserved_36_39:4; /* Must be zero */ - uint64_t es:2; /* Endian swap = 1 */ - uint64_t port:2; /* PCIe port 0,1 */ - uint64_t address:32; /* PCIe IO address */ - } io; - struct { - uint64_t upper:2; /* Normally 2 for XKPHYS */ - uint64_t reserved_49_61:13; /* Must be zero */ - uint64_t io:1; /* 1 for IO space access */ - uint64_t did:5; /* PCIe DID = 3 */ - uint64_t subdid:3; /* PCIe SubDID = 3-6 */ - uint64_t reserved_36_39:4; /* Must be zero */ - uint64_t address:36; /* PCIe Mem address */ - } mem; -}; - -/** - * Return the Core virtual base address for PCIe IO access. IOs are - * read/written as an offset from this address. - * - * @pcie_port: PCIe port the IO is for - * - * Returns 64bit Octeon IO base address for read/write - */ -static inline uint64_t cvmx_pcie_get_io_base_address(int pcie_port) -{ - union cvmx_pcie_address pcie_addr; - pcie_addr.u64 = 0; - pcie_addr.io.upper = 0; - pcie_addr.io.io = 1; - pcie_addr.io.did = 3; - pcie_addr.io.subdid = 2; - pcie_addr.io.es = 1; - pcie_addr.io.port = pcie_port; - return pcie_addr.u64; -} - -/** - * Size of the IO address region returned at address - * cvmx_pcie_get_io_base_address() - * - * @pcie_port: PCIe port the IO is for - * - * Returns Size of the IO window - */ -static inline uint64_t cvmx_pcie_get_io_size(int pcie_port) -{ - return 1ull << 32; -} - -/** - * Return the Core virtual base address for PCIe MEM access. Memory is - * read/written as an offset from this address. - * - * @pcie_port: PCIe port the IO is for - * - * Returns 64bit Octeon IO base address for read/write - */ -static inline uint64_t cvmx_pcie_get_mem_base_address(int pcie_port) -{ - union cvmx_pcie_address pcie_addr; - pcie_addr.u64 = 0; - pcie_addr.mem.upper = 0; - pcie_addr.mem.io = 1; - pcie_addr.mem.did = 3; - pcie_addr.mem.subdid = 3 + pcie_port; - return pcie_addr.u64; -} - -/** - * Size of the Mem address region returned at address - * cvmx_pcie_get_mem_base_address() - * - * @pcie_port: PCIe port the IO is for - * - * Returns Size of the Mem window - */ -static inline uint64_t cvmx_pcie_get_mem_size(int pcie_port) -{ - return 1ull << 36; -} - -/** - * Read a PCIe config space register indirectly. This is used for - * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. - * - * @pcie_port: PCIe port to read from - * @cfg_offset: Address to read - * - * Returns Value read - */ -static uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) -{ - union cvmx_pescx_cfg_rd pescx_cfg_rd; - pescx_cfg_rd.u64 = 0; - pescx_cfg_rd.s.addr = cfg_offset; - cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64); - pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port)); - return pescx_cfg_rd.s.data; -} - -/** - * Write a PCIe config space register indirectly. This is used for - * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. - * - * @pcie_port: PCIe port to write to - * @cfg_offset: Address to write - * @val: Value to write - */ -static void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, - uint32_t val) -{ - union cvmx_pescx_cfg_wr pescx_cfg_wr; - pescx_cfg_wr.u64 = 0; - pescx_cfg_wr.s.addr = cfg_offset; - pescx_cfg_wr.s.data = val; - cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64); -} - -/** - * Build a PCIe config space request address for a device - * - * @pcie_port: PCIe port to access - * @bus: Sub bus - * @dev: Device ID - * @fn: Device sub function - * @reg: Register to access - * - * Returns 64bit Octeon IO address - */ -static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus, - int dev, int fn, int reg) -{ - union cvmx_pcie_address pcie_addr; - union cvmx_pciercx_cfg006 pciercx_cfg006; - - pciercx_cfg006.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port)); - if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0)) - return 0; - - pcie_addr.u64 = 0; - pcie_addr.config.upper = 2; - pcie_addr.config.io = 1; - pcie_addr.config.did = 3; - pcie_addr.config.subdid = 1; - pcie_addr.config.es = 1; - pcie_addr.config.port = pcie_port; - pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum); - pcie_addr.config.bus = bus; - pcie_addr.config.dev = dev; - pcie_addr.config.func = fn; - pcie_addr.config.reg = reg; - return pcie_addr.u64; -} - -/** - * Read 8bits from a Device's config space - * - * @pcie_port: PCIe port the device is on - * @bus: Sub bus - * @dev: Device ID - * @fn: Device sub function - * @reg: Register to access - * - * Returns Result of the read - */ -static uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, - int fn, int reg) -{ - uint64_t address = - __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); - if (address) - return cvmx_read64_uint8(address); - else - return 0xff; -} - -/** - * Read 16bits from a Device's config space - * - * @pcie_port: PCIe port the device is on - * @bus: Sub bus - * @dev: Device ID - * @fn: Device sub function - * @reg: Register to access - * - * Returns Result of the read - */ -static uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, - int fn, int reg) -{ - uint64_t address = - __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); - if (address) - return le16_to_cpu(cvmx_read64_uint16(address)); - else - return 0xffff; -} - -/** - * Read 32bits from a Device's config space - * - * @pcie_port: PCIe port the device is on - * @bus: Sub bus - * @dev: Device ID - * @fn: Device sub function - * @reg: Register to access - * - * Returns Result of the read - */ -static uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, - int fn, int reg) -{ - uint64_t address = - __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); - if (address) - return le32_to_cpu(cvmx_read64_uint32(address)); - else - return 0xffffffff; -} - -/** - * Write 8bits to a Device's config space - * - * @pcie_port: PCIe port the device is on - * @bus: Sub bus - * @dev: Device ID - * @fn: Device sub function - * @reg: Register to access - * @val: Value to write - */ -static void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, - int reg, uint8_t val) -{ - uint64_t address = - __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); - if (address) - cvmx_write64_uint8(address, val); -} - -/** - * Write 16bits to a Device's config space - * - * @pcie_port: PCIe port the device is on - * @bus: Sub bus - * @dev: Device ID - * @fn: Device sub function - * @reg: Register to access - * @val: Value to write - */ -static void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, - int reg, uint16_t val) -{ - uint64_t address = - __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); - if (address) - cvmx_write64_uint16(address, cpu_to_le16(val)); -} - -/** - * Write 32bits to a Device's config space - * - * @pcie_port: PCIe port the device is on - * @bus: Sub bus - * @dev: Device ID - * @fn: Device sub function - * @reg: Register to access - * @val: Value to write - */ -static void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, - int reg, uint32_t val) -{ - uint64_t address = - __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); - if (address) - cvmx_write64_uint32(address, cpu_to_le32(val)); -} - -/** - * Initialize the RC config space CSRs - * - * @pcie_port: PCIe port to initialize - */ -static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) -{ - union cvmx_pciercx_cfg030 pciercx_cfg030; - union cvmx_npei_ctl_status2 npei_ctl_status2; - union cvmx_pciercx_cfg070 pciercx_cfg070; - union cvmx_pciercx_cfg001 pciercx_cfg001; - union cvmx_pciercx_cfg032 pciercx_cfg032; - union cvmx_pciercx_cfg006 pciercx_cfg006; - union cvmx_pciercx_cfg008 pciercx_cfg008; - union cvmx_pciercx_cfg009 pciercx_cfg009; - union cvmx_pciercx_cfg010 pciercx_cfg010; - union cvmx_pciercx_cfg011 pciercx_cfg011; - union cvmx_pciercx_cfg035 pciercx_cfg035; - union cvmx_pciercx_cfg075 pciercx_cfg075; - union cvmx_pciercx_cfg034 pciercx_cfg034; - - /* Max Payload Size (PCIE*_CFG030[MPS]) */ - /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ - /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ - /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ - pciercx_cfg030.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); - /* - * Max payload size = 128 bytes for best Octeon DMA - * performance. - */ - pciercx_cfg030.s.mps = 0; - /* - * Max read request size = 128 bytes for best Octeon DMA - * performance. - */ - pciercx_cfg030.s.mrrs = 0; - /* Enable relaxed ordering. */ - pciercx_cfg030.s.ro_en = 1; - /* Enable no snoop. */ - pciercx_cfg030.s.ns_en = 1; - /* Correctable error reporting enable. */ - pciercx_cfg030.s.ce_en = 1; - /* Non-fatal error reporting enable. */ - pciercx_cfg030.s.nfe_en = 1; - /* Fatal error reporting enable. */ - pciercx_cfg030.s.fe_en = 1; - /* Unsupported request reporting enable. */ - pciercx_cfg030.s.ur_en = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), - pciercx_cfg030.u32); - - /* - * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match - * PCIE*_CFG030[MPS] - * - * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not - * exceed PCIE*_CFG030[MRRS]. - */ - npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); - /* Max payload size = 128 bytes for best Octeon DMA performance */ - npei_ctl_status2.s.mps = 0; - /* Max read request size = 128 bytes for best Octeon DMA performance */ - npei_ctl_status2.s.mrrs = 0; - cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); - - /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ - pciercx_cfg070.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port)); - pciercx_cfg070.s.ge = 1; /* ECRC generation enable. */ - pciercx_cfg070.s.ce = 1; /* ECRC check enable. */ - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port), - pciercx_cfg070.u32); - - /* - * Access Enables (PCIE*_CFG001[MSAE,ME]) ME and MSAE should - * always be set. - * - * Interrupt Disable (PCIE*_CFG001[I_DIS]) System Error - * Message Enable (PCIE*_CFG001[SEE]) - */ - pciercx_cfg001.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port)); - pciercx_cfg001.s.msae = 1; /* Memory space enable. */ - pciercx_cfg001.s.me = 1; /* Bus master enable. */ - pciercx_cfg001.s.i_dis = 1; /* INTx assertion disable. */ - pciercx_cfg001.s.see = 1; /* SERR# enable */ - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port), - pciercx_cfg001.u32); - - /* Advanced Error Recovery Message Enables */ - /* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */ - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG066(pcie_port), 0); - /* Use CVMX_PCIERCX_CFG067 hardware default */ - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0); - - /* Active State Power Management (PCIE*_CFG032[ASLPC]) */ - pciercx_cfg032.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); - pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */ - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port), - pciercx_cfg032.u32); - - /* Entrance Latencies (PCIE*_CFG451[L0EL,L1EL]) */ - - /* - * Link Width Mode (PCIERCn_CFG452[LME]) - Set during - * cvmx_pcie_rc_initialize_link() - * - * Primary Bus Number (PCIERCn_CFG006[PBNUM]) - * - * We set the primary bus number to 1 so IDT bridges are - * happy. They don't like zero. - */ - pciercx_cfg006.u32 = 0; - pciercx_cfg006.s.pbnum = 1; - pciercx_cfg006.s.sbnum = 1; - pciercx_cfg006.s.subbnum = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port), - pciercx_cfg006.u32); - - /* - * Memory-mapped I/O BAR (PCIERCn_CFG008) - * Most applications should disable the memory-mapped I/O BAR by - * setting PCIERCn_CFG008[ML_ADDR] < PCIERCn_CFG008[MB_ADDR] - */ - pciercx_cfg008.u32 = 0; - pciercx_cfg008.s.mb_addr = 0x100; - pciercx_cfg008.s.ml_addr = 0; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port), - pciercx_cfg008.u32); - - /* - * Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011) - * Most applications should disable the prefetchable BAR by setting - * PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] < - * PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE] - */ - pciercx_cfg009.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port)); - pciercx_cfg010.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port)); - pciercx_cfg011.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port)); - pciercx_cfg009.s.lmem_base = 0x100; - pciercx_cfg009.s.lmem_limit = 0; - pciercx_cfg010.s.umem_base = 0x100; - pciercx_cfg011.s.umem_limit = 0; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port), - pciercx_cfg009.u32); - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port), - pciercx_cfg010.u32); - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port), - pciercx_cfg011.u32); - - /* - * System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE]) - * PME Interrupt Enables (PCIERCn_CFG035[PMEIE]) - */ - pciercx_cfg035.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port)); - /* System error on correctable error enable. */ - pciercx_cfg035.s.secee = 1; - /* System error on fatal error enable. */ - pciercx_cfg035.s.sefee = 1; - /* System error on non-fatal error enable. */ - pciercx_cfg035.s.senfee = 1; - /* PME interrupt enable. */ - pciercx_cfg035.s.pmeie = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port), - pciercx_cfg035.u32); - - /* - * Advanced Error Recovery Interrupt Enables - * (PCIERCn_CFG075[CERE,NFERE,FERE]) - */ - pciercx_cfg075.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port)); - /* Correctable error reporting enable. */ - pciercx_cfg075.s.cere = 1; - /* Non-fatal error reporting enable. */ - pciercx_cfg075.s.nfere = 1; - /* Fatal error reporting enable. */ - pciercx_cfg075.s.fere = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port), - pciercx_cfg075.u32); - - /* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN], - * PCIERCn_CFG034[DLLS_EN,CCINT_EN]) - */ - pciercx_cfg034.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port)); - /* Hot-plug interrupt enable. */ - pciercx_cfg034.s.hpint_en = 1; - /* Data Link Layer state changed enable */ - pciercx_cfg034.s.dlls_en = 1; - /* Command completed interrupt enable. */ - pciercx_cfg034.s.ccint_en = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port), - pciercx_cfg034.u32); -} - -/** - * Initialize a host mode PCIe link. This function takes a PCIe - * port from reset to a link up state. Software can then begin - * configuring the rest of the link. - * - * @pcie_port: PCIe port to initialize - * - * Returns Zero on success - */ -static int __cvmx_pcie_rc_initialize_link(int pcie_port) -{ - uint64_t start_cycle; - union cvmx_pescx_ctl_status pescx_ctl_status; - union cvmx_pciercx_cfg452 pciercx_cfg452; - union cvmx_pciercx_cfg032 pciercx_cfg032; - union cvmx_pciercx_cfg448 pciercx_cfg448; - - /* Set the lane width */ - pciercx_cfg452.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port)); - pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); - if (pescx_ctl_status.s.qlm_cfg == 0) { - /* We're in 8 lane (56XX) or 4 lane (54XX) mode */ - pciercx_cfg452.s.lme = 0xf; - } else { - /* We're in 4 lane (56XX) or 2 lane (52XX) mode */ - pciercx_cfg452.s.lme = 0x7; - } - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port), - pciercx_cfg452.u32); - - /* - * CN52XX pass 1.x has an errata where length mismatches on UR - * responses can cause bus errors on 64bit memory - * reads. Turning off length error checking fixes this. - */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { - union cvmx_pciercx_cfg455 pciercx_cfg455; - pciercx_cfg455.u32 = - cvmx_pcie_cfgx_read(pcie_port, - CVMX_PCIERCX_CFG455(pcie_port)); - pciercx_cfg455.s.m_cpl_len_err = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port), - pciercx_cfg455.u32); - } - - /* Lane swap needs to be manually enabled for CN52XX */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) { - pescx_ctl_status.s.lane_swp = 1; - cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), - pescx_ctl_status.u64); - } - - /* Bring up the link */ - pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); - pescx_ctl_status.s.lnk_enb = 1; - cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64); - - /* - * CN52XX pass 1.0: Due to a bug in 2nd order CDR, it needs to - * be disabled. - */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) - __cvmx_helper_errata_qlm_disable_2nd_order_cdr(0); - - /* Wait for the link to come up */ - cvmx_dprintf("PCIe: Waiting for port %d link\n", pcie_port); - start_cycle = cvmx_get_cycle(); - do { - if (cvmx_get_cycle() - start_cycle > - 2 * cvmx_sysinfo_get()->cpu_clock_hz) { - cvmx_dprintf("PCIe: Port %d link timeout\n", - pcie_port); - return -1; - } - cvmx_wait(10000); - pciercx_cfg032.u32 = - cvmx_pcie_cfgx_read(pcie_port, - CVMX_PCIERCX_CFG032(pcie_port)); - } while (pciercx_cfg032.s.dlla == 0); - - /* Display the link status */ - cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, - pciercx_cfg032.s.nlw); - - /* - * Update the Replay Time Limit. Empirically, some PCIe - * devices take a little longer to respond than expected under - * load. As a workaround for this we configure the Replay Time - * Limit to the value expected for a 512 byte MPS instead of - * our actual 256 byte MPS. The numbers below are directly - * from the PCIe spec table 3-4. - */ - pciercx_cfg448.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); - switch (pciercx_cfg032.s.nlw) { - case 1: /* 1 lane */ - pciercx_cfg448.s.rtl = 1677; - break; - case 2: /* 2 lanes */ - pciercx_cfg448.s.rtl = 867; - break; - case 4: /* 4 lanes */ - pciercx_cfg448.s.rtl = 462; - break; - case 8: /* 8 lanes */ - pciercx_cfg448.s.rtl = 258; - break; - } - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), - pciercx_cfg448.u32); - - return 0; -} - -/** - * Initialize a PCIe port for use in host(RC) mode. It doesn't - * enumerate the bus. - * - * @pcie_port: PCIe port to initialize - * - * Returns Zero on success - */ -static int cvmx_pcie_rc_initialize(int pcie_port) -{ - int i; - union cvmx_ciu_soft_prst ciu_soft_prst; - union cvmx_pescx_bist_status pescx_bist_status; - union cvmx_pescx_bist_status2 pescx_bist_status2; - union cvmx_npei_ctl_status npei_ctl_status; - union cvmx_npei_mem_access_ctl npei_mem_access_ctl; - union cvmx_npei_mem_access_subidx mem_access_subid; - union cvmx_npei_dbg_data npei_dbg_data; - union cvmx_pescx_ctl_status2 pescx_ctl_status2; - - /* - * Make sure we aren't trying to setup a target mode interface - * in host mode. - */ - npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); - if ((pcie_port == 0) && !npei_ctl_status.s.host_mode) { - cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called " - "on port0, but port0 is not in host mode\n"); - return -1; - } - - /* - * Make sure a CN52XX isn't trying to bring up port 1 when it - * is disabled. - */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { - npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); - if ((pcie_port == 1) && npei_dbg_data.cn52xx.qlm0_link_width) { - cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() " - "called on port1, but port1 is " - "disabled\n"); - return -1; - } - } - - /* - * PCIe switch arbitration mode. '0' == fixed priority NPEI, - * PCIe0, then PCIe1. '1' == round robin. - */ - npei_ctl_status.s.arb = 1; - /* Allow up to 0x20 config retries */ - npei_ctl_status.s.cfg_rtry = 0x20; - /* - * CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS - * don't reset. - */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { - npei_ctl_status.s.p0_ntags = 0x20; - npei_ctl_status.s.p1_ntags = 0x20; - } - cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64); - - /* Bring the PCIe out of reset */ - if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) { - /* - * The EBH5200 board swapped the PCIe reset lines on - * the board. As a workaround for this bug, we bring - * both PCIe ports out of reset at the same time - * instead of on separate calls. So for port 0, we - * bring both out of reset and do nothing on port 1. - */ - if (pcie_port == 0) { - ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); - /* - * After a chip reset the PCIe will also be in - * reset. If it isn't, most likely someone is - * trying to init it again without a proper - * PCIe reset. - */ - if (ciu_soft_prst.s.soft_prst == 0) { - /* Reset the ports */ - ciu_soft_prst.s.soft_prst = 1; - cvmx_write_csr(CVMX_CIU_SOFT_PRST, - ciu_soft_prst.u64); - ciu_soft_prst.u64 = - cvmx_read_csr(CVMX_CIU_SOFT_PRST1); - ciu_soft_prst.s.soft_prst = 1; - cvmx_write_csr(CVMX_CIU_SOFT_PRST1, - ciu_soft_prst.u64); - /* Wait until pcie resets the ports. */ - udelay(2000); - } - ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); - ciu_soft_prst.s.soft_prst = 0; - cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); - ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); - ciu_soft_prst.s.soft_prst = 0; - cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); - } - } else { - /* - * The normal case: The PCIe ports are completely - * separate and can be brought out of reset - * independently. - */ - if (pcie_port) - ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); - else - ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); - /* - * After a chip reset the PCIe will also be in - * reset. If it isn't, most likely someone is trying - * to init it again without a proper PCIe reset. - */ - if (ciu_soft_prst.s.soft_prst == 0) { - /* Reset the port */ - ciu_soft_prst.s.soft_prst = 1; - if (pcie_port) - cvmx_write_csr(CVMX_CIU_SOFT_PRST1, - ciu_soft_prst.u64); - else - cvmx_write_csr(CVMX_CIU_SOFT_PRST, - ciu_soft_prst.u64); - /* Wait until pcie resets the ports. */ - udelay(2000); - } - if (pcie_port) { - ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); - ciu_soft_prst.s.soft_prst = 0; - cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); - } else { - ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); - ciu_soft_prst.s.soft_prst = 0; - cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); - } - } - - /* - * Wait for PCIe reset to complete. Due to errata PCIE-700, we - * don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a - * fixed number of cycles. - */ - cvmx_wait(400000); - - /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and - CN52XX, so we only probe it on newer chips */ - if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) - && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { - /* Clear PCLK_RUN so we can check if the clock is running */ - pescx_ctl_status2.u64 = - cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); - pescx_ctl_status2.s.pclk_run = 1; - cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), - pescx_ctl_status2.u64); - /* - * Now that we cleared PCLK_RUN, wait for it to be set - * again telling us the clock is running. - */ - if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port), - union cvmx_pescx_ctl_status2, - pclk_run, ==, 1, 10000)) { - cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", - pcie_port); - return -1; - } - } - - /* - * Check and make sure PCIe came out of reset. If it doesn't - * the board probably hasn't wired the clocks up and the - * interface should be skipped. - */ - pescx_ctl_status2.u64 = - cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); - if (pescx_ctl_status2.s.pcierst) { - cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", - pcie_port); - return -1; - } - - /* - * Check BIST2 status. If any bits are set skip this interface. This - * is an attempt to catch PCIE-813 on pass 1 parts. - */ - pescx_bist_status2.u64 = - cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port)); - if (pescx_bist_status2.u64) { - cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this " - "port isn't hooked up, skipping.\n", - pcie_port); - return -1; - } - - /* Check BIST status */ - pescx_bist_status.u64 = - cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port)); - if (pescx_bist_status.u64) - cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", - pcie_port, CAST64(pescx_bist_status.u64)); - - /* Initialize the config space CSRs */ - __cvmx_pcie_rc_initialize_config_space(pcie_port); - - /* Bring the link up */ - if (__cvmx_pcie_rc_initialize_link(pcie_port)) { - cvmx_dprintf - ("PCIe: ERROR: cvmx_pcie_rc_initialize_link() failed\n"); - return -1; - } - - /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ - npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL); - /* Allow 16 words to combine */ - npei_mem_access_ctl.s.max_word = 0; - /* Wait up to 127 cycles for more data */ - npei_mem_access_ctl.s.timer = 127; - cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64); - - /* Setup Mem access SubDIDs */ - mem_access_subid.u64 = 0; - /* Port the request is sent to. */ - mem_access_subid.s.port = pcie_port; - /* Due to an errata on pass 1 chips, no merging is allowed. */ - mem_access_subid.s.nmerge = 1; - /* Endian-swap for Reads. */ - mem_access_subid.s.esr = 1; - /* Endian-swap for Writes. */ - mem_access_subid.s.esw = 1; - /* No Snoop for Reads. */ - mem_access_subid.s.nsr = 1; - /* No Snoop for Writes. */ - mem_access_subid.s.nsw = 1; - /* Disable Relaxed Ordering for Reads. */ - mem_access_subid.s.ror = 0; - /* Disable Relaxed Ordering for Writes. */ - mem_access_subid.s.row = 0; - /* PCIe Adddress Bits <63:34>. */ - mem_access_subid.s.ba = 0; - - /* - * Setup mem access 12-15 for port 0, 16-19 for port 1, - * supplying 36 bits of address space. - */ - for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) { - cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), - mem_access_subid.u64); - /* Set each SUBID to extend the addressable range */ - mem_access_subid.s.ba += 1; - } - - /* - * Disable the peer to peer forwarding register. This must be - * setup by the OS after it enumerates the bus and assigns - * addresses to the PCIe busses. - */ - for (i = 0; i < 4; i++) { - cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1); - cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1); - } - - /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ - cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); - - /* - * Disable Octeon's BAR1. It isn't needed in RC mode since - * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into - * the 2nd 256MB of memory. - */ - cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1); - - /* - * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take - * precedence where they overlap. It also overlaps with the - * device addresses, so make sure the peer to peer forwarding - * is set right. - */ - cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0); - - /* - * Setup BAR2 attributes - * - * Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) - * - PTLP_RO,CTLP_RO should normally be set (except for debug). - * - WAIT_COM=0 will likely work for all applications. - * - * Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]). - */ - if (pcie_port) { - union cvmx_npei_ctl_port1 npei_ctl_port; - npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1); - npei_ctl_port.s.bar2_enb = 1; - npei_ctl_port.s.bar2_esx = 1; - npei_ctl_port.s.bar2_cax = 0; - npei_ctl_port.s.ptlp_ro = 1; - npei_ctl_port.s.ctlp_ro = 1; - npei_ctl_port.s.wait_com = 0; - npei_ctl_port.s.waitl_com = 0; - cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64); - } else { - union cvmx_npei_ctl_port0 npei_ctl_port; - npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0); - npei_ctl_port.s.bar2_enb = 1; - npei_ctl_port.s.bar2_esx = 1; - npei_ctl_port.s.bar2_cax = 0; - npei_ctl_port.s.ptlp_ro = 1; - npei_ctl_port.s.ctlp_ro = 1; - npei_ctl_port.s.wait_com = 0; - npei_ctl_port.s.waitl_com = 0; - cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64); - } - return 0; -} - - -/* Above was cvmx-pcie.c, below original pcie.c */ - - -/** - * Map a PCI device to the appropriate interrupt line - * - * @param dev The Linux PCI device structure for the device to map - * @param slot The slot number for this device on __BUS 0__. Linux - * enumerates through all the bridges and figures out the - * slot on Bus 0 where this device eventually hooks to. - * @param pin The PCI interrupt pin read from the device, then swizzled - * as it goes through each bridge. - * @return Interrupt number for the device - */ -int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, - u8 slot, u8 pin) -{ - /* - * The EBH5600 board with the PCI to PCIe bridge mistakenly - * wires the first slot for both device id 2 and interrupt - * A. According to the PCI spec, device id 2 should be C. The - * following kludge attempts to fix this. - */ - if (strstr(octeon_board_type_string(), "EBH5600") && - dev->bus && dev->bus->parent) { - /* - * Iterate all the way up the device chain and find - * the root bus. - */ - while (dev->bus && dev->bus->parent) - dev = to_pci_dev(dev->bus->bridge); - /* If the root bus is number 0 and the PEX 8114 is the - * root, assume we are behind the miswired bus. We - * need to correct the swizzle level by two. Yuck. - */ - if ((dev->bus->number == 0) && - (dev->vendor == 0x10b5) && (dev->device == 0x8114)) { - /* - * The pin field is one based, not zero. We - * need to swizzle it by minus two. - */ - pin = ((pin - 3) & 3) + 1; - } - } - /* - * The -1 is because pin starts with one, not zero. It might - * be that this equation needs to include the slot number, but - * I don't have hardware to check that against. - */ - return pin - 1 + OCTEON_IRQ_PCI_INT0; -} - -/** - * Read a value from configuration space - * - * @param bus - * @param devfn - * @param reg - * @param size - * @param val - * @return - */ -static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus, - unsigned int devfn, int reg, int size, - u32 *val) -{ - union octeon_cvmemctl cvmmemctl; - union octeon_cvmemctl cvmmemctl_save; - int bus_number = bus->number; - - /* - * We need to force the bus number to be zero on the root - * bus. Linux numbers the 2nd root bus to start after all - * buses on root 0. - */ - if (bus->parent == NULL) - bus_number = 0; - - /* - * PCIe only has a single device connected to Octeon. It is - * always device ID 0. Don't bother doing reads for other - * device IDs on the first segment. - */ - if ((bus_number == 0) && (devfn >> 3 != 0)) - return PCIBIOS_FUNC_NOT_SUPPORTED; - - /* - * The following is a workaround for the CN57XX, CN56XX, - * CN55XX, and CN54XX errata with PCIe config reads from non - * existent devices. These chips will hang the PCIe link if a - * config read is performed that causes a UR response. - */ - if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || - OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) { - /* - * For our EBH5600 board, port 0 has a bridge with two - * PCI-X slots. We need a new special checks to make - * sure we only probe valid stuff. The PCIe->PCI-X - * bridge only respondes to device ID 0, function - * 0-1 - */ - if ((bus_number == 0) && (devfn >= 2)) - return PCIBIOS_FUNC_NOT_SUPPORTED; - /* - * The PCI-X slots are device ID 2,3. Choose one of - * the below "if" blocks based on what is plugged into - * the board. - */ -#if 1 - /* Use this option if you aren't using either slot */ - if (bus_number == 1) - return PCIBIOS_FUNC_NOT_SUPPORTED; -#elif 0 - /* - * Use this option if you are using the first slot but - * not the second. - */ - if ((bus_number == 1) && (devfn >> 3 != 2)) - return PCIBIOS_FUNC_NOT_SUPPORTED; -#elif 0 - /* - * Use this option if you are using the second slot - * but not the first. - */ - if ((bus_number == 1) && (devfn >> 3 != 3)) - return PCIBIOS_FUNC_NOT_SUPPORTED; -#elif 0 - /* Use this opion if you are using both slots */ - if ((bus_number == 1) && - !((devfn == (2 << 3)) || (devfn == (3 << 3)))) - return PCIBIOS_FUNC_NOT_SUPPORTED; -#endif - - /* - * Shorten the DID timeout so bus errors for PCIe - * config reads from non existent devices happen - * faster. This allows us to continue booting even if - * the above "if" checks are wrong. Once one of these - * errors happens, the PCIe port is dead. - */ - cvmmemctl_save.u64 = __read_64bit_c0_register($11, 7); - cvmmemctl.u64 = cvmmemctl_save.u64; - cvmmemctl.s.didtto = 2; - __write_64bit_c0_register($11, 7, cvmmemctl.u64); - } - - switch (size) { - case 4: - *val = cvmx_pcie_config_read32(pcie_port, bus_number, - devfn >> 3, devfn & 0x7, reg); - break; - case 2: - *val = cvmx_pcie_config_read16(pcie_port, bus_number, - devfn >> 3, devfn & 0x7, reg); - break; - case 1: - *val = cvmx_pcie_config_read8(pcie_port, bus_number, devfn >> 3, - devfn & 0x7, reg); - break; - default: - return PCIBIOS_FUNC_NOT_SUPPORTED; - } - - if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || - OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) - __write_64bit_c0_register($11, 7, cvmmemctl_save.u64); - return PCIBIOS_SUCCESSFUL; -} - -static int octeon_pcie0_read_config(struct pci_bus *bus, unsigned int devfn, - int reg, int size, u32 *val) -{ - return octeon_pcie_read_config(0, bus, devfn, reg, size, val); -} - -static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn, - int reg, int size, u32 *val) -{ - return octeon_pcie_read_config(1, bus, devfn, reg, size, val); -} - - - -/** - * Write a value to PCI configuration space - * - * @param bus - * @param devfn - * @param reg - * @param size - * @param val - * @return - */ -static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus, - unsigned int devfn, int reg, - int size, u32 val) -{ - int bus_number = bus->number; - /* - * We need to force the bus number to be zero on the root - * bus. Linux numbers the 2nd root bus to start after all - * busses on root 0. - */ - if (bus->parent == NULL) - bus_number = 0; - - switch (size) { - case 4: - cvmx_pcie_config_write32(pcie_port, bus_number, devfn >> 3, - devfn & 0x7, reg, val); - return PCIBIOS_SUCCESSFUL; - case 2: - cvmx_pcie_config_write16(pcie_port, bus_number, devfn >> 3, - devfn & 0x7, reg, val); - return PCIBIOS_SUCCESSFUL; - case 1: - cvmx_pcie_config_write8(pcie_port, bus_number, devfn >> 3, - devfn & 0x7, reg, val); - return PCIBIOS_SUCCESSFUL; - } -#if PCI_CONFIG_SPACE_DELAY - udelay(PCI_CONFIG_SPACE_DELAY); -#endif - return PCIBIOS_FUNC_NOT_SUPPORTED; -} - -static int octeon_pcie0_write_config(struct pci_bus *bus, unsigned int devfn, - int reg, int size, u32 val) -{ - return octeon_pcie_write_config(0, bus, devfn, reg, size, val); -} - -static int octeon_pcie1_write_config(struct pci_bus *bus, unsigned int devfn, - int reg, int size, u32 val) -{ - return octeon_pcie_write_config(1, bus, devfn, reg, size, val); -} - -static struct pci_ops octeon_pcie0_ops = { - octeon_pcie0_read_config, - octeon_pcie0_write_config, -}; - -static struct resource octeon_pcie0_mem_resource = { - .name = "Octeon PCIe0 MEM", - .flags = IORESOURCE_MEM, -}; - -static struct resource octeon_pcie0_io_resource = { - .name = "Octeon PCIe0 IO", - .flags = IORESOURCE_IO, -}; - -static struct pci_controller octeon_pcie0_controller = { - .pci_ops = &octeon_pcie0_ops, - .mem_resource = &octeon_pcie0_mem_resource, - .io_resource = &octeon_pcie0_io_resource, -}; - -static struct pci_ops octeon_pcie1_ops = { - octeon_pcie1_read_config, - octeon_pcie1_write_config, -}; - -static struct resource octeon_pcie1_mem_resource = { - .name = "Octeon PCIe1 MEM", - .flags = IORESOURCE_MEM, -}; - -static struct resource octeon_pcie1_io_resource = { - .name = "Octeon PCIe1 IO", - .flags = IORESOURCE_IO, -}; - -static struct pci_controller octeon_pcie1_controller = { - .pci_ops = &octeon_pcie1_ops, - .mem_resource = &octeon_pcie1_mem_resource, - .io_resource = &octeon_pcie1_io_resource, -}; - - -/** - * Initialize the Octeon PCIe controllers - * - * @return - */ -static int __init octeon_pcie_setup(void) -{ - union cvmx_npei_ctl_status npei_ctl_status; - int result; - - /* These chips don't have PCIe */ - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) - return 0; - - /* Point pcibios_map_irq() to the PCIe version of it */ - octeon_pcibios_map_irq = octeon_pcie_pcibios_map_irq; - - /* Use the PCIe based DMA mappings */ - octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE; - - /* - * PCIe I/O range. It is based on port 0 but includes up until - * port 1's end. - */ - set_io_port_base(CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0))); - ioport_resource.start = 0; - ioport_resource.end = - cvmx_pcie_get_io_base_address(1) - - cvmx_pcie_get_io_base_address(0) + cvmx_pcie_get_io_size(1) - 1; - - npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); - if (npei_ctl_status.s.host_mode) { - pr_notice("PCIe: Initializing port 0\n"); - result = cvmx_pcie_rc_initialize(0); - if (result == 0) { - /* Memory offsets are physical addresses */ - octeon_pcie0_controller.mem_offset = - cvmx_pcie_get_mem_base_address(0); - /* IO offsets are Mips virtual addresses */ - octeon_pcie0_controller.io_map_base = - CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address - (0)); - octeon_pcie0_controller.io_offset = 0; - /* - * To keep things similar to PCI, we start - * device addresses at the same place as PCI - * uisng big bar support. This normally - * translates to 4GB-256MB, which is the same - * as most x86 PCs. - */ - octeon_pcie0_controller.mem_resource->start = - cvmx_pcie_get_mem_base_address(0) + - (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20); - octeon_pcie0_controller.mem_resource->end = - cvmx_pcie_get_mem_base_address(0) + - cvmx_pcie_get_mem_size(0) - 1; - /* - * Ports must be above 16KB for the ISA bus - * filtering in the PCI-X to PCI bridge. - */ - octeon_pcie0_controller.io_resource->start = 4 << 10; - octeon_pcie0_controller.io_resource->end = - cvmx_pcie_get_io_size(0) - 1; - register_pci_controller(&octeon_pcie0_controller); - } - } else { - pr_notice("PCIe: Port 0 in endpoint mode, skipping.\n"); - } - - /* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { - union cvmx_npei_dbg_data npei_dbg_data; - npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); - if (npei_dbg_data.cn52xx.qlm0_link_width) - return 0; - } - - pr_notice("PCIe: Initializing port 1\n"); - result = cvmx_pcie_rc_initialize(1); - if (result == 0) { - /* Memory offsets are physical addresses */ - octeon_pcie1_controller.mem_offset = - cvmx_pcie_get_mem_base_address(1); - /* IO offsets are Mips virtual addresses */ - octeon_pcie1_controller.io_map_base = - CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(1)); - octeon_pcie1_controller.io_offset = - cvmx_pcie_get_io_base_address(1) - - cvmx_pcie_get_io_base_address(0); - /* - * To keep things similar to PCI, we start device - * addresses at the same place as PCI uisng big bar - * support. This normally translates to 4GB-256MB, - * which is the same as most x86 PCs. - */ - octeon_pcie1_controller.mem_resource->start = - cvmx_pcie_get_mem_base_address(1) + (4ul << 30) - - (OCTEON_PCI_BAR1_HOLE_SIZE << 20); - octeon_pcie1_controller.mem_resource->end = - cvmx_pcie_get_mem_base_address(1) + - cvmx_pcie_get_mem_size(1) - 1; - /* - * Ports must be above 16KB for the ISA bus filtering - * in the PCI-X to PCI bridge. - */ - octeon_pcie1_controller.io_resource->start = - cvmx_pcie_get_io_base_address(1) - - cvmx_pcie_get_io_base_address(0); - octeon_pcie1_controller.io_resource->end = - octeon_pcie1_controller.io_resource->start + - cvmx_pcie_get_io_size(1) - 1; - register_pci_controller(&octeon_pcie1_controller); - } - return 0; -} - -arch_initcall(octeon_pcie_setup); diff --git a/arch/mips/include/asm/octeon/pci-octeon.h b/arch/mips/include/asm/octeon/pci-octeon.h new file mode 100644 index 00000000000..6ac5d3e3398 --- /dev/null +++ b/arch/mips/include/asm/octeon/pci-octeon.h @@ -0,0 +1,45 @@ +/* + * 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) 2005-2009 Cavium Networks + */ + +#ifndef __PCI_OCTEON_H__ +#define __PCI_OCTEON_H__ + +#include + +/* Some PCI cards require delays when accessing config space. */ +#define PCI_CONFIG_SPACE_DELAY 10000 + +/* + * pcibios_map_irq() is defined inside pci-octeon.c. All it does is + * call the Octeon specific version pointed to by this variable. This + * function needs to change for PCI or PCIe based hosts. + */ +extern int (*octeon_pcibios_map_irq)(const struct pci_dev *dev, + u8 slot, u8 pin); + +/* + * The following defines are used when octeon_dma_bar_type = + * OCTEON_DMA_BAR_TYPE_BIG + */ +#define OCTEON_PCI_BAR1_HOLE_BITS 5 +#define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3)) + +enum octeon_dma_bar_type { + OCTEON_DMA_BAR_TYPE_INVALID, + OCTEON_DMA_BAR_TYPE_SMALL, + OCTEON_DMA_BAR_TYPE_BIG, + OCTEON_DMA_BAR_TYPE_PCIE +}; + +/* + * This tells the DMA mapping system in dma-octeon.c how to map PCI + * DMA addresses. + */ +extern enum octeon_dma_bar_type octeon_dma_bar_type; + +#endif diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index e8a97f59e06..63d8a297c58 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -52,3 +52,8 @@ obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o +obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o + +ifdef CONFIG_PCI_MSI +obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o +endif diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c new file mode 100644 index 00000000000..03742e64765 --- /dev/null +++ b/arch/mips/pci/msi-octeon.c @@ -0,0 +1,288 @@ +/* + * 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) 2005-2009 Cavium Networks + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is + * in use. + */ +static uint64_t msi_free_irq_bitmask; + +/* + * Each bit in msi_multiple_irq_bitmask tells that the device using + * this bit in msi_free_irq_bitmask is also using the next bit. This + * is used so we can disable all of the MSI interrupts when a device + * uses multiple. + */ +static uint64_t msi_multiple_irq_bitmask; + +/* + * This lock controls updates to msi_free_irq_bitmask and + * msi_multiple_irq_bitmask. + */ +static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); + + +/** + * Called when a driver request MSI interrupts instead of the + * legacy INT A-D. This routine will allocate multiple interrupts + * for MSI devices that support them. A device can override this by + * programming the MSI control bits [6:4] before calling + * pci_enable_msi(). + * + * @dev: Device requesting MSI interrupts + * @desc: MSI descriptor + * + * Returns 0 on success. + */ +int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +{ + struct msi_msg msg; + uint16_t control; + int configured_private_bits; + int request_private_bits; + int irq; + int irq_step; + uint64_t search_mask; + + /* + * Read the MSI config to figure out how many IRQs this device + * wants. Most devices only want 1, which will give + * configured_private_bits and request_private_bits equal 0. + */ + pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, + &control); + + /* + * If the number of private bits has been configured then use + * that value instead of the requested number. This gives the + * driver the chance to override the number of interrupts + * before calling pci_enable_msi(). + */ + configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4; + if (configured_private_bits == 0) { + /* Nothing is configured, so use the hardware requested size */ + request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1; + } else { + /* + * Use the number of configured bits, assuming the + * driver wanted to override the hardware request + * value. + */ + request_private_bits = configured_private_bits; + } + + /* + * The PCI 2.3 spec mandates that there are at most 32 + * interrupts. If this device asks for more, only give it one. + */ + if (request_private_bits > 5) + request_private_bits = 0; + +try_only_one: + /* + * The IRQs have to be aligned on a power of two based on the + * number being requested. + */ + irq_step = 1 << request_private_bits; + + /* Mask with one bit for each IRQ */ + search_mask = (1 << irq_step) - 1; + + /* + * We're going to search msi_free_irq_bitmask_lock for zero + * bits. This represents an MSI interrupt number that isn't in + * use. + */ + spin_lock(&msi_free_irq_bitmask_lock); + for (irq = 0; irq < 64; irq += irq_step) { + if ((msi_free_irq_bitmask & (search_mask << irq)) == 0) { + msi_free_irq_bitmask |= search_mask << irq; + msi_multiple_irq_bitmask |= (search_mask >> 1) << irq; + break; + } + } + spin_unlock(&msi_free_irq_bitmask_lock); + + /* Make sure the search for available interrupts didn't fail */ + if (irq >= 64) { + if (request_private_bits) { + pr_err("arch_setup_msi_irq: Unable to find %d free " + "interrupts, trying just one", + 1 << request_private_bits); + request_private_bits = 0; + goto try_only_one; + } else + panic("arch_setup_msi_irq: Unable to find a free MSI " + "interrupt"); + } + + /* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */ + irq += OCTEON_IRQ_MSI_BIT0; + + switch (octeon_dma_bar_type) { + case OCTEON_DMA_BAR_TYPE_SMALL: + /* When not using big bar, Bar 0 is based at 128MB */ + msg.address_lo = + ((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff; + msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32; + case OCTEON_DMA_BAR_TYPE_BIG: + /* When using big bar, Bar 0 is based at 0 */ + msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff; + msg.address_hi = (0 + CVMX_PCI_MSI_RCV) >> 32; + break; + case OCTEON_DMA_BAR_TYPE_PCIE: + /* When using PCIe, Bar 0 is based at 0 */ + /* FIXME CVMX_NPEI_MSI_RCV* other than 0? */ + msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff; + msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32; + break; + default: + panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type\n"); + } + msg.data = irq - OCTEON_IRQ_MSI_BIT0; + + /* Update the number of IRQs the device has available to it */ + control &= ~PCI_MSI_FLAGS_QSIZE; + control |= request_private_bits << 4; + pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, + control); + + set_irq_msi(irq, desc); + write_msi_msg(irq, &msg); + return 0; +} + + +/** + * Called when a device no longer needs its MSI interrupts. All + * MSI interrupts for the device are freed. + * + * @irq: The devices first irq number. There may be multple in sequence. + */ +void arch_teardown_msi_irq(unsigned int irq) +{ + int number_irqs; + uint64_t bitmask; + + if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_BIT63)) + panic("arch_teardown_msi_irq: Attempted to teardown illegal " + "MSI interrupt (%d)", irq); + irq -= OCTEON_IRQ_MSI_BIT0; + + /* + * Count the number of IRQs we need to free by looking at the + * msi_multiple_irq_bitmask. Each bit set means that the next + * IRQ is also owned by this device. + */ + number_irqs = 0; + while ((irq+number_irqs < 64) && + (msi_multiple_irq_bitmask & (1ull << (irq + number_irqs)))) + number_irqs++; + number_irqs++; + /* Mask with one bit for each IRQ */ + bitmask = (1 << number_irqs) - 1; + /* Shift the mask to the correct bit location */ + bitmask <<= irq; + if ((msi_free_irq_bitmask & bitmask) != bitmask) + panic("arch_teardown_msi_irq: Attempted to teardown MSI " + "interrupt (%d) not in use", irq); + + /* Checks are done, update the in use bitmask */ + spin_lock(&msi_free_irq_bitmask_lock); + msi_free_irq_bitmask &= ~bitmask; + msi_multiple_irq_bitmask &= ~bitmask; + spin_unlock(&msi_free_irq_bitmask_lock); +} + + +/* + * Called by the interrupt handling code when an MSI interrupt + * occurs. + */ +static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) +{ + uint64_t msi_bits; + int irq; + + if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) + msi_bits = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_RCV0); + else + msi_bits = cvmx_read_csr(CVMX_NPI_NPI_MSI_RCV); + irq = fls64(msi_bits); + if (irq) { + irq += OCTEON_IRQ_MSI_BIT0 - 1; + if (irq_desc[irq].action) { + do_IRQ(irq); + return IRQ_HANDLED; + } else { + pr_err("Spurious MSI interrupt %d\n", irq); + if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { + /* These chips have PCIe */ + cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, + 1ull << (irq - + OCTEON_IRQ_MSI_BIT0)); + } else { + /* These chips have PCI */ + cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, + 1ull << (irq - + OCTEON_IRQ_MSI_BIT0)); + } + } + } + return IRQ_NONE; +} + + +/* + * Initializes the MSI interrupt handling code + */ +int octeon_msi_initialize(void) +{ + if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { + if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, + IRQF_SHARED, + "MSI[0:63]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); + } else if (octeon_is_pci_host()) { + if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, + IRQF_SHARED, + "MSI[0:15]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, + IRQF_SHARED, + "MSI[16:31]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, + IRQF_SHARED, + "MSI[32:47]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, + IRQF_SHARED, + "MSI[48:63]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed"); + + } + return 0; +} + +subsys_initcall(octeon_msi_initialize); diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c new file mode 100644 index 00000000000..9cb0c807f56 --- /dev/null +++ b/arch/mips/pci/pci-octeon.c @@ -0,0 +1,675 @@ +/* + * 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) 2005-2009 Cavium Networks + */ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define USE_OCTEON_INTERNAL_ARBITER + +/* + * Octeon's PCI controller uses did=3, subdid=2 for PCI IO + * addresses. Use PCI endian swapping 1 so no address swapping is + * necessary. The Linux io routines will endian swap the data. + */ +#define OCTEON_PCI_IOSPACE_BASE 0x80011a0400000000ull +#define OCTEON_PCI_IOSPACE_SIZE (1ull<<32) + +/* Octeon't PCI controller uses did=3, subdid=3 for PCI memory. */ +#define OCTEON_PCI_MEMSPACE_OFFSET (0x00011b0000000000ull) + +/** + * This is the bit decoding used for the Octeon PCI controller addresses + */ +union octeon_pci_address { + uint64_t u64; + struct { + uint64_t upper:2; + uint64_t reserved:13; + uint64_t io:1; + uint64_t did:5; + uint64_t subdid:3; + uint64_t reserved2:4; + uint64_t endian_swap:2; + uint64_t reserved3:10; + uint64_t bus:8; + uint64_t dev:5; + uint64_t func:3; + uint64_t reg:8; + } s; +}; + +int __initdata (*octeon_pcibios_map_irq)(const struct pci_dev *dev, + u8 slot, u8 pin); +enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID; + +/** + * Map a PCI device to the appropriate interrupt line + * + * @dev: The Linux PCI device structure for the device to map + * @slot: The slot number for this device on __BUS 0__. Linux + * enumerates through all the bridges and figures out the + * slot on Bus 0 where this device eventually hooks to. + * @pin: The PCI interrupt pin read from the device, then swizzled + * as it goes through each bridge. + * Returns Interrupt number for the device + */ +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + if (octeon_pcibios_map_irq) + return octeon_pcibios_map_irq(dev, slot, pin); + else + panic("octeon_pcibios_map_irq not set."); +} + + +/* + * Called to perform platform specific PCI setup + */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + uint16_t config; + uint32_t dconfig; + int pos; + /* + * Force the Cache line setting to 64 bytes. The standard + * Linux bus scan doesn't seem to set it. Octeon really has + * 128 byte lines, but Intel bridges get really upset if you + * try and set values above 64 bytes. Value is specified in + * 32bit words. + */ + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4); + /* Set latency timers for all devices */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48); + + /* Enable reporting System errors and parity errors on all devices */ + /* Enable parity checking and error reporting */ + pci_read_config_word(dev, PCI_COMMAND, &config); + config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; + pci_write_config_word(dev, PCI_COMMAND, config); + + if (dev->subordinate) { + /* Set latency timers on sub bridges */ + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48); + /* More bridge error detection */ + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config); + config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config); + } + + /* Enable the PCIe normal error reporting */ + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (pos) { + /* Update Device Control */ + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config); + /* Correctable Error Reporting */ + config |= PCI_EXP_DEVCTL_CERE; + /* Non-Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_NFERE; + /* Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_FERE; + /* Unsupported Request */ + config |= PCI_EXP_DEVCTL_URRE; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config); + } + + /* Find the Advanced Error Reporting capability */ + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + if (pos) { + /* Clear Uncorrectable Error Status */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, + &dconfig); + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, + dconfig); + /* Enable reporting of all uncorrectable errors */ + /* Uncorrectable Error Mask - turned on bits disable errors */ + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0); + /* + * Leave severity at HW default. This only controls if + * errors are reported as uncorrectable or + * correctable, not if the error is reported. + */ + /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */ + /* Clear Correctable Error Status */ + pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig); + pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig); + /* Enable reporting of all correctable errors */ + /* Correctable Error Mask - turned on bits disable errors */ + pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0); + /* Advanced Error Capabilities */ + pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig); + /* ECRC Generation Enable */ + if (config & PCI_ERR_CAP_ECRC_GENC) + config |= PCI_ERR_CAP_ECRC_GENE; + /* ECRC Check Enable */ + if (config & PCI_ERR_CAP_ECRC_CHKC) + config |= PCI_ERR_CAP_ECRC_CHKE; + pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig); + /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */ + /* Report all errors to the root complex */ + pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, + PCI_ERR_ROOT_CMD_COR_EN | + PCI_ERR_ROOT_CMD_NONFATAL_EN | + PCI_ERR_ROOT_CMD_FATAL_EN); + /* Clear the Root status register */ + pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig); + pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig); + } + + return 0; +} + +/** + * Return the mapping of PCI device number to IRQ line. Each + * character in the return string represents the interrupt + * line for the device at that position. Device 1 maps to the + * first character, etc. The characters A-D are used for PCI + * interrupts. + * + * Returns PCI interrupt mapping + */ +const char *octeon_get_pci_interrupts(void) +{ + /* + * Returning an empty string causes the interrupts to be + * routed based on the PCI specification. From the PCI spec: + * + * INTA# of Device Number 0 is connected to IRQW on the system + * board. (Device Number has no significance regarding being + * located on the system board or in a connector.) INTA# of + * Device Number 1 is connected to IRQX on the system + * board. INTA# of Device Number 2 is connected to IRQY on the + * system board. INTA# of Device Number 3 is connected to IRQZ + * on the system board. The table below describes how each + * agent's INTx# lines are connected to the system board + * interrupt lines. The following equation can be used to + * determine to which INTx# signal on the system board a given + * device's INTx# line(s) is connected. + * + * MB = (D + I) MOD 4 MB = System board Interrupt (IRQW = 0, + * IRQX = 1, IRQY = 2, and IRQZ = 3) D = Device Number I = + * Interrupt Number (INTA# = 0, INTB# = 1, INTC# = 2, and + * INTD# = 3) + */ + switch (octeon_bootinfo->board_type) { + case CVMX_BOARD_TYPE_NAO38: + /* This is really the NAC38 */ + return "AAAAADABAAAAAAAAAAAAAAAAAAAAAAAA"; + case CVMX_BOARD_TYPE_THUNDER: + return ""; + case CVMX_BOARD_TYPE_EBH3000: + return ""; + case CVMX_BOARD_TYPE_EBH3100: + case CVMX_BOARD_TYPE_CN3010_EVB_HS5: + case CVMX_BOARD_TYPE_CN3005_EVB_HS5: + return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + case CVMX_BOARD_TYPE_BBGW_REF: + return "AABCD"; + default: + return ""; + } +} + +/** + * Map a PCI device to the appropriate interrupt line + * + * @dev: The Linux PCI device structure for the device to map + * @slot: The slot number for this device on __BUS 0__. Linux + * enumerates through all the bridges and figures out the + * slot on Bus 0 where this device eventually hooks to. + * @pin: The PCI interrupt pin read from the device, then swizzled + * as it goes through each bridge. + * Returns Interrupt number for the device + */ +int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev, + u8 slot, u8 pin) +{ + int irq_num; + const char *interrupts; + int dev_num; + + /* Get the board specific interrupt mapping */ + interrupts = octeon_get_pci_interrupts(); + + dev_num = dev->devfn >> 3; + if (dev_num < strlen(interrupts)) + irq_num = ((interrupts[dev_num] - 'A' + pin - 1) & 3) + + OCTEON_IRQ_PCI_INT0; + else + irq_num = ((slot + pin - 3) & 3) + OCTEON_IRQ_PCI_INT0; + return irq_num; +} + + +/* + * Read a value from configuration space + */ +static int octeon_read_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 *val) +{ + union octeon_pci_address pci_addr; + + pci_addr.u64 = 0; + pci_addr.s.upper = 2; + pci_addr.s.io = 1; + pci_addr.s.did = 3; + pci_addr.s.subdid = 1; + pci_addr.s.endian_swap = 1; + pci_addr.s.bus = bus->number; + pci_addr.s.dev = devfn >> 3; + pci_addr.s.func = devfn & 0x7; + pci_addr.s.reg = reg; + +#if PCI_CONFIG_SPACE_DELAY + udelay(PCI_CONFIG_SPACE_DELAY); +#endif + switch (size) { + case 4: + *val = le32_to_cpu(cvmx_read64_uint32(pci_addr.u64)); + return PCIBIOS_SUCCESSFUL; + case 2: + *val = le16_to_cpu(cvmx_read64_uint16(pci_addr.u64)); + return PCIBIOS_SUCCESSFUL; + case 1: + *val = cvmx_read64_uint8(pci_addr.u64); + return PCIBIOS_SUCCESSFUL; + } + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + + +/* + * Write a value to PCI configuration space + */ +static int octeon_write_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 val) +{ + union octeon_pci_address pci_addr; + + pci_addr.u64 = 0; + pci_addr.s.upper = 2; + pci_addr.s.io = 1; + pci_addr.s.did = 3; + pci_addr.s.subdid = 1; + pci_addr.s.endian_swap = 1; + pci_addr.s.bus = bus->number; + pci_addr.s.dev = devfn >> 3; + pci_addr.s.func = devfn & 0x7; + pci_addr.s.reg = reg; + +#if PCI_CONFIG_SPACE_DELAY + udelay(PCI_CONFIG_SPACE_DELAY); +#endif + switch (size) { + case 4: + cvmx_write64_uint32(pci_addr.u64, cpu_to_le32(val)); + return PCIBIOS_SUCCESSFUL; + case 2: + cvmx_write64_uint16(pci_addr.u64, cpu_to_le16(val)); + return PCIBIOS_SUCCESSFUL; + case 1: + cvmx_write64_uint8(pci_addr.u64, val); + return PCIBIOS_SUCCESSFUL; + } + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + + +static struct pci_ops octeon_pci_ops = { + octeon_read_config, + octeon_write_config, +}; + +static struct resource octeon_pci_mem_resource = { + .start = 0, + .end = 0, + .name = "Octeon PCI MEM", + .flags = IORESOURCE_MEM, +}; + +/* + * PCI ports must be above 16KB so the ISA bus filtering in the PCI-X to PCI + * bridge + */ +static struct resource octeon_pci_io_resource = { + .start = 0x4000, + .end = OCTEON_PCI_IOSPACE_SIZE - 1, + .name = "Octeon PCI IO", + .flags = IORESOURCE_IO, +}; + +static struct pci_controller octeon_pci_controller = { + .pci_ops = &octeon_pci_ops, + .mem_resource = &octeon_pci_mem_resource, + .mem_offset = OCTEON_PCI_MEMSPACE_OFFSET, + .io_resource = &octeon_pci_io_resource, + .io_offset = 0, + .io_map_base = OCTEON_PCI_IOSPACE_BASE, +}; + + +/* + * Low level initialize the Octeon PCI controller + */ +static void octeon_pci_initialize(void) +{ + union cvmx_pci_cfg01 cfg01; + union cvmx_npi_ctl_status ctl_status; + union cvmx_pci_ctl_status_2 ctl_status_2; + union cvmx_pci_cfg19 cfg19; + union cvmx_pci_cfg16 cfg16; + union cvmx_pci_cfg22 cfg22; + union cvmx_pci_cfg56 cfg56; + + /* Reset the PCI Bus */ + cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1); + cvmx_read_csr(CVMX_CIU_SOFT_PRST); + + udelay(2000); /* Hold PCI reset for 2 ms */ + + ctl_status.u64 = 0; /* cvmx_read_csr(CVMX_NPI_CTL_STATUS); */ + ctl_status.s.max_word = 1; + ctl_status.s.timer = 1; + cvmx_write_csr(CVMX_NPI_CTL_STATUS, ctl_status.u64); + + /* Deassert PCI reset and advertize PCX Host Mode Device Capability + (64b) */ + cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4); + cvmx_read_csr(CVMX_CIU_SOFT_PRST); + + udelay(2000); /* Wait 2 ms after deasserting PCI reset */ + + ctl_status_2.u32 = 0; + ctl_status_2.s.tsr_hwm = 1; /* Initializes to 0. Must be set + before any PCI reads. */ + ctl_status_2.s.bar2pres = 1; /* Enable BAR2 */ + ctl_status_2.s.bar2_enb = 1; + ctl_status_2.s.bar2_cax = 1; /* Don't use L2 */ + ctl_status_2.s.bar2_esx = 1; + ctl_status_2.s.pmo_amod = 1; /* Round robin priority */ + if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) { + /* BAR1 hole */ + ctl_status_2.s.bb1_hole = OCTEON_PCI_BAR1_HOLE_BITS; + ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */ + ctl_status_2.s.bb_ca = 1; /* Don't use L2 with big bars */ + ctl_status_2.s.bb_es = 1; /* Big bar in byte swap mode */ + ctl_status_2.s.bb1 = 1; /* BAR1 is big */ + ctl_status_2.s.bb0 = 1; /* BAR0 is big */ + } + + octeon_npi_write32(CVMX_NPI_PCI_CTL_STATUS_2, ctl_status_2.u32); + udelay(2000); /* Wait 2 ms before doing PCI reads */ + + ctl_status_2.u32 = octeon_npi_read32(CVMX_NPI_PCI_CTL_STATUS_2); + pr_notice("PCI Status: %s %s-bit\n", + ctl_status_2.s.ap_pcix ? "PCI-X" : "PCI", + ctl_status_2.s.ap_64ad ? "64" : "32"); + + if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) { + union cvmx_pci_cnt_reg cnt_reg_start; + union cvmx_pci_cnt_reg cnt_reg_end; + unsigned long cycles, pci_clock; + + cnt_reg_start.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG); + cycles = read_c0_cvmcount(); + udelay(1000); + cnt_reg_end.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG); + cycles = read_c0_cvmcount() - cycles; + pci_clock = (cnt_reg_end.s.pcicnt - cnt_reg_start.s.pcicnt) / + (cycles / (mips_hpt_frequency / 1000000)); + pr_notice("PCI Clock: %lu MHz\n", pci_clock); + } + + /* + * TDOMC must be set to one in PCI mode. TDOMC should be set to 4 + * in PCI-X mode to allow four oustanding splits. Otherwise, + * should not change from its reset value. Don't write PCI_CFG19 + * in PCI mode (0x82000001 reset value), write it to 0x82000004 + * after PCI-X mode is known. MRBCI,MDWE,MDRE -> must be zero. + * MRBCM -> must be one. + */ + if (ctl_status_2.s.ap_pcix) { + cfg19.u32 = 0; + /* + * Target Delayed/Split request outstanding maximum + * count. [1..31] and 0=32. NOTE: If the user + * programs these bits beyond the Designed Maximum + * outstanding count, then the designed maximum table + * depth will be used instead. No additional + * Deferred/Split transactions will be accepted if + * this outstanding maximum count is + * reached. Furthermore, no additional deferred/split + * transactions will be accepted if the I/O delay/ I/O + * Split Request outstanding maximum is reached. + */ + cfg19.s.tdomc = 4; + /* + * Master Deferred Read Request Outstanding Max Count + * (PCI only). CR4C[26:24] Max SAC cycles MAX DAC + * cycles 000 8 4 001 1 0 010 2 1 011 3 1 100 4 2 101 + * 5 2 110 6 3 111 7 3 For example, if these bits are + * programmed to 100, the core can support 2 DAC + * cycles, 4 SAC cycles or a combination of 1 DAC and + * 2 SAC cycles. NOTE: For the PCI-X maximum + * outstanding split transactions, refer to + * CRE0[22:20]. + */ + cfg19.s.mdrrmc = 2; + /* + * Master Request (Memory Read) Byte Count/Byte Enable + * select. 0 = Byte Enables valid. In PCI mode, a + * burst transaction cannot be performed using Memory + * Read command=4?h6. 1 = DWORD Byte Count valid + * (default). In PCI Mode, the memory read byte + * enables are automatically generated by the + * core. Note: N3 Master Request transaction sizes are + * always determined through the + * am_attr[<35:32>|<7:0>] field. + */ + cfg19.s.mrbcm = 1; + octeon_npi_write32(CVMX_NPI_PCI_CFG19, cfg19.u32); + } + + + cfg01.u32 = 0; + cfg01.s.msae = 1; /* Memory Space Access Enable */ + cfg01.s.me = 1; /* Master Enable */ + cfg01.s.pee = 1; /* PERR# Enable */ + cfg01.s.see = 1; /* System Error Enable */ + cfg01.s.fbbe = 1; /* Fast Back to Back Transaction Enable */ + + octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); + +#ifdef USE_OCTEON_INTERNAL_ARBITER + /* + * When OCTEON is a PCI host, most systems will use OCTEON's + * internal arbiter, so must enable it before any PCI/PCI-X + * traffic can occur. + */ + { + union cvmx_npi_pci_int_arb_cfg pci_int_arb_cfg; + + pci_int_arb_cfg.u64 = 0; + pci_int_arb_cfg.s.en = 1; /* Internal arbiter enable */ + cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64); + } +#endif /* USE_OCTEON_INTERNAL_ARBITER */ + + /* + * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE, + * TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to + * 1..7. + */ + cfg16.u32 = 0; + cfg16.s.mltd = 1; /* Master Latency Timer Disable */ + octeon_npi_write32(CVMX_NPI_PCI_CFG16, cfg16.u32); + + /* + * Should be written to 0x4ff00. MTTV -> must be zero. + * FLUSH -> must be 1. MRV -> should be 0xFF. + */ + cfg22.u32 = 0; + /* Master Retry Value [1..255] and 0=infinite */ + cfg22.s.mrv = 0xff; + /* + * AM_DO_FLUSH_I control NOTE: This bit MUST BE ONE for proper + * N3K operation. + */ + cfg22.s.flush = 1; + octeon_npi_write32(CVMX_NPI_PCI_CFG22, cfg22.u32); + + /* + * MOST Indicates the maximum number of outstanding splits (in -1 + * notation) when OCTEON is in PCI-X mode. PCI-X performance is + * affected by the MOST selection. Should generally be written + * with one of 0x3be807, 0x2be807, 0x1be807, or 0x0be807, + * depending on the desired MOST of 3, 2, 1, or 0, respectively. + */ + cfg56.u32 = 0; + cfg56.s.pxcid = 7; /* RO - PCI-X Capability ID */ + cfg56.s.ncp = 0xe8; /* RO - Next Capability Pointer */ + cfg56.s.dpere = 1; /* Data Parity Error Recovery Enable */ + cfg56.s.roe = 1; /* Relaxed Ordering Enable */ + cfg56.s.mmbc = 1; /* Maximum Memory Byte Count + [0=512B,1=1024B,2=2048B,3=4096B] */ + cfg56.s.most = 3; /* Maximum outstanding Split transactions [0=1 + .. 7=32] */ + + octeon_npi_write32(CVMX_NPI_PCI_CFG56, cfg56.u32); + + /* + * Affects PCI performance when OCTEON services reads to its + * BAR1/BAR2. Refer to Section 10.6.1. The recommended values are + * 0x22, 0x33, and 0x33 for PCI_READ_CMD_6, PCI_READ_CMD_C, and + * PCI_READ_CMD_E, respectively. Unfortunately due to errata DDR-700, + * these values need to be changed so they won't possibly prefetch off + * of the end of memory if PCI is DMAing a buffer at the end of + * memory. Note that these values differ from their reset values. + */ + octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_6, 0x21); + octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_C, 0x31); + octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_E, 0x31); +} + + +/* + * Initialize the Octeon PCI controller + */ +static int __init octeon_pci_setup(void) +{ + union cvmx_npi_mem_access_subidx mem_access; + int index; + + /* Only these chips have PCI */ + if (octeon_has_feature(OCTEON_FEATURE_PCIE)) + return 0; + + /* Point pcibios_map_irq() to the PCI version of it */ + octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq; + + /* Only use the big bars on chips that support it */ + if (OCTEON_IS_MODEL(OCTEON_CN31XX) || + OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) || + OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)) + octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_SMALL; + else + octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG; + + /* PCI I/O and PCI MEM values */ + set_io_port_base(OCTEON_PCI_IOSPACE_BASE); + ioport_resource.start = 0; + ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1; + if (!octeon_is_pci_host()) { + pr_notice("Not in host mode, PCI Controller not initialized\n"); + return 0; + } + + pr_notice("%s Octeon big bar support\n", + (octeon_dma_bar_type == + OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling"); + + octeon_pci_initialize(); + + mem_access.u64 = 0; + mem_access.s.esr = 1; /* Endian-Swap on read. */ + mem_access.s.esw = 1; /* Endian-Swap on write. */ + mem_access.s.nsr = 0; /* No-Snoop on read. */ + mem_access.s.nsw = 0; /* No-Snoop on write. */ + mem_access.s.ror = 0; /* Relax Read on read. */ + mem_access.s.row = 0; /* Relax Order on write. */ + mem_access.s.ba = 0; /* PCI Address bits [63:36]. */ + cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, mem_access.u64); + + /* + * Remap the Octeon BAR 2 above all 32 bit devices + * (0x8000000000ul). This is done here so it is remapped + * before the readl()'s below. We don't want BAR2 overlapping + * with BAR0/BAR1 during these reads. + */ + octeon_npi_write32(CVMX_NPI_PCI_CFG08, 0); + octeon_npi_write32(CVMX_NPI_PCI_CFG09, 0x80); + + /* Disable the BAR1 movable mappings */ + for (index = 0; index < 32; index++) + octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0); + + if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) { + /* Remap the Octeon BAR 0 to 0-2GB */ + octeon_npi_write32(CVMX_NPI_PCI_CFG04, 0); + octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0); + + /* + * Remap the Octeon BAR 1 to map 2GB-4GB (minus the + * BAR 1 hole). + */ + octeon_npi_write32(CVMX_NPI_PCI_CFG06, 2ul << 30); + octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0); + + /* Devices go after BAR1 */ + octeon_pci_mem_resource.start = + OCTEON_PCI_MEMSPACE_OFFSET + (4ul << 30) - + (OCTEON_PCI_BAR1_HOLE_SIZE << 20); + octeon_pci_mem_resource.end = + octeon_pci_mem_resource.start + (1ul << 30); + } else { + /* Remap the Octeon BAR 0 to map 128MB-(128MB+4KB) */ + octeon_npi_write32(CVMX_NPI_PCI_CFG04, 128ul << 20); + octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0); + + /* Remap the Octeon BAR 1 to map 0-128MB */ + octeon_npi_write32(CVMX_NPI_PCI_CFG06, 0); + octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0); + + /* Devices go after BAR0 */ + octeon_pci_mem_resource.start = + OCTEON_PCI_MEMSPACE_OFFSET + (128ul << 20) + + (4ul << 10); + octeon_pci_mem_resource.end = + octeon_pci_mem_resource.start + (1ul << 30); + } + + register_pci_controller(&octeon_pci_controller); + + /* + * Clear any errors that might be pending from before the bus + * was setup properly. + */ + cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1); + return 0; +} + +arch_initcall(octeon_pci_setup); diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c new file mode 100644 index 00000000000..75262247f3e --- /dev/null +++ b/arch/mips/pci/pcie-octeon.c @@ -0,0 +1,1369 @@ +/* + * 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) 2007, 2008 Cavium Networks + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +union cvmx_pcie_address { + uint64_t u64; + struct { + uint64_t upper:2; /* Normally 2 for XKPHYS */ + uint64_t reserved_49_61:13; /* Must be zero */ + uint64_t io:1; /* 1 for IO space access */ + uint64_t did:5; /* PCIe DID = 3 */ + uint64_t subdid:3; /* PCIe SubDID = 1 */ + uint64_t reserved_36_39:4; /* Must be zero */ + uint64_t es:2; /* Endian swap = 1 */ + uint64_t port:2; /* PCIe port 0,1 */ + uint64_t reserved_29_31:3; /* Must be zero */ + /* + * Selects the type of the configuration request (0 = type 0, + * 1 = type 1). + */ + uint64_t ty:1; + /* Target bus number sent in the ID in the request. */ + uint64_t bus:8; + /* + * Target device number sent in the ID in the + * request. Note that Dev must be zero for type 0 + * configuration requests. + */ + uint64_t dev:5; + /* Target function number sent in the ID in the request. */ + uint64_t func:3; + /* + * Selects a register in the configuration space of + * the target. + */ + uint64_t reg:12; + } config; + struct { + uint64_t upper:2; /* Normally 2 for XKPHYS */ + uint64_t reserved_49_61:13; /* Must be zero */ + uint64_t io:1; /* 1 for IO space access */ + uint64_t did:5; /* PCIe DID = 3 */ + uint64_t subdid:3; /* PCIe SubDID = 2 */ + uint64_t reserved_36_39:4; /* Must be zero */ + uint64_t es:2; /* Endian swap = 1 */ + uint64_t port:2; /* PCIe port 0,1 */ + uint64_t address:32; /* PCIe IO address */ + } io; + struct { + uint64_t upper:2; /* Normally 2 for XKPHYS */ + uint64_t reserved_49_61:13; /* Must be zero */ + uint64_t io:1; /* 1 for IO space access */ + uint64_t did:5; /* PCIe DID = 3 */ + uint64_t subdid:3; /* PCIe SubDID = 3-6 */ + uint64_t reserved_36_39:4; /* Must be zero */ + uint64_t address:36; /* PCIe Mem address */ + } mem; +}; + +/** + * Return the Core virtual base address for PCIe IO access. IOs are + * read/written as an offset from this address. + * + * @pcie_port: PCIe port the IO is for + * + * Returns 64bit Octeon IO base address for read/write + */ +static inline uint64_t cvmx_pcie_get_io_base_address(int pcie_port) +{ + union cvmx_pcie_address pcie_addr; + pcie_addr.u64 = 0; + pcie_addr.io.upper = 0; + pcie_addr.io.io = 1; + pcie_addr.io.did = 3; + pcie_addr.io.subdid = 2; + pcie_addr.io.es = 1; + pcie_addr.io.port = pcie_port; + return pcie_addr.u64; +} + +/** + * Size of the IO address region returned at address + * cvmx_pcie_get_io_base_address() + * + * @pcie_port: PCIe port the IO is for + * + * Returns Size of the IO window + */ +static inline uint64_t cvmx_pcie_get_io_size(int pcie_port) +{ + return 1ull << 32; +} + +/** + * Return the Core virtual base address for PCIe MEM access. Memory is + * read/written as an offset from this address. + * + * @pcie_port: PCIe port the IO is for + * + * Returns 64bit Octeon IO base address for read/write + */ +static inline uint64_t cvmx_pcie_get_mem_base_address(int pcie_port) +{ + union cvmx_pcie_address pcie_addr; + pcie_addr.u64 = 0; + pcie_addr.mem.upper = 0; + pcie_addr.mem.io = 1; + pcie_addr.mem.did = 3; + pcie_addr.mem.subdid = 3 + pcie_port; + return pcie_addr.u64; +} + +/** + * Size of the Mem address region returned at address + * cvmx_pcie_get_mem_base_address() + * + * @pcie_port: PCIe port the IO is for + * + * Returns Size of the Mem window + */ +static inline uint64_t cvmx_pcie_get_mem_size(int pcie_port) +{ + return 1ull << 36; +} + +/** + * Read a PCIe config space register indirectly. This is used for + * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. + * + * @pcie_port: PCIe port to read from + * @cfg_offset: Address to read + * + * Returns Value read + */ +static uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) +{ + union cvmx_pescx_cfg_rd pescx_cfg_rd; + pescx_cfg_rd.u64 = 0; + pescx_cfg_rd.s.addr = cfg_offset; + cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64); + pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port)); + return pescx_cfg_rd.s.data; +} + +/** + * Write a PCIe config space register indirectly. This is used for + * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. + * + * @pcie_port: PCIe port to write to + * @cfg_offset: Address to write + * @val: Value to write + */ +static void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, + uint32_t val) +{ + union cvmx_pescx_cfg_wr pescx_cfg_wr; + pescx_cfg_wr.u64 = 0; + pescx_cfg_wr.s.addr = cfg_offset; + pescx_cfg_wr.s.data = val; + cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64); +} + +/** + * Build a PCIe config space request address for a device + * + * @pcie_port: PCIe port to access + * @bus: Sub bus + * @dev: Device ID + * @fn: Device sub function + * @reg: Register to access + * + * Returns 64bit Octeon IO address + */ +static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus, + int dev, int fn, int reg) +{ + union cvmx_pcie_address pcie_addr; + union cvmx_pciercx_cfg006 pciercx_cfg006; + + pciercx_cfg006.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port)); + if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0)) + return 0; + + pcie_addr.u64 = 0; + pcie_addr.config.upper = 2; + pcie_addr.config.io = 1; + pcie_addr.config.did = 3; + pcie_addr.config.subdid = 1; + pcie_addr.config.es = 1; + pcie_addr.config.port = pcie_port; + pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum); + pcie_addr.config.bus = bus; + pcie_addr.config.dev = dev; + pcie_addr.config.func = fn; + pcie_addr.config.reg = reg; + return pcie_addr.u64; +} + +/** + * Read 8bits from a Device's config space + * + * @pcie_port: PCIe port the device is on + * @bus: Sub bus + * @dev: Device ID + * @fn: Device sub function + * @reg: Register to access + * + * Returns Result of the read + */ +static uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, + int fn, int reg) +{ + uint64_t address = + __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); + if (address) + return cvmx_read64_uint8(address); + else + return 0xff; +} + +/** + * Read 16bits from a Device's config space + * + * @pcie_port: PCIe port the device is on + * @bus: Sub bus + * @dev: Device ID + * @fn: Device sub function + * @reg: Register to access + * + * Returns Result of the read + */ +static uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, + int fn, int reg) +{ + uint64_t address = + __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); + if (address) + return le16_to_cpu(cvmx_read64_uint16(address)); + else + return 0xffff; +} + +/** + * Read 32bits from a Device's config space + * + * @pcie_port: PCIe port the device is on + * @bus: Sub bus + * @dev: Device ID + * @fn: Device sub function + * @reg: Register to access + * + * Returns Result of the read + */ +static uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, + int fn, int reg) +{ + uint64_t address = + __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); + if (address) + return le32_to_cpu(cvmx_read64_uint32(address)); + else + return 0xffffffff; +} + +/** + * Write 8bits to a Device's config space + * + * @pcie_port: PCIe port the device is on + * @bus: Sub bus + * @dev: Device ID + * @fn: Device sub function + * @reg: Register to access + * @val: Value to write + */ +static void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, + int reg, uint8_t val) +{ + uint64_t address = + __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); + if (address) + cvmx_write64_uint8(address, val); +} + +/** + * Write 16bits to a Device's config space + * + * @pcie_port: PCIe port the device is on + * @bus: Sub bus + * @dev: Device ID + * @fn: Device sub function + * @reg: Register to access + * @val: Value to write + */ +static void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, + int reg, uint16_t val) +{ + uint64_t address = + __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); + if (address) + cvmx_write64_uint16(address, cpu_to_le16(val)); +} + +/** + * Write 32bits to a Device's config space + * + * @pcie_port: PCIe port the device is on + * @bus: Sub bus + * @dev: Device ID + * @fn: Device sub function + * @reg: Register to access + * @val: Value to write + */ +static void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, + int reg, uint32_t val) +{ + uint64_t address = + __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); + if (address) + cvmx_write64_uint32(address, cpu_to_le32(val)); +} + +/** + * Initialize the RC config space CSRs + * + * @pcie_port: PCIe port to initialize + */ +static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) +{ + union cvmx_pciercx_cfg030 pciercx_cfg030; + union cvmx_npei_ctl_status2 npei_ctl_status2; + union cvmx_pciercx_cfg070 pciercx_cfg070; + union cvmx_pciercx_cfg001 pciercx_cfg001; + union cvmx_pciercx_cfg032 pciercx_cfg032; + union cvmx_pciercx_cfg006 pciercx_cfg006; + union cvmx_pciercx_cfg008 pciercx_cfg008; + union cvmx_pciercx_cfg009 pciercx_cfg009; + union cvmx_pciercx_cfg010 pciercx_cfg010; + union cvmx_pciercx_cfg011 pciercx_cfg011; + union cvmx_pciercx_cfg035 pciercx_cfg035; + union cvmx_pciercx_cfg075 pciercx_cfg075; + union cvmx_pciercx_cfg034 pciercx_cfg034; + + /* Max Payload Size (PCIE*_CFG030[MPS]) */ + /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ + /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ + /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ + pciercx_cfg030.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); + /* + * Max payload size = 128 bytes for best Octeon DMA + * performance. + */ + pciercx_cfg030.s.mps = 0; + /* + * Max read request size = 128 bytes for best Octeon DMA + * performance. + */ + pciercx_cfg030.s.mrrs = 0; + /* Enable relaxed ordering. */ + pciercx_cfg030.s.ro_en = 1; + /* Enable no snoop. */ + pciercx_cfg030.s.ns_en = 1; + /* Correctable error reporting enable. */ + pciercx_cfg030.s.ce_en = 1; + /* Non-fatal error reporting enable. */ + pciercx_cfg030.s.nfe_en = 1; + /* Fatal error reporting enable. */ + pciercx_cfg030.s.fe_en = 1; + /* Unsupported request reporting enable. */ + pciercx_cfg030.s.ur_en = 1; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), + pciercx_cfg030.u32); + + /* + * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match + * PCIE*_CFG030[MPS] + * + * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not + * exceed PCIE*_CFG030[MRRS]. + */ + npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); + /* Max payload size = 128 bytes for best Octeon DMA performance */ + npei_ctl_status2.s.mps = 0; + /* Max read request size = 128 bytes for best Octeon DMA performance */ + npei_ctl_status2.s.mrrs = 0; + cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); + + /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ + pciercx_cfg070.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port)); + pciercx_cfg070.s.ge = 1; /* ECRC generation enable. */ + pciercx_cfg070.s.ce = 1; /* ECRC check enable. */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port), + pciercx_cfg070.u32); + + /* + * Access Enables (PCIE*_CFG001[MSAE,ME]) ME and MSAE should + * always be set. + * + * Interrupt Disable (PCIE*_CFG001[I_DIS]) System Error + * Message Enable (PCIE*_CFG001[SEE]) + */ + pciercx_cfg001.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port)); + pciercx_cfg001.s.msae = 1; /* Memory space enable. */ + pciercx_cfg001.s.me = 1; /* Bus master enable. */ + pciercx_cfg001.s.i_dis = 1; /* INTx assertion disable. */ + pciercx_cfg001.s.see = 1; /* SERR# enable */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port), + pciercx_cfg001.u32); + + /* Advanced Error Recovery Message Enables */ + /* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG066(pcie_port), 0); + /* Use CVMX_PCIERCX_CFG067 hardware default */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0); + + /* Active State Power Management (PCIE*_CFG032[ASLPC]) */ + pciercx_cfg032.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port), + pciercx_cfg032.u32); + + /* Entrance Latencies (PCIE*_CFG451[L0EL,L1EL]) */ + + /* + * Link Width Mode (PCIERCn_CFG452[LME]) - Set during + * cvmx_pcie_rc_initialize_link() + * + * Primary Bus Number (PCIERCn_CFG006[PBNUM]) + * + * We set the primary bus number to 1 so IDT bridges are + * happy. They don't like zero. + */ + pciercx_cfg006.u32 = 0; + pciercx_cfg006.s.pbnum = 1; + pciercx_cfg006.s.sbnum = 1; + pciercx_cfg006.s.subbnum = 1; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port), + pciercx_cfg006.u32); + + /* + * Memory-mapped I/O BAR (PCIERCn_CFG008) + * Most applications should disable the memory-mapped I/O BAR by + * setting PCIERCn_CFG008[ML_ADDR] < PCIERCn_CFG008[MB_ADDR] + */ + pciercx_cfg008.u32 = 0; + pciercx_cfg008.s.mb_addr = 0x100; + pciercx_cfg008.s.ml_addr = 0; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port), + pciercx_cfg008.u32); + + /* + * Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011) + * Most applications should disable the prefetchable BAR by setting + * PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] < + * PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE] + */ + pciercx_cfg009.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port)); + pciercx_cfg010.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port)); + pciercx_cfg011.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port)); + pciercx_cfg009.s.lmem_base = 0x100; + pciercx_cfg009.s.lmem_limit = 0; + pciercx_cfg010.s.umem_base = 0x100; + pciercx_cfg011.s.umem_limit = 0; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port), + pciercx_cfg009.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port), + pciercx_cfg010.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port), + pciercx_cfg011.u32); + + /* + * System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE]) + * PME Interrupt Enables (PCIERCn_CFG035[PMEIE]) + */ + pciercx_cfg035.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port)); + /* System error on correctable error enable. */ + pciercx_cfg035.s.secee = 1; + /* System error on fatal error enable. */ + pciercx_cfg035.s.sefee = 1; + /* System error on non-fatal error enable. */ + pciercx_cfg035.s.senfee = 1; + /* PME interrupt enable. */ + pciercx_cfg035.s.pmeie = 1; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port), + pciercx_cfg035.u32); + + /* + * Advanced Error Recovery Interrupt Enables + * (PCIERCn_CFG075[CERE,NFERE,FERE]) + */ + pciercx_cfg075.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port)); + /* Correctable error reporting enable. */ + pciercx_cfg075.s.cere = 1; + /* Non-fatal error reporting enable. */ + pciercx_cfg075.s.nfere = 1; + /* Fatal error reporting enable. */ + pciercx_cfg075.s.fere = 1; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port), + pciercx_cfg075.u32); + + /* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN], + * PCIERCn_CFG034[DLLS_EN,CCINT_EN]) + */ + pciercx_cfg034.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port)); + /* Hot-plug interrupt enable. */ + pciercx_cfg034.s.hpint_en = 1; + /* Data Link Layer state changed enable */ + pciercx_cfg034.s.dlls_en = 1; + /* Command completed interrupt enable. */ + pciercx_cfg034.s.ccint_en = 1; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port), + pciercx_cfg034.u32); +} + +/** + * Initialize a host mode PCIe link. This function takes a PCIe + * port from reset to a link up state. Software can then begin + * configuring the rest of the link. + * + * @pcie_port: PCIe port to initialize + * + * Returns Zero on success + */ +static int __cvmx_pcie_rc_initialize_link(int pcie_port) +{ + uint64_t start_cycle; + union cvmx_pescx_ctl_status pescx_ctl_status; + union cvmx_pciercx_cfg452 pciercx_cfg452; + union cvmx_pciercx_cfg032 pciercx_cfg032; + union cvmx_pciercx_cfg448 pciercx_cfg448; + + /* Set the lane width */ + pciercx_cfg452.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port)); + pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); + if (pescx_ctl_status.s.qlm_cfg == 0) { + /* We're in 8 lane (56XX) or 4 lane (54XX) mode */ + pciercx_cfg452.s.lme = 0xf; + } else { + /* We're in 4 lane (56XX) or 2 lane (52XX) mode */ + pciercx_cfg452.s.lme = 0x7; + } + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port), + pciercx_cfg452.u32); + + /* + * CN52XX pass 1.x has an errata where length mismatches on UR + * responses can cause bus errors on 64bit memory + * reads. Turning off length error checking fixes this. + */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { + union cvmx_pciercx_cfg455 pciercx_cfg455; + pciercx_cfg455.u32 = + cvmx_pcie_cfgx_read(pcie_port, + CVMX_PCIERCX_CFG455(pcie_port)); + pciercx_cfg455.s.m_cpl_len_err = 1; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port), + pciercx_cfg455.u32); + } + + /* Lane swap needs to be manually enabled for CN52XX */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) { + pescx_ctl_status.s.lane_swp = 1; + cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), + pescx_ctl_status.u64); + } + + /* Bring up the link */ + pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); + pescx_ctl_status.s.lnk_enb = 1; + cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64); + + /* + * CN52XX pass 1.0: Due to a bug in 2nd order CDR, it needs to + * be disabled. + */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) + __cvmx_helper_errata_qlm_disable_2nd_order_cdr(0); + + /* Wait for the link to come up */ + cvmx_dprintf("PCIe: Waiting for port %d link\n", pcie_port); + start_cycle = cvmx_get_cycle(); + do { + if (cvmx_get_cycle() - start_cycle > + 2 * cvmx_sysinfo_get()->cpu_clock_hz) { + cvmx_dprintf("PCIe: Port %d link timeout\n", + pcie_port); + return -1; + } + cvmx_wait(10000); + pciercx_cfg032.u32 = + cvmx_pcie_cfgx_read(pcie_port, + CVMX_PCIERCX_CFG032(pcie_port)); + } while (pciercx_cfg032.s.dlla == 0); + + /* Display the link status */ + cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, + pciercx_cfg032.s.nlw); + + /* + * Update the Replay Time Limit. Empirically, some PCIe + * devices take a little longer to respond than expected under + * load. As a workaround for this we configure the Replay Time + * Limit to the value expected for a 512 byte MPS instead of + * our actual 256 byte MPS. The numbers below are directly + * from the PCIe spec table 3-4. + */ + pciercx_cfg448.u32 = + cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); + switch (pciercx_cfg032.s.nlw) { + case 1: /* 1 lane */ + pciercx_cfg448.s.rtl = 1677; + break; + case 2: /* 2 lanes */ + pciercx_cfg448.s.rtl = 867; + break; + case 4: /* 4 lanes */ + pciercx_cfg448.s.rtl = 462; + break; + case 8: /* 8 lanes */ + pciercx_cfg448.s.rtl = 258; + break; + } + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), + pciercx_cfg448.u32); + + return 0; +} + +/** + * Initialize a PCIe port for use in host(RC) mode. It doesn't + * enumerate the bus. + * + * @pcie_port: PCIe port to initialize + * + * Returns Zero on success + */ +static int cvmx_pcie_rc_initialize(int pcie_port) +{ + int i; + union cvmx_ciu_soft_prst ciu_soft_prst; + union cvmx_pescx_bist_status pescx_bist_status; + union cvmx_pescx_bist_status2 pescx_bist_status2; + union cvmx_npei_ctl_status npei_ctl_status; + union cvmx_npei_mem_access_ctl npei_mem_access_ctl; + union cvmx_npei_mem_access_subidx mem_access_subid; + union cvmx_npei_dbg_data npei_dbg_data; + union cvmx_pescx_ctl_status2 pescx_ctl_status2; + + /* + * Make sure we aren't trying to setup a target mode interface + * in host mode. + */ + npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); + if ((pcie_port == 0) && !npei_ctl_status.s.host_mode) { + cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called " + "on port0, but port0 is not in host mode\n"); + return -1; + } + + /* + * Make sure a CN52XX isn't trying to bring up port 1 when it + * is disabled. + */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { + npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); + if ((pcie_port == 1) && npei_dbg_data.cn52xx.qlm0_link_width) { + cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() " + "called on port1, but port1 is " + "disabled\n"); + return -1; + } + } + + /* + * PCIe switch arbitration mode. '0' == fixed priority NPEI, + * PCIe0, then PCIe1. '1' == round robin. + */ + npei_ctl_status.s.arb = 1; + /* Allow up to 0x20 config retries */ + npei_ctl_status.s.cfg_rtry = 0x20; + /* + * CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS + * don't reset. + */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { + npei_ctl_status.s.p0_ntags = 0x20; + npei_ctl_status.s.p1_ntags = 0x20; + } + cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64); + + /* Bring the PCIe out of reset */ + if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) { + /* + * The EBH5200 board swapped the PCIe reset lines on + * the board. As a workaround for this bug, we bring + * both PCIe ports out of reset at the same time + * instead of on separate calls. So for port 0, we + * bring both out of reset and do nothing on port 1. + */ + if (pcie_port == 0) { + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); + /* + * After a chip reset the PCIe will also be in + * reset. If it isn't, most likely someone is + * trying to init it again without a proper + * PCIe reset. + */ + if (ciu_soft_prst.s.soft_prst == 0) { + /* Reset the ports */ + ciu_soft_prst.s.soft_prst = 1; + cvmx_write_csr(CVMX_CIU_SOFT_PRST, + ciu_soft_prst.u64); + ciu_soft_prst.u64 = + cvmx_read_csr(CVMX_CIU_SOFT_PRST1); + ciu_soft_prst.s.soft_prst = 1; + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, + ciu_soft_prst.u64); + /* Wait until pcie resets the ports. */ + udelay(2000); + } + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); + ciu_soft_prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); + ciu_soft_prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); + } + } else { + /* + * The normal case: The PCIe ports are completely + * separate and can be brought out of reset + * independently. + */ + if (pcie_port) + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); + else + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); + /* + * After a chip reset the PCIe will also be in + * reset. If it isn't, most likely someone is trying + * to init it again without a proper PCIe reset. + */ + if (ciu_soft_prst.s.soft_prst == 0) { + /* Reset the port */ + ciu_soft_prst.s.soft_prst = 1; + if (pcie_port) + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, + ciu_soft_prst.u64); + else + cvmx_write_csr(CVMX_CIU_SOFT_PRST, + ciu_soft_prst.u64); + /* Wait until pcie resets the ports. */ + udelay(2000); + } + if (pcie_port) { + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); + ciu_soft_prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); + } else { + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); + ciu_soft_prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); + } + } + + /* + * Wait for PCIe reset to complete. Due to errata PCIE-700, we + * don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a + * fixed number of cycles. + */ + cvmx_wait(400000); + + /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and + CN52XX, so we only probe it on newer chips */ + if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) + && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { + /* Clear PCLK_RUN so we can check if the clock is running */ + pescx_ctl_status2.u64 = + cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); + pescx_ctl_status2.s.pclk_run = 1; + cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), + pescx_ctl_status2.u64); + /* + * Now that we cleared PCLK_RUN, wait for it to be set + * again telling us the clock is running. + */ + if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port), + union cvmx_pescx_ctl_status2, + pclk_run, ==, 1, 10000)) { + cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", + pcie_port); + return -1; + } + } + + /* + * Check and make sure PCIe came out of reset. If it doesn't + * the board probably hasn't wired the clocks up and the + * interface should be skipped. + */ + pescx_ctl_status2.u64 = + cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); + if (pescx_ctl_status2.s.pcierst) { + cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", + pcie_port); + return -1; + } + + /* + * Check BIST2 status. If any bits are set skip this interface. This + * is an attempt to catch PCIE-813 on pass 1 parts. + */ + pescx_bist_status2.u64 = + cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port)); + if (pescx_bist_status2.u64) { + cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this " + "port isn't hooked up, skipping.\n", + pcie_port); + return -1; + } + + /* Check BIST status */ + pescx_bist_status.u64 = + cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port)); + if (pescx_bist_status.u64) + cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", + pcie_port, CAST64(pescx_bist_status.u64)); + + /* Initialize the config space CSRs */ + __cvmx_pcie_rc_initialize_config_space(pcie_port); + + /* Bring the link up */ + if (__cvmx_pcie_rc_initialize_link(pcie_port)) { + cvmx_dprintf + ("PCIe: ERROR: cvmx_pcie_rc_initialize_link() failed\n"); + return -1; + } + + /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ + npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL); + /* Allow 16 words to combine */ + npei_mem_access_ctl.s.max_word = 0; + /* Wait up to 127 cycles for more data */ + npei_mem_access_ctl.s.timer = 127; + cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64); + + /* Setup Mem access SubDIDs */ + mem_access_subid.u64 = 0; + /* Port the request is sent to. */ + mem_access_subid.s.port = pcie_port; + /* Due to an errata on pass 1 chips, no merging is allowed. */ + mem_access_subid.s.nmerge = 1; + /* Endian-swap for Reads. */ + mem_access_subid.s.esr = 1; + /* Endian-swap for Writes. */ + mem_access_subid.s.esw = 1; + /* No Snoop for Reads. */ + mem_access_subid.s.nsr = 1; + /* No Snoop for Writes. */ + mem_access_subid.s.nsw = 1; + /* Disable Relaxed Ordering for Reads. */ + mem_access_subid.s.ror = 0; + /* Disable Relaxed Ordering for Writes. */ + mem_access_subid.s.row = 0; + /* PCIe Adddress Bits <63:34>. */ + mem_access_subid.s.ba = 0; + + /* + * Setup mem access 12-15 for port 0, 16-19 for port 1, + * supplying 36 bits of address space. + */ + for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) { + cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), + mem_access_subid.u64); + /* Set each SUBID to extend the addressable range */ + mem_access_subid.s.ba += 1; + } + + /* + * Disable the peer to peer forwarding register. This must be + * setup by the OS after it enumerates the bus and assigns + * addresses to the PCIe busses. + */ + for (i = 0; i < 4; i++) { + cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1); + cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1); + } + + /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ + cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); + + /* + * Disable Octeon's BAR1. It isn't needed in RC mode since + * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into + * the 2nd 256MB of memory. + */ + cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1); + + /* + * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take + * precedence where they overlap. It also overlaps with the + * device addresses, so make sure the peer to peer forwarding + * is set right. + */ + cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0); + + /* + * Setup BAR2 attributes + * + * Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) + * - PTLP_RO,CTLP_RO should normally be set (except for debug). + * - WAIT_COM=0 will likely work for all applications. + * + * Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]). + */ + if (pcie_port) { + union cvmx_npei_ctl_port1 npei_ctl_port; + npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1); + npei_ctl_port.s.bar2_enb = 1; + npei_ctl_port.s.bar2_esx = 1; + npei_ctl_port.s.bar2_cax = 0; + npei_ctl_port.s.ptlp_ro = 1; + npei_ctl_port.s.ctlp_ro = 1; + npei_ctl_port.s.wait_com = 0; + npei_ctl_port.s.waitl_com = 0; + cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64); + } else { + union cvmx_npei_ctl_port0 npei_ctl_port; + npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0); + npei_ctl_port.s.bar2_enb = 1; + npei_ctl_port.s.bar2_esx = 1; + npei_ctl_port.s.bar2_cax = 0; + npei_ctl_port.s.ptlp_ro = 1; + npei_ctl_port.s.ctlp_ro = 1; + npei_ctl_port.s.wait_com = 0; + npei_ctl_port.s.waitl_com = 0; + cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64); + } + return 0; +} + + +/* Above was cvmx-pcie.c, below original pcie.c */ + + +/** + * Map a PCI device to the appropriate interrupt line + * + * @dev: The Linux PCI device structure for the device to map + * @slot: The slot number for this device on __BUS 0__. Linux + * enumerates through all the bridges and figures out the + * slot on Bus 0 where this device eventually hooks to. + * @pin: The PCI interrupt pin read from the device, then swizzled + * as it goes through each bridge. + * Returns Interrupt number for the device + */ +int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, + u8 slot, u8 pin) +{ + /* + * The EBH5600 board with the PCI to PCIe bridge mistakenly + * wires the first slot for both device id 2 and interrupt + * A. According to the PCI spec, device id 2 should be C. The + * following kludge attempts to fix this. + */ + if (strstr(octeon_board_type_string(), "EBH5600") && + dev->bus && dev->bus->parent) { + /* + * Iterate all the way up the device chain and find + * the root bus. + */ + while (dev->bus && dev->bus->parent) + dev = to_pci_dev(dev->bus->bridge); + /* If the root bus is number 0 and the PEX 8114 is the + * root, assume we are behind the miswired bus. We + * need to correct the swizzle level by two. Yuck. + */ + if ((dev->bus->number == 0) && + (dev->vendor == 0x10b5) && (dev->device == 0x8114)) { + /* + * The pin field is one based, not zero. We + * need to swizzle it by minus two. + */ + pin = ((pin - 3) & 3) + 1; + } + } + /* + * The -1 is because pin starts with one, not zero. It might + * be that this equation needs to include the slot number, but + * I don't have hardware to check that against. + */ + return pin - 1 + OCTEON_IRQ_PCI_INT0; +} + +/** + * Read a value from configuration space + * + * @bus: + * @devfn: + * @reg: + * @size: + * @val: + * Returns + */ +static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus, + unsigned int devfn, int reg, int size, + u32 *val) +{ + union octeon_cvmemctl cvmmemctl; + union octeon_cvmemctl cvmmemctl_save; + int bus_number = bus->number; + + /* + * We need to force the bus number to be zero on the root + * bus. Linux numbers the 2nd root bus to start after all + * buses on root 0. + */ + if (bus->parent == NULL) + bus_number = 0; + + /* + * PCIe only has a single device connected to Octeon. It is + * always device ID 0. Don't bother doing reads for other + * device IDs on the first segment. + */ + if ((bus_number == 0) && (devfn >> 3 != 0)) + return PCIBIOS_FUNC_NOT_SUPPORTED; + + /* + * The following is a workaround for the CN57XX, CN56XX, + * CN55XX, and CN54XX errata with PCIe config reads from non + * existent devices. These chips will hang the PCIe link if a + * config read is performed that causes a UR response. + */ + if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || + OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) { + /* + * For our EBH5600 board, port 0 has a bridge with two + * PCI-X slots. We need a new special checks to make + * sure we only probe valid stuff. The PCIe->PCI-X + * bridge only respondes to device ID 0, function + * 0-1 + */ + if ((bus_number == 0) && (devfn >= 2)) + return PCIBIOS_FUNC_NOT_SUPPORTED; + /* + * The PCI-X slots are device ID 2,3. Choose one of + * the below "if" blocks based on what is plugged into + * the board. + */ +#if 1 + /* Use this option if you aren't using either slot */ + if (bus_number == 1) + return PCIBIOS_FUNC_NOT_SUPPORTED; +#elif 0 + /* + * Use this option if you are using the first slot but + * not the second. + */ + if ((bus_number == 1) && (devfn >> 3 != 2)) + return PCIBIOS_FUNC_NOT_SUPPORTED; +#elif 0 + /* + * Use this option if you are using the second slot + * but not the first. + */ + if ((bus_number == 1) && (devfn >> 3 != 3)) + return PCIBIOS_FUNC_NOT_SUPPORTED; +#elif 0 + /* Use this opion if you are using both slots */ + if ((bus_number == 1) && + !((devfn == (2 << 3)) || (devfn == (3 << 3)))) + return PCIBIOS_FUNC_NOT_SUPPORTED; +#endif + + /* + * Shorten the DID timeout so bus errors for PCIe + * config reads from non existent devices happen + * faster. This allows us to continue booting even if + * the above "if" checks are wrong. Once one of these + * errors happens, the PCIe port is dead. + */ + cvmmemctl_save.u64 = __read_64bit_c0_register($11, 7); + cvmmemctl.u64 = cvmmemctl_save.u64; + cvmmemctl.s.didtto = 2; + __write_64bit_c0_register($11, 7, cvmmemctl.u64); + } + + switch (size) { + case 4: + *val = cvmx_pcie_config_read32(pcie_port, bus_number, + devfn >> 3, devfn & 0x7, reg); + break; + case 2: + *val = cvmx_pcie_config_read16(pcie_port, bus_number, + devfn >> 3, devfn & 0x7, reg); + break; + case 1: + *val = cvmx_pcie_config_read8(pcie_port, bus_number, devfn >> 3, + devfn & 0x7, reg); + break; + default: + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || + OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) + __write_64bit_c0_register($11, 7, cvmmemctl_save.u64); + return PCIBIOS_SUCCESSFUL; +} + +static int octeon_pcie0_read_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 *val) +{ + return octeon_pcie_read_config(0, bus, devfn, reg, size, val); +} + +static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 *val) +{ + return octeon_pcie_read_config(1, bus, devfn, reg, size, val); +} + + + +/** + * Write a value to PCI configuration space + * + * @bus: + * @devfn: + * @reg: + * @size: + * @val: + * Returns + */ +static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus, + unsigned int devfn, int reg, + int size, u32 val) +{ + int bus_number = bus->number; + /* + * We need to force the bus number to be zero on the root + * bus. Linux numbers the 2nd root bus to start after all + * busses on root 0. + */ + if (bus->parent == NULL) + bus_number = 0; + + switch (size) { + case 4: + cvmx_pcie_config_write32(pcie_port, bus_number, devfn >> 3, + devfn & 0x7, reg, val); + return PCIBIOS_SUCCESSFUL; + case 2: + cvmx_pcie_config_write16(pcie_port, bus_number, devfn >> 3, + devfn & 0x7, reg, val); + return PCIBIOS_SUCCESSFUL; + case 1: + cvmx_pcie_config_write8(pcie_port, bus_number, devfn >> 3, + devfn & 0x7, reg, val); + return PCIBIOS_SUCCESSFUL; + } +#if PCI_CONFIG_SPACE_DELAY + udelay(PCI_CONFIG_SPACE_DELAY); +#endif + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int octeon_pcie0_write_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 val) +{ + return octeon_pcie_write_config(0, bus, devfn, reg, size, val); +} + +static int octeon_pcie1_write_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 val) +{ + return octeon_pcie_write_config(1, bus, devfn, reg, size, val); +} + +static struct pci_ops octeon_pcie0_ops = { + octeon_pcie0_read_config, + octeon_pcie0_write_config, +}; + +static struct resource octeon_pcie0_mem_resource = { + .name = "Octeon PCIe0 MEM", + .flags = IORESOURCE_MEM, +}; + +static struct resource octeon_pcie0_io_resource = { + .name = "Octeon PCIe0 IO", + .flags = IORESOURCE_IO, +}; + +static struct pci_controller octeon_pcie0_controller = { + .pci_ops = &octeon_pcie0_ops, + .mem_resource = &octeon_pcie0_mem_resource, + .io_resource = &octeon_pcie0_io_resource, +}; + +static struct pci_ops octeon_pcie1_ops = { + octeon_pcie1_read_config, + octeon_pcie1_write_config, +}; + +static struct resource octeon_pcie1_mem_resource = { + .name = "Octeon PCIe1 MEM", + .flags = IORESOURCE_MEM, +}; + +static struct resource octeon_pcie1_io_resource = { + .name = "Octeon PCIe1 IO", + .flags = IORESOURCE_IO, +}; + +static struct pci_controller octeon_pcie1_controller = { + .pci_ops = &octeon_pcie1_ops, + .mem_resource = &octeon_pcie1_mem_resource, + .io_resource = &octeon_pcie1_io_resource, +}; + + +/** + * Initialize the Octeon PCIe controllers + * + * Returns + */ +static int __init octeon_pcie_setup(void) +{ + union cvmx_npei_ctl_status npei_ctl_status; + int result; + + /* These chips don't have PCIe */ + if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) + return 0; + + /* Point pcibios_map_irq() to the PCIe version of it */ + octeon_pcibios_map_irq = octeon_pcie_pcibios_map_irq; + + /* Use the PCIe based DMA mappings */ + octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE; + + /* + * PCIe I/O range. It is based on port 0 but includes up until + * port 1's end. + */ + set_io_port_base(CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0))); + ioport_resource.start = 0; + ioport_resource.end = + cvmx_pcie_get_io_base_address(1) - + cvmx_pcie_get_io_base_address(0) + cvmx_pcie_get_io_size(1) - 1; + + npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); + if (npei_ctl_status.s.host_mode) { + pr_notice("PCIe: Initializing port 0\n"); + result = cvmx_pcie_rc_initialize(0); + if (result == 0) { + /* Memory offsets are physical addresses */ + octeon_pcie0_controller.mem_offset = + cvmx_pcie_get_mem_base_address(0); + /* IO offsets are Mips virtual addresses */ + octeon_pcie0_controller.io_map_base = + CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address + (0)); + octeon_pcie0_controller.io_offset = 0; + /* + * To keep things similar to PCI, we start + * device addresses at the same place as PCI + * uisng big bar support. This normally + * translates to 4GB-256MB, which is the same + * as most x86 PCs. + */ + octeon_pcie0_controller.mem_resource->start = + cvmx_pcie_get_mem_base_address(0) + + (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20); + octeon_pcie0_controller.mem_resource->end = + cvmx_pcie_get_mem_base_address(0) + + cvmx_pcie_get_mem_size(0) - 1; + /* + * Ports must be above 16KB for the ISA bus + * filtering in the PCI-X to PCI bridge. + */ + octeon_pcie0_controller.io_resource->start = 4 << 10; + octeon_pcie0_controller.io_resource->end = + cvmx_pcie_get_io_size(0) - 1; + register_pci_controller(&octeon_pcie0_controller); + } + } else { + pr_notice("PCIe: Port 0 in endpoint mode, skipping.\n"); + } + + /* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { + union cvmx_npei_dbg_data npei_dbg_data; + npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); + if (npei_dbg_data.cn52xx.qlm0_link_width) + return 0; + } + + pr_notice("PCIe: Initializing port 1\n"); + result = cvmx_pcie_rc_initialize(1); + if (result == 0) { + /* Memory offsets are physical addresses */ + octeon_pcie1_controller.mem_offset = + cvmx_pcie_get_mem_base_address(1); + /* IO offsets are Mips virtual addresses */ + octeon_pcie1_controller.io_map_base = + CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(1)); + octeon_pcie1_controller.io_offset = + cvmx_pcie_get_io_base_address(1) - + cvmx_pcie_get_io_base_address(0); + /* + * To keep things similar to PCI, we start device + * addresses at the same place as PCI uisng big bar + * support. This normally translates to 4GB-256MB, + * which is the same as most x86 PCs. + */ + octeon_pcie1_controller.mem_resource->start = + cvmx_pcie_get_mem_base_address(1) + (4ul << 30) - + (OCTEON_PCI_BAR1_HOLE_SIZE << 20); + octeon_pcie1_controller.mem_resource->end = + cvmx_pcie_get_mem_base_address(1) + + cvmx_pcie_get_mem_size(1) - 1; + /* + * Ports must be above 16KB for the ISA bus filtering + * in the PCI-X to PCI bridge. + */ + octeon_pcie1_controller.io_resource->start = + cvmx_pcie_get_io_base_address(1) - + cvmx_pcie_get_io_base_address(0); + octeon_pcie1_controller.io_resource->end = + octeon_pcie1_controller.io_resource->start + + cvmx_pcie_get_io_size(1) - 1; + register_pci_controller(&octeon_pcie1_controller); + } + return 0; +} + +arch_initcall(octeon_pcie_setup); -- cgit v1.2.3 From baf922780251d12bc1c24c83df60c4c278abb745 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 3 Jul 2009 07:11:15 +0100 Subject: MIPS: Fix CONFIG_FLATMEM version of pfn_valid() For systems which do not define PHYS_OFFSET as 0 pfn_valid() may falsely have returned 0 on most configurations. Bug introduced by commit 752fbeb2e3555c0d236e992f1195fd7ce30e728d (linux-mips.org) rsp. 6f284a2ce7b8bc49cb8455b1763357897a899abb (kernel.org) titled "[MIPS] FLATMEM: introduce PHYS_OFFSET." Signed-off-by: Ralf Baechle --- arch/mips/include/asm/page.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index dc0eaa73128..96a14a426a7 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -165,7 +165,14 @@ typedef struct { unsigned long pgprot; } pgprot_t; #ifdef CONFIG_FLATMEM -#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr) +#define pfn_valid(pfn) \ +({ \ + unsigned long __pfn = (pfn); \ + /* avoid include hell */ \ + extern unsigned long min_low_pfn; \ + \ + __pfn >= min_low_pfn && __pfn < max_mapnr; \ +}) #elif defined(CONFIG_SPARSEMEM) -- cgit v1.2.3