diff options
| author | Sage Weil <sage@inktank.com> | 2013-08-15 11:11:45 -0700 | 
|---|---|---|
| committer | Sage Weil <sage@inktank.com> | 2013-08-15 11:11:45 -0700 | 
| commit | ee3e542fec6e69bc9fb668698889a37d93950ddf (patch) | |
| tree | e74ee766a4764769ef1d3d45d266b4dea64101d3 /arch/mips/bcm63xx | |
| parent | fe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff) | |
| parent | f1d6e17f540af37bb1891480143669ba7636c4cf (diff) | |
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'arch/mips/bcm63xx')
| -rw-r--r-- | arch/mips/bcm63xx/Kconfig | 9 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/boards/board_bcm963xx.c | 57 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/clk.c | 30 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/cpu.c | 28 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-enet.c | 181 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-flash.c | 1 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-spi.c | 6 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/dev-uart.c | 3 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/irq.c | 23 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/nvram.c | 10 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/prom.c | 49 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/reset.c | 29 | ||||
| -rw-r--r-- | arch/mips/bcm63xx/setup.c | 3 | 
13 files changed, 391 insertions, 38 deletions
| diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index 5639662fd50..b78306ce56c 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -1,6 +1,10 @@  menu "CPU support"  	depends on BCM63XX +config BCM63XX_CPU_3368 +	bool "support 3368 CPU" +	select HW_HAS_PCI +  config BCM63XX_CPU_6328  	bool "support 6328 CPU"  	select HW_HAS_PCI @@ -8,14 +12,9 @@ config BCM63XX_CPU_6328  config BCM63XX_CPU_6338  	bool "support 6338 CPU"  	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  config BCM63XX_CPU_6348  	bool "support 6348 CPU" diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index a9505c4867e..5b974eb125f 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -28,11 +28,47 @@  #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 @@ -639,6 +675,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 @@ -722,8 +761,9 @@ 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/6362 do not have MPI but boot from a fixed address @@ -747,7 +787,12 @@ void __init board_prom_init(void)  	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)) @@ -845,6 +890,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); @@ -873,5 +922,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 c726a97fc79..43da4ae04cc 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -84,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) @@ -110,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);  } @@ -155,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 = { @@ -211,7 +211,7 @@ 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; @@ -318,6 +318,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")) @@ -338,7 +350,7 @@ struct clk *clk_get(struct device *dev, const char *id)  		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_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))  		return &clk_ipsec; diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index 79fe32df5e9..7e17374a9ae 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -29,6 +29,14 @@ 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)  }; @@ -116,6 +124,9 @@ unsigned int bcm63xx_get_memory_size(void)  static unsigned int detect_cpu_clock(void)  {  	switch (bcm63xx_get_cpu_id()) { +	case BCM3368_CPU_ID: +		return 300000000; +  	case BCM6328_CPU_ID:  	{  		unsigned int tmp, mips_pll_fcvo; @@ -266,7 +277,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; @@ -302,10 +313,17 @@ void __init bcm63xx_cpu_init(void)  		chipid_reg = BCM_6345_PERF_BASE;  		break;  	case CPU_BMIPS4350: -		if ((read_c0_prid() & 0xf0) == 0x10) +		switch ((read_c0_prid() & 0xff)) { +		case 0x04: +			chipid_reg = BCM_3368_PERF_BASE; +			break; +		case 0x10:  			chipid_reg = BCM_6345_PERF_BASE; -		else +			break; +		default:  			chipid_reg = BCM_6368_PERF_BASE; +			break; +		}  		break;  	} @@ -322,6 +340,10 @@ void __init bcm63xx_cpu_init(void)  	bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;  	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; 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 588d1ec622e..172dd839717 100644 --- a/arch/mips/bcm63xx/dev-flash.c +++ b/arch/mips/bcm63xx/dev-flash.c @@ -71,6 +71,7 @@ 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) diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c index 3065bb61820..d12daed749b 100644 --- a/arch/mips/bcm63xx/dev-spi.c +++ b/arch/mips/bcm63xx/dev-spi.c @@ -37,7 +37,8 @@ static __init void bcm63xx_spi_regs_init(void)  {  	if (BCMCPU_IS_6338() || BCMCPU_IS_6348())  		bcm63xx_regs_spi = bcm6348_regs_spi; -	if (BCMCPU_IS_6358() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) +	if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || +		BCMCPU_IS_6362() || BCMCPU_IS_6368())  		bcm63xx_regs_spi = bcm6358_regs_spi;  }  #else @@ -87,7 +88,8 @@ int __init bcm63xx_spi_register(void)  		spi_pdata.msg_ctl_width = SPI_6348_MSG_CTL_WIDTH;  	} -	if (BCMCPU_IS_6358() || BCMCPU_IS_6362() || 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/irq.c b/arch/mips/bcm63xx/irq.c index c0ab3887f42..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 @@ -140,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; @@ -294,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) { @@ -475,6 +497,7 @@ 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: diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c index a4b8864f930..e652e578a67 100644 --- a/arch/mips/bcm63xx/nvram.c +++ b/arch/mips/bcm63xx/nvram.c @@ -42,6 +42,7 @@ 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)); @@ -62,6 +63,15 @@ void __init bcm63xx_nvram_init(void *addr)  	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) diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index fd698087fbf..8ac4e095e68 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; @@ -52,6 +58,47 @@ void __init prom_init(void)  	/* do low level board init */  	board_prom_init(); + +	if (IS_ENABLED(CONFIG_CPU_BMIPS4350) && IS_ENABLED(CONFIG_SMP)) { +		/* set up SMP */ +		register_smp_ops(&bmips_smp_ops); + +		/* +		 * BCM6328 might not have its second CPU enabled, while BCM6358 +		 * needs special handling for its 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_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 317931c6cf5..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 @@ -117,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)  }; @@ -146,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()) { @@ -170,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) diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index 24a24445db6..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; | 
