diff options
Diffstat (limited to 'arch/mips/bcm63xx')
| -rw-r--r-- | arch/mips/bcm63xx/Kconfig | 21 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/Makefile | 4 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/boards/board_bcm963xx.c | 97 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/clk.c | 115 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/cpu.c | 173 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-enet.c | 181 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-flash.c | 7 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-hsspi.c | 47 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-spi.c | 39 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-uart.c | 3 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/early_printk.c | 7 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/irq.c | 45 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/nvram.c | 28 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/prom.c | 49 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/reset.c | 57 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/setup.c | 10 |
16 files changed, 727 insertions, 156 deletions
diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index d03e8799d1c..a057fdf111c 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -1,32 +1,43 @@ menu "CPU support" depends on BCM63XX +config BCM63XX_CPU_3368 + bool "support 3368 CPU" + select SYS_HAS_CPU_BMIPS4350 + select HW_HAS_PCI + config BCM63XX_CPU_6328 bool "support 6328 CPU" + select SYS_HAS_CPU_BMIPS4350 select HW_HAS_PCI config BCM63XX_CPU_6338 bool "support 6338 CPU" + select SYS_HAS_CPU_BMIPS32_3300 select HW_HAS_PCI - select USB_ARCH_HAS_OHCI - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO config BCM63XX_CPU_6345 bool "support 6345 CPU" - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO + select SYS_HAS_CPU_BMIPS32_3300 config BCM63XX_CPU_6348 bool "support 6348 CPU" + select SYS_HAS_CPU_BMIPS32_3300 select HW_HAS_PCI config BCM63XX_CPU_6358 bool "support 6358 CPU" + select SYS_HAS_CPU_BMIPS4350 + select HW_HAS_PCI + +config BCM63XX_CPU_6362 + bool "support 6362 CPU" + select SYS_HAS_CPU_BMIPS4350 select HW_HAS_PCI config BCM63XX_CPU_6368 bool "support 6368 CPU" + select SYS_HAS_CPU_BMIPS4350 select HW_HAS_PCI endmenu diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile index ac2807397c1..9019f54aee6 100644 --- a/arch/mips/bcm63xx/Makefile +++ b/arch/mips/bcm63xx/Makefile @@ -1,7 +1,7 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \ setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \ - dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-wdt.o \ - dev-usb-usbd.o + dev-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \ + dev-wdt.o dev-usb-usbd.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += boards/ diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 73be9b34969..33727e7f0c7 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -23,16 +23,53 @@ #include <bcm63xx_dev_enet.h> #include <bcm63xx_dev_dsp.h> #include <bcm63xx_dev_flash.h> +#include <bcm63xx_dev_hsspi.h> #include <bcm63xx_dev_pcmcia.h> #include <bcm63xx_dev_spi.h> #include <bcm63xx_dev_usb_usbd.h> #include <board_bcm963xx.h> +#include <uapi/linux/bcm933xx_hcs.h> + #define PFX "board_bcm963xx: " +#define HCS_OFFSET_128K 0x20000 + static struct board_info board; /* + * known 3368 boards + */ +#ifdef CONFIG_BCM63XX_CPU_3368 +static struct board_info __initdata board_cvg834g = { + .name = "CVG834G_E15R3921", + .expected_cpu_id = 0x3368, + + .has_uart0 = 1, + .has_uart1 = 1, + + .has_enet0 = 1, + .has_pci = 1, + + .enet0 = { + .has_phy = 1, + .use_internal_phy = 1, + }, + + .leds = { + { + .name = "CVG834G:green:power", + .gpio = 37, + .default_trigger= "default-on", + }, + }, + + .ephy_reset_gpio = 36, + .ephy_reset_gpio_flags = GPIOF_INIT_HIGH, +}; +#endif + +/* * known 6328 boards */ #ifdef CONFIG_BCM63XX_CPU_6328 @@ -406,9 +443,9 @@ static struct board_info __initdata board_FAST2404 = { .expected_cpu_id = 0x6348, .has_uart0 = 1, - .has_enet0 = 1, - .has_enet1 = 1, - .has_pci = 1, + .has_enet0 = 1, + .has_enet1 = 1, + .has_pci = 1, .enet0 = { .has_phy = 1, @@ -591,22 +628,22 @@ static struct board_info __initdata board_96358vw2 = { }; static struct board_info __initdata board_AGPFS0 = { - .name = "AGPF-S0", - .expected_cpu_id = 0x6358, + .name = "AGPF-S0", + .expected_cpu_id = 0x6358, .has_uart0 = 1, - .has_enet0 = 1, - .has_enet1 = 1, - .has_pci = 1, + .has_enet0 = 1, + .has_enet1 = 1, + .has_pci = 1, .enet0 = { - .has_phy = 1, - .use_internal_phy = 1, + .has_phy = 1, + .use_internal_phy = 1, }, .enet1 = { - .force_speed_100 = 1, - .force_duplex_full = 1, + .force_speed_100 = 1, + .force_duplex_full = 1, }, .has_ohci0 = 1, @@ -639,6 +676,9 @@ static struct board_info __initdata board_DWVS0 = { * all boards */ static const struct board_info __initconst *bcm963xx_boards[] = { +#ifdef CONFIG_BCM63XX_CPU_3368 + &board_cvg834g, +#endif #ifdef CONFIG_BCM63XX_CPU_6328 &board_96328avng, #endif @@ -677,7 +717,7 @@ static struct ssb_sprom bcm63xx_sprom = { .revision = 0x02, .board_rev = 0x17, .country_code = 0x0, - .ant_available_bg = 0x3, + .ant_available_bg = 0x3, .pa0b0 = 0x15ae, .pa0b1 = 0xfa85, .pa0b2 = 0xfe8d, @@ -722,15 +762,16 @@ void __init board_prom_init(void) unsigned int i; u8 *boot_addr, *cfe; char cfe_version[32]; - char *board_name; + char *board_name = NULL; u32 val; + struct bcm_hcs *hcs; /* read base address of boot chip select (0) - * 6328 does not have MPI but boots from a fixed address + * 6328/6362 do not have MPI but boot from a fixed address */ - if (BCMCPU_IS_6328()) + if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) { val = 0x18000000; - else { + } else { val = bcm_mpi_readl(MPI_CSBASE_REG(0)); val &= MPI_CSBASE_BASE_MASK; } @@ -745,12 +786,14 @@ void __init board_prom_init(void) strcpy(cfe_version, "unknown"); printk(KERN_INFO PFX "CFE version: %s\n", cfe_version); - if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET)) { - printk(KERN_ERR PFX "invalid nvram checksum\n"); - return; - } + bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET); - board_name = bcm63xx_nvram_get_name(); + if (BCMCPU_IS_3368()) { + hcs = (struct bcm_hcs *)boot_addr; + board_name = hcs->filename; + } else { + board_name = bcm63xx_nvram_get_name(); + } /* find board by name */ for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) { if (strncmp(board_name, bcm963xx_boards[i]->name, 16)) @@ -848,6 +891,10 @@ int __init board_register_devices(void) !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr)) bcm63xx_enet_register(1, &board.enet1); + if (board.has_enetsw && + !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr)) + bcm63xx_enetsw_register(&board.enetsw); + if (board.has_usbd) bcm63xx_usbd_register(&board.usbd); @@ -869,6 +916,8 @@ int __init board_register_devices(void) bcm63xx_spi_register(); + bcm63xx_hsspi_register(); + bcm63xx_flash_register(); bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds); @@ -876,5 +925,9 @@ int __init board_register_devices(void) platform_device_register(&bcm63xx_gpio_leds); + if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags) + gpio_request_one(board.ephy_reset_gpio, + board.ephy_reset_gpio_flags, "ephy-reset"); + return 0; } diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c index b9e948d5943..63756528473 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -15,7 +15,13 @@ #include <bcm63xx_io.h> #include <bcm63xx_regs.h> #include <bcm63xx_reset.h> -#include <bcm63xx_clk.h> + +struct clk { + void (*set)(struct clk *, int); + unsigned int rate; + unsigned int usage; + int id; +}; static DEFINE_MUTEX(clocks_mutex); @@ -78,7 +84,7 @@ static void enetx_set(struct clk *clk, int enable) else clk_disable_unlocked(&clk_enet_misc); - if (BCMCPU_IS_6358()) { + if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) { u32 mask; if (clk->id == 0) @@ -104,9 +110,8 @@ static struct clk clk_enet1 = { */ static void ephy_set(struct clk *clk, int enable) { - if (!BCMCPU_IS_6358()) - return; - bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable); + if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) + bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable); } @@ -119,11 +124,18 @@ static struct clk clk_ephy = { */ static void enetsw_set(struct clk *clk, int enable) { - if (!BCMCPU_IS_6368()) + if (BCMCPU_IS_6328()) + bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable); + else if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable); + else if (BCMCPU_IS_6368()) + bcm_hwclock_set(CKCTL_6368_ROBOSW_EN | + CKCTL_6368_SWPKT_USB_EN | + CKCTL_6368_SWPKT_SAR_EN, + enable); + else return; - bcm_hwclock_set(CKCTL_6368_ROBOSW_EN | - CKCTL_6368_SWPKT_USB_EN | - CKCTL_6368_SWPKT_SAR_EN, enable); + if (enable) { /* reset switch core afer clock change */ bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1); @@ -142,9 +154,10 @@ static struct clk clk_enetsw = { */ static void pcm_set(struct clk *clk, int enable) { - if (!BCMCPU_IS_6358()) - return; - bcm_hwclock_set(CKCTL_6358_PCM_EN, enable); + if (BCMCPU_IS_3368()) + bcm_hwclock_set(CKCTL_3368_PCM_EN, enable); + if (BCMCPU_IS_6358()) + bcm_hwclock_set(CKCTL_6358_PCM_EN, enable); } static struct clk clk_pcm = { @@ -160,6 +173,8 @@ static void usbh_set(struct clk *clk, int enable) bcm_hwclock_set(CKCTL_6328_USBH_EN, enable); else if (BCMCPU_IS_6348()) bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); + else if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_USBH_EN, enable); else if (BCMCPU_IS_6368()) bcm_hwclock_set(CKCTL_6368_USBH_EN, enable); } @@ -175,6 +190,8 @@ static void usbd_set(struct clk *clk, int enable) { if (BCMCPU_IS_6328()) bcm_hwclock_set(CKCTL_6328_USBD_EN, enable); + else if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_USBD_EN, enable); else if (BCMCPU_IS_6368()) bcm_hwclock_set(CKCTL_6368_USBD_EN, enable); } @@ -194,8 +211,10 @@ static void spi_set(struct clk *clk, int enable) mask = CKCTL_6338_SPI_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_SPI_EN; - else if (BCMCPU_IS_6358()) + else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) mask = CKCTL_6358_SPI_EN; + else if (BCMCPU_IS_6362()) + mask = CKCTL_6362_SPI_EN; else /* BCMCPU_IS_6368 */ mask = CKCTL_6368_SPI_EN; @@ -207,6 +226,28 @@ static struct clk clk_spi = { }; /* + * HSSPI clock + */ +static void hsspi_set(struct clk *clk, int enable) +{ + u32 mask; + + if (BCMCPU_IS_6328()) + mask = CKCTL_6328_HSSPI_EN; + else if (BCMCPU_IS_6362()) + mask = CKCTL_6362_HSSPI_EN; + else + return; + + bcm_hwclock_set(mask, enable); +} + +static struct clk clk_hsspi = { + .set = hsspi_set, +}; + + +/* * XTM clock */ static void xtm_set(struct clk *clk, int enable) @@ -236,7 +277,10 @@ static struct clk clk_xtm = { */ static void ipsec_set(struct clk *clk, int enable) { - bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable); + if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable); + else if (BCMCPU_IS_6368()) + bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable); } static struct clk clk_ipsec = { @@ -249,7 +293,10 @@ static struct clk clk_ipsec = { static void pcie_set(struct clk *clk, int enable) { - bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable); + if (BCMCPU_IS_6328()) + bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable); + else if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable); } static struct clk clk_pcie = { @@ -293,6 +340,18 @@ unsigned long clk_get_rate(struct clk *clk) EXPORT_SYMBOL(clk_get_rate); +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} +EXPORT_SYMBOL_GPL(clk_set_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} +EXPORT_SYMBOL_GPL(clk_round_rate); + struct clk *clk_get(struct device *dev, const char *id) { if (!strcmp(id, "enet0")) @@ -309,15 +368,17 @@ struct clk *clk_get(struct device *dev, const char *id) return &clk_usbd; if (!strcmp(id, "spi")) return &clk_spi; + if (!strcmp(id, "hsspi")) + return &clk_hsspi; if (!strcmp(id, "xtm")) return &clk_xtm; if (!strcmp(id, "periph")) return &clk_periph; - if (BCMCPU_IS_6358() && !strcmp(id, "pcm")) + if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm")) return &clk_pcm; - if (BCMCPU_IS_6368() && !strcmp(id, "ipsec")) + if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec")) return &clk_ipsec; - if (BCMCPU_IS_6328() && !strcmp(id, "pcie")) + if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie")) return &clk_pcie; return ERR_PTR(-ENOENT); } @@ -329,3 +390,21 @@ void clk_put(struct clk *clk) } EXPORT_SYMBOL(clk_put); + +#define HSSPI_PLL_HZ_6328 133333333 +#define HSSPI_PLL_HZ_6362 400000000 + +static int __init bcm63xx_clk_init(void) +{ + switch (bcm63xx_get_cpu_id()) { + case BCM6328_CPU_ID: + clk_hsspi.rate = HSSPI_PLL_HZ_6328; + break; + case BCM6362_CPU_ID: + clk_hsspi.rate = HSSPI_PLL_HZ_6362; + break; + } + + return 0; +} +arch_initcall(bcm63xx_clk_init); diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index a7afb289b15..fd4e76c00a4 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -25,10 +25,18 @@ const int *bcm63xx_irqs; EXPORT_SYMBOL(bcm63xx_irqs); static u16 bcm63xx_cpu_id; -static u16 bcm63xx_cpu_rev; +static u8 bcm63xx_cpu_rev; static unsigned int bcm63xx_cpu_freq; static unsigned int bcm63xx_memory_size; +static const unsigned long bcm3368_regs_base[] = { + __GEN_CPU_REGS_TABLE(3368) +}; + +static const int bcm3368_irqs[] = { + __GEN_CPU_IRQ_TABLE(3368) +}; + static const unsigned long bcm6328_regs_base[] = { __GEN_CPU_REGS_TABLE(6328) }; @@ -71,6 +79,15 @@ static const int bcm6358_irqs[] = { }; +static const unsigned long bcm6362_regs_base[] = { + __GEN_CPU_REGS_TABLE(6362) +}; + +static const int bcm6362_irqs[] = { + __GEN_CPU_IRQ_TABLE(6362) + +}; + static const unsigned long bcm6368_regs_base[] = { __GEN_CPU_REGS_TABLE(6368) }; @@ -87,7 +104,7 @@ u16 __bcm63xx_get_cpu_id(void) EXPORT_SYMBOL(__bcm63xx_get_cpu_id); -u16 bcm63xx_get_cpu_rev(void) +u8 bcm63xx_get_cpu_rev(void) { return bcm63xx_cpu_rev; } @@ -106,7 +123,12 @@ unsigned int bcm63xx_get_memory_size(void) static unsigned int detect_cpu_clock(void) { - switch (bcm63xx_get_cpu_id()) { + u16 cpu_id = bcm63xx_get_cpu_id(); + + switch (cpu_id) { + case BCM3368_CPU_ID: + return 300000000; + case BCM6328_CPU_ID: { unsigned int tmp, mips_pll_fcvo; @@ -169,6 +191,42 @@ static unsigned int detect_cpu_clock(void) return (16 * 1000000 * n1 * n2) / m1; } + case BCM6362_CPU_ID: + { + unsigned int tmp, mips_pll_fcvo; + + tmp = bcm_misc_readl(MISC_STRAPBUS_6362_REG); + mips_pll_fcvo = (tmp & STRAPBUS_6362_FCVO_MASK) + >> STRAPBUS_6362_FCVO_SHIFT; + switch (mips_pll_fcvo) { + case 0x03: + case 0x0b: + case 0x13: + case 0x1b: + return 240000000; + case 0x04: + case 0x0c: + case 0x14: + case 0x1c: + return 160000000; + case 0x05: + case 0x0e: + case 0x16: + case 0x1e: + case 0x1f: + return 400000000; + case 0x06: + return 440000000; + case 0x07: + case 0x17: + return 384000000; + case 0x15: + case 0x1d: + return 200000000; + default: + return 320000000; + } + } case BCM6368_CPU_ID: { unsigned int tmp, p1, p2, ndiv, m1; @@ -193,7 +251,7 @@ static unsigned int detect_cpu_clock(void) } default: - BUG(); + panic("Failed to detect clock for CPU with id=%04X\n", cpu_id); } } @@ -205,7 +263,7 @@ static unsigned int detect_memory_size(void) unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0; u32 val; - if (BCMCPU_IS_6328()) + if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) return bcm_ddr_readl(DDR_CSEND_REG) << 24; if (BCMCPU_IS_6345()) { @@ -221,7 +279,7 @@ static unsigned int detect_memory_size(void) banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1; } - if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { + if (BCMCPU_IS_3368() || 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; @@ -240,52 +298,32 @@ static unsigned int detect_memory_size(void) void __init bcm63xx_cpu_init(void) { - unsigned int tmp, expected_cpu_id; - struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int tmp; unsigned int cpu = smp_processor_id(); + u32 chipid_reg; /* soc registers location depends on cpu type */ - expected_cpu_id = 0; + chipid_reg = 0; - switch (c->cputype) { + switch (current_cpu_type()) { case CPU_BMIPS3300: - if ((read_c0_prid() & 0xff00) == PRID_IMP_BMIPS3300_ALT) { - expected_cpu_id = BCM6348_CPU_ID; - bcm63xx_regs_base = bcm6348_regs_base; - bcm63xx_irqs = bcm6348_irqs; - } else { + if ((read_c0_prid() & PRID_IMP_MASK) != PRID_IMP_BMIPS3300_ALT) __cpu_name[cpu] = "Broadcom BCM6338"; - expected_cpu_id = BCM6338_CPU_ID; - bcm63xx_regs_base = bcm6338_regs_base; - bcm63xx_irqs = bcm6338_irqs; - } - break; + /* fall-through */ case CPU_BMIPS32: - expected_cpu_id = BCM6345_CPU_ID; - bcm63xx_regs_base = bcm6345_regs_base; - bcm63xx_irqs = bcm6345_irqs; + chipid_reg = BCM_6345_PERF_BASE; break; case CPU_BMIPS4350: - if ((read_c0_prid() & 0xf0) == 0x10) { - expected_cpu_id = BCM6358_CPU_ID; - bcm63xx_regs_base = bcm6358_regs_base; - bcm63xx_irqs = bcm6358_irqs; - } else { - /* all newer chips have the same chip id location */ - u16 chip_id = bcm_readw(BCM_6368_PERF_BASE); - - switch (chip_id) { - case BCM6328_CPU_ID: - expected_cpu_id = BCM6328_CPU_ID; - bcm63xx_regs_base = bcm6328_regs_base; - bcm63xx_irqs = bcm6328_irqs; - break; - case BCM6368_CPU_ID: - expected_cpu_id = BCM6368_CPU_ID; - bcm63xx_regs_base = bcm6368_regs_base; - bcm63xx_irqs = bcm6368_irqs; - break; - } + switch ((read_c0_prid() & PRID_REV_MASK)) { + case 0x04: + chipid_reg = BCM_3368_PERF_BASE; + break; + case 0x10: + chipid_reg = BCM_6345_PERF_BASE; + break; + default: + chipid_reg = BCM_6368_PERF_BASE; + break; } break; } @@ -294,20 +332,51 @@ void __init bcm63xx_cpu_init(void) * really early to panic, but delaying panic would not help since we * will never get any working console */ - if (!expected_cpu_id) + if (!chipid_reg) panic("unsupported Broadcom CPU"); - /* - * bcm63xx_regs_base is set, we can access soc registers - */ - - /* double check CPU type */ - tmp = bcm_perf_readl(PERF_REV_REG); + /* read out CPU type */ + tmp = bcm_readl(chipid_reg); bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT; bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT; - if (bcm63xx_cpu_id != expected_cpu_id) - panic("bcm63xx CPU id mismatch"); + switch (bcm63xx_cpu_id) { + case BCM3368_CPU_ID: + bcm63xx_regs_base = bcm3368_regs_base; + bcm63xx_irqs = bcm3368_irqs; + break; + case BCM6328_CPU_ID: + bcm63xx_regs_base = bcm6328_regs_base; + bcm63xx_irqs = bcm6328_irqs; + break; + case BCM6338_CPU_ID: + bcm63xx_regs_base = bcm6338_regs_base; + bcm63xx_irqs = bcm6338_irqs; + break; + case BCM6345_CPU_ID: + bcm63xx_regs_base = bcm6345_regs_base; + bcm63xx_irqs = bcm6345_irqs; + break; + case BCM6348_CPU_ID: + bcm63xx_regs_base = bcm6348_regs_base; + bcm63xx_irqs = bcm6348_irqs; + break; + case BCM6358_CPU_ID: + bcm63xx_regs_base = bcm6358_regs_base; + bcm63xx_irqs = bcm6358_irqs; + break; + case BCM6362_CPU_ID: + bcm63xx_regs_base = bcm6362_regs_base; + bcm63xx_irqs = bcm6362_irqs; + break; + case BCM6368_CPU_ID: + bcm63xx_regs_base = bcm6368_regs_base; + bcm63xx_irqs = bcm6368_irqs; + break; + default: + panic("unsupported broadcom CPU %x", bcm63xx_cpu_id); + break; + } bcm63xx_cpu_freq = detect_cpu_clock(); bcm63xx_memory_size = detect_memory_size(); diff --git a/arch/mips/bcm63xx/dev-enet.c b/arch/mips/bcm63xx/dev-enet.c index 39c23366c5c..52bc01df9bf 100644 --- a/arch/mips/bcm63xx/dev-enet.c +++ b/arch/mips/bcm63xx/dev-enet.c @@ -9,16 +9,60 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/platform_device.h> +#include <linux/export.h> #include <bcm63xx_dev_enet.h> #include <bcm63xx_io.h> #include <bcm63xx_regs.h> +#ifdef BCMCPU_RUNTIME_DETECT +static const unsigned long bcm6348_regs_enetdmac[] = { + [ENETDMAC_CHANCFG] = ENETDMAC_CHANCFG_REG, + [ENETDMAC_IR] = ENETDMAC_IR_REG, + [ENETDMAC_IRMASK] = ENETDMAC_IRMASK_REG, + [ENETDMAC_MAXBURST] = ENETDMAC_MAXBURST_REG, +}; + +static const unsigned long bcm6345_regs_enetdmac[] = { + [ENETDMAC_CHANCFG] = ENETDMA_6345_CHANCFG_REG, + [ENETDMAC_IR] = ENETDMA_6345_IR_REG, + [ENETDMAC_IRMASK] = ENETDMA_6345_IRMASK_REG, + [ENETDMAC_MAXBURST] = ENETDMA_6345_MAXBURST_REG, + [ENETDMAC_BUFALLOC] = ENETDMA_6345_BUFALLOC_REG, + [ENETDMAC_RSTART] = ENETDMA_6345_RSTART_REG, + [ENETDMAC_FC] = ENETDMA_6345_FC_REG, + [ENETDMAC_LEN] = ENETDMA_6345_LEN_REG, +}; + +const unsigned long *bcm63xx_regs_enetdmac; +EXPORT_SYMBOL(bcm63xx_regs_enetdmac); + +static __init void bcm63xx_enetdmac_regs_init(void) +{ + if (BCMCPU_IS_6345()) + bcm63xx_regs_enetdmac = bcm6345_regs_enetdmac; + else + bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac; +} +#else +static __init void bcm63xx_enetdmac_regs_init(void) { } +#endif + static struct resource shared_res[] = { { .start = -1, /* filled at runtime */ .end = -1, /* filled at runtime */ .flags = IORESOURCE_MEM, }, + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, }; static struct platform_device bcm63xx_enet_shared_device = { @@ -94,6 +138,71 @@ static struct platform_device bcm63xx_enet1_device = { }, }; +static struct resource enetsw_res[] = { + { + /* start & end filled at runtime */ + .flags = IORESOURCE_MEM, + }, + { + /* start filled at runtime */ + .flags = IORESOURCE_IRQ, + }, + { + /* start filled at runtime */ + .flags = IORESOURCE_IRQ, + }, +}; + +static struct bcm63xx_enetsw_platform_data enetsw_pd; + +static struct platform_device bcm63xx_enetsw_device = { + .name = "bcm63xx_enetsw", + .num_resources = ARRAY_SIZE(enetsw_res), + .resource = enetsw_res, + .dev = { + .platform_data = &enetsw_pd, + }, +}; + +static int __init register_shared(void) +{ + int ret, chan_count; + + if (shared_device_registered) + return 0; + + bcm63xx_enetdmac_regs_init(); + + shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); + shared_res[0].end = shared_res[0].start; + if (BCMCPU_IS_6345()) + shared_res[0].end += (RSET_6345_ENETDMA_SIZE) - 1; + else + shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; + + if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) + chan_count = 32; + else if (BCMCPU_IS_6345()) + chan_count = 8; + else + chan_count = 16; + + shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC); + shared_res[1].end = shared_res[1].start; + shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1; + + shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS); + shared_res[2].end = shared_res[2].start; + shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1; + + ret = platform_device_register(&bcm63xx_enet_shared_device); + if (ret) + return ret; + shared_device_registered = 1; + + return 0; +} + int __init bcm63xx_enet_register(int unit, const struct bcm63xx_enet_platform_data *pd) { @@ -104,22 +213,12 @@ int __init bcm63xx_enet_register(int unit, if (unit > 1) return -ENODEV; - if (unit == 1 && BCMCPU_IS_6338()) + if (unit == 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345())) return -ENODEV; - if (!shared_device_registered) { - shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); - shared_res[0].end = shared_res[0].start; - if (BCMCPU_IS_6338()) - shared_res[0].end += (RSET_ENETDMA_SIZE / 2) - 1; - else - shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; - - ret = platform_device_register(&bcm63xx_enet_shared_device); - if (ret) - return ret; - shared_device_registered = 1; - } + ret = register_shared(); + if (ret) + return ret; if (unit == 0) { enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0); @@ -155,8 +254,62 @@ int __init bcm63xx_enet_register(int unit, dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY); } + dpd->dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK; + dpd->dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK; + if (BCMCPU_IS_6345()) { + dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_CHAINING_MASK; + dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_WRAP_EN_MASK; + dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_FLOWC_EN_MASK; + dpd->dma_chan_int_mask |= ENETDMA_IR_BUFDONE_MASK; + dpd->dma_chan_int_mask |= ENETDMA_IR_NOTOWNER_MASK; + dpd->dma_chan_width = ENETDMA_6345_CHAN_WIDTH; + dpd->dma_desc_shift = ENETDMA_6345_DESC_SHIFT; + } else { + dpd->dma_has_sram = true; + dpd->dma_chan_width = ENETDMA_CHAN_WIDTH; + } + ret = platform_device_register(pdev); if (ret) return ret; return 0; } + +int __init +bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd) +{ + int ret; + + if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368()) + return -ENODEV; + + ret = register_shared(); + if (ret) + return ret; + + enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW); + enetsw_res[0].end = enetsw_res[0].start; + enetsw_res[0].end += RSET_ENETSW_SIZE - 1; + enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0); + enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0); + if (!enetsw_res[2].start) + enetsw_res[2].start = -1; + + memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd)); + + if (BCMCPU_IS_6328()) + enetsw_pd.num_ports = ENETSW_PORTS_6328; + else if (BCMCPU_IS_6362() || BCMCPU_IS_6368()) + enetsw_pd.num_ports = ENETSW_PORTS_6368; + + enetsw_pd.dma_has_sram = true; + enetsw_pd.dma_chan_width = ENETDMA_CHAN_WIDTH; + enetsw_pd.dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK; + enetsw_pd.dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK; + + ret = platform_device_register(&bcm63xx_enetsw_device); + if (ret) + return ret; + + return 0; +} diff --git a/arch/mips/bcm63xx/dev-flash.c b/arch/mips/bcm63xx/dev-flash.c index 58371c7deac..172dd839717 100644 --- a/arch/mips/bcm63xx/dev-flash.c +++ b/arch/mips/bcm63xx/dev-flash.c @@ -71,12 +71,19 @@ static int __init bcm63xx_detect_flash_type(void) case BCM6348_CPU_ID: /* no way to auto detect so assume parallel */ return BCM63XX_FLASH_TYPE_PARALLEL; + case BCM3368_CPU_ID: case BCM6358_CPU_ID: val = bcm_gpio_readl(GPIO_STRAPBUS_REG); if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL) return BCM63XX_FLASH_TYPE_PARALLEL; else return BCM63XX_FLASH_TYPE_SERIAL; + case BCM6362_CPU_ID: + val = bcm_misc_readl(MISC_STRAPBUS_6362_REG); + if (val & STRAPBUS_6362_BOOT_SEL_SERIAL) + return BCM63XX_FLASH_TYPE_SERIAL; + else + return BCM63XX_FLASH_TYPE_NAND; case BCM6368_CPU_ID: val = bcm_gpio_readl(GPIO_STRAPBUS_REG); switch (val & STRAPBUS_6368_BOOT_SEL_MASK) { diff --git a/arch/mips/bcm63xx/dev-hsspi.c b/arch/mips/bcm63xx/dev-hsspi.c new file mode 100644 index 00000000000..696abc48e3c --- /dev/null +++ b/arch/mips/bcm63xx/dev-hsspi.c @@ -0,0 +1,47 @@ +/* + * 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) 2012 Jonas Gorski <jonas.gorski@gmail.com> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <bcm63xx_cpu.h> +#include <bcm63xx_dev_hsspi.h> +#include <bcm63xx_regs.h> + +static struct resource spi_resources[] = { + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, + { + .start = -1, /* filled at runtime */ + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bcm63xx_hsspi_device = { + .name = "bcm63xx-hsspi", + .id = 0, + .num_resources = ARRAY_SIZE(spi_resources), + .resource = spi_resources, +}; + +int __init bcm63xx_hsspi_register(void) +{ + if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362()) + return -ENODEV; + + spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI); + spi_resources[0].end = spi_resources[0].start; + spi_resources[0].end += RSET_HSSPI_SIZE - 1; + spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI); + + return platform_device_register(&bcm63xx_hsspi_device); +} diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c index f1c9c3e2f67..d12daed749b 100644 --- a/arch/mips/bcm63xx/dev-spi.c +++ b/arch/mips/bcm63xx/dev-spi.c @@ -22,10 +22,6 @@ /* * register offsets */ -static const unsigned long bcm6338_regs_spi[] = { - __GEN_SPI_REGS_TABLE(6338) -}; - static const unsigned long bcm6348_regs_spi[] = { __GEN_SPI_REGS_TABLE(6348) }; @@ -34,23 +30,16 @@ static const unsigned long bcm6358_regs_spi[] = { __GEN_SPI_REGS_TABLE(6358) }; -static const unsigned long bcm6368_regs_spi[] = { - __GEN_SPI_REGS_TABLE(6368) -}; - const unsigned long *bcm63xx_regs_spi; EXPORT_SYMBOL(bcm63xx_regs_spi); static __init void bcm63xx_spi_regs_init(void) { - if (BCMCPU_IS_6338()) - bcm63xx_regs_spi = bcm6338_regs_spi; - if (BCMCPU_IS_6348()) + if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) bcm63xx_regs_spi = bcm6348_regs_spi; - if (BCMCPU_IS_6358()) + if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || + BCMCPU_IS_6362() || BCMCPU_IS_6368()) bcm63xx_regs_spi = bcm6358_regs_spi; - if (BCMCPU_IS_6368()) - bcm63xx_regs_spi = bcm6368_regs_spi; } #else static __init void bcm63xx_spi_regs_init(void) { } @@ -85,32 +74,22 @@ static struct platform_device bcm63xx_spi_device = { int __init bcm63xx_spi_register(void) { - struct clk *periph_clk; - if (BCMCPU_IS_6328() || BCMCPU_IS_6345()) return -ENODEV; - periph_clk = clk_get(NULL, "periph"); - if (IS_ERR(periph_clk)) { - pr_err("unable to get periph clock\n"); - return -ENODEV; - } - - /* Set bus frequency */ - spi_pdata.speed_hz = clk_get_rate(periph_clk); - spi_resources[0].start = bcm63xx_regset_address(RSET_SPI); spi_resources[0].end = spi_resources[0].start; spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { - spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1; - spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE; - spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT; - spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH; + spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1; + spi_pdata.fifo_size = SPI_6348_MSG_DATA_SIZE; + spi_pdata.msg_type_shift = SPI_6348_MSG_TYPE_SHIFT; + spi_pdata.msg_ctl_width = SPI_6348_MSG_CTL_WIDTH; } - if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { + if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() || + BCMCPU_IS_6368()) { spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT; diff --git a/arch/mips/bcm63xx/dev-uart.c b/arch/mips/bcm63xx/dev-uart.c index d6e42c60832..3bc7f3bfc9a 100644 --- a/arch/mips/bcm63xx/dev-uart.c +++ b/arch/mips/bcm63xx/dev-uart.c @@ -54,7 +54,8 @@ int __init bcm63xx_uart_register(unsigned int id) if (id >= ARRAY_SIZE(bcm63xx_uart_devices)) return -ENODEV; - if (id == 1 && (!BCMCPU_IS_6358() && !BCMCPU_IS_6368())) + if (id == 1 && (!BCMCPU_IS_3368() && !BCMCPU_IS_6358() && + !BCMCPU_IS_6368())) return -ENODEV; if (id == 0) { diff --git a/arch/mips/bcm63xx/early_printk.c b/arch/mips/bcm63xx/early_printk.c index bf353c937df..6092226a6d7 100644 --- a/arch/mips/bcm63xx/early_printk.c +++ b/arch/mips/bcm63xx/early_printk.c @@ -6,11 +6,10 @@ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> */ -#include <linux/init.h> #include <bcm63xx_io.h> -#include <bcm63xx_regs.h> +#include <linux/serial_bcm63xx.h> -static void __init wait_xfered(void) +static void wait_xfered(void) { unsigned int val; @@ -22,7 +21,7 @@ static void __init wait_xfered(void) } while (1); } -void __init prom_putchar(char c) +void prom_putchar(char c) { wait_xfered(); bcm_uart0_writel(c, UART_FIFO_REG); diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index da24c2bd9b7..1525f8a3841 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -27,6 +27,17 @@ 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_3368 +#define irq_stat_reg PERF_IRQSTAT_3368_REG +#define irq_mask_reg PERF_IRQMASK_3368_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_3368 +#define ext_irq_cfg_reg2 0 +#endif #ifdef CONFIG_BCM63XX_CPU_6328 #define irq_stat_reg PERF_IRQSTAT_6328_REG #define irq_mask_reg PERF_IRQMASK_6328_REG @@ -82,6 +93,17 @@ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; #define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358 #define ext_irq_cfg_reg2 0 #endif +#ifdef CONFIG_BCM63XX_CPU_6362 +#define irq_stat_reg PERF_IRQSTAT_6362_REG +#define irq_mask_reg PERF_IRQMASK_6362_REG +#define irq_bits 64 +#define is_ext_irq_cascaded 1 +#define ext_irq_start (BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE) +#define ext_irq_end (BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE) +#define ext_irq_count 4 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6362 +#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 @@ -129,6 +151,13 @@ static void bcm63xx_init_irq(void) irq_mask_addr = bcm63xx_regset_address(RSET_PERF); switch (bcm63xx_get_cpu_id()) { + case BCM3368_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_3368_REG; + irq_mask_addr += PERF_IRQMASK_3368_REG; + irq_bits = 32; + ext_irq_count = 4; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368; + break; case BCM6328_CPU_ID: irq_stat_addr += PERF_IRQSTAT_6328_REG; irq_mask_addr += PERF_IRQMASK_6328_REG; @@ -170,6 +199,16 @@ static void bcm63xx_init_irq(void) ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358; break; + case BCM6362_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6362_REG; + irq_mask_addr += PERF_IRQMASK_6362_REG; + irq_bits = 64; + ext_irq_count = 4; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362; + break; case BCM6368_CPU_ID: irq_stat_addr += PERF_IRQSTAT_6368_REG; irq_mask_addr += PERF_IRQMASK_6368_REG; @@ -273,6 +312,10 @@ asmlinkage void plat_irq_dispatch(void) if (cause & CAUSEF_IP7) do_IRQ(7); + if (cause & CAUSEF_IP0) + do_IRQ(0); + if (cause & CAUSEF_IP1) + do_IRQ(1); if (cause & CAUSEF_IP2) dispatch_internal(); if (!is_ext_irq_cascaded) { @@ -454,10 +497,12 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d, reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq); break; + case BCM3368_CPU_ID: case BCM6328_CPU_ID: case BCM6338_CPU_ID: case BCM6345_CPU_ID: case BCM6358_CPU_ID: + case BCM6362_CPU_ID: case BCM6368_CPU_ID: if (levelsense) reg |= EXTIRQ_CFG_LEVELSENSE(irq); diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c index 62061168083..4b50d40f745 100644 --- a/arch/mips/bcm63xx/nvram.c +++ b/arch/mips/bcm63xx/nvram.c @@ -35,13 +35,16 @@ struct bcm963xx_nvram { u32 checksum_high; }; +#define BCM63XX_DEFAULT_PSI_SIZE 64 + static struct bcm963xx_nvram nvram; static int mac_addr_used; -int __init bcm63xx_nvram_init(void *addr) +void __init bcm63xx_nvram_init(void *addr) { unsigned int check_len; u32 crc, expected_crc; + u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff }; /* extract nvram data */ memcpy(&nvram, addr, sizeof(nvram)); @@ -60,9 +63,17 @@ int __init bcm63xx_nvram_init(void *addr) crc = crc32_le(~0, (u8 *)&nvram, check_len); if (crc != expected_crc) - return -EINVAL; - - return 0; + pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n", + expected_crc, crc); + + /* Cable modems have a different NVRAM which is embedded in the eCos + * firmware and not easily extractible, give at least a MAC address + * pool. + */ + if (BCMCPU_IS_3368()) { + memcpy(nvram.mac_addr_base, hcs_mac_addr, ETH_ALEN); + nvram.mac_addr_count = 2; + } } u8 *bcm63xx_nvram_get_name(void) @@ -105,3 +116,12 @@ int bcm63xx_nvram_get_mac_address(u8 *mac) return 0; } EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address); + +int bcm63xx_nvram_get_psi_size(void) +{ + if (nvram.psi_size > 0) + return nvram.psi_size; + + return BCM63XX_DEFAULT_PSI_SIZE; +} +EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size); diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index 10eaff45807..e1f27d653f6 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -8,7 +8,11 @@ #include <linux/init.h> #include <linux/bootmem.h> +#include <linux/smp.h> #include <asm/bootinfo.h> +#include <asm/bmips.h> +#include <asm/smp-ops.h> +#include <asm/mipsregs.h> #include <bcm63xx_board.h> #include <bcm63xx_cpu.h> #include <bcm63xx_io.h> @@ -26,7 +30,9 @@ void __init prom_init(void) bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG); /* disable all hardware blocks clock for now */ - if (BCMCPU_IS_6328()) + if (BCMCPU_IS_3368()) + mask = CKCTL_3368_ALL_SAFE_EN; + else if (BCMCPU_IS_6328()) mask = CKCTL_6328_ALL_SAFE_EN; else if (BCMCPU_IS_6338()) mask = CKCTL_6338_ALL_SAFE_EN; @@ -36,6 +42,8 @@ void __init prom_init(void) mask = CKCTL_6348_ALL_SAFE_EN; else if (BCMCPU_IS_6358()) mask = CKCTL_6358_ALL_SAFE_EN; + else if (BCMCPU_IS_6362()) + mask = CKCTL_6362_ALL_SAFE_EN; else if (BCMCPU_IS_6368()) mask = CKCTL_6368_ALL_SAFE_EN; else @@ -50,6 +58,45 @@ void __init prom_init(void) /* do low level board init */ board_prom_init(); + + /* set up SMP */ + if (!register_bmips_smp_ops()) { + /* + * BCM6328 might not have its second CPU enabled, while BCM3368 + * and BCM6358 need special handling for their shared TLB, so + * disable SMP for now. + */ + if (BCMCPU_IS_6328()) { + reg = bcm_readl(BCM_6328_OTP_BASE + + OTP_USER_BITS_6328_REG(3)); + + if (reg & OTP_6328_REG3_TP1_DISABLED) + bmips_smp_enabled = 0; + } else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) { + bmips_smp_enabled = 0; + } + + if (!bmips_smp_enabled) + return; + + /* + * The bootloader has set up the CPU1 reset vector at + * 0xa000_0200. + * This conflicts with the special interrupt vector (IV). + * The bootloader has also set up CPU1 to respond to the wrong + * IPI interrupt. + * Here we will start up CPU1 in the background and ask it to + * reconfigure itself then go back to sleep. + */ + memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20); + __sync(); + set_c0_cause(C_SW0); + cpumask_set_cpu(1, &bmips_booted_mask); + + /* + * FIXME: we really should have some sort of hazard barrier here + */ + } } void __init prom_free_prom_memory(void) diff --git a/arch/mips/bcm63xx/reset.c b/arch/mips/bcm63xx/reset.c index 68a31bb90cb..acbeb1fe7c5 100644 --- a/arch/mips/bcm63xx/reset.c +++ b/arch/mips/bcm63xx/reset.c @@ -30,6 +30,19 @@ [BCM63XX_RESET_PCIE] = BCM## __cpu ##_RESET_PCIE, \ [BCM63XX_RESET_PCIE_EXT] = BCM## __cpu ##_RESET_PCIE_EXT, +#define BCM3368_RESET_SPI SOFTRESET_3368_SPI_MASK +#define BCM3368_RESET_ENET SOFTRESET_3368_ENET_MASK +#define BCM3368_RESET_USBH 0 +#define BCM3368_RESET_USBD SOFTRESET_3368_USBS_MASK +#define BCM3368_RESET_DSL 0 +#define BCM3368_RESET_SAR 0 +#define BCM3368_RESET_EPHY SOFTRESET_3368_EPHY_MASK +#define BCM3368_RESET_ENETSW 0 +#define BCM3368_RESET_PCM SOFTRESET_3368_PCM_MASK +#define BCM3368_RESET_MPI SOFTRESET_3368_MPI_MASK +#define BCM3368_RESET_PCIE 0 +#define BCM3368_RESET_PCIE_EXT 0 + #define BCM6328_RESET_SPI SOFTRESET_6328_SPI_MASK #define BCM6328_RESET_ENET 0 #define BCM6328_RESET_USBH SOFTRESET_6328_USBH_MASK @@ -85,6 +98,20 @@ #define BCM6358_RESET_PCIE 0 #define BCM6358_RESET_PCIE_EXT 0 +#define BCM6362_RESET_SPI SOFTRESET_6362_SPI_MASK +#define BCM6362_RESET_ENET 0 +#define BCM6362_RESET_USBH SOFTRESET_6362_USBH_MASK +#define BCM6362_RESET_USBD SOFTRESET_6362_USBS_MASK +#define BCM6362_RESET_DSL 0 +#define BCM6362_RESET_SAR SOFTRESET_6362_SAR_MASK +#define BCM6362_RESET_EPHY SOFTRESET_6362_EPHY_MASK +#define BCM6362_RESET_ENETSW SOFTRESET_6362_ENETSW_MASK +#define BCM6362_RESET_PCM SOFTRESET_6362_PCM_MASK +#define BCM6362_RESET_MPI 0 +#define BCM6362_RESET_PCIE (SOFTRESET_6362_PCIE_MASK | \ + SOFTRESET_6362_PCIE_CORE_MASK) +#define BCM6362_RESET_PCIE_EXT SOFTRESET_6362_PCIE_EXT_MASK + #define BCM6368_RESET_SPI SOFTRESET_6368_SPI_MASK #define BCM6368_RESET_ENET 0 #define BCM6368_RESET_USBH SOFTRESET_6368_USBH_MASK @@ -103,6 +130,10 @@ /* * core reset bits */ +static const u32 bcm3368_reset_bits[] = { + __GEN_RESET_BITS_TABLE(3368) +}; + static const u32 bcm6328_reset_bits[] = { __GEN_RESET_BITS_TABLE(6328) }; @@ -119,6 +150,10 @@ static const u32 bcm6358_reset_bits[] = { __GEN_RESET_BITS_TABLE(6358) }; +static const u32 bcm6362_reset_bits[] = { + __GEN_RESET_BITS_TABLE(6362) +}; + static const u32 bcm6368_reset_bits[] = { __GEN_RESET_BITS_TABLE(6368) }; @@ -128,7 +163,10 @@ static int reset_reg; static int __init bcm63xx_reset_bits_init(void) { - if (BCMCPU_IS_6328()) { + if (BCMCPU_IS_3368()) { + reset_reg = PERF_SOFTRESET_6358_REG; + bcm63xx_reset_bits = bcm3368_reset_bits; + } else if (BCMCPU_IS_6328()) { reset_reg = PERF_SOFTRESET_6328_REG; bcm63xx_reset_bits = bcm6328_reset_bits; } else if (BCMCPU_IS_6338()) { @@ -140,6 +178,9 @@ static int __init bcm63xx_reset_bits_init(void) } else if (BCMCPU_IS_6358()) { reset_reg = PERF_SOFTRESET_6358_REG; bcm63xx_reset_bits = bcm6358_reset_bits; + } else if (BCMCPU_IS_6362()) { + reset_reg = PERF_SOFTRESET_6362_REG; + bcm63xx_reset_bits = bcm6362_reset_bits; } else if (BCMCPU_IS_6368()) { reset_reg = PERF_SOFTRESET_6368_REG; bcm63xx_reset_bits = bcm6368_reset_bits; @@ -149,6 +190,13 @@ static int __init bcm63xx_reset_bits_init(void) } #else +#ifdef CONFIG_BCM63XX_CPU_3368 +static const u32 bcm63xx_reset_bits[] = { + __GEN_RESET_BITS_TABLE(3368) +}; +#define reset_reg PERF_SOFTRESET_6358_REG +#endif + #ifdef CONFIG_BCM63XX_CPU_6328 static const u32 bcm63xx_reset_bits[] = { __GEN_RESET_BITS_TABLE(6328) @@ -182,6 +230,13 @@ static const u32 bcm63xx_reset_bits[] = { #define reset_reg PERF_SOFTRESET_6358_REG #endif +#ifdef CONFIG_BCM63XX_CPU_6362 +static const u32 bcm63xx_reset_bits[] = { + __GEN_RESET_BITS_TABLE(6362) +}; +#define reset_reg PERF_SOFTRESET_6362_REG +#endif + #ifdef CONFIG_BCM63XX_CPU_6368 static const u32 bcm63xx_reset_bits[] = { __GEN_RESET_BITS_TABLE(6368) diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index 314231be788..6660c7ddf87 100644 --- a/arch/mips/bcm63xx/setup.c +++ b/arch/mips/bcm63xx/setup.c @@ -68,6 +68,9 @@ void bcm63xx_machine_reboot(void) /* mask and clear all external irq */ switch (bcm63xx_get_cpu_id()) { + case BCM3368_CPU_ID: + perf_regs[0] = PERF_EXTIRQ_CFG_REG_3368; + break; case BCM6328_CPU_ID: perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328; break; @@ -83,6 +86,9 @@ void bcm63xx_machine_reboot(void) case BCM6358_CPU_ID: perf_regs[0] = PERF_EXTIRQ_CFG_REG_6358; break; + case BCM6362_CPU_ID: + perf_regs[0] = PERF_EXTIRQ_CFG_REG_6362; + break; } for (i = 0; i < 2; i++) { @@ -126,7 +132,7 @@ static void __bcm63xx_machine_reboot(char *p) const char *get_system_type(void) { static char buf[128]; - snprintf(buf, sizeof(buf), "bcm63xx/%s (0x%04x/0x%04X)", + snprintf(buf, sizeof(buf), "bcm63xx/%s (0x%04x/0x%02X)", board_get_name(), bcm63xx_get_cpu_id(), bcm63xx_get_cpu_rev()); return buf; @@ -157,4 +163,4 @@ int __init bcm63xx_register_devices(void) return board_register_devices(); } -device_initcall(bcm63xx_register_devices); +arch_initcall(bcm63xx_register_devices); |
