aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/bcm63xx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/bcm63xx')
-rw-r--r--arch/mips/bcm63xx/Kconfig21
-rw-r--r--arch/mips/bcm63xx/Makefile7
-rw-r--r--arch/mips/bcm63xx/boards/board_bcm963xx.c160
-rw-r--r--arch/mips/bcm63xx/clk.c145
-rw-r--r--arch/mips/bcm63xx/cpu.c173
-rw-r--r--arch/mips/bcm63xx/dev-enet.c181
-rw-r--r--arch/mips/bcm63xx/dev-flash.c7
-rw-r--r--arch/mips/bcm63xx/dev-hsspi.c47
-rw-r--r--arch/mips/bcm63xx/dev-spi.c39
-rw-r--r--arch/mips/bcm63xx/dev-uart.c3
-rw-r--r--arch/mips/bcm63xx/early_printk.c7
-rw-r--r--arch/mips/bcm63xx/irq.c45
-rw-r--r--arch/mips/bcm63xx/nvram.c127
-rw-r--r--arch/mips/bcm63xx/prom.c49
-rw-r--r--arch/mips/bcm63xx/reset.c278
-rw-r--r--arch/mips/bcm63xx/setup.c10
16 files changed, 1079 insertions, 220 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 9bbb30a9dc2..9019f54aee6 100644
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -1,6 +1,7 @@
-obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
- dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
- dev-spi.o dev-uart.o dev-wdt.o dev-usb-usbd.o
+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-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 1cd4d73f23c..33727e7f0c7 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -18,22 +18,58 @@
#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
+#include <bcm63xx_nvram.h>
#include <bcm63xx_dev_pci.h>
#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: "
-static struct bcm963xx_nvram nvram;
-static unsigned int mac_addr_used;
+#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
@@ -407,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,
@@ -592,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,
@@ -640,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
@@ -678,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,
@@ -716,58 +755,23 @@ const char *board_get_name(void)
}
/*
- * register & return a new board mac address
- */
-static int board_get_mac_address(u8 *mac)
-{
- u8 *oui;
- int count;
-
- if (mac_addr_used >= nvram.mac_addr_count) {
- printk(KERN_ERR PFX "not enough mac address\n");
- return -ENODEV;
- }
-
- memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
- oui = mac + ETH_ALEN/2 - 1;
- count = mac_addr_used;
-
- while (count--) {
- u8 *p = mac + ETH_ALEN - 1;
-
- do {
- (*p)++;
- if (*p != 0)
- break;
- p--;
- } while (p != oui);
-
- if (p == oui) {
- printk(KERN_ERR PFX "unable to fetch mac address\n");
- return -ENODEV;
- }
- }
-
- mac_addr_used++;
- return 0;
-}
-
-/*
* early init callback, read nvram data from flash and checksum it
*/
void __init board_prom_init(void)
{
- unsigned int check_len, i;
- u8 *boot_addr, *cfe, *p;
+ unsigned int i;
+ u8 *boot_addr, *cfe;
char cfe_version[32];
+ 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;
}
@@ -782,27 +786,17 @@ void __init board_prom_init(void)
strcpy(cfe_version, "unknown");
printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
- /* extract nvram data */
- memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
+ bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET);
- /* check checksum before using data */
- if (nvram.version <= 4)
- check_len = offsetof(struct bcm963xx_nvram, checksum_old);
- else
- check_len = sizeof(nvram);
- val = 0;
- p = (u8 *)&nvram;
- while (check_len--)
- val += *p;
- if (val) {
- printk(KERN_ERR PFX "invalid nvram checksum\n");
- return;
+ 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(nvram.name, bcm963xx_boards[i]->name,
- sizeof(nvram.name)))
+ if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
continue;
/* copy, board desc array is marked initdata */
memcpy(&board, bcm963xx_boards[i], sizeof(board));
@@ -812,7 +806,7 @@ void __init board_prom_init(void)
/* bail out if board is not found, will complain later */
if (!board.name[0]) {
char name[17];
- memcpy(name, nvram.name, 16);
+ memcpy(name, board_name, 16);
name[16] = 0;
printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
name);
@@ -890,13 +884,17 @@ int __init board_register_devices(void)
bcm63xx_pcmcia_register();
if (board.has_enet0 &&
- !board_get_mac_address(board.enet0.mac_addr))
+ !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
bcm63xx_enet_register(0, &board.enet0);
if (board.has_enet1 &&
- !board_get_mac_address(board.enet1.mac_addr))
+ !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);
@@ -907,7 +905,7 @@ int __init board_register_devices(void)
* do this after registering enet devices
*/
#ifdef CONFIG_SSB_PCIHOST
- if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
+ if (!bcm63xx_nvram_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(
@@ -918,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);
@@ -925,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 dff79ab6005..63756528473 100644
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -14,7 +14,14 @@
#include <bcm63xx_cpu.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
-#include <bcm63xx_clk.h>
+#include <bcm63xx_reset.h>
+
+struct clk {
+ void (*set)(struct clk *, int);
+ unsigned int rate;
+ unsigned int usage;
+ int id;
+};
static DEFINE_MUTEX(clocks_mutex);
@@ -77,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)
@@ -103,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);
}
@@ -118,21 +124,23 @@ 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) {
- u32 val;
+ if (enable) {
/* 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);
+ bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
msleep(10);
- val |= SOFTRESET_6368_ENETSW_MASK;
- bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+ bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
msleep(10);
}
}
@@ -146,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 = {
@@ -164,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);
}
@@ -179,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);
}
@@ -198,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;
@@ -211,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)
@@ -222,15 +259,10 @@ static void xtm_set(struct clk *clk, int enable)
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);
+ bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
mdelay(1);
- val |= SOFTRESET_6368_SAR_MASK;
- bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+ bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
mdelay(1);
}
}
@@ -245,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 = {
@@ -253,6 +288,22 @@ static struct clk clk_ipsec = {
};
/*
+ * PCIe clock
+ */
+
+static void pcie_set(struct clk *clk, int 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 = {
+ .set = pcie_set,
+};
+
+/*
* Internal peripheral clock
*/
static struct clk clk_periph = {
@@ -289,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"))
@@ -305,14 +368,18 @@ 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() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
+ return &clk_pcie;
return ERR_PTR(-ENOENT);
}
@@ -323,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 = &current_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
new file mode 100644
index 00000000000..4b50d40f745
--- /dev/null
+++ b/arch/mips/bcm63xx/nvram.c
@@ -0,0 +1,127 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
+
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+
+#include <bcm63xx_nvram.h>
+
+/*
+ * nvram structure
+ */
+struct bcm963xx_nvram {
+ u32 version;
+ u8 reserved1[256];
+ u8 name[16];
+ u32 main_tp_number;
+ u32 psi_size;
+ u32 mac_addr_count;
+ u8 mac_addr_base[ETH_ALEN];
+ u8 reserved2[2];
+ u32 checksum_old;
+ u8 reserved3[720];
+ u32 checksum_high;
+};
+
+#define BCM63XX_DEFAULT_PSI_SIZE 64
+
+static struct bcm963xx_nvram nvram;
+static int mac_addr_used;
+
+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));
+
+ /* check checksum before using data */
+ if (nvram.version <= 4) {
+ check_len = offsetof(struct bcm963xx_nvram, reserved3);
+ expected_crc = nvram.checksum_old;
+ nvram.checksum_old = 0;
+ } else {
+ check_len = sizeof(nvram);
+ expected_crc = nvram.checksum_high;
+ nvram.checksum_high = 0;
+ }
+
+ crc = crc32_le(~0, (u8 *)&nvram, check_len);
+
+ if (crc != expected_crc)
+ 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)
+{
+ return nvram.name;
+}
+EXPORT_SYMBOL(bcm63xx_nvram_get_name);
+
+int bcm63xx_nvram_get_mac_address(u8 *mac)
+{
+ u8 *oui;
+ int count;
+
+ if (mac_addr_used >= nvram.mac_addr_count) {
+ pr_err("not enough mac addresses\n");
+ return -ENODEV;
+ }
+
+ memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
+ oui = mac + ETH_ALEN/2 - 1;
+ count = mac_addr_used;
+
+ while (count--) {
+ u8 *p = mac + ETH_ALEN - 1;
+
+ do {
+ (*p)++;
+ if (*p != 0)
+ break;
+ p--;
+ } while (p != oui);
+
+ if (p == oui) {
+ pr_err("unable to fetch mac address\n");
+ return -ENODEV;
+ }
+ }
+
+ mac_addr_used++;
+ 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
new file mode 100644
index 00000000000..acbeb1fe7c5
--- /dev/null
+++ b/arch/mips/bcm63xx/reset.c
@@ -0,0 +1,278 @@
+/*
+ * 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/module.h>
+#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>
+#include <bcm63xx_reset.h>
+
+#define __GEN_RESET_BITS_TABLE(__cpu) \
+ [BCM63XX_RESET_SPI] = BCM## __cpu ##_RESET_SPI, \
+ [BCM63XX_RESET_ENET] = BCM## __cpu ##_RESET_ENET, \
+ [BCM63XX_RESET_USBH] = BCM## __cpu ##_RESET_USBH, \
+ [BCM63XX_RESET_USBD] = BCM## __cpu ##_RESET_USBD, \
+ [BCM63XX_RESET_DSL] = BCM## __cpu ##_RESET_DSL, \
+ [BCM63XX_RESET_SAR] = BCM## __cpu ##_RESET_SAR, \
+ [BCM63XX_RESET_EPHY] = BCM## __cpu ##_RESET_EPHY, \
+ [BCM63XX_RESET_ENETSW] = BCM## __cpu ##_RESET_ENETSW, \
+ [BCM63XX_RESET_PCM] = BCM## __cpu ##_RESET_PCM, \
+ [BCM63XX_RESET_MPI] = BCM## __cpu ##_RESET_MPI, \
+ [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
+#define BCM6328_RESET_USBD SOFTRESET_6328_USBS_MASK
+#define BCM6328_RESET_DSL 0
+#define BCM6328_RESET_SAR SOFTRESET_6328_SAR_MASK
+#define BCM6328_RESET_EPHY SOFTRESET_6328_EPHY_MASK
+#define BCM6328_RESET_ENETSW SOFTRESET_6328_ENETSW_MASK
+#define BCM6328_RESET_PCM SOFTRESET_6328_PCM_MASK
+#define BCM6328_RESET_MPI 0
+#define BCM6328_RESET_PCIE \
+ (SOFTRESET_6328_PCIE_MASK | \
+ SOFTRESET_6328_PCIE_CORE_MASK | \
+ SOFTRESET_6328_PCIE_HARD_MASK)
+#define BCM6328_RESET_PCIE_EXT SOFTRESET_6328_PCIE_EXT_MASK
+
+#define BCM6338_RESET_SPI SOFTRESET_6338_SPI_MASK
+#define BCM6338_RESET_ENET SOFTRESET_6338_ENET_MASK
+#define BCM6338_RESET_USBH SOFTRESET_6338_USBH_MASK
+#define BCM6338_RESET_USBD SOFTRESET_6338_USBS_MASK
+#define BCM6338_RESET_DSL SOFTRESET_6338_ADSL_MASK
+#define BCM6338_RESET_SAR SOFTRESET_6338_SAR_MASK
+#define BCM6338_RESET_EPHY 0
+#define BCM6338_RESET_ENETSW 0
+#define BCM6338_RESET_PCM 0
+#define BCM6338_RESET_MPI 0
+#define BCM6338_RESET_PCIE 0
+#define BCM6338_RESET_PCIE_EXT 0
+
+#define BCM6348_RESET_SPI SOFTRESET_6348_SPI_MASK
+#define BCM6348_RESET_ENET SOFTRESET_6348_ENET_MASK
+#define BCM6348_RESET_USBH SOFTRESET_6348_USBH_MASK
+#define BCM6348_RESET_USBD SOFTRESET_6348_USBS_MASK
+#define BCM6348_RESET_DSL SOFTRESET_6348_ADSL_MASK
+#define BCM6348_RESET_SAR SOFTRESET_6348_SAR_MASK
+#define BCM6348_RESET_EPHY 0
+#define BCM6348_RESET_ENETSW 0
+#define BCM6348_RESET_PCM 0
+#define BCM6348_RESET_MPI 0
+#define BCM6348_RESET_PCIE 0
+#define BCM6348_RESET_PCIE_EXT 0
+
+#define BCM6358_RESET_SPI SOFTRESET_6358_SPI_MASK
+#define BCM6358_RESET_ENET SOFTRESET_6358_ENET_MASK
+#define BCM6358_RESET_USBH SOFTRESET_6358_USBH_MASK
+#define BCM6358_RESET_USBD 0
+#define BCM6358_RESET_DSL SOFTRESET_6358_ADSL_MASK
+#define BCM6358_RESET_SAR SOFTRESET_6358_SAR_MASK
+#define BCM6358_RESET_EPHY SOFTRESET_6358_EPHY_MASK
+#define BCM6358_RESET_ENETSW 0
+#define BCM6358_RESET_PCM SOFTRESET_6358_PCM_MASK
+#define BCM6358_RESET_MPI SOFTRESET_6358_MPI_MASK
+#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
+#define BCM6368_RESET_USBD SOFTRESET_6368_USBS_MASK
+#define BCM6368_RESET_DSL 0
+#define BCM6368_RESET_SAR SOFTRESET_6368_SAR_MASK
+#define BCM6368_RESET_EPHY SOFTRESET_6368_EPHY_MASK
+#define BCM6368_RESET_ENETSW 0
+#define BCM6368_RESET_PCM SOFTRESET_6368_PCM_MASK
+#define BCM6368_RESET_MPI SOFTRESET_6368_MPI_MASK
+#define BCM6368_RESET_PCIE 0
+#define BCM6368_RESET_PCIE_EXT 0
+
+#ifdef BCMCPU_RUNTIME_DETECT
+
+/*
+ * 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)
+};
+
+static const u32 bcm6338_reset_bits[] = {
+ __GEN_RESET_BITS_TABLE(6338)
+};
+
+static const u32 bcm6348_reset_bits[] = {
+ __GEN_RESET_BITS_TABLE(6348)
+};
+
+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)
+};
+
+const u32 *bcm63xx_reset_bits;
+static int reset_reg;
+
+static int __init bcm63xx_reset_bits_init(void)
+{
+ 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()) {
+ reset_reg = PERF_SOFTRESET_REG;
+ bcm63xx_reset_bits = bcm6338_reset_bits;
+ } else if (BCMCPU_IS_6348()) {
+ reset_reg = PERF_SOFTRESET_REG;
+ bcm63xx_reset_bits = bcm6348_reset_bits;
+ } 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;
+ }
+
+ return 0;
+}
+#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)
+};
+#define reset_reg PERF_SOFTRESET_6328_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6338
+static const u32 bcm63xx_reset_bits[] = {
+ __GEN_RESET_BITS_TABLE(6338)
+};
+#define reset_reg PERF_SOFTRESET_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6345
+static const u32 bcm63xx_reset_bits[] = { };
+#define reset_reg 0
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6348
+static const u32 bcm63xx_reset_bits[] = {
+ __GEN_RESET_BITS_TABLE(6348)
+};
+#define reset_reg PERF_SOFTRESET_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6358
+static const u32 bcm63xx_reset_bits[] = {
+ __GEN_RESET_BITS_TABLE(6358)
+};
+#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)
+};
+#define reset_reg PERF_SOFTRESET_6368_REG
+#endif
+
+static int __init bcm63xx_reset_bits_init(void) { return 0; }
+#endif
+
+static DEFINE_SPINLOCK(reset_mutex);
+
+static void __bcm63xx_core_set_reset(u32 mask, int enable)
+{
+ unsigned long flags;
+ u32 val;
+
+ if (!mask)
+ return;
+
+ spin_lock_irqsave(&reset_mutex, flags);
+ val = bcm_perf_readl(reset_reg);
+
+ if (enable)
+ val &= ~mask;
+ else
+ val |= mask;
+
+ bcm_perf_writel(val, reset_reg);
+ spin_unlock_irqrestore(&reset_mutex, flags);
+}
+
+void bcm63xx_core_set_reset(enum bcm63xx_core_reset core, int reset)
+{
+ __bcm63xx_core_set_reset(bcm63xx_reset_bits[core], reset);
+}
+EXPORT_SYMBOL(bcm63xx_core_set_reset);
+
+postcore_initcall(bcm63xx_reset_bits_init);
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);