brcm63xx: add kernel 4.1 support

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

SVN-Revision: 46113
owl
Jonas Gorski 2015-06-22 12:28:46 +00:00
parent a0c49ef46f
commit bd398e1765
158 changed files with 16148 additions and 0 deletions

View File

@ -0,0 +1,241 @@
CONFIG_ARCH_BINFMT_ELF_STATE=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set
# CONFIG_ARCH_HAS_SG_CHAIN is not set
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=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_B53_SRAB_DRIVER is not set
CONFIG_BCM6345_EXT_IRQ=y
CONFIG_BCM6345_PERIPH_IRQ=y
CONFIG_BCM63XX=y
CONFIG_BCM63XX_CPU_3368=y
CONFIG_BCM63XX_CPU_6318=y
CONFIG_BCM63XX_CPU_63268=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_BCMA=y
CONFIG_BCMA_BLOCKIO=y
# CONFIG_BCMA_DEBUG is not set
# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
# CONFIG_BCMA_DRIVER_MIPS is not set
CONFIG_BCMA_DRIVER_PCI=y
# CONFIG_BCMA_DRIVER_PCI_HOSTMODE is not set
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
# CONFIG_BCMA_HOST_SOC is not set
CONFIG_BOARD_BCM63XX_DT=y
CONFIG_BOARD_BCM963XX=y
CONFIG_BOARD_LIVEBOX=y
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=y
CONFIG_CPU_BMIPS32_3300=y
CONFIG_CPU_BMIPS4350=y
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_MIPS32=y
CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=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_DTC=y
CONFIG_EARLY_PRINTK=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_IO=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_74X164=y
CONFIG_GPIO_BCM63XX=y
CONFIG_GPIO_DEVRES=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_SYSFS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
# CONFIG_HAVE_ARCH_BITREVERSE is not set
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
CONFIG_HAVE_BPF_JIT=y
CONFIG_HAVE_CC_STACKPROTECTOR=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DMA_CONTIGUOUS=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_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=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_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=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_IRQCHIP=y
CONFIG_IRQ_CPU=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_KEXEC=y
CONFIG_LEDS_GPIO=y
CONFIG_LIBFDT=y
# CONFIG_LZ4_COMPRESS is not set
# CONFIG_LZ4_DECOMPRESS is not set
CONFIG_MDIO_BOARDINFO=y
CONFIG_MIPS=y
CONFIG_MIPS_APPENDED_DTB=y
# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set
CONFIG_MIPS_L1_CACHE_SHIFT=4
CONFIG_MIPS_L1_CACHE_SHIFT_4=y
# CONFIG_MIPS_MACHINE is not set
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_MTD_SPI_NOR=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
# CONFIG_NO_IOPORT_MAP is not set
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_ADDRESS_PCI=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_MDIO=y
CONFIG_OF_MTD=y
CONFIG_OF_NET=y
CONFIG_OF_PCI=y
CONFIG_OF_PCI_IRQ=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_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_RCU_EXPEDITE_BOOT is not set
# CONFIG_RCU_STALL_COMMON is not set
CONFIG_RELAY=y
CONFIG_RTL8366_SMI=y
CONFIG_RTL8367_PHY=y
CONFIG_SCHED_HRTICK=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_SRCU=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_SYNC_R4K=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_SYS_HAS_CPU_BMIPS=y
CONFIG_SYS_HAS_CPU_BMIPS32_3300=y
CONFIG_SYS_HAS_CPU_BMIPS4350=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_SYS_SUPPORTS_HOTPLUG_CPU=y
CONFIG_SYS_SUPPORTS_SMP=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_WEAK_ORDERING=y
CONFIG_ZONE_DMA_FLAG=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/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -391,7 +391,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-hsspi.o dev-uart.o \
- dev-wdt.o dev-usb-usbd.o
+ dev-wdt.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/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -40,6 +40,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"
@@ -868,22 +869,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);
}
/**
@@ -897,14 +883,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_BMIPS32_3300
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-hsspi.o dev-uart.o \
- dev-wdt.o dev-usb-usbd.o usb-common.o
+ dev-wdt.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
@@ -26,6 +26,7 @@
#include <bcm63xx_dev_hsspi.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>
@@ -898,6 +899,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,137 @@
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,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-hsspi.o dev-uart.o \
- dev-wdt.o dev-usb-ohci.o dev-usb-usbd.o usb-common.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/
--- /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
@@ -26,6 +26,7 @@
#include <bcm63xx_dev_hsspi.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>
@@ -899,6 +900,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
@@ -234,7 +234,8 @@ static int m25p_probe(struct spi_device
ppdata.of_node = spi->dev.of_node;
- 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,90 @@
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
@@ -32,6 +32,7 @@ struct m25p {
struct spi_device *spi;
struct spi_nor spi_nor;
struct mtd_info mtd;
+ int max_transfer_len;
u8 command[MAX_CMD_SIZE];
};
@@ -121,7 +122,7 @@ static inline unsigned int m25p80_rx_nbi
* Read an address range from the nor chip. The address range
* may be any size provided it is within the physical boundaries.
*/
-static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
+static int __m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
struct m25p *flash = nor->priv;
@@ -154,6 +155,29 @@ static int m25p80_read(struct spi_nor *n
return 0;
}
+static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct m25p *flash = nor->priv;
+ size_t off;
+ size_t read_len = flash->max_transfer_len;
+ size_t part_len;
+ int ret = 0;
+
+ if (!read_len)
+ return __m25p80_read(nor, from, len, retlen, buf);
+
+ *retlen = 0;
+
+ for (off = 0; off < len && !ret; off += read_len) {
+ ret = __m25p80_read(nor, from + off, min(len - off, read_len),
+ &part_len, buf + off);
+ *retlen += part_len;
+ }
+
+ return ret;
+}
+
static int m25p80_erase(struct spi_nor *nor, loff_t offset)
{
struct m25p *flash = nor->priv;
@@ -228,6 +252,9 @@ static int m25p_probe(struct spi_device
else
flash_name = spi->modalias;
+ if (data)
+ flash->max_transfer_len = data->max_transfer_len;
+
ret = spi_nor_scan(nor, flash_name, mode);
if (ret)
return ret;
--- 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,66 @@
From 6ac09efa8f0e189ffe7dd7b0889289de56ee44cc Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 19 Jan 2014 12:18:03 +0100
Subject: [PATCH] USB: EHCI: allow limiting ports for ehci-platform
In the same way as the ohci platform driver allows limiting ports,
enable the same for ehci. This prevents a mismatch in the available
ports between ehci/ohci on USB 2.0 controllers.
This is needed if the USB host controller always reports the maximum
number of ports regardless of the number of available ports (because
one might be set to be usb device).
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
drivers/usb/host/ehci-hcd.c | 4 ++++
drivers/usb/host/ehci-platform.c | 2 ++
drivers/usb/host/ehci.h | 1 +
include/linux/usb/ehci_pdriver.h | 1 +
4 files changed, 8 insertions(+)
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -665,6 +665,10 @@ int ehci_setup(struct usb_hcd *hcd)
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ if (ehci->num_ports) {
+ ehci->hcs_params &= ~0xf; /* bits 3:0, ports on HC */
+ ehci->hcs_params |= ehci->num_ports;
+ }
ehci->sbrn = HCD_USB2;
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -59,6 +59,9 @@ static int ehci_platform_reset(struct us
hcd->has_tt = pdata->has_tt;
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+ if (pdata->num_ports && pdata->num_ports <= 15)
+ ehci->num_ports = pdata->num_ports;
+
if (pdata->pre_setup) {
retval = pdata->pre_setup(hcd);
if (retval < 0)
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -213,6 +213,7 @@ struct ehci_hcd { /* one per controlle
u32 command;
/* SILICON QUIRKS */
+ unsigned int num_ports;
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
unsigned big_endian_mmio:1;
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -42,6 +42,7 @@ struct usb_hcd;
*/
struct usb_ehci_pdata {
int caps_offset;
+ unsigned int num_ports;
unsigned has_tt:1;
unsigned has_synopsys_hc_bug:1;
unsigned big_endian_desc:1;

View File

@ -0,0 +1,493 @@
From 5a50cb0d53344a2429831b00925d6183d4d332e1 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 9 Mar 2014 03:54:05 +0100
Subject: [PATCH 40/44] MIPS: BCM63XX: move device registration code into its
own file
Move device registration code into its own file to allow sharing it
between board implementations.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/Makefile | 1 +
arch/mips/bcm63xx/boards/board_bcm963xx.c | 188 +-------------------------
arch/mips/bcm63xx/boards/board_common.c | 215 ++++++++++++++++++++++++++++++
arch/mips/bcm63xx/boards/board_common.h | 8 ++
4 files changed, 223 insertions(+), 183 deletions(-)
create mode 100644 arch/mips/bcm63xx/boards/board_common.c
create mode 100644 arch/mips/bcm63xx/boards/board_common.h
--- a/arch/mips/bcm63xx/boards/Makefile
+++ b/arch/mips/bcm63xx/boards/Makefile
@@ -1 +1,2 @@
+obj-y += board_common.o
obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -10,35 +10,22 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/ssb/ssb.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_nvram.h>
-#include <bcm63xx_dev_pci.h>
-#include <bcm63xx_dev_enet.h>
-#include <bcm63xx_dev_dsp.h>
-#include <bcm63xx_dev_flash.h>
-#include <bcm63xx_dev_hsspi.h>
-#include <bcm63xx_dev_pcmcia.h>
-#include <bcm63xx_dev_spi.h>
-#include <bcm63xx_dev_usb_ehci.h>
-#include <bcm63xx_dev_usb_ohci.h>
-#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
+#include "board_common.h"
+
#include <uapi/linux/bcm933xx_hcs.h>
#define PFX "board_bcm963xx: "
#define HCS_OFFSET_128K 0x20000
-static struct board_info board;
-
/*
* known 3368 boards
*/
@@ -711,52 +698,6 @@ static const struct board_info __initcon
};
/*
- * Register a sane SPROMv2 to make the on-board
- * bcm4318 WLAN work
- */
-#ifdef CONFIG_SSB_PCIHOST
-static struct ssb_sprom bcm63xx_sprom = {
- .revision = 0x02,
- .board_rev = 0x17,
- .country_code = 0x0,
- .ant_available_bg = 0x3,
- .pa0b0 = 0x15ae,
- .pa0b1 = 0xfa85,
- .pa0b2 = 0xfe8d,
- .pa1b0 = 0xffff,
- .pa1b1 = 0xffff,
- .pa1b2 = 0xffff,
- .gpio0 = 0xff,
- .gpio1 = 0xff,
- .gpio2 = 0xff,
- .gpio3 = 0xff,
- .maxpwr_bg = 0x004c,
- .itssi_bg = 0x00,
- .boardflags_lo = 0x2848,
- .boardflags_hi = 0x0000,
-};
-
-int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
-{
- if (bus->bustype == SSB_BUSTYPE_PCI) {
- memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
- return 0;
- } else {
- printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
- return -EINVAL;
- }
-}
-#endif
-
-/*
- * return board name for /proc/cpuinfo
- */
-const char *board_get_name(void)
-{
- return board.name;
-}
-
-/*
* early init callback, read nvram data from flash and checksum it
*/
void __init board_prom_init(void)
@@ -801,141 +742,16 @@ void __init board_prom_init(void)
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
continue;
/* copy, board desc array is marked initdata */
- memcpy(&board, bcm963xx_boards[i], sizeof(board));
+ board_early_setup(bcm963xx_boards[i]);
break;
}
- /* bail out if board is not found, will complain later */
- if (!board.name[0]) {
+ /* warn if board is not found, will complain later */
+ if (i == ARRAY_SIZE(bcm963xx_boards)) {
char name[17];
memcpy(name, board_name, 16);
name[16] = 0;
printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
name);
- return;
- }
-
- /* 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;
- }
-
- 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 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,
-};
-
-/*
- * third stage init callback, register all board devices.
- */
-int __init board_register_devices(void)
-{
- 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 &&
- !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
- bcm63xx_enet_register(0, &board.enet0);
-
- if (board.has_enet1 &&
- !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
- bcm63xx_enet_register(1, &board.enet1);
-
- if (board.has_enetsw &&
- !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
- bcm63xx_enetsw_register(&board.enetsw);
-
- if (board.has_usbd)
- bcm63xx_usbd_register(&board.usbd);
-
- if (board.has_ehci0)
- bcm63xx_ehci_register();
-
- if (board.has_ohci0)
- bcm63xx_ohci_register();
-
- if (board.has_dsp)
- bcm63xx_dsp_register(&board.dsp);
-
- /* Generate MAC address for WLAN and register our SPROM,
- * do this after registering enet devices
- */
-#ifdef CONFIG_SSB_PCIHOST
- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
- memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- if (ssb_arch_register_fallback_sprom(
- &bcm63xx_get_fallback_sprom) < 0)
- pr_err(PFX "failed to register fallback SPROM\n");
}
-#endif
-
- bcm63xx_spi_register();
-
- bcm63xx_hsspi_register();
-
- bcm63xx_flash_register();
-
- bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
- bcm63xx_led_data.leds = board.leds;
-
- 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;
}
--- /dev/null
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -0,0 +1,217 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/ssb/ssb.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_nvram.h>
+#include <bcm63xx_dev_pci.h>
+#include <bcm63xx_dev_enet.h>
+#include <bcm63xx_dev_dsp.h>
+#include <bcm63xx_dev_flash.h>
+#include <bcm63xx_dev_hsspi.h>
+#include <bcm63xx_dev_pcmcia.h>
+#include <bcm63xx_dev_spi.h>
+#include <bcm63xx_dev_usb_ehci.h>
+#include <bcm63xx_dev_usb_ohci.h>
+#include <bcm63xx_dev_usb_usbd.h>
+#include <board_bcm963xx.h>
+
+#define PFX "board: "
+
+static struct board_info board;
+
+/*
+ * Register a sane SPROMv2 to make the on-board
+ * bcm4318 WLAN work
+ */
+#ifdef CONFIG_SSB_PCIHOST
+static struct ssb_sprom bcm63xx_sprom = {
+ .revision = 0x02,
+ .board_rev = 0x17,
+ .country_code = 0x0,
+ .ant_available_bg = 0x3,
+ .pa0b0 = 0x15ae,
+ .pa0b1 = 0xfa85,
+ .pa0b2 = 0xfe8d,
+ .pa1b0 = 0xffff,
+ .pa1b1 = 0xffff,
+ .pa1b2 = 0xffff,
+ .gpio0 = 0xff,
+ .gpio1 = 0xff,
+ .gpio2 = 0xff,
+ .gpio3 = 0xff,
+ .maxpwr_bg = 0x004c,
+ .itssi_bg = 0x00,
+ .boardflags_lo = 0x2848,
+ .boardflags_hi = 0x0000,
+};
+
+int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+{
+ if (bus->bustype == SSB_BUSTYPE_PCI) {
+ memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
+ return 0;
+ } else {
+ printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+ return -EINVAL;
+ }
+}
+#endif
+
+/*
+ * return board name for /proc/cpuinfo
+ */
+const char *board_get_name(void)
+{
+ return board.name;
+}
+
+/*
+ * setup board for device registration
+ */
+void __init board_early_setup(const struct board_info *target)
+{
+ u32 val;
+
+ memcpy(&board, target, 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;
+ }
+
+ 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 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,
+};
+
+/*
+ * third stage init callback, register all board devices.
+ */
+int __init board_register_devices(void)
+{
+ 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 &&
+ !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
+ bcm63xx_enet_register(0, &board.enet0);
+
+ if (board.has_enet1 &&
+ !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
+ bcm63xx_enet_register(1, &board.enet1);
+
+ if (board.has_enetsw &&
+ !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
+ bcm63xx_enetsw_register(&board.enetsw);
+
+ if (board.has_usbd)
+ bcm63xx_usbd_register(&board.usbd);
+
+ if (board.has_ehci0)
+ bcm63xx_ehci_register();
+
+ if (board.has_ohci0)
+ bcm63xx_ohci_register();
+
+ if (board.has_dsp)
+ bcm63xx_dsp_register(&board.dsp);
+
+ /* Generate MAC address for WLAN and register our SPROM,
+ * do this after registering enet devices
+ */
+#ifdef CONFIG_SSB_PCIHOST
+ if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ if (ssb_arch_register_fallback_sprom(
+ &bcm63xx_get_fallback_sprom) < 0)
+ pr_err(PFX "failed to register fallback SPROM\n");
+ }
+#endif
+
+ bcm63xx_spi_register();
+
+ bcm63xx_hsspi_register();
+
+ bcm63xx_flash_register();
+
+ bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
+ bcm63xx_led_data.leds = board.leds;
+
+ 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;
+}
--- /dev/null
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -0,0 +1,8 @@
+#ifndef __BOARD_COMMON_H
+#define __BOARD_COMMON_H
+
+#include <board_bcm963xx.h>
+
+void board_early_setup(const struct board_info *board);
+
+#endif /* __BOARD_COMMON_H */

View File

@ -0,0 +1,100 @@
From 4e9c34a37bd3442b286ba55441bfe22c1ac5b65f Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 9 Mar 2014 04:08:06 +0100
Subject: [PATCH 41/44] MIPS: BCM63XX: pass a mac addresss allocator to board
setup
Pass a mac address allocator to board setup code to allow board
implementations to work with third party bootloaders not using nvram
for configuration storage.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 3 ++-
arch/mips/bcm63xx/boards/board_common.c | 16 ++++++++++------
arch/mips/bcm63xx/boards/board_common.h | 3 ++-
3 files changed, 14 insertions(+), 8 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -742,7 +742,8 @@ void __init board_prom_init(void)
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
continue;
/* copy, board desc array is marked initdata */
- board_early_setup(bcm963xx_boards[i]);
+ board_early_setup(bcm963xx_boards[i],
+ bcm63xx_nvram_get_mac_address);
break;
}
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -18,7 +18,6 @@
#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
-#include <bcm63xx_nvram.h>
#include <bcm63xx_dev_pci.h>
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_dsp.h>
@@ -81,15 +80,20 @@ const char *board_get_name(void)
return board.name;
}
+static int (*board_get_mac_address)(u8 mac[ETH_ALEN]);
+
/*
* setup board for device registration
*/
-void __init board_early_setup(const struct board_info *target)
+void __init board_early_setup(const struct board_info *target,
+ int (*get_mac_address)(u8 mac[ETH_ALEN]))
{
u32 val;
memcpy(&board, target, sizeof(board));
+ board_get_mac_address = get_mac_address;
+
/* setup pin multiplexing depending on board enabled device,
* this has to be done this early since PCI init is done
* inside arch_initcall */
@@ -162,15 +166,15 @@ int __init board_register_devices(void)
bcm63xx_pcmcia_register();
if (board.has_enet0 &&
- !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
+ !board_get_mac_address(board.enet0.mac_addr))
bcm63xx_enet_register(0, &board.enet0);
if (board.has_enet1 &&
- !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
+ !board_get_mac_address(board.enet1.mac_addr))
bcm63xx_enet_register(1, &board.enet1);
if (board.has_enetsw &&
- !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
+ !board_get_mac_address(board.enetsw.mac_addr))
bcm63xx_enetsw_register(&board.enetsw);
if (board.has_usbd)
@@ -189,7 +193,7 @@ 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_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(
--- a/arch/mips/bcm63xx/boards/board_common.h
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -3,6 +3,7 @@
#include <board_bcm963xx.h>
-void board_early_setup(const struct board_info *board);
+void board_early_setup(const struct board_info *board,
+ int (*get_mac_address)(u8 mac[ETH_ALEN]));
#endif /* __BOARD_COMMON_H */

View File

@ -0,0 +1,101 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -10,6 +10,8 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
@@ -26,6 +28,9 @@
#define HCS_OFFSET_128K 0x20000
+#define BCM963XX_KEYS_POLL_INTERVAL 20
+#define BCM963XX_KEYS_DEBOUNCE_INTERVAL (BCM963XX_KEYS_POLL_INTERVAL * 3)
+
/*
* known 3368 boards
*/
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/ssb/ssb.h>
+#include <linux/gpio_keys.h>
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
@@ -32,6 +33,8 @@
#define PFX "board: "
+#define BCM963XX_KEYS_POLL_INTERVAL 20
+
static struct board_info board;
/*
@@ -151,11 +154,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);
@@ -217,5 +232,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_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -170,6 +170,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);
@@ -223,10 +224,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_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -222,6 +222,9 @@ int __init board_register_devices(void)
bcm63xx_hsspi_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_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/ssb/ssb.h>
#include <linux/gpio_keys.h>
+#include <linux/spi/spi.h>
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
@@ -225,6 +226,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,27 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -727,10 +727,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,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 <asm/mach-bcm63xx/bcm63xx_nvram.h>
#include <asm/mach-bcm63xx/bcm963xx_tag.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,455 @@
From 301744ecbeece89ab3a9d6beef7802fa22598f00 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 14:53:12 +0100
Subject: [PATCH 1/5] irqchip: add support for bcm6345-style periphery irq
controller
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
.../brcm,bcm6345-periph-intc.txt | 50 +++
drivers/irqchip/Kconfig | 4 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-bcm6345-periph.c | 339 ++++++++++++++++++++
include/linux/irqchip/irq-bcm6345-periph.h | 16 +
5 files changed, 410 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt
create mode 100644 drivers/irqchip/irq-bcm6345-periph.c
create mode 100644 include/linux/irqchip/irq-bcm6345-periph.h
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt
@@ -0,0 +1,50 @@
+Broadcom BCM6345 Level 1 periphery interrupt controller
+
+This block is a interrupt controller that is typically connected directly
+to one of the HW INT lines on each CPU. Every BCM63XX xDSL chip since
+BCM6345 has contained this hardware.
+
+Key elements of the hardware design include:
+
+- 32, 64, or 128 incoming level IRQ lines
+
+- All onchip peripherals are wired directly to an L2 input
+
+- A separate instance of the register set for each CPU, allowing individual
+ peripheral IRQs to be routed to any CPU
+
+- No atomic mask/unmask operations
+
+- No polarity/level/edge settings
+
+- No FIFO or priority encoder logic; software is expected to read all
+ 1-4 status words to determine which IRQs are pending
+
+Required properties:
+
+- compatible: Should be "brcm,bcm6345-periph-intc".
+- reg: Specifies the base physical address and size of the registers.
+ Multiple register addresses may be specified, and must match the amount of
+ parent interrupts.
+- interrupt-controller: Identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
+ source, should be 1.
+- interrupt-parent: Specifies the phandle to the parent interrupt controller
+ this one is cascaded from.
+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller
+ node, valid values depend on the type of parent interrupt controller.
+ Multiple lines are used to route interrupts to different cpus, with the first
+ assumed to be for the boot CPU.
+
+Example:
+
+periph_intc: interrupt-controller@f0406800 {
+ compatible = "brcm,bcm6345-periph-intc";
+ reg = <0x10000020 0x10>, <0x10000030 0x10>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpu_intc>;
+ interrupts = <2>, <3>;
+};
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -75,6 +75,10 @@ config BRCMSTB_L2_IRQ
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+config BCM6345_PERIPH_IRQ
+ bool
+ select IRQ_DOMAIN
+
config DW_APB_ICTL
bool
select GENERIC_IRQ_CHIP
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_MVEBU) += irq-armada-
obj-$(CONFIG_ARCH_MXS) += irq-mxs.o
obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o
+obj-$(CONFIG_BCM6345_PERIPH_IRQ) += irq-bcm6345-periph.o
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
obj-$(CONFIG_METAG) += irq-metag-ext.o
obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-periph.c
@@ -0,0 +1,339 @@
+/*
+ * 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) 2014 Jonas Gorski <jogo@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqchip/irq-bcm6345-periph.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_BCM63XX
+#include <asm/mach-bcm63xx/bcm63xx_irq.h>
+
+#define VIRQ_BASE IRQ_INTERNAL_BASE
+#else
+#define VIRQ_BASE 0
+#endif
+
+#include "irqchip.h"
+
+#define MAX_WORDS 4
+#define MAX_PARENT_IRQS 2
+#define IRQS_PER_WORD 32
+
+struct intc_block {
+ int parent_irq;
+ void __iomem *base;
+ void __iomem *en_reg[MAX_WORDS];
+ void __iomem *status_reg[MAX_WORDS];
+ u32 mask_cache[MAX_WORDS];
+};
+
+struct intc_data {
+ struct irq_chip chip;
+ struct intc_block block[MAX_PARENT_IRQS];
+
+ int num_words;
+
+ struct irq_domain *domain;
+ raw_spinlock_t lock;
+};
+
+static void bcm6345_periph_irq_handle(unsigned int irq, struct irq_desc *desc)
+{
+ struct intc_data *data = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct intc_block *block;
+ unsigned int idx;
+
+ chained_irq_enter(chip, desc);
+
+ for (idx = 0; idx < MAX_PARENT_IRQS; idx++)
+ if (irq == data->block[idx].parent_irq)
+ block = &data->block[idx];
+
+ for (idx = 0; idx < data->num_words; idx++) {
+ int base = idx * IRQS_PER_WORD;
+ unsigned long pending;
+ int hw_irq;
+
+ raw_spin_lock(&data->lock);
+ pending = __raw_readl(block->en_reg[idx]) &
+ __raw_readl(block->status_reg[idx]);
+ raw_spin_unlock(&data->lock);
+
+ for_each_set_bit(hw_irq, &pending, IRQS_PER_WORD) {
+ int virq;
+
+ virq = irq_find_mapping(data->domain, base + hw_irq);
+ generic_handle_irq(virq);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void __bcm6345_periph_enable(struct intc_block *block, int reg, int bit,
+ bool enable)
+{
+ u32 val;
+
+ val = __raw_readl(block->en_reg[reg]);
+ if (enable)
+ val |= BIT(bit);
+ else
+ val &= ~BIT(bit);
+ __raw_writel(val, block->en_reg[reg]);
+}
+
+static void bcm6345_periph_irq_mask(struct irq_data *data)
+{
+ unsigned int i, reg, bit;
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+
+ reg = hwirq / IRQS_PER_WORD;
+ bit = hwirq % IRQS_PER_WORD;
+
+ raw_spin_lock(&priv->lock);
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
+ struct intc_block *block = &priv->block[i];
+
+ if (!block->parent_irq)
+ break;
+
+ __bcm6345_periph_enable(block, reg, bit, false);
+ }
+ raw_spin_unlock(&priv->lock);
+}
+
+static void bcm6345_periph_irq_unmask(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ unsigned int i, reg, bit;
+
+ reg = hwirq / IRQS_PER_WORD;
+ bit = hwirq % IRQS_PER_WORD;
+
+ raw_spin_lock(&priv->lock);
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
+ struct intc_block *block = &priv->block[i];
+
+ if (!block->parent_irq)
+ break;
+
+ if (block->mask_cache[reg] & BIT(bit))
+ __bcm6345_periph_enable(block, reg, bit, true);
+ else
+ __bcm6345_periph_enable(block, reg, bit, false);
+ }
+ raw_spin_unlock(&priv->lock);
+}
+
+#ifdef CONFIG_SMP
+static int bcm6345_periph_set_affinity(struct irq_data *data,
+ const struct cpumask *mask, bool force)
+{
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ struct intc_data *priv = data->domain->host_data;
+ unsigned int i, reg, bit;
+ unsigned long flags;
+ bool enabled;
+ int cpu;
+
+ reg = hwirq / IRQS_PER_WORD;
+ bit = hwirq % IRQS_PER_WORD;
+
+ /* we could route to more than one cpu, but performance
+ suffers, so fix it to one.
+ */
+ cpu = cpumask_any_and(mask, cpu_online_mask);
+ if (cpu >= nr_cpu_ids)
+ return -EINVAL;
+
+ if (cpu >= MAX_PARENT_IRQS)
+ return -EINVAL;
+
+ if (!priv->block[cpu].parent_irq)
+ return -EINVAL;
+
+ raw_spin_lock_irqsave(&priv->lock, flags);
+ enabled = !irqd_irq_masked(data);
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
+ struct intc_block *block = &priv->block[i];
+
+ if (!block->parent_irq)
+ break;
+
+ if (i == cpu) {
+ block->mask_cache[reg] |= BIT(bit);
+ __bcm6345_periph_enable(block, reg, bit, enabled);
+ } else {
+ block->mask_cache[reg] &= ~BIT(bit);
+ __bcm6345_periph_enable(block, reg, bit, false);
+ }
+ }
+ raw_spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+#endif
+
+static int bcm6345_periph_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct intc_data *priv = d->host_data;
+
+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops bcm6345_periph_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = bcm6345_periph_map,
+};
+
+static int __init __bcm6345_periph_intc_init(struct device_node *node,
+ int num_blocks, int *irq,
+ void __iomem **base, int num_words)
+{
+ struct intc_data *data;
+ unsigned int i, w, status_offset;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ raw_spin_lock_init(&data->lock);
+
+ status_offset = num_words * sizeof(u32);
+
+ for (i = 0; i < num_blocks; i++) {
+ struct intc_block *block = &data->block[i];
+
+ block->parent_irq = irq[i];
+ block->base = base[i];
+
+ for (w = 0; w < num_words; w++) {
+ int word_offset = sizeof(u32) * ((num_words - w) - 1);
+
+ block->en_reg[w] = base[i] + word_offset;
+ block->status_reg[w] = base[i] + status_offset;
+ block->status_reg[w] += word_offset;
+
+ /* route all interrupts to line 0 by default */
+ if (i == 0)
+ block->mask_cache[w] = 0xffffffff;
+ }
+
+ irq_set_handler_data(block->parent_irq, data);
+ irq_set_chained_handler(block->parent_irq,
+ bcm6345_periph_irq_handle);
+ }
+
+ data->num_words = num_words;
+
+ data->chip.name = "bcm6345-periph-intc";
+ data->chip.irq_mask = bcm6345_periph_irq_mask;
+ data->chip.irq_unmask = bcm6345_periph_irq_unmask;
+
+#ifdef CONFIG_SMP
+ if (num_blocks > 1)
+ data->chip.irq_set_affinity = bcm6345_periph_set_affinity;
+#endif
+
+ data->domain = irq_domain_add_simple(node, IRQS_PER_WORD * num_words,
+ VIRQ_BASE,
+ &bcm6345_periph_domain_ops, data);
+ if (!data->domain) {
+ kfree(data);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void __init bcm6345_periph_intc_init(int num_blocks, int *irq,
+ void __iomem **base, int num_words)
+{
+ __bcm6345_periph_intc_init(NULL, num_blocks, irq, base, num_words);
+}
+
+#ifdef CONFIG_OF
+static int __init bcm6345_periph_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct resource res;
+ int num_irqs, ret = -EINVAL;
+ int irqs[MAX_PARENT_IRQS] = { 0 };
+ void __iomem *bases[MAX_PARENT_IRQS] = { NULL };
+ int words = 0;
+ int i;
+
+ num_irqs = of_irq_count(node);
+
+ if (num_irqs < 1 || num_irqs > MAX_PARENT_IRQS)
+ return -EINVAL;
+
+ for (i = 0; i < num_irqs; i++) {
+ resource_size_t size;
+
+ irqs[i] = irq_of_parse_and_map(node, i);
+ if (!irqs[i])
+ goto out_unmap;
+
+ if (of_address_to_resource(node, i, &res))
+ goto out_unmap;
+
+ size = resource_size(&res);
+ switch (size) {
+ case 8:
+ case 16:
+ case 32:
+ size = size / 8;
+ break;
+ default:
+ goto out_unmap;
+ }
+
+ if (words && words != size) {
+ ret = -EINVAL;
+ goto out_unmap;
+ }
+ words = size;
+
+ bases[i] = of_iomap(node, i);
+ if (!bases[i]) {
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+ }
+
+ ret = __bcm6345_periph_intc_init(node, num_irqs, irqs, bases, words);
+ if (!ret)
+ return 0;
+
+out_unmap:
+ for (i = 0; i < num_irqs; i++) {
+ iounmap(bases[i]);
+ irq_dispose_mapping(irqs[i]);
+ }
+
+ return ret;
+}
+
+IRQCHIP_DECLARE(bcm6345_periph_intc, "brcm,bcm6345-periph-intc",
+ bcm6345_periph_of_init);
+#endif
--- /dev/null
+++ b/include/linux/irqchip/irq-bcm6345-periph.h
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Nicolas Schichan <nschichan@freebox.fr>
+ */
+
+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H
+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H
+
+void bcm6345_periph_intc_init(int num_blocks, int *irq, void __iomem **base,
+ int num_words);
+
+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H */

View File

@ -0,0 +1,380 @@
From cf908990d4a8ccdb73ee4484aa8cadad379ca314 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 14:54:27 +0100
Subject: [PATCH 2/5] irqchip: add support for bcm6345-style external
interrupt controller
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
.../interrupt-controller/brcm,bcm6345-ext-intc.txt | 29 ++
drivers/irqchip/Kconfig | 4 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-bcm6345-ext.c | 287 ++++++++++++++++++++
include/linux/irqchip/irq-bcm6345-ext.h | 14 +
5 files changed, 335 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
create mode 100644 drivers/irqchip/irq-bcm6345-ext.c
create mode 100644 include/linux/irqchip/irq-bcm6345-ext.h
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
@@ -0,0 +1,29 @@
+Broadcom BCM6345-style external interrupt controller
+
+Required properties:
+
+- compatible: Should be "brcm,bcm6345-l2-intc".
+- reg: Specifies the base physical addresses and size of the registers.
+- interrupt-controller: identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
+ source, Should be 2.
+- interrupt-parent: Specifies the phandle to the parent interrupt controller
+ this one is cascaded from.
+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller
+ node, valid values depend on the type of parent interrupt controller.
+
+Optional properties:
+
+- brcm,field-width: Size of each field (mask, clear, sense, ...) in bits in the
+ register. Defaults to 4.
+
+Example:
+
+ext_intc: interrupt-controller@10000018 {
+ compatible = "brcm,bcm6345-l2-intc";
+ interrupt-parent = <&periph_intc>;
+ #interrupt-cells = <2>;
+ reg = <0x10000018 0x4>;
+ interrupt-controller;
+ interrupts = <24>, <25>, <26>, <27>;
+};
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -75,6 +75,10 @@ config BRCMSTB_L2_IRQ
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+config BCM6345_EXT_IRQ
+ bool
+ select IRQ_DOMAIN
+
config BCM6345_PERIPH_IRQ
bool
select IRQ_DOMAIN
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_MVEBU) += irq-armada-
obj-$(CONFIG_ARCH_MXS) += irq-mxs.o
obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o
+obj-$(CONFIG_BCM6345_EXT_IRQ) += irq-bcm6345-ext.o
obj-$(CONFIG_BCM6345_PERIPH_IRQ) += irq-bcm6345-periph.o
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
obj-$(CONFIG_METAG) += irq-metag-ext.o
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-ext.c
@@ -0,0 +1,287 @@
+/*
+ * 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) 2014 Jonas Gorski <jogo@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqchip/irq-bcm6345-ext.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "irqchip.h"
+
+#ifdef CONFIG_BCM63XX
+#include <asm/mach-bcm63xx/bcm63xx_irq.h>
+
+#define VIRQ_BASE IRQ_EXTERNAL_BASE
+#else
+#define VIRQ_BASE 0
+#endif
+
+#define MAX_IRQS 4
+
+#define EXTIRQ_CFG_SENSE 0
+#define EXTIRQ_CFG_STAT 1
+#define EXTIRQ_CFG_CLEAR 2
+#define EXTIRQ_CFG_MASK 3
+#define EXTIRQ_CFG_BOTHEDGE 4
+#define EXTIRQ_CFG_LEVELSENSE 5
+
+struct intc_data {
+ struct irq_chip chip;
+ struct irq_domain *domain;
+ raw_spinlock_t lock;
+
+ int parent_irq[MAX_IRQS];
+ void __iomem *reg;
+ int shift;
+};
+
+static void bcm6345_ext_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
+{
+ struct intc_data *data = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned int idx;
+
+ chained_irq_enter(chip, desc);
+
+ for (idx = 0; idx < MAX_IRQS; idx++) {
+ if (data->parent_irq[idx] != irq)
+ continue;
+
+ generic_handle_irq(irq_find_mapping(data->domain, idx));
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void bcm6345_ext_intc_irq_ack(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ reg |= hwirq << (EXTIRQ_CFG_CLEAR * priv->shift);
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static void bcm6345_ext_intc_irq_mask(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ reg &= ~(hwirq << (EXTIRQ_CFG_MASK * priv->shift));
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static void bcm6345_ext_intc_irq_unmask(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ reg |= hwirq << (EXTIRQ_CFG_MASK * priv->shift);
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static int bcm6345_ext_intc_set_type(struct irq_data *data,
+ unsigned int flow_type)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ bool levelsense = 0, sense = 0, bothedge = 0;
+ u32 reg;
+
+ flow_type &= IRQ_TYPE_SENSE_MASK;
+
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+
+ switch (flow_type) {
+ case IRQ_TYPE_EDGE_BOTH:
+ bothedge = 1;
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ sense = 1;
+ break;
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ levelsense = 1;
+ sense = 1;
+ break;
+
+ case IRQ_TYPE_LEVEL_LOW:
+ levelsense = 1;
+ break;
+
+ default:
+ pr_err("bogus flow type combination given!\n");
+ return -EINVAL;
+ }
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+
+ if (levelsense)
+ reg |= hwirq << (EXTIRQ_CFG_LEVELSENSE * priv->shift);
+ else
+ reg &= ~(hwirq << (EXTIRQ_CFG_LEVELSENSE * priv->shift));
+ if (sense)
+ reg |= hwirq << (EXTIRQ_CFG_SENSE * priv->shift);
+ else
+ reg &= ~(hwirq << (EXTIRQ_CFG_SENSE * priv->shift));
+ if (bothedge)
+ reg |= hwirq << (EXTIRQ_CFG_BOTHEDGE * priv->shift);
+ else
+ reg &= ~(hwirq << (EXTIRQ_CFG_BOTHEDGE * priv->shift));
+
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+
+ irqd_set_trigger_type(data, flow_type);
+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ __irq_set_handler_locked(data->irq, handle_level_irq);
+ else
+ __irq_set_handler_locked(data->irq, handle_edge_irq);
+
+ return 0;
+}
+
+static int bcm6345_ext_intc_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct intc_data *priv = d->host_data;
+
+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops bcm6345_ext_domain_ops = {
+ .xlate = irq_domain_xlate_twocell,
+ .map = bcm6345_ext_intc_map,
+};
+
+static int __init __bcm6345_ext_intc_init(struct device_node *node,
+ int num_irqs, int *irqs,
+ void __iomem *reg, int shift)
+{
+ struct intc_data *data;
+ unsigned int i;
+ int start = VIRQ_BASE;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ raw_spin_lock_init(&data->lock);
+
+ for (i = 0; i < num_irqs; i++) {
+ data->parent_irq[i] = irqs[i];
+
+ irq_set_handler_data(irqs[i], data);
+ irq_set_chained_handler(irqs[i], bcm6345_ext_intc_irq_handle);
+ }
+
+ data->reg = reg;
+
+ data->chip.name = "bcm6345-ext-intc";
+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack;
+ data->chip.irq_mask = bcm6345_ext_intc_irq_mask;
+ data->chip.irq_unmask = bcm6345_ext_intc_irq_unmask;
+ data->chip.irq_set_type = bcm6345_ext_intc_set_type;
+
+ /*
+ * If we have less than 4 irqs, this is the second controller on
+ * bcm63xx. So increase the VIRQ start to not overlap with the first
+ * one, but only do so if we actually use a non-zero start.
+ *
+ * This can be removed when bcm63xx has no legacy users anymore.
+ */
+ if (start && num_irqs < 4)
+ start += 4;
+
+ data->domain = irq_domain_add_simple(node, num_irqs, start,
+ &bcm6345_ext_domain_ops, data);
+ if (!data->domain) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg,
+ int shift)
+{
+ __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift);
+}
+
+#ifdef CONFIG_OF
+static int __init bcm6345_ext_intc_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ int num_irqs, ret = -EINVAL;
+ unsigned i;
+ void __iomem *base;
+ int irqs[MAX_IRQS] = { 0 };
+ u32 shift;
+
+ num_irqs = of_irq_count(node);
+
+ if (!num_irqs || num_irqs > MAX_IRQS)
+ return -EINVAL;
+
+ if (of_property_read_u32(node, "brcm,field-width", &shift))
+ shift = 4;
+
+ for (i = 0; i < num_irqs; i++) {
+ irqs[i] = irq_of_parse_and_map(node, i);
+ if (!irqs[i]) {
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+ }
+
+ base = of_iomap(node, 0);
+ if (!base)
+ goto out_unmap;
+
+ ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift);
+ if (!ret)
+ return 0;
+out_unmap:
+ iounmap(base);
+
+ for (i = 0; i < num_irqs; i++)
+ irq_dispose_mapping(irqs[i]);
+
+ return ret;
+}
+
+IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc",
+ bcm6345_ext_intc_of_init);
+#endif
--- /dev/null
+++ b/include/linux/irqchip/irq-bcm6345-ext.h
@@ -0,0 +1,14 @@
+/*
+ * 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) 2014 Jonas Gorski <jogo@openwrt.org>
+ */
+
+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H
+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H
+
+void bcm6345_ext_intc_init(int n_irqs, int *irqs, void __iomem *reg, int shift);
+
+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H */

View File

@ -0,0 +1,695 @@
From 86c5d808d660a6aa72cc41d584776fbc8b2736fe Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 14:55:02 +0100
Subject: [PATCH 5/8] MIPS: BCM63XX: switch to IRQ_DOMAIN
Now that we have working IRQ_DOMAIN drivers for both interrupt controllers,
switch to using them.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/Kconfig | 3 +
arch/mips/bcm63xx/irq.c | 612 ++++++++---------------------------------------
2 files changed, 108 insertions(+), 507 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -197,6 +197,9 @@ config BCM63XX
select SYNC_R4K
select DMA_NONCOHERENT
select IRQ_CPU
+ select BCM6345_EXT_IRQ
+ select BCM6345_PERIPH_IRQ
+ select IRQ_DOMAIN
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_HAS_EARLY_PRINTK
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -12,7 +12,9 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/irq.h>
-#include <linux/spinlock.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/irq-bcm6345-ext.h>
+#include <linux/irqchip/irq-bcm6345-periph.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <bcm63xx_cpu.h>
@@ -20,544 +22,140 @@
#include <bcm63xx_io.h>
#include <bcm63xx_irq.h>
-
-static DEFINE_SPINLOCK(ipic_lock);
-static DEFINE_SPINLOCK(epic_lock);
-
-static u32 irq_stat_addr[2];
-static u32 irq_mask_addr[2];
-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;
-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, const struct cpumask *m);
-
-
-static inline u32 get_ext_irq_perf_reg(int irq)
-{
- if (irq < 4)
- return ext_irq_cfg_reg1;
- return ext_irq_cfg_reg2;
-}
-
-static inline void handle_internal(int intbit)
-{
- if (is_ext_irq_cascaded &&
- intbit >= ext_irq_start && intbit <= ext_irq_end)
- do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE);
- else
- do_IRQ(intbit + IRQ_INTERNAL_BASE);
-}
-
-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 &= cpumask_test_cpu(cpu, m);
- else if (irqd_affinity_was_set(d))
- enable &= cpumask_test_cpu(cpu, d->affinity);
-#endif
- return enable;
-}
-
-/*
- * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
- * prioritize any interrupt relatively to another. the static counter
- * will resume the loop where it ended the last time we left this
- * function.
- */
-
-#define BUILD_IPIC_INTERNAL(width) \
-void __dispatch_internal_##width(int cpu) \
-{ \
- u32 pending[width / 32]; \
- unsigned int src, tgt; \
- bool irqs_pending = false; \
- static unsigned int i[2]; \
- unsigned 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; \
- \
- val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
- val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
- pending[--tgt] = val; \
- \
- if (val) \
- irqs_pending = true; \
- } \
- spin_unlock_irqrestore(&ipic_lock, flags); \
- \
- if (!irqs_pending) \
- return; \
- \
- while (1) { \
- unsigned int to_call = *next; \
- \
- *next = (*next + 1) & (width - 1); \
- if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
- handle_internal(to_call); \
- break; \
- } \
- } \
-} \
- \
-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; \
- int cpu; \
- \
- spin_lock_irqsave(&ipic_lock, flags); \
- for_each_present_cpu(cpu) { \
- if (!irq_mask_addr[cpu]) \
- break; \
- \
- val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
- val &= ~(1 << bit); \
- bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
- } \
- spin_unlock_irqrestore(&ipic_lock, flags); \
-} \
- \
-static void __internal_irq_unmask_##width(struct irq_data *d, \
- const struct cpumask *m) \
-{ \
- u32 val; \
- unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
- unsigned reg = (irq / 32) ^ (width/32 - 1); \
- unsigned bit = irq & 0x1f; \
- unsigned long flags; \
- int cpu; \
- \
- spin_lock_irqsave(&ipic_lock, flags); \
- for_each_present_cpu(cpu) { \
- if (!irq_mask_addr[cpu]) \
- break; \
- \
- val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
- if (enable_irq_for_cpu(cpu, d, m)) \
- val |= (1 << bit); \
- else \
- val &= ~(1 << bit); \
- bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
- } \
- spin_unlock_irqrestore(&ipic_lock, flags); \
-}
-
-BUILD_IPIC_INTERNAL(32);
-BUILD_IPIC_INTERNAL(64);
-
-asmlinkage void plat_irq_dispatch(void)
-{
- u32 cause;
-
- do {
- cause = read_c0_cause() & read_c0_status() & ST0_IM;
-
- if (!cause)
- break;
-
- 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(0);
- 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)
- do_IRQ(IRQ_EXT_1);
- if (cause & CAUSEF_IP5)
- do_IRQ(IRQ_EXT_2);
- if (cause & CAUSEF_IP6)
- do_IRQ(IRQ_EXT_3);
- }
- } while (1);
-}
-
-/*
- * internal IRQs operations: only mask/unmask on PERF irq mask
- * register.
- */
-static void bcm63xx_internal_irq_mask(struct irq_data *d)
-{
- internal_irq_mask(d);
-}
-
-static void bcm63xx_internal_irq_unmask(struct irq_data *d)
-{
- internal_irq_unmask(d, NULL);
-}
-
-/*
- * external IRQs operations: mask/unmask and clear on PERF external
- * irq control register.
- */
-static void bcm63xx_external_irq_mask(struct irq_data *d)
-{
- 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())
- reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4);
- else
- 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_get_irq_data(irq + ext_irq_start));
-}
-
-static void bcm63xx_external_irq_unmask(struct irq_data *d)
-{
- 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())
- reg |= EXTIRQ_CFG_MASK_6348(irq % 4);
- else
- 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_get_irq_data(irq + ext_irq_start),
- NULL);
-}
-
-static void bcm63xx_external_irq_clear(struct irq_data *d)
-{
- 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())
- reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4);
- else
- 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,
- unsigned int flow_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;
-
- if (flow_type == IRQ_TYPE_NONE)
- flow_type = IRQ_TYPE_LEVEL_LOW;
-
- levelsense = sense = bothedge = 0;
- switch (flow_type) {
- case IRQ_TYPE_EDGE_BOTH:
- bothedge = 1;
- break;
-
- case IRQ_TYPE_EDGE_RISING:
- sense = 1;
- break;
-
- case IRQ_TYPE_EDGE_FALLING:
- break;
-
- case IRQ_TYPE_LEVEL_HIGH:
- levelsense = 1;
- sense = 1;
- break;
-
- case IRQ_TYPE_LEVEL_LOW:
- levelsense = 1;
- break;
-
- default:
- printk(KERN_ERR "bogus flow type combination given !\n");
- return -EINVAL;
- }
-
- regaddr = get_ext_irq_perf_reg(irq);
- spin_lock_irqsave(&epic_lock, flags);
- reg = bcm_perf_readl(regaddr);
- irq %= 4;
-
- switch (bcm63xx_get_cpu_id()) {
- case BCM6348_CPU_ID:
- if (levelsense)
- reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
- else
- reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq);
- if (sense)
- reg |= EXTIRQ_CFG_SENSE_6348(irq);
- else
- reg &= ~EXTIRQ_CFG_SENSE_6348(irq);
- if (bothedge)
- reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
- else
- reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
- break;
-
- case BCM3368_CPU_ID:
- case BCM6328_CPU_ID:
- case BCM6338_CPU_ID:
- case BCM6345_CPU_ID:
- case BCM6358_CPU_ID:
- case BCM6362_CPU_ID:
- case BCM6368_CPU_ID:
- if (levelsense)
- reg |= EXTIRQ_CFG_LEVELSENSE(irq);
- else
- reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
- if (sense)
- reg |= EXTIRQ_CFG_SENSE(irq);
- else
- reg &= ~EXTIRQ_CFG_SENSE(irq);
- if (bothedge)
- reg |= EXTIRQ_CFG_BOTHEDGE(irq);
- else
- reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
- break;
- default:
- BUG();
- }
-
- 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))
- __irq_set_handler_locked(d->irq, handle_level_irq);
- else
- __irq_set_handler_locked(d->irq, handle_edge_irq);
-
- 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,
- .irq_unmask = bcm63xx_internal_irq_unmask,
-};
-
-static struct irq_chip bcm63xx_external_irq_chip = {
- .name = "bcm63xx_epic",
- .irq_ack = bcm63xx_external_irq_clear,
-
- .irq_mask = bcm63xx_external_irq_mask,
- .irq_unmask = bcm63xx_external_irq_unmask,
-
- .irq_set_type = bcm63xx_external_irq_set_type,
-};
-
-static struct irqaction cpu_ip2_cascade_action = {
- .handler = no_action,
- .name = "cascade_ip2",
- .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",
- .flags = IRQF_NO_THREAD,
-};
-
-static void bcm63xx_init_irq(void)
+void __init arch_init_irq(void)
{
- int irq_bits;
-
- irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
- irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
- irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
- irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
+ void __iomem *periph_bases[2];
+ void __iomem *ext_intc_bases[2];
+ int periph_irq_count, periph_width, ext_irq_count, ext_shift;
+ int periph_irqs[2] = { 2, 3 };
+ int ext_irqs[6];
+
+ periph_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
+ periph_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
+ ext_intc_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
+ ext_intc_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
switch (bcm63xx_get_cpu_id()) {
case BCM3368_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
- irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
- irq_stat_addr[1] = 0;
- irq_mask_addr[1] = 0;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
+ periph_bases[0] += PERF_IRQMASK_3368_REG;
+ periph_irq_count = 1;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_3368;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_3368_EXT_IRQ0;
+ ext_irqs[1] = BCM_3368_EXT_IRQ1;
+ ext_irqs[2] = BCM_3368_EXT_IRQ2;
+ ext_irqs[3] = BCM_3368_EXT_IRQ3;
+ ext_shift = 4;
break;
case BCM6328_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
- irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
- irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
- irq_mask_addr[1] += PERF_IRQMASK_6328_REG(1);
- irq_bits = 64;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
+ periph_bases[0] += PERF_IRQMASK_6328_REG(0);
+ periph_bases[1] += PERF_IRQMASK_6328_REG(1);
+ periph_irq_count = 2;
+ periph_width = 2;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6328;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_6328_EXT_IRQ0;
+ ext_irqs[1] = BCM_6328_EXT_IRQ1;
+ ext_irqs[2] = BCM_6328_EXT_IRQ2;
+ ext_irqs[3] = BCM_6328_EXT_IRQ3;
+ ext_shift = 4;
break;
case BCM6338_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
- irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
- irq_stat_addr[1] = 0;
- irq_mask_addr[1] = 0;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
+ periph_bases[0] += PERF_IRQMASK_6338_REG;
+ periph_irq_count = 1;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6338;
+ ext_irq_count = 4;
+ ext_irqs[0] = 3;
+ ext_irqs[1] = 4;
+ ext_irqs[2] = 5;
+ ext_irqs[3] = 6;
+ ext_shift = 4;
break;
case BCM6345_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
- irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
- irq_stat_addr[1] = 0;
- irq_mask_addr[1] = 0;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
+ periph_bases[0] += PERF_IRQMASK_6345_REG;
+ periph_irq_count = 1;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6345;
+ ext_irq_count = 4;
+ ext_irqs[0] = 3;
+ ext_irqs[1] = 4;
+ ext_irqs[2] = 5;
+ ext_irqs[3] = 6;
+ ext_shift = 4;
break;
case BCM6348_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
- irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
- irq_stat_addr[1] = 0;
- irq_mask_addr[1] = 0;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
+ periph_bases[0] += PERF_IRQMASK_6348_REG;
+ periph_irq_count = 1;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6348;
+ ext_irq_count = 4;
+ ext_irqs[0] = 3;
+ ext_irqs[1] = 4;
+ ext_irqs[2] = 5;
+ ext_irqs[3] = 6;
+ ext_shift = 5;
break;
case BCM6358_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
- irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
- irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
- irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
- irq_bits = 32;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
+ periph_bases[0] += PERF_IRQMASK_6358_REG(0);
+ periph_bases[1] += PERF_IRQMASK_6358_REG(1);
+ periph_irq_count = 2;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_6358_EXT_IRQ0;
+ ext_irqs[1] = BCM_6358_EXT_IRQ1;
+ ext_irqs[2] = BCM_6358_EXT_IRQ2;
+ ext_irqs[3] = BCM_6358_EXT_IRQ3;
+ ext_shift = 4;
break;
case BCM6362_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
- irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
- irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
- irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
- irq_bits = 64;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
+ periph_bases[0] += PERF_IRQMASK_6362_REG(0);
+ periph_bases[1] += PERF_IRQMASK_6362_REG(1);
+ periph_irq_count = 2;
+ periph_width = 2;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6362;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_6362_EXT_IRQ0;
+ ext_irqs[1] = BCM_6362_EXT_IRQ1;
+ ext_irqs[2] = BCM_6362_EXT_IRQ2;
+ ext_irqs[3] = BCM_6362_EXT_IRQ3;
+ ext_shift = 4;
break;
case BCM6368_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
- irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
- irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
- irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
- irq_bits = 64;
+ periph_bases[0] += PERF_IRQMASK_6368_REG(0);
+ periph_bases[1] += PERF_IRQMASK_6368_REG(1);
+ periph_irq_count = 2;
+ periph_width = 2;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6368;
+ ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6368;
ext_irq_count = 6;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
- ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
+ ext_irqs[0] = BCM_6368_EXT_IRQ0;
+ ext_irqs[1] = BCM_6368_EXT_IRQ1;
+ ext_irqs[2] = BCM_6368_EXT_IRQ2;
+ ext_irqs[3] = BCM_6368_EXT_IRQ3;
+ ext_irqs[4] = BCM_6368_EXT_IRQ4;
+ ext_irqs[5] = BCM_6368_EXT_IRQ5;
+ ext_shift = 4;
break;
default:
BUG();
}
- if (irq_bits == 32) {
- dispatch_internal = __dispatch_internal_32;
- internal_irq_mask = __internal_irq_mask_32;
- internal_irq_unmask = __internal_irq_unmask_32;
- } else {
- dispatch_internal = __dispatch_internal_64;
- internal_irq_mask = __internal_irq_mask_64;
- internal_irq_unmask = __internal_irq_unmask_64;
- }
-}
-
-void __init arch_init_irq(void)
-{
- int i;
-
- bcm63xx_init_irq();
mips_cpu_irq_init();
- for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i)
- irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
- handle_level_irq);
-
- for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + ext_irq_count; ++i)
- irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
- handle_edge_irq);
-
- if (!is_ext_irq_cascaded) {
- for (i = 3; i < 3 + ext_irq_count; ++i)
- setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action);
- }
-
- setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
-#ifdef CONFIG_SMP
- 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;
-
- cpumask_clear(irq_default_affinity);
- cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
- }
-#endif
+ bcm6345_periph_intc_init(periph_irq_count, periph_irqs, periph_bases,
+ periph_width);
+ bcm6345_ext_intc_init(4, ext_irqs, ext_intc_bases[0], ext_shift);
+ if (ext_irq_count > 4)
+ bcm6345_ext_intc_init(2, &ext_irqs[4], ext_intc_bases[1],
+ ext_shift);
}

View File

@ -0,0 +1,57 @@
From 4fd286c3e5a5bebab0391cf1937695b3ed6721a3 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 20:20:30 +0100
Subject: [PATCH 4/5] MIPS: BCM63XX: wire up BCM6358's external interrupts 4
and 5
Due to the external interrupts being non consecutive, the previous
implementation did not support them. Now that we treat both registers
as separate irq controllers, there is no such limitation anymore and
we can expose them for drivers to use.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 5 ++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 2 ++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 1 +
3 files changed, 7 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -109,11 +109,14 @@ void __init arch_init_irq(void)
periph_width = 1;
ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358;
- ext_irq_count = 4;
+ ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6358;
+ ext_irq_count = 6;
ext_irqs[0] = BCM_6358_EXT_IRQ0;
ext_irqs[1] = BCM_6358_EXT_IRQ1;
ext_irqs[2] = BCM_6358_EXT_IRQ2;
ext_irqs[3] = BCM_6358_EXT_IRQ3;
+ ext_irqs[4] = BCM_6358_EXT_IRQ4;
+ ext_irqs[5] = BCM_6358_EXT_IRQ5;
ext_shift = 4;
break;
case BCM6362_CPU_ID:
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -895,6 +895,8 @@ enum bcm63xx_irq {
#define BCM_6358_EXT_IRQ1 (IRQ_INTERNAL_BASE + 26)
#define BCM_6358_EXT_IRQ2 (IRQ_INTERNAL_BASE + 27)
#define BCM_6358_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28)
+#define BCM_6358_EXT_IRQ4 (IRQ_INTERNAL_BASE + 20)
+#define BCM_6358_EXT_IRQ5 (IRQ_INTERNAL_BASE + 21)
/*
* 6362 irqs
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -243,6 +243,7 @@
#define PERF_EXTIRQ_CFG_REG_6362 0x18
#define PERF_EXTIRQ_CFG_REG_6368 0x18
+#define PERF_EXTIRQ_CFG_REG2_6358 0x1c
#define PERF_EXTIRQ_CFG_REG2_6368 0x1c
/* for 6348 only */

View File

@ -0,0 +1,77 @@
From c50acd37b425a8a907a6f7f93aa2e658256e79ce Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:08:36 +0100
Subject: [PATCH 40/53] MIPS: BCM63XX: add a new cpu variant helper
---
arch/mips/bcm63xx/cpu.c | 10 ++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 18 ++++++++++++++++++
2 files changed, 28 insertions(+)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -27,6 +27,8 @@ EXPORT_SYMBOL(bcm63xx_irqs);
u16 bcm63xx_cpu_id __read_mostly;
EXPORT_SYMBOL(bcm63xx_cpu_id);
+static u32 bcm63xx_cpu_variant __read_mostly;
+
static u8 bcm63xx_cpu_rev;
static unsigned int bcm63xx_cpu_freq;
static unsigned int bcm63xx_memory_size;
@@ -99,6 +101,13 @@ static const int bcm6368_irqs[] = {
};
+u32 bcm63xx_get_cpu_variant(void)
+{
+ return bcm63xx_cpu_variant;
+}
+
+EXPORT_SYMBOL(bcm63xx_get_cpu_variant);
+
u8 bcm63xx_get_cpu_rev(void)
{
return bcm63xx_cpu_rev;
@@ -333,6 +342,7 @@ void __init bcm63xx_cpu_init(void)
/* read out CPU type */
tmp = bcm_readl(chipid_reg);
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
+ bcm63xx_cpu_variant = bcm63xx_cpu_id;
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
switch (bcm63xx_cpu_id) {
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -19,6 +19,7 @@
#define BCM6368_CPU_ID 0x6368
void __init bcm63xx_cpu_init(void);
+u32 bcm63xx_get_cpu_variant(void);
u8 bcm63xx_get_cpu_rev(void);
unsigned int bcm63xx_get_cpu_freq(void);
@@ -82,6 +83,23 @@ static inline u16 __pure bcm63xx_get_cpu
#define BCMCPU_IS_6362() (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
#define BCMCPU_IS_6368() (bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
+#define BCMCPU_VARIANT_IS_3368() \
+ (bcm63xx_get_cpu_variant() == BCM3368_CPU_ID)
+#define BCMCPU_VARIANT_IS_6328() \
+ (bcm63xx_get_cpu_variant() == BCM6328_CPU_ID)
+#define BCMCPU_VARIANT_IS_6338() \
+ (bcm63xx_get_cpu_variant() == BCM6338_CPU_ID)
+#define BCMCPU_VARIANT_IS_6345() \
+ (bcm63xx_get_cpu_variant() == BCM6345_CPU_ID)
+#define BCMCPU_VARIANT_IS_6348() \
+ (bcm63xx_get_cpu_variant() == BCM6348_CPU_ID)
+#define BCMCPU_VARIANT_IS_6358() \
+ (bcm63xx_get_cpu_cariant() == BCM6358_CPU_ID)
+#define BCMCPU_VARIANT_IS_6362() \
+ (bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
+#define BCMCPU_VARIANT_IS_6368() \
+ (bcm63xx_get_cpu_variant() == BCM6368_CPU_ID)
+
/*
* While registers sets are (mostly) the same across 63xx CPU, base
* address of these sets do change.

View File

@ -0,0 +1,23 @@
From 3bd8e2535265f06f79ed9c0ad788405441e091dc Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:22:41 +0100
Subject: [PATCH 21/45] MIPS: BCM63XX: define variant id field
Some SoC have a variant id field in the chip id register.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -9,6 +9,8 @@
#define PERF_REV_REG 0x0
#define REV_CHIPID_SHIFT 16
#define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT)
+#define REV_VARID_SHIFT 12
+#define REV_VARID_MASK (0xf << REV_VARID_SHIFT)
#define REV_REVID_SHIFT 0
#define REV_REVID_MASK (0xff << REV_REVID_SHIFT)

View File

@ -0,0 +1,68 @@
From d59120f23279ef62a48d9f94847254b061d0a8b6 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:30:59 +0100
Subject: [PATCH 22/45] MIPS: BCM63XX: detect BCM6328 variants
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/cpu.c | 10 ++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 8 ++++++--
2 files changed, 16 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -305,6 +305,7 @@ void __init bcm63xx_cpu_init(void)
unsigned int tmp;
unsigned int cpu = smp_processor_id();
u32 chipid_reg;
+ u8 __maybe_unused varid = 0;
/* soc registers location depends on cpu type */
chipid_reg = 0;
@@ -344,6 +345,7 @@ void __init bcm63xx_cpu_init(void)
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
bcm63xx_cpu_variant = bcm63xx_cpu_id;
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
+ varid = (tmp & REV_VARID_MASK) >> REV_VARID_SHIFT;
switch (bcm63xx_cpu_id) {
case BCM3368_CPU_ID:
@@ -353,6 +355,14 @@ void __init bcm63xx_cpu_init(void)
case BCM6328_CPU_ID:
bcm63xx_regs_base = bcm6328_regs_base;
bcm63xx_irqs = bcm6328_irqs;
+
+ if (varid == 1)
+ bcm63xx_cpu_variant = BCM63281_CPU_ID;
+ else if (varid == 3)
+ bcm63xx_cpu_variant = BCM63283_CPU_ID;
+ else
+ pr_warn("unknown BCM6328 variant: %x\n", varid);
+
break;
case BCM6338_CPU_ID:
bcm63xx_regs_base = bcm6338_regs_base;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -11,6 +11,8 @@
*/
#define BCM3368_CPU_ID 0x3368
#define BCM6328_CPU_ID 0x6328
+#define BCM63281_CPU_ID 0x63281
+#define BCM63283_CPU_ID 0x63283
#define BCM6338_CPU_ID 0x6338
#define BCM6345_CPU_ID 0x6345
#define BCM6348_CPU_ID 0x6348
@@ -85,8 +87,10 @@ static inline u16 __pure bcm63xx_get_cpu
#define BCMCPU_VARIANT_IS_3368() \
(bcm63xx_get_cpu_variant() == BCM3368_CPU_ID)
-#define BCMCPU_VARIANT_IS_6328() \
- (bcm63xx_get_cpu_variant() == BCM6328_CPU_ID)
+#define BCMCPU_VARIANT_IS_63281() \
+ (bcm63xx_get_cpu_variant() == BCM63281_CPU_ID)
+#define BCMCPU_VARIANT_IS_63283() \
+ (bcm63xx_get_cpu_variant() == BCM63283_CPU_ID)
#define BCMCPU_VARIANT_IS_6338() \
(bcm63xx_get_cpu_variant() == BCM6338_CPU_ID)
#define BCMCPU_VARIANT_IS_6345() \

View File

@ -0,0 +1,46 @@
From 04458c3db8eb79da21ecde40ab36a1dde52bef06 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:33:28 +0100
Subject: [PATCH 23/45] MIPS: BCM63XX: detect BCM6362 variants
---
arch/mips/bcm63xx/cpu.c | 8 ++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 3 +++
2 files changed, 11 insertions(+)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -383,6 +383,14 @@ void __init bcm63xx_cpu_init(void)
case BCM6362_CPU_ID:
bcm63xx_regs_base = bcm6362_regs_base;
bcm63xx_irqs = bcm6362_irqs;
+
+ if (varid == 1)
+ bcm63xx_cpu_variant = BCM6362_CPU_ID;
+ else if (varid == 2)
+ bcm63xx_cpu_variant = BCM6361_CPU_ID;
+ else
+ pr_warn("unknown BCM6362 variant: %x\n", varid);
+
break;
case BCM6368_CPU_ID:
bcm63xx_regs_base = bcm6368_regs_base;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -17,6 +17,7 @@
#define BCM6345_CPU_ID 0x6345
#define BCM6348_CPU_ID 0x6348
#define BCM6358_CPU_ID 0x6358
+#define BCM6361_CPU_ID 0x6361
#define BCM6362_CPU_ID 0x6362
#define BCM6368_CPU_ID 0x6368
@@ -99,6 +100,8 @@ static inline u16 __pure bcm63xx_get_cpu
(bcm63xx_get_cpu_variant() == BCM6348_CPU_ID)
#define BCMCPU_VARIANT_IS_6358() \
(bcm63xx_get_cpu_cariant() == BCM6358_CPU_ID)
+#define BCMCPU_VARIANT_IS_6361() \
+ (bcm63xx_get_cpu_variant() == BCM6361_CPU_ID)
#define BCMCPU_VARIANT_IS_6362() \
(bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
#define BCMCPU_VARIANT_IS_6368() \

View File

@ -0,0 +1,48 @@
From 825cc67e56b5e624a05f6850a86d91508b786848 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:36:56 +0100
Subject: [PATCH 24/44] MIPS: BCM63XX: detect BCM6368 variants
The DSL-less BCM6368 variant BCM6367 uses a different chip id. Apart
from missing DSL, there is no difference to BCM6368, so treat it such.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/cpu.c | 4 ++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 3 +++
2 files changed, 7 insertions(+)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -393,8 +393,12 @@ void __init bcm63xx_cpu_init(void)
break;
case BCM6368_CPU_ID:
+ case BCM6369_CPU_ID:
bcm63xx_regs_base = bcm6368_regs_base;
bcm63xx_irqs = bcm6368_irqs;
+
+ /* BCM6369 is a BCM6368 without xDSL, so treat it the same */
+ bcm63xx_cpu_id = BCM6368_CPU_ID;
break;
default:
panic("unsupported broadcom CPU %x", bcm63xx_cpu_id);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -20,6 +20,7 @@
#define BCM6361_CPU_ID 0x6361
#define BCM6362_CPU_ID 0x6362
#define BCM6368_CPU_ID 0x6368
+#define BCM6369_CPU_ID 0x6369
void __init bcm63xx_cpu_init(void);
u32 bcm63xx_get_cpu_variant(void);
@@ -106,6 +107,8 @@ static inline u16 __pure bcm63xx_get_cpu
(bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
#define BCMCPU_VARIANT_IS_6368() \
(bcm63xx_get_cpu_variant() == BCM6368_CPU_ID)
+#define BCMCPU_VARIANT_IS_6369() \
+ (bcm63xx_get_cpu_variant() == BCM6369_CPU_ID)
/*
* While registers sets are (mostly) the same across 63xx CPU, base

View File

@ -0,0 +1,20 @@
From f67f8134b4537c8bbafe7e1975edfe808b813997 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 8 Dec 2013 03:05:54 +0100
Subject: [PATCH 45/53] MIPS: BCM63XX: fix PCIe memory window size
---
arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
@@ -41,7 +41,7 @@
BCM_CB_MEM_SIZE - 1)
#define BCM_PCIE_MEM_BASE_PA 0x10f00000
-#define BCM_PCIE_MEM_SIZE (16 * 1024 * 1024)
+#define BCM_PCIE_MEM_SIZE (1 * 1024 * 1024)
#define BCM_PCIE_MEM_END_PA (BCM_PCIE_MEM_BASE_PA + \
BCM_PCIE_MEM_SIZE - 1)

View File

@ -0,0 +1,70 @@
From aa05464973bc176478af462ca7c53a9239c651d4 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 8 Dec 2013 03:13:06 +0100
Subject: [PATCH 46/53] MIPS: BCM63XX: dynamically set the pcie memory windows
Different SoCs use different memory windows (and sizes), so don't
hardcode it.
---
arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 8 ++++----
arch/mips/pci/pci-bcm63xx.c | 15 ++++++++++-----
2 files changed, 14 insertions(+), 9 deletions(-)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
@@ -40,10 +40,10 @@
#define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \
BCM_CB_MEM_SIZE - 1)
-#define BCM_PCIE_MEM_BASE_PA 0x10f00000
-#define BCM_PCIE_MEM_SIZE (1 * 1024 * 1024)
-#define BCM_PCIE_MEM_END_PA (BCM_PCIE_MEM_BASE_PA + \
- BCM_PCIE_MEM_SIZE - 1)
+#define BCM_PCIE_MEM_BASE_PA_6328 0x10f00000
+#define BCM_PCIE_MEM_SIZE_6328 (1 * 1024 * 1024)
+#define BCM_PCIE_MEM_END_PA_6328 (BCM_PCIE_MEM_BASE_PA_6328 + \
+ BCM_PCIE_MEM_SIZE_6328 - 1)
/*
* Internal registers are accessed through KSEG3
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -77,8 +77,8 @@ struct pci_controller bcm63xx_cb_control
static struct resource bcm_pcie_mem_resource = {
.name = "bcm63xx PCIe memory space",
- .start = BCM_PCIE_MEM_BASE_PA,
- .end = BCM_PCIE_MEM_END_PA,
+ .start = 0,
+ .end = 0,
.flags = IORESOURCE_MEM,
};
@@ -195,12 +195,12 @@ static int __init bcm63xx_register_pcie(
bcm_pcie_writel(val, PCIE_CONFIG2_REG);
/* set bar0 to little endian */
- val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
- val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
+ val = (bcm_pcie_mem_resource.start >> 20) << BASEMASK_BASE_SHIFT;
+ val |= (bcm_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT;
val |= BASEMASK_REMAP_EN;
bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
- val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
+ val = (bcm_pcie_mem_resource.start >> 20) << REBASE_ADDR_BASE_SHIFT;
bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
register_pci_controller(&bcm63xx_pcie_controller);
@@ -334,6 +334,11 @@ static int __init bcm63xx_pci_init(void)
if (!bcm63xx_pci_enabled)
return -ENODEV;
+ if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
+ bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_6328;
+ bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_6328;
+ }
+
switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
case BCM6362_CPU_ID:

View File

@ -0,0 +1,56 @@
From f1477f6e3551fd6beecfee5368fed1325dcd421f Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:54:51 +0100
Subject: [PATCH 47/53] MIPS: BCM63XX: widen cpuid field
---
arch/mips/bcm63xx/cpu.c | 2 +-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -24,7 +24,7 @@ EXPORT_SYMBOL(bcm63xx_regs_base);
const int *bcm63xx_irqs;
EXPORT_SYMBOL(bcm63xx_irqs);
-u16 bcm63xx_cpu_id __read_mostly;
+u32 bcm63xx_cpu_id __read_mostly;
EXPORT_SYMBOL(bcm63xx_cpu_id);
static u32 bcm63xx_cpu_variant __read_mostly;
@@ -127,7 +127,7 @@ unsigned int bcm63xx_get_memory_size(voi
static unsigned int detect_cpu_clock(void)
{
- u16 cpu_id = bcm63xx_get_cpu_id();
+ u32 cpu_id = bcm63xx_get_cpu_id();
switch (cpu_id) {
case BCM3368_CPU_ID:
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -27,7 +27,7 @@ u32 bcm63xx_get_cpu_variant(void);
u8 bcm63xx_get_cpu_rev(void);
unsigned int bcm63xx_get_cpu_freq(void);
-static inline u16 __pure __bcm63xx_get_cpu_id(const u16 cpu_id)
+static inline u32 __pure __bcm63xx_get_cpu_id(const u32 cpu_id)
{
switch (cpu_id) {
#ifdef CONFIG_BCM63XX_CPU_3368
@@ -69,11 +69,11 @@ static inline u16 __pure __bcm63xx_get_c
return cpu_id;
}
-extern u16 bcm63xx_cpu_id;
+extern u32 bcm63xx_cpu_id;
-static inline u16 __pure bcm63xx_get_cpu_id(void)
+static inline u32 __pure bcm63xx_get_cpu_id(void)
{
- const u16 cpu_id = bcm63xx_cpu_id;
+ const u32 cpu_id = bcm63xx_cpu_id;
return __bcm63xx_get_cpu_id(cpu_id);
}

View File

@ -0,0 +1,39 @@
From 6f5658c845cf1f79213b1d20423a04967259fdaa Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 15 Dec 2013 20:46:26 +0100
Subject: [PATCH 48/53] MIPS: BCM63XX: increase number of IRQs
Newer SoCs have 128 bit wide irq registers, thus 128 available internal
interupts.
---
arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h | 4 +++-
arch/mips/include/asm/mach-bcm63xx/irq.h | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h
@@ -1,10 +1,12 @@
#ifndef BCM63XX_IRQ_H_
#define BCM63XX_IRQ_H_
+#include <irq.h>
#include <bcm63xx_cpu.h>
#define IRQ_INTERNAL_BASE 8
-#define IRQ_EXTERNAL_BASE 100
+#define NR_INTERNAL_IRQS 128
+#define IRQ_EXTERNAL_BASE (IRQ_INTERNAL_BASE + NR_INTERNAL_IRQS)
#define IRQ_EXT_0 (IRQ_EXTERNAL_BASE + 0)
#define IRQ_EXT_1 (IRQ_EXTERNAL_BASE + 1)
#define IRQ_EXT_2 (IRQ_EXTERNAL_BASE + 2)
--- a/arch/mips/include/asm/mach-bcm63xx/irq.h
+++ b/arch/mips/include/asm/mach-bcm63xx/irq.h
@@ -1,7 +1,7 @@
#ifndef __ASM_MACH_BCM63XX_IRQ_H
#define __ASM_MACH_BCM63XX_IRQ_H
-#define NR_IRQS 128
+#define NR_IRQS 256
#define MIPS_CPU_IRQ_BASE 0
#endif

View File

@ -0,0 +1,735 @@
From 98f63141190ac02c58b78d58f771bd263c61d756 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 17:14:17 +0100
Subject: [PATCH 48/56] MIPS: BCM63XX: add support for BCM63268
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/Kconfig | 5 +
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
arch/mips/bcm63xx/clk.c | 25 ++++-
arch/mips/bcm63xx/cpu.c | 59 +++++++++-
arch/mips/bcm63xx/dev-flash.c | 6 +
arch/mips/bcm63xx/dev-spi.c | 4 +-
arch/mips/bcm63xx/irq.c | 20 +++-
arch/mips/bcm63xx/reset.c | 21 ++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 130 ++++++++++++++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 2 +
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 79 +++++++++++++
arch/mips/include/asm/mach-bcm63xx/ioremap.h | 1 +
12 files changed, 342 insertions(+), 12 deletions(-)
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -60,6 +60,11 @@ config BCM63XX_CPU_6368
select HW_HAS_PCI
select BCM63XX_OHCI
select BCM63XX_EHCI
+
+config BCM63XX_CPU_63268
+ bool "support 63268 CPU"
+ select SYS_HAS_CPU_BMIPS4350
+ select HW_HAS_PCI
endmenu
source "arch/mips/bcm63xx/boards/Kconfig"
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -717,7 +717,7 @@ void __init board_prom_init(void)
/* read base address of boot chip select (0)
* 6328/6362 do not have MPI but boot from a fixed address
*/
- if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
+ if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) {
val = 0x18000000;
} else {
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -133,6 +133,8 @@ static void enetsw_set(struct clk *clk,
CKCTL_6368_SWPKT_USB_EN |
CKCTL_6368_SWPKT_SAR_EN,
enable);
+ else if (BCMCPU_IS_63268())
+ bcm_hwclock_set(CKCTL_63268_ROBOSW_EN, enable);
else
return;
@@ -177,6 +179,8 @@ 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 if (BCMCPU_IS_63268())
+ bcm_hwclock_set(CKCTL_63268_USBH_EN, enable);
else
return;
@@ -199,6 +203,8 @@ 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 if (BCMCPU_IS_63268())
+ bcm_hwclock_set(CKCTL_63268_USBD_EN, enable);
else
return;
@@ -225,9 +231,13 @@ static void spi_set(struct clk *clk, int
mask = CKCTL_6358_SPI_EN;
else if (BCMCPU_IS_6362())
mask = CKCTL_6362_SPI_EN;
- else
- /* BCMCPU_IS_6368 */
+ else if (BCMCPU_IS_6368())
mask = CKCTL_6368_SPI_EN;
+ else if (BCMCPU_IS_63268())
+ mask = CKCTL_63268_SPI_EN;
+ else
+ return;
+
bcm_hwclock_set(mask, enable);
}
@@ -246,6 +256,8 @@ static void hsspi_set(struct clk *clk, i
mask = CKCTL_6328_HSSPI_EN;
else if (BCMCPU_IS_6362())
mask = CKCTL_6362_HSSPI_EN;
+ else if (BCMCPU_IS_63268())
+ mask = CKCTL_63268_HSSPI_EN;
else
return;
@@ -307,6 +319,8 @@ static void pcie_set(struct clk *clk, in
bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
else if (BCMCPU_IS_6362())
bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
+ else if (BCMCPU_IS_63268())
+ bcm_hwclock_set(CKCTL_63268_PCIE_EN, enable);
}
static struct clk clk_pcie = {
@@ -386,9 +400,11 @@ struct clk *clk_get(struct device *dev,
return &clk_periph;
if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
return &clk_pcm;
- if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
+ if ((BCMCPU_IS_6362() || BCMCPU_IS_6368() || BCMCPU_IS_63268()) &&
+ !strcmp(id, "ipsec"))
return &clk_ipsec;
- if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
+ if ((BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) &&
+ !strcmp(id, "pcie"))
return &clk_pcie;
return ERR_PTR(-ENOENT);
}
@@ -411,6 +427,7 @@ static int __init bcm63xx_clk_init(void)
clk_hsspi.rate = HSSPI_PLL_HZ_6328;
break;
case BCM6362_CPU_ID:
+ case BCM63268_CPU_ID:
clk_hsspi.rate = HSSPI_PLL_HZ_6362;
break;
}
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -101,6 +101,15 @@ static const int bcm6368_irqs[] = {
};
+static const unsigned long bcm63268_regs_base[] = {
+ __GEN_CPU_REGS_TABLE(63268)
+};
+
+static const int bcm63268_irqs[] = {
+ __GEN_CPU_IRQ_TABLE(63268)
+
+};
+
u32 bcm63xx_get_cpu_variant(void)
{
return bcm63xx_cpu_variant;
@@ -253,6 +262,27 @@ static unsigned int detect_cpu_clock(voi
return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
}
+ case BCM63268_CPU_ID:
+ {
+ unsigned int tmp, mips_pll_fcvo;
+
+ tmp = bcm_misc_readl(MISC_STRAPBUS_63268_REG);
+ mips_pll_fcvo = (tmp & STRAPBUS_63268_FCVO_MASK) >>
+ STRAPBUS_63268_FCVO_SHIFT;
+ switch (mips_pll_fcvo) {
+ case 0x3:
+ case 0xe:
+ return 320000000;
+ case 0xa:
+ return 333000000;
+ case 0x2:
+ case 0xb:
+ case 0xf:
+ return 400000000;
+ default:
+ return 0;
+ }
+ }
default:
panic("Failed to detect clock for CPU with id=%04X\n", cpu_id);
@@ -267,7 +297,7 @@ static unsigned int detect_memory_size(v
unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
u32 val;
- if (BCMCPU_IS_6328() || BCMCPU_IS_6362())
+ if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268())
return bcm_ddr_readl(DDR_CSEND_REG) << 24;
if (BCMCPU_IS_6345()) {
@@ -305,6 +335,7 @@ void __init bcm63xx_cpu_init(void)
unsigned int tmp;
unsigned int cpu = smp_processor_id();
u32 chipid_reg;
+ bool long_chipid = false;
u8 __maybe_unused varid = 0;
/* soc registers location depends on cpu type */
@@ -326,6 +357,9 @@ void __init bcm63xx_cpu_init(void)
case 0x10:
chipid_reg = BCM_6345_PERF_BASE;
break;
+ case 0x80:
+ long_chipid = true;
+ /* fall-through */
default:
chipid_reg = BCM_6368_PERF_BASE;
break;
@@ -333,6 +367,7 @@ void __init bcm63xx_cpu_init(void)
break;
}
+
/*
* really early to panic, but delaying panic would not help since we
* will never get any working console
@@ -342,10 +377,17 @@ void __init bcm63xx_cpu_init(void)
/* read out CPU type */
tmp = bcm_readl(chipid_reg);
- bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
- bcm63xx_cpu_variant = bcm63xx_cpu_id;
+
+ if (long_chipid) {
+ bcm63xx_cpu_id = tmp & REV_LONG_CHIPID_MASK;
+ bcm63xx_cpu_id >>= REV_LONG_CHIPID_SHIFT;
+ } else {
+ bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
+ varid = (tmp & REV_VARID_MASK) >> REV_VARID_SHIFT;
+ }
+
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
- varid = (tmp & REV_VARID_MASK) >> REV_VARID_SHIFT;
+ bcm63xx_cpu_variant = bcm63xx_cpu_id;
switch (bcm63xx_cpu_id) {
case BCM3368_CPU_ID:
@@ -400,6 +442,15 @@ void __init bcm63xx_cpu_init(void)
/* BCM6369 is a BCM6368 without xDSL, so treat it the same */
bcm63xx_cpu_id = BCM6368_CPU_ID;
break;
+ case BCM63168_CPU_ID:
+ case BCM63169_CPU_ID:
+ case BCM63268_CPU_ID:
+ case BCM63269_CPU_ID:
+ bcm63xx_regs_base = bcm63268_regs_base;
+ bcm63xx_irqs = bcm63268_irqs;
+
+ bcm63xx_cpu_id = BCM63268_CPU_ID;
+ break;
default:
panic("unsupported broadcom CPU %x", bcm63xx_cpu_id);
break;
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -94,6 +94,12 @@ static int __init bcm63xx_detect_flash_t
case STRAPBUS_6368_BOOT_SEL_PARALLEL:
return BCM63XX_FLASH_TYPE_PARALLEL;
}
+ case BCM63268_CPU_ID:
+ val = bcm_misc_readl(MISC_STRAPBUS_63268_REG);
+ if (val & STRAPBUS_63268_BOOT_SEL_SERIAL)
+ return BCM63XX_FLASH_TYPE_SERIAL;
+ else
+ return BCM63XX_FLASH_TYPE_NAND;
default:
return -EINVAL;
}
--- a/arch/mips/bcm63xx/dev-spi.c
+++ b/arch/mips/bcm63xx/dev-spi.c
@@ -37,7 +37,7 @@ static __init void bcm63xx_spi_regs_init
if (BCMCPU_IS_6338() || BCMCPU_IS_6348())
bcm63xx_regs_spi = bcm6348_regs_spi;
if (BCMCPU_IS_3368() || BCMCPU_IS_6358() ||
- BCMCPU_IS_6362() || BCMCPU_IS_6368())
+ BCMCPU_IS_6362() || BCMCPU_IS_6368() || BCMCPU_IS_63268())
bcm63xx_regs_spi = bcm6358_regs_spi;
}
@@ -85,7 +85,7 @@ int __init bcm63xx_spi_register(void)
}
if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() ||
- BCMCPU_IS_6368()) {
+ BCMCPU_IS_6368() || BCMCPU_IS_63268()) {
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/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -150,6 +150,20 @@ void __init arch_init_irq(void)
ext_irqs[5] = BCM_6368_EXT_IRQ5;
ext_shift = 4;
break;
+ case BCM63268_CPU_ID:
+ periph_bases[0] += PERF_IRQMASK_63268_REG(0);
+ periph_bases[1] += PERF_IRQMASK_63268_REG(1);
+ periph_irq_count = 2;
+ periph_width = 4;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_63268;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_63268_EXT_IRQ0;
+ ext_irqs[1] = BCM_63268_EXT_IRQ1;
+ ext_irqs[2] = BCM_63268_EXT_IRQ2;
+ ext_irqs[3] = BCM_63268_EXT_IRQ3;
+ ext_shift = 4;
+ break;
default:
BUG();
}
--- a/arch/mips/bcm63xx/reset.c
+++ b/arch/mips/bcm63xx/reset.c
@@ -125,6 +125,20 @@
#define BCM6368_RESET_PCIE 0
#define BCM6368_RESET_PCIE_EXT 0
+#define BCM63268_RESET_SPI SOFTRESET_63268_SPI_MASK
+#define BCM63268_RESET_ENET 0
+#define BCM63268_RESET_USBH SOFTRESET_63268_USBH_MASK
+#define BCM63268_RESET_USBD SOFTRESET_63268_USBS_MASK
+#define BCM63268_RESET_DSL 0
+#define BCM63268_RESET_SAR SOFTRESET_63268_SAR_MASK
+#define BCM63268_RESET_EPHY 0
+#define BCM63268_RESET_ENETSW SOFTRESET_63268_ENETSW_MASK
+#define BCM63268_RESET_PCM SOFTRESET_63268_PCM_MASK
+#define BCM63268_RESET_MPI 0
+#define BCM63268_RESET_PCIE (SOFTRESET_63268_PCIE_MASK | \
+ SOFTRESET_63268_PCIE_CORE_MASK)
+#define BCM63268_RESET_PCIE_EXT SOFTRESET_63268_PCIE_EXT_MASK
+
/*
* core reset bits
*/
@@ -156,6 +170,10 @@ static const u32 bcm6368_reset_bits[] =
__GEN_RESET_BITS_TABLE(6368)
};
+static const u32 bcm63268_reset_bits[] = {
+ __GEN_RESET_BITS_TABLE(63268)
+};
+
const u32 *bcm63xx_reset_bits;
static int reset_reg;
@@ -182,6 +200,9 @@ static int __init bcm63xx_reset_bits_ini
} else if (BCMCPU_IS_6368()) {
reset_reg = PERF_SOFTRESET_6368_REG;
bcm63xx_reset_bits = bcm6368_reset_bits;
+ } else if (BCMCPU_IS_63268()) {
+ reset_reg = PERF_SOFTRESET_63268_REG;
+ bcm63xx_reset_bits = bcm63268_reset_bits;
}
return 0;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -21,6 +21,10 @@
#define BCM6362_CPU_ID 0x6362
#define BCM6368_CPU_ID 0x6368
#define BCM6369_CPU_ID 0x6369
+#define BCM63168_CPU_ID 0x63168
+#define BCM63169_CPU_ID 0x63169
+#define BCM63268_CPU_ID 0x63268
+#define BCM63269_CPU_ID 0x63269
void __init bcm63xx_cpu_init(void);
u32 bcm63xx_get_cpu_variant(void);
@@ -61,6 +65,10 @@ static inline u32 __pure __bcm63xx_get_c
#ifdef CONFIG_BCM63XX_CPU_6368
case BCM6368_CPU_ID:
#endif
+
+#ifdef CONFIG_BCM63XX_CPU_63268
+ case BCM63268_CPU_ID:
+#endif
break;
default:
unreachable();
@@ -86,6 +94,7 @@ static inline u32 __pure bcm63xx_get_cpu
#define BCMCPU_IS_6358() (bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
#define BCMCPU_IS_6362() (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
#define BCMCPU_IS_6368() (bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
+#define BCMCPU_IS_63268() (bcm63xx_get_cpu_id() == BCM63268_CPU_ID)
#define BCMCPU_VARIANT_IS_3368() \
(bcm63xx_get_cpu_variant() == BCM3368_CPU_ID)
@@ -109,6 +118,14 @@ static inline u32 __pure bcm63xx_get_cpu
(bcm63xx_get_cpu_variant() == BCM6368_CPU_ID)
#define BCMCPU_VARIANT_IS_6369() \
(bcm63xx_get_cpu_variant() == BCM6369_CPU_ID)
+#define BCMCPU_VARIANT_IS_63168() \
+ (bcm63xx_get_cpu_variant() == BCM63168_CPU_ID)
+#define BCMCPU_VARIANT_IS_63169() \
+ (bcm63xx_get_cpu_variant() == BCM63169_CPU_ID)
+#define BCMCPU_VARIANT_IS_63268() \
+ (bcm63xx_get_cpu_variant() == BCM63268_CPU_ID)
+#define BCMCPU_VARIANT_IS_63269() \
+ (bcm63xx_get_cpu_variant() == BCM63269_CPU_ID)
/*
* While registers sets are (mostly) the same across 63xx CPU, base
@@ -573,6 +590,52 @@ enum bcm63xx_regs_set {
#define BCM_6368_RNG_BASE (0xb0004180)
#define BCM_6368_MISC_BASE (0xdeadbeef)
+/*
+ * 63268 register sets base address
+ */
+#define BCM_63268_DSL_LMEM_BASE (0xdeadbeef)
+#define BCM_63268_PERF_BASE (0xb0000000)
+#define BCM_63268_TIMER_BASE (0xb0000080)
+#define BCM_63268_WDT_BASE (0xb000009c)
+#define BCM_63268_UART0_BASE (0xb0000180)
+#define BCM_63268_UART1_BASE (0xb00001a0)
+#define BCM_63268_GPIO_BASE (0xb00000c0)
+#define BCM_63268_SPI_BASE (0xb0000800)
+#define BCM_63268_HSSPI_BASE (0xb0001000)
+#define BCM_63268_UDC0_BASE (0xdeadbeef)
+#define BCM_63268_USBDMA_BASE (0xb000c800)
+#define BCM_63268_OHCI0_BASE (0xb0002600)
+#define BCM_63268_OHCI_PRIV_BASE (0xdeadbeef)
+#define BCM_63268_USBH_PRIV_BASE (0xb0002700)
+#define BCM_63268_USBD_BASE (0xb0002400)
+#define BCM_63268_MPI_BASE (0xdeadbeef)
+#define BCM_63268_PCMCIA_BASE (0xdeadbeef)
+#define BCM_63268_PCIE_BASE (0xb06e0000)
+#define BCM_63268_SDRAM_REGS_BASE (0xdeadbeef)
+#define BCM_63268_DSL_BASE (0xdeadbeef)
+#define BCM_63268_UBUS_BASE (0xdeadbeef)
+#define BCM_63268_ENET0_BASE (0xdeadbeef)
+#define BCM_63268_ENET1_BASE (0xdeadbeef)
+#define BCM_63268_ENETDMA_BASE (0xb000d800)
+#define BCM_63268_ENETDMAC_BASE (0xb000da00)
+#define BCM_63268_ENETDMAS_BASE (0xb000dc00)
+#define BCM_63268_ENETSW_BASE (0xb0700000)
+#define BCM_63268_EHCI0_BASE (0xb0002500)
+#define BCM_63268_SDRAM_BASE (0xdeadbeef)
+#define BCM_63268_MEMC_BASE (0xdeadbeef)
+#define BCM_63268_DDR_BASE (0xb0003000)
+#define BCM_63268_M2M_BASE (0xdeadbeef)
+#define BCM_63268_ATM_BASE (0xdeadbeef)
+#define BCM_63268_XTM_BASE (0xb0007000)
+#define BCM_63268_XTMDMA_BASE (0xb000b800)
+#define BCM_63268_XTMDMAC_BASE (0xdeadbeef)
+#define BCM_63268_XTMDMAS_BASE (0xdeadbeef)
+#define BCM_63268_PCM_BASE (0xb000b000)
+#define BCM_63268_PCMDMA_BASE (0xb000b800)
+#define BCM_63268_PCMDMAC_BASE (0xdeadbeef)
+#define BCM_63268_PCMDMAS_BASE (0xdeadbeef)
+#define BCM_63268_RNG_BASE (0xdeadbeef)
+#define BCM_63268_MISC_BASE (0xb0001800)
extern const unsigned long *bcm63xx_regs_base;
@@ -1041,6 +1104,73 @@ enum bcm63xx_irq {
#define BCM_6368_EXT_IRQ4 (IRQ_INTERNAL_BASE + 24)
#define BCM_6368_EXT_IRQ5 (IRQ_INTERNAL_BASE + 25)
+/*
+ * 63268 irqs
+ */
+#define BCM_63268_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
+#define BCM_63268_VERY_HIGH_IRQ_BASE (BCM_63268_HIGH_IRQ_BASE + 32)
+
+#define BCM_63268_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
+#define BCM_63268_SPI_IRQ (BCM_63268_VERY_HIGH_IRQ_BASE + 16)
+#define BCM_63268_UART0_IRQ (IRQ_INTERNAL_BASE + 5)
+#define BCM_63268_UART1_IRQ (BCM_63268_HIGH_IRQ_BASE + 2)
+#define BCM_63268_DSL_IRQ (IRQ_INTERNAL_BASE + 23)
+#define BCM_63268_UDC0_IRQ 0
+#define BCM_63268_ENET0_IRQ 0
+#define BCM_63268_ENET1_IRQ 0
+#define BCM_63268_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 13)
+#define BCM_63268_HSSPI_IRQ (IRQ_INTERNAL_BASE + 6)
+#define BCM_63268_OHCI0_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_63268_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10)
+#define BCM_63268_USBD_IRQ (IRQ_INTERNAL_BASE + 11)
+#define BCM_63268_USBD_RXDMA0_IRQ (IRQ_INTERNAL_BASE + 19)
+#define BCM_63268_USBD_TXDMA0_IRQ (BCM_63268_HIGH_IRQ_BASE + 4)
+#define BCM_63268_USBD_RXDMA1_IRQ (IRQ_INTERNAL_BASE + 20)
+#define BCM_63268_USBD_TXDMA1_IRQ (BCM_63268_HIGH_IRQ_BASE + 5)
+#define BCM_63268_USBD_RXDMA2_IRQ (IRQ_INTERNAL_BASE + 21)
+#define BCM_63268_USBD_TXDMA2_IRQ (BCM_63268_HIGH_IRQ_BASE + 6)
+#define BCM_63268_PCMCIA_IRQ 0
+#define BCM_63268_ENET0_RXDMA_IRQ 0
+#define BCM_63268_ENET0_TXDMA_IRQ 0
+#define BCM_63268_ENET1_RXDMA_IRQ 0
+#define BCM_63268_ENET1_TXDMA_IRQ 0
+#define BCM_63268_PCI_IRQ (BCM_63268_HIGH_IRQ_BASE + 8)
+#define BCM_63268_ATM_IRQ 0
+#define BCM_63268_ENETSW_RXDMA0_IRQ (IRQ_INTERNAL_BASE + 1)
+#define BCM_63268_ENETSW_RXDMA1_IRQ (IRQ_INTERNAL_BASE + 2)
+#define BCM_63268_ENETSW_RXDMA2_IRQ (IRQ_INTERNAL_BASE + 3)
+#define BCM_63268_ENETSW_RXDMA3_IRQ (IRQ_INTERNAL_BASE + 4)
+#define BCM_63268_ENETSW_TXDMA0_IRQ (BCM_63268_VERY_HIGH_IRQ_BASE + 0)
+#define BCM_63268_ENETSW_TXDMA1_IRQ (BCM_63268_VERY_HIGH_IRQ_BASE + 1)
+#define BCM_63268_ENETSW_TXDMA2_IRQ (BCM_63268_VERY_HIGH_IRQ_BASE + 2)
+#define BCM_63268_ENETSW_TXDMA3_IRQ (BCM_63268_VERY_HIGH_IRQ_BASE + 3)
+#define BCM_63268_XTM_IRQ (BCM_63268_HIGH_IRQ_BASE + 17)
+#define BCM_63268_XTM_DMA0_IRQ (IRQ_INTERNAL_BASE + 26)
+
+#define BCM_63268_RING_OSC_IRQ (BCM_63268_HIGH_IRQ_BASE + 20)
+#define BCM_63268_WLAN_GPIO_IRQ (BCM_63268_HIGH_IRQ_BASE + 3)
+#define BCM_63268_WLAN_IRQ (IRQ_INTERNAL_BASE + 7)
+#define BCM_63268_IPSEC_IRQ (IRQ_INTERNAL_BASE + 8)
+#define BCM_63268_NAND_IRQ (BCM_63268_HIGH_IRQ_BASE + 18)
+#define BCM_63268_PCM_IRQ (IRQ_INTERNAL_BASE + 13)
+#define BCM_63268_DG_IRQ (IRQ_INTERNAL_BASE + 15)
+#define BCM_63268_EPHY_ENERGY0_IRQ (IRQ_INTERNAL_BASE + 16)
+#define BCM_63268_EPHY_ENERGY1_IRQ (IRQ_INTERNAL_BASE + 17)
+#define BCM_63268_EPHY_ENERGY2_IRQ (IRQ_INTERNAL_BASE + 18)
+#define BCM_63268_EPHY_ENERGY3_IRQ (IRQ_INTERNAL_BASE + 19)
+#define BCM_63268_IPSEC_DMA0_IRQ (IRQ_INTERNAL_BASE + 22)
+#define BCM_63268_IPSEC_DMA1_IRQ (BCM_63268_HIGH_IRQ_BASE + 7)
+#define BCM_63268_FAP0_IRQ (IRQ_INTERNAL_BASE + 24)
+#define BCM_63268_FAP1_IRQ (IRQ_INTERNAL_BASE + 25)
+#define BCM_63268_PCM_DMA0_IRQ (BCM_63268_HIGH_IRQ_BASE + 10)
+#define BCM_63268_PCM_DMA1_IRQ (BCM_63268_HIGH_IRQ_BASE + 11)
+#define BCM_63268_DECT0_IRQ (BCM_63268_HIGH_IRQ_BASE + 0)
+#define BCM_63268_DECT1_IRQ (BCM_63268_HIGH_IRQ_BASE + 1)
+#define BCM_63268_EXT_IRQ0 (BCM_63268_HIGH_IRQ_BASE + 12)
+#define BCM_63268_EXT_IRQ1 (BCM_63268_HIGH_IRQ_BASE + 13)
+#define BCM_63268_EXT_IRQ2 (BCM_63268_HIGH_IRQ_BASE + 14)
+#define BCM_63268_EXT_IRQ3 (BCM_63268_HIGH_IRQ_BASE + 15)
+
extern const int *bcm63xx_irqs;
#define __GEN_CPU_IRQ_TABLE(__cpu) \
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
@@ -22,6 +22,8 @@ static inline unsigned long bcm63xx_gpio
return 48;
case BCM6368_CPU_ID:
return 38;
+ case BCM63268_CPU_ID:
+ return 52;
case BCM6348_CPU_ID:
default:
return 37;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -9,6 +9,8 @@
#define PERF_REV_REG 0x0
#define REV_CHIPID_SHIFT 16
#define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT)
+#define REV_LONG_CHIPID_SHIFT 12
+#define REV_LONG_CHIPID_MASK (0xfffff << REV_LONG_CHIPID_SHIFT)
#define REV_VARID_SHIFT 12
#define REV_VARID_MASK (0xf << REV_VARID_SHIFT)
#define REV_REVID_SHIFT 0
@@ -211,6 +213,52 @@
CKCTL_6368_NAND_EN | \
CKCTL_6368_IPSEC_EN)
+#define CKCTL_63268_DISABLE_GLESS (1 << 0)
+#define CKCTL_63268_VDSL_QPROC_EN (1 << 1)
+#define CKCTL_63268_VDSL_AFE_EN (1 << 2)
+#define CKCTL_63268_VDSL_EN (1 << 3)
+#define CKCTL_63268_MIPS_EN (1 << 4)
+#define CKCTL_63268_WLAN_OCP_EN (1 << 5)
+#define CKCTL_63268_DECT_EN (1 << 6)
+#define CKCTL_63268_FAP0_EN (1 << 7)
+#define CKCTL_63268_FAP1_EN (1 << 8)
+#define CKCTL_63268_SAR_EN (1 << 9)
+#define CKCTL_63268_ROBOSW_EN (1 << 10)
+#define CKCTL_63268_PCM_EN (1 << 11)
+#define CKCTL_63268_USBD_EN (1 << 12)
+#define CKCTL_63268_USBH_EN (1 << 13)
+#define CKCTL_63268_IPSEC_EN (1 << 14)
+#define CKCTL_63268_SPI_EN (1 << 15)
+#define CKCTL_63268_HSSPI_EN (1 << 16)
+#define CKCTL_63268_PCIE_EN (1 << 17)
+#define CKCTL_63268_PHYMIPS_EN (1 << 18)
+#define CKCTL_63268_GMAC_EN (1 << 19)
+#define CKCTL_63268_NAND_EN (1 << 20)
+#define CKCTL_63268_TBUS_EN (1 << 27)
+#define CKCTL_63268_ROBOSW250_EN (1 << 31)
+
+#define CKCTL_63268_ALL_SAFE_EN (CKCTL_63268_VDSL_QPROC_EN | \
+ CKCTL_63268_VDSL_AFE_EN | \
+ CKCTL_63268_VDSL_EN | \
+ CKCTL_63268_WLAN_OCP_EN | \
+ CKCTL_63268_DECT_EN | \
+ CKCTL_63268_FAP0_EN | \
+ CKCTL_63268_FAP1_EN | \
+ CKCTL_63268_SAR_EN | \
+ CKCTL_63268_ROBOSW_EN | \
+ CKCTL_63268_PCM_EN | \
+ CKCTL_63268_USBD_EN | \
+ CKCTL_63268_USBH_EN | \
+ CKCTL_63268_IPSEC_EN | \
+ CKCTL_63268_SPI_EN | \
+ CKCTL_63268_HSSPI_EN | \
+ CKCTL_63268_PCIE_EN | \
+ CKCTL_63268_PHYMIPS_EN | \
+ CKCTL_63268_GMAC_EN | \
+ CKCTL_63268_NAND_EN | \
+ CKCTL_63268_TBUS_EN | \
+ CKCTL_63268_ROBOSW250_EN)
+
/* System PLL Control register */
#define PERF_SYS_PLL_CTL_REG 0x8
#define SYS_PLL_SOFT_RESET 0x1
@@ -224,6 +272,7 @@
#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)
+#define PERF_IRQMASK_63268_REG(x) (0x20 + (x) * 0x20)
/* Interrupt Status register */
#define PERF_IRQSTAT_3368_REG 0x10
@@ -234,6 +283,7 @@
#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)
+#define PERF_IRQSTAT_63268_REG(x) (0x30 + (x) * 0x20)
/* External Interrupt Configuration register */
#define PERF_EXTIRQ_CFG_REG_3368 0x14
@@ -244,6 +294,7 @@
#define PERF_EXTIRQ_CFG_REG_6358 0x14
#define PERF_EXTIRQ_CFG_REG_6362 0x18
#define PERF_EXTIRQ_CFG_REG_6368 0x18
+#define PERF_EXTIRQ_CFG_REG_63268 0x18
#define PERF_EXTIRQ_CFG_REG2_6358 0x1c
#define PERF_EXTIRQ_CFG_REG2_6368 0x1c
@@ -274,6 +325,7 @@
#define PERF_SOFTRESET_6358_REG 0x34
#define PERF_SOFTRESET_6362_REG 0x10
#define PERF_SOFTRESET_6368_REG 0x10
+#define PERF_SOFTRESET_63268_REG 0x10
#define SOFTRESET_3368_SPI_MASK (1 << 0)
#define SOFTRESET_3368_ENET_MASK (1 << 2)
@@ -367,6 +419,26 @@
#define SOFTRESET_6368_USBH_MASK (1 << 12)
#define SOFTRESET_6368_PCM_MASK (1 << 13)
+#define SOFTRESET_63268_SPI_MASK (1 << 0)
+#define SOFTRESET_63268_IPSEC_MASK (1 << 1)
+#define SOFTRESET_63268_EPHY_MASK (1 << 2)
+#define SOFTRESET_63268_SAR_MASK (1 << 3)
+#define SOFTRESET_63268_ENETSW_MASK (1 << 4)
+#define SOFTRESET_63268_USBS_MASK (1 << 5)
+#define SOFTRESET_63268_USBH_MASK (1 << 6)
+#define SOFTRESET_63268_PCM_MASK (1 << 7)
+#define SOFTRESET_63268_PCIE_CORE_MASK (1 << 8)
+#define SOFTRESET_63268_PCIE_MASK (1 << 9)
+#define SOFTRESET_63268_PCIE_EXT_MASK (1 << 10)
+#define SOFTRESET_63268_WLAN_SHIM_MASK (1 << 11)
+#define SOFTRESET_63268_DDR_PHY_MASK (1 << 12)
+#define SOFTRESET_63268_FAP0_MASK (1 << 13)
+#define SOFTRESET_63268_WLAN_UBUS_MASK (1 << 14)
+#define SOFTRESET_63268_DECT_MASK (1 << 15)
+#define SOFTRESET_63268_FAP1_MASK (1 << 16)
+#define SOFTRESET_63268_PCIE_HARD_MASK (1 << 17)
+#define SOFTRESET_63268_GPHY_MASK (1 << 18)
+
/* MIPS PLL control register */
#define PERF_MIPSPLLCTL_REG 0x34
#define MIPSPLLCTL_N1_SHIFT 20
@@ -1366,6 +1438,13 @@
#define STRAPBUS_6362_BOOT_SEL_SERIAL (1 << 15)
#define STRAPBUS_6362_BOOT_SEL_NAND (0 << 15)
+#define MISC_STRAPBUS_63268_REG 0x14
+#define STRAPBUS_63268_HSSPI_CLK_FAST (1 << 9)
+#define STRAPBUS_63268_BOOT_SEL_SERIAL (1 << 11)
+#define STRAPBUS_63268_BOOT_SEL_NAND (0 << 11)
+#define STRAPBUS_63268_FCVO_SHIFT 21
+#define STRAPBUS_63268_FCVO_MASK (0xf << STRAPBUS_63268_FCVO_SHIFT)
+
#define MISC_STRAPBUS_6328_REG 0x240
#define STRAPBUS_6328_FCVO_SHIFT 7
#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
--- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h
+++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h
@@ -25,6 +25,7 @@ static inline int is_bcm63xx_internal_re
case BCM6328_CPU_ID:
case BCM6362_CPU_ID:
case BCM6368_CPU_ID:
+ case BCM63268_CPU_ID:
if (offset >= 0xb0000000 && offset < 0xb1000000)
return 1;
break;
--- a/arch/mips/bcm63xx/dev-hsspi.c
+++ b/arch/mips/bcm63xx/dev-hsspi.c
@@ -35,7 +35,7 @@ static struct platform_device bcm63xx_hs
int __init bcm63xx_hsspi_register(void)
{
- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362())
+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_63268())
return -ENODEV;
spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
--- a/arch/mips/bcm63xx/dev-enet.c
+++ b/arch/mips/bcm63xx/dev-enet.c
@@ -176,7 +176,8 @@ static int __init register_shared(void)
else
shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
- if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
+ if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368() ||
+ BCMCPU_IS_63268())
chan_count = 32;
else if (BCMCPU_IS_6345())
chan_count = 8;
@@ -276,7 +277,8 @@ bcm63xx_enetsw_register(const struct bcm
{
int ret;
- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368() &&
+ !BCMCPU_IS_63268())
return -ENODEV;
ret = register_shared();
@@ -297,6 +299,8 @@ bcm63xx_enetsw_register(const struct bcm
enetsw_pd.num_ports = ENETSW_PORTS_6328;
else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
enetsw_pd.num_ports = ENETSW_PORTS_6368;
+ else if (BCMCPU_IS_63268())
+ enetsw_pd.num_ports = ENETSW_PORTS_63268;
enetsw_pd.dma_has_sram = true;
enetsw_pd.dma_chan_width = ENETDMA_CHAN_WIDTH;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
@@ -62,6 +62,7 @@ struct bcm63xx_enet_platform_data {
#define ENETSW_MAX_PORT 8
#define ENETSW_PORTS_6328 5 /* 4 FE PHY + 1 RGMII */
#define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
+#define ENETSW_PORTS_63268 8 /* 3 FE PHY + 1 GE PHY + 4 RGMII */
#define ENETSW_RGMII_PORT0 4

View File

@ -0,0 +1,55 @@
From 5c290c81dbdb4433600593fe80c88eb4af86e791 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 8 Dec 2013 03:22:40 +0100
Subject: [PATCH 50/53] MIPS: BCM63XX: add pcie support for BCM63268
---
arch/mips/bcm63xx/reset.c | 3 ++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 5 +++++
arch/mips/pci/pci-bcm63xx.c | 4 ++++
3 files changed, 11 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/reset.c
+++ b/arch/mips/bcm63xx/reset.c
@@ -136,7 +136,8 @@
#define BCM63268_RESET_PCM SOFTRESET_63268_PCM_MASK
#define BCM63268_RESET_MPI 0
#define BCM63268_RESET_PCIE (SOFTRESET_63268_PCIE_MASK | \
- SOFTRESET_63268_PCIE_CORE_MASK)
+ SOFTRESET_63268_PCIE_CORE_MASK | \
+ SOFTRESET_63268_PCIE_HARD_MASK)
#define BCM63268_RESET_PCIE_EXT SOFTRESET_63268_PCIE_EXT_MASK
/*
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
@@ -45,6 +45,11 @@
#define BCM_PCIE_MEM_END_PA_6328 (BCM_PCIE_MEM_BASE_PA_6328 + \
BCM_PCIE_MEM_SIZE_6328 - 1)
+#define BCM_PCIE_MEM_BASE_PA_63268 0x11000000
+#define BCM_PCIE_MEM_SIZE_63268 (15 * 1024 * 1024)
+#define BCM_PCIE_MEM_END_PA_63268 (BCM_PCIE_MEM_BASE_PA_63268 + \
+ BCM_PCIE_MEM_SIZE_63268 - 1)
+
/*
* Internal registers are accessed through KSEG3
*/
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -337,11 +337,15 @@ static int __init bcm63xx_pci_init(void)
if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_6328;
bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_6328;
+ } else if (BCMCPU_IS_63268()) {
+ bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_63268;
+ bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_63268;
}
switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
case BCM6362_CPU_ID:
+ case BCM63268_CPU_ID:
return bcm63xx_register_pcie();
case BCM3368_CPU_ID:
case BCM6348_CPU_ID:

View File

@ -0,0 +1,675 @@
From 60c29522a8c77d96145d965589c56befda7d4c3d Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 8 Dec 2013 01:24:09 +0100
Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318
---
arch/mips/bcm63xx/Kconfig | 5 +
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
arch/mips/bcm63xx/clk.c | 8 +-
arch/mips/bcm63xx/cpu.c | 53 +++++++++++
arch/mips/bcm63xx/dev-flash.c | 3 +
arch/mips/bcm63xx/dev-spi.c | 2 +-
arch/mips/bcm63xx/irq.c | 10 ++
arch/mips/bcm63xx/prom.c | 2 +-
arch/mips/bcm63xx/reset.c | 24 +++++
arch/mips/bcm63xx/setup.c | 5 +-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 107 ++++++++++++++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 75 ++++++++++++++-
arch/mips/include/asm/mach-bcm63xx/ioremap.h | 1 +
13 files changed, 291 insertions(+), 6 deletions(-)
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -18,6 +18,11 @@ config BCM63XX_EHCI
select USB_EHCI_BIG_ENDIAN_DESC if USB_EHCI_HCD
select USB_EHCI_BIG_ENDIAN_MMIO if USB_EHCI_HCD
+config BCM63XX_CPU_6318
+ bool "support 6318 CPU"
+ select SYS_HAS_CPU_BMIPS32_3300
+ select HW_HAS_PCI
+
config BCM63XX_CPU_6328
bool "support 6328 CPU"
select SYS_HAS_CPU_BMIPS4350
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -717,7 +717,7 @@ void __init board_prom_init(void)
/* read base address of boot chip select (0)
* 6328/6362 do not have MPI but boot from a fixed address
*/
- if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) {
+ if (BCMCPU_IS_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) {
val = 0x18000000;
} else {
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -252,7 +252,9 @@ static void hsspi_set(struct clk *clk, i
{
u32 mask;
- if (BCMCPU_IS_6328())
+ if (BCMCPU_IS_6318())
+ mask = CKCTL_6318_HSSPI_EN;
+ else if (BCMCPU_IS_6328())
mask = CKCTL_6328_HSSPI_EN;
else if (BCMCPU_IS_6362())
mask = CKCTL_6362_HSSPI_EN;
@@ -417,12 +419,16 @@ void clk_put(struct clk *clk)
EXPORT_SYMBOL(clk_put);
+#define HSSPI_PLL_HZ_6318 250000000
#define HSSPI_PLL_HZ_6328 133333333
#define HSSPI_PLL_HZ_6362 400000000
static int __init bcm63xx_clk_init(void)
{
switch (bcm63xx_get_cpu_id()) {
+ case BCM6318_CPU_ID:
+ clk_hsspi.rate = HSSPI_PLL_HZ_6318;
+ break;
case BCM6328_CPU_ID:
clk_hsspi.rate = HSSPI_PLL_HZ_6328;
break;
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -41,6 +41,14 @@ static const int bcm3368_irqs[] = {
__GEN_CPU_IRQ_TABLE(3368)
};
+static const unsigned long bcm6318_regs_base[] = {
+ __GEN_CPU_REGS_TABLE(6318)
+};
+
+static const int bcm6318_irqs[] = {
+ __GEN_CPU_IRQ_TABLE(6318)
+};
+
static const unsigned long bcm6328_regs_base[] = {
__GEN_CPU_REGS_TABLE(6328)
};
@@ -134,6 +142,10 @@ unsigned int bcm63xx_get_memory_size(voi
return bcm63xx_memory_size;
}
+#define STRAP_OVERRIDE_BUS_REG 0x0
+#define OVERRIDE_BUS_MIPS_FREQ_SHIFT 23
+#define OVERRIDE_BUS_MIPS_FREQ_MASK (0x3 << OVERRIDE_BUS_MIPS_FREQ_SHIFT)
+
static unsigned int detect_cpu_clock(void)
{
u32 cpu_id = bcm63xx_get_cpu_id();
@@ -142,6 +154,28 @@ static unsigned int detect_cpu_clock(voi
case BCM3368_CPU_ID:
return 300000000;
+ case BCM6318_CPU_ID:
+ {
+ unsigned int tmp, mips_pll_fcvo;
+
+ tmp = bcm_readl(BCM_6318_STRAP_BASE + STRAP_OVERRIDE_BUS_REG);
+
+ pr_info("strap_override_bus = %08x\n", tmp);
+
+ mips_pll_fcvo = (tmp & OVERRIDE_BUS_MIPS_FREQ_MASK)
+ >> OVERRIDE_BUS_MIPS_FREQ_SHIFT;
+
+ switch (mips_pll_fcvo) {
+ case 0:
+ return 166000000;
+ case 1:
+ return 400000000;
+ case 2:
+ return 250000000;
+ case 3:
+ return 333000000;
+ };
+ }
case BCM6328_CPU_ID:
{
unsigned int tmp, mips_pll_fcvo;
@@ -297,6 +331,13 @@ static unsigned int detect_memory_size(v
unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
u32 val;
+ if (BCMCPU_IS_6318()) {
+ val = bcm_sdram_readl(SDRAM_CFG_REG);
+ val = val & SDRAM_CFG_6318_SPACE_MASK;
+ val >>= SDRAM_CFG_6318_SPACE_SHIFT;
+ return 1 << (val + 20);
+ }
+
if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268())
return bcm_ddr_readl(DDR_CSEND_REG) << 24;
@@ -343,6 +384,12 @@ void __init bcm63xx_cpu_init(void)
switch (current_cpu_type()) {
case CPU_BMIPS3300:
+ if ((read_c0_prid() & 0xff) >= 0x33) {
+ /* BCM6318 */
+ chipid_reg = BCM_6368_PERF_BASE;
+ break;
+ }
+
if ((read_c0_prid() & PRID_IMP_MASK) != PRID_IMP_BMIPS3300_ALT)
__cpu_name[cpu] = "Broadcom BCM6338";
/* fall-through */
@@ -390,6 +437,10 @@ void __init bcm63xx_cpu_init(void)
bcm63xx_cpu_variant = bcm63xx_cpu_id;
switch (bcm63xx_cpu_id) {
+ case BCM6318_CPU_ID:
+ bcm63xx_regs_base = bcm6318_regs_base;
+ bcm63xx_irqs = bcm6318_irqs;
+ break;
case BCM3368_CPU_ID:
bcm63xx_regs_base = bcm3368_regs_base;
bcm63xx_irqs = bcm3368_irqs;
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -60,6 +60,9 @@ static int __init bcm63xx_detect_flash_t
u32 val;
switch (bcm63xx_get_cpu_id()) {
+ case BCM6318_CPU_ID:
+ /* only support serial flash */
+ return BCM63XX_FLASH_TYPE_SERIAL;
case BCM6328_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
--- a/arch/mips/bcm63xx/dev-spi.c
+++ b/arch/mips/bcm63xx/dev-spi.c
@@ -70,7 +70,7 @@ static struct platform_device bcm63xx_sp
int __init bcm63xx_spi_register(void)
{
- if (BCMCPU_IS_6328() || BCMCPU_IS_6345())
+ if (BCMCPU_IS_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6345())
return -ENODEV;
spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -49,6 +49,19 @@ void __init arch_init_irq(void)
ext_irqs[3] = BCM_3368_EXT_IRQ3;
ext_shift = 4;
break;
+ case BCM6318_CPU_ID:
+ periph_bases[0] += PERF_IRQMASK_6318_REG;
+ periph_irq_count = 1;
+ periph_width = 4;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6318;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_6318_EXT_IRQ0;
+ ext_irqs[1] = BCM_6318_EXT_IRQ0;
+ ext_irqs[2] = BCM_6318_EXT_IRQ0;
+ ext_irqs[3] = BCM_6318_EXT_IRQ0;
+ ext_shift = 4;
+ break;
case BCM6328_CPU_ID:
periph_bases[0] += PERF_IRQMASK_6328_REG(0);
periph_bases[1] += PERF_IRQMASK_6328_REG(1);
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -68,7 +68,7 @@ void __init prom_init(void)
if (reg & OTP_6328_REG3_TP1_DISABLED)
bmips_smp_enabled = 0;
- } else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
+ } else if (BCMCPU_IS_6318() || BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
bmips_smp_enabled = 0;
}
--- a/arch/mips/bcm63xx/reset.c
+++ b/arch/mips/bcm63xx/reset.c
@@ -43,6 +43,23 @@
#define BCM3368_RESET_PCIE 0
#define BCM3368_RESET_PCIE_EXT 0
+
+#define BCM6318_RESET_SPI SOFTRESET_6318_SPI_MASK
+#define BCM6318_RESET_ENET 0
+#define BCM6318_RESET_USBH SOFTRESET_6318_USBH_MASK
+#define BCM6318_RESET_USBD SOFTRESET_6318_USBS_MASK
+#define BCM6318_RESET_DSL 0
+#define BCM6318_RESET_SAR SOFTRESET_6318_SAR_MASK
+#define BCM6318_RESET_EPHY SOFTRESET_6318_EPHY_MASK
+#define BCM6318_RESET_ENETSW SOFTRESET_6318_ENETSW_MASK
+#define BCM6318_RESET_PCM 0
+#define BCM6318_RESET_MPI 0
+#define BCM6318_RESET_PCIE \
+ (SOFTRESET_6318_PCIE_MASK | \
+ SOFTRESET_6318_PCIE_CORE_MASK | \
+ SOFTRESET_6318_PCIE_HARD_MASK)
+#define BCM6318_RESET_PCIE_EXT SOFTRESET_6318_PCIE_EXT_MASK
+
#define BCM6328_RESET_SPI SOFTRESET_6328_SPI_MASK
#define BCM6328_RESET_ENET 0
#define BCM6328_RESET_USBH SOFTRESET_6328_USBH_MASK
@@ -147,6 +164,10 @@ static const u32 bcm3368_reset_bits[] =
__GEN_RESET_BITS_TABLE(3368)
};
+static const u32 bcm6318_reset_bits[] = {
+ __GEN_RESET_BITS_TABLE(6318)
+};
+
static const u32 bcm6328_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6328)
};
@@ -183,6 +204,9 @@ static int __init bcm63xx_reset_bits_ini
if (BCMCPU_IS_3368()) {
reset_reg = PERF_SOFTRESET_6358_REG;
bcm63xx_reset_bits = bcm3368_reset_bits;
+ } else if (BCMCPU_IS_6318()) {
+ reset_reg = PERF_SOFTRESET_6318_REG;
+ bcm63xx_reset_bits = bcm6318_reset_bits;
} else if (BCMCPU_IS_6328()) {
reset_reg = PERF_SOFTRESET_6328_REG;
bcm63xx_reset_bits = bcm6328_reset_bits;
--- a/arch/mips/bcm63xx/setup.c
+++ b/arch/mips/bcm63xx/setup.c
@@ -72,6 +72,9 @@ void bcm63xx_machine_reboot(void)
case BCM3368_CPU_ID:
perf_regs[0] = PERF_EXTIRQ_CFG_REG_3368;
break;
+ case BCM6318_CPU_ID:
+ perf_regs[0] = PERF_EXTIRQ_CFG_REG_6318;
+ break;
case BCM6328_CPU_ID:
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328;
break;
@@ -111,7 +114,7 @@ void bcm63xx_machine_reboot(void)
bcm6348_a1_reboot();
printk(KERN_INFO "triggering watchdog soft-reset...\n");
- if (BCMCPU_IS_6328()) {
+ if (BCMCPU_IS_6318() || BCMCPU_IS_6328()) {
bcm_wdt_writel(1, WDT_SOFTRESET_REG);
} else {
reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -10,6 +10,7 @@
* arm mach-types)
*/
#define BCM3368_CPU_ID 0x3368
+#define BCM6318_CPU_ID 0x6318
#define BCM6328_CPU_ID 0x6328
#define BCM63281_CPU_ID 0x63281
#define BCM63283_CPU_ID 0x63283
@@ -38,6 +39,10 @@ static inline u32 __pure __bcm63xx_get_c
case BCM3368_CPU_ID:
#endif
+#ifdef CONFIG_BCM63XX_CPU_6318
+ case BCM6318_CPU_ID:
+#endif
+
#ifdef CONFIG_BCM63XX_CPU_6328
case BCM6328_CPU_ID:
#endif
@@ -87,6 +92,7 @@ static inline u32 __pure bcm63xx_get_cpu
}
#define BCMCPU_IS_3368() (bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
+#define BCMCPU_IS_6318() (bcm63xx_get_cpu_id() == BCM6318_CPU_ID)
#define BCMCPU_IS_6328() (bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
#define BCMCPU_IS_6338() (bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
#define BCMCPU_IS_6345() (bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
@@ -98,6 +104,8 @@ static inline u32 __pure bcm63xx_get_cpu
#define BCMCPU_VARIANT_IS_3368() \
(bcm63xx_get_cpu_variant() == BCM3368_CPU_ID)
+#define BCMCPU_VARIANT_IS_6318() \
+ (bcm63xx_get_cpu_variant() == BCM6318_CPU_ID)
#define BCMCPU_VARIANT_IS_63281() \
(bcm63xx_get_cpu_variant() == BCM63281_CPU_ID)
#define BCMCPU_VARIANT_IS_63283() \
@@ -252,6 +260,56 @@ enum bcm63xx_regs_set {
#define BCM_3368_MISC_BASE (0xdeadbeef)
/*
+ * 6318 register sets base address
+ */
+#define BCM_6318_DSL_LMEM_BASE (0xdeadbeef)
+#define BCM_6318_PERF_BASE (0xb0000000)
+#define BCM_6318_TIMER_BASE (0xb0000040)
+#define BCM_6318_WDT_BASE (0xb0000068)
+#define BCM_6318_UART0_BASE (0xb0000100)
+#define BCM_6318_UART1_BASE (0xdeadbeef)
+#define BCM_6318_GPIO_BASE (0xb0000080)
+#define BCM_6318_SPI_BASE (0xdeadbeef)
+#define BCM_6318_HSSPI_BASE (0xb0003000)
+#define BCM_6318_UDC0_BASE (0xdeadbeef)
+#define BCM_6318_USBDMA_BASE (0xb0006800)
+#define BCM_6318_OHCI0_BASE (0xb0005100)
+#define BCM_6318_OHCI_PRIV_BASE (0xdeadbeef)
+#define BCM_6318_USBH_PRIV_BASE (0xb0005200)
+#define BCM_6318_USBD_BASE (0xb0006000)
+#define BCM_6318_MPI_BASE (0xdeadbeef)
+#define BCM_6318_PCMCIA_BASE (0xdeadbeef)
+#define BCM_6318_PCIE_BASE (0xb0010000)
+#define BCM_6318_SDRAM_REGS_BASE (0xdeadbeef)
+#define BCM_6318_DSL_BASE (0xdeadbeef)
+#define BCM_6318_UBUS_BASE (0xdeadbeef)
+#define BCM_6318_ENET0_BASE (0xdeadbeef)
+#define BCM_6318_ENET1_BASE (0xdeadbeef)
+#define BCM_6318_ENETDMA_BASE (0xb0088000)
+#define BCM_6318_ENETDMAC_BASE (0xb0088200)
+#define BCM_6318_ENETDMAS_BASE (0xb0088400)
+#define BCM_6318_ENETSW_BASE (0xb0080000)
+#define BCM_6318_EHCI0_BASE (0xb0005000)
+#define BCM_6318_SDRAM_BASE (0xb0004000)
+#define BCM_6318_MEMC_BASE (0xdeadbeef)
+#define BCM_6318_DDR_BASE (0xdeadbeef)
+#define BCM_6318_M2M_BASE (0xdeadbeef)
+#define BCM_6318_ATM_BASE (0xdeadbeef)
+#define BCM_6318_XTM_BASE (0xdeadbeef)
+#define BCM_6318_XTMDMA_BASE (0xb000c000)
+#define BCM_6318_XTMDMAC_BASE (0xdeadbeef)
+#define BCM_6318_XTMDMAS_BASE (0xdeadbeef)
+#define BCM_6318_PCM_BASE (0xdeadbeef)
+#define BCM_6318_PCMDMA_BASE (0xdeadbeef)
+#define BCM_6318_PCMDMAC_BASE (0xdeadbeef)
+#define BCM_6318_PCMDMAS_BASE (0xdeadbeef)
+#define BCM_6318_RNG_BASE (0xdeadbeef)
+#define BCM_6318_MISC_BASE (0xb0000280)
+#define BCM_6318_OTP_BASE (0xdeadbeef)
+
+#define BCM_6318_STRAP_BASE (0xb0000900)
+
+/*
* 6328 register sets base address
*/
#define BCM_6328_DSL_LMEM_BASE (0xdeadbeef)
@@ -774,6 +832,55 @@ enum bcm63xx_irq {
#define BCM_3368_EXT_IRQ2 (IRQ_INTERNAL_BASE + 27)
#define BCM_3368_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28)
+/*
+ * 6318 irqs
+ */
+#define BCM_6318_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
+#define BCM_6318_VERY_HIGH_IRQ_BASE (BCM_6318_HIGH_IRQ_BASE + 32)
+
+#define BCM_6318_TIMER_IRQ (IRQ_INTERNAL_BASE + 31)
+#define BCM_6318_SPI_IRQ 0
+#define BCM_6318_UART0_IRQ (IRQ_INTERNAL_BASE + 28)
+#define BCM_6318_UART1_IRQ 0
+#define BCM_6318_DSL_IRQ (IRQ_INTERNAL_BASE + 21)
+#define BCM_6318_UDC0_IRQ 0
+#define BCM_6318_ENET0_IRQ 0
+#define BCM_6318_ENET1_IRQ 0
+#define BCM_6318_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
+#define BCM_6318_HSSPI_IRQ (IRQ_INTERNAL_BASE + 29)
+#define BCM_6318_OHCI0_IRQ (BCM_6318_HIGH_IRQ_BASE + 9)
+#define BCM_6318_EHCI0_IRQ (BCM_6318_HIGH_IRQ_BASE + 10)
+#define BCM_6318_USBD_IRQ (IRQ_INTERNAL_BASE + 4)
+#define BCM_6318_USBD_RXDMA0_IRQ (IRQ_INTERNAL_BASE + 5)
+#define BCM_6318_USBD_TXDMA0_IRQ (IRQ_INTERNAL_BASE + 6)
+#define BCM_6318_USBD_RXDMA1_IRQ (IRQ_INTERNAL_BASE + 7)
+#define BCM_6318_USBD_TXDMA1_IRQ (IRQ_INTERNAL_BASE + 8)
+#define BCM_6318_USBD_RXDMA2_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_6318_USBD_TXDMA2_IRQ (IRQ_INTERNAL_BASE + 10)
+#define BCM_6318_PCMCIA_IRQ 0
+#define BCM_6318_ENET0_RXDMA_IRQ 0
+#define BCM_6318_ENET0_TXDMA_IRQ 0
+#define BCM_6318_ENET1_RXDMA_IRQ 0
+#define BCM_6318_ENET1_TXDMA_IRQ 0
+#define BCM_6318_PCI_IRQ (IRQ_INTERNAL_BASE + 23)
+#define BCM_6318_ATM_IRQ 0
+#define BCM_6318_ENETSW_RXDMA0_IRQ (BCM_6318_HIGH_IRQ_BASE + 0)
+#define BCM_6318_ENETSW_RXDMA1_IRQ (BCM_6318_HIGH_IRQ_BASE + 1)
+#define BCM_6318_ENETSW_RXDMA2_IRQ (BCM_6318_HIGH_IRQ_BASE + 2)
+#define BCM_6318_ENETSW_RXDMA3_IRQ (BCM_6318_HIGH_IRQ_BASE + 3)
+#define BCM_6318_ENETSW_TXDMA0_IRQ (BCM_6318_VERY_HIGH_IRQ_BASE + 10)
+#define BCM_6318_ENETSW_TXDMA1_IRQ (BCM_6318_VERY_HIGH_IRQ_BASE + 11)
+#define BCM_6318_ENETSW_TXDMA2_IRQ (BCM_6318_VERY_HIGH_IRQ_BASE + 12)
+#define BCM_6318_ENETSW_TXDMA3_IRQ (BCM_6318_VERY_HIGH_IRQ_BASE + 13)
+#define BCM_6318_XTM_IRQ (BCM_6318_HIGH_IRQ_BASE + 31)
+#define BCM_6318_XTM_DMA0_IRQ (BCM_6318_HIGH_IRQ_BASE + 11)
+
+#define BCM_6318_PCM_DMA0_IRQ (IRQ_INTERNAL_BASE + 2)
+#define BCM_6318_PCM_DMA1_IRQ (IRQ_INTERNAL_BASE + 3)
+#define BCM_6318_EXT_IRQ0 (IRQ_INTERNAL_BASE + 24)
+#define BCM_6318_EXT_IRQ1 (IRQ_INTERNAL_BASE + 25)
+#define BCM_6318_EXT_IRQ2 (IRQ_INTERNAL_BASE + 26)
+#define BCM_6318_EXT_IRQ3 (IRQ_INTERNAL_BASE + 27)
/*
* 6328 irqs
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -52,6 +52,39 @@
CKCTL_3368_EMUSB_EN | \
CKCTL_3368_USBU_EN)
+#define CKCTL_6318_ADSL_ASB_EN (1 << 0)
+#define CKCTL_6318_USB_ASB_EN (1 << 1)
+#define CKCTL_6318_MIPS_ASB_EN (1 << 2)
+#define CKCTL_6318_PCIE_ASB_EN (1 << 3)
+#define CKCTL_6318_PHYMIPS_ASB_EN (1 << 4)
+#define CKCTL_6318_ROBOSW_ASB_EN (1 << 5)
+#define CKCTL_6318_SAR_ASB_EN (1 << 6)
+#define CKCTL_6318_SDR_ASB_EN (1 << 7)
+#define CKCTL_6318_SWREG_ASB_EN (1 << 8)
+#define CKCTL_6318_PERIPH_ASB_EN (1 << 9)
+#define CKCTL_6318_CPUBUS160_EN (1 << 10)
+#define CKCTL_6318_ADSL_EN (1 << 11)
+#define CKCTL_6318_SAR125_EN (1 << 12)
+#define CKCTL_6318_MIPS_EN (1 << 13)
+#define CKCTL_6318_PCIE_EN (1 << 14)
+#define CKCTL_6318_ROBOSW250_EN (1 << 16)
+#define CKCTL_6318_ROBOSW025_EN (1 << 17)
+#define CKCTL_6318_SDR_EN (1 << 19)
+#define CKCTL_6318_USB_EN (1 << 20) /* both device and host */
+#define CKCTL_6318_HSSPI_EN (1 << 25)
+#define CKCTL_6318_PCIE25_EN (1 << 27)
+#define CKCTL_6318_PHYMIPS_EN (1 << 28)
+#define CKCTL_6318_ADSL_AFE_EN (1 << 29)
+#define CKCTL_6318_ADSL_QPROC_EN (1 << 30)
+
+#define CKCTL_6318_ALL_SAFE_EN (CKCTL_6318_PHYMIPS_EN | \
+ CKCTL_6318_ADSL_QPROC_EN | \
+ CKCTL_6318_ADSL_AFE_EN | \
+ CKCTL_6318_ADSL_EN | \
+ CKCTL_6318_SAR_EN | \
+ CKCTL_6318_USB_EN | \
+ CKCTL_6318_PCIE_EN)
+
#define CKCTL_6328_PHYMIPS_EN (1 << 0)
#define CKCTL_6328_ADSL_QPROC_EN (1 << 1)
#define CKCTL_6328_ADSL_AFE_EN (1 << 2)
@@ -259,12 +292,27 @@
CKCTL_63268_TBUS_EN | \
CKCTL_63268_ROBOSW250_EN)
+/* UBUS Clock Control register */
+#define PERF_UB_CKCTL_REG 0x10
+
+#define UB_CKCTL_6318_ADSL_EN (1 << 0)
+#define UB_CKCTL_6318_ARB_EN (1 << 1)
+#define UB_CKCTL_6318_MIPS_EN (1 << 2)
+#define UB_CKCTL_6318_PCIE_EN (1 << 3)
+#define UB_CKCTL_6318_PERIPH_EN (1 << 4)
+#define UB_CKCTL_6318_PHYMIPS_EN (1 << 5)
+#define UB_CKCTL_6318_ROBOSW_EN (1 << 6)
+#define UB_CKCTL_6318_SAR_EN (1 << 7)
+#define UB_CKCTL_6318_SDR_EN (1 << 8)
+#define UB_CKCTL_6318_USB_EN (1 << 9)
+
/* System PLL Control register */
#define PERF_SYS_PLL_CTL_REG 0x8
#define SYS_PLL_SOFT_RESET 0x1
/* Interrupt Mask register */
#define PERF_IRQMASK_3368_REG 0xc
+#define PERF_IRQMASK_6318_REG 0x20
#define PERF_IRQMASK_6328_REG(x) (0x20 + (x) * 0x10)
#define PERF_IRQMASK_6338_REG 0xc
#define PERF_IRQMASK_6345_REG 0xc
@@ -276,6 +324,7 @@
/* Interrupt Status register */
#define PERF_IRQSTAT_3368_REG 0x10
+#define PERF_IRQSTAT_6318_REG 0x30
#define PERF_IRQSTAT_6328_REG(x) (0x28 + (x) * 0x10)
#define PERF_IRQSTAT_6338_REG 0x10
#define PERF_IRQSTAT_6345_REG 0x10
@@ -287,6 +336,7 @@
/* External Interrupt Configuration register */
#define PERF_EXTIRQ_CFG_REG_3368 0x14
+#define PERF_EXTIRQ_CFG_REG_6318 0x18
#define PERF_EXTIRQ_CFG_REG_6328 0x18
#define PERF_EXTIRQ_CFG_REG_6338 0x14
#define PERF_EXTIRQ_CFG_REG_6345 0x14
@@ -321,6 +371,7 @@
/* Soft Reset register */
#define PERF_SOFTRESET_REG 0x28
+#define PERF_SOFTRESET_6318_REG 0x10
#define PERF_SOFTRESET_6328_REG 0x10
#define PERF_SOFTRESET_6358_REG 0x34
#define PERF_SOFTRESET_6362_REG 0x10
@@ -334,6 +385,18 @@
#define SOFTRESET_3368_USBS_MASK (1 << 11)
#define SOFTRESET_3368_PCM_MASK (1 << 13)
+#define SOFTRESET_6318_SPI_MASK (1 << 0)
+#define SOFTRESET_6318_EPHY_MASK (1 << 1)
+#define SOFTRESET_6318_SAR_MASK (1 << 2)
+#define SOFTRESET_6318_ENETSW_MASK (1 << 3)
+#define SOFTRESET_6318_USBS_MASK (1 << 4)
+#define SOFTRESET_6318_USBH_MASK (1 << 5)
+#define SOFTRESET_6318_PCIE_CORE_MASK (1 << 6)
+#define SOFTRESET_6318_PCIE_MASK (1 << 7)
+#define SOFTRESET_6318_PCIE_EXT_MASK (1 << 8)
+#define SOFTRESET_6318_PCIE_HARD_MASK (1 << 9)
+#define SOFTRESET_6318_ADSL_MASK (1 << 10)
+
#define SOFTRESET_6328_SPI_MASK (1 << 0)
#define SOFTRESET_6328_EPHY_MASK (1 << 1)
#define SOFTRESET_6328_SAR_MASK (1 << 2)
@@ -505,8 +568,17 @@
#define TIMER_IRQSTAT_TIMER1_IR_EN (1 << 9)
#define TIMER_IRQSTAT_TIMER2_IR_EN (1 << 10)
+#define TIMER_IRQMASK_6318_REG 0x0
+#define TIMER_IRQSTAT_6318_REG 0x4
+#define IRQSTATMASK_TIMER0 (1 << 0)
+#define IRQSTATMASK_TIMER1 (1 << 1)
+#define IRQSTATMASK_TIMER2 (1 << 2)
+#define IRQSTATMASK_TIMER3 (1 << 3)
+#define IRQSTATMASK_WDT (1 << 4)
+
/* Timer control register */
#define TIMER_CTLx_REG(x) (0x4 + (x * 4))
+#define TIMER_CTRx_6318_REG(x) (0x8 + (x * 4))
#define TIMER_CTL0_REG 0x4
#define TIMER_CTL1_REG 0x8
#define TIMER_CTL2_REG 0xC
@@ -1253,6 +1325,8 @@
#define SDRAM_CFG_32B_MASK (1 << SDRAM_CFG_32B_SHIFT)
#define SDRAM_CFG_BANK_SHIFT 13
#define SDRAM_CFG_BANK_MASK (1 << SDRAM_CFG_BANK_SHIFT)
+#define SDRAM_CFG_6318_SPACE_SHIFT 4
+#define SDRAM_CFG_6318_SPACE_MASK (0xf << SDRAM_CFG_6318_SPACE_SHIFT)
#define SDRAM_MBASE_REG 0xc
--- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h
+++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h
@@ -22,6 +22,7 @@ static inline int is_bcm63xx_internal_re
if (offset >= 0xfff00000)
return 1;
break;
+ case BCM6318_CPU_ID:
case BCM6328_CPU_ID:
case BCM6362_CPU_ID:
case BCM6368_CPU_ID:
--- a/arch/mips/bcm63xx/dev-hsspi.c
+++ b/arch/mips/bcm63xx/dev-hsspi.c
@@ -35,7 +35,8 @@ static struct platform_device bcm63xx_hs
int __init bcm63xx_hsspi_register(void)
{
- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_63268())
+ if (!BCMCPU_IS_6318() && !BCMCPU_IS_6328() && !BCMCPU_IS_6362() &&
+ !BCMCPU_IS_63268())
return -ENODEV;
spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
--- a/arch/mips/bcm63xx/dev-usb-usbd.c
+++ b/arch/mips/bcm63xx/dev-usb-usbd.c
@@ -41,7 +41,7 @@ int __init bcm63xx_usbd_register(const s
IRQ_USBD_RXDMA2, IRQ_USBD_TXDMA2 };
int i;
- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
+ if (!BCMCPU_IS_6318() && !BCMCPU_IS_6328() && !BCMCPU_IS_6368())
return 0;
usbd_resources[0].start = bcm63xx_regset_address(RSET_USBD);
--- a/arch/mips/bcm63xx/dev-enet.c
+++ b/arch/mips/bcm63xx/dev-enet.c
@@ -176,8 +176,8 @@ static int __init register_shared(void)
else
shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
- if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368() ||
- BCMCPU_IS_63268())
+ if (BCMCPU_IS_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6362() ||
+ BCMCPU_IS_6368() || BCMCPU_IS_63268())
chan_count = 32;
else if (BCMCPU_IS_6345())
chan_count = 8;
@@ -277,8 +277,8 @@ bcm63xx_enetsw_register(const struct bcm
{
int ret;
- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368() &&
- !BCMCPU_IS_63268())
+ if (!BCMCPU_IS_6318() && !BCMCPU_IS_6328() && !BCMCPU_IS_6362() &&
+ !BCMCPU_IS_6368() && !BCMCPU_IS_63268())
return -ENODEV;
ret = register_shared();
@@ -295,7 +295,7 @@ bcm63xx_enetsw_register(const struct bcm
memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd));
- if (BCMCPU_IS_6328())
+ if (BCMCPU_IS_6318() || BCMCPU_IS_6328())
enetsw_pd.num_ports = ENETSW_PORTS_6328;
else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
enetsw_pd.num_ports = ENETSW_PORTS_6368;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
@@ -9,6 +9,8 @@ int __init bcm63xx_gpio_init(void);
static inline unsigned long bcm63xx_gpio_count(void)
{
switch (bcm63xx_get_cpu_id()) {
+ case BCM6318_CPU_ID:
+ return 50;
case BCM6328_CPU_ID:
return 32;
case BCM3368_CPU_ID:
--- a/arch/mips/bcm63xx/dev-usb-ehci.c
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
@@ -81,7 +81,8 @@ static struct platform_device bcm63xx_eh
int __init bcm63xx_ehci_register(void)
{
- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6358() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
+ if (!BCMCPU_IS_6318() && !BCMCPU_IS_6328() && !BCMCPU_IS_6358() &&
+ !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
return 0;
ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);

View File

@ -0,0 +1,156 @@
From 4bdfacdeaf3c988c4f3256c88118893eac640b03 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 8 Dec 2013 14:17:50 +0100
Subject: [PATCH 52/53] MIPS: BCM63XX: split PCIE reset signals
---
arch/mips/bcm63xx/reset.c | 39 ++++++++++++++--------
arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h | 2 ++
arch/mips/pci/pci-bcm63xx.c | 7 ++++
3 files changed, 34 insertions(+), 14 deletions(-)
--- a/arch/mips/bcm63xx/reset.c
+++ b/arch/mips/bcm63xx/reset.c
@@ -28,7 +28,9 @@
[BCM63XX_RESET_PCM] = BCM## __cpu ##_RESET_PCM, \
[BCM63XX_RESET_MPI] = BCM## __cpu ##_RESET_MPI, \
[BCM63XX_RESET_PCIE] = BCM## __cpu ##_RESET_PCIE, \
- [BCM63XX_RESET_PCIE_EXT] = BCM## __cpu ##_RESET_PCIE_EXT,
+ [BCM63XX_RESET_PCIE_EXT] = BCM## __cpu ##_RESET_PCIE_EXT, \
+ [BCM63XX_RESET_PCIE_CORE] = BCM## __cpu ##_RESET_PCIE_CORE, \
+ [BCM63XX_RESET_PCIE_HARD] = BCM## __cpu ##_RESET_PCIE_HARD,
#define BCM3368_RESET_SPI SOFTRESET_3368_SPI_MASK
#define BCM3368_RESET_ENET SOFTRESET_3368_ENET_MASK
@@ -42,6 +44,8 @@
#define BCM3368_RESET_MPI SOFTRESET_3368_MPI_MASK
#define BCM3368_RESET_PCIE 0
#define BCM3368_RESET_PCIE_EXT 0
+#define BCM3368_RESET_PCIE_CORE 0
+#define BCM3368_RESET_PCIE_HARD 0
#define BCM6318_RESET_SPI SOFTRESET_6318_SPI_MASK
@@ -54,11 +58,10 @@
#define BCM6318_RESET_ENETSW SOFTRESET_6318_ENETSW_MASK
#define BCM6318_RESET_PCM 0
#define BCM6318_RESET_MPI 0
-#define BCM6318_RESET_PCIE \
- (SOFTRESET_6318_PCIE_MASK | \
- SOFTRESET_6318_PCIE_CORE_MASK | \
- SOFTRESET_6318_PCIE_HARD_MASK)
+#define BCM6318_RESET_PCIE SOFTRESET_6318_PCIE_MASK
#define BCM6318_RESET_PCIE_EXT SOFTRESET_6318_PCIE_EXT_MASK
+#define BCM6318_RESET_PCIE_CORE SOFTRESET_6318_PCIE_CORE_MASK
+#define BCM6318_RESET_PCIE_HARD SOFTRESET_6318_PCIE_HARD_MASK
#define BCM6328_RESET_SPI SOFTRESET_6328_SPI_MASK
#define BCM6328_RESET_ENET 0
@@ -70,11 +73,10 @@
#define BCM6328_RESET_ENETSW SOFTRESET_6328_ENETSW_MASK
#define BCM6328_RESET_PCM SOFTRESET_6328_PCM_MASK
#define BCM6328_RESET_MPI 0
-#define BCM6328_RESET_PCIE \
- (SOFTRESET_6328_PCIE_MASK | \
- SOFTRESET_6328_PCIE_CORE_MASK | \
- SOFTRESET_6328_PCIE_HARD_MASK)
+#define BCM6328_RESET_PCIE SOFTRESET_6328_PCIE_MASK
#define BCM6328_RESET_PCIE_EXT SOFTRESET_6328_PCIE_EXT_MASK
+#define BCM6328_RESET_PCIE_CORE SOFTRESET_6328_PCIE_CORE_MASK
+#define BCM6328_RESET_PCIE_HARD SOFTRESET_6328_PCIE_HARD_MASK
#define BCM6338_RESET_SPI SOFTRESET_6338_SPI_MASK
#define BCM6338_RESET_ENET SOFTRESET_6338_ENET_MASK
@@ -88,6 +90,8 @@
#define BCM6338_RESET_MPI 0
#define BCM6338_RESET_PCIE 0
#define BCM6338_RESET_PCIE_EXT 0
+#define BCM6338_RESET_PCIE_CORE 0
+#define BCM6338_RESET_PCIE_HARD 0
#define BCM6348_RESET_SPI SOFTRESET_6348_SPI_MASK
#define BCM6348_RESET_ENET SOFTRESET_6348_ENET_MASK
@@ -101,6 +105,8 @@
#define BCM6348_RESET_MPI 0
#define BCM6348_RESET_PCIE 0
#define BCM6348_RESET_PCIE_EXT 0
+#define BCM6348_RESET_PCIE_CORE 0
+#define BCM6348_RESET_PCIE_HARD 0
#define BCM6358_RESET_SPI SOFTRESET_6358_SPI_MASK
#define BCM6358_RESET_ENET SOFTRESET_6358_ENET_MASK
@@ -114,6 +120,8 @@
#define BCM6358_RESET_MPI SOFTRESET_6358_MPI_MASK
#define BCM6358_RESET_PCIE 0
#define BCM6358_RESET_PCIE_EXT 0
+#define BCM6358_RESET_PCIE_CORE 0
+#define BCM6358_RESET_PCIE_HARD 0
#define BCM6362_RESET_SPI SOFTRESET_6362_SPI_MASK
#define BCM6362_RESET_ENET 0
@@ -125,9 +133,10 @@
#define BCM6362_RESET_ENETSW SOFTRESET_6362_ENETSW_MASK
#define BCM6362_RESET_PCM SOFTRESET_6362_PCM_MASK
#define BCM6362_RESET_MPI 0
-#define BCM6362_RESET_PCIE (SOFTRESET_6362_PCIE_MASK | \
- SOFTRESET_6362_PCIE_CORE_MASK)
+#define BCM6362_RESET_PCIE SOFTRESET_6362_PCIE_MASK
#define BCM6362_RESET_PCIE_EXT SOFTRESET_6362_PCIE_EXT_MASK
+#define BCM6362_RESET_PCIE_CORE SOFTRESET_6362_PCIE_CORE_MASK
+#define BCM6362_RESET_PCIE_HARD 0
#define BCM6368_RESET_SPI SOFTRESET_6368_SPI_MASK
#define BCM6368_RESET_ENET 0
@@ -141,6 +150,8 @@
#define BCM6368_RESET_MPI SOFTRESET_6368_MPI_MASK
#define BCM6368_RESET_PCIE 0
#define BCM6368_RESET_PCIE_EXT 0
+#define BCM6368_RESET_PCIE_CORE 0
+#define BCM6368_RESET_PCIE_HARD 0
#define BCM63268_RESET_SPI SOFTRESET_63268_SPI_MASK
#define BCM63268_RESET_ENET 0
@@ -152,10 +163,10 @@
#define BCM63268_RESET_ENETSW SOFTRESET_63268_ENETSW_MASK
#define BCM63268_RESET_PCM SOFTRESET_63268_PCM_MASK
#define BCM63268_RESET_MPI 0
-#define BCM63268_RESET_PCIE (SOFTRESET_63268_PCIE_MASK | \
- SOFTRESET_63268_PCIE_CORE_MASK | \
- SOFTRESET_63268_PCIE_HARD_MASK)
+#define BCM63268_RESET_PCIE SOFTRESET_63268_PCIE_MASK
#define BCM63268_RESET_PCIE_EXT SOFTRESET_63268_PCIE_EXT_MASK
+#define BCM63268_RESET_PCIE_CORE SOFTRESET_63268_PCIE_CORE_MASK
+#define BCM63268_RESET_PCIE_HARD SOFTRESET_63268_PCIE_HARD_MASK
/*
* core reset bits
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h
@@ -14,6 +14,8 @@ enum bcm63xx_core_reset {
BCM63XX_RESET_MPI,
BCM63XX_RESET_PCIE,
BCM63XX_RESET_PCIE_EXT,
+ BCM63XX_RESET_PCIE_CORE,
+ BCM63XX_RESET_PCIE_HARD,
};
void bcm63xx_core_set_reset(enum bcm63xx_core_reset, int reset);
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -135,9 +135,16 @@ static void __init bcm63xx_reset_pcie(vo
/* reset the PCIe core */
bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 1);
bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1);
+ if (BCMCPU_IS_6328() || BCMCPU_IS_63268()) {
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_HARD, 1);
+ mdelay(10);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_HARD, 0);
+ }
mdelay(10);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 0);
bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0);
mdelay(10);

View File

@ -0,0 +1,342 @@
From 11a8ab8dac4ef5d0d70199843043927edce1d4db Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 15 Dec 2013 20:47:34 +0100
Subject: [PATCH 53/53] MIPS: BCM63XX: add PCIe support for BCM6318
---
arch/mips/bcm63xx/clk.c | 25 ++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 6 ++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 60 +++++++++++-
arch/mips/pci/ops-bcm63xx.c | 16 +++-
arch/mips/pci/pci-bcm63xx.c | 106 ++++++++++++++++++----
5 files changed, 184 insertions(+), 29 deletions(-)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -50,6 +50,18 @@ static void bcm_hwclock_set(u32 mask, in
bcm_perf_writel(reg, PERF_CKCTL_REG);
}
+static void bcm_ub_hwclock_set(u32 mask, int enable)
+{
+ u32 reg;
+
+ reg = bcm_perf_readl(PERF_UB_CKCTL_REG);
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ bcm_perf_writel(reg, PERF_UB_CKCTL_REG);
+}
+
/*
* Ethernet MAC "misc" clock: dma clocks and main clock on 6348
*/
@@ -317,12 +329,17 @@ static struct clk clk_ipsec = {
static void pcie_set(struct clk *clk, int enable)
{
- if (BCMCPU_IS_6328())
+ if (BCMCPU_IS_6318()) {
+ bcm_hwclock_set(CKCTL_6318_PCIE_EN, enable);
+ bcm_hwclock_set(CKCTL_6318_PCIE25_EN, enable);
+ bcm_ub_hwclock_set(UB_CKCTL_6318_PCIE_EN, enable);
+ } else if (BCMCPU_IS_6328()) {
bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
- else if (BCMCPU_IS_6362())
+ } else if (BCMCPU_IS_6362()) {
bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
- else if (BCMCPU_IS_63268())
+ } else if (BCMCPU_IS_63268()) {
bcm_hwclock_set(CKCTL_63268_PCIE_EN, enable);
+ }
}
static struct clk clk_pcie = {
@@ -405,7 +422,7 @@ struct clk *clk_get(struct device *dev,
if ((BCMCPU_IS_6362() || BCMCPU_IS_6368() || BCMCPU_IS_63268()) &&
!strcmp(id, "ipsec"))
return &clk_ipsec;
- if ((BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) &&
+ if ((BCMCPU_IS_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) &&
!strcmp(id, "pcie"))
return &clk_pcie;
return ERR_PTR(-ENOENT);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
@@ -40,6 +40,12 @@
#define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \
BCM_CB_MEM_SIZE - 1)
+#define BCM_PCIE_MEM_BASE_PA_6318 0x10200000
+#define BCM_PCIE_MEM_SIZE_6318 (1 * 1024 * 1024)
+#define BCM_PCIE_MEM_END_PA_6318 (BCM_PCIE_MEM_BASE_PA_6318 + \
+ BCM_PCIE_MEM_SIZE_6318 - 1)
+
+
#define BCM_PCIE_MEM_BASE_PA_6328 0x10f00000
#define BCM_PCIE_MEM_SIZE_6328 (1 * 1024 * 1024)
#define BCM_PCIE_MEM_END_PA_6328 (BCM_PCIE_MEM_BASE_PA_6328 + \
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -1529,6 +1529,17 @@
* _REG relative to RSET_PCIE
*************************************************************************/
+#define PCIE_SPECIFIC_REG 0x188
+#define SPECIFIC_ENDIAN_MODE_BAR1_SHIFT 0
+#define SPECIFIC_ENDIAN_MODE_BAR1_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
+#define SPECIFIC_ENDIAN_MODE_BAR2_SHIFT 2
+#define SPECIFIC_ENDIAN_MODE_BAR2_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
+#define SPECIFIC_ENDIAN_MODE_BAR3_SHIFT 4
+#define SPECIFIC_ENDIAN_MODE_BAR3_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
+#define SPECIFIC_ENDIAN_MODE_WORD_ALIGN 0
+#define SPECIFIC_ENDIAN_MODE_HALFWORD_ALIGN 1
+#define SPECIFIC_ENDIAN_MODE_BYTE_ALIGN 2
+
#define PCIE_CONFIG2_REG 0x408
#define CONFIG2_BAR1_SIZE_EN 1
#define CONFIG2_BAR1_SIZE_MASK 0xf
@@ -1574,7 +1585,54 @@
#define PCIE_RC_INT_C (1 << 2)
#define PCIE_RC_INT_D (1 << 3)
-#define PCIE_DEVICE_OFFSET 0x8000
+#define PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG 0x400c
+#define C2P_MEM_WIN_ENDIAN_MODE_MASK 0x3
+#define C2P_MEM_WIN_ENDIAN_NO_SWAP 0
+#define C2P_MEM_WIN_ENDIAN_HALF_WORD_SWAP 1
+#define C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP 2
+#define C2P_MEM_WIN_BASE_ADDR_SHIFT 20
+#define C2P_MEM_WIN_BASE_ADDR_MASK (0xfff << C2P_MEM_WIN_BASE_ADDR_SHIFT)
+
+#define PCIE_RC_BAR1_CONFIG_LO_REG 0x402c
+#define RC_BAR_CFG_LO_SIZE_256MB 0xd
+#define RC_BAR_CFG_LO_MATCH_ADDR_SHIFT 20
+#define RC_BAR_CFG_LO_MATCH_ADDR_MASK (0xfff << RC_BAR_CFG_LO_MATCH_ADDR_SHIFT)
+
+#define PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG 0x4070
+#define C2P_BASELIMIT_LIMIT_SHIFT 20
+#define C2P_BASELIMIT_LIMIT_MASK (0xfff << C2P_BASELIMIT_LIMIT_SHIFT)
+#define C2P_BASELIMIT_BASE_SHIFT 4
+#define C2P_BASELIMIT_BASE_MASK (0xfff << C2P_BASELIMIT_BASE_SHIFT)
+
+#define PCIE_UBUS_BAR1_CFG_REMAP_REG 0x4088
+#define BAR1_CFG_REMAP_OFFSET_SHIFT 20
+#define BAR1_CFG_REMAP_OFFSET_MASK (0xfff << BAR1_CFG_REMAP_OFFSET_SHIFT)
+#define BAR1_CFG_REMAP_ACCESS_EN 1
+
+#define PCIE_HARD_DEBUG_REG 0x4204
+#define HARD_DEBUG_SERDES_IDDQ (1 << 23)
+
+#define PCIE_CPU_INT1_MASK_CLEAR_REG 0x830c
+#define CPU_INT_PCIE_ERR_ATTN_CPU (1 << 0)
+#define CPU_INT_PCIE_INTA (1 << 1)
+#define CPU_INT_PCIE_INTB (1 << 2)
+#define CPU_INT_PCIE_INTC (1 << 3)
+#define CPU_INT_PCIE_INTD (1 << 4)
+#define CPU_INT_PCIE_INTR (1 << 5)
+#define CPU_INT_PCIE_NMI (1 << 6)
+#define CPU_INT_PCIE_UBUS (1 << 7)
+#define CPU_INT_IPI (1 << 8)
+
+#define PCIE_EXT_CFG_INDEX_REG 0x8400
+#define EXT_CFG_FUNC_NUM_SHIFT 12
+#define EXT_CFG_FUNC_NUM_MASK (0x7 << EXT_CFG_FUNC_NUM_SHIFT)
+#define EXT_CFG_DEV_NUM_SHIFT 15
+#define EXT_CFG_DEV_NUM_MASK (0xf << EXT_CFG_DEV_NUM_SHIFT)
+#define EXT_CFG_BUS_NUM_SHIFT 20
+#define EXT_CFG_BUS_NUM_MASK (0xff << EXT_CFG_BUS_NUM_SHIFT)
+
+#define PCIE_DEVICE_OFFSET_6318 0x9000
+#define PCIE_DEVICE_OFFSET_6328 0x8000
/*************************************************************************
* _REG relative to RSET_OTP
--- a/arch/mips/pci/ops-bcm63xx.c
+++ b/arch/mips/pci/ops-bcm63xx.c
@@ -488,8 +488,12 @@ static int bcm63xx_pcie_read(struct pci_
if (!bcm63xx_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
- if (bus->number == PCIE_BUS_DEVICE)
- reg += PCIE_DEVICE_OFFSET;
+ if (bus->number == PCIE_BUS_DEVICE) {
+ if (BCMCPU_IS_6318())
+ reg += PCIE_DEVICE_OFFSET_6318;
+ else
+ reg += PCIE_DEVICE_OFFSET_6328;
+ }
data = bcm_pcie_readl(reg);
@@ -508,8 +512,12 @@ static int bcm63xx_pcie_write(struct pci
if (!bcm63xx_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
- if (bus->number == PCIE_BUS_DEVICE)
- reg += PCIE_DEVICE_OFFSET;
+ if (bus->number == PCIE_BUS_DEVICE) {
+ if (BCMCPU_IS_6318())
+ reg += PCIE_DEVICE_OFFSET_6318;
+ else
+ reg += PCIE_DEVICE_OFFSET_6328;
+ }
data = bcm_pcie_readl(reg);
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -118,7 +118,7 @@ static void bcm63xx_int_cfg_writel(u32 v
void __iomem *pci_iospace_start;
-static void __init bcm63xx_reset_pcie(void)
+static void __init bcm63xx_reset_pcie_gen1(void)
{
u32 val;
u32 reg;
@@ -152,20 +152,32 @@ static void __init bcm63xx_reset_pcie(vo
mdelay(200);
}
-static struct clk *pcie_clk;
-
-static int __init bcm63xx_register_pcie(void)
+static void __init bcm63xx_reset_pcie_gen2(void)
{
u32 val;
- /* enable clock */
- pcie_clk = clk_get(NULL, "pcie");
- if (IS_ERR_OR_NULL(pcie_clk))
- return -ENODEV;
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_HARD, 0);
- clk_prepare_enable(pcie_clk);
+ /* reset the PCIe core */
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 1);
+ mdelay(10);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 0);
+ mdelay(10);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0);
+ mdelay(10);
+ val = bcm_pcie_readl(PCIE_HARD_DEBUG_REG);
+ val &= ~HARD_DEBUG_SERDES_IDDQ;
+ bcm_pcie_writel(val, PCIE_HARD_DEBUG_REG);
+ mdelay(10);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 0);
+ mdelay(200);
+}
- bcm63xx_reset_pcie();
+static void __init bcm63xx_init_pcie_gen1(void)
+{
+ u32 val;
/* configure the PCIe bridge */
val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
@@ -190,6 +202,65 @@ static int __init bcm63xx_register_pcie(
val |= OPT2_CFG_TYPE1_BD_SEL;
bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
+ /* set bar0 to little endian */
+ val = (bcm_pcie_mem_resource.start >> 20) << BASEMASK_BASE_SHIFT;
+ val |= (bcm_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT;
+ val |= BASEMASK_REMAP_EN;
+ bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
+
+ val = (bcm_pcie_mem_resource.start >> 20) << REBASE_ADDR_BASE_SHIFT;
+ bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
+}
+
+static void __init bcm63xx_init_pcie_gen2(void)
+{
+ u32 val;
+
+ bcm_pcie_writel(CPU_INT_PCIE_INTA | CPU_INT_PCIE_INTB |
+ CPU_INT_PCIE_INTC | CPU_INT_PCIE_INTD,
+ PCIE_CPU_INT1_MASK_CLEAR_REG);
+
+ val = bcm_pcie_mem_resource.end & C2P_BASELIMIT_LIMIT_MASK;
+ val |= (bcm_pcie_mem_resource.start >> C2P_BASELIMIT_LIMIT_SHIFT) <<
+ C2P_BASELIMIT_BASE_SHIFT;
+
+ bcm_pcie_writel(val, PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG);
+
+ /* set bar0 to little endian */
+ val = bcm_pcie_readl(PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG);
+ val |= bcm_pcie_mem_resource.start & C2P_MEM_WIN_BASE_ADDR_MASK;
+ val |= C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP;
+ bcm_pcie_writel(val, PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG);
+
+ bcm_pcie_writel(SPECIFIC_ENDIAN_MODE_BYTE_ALIGN, PCIE_SPECIFIC_REG);
+ bcm_pcie_writel(RC_BAR_CFG_LO_SIZE_256MB, PCIE_RC_BAR1_CONFIG_LO_REG);
+ bcm_pcie_writel(BAR1_CFG_REMAP_ACCESS_EN, PCIE_UBUS_BAR1_CFG_REMAP_REG);
+
+ bcm_pcie_writel(PCIE_BUS_DEVICE << EXT_CFG_BUS_NUM_SHIFT,
+ PCIE_EXT_CFG_INDEX_REG);
+}
+
+static struct clk *pcie_clk;
+
+static int __init bcm63xx_register_pcie(void)
+{
+ u32 val;
+
+ /* enable clock */
+ pcie_clk = clk_get(NULL, "pcie");
+ if (IS_ERR_OR_NULL(pcie_clk))
+ return -ENODEV;
+
+ clk_prepare_enable(pcie_clk);
+
+ if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) {
+ bcm63xx_reset_pcie_gen1();
+ bcm63xx_init_pcie_gen1();
+ } else {
+ bcm63xx_reset_pcie_gen2();
+ bcm63xx_init_pcie_gen2();
+ }
+
/* setup class code as bridge */
val = bcm_pcie_readl(PCIE_IDVAL3_REG);
val &= ~IDVAL3_CLASS_CODE_MASK;
@@ -201,15 +272,6 @@ static int __init bcm63xx_register_pcie(
val &= ~CONFIG2_BAR1_SIZE_MASK;
bcm_pcie_writel(val, PCIE_CONFIG2_REG);
- /* set bar0 to little endian */
- val = (bcm_pcie_mem_resource.start >> 20) << BASEMASK_BASE_SHIFT;
- val |= (bcm_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT;
- val |= BASEMASK_REMAP_EN;
- bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
-
- val = (bcm_pcie_mem_resource.start >> 20) << REBASE_ADDR_BASE_SHIFT;
- bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
-
register_pci_controller(&bcm63xx_pcie_controller);
return 0;
@@ -341,7 +403,10 @@ static int __init bcm63xx_pci_init(void)
if (!bcm63xx_pci_enabled)
return -ENODEV;
- if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
+ if (BCMCPU_IS_6318()) {
+ bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_6318;
+ bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_6318;
+ } if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_6328;
bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_6328;
} else if (BCMCPU_IS_63268()) {
@@ -350,6 +415,7 @@ static int __init bcm63xx_pci_init(void)
}
switch (bcm63xx_get_cpu_id()) {
+ case BCM6318_CPU_ID:
case BCM6328_CPU_ID:
case BCM6362_CPU_ID:
case BCM63268_CPU_ID:

View File

@ -0,0 +1,74 @@
From 9a97177b907330971aa7bf41855fafc2602e1c18 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 22 Dec 2013 12:26:57 +0100
Subject: [PATCH 51/56] MIPS: BCM63XX: detect flash type early and store the
result
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/dev-flash.c | 10 +++++++---
arch/mips/bcm63xx/prom.c | 4 ++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 2 ++
3 files changed, 13 insertions(+), 3 deletions(-)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -22,6 +22,8 @@
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
+static int flash_type;
+
static struct mtd_partition mtd_partitions[] = {
{
.name = "cfe",
@@ -108,13 +110,15 @@ static int __init bcm63xx_detect_flash_t
}
}
+void __init bcm63xx_flash_detect(void)
+{
+ flash_type = bcm63xx_detect_flash_type();
+}
+
int __init bcm63xx_flash_register(void)
{
- int flash_type;
u32 val;
- flash_type = bcm63xx_detect_flash_type();
-
switch (flash_type) {
case BCM63XX_FLASH_TYPE_PARALLEL:
/* read base address of boot chip select (0) */
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -17,6 +17,7 @@
#include <bcm63xx_cpu.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
+#include <bcm63xx_dev_flash.h>
void __init prom_init(void)
{
@@ -52,6 +53,9 @@ void __init prom_init(void)
reg &= ~mask;
bcm_perf_writel(reg, PERF_CKCTL_REG);
+ /* detect and setup flash access */
+ bcm63xx_flash_detect();
+
/* do low level board init */
board_prom_init();
--- 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,
};
+void bcm63xx_flash_detect(void);
+
int __init bcm63xx_flash_register(void);
#endif /* __BCM63XX_FLASH_H */

View File

@ -0,0 +1,63 @@
From 1cacd0f7b0d35f8e3d3f8a69ecb3b5e436d6b9e8 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 22 Dec 2013 13:25:25 +0100
Subject: [PATCH 52/56] MIPS: BCM63XX: fixup mapped SPI flash access on boot
Some bootloaders leave the flash access in an invalid state with dual
read enabled; fix it by disabling it and falling back to simple fast
reads.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/dev-flash.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -110,9 +110,46 @@ static int __init bcm63xx_detect_flash_t
}
}
+#define HSSPI_FLASH_CTRL_REG 0x14
+#define FLASH_CTRL_READ_OPCODE_MASK 0xff
+#define FLASH_CTRL_ADDR_BYTES_MASK (0x3 << 8)
+#define FLASH_CTRL_ADDR_BYTES_2 (0 << 8)
+#define FLASH_CTRL_ADDR_BYTES_3 (1 << 8)
+#define FLASH_CTRL_ADDR_BYTES_4 (2 << 8)
+#define FLASH_CTRL_MB_EN (1 << 23)
+
void __init bcm63xx_flash_detect(void)
{
flash_type = bcm63xx_detect_flash_type();
+
+ /* reduce flash mapping to single i/o reads for safety */
+ if (flash_type == BCM63XX_FLASH_TYPE_SERIAL &&
+ (BCMCPU_IS_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6362() ||
+ BCMCPU_IS_63268())) {
+ u32 val = bcm_rset_readl(RSET_HSSPI, HSSPI_FLASH_CTRL_REG);
+
+ if (!(val & FLASH_CTRL_MB_EN))
+ return;
+
+ val &= ~FLASH_CTRL_MB_EN;
+ val &= ~FLASH_CTRL_READ_OPCODE_MASK;
+
+ switch (val & FLASH_CTRL_ADDR_BYTES_MASK) {
+ case FLASH_CTRL_ADDR_BYTES_3:
+ val |= 0x0b; /* OPCODE_FAST_READ */
+ break;
+ case FLASH_CTRL_ADDR_BYTES_4:
+ val |= 0x0c; /* OPCODE_FAST_READ_4B */
+ break;
+ case FLASH_CTRL_ADDR_BYTES_2:
+ default:
+ pr_warn("unsupported address byte mode (%x), not fixing up\n",
+ val & FLASH_CTRL_ADDR_BYTES_MASK);
+ return;
+ }
+
+ bcm_rset_writel(RSET_HSSPI, val, HSSPI_FLASH_CTRL_REG);
+ }
}
int __init bcm63xx_flash_register(void)

View File

@ -0,0 +1,56 @@
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -136,7 +136,11 @@ static struct clk clk_ephy = {
*/
static void enetsw_set(struct clk *clk, int enable)
{
- if (BCMCPU_IS_6328())
+ if (BCMCPU_IS_6318()) {
+ bcm_hwclock_set(CKCTL_6318_ROBOSW250_EN |
+ CKCTL_6318_ROBOSW025_EN, enable);
+ bcm_ub_hwclock_set(UB_CKCTL_6318_ROBOSW_EN, enable);
+ } else if (BCMCPU_IS_6328())
bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
else if (BCMCPU_IS_6362())
bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
@@ -183,18 +187,22 @@ static struct clk clk_pcm = {
*/
static void usbh_set(struct clk *clk, int enable)
{
- if (BCMCPU_IS_6328())
+ if (BCMCPU_IS_6318()) {
+ bcm_hwclock_set(CKCTL_6318_USB_EN, enable);
+ bcm_ub_hwclock_set(UB_CKCTL_6318_USB_EN, enable);
+ } else if (BCMCPU_IS_6328()) {
bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
- else if (BCMCPU_IS_6348())
+ } else if (BCMCPU_IS_6348()) {
bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
- else if (BCMCPU_IS_6362())
+ } else if (BCMCPU_IS_6362()) {
bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
- else if (BCMCPU_IS_6368())
+ } else if (BCMCPU_IS_6368()) {
bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
- else if (BCMCPU_IS_63268())
+ } else if (BCMCPU_IS_63268()) {
bcm_hwclock_set(CKCTL_63268_USBH_EN, enable);
- else
+ } else {
return;
+ }
if (enable)
msleep(100);
@@ -405,9 +413,9 @@ struct clk *clk_get(struct device *dev,
return &clk_enetsw;
if (!strcmp(id, "ephy"))
return &clk_ephy;
- if (!strcmp(id, "usbh"))
+ if (!strcmp(id, "usbh") || (BCMCPU_IS_6318() && !strcmp(id, "usbd")))
return &clk_usbh;
- if (!strcmp(id, "usbd"))
+ if (!strcmp(id, "usbd") && !BCMCPU_IS_6318())
return &clk_usbd;
if (!strcmp(id, "spi"))
return &clk_spi;

View File

@ -0,0 +1,124 @@
--- a/arch/mips/bcm63xx/usb-common.c
+++ b/arch/mips/bcm63xx/usb-common.c
@@ -109,6 +109,27 @@ void bcm63xx_usb_priv_ohci_cfg_set(void)
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);
+ } else if (BCMCPU_IS_6318()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6318_REG);
+ reg |= USBH_PRIV_PLL_CTRL1_SUSP_EN;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6318_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6318_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_6318_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6318_REG);
+ reg |= USBH_PRIV_SETUP_IOC_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6318_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6318_REG);
+ reg &= ~USBH_PRIV_PLL_CTRL1_IDDQ_PWRDN;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6318_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SIM_CTRL_6318_REG);
+ reg |= USBH_PRIV_SIM_CTRL_LADDR_SEL;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SIM_CTRL_6318_REG);
}
spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
@@ -144,6 +165,27 @@ void bcm63xx_usb_priv_ehci_cfg_set(void)
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);
+ } else if (BCMCPU_IS_6318()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6318_REG);
+ reg |= USBH_PRIV_PLL_CTRL1_SUSP_EN;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6318_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6318_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_6318_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6318_REG);
+ reg |= USBH_PRIV_SETUP_IOC_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6318_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6318_REG);
+ reg &= ~USBH_PRIV_PLL_CTRL1_IDDQ_PWRDN;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6318_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SIM_CTRL_6318_REG);
+ reg |= USBH_PRIV_SIM_CTRL_LADDR_SEL;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SIM_CTRL_6318_REG);
}
spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -681,6 +681,12 @@
#define GPIO_MODE_6368_SPI_SSN4 (1 << 30)
#define GPIO_MODE_6368_SPI_SSN5 (1 << 31)
+#define GPIO_PINMUX_SEL0_6318 0x1c
+#define GPIO_PINMUX_SEL0_GPIO13_SHIFT 26
+#define GPIO_PINMUX_SEL0_GPIO13_MASK (0x3 << GPIO_PINMUX_SEL0_GPIO13_SHIFT)
+#define GPIO_PINMUX_SEL0_GPIO13_PWRON (1 << GPIO_PINMUX_SEL0_GPIO13_SHIFT)
+#define GPIO_PINMUX_SEL0_GPIO13_LED (2 << GPIO_PINMUX_SEL0_GPIO13_SHIFT)
+#define GPIO_PINMUX_SEL0_GPIO13_GPIO (3 << GPIO_PINMUX_SEL0_GPIO13_SHIFT)
#define GPIO_PINMUX_OTHR_REG 0x24
#define GPIO_PINMUX_OTHR_6328_USB_SHIFT 12
@@ -999,6 +1005,7 @@
#define USBH_PRIV_SWAP_6358_REG 0x0
#define USBH_PRIV_SWAP_6368_REG 0x1c
+#define USBH_PRIV_SWAP_6318_REG 0x0c
#define USBH_PRIV_SWAP_USBD_SHIFT 6
#define USBH_PRIV_SWAP_USBD_MASK (1 << USBH_PRIV_SWAP_USBD_SHIFT)
@@ -1024,6 +1031,13 @@
#define USBH_PRIV_SETUP_IOC_SHIFT 4
#define USBH_PRIV_SETUP_IOC_MASK (1 << USBH_PRIV_SETUP_IOC_SHIFT)
+#define USBH_PRIV_SETUP_6318_REG 0x00
+#define USBH_PRIV_PLL_CTRL1_6318_REG 0x04
+#define USBH_PRIV_PLL_CTRL1_SUSP_EN (1 << 27)
+#define USBH_PRIV_PLL_CTRL1_IDDQ_PWRDN (1 << 31)
+#define USBH_PRIV_SIM_CTRL_6318_REG 0x20
+#define USBH_PRIV_SIM_CTRL_LADDR_SEL (1 << 5)
+
/*************************************************************************
* _REG relative to RSET_USBD
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -129,6 +129,15 @@ void __init board_early_setup(const stru
}
bcm_gpio_writel(val, GPIO_MODE_REG);
+
+#if IS_ENABLED(CONFIG_USB)
+ if (BCMCPU_IS_6318() && (board.has_ehci0 || board.has_ohci0)) {
+ val = bcm_gpio_readl(GPIO_PINMUX_SEL0_6318);
+ val &= ~GPIO_PINMUX_SEL0_GPIO13_MASK;
+ val |= GPIO_PINMUX_SEL0_GPIO13_PWRON;
+ bcm_gpio_writel(val, GPIO_PINMUX_SEL0_6318);
+ }
+#endif
}
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -22,6 +22,8 @@ config BCM63XX_CPU_6318
bool "support 6318 CPU"
select SYS_HAS_CPU_BMIPS32_3300
select HW_HAS_PCI
+ select BCM63XX_OHCI
+ select BCM63XX_EHCI
config BCM63XX_CPU_6328
bool "support 6328 CPU"

View File

@ -0,0 +1,71 @@
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -586,6 +586,9 @@
#define TIMER_CTL_MONOTONIC_MASK (1 << 30)
#define TIMER_CTL_ENABLE_MASK (1 << 31)
+/* Clock reset control (63268 only) */
+#define TIMER_CLK_RST_CTL_REG 0x2c
+#define CLK_RST_CTL_USB_REF_CLK_EN (1 << 18)
/*************************************************************************
* _REG relative to RSET_WDT
@@ -1533,6 +1536,11 @@
#define STRAPBUS_63268_FCVO_SHIFT 21
#define STRAPBUS_63268_FCVO_MASK (0xf << STRAPBUS_63268_FCVO_SHIFT)
+#define MISC_IDDQ_CTRL_6328_REG 0x48
+#define MISC_IDDQ_CTRL_63268_REG 0x4c
+
+#define IDDQ_CTRL_63268_USBH (1 << 4)
+
#define MISC_STRAPBUS_6328_REG 0x240
#define STRAPBUS_6328_FCVO_SHIFT 7
#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -62,6 +62,26 @@ static void bcm_ub_hwclock_set(u32 mask,
bcm_perf_writel(reg, PERF_UB_CKCTL_REG);
}
+static void bcm_misc_iddq_set(u32 mask, int enable)
+{
+ u32 offset;
+ u32 reg;
+
+ if (BCMCPU_IS_6328() || BCMCPU_IS_6362())
+ offset = MISC_IDDQ_CTRL_6328_REG;
+ else if (BCMCPU_IS_63268())
+ offset = MISC_IDDQ_CTRL_63268_REG;
+ else
+ return;
+
+ reg = bcm_misc_readl(offset);
+ if (enable)
+ reg &= ~mask;
+ else
+ reg |= mask;
+ bcm_misc_writel(reg, offset);
+}
+
/*
* Ethernet MAC "misc" clock: dma clocks and main clock on 6348
*/
@@ -199,7 +219,17 @@ static void usbh_set(struct clk *clk, in
} else if (BCMCPU_IS_6368()) {
bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
} else if (BCMCPU_IS_63268()) {
+ u32 reg;
+
bcm_hwclock_set(CKCTL_63268_USBH_EN, enable);
+ bcm_misc_iddq_set(IDDQ_CTRL_63268_USBH, enable);
+ bcm63xx_core_set_reset(BCM63XX_RESET_USBH, !enable);
+ reg = bcm_timer_readl(TIMER_CLK_RST_CTL_REG);
+ if (enable)
+ reg |= CLK_RST_CTL_USB_REF_CLK_EN;
+ else
+ reg &= ~CLK_RST_CTL_USB_REF_CLK_EN;
+ bcm_timer_writel(reg, TIMER_CLK_RST_CTL_REG);
} else {
return;
}

View File

@ -0,0 +1,117 @@
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -1033,11 +1033,18 @@
#define USBH_PRIV_SETUP_6368_REG 0x28
#define USBH_PRIV_SETUP_IOC_SHIFT 4
#define USBH_PRIV_SETUP_IOC_MASK (1 << USBH_PRIV_SETUP_IOC_SHIFT)
+#define USBH_PRIV_SETUP_IPP_SHIFT 5
+#define USBH_PRIV_SETUP_IPP_MASK (1 << USBH_PRIV_SETUP_IPP_SHIFT)
#define USBH_PRIV_SETUP_6318_REG 0x00
+#define USBH_PRIV_PLL_CTRL1_6368_REG 0x18
#define USBH_PRIV_PLL_CTRL1_6318_REG 0x04
-#define USBH_PRIV_PLL_CTRL1_SUSP_EN (1 << 27)
-#define USBH_PRIV_PLL_CTRL1_IDDQ_PWRDN (1 << 31)
+
+#define USBH_PRIV_PLL_CTRL1_6318_SUSP_EN (1 << 27)
+#define USBH_PRIV_PLL_CTRL1_6318_IDDQ_PWRDN (1 << 31)
+#define USBH_PRIV_PLL_CTRL1_63268_IDDQ_PWRDN (1 << 9)
+#define USBH_PRIV_PLL_CTRL1_63268_PWRDN_DELAY (1 << 10)
+
#define USBH_PRIV_SIM_CTRL_6318_REG 0x20
#define USBH_PRIV_SIM_CTRL_LADDR_SEL (1 << 5)
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -72,6 +72,8 @@ config BCM63XX_CPU_63268
bool "support 63268 CPU"
select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
+ select BCM63XX_OHCI
+ select BCM63XX_EHCI
endmenu
source "arch/mips/bcm63xx/boards/Kconfig"
--- a/arch/mips/bcm63xx/dev-usb-ehci.c
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
@@ -82,7 +82,7 @@ static struct platform_device bcm63xx_eh
int __init bcm63xx_ehci_register(void)
{
if (!BCMCPU_IS_6318() && !BCMCPU_IS_6328() && !BCMCPU_IS_6358() &&
- !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
+ !BCMCPU_IS_6362() && !BCMCPU_IS_6368() && !BCMCPU_IS_63268())
return 0;
ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
--- a/arch/mips/bcm63xx/usb-common.c
+++ b/arch/mips/bcm63xx/usb-common.c
@@ -109,9 +109,24 @@ void bcm63xx_usb_priv_ohci_cfg_set(void)
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);
+ } else if (BCMCPU_IS_63268()) {
+ 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;
+ reg &= ~USBH_PRIV_SETUP_IPP_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6368_REG);
+ reg &= ~(USBH_PRIV_PLL_CTRL1_63268_IDDQ_PWRDN |
+ USBH_PRIV_PLL_CTRL1_63268_PWRDN_DELAY);
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6368_REG);
} else if (BCMCPU_IS_6318()) {
reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6318_REG);
- reg |= USBH_PRIV_PLL_CTRL1_SUSP_EN;
+ reg |= USBH_PRIV_PLL_CTRL1_6318_SUSP_EN;
bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6318_REG);
reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6318_REG);
@@ -124,7 +139,7 @@ void bcm63xx_usb_priv_ohci_cfg_set(void)
bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6318_REG);
reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6318_REG);
- reg &= ~USBH_PRIV_PLL_CTRL1_IDDQ_PWRDN;
+ reg &= ~USBH_PRIV_PLL_CTRL1_6318_IDDQ_PWRDN;
bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6318_REG);
reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SIM_CTRL_6318_REG);
@@ -165,9 +180,24 @@ void bcm63xx_usb_priv_ehci_cfg_set(void)
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);
+ } else if (BCMCPU_IS_63268()) {
+ 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;
+ reg &= ~USBH_PRIV_SETUP_IPP_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6368_REG);
+ reg &= ~(USBH_PRIV_PLL_CTRL1_63268_IDDQ_PWRDN |
+ USBH_PRIV_PLL_CTRL1_63268_PWRDN_DELAY);
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6368_REG);
} else if (BCMCPU_IS_6318()) {
reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6318_REG);
- reg |= USBH_PRIV_PLL_CTRL1_SUSP_EN;
+ reg |= USBH_PRIV_PLL_CTRL1_6318_SUSP_EN;
bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6318_REG);
reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6318_REG);
@@ -180,7 +210,7 @@ void bcm63xx_usb_priv_ehci_cfg_set(void)
bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6318_REG);
reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_PLL_CTRL1_6318_REG);
- reg &= ~USBH_PRIV_PLL_CTRL1_IDDQ_PWRDN;
+ reg &= ~USBH_PRIV_PLL_CTRL1_6318_IDDQ_PWRDN;
bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_PLL_CTRL1_6318_REG);
reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SIM_CTRL_6318_REG);

View File

@ -0,0 +1,107 @@
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -42,6 +42,7 @@ struct board_info {
/* USB config */
struct bcm63xx_usbd_platform_data usbd;
+ unsigned int num_usbh_ports:2;
/* DSP config */
struct bcm63xx_dsp_platform_data dsp;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
@@ -1,6 +1,6 @@
#ifndef BCM63XX_DEV_USB_EHCI_H_
#define BCM63XX_DEV_USB_EHCI_H_
-int bcm63xx_ehci_register(void);
+int bcm63xx_ehci_register(unsigned int num_ports);
#endif /* BCM63XX_DEV_USB_EHCI_H_ */
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
@@ -1,6 +1,6 @@
#ifndef BCM63XX_DEV_USB_OHCI_H_
#define BCM63XX_DEV_USB_OHCI_H_
-int bcm63xx_ohci_register(void);
+int bcm63xx_ohci_register(unsigned int num_ports);
#endif /* BCM63XX_DEV_USB_OHCI_H_ */
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -181,6 +181,7 @@ int __init board_register_devices(void)
{
int button_count = 0;
int led_count = 0;
+ int usbh_ports = 0;
if (board.has_uart0)
bcm63xx_uart_register(0);
@@ -203,14 +204,21 @@ int __init board_register_devices(void)
!board_get_mac_address(board.enetsw.mac_addr))
bcm63xx_enetsw_register(&board.enetsw);
+ if ((board.has_ohci0 || board.has_ehci0)) {
+ usbh_ports = board.num_usbh_ports;
+
+ if (!usbh_ports || WARN_ON(usbh_ports > 1 && board.has_usbd))
+ usbh_ports = 1;
+ }
+
if (board.has_usbd)
bcm63xx_usbd_register(&board.usbd);
if (board.has_ehci0)
- bcm63xx_ehci_register();
+ bcm63xx_ehci_register(usbh_ports);
if (board.has_ohci0)
- bcm63xx_ohci_register();
+ bcm63xx_ohci_register(usbh_ports);
if (board.has_dsp)
bcm63xx_dsp_register(&board.dsp);
--- a/arch/mips/bcm63xx/dev-usb-ehci.c
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
@@ -79,12 +79,14 @@ static struct platform_device bcm63xx_eh
},
};
-int __init bcm63xx_ehci_register(void)
+int __init bcm63xx_ehci_register(unsigned int num_ports)
{
if (!BCMCPU_IS_6318() && !BCMCPU_IS_6328() && !BCMCPU_IS_6358() &&
!BCMCPU_IS_6362() && !BCMCPU_IS_6368() && !BCMCPU_IS_63268())
return 0;
+ bcm63xx_ehci_pdata.num_ports = num_ports;
+
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;
--- a/arch/mips/bcm63xx/dev-usb-ohci.c
+++ b/arch/mips/bcm63xx/dev-usb-ohci.c
@@ -62,7 +62,6 @@ static struct usb_ohci_pdata bcm63xx_ohc
.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,
@@ -80,11 +79,13 @@ static struct platform_device bcm63xx_oh
},
};
-int __init bcm63xx_ohci_register(void)
+int __init bcm63xx_ohci_register(unsigned int num_ports)
{
if (BCMCPU_IS_6345() || BCMCPU_IS_6338())
return -ENODEV;
+ bcm63xx_ohci_pdata.num_ports = num_ports;
+
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;

View File

@ -0,0 +1,10 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -596,6 +596,7 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pccard = 1,
.has_ehci0 = 1,
+ .num_usbh_ports = 2,
.leds = {
{

View File

@ -0,0 +1,95 @@
From 0daf361ea799fba0af5a232036d0f06cea85ad24 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 21 Jun 2014 12:47:49 +0200
Subject: [PATCH 42/44] MIPS: BCM63XX: allow building support for more than one
board type
Use the arguments passed to the kernel to detect being booted with
CFE as the indicator for bcm963xx board support, allowing the
non presence of CFE_EPTSEAL to assume a different board type.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/Kconfig | 7 +++----
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
arch/mips/bcm63xx/boards/board_common.c | 13 +++++++++++++
arch/mips/bcm63xx/boards/board_common.h | 6 ++++++
4 files changed, 23 insertions(+), 5 deletions(-)
--- a/arch/mips/bcm63xx/boards/Kconfig
+++ b/arch/mips/bcm63xx/boards/Kconfig
@@ -1,11 +1,10 @@
-choice
- prompt "Board support"
+menu "Board support"
depends on BCM63XX
- default BOARD_BCM963XX
config BOARD_BCM963XX
bool "Generic Broadcom 963xx boards"
select SSB
+ default y
help
-endchoice
+endmenu
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -706,7 +706,7 @@ static const struct board_info __initcon
/*
* early init callback, read nvram data from flash and checksum it
*/
-void __init board_prom_init(void)
+void __init board_bcm963xx_init(void)
{
unsigned int i;
u8 *boot_addr, *cfe;
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -15,6 +15,8 @@
#include <linux/gpio_keys.h>
#include <linux/spi/spi.h>
#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/fw/cfe/cfe_api.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_uart.h>
@@ -32,6 +34,8 @@
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
+#include "board_common.h"
+
#define PFX "board: "
#define BCM963XX_KEYS_POLL_INTERVAL 20
@@ -84,6 +88,15 @@ const char *board_get_name(void)
return board.name;
}
+void __init board_prom_init(void)
+{
+ /* detect bootloader */
+ if (fw_arg3 == CFE_EPTSEAL)
+ board_bcm963xx_init();
+ else
+ panic("unsupported bootloader detected");
+}
+
static int (*board_get_mac_address)(u8 mac[ETH_ALEN]);
/*
--- a/arch/mips/bcm63xx/boards/board_common.h
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -6,4 +6,10 @@
void board_early_setup(const struct board_info *board,
int (*get_mac_address)(u8 mac[ETH_ALEN]));
+#if defined(CONFIG_BOARD_BCM963XX)
+void board_bcm963xx_init(void);
+#else
+static inline void board_bcm963xx_init(void) { }
+#endif
+
#endif /* __BOARD_COMMON_H */

View File

@ -0,0 +1,61 @@
From 8a30097a899b975709f728666d5ad20c8b832d21 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 9 Mar 2014 04:28:14 +0100
Subject: [PATCH 43/44] MIPS: BCM63XX: allow board implementations to force
flash address
Allow board implementations to force the physmap address.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/dev-flash.c | 19 ++++++++++++++-----
.../mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 2 ++
2 files changed, 16 insertions(+), 5 deletions(-)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -57,6 +57,12 @@ static struct platform_device mtd_dev =
},
};
+void __init bcm63xx_flash_force_phys_base_address(u32 start, u32 end)
+{
+ mtd_resources[0].start = start;
+ mtd_resources[0].end = end;
+}
+
static int __init bcm63xx_detect_flash_type(void)
{
u32 val;
@@ -158,12 +164,15 @@ int __init bcm63xx_flash_register(void)
switch (flash_type) {
case BCM63XX_FLASH_TYPE_PARALLEL:
- /* read base address of boot chip select (0) */
- val = bcm_mpi_readl(MPI_CSBASE_REG(0));
- val &= MPI_CSBASE_BASE_MASK;
- mtd_resources[0].start = val;
- mtd_resources[0].end = 0x1FFFFFFF;
+ if (!mtd_resources[0].start) {
+ /* read base address of boot chip select (0) */
+ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+ val &= MPI_CSBASE_BASE_MASK;
+
+ mtd_resources[0].start = val;
+ mtd_resources[0].end = 0x1FFFFFFF;
+ }
return platform_device_register(&mtd_dev);
case BCM63XX_FLASH_TYPE_SERIAL:
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
@@ -9,6 +9,8 @@ enum {
void bcm63xx_flash_detect(void);
+void bcm63xx_flash_force_phys_base_address(u32 start, u32 end);
+
int __init bcm63xx_flash_register(void);
#endif /* __BCM63XX_FLASH_H */

View File

@ -0,0 +1,188 @@
From cc025e749a1fece61a6cc0d64bbe7b12472259cc Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 29 Jul 2014 21:31:12 +0200
Subject: [PATCH 01/10] MIPS: BCM63XX: move fallback sprom support into its own
unit
In preparation for enhancing it, move it into its own file. Require a
mac address to be passed as the argument to always "reserve" the mac
regardless of the inclusion state of SSB.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/boards/board_common.c | 53 ++--------------
arch/mips/bcm63xx/sprom.c | 70 ++++++++++++++++++++++
.../asm/mach-bcm63xx/bcm63xx_fallback_sprom.h | 6 ++
4 files changed, 83 insertions(+), 48 deletions(-)
create mode 100644 arch/mips/bcm63xx/sprom.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.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-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \
dev-wdt.o dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o \
- usb-common.o
+ usb-common.o sprom.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -43,44 +43,6 @@
static struct board_info board;
/*
- * Register a sane SPROMv2 to make the on-board
- * bcm4318 WLAN work
- */
-#ifdef CONFIG_SSB_PCIHOST
-static struct ssb_sprom bcm63xx_sprom = {
- .revision = 0x02,
- .board_rev = 0x17,
- .country_code = 0x0,
- .ant_available_bg = 0x3,
- .pa0b0 = 0x15ae,
- .pa0b1 = 0xfa85,
- .pa0b2 = 0xfe8d,
- .pa1b0 = 0xffff,
- .pa1b1 = 0xffff,
- .pa1b2 = 0xffff,
- .gpio0 = 0xff,
- .gpio1 = 0xff,
- .gpio2 = 0xff,
- .gpio3 = 0xff,
- .maxpwr_bg = 0x004c,
- .itssi_bg = 0x00,
- .boardflags_lo = 0x2848,
- .boardflags_hi = 0x0000,
-};
-
-int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
-{
- if (bus->bustype == SSB_BUSTYPE_PCI) {
- memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
- return 0;
- } else {
- printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
- return -EINVAL;
- }
-}
-#endif
-
-/*
* return board name for /proc/cpuinfo
*/
const char *board_get_name(void)
@@ -195,6 +157,7 @@ int __init board_register_devices(void)
int button_count = 0;
int led_count = 0;
int usbh_ports = 0;
+ u8 mac[ETH_ALEN];
if (board.has_uart0)
bcm63xx_uart_register(0);
@@ -239,15 +202,10 @@ int __init board_register_devices(void)
/* Generate MAC address for WLAN and register our SPROM,
* do this after registering enet devices
*/
-#ifdef CONFIG_SSB_PCIHOST
- if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
- memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- if (ssb_arch_register_fallback_sprom(
- &bcm63xx_get_fallback_sprom) < 0)
- pr_err(PFX "failed to register fallback SPROM\n");
- }
-#endif
+
+ if (board_get_mac_address(mac) ||
+ bcm63xx_register_fallback_sprom(mac))
+ pr_err(PFX "failed to register fallback SPROM\n");
bcm63xx_spi_register();
--- /dev/null
+++ b/arch/mips/bcm63xx/sprom.c
@@ -0,0 +1,70 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/ssb/ssb.h>
+#include <bcm63xx_fallback_sprom.h>
+#include <board_bcm963xx.h>
+
+#define PFX "sprom: "
+
+/*
+ * Register a sane SPROMv2 to make the on-board
+ * bcm4318 WLAN work
+ */
+#ifdef CONFIG_SSB_PCIHOST
+static struct ssb_sprom bcm63xx_sprom = {
+ .revision = 0x02,
+ .board_rev = 0x17,
+ .country_code = 0x0,
+ .ant_available_bg = 0x3,
+ .pa0b0 = 0x15ae,
+ .pa0b1 = 0xfa85,
+ .pa0b2 = 0xfe8d,
+ .pa1b0 = 0xffff,
+ .pa1b1 = 0xffff,
+ .pa1b2 = 0xffff,
+ .gpio0 = 0xff,
+ .gpio1 = 0xff,
+ .gpio2 = 0xff,
+ .gpio3 = 0xff,
+ .maxpwr_bg = 0x004c,
+ .itssi_bg = 0x00,
+ .boardflags_lo = 0x2848,
+ .boardflags_hi = 0x0000,
+};
+
+int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+{
+ if (bus->bustype == SSB_BUSTYPE_PCI) {
+ memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
+ return 0;
+ } else {
+ printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+ return -EINVAL;
+ }
+}
+#endif
+
+int __init bcm63xx_register_fallback_sprom(u8 *mac)
+{
+ int ret = 0;
+
+#ifdef CONFIG_SSB_PCIHOST
+ memcpy(bcm63xx_sprom.il0mac, mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et0mac, mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, mac, ETH_ALEN);
+
+ ret = ssb_arch_register_fallback_sprom(&bcm63xx_get_fallback_sprom);
+#endif
+ return ret;
+}
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
@@ -0,0 +1,6 @@
+#ifndef __BCM63XX_FALLBACK_SPROM
+#define __BCM63XX_FALLBACK_SPROM
+
+int bcm63xx_register_fallback_sprom(u8 *mac);
+
+#endif

View File

@ -0,0 +1,95 @@
From 9912a8b3c240a9b0af01ff496b7e8ed9e4cc5b82 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 29 Jul 2014 21:43:49 +0200
Subject: [PATCH 02/10] MIPS: BCM63XX: use platform data for the sprom
Similar to ethernet setup, use a platform data struct for passing
the mac. This eliminates the requirement to allocate an array on
stack for the mac passed.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_common.c | 6 ++----
arch/mips/bcm63xx/sprom.c | 8 ++++----
arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h | 8 +++++++-
arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 4 ++++
4 files changed, 17 insertions(+), 9 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -157,7 +157,6 @@ int __init board_register_devices(void)
int button_count = 0;
int led_count = 0;
int usbh_ports = 0;
- u8 mac[ETH_ALEN];
if (board.has_uart0)
bcm63xx_uart_register(0);
@@ -203,8 +202,8 @@ int __init board_register_devices(void)
* do this after registering enet devices
*/
- if (board_get_mac_address(mac) ||
- bcm63xx_register_fallback_sprom(mac))
+ if (board_get_mac_address(board.fallback_sprom.mac_addr) ||
+ bcm63xx_register_fallback_sprom(&board.fallback_sprom))
pr_err(PFX "failed to register fallback SPROM\n");
bcm63xx_spi_register();
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -55,14 +55,14 @@ int bcm63xx_get_fallback_sprom(struct ss
}
#endif
-int __init bcm63xx_register_fallback_sprom(u8 *mac)
+int __init bcm63xx_register_fallback_sprom(struct fallback_sprom_data *data)
{
int ret = 0;
#ifdef CONFIG_SSB_PCIHOST
- memcpy(bcm63xx_sprom.il0mac, mac, ETH_ALEN);
- memcpy(bcm63xx_sprom.et0mac, mac, ETH_ALEN);
- memcpy(bcm63xx_sprom.et1mac, mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.il0mac, data->mac_addr, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et0mac, data->mac_addr, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, data->mac_addr, ETH_ALEN);
ret = ssb_arch_register_fallback_sprom(&bcm63xx_get_fallback_sprom);
#endif
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
@@ -1,6 +1,12 @@
#ifndef __BCM63XX_FALLBACK_SPROM
#define __BCM63XX_FALLBACK_SPROM
-int bcm63xx_register_fallback_sprom(u8 *mac);
+#include <linux/if_ether.h>
+
+struct fallback_sprom_data {
+ u8 mac_addr[ETH_ALEN];
+};
+
+int bcm63xx_register_fallback_sprom(struct fallback_sprom_data *data);
#endif
--- 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 <bcm63xx_fallback_sprom.h>
/*
* flash mapping
@@ -59,6 +60,9 @@ struct board_info {
/* External PHY reset GPIO flags from gpio.h */
unsigned long ephy_reset_gpio_flags;
+ /* fallback sprom config */
+ struct fallback_sprom_data fallback_sprom;
+
/* Additional platform devices */
struct platform_device **devs;
unsigned int num_devs;

View File

@ -0,0 +1,140 @@
From 83131acbfb59760a19f3711c09526e191c8aad54 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 29 Jul 2014 21:52:56 +0200
Subject: [PATCH 03/10] MIPS: BCM63XX: make fallback sprom optional
Some devices do not provide enough mac addresses to populate wifi in
addition to ethernet.
Use having pci enabled as a rough heuristic which boards should have it
enabled.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 12 ++++++++++++
arch/mips/bcm63xx/boards/board_common.c | 5 +++--
arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 1 +
3 files changed, 16 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -74,6 +74,7 @@ static struct board_info __initdata boar
.has_uart0 = 1,
.has_pci = 1,
.has_usbd = 0,
+ .use_fallback_sprom = 1,
.usbd = {
.use_fullspeed = 0,
@@ -223,6 +224,7 @@ static struct board_info __initdata boar
.has_uart0 = 1,
.has_enet0 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -268,6 +270,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -328,6 +331,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -382,6 +386,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -440,6 +445,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -463,6 +469,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -481,6 +488,7 @@ static struct board_info __initdata boar
.has_uart0 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.has_ohci0 = 1,
.has_enet0 = 1,
@@ -503,6 +511,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -529,6 +538,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -581,6 +591,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
@@ -652,6 +663,7 @@ static struct board_info __initdata boar
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.enet0 = {
.has_phy = 1,
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -202,8 +202,9 @@ int __init board_register_devices(void)
* do this after registering enet devices
*/
- if (board_get_mac_address(board.fallback_sprom.mac_addr) ||
- bcm63xx_register_fallback_sprom(&board.fallback_sprom))
+ if (board.use_fallback_sprom &&
+ (board_get_mac_address(board.fallback_sprom.mac_addr) ||
+ bcm63xx_register_fallback_sprom(&board.fallback_sprom)))
pr_err(PFX "failed to register fallback SPROM\n");
bcm63xx_spi_register();
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -35,6 +35,7 @@ struct board_info {
unsigned int has_dsp:1;
unsigned int has_uart0:1;
unsigned int has_uart1:1;
+ unsigned int use_fallback_sprom:1;
/* ethernet config */
struct bcm63xx_enet_platform_data enet0;

View File

@ -0,0 +1,66 @@
From 1cece9f7aca1f0c193edce201f77a87008c5a405 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 29 Jul 2014 21:58:38 +0200
Subject: [PATCH 04/10] MIPS: BCM63XX: allow different types of sprom
Different chips require different sprom contents, so prepare for
supplying the appropriate sprom type.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/sprom.c | 13 ++++++++++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h | 5 +++++
2 files changed, 17 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -22,7 +22,7 @@
* bcm4318 WLAN work
*/
#ifdef CONFIG_SSB_PCIHOST
-static struct ssb_sprom bcm63xx_sprom = {
+static __initconst struct ssb_sprom bcm63xx_default_sprom = {
.revision = 0x02,
.board_rev = 0x17,
.country_code = 0x0,
@@ -43,6 +43,8 @@ static struct ssb_sprom bcm63xx_sprom =
.boardflags_hi = 0x0000,
};
+static struct ssb_sprom bcm63xx_sprom;
+
int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
{
if (bus->bustype == SSB_BUSTYPE_PCI) {
@@ -60,6 +62,15 @@ int __init bcm63xx_register_fallback_spr
int ret = 0;
#ifdef CONFIG_SSB_PCIHOST
+ switch (data->type) {
+ case SPROM_DEFAULT:
+ memcpy(&bcm63xx_sprom, &bcm63xx_default_sprom,
+ sizeof(bcm63xx_sprom));
+ break;
+ default:
+ return -EINVAL;
+ }
+
memcpy(bcm63xx_sprom.il0mac, data->mac_addr, ETH_ALEN);
memcpy(bcm63xx_sprom.et0mac, data->mac_addr, ETH_ALEN);
memcpy(bcm63xx_sprom.et1mac, data->mac_addr, ETH_ALEN);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
@@ -3,8 +3,13 @@
#include <linux/if_ether.h>
+enum sprom_type {
+ SPROM_DEFAULT, /* default fallback sprom */
+};
+
struct fallback_sprom_data {
u8 mac_addr[ETH_ALEN];
+ enum sprom_type type;
};
int bcm63xx_register_fallback_sprom(struct fallback_sprom_data *data);

View File

@ -0,0 +1,517 @@
From cedee63bc73f8b7d45b8c0cba1236986812c1f83 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 29 Jul 2014 22:16:36 +0200
Subject: [PATCH 05/10] MIPS: BCM63XX: add support for "raw" sproms
Allow using raw sprom content as templates.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/sprom.c | 482 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 482 insertions(+)
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -55,13 +55,492 @@ int bcm63xx_get_fallback_sprom(struct ss
return -EINVAL;
}
}
+
+/* FIXME: use lib_sprom after submission upstream */
+
+/* Get the word-offset for a SSB_SPROM_XXX define. */
+#define SPOFF(offset) ((offset) / sizeof(u16))
+/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
+#define SPEX16(_outvar, _offset, _mask, _shift) \
+ out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
+#define SPEX32(_outvar, _offset, _mask, _shift) \
+ out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
+ in[SPOFF(_offset)]) & (_mask)) >> (_shift))
+#define SPEX(_outvar, _offset, _mask, _shift) \
+ SPEX16(_outvar, _offset, _mask, _shift)
+
+#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
+ do { \
+ SPEX(_field[0], _offset + 0, _mask, _shift); \
+ SPEX(_field[1], _offset + 2, _mask, _shift); \
+ SPEX(_field[2], _offset + 4, _mask, _shift); \
+ SPEX(_field[3], _offset + 6, _mask, _shift); \
+ SPEX(_field[4], _offset + 8, _mask, _shift); \
+ SPEX(_field[5], _offset + 10, _mask, _shift); \
+ SPEX(_field[6], _offset + 12, _mask, _shift); \
+ SPEX(_field[7], _offset + 14, _mask, _shift); \
+ } while (0)
+
+
+static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
+ u16 mask, u16 shift)
+{
+ u16 v;
+ u8 gain;
+
+ v = in[SPOFF(SSB_SPROM1_AGAIN)];
+ gain = (v & mask) >> shift;
+ if (gain == 0xFF)
+ gain = 2; /* If unset use 2dBm */
+ if (sprom_revision == 1) {
+ /* Convert to Q5.2 */
+ gain <<= 2;
+ } else {
+ /* Q5.2 Fractional part is stored in 0xC0 */
+ gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
+ }
+
+ return (s8)gain;
+}
+
+static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
+{
+ SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
+ SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
+ SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
+ SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
+ SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
+ SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
+ SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
+ SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
+ SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
+ SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
+ SSB_SPROM2_MAXP_A_LO_SHIFT);
+}
+
+static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
+{
+ u16 loc[3];
+
+ if (out->revision == 3) /* rev 3 moved MAC */
+ loc[0] = SSB_SPROM3_IL0MAC;
+ else {
+ loc[0] = SSB_SPROM1_IL0MAC;
+ loc[1] = SSB_SPROM1_ET0MAC;
+ loc[2] = SSB_SPROM1_ET1MAC;
+ }
+
+ SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
+ SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
+ SSB_SPROM1_ETHPHY_ET1A_SHIFT);
+ SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
+ SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
+ SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
+ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
+ if (out->revision == 1)
+ SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
+ SSB_SPROM1_BINF_CCODE_SHIFT);
+ SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
+ SSB_SPROM1_BINF_ANTA_SHIFT);
+ SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
+ SSB_SPROM1_BINF_ANTBG_SHIFT);
+ SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
+ SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
+ SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
+ SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
+ SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
+ SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
+ SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
+ SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
+ SSB_SPROM1_GPIOA_P1_SHIFT);
+ SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
+ SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
+ SSB_SPROM1_GPIOB_P3_SHIFT);
+ SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
+ SSB_SPROM1_MAXPWR_A_SHIFT);
+ SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
+ SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
+ SSB_SPROM1_ITSSI_A_SHIFT);
+ SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
+ SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
+
+ SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
+ SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
+
+ /* Extract the antenna gain values. */
+ out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
+ SSB_SPROM1_AGAIN_BG,
+ SSB_SPROM1_AGAIN_BG_SHIFT);
+ out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
+ SSB_SPROM1_AGAIN_A,
+ SSB_SPROM1_AGAIN_A_SHIFT);
+ if (out->revision >= 2)
+ sprom_extract_r23(out, in);
+}
+
+/* Revs 4 5 and 8 have partially shared layout */
+static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
+{
+ SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
+ SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
+ SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
+ SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
+ SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
+ SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
+ SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
+ SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
+
+ SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
+ SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
+ SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
+ SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
+ SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
+ SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
+ SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
+ SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
+
+ SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
+ SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
+ SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
+ SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
+ SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
+ SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
+ SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
+ SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
+
+ SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
+ SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
+ SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
+ SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
+ SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
+ SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
+ SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
+ SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
+}
+
+static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
+{
+ u16 il0mac_offset;
+
+ if (out->revision == 4)
+ il0mac_offset = SSB_SPROM4_IL0MAC;
+ else
+ il0mac_offset = SSB_SPROM5_IL0MAC;
+
+ SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
+ SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
+ SSB_SPROM4_ETHPHY_ET1A_SHIFT);
+ SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
+ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
+ if (out->revision == 4) {
+ SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
+ SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
+ SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
+ SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+ SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
+ SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
+ } else {
+ SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
+ SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
+ SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
+ SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+ SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
+ SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
+ }
+ SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
+ SSB_SPROM4_ANTAVAIL_A_SHIFT);
+ SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
+ SSB_SPROM4_ANTAVAIL_BG_SHIFT);
+ SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
+ SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
+ SSB_SPROM4_ITSSI_BG_SHIFT);
+ SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
+ SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
+ SSB_SPROM4_ITSSI_A_SHIFT);
+ if (out->revision == 4) {
+ SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
+ SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
+ SSB_SPROM4_GPIOA_P1_SHIFT);
+ SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
+ SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
+ SSB_SPROM4_GPIOB_P3_SHIFT);
+ } else {
+ SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
+ SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
+ SSB_SPROM5_GPIOA_P1_SHIFT);
+ SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
+ SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
+ SSB_SPROM5_GPIOB_P3_SHIFT);
+ }
+
+ /* Extract the antenna gain values. */
+ SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
+ SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
+ SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
+ SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
+ SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
+ SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
+ SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
+ SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
+
+ sprom_extract_r458(out, in);
+
+ /* TODO - get remaining rev 4 stuff needed */
+}
+
+static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
+{
+ int i;
+ u16 o;
+ u16 pwr_info_offset[] = {
+ SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
+ SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
+ };
+ BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
+ ARRAY_SIZE(out->core_pwr_info));
+
+ SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
+ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
+ SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
+ SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
+ SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
+ SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+ SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
+ SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
+ SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
+ SSB_SPROM8_ANTAVAIL_A_SHIFT);
+ SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
+ SSB_SPROM8_ANTAVAIL_BG_SHIFT);
+ SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
+ SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
+ SSB_SPROM8_ITSSI_BG_SHIFT);
+ SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
+ SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
+ SSB_SPROM8_ITSSI_A_SHIFT);
+ SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
+ SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
+ SSB_SPROM8_MAXP_AL_SHIFT);
+ SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
+ SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
+ SSB_SPROM8_GPIOA_P1_SHIFT);
+ SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
+ SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
+ SSB_SPROM8_GPIOB_P3_SHIFT);
+ SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
+ SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
+ SSB_SPROM8_TRI5G_SHIFT);
+ SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
+ SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
+ SSB_SPROM8_TRI5GH_SHIFT);
+ SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
+ SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
+ SSB_SPROM8_RXPO5G_SHIFT);
+ SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
+ SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
+ SSB_SPROM8_RSSISMC2G_SHIFT);
+ SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
+ SSB_SPROM8_RSSISAV2G_SHIFT);
+ SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
+ SSB_SPROM8_BXA2G_SHIFT);
+ SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
+ SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
+ SSB_SPROM8_RSSISMC5G_SHIFT);
+ SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
+ SSB_SPROM8_RSSISAV5G_SHIFT);
+ SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
+ SSB_SPROM8_BXA5G_SHIFT);
+ SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
+ SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
+ SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
+ SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
+ SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
+ SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
+ SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
+ SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
+ SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
+ SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
+ SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
+ SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
+ SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
+ SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
+
+ /* Extract the antenna gain values. */
+ SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
+ SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
+ SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
+ SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
+ SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
+ SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
+ SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
+ SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
+
+ /* Extract cores power info info */
+ for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
+ o = pwr_info_offset[i];
+ SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
+ SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
+ SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
+ SSB_SPROM8_2G_MAXP, 0);
+
+ SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
+ SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
+ SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
+
+ SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
+ SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
+ SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
+ SSB_SPROM8_5G_MAXP, 0);
+ SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
+ SSB_SPROM8_5GH_MAXP, 0);
+ SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
+ SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
+
+ SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
+ SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
+ SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
+ SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
+ SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
+ SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
+ SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
+ SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
+ SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
+ }
+
+ /* Extract FEM info */
+ SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
+ SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
+ SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
+ SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
+ SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
+ SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
+ SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
+ SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
+ SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
+ SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
+
+ SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
+ SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
+ SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
+ SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
+ SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
+ SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
+ SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
+ SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
+ SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
+ SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
+
+ SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
+ SSB_SPROM8_LEDDC_ON_SHIFT);
+ SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
+ SSB_SPROM8_LEDDC_OFF_SHIFT);
+
+ SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
+ SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
+ SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
+ SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
+ SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
+ SSB_SPROM8_TXRXC_SWITCH_SHIFT);
+
+ SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
+
+ SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
+ SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
+ SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
+ SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
+
+ SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
+ SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
+ SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
+ SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
+ SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
+ SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
+ SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
+ SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
+ SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
+ SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
+ SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
+ SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
+ SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
+ SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
+ SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
+ SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
+ SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
+ SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
+ SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
+ SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
+
+ SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
+ SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
+ SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
+ SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
+
+ SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
+ SSB_SPROM8_THERMAL_TRESH_SHIFT);
+ SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
+ SSB_SPROM8_THERMAL_OFFSET_SHIFT);
+ SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
+ SSB_SPROM8_TEMPDELTA_PHYCAL,
+ SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
+ SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
+ SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
+ SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
+ SSB_SPROM8_TEMPDELTA_HYSTERESIS,
+ SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
+ sprom_extract_r458(out, in);
+
+ /* TODO - get remaining rev 8 stuff needed */
+}
+
+static int sprom_extract(struct ssb_sprom *out, const u16 *in, u16 size)
+{
+ memset(out, 0, sizeof(*out));
+
+ out->revision = in[size - 1] & 0x00FF;
+ memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
+ memset(out->et1mac, 0xFF, 6);
+
+ switch (out->revision) {
+ case 1:
+ case 2:
+ case 3:
+ sprom_extract_r123(out, in);
+ break;
+ case 4:
+ case 5:
+ sprom_extract_r45(out, in);
+ break;
+ case 8:
+ sprom_extract_r8(out, in);
+ break;
+ default:
+ pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
+ out->revision);
+ out->revision = 1;
+ sprom_extract_r123(out, in);
+ }
+
+ if (out->boardflags_lo == 0xFFFF)
+ out->boardflags_lo = 0; /* per specs */
+ if (out->boardflags_hi == 0xFFFF)
+ out->boardflags_hi = 0; /* per specs */
+
+ return 0;
+}
+
+static __initdata u16 template_sprom[220];
#endif
+
int __init bcm63xx_register_fallback_sprom(struct fallback_sprom_data *data)
{
int ret = 0;
#ifdef CONFIG_SSB_PCIHOST
+ u16 size = 0;
+
switch (data->type) {
case SPROM_DEFAULT:
memcpy(&bcm63xx_sprom, &bcm63xx_default_sprom,
@@ -71,6 +550,9 @@ int __init bcm63xx_register_fallback_spr
return -EINVAL;
}
+ if (size > 0)
+ sprom_extract(&bcm63xx_sprom, template_sprom, size);
+
memcpy(bcm63xx_sprom.il0mac, data->mac_addr, ETH_ALEN);
memcpy(bcm63xx_sprom.et0mac, data->mac_addr, ETH_ALEN);
memcpy(bcm63xx_sprom.et1mac, data->mac_addr, ETH_ALEN);

View File

@ -0,0 +1,181 @@
From 7be5bb46003295c9e04fd4e795593b2deaacd783 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 29 Jul 2014 22:33:38 +0200
Subject: [PATCH 06/10] MIPS: BCM63XX: add raw fallback sproms for most common
ssb cards
Add template sproms for BCM4306, BCM4318, BCM4321, BCM4322, and BCM43222.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/sprom.c | 136 +++++++++++++++++++++
.../asm/mach-bcm63xx/bcm63xx_fallback_sprom.h | 6 +
2 files changed, 142 insertions(+)
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -43,6 +43,122 @@ static __initconst struct ssb_sprom bcm6
.boardflags_hi = 0x0000,
};
+
+static __initconst u16 bcm4306_sprom[] = {
+ 0x4001, 0x0000, 0x0453, 0x14e4, 0x4320, 0x8000, 0x0002, 0x0002,
+ 0x1000, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x3034, 0x14d4,
+ 0xfa91, 0xfe60, 0xffff, 0xffff, 0x004c, 0xffff, 0xffff, 0xffff,
+ 0x003e, 0x0a49, 0xff02, 0x0000, 0xff10, 0xffff, 0xffff, 0x0002,
+};
+
+static __initconst u16 bcm4318_sprom[] = {
+ 0x2001, 0x0000, 0x0449, 0x14e4, 0x4318, 0x8000, 0x0002, 0x0000,
+ 0x1000, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x3046, 0x15a7,
+ 0xfab0, 0xfe97, 0xffff, 0xffff, 0x0048, 0xffff, 0xffff, 0xffff,
+ 0x003e, 0xea49, 0xff02, 0x0000, 0xff08, 0xffff, 0xffff, 0x0002,
+};
+
+static __initconst u16 bcm4321_sprom[] = {
+ 0x3001, 0x0000, 0x046c, 0x14e4, 0x4328, 0x8000, 0x0002, 0x0000,
+ 0x1000, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x5372, 0x0032, 0x4a01, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0x0303, 0x0202,
+ 0xffff, 0x2728, 0x5b5b, 0x222b, 0x5b5b, 0x1927, 0x5b5b, 0x1e36,
+ 0x5b5b, 0x303c, 0x3030, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x3e4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x7838, 0x3a34, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x3e4c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7838, 0x3a34, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x0008, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x0004,
+};
+
+static __initconst u16 bcm4322_sprom[] = {
+ 0x3001, 0x0000, 0x04bc, 0x14e4, 0x432c, 0x8000, 0x0002, 0x0000,
+ 0x1730, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x5372, 0x1209, 0x0200, 0x0000, 0x0400, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0x0303, 0x0202,
+ 0xffff, 0x0033, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0301,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x2048, 0xfe9a, 0x1571, 0xfabd, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x2048, 0xfeb9, 0x159f, 0xfadd, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3333, 0x5555, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x0008,
+};
+
+static __initconst u16 bcm43222_sprom[] = {
+ 0x2001, 0x0000, 0x04d4, 0x14e4, 0x4351, 0x8000, 0x0002, 0x0000,
+ 0x1730, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x5372, 0x2305, 0x0200, 0x0000, 0x2400, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0x0303, 0x0202,
+ 0xffff, 0x0033, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0325,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x204c, 0xfea6, 0x1717, 0xfa6d, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x204c, 0xfeb8, 0x167c, 0xfa9e, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x3333, 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333,
+ 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x0008,
+};
+
static struct ssb_sprom bcm63xx_sprom;
int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
@@ -542,6 +658,26 @@ int __init bcm63xx_register_fallback_spr
u16 size = 0;
switch (data->type) {
+ case SPROM_BCM4306:
+ memcpy(&template_sprom, &bcm4306_sprom, sizeof(bcm4306_sprom));
+ size = ARRAY_SIZE(bcm4306_sprom);
+ break;
+ case SPROM_BCM4318:
+ memcpy(&template_sprom, &bcm4318_sprom, sizeof(bcm4318_sprom));
+ size = ARRAY_SIZE(bcm4318_sprom);
+ break;
+ case SPROM_BCM4321:
+ memcpy(&template_sprom, &bcm4321_sprom, sizeof(bcm4321_sprom));
+ size = ARRAY_SIZE(bcm4321_sprom);
+ break;
+ case SPROM_BCM4322:
+ memcpy(&template_sprom, &bcm4322_sprom, sizeof(bcm4322_sprom));
+ size = ARRAY_SIZE(bcm4322_sprom);
+ break;
+ case SPROM_BCM43222:
+ memcpy(&template_sprom, &bcm43222_sprom, sizeof(bcm43222_sprom));
+ size = ARRAY_SIZE(bcm43222_sprom);
+ break;
case SPROM_DEFAULT:
memcpy(&bcm63xx_sprom, &bcm63xx_default_sprom,
sizeof(bcm63xx_sprom));
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
@@ -5,6 +5,12 @@
enum sprom_type {
SPROM_DEFAULT, /* default fallback sprom */
+ /* SSB based */
+ SPROM_BCM4306,
+ SPROM_BCM4318,
+ SPROM_BCM4321,
+ SPROM_BCM4322,
+ SPROM_BCM43222,
};
struct fallback_sprom_data {

View File

@ -0,0 +1,128 @@
From 03feb9db77fba3eef3d83e17a87a56979659b248 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 29 Jul 2014 22:48:26 +0200
Subject: [PATCH 07/10] MIPS: BCM63XX: also register a fallback sprom for bcma
Similar to SSB, register a fallback sprom handler for BCMA.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/Kconfig | 1 +
arch/mips/bcm63xx/sprom.c | 40 +++++++++++++++++++++++++++++++++++-----
2 files changed, 36 insertions(+), 5 deletions(-)
--- a/arch/mips/bcm63xx/boards/Kconfig
+++ b/arch/mips/bcm63xx/boards/Kconfig
@@ -4,6 +4,7 @@ menu "Board support"
config BOARD_BCM963XX
bool "Generic Broadcom 963xx boards"
select SSB
+ select BCMA
default y
help
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/ssb/ssb.h>
+#include <linux/bcma/bcma.h>
#include <bcm63xx_fallback_sprom.h>
#include <board_bcm963xx.h>
@@ -21,7 +22,7 @@
* Register a sane SPROMv2 to make the on-board
* bcm4318 WLAN work
*/
-#ifdef CONFIG_SSB_PCIHOST
+#if defined(CONFIG_SSB_PCIHOST) || defined(CONFIG_BCMA_HOST_PCI)
static __initconst struct ssb_sprom bcm63xx_default_sprom = {
.revision = 0x02,
.board_rev = 0x17,
@@ -43,7 +44,7 @@ static __initconst struct ssb_sprom bcm6
.boardflags_hi = 0x0000,
};
-
+#if defined (CONFIG_SSB_PCIHOST)
static __initconst u16 bcm4306_sprom[] = {
0x4001, 0x0000, 0x0453, 0x14e4, 0x4320, 0x8000, 0x0002, 0x0002,
0x1000, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -158,10 +159,12 @@ static __initconst u16 bcm43222_sprom[]
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0x0008,
};
+#endif /* CONFIG_SSB_PCIHOST */
static struct ssb_sprom bcm63xx_sprom;
-int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+#if defined(CONFIG_SSB_PCIHOST)
+int bcm63xx_get_fallback_ssb_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
{
if (bus->bustype == SSB_BUSTYPE_PCI) {
memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
@@ -171,6 +174,20 @@ int bcm63xx_get_fallback_sprom(struct ss
return -EINVAL;
}
}
+#endif
+
+#if defined(CONFIG_BCMA_HOST_PCI)
+int bcm63xx_get_fallback_bcma_sprom(struct bcma_bus *bus, struct ssb_sprom *out)
+{
+ if (bus->hosttype == BCMA_HOSTTYPE_PCI) {
+ memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
+ return 0;
+ } else {
+ printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+ return -EINVAL;
+ }
+}
+#endif
/* FIXME: use lib_sprom after submission upstream */
@@ -654,10 +671,11 @@ int __init bcm63xx_register_fallback_spr
{
int ret = 0;
-#ifdef CONFIG_SSB_PCIHOST
+#if defined(CONFIG_SSB_PCIHOST) || defined(CONFIG_BCMA_HOST_PCI)
u16 size = 0;
switch (data->type) {
+#if defined(CONFIG_SSB_PCIHOST)
case SPROM_BCM4306:
memcpy(&template_sprom, &bcm4306_sprom, sizeof(bcm4306_sprom));
size = ARRAY_SIZE(bcm4306_sprom);
@@ -678,6 +696,7 @@ int __init bcm63xx_register_fallback_spr
memcpy(&template_sprom, &bcm43222_sprom, sizeof(bcm43222_sprom));
size = ARRAY_SIZE(bcm43222_sprom);
break;
+#endif
case SPROM_DEFAULT:
memcpy(&bcm63xx_sprom, &bcm63xx_default_sprom,
sizeof(bcm63xx_sprom));
@@ -692,8 +711,19 @@ int __init bcm63xx_register_fallback_spr
memcpy(bcm63xx_sprom.il0mac, data->mac_addr, ETH_ALEN);
memcpy(bcm63xx_sprom.et0mac, data->mac_addr, ETH_ALEN);
memcpy(bcm63xx_sprom.et1mac, data->mac_addr, ETH_ALEN);
+#endif /* defined(CONFIG_SSB_PCIHOST) || defined(CONFIG_BCMA_HOST_PCI) */
+
+#if defined(CONFIG_SSB_PCIHOST)
+ ret = ssb_arch_register_fallback_sprom(&bcm63xx_get_fallback_ssb_sprom);
+ if (ret)
+ return ret;
+
+#endif
- ret = ssb_arch_register_fallback_sprom(&bcm63xx_get_fallback_sprom);
+#if defined(CONFIG_BCMA_HOST_PCI)
+ ret = bcma_arch_register_fallback_sprom(bcm63xx_get_fallback_bcma_sprom);
+ if (ret)
+ return ret;
#endif
return ret;
}

View File

@ -0,0 +1,303 @@
From 27bf70e3fe797691b17df07ecbfaf9f5a4419f49 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Wed, 30 Jul 2014 23:14:27 +0200
Subject: [PATCH 08/10] MIPS: BCM63XX: add BCMA based sprom templates
Add fallback sproms for BCM4313, BCM43131, BCM43217, BCM43225, BCM43227,
BCM43228, and BCM4331.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/sprom.c | 256 +++++++++++++++++++++
.../asm/mach-bcm63xx/bcm63xx_fallback_sprom.h | 8 +
2 files changed, 264 insertions(+)
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -161,6 +161,226 @@ static __initconst u16 bcm43222_sprom[]
};
#endif /* CONFIG_SSB_PCIHOST */
+#if defined(CONFIG_BCMA_HOST_PCI)
+static __initconst u16 bcm4313_sprom[] = {
+ 0x2801, 0x0000, 0x0510, 0x14e4, 0x0078, 0xedbe, 0x0000, 0x2bc4,
+ 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820,
+ 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100,
+ 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4727, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5372, 0x1215, 0x2a00, 0x0800, 0x0800, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0003, 0x0202,
+ 0xffff, 0x0011, 0x007a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0201,
+ 0x0000, 0x7800, 0x7c0a, 0x0398, 0x0008, 0x0000, 0x0000, 0x0000,
+ 0x0044, 0x1684, 0xfd0d, 0xff35, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0048, 0xfed2, 0x15d9, 0xfac6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0008,
+};
+
+static __initconst u16 bcm43131_sprom[] = {
+ 0x2801, 0x0000, 0x05f7, 0x14e4, 0x0070, 0xedbe, 0x1c00, 0x2bc4,
+ 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820,
+ 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100,
+ 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x43aa, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5372, 0x1280, 0x0200, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0002, 0x0202,
+ 0xffff, 0x0022, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0415,
+ 0x0000, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x204c, 0xfe96, 0x192c, 0xfa15, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x204c, 0xfe91, 0x1950, 0xfa0a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x4444, 0x4444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4444, 0x4444, 0x4444, 0x4444, 0x6666, 0x6666, 0x6666,
+ 0x6666, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x0008,
+};
+
+static __initconst u16 bcm43217_sprom[] = {
+ 0x2801, 0x0000, 0x05e9, 0x14e4, 0x0070, 0xedbe, 0x0000, 0x2bc4,
+ 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820,
+ 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100,
+ 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x43a9, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5372, 0x1252, 0x0200, 0x0000, 0x9800, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0003, 0x0202,
+ 0xffff, 0x0033, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0415,
+ 0x0000, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x204c, 0xfe96, 0x192c, 0xfa15, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x204c, 0xfe91, 0x1950, 0xfa0a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x4444, 0x4444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4444, 0x4444, 0x4444, 0x4444, 0x6666, 0x6666, 0x6666,
+ 0x6666, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x7a08,
+};
+
+static __initconst u16 bcm43225_sprom[] = {
+ 0x2801, 0x0000, 0x04da, 0x14e4, 0x0078, 0xedbe, 0x0000, 0x2bc4,
+ 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820,
+ 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100,
+ 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x1008, 0x0005, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x4357, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x5372, 0x1200, 0x0200, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x88ff, 0xffff, 0xffff, 0x0303, 0x0202,
+ 0xffff, 0x0033, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0325,
+ 0xffff, 0x7800, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x204e, 0xfead, 0x1611, 0xfa9a, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x204e, 0xfec1, 0x1674, 0xfab2, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x5555, 0x5555, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5555, 0x7555, 0x5555, 0x7555, 0x5555, 0x7555, 0x5555,
+ 0x7555, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x0008,
+};
+
+static __initconst u16 bcm43227_sprom[] = {
+ 0x2801, 0x0000, 0x0543, 0x14e4, 0x0070, 0xedbe, 0x0000, 0x2bc4,
+ 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820,
+ 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100,
+ 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4358, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5372, 0x1402, 0x0200, 0x0000, 0x0800, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0003, 0x0202,
+ 0xffff, 0x0033, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0415,
+ 0x0000, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x204c, 0xff36, 0x16d2, 0xfaae, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x204c, 0xfeca, 0x159b, 0xfa80, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x4444, 0x4444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4444, 0x4444, 0x4444, 0x4444, 0x6666, 0x6666, 0x6666,
+ 0x6666, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x0008,
+};
+
+static __initconst u16 bcm43228_sprom[] = {
+ 0x2801, 0x0000, 0x0011, 0x1028, 0x0070, 0xedbe, 0x0000, 0x2bc4,
+ 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820,
+ 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100,
+ 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4359, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5372, 0x1203, 0x0200, 0x0000, 0x0800, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0303, 0x0202,
+ 0xffff, 0x0033, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0215,
+ 0x0215, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x204c, 0xff73, 0x1762, 0xfaa4, 0x3e34, 0x3434, 0xfea1, 0x154c,
+ 0xfad0, 0xfea1, 0x144c, 0xfafb, 0xfe7b, 0x13fe, 0xfafc, 0x0000,
+ 0x204c, 0xff41, 0x16a3, 0xfa8f, 0x3e34, 0x3434, 0xfe97, 0x1446,
+ 0xfb05, 0xfe97, 0x1346, 0xfb32, 0xfeb9, 0x1516, 0xfaee, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x4444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4444, 0x4444, 0x4444, 0x4444, 0x8888, 0x8888, 0x8888,
+ 0x8888, 0x0000, 0x0000, 0x0000, 0x0000, 0x3333, 0x3333, 0x3333,
+ 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x3333, 0x3333, 0x3333,
+ 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x3333, 0x3333, 0x3333,
+ 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xf008,
+};
+
+static __initconst u16 bcm4331_sprom[] = {
+ 0x2801, 0x0000, 0x0525, 0x14e4, 0x0078, 0xedbe, 0x0000, 0x2bc4,
+ 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820,
+ 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100,
+ 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x1010, 0x0005, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x4331, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x5372, 0x1104, 0x0200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xffff, 0x88ff, 0xffff, 0x0707, 0x0202,
+ 0xff02, 0x0077, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0325,
+ 0x0325, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x2048, 0xfe56, 0x16f2, 0xfa44, 0x3e3c, 0x3c3c, 0xfe77, 0x1657,
+ 0xfa75, 0xffff, 0xffff, 0xffff, 0xfe76, 0x15da, 0xfa85, 0x0000,
+ 0x2048, 0xfe5c, 0x16b5, 0xfa56, 0x3e3c, 0x3c3c, 0xfe7c, 0x169d,
+ 0xfa6b, 0xffff, 0xffff, 0xffff, 0xfe7a, 0x1597, 0xfa97, 0x0000,
+ 0x2048, 0xfe68, 0x1734, 0xfa46, 0x3e3c, 0x3c3c, 0xfe7f, 0x15e4,
+ 0xfa94, 0xffff, 0xffff, 0xffff, 0xfe7d, 0x1582, 0xfa9f, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x0009,
+};
+
+#endif /* CONFIG_BCMA_HOST_PCI */
+
static struct ssb_sprom bcm63xx_sprom;
#if defined(CONFIG_SSB_PCIHOST)
@@ -697,6 +917,42 @@ int __init bcm63xx_register_fallback_spr
size = ARRAY_SIZE(bcm43222_sprom);
break;
#endif
+#if defined(CONFIG_BCMA_HOST_PCI)
+ case SPROM_BCM4313:
+ memcpy(&template_sprom, &bcm4313_sprom,
+ sizeof(bcm4313_sprom));
+ size = ARRAY_SIZE(bcm4313_sprom);
+ break;
+ case SPROM_BCM43131:
+ memcpy(&template_sprom, &bcm43131_sprom,
+ sizeof(bcm43131_sprom));
+ size = ARRAY_SIZE(bcm43131_sprom);
+ break;
+ case SPROM_BCM43217:
+ memcpy(&template_sprom, &bcm43217_sprom,
+ sizeof(bcm43217_sprom));
+ size = ARRAY_SIZE(bcm43217_sprom);
+ break;
+ case SPROM_BCM43225:
+ memcpy(&template_sprom, &bcm43225_sprom,
+ sizeof(bcm43225_sprom));
+ size = ARRAY_SIZE(bcm43225_sprom);
+ break;
+ case SPROM_BCM43227:
+ memcpy(&template_sprom, &bcm43227_sprom,
+ sizeof(bcm43227_sprom));
+ size = ARRAY_SIZE(bcm43227_sprom);
+ break;
+ case SPROM_BCM43228:
+ memcpy(&template_sprom, &bcm43228_sprom,
+ sizeof(bcm43228_sprom));
+ size = ARRAY_SIZE(bcm43228_sprom);
+ break;
+ case SPROM_BCM4331:
+ memcpy(&template_sprom, &bcm4331_sprom, sizeof(&bcm4331_sprom));
+ size = ARRAY_SIZE(bcm4331_sprom);
+ break;
+#endif
case SPROM_DEFAULT:
memcpy(&bcm63xx_sprom, &bcm63xx_default_sprom,
sizeof(bcm63xx_sprom));
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
@@ -11,6 +11,14 @@ enum sprom_type {
SPROM_BCM4321,
SPROM_BCM4322,
SPROM_BCM43222,
+ /* BCMA based */
+ SPROM_BCM4313,
+ SPROM_BCM43131,
+ SPROM_BCM43217,
+ SPROM_BCM43225,
+ SPROM_BCM43227,
+ SPROM_BCM43228,
+ SPROM_BCM4331,
};
struct fallback_sprom_data {

View File

@ -0,0 +1,67 @@
From 8575548b08e33c9ff4fd540abec09dd177e33682 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 31 Jul 2014 19:12:33 +0200
Subject: [PATCH 09/10] MIPS: BCM63XX: allow board files to provide sprom
fixups
Allow board_info files to supply fixups for the base sproms to adapt
them to the actual used sprom contents in case they do not use the
default ones.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/sprom.c | 14 +++++++++++++-
.../mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h | 8 ++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -883,6 +883,14 @@ static int sprom_extract(struct ssb_spro
return 0;
}
+void sprom_apply_fixups(u16 *sprom, struct sprom_fixup *fixups, int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ sprom[fixups[i].offset] = fixups[i].value;
+}
+
static __initdata u16 template_sprom[220];
#endif
@@ -961,8 +969,12 @@ int __init bcm63xx_register_fallback_spr
return -EINVAL;
}
- if (size > 0)
+ if (size > 0) {
+ sprom_apply_fixups(template_sprom, data->board_fixups,
+ data->num_board_fixups);
+
sprom_extract(&bcm63xx_sprom, template_sprom, size);
+ }
memcpy(bcm63xx_sprom.il0mac, data->mac_addr, ETH_ALEN);
memcpy(bcm63xx_sprom.et0mac, data->mac_addr, ETH_ALEN);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
@@ -21,9 +21,17 @@ enum sprom_type {
SPROM_BCM4331,
};
+struct sprom_fixup {
+ u16 offset;
+ u16 value;
+};
+
struct fallback_sprom_data {
u8 mac_addr[ETH_ALEN];
enum sprom_type type;
+
+ struct sprom_fixup *board_fixups;
+ unsigned int num_board_fixups;
};
int bcm63xx_register_fallback_sprom(struct fallback_sprom_data *data);

View File

@ -0,0 +1,102 @@
From f393eaacf178e7e8a61eb11a96edd7dfb35cb49d Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 31 Jul 2014 20:39:44 +0200
Subject: [PATCH 10/10] MIPS: BCM63XX: allow setting a pci bus/device for
fallback sprom
Warn if the set pci bus/slot does not match the actual request.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/sprom.c | 31 ++++++++++++++++++----
.../asm/mach-bcm63xx/bcm63xx_fallback_sprom.h | 3 +++
2 files changed, 29 insertions(+), 5 deletions(-)
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -381,13 +381,25 @@ static __initconst u16 bcm4331_sprom[] =
#endif /* CONFIG_BCMA_HOST_PCI */
-static struct ssb_sprom bcm63xx_sprom;
+struct fallback_sprom_match {
+ u8 pci_bus;
+ u8 pci_dev;
+ struct ssb_sprom sprom;
+};
+
+static struct fallback_sprom_match fallback_sprom;
#if defined(CONFIG_SSB_PCIHOST)
int bcm63xx_get_fallback_ssb_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
{
if (bus->bustype == SSB_BUSTYPE_PCI) {
- memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
+ if (bus->host_pci->bus->number != fallback_sprom.pci_bus ||
+ PCI_SLOT(bus->host_pci->devfn) != fallback_sprom.pci_dev)
+ pr_warn("ssb_fallback_sprom: pci bus/device num mismatch: expected %i/%i, but got %i/%i\n",
+ fallback_sprom.pci_bus, fallback_sprom.pci_dev,
+ bus->host_pci->bus->number,
+ PCI_SLOT(bus->host_pci->devfn));
+ memcpy(out, &fallback_sprom.sprom, sizeof(struct ssb_sprom));
return 0;
} else {
printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
@@ -400,7 +412,13 @@ int bcm63xx_get_fallback_ssb_sprom(struc
int bcm63xx_get_fallback_bcma_sprom(struct bcma_bus *bus, struct ssb_sprom *out)
{
if (bus->hosttype == BCMA_HOSTTYPE_PCI) {
- memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
+ if (bus->host_pci->bus->number != fallback_sprom.pci_bus ||
+ PCI_SLOT(bus->host_pci->devfn) != fallback_sprom.pci_dev)
+ pr_warn("bcma_fallback_sprom: pci bus/device num mismatch: expected %i/%i, but got %i/%i\n",
+ fallback_sprom.pci_bus, fallback_sprom.pci_dev,
+ bus->host_pci->bus->number,
+ PCI_SLOT(bus->host_pci->devfn));
+ memcpy(out, &fallback_sprom.sprom, sizeof(struct ssb_sprom));
return 0;
} else {
printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
@@ -962,8 +980,8 @@ int __init bcm63xx_register_fallback_spr
break;
#endif
case SPROM_DEFAULT:
- memcpy(&bcm63xx_sprom, &bcm63xx_default_sprom,
- sizeof(bcm63xx_sprom));
+ memcpy(&fallback_sprom.sprom, &bcm63xx_default_sprom,
+ sizeof(bcm63xx_default_sprom));
break;
default:
return -EINVAL;
@@ -973,12 +991,15 @@ int __init bcm63xx_register_fallback_spr
sprom_apply_fixups(template_sprom, data->board_fixups,
data->num_board_fixups);
- sprom_extract(&bcm63xx_sprom, template_sprom, size);
+ sprom_extract(&fallback_sprom.sprom, template_sprom, size);
}
- memcpy(bcm63xx_sprom.il0mac, data->mac_addr, ETH_ALEN);
- memcpy(bcm63xx_sprom.et0mac, data->mac_addr, ETH_ALEN);
- memcpy(bcm63xx_sprom.et1mac, data->mac_addr, ETH_ALEN);
+ memcpy(fallback_sprom.sprom.il0mac, data->mac_addr, ETH_ALEN);
+ memcpy(fallback_sprom.sprom.et0mac, data->mac_addr, ETH_ALEN);
+ memcpy(fallback_sprom.sprom.et1mac, data->mac_addr, ETH_ALEN);
+
+ fallback_sprom.pci_bus = data->pci_bus;
+ fallback_sprom.pci_dev = data->pci_dev;
#endif /* defined(CONFIG_SSB_PCIHOST) || defined(CONFIG_BCMA_HOST_PCI) */
#if defined(CONFIG_SSB_PCIHOST)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_fallback_sprom.h
@@ -30,6 +30,9 @@ struct fallback_sprom_data {
u8 mac_addr[ETH_ALEN];
enum sprom_type type;
+ u8 pci_bus;
+ u8 pci_dev;
+
struct sprom_fixup *board_fixups;
unsigned int num_board_fixups;
};

View File

@ -0,0 +1,124 @@
From 318c1fce4aeef298cbb6153416c499c94ad7cda0 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 24 Jun 2014 10:53:15 +0200
Subject: [PATCH RFC v3] MIPS: add support for vmlinux.bin appended DTB
Add support for populating initial_boot_params through a dtb
blob appended to raw vmlinux.bin.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
Changes RFC v2 -> v3
* fixed !smp kernels (TODO: move it to its own patch
Changes RFC v1 -> v2
* changed all occurences of vmlinux to vmlinux.bin
* clarified this applies to the raw vmlinux.bin without decompressor
* s/initial_device_params/initial_boot_params/
Initial comments by me still valid:
Mostly adapted from how ARM is doing it.
Sent as an RFC PATCH because I am not sure if this is the right way to
it, and whether storing the pointer in initial_boot_params is a good
idea, or a new variable should be introduced.
The reasoning for initial_boot_params is that there is no common
MIPS interface yet, so the next best thing was using that. This also
has the advantage of keeping the original fw_args intact.
This patch works for me on bcm63xx, where the bootloader expects
an lzma compressed kernel, so I didn't want to double compress using
the in-kernel compressed kernel support.
Completely untested on anything except MIPS32 / big endian.
arch/mips/Kconfig | 18 ++++++++++++++++++
arch/mips/kernel/head.S | 19 +++++++++++++++++++
arch/mips/kernel/vmlinux.lds.S | 7 +++++++
3 files changed, 43 insertions(+)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2831,6 +2831,24 @@ config RAPIDIO
source "drivers/rapidio/Kconfig"
+config MIPS_APPENDED_DTB
+ bool "Use appended device tree blob to vmlinux.bin (EXPERIMENTAL)"
+ depends on OF
+ help
+ With this option, the boot code will look for a device tree binary
+ DTB) appended to raw vmlinux.bin (without decompressor).
+ (e.g. cat vmlinux.bin <filename>.dtb > vmlinux_w_dtb).
+
+ This is meant as a backward compatibility convenience for those
+ systems with a bootloader that can't be upgraded to accommodate
+ the documented boot protocol using a device tree.
+
+ Beware that there is very little in terms of protection against
+ this option being confused by leftover garbage in memory that might
+ look like a DTB header after a reboot if no actual DTB is appended
+ to vmlinux.bin. Do not leave this option active in a production kernel
+ if you don't intend to always append a DTB.
+
endmenu
menu "Executable file formats"
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -100,6 +100,22 @@ NESTED(kernel_entry, 16, sp) # kernel
jr t0
0:
+#ifdef CONFIG_MIPS_APPENDED_DTB
+ PTR_LA t0, __appended_dtb
+ PTR_LI t3, 0
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ PTR_LI t1, 0xd00dfeed
+#else
+ PTR_LI t1, 0xedfe0dd0
+#endif
+ LONG_L t2, (t0)
+ bne t1, t2, not_found
+
+ PTR_LA t3, __appended_dtb
+
+not_found:
+#endif
PTR_LA t0, __bss_start # clear .bss
LONG_S zero, (t0)
PTR_LA t1, __bss_stop - LONGSIZE
@@ -113,6 +129,10 @@ NESTED(kernel_entry, 16, sp) # kernel
LONG_S a2, fw_arg2
LONG_S a3, fw_arg3
+#ifdef CONFIG_MIPS_APPENDED_DTB
+ LONG_S t3, initial_boot_params
+#endif
+
MTC0 zero, CP0_CONTEXT # clear context register
PTR_LA $28, init_thread_union
/* Set the SP after an empty pt_regs. */
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -125,8 +125,14 @@ SECTIONS
.exit.data : {
EXIT_DATA
}
-
+#ifdef CONFIG_SMP
PERCPU_SECTION(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
+#endif
+#ifdef CONFIG_MIPS_APPENDED_DTB
+ __appended_dtb = .;
+ /* leave space for appended DTB */
+ . = . + 0x100000;
+#endif
/*
* Align to 64K in attempt to eliminate holes before the
* .bss..swapper_pg_dir section at the start of .bss. This

View File

@ -0,0 +1,96 @@
From db896341299cbcb703821228574ba9b79b6a3565 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 24 Jun 2014 10:57:51 +0200
Subject: [PATCH 45/48] MIPS: BCM63XX: add support for loading DTB
---
arch/mips/bcm63xx/boards/Kconfig | 4 ++++
arch/mips/bcm63xx/boards/board_common.c | 34 +++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
--- a/arch/mips/bcm63xx/boards/Kconfig
+++ b/arch/mips/bcm63xx/boards/Kconfig
@@ -1,6 +1,10 @@
menu "Board support"
depends on BCM63XX
+config BOARD_BCM63XX_DT
+ bool "Device Tree boards (experimential)"
+ select USE_OF
+
config BOARD_BCM963XX
bool "Generic Broadcom 963xx boards"
select SSB
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -10,6 +10,8 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/ssb/ssb.h>
#include <linux/gpio_keys.h>
@@ -17,6 +19,7 @@
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/fw/cfe/cfe_api.h>
+#include <asm/prom.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_uart.h>
@@ -129,8 +132,23 @@ void __init board_setup(void)
/* make sure we're running on expected cpu */
if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
panic("unexpected CPU for bcm963xx board");
+
+#if CONFIG_OF
+ if (initial_boot_params)
+ __dt_setup_arch(initial_boot_params);
+#endif
}
+#if CONFIG_OF
+void __init device_tree_init(void)
+{
+ if (!initial_boot_params)
+ return;
+
+ unflatten_and_copy_device_tree();
+}
+#endif
+
static struct gpio_led_platform_data bcm63xx_led_data;
static struct platform_device bcm63xx_gpio_leds = {
@@ -149,6 +167,13 @@ static struct platform_device bcm63xx_gp
.dev.platform_data = &bcm63xx_gpio_keys_data,
};
+#if CONFIG_OF
+static struct of_device_id of_ids[] = {
+ { /* filled at runtime */ },
+ { .compatible = "simple-bus" },
+ { },
+};
+#endif
/*
* third stage init callback, register all board devices.
*/
@@ -158,6 +183,15 @@ int __init board_register_devices(void)
int led_count = 0;
int usbh_ports = 0;
+#if CONFIG_OF
+ if (of_have_populated_dt()) {
+ snprintf(of_ids[0].compatible, sizeof(of_ids[0].compatible),
+ "brcm,bcm%x", bcm63xx_get_cpu_id());
+
+ of_platform_populate(NULL, of_ids, NULL, NULL);
+ }
+#endif
+
if (board.has_uart0)
bcm63xx_uart_register(0);

View File

@ -0,0 +1,95 @@
From 25bf2b5836c892f091651d8a3384c9c57ce1b400 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Thu, 26 Jun 2014 12:51:00 +0200
Subject: [PATCH 46/48] MIPS: BCM63XX: add support for matching the board_info
by dtb
Allow using the passed dtb's compatible property to match board_info
structs instead of nvram's boardname field, which is not unique anyway.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 15 +++++++++++++++
arch/mips/bcm63xx/boards/board_common.c | 18 ++++++++++++++++++
arch/mips/bcm63xx/boards/board_common.h | 3 +++
3 files changed, 36 insertions(+)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -715,6 +715,10 @@ static const struct board_info __initcon
#endif
};
+static struct of_device_id const bcm963xx_boards_dt[] = {
+ { },
+};
+
/*
* early init callback, read nvram data from flash and checksum it
*/
@@ -726,6 +730,7 @@ void __init board_bcm963xx_init(void)
char *board_name = NULL;
u32 val;
struct bcm_hcs *hcs;
+ const struct of_device_id *board_match;
/* read base address of boot chip select (0)
* 6328/6362 do not have MPI but boot from a fixed address
@@ -765,6 +770,16 @@ void __init board_bcm963xx_init(void)
} else {
board_name = bcm63xx_nvram_get_name();
}
+
+ /* find board by compat */
+ board_match = bcm63xx_match_board(bcm963xx_boards_dt);
+ if (board_match) {
+ board_early_setup(board_match->data,
+ bcm63xx_nvram_get_mac_address);
+
+ return;
+ }
+
/* find board by name */
for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -281,3 +281,21 @@ int __init board_register_devices(void)
return 0;
}
+
+const struct of_device_id * __init bcm63xx_match_board(const struct of_device_id *m)
+{
+ const struct of_device_id *match;
+ unsigned long dt_root;
+
+ if (!IS_ENABLED(CONFIG_OF) || !initial_boot_params)
+ return NULL;
+
+ dt_root = of_get_flat_dt_root();
+
+ for (match = m; match->compatible[0]; match++) {
+ if (of_flat_dt_is_compatible(dt_root, match->compatible))
+ return match;
+ }
+
+ return NULL;
+}
--- a/arch/mips/bcm63xx/boards/board_common.h
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -1,11 +1,14 @@
#ifndef __BOARD_COMMON_H
#define __BOARD_COMMON_H
+#include <linux/of.h>
#include <board_bcm963xx.h>
void board_early_setup(const struct board_info *board,
int (*get_mac_address)(u8 mac[ETH_ALEN]));
+const struct of_device_id *bcm63xx_match_board(const struct of_device_id *);
+
#if defined(CONFIG_BOARD_BCM963XX)
void board_bcm963xx_init(void);
#else

View File

@ -0,0 +1,65 @@
From e71eea9953c774dfadb754258824fb1888c279f4 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 21 Nov 2014 16:54:06 +0100
Subject: [PATCH 47/48] MIPS: BCM63XX: populate the compatible to board_info
list
Populate the compatible to board_info list to allow dtbs to be used
for known boards.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 34 +++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -716,6 +716,48 @@ static const struct board_info __initcon
};
static struct of_device_id const bcm963xx_boards_dt[] = {
+#ifdef CONFIG_OF
+#ifdef CONFIG_BCM63XX_CPU_3368
+ { .compatible = "netgear,cvg834g", .data = &board_cvg834g, },
+#endif
+#ifdef CONFIG_BCM63XX_CPU_6328
+ { .compatible = "brcm,bcm96328avng", .data = &board_96328avng, },
+#endif
+#ifdef CONFIG_BCM63XX_CPU_6338
+ { .compatible = "brcm,bcm96338gw", .data = &board_96338gw, },
+ { .compatible = "brcm,bcm96338w", .data = &board_96338w, },
+#endif
+#ifdef CONFIG_BCM63XX_CPU_6345
+ { .compatible = "brcm,bcm96345gw2", .data = &board_96345gw2, },
+#endif
+#ifdef CONFIG_BCM63XX_CPU_6348
+ { .compatible = "belkin,f5d7633", .data = &board_96348gw_10, },
+ { .compatible = "brcm,bcm96348r", .data = &board_96348r, },
+ { .compatible = "brcm,bcm96348gw-10", .data = &board_96348gw_10, },
+ { .compatible = "brcm,bcm96348gw-11", .data = &board_96348gw_11, },
+ { .compatible = "brcm,bcm96348gw-a", .data = &board_96348gw_a, },
+ { .compatible = "davolink,dv-201amr", .data = &board_DV201AMR, },
+ { .compatible = "dynalink,rta1025w", .data = &board_rta1025w_16, },
+ { .compatible = "netgear,dg834gtpn", .data = &board_96348gw_10, },
+ { .compatible = "sagem,f@st2404", .data = &board_FAST2404, },
+ { .compatible = "tp-link,td-w8900gb", .data = &board_96348gw_11, },
+ { .compatible = "usr,9108", .data = &board_96348gw_a, },
+#endif
+#ifdef CONFIG_BCM63XX_CPU_6358
+ { .compatible = "alcatel,rg100a", .data = &board_96358vw2, },
+ { .compatible = "brcm,bcm96358vw", .data = &board_96358vw, },
+ { .compatible = "brcm,bcm96358vw2", .data = &board_96358vw2, },
+ { .compatible = "d-link,dsl-2650u", .data = &board_96358vw2, },
+ { .compatible = "pirelli,a226g", .data = &board_DWVS0, },
+ { .compatible = "pirelli,a226m", .data = &board_DWVS0, },
+ { .compatible = "pirelli,a226m-fwb", .data = &board_DWVS0, },
+ { .compatible = "pirelli,agpf-s0", .data = &board_AGPFS0, },
+#endif
+#ifdef CONFIG_BCM63XX_CPU_6368
+#endif
+#ifdef CONFIG_BCM63XX_CPU_63268
+#endif
+#endif /* CONFIG_OF */
{ },
};

View File

@ -0,0 +1,37 @@
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -147,6 +147,18 @@ void __init device_tree_init(void)
unflatten_and_copy_device_tree();
}
+
+int board_of_device_present(const char *alias)
+{
+ bool present;
+ struct device_node *np;
+
+ np = of_find_node_by_path(alias);
+ present = of_device_is_available(np);
+ of_node_put(np);
+
+ return present;
+}
#endif
static struct gpio_led_platform_data bcm63xx_led_data;
--- a/arch/mips/bcm63xx/boards/board_common.h
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -15,4 +15,13 @@ void board_bcm963xx_init(void);
static inline void board_bcm963xx_init(void) { }
#endif
+#if defined(CONFIG_OF)
+int board_of_device_present(const char *alias);
+#else
+static inline void board_of_device_present(const char *alias)
+{
+ return 0;
+}
+#endif
+
#endif /* __BOARD_COMMON_H */

View File

@ -0,0 +1,21 @@
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -22,6 +22,8 @@
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
+#include "boards/board_common.h"
+
static int flash_type;
static struct mtd_partition mtd_partitions[] = {
@@ -164,6 +166,9 @@ int __init bcm63xx_flash_register(void)
switch (flash_type) {
case BCM63XX_FLASH_TYPE_PARALLEL:
+ /* don't register when already registered through from dtb */
+ if (board_of_device_present("pflash"))
+ return 0;
if (!mtd_resources[0].start) {
/* read base address of boot chip select (0) */

View File

@ -0,0 +1,45 @@
From 8a0803979163c647736cb234ee1620c049c4915c Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Mon, 1 Dec 2014 00:20:07 +0100
Subject: [PATCH 5/5] MIPS: BCM63XX: register interrupt controllers through DT
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -15,6 +15,8 @@
#include <linux/irqchip.h>
#include <linux/irqchip/irq-bcm6345-ext.h>
#include <linux/irqchip/irq-bcm6345-periph.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <bcm63xx_cpu.h>
@@ -22,6 +24,9 @@
#include <bcm63xx_io.h>
#include <bcm63xx_irq.h>
+OF_DECLARE_2(irqchip, mips_cpu_intc, "mti,cpu-interrupt-controller",
+ mips_cpu_irq_of_init);
+
void __init arch_init_irq(void)
{
void __iomem *periph_bases[2];
@@ -30,6 +35,13 @@ void __init arch_init_irq(void)
int periph_irqs[2] = { 2, 3 };
int ext_irqs[6];
+#ifdef CONFIG_OF
+ if (initial_boot_params) {
+ irqchip_init();
+ return;
+ }
+#endif
+
periph_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
periph_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
ext_intc_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);

View File

@ -0,0 +1,165 @@
From dbe94a8daaa63ef81b7414f2a17bca8e36dd6daa Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 20 Feb 2015 19:55:32 +0100
Subject: [PATCH 1/6] gpio: add a simple GPIO driver for bcm63xx
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
drivers/gpio/Kconfig | 8 +++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-bcm63xx.c | 122 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 131 insertions(+)
create mode 100644 drivers/gpio/gpio-bcm63xx.c
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -126,6 +126,13 @@ config GPIO_BCM_KONA
help
Turn on GPIO support for Broadcom "Kona" chips.
+config GPIO_BCM63XX
+ bool "Broadcom BCM63XX GPIO"
+ depends on MIPS || COMPILE_TEST
+ select GPIO_GENERIC
+ help
+ Turn on GPIO support for Broadcom BCM63XX xDSL chips.
+
config GPIO_CLPS711X
tristate "CLPS711X GPIO support"
depends on ARCH_CLPS711X || COMPILE_TEST
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_GPIO_ALTERA) += gpio-alte
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
+obj-$(CONFIG_GPIO_BCM63XX) += gpio-bcm63xx.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
--- /dev/null
+++ b/drivers/gpio/gpio-bcm63xx.c
@@ -0,0 +1,122 @@
+/*
+ * Driver for BCM63XX memory-mapped GPIO controllers, based on
+ * Generic driver for memory-mapped GPIO controllers.
+ *
+ * Copyright 2008 MontaVista Software, Inc.
+ * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
+ * Copyright 2015 Jonas Gorski <jogo@openwrt.org>
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/log2.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
+static int bcm63xx_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *dat_r, *dirout_r;
+ void __iomem *dat;
+ void __iomem *dirout;
+ unsigned long sz;
+ int err;
+ struct bgpio_chip *bgc;
+ struct bgpio_pdata *pdata = dev_get_platdata(dev);
+
+ dirout_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dat_r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!dat_r || !dirout_r)
+ return -EINVAL;
+
+ if (resource_size(dat_r) != resource_size(dirout_r))
+ return -EINVAL;
+
+ sz = resource_size(dat_r);
+
+ dat = devm_ioremap_resource(dev, dat_r);
+ if (IS_ERR(dat))
+ return PTR_ERR(dat);
+
+ dirout = devm_ioremap_resource(dev, dirout_r);
+ if (IS_ERR(dirout))
+ return PTR_ERR(dirout);
+
+ bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
+ if (!bgc)
+ return -ENOMEM;
+
+ err = bgpio_init(bgc, dev, sz, dat, NULL, NULL, dirout, NULL,
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+ if (err)
+ return err;
+
+ platform_set_drvdata(pdev, bgc);
+
+ if (dev->of_node) {
+ int id = of_alias_get_id(dev->of_node, "gpio");
+ u32 ngpios;
+
+ if (id >= 0)
+ bgc->gc.label = devm_kasprintf(dev, GFP_KERNEL,
+ "bcm63xx-gpio.%d", id);
+
+ if (!of_property_read_u32(dev->of_node, "ngpios", &ngpios))
+ bgc->gc.ngpio = ngpios;
+
+ } else if (pdata) {
+ bgc->gc.base = pdata->base;
+ if (pdata->ngpio > 0)
+ bgc->gc.ngpio = pdata->ngpio;
+ }
+
+ return gpiochip_add(&bgc->gc);
+}
+
+static int bcm63xx_gpio_remove(struct platform_device *pdev)
+{
+ struct bgpio_chip *bgc = platform_get_drvdata(pdev);
+
+ return bgpio_remove(bgc);
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id bcm63xx_gpio_of_match[] = {
+ { .compatible = "brcm,bcm6345-gpio" },
+ { },
+};
+#endif
+
+static struct platform_driver bcm63xx_gpio_driver = {
+ .probe = bcm63xx_gpio_probe,
+ .remove = bcm63xx_gpio_remove,
+ .driver = {
+ .name = "bcm63xx-gpio",
+ .of_match_table = of_match_ptr(bcm63xx_gpio_of_match),
+ },
+};
+
+module_platform_driver(bcm63xx_gpio_driver);
+
+MODULE_DESCRIPTION("Driver for BCM63XX memory-mapped GPIO controllers");
+MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,216 @@
From cc99dca188bb63ba390008e2f7fa62d0300233e0 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 20 Feb 2015 23:58:54 +0100
Subject: [PATCH 2/6] MIPS: BCM63XX: switch to new gpio driver
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_common.c | 2 +
arch/mips/bcm63xx/gpio.c | 147 +++++++------------------------
arch/mips/bcm63xx/setup.c | 3 -
3 files changed, 33 insertions(+), 119 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -204,6 +204,8 @@ int __init board_register_devices(void)
}
#endif
+ bcm63xx_gpio_init();
+
if (board.has_uart0)
bcm63xx_uart_register(0);
--- a/arch/mips/bcm63xx/gpio.c
+++ b/arch/mips/bcm63xx/gpio.c
@@ -5,147 +5,62 @@
*
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
* Copyright (C) 2008-2011 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) Jonas Gorski <jogo@openwrt.org>
*/
#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
#include <linux/platform_device.h>
+#include <linux/basic_mmio_gpio.h>
#include <linux/gpio.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_gpio.h>
-#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
-static u32 gpio_out_low_reg;
-
-static void bcm63xx_gpio_out_low_reg_init(void)
+static void __init bcm63xx_gpio_init_one(int id, int dir, int data, int ngpio)
{
- switch (bcm63xx_get_cpu_id()) {
- case BCM6345_CPU_ID:
- gpio_out_low_reg = GPIO_DATA_LO_REG_6345;
- break;
- default:
- gpio_out_low_reg = GPIO_DATA_LO_REG;
- break;
- }
-}
-
-static DEFINE_SPINLOCK(bcm63xx_gpio_lock);
-static u32 gpio_out_low, gpio_out_high;
+ struct resource res[2];
+ struct bgpio_pdata pdata;
-static void bcm63xx_gpio_set(struct gpio_chip *chip,
- unsigned gpio, int val)
-{
- u32 reg;
- u32 mask;
- u32 *v;
- unsigned long flags;
-
- if (gpio >= chip->ngpio)
- BUG();
-
- if (gpio < 32) {
- reg = gpio_out_low_reg;
- mask = 1 << gpio;
- v = &gpio_out_low;
- } else {
- reg = GPIO_DATA_HI_REG;
- mask = 1 << (gpio - 32);
- v = &gpio_out_high;
- }
-
- spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
- if (val)
- *v |= mask;
- else
- *v &= ~mask;
- bcm_gpio_writel(*v, reg);
- spin_unlock_irqrestore(&bcm63xx_gpio_lock, flags);
-}
+ memset(res, 0, sizeof(res));
+ memset(&pdata, 0, sizeof(pdata));
-static int bcm63xx_gpio_get(struct gpio_chip *chip, unsigned gpio)
-{
- u32 reg;
- u32 mask;
+ res[0].flags = IORESOURCE_MEM;
+ res[0].start = bcm63xx_regset_address(RSET_GPIO);
+ res[0].start += dir;
- if (gpio >= chip->ngpio)
- BUG();
+ res[0].end = res[0].start + 3;
- if (gpio < 32) {
- reg = gpio_out_low_reg;
- mask = 1 << gpio;
- } else {
- reg = GPIO_DATA_HI_REG;
- mask = 1 << (gpio - 32);
- }
+ res[1].flags = IORESOURCE_MEM;
+ res[1].start = bcm63xx_regset_address(RSET_GPIO);
+ res[1].start += data;
- return !!(bcm_gpio_readl(reg) & mask);
-}
+ res[1].end = res[1].start + 3;
-static int bcm63xx_gpio_set_direction(struct gpio_chip *chip,
- unsigned gpio, int dir)
-{
- u32 reg;
- u32 mask;
- u32 tmp;
- unsigned long flags;
-
- if (gpio >= chip->ngpio)
- BUG();
-
- if (gpio < 32) {
- reg = GPIO_CTL_LO_REG;
- mask = 1 << gpio;
- } else {
- reg = GPIO_CTL_HI_REG;
- mask = 1 << (gpio - 32);
- }
-
- spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
- tmp = bcm_gpio_readl(reg);
- if (dir == BCM63XX_GPIO_DIR_IN)
- tmp &= ~mask;
- else
- tmp |= mask;
- bcm_gpio_writel(tmp, reg);
- spin_unlock_irqrestore(&bcm63xx_gpio_lock, flags);
+ pdata.base = id * 32;
+ pdata.ngpio = ngpio;
- return 0;
+ platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
+ &pdata, sizeof(pdata));
}
-static int bcm63xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+int __init bcm63xx_gpio_init(void)
{
- return bcm63xx_gpio_set_direction(chip, gpio, BCM63XX_GPIO_DIR_IN);
-}
+ int ngpio = bcm63xx_gpio_count();
+ int data_low_reg;
-static int bcm63xx_gpio_direction_output(struct gpio_chip *chip,
- unsigned gpio, int value)
-{
- bcm63xx_gpio_set(chip, gpio, value);
- return bcm63xx_gpio_set_direction(chip, gpio, BCM63XX_GPIO_DIR_OUT);
-}
+ if (BCMCPU_IS_6345())
+ data_low_reg = GPIO_DATA_LO_REG_6345;
+ else
+ data_low_reg = GPIO_DATA_LO_REG;
+ bcm63xx_gpio_init_one(0, GPIO_CTL_LO_REG, data_low_reg, min(ngpio, 32));
-static struct gpio_chip bcm63xx_gpio_chip = {
- .label = "bcm63xx-gpio",
- .direction_input = bcm63xx_gpio_direction_input,
- .direction_output = bcm63xx_gpio_direction_output,
- .get = bcm63xx_gpio_get,
- .set = bcm63xx_gpio_set,
- .base = 0,
-};
+ if (ngpio <= 32)
+ return 0;
-int __init bcm63xx_gpio_init(void)
-{
- bcm63xx_gpio_out_low_reg_init();
+ bcm63xx_gpio_init_one(1, GPIO_CTL_HI_REG, GPIO_DATA_HI_REG, ngpio - 32);
- gpio_out_low = bcm_gpio_readl(gpio_out_low_reg);
- if (!BCMCPU_IS_6345())
- gpio_out_high = bcm_gpio_readl(GPIO_DATA_HI_REG);
- bcm63xx_gpio_chip.ngpio = bcm63xx_gpio_count();
- pr_info("registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio);
+ return 0;
- return gpiochip_add(&bcm63xx_gpio_chip);
}
--- a/arch/mips/bcm63xx/setup.c
+++ b/arch/mips/bcm63xx/setup.c
@@ -164,9 +164,6 @@ void __init plat_mem_setup(void)
int __init bcm63xx_register_devices(void)
{
- /* register gpiochip */
- bcm63xx_gpio_init();
-
return board_register_devices();
}

View File

@ -0,0 +1,46 @@
From ec905f2ea78ec40602a685ede31c5e4f9893d196 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 21 Feb 2015 16:35:07 +0100
Subject: [PATCH 3/6] net: bcm63xx_enet: use named gpio for ephy reset gpio
Allow using a named optional gpio for ephy reset gpio registration.
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- 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/gpio/consumer.h>
#include <bcm63xx_dev_enet.h>
#include "bcm63xx_enet.h"
@@ -2848,10 +2849,15 @@ static int bcm_enet_shared_probe(struct
{
struct resource *res;
void __iomem *p[3];
+ struct gpio_desc *ephy_reset;
unsigned int i;
memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base));
+ ephy_reset = devm_gpiod_get_optional(&pdev->dev, "ephy-reset");
+ if (IS_ERR(ephy_reset))
+ return PTR_ERR(ephy_reset);
+
for (i = 0; i < 3; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
p[i] = devm_ioremap_resource(&pdev->dev, res);
@@ -2861,6 +2867,9 @@ static int bcm_enet_shared_probe(struct
memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base));
+ if (ephy_reset)
+ gpiod_direction_output(ephy_reset, 0);
+
return 0;
}

View File

@ -0,0 +1,138 @@
From d13bdf92ec885105cf107183f8464c40e5f3b93b Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 21 Feb 2015 17:21:59 +0100
Subject: [PATCH 4/6] MIPS: BCM63XX: register lookup for ephy-reset gpio
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
arch/mips/bcm63xx/boards/board_common.c | 7 +++--
arch/mips/bcm63xx/gpio.c | 32 ++++++++++++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 2 ++
.../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 5 +--
5 files changed, 42 insertions(+), 6 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -59,7 +59,7 @@ static struct board_info __initdata boar
},
.ephy_reset_gpio = 36,
- .ephy_reset_gpio_flags = GPIOF_INIT_HIGH,
+ .ephy_reset_gpio_flags = GPIO_ACTIVE_LOW,
};
#endif
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -278,9 +278,10 @@ 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");
+ if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags) {
+ bcm63xx_gpio_ephy_reset(board.ephy_reset_gpio,
+ board.ephy_reset_gpio_flags);
+ }
/* count number of BUTTONs defined by this device */
while (button_count < ARRAY_SIZE(board.buttons) && board.buttons[button_count].desc)
--- a/arch/mips/bcm63xx/gpio.c
+++ b/arch/mips/bcm63xx/gpio.c
@@ -8,15 +8,24 @@
* Copyright (C) Jonas Gorski <jogo@openwrt.org>
*/
+#include <asm/addrspace.h>
+
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/basic_mmio_gpio.h>
#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_gpio.h>
#include <bcm63xx_regs.h>
+/* for registering lookups; make them large enough to hold OF names */
+static char *gpio_chip_labels[] = {
+ "xxxxxxxx.gpio-controller",
+ "xxxxxxxx.gpio-controller",
+};
+
static void __init bcm63xx_gpio_init_one(int id, int dir, int data, int ngpio)
{
struct resource res[2];
@@ -40,6 +49,7 @@ static void __init bcm63xx_gpio_init_one
pdata.base = id * 32;
pdata.ngpio = ngpio;
+ sprintf(gpio_chip_labels[id], "bcm63xx-gpio.%d", id);
platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
&pdata, sizeof(pdata));
}
@@ -64,3 +74,25 @@ int __init bcm63xx_gpio_init(void)
return 0;
}
+
+static struct gpiod_lookup_table ephy_reset = {
+ .dev_id = "bcm63xx_enet_shared.0",
+ .table = {
+ { /* filled at runtime */ },
+ { },
+ },
+};
+
+
+void bcm63xx_gpio_ephy_reset(int hw_gpio, enum gpio_lookup_flags flags)
+{
+ if (ephy_reset.table[0].chip_label)
+ return;
+
+ ephy_reset.table[0].chip_label = gpio_chip_labels[hw_gpio / 32];
+ ephy_reset.table[0].chip_hwnum = hw_gpio % 32;
+ ephy_reset.table[0].con_id = "ephy-reset";
+ ephy_reset.table[0].flags = flags;
+
+ gpiod_add_lookup_table(&ephy_reset);
+}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
@@ -2,9 +2,11 @@
#define BCM63XX_GPIO_H
#include <linux/init.h>
+#include <linux/gpio/machine.h>
#include <bcm63xx_cpu.h>
int __init bcm63xx_gpio_init(void);
+void bcm63xx_gpio_ephy_reset(int hw_gpio, enum gpio_lookup_flags flags);
static inline unsigned long bcm63xx_gpio_count(void)
{
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
+#include <linux/gpio/machine.h>
#include <linux/leds.h>
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_usb_usbd.h>
@@ -58,8 +59,8 @@ struct board_info {
/* External PHY reset GPIO */
unsigned int ephy_reset_gpio;
- /* External PHY reset GPIO flags from gpio.h */
- unsigned long ephy_reset_gpio_flags;
+ /* External PHY reset GPIO flags from gpio/machine.h */
+ enum gpio_lookup_flags ephy_reset_gpio_flags;
/* fallback sprom config */
struct fallback_sprom_data fallback_sprom;

View File

@ -0,0 +1,34 @@
From e55892aac9d5508a000647ca66f0e678e02be3bb Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 21 Feb 2015 17:26:50 +0100
Subject: [PATCH 5/6] MIPS: BCM63XX: do not register gpio-controller if
present in dtb
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/gpio.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/gpio.c
+++ b/arch/mips/bcm63xx/gpio.c
@@ -20,6 +20,8 @@
#include <bcm63xx_gpio.h>
#include <bcm63xx_regs.h>
+#include "boards/board_common.h"
+
/* for registering lookups; make them large enough to hold OF names */
static char *gpio_chip_labels[] = {
"xxxxxxxx.gpio-controller",
@@ -50,8 +52,9 @@ static void __init bcm63xx_gpio_init_one
pdata.ngpio = ngpio;
sprintf(gpio_chip_labels[id], "bcm63xx-gpio.%d", id);
- platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
- &pdata, sizeof(pdata));
+ if (!board_of_device_present("gpio0"))
+ platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res,
+ 2, &pdata, sizeof(pdata));
}
int __init bcm63xx_gpio_init(void)

View File

@ -0,0 +1,59 @@
From 1647cccc871bf43876c3df9852869680880d054c Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Wed, 25 Mar 2015 13:52:02 +0100
Subject: [PATCH 1/2] MIPS: BCM63XX: provide a gpio lookup for the pcmcia
ready gpio
To prepare for a time when gpiobases don't need to be fixed anymore.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/dev-pcmcia.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/arch/mips/bcm63xx/dev-pcmcia.c
+++ b/arch/mips/bcm63xx/dev-pcmcia.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <linux/platform_device.h>
+#include <linux/gpio/machine.h>
#include <bcm63xx_cs.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_pcmcia.h>
@@ -101,6 +102,14 @@ static const struct {
},
};
+static struct gpiod_lookup_table pcmcia_gpios_table = {
+ .dev_id = "bcm63xx_pcmcia.0",
+ .table = {
+ GPIO_LOOKUP("bcm63xx-gpio.0", 0, "ready", GPIO_ACTIVE_HIGH),
+ { },
+ },
+};
+
int __init bcm63xx_pcmcia_register(void)
{
int ret, i;
@@ -112,16 +121,20 @@ int __init bcm63xx_pcmcia_register(void)
switch (bcm63xx_get_cpu_id()) {
case BCM6348_CPU_ID:
pd.ready_gpio = 22;
+ pcmcia_gpios_table.table[0].chip_hwnum = 22;
break;
case BCM6358_CPU_ID:
pd.ready_gpio = 18;
+ pcmcia_gpios_table.table[0].chip_hwnum = 18;
break;
default:
return -ENODEV;
}
+ gpiod_add_lookup_table(&pcmcia_gpios_table);
+
pcmcia_resources[0].start = bcm63xx_regset_address(RSET_PCMCIA);
pcmcia_resources[0].end = pcmcia_resources[0].start +
RSET_PCMCIA_SIZE - 1;

View File

@ -0,0 +1,59 @@
From c4e04f1c54928a49b227a5420d38b18226838775 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Wed, 25 Mar 2015 13:54:56 +0100
Subject: [PATCH 2/2] pcmcia: bcm63xx_pmcia: use the new named gpio
Use the new named gpio instead of relying on the hardware gpio numbers
matching the virtual gpio numbers.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
drivers/pcmcia/bcm63xx_pcmcia.c | 9 ++++++++-
drivers/pcmcia/bcm63xx_pcmcia.h | 4 ++++
2 files changed, 12 insertions(+), 1 deletion(-)
--- a/drivers/pcmcia/bcm63xx_pcmcia.c
+++ b/drivers/pcmcia/bcm63xx_pcmcia.c
@@ -237,7 +237,7 @@ static unsigned int __get_socket_status(
stat |= SS_XVCARD;
stat |= SS_POWERON;
- if (gpio_get_value(skt->pd->ready_gpio))
+ if (gpiod_get_value(skt->ready_gpio))
stat |= SS_READY;
return stat;
@@ -373,6 +373,13 @@ static int bcm63xx_drv_pcmcia_probe(stru
goto err;
}
+ /* get ready gpio */
+ skt->ready_gpio = devm_gpiod_get(&pdev->dev, "ready", GPIOD_IN);
+ if (IS_ERR(skt->ready_gpio)) {
+ ret = PTR_ERR(skt->ready_gpio);
+ goto err;
+ }
+
/* resources are static */
sock->resource_ops = &pccard_static_ops;
sock->ops = &bcm63xx_pcmcia_operations;
--- a/drivers/pcmcia/bcm63xx_pcmcia.h
+++ b/drivers/pcmcia/bcm63xx_pcmcia.h
@@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/timer.h>
+#include <linux/gpio/consumer.h>
#include <pcmcia/ss.h>
#include <bcm63xx_dev_pcmcia.h>
@@ -55,6 +56,9 @@ struct bcm63xx_pcmcia_socket {
/* base address of io memory */
void __iomem *io_base;
+
+ /* ready gpio */
+ struct gpio_desc *ready_gpio;
};
#endif /* BCM63XX_PCMCIA_H_ */

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
@@ -34,7 +34,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/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
+++ b/arch/mips/include/asm/mach-bcm63xx/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
@@ -1633,7 +1633,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_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -104,6 +104,8 @@ void __init board_early_setup(const stru
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
@@ -651,6 +651,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
@@ -871,10 +871,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;
@@ -882,40 +880,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 */
@@ -925,7 +893,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, 0,
dev->name, dev);
@@ -1128,9 +1096,6 @@ out_freeirq_rx:
out_freeirq:
free_irq(dev->irq, dev);
-out_phy_disconnect:
- phy_disconnect(priv->phydev);
-
return ret;
}
@@ -1235,12 +1200,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;
}
@@ -1831,6 +1790,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) {
@@ -1868,6 +1829,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 */
@@ -1913,6 +1906,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);
@@ -1954,6 +1950,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
@@ -967,6 +967,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
@@ -2225,6 +2225,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,133 @@
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>
@@ -65,6 +68,21 @@ void __init bcm63xx_flash_force_phys_bas
mtd_resources[0].end = end;
}
+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;
@@ -72,9 +90,15 @@ static int __init bcm63xx_detect_flash_t
switch (bcm63xx_get_cpu_id()) {
case BCM6318_CPU_ID:
/* only support serial flash */
+ bcm63xx_spi_flash_info[0].max_speed_hz = 62500000;
return BCM63XX_FLASH_TYPE_SERIAL;
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
@@ -93,12 +117,20 @@ static int __init bcm63xx_detect_flash_t
return BCM63XX_FLASH_TYPE_SERIAL;
case BCM6362_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
+ if (val & STRAPBUS_6362_HSSPI_CLK_FAST)
+ bcm63xx_spi_flash_info[0].max_speed_hz = 50000000;
+ else
+ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
+
if (val & STRAPBUS_6362_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
return BCM63XX_FLASH_TYPE_NAND;
case BCM6368_CPU_ID:
val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
+ 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;
@@ -109,6 +141,11 @@ static int __init bcm63xx_detect_flash_t
}
case BCM63268_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_63268_REG);
+ if (val & STRAPBUS_63268_HSSPI_CLK_FAST)
+ bcm63xx_spi_flash_info[0].max_speed_hz = 50000000;
+ else
+ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
+
if (val & STRAPBUS_63268_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
@@ -181,8 +218,15 @@ 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_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6362() ||
+ BCMCPU_IS_63268())
+ bcm63xx_spi_flash_info[0].bus_num = 1;
+
+ if (BCMCPU_IS_6358() || BCMCPU_IS_6368())
+ bcm63xx_flash_data.max_transfer_len = SPI_6358_MSG_DATA_SIZE;
+
+ 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
@@ -708,6 +708,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
@@ -1564,6 +1565,7 @@
#define IDDQ_CTRL_63268_USBH (1 << 4)
#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
@@ -96,6 +96,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;
@@ -187,8 +188,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
@@ -31,6 +31,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,72 @@
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_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -36,6 +36,7 @@
#include <bcm63xx_dev_usb_ohci.h>
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
+#include <pci_ath9k_fixup.h>
#include "board_common.h"
@@ -196,6 +197,7 @@ int __init board_register_devices(void)
int button_count = 0;
int led_count = 0;
int usbh_ports = 0;
+ int i;
#if CONFIG_OF
if (of_have_populated_dt()) {
@@ -296,6 +298,10 @@ 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
@@ -10,6 +10,7 @@
#include <bcm63xx_dev_usb_usbd.h>
#include <bcm63xx_dev_dsp.h>
#include <bcm63xx_fallback_sprom.h>
+#include <pci_ath9k_fixup.h>
/*
* flash mapping
@@ -17,6 +18,11 @@
#define BCM963XX_CFE_VERSION_OFFSET 0x570
#define BCM963XX_NVRAM_OFFSET 0x580
+struct ath9k_caldata {
+ unsigned int slot;
+ u32 caldata_offset;
+};
+
/*
* board definition
*/
@@ -37,6 +43,10 @@ struct board_info {
unsigned int has_uart0:1;
unsigned int has_uart1:1;
unsigned int use_fallback_sprom: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
@@ -255,6 +255,9 @@ static int m25p_probe(struct spi_device
if (data)
flash->max_transfer_len = data->max_transfer_len;
+ if (data && data->pp_data)
+ memcpy(&ppdata, data->pp_data, sizeof(ppdata));
+
ret = spi_nor_scan(nor, flash_name, mode);
if (ret)
return ret;
--- 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,31 @@
From 066f1e37742ee434496d32a41a9284458de96742 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Mon, 13 Jan 2014 12:12:30 +0100
Subject: [PATCH] MIPS: BCM63XX: export the attached flash type
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/dev-flash.c | 5 +++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 2 ++
2 files changed, 7 insertions(+)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -236,3 +236,8 @@ int __init bcm63xx_flash_register(void)
return -ENODEV;
}
}
+
+int bcm63xx_flash_get_type(void)
+{
+ return flash_type;
+}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
@@ -13,4 +13,6 @@ void bcm63xx_flash_force_phys_base_addre
int __init bcm63xx_flash_register(void);
+int bcm63xx_flash_get_type(void);
+
#endif /* __BCM63XX_FLASH_H */

View File

@ -0,0 +1,236 @@
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-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \
dev-wdt.o dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o \
- usb-common.o sprom.o
+ pci-ath9k-fixup.o usb-common.o sprom.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/pci-ath9k-fixup.c
@@ -0,0 +1,199 @@
+/*
+ * 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>
+
+#define bcm_hsspi_writel(v, o) bcm_rset_writel(RSET_HSSPI, (v), (o))
+
+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_flash_get_type()) {
+ 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;
+ struct pci_dev *bridge = pci_upstream_bridge(dev);
+ 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_6328;
+ 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;
+ }
+
+ if (bridge)
+ pci_enable_device(bridge);
+
+ 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);
+
+ if (bridge)
+ pci_disable_device(bridge);
+
+ 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() * SZ_1K;
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,83 @@
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_common.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_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -269,7 +269,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
@@ -37,12 +37,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[] = {
@@ -70,6 +73,7 @@ void __init bcm63xx_flash_force_phys_bas
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[] = {
@@ -197,9 +201,13 @@ void __init bcm63xx_flash_detect(void)
}
}
-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;
switch (flash_type) {
case BCM63XX_FLASH_TYPE_PARALLEL:
--- 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,
@@ -11,7 +13,7 @@ void bcm63xx_flash_detect(void);
void bcm63xx_flash_force_phys_base_address(u32 start, u32 end);
-int __init bcm63xx_flash_register(void);
+int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata);
int bcm63xx_flash_get_type(void);

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
@@ -21,6 +21,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
@@ -181,12 +181,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_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -300,7 +300,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_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -301,7 +301,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
@@ -182,13 +182,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
@@ -22,6 +22,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,206 @@
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-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.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 sprom.o
+ pci-ath9k-fixup.o pci-rt2x00-fixup.o usb-common.o sprom.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -37,6 +37,7 @@
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
#include <pci_ath9k_fixup.h>
+#include <pci_rt2x00_fixup.h>
#include "board_common.h"
@@ -299,9 +300,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
@@ -201,7 +201,7 @@ void __init bcm63xx_flash_detect(void)
}
}
-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
@@ -13,7 +13,7 @@ void bcm63xx_flash_detect(void);
void bcm63xx_flash_force_phys_base_address(u32 start, u32 end);
-int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata);
+int __init bcm63xx_flash_register(int num_caldata, struct bcm63xx_caldata *caldata);
int bcm63xx_flash_get_type(void);
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -11,6 +11,7 @@
#include <bcm63xx_dev_dsp.h>
#include <bcm63xx_fallback_sprom.h>
#include <pci_ath9k_fixup.h>
+#include <pci_rt2x00_fixup.h>
/*
* flash mapping
@@ -18,11 +19,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;
};
/*
@@ -48,7 +53,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
@@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/if_vlan.h>
#include <linux/gpio/consumer.h>
+#include <linux/platform_data/b53.h>
#include <bcm63xx_dev_enet.h>
#include "bcm63xx_enet.h"
@@ -1975,7 +1976,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 = {
@@ -1984,6 +1986,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
*/
@@ -2237,29 +2275,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));
@@ -2719,6 +2734,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 ?)
@@ -2808,6 +2826,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:
@@ -2836,6 +2891,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,15 @@
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -2781,12 +2781,6 @@ static int bcm_enetsw_probe(struct platf
if (ret)
goto out;
- if (!request_mem_region(res_mem->start, resource_size(res_mem),
- "bcm63xx_enetsw")) {
- ret = -EBUSY;
- goto out;
- }
-
priv->base = ioremap(res_mem->start, resource_size(res_mem));
if (priv->base == NULL) {
ret = -ENOMEM;

View File

@ -0,0 +1,357 @@
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -32,6 +32,7 @@
#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/of.h>
#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
#include <asm/mach-bcm63xx/bcm963xx_tag.h>
@@ -43,66 +44,35 @@
#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
-static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
- struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
+static bool node_has_compatible(struct device_node *pp)
+{
+ return of_get_property(pp, "compatible", NULL);
+}
+
+static int parse_bcmtag(struct mtd_info *master, struct mtd_partition *pparts,
+ int next_part, size_t offset, size_t size)
{
- /* CFE, NVRAM and global Linux are always present */
- int nrparts = 3, curpart = 0;
struct bcm_tag *buf;
- struct mtd_partition *parts;
+ u32 computed_crc;
int ret;
size_t retlen;
- 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;
+ unsigned int rootfsaddr, kerneladdr;
+ unsigned int rootfslen, kernellen, totallen;
bool rootfs_first = false;
-
- if (!bcm63xx_is_cfe_present())
- return -EINVAL;
-
- cfe_erasesize = max_t(uint32_t, master->erasesize,
- BCM63XX_CFE_BLOCK_SIZE);
-
- cfelen = cfe_erasesize;
- nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K;
- 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;
- }
- }
+ int curr_part = next_part;
/* Allocate memory for buffer */
- buf = vmalloc(sizeof(struct bcm_tag));
+ buf = vmalloc(sizeof(*buf));
if (!buf)
return -ENOMEM;
/* Get the tag */
- ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen,
+ ret = mtd_read(master, offset, sizeof(*buf), &retlen,
(void *)buf);
- if (retlen != sizeof(struct bcm_tag)) {
+ if (retlen != sizeof(*buf)) {
vfree(buf);
- return -EIO;
+ return 0;
}
computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
@@ -121,7 +91,6 @@ static int bcm63xx_parse_cfe_partitions(
kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE;
- spareaddr = roundup(totallen, master->erasesize) + cfelen;
if (rootfsaddr < kerneladdr) {
/* default Broadcom layout */
@@ -130,8 +99,8 @@ static int bcm63xx_parse_cfe_partitions(
} else {
/* OpenWrt layout */
rootfsaddr = kerneladdr + kernellen;
- rootfslen = buf->real_rootfs_length;
- spareaddr = rootfsaddr + rootfslen;
+ rootfslen = size - kernellen -
+ sizeof(*buf);
}
} else {
pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n",
@@ -139,16 +108,153 @@ static int bcm63xx_parse_cfe_partitions(
kernellen = 0;
rootfslen = 0;
rootfsaddr = 0;
- spareaddr = cfelen;
}
- sparelen = min_not_zero(nvramaddr, caldataaddr1) - spareaddr;
- /* Determine number of partitions */
- if (rootfslen > 0)
- nrparts++;
+ if (kernellen > 0) {
+ int kernelpart = curr_part;
- if (kernellen > 0)
- nrparts++;
+ if (rootfslen > 0 && rootfs_first)
+ kernelpart++;
+ pparts[kernelpart].name = "kernel";
+ pparts[kernelpart].offset = kerneladdr;
+ pparts[kernelpart].size = kernellen;
+ curr_part++;
+ }
+
+ if (rootfslen > 0) {
+ int rootfspart = curr_part;
+
+ if (kernellen > 0 && rootfs_first)
+ rootfspart--;
+ pparts[rootfspart].name = "rootfs";
+ pparts[rootfspart].offset = rootfsaddr;
+ pparts[rootfspart].size = rootfslen;
+
+ curr_part++;
+ }
+
+ vfree(buf);
+
+ return curr_part - next_part;
+}
+
+
+static int bcm63xx_parse_cfe_partitions_of(struct mtd_info *master,
+ struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ struct device_node *dp = data->of_node;
+ struct device_node *pp;
+ int i, nr_parts = 0;
+ const char *partname;
+ int len;
+
+ for_each_child_of_node(dp, pp) {
+ if (node_has_compatible(pp))
+ continue;
+
+ if (!of_get_property(pp, "reg", &len))
+ continue;
+
+ partname = of_get_property(pp, "label", &len);
+ if (!partname)
+ partname = of_get_property(pp, "name", &len);
+
+ if (!strcmp(partname, "linux"))
+ nr_parts += 2;
+
+ nr_parts++;
+ }
+
+ *pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL);
+ if (!*pparts)
+ return -ENOMEM;
+
+ i = 0;
+ for_each_child_of_node(dp, pp) {
+ const __be32 *reg;
+ int a_cells, s_cells;
+ size_t size, offset;
+
+ if (node_has_compatible(pp))
+ continue;
+
+ reg = of_get_property(pp, "reg", &len);
+ if (!reg)
+ continue;
+
+ a_cells = of_n_addr_cells(pp);
+ s_cells = of_n_size_cells(pp);
+ offset = of_read_number(reg, a_cells);
+ size = of_read_number(reg + a_cells, s_cells);
+ partname = of_get_property(pp, "label", &len);
+ if (!partname)
+ partname = of_get_property(pp, "name", &len);
+
+ if (!strcmp(partname, "linux"))
+ i += parse_bcmtag(master, *pparts, i, offset, size);
+
+ if (of_get_property(pp, "read-only", &len))
+ (*pparts)[i].mask_flags |= MTD_WRITEABLE;
+
+ if (of_get_property(pp, "lock", &len))
+ (*pparts)[i].mask_flags |= MTD_POWERUP_LOCK;
+
+ (*pparts)[i].offset = offset;
+ (*pparts)[i].size = size;
+ (*pparts)[i].name = partname;
+
+ i++;
+ }
+
+ return i;
+}
+
+static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
+ struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ /* CFE, NVRAM and global Linux are always present */
+ int nrparts = 5, curpart = 0;
+ struct mtd_partition *parts;
+ unsigned int nvramaddr;
+ unsigned int cfelen, nvramlen;
+ unsigned int cfe_erasesize;
+ unsigned int caldatalen1 = 0, caldataaddr1 = 0;
+ unsigned int caldatalen2 = 0, caldataaddr2 = 0;
+ unsigned int imageaddr, imagelen;
+ int i;
+
+ if (!bcm63xx_is_cfe_present())
+ return -EINVAL;
+
+ cfe_erasesize = max_t(uint32_t, master->erasesize,
+ BCM63XX_CFE_BLOCK_SIZE);
+
+ cfelen = cfe_erasesize;
+ nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K;
+ 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;
+ }
+ }
+
+ imageaddr = cfelen;
+ imagelen = min_not_zero(nvramaddr, caldataaddr1) - imageaddr;
if (caldatalen1 > 0)
nrparts++;
@@ -158,10 +264,8 @@ static int bcm63xx_parse_cfe_partitions(
/* Ask kernel for more memory */
parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
- if (!parts) {
- vfree(buf);
+ if (!parts)
return -ENOMEM;
- }
/* Start building partition list */
parts[curpart].name = "CFE";
@@ -169,29 +273,7 @@ static int bcm63xx_parse_cfe_partitions(
parts[curpart].size = cfelen;
curpart++;
- if (kernellen > 0) {
- int kernelpart = curpart;
-
- if (rootfslen > 0 && rootfs_first)
- kernelpart++;
- parts[kernelpart].name = "kernel";
- parts[kernelpart].offset = kerneladdr;
- parts[kernelpart].size = kernellen;
- curpart++;
- }
-
- if (rootfslen > 0) {
- int rootfspart = curpart;
-
- if (kernellen > 0 && rootfs_first)
- rootfspart--;
- parts[rootfspart].name = "rootfs";
- parts[rootfspart].offset = rootfsaddr;
- parts[rootfspart].size = rootfslen;
- if (sparelen > 0 && !rootfs_first)
- parts[rootfspart].size += sparelen;
- curpart++;
- }
+ curpart += parse_bcmtag(master, parts, curpart, imageaddr, imagelen);
if (caldatalen1 > 0) {
if (caldatalen2 > 0)
@@ -217,25 +299,33 @@ static int bcm63xx_parse_cfe_partitions(
/* Global partition "linux" to make easy firmware upgrade */
parts[curpart].name = "linux";
- parts[curpart].offset = cfelen;
- parts[curpart].size = min_not_zero(nvramaddr, caldataaddr1) - cfelen;
+ parts[curpart].offset = imageaddr;
+ parts[curpart].size = imagelen;
+ curpart++;
- for (i = 0; i < nrparts; i++)
+ for (i = 0; i < curpart; i++)
pr_info("Partition %d is %s offset %llx and length %llx\n", i,
parts[i].name, parts[i].offset, parts[i].size);
- pr_info("Spare partition is offset %x and length %x\n", spareaddr,
- sparelen);
-
*pparts = parts;
- vfree(buf);
return nrparts;
};
+
+static int bcm63xx_parse_partitions(struct mtd_info *master,
+ struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ if (data && data->of_node)
+ return bcm63xx_parse_cfe_partitions_of(master, pparts, data);
+ else
+ return bcm63xx_parse_cfe_partitions(master, pparts, data);
+}
+
static struct mtd_part_parser bcm63xx_cfe_parser = {
.owner = THIS_MODULE,
- .parse_fn = bcm63xx_parse_cfe_partitions,
+ .parse_fn = bcm63xx_parse_partitions,
.name = "bcm63xxpart",
};

View File

@ -0,0 +1,56 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -61,7 +61,7 @@ static struct board_info __initdata boar
.ephy_reset_gpio = 36,
.ephy_reset_gpio_flags = GPIO_ACTIVE_LOW,
};
-#endif
+#endif /* CONFIG_BCM63XX_CPU_3368 */
/*
* known 6328 boards
@@ -110,7 +110,7 @@ static struct board_info __initdata boar
},
},
};
-#endif
+#endif /* CONFIG_BCM63XX_CPU_6328 */
/*
* known 6338 boards
@@ -199,7 +199,7 @@ static struct board_info __initdata boar
},
},
};
-#endif
+#endif /* CONFIG_BCM63XX_CPU_6338 */
/*
* known 6345 boards
@@ -211,7 +211,7 @@ static struct board_info __initdata boar
.has_uart0 = 1,
};
-#endif
+#endif /* CONFIG_BCM63XX_CPU_6345 */
/*
* known 6348 boards
@@ -524,7 +524,7 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
};
-#endif
+#endif /* CONFIG_BCM63XX_CPU_6348 */
/*
* known 6358 boards
@@ -677,7 +677,7 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
};
-#endif
+#endif /* CONFIG_BCM63XX_CPU_6358 */
/*
* all boards

View File

@ -0,0 +1,41 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -524,6 +524,22 @@ 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,
+ },
+};
#endif /* CONFIG_BCM63XX_CPU_6348 */
/*
@@ -705,6 +721,7 @@ static const struct board_info __initcon
&board_DV201AMR,
&board_96348gw_a,
&board_rta1025w_16,
+ &board_96348_D4PW,
#endif
#ifdef CONFIG_BCM63XX_CPU_6358
@@ -736,6 +753,7 @@ static struct of_device_id const bcm963x
{ .compatible = "brcm,bcm96348gw-10", .data = &board_96348gw_10, },
{ .compatible = "brcm,bcm96348gw-11", .data = &board_96348gw_11, },
{ .compatible = "brcm,bcm96348gw-a", .data = &board_96348gw_a, },
+ { .compatible = "d-link,dsl-2640b-b", .data = &board_96348_D4PW, },
{ .compatible = "davolink,dv-201amr", .data = &board_DV201AMR, },
{ .compatible = "dynalink,rta1025w", .data = &board_rta1025w_16, },
{ .compatible = "netgear,dg834gtpn", .data = &board_96348gw_10, },

View File

@ -0,0 +1,83 @@
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -693,6 +693,62 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
};
+
+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,
+ .num_usbh_ports = 2,
+};
+
+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,
+ .num_usbh_ports = 2,
+};
#endif /* CONFIG_BCM63XX_CPU_6358 */
/*
@@ -729,6 +785,8 @@ static const struct board_info __initcon
&board_96358vw2,
&board_AGPFS0,
&board_DWVS0,
+ &board_nb4_ser_r0,
+ &board_nb4_fxc_r1,
#endif
};
@@ -770,6 +828,8 @@ static struct of_device_id const bcm963x
{ .compatible = "pirelli,a226m", .data = &board_DWVS0, },
{ .compatible = "pirelli,a226m-fwb", .data = &board_DWVS0, },
{ .compatible = "pirelli,agpf-s0", .data = &board_AGPFS0, },
+ { .compatible = "sfr,nb4-ser-r0", .data = &board_nb4_ser_r0, },
+ { .compatible = "sfr,nb4-fxc-r1", .data = &board_nb4_fxc_r1, },
#endif
#ifdef CONFIG_BCM63XX_CPU_6368
#endif

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