brcm63xx: add linux 3.10 support

Signed-off-by: Jonas Gorski <jogo@openwrt.org>

SVN-Revision: 37481
This commit is contained in:
Jonas Gorski 2013-07-20 11:30:26 +00:00
parent 205f7248ae
commit 7ef37c8e3e
128 changed files with 15510 additions and 0 deletions

View file

@ -0,0 +1,187 @@
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_AUDIT=y
CONFIG_AUDIT_GENERIC=y
CONFIG_B53=y
CONFIG_B53_MMAP_DRIVER=y
CONFIG_B53_PHY_DRIVER=y
CONFIG_B53_PHY_FIXUP=y
CONFIG_B53_SPI_DRIVER=y
CONFIG_BCM63XX=y
CONFIG_BCM63XX_CPU_3368=y
CONFIG_BCM63XX_CPU_6328=y
CONFIG_BCM63XX_CPU_6338=y
CONFIG_BCM63XX_CPU_6345=y
CONFIG_BCM63XX_CPU_6348=y
CONFIG_BCM63XX_CPU_6358=y
CONFIG_BCM63XX_CPU_6362=y
CONFIG_BCM63XX_CPU_6368=y
CONFIG_BCM63XX_EHCI=y
CONFIG_BCM63XX_ENET=y
CONFIG_BCM63XX_OHCI=y
CONFIG_BCM63XX_PHY=y
CONFIG_BCM63XX_WDT=y
CONFIG_BOARD_BCM963XX=y
# CONFIG_BOARD_LIVEBOX is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_CEVT_R4K=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 noinitrd console=ttyS0,115200"
CONFIG_CMDLINE_BOOL=y
# CONFIG_CMDLINE_OVERRIDE is not set
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CPU_BMIPS is not set
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_MIPS32=y
CONFIG_CPU_MIPS32_R1=y
CONFIG_CPU_MIPSR1=y
CONFIG_CPU_R4K_CACHE_TLB=y
CONFIG_CPU_R4K_FPU=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_EARLY_PRINTK=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_IO=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_74X164=y
CONFIG_GPIO_DEVRES=y
CONFIG_GPIO_SYSFS=y
# CONFIG_HAMRADIO is not set
CONFIG_HARDWARE_WATCHPOINTS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
CONFIG_HAVE_CLK=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_GENERIC_HARDIRQS=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_HAVE_NET_DSA=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HW_HAS_PCI=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_BCM63XX=y
CONFIG_HZ=250
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
CONFIG_HZ_PERIODIC=y
CONFIG_IMAGE_CMDLINE_HACK=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_IRQ_CPU=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_KEXEC=y
CONFIG_LEDS_GPIO=y
CONFIG_M25PXX_USE_FAST_READ=y
CONFIG_MDIO_BOARDINFO=y
CONFIG_MIPS=y
# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set
CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_MIPS_MACHINE is not set
CONFIG_MIPS_MT_DISABLED=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MTD_BCM63XX_PARTS=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_BE_BYTE_SWAP=y
# CONFIG_MTD_CFI_GEOMETRY is not set
# CONFIG_MTD_CFI_NOSWAP is not set
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
CONFIG_NR_CPUS_DEFAULT_2=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PCI=y
# CONFIG_PCIEAER is not set
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_DOMAINS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_PREEMPT_RCU is not set
# CONFIG_RCU_STALL_COMMON is not set
CONFIG_RELAY=y
CONFIG_RTL8366_SMI=y
CONFIG_RTL8367_PHY=y
# CONFIG_SCSI_DMA is not set
# CONFIG_SERIAL_8250 is not set
CONFIG_SERIAL_BCM63XX=y
CONFIG_SERIAL_BCM63XX_CONSOLE=y
CONFIG_SPI=y
CONFIG_SPI_BCM63XX=y
CONFIG_SPI_BCM63XX_HSSPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_MASTER=y
CONFIG_SQUASHFS_EMBEDDED=y
CONFIG_SSB=y
CONFIG_SSB_B43_PCI_BRIDGE=y
CONFIG_SSB_BLOCKIO=y
# CONFIG_SSB_DRIVER_MIPS is not set
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_PCIHOST=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_SPROM=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_SWCONFIG=y
CONFIG_SYS_HAS_CPU_BMIPS=y
CONFIG_SYS_HAS_CPU_BMIPS3300=y
CONFIG_SYS_HAS_CPU_BMIPS4350=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_UIDGID_CONVERTED=y
CONFIG_USB_ARCH_HAS_XHCI=y
CONFIG_USB_SUPPORT=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_ZONE_DMA_FLAG=0

View file

@ -0,0 +1,29 @@
From e2092cf1b164ede62b740c7c95905171fb6232ff Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 23 Mar 2013 12:32:56 +0100
Subject: [PATCH v2 1/3] MTD: bcm63xxpart: use size macro for CFE block size
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
drivers/mtd/bcm63xxpart.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -27,6 +27,7 @@
#include <linux/crc32.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
@@ -37,7 +38,7 @@
#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
-#define BCM63XX_CFE_BLOCK_SIZE 0x10000 /* always at least 64KiB */
+#define BCM63XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */
#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0

View file

@ -0,0 +1,58 @@
From bda508f975d1372568a4fc9862be501a6176fd46 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 12 May 2012 23:04:17 +0200
Subject: [PATCH v2 2/3] MIPS: BCM63XX: export PSI size from nvram
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/nvram.c | 13 +++++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h | 7 +++++++
2 files changed, 20 insertions(+)
--- a/arch/mips/bcm63xx/nvram.c
+++ b/arch/mips/bcm63xx/nvram.c
@@ -15,6 +15,7 @@
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/if_ether.h>
+#include <linux/sizes.h>
#include <bcm63xx_nvram.h>
@@ -35,6 +36,8 @@ struct bcm963xx_nvram {
u32 checksum_high;
};
+#define BCM63XX_DEFAULT_PSI_SIZE SZ_64K
+
static struct bcm963xx_nvram nvram;
static int mac_addr_used;
@@ -104,3 +107,13 @@ int bcm63xx_nvram_get_mac_address(u8 *ma
return 0;
}
EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
+
+unsigned int bcm63xx_nvram_get_psi_size(void)
+{
+ /* max is 64k, but some vendors use higher values */
+ if (nvram.psi_size > 0 && nvram.psi_size <= 512)
+ return nvram.psi_size * SZ_1K;
+
+ return BCM63XX_DEFAULT_PSI_SIZE;
+}
+EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
@@ -30,4 +30,11 @@ u8 *bcm63xx_nvram_get_name(void);
*/
int bcm63xx_nvram_get_mac_address(u8 *mac);
+/**
+ * bcm63xx_nvram_get_psi_size() - returns the size of the PSI area
+ *
+ * Returns the size of the Persitent Storage Information area in bytes.
+ */
+unsigned int bcm63xx_nvram_get_psi_size(void);
+
#endif /* BCM63XX_NVRAM_H */

View file

@ -0,0 +1,42 @@
From f6eefaa4a08ec27c69485c2fc4db23247b84f8c9 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 1 May 2012 14:10:39 +0200
Subject: [PATCH v2 3/3] MTD: bcm63xxpart: use nvram for PSI size
Read out the SPI size from nvram instead of defaulting to 64K - some
vendors actually use values larger than the "max" value of 64.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
drivers/mtd/bcm63xxpart.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -4,7 +4,7 @@
* Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org>
* Mike Albon <malbon@openwrt.org>
* Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
- * Copyright © 2011-2012 Jonas Gorski <jonas.gorski@gmail.com>
+ * Copyright © 2011-2013 Jonas Gorski <jonas.gorski@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,6 +34,7 @@
#include <linux/mtd/partitions.h>
#include <linux/bcm963xx_tag.h>
+#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
#include <asm/mach-bcm63xx/board_bcm963xx.h>
#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
@@ -91,7 +92,8 @@ static int bcm63xx_parse_cfe_partitions(
BCM63XX_CFE_BLOCK_SIZE);
cfelen = cfe_erasesize;
- nvramlen = cfe_erasesize;
+ nvramlen = bcm63xx_nvram_get_psi_size();
+ nvramlen = roundup(nvramlen, cfe_erasesize);
/* Allocate memory for buffer */
buf = vmalloc(sizeof(struct bcm_tag));

View file

@ -0,0 +1,28 @@
From 1a66581c94ad3966a823f2efaf8a5cc514895318 Mon Sep 17 00:00:00 2001
From: Kevin Cernekee <cernekee@gmail.com>
Date: Mon, 31 Oct 2011 11:52:10 -0700
Subject: [PATCH 2/3] MIPS: BCM63XX: Handle SW IRQs 0-1
MIPS software IRQs 0 and 1 are used for interprocessor signaling (IPI)
on BMIPS SMP. Make the board support code aware of them.
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
[jogo@openwrt.org: move sw irqs behind timer irq]
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -294,6 +294,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) {

View file

@ -0,0 +1,27 @@
From 158a11f25e070a6ed99cf8faa985da1f2669230f Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 21 Apr 2013 14:44:00 +0200
Subject: [PATCH 3/3] MIPS: BCM63XX: select BMIPS4350 and default to 2 CPUs
for supported SoCs
All BCM63XX SoCs starting with BCM6358 have a BMIPS4350 instead of a
BMIPS3300, so select it unless support for any of the older SoCs is
selected.
All BMIPS4350 have only two CPUs, so select the appropriate default.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/Kconfig | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -128,6 +128,8 @@ config BCM63XX
select DMA_NONCOHERENT
select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_CPU_BMIPS4350 if !BCM63XX_CPU_6338 && !BCM63XX_CPU_6345 && !BCM63XX_CPU_6348
+ select NR_CPUS_DEFAULT_2
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_HAS_EARLY_PRINTK

View file

@ -0,0 +1,30 @@
From 373eb1a286bf31b41f966d5d3826cfe63e826c92 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Tue, 18 Jun 2013 16:55:39 +0000
Subject: [PATCH 1/6] MIPS: BCM63XX: select BOOT_RAW
Enabling BOOT_RAW is mandatory to get a binary image (objcopy from ELF
to binary) to work. This does not affect the ELF kernels which are used
by CFE on BCM63XX DSL platforms, but is going to be necessary to support
BCM63XX on Cable Modem chips such as BCM3368.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Cc: jogo@openwrt.org
Patchwork: https://patchwork.linux-mips.org/patch/5500/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/Kconfig | 1 +
1 file changed, 1 insertion(+)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -123,6 +123,7 @@ config BCM47XX
config BCM63XX
bool "Broadcom BCM63XX based boards"
+ select BOOT_RAW
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT

View file

@ -0,0 +1,629 @@
From 31c761c9c1fa91bf4ed83d75dcbc4e426ea2b670 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Tue, 18 Jun 2013 16:55:40 +0000
Subject: [PATCH 2/6] MIPS: BCM63XX: add support for BCM3368 Cable Modem
The Broadcom BCM3368 Cable Modem SoC is extremely similar to the
existing BCM63xx DSL SoCs, in particular BCM6358, therefore little effort
in the existing code base is required to get it supported. This patch adds
support for the following on-chip peripherals:
- two UARTS
- GPIO
- Ethernet
- SPI
- PCI
- NOR Flash
The most noticeable difference with 3368 is that it has its peripheral
register at 0xfff8_0000 we check that separately in ioremap.h. Since
3368 is identical to 6358 for its clock and reset bits, we use them
verbatim.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Cc: jogo@openwrt.org
Patchwork: https://patchwork.linux-mips.org/patch/5499/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/bcm63xx/Kconfig | 4 +
arch/mips/bcm63xx/clk.c | 18 ++--
arch/mips/bcm63xx/cpu.c | 28 +++++-
arch/mips/bcm63xx/dev-flash.c | 1 +
arch/mips/bcm63xx/dev-spi.c | 6 +-
arch/mips/bcm63xx/dev-uart.c | 3 +-
arch/mips/bcm63xx/irq.c | 19 ++++
arch/mips/bcm63xx/prom.c | 4 +-
arch/mips/bcm63xx/reset.c | 29 +++++-
arch/mips/bcm63xx/setup.c | 3 +
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 110 +++++++++++++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 1 +
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 45 ++++++++-
arch/mips/include/asm/mach-bcm63xx/ioremap.h | 4 +
arch/mips/pci/pci-bcm63xx.c | 3 +-
15 files changed, 259 insertions(+), 19 deletions(-)
--- 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
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -84,7 +84,7 @@ static void enetx_set(struct clk *clk, i
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
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;
@@ -338,7 +338,7 @@ struct clk *clk_get(struct device *dev,
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;
--- 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(voi
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(v
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;
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -71,6 +71,7 @@ static int __init bcm63xx_detect_flash_t
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)
--- 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
{
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;
--- a/arch/mips/bcm63xx/dev-uart.c
+++ b/arch/mips/bcm63xx/dev-uart.c
@@ -54,7 +54,8 @@ int __init bcm63xx_uart_register(unsigne
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) {
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -27,6 +27,17 @@ static void __internal_irq_unmask_32(uns
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;
@@ -479,6 +497,7 @@ static int bcm63xx_external_irq_set_type
reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
break;
+ case BCM3368_CPU_ID:
case BCM6328_CPU_ID:
case BCM6338_CPU_ID:
case BCM6345_CPU_ID:
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -26,7 +26,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;
--- 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_ini
}
#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)
--- 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;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -9,6 +9,7 @@
* compile time if only one CPU support is enabled (idea stolen from
* arm mach-types)
*/
+#define BCM3368_CPU_ID 0x3368
#define BCM6328_CPU_ID 0x6328
#define BCM6338_CPU_ID 0x6338
#define BCM6345_CPU_ID 0x6345
@@ -22,6 +23,19 @@ u16 __bcm63xx_get_cpu_id(void);
u8 bcm63xx_get_cpu_rev(void);
unsigned int bcm63xx_get_cpu_freq(void);
+#ifdef CONFIG_BCM63XX_CPU_3368
+# ifdef bcm63xx_get_cpu_id
+# undef bcm63xx_get_cpu_id
+# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
+# define BCMCPU_RUNTIME_DETECT
+# else
+# define bcm63xx_get_cpu_id() BCM3368_CPU_ID
+# endif
+# define BCMCPU_IS_3368() (bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
+#else
+# define BCMCPU_IS_3368() (0)
+#endif
+
#ifdef CONFIG_BCM63XX_CPU_6328
# ifdef bcm63xx_get_cpu_id
# undef bcm63xx_get_cpu_id
@@ -191,6 +205,53 @@ enum bcm63xx_regs_set {
#define RSET_RNG_SIZE 20
/*
+ * 3368 register sets base address
+ */
+#define BCM_3368_DSL_LMEM_BASE (0xdeadbeef)
+#define BCM_3368_PERF_BASE (0xfff8c000)
+#define BCM_3368_TIMER_BASE (0xfff8c040)
+#define BCM_3368_WDT_BASE (0xfff8c080)
+#define BCM_3368_UART0_BASE (0xfff8c100)
+#define BCM_3368_UART1_BASE (0xfff8c120)
+#define BCM_3368_GPIO_BASE (0xfff8c080)
+#define BCM_3368_SPI_BASE (0xfff8c800)
+#define BCM_3368_HSSPI_BASE (0xdeadbeef)
+#define BCM_3368_UDC0_BASE (0xdeadbeef)
+#define BCM_3368_USBDMA_BASE (0xdeadbeef)
+#define BCM_3368_OHCI0_BASE (0xdeadbeef)
+#define BCM_3368_OHCI_PRIV_BASE (0xdeadbeef)
+#define BCM_3368_USBH_PRIV_BASE (0xdeadbeef)
+#define BCM_3368_USBD_BASE (0xdeadbeef)
+#define BCM_3368_MPI_BASE (0xfff80000)
+#define BCM_3368_PCMCIA_BASE (0xfff80054)
+#define BCM_3368_PCIE_BASE (0xdeadbeef)
+#define BCM_3368_SDRAM_REGS_BASE (0xdeadbeef)
+#define BCM_3368_DSL_BASE (0xdeadbeef)
+#define BCM_3368_UBUS_BASE (0xdeadbeef)
+#define BCM_3368_ENET0_BASE (0xfff98000)
+#define BCM_3368_ENET1_BASE (0xfff98800)
+#define BCM_3368_ENETDMA_BASE (0xfff99800)
+#define BCM_3368_ENETDMAC_BASE (0xfff99900)
+#define BCM_3368_ENETDMAS_BASE (0xfff99a00)
+#define BCM_3368_ENETSW_BASE (0xdeadbeef)
+#define BCM_3368_EHCI0_BASE (0xdeadbeef)
+#define BCM_3368_SDRAM_BASE (0xdeadbeef)
+#define BCM_3368_MEMC_BASE (0xfff84000)
+#define BCM_3368_DDR_BASE (0xdeadbeef)
+#define BCM_3368_M2M_BASE (0xdeadbeef)
+#define BCM_3368_ATM_BASE (0xdeadbeef)
+#define BCM_3368_XTM_BASE (0xdeadbeef)
+#define BCM_3368_XTMDMA_BASE (0xdeadbeef)
+#define BCM_3368_XTMDMAC_BASE (0xdeadbeef)
+#define BCM_3368_XTMDMAS_BASE (0xdeadbeef)
+#define BCM_3368_PCM_BASE (0xfff9c200)
+#define BCM_3368_PCMDMA_BASE (0xdeadbeef)
+#define BCM_3368_PCMDMAC_BASE (0xdeadbeef)
+#define BCM_3368_PCMDMAS_BASE (0xdeadbeef)
+#define BCM_3368_RNG_BASE (0xdeadbeef)
+#define BCM_3368_MISC_BASE (0xdeadbeef)
+
+/*
* 6328 register sets base address
*/
#define BCM_6328_DSL_LMEM_BASE (0xdeadbeef)
@@ -620,6 +681,9 @@ static inline unsigned long bcm63xx_regs
#ifdef BCMCPU_RUNTIME_DETECT
return bcm63xx_regs_base[set];
#else
+#ifdef CONFIG_BCM63XX_CPU_3368
+ __GEN_RSET(3368)
+#endif
#ifdef CONFIG_BCM63XX_CPU_6328
__GEN_RSET(6328)
#endif
@@ -687,6 +751,52 @@ enum bcm63xx_irq {
};
/*
+ * 3368 irqs
+ */
+#define BCM_3368_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
+#define BCM_3368_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
+#define BCM_3368_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
+#define BCM_3368_UART1_IRQ (IRQ_INTERNAL_BASE + 3)
+#define BCM_3368_DSL_IRQ 0
+#define BCM_3368_UDC0_IRQ 0
+#define BCM_3368_OHCI0_IRQ 0
+#define BCM_3368_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
+#define BCM_3368_ENET1_IRQ (IRQ_INTERNAL_BASE + 6)
+#define BCM_3368_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_3368_ENET0_RXDMA_IRQ (IRQ_INTERNAL_BASE + 15)
+#define BCM_3368_ENET0_TXDMA_IRQ (IRQ_INTERNAL_BASE + 16)
+#define BCM_3368_HSSPI_IRQ 0
+#define BCM_3368_EHCI0_IRQ 0
+#define BCM_3368_USBD_IRQ 0
+#define BCM_3368_USBD_RXDMA0_IRQ 0
+#define BCM_3368_USBD_TXDMA0_IRQ 0
+#define BCM_3368_USBD_RXDMA1_IRQ 0
+#define BCM_3368_USBD_TXDMA1_IRQ 0
+#define BCM_3368_USBD_RXDMA2_IRQ 0
+#define BCM_3368_USBD_TXDMA2_IRQ 0
+#define BCM_3368_ENET1_RXDMA_IRQ (IRQ_INTERNAL_BASE + 17)
+#define BCM_3368_ENET1_TXDMA_IRQ (IRQ_INTERNAL_BASE + 18)
+#define BCM_3368_PCI_IRQ (IRQ_INTERNAL_BASE + 31)
+#define BCM_3368_PCMCIA_IRQ 0
+#define BCM_3368_ATM_IRQ 0
+#define BCM_3368_ENETSW_RXDMA0_IRQ 0
+#define BCM_3368_ENETSW_RXDMA1_IRQ 0
+#define BCM_3368_ENETSW_RXDMA2_IRQ 0
+#define BCM_3368_ENETSW_RXDMA3_IRQ 0
+#define BCM_3368_ENETSW_TXDMA0_IRQ 0
+#define BCM_3368_ENETSW_TXDMA1_IRQ 0
+#define BCM_3368_ENETSW_TXDMA2_IRQ 0
+#define BCM_3368_ENETSW_TXDMA3_IRQ 0
+#define BCM_3368_XTM_IRQ 0
+#define BCM_3368_XTM_DMA0_IRQ 0
+
+#define BCM_3368_EXT_IRQ0 (IRQ_INTERNAL_BASE + 25)
+#define BCM_3368_EXT_IRQ1 (IRQ_INTERNAL_BASE + 26)
+#define BCM_3368_EXT_IRQ2 (IRQ_INTERNAL_BASE + 27)
+#define BCM_3368_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28)
+
+
+/*
* 6328 irqs
*/
#define BCM_6328_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
@@ -11,6 +11,7 @@ static inline unsigned long bcm63xx_gpio
switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
return 32;
+ case BCM3368_CPU_ID:
case BCM6358_CPU_ID:
return 40;
case BCM6338_CPU_ID:
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -15,6 +15,39 @@
/* Clock Control register */
#define PERF_CKCTL_REG 0x4
+#define CKCTL_3368_MAC_EN (1 << 3)
+#define CKCTL_3368_TC_EN (1 << 5)
+#define CKCTL_3368_US_TOP_EN (1 << 6)
+#define CKCTL_3368_DS_TOP_EN (1 << 7)
+#define CKCTL_3368_APM_EN (1 << 8)
+#define CKCTL_3368_SPI_EN (1 << 9)
+#define CKCTL_3368_USBS_EN (1 << 10)
+#define CKCTL_3368_BMU_EN (1 << 11)
+#define CKCTL_3368_PCM_EN (1 << 12)
+#define CKCTL_3368_NTP_EN (1 << 13)
+#define CKCTL_3368_ACP_B_EN (1 << 14)
+#define CKCTL_3368_ACP_A_EN (1 << 15)
+#define CKCTL_3368_EMUSB_EN (1 << 17)
+#define CKCTL_3368_ENET0_EN (1 << 18)
+#define CKCTL_3368_ENET1_EN (1 << 19)
+#define CKCTL_3368_USBU_EN (1 << 20)
+#define CKCTL_3368_EPHY_EN (1 << 21)
+
+#define CKCTL_3368_ALL_SAFE_EN (CKCTL_3368_MAC_EN | \
+ CKCTL_3368_TC_EN | \
+ CKCTL_3368_US_TOP_EN | \
+ CKCTL_3368_DS_TOP_EN | \
+ CKCTL_3368_APM_EN | \
+ CKCTL_3368_SPI_EN | \
+ CKCTL_3368_USBS_EN | \
+ CKCTL_3368_BMU_EN | \
+ CKCTL_3368_PCM_EN | \
+ CKCTL_3368_NTP_EN | \
+ CKCTL_3368_ACP_B_EN | \
+ CKCTL_3368_ACP_A_EN | \
+ CKCTL_3368_EMUSB_EN | \
+ CKCTL_3368_USBU_EN)
+
#define CKCTL_6328_PHYMIPS_EN (1 << 0)
#define CKCTL_6328_ADSL_QPROC_EN (1 << 1)
#define CKCTL_6328_ADSL_AFE_EN (1 << 2)
@@ -181,6 +214,7 @@
#define SYS_PLL_SOFT_RESET 0x1
/* Interrupt Mask register */
+#define PERF_IRQMASK_3368_REG 0xc
#define PERF_IRQMASK_6328_REG 0x20
#define PERF_IRQMASK_6338_REG 0xc
#define PERF_IRQMASK_6345_REG 0xc
@@ -190,6 +224,7 @@
#define PERF_IRQMASK_6368_REG 0x20
/* Interrupt Status register */
+#define PERF_IRQSTAT_3368_REG 0x10
#define PERF_IRQSTAT_6328_REG 0x28
#define PERF_IRQSTAT_6338_REG 0x10
#define PERF_IRQSTAT_6345_REG 0x10
@@ -199,6 +234,7 @@
#define PERF_IRQSTAT_6368_REG 0x28
/* External Interrupt Configuration register */
+#define PERF_EXTIRQ_CFG_REG_3368 0x14
#define PERF_EXTIRQ_CFG_REG_6328 0x18
#define PERF_EXTIRQ_CFG_REG_6338 0x14
#define PERF_EXTIRQ_CFG_REG_6345 0x14
@@ -236,6 +272,13 @@
#define PERF_SOFTRESET_6362_REG 0x10
#define PERF_SOFTRESET_6368_REG 0x10
+#define SOFTRESET_3368_SPI_MASK (1 << 0)
+#define SOFTRESET_3368_ENET_MASK (1 << 2)
+#define SOFTRESET_3368_MPI_MASK (1 << 3)
+#define SOFTRESET_3368_EPHY_MASK (1 << 6)
+#define SOFTRESET_3368_USBS_MASK (1 << 11)
+#define SOFTRESET_3368_PCM_MASK (1 << 13)
+
#define SOFTRESET_6328_SPI_MASK (1 << 0)
#define SOFTRESET_6328_EPHY_MASK (1 << 1)
#define SOFTRESET_6328_SAR_MASK (1 << 2)
@@ -1293,7 +1336,7 @@
#define SPI_6348_RX_DATA 0x80
#define SPI_6348_RX_DATA_SIZE 0x3f
-/* BCM 6358/6262/6368 SPI core */
+/* BCM 3368/6358/6262/6368 SPI core */
#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */
#define SPI_6358_MSG_CTL_WIDTH 16
#define SPI_6358_MSG_DATA 0x02
--- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h
+++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h
@@ -11,6 +11,10 @@ static inline phys_t fixup_bigphys_addr(
static inline int is_bcm63xx_internal_registers(phys_t offset)
{
switch (bcm63xx_get_cpu_id()) {
+ case BCM3368_CPU_ID:
+ if (offset >= 0xfff80000)
+ return 1;
+ break;
case BCM6338_CPU_ID:
case BCM6345_CPU_ID:
case BCM6348_CPU_ID:
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -266,7 +266,7 @@ static int __init bcm63xx_register_pci(v
/* setup PCI to local bus access, used by PCI device to target
* local RAM while bus mastering */
bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3);
- if (BCMCPU_IS_6358() || BCMCPU_IS_6368())
+ if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6368())
val = MPI_SP0_REMAP_ENABLE_MASK;
else
val = 0;
@@ -338,6 +338,7 @@ static int __init bcm63xx_pci_init(void)
case BCM6328_CPU_ID:
case BCM6362_CPU_ID:
return bcm63xx_register_pcie();
+ case BCM3368_CPU_ID:
case BCM6348_CPU_ID:
case BCM6358_CPU_ID:
case BCM6368_CPU_ID:

View file

@ -0,0 +1,101 @@
From f3b3faafe7b5a1c07b12d18e96c36bc8a0eecaed Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Tue, 18 Jun 2013 16:55:41 +0000
Subject: [PATCH 3/6] MIPS: BCM63XX: recognize Cable Modem firmware format
Add the firmware header format which is used by Broadcom Cable Modem
SoCs such as the BCM3368 SoC. We export the bcm_hcs firmware format
structure because it is used by user-land tools to create firmware
images for these SoCs and will later be used by a corresponding MTD
parser.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Cc: jogo@openwrt.org
Patchwork: https://patchwork.linux-mips.org/patch/5496/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 14 ++++++++++++--
include/uapi/linux/Kbuild | 1 +
include/uapi/linux/bcm933xx_hcs.h | 24 ++++++++++++++++++++++++
3 files changed, 37 insertions(+), 2 deletions(-)
create mode 100644 include/uapi/linux/bcm933xx_hcs.h
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -28,8 +28,12 @@
#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;
/*
@@ -722,8 +726,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 +752,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))
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -62,6 +62,7 @@ header-y += auxvec.h
header-y += ax25.h
header-y += b1lli.h
header-y += baycom.h
+header-y += bcm933xx_hcs.h
header-y += bfs_fs.h
header-y += binfmts.h
header-y += blkpg.h
--- /dev/null
+++ b/include/uapi/linux/bcm933xx_hcs.h
@@ -0,0 +1,24 @@
+/*
+ * Broadcom Cable Modem firmware format
+ */
+
+#ifndef __BCM933XX_HCS_H
+#define __BCM933XX_HCS_H
+
+#include <linux/types.h>
+
+struct bcm_hcs {
+ __u16 magic;
+ __u16 control;
+ __u16 rev_maj;
+ __u16 rev_min;
+ __u32 build_date;
+ __u32 filelen;
+ __u32 ldaddress;
+ char filename[64];
+ __u16 hcs;
+ __u16 her_znaet_chto;
+ __u32 crc;
+};
+
+#endif /* __BCM933XX_HCS */

View file

@ -0,0 +1,46 @@
From 404fdc457082772ff52e22988e09e82c0d6e8780 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Tue, 18 Jun 2013 16:55:42 +0000
Subject: [PATCH 4/6] MIPS: BCM63XX: provide a MAC address for BCM3368 chips
The BCM3368 SoC uses a NVRAM format which is not compatible with the one
used by CFE, provide a default MAC address which is suitable for use and
which is the default one also being used by the bootloader on these
chips.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Cc: jogo@openwrt.org
Patchwork: https://patchwork.linux-mips.org/patch/5498/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/bcm63xx/nvram.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/arch/mips/bcm63xx/nvram.c
+++ b/arch/mips/bcm63xx/nvram.c
@@ -45,6 +45,7 @@ void __init bcm63xx_nvram_init(void *add
{
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));
@@ -65,6 +66,15 @@ void __init bcm63xx_nvram_init(void *add
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)

View file

@ -0,0 +1,49 @@
From 0a97aafe7fe50ed183e7fa0121fa7838e2e20306 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Tue, 18 Jun 2013 16:55:43 +0000
Subject: [PATCH 5/6] MIPS: BCM63XX: let board specify an external GPIO to
reset PHY
Some boards may need to reset their external PHY or switch they are
attached to, add a hook for doing this along with providing custom
linux/gpio.h flags for doing this.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Cc: jogo@openwrt.org
Cc: Florian Fainelli <florian@openwrt.org>
Patchwork: https://patchwork.linux-mips.org/patch/5501/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++++
arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 6 ++++++
2 files changed, 10 insertions(+)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -883,5 +883,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;
}
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -45,6 +45,12 @@ struct board_info {
/* GPIO LEDs */
struct gpio_led leds[5];
+
+ /* External PHY reset GPIO */
+ unsigned int ephy_reset_gpio;
+
+ /* External PHY reset GPIO flags from gpio.h */
+ unsigned long ephy_reset_gpio_flags;
};
#endif /* ! BOARD_BCM963XX_H_ */

View file

@ -0,0 +1,70 @@
From 04760855f0d99a1cdc67ae0152d95bcc4525cff5 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Tue, 18 Jun 2013 16:55:44 +0000
Subject: [PATCH 6/6] MIPS: BCM63XX: add support for the Netgear CVG834G
Add support for the Netgear CVG834G and enable the two UARTs, Ethernet
on the first MAC, PCI and the two leds.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Cc: jogo@openwrt.org
Cc: Florian Fainelli <florian@openwrt.org>
Patchwork: https://patchwork.linux-mips.org/patch/5502/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 35 +++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -37,6 +37,38 @@
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
@@ -643,6 +675,9 @@ static struct board_info __initdata boar
* 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

View file

@ -0,0 +1,47 @@
From 318883517ebc56e1f9068597e9875f578016e225 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Tue, 18 Jun 2013 16:55:38 +0000
Subject: [PATCH] MIPS: BCM63XX: remove bogus Kconfig selects
Remove the bogus selects on USB-related symbols for 6345 and 6338, not
only we do not yet support USB on BCM63XX, but they also cause the
following warnings:
warning: (BCM63XX_CPU_6338 && BCM63XX_CPU_6345) selects
USB_OHCI_BIG_ENDIAN_MMIO which has unmet direct dependencies
(USB_SUPPORT && USB && USB_OHCI_HCD)
warning: (BCM63XX_CPU_6338 && BCM63XX_CPU_6345) selects
USB_OHCI_BIG_ENDIAN_DESC which has unmet direct dependencies
(USB_SUPPORT && USB && USB_OHCI_HCD)
make[4]: Leaving directory `/home/florian/dev/linux'
Just get rid of these bogus Kconfig selects because neither 6345 nor
6338 actually have built-in USB host controllers.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Cc: jogo@openwrt.org
Patchwork: http://patchwork.linux-mips.org/patch/5497/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/bcm63xx/Kconfig | 5 -----
1 file changed, 5 deletions(-)
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -12,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"

View file

@ -0,0 +1,89 @@
From 672d6bea85c7c9c63c086a9423e6d4e5fc286152 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Wed, 26 Jun 2013 18:11:56 +0000
Subject: [PATCH] MIPS: BMIPS: support booting from physical CPU other than 0
BMIPS43xx CPUs have two hardware threads, and on some SoCs such as 3368,
the bootloader has configured the system to boot from TP1 instead of the
more usual TP0. Create the physical to logical CPU mapping to cope with
that, do not remap the software interrupts to be cross CPUs such that we
do not have to do use the logical CPU mapping further down the code, and
finally, reset the slave TP1 only if booted from TP0.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: blogic@openwrt.org
Cc: cernekee@gmail.com
Patchwork: https://patchwork.linux-mips.org/patch/5553/
Patchwork: https://patchwork.linux-mips.org/patch/5556/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/kernel/smp-bmips.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -63,7 +63,7 @@ static irqreturn_t bmips_ipi_interrupt(i
static void __init bmips_smp_setup(void)
{
- int i;
+ int i, cpu = 1, boot_cpu = 0;
#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
/* arbitration priority */
@@ -72,13 +72,22 @@ static void __init bmips_smp_setup(void)
/* NBK and weak order flags */
set_c0_brcm_config_0(0x30000);
+ /* Find out if we are running on TP0 or TP1 */
+ boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
+
/*
* MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread
* MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
* MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
+ *
+ * If booting from TP1, leave the existing CMT interrupt routing
+ * such that TP0 responds to SW1 and TP1 responds to SW0.
*/
- change_c0_brcm_cmt_intr(0xf8018000,
- (0x02 << 27) | (0x03 << 15));
+ if (boot_cpu == 0)
+ change_c0_brcm_cmt_intr(0xf8018000,
+ (0x02 << 27) | (0x03 << 15));
+ else
+ change_c0_brcm_cmt_intr(0xf8018000, (0x1d << 27));
/* single core, 2 threads (2 pipelines) */
max_cpus = 2;
@@ -106,9 +115,15 @@ static void __init bmips_smp_setup(void)
if (!board_ebase_setup)
board_ebase_setup = &bmips_ebase_setup;
+ __cpu_number_map[boot_cpu] = 0;
+ __cpu_logical_map[0] = boot_cpu;
+
for (i = 0; i < max_cpus; i++) {
- __cpu_number_map[i] = 1;
- __cpu_logical_map[i] = 1;
+ if (i != boot_cpu) {
+ __cpu_number_map[i] = cpu;
+ __cpu_logical_map[cpu] = i;
+ cpu++;
+ }
set_cpu_possible(i, 1);
set_cpu_present(i, 1);
}
@@ -157,7 +172,9 @@ static void bmips_boot_secondary(int cpu
bmips_send_ipi_single(cpu, 0);
else {
#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
- set_c0_brcm_cmt_ctrl(0x01);
+ /* Reset slave TP1 if booting from TP0 */
+ if (cpu_logical_map(cpu) == 0)
+ set_c0_brcm_cmt_ctrl(0x01);
#elif defined(CONFIG_CPU_BMIPS5000)
if (cpu & 0x01)
write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));

View file

@ -0,0 +1,82 @@
From 7c44eabf20cba12049bf9eebfa192afcc2053b2d Mon Sep 17 00:00:00 2001
From: Kevin Cernekee <cernekee@gmail.com>
Date: Sat, 9 Jul 2011 12:15:06 -0700
Subject: [PATCH V2 1/2] MIPS: BCM63XX: Add SMP support to prom.c
This involves two changes to the BSP code:
1) register_smp_ops() for BMIPS SMP
2) The CPU1 boot vector on some of the BCM63xx platforms conflicts with
the special interrupt vector (IV). Move it to 0x8000_0380 at boot time,
to resolve the conflict.
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
[jogo@openwrt.org: moved SMP ops registration into ifdef guard,
changed ifdef guards to if (IS_ENABLED())]
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
V1 -> V2:
* changed ifdef guards to if (IS_ENABLED())
arch/mips/bcm63xx/prom.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
--- 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>
@@ -54,6 +58,43 @@ 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()) {
+ 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)

View file

@ -0,0 +1,55 @@
From 41fa6dec9df9b4e55ac522c899270a72e51a9b4b Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 9 Jul 2011 12:15:06 -0700
Subject: [PATCH V2 2/2] MIPS: BCM63XX: Enable second core SMP on BCM6328 if
available
BCM6328 has a OTP which tells us if the second core is available.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/prom.c | 6 +++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 2 ++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 7 +++++++
3 files changed, 14 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -69,7 +69,11 @@ void __init prom_init(void)
* for now.
*/
if (BCMCPU_IS_6328()) {
- bmips_smp_enabled = 0;
+ 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;
}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -296,6 +296,8 @@ enum bcm63xx_regs_set {
#define BCM_6328_PCMDMAS_BASE (0xdeadbeef)
#define BCM_6328_RNG_BASE (0xdeadbeef)
#define BCM_6328_MISC_BASE (0xb0001800)
+#define BCM_6328_OTP_BASE (0xb0000600)
+
/*
* 6338 register sets base address
*/
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -1477,4 +1477,11 @@
#define PCIE_DEVICE_OFFSET 0x8000
+/*************************************************************************
+ * _REG relative to RSET_OTP
+ *************************************************************************/
+
+#define OTP_USER_BITS_6328_REG(i) (0x20 + (i) * 4)
+#define OTP_6328_REG3_TP1_DISABLED BIT(9)
+
#endif /* BCM63XX_REGS_H_ */

View file

@ -0,0 +1,44 @@
From a15c33450df64f183c8ab5de8ef113091081679d Mon Sep 17 00:00:00 2001
From: Maxime Bizon <mbizon@freebox.fr>
Date: Tue, 4 Jun 2013 20:53:33 +0000
Subject: [PATCH 1/3] bcm63xx_enet: implement reset autoneg ethtool callback
Implement the rset_nway ethtool callback which uses libphy generic
autonegotiation restart function.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1328,6 +1328,20 @@ static void bcm_enet_get_ethtool_stats(s
mutex_unlock(&priv->mib_update_lock);
}
+static int bcm_enet_nway_reset(struct net_device *dev)
+{
+ struct bcm_enet_priv *priv;
+
+ priv = netdev_priv(dev);
+ if (priv->has_phy) {
+ if (!priv->phydev)
+ return -ENODEV;
+ return genphy_restart_aneg(priv->phydev);
+ }
+
+ return -EOPNOTSUPP;
+}
+
static int bcm_enet_get_settings(struct net_device *dev,
struct ethtool_cmd *cmd)
{
@@ -1470,6 +1484,7 @@ static const struct ethtool_ops bcm_enet
.get_strings = bcm_enet_get_strings,
.get_sset_count = bcm_enet_get_sset_count,
.get_ethtool_stats = bcm_enet_get_ethtool_stats,
+ .nway_reset = bcm_enet_nway_reset,
.get_settings = bcm_enet_get_settings,
.set_settings = bcm_enet_set_settings,
.get_drvinfo = bcm_enet_get_drvinfo,

View file

@ -0,0 +1,346 @@
From 33cab1696444a8e333cf0490bfe04c32d583fd51 Mon Sep 17 00:00:00 2001
From: Maxime Bizon <mbizon@freebox.fr>
Date: Tue, 4 Jun 2013 20:53:34 +0000
Subject: [PATCH 2/3] bcm63xx_enet: split DMA channel register accesses
The current bcm63xx_enet driver always uses bcmenet_shared_base whenever
it needs to access DMA channel configuration space or access the DMA
channel state RAM. Split these register in 3 parts to be more accurate:
- global DMA configuration
- per DMA channel configuration space
- per DMA channel state RAM space
This is preliminary to support new chips where the global DMA
configuration remains the same, but there is a varying number of DMA
channels located at a different memory offset.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/dev-enet.c | 23 +++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 4 +-
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 139 +++++++++++++---------
3 files changed, 105 insertions(+), 61 deletions(-)
--- a/arch/mips/bcm63xx/dev-enet.c
+++ b/arch/mips/bcm63xx/dev-enet.c
@@ -19,6 +19,16 @@ static struct resource shared_res[] = {
.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 = {
@@ -110,10 +120,15 @@ int __init bcm63xx_enet_register(int uni
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;
+ shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
+
+ shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
+ shared_res[1].end = shared_res[1].start;
+ shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 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(16) - 1;
ret = platform_device_register(&bcm63xx_enet_shared_device);
if (ret)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -187,7 +187,9 @@ enum bcm63xx_regs_set {
#define BCM_6358_RSET_SPI_SIZE 1804
#define BCM_6368_RSET_SPI_SIZE 1804
#define RSET_ENET_SIZE 2048
-#define RSET_ENETDMA_SIZE 2048
+#define RSET_ENETDMA_SIZE 256
+#define RSET_ENETDMAC_SIZE(chans) (16 * (chans))
+#define RSET_ENETDMAS_SIZE(chans) (16 * (chans))
#define RSET_ENETSW_SIZE 65536
#define RSET_UART_SIZE 24
#define RSET_UDC_SIZE 256
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -41,8 +41,8 @@ static int copybreak __read_mostly = 128
module_param(copybreak, int, 0);
MODULE_PARM_DESC(copybreak, "Receive copy threshold");
-/* io memory shared between all devices */
-static void __iomem *bcm_enet_shared_base;
+/* io registers memory shared between all devices */
+static void __iomem *bcm_enet_shared_base[3];
/*
* io helpers to access mac registers
@@ -63,13 +63,35 @@ static inline void enet_writel(struct bc
*/
static inline u32 enet_dma_readl(struct bcm_enet_priv *priv, u32 off)
{
- return bcm_readl(bcm_enet_shared_base + off);
+ return bcm_readl(bcm_enet_shared_base[0] + off);
}
static inline void enet_dma_writel(struct bcm_enet_priv *priv,
u32 val, u32 off)
{
- bcm_writel(val, bcm_enet_shared_base + off);
+ bcm_writel(val, bcm_enet_shared_base[0] + off);
+}
+
+static inline u32 enet_dmac_readl(struct bcm_enet_priv *priv, u32 off)
+{
+ return bcm_readl(bcm_enet_shared_base[1] + off);
+}
+
+static inline void enet_dmac_writel(struct bcm_enet_priv *priv,
+ u32 val, u32 off)
+{
+ bcm_writel(val, bcm_enet_shared_base[1] + off);
+}
+
+static inline u32 enet_dmas_readl(struct bcm_enet_priv *priv, u32 off)
+{
+ return bcm_readl(bcm_enet_shared_base[2] + off);
+}
+
+static inline void enet_dmas_writel(struct bcm_enet_priv *priv,
+ u32 val, u32 off)
+{
+ bcm_writel(val, bcm_enet_shared_base[2] + off);
}
/*
@@ -353,8 +375,8 @@ static int bcm_enet_receive_queue(struct
bcm_enet_refill_rx(dev);
/* kick rx dma */
- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
- ENETDMA_CHANCFG_REG(priv->rx_chan));
+ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
+ ENETDMAC_CHANCFG_REG(priv->rx_chan));
}
return processed;
@@ -429,10 +451,10 @@ static int bcm_enet_poll(struct napi_str
dev = priv->net_dev;
/* ack interrupts */
- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
- ENETDMA_IR_REG(priv->rx_chan));
- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
- ENETDMA_IR_REG(priv->tx_chan));
+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
+ ENETDMAC_IR_REG(priv->rx_chan));
+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
+ ENETDMAC_IR_REG(priv->tx_chan));
/* reclaim sent skb */
tx_work_done = bcm_enet_tx_reclaim(dev, 0);
@@ -451,10 +473,10 @@ static int bcm_enet_poll(struct napi_str
napi_complete(napi);
/* restore rx/tx interrupt */
- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
- ENETDMA_IRMASK_REG(priv->rx_chan));
- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
- ENETDMA_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
+ ENETDMAC_IRMASK_REG(priv->rx_chan));
+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
+ ENETDMAC_IRMASK_REG(priv->tx_chan));
return rx_work_done;
}
@@ -497,8 +519,8 @@ static irqreturn_t bcm_enet_isr_dma(int
priv = netdev_priv(dev);
/* mask rx/tx interrupts */
- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
napi_schedule(&priv->napi);
@@ -557,8 +579,8 @@ static int bcm_enet_start_xmit(struct sk
wmb();
/* kick tx dma */
- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
- ENETDMA_CHANCFG_REG(priv->tx_chan));
+ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
+ ENETDMAC_CHANCFG_REG(priv->tx_chan));
/* stop queue if no more desc available */
if (!priv->tx_desc_count)
@@ -833,8 +855,8 @@ static int bcm_enet_open(struct net_devi
/* mask all interrupts and request them */
enet_writel(priv, 0, ENET_IRMASK_REG);
- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev);
if (ret)
@@ -919,28 +941,28 @@ static int bcm_enet_open(struct net_devi
}
/* write rx & tx ring addresses */
- enet_dma_writel(priv, priv->rx_desc_dma,
- ENETDMA_RSTART_REG(priv->rx_chan));
- enet_dma_writel(priv, priv->tx_desc_dma,
- ENETDMA_RSTART_REG(priv->tx_chan));
+ enet_dmas_writel(priv, priv->rx_desc_dma,
+ ENETDMAS_RSTART_REG(priv->rx_chan));
+ enet_dmas_writel(priv, priv->tx_desc_dma,
+ ENETDMAS_RSTART_REG(priv->tx_chan));
/* clear remaining state ram for rx & tx channel */
- enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->rx_chan));
- enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->tx_chan));
- enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->rx_chan));
- enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->tx_chan));
- enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->rx_chan));
- enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->tx_chan));
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan));
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan));
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan));
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan));
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan));
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
/* set max rx/tx length */
enet_writel(priv, priv->hw_mtu, ENET_RXMAXLEN_REG);
enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG);
/* set dma maximum burst len */
- enet_dma_writel(priv, BCMENET_DMA_MAXBURST,
- ENETDMA_MAXBURST_REG(priv->rx_chan));
- enet_dma_writel(priv, BCMENET_DMA_MAXBURST,
- ENETDMA_MAXBURST_REG(priv->tx_chan));
+ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
+ ENETDMAC_MAXBURST_REG(priv->rx_chan));
+ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
+ ENETDMAC_MAXBURST_REG(priv->tx_chan));
/* set correct transmit fifo watermark */
enet_writel(priv, BCMENET_TX_FIFO_TRESH, ENET_TXWMARK_REG);
@@ -958,26 +980,26 @@ static int bcm_enet_open(struct net_devi
val |= ENET_CTL_ENABLE_MASK;
enet_writel(priv, val, ENET_CTL_REG);
enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
- ENETDMA_CHANCFG_REG(priv->rx_chan));
+ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
+ ENETDMAC_CHANCFG_REG(priv->rx_chan));
/* watch "mib counters about to overflow" interrupt */
enet_writel(priv, ENET_IR_MIB, ENET_IR_REG);
enet_writel(priv, ENET_IR_MIB, ENET_IRMASK_REG);
/* watch "packet transferred" interrupt in rx and tx */
- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
- ENETDMA_IR_REG(priv->rx_chan));
- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
- ENETDMA_IR_REG(priv->tx_chan));
+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
+ ENETDMAC_IR_REG(priv->rx_chan));
+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
+ ENETDMAC_IR_REG(priv->tx_chan));
/* make sure we enable napi before rx interrupt */
napi_enable(&priv->napi);
- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
- ENETDMA_IRMASK_REG(priv->rx_chan));
- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
- ENETDMA_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
+ ENETDMAC_IRMASK_REG(priv->rx_chan));
+ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
+ ENETDMAC_IRMASK_REG(priv->tx_chan));
if (priv->has_phy)
phy_start(priv->phydev);
@@ -1057,14 +1079,14 @@ static void bcm_enet_disable_dma(struct
{
int limit;
- enet_dma_writel(priv, 0, ENETDMA_CHANCFG_REG(chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_CHANCFG_REG(chan));
limit = 1000;
do {
u32 val;
- val = enet_dma_readl(priv, ENETDMA_CHANCFG_REG(chan));
- if (!(val & ENETDMA_CHANCFG_EN_MASK))
+ val = enet_dmac_readl(priv, ENETDMAC_CHANCFG_REG(chan));
+ if (!(val & ENETDMAC_CHANCFG_EN_MASK))
break;
udelay(1);
} while (limit--);
@@ -1090,8 +1112,8 @@ static int bcm_enet_stop(struct net_devi
/* mask all interrupts */
enet_writel(priv, 0, ENET_IRMASK_REG);
- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
/* make sure no mib update is scheduled */
cancel_work_sync(&priv->mib_update_task);
@@ -1636,7 +1658,7 @@ static int bcm_enet_probe(struct platfor
/* stop if shared driver failed, assume driver->probe will be
* called in the same order we register devices (correct ?) */
- if (!bcm_enet_shared_base)
+ if (!bcm_enet_shared_base[0])
return -ENODEV;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1882,14 +1904,19 @@ struct platform_driver bcm63xx_enet_driv
static int bcm_enet_shared_probe(struct platform_device *pdev)
{
struct resource *res;
+ void __iomem *p[3];
+ unsigned int i;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
+ memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base));
- bcm_enet_shared_base = devm_request_and_ioremap(&pdev->dev, res);
- if (!bcm_enet_shared_base)
- return -ENOMEM;
+ for (i = 0; i < 3; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ p[i] = devm_ioremap_resource(&pdev->dev, res);
+ if (!p[i])
+ return -ENOMEM;
+ }
+
+ memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base));
return 0;
}

View file

@ -0,0 +1,838 @@
From fb7e08ec47f7168b8f4f72d8e3b5bcf625e1089e Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Wed, 12 Jun 2013 18:53:05 +0000
Subject: [PATCH] bcm63xx_enet: add support Broadcom BCM6345 Ethernet
This patch adds support for the Broadcom BCM6345 SoC Ethernet. BCM6345
has a slightly different and older DMA engine which requires the
following modifications:
- the width of the DMA channels on BCM6345 is 64 bytes vs 16 bytes,
which means that the helpers enet_dma{c,s} need to account for this
channel width and we can no longer use macros
- BCM6345 DMA engine does not have any internal SRAM for transfering
buffers
- BCM6345 buffer allocation and flow control is not per-channel but
global (done in RSET_ENETDMA)
- the DMA engine bits are right-shifted by 3 compared to other DMA
generations
- the DMA enable/interrupt masks are a little different (we need to
enabled more bits for 6345)
- some register have the same meaning but are offsetted in the ENET_DMAC
space so a lookup table is required to return the proper offset
The MAC itself is identical and requires no modifications to work.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/bcm63xx/dev-enet.c | 65 ++++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 3 +-
.../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 94 +++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 43 ++++-
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 200 ++++++++++++--------
drivers/net/ethernet/broadcom/bcm63xx_enet.h | 15 ++
6 files changed, 329 insertions(+), 91 deletions(-)
--- a/arch/mips/bcm63xx/dev-enet.c
+++ b/arch/mips/bcm63xx/dev-enet.c
@@ -9,10 +9,44 @@
#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 */
@@ -137,12 +171,19 @@ static int __init register_shared(void)
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;
- shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
+ 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;
@@ -172,7 +213,7 @@ int __init bcm63xx_enet_register(int uni
if (unit > 1)
return -ENODEV;
- if (unit == 1 && BCMCPU_IS_6338())
+ if (unit == 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345()))
return -ENODEV;
ret = register_shared();
@@ -213,6 +254,21 @@ int __init bcm63xx_enet_register(int uni
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;
@@ -246,6 +302,11 @@ bcm63xx_enetsw_register(const struct bcm
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;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -188,6 +188,7 @@ enum bcm63xx_regs_set {
#define BCM_6368_RSET_SPI_SIZE 1804
#define RSET_ENET_SIZE 2048
#define RSET_ENETDMA_SIZE 256
+#define RSET_6345_ENETDMA_SIZE 64
#define RSET_ENETDMAC_SIZE(chans) (16 * (chans))
#define RSET_ENETDMAS_SIZE(chans) (16 * (chans))
#define RSET_ENETSW_SIZE 65536
@@ -363,7 +364,7 @@ enum bcm63xx_regs_set {
#define BCM_6345_USBDMA_BASE (0xfffe2800)
#define BCM_6345_ENET0_BASE (0xfffe1800)
#define BCM_6345_ENETDMA_BASE (0xfffe2800)
-#define BCM_6345_ENETDMAC_BASE (0xfffe2900)
+#define BCM_6345_ENETDMAC_BASE (0xfffe2840)
#define BCM_6345_ENETDMAS_BASE (0xfffe2a00)
#define BCM_6345_ENETSW_BASE (0xdeadbeef)
#define BCM_6345_PCMCIA_BASE (0xfffe2028)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
@@ -4,6 +4,8 @@
#include <linux/if_ether.h>
#include <linux/init.h>
+#include <bcm63xx_regs.h>
+
/*
* on board ethernet platform data
*/
@@ -37,6 +39,21 @@ struct bcm63xx_enet_platform_data {
int phy_id, int reg),
void (*mii_write)(struct net_device *dev,
int phy_id, int reg, int val));
+
+ /* DMA channel enable mask */
+ u32 dma_chan_en_mask;
+
+ /* DMA channel interrupt mask */
+ u32 dma_chan_int_mask;
+
+ /* DMA engine has internal SRAM */
+ bool dma_has_sram;
+
+ /* DMA channel register width */
+ unsigned int dma_chan_width;
+
+ /* DMA descriptor shift */
+ unsigned int dma_desc_shift;
};
/*
@@ -63,6 +80,18 @@ struct bcm63xx_enetsw_platform_data {
char mac_addr[ETH_ALEN];
int num_ports;
struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
+
+ /* DMA channel enable mask */
+ u32 dma_chan_en_mask;
+
+ /* DMA channel interrupt mask */
+ u32 dma_chan_int_mask;
+
+ /* DMA channel register width */
+ unsigned int dma_chan_width;
+
+ /* DMA engine has internal SRAM */
+ bool dma_has_sram;
};
int __init bcm63xx_enet_register(int unit,
@@ -70,4 +99,69 @@ int __init bcm63xx_enet_register(int uni
int bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd);
+enum bcm63xx_regs_enetdmac {
+ ENETDMAC_CHANCFG,
+ ENETDMAC_IR,
+ ENETDMAC_IRMASK,
+ ENETDMAC_MAXBURST,
+ ENETDMAC_BUFALLOC,
+ ENETDMAC_RSTART,
+ ENETDMAC_FC,
+ ENETDMAC_LEN,
+};
+
+static inline unsigned long bcm63xx_enetdmacreg(enum bcm63xx_regs_enetdmac reg)
+{
+#ifdef BCMCPU_RUNTIME_DETECT
+ extern const unsigned long *bcm63xx_regs_enetdmac;
+
+ return bcm63xx_regs_enetdmac[reg];
+#else
+#ifdef CONFIG_BCM63XX_CPU_6345
+ switch (reg) {
+ case ENETDMAC_CHANCFG:
+ return ENETDMA_6345_CHANCFG_REG;
+ case ENETDMAC_IR:
+ return ENETDMA_6345_IR_REG;
+ case ENETDMAC_IRMASK:
+ return ENETDMA_6345_IRMASK_REG;
+ case ENETDMAC_MAXBURST:
+ return ENETDMA_6345_MAXBURST_REG;
+ case ENETDMAC_BUFALLOC:
+ return ENETDMA_6345_BUFALLOC_REG;
+ case ENETDMAC_RSTART:
+ return ENETDMA_6345_RSTART_REG;
+ case ENETDMAC_FC:
+ return ENETDMA_6345_FC_REG;
+ case ENETDMAC_LEN:
+ return ENETDMA_6345_LEN_REG;
+ }
+#endif
+#if defined(CONFIG_BCM63XX_CPU_6328) || \
+ defined(CONFIG_BCM63XX_CPU_6338) || \
+ defined(CONFIG_BCM63XX_CPU_6348) || \
+ defined(CONFIG_BCM63XX_CPU_6358) || \
+ defined(CONFIG_BCM63XX_CPU_6362) || \
+ defined(CONFIG_BCM63XX_CPU_6368)
+ switch (reg) {
+ case ENETDMAC_CHANCFG:
+ return ENETDMAC_CHANCFG_REG;
+ case ENETDMAC_IR:
+ return ENETDMAC_IR_REG;
+ case ENETDMAC_IRMASK:
+ return ENETDMAC_IRMASK_REG;
+ case ENETDMAC_MAXBURST:
+ return ENETDMAC_MAXBURST_REG;
+ case ENETDMAC_BUFALLOC:
+ case ENETDMAC_RSTART:
+ case ENETDMAC_FC:
+ case ENETDMAC_LEN:
+ return 0;
+ }
+#endif
+#endif
+ return 0;
+}
+
+
#endif /* ! BCM63XX_DEV_ENET_H_ */
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -770,6 +770,8 @@
/*************************************************************************
* _REG relative to RSET_ENETDMA
*************************************************************************/
+#define ENETDMA_CHAN_WIDTH 0x10
+#define ENETDMA_6345_CHAN_WIDTH 0x40
/* Controller Configuration Register */
#define ENETDMA_CFG_REG (0x0)
@@ -825,31 +827,56 @@
/* State Ram Word 4 */
#define ENETDMA_SRAM4_REG(x) (0x20c + (x) * 0x10)
+/* Broadcom 6345 ENET DMA definitions */
+#define ENETDMA_6345_CHANCFG_REG (0x00)
+
+#define ENETDMA_6345_MAXBURST_REG (0x40)
+
+#define ENETDMA_6345_RSTART_REG (0x08)
+
+#define ENETDMA_6345_LEN_REG (0x0C)
+
+#define ENETDMA_6345_IR_REG (0x14)
+
+#define ENETDMA_6345_IRMASK_REG (0x18)
+
+#define ENETDMA_6345_FC_REG (0x1C)
+
+#define ENETDMA_6345_BUFALLOC_REG (0x20)
+
+/* Shift down for EOP, SOP and WRAP bits */
+#define ENETDMA_6345_DESC_SHIFT (3)
/*************************************************************************
* _REG relative to RSET_ENETDMAC
*************************************************************************/
/* Channel Configuration register */
-#define ENETDMAC_CHANCFG_REG(x) ((x) * 0x10)
+#define ENETDMAC_CHANCFG_REG (0x0)
#define ENETDMAC_CHANCFG_EN_SHIFT 0
#define ENETDMAC_CHANCFG_EN_MASK (1 << ENETDMAC_CHANCFG_EN_SHIFT)
#define ENETDMAC_CHANCFG_PKTHALT_SHIFT 1
#define ENETDMAC_CHANCFG_PKTHALT_MASK (1 << ENETDMAC_CHANCFG_PKTHALT_SHIFT)
#define ENETDMAC_CHANCFG_BUFHALT_SHIFT 2
#define ENETDMAC_CHANCFG_BUFHALT_MASK (1 << ENETDMAC_CHANCFG_BUFHALT_SHIFT)
+#define ENETDMAC_CHANCFG_CHAINING_SHIFT 2
+#define ENETDMAC_CHANCFG_CHAINING_MASK (1 << ENETDMAC_CHANCFG_CHAINING_SHIFT)
+#define ENETDMAC_CHANCFG_WRAP_EN_SHIFT 3
+#define ENETDMAC_CHANCFG_WRAP_EN_MASK (1 << ENETDMAC_CHANCFG_WRAP_EN_SHIFT)
+#define ENETDMAC_CHANCFG_FLOWC_EN_SHIFT 4
+#define ENETDMAC_CHANCFG_FLOWC_EN_MASK (1 << ENETDMAC_CHANCFG_FLOWC_EN_SHIFT)
/* Interrupt Control/Status register */
-#define ENETDMAC_IR_REG(x) (0x4 + (x) * 0x10)
+#define ENETDMAC_IR_REG (0x4)
#define ENETDMAC_IR_BUFDONE_MASK (1 << 0)
#define ENETDMAC_IR_PKTDONE_MASK (1 << 1)
#define ENETDMAC_IR_NOTOWNER_MASK (1 << 2)
/* Interrupt Mask register */
-#define ENETDMAC_IRMASK_REG(x) (0x8 + (x) * 0x10)
+#define ENETDMAC_IRMASK_REG (0x8)
/* Maximum Burst Length */
-#define ENETDMAC_MAXBURST_REG(x) (0xc + (x) * 0x10)
+#define ENETDMAC_MAXBURST_REG (0xc)
/*************************************************************************
@@ -857,16 +884,16 @@
*************************************************************************/
/* Ring Start Address register */
-#define ENETDMAS_RSTART_REG(x) ((x) * 0x10)
+#define ENETDMAS_RSTART_REG (0x0)
/* State Ram Word 2 */
-#define ENETDMAS_SRAM2_REG(x) (0x4 + (x) * 0x10)
+#define ENETDMAS_SRAM2_REG (0x4)
/* State Ram Word 3 */
-#define ENETDMAS_SRAM3_REG(x) (0x8 + (x) * 0x10)
+#define ENETDMAS_SRAM3_REG (0x8)
/* State Ram Word 4 */
-#define ENETDMAS_SRAM4_REG(x) (0xc + (x) * 0x10)
+#define ENETDMAS_SRAM4_REG (0xc)
/*************************************************************************
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -107,26 +107,28 @@ static inline void enet_dma_writel(struc
bcm_writel(val, bcm_enet_shared_base[0] + off);
}
-static inline u32 enet_dmac_readl(struct bcm_enet_priv *priv, u32 off)
+static inline u32 enet_dmac_readl(struct bcm_enet_priv *priv, u32 off, int chan)
{
- return bcm_readl(bcm_enet_shared_base[1] + off);
+ return bcm_readl(bcm_enet_shared_base[1] +
+ bcm63xx_enetdmacreg(off) + chan * priv->dma_chan_width);
}
static inline void enet_dmac_writel(struct bcm_enet_priv *priv,
- u32 val, u32 off)
+ u32 val, u32 off, int chan)
{
- bcm_writel(val, bcm_enet_shared_base[1] + off);
+ bcm_writel(val, bcm_enet_shared_base[1] +
+ bcm63xx_enetdmacreg(off) + chan * priv->dma_chan_width);
}
-static inline u32 enet_dmas_readl(struct bcm_enet_priv *priv, u32 off)
+static inline u32 enet_dmas_readl(struct bcm_enet_priv *priv, u32 off, int chan)
{
- return bcm_readl(bcm_enet_shared_base[2] + off);
+ return bcm_readl(bcm_enet_shared_base[2] + off + chan * priv->dma_chan_width);
}
static inline void enet_dmas_writel(struct bcm_enet_priv *priv,
- u32 val, u32 off)
+ u32 val, u32 off, int chan)
{
- bcm_writel(val, bcm_enet_shared_base[2] + off);
+ bcm_writel(val, bcm_enet_shared_base[2] + off + chan * priv->dma_chan_width);
}
/*
@@ -262,7 +264,7 @@ static int bcm_enet_refill_rx(struct net
len_stat = priv->rx_skb_size << DMADESC_LENGTH_SHIFT;
len_stat |= DMADESC_OWNER_MASK;
if (priv->rx_dirty_desc == priv->rx_ring_size - 1) {
- len_stat |= DMADESC_WRAP_MASK;
+ len_stat |= (DMADESC_WRAP_MASK >> priv->dma_desc_shift);
priv->rx_dirty_desc = 0;
} else {
priv->rx_dirty_desc++;
@@ -273,7 +275,10 @@ static int bcm_enet_refill_rx(struct net
priv->rx_desc_count++;
/* tell dma engine we allocated one buffer */
- enet_dma_writel(priv, 1, ENETDMA_BUFALLOC_REG(priv->rx_chan));
+ if (priv->dma_has_sram)
+ enet_dma_writel(priv, 1, ENETDMA_BUFALLOC_REG(priv->rx_chan));
+ else
+ enet_dmac_writel(priv, 1, ENETDMAC_BUFALLOC, priv->rx_chan);
}
/* If rx ring is still empty, set a timer to try allocating
@@ -349,7 +354,8 @@ static int bcm_enet_receive_queue(struct
/* if the packet does not have start of packet _and_
* end of packet flag set, then just recycle it */
- if ((len_stat & DMADESC_ESOP_MASK) != DMADESC_ESOP_MASK) {
+ if ((len_stat & (DMADESC_ESOP_MASK >> priv->dma_desc_shift)) !=
+ (DMADESC_ESOP_MASK >> priv->dma_desc_shift)) {
dev->stats.rx_dropped++;
continue;
}
@@ -410,8 +416,8 @@ static int bcm_enet_receive_queue(struct
bcm_enet_refill_rx(dev);
/* kick rx dma */
- enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
- ENETDMAC_CHANCFG_REG(priv->rx_chan));
+ enet_dmac_writel(priv, priv->dma_chan_en_mask,
+ ENETDMAC_CHANCFG, priv->rx_chan);
}
return processed;
@@ -486,10 +492,10 @@ static int bcm_enet_poll(struct napi_str
dev = priv->net_dev;
/* ack interrupts */
- enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IR_REG(priv->rx_chan));
- enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IR_REG(priv->tx_chan));
+ enet_dmac_writel(priv, priv->dma_chan_int_mask,
+ ENETDMAC_IR, priv->rx_chan);
+ enet_dmac_writel(priv, priv->dma_chan_int_mask,
+ ENETDMAC_IR, priv->tx_chan);
/* reclaim sent skb */
tx_work_done = bcm_enet_tx_reclaim(dev, 0);
@@ -508,10 +514,10 @@ static int bcm_enet_poll(struct napi_str
napi_complete(napi);
/* restore rx/tx interrupt */
- enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IRMASK_REG(priv->rx_chan));
- enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, priv->dma_chan_int_mask,
+ ENETDMAC_IRMASK, priv->rx_chan);
+ enet_dmac_writel(priv, priv->dma_chan_int_mask,
+ ENETDMAC_IRMASK, priv->tx_chan);
return rx_work_done;
}
@@ -554,8 +560,8 @@ static irqreturn_t bcm_enet_isr_dma(int
priv = netdev_priv(dev);
/* mask rx/tx interrupts */
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan);
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan);
napi_schedule(&priv->napi);
@@ -616,14 +622,14 @@ static int bcm_enet_start_xmit(struct sk
DMA_TO_DEVICE);
len_stat = (skb->len << DMADESC_LENGTH_SHIFT) & DMADESC_LENGTH_MASK;
- len_stat |= DMADESC_ESOP_MASK |
+ len_stat |= (DMADESC_ESOP_MASK >> priv->dma_desc_shift) |
DMADESC_APPEND_CRC |
DMADESC_OWNER_MASK;
priv->tx_curr_desc++;
if (priv->tx_curr_desc == priv->tx_ring_size) {
priv->tx_curr_desc = 0;
- len_stat |= DMADESC_WRAP_MASK;
+ len_stat |= (DMADESC_WRAP_MASK >> priv->dma_desc_shift);
}
priv->tx_desc_count--;
@@ -634,8 +640,8 @@ static int bcm_enet_start_xmit(struct sk
wmb();
/* kick tx dma */
- enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
- ENETDMAC_CHANCFG_REG(priv->tx_chan));
+ enet_dmac_writel(priv, priv->dma_chan_en_mask,
+ ENETDMAC_CHANCFG, priv->tx_chan);
/* stop queue if no more desc available */
if (!priv->tx_desc_count)
@@ -763,6 +769,9 @@ static void bcm_enet_set_flow(struct bcm
val &= ~ENET_RXCFG_ENFLOW_MASK;
enet_writel(priv, val, ENET_RXCFG_REG);
+ if (!priv->dma_has_sram)
+ return;
+
/* tx flow control (pause frame generation) */
val = enet_dma_readl(priv, ENETDMA_CFG_REG);
if (tx_en)
@@ -910,8 +919,8 @@ static int bcm_enet_open(struct net_devi
/* mask all interrupts and request them */
enet_writel(priv, 0, ENET_IRMASK_REG);
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan);
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan);
ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev);
if (ret)
@@ -986,8 +995,12 @@ static int bcm_enet_open(struct net_devi
priv->rx_curr_desc = 0;
/* initialize flow control buffer allocation */
- enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
- ENETDMA_BUFALLOC_REG(priv->rx_chan));
+ if (priv->dma_has_sram)
+ enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
+ ENETDMA_BUFALLOC_REG(priv->rx_chan));
+ else
+ enet_dmac_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
+ ENETDMAC_BUFALLOC, priv->rx_chan);
if (bcm_enet_refill_rx(dev)) {
dev_err(kdev, "cannot allocate rx skb queue\n");
@@ -996,18 +1009,30 @@ static int bcm_enet_open(struct net_devi
}
/* write rx & tx ring addresses */
- enet_dmas_writel(priv, priv->rx_desc_dma,
- ENETDMAS_RSTART_REG(priv->rx_chan));
- enet_dmas_writel(priv, priv->tx_desc_dma,
- ENETDMAS_RSTART_REG(priv->tx_chan));
+ if (priv->dma_has_sram) {
+ enet_dmas_writel(priv, priv->rx_desc_dma,
+ ENETDMAS_RSTART_REG, priv->rx_chan);
+ enet_dmas_writel(priv, priv->tx_desc_dma,
+ ENETDMAS_RSTART_REG, priv->tx_chan);
+ } else {
+ enet_dmac_writel(priv, priv->rx_desc_dma,
+ ENETDMAC_RSTART, priv->rx_chan);
+ enet_dmac_writel(priv, priv->tx_desc_dma,
+ ENETDMAC_RSTART, priv->tx_chan);
+ }
/* clear remaining state ram for rx & tx channel */
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
+ if (priv->dma_has_sram) {
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG, priv->rx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG, priv->tx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG, priv->rx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG, priv->tx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG, priv->rx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG, priv->tx_chan);
+ } else {
+ enet_dmac_writel(priv, 0, ENETDMAC_FC, priv->rx_chan);
+ enet_dmac_writel(priv, 0, ENETDMAC_FC, priv->tx_chan);
+ }
/* set max rx/tx length */
enet_writel(priv, priv->hw_mtu, ENET_RXMAXLEN_REG);
@@ -1015,18 +1040,24 @@ static int bcm_enet_open(struct net_devi
/* set dma maximum burst len */
enet_dmac_writel(priv, priv->dma_maxburst,
- ENETDMAC_MAXBURST_REG(priv->rx_chan));
+ ENETDMAC_MAXBURST, priv->rx_chan);
enet_dmac_writel(priv, priv->dma_maxburst,
- ENETDMAC_MAXBURST_REG(priv->tx_chan));
+ ENETDMAC_MAXBURST, priv->tx_chan);
/* set correct transmit fifo watermark */
enet_writel(priv, BCMENET_TX_FIFO_TRESH, ENET_TXWMARK_REG);
/* set flow control low/high threshold to 1/3 / 2/3 */
- val = priv->rx_ring_size / 3;
- enet_dma_writel(priv, val, ENETDMA_FLOWCL_REG(priv->rx_chan));
- val = (priv->rx_ring_size * 2) / 3;
- enet_dma_writel(priv, val, ENETDMA_FLOWCH_REG(priv->rx_chan));
+ if (priv->dma_has_sram) {
+ val = priv->rx_ring_size / 3;
+ enet_dma_writel(priv, val, ENETDMA_FLOWCL_REG(priv->rx_chan));
+ val = (priv->rx_ring_size * 2) / 3;
+ enet_dma_writel(priv, val, ENETDMA_FLOWCH_REG(priv->rx_chan));
+ } else {
+ enet_dmac_writel(priv, 5, ENETDMAC_FC, priv->rx_chan);
+ enet_dmac_writel(priv, priv->rx_ring_size, ENETDMAC_LEN, priv->rx_chan);
+ enet_dmac_writel(priv, priv->tx_ring_size, ENETDMAC_LEN, priv->tx_chan);
+ }
/* all set, enable mac and interrupts, start dma engine and
* kick rx dma channel */
@@ -1035,26 +1066,26 @@ static int bcm_enet_open(struct net_devi
val |= ENET_CTL_ENABLE_MASK;
enet_writel(priv, val, ENET_CTL_REG);
enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
- enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
- ENETDMAC_CHANCFG_REG(priv->rx_chan));
+ enet_dmac_writel(priv, priv->dma_chan_en_mask,
+ ENETDMAC_CHANCFG, priv->rx_chan);
/* watch "mib counters about to overflow" interrupt */
enet_writel(priv, ENET_IR_MIB, ENET_IR_REG);
enet_writel(priv, ENET_IR_MIB, ENET_IRMASK_REG);
/* watch "packet transferred" interrupt in rx and tx */
- enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IR_REG(priv->rx_chan));
- enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IR_REG(priv->tx_chan));
+ enet_dmac_writel(priv, priv->dma_chan_int_mask,
+ ENETDMAC_IR, priv->rx_chan);
+ enet_dmac_writel(priv, priv->dma_chan_int_mask,
+ ENETDMAC_IR, priv->tx_chan);
/* make sure we enable napi before rx interrupt */
napi_enable(&priv->napi);
- enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IRMASK_REG(priv->rx_chan));
- enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, priv->dma_chan_int_mask,
+ ENETDMAC_IRMASK, priv->rx_chan);
+ enet_dmac_writel(priv, priv->dma_chan_int_mask,
+ ENETDMAC_IRMASK, priv->tx_chan);
if (priv->has_phy)
phy_start(priv->phydev);
@@ -1134,13 +1165,13 @@ static void bcm_enet_disable_dma(struct
{
int limit;
- enet_dmac_writel(priv, 0, ENETDMAC_CHANCFG_REG(chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_CHANCFG, chan);
limit = 1000;
do {
u32 val;
- val = enet_dmac_readl(priv, ENETDMAC_CHANCFG_REG(chan));
+ val = enet_dmac_readl(priv, ENETDMAC_CHANCFG, chan);
if (!(val & ENETDMAC_CHANCFG_EN_MASK))
break;
udelay(1);
@@ -1167,8 +1198,8 @@ static int bcm_enet_stop(struct net_devi
/* mask all interrupts */
enet_writel(priv, 0, ENET_IRMASK_REG);
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan);
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan);
/* make sure no mib update is scheduled */
cancel_work_sync(&priv->mib_update_task);
@@ -1782,6 +1813,11 @@ static int bcm_enet_probe(struct platfor
priv->pause_tx = pd->pause_tx;
priv->force_duplex_full = pd->force_duplex_full;
priv->force_speed_100 = pd->force_speed_100;
+ priv->dma_chan_en_mask = pd->dma_chan_en_mask;
+ priv->dma_chan_int_mask = pd->dma_chan_int_mask;
+ priv->dma_chan_width = pd->dma_chan_width;
+ priv->dma_has_sram = pd->dma_has_sram;
+ priv->dma_desc_shift = pd->dma_desc_shift;
}
if (priv->mac_id == 0 && priv->has_phy && !priv->use_external_mii) {
@@ -2119,8 +2155,8 @@ static int bcm_enetsw_open(struct net_de
kdev = &priv->pdev->dev;
/* mask all interrupts and request them */
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan);
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan);
ret = request_irq(priv->irq_rx, bcm_enet_isr_dma,
IRQF_DISABLED, dev->name, dev);
@@ -2232,23 +2268,23 @@ static int bcm_enetsw_open(struct net_de
/* write rx & tx ring addresses */
enet_dmas_writel(priv, priv->rx_desc_dma,
- ENETDMAS_RSTART_REG(priv->rx_chan));
+ ENETDMAS_RSTART_REG, priv->rx_chan);
enet_dmas_writel(priv, priv->tx_desc_dma,
- ENETDMAS_RSTART_REG(priv->tx_chan));
+ ENETDMAS_RSTART_REG, priv->tx_chan);
/* clear remaining state ram for rx & tx channel */
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan));
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG, priv->rx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG, priv->tx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG, priv->rx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG, priv->tx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG, priv->rx_chan);
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG, priv->tx_chan);
/* set dma maximum burst len */
enet_dmac_writel(priv, priv->dma_maxburst,
- ENETDMAC_MAXBURST_REG(priv->rx_chan));
+ ENETDMAC_MAXBURST, priv->rx_chan);
enet_dmac_writel(priv, priv->dma_maxburst,
- ENETDMAC_MAXBURST_REG(priv->tx_chan));
+ ENETDMAC_MAXBURST, priv->tx_chan);
/* set flow control low/high threshold to 1/3 / 2/3 */
val = priv->rx_ring_size / 3;
@@ -2262,21 +2298,21 @@ static int bcm_enetsw_open(struct net_de
wmb();
enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
- ENETDMAC_CHANCFG_REG(priv->rx_chan));
+ ENETDMAC_CHANCFG, priv->rx_chan);
/* watch "packet transferred" interrupt in rx and tx */
enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IR_REG(priv->rx_chan));
+ ENETDMAC_IR, priv->rx_chan);
enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IR_REG(priv->tx_chan));
+ ENETDMAC_IR, priv->tx_chan);
/* make sure we enable napi before rx interrupt */
napi_enable(&priv->napi);
enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IRMASK_REG(priv->rx_chan));
+ ENETDMAC_IRMASK, priv->rx_chan);
enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
- ENETDMAC_IRMASK_REG(priv->tx_chan));
+ ENETDMAC_IRMASK, priv->tx_chan);
netif_carrier_on(dev);
netif_start_queue(dev);
@@ -2378,8 +2414,8 @@ static int bcm_enetsw_stop(struct net_de
del_timer_sync(&priv->rx_timeout);
/* mask all interrupts */
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
- enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan);
+ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan);
/* disable dma & mac */
bcm_enet_disable_dma(priv, priv->tx_chan);
@@ -2713,6 +2749,10 @@ static int bcm_enetsw_probe(struct platf
memcpy(priv->used_ports, pd->used_ports,
sizeof(pd->used_ports));
priv->num_ports = pd->num_ports;
+ priv->dma_has_sram = pd->dma_has_sram;
+ priv->dma_chan_en_mask = pd->dma_chan_en_mask;
+ priv->dma_chan_int_mask = pd->dma_chan_int_mask;
+ priv->dma_chan_width = pd->dma_chan_width;
}
ret = compute_hw_mtu(priv, dev->mtu);
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
@@ -339,6 +339,21 @@ struct bcm_enet_priv {
/* used to poll switch port state */
struct timer_list swphy_poll;
spinlock_t enetsw_mdio_lock;
+
+ /* dma channel enable mask */
+ u32 dma_chan_en_mask;
+
+ /* dma channel interrupt mask */
+ u32 dma_chan_int_mask;
+
+ /* DMA engine has internal SRAM */
+ bool dma_has_sram;
+
+ /* dma channel width */
+ unsigned int dma_chan_width;
+
+ /* dma descriptor shift value */
+ unsigned int dma_desc_shift;
};

View file

@ -0,0 +1,67 @@
From d55975b74389b2cf1a38732062ff89303940f6e1 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 29 Jun 2013 11:46:56 +0200
Subject: [PATCH 01/10] MIPS: bmips: fix compilation for BMIPS5000
Replace the macro names in strings with actual macro invocation.
Fixes the following build error:
CC arch/mips/kernel/smp-bmips.o
{standard input}: Assembler messages:
{standard input}:951: Error: Unrecognized opcode `_ssnop'
{standard input}:952: Error: Unrecognized opcode `_ssnop'
(...)
make[6]: *** [arch/mips/kernel/smp-bmips.o] Error 1
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/include/asm/bmips.h | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
--- a/arch/mips/include/asm/bmips.h
+++ b/arch/mips/include/asm/bmips.h
@@ -70,15 +70,15 @@ static inline unsigned long bmips_read_z
".set noreorder\n"
"cache %1, 0(%2)\n"
"sync\n"
- "_ssnop\n"
- "_ssnop\n"
- "_ssnop\n"
- "_ssnop\n"
- "_ssnop\n"
- "_ssnop\n"
- "_ssnop\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
"mfc0 %0, $28, 3\n"
- "_ssnop\n"
+ __stringify(___ssnop) "\n"
".set pop\n"
: "=&r" (ret)
: "i" (Index_Load_Tag_S), "r" (ZSCM_REG_BASE + offset)
@@ -92,13 +92,13 @@ static inline void bmips_write_zscm_reg(
".set push\n"
".set noreorder\n"
"mtc0 %0, $28, 3\n"
- "_ssnop\n"
- "_ssnop\n"
- "_ssnop\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
"cache %1, 0(%2)\n"
- "_ssnop\n"
- "_ssnop\n"
- "_ssnop\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
+ __stringify(___ssnop) "\n"
: /* no outputs */
: "r" (data),
"i" (Index_Store_Tag_S), "r" (ZSCM_REG_BASE + offset)

View file

@ -0,0 +1,31 @@
From 520f4bf75026cc60ba47946331966fb670b39cb0 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 27 Jun 2013 21:32:41 +0200
Subject: [PATCH 02/10] MIPS: allow asm/cpu.h to be included from assembly
Add guards around the enum to allow including cpu.h from assembly.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/include/asm/cpu.h | 3 +++
1 file changed, 3 insertions(+)
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -225,6 +225,8 @@
#define FPIR_IMP_NONE 0x0000
+#if !defined(__ASSEMBLY__)
+
enum cpu_type_enum {
CPU_UNKNOWN,
@@ -277,6 +279,7 @@ enum cpu_type_enum {
CPU_LAST
};
+#endif /* !__ASSEMBLY */
/*
* ISA Level encodings

View file

@ -0,0 +1,36 @@
From 971b8b3d5101b3bb868e63f3eb96fe69b7110c61 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 27 Jun 2013 12:40:15 +0200
Subject: [PATCH 03/10] MIPS: bmips: add macros for testing the current bmips
CPU
Makes it easy to make code conditionally compiled for supported CPUs
without directly relying on #ifdefs.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/include/asm/bmips.h | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/arch/mips/include/asm/bmips.h
+++ b/arch/mips/include/asm/bmips.h
@@ -45,8 +45,19 @@
#if !defined(__ASSEMBLY__)
#include <linux/cpumask.h>
+#include <asm/cpu-features.h>
#include <asm/r4kcache.h>
+#define cpu_is_bmips32() (current_cpu_type() == CPU_BMIPS32)
+#define cpu_is_bmips3300() (IS_ENABLED(CONFIG_CPU_BMIPS3300) && \
+ current_cpu_type() == CPU_BMIPS3300)
+#define cpu_is_bmips4350() (IS_ENABLED(CONFIG_CPU_BMIPS4350) && \
+ current_cpu_type() == CPU_BMIPS4350)
+#define cpu_is_bmips4380() (IS_ENABLED(CONFIG_CPU_BMIPS4380) && \
+ current_cpu_type() == CPU_BMIPS4380)
+#define cpu_is_bmips5000() (IS_ENABLED(CONFIG_CPU_BMIPS5000) && \
+ current_cpu_type() == CPU_BMIPS5000)
+
extern struct plat_smp_ops bmips_smp_ops;
extern char bmips_reset_nmi_vec;
extern char bmips_reset_nmi_vec_end;

View file

@ -0,0 +1,482 @@
From 12594762fcbec024cb424c9b77efb28402651667 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 27 Jun 2013 21:33:56 +0200
Subject: [PATCH 04/10] MIPS: bmips: change compile time checks to runtime
checks
Allow building for all bmips cpus at the same time by changing ifdefs
to checks for the cpu type, or adding appropriate checks to the
assembly.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/kernel/bmips_vec.S | 55 +++++++---
arch/mips/kernel/smp-bmips.c | 241 ++++++++++++++++++++++--------------------
2 files changed, 172 insertions(+), 124 deletions(-)
--- a/arch/mips/kernel/bmips_vec.S
+++ b/arch/mips/kernel/bmips_vec.S
@@ -13,6 +13,7 @@
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/cacheops.h>
+#include <asm/cpu.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
@@ -89,12 +90,18 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
beqz k0, bmips_smp_entry
#if defined(CONFIG_CPU_BMIPS5000)
+ mfc0 k0, CP0_PRID
+ li k1, PRID_IMP_BMIPS5000
+ andi k0, 0xff00
+ bne k0, k1, 1f
+
/* if we're not on core 0, this must be the SMP boot signal */
li k1, (3 << 25)
mfc0 k0, $22
and k0, k1
bnez k0, bmips_smp_entry
-#endif
+1:
+#endif /* CONFIG_CPU_BMIPS5000 */
#endif /* CONFIG_SMP */
/* nope, it's just a regular NMI */
@@ -137,7 +144,12 @@ bmips_smp_entry:
xori k0, 0x04
mtc0 k0, CP0_CONFIG
+ mfc0 k0, CP0_PRID
+ andi k0, 0xff00
#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
+ li k1, PRID_IMP_BMIPS43XX
+ bne k0, k1, 2f
+
/* initialize CPU1's local I-cache */
li k0, 0x80000000
li k1, 0x80010000
@@ -148,14 +160,21 @@ bmips_smp_entry:
1: cache Index_Store_Tag_I, 0(k0)
addiu k0, 16
bne k0, k1, 1b
-#elif defined(CONFIG_CPU_BMIPS5000)
+
+ b 3f
+2:
+#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
+#if defined(CONFIG_CPU_BMIPS5000)
/* set exception vector base */
+ li k1, PRID_IMP_BMIPS5000
+ bne k0, k1, 3f
+
la k0, ebase
lw k0, 0(k0)
mtc0 k0, $15, 1
BARRIER
-#endif
-
+#endif /* CONFIG_CPU_BMIPS5000 */
+3:
/* jump back to kseg0 in case we need to remap the kseg1 area */
la k0, 1f
jr k0
@@ -221,8 +240,18 @@ END(bmips_smp_int_vec)
LEAF(bmips_enable_xks01)
#if defined(CONFIG_XKS01)
-
+ mfc0 t0, CP0_PRID
+ andi t2, t0, 0xff00
#if defined(CONFIG_CPU_BMIPS4380)
+ li t1, PRID_IMP_BMIPS43XX
+ bne t2, t1, 1f
+
+ andi t0, 0xff
+ addiu t1, t0, -PRID_REV_BMIPS4380_HI
+ bgtz t1, 2f
+ addiu t0, -PRID_REV_BMIPS4380_LO
+ bltz t0, 2f
+
mfc0 t0, $22, 3
li t1, 0x1ff0
li t2, (1 << 12) | (1 << 9)
@@ -231,7 +260,13 @@ LEAF(bmips_enable_xks01)
or t0, t2
mtc0 t0, $22, 3
BARRIER
-#elif defined(CONFIG_CPU_BMIPS5000)
+ b 2f
+1:
+#endif /* CONFIG_CPU_BMIPS4380 */
+#if defined(CONFIG_CPU_BMIPS5000)
+ li t1, PRID_IMP_BMIPS5000
+ bne t2, t1, 2f
+
mfc0 t0, $22, 5
li t1, 0x01ff
li t2, (1 << 8) | (1 << 5)
@@ -240,12 +275,8 @@ LEAF(bmips_enable_xks01)
or t0, t2
mtc0 t0, $22, 5
BARRIER
-#else
-
-#error Missing XKS01 setup
-
-#endif
-
+#endif /* CONFIG_CPU_BMIPS5000 */
+2:
#endif /* defined(CONFIG_XKS01) */
jr ra
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -49,8 +49,11 @@ cpumask_t bmips_booted_mask;
unsigned long bmips_smp_boot_sp;
unsigned long bmips_smp_boot_gp;
+static void bmips43xx_send_ipi_single(int cpu, unsigned int action);
+static void bmips5000_send_ipi_single(int cpu, unsigned int action);
static void bmips_send_ipi_single(int cpu, unsigned int action);
-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id);
+static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id);
+static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id);
/* SW interrupts 0,1 are used for interprocessor signaling */
#define IPI0_IRQ (MIPS_CPU_IRQ_BASE + 0)
@@ -65,48 +68,49 @@ static void __init bmips_smp_setup(void)
{
int i, cpu = 1, boot_cpu = 0;
-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
- /* arbitration priority */
- clear_c0_brcm_cmt_ctrl(0x30);
-
- /* NBK and weak order flags */
- set_c0_brcm_config_0(0x30000);
-
- /* Find out if we are running on TP0 or TP1 */
- boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
-
- /*
- * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread
- * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
- * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
- *
- * If booting from TP1, leave the existing CMT interrupt routing
- * such that TP0 responds to SW1 and TP1 responds to SW0.
- */
- if (boot_cpu == 0)
- change_c0_brcm_cmt_intr(0xf8018000,
+ if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
+ /* arbitration priority */
+ clear_c0_brcm_cmt_ctrl(0x30);
+
+ /* NBK and weak order flags */
+ set_c0_brcm_config_0(0x30000);
+
+ /* Find out if we are running on TP0 or TP1 */
+ boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
+
+ /*
+ * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other
+ * thread
+ * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
+ * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
+ *
+ * If booting from TP1, leave the existing CMT interrupt routing
+ * such that TP0 responds to SW1 and TP1 responds to SW0.
+ */
+ if (boot_cpu == 0)
+ change_c0_brcm_cmt_intr(0xf8018000,
(0x02 << 27) | (0x03 << 15));
- else
- change_c0_brcm_cmt_intr(0xf8018000, (0x1d << 27));
-
- /* single core, 2 threads (2 pipelines) */
- max_cpus = 2;
-#elif defined(CONFIG_CPU_BMIPS5000)
- /* enable raceless SW interrupts */
- set_c0_brcm_config(0x03 << 22);
-
- /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
- change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
+ else
+ change_c0_brcm_cmt_intr(0xf8018000, (0x1d << 27));
- /* N cores, 2 threads per core */
- max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
-
- /* clear any pending SW interrupts */
- for (i = 0; i < max_cpus; i++) {
- write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
- write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
+ /* single core, 2 threads (2 pipelines) */
+ max_cpus = 2;
+ } else if (cpu_is_bmips5000()) {
+ /* enable raceless SW interrupts */
+ set_c0_brcm_config(0x03 << 22);
+
+ /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
+ change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
+
+ /* N cores, 2 threads per core */
+ max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
+
+ /* clear any pending SW interrupts */
+ for (i = 0; i < max_cpus; i++) {
+ write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
+ write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
+ }
}
-#endif
if (!bmips_smp_enabled)
max_cpus = 1;
@@ -134,6 +138,15 @@ static void __init bmips_smp_setup(void)
*/
static void bmips_prepare_cpus(unsigned int max_cpus)
{
+ irqreturn_t (*bmips_ipi_interrupt)(int irq, void *dev_id);
+
+ if (cpu_is_bmips4350() || cpu_is_bmips4380())
+ bmips_ipi_interrupt = bmips43xx_ipi_interrupt;
+ else if (cpu_is_bmips5000())
+ bmips_ipi_interrupt = bmips5000_ipi_interrupt;
+ else
+ return;
+
if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
"smp_ipi0", NULL))
panic("Can't request IPI0 interrupt\n");
@@ -168,26 +181,26 @@ static void bmips_boot_secondary(int cpu
pr_info("SMP: Booting CPU%d...\n", cpu);
- if (cpumask_test_cpu(cpu, &bmips_booted_mask))
+ if (cpumask_test_cpu(cpu, &bmips_booted_mask)) {
bmips_send_ipi_single(cpu, 0);
- else {
-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
- /* Reset slave TP1 if booting from TP0 */
- if (cpu_logical_map(cpu) == 0)
- set_c0_brcm_cmt_ctrl(0x01);
-#elif defined(CONFIG_CPU_BMIPS5000)
- if (cpu & 0x01)
- write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
- else {
- /*
- * core N thread 0 was already booted; just
- * pulse the NMI line
- */
- bmips_write_zscm_reg(0x210, 0xc0000000);
- udelay(10);
- bmips_write_zscm_reg(0x210, 0x00);
+ } else {
+ if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
+ /* Reset slave TP1 if booting from TP0 */
+ if (cpu_logical_map(cpu) == 0)
+ set_c0_brcm_cmt_ctrl(0x01);
+ } else if (cpu_is_bmips5000()) {
+ if (cpu & 0x01)
+ write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
+ else {
+ /*
+ * core N thread 0 was already booted; just
+ * pulse the NMI line
+ */
+ bmips_write_zscm_reg(0x210, 0xc0000000);
+ udelay(10);
+ bmips_write_zscm_reg(0x210, 0x00);
+ }
}
-#endif
cpumask_set_cpu(cpu, &bmips_booted_mask);
}
}
@@ -199,20 +212,21 @@ static void bmips_init_secondary(void)
{
/* move NMI vector to kseg0, in case XKS01 is enabled */
-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
- void __iomem *cbr = BMIPS_GET_CBR();
- unsigned long old_vec;
-
- old_vec = __raw_readl(cbr + BMIPS_RELO_VECTOR_CONTROL_1);
- __raw_writel(old_vec & ~0x20000000, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
-
- clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
-#elif defined(CONFIG_CPU_BMIPS5000)
- write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
- (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
+ if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
+ void __iomem *cbr = BMIPS_GET_CBR();
+ unsigned long old_vec;
+
+ old_vec = __raw_readl(cbr + BMIPS_RELO_VECTOR_CONTROL_1);
+ __raw_writel(old_vec & ~0x20000000,
+ cbr + BMIPS_RELO_VECTOR_CONTROL_1);
+
+ clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
+ } else if (cpu_is_bmips5000()) {
+ write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
+ (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
- write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
-#endif
+ write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
+ }
}
/*
@@ -237,8 +251,6 @@ static void bmips_cpus_done(void)
{
}
-#if defined(CONFIG_CPU_BMIPS5000)
-
/*
* BMIPS5000 raceless IPIs
*
@@ -247,12 +259,12 @@ static void bmips_cpus_done(void)
* IPI1 is used for SMP_CALL_FUNCTION
*/
-static void bmips_send_ipi_single(int cpu, unsigned int action)
+static void bmips5000_send_ipi_single(int cpu, unsigned int action)
{
write_c0_brcm_action(ACTION_SET_IPI(cpu, action == SMP_CALL_FUNCTION));
}
-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
+static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id)
{
int action = irq - IPI0_IRQ;
@@ -266,8 +278,6 @@ static irqreturn_t bmips_ipi_interrupt(i
return IRQ_HANDLED;
}
-#else
-
/*
* BMIPS43xx racey IPIs
*
@@ -281,7 +291,7 @@ static irqreturn_t bmips_ipi_interrupt(i
static DEFINE_SPINLOCK(ipi_lock);
static DEFINE_PER_CPU(int, ipi_action_mask);
-static void bmips_send_ipi_single(int cpu, unsigned int action)
+static void bmips43xx_send_ipi_single(int cpu, unsigned int action)
{
unsigned long flags;
@@ -292,7 +302,7 @@ static void bmips_send_ipi_single(int cp
spin_unlock_irqrestore(&ipi_lock, flags);
}
-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
+static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id)
{
unsigned long flags;
int action, cpu = irq - IPI0_IRQ;
@@ -311,7 +321,13 @@ static irqreturn_t bmips_ipi_interrupt(i
return IRQ_HANDLED;
}
-#endif /* BMIPS type */
+static void bmips_send_ipi_single(int cpu, unsigned int action)
+{
+ if (cpu_is_bmips4350() || cpu_is_bmips4380())
+ bmips43xx_send_ipi_single(cpu, action);
+ else if (cpu_is_bmips5000())
+ bmips5000_send_ipi_single(cpu, action);
+}
static void bmips_send_ipi_mask(const struct cpumask *mask,
unsigned int action)
@@ -421,43 +437,44 @@ void __cpuinit bmips_ebase_setup(void)
BUG_ON(ebase != CKSEG0);
-#if defined(CONFIG_CPU_BMIPS4350)
- /*
- * BMIPS4350 cannot relocate the normal vectors, but it
- * can relocate the BEV=1 vectors. So CPU1 starts up at
- * the relocated BEV=1, IV=0 general exception vector @
- * 0xa000_0380.
- *
- * set_uncached_handler() is used here because:
- * - CPU1 will run this from uncached space
- * - None of the cacheflush functions are set up yet
- */
- set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
- &bmips_smp_int_vec, 0x80);
- __sync();
- return;
-#elif defined(CONFIG_CPU_BMIPS4380)
- /*
- * 0x8000_0000: reset/NMI (initially in kseg1)
- * 0x8000_0400: normal vectors
- */
- new_ebase = 0x80000400;
- cbr = BMIPS_GET_CBR();
- __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
- __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
-#elif defined(CONFIG_CPU_BMIPS5000)
- /*
- * 0x8000_0000: reset/NMI (initially in kseg1)
- * 0x8000_1000: normal vectors
- */
- new_ebase = 0x80001000;
- write_c0_brcm_bootvec(0xa0088008);
- write_c0_ebase(new_ebase);
- if (max_cpus > 2)
- bmips_write_zscm_reg(0xa0, 0xa008a008);
-#else
- return;
-#endif
+ if (cpu_is_bmips4350()) {
+ /*
+ * BMIPS4350 cannot relocate the normal vectors, but it
+ * can relocate the BEV=1 vectors. So CPU1 starts up at
+ * the relocated BEV=1, IV=0 general exception vector @
+ * 0xa000_0380.
+ *
+ * set_uncached_handler() is used here because:
+ * - CPU1 will run this from uncached space
+ * - None of the cacheflush functions are set up yet
+ */
+ set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
+ &bmips_smp_int_vec, 0x80);
+ __sync();
+ return;
+ } else if (cpu_is_bmips4380()) {
+ /*
+ * 0x8000_0000: reset/NMI (initially in kseg1)
+ * 0x8000_0400: normal vectors
+ */
+ new_ebase = 0x80000400;
+ cbr = BMIPS_GET_CBR();
+ __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
+ __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
+ } else if (cpu_is_bmips5000()) {
+ /*
+ * 0x8000_0000: reset/NMI (initially in kseg1)
+ * 0x8000_1000: normal vectors
+ */
+ new_ebase = 0x80001000;
+ write_c0_brcm_bootvec(0xa0088008);
+ write_c0_ebase(new_ebase);
+ if (max_cpus > 2)
+ bmips_write_zscm_reg(0xa0, 0xa008a008);
+ } else {
+ return;
+ }
+
board_nmi_handler_setup = &bmips_nmi_handler_setup;
ebase = new_ebase;
}

View file

@ -0,0 +1,126 @@
From 1ecac776e6c652e3059d4f4d9dd8369e89ebef81 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 27 Jun 2013 23:57:20 +0200
Subject: [PATCH 05/10] MIPS: bmips: merge CPU options into one option
Instead of treating each flavour as an exclusive CPU to select, make
BMIPS the only option and let SYS_HAS_CPU_BMIPS* decide for which
flavours to include support.
Run tested on BMIPS3300 and BMIPS4350, only build tested for BMIPS4380
and BMISP5000.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/Kconfig | 77 +++++++++++++++++++++++++----------------------------
1 file changed, 36 insertions(+), 41 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -129,6 +129,7 @@ config BCM63XX
select DMA_NONCOHERENT
select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_CPU_BMIPS
select SYS_HAS_CPU_BMIPS4350 if !BCM63XX_CPU_6338 && !BCM63XX_CPU_6345 && !BCM63XX_CPU_6348
select NR_CPUS_DEFAULT_2
select SYS_SUPPORTS_32BIT_KERNEL
@@ -1447,41 +1448,21 @@ config CPU_CAVIUM_OCTEON
can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets.
Full details can be found at http://www.caviumnetworks.com.
-config CPU_BMIPS3300
- bool "BMIPS3300"
- depends on SYS_HAS_CPU_BMIPS3300
- select CPU_BMIPS
- help
- Broadcom BMIPS3300 processors.
-
-config CPU_BMIPS4350
- bool "BMIPS4350"
- depends on SYS_HAS_CPU_BMIPS4350
- select CPU_BMIPS
- select SYS_SUPPORTS_SMP
- select SYS_SUPPORTS_HOTPLUG_CPU
- help
- Broadcom BMIPS4350 ("VIPER") processors.
-
-config CPU_BMIPS4380
- bool "BMIPS4380"
- depends on SYS_HAS_CPU_BMIPS4380
- select CPU_BMIPS
- select SYS_SUPPORTS_SMP
- select SYS_SUPPORTS_HOTPLUG_CPU
- help
- Broadcom BMIPS4380 processors.
-
-config CPU_BMIPS5000
- bool "BMIPS5000"
- depends on SYS_HAS_CPU_BMIPS5000
- select CPU_BMIPS
- select CPU_SUPPORTS_HIGHMEM
- select MIPS_CPU_SCACHE
- select SYS_SUPPORTS_SMP
- select SYS_SUPPORTS_HOTPLUG_CPU
+config CPU_BMIPS
+ bool "Broadcom BMIPS"
+ depends on SYS_HAS_CPU_BMIPS
+ select CPU_MIPS32
+ select CPU_BMIPS3300 if SYS_HAS_CPU_BMIPS3300
+ select CPU_BMIPS4350 if SYS_HAS_CPU_BMIPS4350
+ select CPU_BMIPS4350 if SYS_HAS_CPU_BMIPS4380
+ select CPU_BMIPS5000 if SYS_HAS_CPU_BMIPS5000
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select SWAP_IO_SPACE
+ select WEAK_ORDERING
help
- Broadcom BMIPS5000 processors.
+ Support for BMIPS3300/4350/4380 and BMIPS5000 processors.
config CPU_XLR
bool "Netlogic XLR SoC"
@@ -1562,14 +1543,25 @@ config CPU_LOONGSON1
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
-config CPU_BMIPS
+config CPU_BMIPS3300
bool
- select CPU_MIPS32
- select CPU_SUPPORTS_32BIT_KERNEL
- select DMA_NONCOHERENT
- select IRQ_CPU
- select SWAP_IO_SPACE
- select WEAK_ORDERING
+
+config CPU_BMIPS4350
+ bool
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_HOTPLUG_CPU
+
+config CPU_BMIPS4380
+ bool
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_HOTPLUG_CPU
+
+config CPU_BMIPS5000
+ bool
+ select CPU_SUPPORTS_HIGHMEM
+ select MIPS_CPU_SCACHE
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_HOTPLUG_CPU
config SYS_HAS_CPU_LOONGSON2E
bool
@@ -1643,6 +1635,9 @@ config SYS_HAS_CPU_SB1
config SYS_HAS_CPU_CAVIUM_OCTEON
bool
+config SYS_HAS_CPU_BMIPS
+ bool
+
config SYS_HAS_CPU_BMIPS3300
bool

View file

@ -0,0 +1,72 @@
From 9d1e9d7abd2f2d067169fb0c62e34cf080bbd7a1 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 23 Jun 2013 12:25:49 +0200
Subject: [PATCH 06/10] MIPS: BCM63XX: let the individual SoCs select the
appropriate CPUs
Let each supported chip select the appropirate SYS_HAS_CPU_BMIPS*
option for its embedded processor, so support will be conditionally
included.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
fix bmips selection
---
arch/mips/Kconfig | 1 -
arch/mips/bcm63xx/Kconfig | 8 ++++++++
2 files changed, 8 insertions(+), 1 deletion(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -130,7 +130,6 @@ config BCM63XX
select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_BMIPS
- select SYS_HAS_CPU_BMIPS4350 if !BCM63XX_CPU_6338 && !BCM63XX_CPU_6345 && !BCM63XX_CPU_6348
select NR_CPUS_DEFAULT_2
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -3,33 +3,41 @@ menu "CPU support"
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_BMIPS3300
select HW_HAS_PCI
config BCM63XX_CPU_6345
bool "support 6345 CPU"
+ select SYS_HAS_CPU_BMIPS3300
config BCM63XX_CPU_6348
bool "support 6348 CPU"
+ select SYS_HAS_CPU_BMIPS3300
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

View file

@ -0,0 +1,42 @@
From aa15ac91faccc3bf01a29670b1f9ae1945cea056 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 23 Jun 2013 14:04:51 +0200
Subject: [PATCH 07/10] MIPS: bmips: add a helper function for registering smp
ops
Add a helper similar to the generic register_XXX_smp_ops() for bmips.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/include/asm/bmips.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/arch/mips/include/asm/bmips.h
+++ b/arch/mips/include/asm/bmips.h
@@ -47,6 +47,7 @@
#include <linux/cpumask.h>
#include <asm/cpu-features.h>
#include <asm/r4kcache.h>
+#include <asm/smp-ops.h>
#define cpu_is_bmips32() (current_cpu_type() == CPU_BMIPS32)
#define cpu_is_bmips3300() (IS_ENABLED(CONFIG_CPU_BMIPS3300) && \
@@ -59,6 +60,18 @@
current_cpu_type() == CPU_BMIPS5000)
extern struct plat_smp_ops bmips_smp_ops;
+
+static inline int register_bmips_smp_ops(void)
+{
+#ifdef CONFIG_CPU_BMIPS
+ register_smp_ops(&bmips_smp_ops);
+
+ return 0;
+#else
+ return -ENODEV;
+#endif
+}
+
extern char bmips_reset_nmi_vec;
extern char bmips_reset_nmi_vec_end;
extern char bmips_smp_movevec;

View file

@ -0,0 +1,26 @@
From c489eace9492d1b8bedb314bdef169e719161bff Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 28 Jun 2013 00:08:16 +0200
Subject: [PATCH 08/10] MIPS: BCM63XX: always register bmips smp ops
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/prom.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -59,10 +59,10 @@ 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);
+ /* set up SMP */
+ register_bmips_smp_ops();
+ if (IS_ENABLED(CONFIG_CPU_BMIPS4350) && IS_ENABLED(CONFIG_SMP)) {
/*
* BCM6328 might not have its second CPU enabled, while BCM6358
* needs special handling for its shared TLB, so disable SMP

View file

@ -0,0 +1,21 @@
From 3a862fd3cc4f477ad2232370abfceca1ec2145ae Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 28 Jun 2013 00:10:07 +0200
Subject: [PATCH 09/10] MIPS: BCM63XX: change the guard to a BMIPS4350 check
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/prom.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -62,7 +62,7 @@ void __init prom_init(void)
/* set up SMP */
register_bmips_smp_ops();
- if (IS_ENABLED(CONFIG_CPU_BMIPS4350) && IS_ENABLED(CONFIG_SMP)) {
+ if (cpu_is_bmips4350()) {
/*
* BCM6328 might not have its second CPU enabled, while BCM6358
* needs special handling for its shared TLB, so disable SMP

View file

@ -0,0 +1,36 @@
From 32d4b03c0aedb96022e86a67a560f6eaf488200a Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 28 Jun 2013 00:25:13 +0200
Subject: [PATCH 10/10] MIPS: BCM63XX: disable SMP also on BCM3368
BCM3368 has the same shared TLB as BCM6358.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/prom.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -64,9 +64,9 @@ void __init prom_init(void)
if (cpu_is_bmips4350()) {
/*
- * BCM6328 might not have its second CPU enabled, while BCM6358
- * needs special handling for its shared TLB, so disable SMP
- * for now.
+ * 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 +
@@ -74,7 +74,7 @@ void __init prom_init(void)
if (reg & OTP_6328_REG3_TP1_DISABLED)
bmips_smp_enabled = 0;
- } else if (BCMCPU_IS_6358()) {
+ } else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
bmips_smp_enabled = 0;
}

View file

@ -0,0 +1,28 @@
From 80a2f983e9f44dbc3e01ae31c62d877846a7f791 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:19 +0100
Subject: [PATCH 01/11] MIPS: BCM63XX: add USB host clock enable delay
Knowledge of the clock setup delay should remain at the clock level (so
it can be clock specific and CPU specific). Add the 100 milliseconds
required clock delay for the USB host clock when it gets enabled.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/clk.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -177,6 +177,11 @@ static void usbh_set(struct clk *clk, in
bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
else if (BCMCPU_IS_6368())
bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
+ else
+ return;
+
+ if (enable)
+ msleep(100);
}
static struct clk clk_usbh = {

View file

@ -0,0 +1,41 @@
From 8e9bf528a122741f0171b89c297b63041116d704 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:20 +0100
Subject: [PATCH 02/11] MIPS: BCM63XX: add USB device clock enable delay to
clock code
This patch adds the required 10 micro seconds delay to the USB device
clock enable operation. Put this where the correct clock knowledege is,
which is in the clock code, and remove this delay from the bcm63xx_udc
gadget driver where it was before.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/clk.c | 5 +++++
drivers/usb/gadget/bcm63xx_udc.c | 1 -
2 files changed, 5 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -199,6 +199,11 @@ static void usbd_set(struct clk *clk, in
bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
else if (BCMCPU_IS_6368())
bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
+ else
+ return;
+
+ if (enable)
+ udelay(10);
}
static struct clk clk_usbd = {
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -386,7 +386,6 @@ static inline void set_clocks(struct bcm
if (is_enabled) {
clk_enable(udc->usbh_clk);
clk_enable(udc->usbd_clk);
- udelay(10);
} else {
clk_disable(udc->usbd_clk);
clk_disable(udc->usbh_clk);

View file

@ -0,0 +1,151 @@
From ac9b0b574d54be28b300bf99ffe092a2c589484f Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:21 +0100
Subject: [PATCH 03/11] MIPS: BCM63XX: move code touching the USB private
register
This patch moves the code touching the USB private register in the
bcm63xx USB gadget driver to arch/mips/bcm63xx/usb-common.c in
preparation for adding support for OHCI and EHCI host controllers which
will also touch the USB private register.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/usb-common.c | 53 ++++++++++++++++++++
.../include/asm/mach-bcm63xx/bcm63xx_usb_priv.h | 9 ++++
drivers/usb/gadget/bcm63xx_udc.c | 27 ++--------
4 files changed, 67 insertions(+), 24 deletions(-)
create mode 100644 arch/mips/bcm63xx/usb-common.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
--- 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-usb-usbd.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/usb-common.c
@@ -0,0 +1,53 @@
+/*
+ * Broadcom BCM63xx common USB device configuration code
+ *
+ * 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 Kevin Cernekee <cernekee@gmail.com>
+ * Copyright (C) 2012 Broadcom Corporation
+ *
+ */
+#include <linux/export.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_usb_priv.h>
+
+void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
+{
+ u32 val;
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
+ if (is_device) {
+ val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
+ val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ } else {
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ }
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ if (is_device)
+ val |= USBH_PRIV_SWAP_USBD_MASK;
+ else
+ val &= ~USBH_PRIV_SWAP_USBD_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+}
+EXPORT_SYMBOL(bcm63xx_usb_priv_select_phy_mode);
+
+void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on)
+{
+ u32 val;
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
+ if (is_on)
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ else
+ val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+}
+EXPORT_SYMBOL(bcm63xx_usb_priv_select_pullup);
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
@@ -0,0 +1,9 @@
+#ifndef BCM63XX_USB_PRIV_H_
+#define BCM63XX_USB_PRIV_H_
+
+#include <linux/types.h>
+
+void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device);
+void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on);
+
+#endif /* BCM63XX_USB_PRIV_H_ */
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -41,6 +41,7 @@
#include <bcm63xx_dev_usb_usbd.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
+#include <bcm63xx_usb_priv.h>
#define DRV_MODULE_NAME "bcm63xx_udc"
@@ -863,22 +864,7 @@ static void bcm63xx_select_phy_mode(stru
bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG);
}
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
- if (is_device) {
- val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
- val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- } else {
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- }
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
-
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
- if (is_device)
- val |= USBH_PRIV_SWAP_USBD_MASK;
- else
- val &= ~USBH_PRIV_SWAP_USBD_MASK;
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+ bcm63xx_usb_priv_select_phy_mode(portmask, is_device);
}
/**
@@ -892,14 +878,9 @@ static void bcm63xx_select_phy_mode(stru
*/
static void bcm63xx_select_pullup(struct bcm63xx_udc *udc, bool is_on)
{
- u32 val, portmask = BIT(udc->pd->port_no);
+ u32 portmask = BIT(udc->pd->port_no);
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
- if (is_on)
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- else
- val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+ bcm63xx_usb_priv_select_pullup(portmask, is_on);
}
/**

View file

@ -0,0 +1,169 @@
From 28758a9da77954ed323f86123ef448c6a563c037 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:22 +0100
Subject: [PATCH 04/11] MIPS: BCM63XX: add OHCI/EHCI configuration bits to
common USB code
This patch updates the common USB code touching the USB private
registers with the specific bits to properly enable OHCI and EHCI
controllers on BCM63xx SoCs. As a result we now need to protect access
to Read Modify Write sequences using a spinlock because we cannot
guarantee that any of the exposed helper will not be called
concurrently.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/usb-common.c | 97 ++++++++++++++++++++
.../include/asm/mach-bcm63xx/bcm63xx_usb_priv.h | 2 +
2 files changed, 99 insertions(+)
--- a/arch/mips/bcm63xx/usb-common.c
+++ b/arch/mips/bcm63xx/usb-common.c
@@ -5,10 +5,12 @@
* 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) 2012 Kevin Cernekee <cernekee@gmail.com>
* Copyright (C) 2012 Broadcom Corporation
*
*/
+#include <linux/spinlock.h>
#include <linux/export.h>
#include <bcm63xx_cpu.h>
@@ -16,9 +18,14 @@
#include <bcm63xx_io.h>
#include <bcm63xx_usb_priv.h>
+static DEFINE_SPINLOCK(usb_priv_reg_lock);
+
void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
{
u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
if (is_device) {
@@ -36,12 +43,17 @@ void bcm63xx_usb_priv_select_phy_mode(u3
else
val &= ~USBH_PRIV_SWAP_USBD_MASK;
bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
}
EXPORT_SYMBOL(bcm63xx_usb_priv_select_phy_mode);
void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on)
{
u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
if (is_on)
@@ -49,5 +61,90 @@ void bcm63xx_usb_priv_select_pullup(u32
else
val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
}
EXPORT_SYMBOL(bcm63xx_usb_priv_select_pullup);
+
+/* The following array represents the meaning of the DESC/DATA
+ * endian swapping with respect to the CPU configured endianness
+ *
+ * DATA ENDN mmio descriptor
+ * 0 0 BE invalid
+ * 0 1 BE LE
+ * 1 0 BE BE
+ * 1 1 BE invalid
+ *
+ * Since BCM63XX SoCs are configured to be in big-endian mode
+ * we want configuration at line 3.
+ */
+void bcm63xx_usb_priv_ohci_cfg_set(void)
+{
+ u32 reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
+
+ if (BCMCPU_IS_6348())
+ bcm_rset_writel(RSET_OHCI_PRIV, 0, OHCI_PRIV_REG);
+ else if (BCMCPU_IS_6358()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
+ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
+ /*
+ * The magic value comes for the original vendor BSP
+ * and is needed for USB to work. Datasheet does not
+ * help, so the magic value is used as-is.
+ */
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
+ USBH_PRIV_TEST_6358_REG);
+
+ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
+ reg |= USBH_PRIV_SETUP_IOC_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
+ }
+
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
+}
+
+void bcm63xx_usb_priv_ehci_cfg_set(void)
+{
+ u32 reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
+
+ if (BCMCPU_IS_6358()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
+ reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
+
+ /*
+ * The magic value comes for the original vendor BSP
+ * and is needed for USB to work. Datasheet does not
+ * help, so the magic value is used as-is.
+ */
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
+ USBH_PRIV_TEST_6358_REG);
+
+ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
+ reg |= USBH_PRIV_SETUP_IOC_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
+ }
+
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
+}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
@@ -5,5 +5,7 @@
void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device);
void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on);
+void bcm63xx_usb_priv_ohci_cfg_set(void);
+void bcm63xx_usb_priv_ehci_cfg_set(void);
#endif /* BCM63XX_USB_PRIV_H_ */

View file

@ -0,0 +1,62 @@
From 94ec618bd1a6b07fafbbfc9bcc54e7f9360ff9a0 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:23 +0100
Subject: [PATCH 05/11] MIPS: BCM63XX: introduce BCM63XX_OHCI configuration
symbol
This configuration symbol can be used by CPUs supporting the on-chip
OHCI controller, and ensures that all relevant OHCI-related
configuration options are correctly selected. So far, OHCI support is
available for the 6328, 6348, 6358 and 6358 SoCs.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Kconfig | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -6,10 +6,17 @@ config BCM63XX_CPU_3368
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
+config BCM63XX_OHCI
+ bool
+ select USB_ARCH_HAS_OHCI
+ select USB_OHCI_BIG_ENDIAN_DESC if USB_OHCI_HCD
+ select USB_OHCI_BIG_ENDIAN_MMIO if USB_OHCI_HCD
+
config BCM63XX_CPU_6328
bool "support 6328 CPU"
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
+ select BCM63XX_OHCI
config BCM63XX_CPU_6338
bool "support 6338 CPU"
@@ -24,21 +31,25 @@ config BCM63XX_CPU_6348
bool "support 6348 CPU"
select SYS_HAS_CPU_BMIPS3300
select HW_HAS_PCI
+ select BCM63XX_OHCI
config BCM63XX_CPU_6358
bool "support 6358 CPU"
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
+ select BCM63XX_OHCI
config BCM63XX_CPU_6362
bool "support 6362 CPU"
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
+ select BCM63XX_OHCI
config BCM63XX_CPU_6368
bool "support 6368 CPU"
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
+ select BCM63XX_OHCI
endmenu
source "arch/mips/bcm63xx/boards/Kconfig"

View file

@ -0,0 +1,138 @@
From 30d22baef255c99a12c4858ce4ab0d45f0d8c9ae Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:24 +0100
Subject: [PATCH 06/11] MIPS: BCM63XX: add support for the on-chip OHCI
controller
Broadcom BCM63XX SoCs include an on-chip OHCI controller which can be
driven by the ohci-platform generic driver by using specific power
on/off/suspend callback to manage clocks and hardware specific
configuration.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/dev-usb-ohci.c | 94 ++++++++++++++++++++
.../asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h | 6 ++
3 files changed, 101 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/bcm63xx/dev-usb-ohci.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
--- 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 usb-common.o
+ dev-usb-ohci.o dev-usb-usbd.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/dev-usb-ohci.c
@@ -0,0 +1,94 @@
+/*
+ * 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) 2013 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_usb_priv.h>
+#include <bcm63xx_dev_usb_ohci.h>
+
+static struct resource ohci_resources[] = {
+ {
+ .start = -1, /* filled at runtime */
+ .end = -1, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = -1, /* filled at runtime */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 ohci_dmamask = DMA_BIT_MASK(32);
+
+static struct clk *usb_host_clock;
+
+static int bcm63xx_ohci_power_on(struct platform_device *pdev)
+{
+ usb_host_clock = clk_get(&pdev->dev, "usbh");
+ if (IS_ERR_OR_NULL(usb_host_clock))
+ return -ENODEV;
+
+ clk_prepare_enable(usb_host_clock);
+
+ bcm63xx_usb_priv_ohci_cfg_set();
+
+ return 0;
+}
+
+static void bcm63xx_ohci_power_off(struct platform_device *pdev)
+{
+ if (!IS_ERR_OR_NULL(usb_host_clock)) {
+ clk_disable_unprepare(usb_host_clock);
+ clk_put(usb_host_clock);
+ }
+}
+
+static struct usb_ohci_pdata bcm63xx_ohci_pdata = {
+ .big_endian_desc = 1,
+ .big_endian_mmio = 1,
+ .no_big_frame_no = 1,
+ .num_ports = 1,
+ .power_on = bcm63xx_ohci_power_on,
+ .power_off = bcm63xx_ohci_power_off,
+ .power_suspend = bcm63xx_ohci_power_off,
+};
+
+static struct platform_device bcm63xx_ohci_device = {
+ .name = "ohci-platform",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ohci_resources),
+ .resource = ohci_resources,
+ .dev = {
+ .platform_data = &bcm63xx_ohci_pdata,
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+int __init bcm63xx_ohci_register(void)
+{
+ if (BCMCPU_IS_6345() || BCMCPU_IS_6338())
+ return -ENODEV;
+
+ ohci_resources[0].start = bcm63xx_regset_address(RSET_OHCI0);
+ ohci_resources[0].end = ohci_resources[0].start;
+ ohci_resources[0].end += RSET_OHCI_SIZE - 1;
+ ohci_resources[1].start = bcm63xx_get_irq_number(IRQ_OHCI0);
+
+ return platform_device_register(&bcm63xx_ohci_device);
+}
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
@@ -0,0 +1,6 @@
+#ifndef BCM63XX_DEV_USB_OHCI_H_
+#define BCM63XX_DEV_USB_OHCI_H_
+
+int bcm63xx_ohci_register(void);
+
+#endif /* BCM63XX_DEV_USB_OHCI_H_ */

View file

@ -0,0 +1,36 @@
From 33ef960aed15f9a98a2c51d8d794cd72418e0be4 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:25 +0100
Subject: [PATCH 07/11] MIPS: BCM63XX: register OHCI controller if board
enables it
BCM63XX-based boards can control the registration of the OHCI controller
by setting their has_ohci0 flag to 1. Handle this in the generic
code dealing with board registration and call the actual helper to
register the OHCI controller.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -25,6 +25,7 @@
#include <bcm63xx_dev_flash.h>
#include <bcm63xx_dev_pcmcia.h>
#include <bcm63xx_dev_spi.h>
+#include <bcm63xx_dev_usb_ohci.h>
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
@@ -897,6 +898,9 @@ int __init board_register_devices(void)
if (board.has_usbd)
bcm63xx_usbd_register(&board.usbd);
+ if (board.has_ohci0)
+ bcm63xx_ohci_register();
+
if (board.has_dsp)
bcm63xx_dsp_register(&board.dsp);

View file

@ -0,0 +1,62 @@
From 00da1683364e58c6430a4577123d01037f8faddc Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:26 +0100
Subject: [PATCH 08/11] MIPS: BCM63XX: introduce BCM63XX_EHCI configuration
symbol
This configuration symbol can be used by CPUs supporting the on-chip
EHCI controller, and ensures that all relevant EHCI-related
configuration options are selected. So far BCM6328, BCM6358 and BCM6368
have an EHCI controller and do select this symbol. Update
drivers/usb/host/Kconfig with BCM63XX to update direct unmet
dependencies.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Kconfig | 9 +++++++++
drivers/usb/host/Kconfig | 5 +++--
2 files changed, 12 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -12,11 +12,18 @@ config BCM63XX_OHCI
select USB_OHCI_BIG_ENDIAN_DESC if USB_OHCI_HCD
select USB_OHCI_BIG_ENDIAN_MMIO if USB_OHCI_HCD
+config BCM63XX_EHCI
+ bool
+ select USB_ARCH_HAS_EHCI
+ select USB_EHCI_BIG_ENDIAN_DESC if USB_EHCI_HCD
+ select USB_EHCI_BIG_ENDIAN_MMIO if USB_EHCI_HCD
+
config BCM63XX_CPU_6328
bool "support 6328 CPU"
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
select BCM63XX_OHCI
+ select BCM63XX_EHCI
config BCM63XX_CPU_6338
bool "support 6338 CPU"
@@ -38,18 +45,21 @@ config BCM63XX_CPU_6358
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
select BCM63XX_OHCI
+ select BCM63XX_EHCI
config BCM63XX_CPU_6362
bool "support 6362 CPU"
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
select BCM63XX_OHCI
+ select BCM63XX_EHCI
config BCM63XX_CPU_6368
bool "support 6368 CPU"
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
select BCM63XX_OHCI
+ select BCM63XX_EHCI
endmenu
source "arch/mips/bcm63xx/boards/Kconfig"

View file

@ -0,0 +1,136 @@
From e38f13bd6408769c0b565bb1079024f496eee121 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:27 +0100
Subject: [PATCH 09/11] MIPS: BCM63XX: add support for the on-chip EHCI
controller
Broadcom BCM63XX SoCs include an on-chip EHCI controller which can be
driven by the generic ehci-platform driver by using specific power
on/off/suspend callbacks to manage clocks and hardware specific
configuration.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/dev-usb-ehci.c | 92 ++++++++++++++++++++
.../asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h | 6 ++
3 files changed, 99 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/bcm63xx/dev-usb-ehci.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
--- 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-ohci.o dev-usb-usbd.o usb-common.o
+ dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
@@ -0,0 +1,92 @@
+/*
+ * 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) 2013 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/dma-mapping.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_usb_priv.h>
+#include <bcm63xx_dev_usb_ehci.h>
+
+static struct resource ehci_resources[] = {
+ {
+ .start = -1, /* filled at runtime */
+ .end = -1, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = -1, /* filled at runtime */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
+
+static struct clk *usb_host_clock;
+
+static int bcm63xx_ehci_power_on(struct platform_device *pdev)
+{
+ usb_host_clock = clk_get(&pdev->dev, "usbh");
+ if (IS_ERR_OR_NULL(usb_host_clock))
+ return -ENODEV;
+
+ clk_prepare_enable(usb_host_clock);
+
+ bcm63xx_usb_priv_ehci_cfg_set();
+
+ return 0;
+}
+
+static void bcm63xx_ehci_power_off(struct platform_device *pdev)
+{
+ if (!IS_ERR_OR_NULL(usb_host_clock)) {
+ clk_disable_unprepare(usb_host_clock);
+ clk_put(usb_host_clock);
+ }
+}
+
+static struct usb_ehci_pdata bcm63xx_ehci_pdata = {
+ .big_endian_desc = 1,
+ .big_endian_mmio = 1,
+ .power_on = bcm63xx_ehci_power_on,
+ .power_off = bcm63xx_ehci_power_off,
+ .power_suspend = bcm63xx_ehci_power_off,
+};
+
+static struct platform_device bcm63xx_ehci_device = {
+ .name = "ehci-platform",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ehci_resources),
+ .resource = ehci_resources,
+ .dev = {
+ .platform_data = &bcm63xx_ehci_pdata,
+ .dma_mask = &ehci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+int __init bcm63xx_ehci_register(void)
+{
+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6358() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
+ return 0;
+
+ ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
+ ehci_resources[0].end = ehci_resources[0].start;
+ ehci_resources[0].end += RSET_EHCI_SIZE - 1;
+ ehci_resources[1].start = bcm63xx_get_irq_number(IRQ_EHCI0);
+
+ return platform_device_register(&bcm63xx_ehci_device);
+}
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
@@ -0,0 +1,6 @@
+#ifndef BCM63XX_DEV_USB_EHCI_H_
+#define BCM63XX_DEV_USB_EHCI_H_
+
+int bcm63xx_ehci_register(void);
+
+#endif /* BCM63XX_DEV_USB_EHCI_H_ */

View file

@ -0,0 +1,36 @@
From 709ef2034f5ba06da35f89856ad7baf2b7a41287 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:28 +0100
Subject: [PATCH 10/11] MIPS: BCM63XX: register EHCI controller if board
enables it
BCM63XX-based board can control the registration of the EHCI controller
by setting their has_ehci0 flag to 1. Handle this in the generic
code dealing with board registration and call the actual helper to register
the EHCI controller.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -25,6 +25,7 @@
#include <bcm63xx_dev_flash.h>
#include <bcm63xx_dev_pcmcia.h>
#include <bcm63xx_dev_spi.h>
+#include <bcm63xx_dev_usb_ehci.h>
#include <bcm63xx_dev_usb_ohci.h>
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
@@ -898,6 +899,9 @@ int __init board_register_devices(void)
if (board.has_usbd)
bcm63xx_usbd_register(&board.usbd);
+ if (board.has_ehci0)
+ bcm63xx_ehci_register();
+
if (board.has_ohci0)
bcm63xx_ohci_register();

View file

@ -0,0 +1,24 @@
From 111bbd770441ab34f9da5bb1d85767a9b75227b4 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:30 +0100
Subject: [PATCH 12/12] MIPS: BCM63XX: EHCI controller does not support
overcurrent
This patch sets the ignore_oc flag for the BCM63XX EHCI controller as it
does not support proper overcurrent reporting.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/dev-usb-ehci.c | 1 +
1 file changed, 1 insertion(+)
--- a/arch/mips/bcm63xx/dev-usb-ehci.c
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
@@ -61,6 +61,7 @@ static void bcm63xx_ehci_power_off(struc
static struct usb_ehci_pdata bcm63xx_ehci_pdata = {
.big_endian_desc = 1,
.big_endian_mmio = 1,
+ .ignore_oc = 1,
.power_on = bcm63xx_ehci_power_on,
.power_off = bcm63xx_ehci_power_off,
.power_suspend = bcm63xx_ehci_power_off,

View file

@ -0,0 +1,38 @@
From 3f650fc30aa0badf9d02842ce396cea3eef2eeaa Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 1 Jul 2011 23:16:47 +0200
Subject: [PATCH 49/79] SPI: Allow specifying the parsers for SPI flash
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
include/linux/spi/flash.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/include/linux/spi/flash.h
+++ b/include/linux/spi/flash.h
@@ -2,7 +2,7 @@
#define LINUX_SPI_FLASH_H
struct mtd_partition;
-
+struct mtd_part_parser_data;
/**
* struct flash_platform_data: board-specific flash data
* @name: optional flash device name (eg, as used with mtdparts=)
@@ -10,6 +10,8 @@ struct mtd_partition;
* @nr_parts: number of mtd_partitions for static partitoning
* @type: optional flash device type (e.g. m25p80 vs m25p64), for use
* with chips that can't be queried for JEDEC or other IDs
+ * @part_probe_types: optional list of MTD parser names to use for
+ * partitioning
*
* Board init code (in arch/.../mach-xxx/board-yyy.c files) can
* provide information about SPI flash parts (such as DataFlash) to
@@ -25,6 +27,7 @@ struct flash_platform_data {
char *type;
+ const char **part_probe_types;
/* we'll likely add more ... use JEDEC IDs, etc */
};

View file

@ -0,0 +1,23 @@
From c7c3c338cb25d7f55ddb3f6bfbf3572758ca3896 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Thu, 10 Nov 2011 16:53:08 +0100
Subject: [PATCH 50/79] MTD: DEVICES: m25p80: use parsers if provided in flash
platform data
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/mtd/devices/m25p80.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -1092,7 +1092,8 @@ static int m25p_probe(struct spi_device
/* partitions should match sector boundaries; and it may be good to
* use readonly partitions for writeprotected sectors (BP2..BP0).
*/
- return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
+ return mtd_device_parse_register(&flash->mtd,
+ data ? data->part_probe_types : NULL, &ppdata,
data ? data->parts : NULL,
data ? data->nr_parts : 0);
}

View file

@ -0,0 +1,92 @@
From 5fb4e8d7287ac8fcb33aae8b1e9e22c5a3c392bd Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Thu, 10 Nov 2011 17:33:40 +0100
Subject: [PATCH 51/79] MTD: DEVICES: m25p80: add support for limiting reads
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/mtd/devices/m25p80.c | 29 +++++++++++++++++++++++++++--
include/linux/spi/flash.h | 4 ++++
2 files changed, 31 insertions(+), 2 deletions(-)
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -93,6 +93,7 @@ struct m25p {
u8 erase_opcode;
u8 *command;
bool fast_read;
+ int max_transfer_len;
};
static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -337,10 +338,9 @@ static int m25p80_erase(struct mtd_info
* Read an address range from the flash chip. The address range
* may be any size provided it is within the physical boundaries.
*/
-static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+static int __m25p80_read(struct m25p *flash, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
- struct m25p *flash = mtd_to_m25p(mtd);
struct spi_transfer t[2];
struct spi_message m;
uint8_t opcode;
@@ -392,6 +392,28 @@ static int m25p80_read(struct mtd_info *
return 0;
}
+static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ size_t off;
+ size_t read_len = flash->max_transfer_len;
+ size_t part_len;
+ int ret = 0;
+
+ if (!read_len)
+ return __m25p80_read(flash, from, len, retlen, buf);
+
+ *retlen = 0;
+
+ for (off = 0; off < len && !ret; off += read_len) {
+ ret = __m25p80_read(flash, from + off, min(len - off, read_len),
+ &part_len, buf + off);
+ *retlen += part_len;
+ }
+
+ return ret;
+}
/*
* Write an address range to the flash chip. Data must be written in
* FLASH_PAGESIZE chunks. The address range may be any size provided
@@ -987,6 +1009,9 @@ static int m25p_probe(struct spi_device
return -ENOMEM;
}
+ if (data)
+ flash->max_transfer_len = data->max_transfer_len;
+
flash->spi = spi;
mutex_init(&flash->lock);
dev_set_drvdata(&spi->dev, flash);
--- a/include/linux/spi/flash.h
+++ b/include/linux/spi/flash.h
@@ -13,6 +13,8 @@ struct mtd_part_parser_data;
* @part_probe_types: optional list of MTD parser names to use for
* partitioning
*
+ * @max_transfer_len: option maximum read/write length limitation for
+ * SPI controllers not able to transfer any length commands.
* Board init code (in arch/.../mach-xxx/board-yyy.c files) can
* provide information about SPI flash parts (such as DataFlash) to
* help set up the device and its appropriate default partitioning.
@@ -28,6 +30,8 @@ struct flash_platform_data {
char *type;
const char **part_probe_types;
+
+ unsigned int max_transfer_len;
/* we'll likely add more ... use JEDEC IDs, etc */
};

View file

@ -0,0 +1,116 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -12,6 +12,8 @@
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/ssb/ssb.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
@@ -36,6 +38,9 @@
#define HCS_OFFSET_128K 0x20000
+#define BCM963XX_KEYS_POLL_INTERVAL 20
+#define BCM963XX_KEYS_DEBOUNCE_INTERVAL (BCM963XX_KEYS_POLL_INTERVAL * 3)
+
static struct board_info board;
/*
@@ -379,6 +384,16 @@ static struct board_info __initdata boar
.active_low = 1,
},
},
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 33,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
};
static struct board_info __initdata board_96348gw = {
@@ -437,6 +452,16 @@ static struct board_info __initdata boar
.active_low = 1,
},
},
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 36,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
};
static struct board_info __initdata board_FAST2404 = {
@@ -870,11 +895,23 @@ static struct platform_device bcm63xx_gp
.dev.platform_data = &bcm63xx_led_data,
};
+static struct gpio_keys_platform_data bcm63xx_gpio_keys_data = {
+ .poll_interval = BCM963XX_KEYS_POLL_INTERVAL,
+};
+
+static struct platform_device bcm63xx_gpio_keys_device = {
+ .name = "gpio-keys-polled",
+ .id = 0,
+ .dev.platform_data = &bcm63xx_gpio_keys_data,
+};
+
/*
* third stage init callback, register all board devices.
*/
int __init board_register_devices(void)
{
+ int button_count = 0;
+
if (board.has_uart0)
bcm63xx_uart_register(0);
@@ -934,5 +971,16 @@ int __init board_register_devices(void)
gpio_request_one(board.ephy_reset_gpio,
board.ephy_reset_gpio_flags, "ephy-reset");
+ /* count number of BUTTONs defined by this device */
+ while (button_count < ARRAY_SIZE(board.buttons) && board.buttons[button_count].desc)
+ button_count++;
+
+ if (button_count) {
+ bcm63xx_gpio_keys_data.nbuttons = button_count;
+ bcm63xx_gpio_keys_data.buttons = board.buttons;
+
+ platform_device_register(&bcm63xx_gpio_keys_device);
+ }
+
return 0;
}
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
#include <linux/leds.h>
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_usb_usbd.h>
@@ -48,6 +49,9 @@ struct board_info {
/* GPIO LEDs */
struct gpio_led leds[5];
+ /* Buttons */
+ struct gpio_keys_button buttons[4];
+
/* External PHY reset GPIO */
unsigned int ephy_reset_gpio;

View file

@ -0,0 +1,41 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -911,6 +911,7 @@ static struct platform_device bcm63xx_gp
int __init board_register_devices(void)
{
int button_count = 0;
+ int led_count = 0;
if (board.has_uart0)
bcm63xx_uart_register(0);
@@ -962,10 +963,16 @@ int __init board_register_devices(void)
bcm63xx_flash_register();
- bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
- bcm63xx_led_data.leds = board.leds;
+ /* count number of LEDs defined by this device */
+ while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
+ led_count++;
+
+ if (led_count) {
+ bcm63xx_led_data.num_leds = led_count;
+ bcm63xx_led_data.leds = board.leds;
- platform_device_register(&bcm63xx_gpio_leds);
+ platform_device_register(&bcm63xx_gpio_leds);
+ }
if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
gpio_request_one(board.ephy_reset_gpio,
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -47,7 +47,7 @@ struct board_info {
struct bcm63xx_dsp_platform_data dsp;
/* GPIO LEDs */
- struct gpio_led leds[5];
+ struct gpio_led leds[14];
/* Buttons */
struct gpio_keys_button buttons[4];

View file

@ -0,0 +1,25 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -961,6 +961,9 @@ int __init board_register_devices(void)
bcm63xx_spi_register();
+ if (board.num_devs)
+ platform_add_devices(board.devs, board.num_devs);
+
bcm63xx_flash_register();
/* count number of LEDs defined by this device */
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -57,6 +57,10 @@ struct board_info {
/* External PHY reset GPIO flags from gpio.h */
unsigned long ephy_reset_gpio_flags;
+
+ /* Additional platform devices */
+ struct platform_device **devs;
+ unsigned int num_devs;
};
#endif /* ! BOARD_BCM963XX_H_ */

View file

@ -0,0 +1,33 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -14,6 +14,7 @@
#include <linux/ssb/ssb.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
+#include <linux/spi/spi.h>
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
@@ -964,6 +965,9 @@ int __init board_register_devices(void)
if (board.num_devs)
platform_add_devices(board.devs, board.num_devs);
+ if (board.num_spis)
+ spi_register_board_info(board.spis, board.num_spis);
+
bcm63xx_flash_register();
/* count number of LEDs defined by this device */
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -61,6 +61,10 @@ struct board_info {
/* Additional platform devices */
struct platform_device **devs;
unsigned int num_devs;
+
+ /* Additional platform devices */
+ struct spi_board_info *spis;
+ unsigned int num_spis;
};
#endif /* ! BOARD_BCM963XX_H_ */

View file

@ -0,0 +1,62 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -34,6 +34,7 @@
#include <board_bcm963xx.h>
#include <uapi/linux/bcm933xx_hcs.h>
+#include <uapi/linux/bcm963xx_tag.h>
#define PFX "board_bcm963xx: "
@@ -42,6 +43,9 @@
#define BCM963XX_KEYS_POLL_INTERVAL 20
#define BCM963XX_KEYS_DEBOUNCE_INTERVAL (BCM963XX_KEYS_POLL_INTERVAL * 3)
+#define CFE_OFFSET_64K 0x10000
+#define CFE_OFFSET_128K 0x20000
+
static struct board_info board;
/*
@@ -781,6 +785,30 @@ const char *board_get_name(void)
return board.name;
}
+static void __init boardid_fixup(u8 *boot_addr)
+{
+ struct bcm_tag *tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_64K);
+ char *board_name = (char *)bcm63xx_nvram_get_name();
+
+ /* check if bcm_tag is at 64k offset */
+ if (strncmp(board_name, tag->board_id, BOARDID_LEN) != 0) {
+ /* else try 128k */
+ tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_128K);
+ if (strncmp(board_name, tag->board_id, BOARDID_LEN) != 0) {
+ /* No tag found */
+ printk(KERN_DEBUG "No bcm_tag found!\n");
+ return;
+ }
+ }
+ /* check if we should override the boardid */
+ if (tag->information1[0] != '+')
+ return;
+
+ strncpy(board_name, &tag->information1[1], BOARDID_LEN);
+
+ printk(KERN_INFO "Overriding boardid with '%s'\n", board_name);
+}
+
/*
* early init callback, read nvram data from flash and checksum it
*/
@@ -819,6 +847,10 @@ void __init board_prom_init(void)
hcs = (struct bcm_hcs *)boot_addr;
board_name = hcs->filename;
} else {
+ if (strcmp(cfe_version, "unknown") != 0) {
+ /* cfe present */
+ boardid_fixup(boot_addr);
+ }
board_name = bcm63xx_nvram_get_name();
}
/* find board by name */

View file

@ -0,0 +1,48 @@
From 5aeb6273a610f8aab090b3499827177eb41311ba Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sat, 12 Nov 2011 12:19:09 +0100
Subject: [PATCH 53/79] MIPS: BCM63XX: expose the HS SPI clock
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
arch/mips/bcm63xx/clk.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -236,6 +236,26 @@ static struct clk clk_spi = {
};
/*
+ * SPI clock
+ */
+static void hsspi_set(struct clk *clk, int enable)
+{
+ u32 mask;
+
+ if (BCMCPU_IS_6328())
+ mask = CKCTL_6328_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)
@@ -344,6 +364,8 @@ struct clk *clk_get(struct device *dev,
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"))

View file

@ -0,0 +1,211 @@
From 70f970222bc1096689ae1bffeb9ed09a7c4bed07 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sat, 12 Nov 2011 12:19:55 +0100
Subject: [PATCH 28/60] MIPS: BCM63XX: add HSSPI register definitions
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 18 ++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 47 +++++++++++++++++++++
2 files changed, 65 insertions(+), 0 deletions(-)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -145,6 +145,7 @@ enum bcm63xx_regs_set {
RSET_UART1,
RSET_GPIO,
RSET_SPI,
+ RSET_HSSPI,
RSET_UDC0,
RSET_OHCI0,
RSET_OHCI_PRIV,
@@ -193,6 +194,7 @@ enum bcm63xx_regs_set {
#define RSET_ENETDMAS_SIZE(chans) (16 * (chans))
#define RSET_ENETSW_SIZE 65536
#define RSET_UART_SIZE 24
+#define RSET_HSSPI_SIZE 1536
#define RSET_UDC_SIZE 256
#define RSET_OHCI_SIZE 256
#define RSET_EHCI_SIZE 256
@@ -265,6 +267,7 @@ enum bcm63xx_regs_set {
#define BCM_6328_UART1_BASE (0xb0000120)
#define BCM_6328_GPIO_BASE (0xb0000080)
#define BCM_6328_SPI_BASE (0xdeadbeef)
+#define BCM_6328_HSSPI_BASE (0xb0001000)
#define BCM_6328_UDC0_BASE (0xdeadbeef)
#define BCM_6328_USBDMA_BASE (0xb000c000)
#define BCM_6328_OHCI0_BASE (0xb0002600)
@@ -313,6 +316,7 @@ enum bcm63xx_regs_set {
#define BCM_6338_UART1_BASE (0xdeadbeef)
#define BCM_6338_GPIO_BASE (0xfffe0400)
#define BCM_6338_SPI_BASE (0xfffe0c00)
+#define BCM_6338_HSSPI_BASE (0xdeadbeef)
#define BCM_6338_UDC0_BASE (0xdeadbeef)
#define BCM_6338_USBDMA_BASE (0xfffe2400)
#define BCM_6338_OHCI0_BASE (0xdeadbeef)
@@ -360,6 +364,7 @@ enum bcm63xx_regs_set {
#define BCM_6345_UART1_BASE (0xdeadbeef)
#define BCM_6345_GPIO_BASE (0xfffe0400)
#define BCM_6345_SPI_BASE (0xdeadbeef)
+#define BCM_6345_HSSPI_BASE (0xdeadbeef)
#define BCM_6345_UDC0_BASE (0xdeadbeef)
#define BCM_6345_USBDMA_BASE (0xfffe2800)
#define BCM_6345_ENET0_BASE (0xfffe1800)
@@ -406,6 +411,7 @@ enum bcm63xx_regs_set {
#define BCM_6348_UART1_BASE (0xdeadbeef)
#define BCM_6348_GPIO_BASE (0xfffe0400)
#define BCM_6348_SPI_BASE (0xfffe0c00)
+#define BCM_6348_HSSPI_BASE (0xdeadbeef)
#define BCM_6348_UDC0_BASE (0xfffe1000)
#define BCM_6348_USBDMA_BASE (0xdeadbeef)
#define BCM_6348_OHCI0_BASE (0xfffe1b00)
@@ -451,6 +457,7 @@ enum bcm63xx_regs_set {
#define BCM_6358_UART1_BASE (0xfffe0120)
#define BCM_6358_GPIO_BASE (0xfffe0080)
#define BCM_6358_SPI_BASE (0xfffe0800)
+#define BCM_6358_HSSPI_BASE (0xdeadbeef)
#define BCM_6358_UDC0_BASE (0xfffe0800)
#define BCM_6358_USBDMA_BASE (0xdeadbeef)
#define BCM_6358_OHCI0_BASE (0xfffe1400)
@@ -553,6 +560,7 @@ enum bcm63xx_regs_set {
#define BCM_6368_UART1_BASE (0xb0000120)
#define BCM_6368_GPIO_BASE (0xb0000080)
#define BCM_6368_SPI_BASE (0xb0000800)
+#define BCM_6368_HSSPI_BASE (0xdeadbeef)
#define BCM_6368_UDC0_BASE (0xdeadbeef)
#define BCM_6368_USBDMA_BASE (0xb0004800)
#define BCM_6368_OHCI0_BASE (0xb0001600)
@@ -604,6 +612,7 @@ extern const unsigned long *bcm63xx_regs
__GEN_RSET_BASE(__cpu, UART1) \
__GEN_RSET_BASE(__cpu, GPIO) \
__GEN_RSET_BASE(__cpu, SPI) \
+ __GEN_RSET_BASE(__cpu, HSSPI) \
__GEN_RSET_BASE(__cpu, UDC0) \
__GEN_RSET_BASE(__cpu, OHCI0) \
__GEN_RSET_BASE(__cpu, OHCI_PRIV) \
@@ -647,6 +656,7 @@ extern const unsigned long *bcm63xx_regs
[RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \
[RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \
[RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \
+ [RSET_HSSPI] = BCM_## __cpu ##_HSSPI_BASE, \
[RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \
[RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \
[RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \
@@ -727,6 +737,7 @@ enum bcm63xx_irq {
IRQ_ENET0,
IRQ_ENET1,
IRQ_ENET_PHY,
+ IRQ_HSSPI,
IRQ_OHCI0,
IRQ_EHCI0,
IRQ_USBD,
@@ -815,6 +826,7 @@ enum bcm63xx_irq {
#define BCM_6328_ENET0_IRQ 0
#define BCM_6328_ENET1_IRQ 0
#define BCM_6328_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
+#define BCM_6328_HSSPI_IRQ (IRQ_INTERNAL_BASE + 29)
#define BCM_6328_OHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 9)
#define BCM_6328_EHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 10)
#define BCM_6328_USBD_IRQ (IRQ_INTERNAL_BASE + 4)
@@ -860,6 +872,7 @@ enum bcm63xx_irq {
#define BCM_6338_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
#define BCM_6338_ENET1_IRQ 0
#define BCM_6338_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_6338_HSSPI_IRQ 0
#define BCM_6338_OHCI0_IRQ 0
#define BCM_6338_EHCI0_IRQ 0
#define BCM_6338_USBD_IRQ 0
@@ -898,6 +911,7 @@ enum bcm63xx_irq {
#define BCM_6345_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
#define BCM_6345_ENET1_IRQ 0
#define BCM_6345_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
+#define BCM_6345_HSSPI_IRQ 0
#define BCM_6345_OHCI0_IRQ 0
#define BCM_6345_EHCI0_IRQ 0
#define BCM_6345_USBD_IRQ 0
@@ -936,6 +950,7 @@ enum bcm63xx_irq {
#define BCM_6348_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
#define BCM_6348_ENET1_IRQ (IRQ_INTERNAL_BASE + 7)
#define BCM_6348_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_6348_HSSPI_IRQ 0
#define BCM_6348_OHCI0_IRQ (IRQ_INTERNAL_BASE + 12)
#define BCM_6348_EHCI0_IRQ 0
#define BCM_6348_USBD_IRQ 0
@@ -974,6 +989,7 @@ enum bcm63xx_irq {
#define BCM_6358_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
#define BCM_6358_ENET1_IRQ (IRQ_INTERNAL_BASE + 6)
#define BCM_6358_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_6358_HSSPI_IRQ 0
#define BCM_6358_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5)
#define BCM_6358_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10)
#define BCM_6358_USBD_IRQ 0
@@ -1086,6 +1102,7 @@ enum bcm63xx_irq {
#define BCM_6368_ENET0_IRQ 0
#define BCM_6368_ENET1_IRQ 0
#define BCM_6368_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 15)
+#define BCM_6368_HSSPI_IRQ 0
#define BCM_6368_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5)
#define BCM_6368_EHCI0_IRQ (IRQ_INTERNAL_BASE + 7)
#define BCM_6368_USBD_IRQ (IRQ_INTERNAL_BASE + 8)
@@ -1133,6 +1150,7 @@ extern const int *bcm63xx_irqs;
[IRQ_ENET0] = BCM_## __cpu ##_ENET0_IRQ, \
[IRQ_ENET1] = BCM_## __cpu ##_ENET1_IRQ, \
[IRQ_ENET_PHY] = BCM_## __cpu ##_ENET_PHY_IRQ, \
+ [IRQ_HSSPI] = BCM_## __cpu ##_HSSPI_IRQ, \
[IRQ_OHCI0] = BCM_## __cpu ##_OHCI0_IRQ, \
[IRQ_EHCI0] = BCM_## __cpu ##_EHCI0_IRQ, \
[IRQ_USBD] = BCM_## __cpu ##_USBD_IRQ, \
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -1561,4 +1561,51 @@
#define OTP_USER_BITS_6328_REG(i) (0x20 + (i) * 4)
#define OTP_6328_REG3_TP1_DISABLED BIT(9)
+/*************************************************************************
+ * _REG relative to RSET_HSSPI
+ *************************************************************************/
+
+#define HSSPI_GLOBAL_CTRL_REG 0x0
+#define GLOBAL_CTRL_CLK_POLARITY (1 << 17)
+#define GLOBAL_CTRL_CLK_GATE_SSOFF (1 << 16)
+
+#define HSSPI_GLOBAL_EXT_TRIGGER_REG 0x4
+
+#define HSSPI_INT_STATUS_REG 0x8
+#define HSSPI_INT_STATUS_MASKED_REG 0xc
+#define HSSPI_INT_MASK_REG 0x10
+
+#define HSSPI_PING0_CMD_DONE (1 << 0)
+
+#define HSSPI_INT_CLEAR_ALL 0xff001f1f
+
+#define HSSPI_PINGPONG_COMMAND_REG(x) (0x80 + (x) * 0x40)
+#define PINGPONG_CMD_COMMAND_MASK 0xf
+#define PINGPONG_COMMAND_NOOP 0
+#define PINGPONG_COMMAND_START_NOW 1
+#define PINGPONG_COMMAND_START_TRIGGER 2
+#define PINGPONG_COMMAND_HALT 3
+#define PINGPONG_COMMAND_FLUSH 4
+#define PINGPONG_CMD_PROFILE_SHIFT 8
+#define PINGPONG_CMD_SS_SHIFT 12
+
+#define HSSPI_PINGPONG_STATUS_REG(x) (0x84 + (x) * 0x40)
+
+#define HSSPI_PROFILE_CLK_CTRL_REG(x) (0x100 + (x) * 0x20)
+#define CLK_CTRL_ACCUM_RST_ON_LOOP (1 << 15)
+
+#define HSSPI_PROFILE_SIGNAL_CTRL_REG(x) (0x104 + (x) * 0x20)
+#define SIGNAL_CTRL_LATCH_RISING (1 << 12)
+#define SIGNAL_CTRL_LAUNCH_RISING (1 << 13)
+#define SIGNAL_CTRL_ASYNC_INPUT_PATH (1 << 16)
+
+#define HSSPI_PROFILE_MODE_CTRL_REG(x) (0x108 + (x) * 0x20)
+#define MODE_CTRL_MULTIDATA_RD_STRT_SHIFT 8
+#define MODE_CTRL_MULTIDATA_WR_STRT_SHIFT 12
+#define MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT 16
+#define MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT 18
+#define MODE_CTRL_PREPENDBYTE_CNT_SHIFT 24
+
+#define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200)
+
#endif /* BCM63XX_REGS_H_ */

View file

@ -0,0 +1,267 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -147,28 +147,28 @@ static struct board_info __initdata boar
.leds = {
{
- .name = "adsl",
+ .name = "96338GW:green:adsl",
.gpio = 3,
.active_low = 1,
},
{
- .name = "ses",
+ .name = "96338GW:green:ses",
.gpio = 5,
.active_low = 1,
},
{
- .name = "ppp-fail",
+ .name = "96338GW:green:ppp-fail",
.gpio = 4,
.active_low = 1,
},
{
- .name = "power",
+ .name = "96338GW:green:power",
.gpio = 0,
.active_low = 1,
.default_trigger = "default-on",
},
{
- .name = "stop",
+ .name = "96338GW:green:stop",
.gpio = 1,
.active_low = 1,
}
@@ -188,28 +188,28 @@ static struct board_info __initdata boar
.leds = {
{
- .name = "adsl",
+ .name = "96338W:green:adsl",
.gpio = 3,
.active_low = 1,
},
{
- .name = "ses",
+ .name = "96338W:green:ses",
.gpio = 5,
.active_low = 1,
},
{
- .name = "ppp-fail",
+ .name = "96338W:green:ppp-fail",
.gpio = 4,
.active_low = 1,
},
{
- .name = "power",
+ .name = "96338W:green:power",
.gpio = 0,
.active_low = 1,
.default_trigger = "default-on",
},
{
- .name = "stop",
+ .name = "96338W:green:stop",
.gpio = 1,
.active_low = 1,
},
@@ -248,29 +248,29 @@ static struct board_info __initdata boar
.leds = {
{
- .name = "adsl-fail",
+ .name = "96348R:green:adsl-fail",
.gpio = 2,
.active_low = 1,
},
{
- .name = "ppp",
+ .name = "96348R:green:ppp",
.gpio = 3,
.active_low = 1,
},
{
- .name = "ppp-fail",
+ .name = "96348R:green:ppp-fail",
.gpio = 4,
.active_low = 1,
},
{
- .name = "power",
+ .name = "96348R:green:power",
.gpio = 0,
.active_low = 1,
.default_trigger = "default-on",
},
{
- .name = "stop",
+ .name = "96348R:green:stop",
.gpio = 1,
.active_low = 1,
},
@@ -309,28 +309,28 @@ static struct board_info __initdata boar
.leds = {
{
- .name = "adsl-fail",
+ .name = "96348GW-10:green:adsl-fail",
.gpio = 2,
.active_low = 1,
},
{
- .name = "ppp",
+ .name = "96348GW-10:green:ppp",
.gpio = 3,
.active_low = 1,
},
{
- .name = "ppp-fail",
+ .name = "96348GW-10:green:ppp-fail",
.gpio = 4,
.active_low = 1,
},
{
- .name = "power",
+ .name = "96348GW-10:green:power",
.gpio = 0,
.active_low = 1,
.default_trigger = "default-on",
},
{
- .name = "stop",
+ .name = "96348GW-10:green:stop",
.gpio = 1,
.active_low = 1,
},
@@ -363,28 +363,28 @@ static struct board_info __initdata boar
.leds = {
{
- .name = "adsl-fail",
+ .name = "96348GW-11:green:adsl-fail",
.gpio = 2,
.active_low = 1,
},
{
- .name = "ppp",
+ .name = "96348GW-11:green:ppp",
.gpio = 3,
.active_low = 1,
},
{
- .name = "ppp-fail",
+ .name = "96348GW-11:green:ppp-fail",
.gpio = 4,
.active_low = 1,
},
{
- .name = "power",
+ .name = "96348GW-11:green:power",
.gpio = 0,
.active_low = 1,
.default_trigger = "default-on",
},
{
- .name = "stop",
+ .name = "96348GW-11:green:stop",
.gpio = 1,
.active_low = 1,
},
@@ -431,28 +431,28 @@ static struct board_info __initdata boar
.leds = {
{
- .name = "adsl-fail",
+ .name = "96348GW:green:adsl-fail",
.gpio = 2,
.active_low = 1,
},
{
- .name = "ppp",
+ .name = "96348GW:green:ppp",
.gpio = 3,
.active_low = 1,
},
{
- .name = "ppp-fail",
+ .name = "96348GW:green:ppp-fail",
.gpio = 4,
.active_low = 1,
},
{
- .name = "power",
+ .name = "96348GW:green:power",
.gpio = 0,
.active_low = 1,
.default_trigger = "default-on",
},
{
- .name = "stop",
+ .name = "96348GW:green:stop",
.gpio = 1,
.active_low = 1,
},
@@ -584,27 +584,27 @@ static struct board_info __initdata boar
.leds = {
{
- .name = "adsl-fail",
+ .name = "96358VW:green:adsl-fail",
.gpio = 15,
.active_low = 1,
},
{
- .name = "ppp",
+ .name = "96358VW:green:ppp",
.gpio = 22,
.active_low = 1,
},
{
- .name = "ppp-fail",
+ .name = "96358VW:green:ppp-fail",
.gpio = 23,
.active_low = 1,
},
{
- .name = "power",
+ .name = "96358VW:green:power",
.gpio = 4,
.default_trigger = "default-on",
},
{
- .name = "stop",
+ .name = "96358VW:green:stop",
.gpio = 5,
},
},
@@ -636,22 +636,22 @@ static struct board_info __initdata boar
.leds = {
{
- .name = "adsl",
+ .name = "96358VW2:green:adsl",
.gpio = 22,
.active_low = 1,
},
{
- .name = "ppp-fail",
+ .name = "96358VW2:green:ppp-fail",
.gpio = 23,
},
{
- .name = "power",
+ .name = "96358VW2:green:power",
.gpio = 5,
.active_low = 1,
.default_trigger = "default-on",
},
{
- .name = "stop",
+ .name = "96358VW2:green:stop",
.gpio = 4,
.active_low = 1,
},

View file

@ -0,0 +1,27 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -834,10 +834,20 @@ void __init board_prom_init(void)
/* dump cfe version */
cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET;
- if (!memcmp(cfe, "cfe-v", 5))
- snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u",
- cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
- else
+ if (strstarts(cfe, "cfe-")) {
+ if(cfe[4] == 'v') {
+ if(cfe[5] == 'd')
+ snprintf(cfe_version, 11, "%s", (char *) &cfe[5]);
+ else if (cfe[10] > 0)
+ snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u-%u",
+ cfe[5], cfe[6], cfe[7], cfe[8], cfe[9], cfe[10]);
+ else
+ snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u",
+ cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
+ } else {
+ snprintf(cfe_version, 12, "%s", (char *) &cfe[4]);
+ }
+ } else
strcpy(cfe_version, "unknown");
printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);

View file

@ -0,0 +1,51 @@
From 3bc62bd6e8c8a37d64cb797d24955711e98de15c Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 21 Mar 2013 17:05:15 +0100
Subject: [PATCH 05/14] MIPS: BCM63XX: rename __dispatch_internal to
__dispatch_internal_32
Make it follow the same naming convention as the other functions.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -19,7 +19,7 @@
#include <bcm63xx_io.h>
#include <bcm63xx_irq.h>
-static void __dispatch_internal(void) __maybe_unused;
+static void __dispatch_internal_32(void) __maybe_unused;
static void __dispatch_internal_64(void) __maybe_unused;
static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
@@ -117,7 +117,7 @@ static void __internal_irq_unmask_64(uns
#endif
#if irq_bits == 32
-#define dispatch_internal __dispatch_internal
+#define dispatch_internal __dispatch_internal_32
#define internal_irq_mask __internal_irq_mask_32
#define internal_irq_unmask __internal_irq_unmask_32
#else
@@ -225,7 +225,7 @@ static void bcm63xx_init_irq(void)
}
if (irq_bits == 32) {
- dispatch_internal = __dispatch_internal;
+ dispatch_internal = __dispatch_internal_32;
internal_irq_mask = __internal_irq_mask_32;
internal_irq_unmask = __internal_irq_unmask_32;
} else {
@@ -258,7 +258,7 @@ static inline void handle_internal(int i
* will resume the loop where it ended the last time we left this
* function.
*/
-static void __dispatch_internal(void)
+static void __dispatch_internal_32(void)
{
u32 pending;
static int i;

View file

@ -0,0 +1,167 @@
From 7447daa9a0768db157bbb64585f5411389712d59 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 18 Apr 2013 21:14:49 +0200
Subject: [PATCH 06/14] MIPS: BCM63XX: replace irq dispatch code with a
generic version
The generic version uses a variable length of u32 registers of u32/u64.
This allows easier support for longer registers without having to rewrite
verything.
This "generic" version is not slower than the old version in the best case
(= i == next set bit), and twice as fast in the worst case in 64 bits.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 130 ++++++++++++++++++++---------------------------
1 file changed, 56 insertions(+), 74 deletions(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -258,47 +258,65 @@ static inline void handle_internal(int i
* will resume the loop where it ended the last time we left this
* function.
*/
-static void __dispatch_internal_32(void)
-{
- u32 pending;
- static int i;
-
- pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
-
- if (!pending)
- return ;
-
- while (1) {
- int to_call = i;
- i = (i + 1) & 0x1f;
- if (pending & (1 << to_call)) {
- handle_internal(to_call);
- break;
- }
- }
+#define BUILD_IPIC_INTERNAL(width) \
+void __dispatch_internal_##width(void) \
+{ \
+ u32 pending[width / 32]; \
+ unsigned int src, tgt; \
+ bool irqs_pending = false; \
+ static int i; \
+ \
+ /* read registers in reverse order */ \
+ for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
+ u32 val; \
+ \
+ val = bcm_readl(irq_stat_addr + src * sizeof(u32)); \
+ val &= bcm_readl(irq_mask_addr + src * sizeof(u32)); \
+ pending[--tgt] = val; \
+ \
+ if (val) \
+ irqs_pending = true; \
+ } \
+ \
+ if (!irqs_pending) \
+ return; \
+ \
+ while (1) { \
+ int to_call = i; \
+ \
+ i = (i + 1) & (width - 1); \
+ if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
+ handle_internal(to_call); \
+ break; \
+ } \
+ } \
+} \
+ \
+static void __internal_irq_mask_##width(unsigned int irq) \
+{ \
+ u32 val; \
+ unsigned reg = (irq / 32) ^ (width/32 - 1); \
+ unsigned bit = irq & 0x1f; \
+ \
+ val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
+ val &= ~(1 << bit); \
+ bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+} \
+ \
+static void __internal_irq_unmask_##width(unsigned int irq) \
+{ \
+ u32 val; \
+ unsigned reg = (irq / 32) ^ (width/32 - 1); \
+ unsigned bit = irq & 0x1f; \
+ \
+ val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
+ val |= (1 << bit); \
+ bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
}
-static void __dispatch_internal_64(void)
-{
- u64 pending;
- static int i;
-
- pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
-
- if (!pending)
- return ;
-
- while (1) {
- int to_call = i;
-
- i = (i + 1) & 0x3f;
- if (pending & (1ull << to_call)) {
- handle_internal(to_call);
- break;
- }
- }
-}
+BUILD_IPIC_INTERNAL(32);
+BUILD_IPIC_INTERNAL(64);
asmlinkage void plat_irq_dispatch(void)
{
@@ -335,42 +353,6 @@ asmlinkage void plat_irq_dispatch(void)
* internal IRQs operations: only mask/unmask on PERF irq mask
* register.
*/
-static void __internal_irq_mask_32(unsigned int irq)
-{
- u32 mask;
-
- mask = bcm_readl(irq_mask_addr);
- mask &= ~(1 << irq);
- bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_mask_64(unsigned int irq)
-{
- u64 mask;
-
- mask = bcm_readq(irq_mask_addr);
- mask &= ~(1ull << irq);
- bcm_writeq(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_32(unsigned int irq)
-{
- u32 mask;
-
- mask = bcm_readl(irq_mask_addr);
- mask |= (1 << irq);
- bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_64(unsigned int irq)
-{
- u64 mask;
-
- mask = bcm_readq(irq_mask_addr);
- mask |= (1ull << irq);
- bcm_writeq(mask, irq_mask_addr);
-}
-
static void bcm63xx_internal_irq_mask(struct irq_data *d)
{
internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);

View file

@ -0,0 +1,279 @@
From 46442450ffb95a869894b0dfd1e5b4f973d4b4ee Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 25 Apr 2013 00:24:06 +0200
Subject: [PATCH 07/14] MIPS: BCM63XX: append cpu number to irq_{stat,mask}*
The SMP capable irq controllers have two interupt output pins which are
controlled through separate registers.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 86 ++++++++++-----------
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 16 ++--
2 files changed, 51 insertions(+), 51 deletions(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -28,8 +28,8 @@ static void __internal_irq_unmask_64(uns
#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_stat_reg0 PERF_IRQSTAT_3368_REG
+#define irq_mask_reg0 PERF_IRQMASK_3368_REG
#define irq_bits 32
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
@@ -39,8 +39,8 @@ static void __internal_irq_unmask_64(uns
#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
+#define irq_stat_reg0 PERF_IRQSTAT_6328_REG(0)
+#define irq_mask_reg0 PERF_IRQMASK_6328_REG(0)
#define irq_bits 64
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
@@ -50,8 +50,8 @@ static void __internal_irq_unmask_64(uns
#define ext_irq_cfg_reg2 0
#endif
#ifdef CONFIG_BCM63XX_CPU_6338
-#define irq_stat_reg PERF_IRQSTAT_6338_REG
-#define irq_mask_reg PERF_IRQMASK_6338_REG
+#define irq_stat_reg0 PERF_IRQSTAT_6338_REG
+#define irq_mask_reg0 PERF_IRQMASK_6338_REG
#define irq_bits 32
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
@@ -61,8 +61,8 @@ static void __internal_irq_unmask_64(uns
#define ext_irq_cfg_reg2 0
#endif
#ifdef CONFIG_BCM63XX_CPU_6345
-#define irq_stat_reg PERF_IRQSTAT_6345_REG
-#define irq_mask_reg PERF_IRQMASK_6345_REG
+#define irq_stat_reg0 PERF_IRQSTAT_6345_REG
+#define irq_mask_reg0 PERF_IRQMASK_6345_REG
#define irq_bits 32
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
@@ -72,8 +72,8 @@ static void __internal_irq_unmask_64(uns
#define ext_irq_cfg_reg2 0
#endif
#ifdef CONFIG_BCM63XX_CPU_6348
-#define irq_stat_reg PERF_IRQSTAT_6348_REG
-#define irq_mask_reg PERF_IRQMASK_6348_REG
+#define irq_stat_reg0 PERF_IRQSTAT_6348_REG
+#define irq_mask_reg0 PERF_IRQMASK_6348_REG
#define irq_bits 32
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
@@ -83,8 +83,8 @@ static void __internal_irq_unmask_64(uns
#define ext_irq_cfg_reg2 0
#endif
#ifdef CONFIG_BCM63XX_CPU_6358
-#define irq_stat_reg PERF_IRQSTAT_6358_REG
-#define irq_mask_reg PERF_IRQMASK_6358_REG
+#define irq_stat_reg0 PERF_IRQSTAT_6358_REG(0)
+#define irq_mask_reg0 PERF_IRQMASK_6358_REG(0)
#define irq_bits 32
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
@@ -94,8 +94,8 @@ static void __internal_irq_unmask_64(uns
#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_stat_reg0 PERF_IRQSTAT_6362_REG(0)
+#define irq_mask_reg0 PERF_IRQMASK_6362_REG(0)
#define irq_bits 64
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
@@ -105,8 +105,8 @@ static void __internal_irq_unmask_64(uns
#define ext_irq_cfg_reg2 0
#endif
#ifdef CONFIG_BCM63XX_CPU_6368
-#define irq_stat_reg PERF_IRQSTAT_6368_REG
-#define irq_mask_reg PERF_IRQMASK_6368_REG
+#define irq_stat_reg0 PERF_IRQSTAT_6368_REG(0)
+#define irq_mask_reg0 PERF_IRQMASK_6368_REG(0)
#define irq_bits 64
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE)
@@ -126,15 +126,15 @@ static void __internal_irq_unmask_64(uns
#define internal_irq_unmask __internal_irq_unmask_64
#endif
-#define irq_stat_addr (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg)
-#define irq_mask_addr (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg)
+#define irq_stat_addr0 (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg0)
+#define irq_mask_addr0 (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg0)
static inline void bcm63xx_init_irq(void)
{
}
#else /* ! BCMCPU_RUNTIME_DETECT */
-static u32 irq_stat_addr, irq_mask_addr;
+static u32 irq_stat_addr0, irq_mask_addr0;
static void (*dispatch_internal)(void);
static int is_ext_irq_cascaded;
static unsigned int ext_irq_count;
@@ -147,20 +147,20 @@ static void bcm63xx_init_irq(void)
{
int irq_bits;
- irq_stat_addr = bcm63xx_regset_address(RSET_PERF);
- irq_mask_addr = bcm63xx_regset_address(RSET_PERF);
+ irq_stat_addr0 = bcm63xx_regset_address(RSET_PERF);
+ irq_mask_addr0 = 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_stat_addr0 += PERF_IRQSTAT_3368_REG;
+ irq_mask_addr0 += 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;
+ irq_stat_addr0 += PERF_IRQSTAT_6328_REG(0);
+ irq_mask_addr0 += PERF_IRQMASK_6328_REG(0);
irq_bits = 64;
ext_irq_count = 4;
is_ext_irq_cascaded = 1;
@@ -169,29 +169,29 @@ static void bcm63xx_init_irq(void)
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
break;
case BCM6338_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6338_REG;
- irq_mask_addr += PERF_IRQMASK_6338_REG;
+ irq_stat_addr0 += PERF_IRQSTAT_6338_REG;
+ irq_mask_addr0 += PERF_IRQMASK_6338_REG;
irq_bits = 32;
ext_irq_count = 4;
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
break;
case BCM6345_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6345_REG;
- irq_mask_addr += PERF_IRQMASK_6345_REG;
+ irq_stat_addr0 += PERF_IRQSTAT_6345_REG;
+ irq_mask_addr0 += PERF_IRQMASK_6345_REG;
irq_bits = 32;
ext_irq_count = 4;
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
break;
case BCM6348_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6348_REG;
- irq_mask_addr += PERF_IRQMASK_6348_REG;
+ irq_stat_addr0 += PERF_IRQSTAT_6348_REG;
+ irq_mask_addr0 += PERF_IRQMASK_6348_REG;
irq_bits = 32;
ext_irq_count = 4;
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
break;
case BCM6358_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6358_REG;
- irq_mask_addr += PERF_IRQMASK_6358_REG;
+ irq_stat_addr0 += PERF_IRQSTAT_6358_REG(0);
+ irq_mask_addr0 += PERF_IRQMASK_6358_REG(0);
irq_bits = 32;
ext_irq_count = 4;
is_ext_irq_cascaded = 1;
@@ -200,8 +200,8 @@ static void bcm63xx_init_irq(void)
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_stat_addr0 += PERF_IRQSTAT_6362_REG(0);
+ irq_mask_addr0 += PERF_IRQMASK_6362_REG(0);
irq_bits = 64;
ext_irq_count = 4;
is_ext_irq_cascaded = 1;
@@ -210,8 +210,8 @@ static void bcm63xx_init_irq(void)
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;
+ irq_stat_addr0 += PERF_IRQSTAT_6368_REG(0);
+ irq_mask_addr0 += PERF_IRQMASK_6368_REG(0);
irq_bits = 64;
ext_irq_count = 6;
is_ext_irq_cascaded = 1;
@@ -271,8 +271,8 @@ void __dispatch_internal_##width(void)
for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
u32 val; \
\
- val = bcm_readl(irq_stat_addr + src * sizeof(u32)); \
- val &= bcm_readl(irq_mask_addr + src * sizeof(u32)); \
+ val = bcm_readl(irq_stat_addr0 + src * sizeof(u32)); \
+ val &= bcm_readl(irq_mask_addr0 + src * sizeof(u32)); \
pending[--tgt] = val; \
\
if (val) \
@@ -299,9 +299,9 @@ static void __internal_irq_mask_##width(
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
\
- val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
+ val = bcm_readl(irq_mask_addr0 + reg * sizeof(u32)); \
val &= ~(1 << bit); \
- bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+ bcm_writel(val, irq_mask_addr0 + reg * sizeof(u32)); \
} \
\
static void __internal_irq_unmask_##width(unsigned int irq) \
@@ -310,9 +310,9 @@ static void __internal_irq_unmask_##widt
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
\
- val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
+ val = bcm_readl(irq_mask_addr0 + reg * sizeof(u32)); \
val |= (1 << bit); \
- bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+ bcm_writel(val, irq_mask_addr0 + reg * sizeof(u32)); \
}
BUILD_IPIC_INTERNAL(32);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -215,23 +215,23 @@
/* Interrupt Mask register */
#define PERF_IRQMASK_3368_REG 0xc
-#define PERF_IRQMASK_6328_REG 0x20
+#define PERF_IRQMASK_6328_REG(x) (0x20 + (x) * 0x10)
#define PERF_IRQMASK_6338_REG 0xc
#define PERF_IRQMASK_6345_REG 0xc
#define PERF_IRQMASK_6348_REG 0xc
-#define PERF_IRQMASK_6358_REG 0xc
-#define PERF_IRQMASK_6362_REG 0x20
-#define PERF_IRQMASK_6368_REG 0x20
+#define PERF_IRQMASK_6358_REG(x) (0xc + (x) * 0x2c)
+#define PERF_IRQMASK_6362_REG(x) (0x20 + (x) * 0x10)
+#define PERF_IRQMASK_6368_REG(x) (0x20 + (x) * 0x10)
/* Interrupt Status register */
#define PERF_IRQSTAT_3368_REG 0x10
-#define PERF_IRQSTAT_6328_REG 0x28
+#define PERF_IRQSTAT_6328_REG(x) (0x28 + (x) * 0x10)
#define PERF_IRQSTAT_6338_REG 0x10
#define PERF_IRQSTAT_6345_REG 0x10
#define PERF_IRQSTAT_6348_REG 0x10
-#define PERF_IRQSTAT_6358_REG 0x10
-#define PERF_IRQSTAT_6362_REG 0x28
-#define PERF_IRQSTAT_6368_REG 0x28
+#define PERF_IRQSTAT_6358_REG(x) (0x10 + (x) * 0x2c)
+#define PERF_IRQSTAT_6362_REG(x) (0x28 + (x) * 0x10)
+#define PERF_IRQSTAT_6368_REG(x) (0x28 + (x) * 0x10)
/* External Interrupt Configuration register */
#define PERF_EXTIRQ_CFG_REG_3368 0x14

View file

@ -0,0 +1,186 @@
From 1a1769d6268c93b042f635b31b43024fea7feb30 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 25 Apr 2013 00:31:29 +0200
Subject: [PATCH 08/14] MIPS: BCM63XX: populate irq_{stat,mask}_addr for
second pin
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -30,6 +30,8 @@ static void __internal_irq_unmask_64(uns
#ifdef CONFIG_BCM63XX_CPU_3368
#define irq_stat_reg0 PERF_IRQSTAT_3368_REG
#define irq_mask_reg0 PERF_IRQMASK_3368_REG
+#define irq_stat_reg1 0
+#define irq_mask_reg1 0
#define irq_bits 32
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
@@ -41,6 +43,8 @@ static void __internal_irq_unmask_64(uns
#ifdef CONFIG_BCM63XX_CPU_6328
#define irq_stat_reg0 PERF_IRQSTAT_6328_REG(0)
#define irq_mask_reg0 PERF_IRQMASK_6328_REG(0)
+#define irq_stat_reg1 PERF_IRQSTAT_6328_REG(1)
+#define irq_mask_reg1 PERF_IRQMASK_6328_REG(1)
#define irq_bits 64
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
@@ -52,6 +56,8 @@ static void __internal_irq_unmask_64(uns
#ifdef CONFIG_BCM63XX_CPU_6338
#define irq_stat_reg0 PERF_IRQSTAT_6338_REG
#define irq_mask_reg0 PERF_IRQMASK_6338_REG
+#define irq_stat_reg1 0
+#define irq_mask_reg1 0
#define irq_bits 32
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
@@ -63,6 +69,8 @@ static void __internal_irq_unmask_64(uns
#ifdef CONFIG_BCM63XX_CPU_6345
#define irq_stat_reg0 PERF_IRQSTAT_6345_REG
#define irq_mask_reg0 PERF_IRQMASK_6345_REG
+#define irq_stat_reg1 0
+#define irq_mask_reg1 0
#define irq_bits 32
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
@@ -74,6 +82,8 @@ static void __internal_irq_unmask_64(uns
#ifdef CONFIG_BCM63XX_CPU_6348
#define irq_stat_reg0 PERF_IRQSTAT_6348_REG
#define irq_mask_reg0 PERF_IRQMASK_6348_REG
+#define irq_stat_reg1 0
+#define irq_mask_reg1 0
#define irq_bits 32
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
@@ -85,6 +95,8 @@ static void __internal_irq_unmask_64(uns
#ifdef CONFIG_BCM63XX_CPU_6358
#define irq_stat_reg0 PERF_IRQSTAT_6358_REG(0)
#define irq_mask_reg0 PERF_IRQMASK_6358_REG(0)
+#define irq_stat_reg1 PERF_IRQSTAT_6358_REG(1)
+#define irq_mask_reg1 PERF_IRQMASK_6358_REG(1)
#define irq_bits 32
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
@@ -96,6 +108,8 @@ static void __internal_irq_unmask_64(uns
#ifdef CONFIG_BCM63XX_CPU_6362
#define irq_stat_reg0 PERF_IRQSTAT_6362_REG(0)
#define irq_mask_reg0 PERF_IRQMASK_6362_REG(0)
+#define irq_stat_reg1 PERF_IRQSTAT_6362_REG(1)
+#define irq_mask_reg1 PERF_IRQMASK_6362_REG(1)
#define irq_bits 64
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
@@ -107,6 +121,8 @@ static void __internal_irq_unmask_64(uns
#ifdef CONFIG_BCM63XX_CPU_6368
#define irq_stat_reg0 PERF_IRQSTAT_6368_REG(0)
#define irq_mask_reg0 PERF_IRQMASK_6368_REG(0)
+#define irq_stat_reg1 PERF_IRQSTAT_6368_REG(1)
+#define irq_mask_reg1 PERF_IRQMASK_6368_REG(1)
#define irq_bits 64
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE)
@@ -128,13 +144,20 @@ static void __internal_irq_unmask_64(uns
#define irq_stat_addr0 (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg0)
#define irq_mask_addr0 (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg0)
+#if (irq_stat_reg1 > 0) && (irq_mask_reg1 > 0)
+#define irq_stat_addr1 (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg1)
+#define irq_mask_addr1 (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg1)
+#else
+#define irq_stat_addr1 0
+#define irq_mask_addr1 0
+#endif
static inline void bcm63xx_init_irq(void)
{
}
#else /* ! BCMCPU_RUNTIME_DETECT */
-static u32 irq_stat_addr0, irq_mask_addr0;
+static u32 irq_stat_addr0, irq_mask_addr0, irq_stat_addr1, irq_mask_addr1;
static void (*dispatch_internal)(void);
static int is_ext_irq_cascaded;
static unsigned int ext_irq_count;
@@ -149,11 +172,15 @@ static void bcm63xx_init_irq(void)
irq_stat_addr0 = bcm63xx_regset_address(RSET_PERF);
irq_mask_addr0 = bcm63xx_regset_address(RSET_PERF);
+ irq_stat_addr1 = bcm63xx_regset_address(RSET_PERF);
+ irq_mask_addr1 = bcm63xx_regset_address(RSET_PERF);
switch (bcm63xx_get_cpu_id()) {
case BCM3368_CPU_ID:
irq_stat_addr0 += PERF_IRQSTAT_3368_REG;
irq_mask_addr0 += PERF_IRQMASK_3368_REG;
+ irq_stat_addr1 = 0;
+ irq_stat_addr1 = 0;
irq_bits = 32;
ext_irq_count = 4;
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
@@ -161,6 +188,8 @@ static void bcm63xx_init_irq(void)
case BCM6328_CPU_ID:
irq_stat_addr0 += PERF_IRQSTAT_6328_REG(0);
irq_mask_addr0 += PERF_IRQMASK_6328_REG(0);
+ irq_stat_addr1 += PERF_IRQSTAT_6328_REG(1);
+ irq_stat_addr1 += PERF_IRQMASK_6328_REG(1);
irq_bits = 64;
ext_irq_count = 4;
is_ext_irq_cascaded = 1;
@@ -171,6 +200,8 @@ static void bcm63xx_init_irq(void)
case BCM6338_CPU_ID:
irq_stat_addr0 += PERF_IRQSTAT_6338_REG;
irq_mask_addr0 += PERF_IRQMASK_6338_REG;
+ irq_stat_addr1 = 0;
+ irq_mask_addr1 = 0;
irq_bits = 32;
ext_irq_count = 4;
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
@@ -178,6 +209,8 @@ static void bcm63xx_init_irq(void)
case BCM6345_CPU_ID:
irq_stat_addr0 += PERF_IRQSTAT_6345_REG;
irq_mask_addr0 += PERF_IRQMASK_6345_REG;
+ irq_stat_addr1 = 0;
+ irq_mask_addr1 = 0;
irq_bits = 32;
ext_irq_count = 4;
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
@@ -185,6 +218,8 @@ static void bcm63xx_init_irq(void)
case BCM6348_CPU_ID:
irq_stat_addr0 += PERF_IRQSTAT_6348_REG;
irq_mask_addr0 += PERF_IRQMASK_6348_REG;
+ irq_stat_addr1 = 0;
+ irq_mask_addr1 = 0;
irq_bits = 32;
ext_irq_count = 4;
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
@@ -192,6 +227,8 @@ static void bcm63xx_init_irq(void)
case BCM6358_CPU_ID:
irq_stat_addr0 += PERF_IRQSTAT_6358_REG(0);
irq_mask_addr0 += PERF_IRQMASK_6358_REG(0);
+ irq_stat_addr1 += PERF_IRQSTAT_6358_REG(1);
+ irq_mask_addr1 += PERF_IRQMASK_6358_REG(1);
irq_bits = 32;
ext_irq_count = 4;
is_ext_irq_cascaded = 1;
@@ -202,6 +239,8 @@ static void bcm63xx_init_irq(void)
case BCM6362_CPU_ID:
irq_stat_addr0 += PERF_IRQSTAT_6362_REG(0);
irq_mask_addr0 += PERF_IRQMASK_6362_REG(0);
+ irq_stat_addr1 += PERF_IRQSTAT_6362_REG(1);
+ irq_mask_addr1 += PERF_IRQMASK_6362_REG(1);
irq_bits = 64;
ext_irq_count = 4;
is_ext_irq_cascaded = 1;
@@ -212,6 +251,8 @@ static void bcm63xx_init_irq(void)
case BCM6368_CPU_ID:
irq_stat_addr0 += PERF_IRQSTAT_6368_REG(0);
irq_mask_addr0 += PERF_IRQMASK_6368_REG(0);
+ irq_stat_addr1 += PERF_IRQSTAT_6368_REG(1);
+ irq_mask_addr1 += PERF_IRQMASK_6368_REG(1);
irq_bits = 64;
ext_irq_count = 6;
is_ext_irq_cascaded = 1;

View file

@ -0,0 +1,80 @@
From 353f07637d82cf485a9319d203a6ed9b38590526 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 25 Apr 2013 15:35:12 +0200
Subject: [PATCH 09/14] MIPS: BCM63XX: use a helper for getting the right
register address
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -284,6 +284,20 @@ static inline u32 get_ext_irq_perf_reg(i
return ext_irq_cfg_reg2;
}
+static inline u32 get_irq_stat_addr(int pin)
+{
+ if (pin == 0)
+ return irq_stat_addr0;
+ return irq_stat_addr1;
+}
+
+static inline u32 get_irq_mask_addr(int pin)
+{
+ if (pin == 0)
+ return irq_mask_addr0;
+ return irq_mask_addr1;
+}
+
static inline void handle_internal(int intbit)
{
if (is_ext_irq_cascaded &&
@@ -307,13 +321,15 @@ void __dispatch_internal_##width(void)
unsigned int src, tgt; \
bool irqs_pending = false; \
static int i; \
+ u32 irq_stat_addr = get_irq_stat_addr(0); \
+ u32 irq_mask_addr = get_irq_mask_addr(0); \
\
/* read registers in reverse order */ \
for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
u32 val; \
\
- val = bcm_readl(irq_stat_addr0 + src * sizeof(u32)); \
- val &= bcm_readl(irq_mask_addr0 + src * sizeof(u32)); \
+ val = bcm_readl(irq_stat_addr + src * sizeof(u32)); \
+ val &= bcm_readl(irq_mask_addr + src * sizeof(u32)); \
pending[--tgt] = val; \
\
if (val) \
@@ -339,10 +355,11 @@ static void __internal_irq_mask_##width(
u32 val; \
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
+ u32 irq_mask_addr = get_irq_mask_addr(0); \
\
- val = bcm_readl(irq_mask_addr0 + reg * sizeof(u32)); \
+ val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
val &= ~(1 << bit); \
- bcm_writel(val, irq_mask_addr0 + reg * sizeof(u32)); \
+ bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
} \
\
static void __internal_irq_unmask_##width(unsigned int irq) \
@@ -350,10 +367,11 @@ static void __internal_irq_unmask_##widt
u32 val; \
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
+ u32 irq_mask_addr = get_irq_mask_addr(0); \
\
- val = bcm_readl(irq_mask_addr0 + reg * sizeof(u32)); \
+ val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
val |= (1 << bit); \
- bcm_writel(val, irq_mask_addr0 + reg * sizeof(u32)); \
+ bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
}
BUILD_IPIC_INTERNAL(32);

View file

@ -0,0 +1,73 @@
From b6b668f780d62d41bc14bc7baba1692e17cabf84 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 26 Apr 2013 11:21:16 +0200
Subject: [PATCH 10/14] MIPS: BCM63XX: add cpu argument to dispatch internal
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -19,8 +19,8 @@
#include <bcm63xx_io.h>
#include <bcm63xx_irq.h>
-static void __dispatch_internal_32(void) __maybe_unused;
-static void __dispatch_internal_64(void) __maybe_unused;
+static void __dispatch_internal_32(int cpu) __maybe_unused;
+static void __dispatch_internal_64(int cpu) __maybe_unused;
static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
@@ -158,7 +158,7 @@ static inline void bcm63xx_init_irq(void
#else /* ! BCMCPU_RUNTIME_DETECT */
static u32 irq_stat_addr0, irq_mask_addr0, irq_stat_addr1, irq_mask_addr1;
-static void (*dispatch_internal)(void);
+static void (*dispatch_internal)(int cpu);
static int is_ext_irq_cascaded;
static unsigned int ext_irq_count;
static unsigned int ext_irq_start, ext_irq_end;
@@ -315,14 +315,15 @@ static inline void handle_internal(int i
*/
#define BUILD_IPIC_INTERNAL(width) \
-void __dispatch_internal_##width(void) \
+void __dispatch_internal_##width(int cpu) \
{ \
u32 pending[width / 32]; \
unsigned int src, tgt; \
bool irqs_pending = false; \
- static int i; \
- u32 irq_stat_addr = get_irq_stat_addr(0); \
- u32 irq_mask_addr = get_irq_mask_addr(0); \
+ static int i[NR_CPUS]; \
+ u32 irq_stat_addr = get_irq_stat_addr(cpu); \
+ u32 irq_mask_addr = get_irq_mask_addr(cpu); \
+ int *next = &i[cpu]; \
\
/* read registers in reverse order */ \
for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
@@ -340,9 +341,9 @@ void __dispatch_internal_##width(void)
return; \
\
while (1) { \
- int to_call = i; \
+ int to_call = *next; \
\
- i = (i + 1) & (width - 1); \
+ *next = (*next + 1) & (width - 1); \
if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
handle_internal(to_call); \
break; \
@@ -394,7 +395,7 @@ asmlinkage void plat_irq_dispatch(void)
if (cause & CAUSEF_IP1)
do_IRQ(1);
if (cause & CAUSEF_IP2)
- dispatch_internal();
+ dispatch_internal(0);
if (!is_ext_irq_cascaded) {
if (cause & CAUSEF_IP3)
do_IRQ(IRQ_EXT_0);

View file

@ -0,0 +1,158 @@
From 05e32e9dc84ee96728596c0b8b86de7eae8de229 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 21 Apr 2013 15:38:56 +0200
Subject: [PATCH 11/14] MIPS: BCM63XX: protect irq register accesses
---
arch/mips/bcm63xx/irq.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/irq.h>
+#include <linux/spinlock.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <bcm63xx_cpu.h>
@@ -26,6 +27,9 @@ static void __internal_irq_mask_64(unsig
static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
+static DEFINE_SPINLOCK(ipic_lock);
+static DEFINE_SPINLOCK(epic_lock);
+
#ifndef BCMCPU_RUNTIME_DETECT
#ifdef CONFIG_BCM63XX_CPU_3368
#define irq_stat_reg0 PERF_IRQSTAT_3368_REG
@@ -324,8 +328,10 @@ void __dispatch_internal_##width(int cpu
u32 irq_stat_addr = get_irq_stat_addr(cpu); \
u32 irq_mask_addr = get_irq_mask_addr(cpu); \
int *next = &i[cpu]; \
+ unsigned long flags; \
\
/* read registers in reverse order */ \
+ spin_lock_irqsave(&ipic_lock, flags); \
for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
u32 val; \
\
@@ -336,6 +342,7 @@ void __dispatch_internal_##width(int cpu
if (val) \
irqs_pending = true; \
} \
+ spin_unlock_irqrestore(&ipic_lock, flags); \
\
if (!irqs_pending) \
return; \
@@ -357,10 +364,13 @@ static void __internal_irq_mask_##width(
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
u32 irq_mask_addr = get_irq_mask_addr(0); \
+ unsigned long flags; \
\
+ spin_lock_irqsave(&ipic_lock, flags); \
val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
val &= ~(1 << bit); \
bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+ spin_unlock_irqrestore(&ipic_lock, flags); \
} \
\
static void __internal_irq_unmask_##width(unsigned int irq) \
@@ -369,10 +379,13 @@ static void __internal_irq_unmask_##widt
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
u32 irq_mask_addr = get_irq_mask_addr(0); \
+ unsigned long flags; \
\
+ spin_lock_irqsave(&ipic_lock, flags); \
val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
val |= (1 << bit); \
bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+ spin_unlock_irqrestore(&ipic_lock, flags); \
}
BUILD_IPIC_INTERNAL(32);
@@ -431,8 +444,10 @@ static void bcm63xx_external_irq_mask(st
{
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
u32 reg, regaddr;
+ unsigned long flags;
regaddr = get_ext_irq_perf_reg(irq);
+ spin_lock_irqsave(&epic_lock, flags);
reg = bcm_perf_readl(regaddr);
if (BCMCPU_IS_6348())
@@ -441,6 +456,8 @@ static void bcm63xx_external_irq_mask(st
reg &= ~EXTIRQ_CFG_MASK(irq % 4);
bcm_perf_writel(reg, regaddr);
+ spin_unlock_irqrestore(&epic_lock, flags);
+
if (is_ext_irq_cascaded)
internal_irq_mask(irq + ext_irq_start);
}
@@ -449,8 +466,10 @@ static void bcm63xx_external_irq_unmask(
{
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
u32 reg, regaddr;
+ unsigned long flags;
regaddr = get_ext_irq_perf_reg(irq);
+ spin_lock_irqsave(&epic_lock, flags);
reg = bcm_perf_readl(regaddr);
if (BCMCPU_IS_6348())
@@ -459,6 +478,7 @@ static void bcm63xx_external_irq_unmask(
reg |= EXTIRQ_CFG_MASK(irq % 4);
bcm_perf_writel(reg, regaddr);
+ spin_unlock_irqrestore(&epic_lock, flags);
if (is_ext_irq_cascaded)
internal_irq_unmask(irq + ext_irq_start);
@@ -468,8 +488,10 @@ static void bcm63xx_external_irq_clear(s
{
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
u32 reg, regaddr;
+ unsigned long flags;
regaddr = get_ext_irq_perf_reg(irq);
+ spin_lock_irqsave(&epic_lock, flags);
reg = bcm_perf_readl(regaddr);
if (BCMCPU_IS_6348())
@@ -478,6 +500,7 @@ static void bcm63xx_external_irq_clear(s
reg |= EXTIRQ_CFG_CLEAR(irq % 4);
bcm_perf_writel(reg, regaddr);
+ spin_unlock_irqrestore(&epic_lock, flags);
}
static int bcm63xx_external_irq_set_type(struct irq_data *d,
@@ -486,6 +509,7 @@ static int bcm63xx_external_irq_set_type
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
u32 reg, regaddr;
int levelsense, sense, bothedge;
+ unsigned long flags;
flow_type &= IRQ_TYPE_SENSE_MASK;
@@ -520,6 +544,7 @@ static int bcm63xx_external_irq_set_type
}
regaddr = get_ext_irq_perf_reg(irq);
+ spin_lock_irqsave(&epic_lock, flags);
reg = bcm_perf_readl(regaddr);
irq %= 4;
@@ -564,6 +589,7 @@ static int bcm63xx_external_irq_set_type
}
bcm_perf_writel(reg, regaddr);
+ spin_unlock_irqrestore(&epic_lock, flags);
irqd_set_trigger_type(d, flow_type);
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))

View file

@ -0,0 +1,100 @@
From 70c33fe0df8d14e40f3ca92ce56a668d66184858 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 26 Apr 2013 12:03:15 +0200
Subject: [PATCH 12/14] MIPS: BCM63XX: wire up the second cpu's irq line
---
arch/mips/bcm63xx/irq.c | 50 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 41 insertions(+), 9 deletions(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -363,13 +363,20 @@ static void __internal_irq_mask_##width(
u32 val; \
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
- u32 irq_mask_addr = get_irq_mask_addr(0); \
unsigned long flags; \
+ int cpu; \
\
spin_lock_irqsave(&ipic_lock, flags); \
- val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
- val &= ~(1 << bit); \
- bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+ for_each_present_cpu(cpu) { \
+ u32 irq_mask_addr = get_irq_mask_addr(cpu); \
+ \
+ if (!irq_mask_addr) \
+ break; \
+ \
+ val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
+ val &= ~(1 << bit); \
+ bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+ } \
spin_unlock_irqrestore(&ipic_lock, flags); \
} \
\
@@ -378,13 +385,23 @@ static void __internal_irq_unmask_##widt
u32 val; \
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
- u32 irq_mask_addr = get_irq_mask_addr(0); \
unsigned long flags; \
+ int cpu; \
\
spin_lock_irqsave(&ipic_lock, flags); \
- val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
- val |= (1 << bit); \
- bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+ for_each_present_cpu(cpu) { \
+ u32 irq_mask_addr = get_irq_mask_addr(cpu); \
+ \
+ if (!irq_mask_addr) \
+ break; \
+ \
+ val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
+ if (cpu_online(cpu)) \
+ val |= (1 << bit); \
+ else \
+ val &= ~(1 << bit); \
+ bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
+ } \
spin_unlock_irqrestore(&ipic_lock, flags); \
}
@@ -409,7 +426,10 @@ asmlinkage void plat_irq_dispatch(void)
do_IRQ(1);
if (cause & CAUSEF_IP2)
dispatch_internal(0);
- if (!is_ext_irq_cascaded) {
+ if (is_ext_irq_cascaded) {
+ if (cause & CAUSEF_IP3)
+ dispatch_internal(1);
+ } else {
if (cause & CAUSEF_IP3)
do_IRQ(IRQ_EXT_0);
if (cause & CAUSEF_IP4)
@@ -622,6 +642,14 @@ static struct irqaction cpu_ip2_cascade_
.flags = IRQF_NO_THREAD,
};
+#ifdef CONFIG_SMP
+static struct irqaction cpu_ip3_cascade_action = {
+ .handler = no_action,
+ .name = "cascade_ip3",
+ .flags = IRQF_NO_THREAD,
+};
+#endif
+
static struct irqaction cpu_ext_cascade_action = {
.handler = no_action,
.name = "cascade_extirq",
@@ -648,4 +676,8 @@ void __init arch_init_irq(void)
}
setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
+#ifdef CONFIG_SMP
+ if (is_ext_irq_cascaded)
+ setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+#endif
}

View file

@ -0,0 +1,98 @@
From 0e692ab15a69ac4534c18e67ed3cb7685f728037 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 30 Apr 2013 11:26:53 +0200
Subject: [PATCH 13/14] MIPS: BCM63XX: use irq_desc as argument for (un)mask
In preparation for applying affinity, use the irq descriptor as the
argument for (un)mask.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -22,10 +22,10 @@
static void __dispatch_internal_32(int cpu) __maybe_unused;
static void __dispatch_internal_64(int cpu) __maybe_unused;
-static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
+static void __internal_irq_mask_32(struct irq_data *d) __maybe_unused;
+static void __internal_irq_mask_64(struct irq_data *d) __maybe_unused;
+static void __internal_irq_unmask_32(struct irq_data *d) __maybe_unused;
+static void __internal_irq_unmask_64(struct irq_data *d) __maybe_unused;
static DEFINE_SPINLOCK(ipic_lock);
static DEFINE_SPINLOCK(epic_lock);
@@ -167,8 +167,8 @@ static int is_ext_irq_cascaded;
static unsigned int ext_irq_count;
static unsigned int ext_irq_start, ext_irq_end;
static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
-static void (*internal_irq_mask)(unsigned int irq);
-static void (*internal_irq_unmask)(unsigned int irq);
+static void (*internal_irq_mask)(struct irq_data *d);
+static void (*internal_irq_unmask)(struct irq_data *d);
static void bcm63xx_init_irq(void)
{
@@ -358,9 +358,10 @@ void __dispatch_internal_##width(int cpu
} \
} \
\
-static void __internal_irq_mask_##width(unsigned int irq) \
+static void __internal_irq_mask_##width(struct irq_data *d) \
{ \
u32 val; \
+ unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
unsigned long flags; \
@@ -380,9 +381,10 @@ static void __internal_irq_mask_##width(
spin_unlock_irqrestore(&ipic_lock, flags); \
} \
\
-static void __internal_irq_unmask_##width(unsigned int irq) \
+static void __internal_irq_unmask_##width(struct irq_data *d) \
{ \
u32 val; \
+ unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
unsigned reg = (irq / 32) ^ (width/32 - 1); \
unsigned bit = irq & 0x1f; \
unsigned long flags; \
@@ -448,12 +450,12 @@ asmlinkage void plat_irq_dispatch(void)
*/
static void bcm63xx_internal_irq_mask(struct irq_data *d)
{
- internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
+ internal_irq_mask(d);
}
static void bcm63xx_internal_irq_unmask(struct irq_data *d)
{
- internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE);
+ internal_irq_unmask(d);
}
/*
@@ -479,7 +481,7 @@ static void bcm63xx_external_irq_mask(st
spin_unlock_irqrestore(&epic_lock, flags);
if (is_ext_irq_cascaded)
- internal_irq_mask(irq + ext_irq_start);
+ internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
}
static void bcm63xx_external_irq_unmask(struct irq_data *d)
@@ -501,7 +503,7 @@ static void bcm63xx_external_irq_unmask(
spin_unlock_irqrestore(&epic_lock, flags);
if (is_ext_irq_cascaded)
- internal_irq_unmask(irq + ext_irq_start);
+ internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start));
}
static void bcm63xx_external_irq_clear(struct irq_data *d)

View file

@ -0,0 +1,124 @@
From 9e341df1f67c3c64dc5ac668a30bbb6b5ab5f2b4 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 26 Apr 2013 12:06:03 +0200
Subject: [PATCH 14/14] MIPS: BCM63XX: allow setting affinity for IPIC
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 49 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 41 insertions(+), 8 deletions(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -24,8 +24,10 @@ static void __dispatch_internal_32(int c
static void __dispatch_internal_64(int cpu) __maybe_unused;
static void __internal_irq_mask_32(struct irq_data *d) __maybe_unused;
static void __internal_irq_mask_64(struct irq_data *d) __maybe_unused;
-static void __internal_irq_unmask_32(struct irq_data *d) __maybe_unused;
-static void __internal_irq_unmask_64(struct irq_data *d) __maybe_unused;
+static void __internal_irq_unmask_32(struct irq_data *d,
+ const struct cpumask *mask) __maybe_unused;
+static void __internal_irq_unmask_64(struct irq_data *d,
+ const struct cpumask *mask) __maybe_unused;
static DEFINE_SPINLOCK(ipic_lock);
static DEFINE_SPINLOCK(epic_lock);
@@ -168,7 +170,7 @@ static unsigned int ext_irq_count;
static unsigned int ext_irq_start, ext_irq_end;
static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
static void (*internal_irq_mask)(struct irq_data *d);
-static void (*internal_irq_unmask)(struct irq_data *d);
+static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
static void bcm63xx_init_irq(void)
{
@@ -311,6 +313,20 @@ static inline void handle_internal(int i
do_IRQ(intbit + IRQ_INTERNAL_BASE);
}
+static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
+ const struct cpumask *m)
+{
+ bool enable = cpu_online(cpu);
+#ifdef CONFIG_SMP
+
+ if (m)
+ enable &= cpu_isset(cpu, *m);
+ else if (irqd_affinity_was_set(d))
+ enable &= cpu_isset(cpu, *d->affinity);
+#endif
+ return enable;
+}
+
/*
* dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
* prioritize any interrupt relatively to another. the static counter
@@ -381,7 +397,8 @@ static void __internal_irq_mask_##width(
spin_unlock_irqrestore(&ipic_lock, flags); \
} \
\
-static void __internal_irq_unmask_##width(struct irq_data *d) \
+static void __internal_irq_unmask_##width(struct irq_data *d, \
+ const struct cpumask *m) \
{ \
u32 val; \
unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
@@ -398,7 +415,7 @@ static void __internal_irq_unmask_##widt
break; \
\
val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
- if (cpu_online(cpu)) \
+ if (enable_irq_for_cpu(cpu, d, m)) \
val |= (1 << bit); \
else \
val &= ~(1 << bit); \
@@ -455,7 +472,7 @@ static void bcm63xx_internal_irq_mask(st
static void bcm63xx_internal_irq_unmask(struct irq_data *d)
{
- internal_irq_unmask(d);
+ internal_irq_unmask(d, NULL);
}
/*
@@ -503,7 +520,8 @@ static void bcm63xx_external_irq_unmask(
spin_unlock_irqrestore(&epic_lock, flags);
if (is_ext_irq_cascaded)
- internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start));
+ internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
+ NULL);
}
static void bcm63xx_external_irq_clear(struct irq_data *d)
@@ -622,6 +640,18 @@ static int bcm63xx_external_irq_set_type
return IRQ_SET_MASK_OK_NOCOPY;
}
+#ifdef CONFIG_SMP
+static int bcm63xx_internal_set_affinity(struct irq_data *data,
+ const struct cpumask *dest,
+ bool force)
+{
+ if (!irqd_irq_disabled(data))
+ internal_irq_unmask(data, dest);
+
+ return 0;
+}
+#endif
+
static struct irq_chip bcm63xx_internal_irq_chip = {
.name = "bcm63xx_ipic",
.irq_mask = bcm63xx_internal_irq_mask,
@@ -679,7 +709,10 @@ void __init arch_init_irq(void)
setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
#ifdef CONFIG_SMP
- if (is_ext_irq_cascaded)
+ if (is_ext_irq_cascaded) {
setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+ bcm63xx_internal_irq_chip.irq_set_affinity =
+ bcm63xx_internal_set_affinity;
+ }
#endif
}

View file

@ -0,0 +1,20 @@
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_board.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_board.h
@@ -1,6 +1,8 @@
#ifndef BCM63XX_BOARD_H_
#define BCM63XX_BOARD_H_
+#include <asm/bootinfo.h>
+
const char *board_get_name(void);
void board_prom_init(void);
@@ -9,4 +11,8 @@ void board_setup(void);
int board_register_devices(void);
+static inline bool bcm63xx_is_cfe_present(void) {
+ return fw_arg3 == 0x43464531;
+}
+
#endif /* ! BCM63XX_BOARD_H_ */

View file

@ -0,0 +1,51 @@
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -35,7 +35,7 @@
#include <linux/bcm963xx_tag.h>
#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
-#include <asm/mach-bcm63xx/board_bcm963xx.h>
+#include <asm/mach-bcm63xx/bcm63xx_board.h>
#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
@@ -43,30 +43,6 @@
#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
-static int bcm63xx_detect_cfe(struct mtd_info *master)
-{
- char buf[9];
- int ret;
- size_t retlen;
-
- ret = mtd_read(master, BCM963XX_CFE_VERSION_OFFSET, 5, &retlen,
- (void *)buf);
- buf[retlen] = 0;
-
- if (ret)
- return ret;
-
- if (strncmp("cfe-v", buf, 5) == 0)
- return 0;
-
- /* very old CFE's do not have the cfe-v string, so check for magic */
- ret = mtd_read(master, BCM63XX_CFE_MAGIC_OFFSET, 8, &retlen,
- (void *)buf);
- buf[retlen] = 0;
-
- return strncmp("CFE1CFE1", buf, 8);
-}
-
static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
struct mtd_partition **pparts,
struct mtd_part_parser_data *data)
@@ -85,7 +61,7 @@ static int bcm63xx_parse_cfe_partitions(
u32 computed_crc;
bool rootfs_first = false;
- if (bcm63xx_detect_cfe(master))
+ if (!bcm63xx_is_cfe_present())
return -EINVAL;
cfe_erasesize = max_t(uint32_t, master->erasesize,

View file

@ -0,0 +1,65 @@
From a4d005c91d403d9f3d0272db6cc46202c06ec774 Mon Sep 17 00:00:00 2001
From: Axel Gembe <ago@bastart.eu.org>
Date: Mon, 12 May 2008 18:54:09 +0200
Subject: [PATCH] bcm963xx: flashmap support
Signed-off-by: Axel Gembe <ago@bastart.eu.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 19 +----------------
drivers/mtd/maps/bcm963xx-flash.c | 32 ++++++++++++++++++++++++----
drivers/mtd/redboot.c | 13 +++++++++--
3 files changed, 38 insertions(+), 26 deletions(-)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -30,7 +30,7 @@ static struct mtd_partition mtd_partitio
}
};
-static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
+static const char *bcm63xx_part_types[] = { "bcm63xxpart", "RedBoot", NULL };
static struct physmap_flash_data flash_data = {
.width = 2,
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -72,6 +72,7 @@ static int parse_redboot_partitions(stru
int nulllen = 0;
int numslots;
unsigned long offset;
+ unsigned long fis_origin = 0;
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
static char nullstring[] = "unallocated";
#endif
@@ -176,6 +177,16 @@ static int parse_redboot_partitions(stru
goto out;
}
+ if (data && data->origin) {
+ fis_origin = data->origin;
+ } else {
+ for (i = 0; i < numslots; i++) {
+ if (!strncmp(buf[i].name, "RedBoot", 8)) {
+ fis_origin = (buf[i].flash_base & (master->size << 1) - 1);
+ }
+ }
+ }
+
for (i = 0; i < numslots; i++) {
struct fis_list *new_fl, **prev;
@@ -196,10 +207,10 @@ static int parse_redboot_partitions(stru
goto out;
}
new_fl->img = &buf[i];
- if (data && data->origin)
- buf[i].flash_base -= data->origin;
- else
- buf[i].flash_base &= master->size-1;
+ if (fis_origin)
+ buf[i].flash_base -= fis_origin;
+
+ buf[i].flash_base &= (master->size << 1) - 1;
/* I'm sure the JFFS2 code has done me permanent damage.
* I now think the following is _normal_

View file

@ -0,0 +1,27 @@
--- a/include/uapi/linux/bcm963xx_tag.h
+++ b/include/uapi/linux/bcm963xx_tag.h
@@ -85,8 +85,10 @@ struct bcm_tag {
__u32 rootfs_crc;
/* 224-227: CRC32 of kernel partition */
__u32 kernel_crc;
- /* 228-235: Unused at present */
- char reserved1[8];
+ /* 228-231: Image sequence number */
+ char image_sequence[4];
+ /* 222-235: Openwrt: real rootfs length */
+ __u32 real_rootfs_length;
/* 236-239: CRC32 of header excluding last 20 bytes */
__u32 header_crc;
/* 240-255: Unused at present */
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -110,7 +110,8 @@ static int bcm63xx_parse_cfe_partitions(
} else {
/* OpenWrt layout */
rootfsaddr = kerneladdr + kernellen;
- rootfslen = spareaddr - rootfsaddr;
+ rootfslen = buf->real_rootfs_length;
+ spareaddr = rootfsaddr + rootfslen;
}
} else {
pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n",

View file

@ -0,0 +1,11 @@
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1635,7 +1635,7 @@ static int compute_hw_mtu(struct bcm_ene
actual_mtu = mtu;
/* add ethernet header + vlan tag size */
- actual_mtu += VLAN_ETH_HLEN;
+ actual_mtu += VLAN_ETH_HLEN + VLAN_HLEN;
if (actual_mtu < 64 || actual_mtu > BCMENET_MAX_MTU)
return -EINVAL;

View file

@ -0,0 +1,22 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -910,6 +910,8 @@ void __init board_prom_init(void)
if (BCMCPU_IS_6348())
val |= GPIO_MODE_6348_G3_EXT_MII |
GPIO_MODE_6348_G0_EXT_MII;
+ else if (BCMCPU_IS_6358())
+ val |= GPIO_MODE_6358_ENET1_MII_CLK_INV;
}
bcm_gpio_writel(val, GPIO_MODE_REG);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -621,6 +621,8 @@
#define GPIO_MODE_6358_EXTRA_SPI_SS (1 << 7)
#define GPIO_MODE_6358_SERIAL_LED (1 << 10)
#define GPIO_MODE_6358_UTOPIA (1 << 12)
+#define GPIO_MODE_6358_ENET1_MII_CLK_INV (1 << 30)
+#define GPIO_MODE_6358_ENET0_MII_CLK_INV (1 << 31)
#define GPIO_MODE_6368_ANALOG_AFE_0 (1 << 0)
#define GPIO_MODE_6368_ANALOG_AFE_1 (1 << 1)

View file

@ -0,0 +1,169 @@
From b11218c750ab92cfab4408a0328f1b36ceec3f33 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 6 Jan 2012 12:24:18 +0100
Subject: [PATCH 19/63] NET: bcm63xx_enet: move phy_(dis)connect into probe/remove
Only connect/disconnect the phy during probe and remove, not during any
open/close. The phy seldom changes during the runtime, and disconnecting
the phy during close will prevent it from keeping any configuration over
a down/up cycle.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 84 +++++++++++++-------------
1 files changed, 41 insertions(+), 43 deletions(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -870,10 +870,8 @@ static int bcm_enet_open(struct net_devi
struct bcm_enet_priv *priv;
struct sockaddr addr;
struct device *kdev;
- struct phy_device *phydev;
int i, ret;
unsigned int size;
- char phy_id[MII_BUS_ID_SIZE + 3];
void *p;
u32 val;
@@ -881,40 +879,10 @@ static int bcm_enet_open(struct net_devi
kdev = &priv->pdev->dev;
if (priv->has_phy) {
- /* connect to PHY */
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
- priv->mii_bus->id, priv->phy_id);
-
- phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link,
- PHY_INTERFACE_MODE_MII);
-
- if (IS_ERR(phydev)) {
- dev_err(kdev, "could not attach to PHY\n");
- return PTR_ERR(phydev);
- }
-
- /* mask with MAC supported features */
- phydev->supported &= (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_MII);
- phydev->advertising = phydev->supported;
-
- if (priv->pause_auto && priv->pause_rx && priv->pause_tx)
- phydev->advertising |= SUPPORTED_Pause;
- else
- phydev->advertising &= ~SUPPORTED_Pause;
-
- dev_info(kdev, "attached PHY at address %d [%s]\n",
- phydev->addr, phydev->drv->name);
-
+ /* Reset state */
priv->old_link = 0;
priv->old_duplex = -1;
priv->old_pause = -1;
- priv->phydev = phydev;
}
/* mask all interrupts and request them */
@@ -924,7 +892,7 @@ static int bcm_enet_open(struct net_devi
ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev);
if (ret)
- goto out_phy_disconnect;
+ return ret;
ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, IRQF_DISABLED,
dev->name, dev);
@@ -1129,9 +1097,6 @@ out_freeirq_rx:
out_freeirq:
free_irq(dev->irq, dev);
-out_phy_disconnect:
- phy_disconnect(priv->phydev);
-
return ret;
}
@@ -1236,12 +1201,6 @@ static int bcm_enet_stop(struct net_devi
free_irq(priv->irq_rx, dev);
free_irq(dev->irq, dev);
- /* release phy */
- if (priv->has_phy) {
- phy_disconnect(priv->phydev);
- priv->phydev = NULL;
- }
-
return 0;
}
@@ -1836,6 +1795,8 @@ static int bcm_enet_probe(struct platfor
/* MII bus registration */
if (priv->has_phy) {
+ struct phy_device *phydev;
+ char phy_id[MII_BUS_ID_SIZE + 3];
priv->mii_bus = mdiobus_alloc();
if (!priv->mii_bus) {
@@ -1873,6 +1834,38 @@ static int bcm_enet_probe(struct platfor
dev_err(&pdev->dev, "unable to register mdio bus\n");
goto out_free_mdio;
}
+
+ /* connect to PHY */
+ snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
+ priv->mii_bus->id, priv->phy_id);
+
+ phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link,
+ PHY_INTERFACE_MODE_MII);
+
+ if (IS_ERR(phydev)) {
+ dev_err(&pdev->dev, "could not attach to PHY\n");
+ goto out_unregister_mdio;
+ }
+
+ /* mask with MAC supported features */
+ phydev->supported &= (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_MII);
+ phydev->advertising = phydev->supported;
+
+ if (priv->pause_auto && priv->pause_rx && priv->pause_tx)
+ phydev->advertising |= SUPPORTED_Pause;
+ else
+ phydev->advertising &= ~SUPPORTED_Pause;
+
+ dev_info(&pdev->dev, "attached PHY at address %d [%s]\n",
+ phydev->addr, phydev->drv->name);
+
+ priv->phydev = phydev;
} else {
/* run platform code to initialize PHY device */
@@ -1918,6 +1911,9 @@ static int bcm_enet_probe(struct platfor
return 0;
out_unregister_mdio:
+ if (priv->phydev)
+ phy_disconnect(priv->phydev);
+
if (priv->mii_bus)
mdiobus_unregister(priv->mii_bus);
@@ -1959,6 +1955,8 @@ static int bcm_enet_remove(struct platfo
enet_writel(priv, 0, ENET_MIISC_REG);
if (priv->has_phy) {
+ phy_disconnect(priv->phydev);
+ priv->phydev = NULL;
mdiobus_unregister(priv->mii_bus);
mdiobus_free(priv->mii_bus);
} else {

View file

@ -0,0 +1,53 @@
From d8237d704fc25eb2fc25ef4403608b78c6a6d4be Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sun, 15 Jul 2012 20:08:57 +0200
Subject: [PATCH 54/81] bcm63xx_enet: enable rgmii clock on external ports
---
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 13 +++++++++++++
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 12 ++++++++++++
2 files changed, 25 insertions(+), 0 deletions(-)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -931,6 +931,19 @@
#define ENETSW_PORTOV_FDX_MASK (1 << 1)
#define ENETSW_PORTOV_LINKUP_MASK (1 << 0)
+/* Port RGMII control register */
+#define ENETSW_RGMII_CTRL_REG(x) (0x60 + (x))
+#define ENETSW_RGMII_CTRL_GMII_CLK_EN (1 << 7)
+#define ENETSW_RGMII_CTRL_MII_OVERRIDE_EN (1 << 6)
+#define ENETSW_RGMII_CTRL_MII_MODE_MASK (3 << 4)
+#define ENETSW_RGMII_CTRL_RGMII_MODE (0 << 4)
+#define ENETSW_RGMII_CTRL_MII_MODE (1 << 4)
+#define ENETSW_RGMII_CTRL_RVMII_MODE (2 << 4)
+#define ENETSW_RGMII_CTRL_TIMING_SEL_EN (1 << 0)
+
+/* Port RGMII timing register */
+#define ENETSW_RGMII_TIMING_REG(x) (0x68 + (x))
+
/* MDIO control register */
#define ENETSW_MDIOC_REG (0xb0)
#define ENETSW_MDIOC_EXT_MASK (1 << 16)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -2231,6 +2231,18 @@ static int bcm_enetsw_open(struct net_de
priv->sw_port_link[i] = 0;
}
+ /* enable external ports */
+ for (i = ENETSW_RGMII_PORT0; i < priv->num_ports; i++) {
+ u8 rgmii_ctrl;
+
+ if (!priv->used_ports[i].used)
+ continue;
+
+ rgmii_ctrl = enetsw_readb(priv, ENETSW_RGMII_CTRL_REG(i));
+ rgmii_ctrl |= ENETSW_RGMII_CTRL_GMII_CLK_EN;
+ enetsw_writeb(priv, rgmii_ctrl, ENETSW_RGMII_CTRL_REG(i));
+ }
+
/* reset mib */
val = enetsw_readb(priv, ENETSW_GMCR_REG);
val |= ENETSW_GMCR_RST_MIB_MASK;

View file

@ -0,0 +1,134 @@
From 261ee140e75615351128eee497e6bbd76686784b Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sat, 12 Nov 2011 12:18:26 +0100
Subject: [PATCH 51/72] MIPS: BCM63XX: add HS SPI platform device and register
it
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
arch/mips/bcm63xx/Makefile | 4 +-
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +
arch/mips/bcm63xx/dev-hsspi.c | 57 ++++++++++++++++++++
.../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 20 +++++++
4 files changed, 81 insertions(+), 2 deletions(-)
create mode 100644 arch/mips/bcm63xx/dev-hsspi.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -1,7 +1,8 @@
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-ehci.o dev-usb-ohci.o dev-usb-usbd.o usb-common.o
+ dev-hsspi.o dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o \
+ dev-wdt.o dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o \
+ usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -26,6 +26,7 @@
#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_ehci.h>
@@ -1003,6 +1004,7 @@ int __init board_register_devices(void)
pr_err(PFX "failed to register fallback SPROM\n");
}
#endif
+ bcm63xx_hsspi_register();
bcm63xx_spi_register();
--- /dev/null
+++ b/arch/mips/bcm63xx/dev-hsspi.c
@@ -0,0 +1,60 @@
+/*
+ * 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 bcm63xx_hsspi_pdata spi_pdata = {
+ .bus_num = 1,
+};
+
+static struct platform_device bcm63xx_hsspi_device = {
+ .name = "bcm63xx-hsspi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(spi_resources),
+ .resource = spi_resources,
+ .dev = {
+ .platform_data = &spi_pdata,
+ },
+};
+
+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);
+
+ if (BCMCPU_IS_6328())
+ spi_pdata.speed_hz = HSSPI_PLL_HZ_6328;
+ else if (BCMCPU_IS_6362())
+ spi_pdata.speed_hz = HSSPI_PLL_HZ_6362;
+
+ return platform_device_register(&bcm63xx_hsspi_device);
+}
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
@@ -0,0 +1,21 @@
+#ifndef BCM63XX_DEV_HSSPI_H
+#define BCM63XX_DEV_HSSPI_H
+
+#include <linux/types.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_regs.h>
+
+int __init bcm63xx_hsspi_register(void);
+
+struct bcm63xx_hsspi_pdata {
+ int bus_num;
+ u32 speed_hz;
+};
+
+#define bcm_hsspi_readl(o) bcm_rset_readl(RSET_HSSPI, (o))
+#define bcm_hsspi_writel(v, o) bcm_rset_writel(RSET_HSSPI, (v), (o))
+
+#define HSSPI_PLL_HZ_6328 133333333
+#define HSSPI_PLL_HZ_6362 400000000
+
+#endif /* BCM63XX_DEV_HSSPI_H */

View file

@ -0,0 +1,481 @@
From 4b27423676485d05bcd6fc6f3809164fb8f9d22d Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sat, 12 Nov 2011 12:19:55 +0100
Subject: [PATCH 30/60] SPI: MIPS: BCM63XX: Add HSSPI driver
Add a driver for the High Speed SPI controller found on newer BCM63XX SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 2 +
drivers/spi/Kconfig | 7 +
drivers/spi/Makefile | 1 +
drivers/spi/spi-bcm63xx-hsspi.c | 427 ++++++++++++++++++++
4 files changed, 437 insertions(+), 0 deletions(-)
create mode 100644 drivers/spi/spi-bcm63xx-hsspi.c
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
@@ -18,4 +18,6 @@ struct bcm63xx_hsspi_pdata {
#define HSSPI_PLL_HZ_6328 133333333
#define HSSPI_PLL_HZ_6362 400000000
+#define HSSPI_BUFFER_LEN 512
+
#endif /* BCM63XX_DEV_HSSPI_H */
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -112,6 +112,13 @@ config SPI_BCM63XX
help
Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
+config SPI_BCM63XX_HSSPI
+ tristate "Broadcom BCM63XX HS SPI controller driver"
+ depends on BCM63XX
+ help
+ This enables support for the High Speed SPI controller present on
+ newer Broadcom BCM63XX SoCs.
+
config SPI_BITBANG
tristate "Utilities for Bitbanging SPI masters"
help
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
+obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o
obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
--- /dev/null
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -0,0 +1,427 @@
+/*
+ * Broadcom BCM63XX High Speed SPI Controller driver
+ *
+ * Copyright 2000-2010 Broadcom Corporation
+ * Copyright 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+
+#include <bcm63xx_regs.h>
+#include <bcm63xx_dev_hsspi.h>
+
+#define HSSPI_OP_CODE_SHIFT 13
+#define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_WRITE (2 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_READ (3 << HSSPI_OP_CODE_SHIFT)
+
+#define HSSPI_MAX_PREPEND_LEN 15
+
+#define HSSPI_MAX_SYNC_CLOCK 30000000
+
+struct bcm63xx_hsspi {
+ struct completion done;
+ struct spi_transfer *curr_trans;
+
+ struct platform_device *pdev;
+ struct clk *clk;
+ void __iomem *regs;
+ u8 __iomem *fifo;
+
+ u32 speed_hz;
+ int irq;
+};
+
+static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, int hz,
+ int profile)
+{
+ u32 reg;
+
+ reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
+ bcm_hsspi_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
+ HSSPI_PROFILE_CLK_CTRL_REG(profile));
+
+ reg = bcm_hsspi_readl(HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
+ if (hz > HSSPI_MAX_SYNC_CLOCK)
+ reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
+ else
+ reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
+ bcm_hsspi_writel(reg, HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
+}
+
+static int bcm63xx_hsspi_do_txrx(struct spi_device *spi,
+ struct spi_transfer *t1,
+ struct spi_transfer *t2)
+{
+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
+ u8 chip_select = spi->chip_select;
+ u16 opcode = 0;
+ int len, prepend_size = 0;
+
+ init_completion(&bs->done);
+
+ bs->curr_trans = t2 ? t2 : t1;
+ bcm63xx_hsspi_set_clk(bs, bs->curr_trans->speed_hz, chip_select);
+
+ if (t2 && !t2->tx_buf)
+ prepend_size = t1->len;
+
+ bcm_hsspi_writel(prepend_size << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
+ 2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
+ 2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
+ HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
+
+ if (t1->rx_buf && t1->tx_buf)
+ opcode = HSSPI_OP_READ_WRITE;
+ else if (t1->rx_buf || (t2 && t2->rx_buf))
+ opcode = HSSPI_OP_READ;
+ else if (t1->tx_buf)
+ opcode = HSSPI_OP_WRITE;
+
+ if (opcode == HSSPI_OP_READ && t2)
+ len = t2->len;
+ else
+ len = t1->len;
+
+ if (t1->tx_buf) {
+ memcpy_toio(bs->fifo + 2, t1->tx_buf, t1->len);
+ if (t2 && t2->tx_buf) {
+ memcpy_toio(bs->fifo + 2 + t1->len,
+ t2->tx_buf, t2->len);
+ len += t2->len;
+ }
+ }
+
+ opcode |= len;
+ memcpy_toio(bs->fifo, &opcode, sizeof(opcode));
+
+ /* enable interrupt */
+ bcm_hsspi_writel(HSSPI_PING0_CMD_DONE, HSSPI_INT_MASK_REG);
+
+ /* start the transfer */
+ bcm_hsspi_writel(chip_select << PINGPONG_CMD_SS_SHIFT |
+ chip_select << PINGPONG_CMD_PROFILE_SHIFT |
+ PINGPONG_COMMAND_START_NOW,
+ HSSPI_PINGPONG_COMMAND_REG(0));
+
+ if (wait_for_completion_timeout(&bs->done, HZ) == 0) {
+ dev_err(&bs->pdev->dev, "transfer timed out!\n");
+ return -ETIMEDOUT;
+ }
+
+ return t1->len + (t2 ? t2->len : 0);
+}
+
+static int bcm63xx_hsspi_setup(struct spi_device *spi)
+{
+ u32 reg;
+
+ if (spi->bits_per_word != 8)
+ return -EINVAL;
+
+ if (spi->max_speed_hz == 0)
+ return -EINVAL;
+
+ reg = bcm_hsspi_readl(HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
+ reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
+ if (spi->mode & SPI_CPHA)
+ reg |= SIGNAL_CTRL_LAUNCH_RISING;
+ else
+ reg |= SIGNAL_CTRL_LATCH_RISING;
+ bcm_hsspi_writel(reg, HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
+
+ return 0;
+}
+
+static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
+ struct spi_message *msg)
+{
+ struct spi_transfer *t, *prev = NULL;
+ struct spi_device *spi = msg->spi;
+ u32 reg;
+ int ret = -EINVAL;
+ int len = 0;
+
+ /* check if we are able to make these transfers */
+ list_for_each_entry(t, &msg->transfers, transfer_list) {
+ if (!t->tx_buf && !t->rx_buf)
+ goto out;
+
+ if (t->speed_hz == 0)
+ t->speed_hz = spi->max_speed_hz;
+
+ if (t->speed_hz > spi->max_speed_hz)
+ goto out;
+
+ if (t->len > HSSPI_BUFFER_LEN)
+ goto out;
+
+ /*
+ * This controller does not support keeping the chip select
+ * active between transfers.
+ * This logic currently supports combining:
+ * write then read with no cs_change (e.g. m25p80 RDSR)
+ * write then write with no cs_change (e.g. m25p80 PP)
+ */
+ if (prev && prev->tx_buf && !prev->cs_change && !t->cs_change) {
+ /*
+ * reject if we have to combine two tx transfers and
+ * their combined length is bigger than the buffer
+ */
+ if (prev->tx_buf && t->tx_buf &&
+ (prev->len + t->len) > HSSPI_BUFFER_LEN)
+ goto out;
+ /*
+ * reject if we need write more than 15 bytes in read
+ * then write.
+ */
+ if (prev->tx_buf && t->rx_buf &&
+ prev->len > HSSPI_MAX_PREPEND_LEN)
+ goto out;
+ }
+
+ }
+
+ /* setup clock polarity */
+ reg = bcm_hsspi_readl(HSSPI_GLOBAL_CTRL_REG);
+ reg &= ~GLOBAL_CTRL_CLK_POLARITY;
+ if (spi->mode & SPI_CPOL)
+ reg |= GLOBAL_CTRL_CLK_POLARITY;
+ bcm_hsspi_writel(reg, HSSPI_GLOBAL_CTRL_REG);
+
+ list_for_each_entry(t, &msg->transfers, transfer_list) {
+ if (prev && prev->tx_buf && !prev->cs_change && !t->cs_change) {
+ /* combine write with following transfer */
+ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, t);
+ if (ret < 0)
+ goto out;
+
+ len += ret;
+ prev = NULL;
+ continue;
+ }
+
+ /* write the previous pending transfer */
+ if (prev != NULL) {
+ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, NULL);
+ if (ret < 0)
+ goto out;
+
+ len += ret;
+ }
+
+ prev = t;
+ }
+
+ /* do last pending transfer */
+ if (prev != NULL) {
+ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, NULL);
+ if (ret < 0)
+ goto out;
+ len += ret;
+ }
+
+ msg->actual_length = len;
+ ret = 0;
+out:
+ msg->status = ret;
+ spi_finalize_current_message(master);
+ return 0;
+}
+
+static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
+{
+ struct spi_master *master = (struct spi_master *)dev_id;
+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+ if (bcm_hsspi_readl(HSSPI_INT_STATUS_MASKED_REG) == 0)
+ return IRQ_NONE;
+
+ bcm_hsspi_writel(HSSPI_INT_CLEAR_ALL, HSSPI_INT_STATUS_REG);
+ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
+
+ if (bs->curr_trans && bs->curr_trans->rx_buf)
+ memcpy_fromio(bs->curr_trans->rx_buf, bs->fifo,
+ bs->curr_trans->len);
+ complete(&bs->done);
+
+ return IRQ_HANDLED;
+}
+
+static int bcm63xx_hsspi_probe(struct platform_device *pdev)
+{
+
+ struct spi_master *master;
+ struct bcm63xx_hsspi *bs;
+ struct resource *res_mem;
+ void __iomem *regs;
+ struct device *dev = &pdev->dev;
+ struct bcm63xx_hsspi_pdata *pdata = pdev->dev.platform_data;
+ struct clk *clk;
+ int irq;
+ int ret;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq\n");
+ return -ENXIO;
+ }
+
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ regs = devm_request_and_ioremap(dev, res_mem);
+ if (!regs) {
+ dev_err(dev, "unable to ioremap regs\n");
+ return -ENXIO;
+ }
+
+ clk = clk_get(dev, "hsspi");
+
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto out_release;
+ }
+
+ clk_prepare_enable(clk);
+
+ master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+ if (!master) {
+ ret = -ENOMEM;
+ goto out_disable_clk;
+ }
+
+ bs = spi_master_get_devdata(master);
+ bs->pdev = pdev;
+ bs->clk = clk;
+ bs->regs = regs;
+
+ master->bus_num = pdata->bus_num;
+ master->num_chipselect = 8;
+ master->setup = bcm63xx_hsspi_setup;
+ master->transfer_one_message = bcm63xx_hsspi_transfer_one;
+ master->mode_bits = SPI_CPOL | SPI_CPHA;
+
+ bs->speed_hz = pdata->speed_hz;
+ bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
+
+ platform_set_drvdata(pdev, master);
+
+ bs->curr_trans = NULL;
+
+ /* Initialize the hardware */
+ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
+
+ /* clean up any pending interrupts */
+ bcm_hsspi_writel(HSSPI_INT_CLEAR_ALL, HSSPI_INT_STATUS_REG);
+
+ bcm_hsspi_writel(bcm_hsspi_readl(HSSPI_GLOBAL_CTRL_REG) |
+ GLOBAL_CTRL_CLK_GATE_SSOFF,
+ HSSPI_GLOBAL_CTRL_REG);
+
+ ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
+ pdev->name, master);
+
+ if (ret)
+ goto out_put_master;
+
+ /* register and we are done */
+ ret = spi_register_master(master);
+ if (ret)
+ goto out_free_irq;
+
+ return 0;
+
+out_free_irq:
+ devm_free_irq(dev, bs->irq, master);
+out_put_master:
+ spi_master_put(master);
+out_disable_clk:
+ clk_disable_unprepare(clk);
+ clk_put(clk);
+out_release:
+ devm_ioremap_release(dev, regs);
+
+ return ret;
+}
+
+
+static int __exit bcm63xx_hsspi_remove(struct platform_device *pdev)
+{
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+ spi_unregister_master(master);
+
+ /* reset the hardware and block queue progress */
+ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
+ clk_disable_unprepare(bs->clk);
+ clk_put(bs->clk);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int bcm63xx_hsspi_suspend(struct platform_device *pdev,
+ pm_message_t mesg)
+{
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+ spi_master_suspend(master);
+ clk_disable(bs->clk);
+
+ return 0;
+}
+
+static int bcm63xx_hsspi_resume(struct platform_device *pdev)
+{
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+ clk_enable(bs->clk);
+ spi_master_resume(master);
+
+ return 0;
+}
+
+static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = {
+ .suspend = bcm63xx_hsspi_suspend,
+ .resume = bcm63xx_hsspi_resume,
+};
+
+#define BCM63XX_HSSPI_PM_OPS (&bcm63xx_hsspi_pm_ops)
+#else
+#define BCM63XX_HSSPI_PM_OPS NULL
+#endif
+
+
+
+static struct platform_driver bcm63xx_hsspi_driver = {
+ .driver = {
+ .name = "bcm63xx-hsspi",
+ .owner = THIS_MODULE,
+ .pm = BCM63XX_HSSPI_PM_OPS,
+ },
+ .probe = bcm63xx_hsspi_probe,
+ .remove = __exit_p(bcm63xx_hsspi_remove),
+};
+
+module_platform_driver(bcm63xx_hsspi_driver);
+
+MODULE_ALIAS("platform:bcm63xx_hsspi");
+MODULE_DESCRIPTION("Broadcom BCM63xx HS SPI Controller driver");
+MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com>");
+MODULE_LICENSE("GPL");

View file

@ -0,0 +1,104 @@
From d135d94b3d1fe599d13e7198d5f502912d694c13 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sun, 3 Jul 2011 15:00:38 +0200
Subject: [PATCH 29/60] MIPS: BCM63XX: Register SPI flash if present
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
arch/mips/bcm63xx/dev-flash.c | 33 +++++++++++++++++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 +
2 files changed, 33 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -16,9 +16,12 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_flash.h>
+#include <bcm63xx_dev_hsspi.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
@@ -55,6 +58,21 @@ static struct platform_device mtd_dev =
},
};
+static struct flash_platform_data bcm63xx_flash_data = {
+ .part_probe_types = bcm63xx_part_types,
+};
+
+static struct spi_board_info bcm63xx_spi_flash_info[] = {
+ {
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = 0,
+ .max_speed_hz = 781000,
+ .modalias = "m25p80",
+ .platform_data = &bcm63xx_flash_data,
+ },
+};
+
static int __init bcm63xx_detect_flash_type(void)
{
u32 val;
@@ -62,6 +80,11 @@ static int __init bcm63xx_detect_flash_t
switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
+ if (val & STRAPBUS_6328_HSSPI_CLK_FAST)
+ bcm63xx_spi_flash_info[0].max_speed_hz = 33333334;
+ else
+ bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
+
if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
@@ -86,6 +109,9 @@ static int __init bcm63xx_detect_flash_t
return BCM63XX_FLASH_TYPE_NAND;
case BCM6368_CPU_ID:
val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
+ if (val & STRAPBUS_6368_SPI_CLK_FAST)
+ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
+
switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
case STRAPBUS_6368_BOOT_SEL_NAND:
return BCM63XX_FLASH_TYPE_NAND;
@@ -117,8 +143,13 @@ int __init bcm63xx_flash_register(void)
return platform_device_register(&mtd_dev);
case BCM63XX_FLASH_TYPE_SERIAL:
- pr_warn("unsupported serial flash detected\n");
- return -ENODEV;
+ if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
+ bcm63xx_spi_flash_info[0].bus_num = 1;
+ bcm63xx_flash_data.max_transfer_len = HSSPI_BUFFER_LEN;
+ }
+
+ return spi_register_board_info(bcm63xx_spi_flash_info,
+ ARRAY_SIZE(bcm63xx_spi_flash_info));
case BCM63XX_FLASH_TYPE_NAND:
pr_warn("unsupported NAND flash detected\n");
return -ENODEV;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -672,6 +672,7 @@
#define GPIO_STRAPBUS_REG 0x40
#define STRAPBUS_6358_BOOT_SEL_PARALLEL (1 << 1)
#define STRAPBUS_6358_BOOT_SEL_SERIAL (0 << 1)
+#define STRAPBUS_6368_SPI_CLK_FAST (1 << 6)
#define STRAPBUS_6368_BOOT_SEL_MASK 0x3
#define STRAPBUS_6368_BOOT_SEL_NAND 0
#define STRAPBUS_6368_BOOT_SEL_SERIAL 1
@@ -1513,6 +1514,7 @@
#define STRAPBUS_6362_BOOT_SEL_NAND (0 << 15)
#define MISC_STRAPBUS_6328_REG 0x240
+#define STRAPBUS_6328_HSSPI_CLK_FAST (1 << 4)
#define STRAPBUS_6328_FCVO_SHIFT 7
#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
#define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)

View file

@ -0,0 +1,41 @@
From 266c506f4b262bd6aba0776a03d82c98e65d9906 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Tue, 1 May 2012 17:32:36 +0200
Subject: [PATCH 63/79] MTD: physmap: allow passing pp_data
---
drivers/mtd/maps/physmap.c | 4 +++-
include/linux/mtd/physmap.h | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -97,6 +97,7 @@ static int physmap_flash_probe(struct pl
{
struct physmap_flash_data *physmap_data;
struct physmap_flash_info *info;
+ struct mtd_part_parser_data *pp_data;
const char * const *probe_type;
const char * const *part_types;
int err = 0;
@@ -188,8 +189,9 @@ static int physmap_flash_probe(struct pl
spin_lock_init(&info->vpp_lock);
part_types = physmap_data->part_probe_types ? : part_probe_types;
+ pp_data = physmap_data->pp_data ? physmap_data->pp_data : NULL;
- mtd_device_parse_register(info->cmtd, part_types, NULL,
+ mtd_device_parse_register(info->cmtd, part_types, pp_data,
physmap_data->parts, physmap_data->nr_parts);
return 0;
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -32,6 +32,7 @@ struct physmap_flash_data {
char *probe_type;
struct mtd_partition *parts;
const char * const *part_probe_types;
+ struct mtd_part_parser_data *pp_data;
};
#endif /* __LINUX_MTD_PHYSMAP__ */

View file

@ -0,0 +1,81 @@
From 8879e209111192c5e9752d7bd203cf7582693328 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Thu, 3 May 2012 14:40:03 +0200
Subject: [PATCH 58/72] BCM63XX: allow providing fixup data in board data
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 9 ++++++++-
arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 10 ++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -33,6 +33,7 @@
#include <bcm63xx_dev_usb_ohci.h>
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
+#include <pci_ath9k_fixup.h>
#include <uapi/linux/bcm933xx_hcs.h>
#include <uapi/linux/bcm963xx_tag.h>
@@ -958,6 +959,7 @@ int __init board_register_devices(void)
{
int button_count = 0;
int led_count = 0;
+ int i;
if (board.has_uart0)
bcm63xx_uart_register(0);
@@ -996,7 +998,8 @@ int __init board_register_devices(void)
* do this after registering enet devices
*/
#ifdef CONFIG_SSB_PCIHOST
- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ if (!board.has_caldata &&
+ !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(
@@ -1042,5 +1045,9 @@ int __init board_register_devices(void)
platform_device_register(&bcm63xx_gpio_keys_device);
}
+ /* register any fixups */
+ for (i = 0; i < board.has_caldata; i++)
+ pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset);
+
return 0;
}
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -8,6 +8,7 @@
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_usb_usbd.h>
#include <bcm63xx_dev_dsp.h>
+#include <pci_ath9k_fixup.h>
/*
* flash mapping
@@ -15,6 +16,11 @@
#define BCM963XX_CFE_VERSION_OFFSET 0x570
#define BCM963XX_NVRAM_OFFSET 0x580
+struct ath9k_caldata {
+ unsigned int slot;
+ u32 caldata_offset;
+};
+
/*
* board definition
*/
@@ -34,6 +40,10 @@ struct board_info {
unsigned int has_dsp:1;
unsigned int has_uart0:1;
unsigned int has_uart1:1;
+ unsigned int has_caldata:2;
+
+ /* wifi calibration data config */
+ struct ath9k_caldata caldata[2];
/* ethernet config */
struct bcm63xx_enet_platform_data enet0;

View file

@ -0,0 +1,40 @@
From 7f17dfe9009beb07a3de0e380932a725293829df Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Tue, 1 May 2012 17:33:03 +0200
Subject: [PATCH 64/79] MTD: m25p80: allow passing pp_data
---
drivers/mtd/devices/m25p80.c | 3 +++
include/linux/spi/flash.h | 2 ++
2 files changed, 5 insertions(+)
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -976,6 +976,9 @@ static int m25p_probe(struct spi_device
dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
}
+ if (data && data->pp_data)
+ memcpy(&ppdata, data->pp_data, sizeof(ppdata));
+
info = (void *)id->driver_data;
if (info->jedec_id) {
--- a/include/linux/spi/flash.h
+++ b/include/linux/spi/flash.h
@@ -12,6 +12,7 @@ struct mtd_part_parser_data;
* with chips that can't be queried for JEDEC or other IDs
* @part_probe_types: optional list of MTD parser names to use for
* partitioning
+ * @pp_data: optional partition parser data.
*
* @max_transfer_len: option maximum read/write length limitation for
* SPI controllers not able to transfer any length commands.
@@ -30,6 +31,7 @@ struct flash_platform_data {
char *type;
const char **part_probe_types;
+ struct mtd_part_parser_data *pp_data;
unsigned int max_transfer_len;
/* we'll likely add more ... use JEDEC IDs, etc */

View file

@ -0,0 +1,119 @@
From f888824d352df894ab721a5ca067b0313500efe7 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Thu, 3 May 2012 12:17:54 +0200
Subject: [PATCH 38/59] MIPS: BCM63XX: store the flash type in global variable
---
arch/mips/bcm63xx/dev-flash.c | 36 +++++++++++++------
.../include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 2 +
2 files changed, 26 insertions(+), 12 deletions(-)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -25,6 +25,8 @@
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
+int bcm63xx_attached_flash = -1;
+
static struct mtd_partition mtd_partitions[] = {
{
.name = "cfe",
@@ -86,27 +88,31 @@ static int __init bcm63xx_detect_flash_t
bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
- return BCM63XX_FLASH_TYPE_SERIAL;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
else
- return BCM63XX_FLASH_TYPE_NAND;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
+ break;
case BCM6338_CPU_ID:
case BCM6345_CPU_ID:
case BCM6348_CPU_ID:
/* no way to auto detect so assume parallel */
- return BCM63XX_FLASH_TYPE_PARALLEL;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
+ break;
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;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
else
- return BCM63XX_FLASH_TYPE_SERIAL;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
+ break;
case BCM6362_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
if (val & STRAPBUS_6362_BOOT_SEL_SERIAL)
- return BCM63XX_FLASH_TYPE_SERIAL;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
else
- return BCM63XX_FLASH_TYPE_NAND;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
+ break;
case BCM6368_CPU_ID:
val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
if (val & STRAPBUS_6368_SPI_CLK_FAST)
@@ -114,25 +120,32 @@ static int __init bcm63xx_detect_flash_t
switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
case STRAPBUS_6368_BOOT_SEL_NAND:
- return BCM63XX_FLASH_TYPE_NAND;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
+ break;
case STRAPBUS_6368_BOOT_SEL_SERIAL:
- return BCM63XX_FLASH_TYPE_SERIAL;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
+ break;
case STRAPBUS_6368_BOOT_SEL_PARALLEL:
- return BCM63XX_FLASH_TYPE_PARALLEL;
+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
+ break;
+ default:
+ return -EINVAL;
}
default:
return -EINVAL;
}
+
+ return 0;
}
int __init bcm63xx_flash_register(void)
{
- int flash_type;
u32 val;
- flash_type = bcm63xx_detect_flash_type();
- switch (flash_type) {
+ bcm63xx_detect_flash_type();
+
+ switch (bcm63xx_attached_flash) {
case BCM63XX_FLASH_TYPE_PARALLEL:
/* read base address of boot chip select (0) */
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
@@ -155,7 +168,7 @@ int __init bcm63xx_flash_register(void)
return -ENODEV;
default:
pr_err("flash detection failed for BCM%x: %d\n",
- bcm63xx_get_cpu_id(), flash_type);
+ bcm63xx_get_cpu_id(), bcm63xx_attached_flash);
return -ENODEV;
}
}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
@@ -7,6 +7,8 @@ enum {
BCM63XX_FLASH_TYPE_NAND,
};
+extern int bcm63xx_attached_flash;
+
int __init bcm63xx_flash_register(void);
#endif /* __BCM63XX_FLASH_H */

View file

@ -0,0 +1,227 @@
From bbebbf735a02b6d044ed928978ab4bd5f1833364 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Thu, 3 May 2012 14:36:11 +0200
Subject: [PATCH 61/72] BCM63XX: add a fixup for ath9k devices
---
arch/mips/bcm63xx/Makefile | 3 +-
arch/mips/bcm63xx/pci-ath9k-fixup.c | 190 ++++++++++++++++++++
.../include/asm/mach-bcm63xx/pci_ath9k_fixup.h | 7 +
3 files changed, 199 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/bcm63xx/pci-ath9k-fixup.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -2,7 +2,7 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o
setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
dev-hsspi.o dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o \
dev-wdt.o dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o \
- usb-common.o
+ pci-ath9k-fixup.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/pci-ath9k-fixup.c
@@ -0,0 +1,190 @@
+/*
+ * Broadcom BCM63XX Ath9k EEPROM fixup helper.
+ *
+ * Copytight (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ *
+ * Based on
+ *
+ * Atheros AP94 reference board PCI initialization
+ *
+ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ath9k_platform.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_nvram.h>
+#include <bcm63xx_dev_pci.h>
+#include <bcm63xx_dev_flash.h>
+#include <bcm63xx_dev_hsspi.h>
+#include <pci_ath9k_fixup.h>
+
+struct ath9k_fixup {
+ unsigned slot;
+ u8 mac[ETH_ALEN];
+ struct ath9k_platform_data pdata;
+};
+
+static int ath9k_num_fixups;
+static struct ath9k_fixup ath9k_fixups[2] = {
+ {
+ .slot = 255,
+ .pdata = {
+ .led_pin = -1,
+ },
+ },
+ {
+ .slot = 255,
+ .pdata = {
+ .led_pin = -1,
+ },
+ },
+};
+
+static u16 *bcm63xx_read_eeprom(u16 *eeprom, u32 offset)
+{
+ u32 addr;
+
+ if (BCMCPU_IS_6328()) {
+ addr = 0x18000000;
+ } else {
+ addr = bcm_mpi_readl(MPI_CSBASE_REG(0));
+ addr &= MPI_CSBASE_BASE_MASK;
+ }
+
+ switch (bcm63xx_attached_flash) {
+ case BCM63XX_FLASH_TYPE_PARALLEL:
+ memcpy(eeprom, (void *)KSEG1ADDR(addr + offset), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
+ return eeprom;
+ case BCM63XX_FLASH_TYPE_SERIAL:
+ /* the first megabyte is memory mapped */
+ if (offset < 0x100000) {
+ memcpy(eeprom, (void *)KSEG1ADDR(addr + offset), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
+ return eeprom;
+ }
+
+ if (BCMCPU_IS_6328()) {
+ /* we can change the memory mapped megabyte */
+ bcm_hsspi_writel(offset & 0xf00000, 0x18);
+ memcpy(eeprom, (void *)KSEG1ADDR(addr + (offset & 0xfffff)), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
+ bcm_hsspi_writel(0, 0x18);
+ return eeprom;
+ }
+ /* can't do anything here without talking to the SPI controller. */
+ case BCM63XX_FLASH_TYPE_NAND:
+ default:
+ return NULL;
+ }
+}
+
+static void ath9k_pci_fixup(struct pci_dev *dev)
+{
+ void __iomem *mem;
+ struct ath9k_platform_data *pdata = NULL;
+ u16 *cal_data = NULL;
+ u16 cmd;
+ u32 bar0;
+ u32 val;
+ unsigned i;
+
+ for (i = 0; i < ath9k_num_fixups; i++) {
+ if (ath9k_fixups[i].slot != PCI_SLOT(dev->devfn))
+ continue;
+
+ cal_data = ath9k_fixups[i].pdata.eeprom_data;
+ pdata = &ath9k_fixups[i].pdata;
+ break;
+ }
+
+ if (cal_data == NULL)
+ return;
+
+ if (*cal_data != 0xa55a) {
+ pr_err("pci %s: invalid calibration data\n", pci_name(dev));
+ return;
+ }
+
+ pr_info("pci %s: fixup device configuration\n", pci_name(dev));
+
+ switch (bcm63xx_get_cpu_id()) {
+ case BCM6328_CPU_ID:
+ val = BCM_PCIE_MEM_BASE_PA;
+ break;
+ case BCM6348_CPU_ID:
+ case BCM6358_CPU_ID:
+ case BCM6368_CPU_ID:
+ val = BCM_PCI_MEM_BASE_PA;
+ break;
+ default:
+ BUG();
+ }
+
+ mem = ioremap(val, 0x10000);
+ if (!mem) {
+ pr_err("pci %s: ioremap error\n", pci_name(dev));
+ return;
+ }
+
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, val);
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+ /* set offset to first reg address */
+ cal_data += 3;
+ while(*cal_data != 0xffff) {
+ u32 reg;
+ reg = *cal_data++;
+ val = *cal_data++;
+ val |= (*cal_data++) << 16;
+
+ writel(val, mem + reg);
+ udelay(100);
+ }
+
+ pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
+ dev->vendor = val & 0xffff;
+ dev->device = (val >> 16) & 0xffff;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
+ dev->revision = val & 0xff;
+ dev->class = val >> 8; /* upper 3 bytes */
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
+
+ iounmap(mem);
+
+ dev->dev.platform_data = pdata;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
+
+void __init pci_enable_ath9k_fixup(unsigned slot, u32 offset)
+{
+ if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups))
+ return;
+
+ ath9k_fixups[ath9k_num_fixups].slot = slot;
+
+ if (!bcm63xx_read_eeprom(ath9k_fixups[ath9k_num_fixups].pdata.eeprom_data, offset))
+ return;
+
+ if (bcm63xx_nvram_get_mac_address(ath9k_fixups[ath9k_num_fixups].mac))
+ return;
+
+ ath9k_fixups[ath9k_num_fixups].pdata.macaddr = ath9k_fixups[ath9k_num_fixups].mac;
+ ath9k_num_fixups++;
+}
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
@@ -0,0 +1,7 @@
+#ifndef _PCI_ATH9K_FIXUP
+#define _PCI_ATH9K_FIXUP
+
+
+void pci_enable_ath9k_fixup(unsigned slot, u32 offset) __init;
+
+#endif /* _PCI_ATH9K_FIXUP */

View file

@ -0,0 +1,120 @@
Allow bcm63xxpart to receive a caldata offset if calibration data is
contained in flash.
---
drivers/mtd/bcm63xxpart.c | 51 ++++++++++++++++++++++++++++++++++++---
include/linux/mtd/partitions.h | 2 +
2 files changed, 49 insertions(+), 4 deletions(-)
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -53,10 +53,12 @@ static int bcm63xx_parse_cfe_partitions(
struct mtd_partition *parts;
int ret;
size_t retlen;
- unsigned int rootfsaddr, kerneladdr, spareaddr;
+ unsigned int rootfsaddr, kerneladdr, spareaddr, nvramaddr;
unsigned int rootfslen, kernellen, sparelen, totallen;
unsigned int cfelen, nvramlen;
unsigned int cfe_erasesize;
+ unsigned int caldatalen1 = 0, caldataaddr1 = 0;
+ unsigned int caldatalen2 = 0, caldataaddr2 = 0;
int i;
u32 computed_crc;
bool rootfs_first = false;
@@ -70,6 +72,24 @@ static int bcm63xx_parse_cfe_partitions(
cfelen = cfe_erasesize;
nvramlen = bcm63xx_nvram_get_psi_size();
nvramlen = roundup(nvramlen, cfe_erasesize);
+ nvramaddr = master->size - nvramlen;
+
+ if (data) {
+ if (data->caldata[0]) {
+ caldatalen1 = cfe_erasesize;
+ caldataaddr1 = rounddown(data->caldata[0],
+ cfe_erasesize);
+ }
+ if (data->caldata[1]) {
+ caldatalen2 = cfe_erasesize;
+ caldataaddr2 = rounddown(data->caldata[1],
+ cfe_erasesize);
+ }
+ if (caldataaddr1 == caldataaddr2) {
+ caldataaddr2 = 0;
+ caldatalen2 = 0;
+ }
+ }
/* Allocate memory for buffer */
buf = vmalloc(sizeof(struct bcm_tag));
@@ -121,7 +141,7 @@ static int bcm63xx_parse_cfe_partitions(
rootfsaddr = 0;
spareaddr = cfelen;
}
- sparelen = master->size - spareaddr - nvramlen;
+ sparelen = min_not_zero(nvramaddr, caldataaddr1) - spareaddr;
/* Determine number of partitions */
if (rootfslen > 0)
@@ -130,6 +150,12 @@ static int bcm63xx_parse_cfe_partitions(
if (kernellen > 0)
nrparts++;
+ if (caldatalen1 > 0)
+ nrparts++;
+
+ if (caldatalen2 > 0)
+ nrparts++;
+
/* Ask kernel for more memory */
parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
if (!parts) {
@@ -167,15 +193,32 @@ static int bcm63xx_parse_cfe_partitions(
curpart++;
}
+ if (caldatalen1 > 0) {
+ if (caldatalen2 > 0)
+ parts[curpart].name = "cal_data1";
+ else
+ parts[curpart].name = "cal_data";
+ parts[curpart].offset = caldataaddr1;
+ parts[curpart].size = caldatalen1;
+ curpart++;
+ }
+
+ if (caldatalen2 > 0) {
+ parts[curpart].name = "cal_data2";
+ parts[curpart].offset = caldataaddr2;
+ parts[curpart].size = caldatalen2;
+ curpart++;
+ }
+
parts[curpart].name = "nvram";
- parts[curpart].offset = master->size - nvramlen;
+ parts[curpart].offset = nvramaddr;
parts[curpart].size = nvramlen;
curpart++;
/* Global partition "linux" to make easy firmware upgrade */
parts[curpart].name = "linux";
parts[curpart].offset = cfelen;
- parts[curpart].size = master->size - cfelen - nvramlen;
+ parts[curpart].size = min_not_zero(nvramaddr, caldataaddr1) - cfelen;
for (i = 0; i < nrparts; i++)
pr_info("Partition %d is %s offset %llx and length %llx\n", i,
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -56,10 +56,12 @@ struct device_node;
/**
* struct mtd_part_parser_data - used to pass data to MTD partition parsers.
* @origin: for RedBoot, start address of MTD device
+ * @caldata: for CFE, start address of wifi calibration data
* @of_node: for OF parsers, device node containing partitioning information
*/
struct mtd_part_parser_data {
unsigned long origin;
+ unsigned long caldata[2];
struct device_node *of_node;
};

View file

@ -0,0 +1,82 @@
From 977f8a30103b9c4992cab8f49357fe0d4274004f Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Thu, 3 May 2012 14:55:26 +0200
Subject: [PATCH 69/80] MIPS: BCM63XX: pass caldata info to flash
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
arch/mips/bcm63xx/dev-flash.c | 9 ++++++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 4 +++-
3 files changed, 12 insertions(+), 3 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -1017,7 +1017,7 @@ int __init board_register_devices(void)
if (board.num_spis)
spi_register_board_info(board.spis, board.num_spis);
- bcm63xx_flash_register();
+ bcm63xx_flash_register(board.has_caldata, board.caldata);
/* count number of LEDs defined by this device */
while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -35,12 +35,15 @@ static struct mtd_partition mtd_partitio
}
};
+static struct mtd_part_parser_data bcm63xx_parser_data;
+
static const char *bcm63xx_part_types[] = { "bcm63xxpart", "RedBoot", NULL };
static struct physmap_flash_data flash_data = {
.width = 2,
.parts = mtd_partitions,
.part_probe_types = bcm63xx_part_types,
+ .pp_data = &bcm63xx_parser_data,
};
static struct resource mtd_resources[] = {
@@ -62,6 +65,7 @@ static struct platform_device mtd_dev =
static struct flash_platform_data bcm63xx_flash_data = {
.part_probe_types = bcm63xx_part_types,
+ .pp_data = &bcm63xx_parser_data,
};
static struct spi_board_info bcm63xx_spi_flash_info[] = {
@@ -138,10 +142,13 @@ static int __init bcm63xx_detect_flash_t
return 0;
}
-int __init bcm63xx_flash_register(void)
+int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata)
{
u32 val;
+ unsigned int i;
+ for (i = 0; i < num_caldata; i++)
+ bcm63xx_parser_data.caldata[i] = caldata[i].caldata_offset;
bcm63xx_detect_flash_type();
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
@@ -1,6 +1,8 @@
#ifndef __BCM63XX_FLASH_H
#define __BCM63XX_FLASH_H
+#include <board_bcm963xx.h>
+
enum {
BCM63XX_FLASH_TYPE_PARALLEL,
BCM63XX_FLASH_TYPE_SERIAL,
@@ -9,6 +11,6 @@ enum {
extern int bcm63xx_attached_flash;
-int __init bcm63xx_flash_register(void);
+int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata);
#endif /* __BCM63XX_FLASH_H */

View file

@ -0,0 +1,51 @@
--- a/arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
+++ b/arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
@@ -2,6 +2,7 @@
#define _PCI_ATH9K_FIXUP
-void pci_enable_ath9k_fixup(unsigned slot, u32 offset) __init;
+void pci_enable_ath9k_fixup(unsigned slot, u32 offset,
+ unsigned endian_check) __init;
#endif /* _PCI_ATH9K_FIXUP */
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -19,6 +19,7 @@
struct ath9k_caldata {
unsigned int slot;
u32 caldata_offset;
+ unsigned int endian_check:1;
};
/*
--- a/arch/mips/bcm63xx/pci-ath9k-fixup.c
+++ b/arch/mips/bcm63xx/pci-ath9k-fixup.c
@@ -172,12 +172,14 @@ static void ath9k_pci_fixup(struct pci_d
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
-void __init pci_enable_ath9k_fixup(unsigned slot, u32 offset)
+void __init pci_enable_ath9k_fixup(unsigned slot, u32 offset,
+ unsigned endian_check)
{
if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups))
return;
ath9k_fixups[ath9k_num_fixups].slot = slot;
+ ath9k_fixups[ath9k_num_fixups].pdata.endian_check = endian_check;
if (!bcm63xx_read_eeprom(ath9k_fixups[ath9k_num_fixups].pdata.eeprom_data, offset))
return;
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -1047,7 +1047,8 @@ int __init board_register_devices(void)
/* register any fixups */
for (i = 0; i < board.has_caldata; i++)
- pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset);
+ pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset,
+ board.caldata[i].endian_check);
return 0;
}

View file

@ -0,0 +1,49 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -1048,7 +1048,7 @@ int __init board_register_devices(void)
/* register any fixups */
for (i = 0; i < board.has_caldata; i++)
pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset,
- board.caldata[i].endian_check);
+ board.caldata[i].endian_check, board.caldata[i].led_pin);
return 0;
}
--- a/arch/mips/bcm63xx/pci-ath9k-fixup.c
+++ b/arch/mips/bcm63xx/pci-ath9k-fixup.c
@@ -173,13 +173,14 @@ static void ath9k_pci_fixup(struct pci_d
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
void __init pci_enable_ath9k_fixup(unsigned slot, u32 offset,
- unsigned endian_check)
+ unsigned endian_check, int led_pin)
{
if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups))
return;
ath9k_fixups[ath9k_num_fixups].slot = slot;
ath9k_fixups[ath9k_num_fixups].pdata.endian_check = endian_check;
+ ath9k_fixups[ath9k_num_fixups].pdata.led_pin = led_pin;
if (!bcm63xx_read_eeprom(ath9k_fixups[ath9k_num_fixups].pdata.eeprom_data, offset))
return;
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -20,6 +20,7 @@ struct ath9k_caldata {
unsigned int slot;
u32 caldata_offset;
unsigned int endian_check:1;
+ int led_pin;
};
/*
--- a/arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
+++ b/arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
@@ -3,6 +3,6 @@
void pci_enable_ath9k_fixup(unsigned slot, u32 offset,
- unsigned endian_check) __init;
+ unsigned endian_check, int led_pin) __init;
#endif /* _PCI_ATH9K_FIXUP */

View file

@ -0,0 +1,205 @@
From 5ed5b5e9614fa5b02da699ab565af76c7e63d64d Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Mon, 7 Jan 2013 17:45:39 +0100
Subject: [PATCH 72/72] 446-BCM63XX-add-a-fixup-for-rt2x00-devices
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/boards/board_bcm963xx.c | 17 ++++-
arch/mips/bcm63xx/dev-flash.c | 2 +-
arch/mips/bcm63xx/pci-rt2x00-fixup.c | 71 ++++++++++++++++++++
.../include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 2 +-
.../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 9 ++-
.../include/asm/mach-bcm63xx/pci_rt2x00_fixup.h | 9 +++
7 files changed, 104 insertions(+), 8 deletions(-)
create mode 100644 arch/mips/bcm63xx/pci-rt2x00-fixup.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/pci_rt2x00_fixup.h
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -2,7 +2,7 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o
setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
dev-hsspi.o dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o \
dev-wdt.o dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o \
- pci-ath9k-fixup.o usb-common.o
+ pci-ath9k-fixup.o pci-rt2x00-fixup.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -34,6 +34,7 @@
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
#include <pci_ath9k_fixup.h>
+#include <pci_rt2x00_fixup.h>
#include <uapi/linux/bcm933xx_hcs.h>
#include <uapi/linux/bcm963xx_tag.h>
@@ -1046,9 +1047,19 @@ int __init board_register_devices(void)
}
/* register any fixups */
- for (i = 0; i < board.has_caldata; i++)
- pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset,
- board.caldata[i].endian_check, board.caldata[i].led_pin);
+ for (i = 0; i < board.has_caldata; i++) {
+ switch (board.caldata[i].vendor) {
+ case PCI_VENDOR_ID_ATHEROS:
+ pci_enable_ath9k_fixup(board.caldata[i].slot,
+ board.caldata[i].caldata_offset, board.caldata[i].endian_check,
+ board.caldata[i].led_pin);
+ break;
+ case PCI_VENDOR_ID_RALINK:
+ pci_enable_rt2x00_fixup(board.caldata[i].slot,
+ board.caldata[i].eeprom);
+ break;
+ }
+ }
return 0;
}
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -142,7 +142,7 @@ static int __init bcm63xx_detect_flash_t
return 0;
}
-int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata)
+int __init bcm63xx_flash_register(int num_caldata, struct bcm63xx_caldata *caldata)
{
u32 val;
unsigned int i;
--- /dev/null
+++ b/arch/mips/bcm63xx/pci-rt2x00-fixup.c
@@ -0,0 +1,72 @@
+/*
+ * Broadcom BCM63XX RT2x00 EEPROM fixup helper.
+ *
+ * Copyright (C) 2012 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Based on
+ *
+ * Broadcom BCM63XX Ath9k EEPROM fixup helper.
+ *
+ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/if_ether.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/rt2x00_platform.h>
+
+#include <bcm63xx_nvram.h>
+#include <pci_rt2x00_fixup.h>
+
+struct rt2x00_fixup {
+ unsigned slot;
+ u8 mac[ETH_ALEN];
+ struct rt2x00_platform_data pdata;
+};
+
+static int rt2x00_num_fixups;
+static struct rt2x00_fixup rt2x00_fixups[2] = {
+ {
+ .slot = 255,
+ },
+ {
+ .slot = 255,
+ },
+};
+
+static void rt2x00_pci_fixup(struct pci_dev *dev)
+{
+ unsigned i;
+ struct rt2x00_platform_data *pdata = NULL;
+
+ for (i = 0; i < rt2x00_num_fixups; i++) {
+ if (rt2x00_fixups[i].slot != PCI_SLOT(dev->devfn))
+ continue;
+
+ pdata = &rt2x00_fixups[i].pdata;
+ break;
+ }
+
+ dev->dev.platform_data = pdata;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RALINK, PCI_ANY_ID, rt2x00_pci_fixup);
+
+void __init pci_enable_rt2x00_fixup(unsigned slot, char* eeprom)
+{
+ if (rt2x00_num_fixups >= ARRAY_SIZE(rt2x00_fixups))
+ return;
+
+ rt2x00_fixups[rt2x00_num_fixups].slot = slot;
+ rt2x00_fixups[rt2x00_num_fixups].pdata.eeprom_file_name = kstrdup(eeprom, GFP_KERNEL);
+
+ if (bcm63xx_nvram_get_mac_address(rt2x00_fixups[rt2x00_num_fixups].mac))
+ return;
+
+ rt2x00_fixups[rt2x00_num_fixups].pdata.mac_address = rt2x00_fixups[rt2x00_num_fixups].mac;
+ rt2x00_num_fixups++;
+}
+
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
@@ -11,6 +11,6 @@ enum {
extern int bcm63xx_attached_flash;
-int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata);
+int __init bcm63xx_flash_register(int num_caldata, struct bcm63xx_caldata *caldata);
#endif /* __BCM63XX_FLASH_H */
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -9,6 +9,7 @@
#include <bcm63xx_dev_usb_usbd.h>
#include <bcm63xx_dev_dsp.h>
#include <pci_ath9k_fixup.h>
+#include <pci_rt2x00_fixup.h>
/*
* flash mapping
@@ -16,11 +17,15 @@
#define BCM963XX_CFE_VERSION_OFFSET 0x570
#define BCM963XX_NVRAM_OFFSET 0x580
-struct ath9k_caldata {
+struct bcm63xx_caldata {
+ unsigned int vendor;
unsigned int slot;
u32 caldata_offset;
+ /* Atheros */
unsigned int endian_check:1;
int led_pin;
+ /* Ralink */
+ char* eeprom;
};
/*
@@ -45,7 +50,7 @@ struct board_info {
unsigned int has_caldata:2;
/* wifi calibration data config */
- struct ath9k_caldata caldata[2];
+ struct bcm63xx_caldata caldata[2];
/* ethernet config */
struct bcm63xx_enet_platform_data enet0;
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/pci_rt2x00_fixup.h
@@ -0,0 +1,9 @@
+#ifndef _PCI_RT2X00_FIXUP
+#define _PCI_RT2X00_FIXUP
+
+#define PCI_VENDOR_ID_RALINK 0x1814
+
+void pci_enable_rt2x00_fixup(unsigned slot, char* eeprom) __init;
+
+#endif /* _PCI_RT2X00_FIXUP */
+

View file

@ -0,0 +1,169 @@
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
@@ -336,6 +336,9 @@ struct bcm_enet_priv {
struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
int sw_port_link[ENETSW_MAX_PORT];
+ /* platform device for associated switch */
+ struct platform_device *b53_device;
+
/* used to poll switch port state */
struct timer_list swphy_poll;
spinlock_t enetsw_mdio_lock;
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -30,6 +30,7 @@
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/if_vlan.h>
+#include <linux/platform_data/b53.h>
#include <bcm63xx_dev_enet.h>
#include "bcm63xx_enet.h"
@@ -1981,7 +1982,8 @@ static int bcm_enet_remove(struct platfo
return 0;
}
-struct platform_driver bcm63xx_enet_driver = {
+
+static struct platform_driver bcm63xx_enet_driver = {
.probe = bcm_enet_probe,
.remove = bcm_enet_remove,
.driver = {
@@ -1990,6 +1992,42 @@ struct platform_driver bcm63xx_enet_driv
},
};
+struct b53_platform_data bcm63xx_b53_pdata = {
+ .chip_id = 0x6300,
+ .big_endian = 1,
+};
+
+struct platform_device bcm63xx_b53_dev = {
+ .name = "b53-switch",
+ .id = -1,
+ .dev = {
+ .platform_data = &bcm63xx_b53_pdata,
+ },
+};
+
+static int bcmenet_switch_register(struct bcm_enet_priv *priv, u16 port_mask)
+{
+ int ret;
+
+ bcm63xx_b53_pdata.regs = priv->base;
+ bcm63xx_b53_pdata.enabled_ports = port_mask;
+ bcm63xx_b53_pdata.alias = priv->net_dev->name;
+
+ ret = platform_device_register(&bcm63xx_b53_dev);
+ if (!ret)
+ priv->b53_device = &bcm63xx_b53_dev;
+
+ return ret;
+}
+
+static void bcmenet_switch_unregister(struct bcm_enet_priv *priv)
+{
+ if (priv->b53_device)
+ platform_device_unregister(&bcm63xx_b53_dev);
+
+ priv->b53_device = NULL;
+}
+
/*
* switch mii access callbacks
*/
@@ -2243,29 +2281,6 @@ static int bcm_enetsw_open(struct net_de
enetsw_writeb(priv, rgmii_ctrl, ENETSW_RGMII_CTRL_REG(i));
}
- /* reset mib */
- val = enetsw_readb(priv, ENETSW_GMCR_REG);
- val |= ENETSW_GMCR_RST_MIB_MASK;
- enetsw_writeb(priv, val, ENETSW_GMCR_REG);
- mdelay(1);
- val &= ~ENETSW_GMCR_RST_MIB_MASK;
- enetsw_writeb(priv, val, ENETSW_GMCR_REG);
- mdelay(1);
-
- /* force CPU port state */
- val = enetsw_readb(priv, ENETSW_IMPOV_REG);
- val |= ENETSW_IMPOV_FORCE_MASK | ENETSW_IMPOV_LINKUP_MASK;
- enetsw_writeb(priv, val, ENETSW_IMPOV_REG);
-
- /* enable switch forward engine */
- val = enetsw_readb(priv, ENETSW_SWMODE_REG);
- val |= ENETSW_SWMODE_FWD_EN_MASK;
- enetsw_writeb(priv, val, ENETSW_SWMODE_REG);
-
- /* enable jumbo on all ports */
- enetsw_writel(priv, 0x1ff, ENETSW_JMBCTL_PORT_REG);
- enetsw_writew(priv, 9728, ENETSW_JMBCTL_MAXSIZE_REG);
-
/* initialize flow control buffer allocation */
enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
ENETDMA_BUFALLOC_REG(priv->rx_chan));
@@ -2725,6 +2740,9 @@ static int bcm_enetsw_probe(struct platf
struct bcm63xx_enetsw_platform_data *pd;
struct resource *res_mem;
int ret, irq_rx, irq_tx;
+ unsigned i, num_ports = 0;
+ u16 port_mask = BIT(8);
+ u8 val;
/* stop if shared driver failed, assume driver->probe will be
* called in the same order we register devices (correct ?)
@@ -2814,6 +2832,43 @@ static int bcm_enetsw_probe(struct platf
priv->pdev = pdev;
priv->net_dev = dev;
+ /* reset mib */
+ val = enetsw_readb(priv, ENETSW_GMCR_REG);
+ val |= ENETSW_GMCR_RST_MIB_MASK;
+ enetsw_writeb(priv, val, ENETSW_GMCR_REG);
+ mdelay(1);
+ val &= ~ENETSW_GMCR_RST_MIB_MASK;
+ enetsw_writeb(priv, val, ENETSW_GMCR_REG);
+ mdelay(1);
+
+ /* force CPU port state */
+ val = enetsw_readb(priv, ENETSW_IMPOV_REG);
+ val |= ENETSW_IMPOV_FORCE_MASK | ENETSW_IMPOV_LINKUP_MASK;
+ enetsw_writeb(priv, val, ENETSW_IMPOV_REG);
+
+ /* enable switch forward engine */
+ val = enetsw_readb(priv, ENETSW_SWMODE_REG);
+ val |= ENETSW_SWMODE_FWD_EN_MASK;
+ enetsw_writeb(priv, val, ENETSW_SWMODE_REG);
+
+ /* enable jumbo on all ports */
+ enetsw_writel(priv, 0x1ff, ENETSW_JMBCTL_PORT_REG);
+ enetsw_writew(priv, 9728, ENETSW_JMBCTL_MAXSIZE_REG);
+
+ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm63xx_enetsw_port *port = &priv->used_ports[i];
+
+ if (!port->used)
+ continue;
+
+ num_ports++;
+ port_mask |= BIT(i);
+ }
+
+ /* only register if there is more than one external port */
+ if (num_ports > 1)
+ bcmenet_switch_register(priv, port_mask);
+
return 0;
out_put_clk:
@@ -2842,6 +2897,9 @@ static int bcm_enetsw_remove(struct plat
priv = netdev_priv(dev);
unregister_netdev(dev);
+ /* remove switch */
+ bcmenet_switch_unregister(priv);
+
/* release device resources */
iounmap(priv->base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

View file

@ -0,0 +1,67 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -555,6 +555,56 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
};
+
+static struct board_info __initdata board_96348_D4PW = {
+ .name = "D-4P-W",
+ .expected_cpu_id = 0x6348,
+
+ .has_enet1 = 1,
+ .has_pci = 1,
+ .has_uart0 = 1,
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .leds = {
+ {
+ .name = "D-4P-W:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ },
+ {
+ .name = "D-4P-W::status",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+ .name = "D-4P-W:green:internet",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "D-4P-W:red:internet",
+ .gpio = 5,
+ .active_low = 1,
+ },
+ },
+
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 7,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
#endif
/*
@@ -732,6 +782,7 @@ static const struct board_info __initcon
&board_DV201AMR,
&board_96348gw_a,
&board_rta1025w_16,
+ &board_96348_D4PW,
#endif
#ifdef CONFIG_BCM63XX_CPU_6358

View file

@ -0,0 +1,650 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -15,6 +15,8 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/74x164.h>
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
@@ -49,6 +51,12 @@
#define CFE_OFFSET_64K 0x10000
#define CFE_OFFSET_128K 0x20000
+#define NB4_PID_OFFSET 0xff80
+#define NB4_74X164_GPIO_BASE 64
+#define NB4_SPI_GPIO_MOSI 7
+#define NB4_SPI_GPIO_CLK 6
+#define NB4_74HC64_GPIO(X) (NB4_74X164_GPIO_BASE + (X))
+
static struct board_info board;
/*
@@ -754,6 +762,596 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
};
+
+struct spi_gpio_platform_data nb4_spi_gpio_data = {
+ .sck = NB4_SPI_GPIO_CLK,
+ .mosi = NB4_SPI_GPIO_MOSI,
+ .miso = SPI_GPIO_NO_MISO,
+ .num_chipselect = 1,
+};
+
+
+static struct platform_device nb4_spi_gpio = {
+ .name = "spi_gpio",
+ .id = 1,
+ .dev = {
+ .platform_data = &nb4_spi_gpio_data,
+ },
+};
+
+static struct platform_device * __initdata nb4_devices[] = {
+ &nb4_spi_gpio,
+};
+
+const struct gen_74x164_chip_platform_data nb4_74x164_platform_data = {
+ .base = NB4_74X164_GPIO_BASE
+};
+
+static struct spi_board_info nb4_spi_devices[] = {
+ {
+ .modalias = "74x164",
+ .max_speed_hz = 781000,
+ .bus_num = 1,
+ .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT,
+ .mode = SPI_MODE_0,
+ .platform_data = &nb4_74x164_platform_data
+ }
+};
+
+static struct board_info __initdata board_nb4_ser_r0 = {
+ .name = "NB4-SER-r0",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+
+ .has_ohci0 = 1,
+ .has_pccard = 1,
+ .has_ehci0 = 1,
+
+ .leds = {
+ {
+ .name = "NB4-SER-r0:white:adsl",
+ .gpio = NB4_74HC64_GPIO(4),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r0:white:traffic",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r0:white:tel",
+ .gpio = NB4_74HC64_GPIO(3),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r0:white:tv",
+ .gpio = NB4_74HC64_GPIO(2),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r0:white:wifi",
+ .gpio = 15,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r0:white:alarm",
+ .gpio = NB4_74HC64_GPIO(0),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r0:red:service",
+ .gpio = 29,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r0:green:service",
+ .gpio = 30,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r0:blue:service",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ },
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 34,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "wps",
+ .gpio = 37,
+ .type = EV_KEY,
+ .code = KEY_WPS_BUTTON,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "service",
+ .gpio = 27,
+ .type = EV_KEY,
+ .code = BTN_0,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "clip",
+ .gpio = 31,
+ .type = EV_KEY,
+ .code = BTN_1,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+ .devs = nb4_devices,
+ .num_devs = ARRAY_SIZE(nb4_devices),
+ .spis = nb4_spi_devices,
+ .num_spis = ARRAY_SIZE(nb4_spi_devices),
+};
+
+static struct board_info __initdata board_nb4_ser_r1 = {
+ .name = "NB4-SER-r1",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+
+ .has_ohci0 = 1,
+ .has_pccard = 1,
+ .has_ehci0 = 1,
+
+ .leds = {
+ {
+ .name = "NB4-SER-r1:white:adsl",
+ .gpio = NB4_74HC64_GPIO(4),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r1:white:traffic",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r1:white:tel",
+ .gpio = NB4_74HC64_GPIO(3),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r1:white:tv",
+ .gpio = NB4_74HC64_GPIO(2),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r1:white:wifi",
+ .gpio = 15,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r1:white:alarm",
+ .gpio = NB4_74HC64_GPIO(0),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r1:red:service",
+ .gpio = 29,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r1:green:service",
+ .gpio = 30,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r1:blue:service",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ },
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 34,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "wps",
+ .gpio = 37,
+ .type = EV_KEY,
+ .code = KEY_WPS_BUTTON,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "service",
+ .gpio = 27,
+ .type = EV_KEY,
+ .code = BTN_0,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "clip",
+ .gpio = 31,
+ .type = EV_KEY,
+ .code = BTN_1,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+ .devs = nb4_devices,
+ .num_devs = ARRAY_SIZE(nb4_devices),
+ .spis = nb4_spi_devices,
+ .num_spis = ARRAY_SIZE(nb4_spi_devices),
+};
+
+static struct board_info __initdata board_nb4_ser_r2 = {
+ .name = "NB4-SER-r2",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+
+ .has_ohci0 = 1,
+ .has_pccard = 1,
+ .has_ehci0 = 1,
+
+ .leds = {
+ {
+ .name = "NB4-SER-r2:white:adsl",
+ .gpio = NB4_74HC64_GPIO(4),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r2:white:traffic",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r2:white:tel",
+ .gpio = NB4_74HC64_GPIO(3),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r2:white:tv",
+ .gpio = NB4_74HC64_GPIO(2),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r2:white:wifi",
+ .gpio = 15,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r2:white:alarm",
+ .gpio = NB4_74HC64_GPIO(0),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r2:red:service",
+ .gpio = 29,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r2:green:service",
+ .gpio = 30,
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-SER-r2:blue:service",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ },
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 34,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "wps",
+ .gpio = 37,
+ .type = EV_KEY,
+ .code = KEY_WPS_BUTTON,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "service",
+ .gpio = 27,
+ .type = EV_KEY,
+ .code = BTN_0,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "clip",
+ .gpio = 31,
+ .type = EV_KEY,
+ .code = BTN_1,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+ .devs = nb4_devices,
+ .num_devs = ARRAY_SIZE(nb4_devices),
+ .spis = nb4_spi_devices,
+ .num_spis = ARRAY_SIZE(nb4_spi_devices),
+};
+
+static struct board_info __initdata board_nb4_fxc_r1 = {
+ .name = "NB4-FXC-r1",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+
+ .has_ohci0 = 1,
+ .has_pccard = 1,
+ .has_ehci0 = 1,
+
+ .leds = {
+ {
+ .name = "NB4-FXC-r1:white:adsl",
+ .gpio = NB4_74HC64_GPIO(4),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-FXC-r1:white:traffic",
+ .gpio = 2,
+ },
+ {
+ .name = "NB4-FXC-r1:white:tel",
+ .gpio = NB4_74HC64_GPIO(3),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-FXC-r1:white:tv",
+ .gpio = NB4_74HC64_GPIO(2),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-FXC-r1:white:wifi",
+ .gpio = 15,
+ },
+ {
+ .name = "NB4-FXC-r1:white:alarm",
+ .gpio = NB4_74HC64_GPIO(0),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-FXC-r1:red:service",
+ .gpio = 29,
+ },
+ {
+ .name = "NB4-FXC-r1:green:service",
+ .gpio = 30,
+ },
+ {
+ .name = "NB4-FXC-r1:blue:service",
+ .gpio = 4,
+ },
+ },
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 34,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "wps",
+ .gpio = 37,
+ .type = EV_KEY,
+ .code = KEY_WPS_BUTTON,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "service",
+ .gpio = 27,
+ .type = EV_KEY,
+ .code = BTN_0,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "clip",
+ .gpio = 31,
+ .type = EV_KEY,
+ .code = BTN_1,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+ .devs = nb4_devices,
+ .num_devs = ARRAY_SIZE(nb4_devices),
+ .spis = nb4_spi_devices,
+ .num_spis = ARRAY_SIZE(nb4_spi_devices),
+};
+
+static struct board_info __initdata board_nb4_fxc_r2 = {
+ .name = "NB4-FXC-r2",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+
+ .has_ohci0 = 1,
+ .has_pccard = 1,
+ .has_ehci0 = 1,
+
+ .leds = {
+ {
+ .name = "NB4-FXC-r2:white:adsl",
+ .gpio = NB4_74HC64_GPIO(4),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-FXC-r2:white:traffic",
+ .gpio = 2,
+ },
+ {
+ .name = "NB4-FXC-r2:white:tel",
+ .gpio = NB4_74HC64_GPIO(3),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-FXC-r2:white:tv",
+ .gpio = NB4_74HC64_GPIO(2),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-FXC-r2:white:wifi",
+ .gpio = 15,
+ },
+ {
+ .name = "NB4-FXC-r2:white:alarm",
+ .gpio = NB4_74HC64_GPIO(0),
+ .active_low = 1,
+ },
+ {
+ .name = "NB4-FXC-r2:red:service",
+ .gpio = 29,
+ },
+ {
+ .name = "NB4-FXC-r2:green:service",
+ .gpio = 30,
+ },
+ {
+ .name = "NB4-FXC-r2:blue:service",
+ .gpio = 4,
+ },
+ },
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 34,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "wps",
+ .gpio = 37,
+ .type = EV_KEY,
+ .code = KEY_WPS_BUTTON,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "service",
+ .gpio = 27,
+ .type = EV_KEY,
+ .code = BTN_0,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "clip",
+ .gpio = 31,
+ .type = EV_KEY,
+ .code = BTN_1,
+ .active_low = 1,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+ .devs = nb4_devices,
+ .num_devs = ARRAY_SIZE(nb4_devices),
+ .spis = nb4_spi_devices,
+ .num_spis = ARRAY_SIZE(nb4_spi_devices),
+};
#endif
/*
@@ -790,6 +1388,11 @@ static const struct board_info __initcon
&board_96358vw2,
&board_AGPFS0,
&board_DWVS0,
+ &board_nb4_ser_r0,
+ &board_nb4_ser_r1,
+ &board_nb4_ser_r2,
+ &board_nb4_fxc_r1,
+ &board_nb4_fxc_r2,
#endif
};
@@ -844,6 +1447,16 @@ static void __init boardid_fixup(u8 *boo
struct bcm_tag *tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_64K);
char *board_name = (char *)bcm63xx_nvram_get_name();
+ if (BCMCPU_IS_6358() && (!strcmp(board_name, "96358VW"))) {
+ u8 *p = boot_addr + NB4_PID_OFFSET;
+
+ /* Extract nb4 PID */
+ if (!memcmp(p, "NB4-", 4)) {
+ memcpy(board_name, p, sizeof("NB4-XXX-rX"));
+ return;
+ }
+ }
+
/* check if bcm_tag is at 64k offset */
if (strncmp(board_name, tag->board_id, BOARDID_LEN) != 0) {
/* else try 128k */

View file

@ -0,0 +1,51 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -226,6 +226,40 @@ static struct board_info __initdata boar
},
},
};
+
+static struct board_info __initdata board_96338w2_e7t = {
+ .name = "96338W2_E7T",
+ .expected_cpu_id = 0x6338,
+
+ .has_enet0 = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .leds = {
+ {
+ .name = "96338W2_E7T:green:ppp",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "96338W2_E7T:green:ppp-fail",
+ .gpio = 5,
+ .active_low = 1,
+ },
+ {
+ .name = "96338W2_E7T:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+
+ },
+ },
+};
#endif
/*
@@ -1367,6 +1401,7 @@ static const struct board_info __initcon
#ifdef CONFIG_BCM63XX_CPU_6338
&board_96338gw,
&board_96338w,
+ &board_96338w2_e7t,
#endif
#ifdef CONFIG_BCM63XX_CPU_6345
&board_96345gw2,

View file

@ -0,0 +1,109 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -753,6 +753,98 @@ static struct board_info __initdata boar
},
};
+static struct board_info __initdata board_CPVA642 = {
+ .name = "CPVA642",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .has_ohci0 = 1,
+ .has_ehci0 = 1,
+
+ .leds = {
+ {
+ .name = "CPVA642:red:power",
+ .gpio = 14,
+ .active_low = 1,
+ },
+ {
+ .name = "CPVA642:green:power",
+ .gpio = 11,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "CPVA642:red:wifi",
+ .gpio = 6,
+ .active_low = 1,
+ },
+ {
+ .name = "CPVA642:green:wifi",
+ .gpio = 28,
+ .active_low = 0,
+ },
+ {
+ .name = "CPVA642:red:link",
+ .gpio = 9,
+ .active_low = 1,
+ },
+ {
+ .name = "CPVA642:green:link",
+ .gpio = 10,
+ .active_low = 1,
+ },
+ {
+ .name = "CPVA642:green:ether",
+ .gpio = 1,
+ .active_low = 1,
+ },
+ {
+ .name = "CPVA642:green:phone1",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "CPVA642:green:phone2",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+ .name = "CPVA642:green:usb",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ },
+
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 36,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "wps",
+ .gpio = 37,
+ .type = EV_KEY,
+ .code = KEY_WPS_BUTTON,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
+
+
static struct board_info __initdata board_AGPFS0 = {
.name = "AGPF-S0",
.expected_cpu_id = 0x6358,
@@ -1422,6 +1514,7 @@ static const struct board_info __initcon
&board_96358vw,
&board_96358vw2,
&board_AGPFS0,
+ &board_CPVA642,
&board_DWVS0,
&board_nb4_ser_r0,
&board_nb4_ser_r1,

View file

@ -0,0 +1,72 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -889,6 +889,61 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
};
+/* D-Link DSL-274xB revison C2/C3 */
+static struct board_info __initdata board_dsl_274xb_rev_c = {
+ .name = "AW4139",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .leds = {
+ {
+ .name = "dsl-274xb:green:power",
+ .gpio = 5,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "dsl-274xb:red:power",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "dsl-274xb:green:adsl",
+ .gpio = 9,
+ .active_low = 1,
+ },
+ {
+ .name = "dsl-274xb:green:internet",
+ .gpio = 2,
+ },
+ {
+ .name = "dsl-274xb:red:internet",
+ .gpio = 10,
+ },
+ },
+
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 34,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
+
struct spi_gpio_platform_data nb4_spi_gpio_data = {
.sck = NB4_SPI_GPIO_CLK,
.mosi = NB4_SPI_GPIO_MOSI,
@@ -1516,6 +1571,7 @@ static const struct board_info __initcon
&board_AGPFS0,
&board_CPVA642,
&board_DWVS0,
+ &board_dsl_274xb_rev_c,
&board_nb4_ser_r0,
&board_nb4_ser_r1,
&board_nb4_ser_r2,

View file

@ -0,0 +1,78 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -647,6 +647,67 @@ static struct board_info __initdata boar
},
},
};
+
+static struct board_info __initdata board_spw500v = {
+ .name = "SPW500V",
+ .expected_cpu_id = 0x6348,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .has_dsp = 1,
+ .dsp = {
+ .gpio_rst = 6,
+ .gpio_int = 34,
+ .ext_irq = 2,
+ .cs = 2,
+ },
+
+ .leds = {
+ {
+ .name = "SPW500V:red:power",
+ .gpio = 1,
+ .active_low = 1,
+ },
+ {
+ .name = "SPW500V:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "SPW500V:green:ppp",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ { .name = "SPW500V:green:pstn",
+ .gpio = 28,
+ .active_low = 1,
+ },
+ {
+ .name = "SPW500V:green:voip",
+ .gpio = 32,
+ .active_low = 1,
+ },
+ },
+
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 33,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
#endif
/*
@@ -1563,6 +1624,7 @@ static const struct board_info __initcon
&board_96348gw_a,
&board_rta1025w_16,
&board_96348_D4PW,
+ &board_spw500v,
#endif
#ifdef CONFIG_BCM63XX_CPU_6358

View file

@ -0,0 +1,124 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -514,6 +514,112 @@ static struct board_info __initdata boar
},
};
+static struct board_info __initdata board_gw6200 = {
+ .name = "GW6200",
+ .expected_cpu_id = 0x6348,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+ .enet1 = {
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .has_ohci0 = 1,
+
+ .has_dsp = 1,
+ .dsp = {
+ .gpio_rst = 8, /* FIXME: What is real GPIO here? */
+ .gpio_int = 34,
+ .ext_irq = 2,
+ .cs = 2,
+ },
+
+ .leds = {
+ {
+ .name = "GW6200:green:line1",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "GW6200:green:line2",
+ .gpio = 5,
+ .active_low = 1,
+ },
+ {
+ .name = "GW6200:green:line3",
+ .gpio = 6,
+ .active_low = 1,
+ },
+ {
+ .name = "GW6200:green:tel",
+ .gpio = 7,
+ .active_low = 1,
+ },
+ },
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 36,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
+
+static struct board_info __initdata board_gw6000 = {
+ .name = "GW6000",
+ .expected_cpu_id = 0x6348,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+ .enet1 = {
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .has_ohci0 = 1,
+
+ .has_dsp = 1,
+ .dsp = {
+ .gpio_rst = 6,
+ .gpio_int = 34,
+ .ext_irq = 2,
+ .cs = 2,
+ },
+
+ /* GW6000 has no GPIO-controlled leds */
+
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 36,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
+
+
+
static struct board_info __initdata board_FAST2404 = {
.name = "F@ST2404",
.expected_cpu_id = 0x6348,
@@ -1617,6 +1723,8 @@ static const struct board_info __initcon
#ifdef CONFIG_BCM63XX_CPU_6348
&board_96348r,
&board_96348gw,
+ &board_gw6000,
+ &board_gw6200,
&board_96348gw_10,
&board_96348gw_11,
&board_FAST2404,

View file

@ -0,0 +1,89 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -814,6 +814,78 @@ static struct board_info __initdata boar
},
},
};
+
+static struct board_info __initdata board_96348sv = {
+ .name = "MAGIC",
+ .expected_cpu_id = 0x6348,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+ .enet1 = {
+ /* it has BP_ENET_EXTERNAL_PHY */
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .has_ohci0 = 1,
+ .has_pccard = 1,
+ .has_ehci0 = 1,
+
+ .has_dsp = 1,
+ .dsp = {
+ .gpio_rst = 25,
+ .gpio_int = 34,
+ .cs = 2,
+ .ext_irq = 2,
+ },
+
+ .leds = {
+ {
+ .name = "MAGIC:green:voip",
+ .gpio = 22,
+ .active_low = 1,
+ },
+ {
+ .name = "MAGIC:green:adsl",
+ .gpio = 5,
+ .active_low = 1,
+ },
+ {
+ .name = "MAGIC:green:wifi",
+ .gpio = 28,
+ },
+ {
+ .name = "MAGIC:green:usb",
+ .gpio = 35,
+ .active_low = 1,
+ },
+ {
+ .name = "MAGIC:green:hpna",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "MAGIC:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "MAGIC:green:stop",
+ .gpio = 1,
+ .active_low = 1,
+ },
+ },
+};
#endif
/*
@@ -1733,6 +1805,7 @@ static const struct board_info __initcon
&board_rta1025w_16,
&board_96348_D4PW,
&board_spw500v,
+ &board_96348sv,
#endif
#ifdef CONFIG_BCM63XX_CPU_6358

View file

@ -0,0 +1,93 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -1772,6 +1772,82 @@ static struct board_info __initdata boar
.spis = nb4_spi_devices,
.num_spis = ARRAY_SIZE(nb4_spi_devices),
};
+
+static struct board_info __initdata board_HW553 = {
+ .name = "HW553",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .has_ohci0 = 1,
+ .has_ehci0 = 1,
+
+ .leds = {
+ {
+ .name = "HW553:red:lan",
+ .gpio = 34,
+ .active_low = 1,
+ },
+ {
+ .name = "HW553:blue:lan",
+ .gpio = 35,
+ .active_low = 1,
+ },
+ {
+ .name = "HW553:red:adsl",
+ .gpio = 22,
+ .active_low = 1,
+ },
+ {
+ .name = "HW553:blue:adsl",
+ .gpio = 23,
+ .active_low = 1,
+ },
+ {
+ .name = "HW553:red:power",
+ .gpio = 5,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+
+ {
+ .name = "HW553:blue:power",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "HW553:red:wifi",
+ .gpio = 25,
+ .active_low = 1,
+ },
+ {
+ .name = "HW553:red:internetkey",
+ .gpio = 12,
+ .active_low = 1,
+ },
+ {
+ .name = "HW553:blue:internetkey",
+ .gpio = 13,
+ .active_low = 1,
+ },
+ },
+};
#endif
/*
@@ -1820,6 +1896,7 @@ static const struct board_info __initcon
&board_nb4_ser_r2,
&board_nb4_fxc_r1,
&board_nb4_fxc_r2,
+ &board_HW553,
#endif
};

View file

@ -0,0 +1,56 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -260,6 +260,45 @@ static struct board_info __initdata boar
},
},
};
+
+static struct board_info __initdata board_rta1320_16m = {
+ .name = "RTA1320_16M",
+ .expected_cpu_id = 0x6338,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .leds = {
+ {
+ .name = "RTA1320_16M:green:adsl",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+ .name = "RTA1320_16M:green:ppp",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "RTA1320_16M:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "RTA1320_16M:green:stop",
+ .gpio = 1,
+ .active_low = 1,
+ },
+ },
+};
#endif
/*
@@ -1864,6 +1903,7 @@ static const struct board_info __initcon
&board_96338gw,
&board_96338w,
&board_96338w2_e7t,
+ &board_rta1320_16m,
#endif
#ifdef CONFIG_BCM63XX_CPU_6345
&board_96345gw2,

View file

@ -0,0 +1,83 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -1887,6 +1887,72 @@ static struct board_info __initdata boar
},
},
};
+
+ /* T-Home Speedport W 303V Typ B */
+static struct board_info __initdata board_spw303v = {
+ .name = "96358-502V",
+ .expected_cpu_id = 0x6358,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .leds = {
+ {
+ .name = "spw303v:green:power+adsl",
+ .gpio = 22,
+ .active_low = 1,
+ },
+ {
+ .name = "spw303v:red:power+adsl",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+ .name = "spw303v:green:ppp",
+ .gpio = 5,
+ .active_low = 1,
+ },
+ {
+ .name = "spw303v:green:ses",
+ .gpio = 0,
+ .active_low = 1,
+ },
+ {
+ .name = "spw303v:green:voip",
+ .gpio = 27,
+ .active_low = 1,
+ },
+ {
+ .name = "spw303v:green:pots",
+ .gpio = 31,
+ .active_low = 1,
+ },
+ },
+
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 11,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "ses",
+ .gpio = 37,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_WPS_BUTTON,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ }
+};
#endif
/*
@@ -1937,6 +2003,7 @@ static const struct board_info __initcon
&board_nb4_fxc_r1,
&board_nb4_fxc_r2,
&board_HW553,
+ &board_spw303v,
#endif
};

View file

@ -0,0 +1,123 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -925,6 +925,65 @@ static struct board_info __initdata boar
},
},
};
+
+static struct board_info __initdata board_V2500V_BB = {
+ .name = "V2500V_BB",
+ .expected_cpu_id = 0x6348,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .leds = {
+ {
+ .name = "V2500V_BB:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "V2500V_BB:red:power",
+ .gpio = 1,
+ .active_low = 1,
+ },
+ {
+ .name = "V2500V_BB:green:adsl",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ { .name = "V2500V_BB:green:ppp",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+ .name = "V2500V_BB:green:wireless",
+ .gpio = 6,
+ .active_low = 1,
+ },
+ },
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 31,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
#endif
/*
@@ -1988,6 +2047,7 @@ static const struct board_info __initcon
&board_96348_D4PW,
&board_spw500v,
&board_96348sv,
+ &board_V2500V_BB,
#endif
#ifdef CONFIG_BCM63XX_CPU_6358
@@ -2109,6 +2169,22 @@ void __init board_prom_init(void)
val &= MPI_CSBASE_BASE_MASK;
}
boot_addr = (u8 *)KSEG1ADDR(val);
+ printk(KERN_INFO PFX "Boot address 0x%08x\n",(unsigned int)boot_addr);
+
+ /* BT Voyager 2500V (RTA1046VW PCB) has 8 Meg flash used as two */
+ /* banks of 4 Meg. The byte at 0xBF800000 identifies the back to use.*/
+ /* Loading firmware from the CFE Prompt always loads to Bank 0 */
+ /* Do an early check of CFE and then select bank 0 */
+
+ if (boot_addr == (u8 *)0xbf800000) {
+ u8 *tmp_boot_addr = (u8*)0xbfc00000;
+
+ bcm63xx_nvram_init(tmp_boot_addr + BCM963XX_NVRAM_OFFSET);
+ if (!strcmp(bcm63xx_nvram_get_name(), "V2500V_BB")) {
+ printk(KERN_INFO PFX "V2500V: nvram bank 0\n");
+ boot_addr = tmp_boot_addr;
+ }
+ }
/* dump cfe version */
cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET;
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -19,6 +19,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
+#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_flash.h>
#include <bcm63xx_dev_hsspi.h>
@@ -158,6 +159,13 @@ int __init bcm63xx_flash_register(int nu
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
val &= MPI_CSBASE_BASE_MASK;
+ /* BT Voyager 2500V has 8 Meg flash in two 4 Meg banks */
+ /* Loading from CFE always uses Bank 0 */
+ if (!strcmp(board_get_name(), "V2500V_BB")) {
+ pr_info("V2500V: Start in Bank 0\n");
+ val = val + 0x400000; // Select Bank 0 start address
+ }
+
mtd_resources[0].start = val;
mtd_resources[0].end = 0x1FFFFFFF;

View file

@ -0,0 +1,75 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -485,6 +485,64 @@ static struct board_info __initdata boar
},
};
+
+/* BT Voyager 2110 */
+static struct board_info __initdata board_V2110 = {
+ .name = "V2110",
+ .expected_cpu_id = 0x6348,
+
+ .has_uart0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .leds = {
+ {
+ .name = "V2110:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "V2110:red:power",
+ .gpio = 1,
+ .active_low = 1,
+ },
+ {
+ .name = "V2110:green:adsl",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ { .name = "V2110:green:ppp",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+ .name = "V2110:green:wireless",
+ .gpio = 6,
+ .active_low = 1,
+ },
+ },
+
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 33,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
+
+
static struct board_info __initdata board_96348gw = {
.name = "96348GW",
.expected_cpu_id = 0x6348,
@@ -2048,6 +2106,7 @@ static const struct board_info __initcon
&board_spw500v,
&board_96348sv,
&board_V2500V_BB,
+ &board_V2110,
#endif
#ifdef CONFIG_BCM63XX_CPU_6358

View file

@ -0,0 +1,390 @@
--- a/arch/mips/bcm63xx/boards/Kconfig
+++ b/arch/mips/bcm63xx/boards/Kconfig
@@ -8,4 +8,10 @@ config BOARD_BCM963XX
select SSB
help
+config BOARD_LIVEBOX
+ bool "Inventel Livebox(es) boards"
+ select SSB
+ help
+ Inventel Livebox boards using the RedBoot bootloader.
+
endchoice
--- a/arch/mips/bcm63xx/boards/Makefile
+++ b/arch/mips/bcm63xx/boards/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
+obj-$(CONFIG_BOARD_LIVEBOX) += board_livebox.o
--- /dev/null
+++ b/arch/mips/bcm63xx/boards/board_livebox.c
@@ -0,0 +1,369 @@
+/*
+ * 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 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/ssb/ssb.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <asm/addrspace.h>
+#include <bcm63xx_board.h>
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_dev_uart.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_dev_pci.h>
+#include <bcm63xx_dev_enet.h>
+#include <bcm63xx_dev_dsp.h>
+#include <bcm63xx_dev_pcmcia.h>
+#include <bcm63xx_dev_usb_ohci.h>
+#include <bcm63xx_dev_usb_ehci.h>
+#include <bcm63xx_dev_spi.h>
+#include <board_bcm963xx.h>
+
+#define PFX "board_livebox: "
+
+#define LIVEBOX_KEYS_POLL_INTERVAL 20
+#define LIVEBOX_KEYS_DEBOUNCE_INTERVAL (LIVEBOX_KEYS_POLL_INTERVAL * 3)
+
+static unsigned int mac_addr_used = 0;
+static struct board_info board;
+
+/*
+ * known 6348 boards
+ */
+#ifdef CONFIG_BCM63XX_CPU_6348
+static struct board_info __initdata board_livebox_blue5g = {
+ .name = "Livebox-blue-5g",
+ .expected_cpu_id = 0x6348,
+
+ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet0 = {
+ .has_phy = 1,
+ .use_internal_phy = 1,
+ },
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 31,
+ },
+
+ .has_ohci0 = 1,
+ .has_pccard = 1,
+
+ .has_dsp = 0, /*TODO some Liveboxes have dsp*/
+ .dsp = {
+ .gpio_rst = 6, /*FIXME eth1 shares gpio6 with dsp?*/
+ .gpio_int = 35,
+ .cs = 2,
+ .ext_irq = 2,
+ },
+
+ .leds = {
+ {
+ .name = "Livebox-blue-5g::adsl-fail",
+ .gpio = 0,
+ .active_low = 0,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "Livebox-blue-5g::adsl",
+ .gpio = 1,
+ },
+ {
+ .name = "Livebox-blue-5g::traffic",
+ .gpio = 2,
+ },
+ {
+ .name = "Livebox-blue-5g::phone",
+ .gpio = 3,
+ },
+ {
+ .name = "Livebox-blue-5g::wifi",
+ .gpio = 4,
+ },
+ },
+
+ .buttons = {
+ {
+ .desc = "BTN_1",
+ .gpio = 36,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = BTN_1,
+ .debounce_interval = LIVEBOX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ {
+ .desc = "BTN_2",
+ .gpio = 7,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = BTN_2,
+ .debounce_interval = LIVEBOX_KEYS_DEBOUNCE_INTERVAL,
+ },
+
+ },
+};
+#endif
+
+/*
+ * all boards
+ */
+static const struct board_info __initdata *bcm963xx_boards[] = {
+#ifdef CONFIG_BCM63XX_CPU_6348
+ &board_livebox_blue5g
+#endif
+};
+/*
+ * return board name for /proc/cpuinfo
+ */
+const char *board_get_name(void)
+{
+ return board.name;
+}
+
+/*
+ * register & return a new board mac address
+ */
+static int board_get_mac_address(u8 *mac)
+{
+ u8 *p;
+ int count;
+
+ memcpy(mac, (u8 *)0xBEBFF377, ETH_ALEN);
+
+ p = mac + ETH_ALEN - 1;
+ count = mac_addr_used;
+
+ while (count--) {
+ do {
+ (*p)++;
+ if (*p != 0)
+ break;
+ p--;
+ } while (p != mac);
+ }
+
+ if (p == mac) {
+ printk(KERN_ERR PFX "unable to fetch mac address\n");
+ return -ENODEV;
+ }
+ mac_addr_used++;
+
+ return 0;
+}
+
+/*
+ * early init callback
+ */
+#define LIVEBOX_GPIO_DETECT_MASK 0x000000ff
+#define LIVEBOX_BOOT_ADDR 0x1e400000
+
+#define LIVEBOX_HW_BLUE5G_9 0x90
+
+void __init board_prom_init(void)
+{
+ u32 val;
+ u8 hw_version;
+
+ /* Get hardware version */
+ val = bcm_gpio_readl(GPIO_CTL_LO_REG);
+ val &= ~LIVEBOX_GPIO_DETECT_MASK;
+ bcm_gpio_writel(val, GPIO_CTL_LO_REG);
+
+ hw_version = bcm_gpio_readl(GPIO_DATA_LO_REG) & LIVEBOX_GPIO_DETECT_MASK;
+ switch (hw_version) {
+ case LIVEBOX_HW_BLUE5G_9:
+ printk(KERN_INFO PFX "Livebox BLUE5G.9\n");
+ memcpy(&board, bcm963xx_boards[0], sizeof(board));
+ break;
+ default:
+ printk(KERN_INFO PFX "Unknown livebox version: %02x\n", hw_version);
+ break;
+ }
+
+ /* use default livebox configuration */
+ memcpy(&board, bcm963xx_boards[0], sizeof(board));
+
+ /* setup pin multiplexing depending on board enabled device,
+ * this has to be done this early since PCI init is done
+ * inside arch_initcall */
+ val = 0;
+
+#ifdef CONFIG_PCI
+ if (board.has_pci) {
+ bcm63xx_pci_enabled = 1;
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G2_PCI;
+ }
+#endif
+ if (board.has_pccard) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G1_MII_PCCARD;
+ }
+
+ if (board.has_enet0 && !board.enet0.use_internal_phy) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G3_EXT_MII |
+ GPIO_MODE_6348_G0_EXT_MII;
+ }
+
+ if (board.has_enet1 && !board.enet1.use_internal_phy) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G3_EXT_MII |
+ GPIO_MODE_6348_G0_EXT_MII;
+ printk(KERN_INFO PFX "resetting gpio6 for eth1...\n");
+ gpio_request(6, "dsp_eth_rst");
+ gpio_direction_output(6, 0);
+ gpio_set_value(6, 1);
+ }
+
+ bcm_gpio_writel(val, GPIO_MODE_REG);
+}
+
+/*
+ * second stage init callback, good time to panic if we couldn't
+ * identify on which board we're running since early printk is working
+ */
+void __init board_setup(void)
+{
+ if (!board.name[0])
+ panic("unable to detect bcm963xx board");
+ printk(KERN_INFO PFX "board name: %s\n", board.name);
+
+ /* make sure we're running on expected cpu */
+ if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
+ panic("unexpected CPU for bcm963xx board");
+}
+
+static struct physmap_flash_data flash_data = {
+ .width = 2,
+};
+
+static struct resource mtd_resources[] = {
+ {
+ .start = 0, /* filled at runtime */
+ .end = 0, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device mtd_dev = {
+ .name = "physmap-flash",
+ .resource = mtd_resources,
+ .num_resources = ARRAY_SIZE(mtd_resources),
+ .dev = {
+ .platform_data = &flash_data,
+ },
+};
+
+static struct gpio_led_platform_data bcm63xx_led_data;
+
+static struct platform_device bcm63xx_gpio_leds = {
+ .name = "leds-gpio",
+ .id = 0,
+ .dev.platform_data = &bcm63xx_led_data,
+};
+
+static struct gpio_keys_platform_data bcm63xx_gpio_keys_data = {
+ .poll_interval = LIVEBOX_KEYS_POLL_INTERVAL,
+};
+
+static struct platform_device bcm63xx_gpio_keys_device = {
+ .name = "gpio-keys-polled",
+ .id = 0,
+ .dev.platform_data = &bcm63xx_gpio_keys_data,
+};
+
+/*
+ * third stage init callback, register all board devices.
+ */
+int __init board_register_devices(void)
+{
+ u32 val;
+ int led_count = 0;
+ int button_count = 0;
+
+ if (board.has_uart0)
+ bcm63xx_uart_register(0);
+
+ if (board.has_uart1)
+ bcm63xx_uart_register(1);
+
+ if (board.has_pccard)
+ bcm63xx_pcmcia_register();
+
+ if (board.has_enet0 &&
+ !board_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_enet_register(1, &board.enet1);
+
+ if (board.has_ehci0)
+ bcm63xx_ehci_register();
+
+ if (board.has_ohci0)
+ bcm63xx_ohci_register();
+
+ if (board.has_dsp)
+ bcm63xx_dsp_register(&board.dsp);
+
+ bcm63xx_spi_register();
+
+ if (board.num_devs)
+ platform_add_devices(board.devs, board.num_devs);
+
+ if (board.num_spis)
+ spi_register_board_info(board.spis, board.num_spis);
+
+
+ /* read base address of boot chip select (0) */
+ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+ val &= MPI_CSBASE_BASE_MASK;
+ if (val != LIVEBOX_BOOT_ADDR)
+ printk(KERN_NOTICE PFX "flash address is: 0x%08x, forcing to: 0x%08x\n",
+ val, LIVEBOX_BOOT_ADDR);
+ mtd_resources[0].start = LIVEBOX_BOOT_ADDR;
+ mtd_resources[0].end = 0x1ebfffff;
+
+ platform_device_register(&mtd_dev);
+
+ /* count number of LEDs defined by this device */
+ while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
+ led_count++;
+
+ bcm63xx_led_data.num_leds = led_count;
+ bcm63xx_led_data.leds = board.leds;
+
+ platform_device_register(&bcm63xx_gpio_leds);
+
+ /* count number of BUTTONs defined by this device */
+ while (button_count < ARRAY_SIZE(board.buttons) && board.buttons[button_count].desc)
+ button_count++;
+
+ if (button_count) {
+ bcm63xx_gpio_keys_data.nbuttons = button_count;
+ bcm63xx_gpio_keys_data.buttons = board.buttons;
+
+ platform_device_register(&bcm63xx_gpio_keys_device);
+ }
+
+ return 0;
+}

View file

@ -0,0 +1,62 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -543,6 +543,51 @@ static struct board_info __initdata boar
};
+static struct board_info __initdata board_ct536_ct5621 = {
+ .name = "CT536_CT5621",
+ .expected_cpu_id = 0x6348,
+
+ .has_uart0 = 1,
+ .has_enet0 = 0,
+ .has_enet1 = 1,
+ .has_pci = 1,
+
+ .enet1 = {
+ .has_phy = 1,
+ .phy_id = 0,
+ .force_speed_100 = 1,
+ .force_duplex_full = 1,
+ },
+
+ .has_ohci0 = 1,
+ .has_pccard = 1,
+ .has_ehci0 = 1,
+
+ .leds = {
+ {
+ .name = "CT536_CT5621:green:adsl-fail",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+ .name = "CT536_CT5621:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ },
+ .buttons = {
+ {
+ .desc = "reset",
+ .gpio = 33,
+ .active_low = 1,
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
+ },
+ },
+};
+
static struct board_info __initdata board_96348gw = {
.name = "96348GW",
.expected_cpu_id = 0x6348,
@@ -2107,6 +2152,7 @@ static const struct board_info __initcon
&board_96348sv,
&board_V2500V_BB,
&board_V2110,
+ &board_ct536_ct5621,
#endif
#ifdef CONFIG_BCM63XX_CPU_6358

Some files were not shown because too many files have changed in this diff Show more