diff options
Diffstat (limited to 'arch/mips/bcm63xx')
-rw-r--r-- | arch/mips/bcm63xx/Kconfig | 4 | ||||
-rw-r--r-- | arch/mips/bcm63xx/boards/board_bcm963xx.c | 46 | ||||
-rw-r--r-- | arch/mips/bcm63xx/clk.c | 70 | ||||
-rw-r--r-- | arch/mips/bcm63xx/cpu.c | 261 | ||||
-rw-r--r-- | arch/mips/bcm63xx/dev-uart.c | 2 | ||||
-rw-r--r-- | arch/mips/bcm63xx/gpio.c | 41 | ||||
-rw-r--r-- | arch/mips/bcm63xx/irq.c | 403 | ||||
-rw-r--r-- | arch/mips/bcm63xx/prom.c | 7 | ||||
-rw-r--r-- | arch/mips/bcm63xx/setup.c | 32 |
9 files changed, 582 insertions, 284 deletions
diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index fb177d6df066..6b1b9ad8d857 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -20,6 +20,10 @@ config BCM63XX_CPU_6348 config BCM63XX_CPU_6358 bool "support 6358 CPU" select HW_HAS_PCI + +config BCM63XX_CPU_6368 + bool "support 6368 CPU" + select HW_HAS_PCI endmenu source "arch/mips/bcm63xx/boards/Kconfig" diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index c22385400fc9..2f1773f3fb7a 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -709,15 +709,9 @@ void __init board_prom_init(void) char cfe_version[32]; u32 val; - /* read base address of boot chip select (0) - * 6345 does not have MPI but boots from standard - * MIPS Flash address */ - if (BCMCPU_IS_6345()) - val = 0x1fc00000; - else { - val = bcm_mpi_readl(MPI_CSBASE_REG(0)); - val &= MPI_CSBASE_BASE_MASK; - } + /* read base address of boot chip select (0) */ + val = bcm_mpi_readl(MPI_CSBASE_REG(0)); + val &= MPI_CSBASE_BASE_MASK; boot_addr = (u8 *)KSEG1ADDR(val); /* dump cfe version */ @@ -797,18 +791,6 @@ void __init board_prom_init(void) } bcm_gpio_writel(val, GPIO_MODE_REG); - - /* Generate MAC address for WLAN and - * register our SPROM */ -#ifdef CONFIG_SSB_PCIHOST - if (!board_get_mac_address(bcm63xx_sprom.il0mac)) { - memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN); - memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN); - if (ssb_arch_register_fallback_sprom( - &bcm63xx_get_fallback_sprom) < 0) - printk(KERN_ERR PFX "failed to register fallback SPROM\n"); - } -#endif } /* @@ -895,13 +877,23 @@ int __init board_register_devices(void) if (board.has_dsp) bcm63xx_dsp_register(&board.dsp); - /* read base address of boot chip select (0) */ - if (BCMCPU_IS_6345()) - val = 0x1fc00000; - else { - val = bcm_mpi_readl(MPI_CSBASE_REG(0)); - val &= MPI_CSBASE_BASE_MASK; + /* Generate MAC address for WLAN and register our SPROM, + * do this after registering enet devices + */ +#ifdef CONFIG_SSB_PCIHOST + if (!board_get_mac_address(bcm63xx_sprom.il0mac)) { + memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN); + memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN); + if (ssb_arch_register_fallback_sprom( + &bcm63xx_get_fallback_sprom) < 0) + pr_err(PFX "failed to register fallback SPROM\n"); } +#endif + + /* read base address of boot chip select (0) */ + val = bcm_mpi_readl(MPI_CSBASE_REG(0)); + val &= MPI_CSBASE_BASE_MASK; + mtd_resources[0].start = val; mtd_resources[0].end = 0x1FFFFFFF; diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c index 2c68ee9ccee2..9d57c71b7b58 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -10,6 +10,7 @@ #include <linux/mutex.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/delay.h> #include <bcm63xx_cpu.h> #include <bcm63xx_io.h> #include <bcm63xx_regs.h> @@ -113,6 +114,34 @@ static struct clk clk_ephy = { }; /* + * Ethernet switch clock + */ +static void enetsw_set(struct clk *clk, int enable) +{ + if (!BCMCPU_IS_6368()) + return; + bcm_hwclock_set(CKCTL_6368_ROBOSW_CLK_EN | + CKCTL_6368_SWPKT_USB_EN | + CKCTL_6368_SWPKT_SAR_EN, enable); + if (enable) { + u32 val; + + /* reset switch core afer clock change */ + val = bcm_perf_readl(PERF_SOFTRESET_6368_REG); + val &= ~SOFTRESET_6368_ENETSW_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6368_REG); + msleep(10); + val |= SOFTRESET_6368_ENETSW_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6368_REG); + msleep(10); + } +} + +static struct clk clk_enetsw = { + .set = enetsw_set, +}; + +/* * PCM clock */ static void pcm_set(struct clk *clk, int enable) @@ -131,9 +160,10 @@ static struct clk clk_pcm = { */ static void usbh_set(struct clk *clk, int enable) { - if (!BCMCPU_IS_6348()) - return; - bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); + if (BCMCPU_IS_6348()) + bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); + else if (BCMCPU_IS_6368()) + bcm_hwclock_set(CKCTL_6368_USBH_CLK_EN, enable); } static struct clk clk_usbh = { @@ -162,6 +192,36 @@ static struct clk clk_spi = { }; /* + * XTM clock + */ +static void xtm_set(struct clk *clk, int enable) +{ + if (!BCMCPU_IS_6368()) + return; + + bcm_hwclock_set(CKCTL_6368_SAR_CLK_EN | + CKCTL_6368_SWPKT_SAR_EN, enable); + + if (enable) { + u32 val; + + /* reset sar core afer clock change */ + val = bcm_perf_readl(PERF_SOFTRESET_6368_REG); + val &= ~SOFTRESET_6368_SAR_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6368_REG); + mdelay(1); + val |= SOFTRESET_6368_SAR_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6368_REG); + mdelay(1); + } +} + + +static struct clk clk_xtm = { + .set = xtm_set, +}; + +/* * Internal peripheral clock */ static struct clk clk_periph = { @@ -204,12 +264,16 @@ struct clk *clk_get(struct device *dev, const char *id) return &clk_enet0; if (!strcmp(id, "enet1")) return &clk_enet1; + if (!strcmp(id, "enetsw")) + return &clk_enetsw; if (!strcmp(id, "ephy")) return &clk_ephy; if (!strcmp(id, "usbh")) return &clk_usbh; if (!strcmp(id, "spi")) return &clk_spi; + if (!strcmp(id, "xtm")) + return &clk_xtm; if (!strcmp(id, "periph")) return &clk_periph; if (BCMCPU_IS_6358() && !strcmp(id, "pcm")) diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index 7c7e4d4486ce..8f0d6c7725ea 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -29,166 +29,47 @@ static u16 bcm63xx_cpu_rev; static unsigned int bcm63xx_cpu_freq; static unsigned int bcm63xx_memory_size; -/* - * 6338 register sets and irqs - */ -static const unsigned long bcm96338_regs_base[] = { - [RSET_DSL_LMEM] = BCM_6338_DSL_LMEM_BASE, - [RSET_PERF] = BCM_6338_PERF_BASE, - [RSET_TIMER] = BCM_6338_TIMER_BASE, - [RSET_WDT] = BCM_6338_WDT_BASE, - [RSET_UART0] = BCM_6338_UART0_BASE, - [RSET_UART1] = BCM_6338_UART1_BASE, - [RSET_GPIO] = BCM_6338_GPIO_BASE, - [RSET_SPI] = BCM_6338_SPI_BASE, - [RSET_OHCI0] = BCM_6338_OHCI0_BASE, - [RSET_OHCI_PRIV] = BCM_6338_OHCI_PRIV_BASE, - [RSET_USBH_PRIV] = BCM_6338_USBH_PRIV_BASE, - [RSET_UDC0] = BCM_6338_UDC0_BASE, - [RSET_MPI] = BCM_6338_MPI_BASE, - [RSET_PCMCIA] = BCM_6338_PCMCIA_BASE, - [RSET_SDRAM] = BCM_6338_SDRAM_BASE, - [RSET_DSL] = BCM_6338_DSL_BASE, - [RSET_ENET0] = BCM_6338_ENET0_BASE, - [RSET_ENET1] = BCM_6338_ENET1_BASE, - [RSET_ENETDMA] = BCM_6338_ENETDMA_BASE, - [RSET_MEMC] = BCM_6338_MEMC_BASE, - [RSET_DDR] = BCM_6338_DDR_BASE, +static const unsigned long bcm6338_regs_base[] = { + __GEN_CPU_REGS_TABLE(6338) }; -static const int bcm96338_irqs[] = { - [IRQ_TIMER] = BCM_6338_TIMER_IRQ, - [IRQ_UART0] = BCM_6338_UART0_IRQ, - [IRQ_DSL] = BCM_6338_DSL_IRQ, - [IRQ_ENET0] = BCM_6338_ENET0_IRQ, - [IRQ_ENET_PHY] = BCM_6338_ENET_PHY_IRQ, - [IRQ_ENET0_RXDMA] = BCM_6338_ENET0_RXDMA_IRQ, - [IRQ_ENET0_TXDMA] = BCM_6338_ENET0_TXDMA_IRQ, +static const int bcm6338_irqs[] = { + __GEN_CPU_IRQ_TABLE(6338) }; -/* - * 6345 register sets and irqs - */ -static const unsigned long bcm96345_regs_base[] = { - [RSET_DSL_LMEM] = BCM_6345_DSL_LMEM_BASE, - [RSET_PERF] = BCM_6345_PERF_BASE, - [RSET_TIMER] = BCM_6345_TIMER_BASE, - [RSET_WDT] = BCM_6345_WDT_BASE, - [RSET_UART0] = BCM_6345_UART0_BASE, - [RSET_UART1] = BCM_6345_UART1_BASE, - [RSET_GPIO] = BCM_6345_GPIO_BASE, - [RSET_SPI] = BCM_6345_SPI_BASE, - [RSET_UDC0] = BCM_6345_UDC0_BASE, - [RSET_OHCI0] = BCM_6345_OHCI0_BASE, - [RSET_OHCI_PRIV] = BCM_6345_OHCI_PRIV_BASE, - [RSET_USBH_PRIV] = BCM_6345_USBH_PRIV_BASE, - [RSET_MPI] = BCM_6345_MPI_BASE, - [RSET_PCMCIA] = BCM_6345_PCMCIA_BASE, - [RSET_DSL] = BCM_6345_DSL_BASE, - [RSET_ENET0] = BCM_6345_ENET0_BASE, - [RSET_ENET1] = BCM_6345_ENET1_BASE, - [RSET_ENETDMA] = BCM_6345_ENETDMA_BASE, - [RSET_EHCI0] = BCM_6345_EHCI0_BASE, - [RSET_SDRAM] = BCM_6345_SDRAM_BASE, - [RSET_MEMC] = BCM_6345_MEMC_BASE, - [RSET_DDR] = BCM_6345_DDR_BASE, +static const unsigned long bcm6345_regs_base[] = { + __GEN_CPU_REGS_TABLE(6345) }; -static const int bcm96345_irqs[] = { - [IRQ_TIMER] = BCM_6345_TIMER_IRQ, - [IRQ_UART0] = BCM_6345_UART0_IRQ, - [IRQ_DSL] = BCM_6345_DSL_IRQ, - [IRQ_ENET0] = BCM_6345_ENET0_IRQ, - [IRQ_ENET_PHY] = BCM_6345_ENET_PHY_IRQ, - [IRQ_ENET0_RXDMA] = BCM_6345_ENET0_RXDMA_IRQ, - [IRQ_ENET0_TXDMA] = BCM_6345_ENET0_TXDMA_IRQ, +static const int bcm6345_irqs[] = { + __GEN_CPU_IRQ_TABLE(6345) }; -/* - * 6348 register sets and irqs - */ -static const unsigned long bcm96348_regs_base[] = { - [RSET_DSL_LMEM] = BCM_6348_DSL_LMEM_BASE, - [RSET_PERF] = BCM_6348_PERF_BASE, - [RSET_TIMER] = BCM_6348_TIMER_BASE, - [RSET_WDT] = BCM_6348_WDT_BASE, - [RSET_UART0] = BCM_6348_UART0_BASE, - [RSET_UART1] = BCM_6348_UART1_BASE, - [RSET_GPIO] = BCM_6348_GPIO_BASE, - [RSET_SPI] = BCM_6348_SPI_BASE, - [RSET_OHCI0] = BCM_6348_OHCI0_BASE, - [RSET_OHCI_PRIV] = BCM_6348_OHCI_PRIV_BASE, - [RSET_USBH_PRIV] = BCM_6348_USBH_PRIV_BASE, - [RSET_MPI] = BCM_6348_MPI_BASE, - [RSET_PCMCIA] = BCM_6348_PCMCIA_BASE, - [RSET_SDRAM] = BCM_6348_SDRAM_BASE, - [RSET_DSL] = BCM_6348_DSL_BASE, - [RSET_ENET0] = BCM_6348_ENET0_BASE, - [RSET_ENET1] = BCM_6348_ENET1_BASE, - [RSET_ENETDMA] = BCM_6348_ENETDMA_BASE, - [RSET_MEMC] = BCM_6348_MEMC_BASE, - [RSET_DDR] = BCM_6348_DDR_BASE, +static const unsigned long bcm6348_regs_base[] = { + __GEN_CPU_REGS_TABLE(6348) }; -static const int bcm96348_irqs[] = { - [IRQ_TIMER] = BCM_6348_TIMER_IRQ, - [IRQ_UART0] = BCM_6348_UART0_IRQ, - [IRQ_DSL] = BCM_6348_DSL_IRQ, - [IRQ_ENET0] = BCM_6348_ENET0_IRQ, - [IRQ_ENET1] = BCM_6348_ENET1_IRQ, - [IRQ_ENET_PHY] = BCM_6348_ENET_PHY_IRQ, - [IRQ_OHCI0] = BCM_6348_OHCI0_IRQ, - [IRQ_PCMCIA] = BCM_6348_PCMCIA_IRQ, - [IRQ_ENET0_RXDMA] = BCM_6348_ENET0_RXDMA_IRQ, - [IRQ_ENET0_TXDMA] = BCM_6348_ENET0_TXDMA_IRQ, - [IRQ_ENET1_RXDMA] = BCM_6348_ENET1_RXDMA_IRQ, - [IRQ_ENET1_TXDMA] = BCM_6348_ENET1_TXDMA_IRQ, - [IRQ_PCI] = BCM_6348_PCI_IRQ, +static const int bcm6348_irqs[] = { + __GEN_CPU_IRQ_TABLE(6348) + }; -/* - * 6358 register sets and irqs - */ -static const unsigned long bcm96358_regs_base[] = { - [RSET_DSL_LMEM] = BCM_6358_DSL_LMEM_BASE, - [RSET_PERF] = BCM_6358_PERF_BASE, - [RSET_TIMER] = BCM_6358_TIMER_BASE, - [RSET_WDT] = BCM_6358_WDT_BASE, - [RSET_UART0] = BCM_6358_UART0_BASE, - [RSET_UART1] = BCM_6358_UART1_BASE, - [RSET_GPIO] = BCM_6358_GPIO_BASE, - [RSET_SPI] = BCM_6358_SPI_BASE, - [RSET_OHCI0] = BCM_6358_OHCI0_BASE, - [RSET_EHCI0] = BCM_6358_EHCI0_BASE, - [RSET_OHCI_PRIV] = BCM_6358_OHCI_PRIV_BASE, - [RSET_USBH_PRIV] = BCM_6358_USBH_PRIV_BASE, - [RSET_MPI] = BCM_6358_MPI_BASE, - [RSET_PCMCIA] = BCM_6358_PCMCIA_BASE, - [RSET_SDRAM] = BCM_6358_SDRAM_BASE, - [RSET_DSL] = BCM_6358_DSL_BASE, - [RSET_ENET0] = BCM_6358_ENET0_BASE, - [RSET_ENET1] = BCM_6358_ENET1_BASE, - [RSET_ENETDMA] = BCM_6358_ENETDMA_BASE, - [RSET_MEMC] = BCM_6358_MEMC_BASE, - [RSET_DDR] = BCM_6358_DDR_BASE, +static const unsigned long bcm6358_regs_base[] = { + __GEN_CPU_REGS_TABLE(6358) +}; + +static const int bcm6358_irqs[] = { + __GEN_CPU_IRQ_TABLE(6358) + }; -static const int bcm96358_irqs[] = { - [IRQ_TIMER] = BCM_6358_TIMER_IRQ, - [IRQ_UART0] = BCM_6358_UART0_IRQ, - [IRQ_UART1] = BCM_6358_UART1_IRQ, - [IRQ_DSL] = BCM_6358_DSL_IRQ, - [IRQ_ENET0] = BCM_6358_ENET0_IRQ, - [IRQ_ENET1] = BCM_6358_ENET1_IRQ, - [IRQ_ENET_PHY] = BCM_6358_ENET_PHY_IRQ, - [IRQ_OHCI0] = BCM_6358_OHCI0_IRQ, - [IRQ_EHCI0] = BCM_6358_EHCI0_IRQ, - [IRQ_PCMCIA] = BCM_6358_PCMCIA_IRQ, - [IRQ_ENET0_RXDMA] = BCM_6358_ENET0_RXDMA_IRQ, - [IRQ_ENET0_TXDMA] = BCM_6358_ENET0_TXDMA_IRQ, - [IRQ_ENET1_RXDMA] = BCM_6358_ENET1_RXDMA_IRQ, - [IRQ_ENET1_TXDMA] = BCM_6358_ENET1_TXDMA_IRQ, - [IRQ_PCI] = BCM_6358_PCI_IRQ, +static const unsigned long bcm6368_regs_base[] = { + __GEN_CPU_REGS_TABLE(6368) +}; + +static const int bcm6368_irqs[] = { + __GEN_CPU_IRQ_TABLE(6368) + }; u16 __bcm63xx_get_cpu_id(void) @@ -217,20 +98,19 @@ unsigned int bcm63xx_get_memory_size(void) static unsigned int detect_cpu_clock(void) { - unsigned int tmp, n1 = 0, n2 = 0, m1 = 0; - - /* BCM6338 has a fixed 240 Mhz frequency */ - if (BCMCPU_IS_6338()) + switch (bcm63xx_get_cpu_id()) { + case BCM6338_CPU_ID: + /* BCM6338 has a fixed 240 Mhz frequency */ return 240000000; - /* BCM6345 has a fixed 140Mhz frequency */ - if (BCMCPU_IS_6345()) + case BCM6345_CPU_ID: + /* BCM6345 has a fixed 140Mhz frequency */ return 140000000; - /* - * frequency depends on PLL configuration: - */ - if (BCMCPU_IS_6348()) { + case BCM6348_CPU_ID: + { + unsigned int tmp, n1, n2, m1; + /* 16MHz * (N1 + 1) * (N2 + 2) / (M1_CPU + 1) */ tmp = bcm_perf_readl(PERF_MIPSPLLCTL_REG); n1 = (tmp & MIPSPLLCTL_N1_MASK) >> MIPSPLLCTL_N1_SHIFT; @@ -239,17 +119,47 @@ static unsigned int detect_cpu_clock(void) n1 += 1; n2 += 2; m1 += 1; + return (16 * 1000000 * n1 * n2) / m1; } - if (BCMCPU_IS_6358()) { + case BCM6358_CPU_ID: + { + unsigned int tmp, n1, n2, m1; + /* 16MHz * N1 * N2 / M1_CPU */ tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_REG); n1 = (tmp & DMIPSPLLCFG_N1_MASK) >> DMIPSPLLCFG_N1_SHIFT; n2 = (tmp & DMIPSPLLCFG_N2_MASK) >> DMIPSPLLCFG_N2_SHIFT; m1 = (tmp & DMIPSPLLCFG_M1_MASK) >> DMIPSPLLCFG_M1_SHIFT; + return (16 * 1000000 * n1 * n2) / m1; } - return (16 * 1000000 * n1 * n2) / m1; + case BCM6368_CPU_ID: + { + unsigned int tmp, p1, p2, ndiv, m1; + + /* (64MHz / P1) * P2 * NDIV / M1_CPU */ + tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_6368_REG); + + p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >> + DMIPSPLLCFG_6368_P1_SHIFT; + + p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >> + DMIPSPLLCFG_6368_P2_SHIFT; + + ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >> + DMIPSPLLCFG_6368_NDIV_SHIFT; + + tmp = bcm_ddr_readl(DDR_DMIPSPLLDIV_6368_REG); + m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >> + DMIPSPLLDIV_6368_MDIV_SHIFT; + + return (((64 * 1000000) / p1) * p2 * ndiv) / m1; + } + + default: + BUG(); + } } /* @@ -260,8 +170,10 @@ static unsigned int detect_memory_size(void) unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0; u32 val; - if (BCMCPU_IS_6345()) - return (8 * 1024 * 1024); + if (BCMCPU_IS_6345()) { + val = bcm_sdram_readl(SDRAM_MBASE_REG); + return (val * 8 * 1024 * 1024); + } if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { val = bcm_sdram_readl(SDRAM_CFG_REG); @@ -271,7 +183,7 @@ static unsigned int detect_memory_size(void) banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1; } - if (BCMCPU_IS_6358()) { + if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { val = bcm_memc_readl(MEMC_CFG_REG); rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT; cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT; @@ -301,24 +213,33 @@ void __init bcm63xx_cpu_init(void) case CPU_BMIPS3300: if ((read_c0_prid() & 0xff00) == PRID_IMP_BMIPS3300_ALT) { expected_cpu_id = BCM6348_CPU_ID; - bcm63xx_regs_base = bcm96348_regs_base; - bcm63xx_irqs = bcm96348_irqs; + bcm63xx_regs_base = bcm6348_regs_base; + bcm63xx_irqs = bcm6348_irqs; } else { __cpu_name[cpu] = "Broadcom BCM6338"; expected_cpu_id = BCM6338_CPU_ID; - bcm63xx_regs_base = bcm96338_regs_base; - bcm63xx_irqs = bcm96338_irqs; + bcm63xx_regs_base = bcm6338_regs_base; + bcm63xx_irqs = bcm6338_irqs; } break; case CPU_BMIPS32: expected_cpu_id = BCM6345_CPU_ID; - bcm63xx_regs_base = bcm96345_regs_base; - bcm63xx_irqs = bcm96345_irqs; + bcm63xx_regs_base = bcm6345_regs_base; + bcm63xx_irqs = bcm6345_irqs; break; case CPU_BMIPS4350: - expected_cpu_id = BCM6358_CPU_ID; - bcm63xx_regs_base = bcm96358_regs_base; - bcm63xx_irqs = bcm96358_irqs; + switch (read_c0_prid() & 0xf0) { + case 0x10: + expected_cpu_id = BCM6358_CPU_ID; + bcm63xx_regs_base = bcm6358_regs_base; + bcm63xx_irqs = bcm6358_irqs; + break; + case 0x30: + expected_cpu_id = BCM6368_CPU_ID; + bcm63xx_regs_base = bcm6368_regs_base; + bcm63xx_irqs = bcm6368_irqs; + break; + } break; } diff --git a/arch/mips/bcm63xx/dev-uart.c b/arch/mips/bcm63xx/dev-uart.c index c2963da0253e..d6e42c608325 100644 --- a/arch/mips/bcm63xx/dev-uart.c +++ b/arch/mips/bcm63xx/dev-uart.c @@ -54,7 +54,7 @@ int __init bcm63xx_uart_register(unsigned int id) if (id >= ARRAY_SIZE(bcm63xx_uart_devices)) return -ENODEV; - if (id == 1 && !BCMCPU_IS_6358()) + if (id == 1 && (!BCMCPU_IS_6358() && !BCMCPU_IS_6368())) return -ENODEV; if (id == 0) { diff --git a/arch/mips/bcm63xx/gpio.c b/arch/mips/bcm63xx/gpio.c index f560fe7d38dd..a6c2135dbf38 100644 --- a/arch/mips/bcm63xx/gpio.c +++ b/arch/mips/bcm63xx/gpio.c @@ -4,7 +4,7 @@ * for more details. * * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> - * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org> + * Copyright (C) 2008-2011 Florian Fainelli <florian@openwrt.org> */ #include <linux/kernel.h> @@ -18,6 +18,34 @@ #include <bcm63xx_io.h> #include <bcm63xx_regs.h> +#ifndef BCMCPU_RUNTIME_DETECT +#define gpio_out_low_reg GPIO_DATA_LO_REG +#ifdef CONFIG_BCM63XX_CPU_6345 +#ifdef gpio_out_low_reg +#undef gpio_out_low_reg +#define gpio_out_low_reg GPIO_DATA_LO_REG_6345 +#endif /* gpio_out_low_reg */ +#endif /* CONFIG_BCM63XX_CPU_6345 */ + +static inline void bcm63xx_gpio_out_low_reg_init(void) +{ +} +#else /* ! BCMCPU_RUNTIME_DETECT */ +static u32 gpio_out_low_reg; + +static void bcm63xx_gpio_out_low_reg_init(void) +{ + switch (bcm63xx_get_cpu_id()) { + case BCM6345_CPU_ID: + gpio_out_low_reg = GPIO_DATA_LO_REG_6345; + break; + default: + gpio_out_low_reg = GPIO_DATA_LO_REG; + break; + } +} +#endif /* ! BCMCPU_RUNTIME_DETECT */ + static DEFINE_SPINLOCK(bcm63xx_gpio_lock); static u32 gpio_out_low, gpio_out_high; @@ -33,7 +61,7 @@ static void bcm63xx_gpio_set(struct gpio_chip *chip, BUG(); if (gpio < 32) { - reg = GPIO_DATA_LO_REG; + reg = gpio_out_low_reg; mask = 1 << gpio; v = &gpio_out_low; } else { @@ -60,7 +88,7 @@ static int bcm63xx_gpio_get(struct gpio_chip *chip, unsigned gpio) BUG(); if (gpio < 32) { - reg = GPIO_DATA_LO_REG; + reg = gpio_out_low_reg; mask = 1 << gpio; } else { reg = GPIO_DATA_HI_REG; @@ -125,8 +153,11 @@ static struct gpio_chip bcm63xx_gpio_chip = { int __init bcm63xx_gpio_init(void) { - gpio_out_low = bcm_gpio_readl(GPIO_DATA_LO_REG); - gpio_out_high = bcm_gpio_readl(GPIO_DATA_HI_REG); + bcm63xx_gpio_out_low_reg_init(); + + gpio_out_low = bcm_gpio_readl(gpio_out_low_reg); + if (!BCMCPU_IS_6345()) + gpio_out_high = bcm_gpio_readl(GPIO_DATA_HI_REG); bcm63xx_gpio_chip.ngpio = bcm63xx_gpio_count(); pr_info("registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio); diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index 162e11b4ed75..9a216a451d92 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -19,19 +19,187 @@ #include <bcm63xx_io.h> #include <bcm63xx_irq.h> +static void __dispatch_internal(void) __maybe_unused; +static void __dispatch_internal_64(void) __maybe_unused; +static void __internal_irq_mask_32(unsigned int irq) __maybe_unused; +static void __internal_irq_mask_64(unsigned int irq) __maybe_unused; +static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused; +static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; + +#ifndef BCMCPU_RUNTIME_DETECT +#ifdef CONFIG_BCM63XX_CPU_6338 +#define irq_stat_reg PERF_IRQSTAT_6338_REG +#define irq_mask_reg PERF_IRQMASK_6338_REG +#define irq_bits 32 +#define is_ext_irq_cascaded 0 +#define ext_irq_start 0 +#define ext_irq_end 0 +#define ext_irq_count 4 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6338 +#define ext_irq_cfg_reg2 0 +#endif +#ifdef CONFIG_BCM63XX_CPU_6345 +#define irq_stat_reg PERF_IRQSTAT_6345_REG +#define irq_mask_reg PERF_IRQMASK_6345_REG +#define irq_bits 32 +#define is_ext_irq_cascaded 0 +#define ext_irq_start 0 +#define ext_irq_end 0 +#define ext_irq_count 0 +#define ext_irq_cfg_reg1 0 +#define ext_irq_cfg_reg2 0 +#endif +#ifdef CONFIG_BCM63XX_CPU_6348 +#define irq_stat_reg PERF_IRQSTAT_6348_REG +#define irq_mask_reg PERF_IRQMASK_6348_REG +#define irq_bits 32 +#define is_ext_irq_cascaded 0 +#define ext_irq_start 0 +#define ext_irq_end 0 +#define ext_irq_count 4 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6348 +#define ext_irq_cfg_reg2 0 +#endif +#ifdef CONFIG_BCM63XX_CPU_6358 +#define irq_stat_reg PERF_IRQSTAT_6358_REG +#define irq_mask_reg PERF_IRQMASK_6358_REG +#define irq_bits 32 +#define is_ext_irq_cascaded 1 +#define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE) +#define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE) +#define ext_irq_count 4 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358 +#define ext_irq_cfg_reg2 0 +#endif +#ifdef CONFIG_BCM63XX_CPU_6368 +#define irq_stat_reg PERF_IRQSTAT_6368_REG +#define irq_mask_reg PERF_IRQMASK_6368_REG +#define irq_bits 64 +#define is_ext_irq_cascaded 1 +#define ext_irq_start (BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE) +#define ext_irq_end (BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE) +#define ext_irq_count 6 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6368 +#define ext_irq_cfg_reg2 PERF_EXTIRQ_CFG_REG2_6368 +#endif + +#if irq_bits == 32 +#define dispatch_internal __dispatch_internal +#define internal_irq_mask __internal_irq_mask_32 +#define internal_irq_unmask __internal_irq_unmask_32 +#else +#define dispatch_internal __dispatch_internal_64 +#define internal_irq_mask __internal_irq_mask_64 +#define internal_irq_unmask __internal_irq_unmask_64 +#endif + +#define irq_stat_addr (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg) +#define irq_mask_addr (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg) + +static inline void bcm63xx_init_irq(void) +{ +} +#else /* ! BCMCPU_RUNTIME_DETECT */ + +static u32 irq_stat_addr, irq_mask_addr; +static void (*dispatch_internal)(void); +static int is_ext_irq_cascaded; +static unsigned int ext_irq_count; +static unsigned int ext_irq_start, ext_irq_end; +static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2; +static void (*internal_irq_mask)(unsigned int irq); +static void (*internal_irq_unmask)(unsigned int irq); + +static void bcm63xx_init_irq(void) +{ + int irq_bits; + + irq_stat_addr = bcm63xx_regset_address(RSET_PERF); + irq_mask_addr = bcm63xx_regset_address(RSET_PERF); + + switch (bcm63xx_get_cpu_id()) { + case BCM6338_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6338_REG; + irq_mask_addr += PERF_IRQMASK_6338_REG; + irq_bits = 32; + break; + case BCM6345_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6345_REG; + irq_mask_addr += PERF_IRQMASK_6345_REG; + irq_bits = 32; + break; + case BCM6348_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6348_REG; + irq_mask_addr += PERF_IRQMASK_6348_REG; + irq_bits = 32; + ext_irq_count = 4; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348; + break; + case BCM6358_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6358_REG; + irq_mask_addr += PERF_IRQMASK_6358_REG; + irq_bits = 32; + ext_irq_count = 4; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358; + break; + case BCM6368_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6368_REG; + irq_mask_addr += PERF_IRQMASK_6368_REG; + irq_bits = 64; + ext_irq_count = 6; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368; + ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368; + break; + default: + BUG(); + } + + if (irq_bits == 32) { + dispatch_internal = __dispatch_internal; + internal_irq_mask = __internal_irq_mask_32; + internal_irq_unmask = __internal_irq_unmask_32; + } else { + dispatch_internal = __dispatch_internal_64; + internal_irq_mask = __internal_irq_mask_64; + internal_irq_unmask = __internal_irq_unmask_64; + } +} +#endif /* ! BCMCPU_RUNTIME_DETECT */ + +static inline u32 get_ext_irq_perf_reg(int irq) +{ + if (irq < 4) + return ext_irq_cfg_reg1; + return ext_irq_cfg_reg2; +} + +static inline void handle_internal(int intbit) +{ + if (is_ext_irq_cascaded && + intbit >= ext_irq_start && intbit <= ext_irq_end) + do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE); + else + do_IRQ(intbit + IRQ_INTERNAL_BASE); +} + /* * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not * prioritize any interrupt relatively to another. the static counter * will resume the loop where it ended the last time we left this * function. */ -static void bcm63xx_irq_dispatch_internal(void) +static void __dispatch_internal(void) { u32 pending; static int i; - pending = bcm_perf_readl(PERF_IRQMASK_REG) & - bcm_perf_readl(PERF_IRQSTAT_REG); + pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr); if (!pending) return ; @@ -41,7 +209,28 @@ static void bcm63xx_irq_dispatch_internal(void) i = (i + 1) & 0x1f; if (pending & (1 << to_call)) { - do_IRQ(to_call + IRQ_INTERNAL_BASE); + handle_internal(to_call); + break; + } + } +} + +static void __dispatch_internal_64(void) +{ + u64 pending; + static int i; + + pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr); + + if (!pending) + return ; + + while (1) { + int to_call = i; + + i = (i + 1) & 0x3f; + if (pending & (1ull << to_call)) { + handle_internal(to_call); break; } } @@ -60,15 +249,17 @@ asmlinkage void plat_irq_dispatch(void) if (cause & CAUSEF_IP7) do_IRQ(7); if (cause & CAUSEF_IP2) - bcm63xx_irq_dispatch_internal(); - if (cause & CAUSEF_IP3) - do_IRQ(IRQ_EXT_0); - if (cause & CAUSEF_IP4) - do_IRQ(IRQ_EXT_1); - if (cause & CAUSEF_IP5) - do_IRQ(IRQ_EXT_2); - if (cause & CAUSEF_IP6) - do_IRQ(IRQ_EXT_3); + dispatch_internal(); + if (!is_ext_irq_cascaded) { + if (cause & CAUSEF_IP3) + do_IRQ(IRQ_EXT_0); + if (cause & CAUSEF_IP4) + do_IRQ(IRQ_EXT_1); + if (cause & CAUSEF_IP5) + do_IRQ(IRQ_EXT_2); + if (cause & CAUSEF_IP6) + do_IRQ(IRQ_EXT_3); + } } while (1); } @@ -76,24 +267,50 @@ asmlinkage void plat_irq_dispatch(void) * internal IRQs operations: only mask/unmask on PERF irq mask * register. */ -static inline void bcm63xx_internal_irq_mask(struct irq_data *d) +static void __internal_irq_mask_32(unsigned int irq) { - unsigned int irq = d->irq - IRQ_INTERNAL_BASE; u32 mask; - mask = bcm_perf_readl(PERF_IRQMASK_REG); + mask = bcm_readl(irq_mask_addr); mask &= ~(1 << irq); - bcm_perf_writel(mask, PERF_IRQMASK_REG); + bcm_writel(mask, irq_mask_addr); } -static void bcm63xx_internal_irq_unmask(struct irq_data *d) +static void __internal_irq_mask_64(unsigned int irq) +{ + u64 mask; + + mask = bcm_readq(irq_mask_addr); + mask &= ~(1ull << irq); + bcm_writeq(mask, irq_mask_addr); +} + +static void __internal_irq_unmask_32(unsigned int irq) { - unsigned int irq = d->irq - IRQ_INTERNAL_BASE; u32 mask; - mask = bcm_perf_readl(PERF_IRQMASK_REG); + mask = bcm_readl(irq_mask_addr); mask |= (1 << irq); - bcm_perf_writel(mask, PERF_IRQMASK_REG); + bcm_writel(mask, irq_mask_addr); +} + +static void __internal_irq_unmask_64(unsigned int irq) +{ + u64 mask; + + mask = bcm_readq(irq_mask_addr); + mask |= (1ull << irq); + bcm_writeq(mask, irq_mask_addr); +} + +static void bcm63xx_internal_irq_mask(struct irq_data *d) +{ + internal_irq_mask(d->irq - IRQ_INTERNAL_BASE); +} + +static void bcm63xx_internal_irq_unmask(struct irq_data *d) +{ + internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE); } /* @@ -102,94 +319,131 @@ static void bcm63xx_internal_irq_unmask(struct irq_data *d) */ static void bcm63xx_external_irq_mask(struct irq_data *d) { - unsigned int irq = d->irq - IRQ_EXT_BASE; - u32 reg; + unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; + u32 reg, regaddr; - reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); - reg &= ~EXTIRQ_CFG_MASK(irq); - bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); + regaddr = get_ext_irq_perf_reg(irq); + reg = bcm_perf_readl(regaddr); + + if (BCMCPU_IS_6348()) + reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4); + else + reg &= ~EXTIRQ_CFG_MASK(irq % 4); + + bcm_perf_writel(reg, regaddr); + if (is_ext_irq_cascaded) + internal_irq_mask(irq + ext_irq_start); } static void bcm63xx_external_irq_unmask(struct irq_data *d) { - unsigned int irq = d->irq - IRQ_EXT_BASE; - u32 reg; + unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; + u32 reg, regaddr; - reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); - reg |= EXTIRQ_CFG_MASK(irq); - bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); + regaddr = get_ext_irq_perf_reg(irq); + reg = bcm_perf_readl(regaddr); + + if (BCMCPU_IS_6348()) + reg |= EXTIRQ_CFG_MASK_6348(irq % 4); + else + reg |= EXTIRQ_CFG_MASK(irq % 4); + + bcm_perf_writel(reg, regaddr); + + if (is_ext_irq_cascaded) + internal_irq_unmask(irq + ext_irq_start); } static void bcm63xx_external_irq_clear(struct irq_data *d) { - unsigned int irq = d->irq - IRQ_EXT_BASE; - u32 reg; + unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; + u32 reg, regaddr; - reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); - reg |= EXTIRQ_CFG_CLEAR(irq); - bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); -} + regaddr = get_ext_irq_perf_reg(irq); + reg = bcm_perf_readl(regaddr); -static unsigned int bcm63xx_external_irq_startup(struct irq_data *d) -{ - set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); - irq_enable_hazard(); - bcm63xx_external_irq_unmask(d); - return 0; -} + if (BCMCPU_IS_6348()) + reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4); + else + reg |= EXTIRQ_CFG_CLEAR(irq % 4); -static void bcm63xx_external_irq_shutdown(struct irq_data *d) -{ - bcm63xx_external_irq_mask(d); - clear_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); - irq_disable_hazard(); + bcm_perf_writel(reg, regaddr); } static int bcm63xx_external_irq_set_type(struct irq_data *d, unsigned int flow_type) { - unsigned int irq = d->irq - IRQ_EXT_BASE; - u32 reg; + unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; + u32 reg, regaddr; + int levelsense, sense, bothedge; flow_type &= IRQ_TYPE_SENSE_MASK; if (flow_type == IRQ_TYPE_NONE) flow_type = IRQ_TYPE_LEVEL_LOW; - reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); + levelsense = sense = bothedge = 0; switch (flow_type) { case IRQ_TYPE_EDGE_BOTH: - reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); - reg |= EXTIRQ_CFG_BOTHEDGE(irq); + bothedge = 1; break; case IRQ_TYPE_EDGE_RISING: - reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); - reg |= EXTIRQ_CFG_SENSE(irq); - reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); + sense = 1; break; case IRQ_TYPE_EDGE_FALLING: - reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); - reg &= ~EXTIRQ_CFG_SENSE(irq); - reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); break; case IRQ_TYPE_LEVEL_HIGH: - reg |= EXTIRQ_CFG_LEVELSENSE(irq); - reg |= EXTIRQ_CFG_SENSE(irq); + levelsense = 1; + sense = 1; break; case IRQ_TYPE_LEVEL_LOW: - reg |= EXTIRQ_CFG_LEVELSENSE(irq); - reg &= ~EXTIRQ_CFG_SENSE(irq); + levelsense = 1; break; default: printk(KERN_ERR "bogus flow type combination given !\n"); return -EINVAL; } - bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); + + regaddr = get_ext_irq_perf_reg(irq); + reg = bcm_perf_readl(regaddr); + irq %= 4; + + if (BCMCPU_IS_6348()) { + if (levelsense) + reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq); + else + reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq); + if (sense) + reg |= EXTIRQ_CFG_SENSE_6348(irq); + else + reg &= ~EXTIRQ_CFG_SENSE_6348(irq); + if (bothedge) + reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq); + else + reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq); + } + + if (BCMCPU_IS_6338() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) { + if (levelsense) + reg |= EXTIRQ_CFG_LEVELSENSE(irq); + else + reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); + if (sense) + reg |= EXTIRQ_CFG_SENSE(irq); + else + reg &= ~EXTIRQ_CFG_SENSE(irq); + if (bothedge) + reg |= EXTIRQ_CFG_BOTHEDGE(irq); + else + reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); + } + + bcm_perf_writel(reg, regaddr); irqd_set_trigger_type(d, flow_type); if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) @@ -208,9 +462,6 @@ static struct irq_chip bcm63xx_internal_irq_chip = { static struct irq_chip bcm63xx_external_irq_chip = { .name = "bcm63xx_epic", - .irq_startup = bcm63xx_external_irq_startup, - .irq_shutdown = bcm63xx_external_irq_shutdown, - .irq_ack = bcm63xx_external_irq_clear, .irq_mask = bcm63xx_external_irq_mask, @@ -225,18 +476,30 @@ static struct irqaction cpu_ip2_cascade_action = { .flags = IRQF_NO_THREAD, }; +static struct irqaction cpu_ext_cascade_action = { + .handler = no_action, + .name = "cascade_extirq", + .flags = IRQF_NO_THREAD, +}; + void __init arch_init_irq(void) { int i; + bcm63xx_init_irq(); mips_cpu_irq_init(); for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i) irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip, handle_level_irq); - for (i = IRQ_EXT_BASE; i < IRQ_EXT_BASE + 4; ++i) + for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + ext_irq_count; ++i) irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip, handle_edge_irq); - setup_irq(IRQ_MIPS_BASE + 2, &cpu_ip2_cascade_action); + if (!is_ext_irq_cascaded) { + for (i = 3; i < 3 + ext_irq_count; ++i) + setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action); + } + + setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action); } diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index be252efa0757..99d7f405cbeb 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -32,9 +32,12 @@ void __init prom_init(void) mask = CKCTL_6345_ALL_SAFE_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_ALL_SAFE_EN; - else - /* BCMCPU_IS_6358() */ + else if (BCMCPU_IS_6358()) mask = CKCTL_6358_ALL_SAFE_EN; + else if (BCMCPU_IS_6368()) + mask = CKCTL_6368_ALL_SAFE_EN; + else + mask = 0; reg = bcm_perf_readl(PERF_CKCTL_REG); reg &= ~mask; diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index d0056598fbfc..d209f85d87bb 100644 --- a/arch/mips/bcm63xx/setup.c +++ b/arch/mips/bcm63xx/setup.c @@ -63,13 +63,33 @@ static void bcm6348_a1_reboot(void) void bcm63xx_machine_reboot(void) { - u32 reg; + u32 reg, perf_regs[2] = { 0, 0 }; + unsigned int i; /* mask and clear all external irq */ - reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); - reg &= ~EXTIRQ_CFG_MASK_ALL; - reg |= EXTIRQ_CFG_CLEAR_ALL; - bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); + switch (bcm63xx_get_cpu_id()) { + case BCM6338_CPU_ID: + perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338; + break; + case BCM6348_CPU_ID: + perf_regs[0] = PERF_EXTIRQ_CFG_REG_6348; + break; + case BCM6358_CPU_ID: + perf_regs[0] = PERF_EXTIRQ_CFG_REG_6358; + break; + } + + for (i = 0; i < 2; i++) { + reg = bcm_perf_readl(perf_regs[i]); + if (BCMCPU_IS_6348()) { + reg &= ~EXTIRQ_CFG_MASK_ALL_6348; + reg |= EXTIRQ_CFG_CLEAR_ALL_6348; + } else { + reg &= ~EXTIRQ_CFG_MASK_ALL; + reg |= EXTIRQ_CFG_CLEAR_ALL; + } + bcm_perf_writel(reg, perf_regs[i]); + } if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1)) bcm6348_a1_reboot(); @@ -124,4 +144,4 @@ int __init bcm63xx_register_devices(void) return board_register_devices(); } -arch_initcall(bcm63xx_register_devices); +device_initcall(bcm63xx_register_devices); |