Update enetswith driver with latest fixes and additions.
Signed-off-by: Jonas Gorski <jonas.gorski+openwrt@gmail.com>
SVN-Revision: 32921
+++ /dev/null
-From 37d151859e09d09a950ad3ae615db1903bcc59d3 Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Sun, 13 Nov 2011 14:59:37 +0100
-Subject: [PATCH 43/79] bcm63xx_enet: fix lockup on BCM6328
-
-BCM6328 locks up on a maxburst size of 16, reduce it to 8 for BCM6328 and
-BCM6368.
-
-Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
----
- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 14 ++++++++------
- drivers/net/ethernet/broadcom/bcm63xx_enet.h | 4 ++++
- 2 files changed, 12 insertions(+), 6 deletions(-)
-
---- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
-+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
-@@ -261,7 +261,6 @@ static int bcm_enet_refill_rx(struct net
- if (!skb)
- break;
- priv->rx_skb[desc_idx] = skb;
--
- p = dma_map_single(&priv->pdev->dev, skb->data,
- priv->rx_skb_size,
- DMA_FROM_DEVICE);
-@@ -995,9 +994,9 @@ static int bcm_enet_open(struct net_devi
- enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG);
-
- /* set dma maximum burst len */
-- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
-+ enet_dmac_writel(priv, priv->dma_maxburst,
- ENETDMAC_MAXBURST_REG(priv->rx_chan));
-- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
-+ enet_dmac_writel(priv, priv->dma_maxburst,
- ENETDMAC_MAXBURST_REG(priv->tx_chan));
-
- /* set correct transmit fifo watermark */
-@@ -1593,7 +1592,7 @@ static int compute_hw_mtu(struct bcm_ene
- * it's appended
- */
- priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
-- BCMENET_DMA_MAXBURST * 4);
-+ priv->dma_maxburst * 4);
- return 0;
- }
-
-@@ -1700,6 +1699,8 @@ static int __devinit bcm_enet_probe(stru
- return -ENOMEM;
- priv = netdev_priv(dev);
-
-+ priv->dma_maxburst = bcm_enet_is_sw(priv) ?
-+ BCMENETSW_DMA_MAXBURST : BCMENET_DMA_MAXBURST;
- ret = compute_hw_mtu(priv, dev->mtu);
- if (ret)
- goto out;
-@@ -2263,9 +2264,9 @@ static int bcm_enetsw_open(struct net_de
- enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
-
- /* set dma maximum burst len */
-- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
-+ enet_dmac_writel(priv, priv->dma_maxburst,
- ENETDMAC_MAXBURST_REG(priv->rx_chan));
-- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
-+ enet_dmac_writel(priv, priv->dma_maxburst,
- ENETDMAC_MAXBURST_REG(priv->tx_chan));
-
- /* set flow control low/high threshold to 1/3 / 2/3 */
-@@ -2727,6 +2728,7 @@ static int __devinit bcm_enetsw_probe(st
- priv->irq_tx = irq_tx;
- priv->rx_ring_size = BCMENET_DEF_RX_DESC;
- priv->tx_ring_size = BCMENET_DEF_TX_DESC;
-+ priv->dma_maxburst = BCMENETSW_DMA_MAXBURST;
-
- pd = pdev->dev.platform_data;
- if (pd) {
---- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
-+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
-@@ -17,6 +17,7 @@
-
- /* maximum burst len for dma (4 bytes unit) */
- #define BCMENET_DMA_MAXBURST 16
-+#define BCMENETSW_DMA_MAXBURST 8
-
- /* tx transmit threshold (4 bytes unit), fifo is 256 bytes, the value
- * must be low enough so that a DMA transfer of above burst length can
-@@ -280,6 +281,9 @@ struct bcm_enet_priv {
- /* number of dma desc in tx ring */
- int tx_ring_size;
-
-+ /* maximum dma burst size */
-+ int dma_maxburst;
-+
- /* cpu view of rx dma ring */
- struct bcm_enet_desc *tx_desc_cpu;
-
--- /dev/null
+From 6d5c5bb13db3fd8e3dd0b82742b3957f41a4a3ac Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 24 May 2012 20:38:58 +0200
+Subject: [PATCH] bcm63xx_enet: reset port link state in bcm_enetsw_open
+
+bcm_enetsw_open disables all ports, but does not reset their link state.
+This results in connected ports staying disabled after a ifdown/ifup
+cycle, since bcm_enetsw_phy_poll only enables them if their current state
+is different from the stored link state.
+
+Fix this by also resetting the port link state.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2213,6 +2213,8 @@ static int bcm_enetsw_open(struct net_de
+ enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
+ ENETSW_PTCTRL_TXDIS_MASK,
+ ENETSW_PTCTRL_REG(i));
++
++ priv->sw_port_link[i] = 0;
+ }
+
+ /* reset mib */
+++ /dev/null
-From 44e21f4c7c556573fff0432f7846086763df3455 Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Tue, 14 Jun 2011 21:14:39 +0200
-Subject: [PATCH 44/79] MIPS: BCM63XX: add support for BCM6328 in bcm_enetsw
-
-Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
----
- arch/mips/bcm63xx/clk.c | 34 +++++++++++++++++++-------
- arch/mips/bcm63xx/dev-enet.c | 4 +--
- drivers/net/ethernet/broadcom/bcm63xx_enet.h | 2 +-
- 3 files changed, 28 insertions(+), 12 deletions(-)
-
---- a/arch/mips/bcm63xx/clk.c
-+++ b/arch/mips/bcm63xx/clk.c
-@@ -118,21 +118,37 @@ static struct clk clk_ephy = {
- */
- static void enetsw_set(struct clk *clk, int enable)
- {
-- if (!BCMCPU_IS_6368())
-+ u32 mask;
-+
-+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
- return;
-- bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
-- CKCTL_6368_SWPKT_USB_EN |
-- CKCTL_6368_SWPKT_SAR_EN, enable);
-+
-+ if (BCMCPU_IS_6328())
-+ mask = CKCTL_6328_ROBOSW_EN;
-+ else
-+ mask = CKCTL_6368_ROBOSW_EN | CKCTL_6368_SWPKT_USB_EN |
-+ CKCTL_6368_SWPKT_SAR_EN;
-+
-+ bcm_hwclock_set(mask, enable);
- if (enable) {
-+ u32 reg;
- u32 val;
-
-+ if (BCMCPU_IS_6328()) {
-+ reg = PERF_SOFTRESET_6328_REG;
-+ mask = SOFTRESET_6328_ENETSW_MASK;
-+ } else {
-+ reg = PERF_SOFTRESET_6368_REG;
-+ mask = SOFTRESET_6368_ENETSW_MASK;
-+ }
-+
- /* reset switch core afer clock change */
-- val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
-- val &= ~SOFTRESET_6368_ENETSW_MASK;
-- bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
-+ val = bcm_perf_readl(reg);
-+ val &= ~mask;
-+ bcm_perf_writel(val, reg);
- msleep(10);
-- val |= SOFTRESET_6368_ENETSW_MASK;
-- bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
-+ val |= mask;
-+ bcm_perf_writel(val, reg);
- msleep(10);
- }
- }
---- a/arch/mips/bcm63xx/dev-enet.c
-+++ b/arch/mips/bcm63xx/dev-enet.c
-@@ -141,7 +141,7 @@ static int __init register_shared(void)
- shared_res[0].end = shared_res[0].start;
- shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
-
-- if (BCMCPU_IS_6368())
-+ if (BCMCPU_IS_6328() || BCMCPU_IS_6368())
- chan_count = 32;
- else
- chan_count = 16;
-@@ -224,7 +224,7 @@ bcm63xx_enetsw_register(const struct bcm
- {
- int ret;
-
-- if (!BCMCPU_IS_6368())
-+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
- return -ENODEV;
-
- ret = register_shared();
---- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
-+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
-@@ -368,7 +368,7 @@ struct bcm_enet_priv {
-
- static inline int bcm_enet_is_sw(struct bcm_enet_priv *priv)
- {
-- if (BCMCPU_IS_6368())
-+ if (BCMCPU_IS_6328() || BCMCPU_IS_6368())
- return 1;
- else
- return 0;
--- /dev/null
+From e79bc74f76361020d820ed4611d28f70ebd845ca Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 10 Jul 2012 10:44:09 +0200
+Subject: [PATCH 34/84] bcm63xx_enet: don't overwrite settings when setting duplex on force
+
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2333,7 +2333,7 @@ static int bcm_enetsw_open(struct net_de
+ }
+
+ if (port->force_duplex_full)
+- override = ENETSW_IMPOV_FDX_MASK;
++ override |= ENETSW_IMPOV_FDX_MASK;
+
+
+ enetsw_writeb(priv, override, ENETSW_PORTOV_REG(i));
+++ /dev/null
-From 56be5a2d7e08faa7bb306faaf352ac4e6ac52c01 Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Sat, 12 Nov 2011 12:18:26 +0100
-Subject: [PATCH 26/60] MIPS: BCM63XX: add HS SPI platform device and register it
-
-Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
----
- arch/mips/bcm63xx/Makefile | 5 +-
- arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +
- arch/mips/bcm63xx/dev-hsspi.c | 57 ++++++++++++++++++++
- .../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 20 +++++++
- 4 files changed, 82 insertions(+), 2 deletions(-)
- create mode 100644 arch/mips/bcm63xx/dev-hsspi.c
- create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
-
---- a/arch/mips/bcm63xx/Makefile
-+++ b/arch/mips/bcm63xx/Makefile
-@@ -1,6 +1,7 @@
- obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
-- dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
-- dev-spi.o dev-uart.o dev-usb-ehci.o dev-usb-ohci.o dev-wdt.o
-+ dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o dev-pcmcia.o \
-+ dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
-+ dev-usb-ohci.o dev-wdt.o
- obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-
- obj-y += boards/
---- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
-+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -25,6 +25,7 @@
- #include <bcm63xx_dev_enet.h>
- #include <bcm63xx_dev_dsp.h>
- #include <bcm63xx_dev_flash.h>
-+#include <bcm63xx_dev_hsspi.h>
- #include <bcm63xx_dev_pcmcia.h>
- #include <bcm63xx_dev_spi.h>
- #include <bcm63xx_dev_usb_ohci.h>
-@@ -945,6 +946,7 @@ int __init board_register_devices(void)
- pr_err(PFX "failed to register fallback SPROM\n");
- }
- #endif
-+ bcm63xx_hsspi_register();
-
- bcm63xx_spi_register();
-
---- /dev/null
-+++ b/arch/mips/bcm63xx/dev-hsspi.c
-@@ -0,0 +1,57 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/platform_device.h>
-+
-+#include <bcm63xx_cpu.h>
-+#include <bcm63xx_dev_hsspi.h>
-+#include <bcm63xx_regs.h>
-+
-+static struct resource spi_resources[] = {
-+ {
-+ .start = -1, /* filled at runtime */
-+ .end = -1, /* filled at runtime */
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = -1, /* filled at runtime */
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct bcm63xx_hsspi_pdata spi_pdata = {
-+ .bus_num = 0,
-+};
-+
-+static struct platform_device bcm63xx_hsspi_device = {
-+ .name = "bcm63xx-hsspi",
-+ .id = 0,
-+ .num_resources = ARRAY_SIZE(spi_resources),
-+ .resource = spi_resources,
-+ .dev = {
-+ .platform_data = &spi_pdata,
-+ },
-+};
-+
-+int __init bcm63xx_hsspi_register(void)
-+{
-+
-+ if (!BCMCPU_IS_6328())
-+ return -ENODEV;
-+
-+ spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
-+ spi_resources[0].end = spi_resources[0].start;
-+ spi_resources[0].end += RSET_HSSPI_SIZE - 1;
-+ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI);
-+
-+ spi_pdata.speed_hz = HSSPI_PLL_HZ_6328;
-+
-+ return platform_device_register(&bcm63xx_hsspi_device);
-+}
---- /dev/null
-+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
-@@ -0,0 +1,20 @@
-+#ifndef BCM63XX_DEV_HSSPI_H
-+#define BCM63XX_DEV_HSSPI_H
-+
-+#include <linux/types.h>
-+#include <bcm63xx_io.h>
-+#include <bcm63xx_regs.h>
-+
-+int __init bcm63xx_hsspi_register(void);
-+
-+struct bcm63xx_hsspi_pdata {
-+ int bus_num;
-+ u32 speed_hz;
-+};
-+
-+#define bcm_hsspi_readl(o) bcm_rset_readl(RSET_HSSPI, (o))
-+#define bcm_hsspi_writel(v, o) bcm_rset_writel(RSET_HSSPI, (v), (o))
-+
-+#define HSSPI_PLL_HZ_6328 133333333
-+
-+#endif /* BCM63XX_DEV_HSSPI_H */
--- /dev/null
+From efe31ec8fca92162fc21630611971345014a81a0 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 10 Jul 2012 10:39:30 +0200
+Subject: [PATCH 33/84] bcm63xx_enet: store the number of ports instead of hardcoding them
+
+This will be needed for devices with a different number of ports
+---
+ arch/mips/bcm63xx/dev-enet.c | 2 ++
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 2 ++
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 9 +++++----
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 1 +
+ 4 files changed, 10 insertions(+), 4 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -239,6 +239,8 @@ bcm63xx_enetsw_register(const struct bcm
+
+ memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof (*pd));
+
++ enetsw_pd.num_ports = ENETSW_PORTS_6368;
++
+ ret = platform_device_register(&bcm63xx_enetsw_device);
+ if (ret)
+ return ret;
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+@@ -43,6 +43,7 @@ struct bcm63xx_enet_platform_data {
+ * on board ethernet switch platform data
+ */
+ #define ENETSW_MAX_PORT 6
++#define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
+
+ struct bcm63xx_enetsw_port {
+ int used;
+@@ -58,6 +59,7 @@ struct bcm63xx_enetsw_port {
+
+ struct bcm63xx_enetsw_platform_data {
+ char mac_addr[ETH_ALEN];
++ int num_ports;
+ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
+ };
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2041,7 +2041,7 @@ static void swphy_poll_timer(unsigned lo
+ struct bcm_enet_priv *priv = (struct bcm_enet_priv *)data;
+ unsigned int i;
+
+- for (i = 0; i < ARRAY_SIZE(priv->used_ports); i++) {
++ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm63xx_enetsw_port *port;
+ int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
+ u8 override;
+@@ -2207,7 +2207,7 @@ static int bcm_enetsw_open(struct net_de
+ priv->rx_curr_desc = 0;
+
+ /* disable all ports */
+- for (i = 0; i < 6; i++) {
++ for (i = 0; i < priv->num_ports; i++) {
+ enetsw_writeb(priv, ENETSW_PORTOV_ENABLE_MASK,
+ ENETSW_PORTOV_REG(i));
+ enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
+@@ -2303,7 +2303,7 @@ static int bcm_enetsw_open(struct net_de
+ /*
+ * apply override config for bypass_link ports here.
+ */
+- for (i = 0; i < ARRAY_SIZE(priv->used_ports); i++) {
++ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm63xx_enetsw_port *port;
+ u8 override;
+ port = &priv->used_ports[i];
+@@ -2447,7 +2447,7 @@ static int bcm_enetsw_phy_is_external(st
+ {
+ int i;
+
+- for (i = 0; i < (int)ARRAY_SIZE(priv->used_ports); ++i) {
++ for (i = 0; i < priv->num_ports; ++i) {
+ if (!priv->used_ports[i].used)
+ continue;
+ if (priv->used_ports[i].phy_id == phy_id)
+@@ -2735,6 +2735,7 @@ static int __devinit bcm_enetsw_probe(st
+ memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN);
+ memcpy(priv->used_ports, pd->used_ports,
+ sizeof (pd->used_ports));
++ priv->num_ports = pd->num_ports;
+ }
+
+ ret = compute_hw_mtu(priv, dev->mtu);
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -354,6 +354,7 @@ struct bcm_enet_priv {
+ unsigned int hw_mtu;
+
+ /* port mapping for switch devices */
++ int num_ports;
+ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
+ int sw_port_link[ENETSW_MAX_PORT];
+
+++ /dev/null
-From 4b27423676485d05bcd6fc6f3809164fb8f9d22d Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Sat, 12 Nov 2011 12:19:55 +0100
-Subject: [PATCH 30/60] SPI: MIPS: BCM63XX: Add HSSPI driver
-
-Add a driver for the High Speed SPI controller found on newer BCM63XX SoCs.
-
-Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
----
- .../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 2 +
- drivers/spi/Kconfig | 7 +
- drivers/spi/Makefile | 1 +
- drivers/spi/spi-bcm63xx-hsspi.c | 427 ++++++++++++++++++++
- 4 files changed, 437 insertions(+), 0 deletions(-)
- create mode 100644 drivers/spi/spi-bcm63xx-hsspi.c
-
---- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
-+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
-@@ -17,4 +17,6 @@ struct bcm63xx_hsspi_pdata {
-
- #define HSSPI_PLL_HZ_6328 133333333
-
-+#define HSSPI_BUFFER_LEN 512
-+
- #endif /* BCM63XX_DEV_HSSPI_H */
---- a/drivers/spi/Kconfig
-+++ b/drivers/spi/Kconfig
-@@ -100,6 +100,13 @@ config SPI_BCM63XX
- help
- Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
-
-+config SPI_BCM63XX_HSSPI
-+ tristate "Broadcom BCM63XX HS SPI controller driver"
-+ depends on BCM63XX
-+ help
-+ This enables support for the High Speed SPI controller present on
-+ newer Broadcom BCM63XX SoCs.
-+
- config SPI_BITBANG
- tristate "Utilities for Bitbanging SPI masters"
- help
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
- obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
- obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
- obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
-+obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o
- obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o
- obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
- obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
---- /dev/null
-+++ b/drivers/spi/spi-bcm63xx-hsspi.c
-@@ -0,0 +1,427 @@
-+/*
-+ * Broadcom BCM63XX High Speed SPI Controller driver
-+ *
-+ * Copyright 2000-2010 Broadcom Corporation
-+ * Copyright 2012 Jonas Gorski <jonas.gorski@gmail.com>
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/clk.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/err.h>
-+#include <linux/interrupt.h>
-+#include <linux/spi/spi.h>
-+#include <linux/workqueue.h>
-+
-+#include <bcm63xx_regs.h>
-+#include <bcm63xx_dev_hsspi.h>
-+
-+#define HSSPI_OP_CODE_SHIFT 13
-+#define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT)
-+#define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT)
-+#define HSSPI_OP_WRITE (2 << HSSPI_OP_CODE_SHIFT)
-+#define HSSPI_OP_READ (3 << HSSPI_OP_CODE_SHIFT)
-+
-+#define HSSPI_MAX_PREPEND_LEN 15
-+
-+#define HSSPI_MAX_SYNC_CLOCK 30000000
-+
-+struct bcm63xx_hsspi {
-+ struct completion done;
-+ struct spi_transfer *curr_trans;
-+
-+ struct platform_device *pdev;
-+ struct clk *clk;
-+ void __iomem *regs;
-+ u8 __iomem *fifo;
-+
-+ u32 speed_hz;
-+ int irq;
-+};
-+
-+static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, int hz,
-+ int profile)
-+{
-+ u32 reg;
-+
-+ reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
-+ bcm_hsspi_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
-+ HSSPI_PROFILE_CLK_CTRL_REG(profile));
-+
-+ reg = bcm_hsspi_readl(HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
-+ if (hz > HSSPI_MAX_SYNC_CLOCK)
-+ reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
-+ else
-+ reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
-+ bcm_hsspi_writel(reg, HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
-+}
-+
-+static int bcm63xx_hsspi_do_txrx(struct spi_device *spi,
-+ struct spi_transfer *t1,
-+ struct spi_transfer *t2)
-+{
-+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
-+ u8 chip_select = spi->chip_select;
-+ u16 opcode = 0;
-+ int len, prepend_size = 0;
-+
-+ init_completion(&bs->done);
-+
-+ bs->curr_trans = t2 ? t2 : t1;
-+ bcm63xx_hsspi_set_clk(bs, bs->curr_trans->speed_hz, chip_select);
-+
-+ if (t2 && !t2->tx_buf)
-+ prepend_size = t1->len;
-+
-+ bcm_hsspi_writel(prepend_size << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
-+ 2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
-+ 2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
-+ HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
-+
-+ if (t1->rx_buf && t1->tx_buf)
-+ opcode = HSSPI_OP_READ_WRITE;
-+ else if (t1->rx_buf || (t2 && t2->rx_buf))
-+ opcode = HSSPI_OP_READ;
-+ else if (t1->tx_buf)
-+ opcode = HSSPI_OP_WRITE;
-+
-+ if (opcode == HSSPI_OP_READ && t2)
-+ len = t2->len;
-+ else
-+ len = t1->len;
-+
-+ if (t1->tx_buf) {
-+ memcpy_toio(bs->fifo + 2, t1->tx_buf, t1->len);
-+ if (t2 && t2->tx_buf) {
-+ memcpy_toio(bs->fifo + 2 + t1->len,
-+ t2->tx_buf, t2->len);
-+ len += t2->len;
-+ }
-+ }
-+
-+ opcode |= len;
-+ memcpy_toio(bs->fifo, &opcode, sizeof(opcode));
-+
-+ /* enable interrupt */
-+ bcm_hsspi_writel(HSSPI_PING0_CMD_DONE, HSSPI_INT_MASK_REG);
-+
-+ /* start the transfer */
-+ bcm_hsspi_writel(chip_select << PINGPONG_CMD_SS_SHIFT |
-+ chip_select << PINGPONG_CMD_PROFILE_SHIFT |
-+ PINGPONG_COMMAND_START_NOW,
-+ HSSPI_PINGPONG_COMMAND_REG(0));
-+
-+ if (wait_for_completion_timeout(&bs->done, HZ) == 0) {
-+ dev_err(&bs->pdev->dev, "transfer timed out!\n");
-+ return -ETIMEDOUT;
-+ }
-+
-+ return t1->len + (t2 ? t2->len : 0);
-+}
-+
-+static int bcm63xx_hsspi_setup(struct spi_device *spi)
-+{
-+ u32 reg;
-+
-+ if (spi->bits_per_word != 8)
-+ return -EINVAL;
-+
-+ if (spi->max_speed_hz == 0)
-+ return -EINVAL;
-+
-+ reg = bcm_hsspi_readl(HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
-+ reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
-+ if (spi->mode & SPI_CPHA)
-+ reg |= SIGNAL_CTRL_LAUNCH_RISING;
-+ else
-+ reg |= SIGNAL_CTRL_LATCH_RISING;
-+ bcm_hsspi_writel(reg, HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
-+
-+ return 0;
-+}
-+
-+static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
-+ struct spi_message *msg)
-+{
-+ struct spi_transfer *t, *prev = NULL;
-+ struct spi_device *spi = msg->spi;
-+ u32 reg;
-+ int ret = -EINVAL;
-+ int len = 0;
-+
-+ /* check if we are able to make these transfers */
-+ list_for_each_entry(t, &msg->transfers, transfer_list) {
-+ if (!t->tx_buf && !t->rx_buf)
-+ goto out;
-+
-+ if (t->speed_hz == 0)
-+ t->speed_hz = spi->max_speed_hz;
-+
-+ if (t->speed_hz > spi->max_speed_hz)
-+ goto out;
-+
-+ if (t->len > HSSPI_BUFFER_LEN)
-+ goto out;
-+
-+ /*
-+ * This controller does not support keeping the chip select
-+ * active between transfers.
-+ * This logic currently supports combining:
-+ * write then read with no cs_change (e.g. m25p80 RDSR)
-+ * write then write with no cs_change (e.g. m25p80 PP)
-+ */
-+ if (prev && prev->tx_buf && !prev->cs_change && !t->cs_change) {
-+ /*
-+ * reject if we have to combine two tx transfers and
-+ * their combined length is bigger than the buffer
-+ */
-+ if (prev->tx_buf && t->tx_buf &&
-+ (prev->len + t->len) > HSSPI_BUFFER_LEN)
-+ goto out;
-+ /*
-+ * reject if we need write more than 15 bytes in read
-+ * then write.
-+ */
-+ if (prev->tx_buf && t->rx_buf &&
-+ prev->len > HSSPI_MAX_PREPEND_LEN)
-+ goto out;
-+ }
-+
-+ }
-+
-+ /* setup clock polarity */
-+ reg = bcm_hsspi_readl(HSSPI_GLOBAL_CTRL_REG);
-+ reg &= ~GLOBAL_CTRL_CLK_POLARITY;
-+ if (spi->mode & SPI_CPOL)
-+ reg |= GLOBAL_CTRL_CLK_POLARITY;
-+ bcm_hsspi_writel(reg, HSSPI_GLOBAL_CTRL_REG);
-+
-+ list_for_each_entry(t, &msg->transfers, transfer_list) {
-+ if (prev && prev->tx_buf && !prev->cs_change && !t->cs_change) {
-+ /* combine write with following transfer */
-+ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, t);
-+ if (ret < 0)
-+ goto out;
-+
-+ len += ret;
-+ prev = NULL;
-+ continue;
-+ }
-+
-+ /* write the previous pending transfer */
-+ if (prev != NULL) {
-+ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, NULL);
-+ if (ret < 0)
-+ goto out;
-+
-+ len += ret;
-+ }
-+
-+ prev = t;
-+ }
-+
-+ /* do last pending transfer */
-+ if (prev != NULL) {
-+ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, NULL);
-+ if (ret < 0)
-+ goto out;
-+ len += ret;
-+ }
-+
-+ msg->actual_length = len;
-+ ret = 0;
-+out:
-+ msg->status = ret;
-+ spi_finalize_current_message(master);
-+ return 0;
-+}
-+
-+static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
-+{
-+ struct spi_master *master = (struct spi_master *)dev_id;
-+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
-+
-+ if (bcm_hsspi_readl(HSSPI_INT_STATUS_MASKED_REG) == 0)
-+ return IRQ_NONE;
-+
-+ bcm_hsspi_writel(HSSPI_INT_CLEAR_ALL, HSSPI_INT_STATUS_REG);
-+ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
-+
-+ if (bs->curr_trans && bs->curr_trans->rx_buf)
-+ memcpy_fromio(bs->curr_trans->rx_buf, bs->fifo,
-+ bs->curr_trans->len);
-+ complete(&bs->done);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int __devinit bcm63xx_hsspi_probe(struct platform_device *pdev)
-+{
-+
-+ struct spi_master *master;
-+ struct bcm63xx_hsspi *bs;
-+ struct resource *res_mem;
-+ void __iomem *regs;
-+ struct device *dev = &pdev->dev;
-+ struct bcm63xx_hsspi_pdata *pdata = pdev->dev.platform_data;
-+ struct clk *clk;
-+ int irq;
-+ int ret;
-+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq < 0) {
-+ dev_err(dev, "no irq\n");
-+ return -ENXIO;
-+ }
-+
-+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ regs = devm_request_and_ioremap(dev, res_mem);
-+ if (!regs) {
-+ dev_err(dev, "unable to ioremap regs\n");
-+ return -ENXIO;
-+ }
-+
-+ clk = clk_get(dev, "hsspi");
-+
-+ if (IS_ERR(clk)) {
-+ ret = PTR_ERR(clk);
-+ goto out_release;
-+ }
-+
-+ clk_prepare_enable(clk);
-+
-+ master = spi_alloc_master(&pdev->dev, sizeof(*bs));
-+ if (!master) {
-+ ret = -ENOMEM;
-+ goto out_disable_clk;
-+ }
-+
-+ bs = spi_master_get_devdata(master);
-+ bs->pdev = pdev;
-+ bs->clk = clk;
-+ bs->regs = regs;
-+
-+ master->bus_num = pdata->bus_num;
-+ master->num_chipselect = 8;
-+ master->setup = bcm63xx_hsspi_setup;
-+ master->transfer_one_message = bcm63xx_hsspi_transfer_one;
-+ master->mode_bits = SPI_CPOL | SPI_CPHA;
-+
-+ bs->speed_hz = pdata->speed_hz;
-+ bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
-+
-+ platform_set_drvdata(pdev, master);
-+
-+ bs->curr_trans = NULL;
-+
-+ /* Initialize the hardware */
-+ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
-+
-+ /* clean up any pending interrupts */
-+ bcm_hsspi_writel(HSSPI_INT_CLEAR_ALL, HSSPI_INT_STATUS_REG);
-+
-+ bcm_hsspi_writel(bcm_hsspi_readl(HSSPI_GLOBAL_CTRL_REG) |
-+ GLOBAL_CTRL_CLK_GATE_SSOFF,
-+ HSSPI_GLOBAL_CTRL_REG);
-+
-+ ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
-+ pdev->name, master);
-+
-+ if (ret)
-+ goto out_put_master;
-+
-+ /* register and we are done */
-+ ret = spi_register_master(master);
-+ if (ret)
-+ goto out_free_irq;
-+
-+ return 0;
-+
-+out_free_irq:
-+ devm_free_irq(dev, bs->irq, master);
-+out_put_master:
-+ spi_master_put(master);
-+out_disable_clk:
-+ clk_disable_unprepare(clk);
-+ clk_put(clk);
-+out_release:
-+ devm_ioremap_release(dev, regs);
-+
-+ return ret;
-+}
-+
-+
-+static int __exit bcm63xx_hsspi_remove(struct platform_device *pdev)
-+{
-+ struct spi_master *master = platform_get_drvdata(pdev);
-+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
-+
-+ spi_unregister_master(master);
-+
-+ /* reset the hardware and block queue progress */
-+ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
-+ clk_disable_unprepare(bs->clk);
-+ clk_put(bs->clk);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int bcm63xx_hsspi_suspend(struct platform_device *pdev,
-+ pm_message_t mesg)
-+{
-+ struct spi_master *master = platform_get_drvdata(pdev);
-+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
-+
-+ spi_master_suspend(master);
-+ clk_disable(bs->clk);
-+
-+ return 0;
-+}
-+
-+static int bcm63xx_hsspi_resume(struct platform_device *pdev)
-+{
-+ struct spi_master *master = platform_get_drvdata(pdev);
-+ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
-+
-+ clk_enable(bs->clk);
-+ spi_master_resume(master);
-+
-+ return 0;
-+}
-+
-+static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = {
-+ .suspend = bcm63xx_hsspi_suspend,
-+ .resume = bcm63xx_hsspi_resume,
-+};
-+
-+#define BCM63XX_HSSPI_PM_OPS (&bcm63xx_hsspi_pm_ops)
-+#else
-+#define BCM63XX_HSSPI_PM_OPS NULL
-+#endif
-+
-+
-+
-+static struct platform_driver bcm63xx_hsspi_driver = {
-+ .driver = {
-+ .name = "bcm63xx-hsspi",
-+ .owner = THIS_MODULE,
-+ .pm = BCM63XX_HSSPI_PM_OPS,
-+ },
-+ .probe = bcm63xx_hsspi_probe,
-+ .remove = __exit_p(bcm63xx_hsspi_remove),
-+};
-+
-+module_platform_driver(bcm63xx_hsspi_driver);
-+
-+MODULE_ALIAS("platform:bcm63xx_hsspi");
-+MODULE_DESCRIPTION("Broadcom BCM63xx HS SPI Controller driver");
-+MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com>");
-+MODULE_LICENSE("GPL");
--- /dev/null
+From ef581388c45dbc48f7bbe050e87deb1e3c63a698 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 10 Jul 2012 10:52:02 +0200
+Subject: [PATCH 35/84] bcm63xx_enet: store is_sw in a variable instead of checking the cpuid
+
+Reduces the number of changes needed for making enetsw work on new
+chips.
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 7 +++++--
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 10 ++--------
+ 2 files changed, 7 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -364,7 +364,7 @@ static int bcm_enet_receive_queue(struct
+ }
+
+ /* recycle packet if it's marked as bad */
+- if (!bcm_enet_is_sw(priv) &&
++ if (!priv->enet_is_sw &&
+ unlikely(len_stat & DMADESC_ERR_MASK)) {
+ dev->stats.rx_errors++;
+
+@@ -597,7 +597,7 @@ static int bcm_enet_start_xmit(struct sk
+ }
+
+ /* pad small packets sent on a switch device */
+- if (bcm_enet_is_sw(priv) && skb->len < 64) {
++ if (priv->enet_is_sw && skb->len < 64) {
+ int needed = 64 - skb->len;
+ char *data;
+
+@@ -1700,6 +1700,8 @@ static int __devinit bcm_enet_probe(stru
+ return -ENOMEM;
+ priv = netdev_priv(dev);
+
++ priv->enet_is_sw = false;
++
+ ret = compute_hw_mtu(priv, dev->mtu);
+ if (ret)
+ goto out;
+@@ -2725,6 +2727,7 @@ static int __devinit bcm_enetsw_probe(st
+ memset(priv, 0, sizeof(*priv));
+
+ /* initialize default and fetch platform data */
++ priv->enet_is_sw = true;
+ priv->irq_rx = irq_rx;
+ priv->irq_tx = irq_tx;
+ priv->rx_ring_size = BCMENET_DEF_RX_DESC;
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -353,6 +353,8 @@ struct bcm_enet_priv {
+ /* maximum hardware transmit/receive size */
+ unsigned int hw_mtu;
+
++ bool enet_is_sw;
++
+ /* port mapping for switch devices */
+ int num_ports;
+ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
+@@ -363,12 +365,4 @@ struct bcm_enet_priv {
+ spinlock_t enetsw_mdio_lock;
+ };
+
+-static inline int bcm_enet_is_sw(struct bcm_enet_priv *priv)
+-{
+- if (BCMCPU_IS_6368())
+- return 1;
+- else
+- return 0;
+-}
+-
+ #endif /* ! BCM63XX_ENET_H_ */
--- /dev/null
+From 625894c377ba266c0044675b53f05d65db6355b6 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 8 Jul 2012 13:07:52 +0200
+Subject: [PATCH 38/84] BCM63XX: allow enetsw without tx irq
+
+---
+ arch/mips/bcm63xx/dev-enet.c | 2 ++
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 18 +++++++++++-------
+ 2 files changed, 13 insertions(+), 7 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -236,6 +236,8 @@ bcm63xx_enetsw_register(const struct bcm
+ enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
+ enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
+ enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
++ if (!enetsw_res[2].start)
++ enetsw_res[2].start = -1;
+
+ memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof (*pd));
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2151,10 +2151,12 @@ static int bcm_enetsw_open(struct net_de
+ if (ret)
+ goto out_freeirq;
+
+- ret = request_irq(priv->irq_tx, bcm_enet_isr_dma,
+- IRQF_DISABLED, dev->name, dev);
+- if (ret)
+- goto out_freeirq_rx;
++ if (priv->irq_tx != -1) {
++ ret = request_irq(priv->irq_tx, bcm_enet_isr_dma,
++ IRQF_DISABLED, dev->name, dev);
++ if (ret)
++ goto out_freeirq_rx;
++ }
+
+ /* allocate rx dma ring */
+ size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
+@@ -2376,7 +2378,8 @@ out_free_rx_ring:
+ priv->rx_desc_cpu, priv->rx_desc_dma);
+
+ out_freeirq_tx:
+- free_irq(priv->irq_tx, dev);
++ if (priv->irq_tx != -1)
++ free_irq(priv->irq_tx, dev);
+
+ out_freeirq_rx:
+ free_irq(priv->irq_rx, dev);
+@@ -2433,7 +2436,8 @@ static int bcm_enetsw_stop(struct net_de
+ priv->rx_desc_cpu, priv->rx_desc_dma);
+ dma_free_coherent(kdev, priv->tx_desc_alloc_size,
+ priv->tx_desc_cpu, priv->tx_desc_dma);
+- free_irq(priv->irq_tx, dev);
++ if (priv->irq_tx != -1)
++ free_irq(priv->irq_tx, dev);
+ free_irq(priv->irq_rx, dev);
+
+ return 0;
+@@ -2716,7 +2720,7 @@ static int __devinit bcm_enetsw_probe(st
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq_rx = platform_get_irq(pdev, 0);
+ irq_tx = platform_get_irq(pdev, 1);
+- if (!res_mem || irq_rx < 0 || irq_tx < 0)
++ if (!res_mem || irq_rx < 0)
+ return -ENODEV;
+
+ ret = 0;
+++ /dev/null
-From d135d94b3d1fe599d13e7198d5f502912d694c13 Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Sun, 3 Jul 2011 15:00:38 +0200
-Subject: [PATCH 29/60] MIPS: BCM63XX: Register SPI flash if present
-
-Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
----
- arch/mips/bcm63xx/dev-flash.c | 33 +++++++++++++++++++-
- arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 +
- 2 files changed, 33 insertions(+), 2 deletions(-)
-
---- a/arch/mips/bcm63xx/dev-flash.c
-+++ b/arch/mips/bcm63xx/dev-flash.c
-@@ -16,9 +16,12 @@
- #include <linux/mtd/mtd.h>
- #include <linux/mtd/partitions.h>
- #include <linux/mtd/physmap.h>
-+#include <linux/spi/spi.h>
-+#include <linux/spi/flash.h>
-
- #include <bcm63xx_cpu.h>
- #include <bcm63xx_dev_flash.h>
-+#include <bcm63xx_dev_hsspi.h>
- #include <bcm63xx_regs.h>
- #include <bcm63xx_io.h>
-
-@@ -55,6 +58,21 @@ static struct platform_device mtd_dev =
- },
- };
-
-+static struct flash_platform_data bcm63xx_flash_data = {
-+ .part_probe_types = bcm63xx_part_types,
-+};
-+
-+static struct spi_board_info bcm63xx_spi_flash_info[] = {
-+ {
-+ .bus_num = 0,
-+ .chip_select = 0,
-+ .mode = 0,
-+ .max_speed_hz = 781000,
-+ .modalias = "m25p80",
-+ .platform_data = &bcm63xx_flash_data,
-+ },
-+};
-+
- static int __init bcm63xx_detect_flash_type(void)
- {
- u32 val;
-@@ -62,6 +80,11 @@ static int __init bcm63xx_detect_flash_t
- switch (bcm63xx_get_cpu_id()) {
- case BCM6328_CPU_ID:
- val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
-+ if (val & STRAPBUS_6328_HSSPI_CLK_FAST)
-+ bcm63xx_spi_flash_info[0].max_speed_hz = 33333334;
-+ else
-+ bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
-+
- if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
- return BCM63XX_FLASH_TYPE_SERIAL;
- else
-@@ -79,6 +102,9 @@ static int __init bcm63xx_detect_flash_t
- return BCM63XX_FLASH_TYPE_SERIAL;
- 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;
-@@ -110,8 +136,11 @@ int __init bcm63xx_flash_register(void)
-
- return platform_device_register(&mtd_dev);
- case BCM63XX_FLASH_TYPE_SERIAL:
-- pr_warn("unsupported serial flash detected\n");
-- return -ENODEV;
-+ if (BCMCPU_IS_6328())
-+ bcm63xx_flash_data.max_transfer_len = HSSPI_BUFFER_LEN;
-+
-+ return spi_register_board_info(bcm63xx_spi_flash_info,
-+ ARRAY_SIZE(bcm63xx_spi_flash_info));
- case BCM63XX_FLASH_TYPE_NAND:
- pr_warn("unsupported NAND flash detected\n");
- return -ENODEV;
---- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-@@ -555,6 +555,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
-@@ -1227,6 +1228,7 @@
- #define SERDES_PCIE_EXD_EN (1 << 15)
-
- #define MISC_STRAPBUS_6328_REG 0x240
-+#define STRAPBUS_6328_HSSPI_CLK_FAST (1 << 4)
- #define STRAPBUS_6328_FCVO_SHIFT 7
- #define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
- #define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)
--- /dev/null
+From 85e4551e033df7cb043e93042661fc1e58799efa Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 8 Jul 2012 15:36:23 +0200
+Subject: [PATCH 52/84] BCM63XX: use port id for deciding external phy
+
+Ports 0-3 always use the internal phy, while 4+ always need an external
+phy to work.
+---
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 3 ++-
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 15 ++++++++-------
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 5 +++++
+ 3 files changed, 15 insertions(+), 8 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+@@ -45,9 +45,10 @@ struct bcm63xx_enet_platform_data {
+ #define ENETSW_MAX_PORT 6
+ #define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
+
++#define ENETSW_RGMII_PORT0 4
++
+ struct bcm63xx_enetsw_port {
+ int used;
+- int external_phy;
+ int phy_id;
+
+ int bypass_link;
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2046,6 +2046,7 @@ static void swphy_poll_timer(unsigned lo
+ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm63xx_enetsw_port *port;
+ int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
++ int external_phy = bcm_enet_port_is_rgmii(i);
+ u8 override;
+
+ port = &priv->used_ports[i];
+@@ -2057,7 +2058,7 @@ static void swphy_poll_timer(unsigned lo
+
+ /* dummy read to clear */
+ for (j = 0; j < 2; j++)
+- val = bcmenet_sw_mdio_read(priv, port->external_phy,
++ val = bcmenet_sw_mdio_read(priv, external_phy,
+ port->phy_id, MII_BMSR);
+
+ if (val == 0xffff)
+@@ -2081,14 +2082,14 @@ static void swphy_poll_timer(unsigned lo
+ continue;
+ }
+
+- advertise = bcmenet_sw_mdio_read(priv, port->external_phy,
++ advertise = bcmenet_sw_mdio_read(priv, external_phy,
+ port->phy_id, MII_ADVERTISE);
+
+- lpa = bcmenet_sw_mdio_read(priv, port->external_phy,
+- port->phy_id, MII_LPA);
++ lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
++ MII_LPA);
+
+- lpa2 = bcmenet_sw_mdio_read(priv, port->external_phy,
+- port->phy_id, MII_STAT1000);
++ lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
++ MII_STAT1000);
+
+ /* figure out media and duplex from advertise and LPA values */
+ media = mii_nway_result(lpa & advertise);
+@@ -2457,7 +2458,7 @@ static int bcm_enetsw_phy_is_external(st
+ if (!priv->used_ports[i].used)
+ continue;
+ if (priv->used_ports[i].phy_id == phy_id)
+- return priv->used_ports[i].external_phy;
++ return bcm_enet_port_is_rgmii(i);
+ }
+
+ printk_once(KERN_WARNING "bcm63xx_enet: could not find a used port "
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -365,4 +365,9 @@ struct bcm_enet_priv {
+ spinlock_t enetsw_mdio_lock;
+ };
+
++static inline int bcm_enet_port_is_rgmii(int portid)
++{
++ return portid >= ENETSW_RGMII_PORT0;
++}
++
+ #endif /* ! BCM63XX_ENET_H_ */
+++ /dev/null
-From 5b753c1d01c6af23d7d37d37d9de30da8a971084 Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Sat, 12 May 2012 22:51:08 +0200
-Subject: [PATCH 60/79] MIPS: BCM63XX: move nvram related functions into their
- own file
-
-Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
----
- arch/mips/bcm63xx/Makefile | 6 +-
- arch/mips/bcm63xx/boards/board_bcm963xx.c | 74 +++--------------
- arch/mips/bcm63xx/nvram.c | 84 ++++++++++++++++++++
- arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h | 34 ++++++++
- .../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 17 ----
- 5 files changed, 134 insertions(+), 81 deletions(-)
- create mode 100644 arch/mips/bcm63xx/nvram.c
- create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
-
---- a/arch/mips/bcm63xx/Makefile
-+++ b/arch/mips/bcm63xx/Makefile
-@@ -1,6 +1,6 @@
--obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
-- dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o dev-pcmcia.o \
-- dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
-+obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o setup.o \
-+ timer.o dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o \
-+ dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
- dev-usb-ohci.o dev-wdt.o
- obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-
---- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
-+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -21,6 +21,7 @@
- #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>
-@@ -41,8 +42,6 @@
- #define CFE_OFFSET_64K 0x10000
- #define CFE_OFFSET_128K 0x20000
-
--static struct bcm963xx_nvram nvram;
--static unsigned int mac_addr_used;
- static struct board_info board;
-
- /*
-@@ -696,50 +695,16 @@ const char *board_get_name(void)
- return board.name;
- }
-
--/*
-- * register & return a new board mac address
-- */
--static int board_get_mac_address(u8 *mac)
--{
-- u8 *p;
-- int count;
--
-- if (mac_addr_used >= nvram.mac_addr_count) {
-- printk(KERN_ERR PFX "not enough mac address\n");
-- return -ENODEV;
-- }
--
-- memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
-- p = mac + ETH_ALEN - 1;
-- count = mac_addr_used;
--
-- while (count--) {
-- do {
-- (*p)++;
-- if (*p != 0)
-- break;
-- p--;
-- } while (p != mac);
-- }
--
-- if (p == mac) {
-- printk(KERN_ERR PFX "unable to fetch mac address\n");
-- return -ENODEV;
-- }
--
-- mac_addr_used++;
-- return 0;
--}
--
- static void __init boardid_fixup(u8 *boot_addr)
- {
- struct bcm_tag *tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_64K);
-+ char *board_name = (char *)bcm63xx_nvram_get_name();
-
- /* check if bcm_tag is at 64k offset */
-- if (strncmp(nvram.name, tag->boardid, BOARDID_LEN) != 0) {
-+ if (strncmp(board_name, tag->boardid, BOARDID_LEN) != 0) {
- /* else try 128k */
- tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_128K);
-- if (strncmp(nvram.name, tag->boardid, BOARDID_LEN) != 0) {
-+ if (strncmp(board_name, tag->boardid, BOARDID_LEN) != 0) {
- /* No tag found */
- printk(KERN_DEBUG "No bcm_tag found!\n");
- return;
-@@ -749,9 +714,9 @@ static void __init boardid_fixup(u8 *boo
- if (tag->information1[0] != '+')
- return;
-
-- strncpy(nvram.name, &tag->information1[1], BOARDID_LEN);
-+ strncpy(board_name, &tag->information1[1], BOARDID_LEN);
-
-- printk(KERN_INFO "Overriding boardid with '%s'\n", nvram.name);
-+ printk(KERN_INFO "Overriding boardid with '%s'\n", board_name);
- }
-
- /*
-@@ -759,9 +724,10 @@ static void __init boardid_fixup(u8 *boo
- */
- void __init board_prom_init(void)
- {
-- unsigned int check_len, i;
-- u8 *boot_addr, *cfe, *p;
-+ unsigned int i;
-+ u8 *boot_addr, *cfe;
- char cfe_version[32];
-+ char *board_name;
- u32 val;
-
- /* read base address of boot chip select (0)
-@@ -786,32 +752,19 @@ void __init board_prom_init(void)
- strcpy(cfe_version, "unknown");
- printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
-
-- /* extract nvram data */
-- memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
--
-- /* check checksum before using data */
-- if (nvram.version <= 4)
-- check_len = offsetof(struct bcm963xx_nvram, checksum_old);
-- else
-- check_len = sizeof(nvram);
-- val = 0;
-- p = (u8 *)&nvram;
-- while (check_len--)
-- val += *p;
-- if (val) {
-- printk(KERN_ERR PFX "invalid nvram checksum\n");
-+ if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET))
- return;
-- }
-
- if (strcmp(cfe_version, "unknown") != 0) {
- /* cfe present */
- boardid_fixup(boot_addr);
- }
-
-+ board_name = bcm63xx_nvram_get_name();
- /* find board by name */
- for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
-- if (strncmp(nvram.name, bcm963xx_boards[i]->name,
-- sizeof(nvram.name)))
-+ if (strncmp(board_name, bcm963xx_boards[i]->name,
-+ BCM63XX_NVRAM_NAMELEN))
- continue;
- /* copy, board desc array is marked initdata */
- memcpy(&board, bcm963xx_boards[i], sizeof(board));
-@@ -821,7 +774,7 @@ void __init board_prom_init(void)
- /* bail out if board is not found, will complain later */
- if (!board.name[0]) {
- char name[17];
-- memcpy(name, nvram.name, 16);
-+ memcpy(name, board_name, 16);
- name[16] = 0;
- printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
- name);
-@@ -914,15 +867,15 @@ int __init board_register_devices(void)
- bcm63xx_pcmcia_register();
-
- if (board.has_enet0 &&
-- !board_get_mac_address(board.enet0.mac_addr))
-+ !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
- bcm63xx_enet_register(0, &board.enet0);
-
- if (board.has_enet1 &&
-- !board_get_mac_address(board.enet1.mac_addr))
-+ !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
- bcm63xx_enet_register(1, &board.enet1);
-
- if (board.has_enetsw &&
-- !board_get_mac_address(board.enetsw.mac_addr))
-+ !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
- bcm63xx_enetsw_register(&board.enetsw);
-
- if (board.has_ehci0)
-@@ -938,7 +891,7 @@ int __init board_register_devices(void)
- * do this after registering enet devices
- */
- #ifdef CONFIG_SSB_PCIHOST
-- if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
-+ if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
- memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- if (ssb_arch_register_fallback_sprom(
---- /dev/null
-+++ b/arch/mips/bcm63xx/nvram.c
-@@ -0,0 +1,84 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
-+ */
-+
-+#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
-+
-+#include <linux/init.h>
-+#include <linux/export.h>
-+#include <linux/kernel.h>
-+
-+#include <bcm63xx_nvram.h>
-+
-+static struct bcm963xx_nvram nvram;
-+static int mac_addr_used;
-+
-+int __init bcm63xx_nvram_init(void *addr)
-+{
-+ unsigned int check_len;
-+ u8 *p;
-+ u32 val;
-+
-+ /* extract nvram data */
-+ memcpy(&nvram, addr, sizeof(nvram));
-+
-+ /* check checksum before using data */
-+ if (nvram.version <= 4)
-+ check_len = offsetof(struct bcm963xx_nvram, checksum_old);
-+ else
-+ check_len = sizeof(nvram);
-+ val = 0;
-+ p = (u8 *)&nvram;
-+
-+ while (check_len--)
-+ val += *p;
-+ if (val) {
-+ pr_err("invalid nvram checksum\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+u8 *bcm63xx_nvram_get_name(void)
-+{
-+ return nvram.name;
-+}
-+EXPORT_SYMBOL(bcm63xx_nvram_get_name);
-+
-+int bcm63xx_nvram_get_mac_address(u8 *mac)
-+{
-+ u8 *p;
-+ int count;
-+
-+ if (mac_addr_used >= nvram.mac_addr_count) {
-+ pr_err("not enough mac address\n");
-+ return -ENODEV;
-+ }
-+
-+ memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
-+ p = mac + ETH_ALEN - 1;
-+ count = mac_addr_used;
-+
-+ while (count--) {
-+ do {
-+ (*p)++;
-+ if (*p != 0)
-+ break;
-+ p--;
-+ } while (p != mac);
-+ }
-+
-+ if (p == mac) {
-+ pr_err("unable to fetch mac address\n");
-+ return -ENODEV;
-+ }
-+
-+ mac_addr_used++;
-+ return 0;
-+}
-+EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
---- /dev/null
-+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
-@@ -0,0 +1,34 @@
-+#ifndef BCM63XX_NVRAM_H
-+#define BCM63XX_NVRAM_H
-+
-+#include <linux/if_ether.h>
-+
-+#define BCM63XX_NVRAM_NAMELEN 16
-+
-+/*
-+ * nvram structure
-+ */
-+struct bcm963xx_nvram {
-+ u32 version;
-+ u8 reserved1[256];
-+ u8 name[BCM63XX_NVRAM_NAMELEN];
-+ u32 main_tp_number;
-+ u32 psi_size;
-+ u32 mac_addr_count;
-+ u8 mac_addr_base[ETH_ALEN];
-+ u8 reserved2[2];
-+ u32 checksum_old;
-+ u8 reserved3[720];
-+ u32 checksum_high;
-+};
-+
-+int __init bcm63xx_nvram_init(void *);
-+
-+u8 *bcm63xx_nvram_get_name(void);
-+
-+/*
-+ * register & return a new board mac address
-+ */
-+int bcm63xx_nvram_get_mac_address(u8 *mac);
-+
-+#endif /* BCM63XX_NVRAM_H */
---- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
-+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
-@@ -15,23 +15,6 @@
- #define BCM963XX_NVRAM_OFFSET 0x580
-
- /*
-- * nvram structure
-- */
--struct bcm963xx_nvram {
-- u32 version;
-- u8 reserved1[256];
-- u8 name[16];
-- u32 main_tp_number;
-- u32 psi_size;
-- u32 mac_addr_count;
-- u8 mac_addr_base[6];
-- u8 reserved2[2];
-- u32 checksum_old;
-- u8 reserved3[720];
-- u32 checksum_high;
--};
--
--/*
- * board definition
- */
- struct board_info {
+++ /dev/null
-From ffbeb183bf0e9e12fd607c5352f48420c32f588f Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Sat, 12 May 2012 23:04:17 +0200
-Subject: [PATCH 61/79] MIPS: BCM63XX: export PSI size from nvram
-
-Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
----
- arch/mips/bcm63xx/nvram.c | 11 +++++++++++
- arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h | 2 ++
- 2 files changed, 13 insertions(+)
-
---- a/arch/mips/bcm63xx/nvram.c
-+++ b/arch/mips/bcm63xx/nvram.c
-@@ -14,6 +14,8 @@
-
- #include <bcm63xx_nvram.h>
-
-+#define BCM63XX_DEFAULT_PSI_SIZE 64
-+
- static struct bcm963xx_nvram nvram;
- static int mac_addr_used;
-
-@@ -82,3 +84,12 @@ int bcm63xx_nvram_get_mac_address(u8 *ma
- return 0;
- }
- EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
-+
-+int bcm63xx_nvram_get_psi_size(void)
-+{
-+ if (nvram.psi_size > 0)
-+ return nvram.psi_size;
-+
-+ return BCM63XX_DEFAULT_PSI_SIZE;
-+}
-+EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);
---- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
-+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
-@@ -31,4 +31,6 @@ u8 *bcm63xx_nvram_get_name(void);
- */
- int bcm63xx_nvram_get_mac_address(u8 *mac);
-
-+int bcm63xx_nvram_get_psi_size(void);
-+
- #endif /* BCM63XX_NVRAM_H */
--- /dev/null
+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
+@@ -779,6 +779,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
+@@ -2222,6 +2222,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;
+++ /dev/null
-From 658afad639a9456e1bb6fe5bba0032f3c0c3f699 Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Tue, 1 May 2012 14:10:39 +0200
-Subject: [PATCH 62/79] MTD: bcm63xxpart: use nvram for PSI size
-
----
- drivers/mtd/bcm63xxpart.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/drivers/mtd/bcm63xxpart.c
-+++ b/drivers/mtd/bcm63xxpart.c
-@@ -32,6 +32,7 @@
- #include <linux/mtd/mtd.h>
- #include <linux/mtd/partitions.h>
-
-+#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
- #include <asm/mach-bcm63xx/bcm963xx_tag.h>
- #include <asm/mach-bcm63xx/board_bcm963xx.h>
-
-@@ -90,7 +91,8 @@ static int bcm63xx_parse_cfe_partitions(
- BCM63XX_CFE_BLOCK_SIZE);
-
- cfelen = cfe_erasesize;
-- nvramlen = cfe_erasesize;
-+ nvramlen = bcm63xx_nvram_get_psi_size() * 1024;
-+ nvramlen = roundup(nvramlen, cfe_erasesize);
-
- /* Allocate memory for buffer */
- buf = vmalloc(sizeof(struct bcm_tag));
--- /dev/null
+From 382a0b0dc4cbd0e0fbfd6c2d132e972c3d1245b0 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 13 Nov 2011 14:59:37 +0100
+Subject: [PATCH 39/84] bcm63xx_enet: fix lockup on BCM6328
+
+BCM6328 locks up on a maxburst size of 16, reduce it to 8 for BCM6328 and
+BCM6368.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 13 +++++++------
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 4 ++++
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -261,7 +261,6 @@ static int bcm_enet_refill_rx(struct net
+ if (!skb)
+ break;
+ priv->rx_skb[desc_idx] = skb;
+-
+ p = dma_map_single(&priv->pdev->dev, skb->data,
+ priv->rx_skb_size,
+ DMA_FROM_DEVICE);
+@@ -995,9 +994,9 @@ static int bcm_enet_open(struct net_devi
+ enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG);
+
+ /* set dma maximum burst len */
+- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ enet_dmac_writel(priv, priv->dma_maxburst,
+ ENETDMAC_MAXBURST_REG(priv->rx_chan));
+- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ enet_dmac_writel(priv, priv->dma_maxburst,
+ ENETDMAC_MAXBURST_REG(priv->tx_chan));
+
+ /* set correct transmit fifo watermark */
+@@ -1593,7 +1592,7 @@ static int compute_hw_mtu(struct bcm_ene
+ * it's appended
+ */
+ priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
+- BCMENET_DMA_MAXBURST * 4);
++ priv->dma_maxburst * 4);
+ return 0;
+ }
+
+@@ -1701,6 +1700,7 @@ static int __devinit bcm_enet_probe(stru
+ priv = netdev_priv(dev);
+
+ priv->enet_is_sw = false;
++ priv->dma_maxburst = BCMENET_DMA_MAXBURST;
+
+ ret = compute_hw_mtu(priv, dev->mtu);
+ if (ret)
+@@ -2282,9 +2282,9 @@ static int bcm_enetsw_open(struct net_de
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
+
+ /* set dma maximum burst len */
+- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ enet_dmac_writel(priv, priv->dma_maxburst,
+ ENETDMAC_MAXBURST_REG(priv->rx_chan));
+- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ enet_dmac_writel(priv, priv->dma_maxburst,
+ ENETDMAC_MAXBURST_REG(priv->tx_chan));
+
+ /* set flow control low/high threshold to 1/3 / 2/3 */
+@@ -2749,6 +2749,7 @@ static int __devinit bcm_enetsw_probe(st
+ priv->irq_tx = irq_tx;
+ priv->rx_ring_size = BCMENET_DEF_RX_DESC;
+ priv->tx_ring_size = BCMENET_DEF_TX_DESC;
++ priv->dma_maxburst = BCMENETSW_DMA_MAXBURST;
+
+ pd = pdev->dev.platform_data;
+ if (pd) {
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -17,6 +17,7 @@
+
+ /* maximum burst len for dma (4 bytes unit) */
+ #define BCMENET_DMA_MAXBURST 16
++#define BCMENETSW_DMA_MAXBURST 8
+
+ /* tx transmit threshold (4 bytes unit), fifo is 256 bytes, the value
+ * must be low enough so that a DMA transfer of above burst length can
+@@ -280,6 +281,9 @@ struct bcm_enet_priv {
+ /* number of dma desc in tx ring */
+ int tx_ring_size;
+
++ /* maximum dma burst size */
++ int dma_maxburst;
++
+ /* cpu view of rx dma ring */
+ struct bcm_enet_desc *tx_desc_cpu;
+
--- /dev/null
+From f1c1bfa89cdac76a215d0e21161da9f8f8373437 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 14 Jun 2011 21:14:39 +0200
+Subject: [PATCH 40/84] MIPS: BCM63XX: add support for BCM6328 in bcm_enetsw
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/clk.c | 34 ++++++++++++++-----
+ arch/mips/bcm63xx/dev-enet.c | 9 +++--
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 1 +
+ 3 files changed, 32 insertions(+), 12 deletions(-)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -118,21 +118,37 @@ static struct clk clk_ephy = {
+ */
+ static void enetsw_set(struct clk *clk, int enable)
+ {
+- if (!BCMCPU_IS_6368())
++ u32 mask;
++
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
+ return;
+- bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
+- CKCTL_6368_SWPKT_USB_EN |
+- CKCTL_6368_SWPKT_SAR_EN, enable);
++
++ if (BCMCPU_IS_6328())
++ mask = CKCTL_6328_ROBOSW_EN;
++ else
++ mask = CKCTL_6368_ROBOSW_EN | CKCTL_6368_SWPKT_USB_EN |
++ CKCTL_6368_SWPKT_SAR_EN;
++
++ bcm_hwclock_set(mask, enable);
+ if (enable) {
++ u32 reg;
+ u32 val;
+
++ if (BCMCPU_IS_6328()) {
++ reg = PERF_SOFTRESET_6328_REG;
++ mask = SOFTRESET_6328_ENETSW_MASK;
++ } else {
++ reg = PERF_SOFTRESET_6368_REG;
++ mask = SOFTRESET_6368_ENETSW_MASK;
++ }
++
+ /* reset switch core afer clock change */
+- val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
+- val &= ~SOFTRESET_6368_ENETSW_MASK;
+- bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
++ val = bcm_perf_readl(reg);
++ val &= ~mask;
++ bcm_perf_writel(val, reg);
+ msleep(10);
+- val |= SOFTRESET_6368_ENETSW_MASK;
+- bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
++ val |= mask;
++ bcm_perf_writel(val, reg);
+ msleep(10);
+ }
+ }
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -141,7 +141,7 @@ static int __init register_shared(void)
+ shared_res[0].end = shared_res[0].start;
+ shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
+
+- if (BCMCPU_IS_6368())
++ if (BCMCPU_IS_6328() || BCMCPU_IS_6368())
+ chan_count = 32;
+ else
+ chan_count = 16;
+@@ -224,7 +224,7 @@ bcm63xx_enetsw_register(const struct bcm
+ {
+ int ret;
+
+- if (!BCMCPU_IS_6368())
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
+ return -ENODEV;
+
+ ret = register_shared();
+@@ -241,7 +241,10 @@ bcm63xx_enetsw_register(const struct bcm
+
+ memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof (*pd));
+
+- enetsw_pd.num_ports = ENETSW_PORTS_6368;
++ if (BCMCPU_IS_6328())
++ enetsw_pd.num_ports = ENETSW_PORTS_6328;
++ else if (BCMCPU_IS_6368())
++ enetsw_pd.num_ports = ENETSW_PORTS_6368;
+
+ ret = platform_device_register(&bcm63xx_enetsw_device);
+ if (ret)
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+@@ -43,6 +43,7 @@ struct bcm63xx_enet_platform_data {
+ * on board ethernet switch platform data
+ */
+ #define ENETSW_MAX_PORT 6
++#define ENETSW_PORTS_6328 5 /* 4 FE PHY + 1 RGMII */
+ #define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
+
+ #define ENETSW_RGMII_PORT0 4
+++ /dev/null
-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
-@@ -84,6 +84,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 **probe_type;
- const char **part_types;
- int err = 0;
-@@ -173,8 +174,9 @@ static int physmap_flash_probe(struct pl
- goto err_out;
-
- 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, 0,
-+ mtd_device_parse_register(info->cmtd, part_types, pp_data,
- physmap_data->parts, physmap_data->nr_parts);
- return 0;
-
---- a/include/linux/mtd/physmap.h
-+++ b/include/linux/mtd/physmap.h
-@@ -32,6 +32,7 @@ struct physmap_flash_data {
- char *probe_type;
- struct mtd_partition *parts;
- const char **part_probe_types;
-+ struct mtd_part_parser_data *pp_data;
- };
-
- #endif /* __LINUX_MTD_PHYSMAP__ */
+++ /dev/null
-From 5131195413b62df73dfd394fea272830ea8c4e1a 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 67/80] BCM63XX: allow providing fixup data in board data
-
----
- arch/mips/bcm63xx/boards/board_bcm963xx.c | 10 +++++++++-
- arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 10 ++++++++++
- 2 files changed, 19 insertions(+), 1 deletion(-)
-
---- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
-+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -33,6 +33,7 @@
- #include <bcm63xx_dev_usb_ehci.h>
- #include <board_bcm963xx.h>
- #include <bcm_tag.h>
-+#include <pci_ath9k_fixup.h>
-
- #define PFX "board_bcm963xx: "
-
-@@ -856,6 +857,7 @@ int __init board_register_devices(void)
- {
- int button_count = 0;
- int led_count = 0;
-+ int i;
-
- if (board.has_uart0)
- bcm63xx_uart_register(0);
-@@ -891,7 +893,8 @@ int __init board_register_devices(void)
- * do this after registering enet devices
- */
- #ifdef CONFIG_SSB_PCIHOST
-- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
-+ if (!board.has_caldata &&
-+ !bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
- memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- if (ssb_arch_register_fallback_sprom(
-@@ -931,5 +934,9 @@ int __init board_register_devices(void)
- platform_device_register(&bcm63xx_gpio_keys_device);
- }
-
-+ /* register any fixups */
-+ for (i = 0; i < board.has_caldata; i++)
-+ pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset);
-+
- return 0;
- }
---- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
-+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
-@@ -7,6 +7,7 @@
- #include <linux/leds.h>
- #include <bcm63xx_dev_enet.h>
- #include <bcm63xx_dev_dsp.h>
-+#include <pci_ath9k_fixup.h>
-
- /*
- * flash mapping
-@@ -14,6 +15,11 @@
- #define BCM963XX_CFE_VERSION_OFFSET 0x570
- #define BCM963XX_NVRAM_OFFSET 0x580
-
-+struct ath9k_caldata {
-+ unsigned int slot;
-+ u32 caldata_offset;
-+};
-+
- /*
- * board definition
- */
-@@ -32,6 +38,10 @@ struct board_info {
- unsigned int has_dsp:1;
- unsigned int has_uart0:1;
- unsigned int has_uart1:1;
-+ unsigned int has_caldata:2;
-+
-+ /* wifi calibration data config */
-+ struct ath9k_caldata caldata[2];
-
- /* ethernet config */
- struct bcm63xx_enet_platform_data enet0;
--- /dev/null
+From 56be5a2d7e08faa7bb306faaf352ac4e6ac52c01 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 Nov 2011 12:18:26 +0100
+Subject: [PATCH 26/60] MIPS: BCM63XX: add HS SPI platform device and register it
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/Makefile | 5 +-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +
+ arch/mips/bcm63xx/dev-hsspi.c | 57 ++++++++++++++++++++
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 20 +++++++
+ 4 files changed, 82 insertions(+), 2 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/dev-hsspi.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,6 +1,7 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+- dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
+- dev-spi.o dev-uart.o dev-usb-ehci.o dev-usb-ohci.o dev-wdt.o
++ dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o dev-pcmcia.o \
++ dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
++ dev-usb-ohci.o dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -25,6 +25,7 @@
+ #include <bcm63xx_dev_enet.h>
+ #include <bcm63xx_dev_dsp.h>
+ #include <bcm63xx_dev_flash.h>
++#include <bcm63xx_dev_hsspi.h>
+ #include <bcm63xx_dev_pcmcia.h>
+ #include <bcm63xx_dev_spi.h>
+ #include <bcm63xx_dev_usb_ohci.h>
+@@ -945,6 +946,7 @@ int __init board_register_devices(void)
+ pr_err(PFX "failed to register fallback SPROM\n");
+ }
+ #endif
++ bcm63xx_hsspi_register();
+
+ bcm63xx_spi_register();
+
+--- /dev/null
++++ b/arch/mips/bcm63xx/dev-hsspi.c
+@@ -0,0 +1,57 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_dev_hsspi.h>
++#include <bcm63xx_regs.h>
++
++static struct resource spi_resources[] = {
++ {
++ .start = -1, /* filled at runtime */
++ .end = -1, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = -1, /* filled at runtime */
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct bcm63xx_hsspi_pdata spi_pdata = {
++ .bus_num = 0,
++};
++
++static struct platform_device bcm63xx_hsspi_device = {
++ .name = "bcm63xx-hsspi",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(spi_resources),
++ .resource = spi_resources,
++ .dev = {
++ .platform_data = &spi_pdata,
++ },
++};
++
++int __init bcm63xx_hsspi_register(void)
++{
++
++ if (!BCMCPU_IS_6328())
++ return -ENODEV;
++
++ spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
++ spi_resources[0].end = spi_resources[0].start;
++ spi_resources[0].end += RSET_HSSPI_SIZE - 1;
++ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI);
++
++ spi_pdata.speed_hz = HSSPI_PLL_HZ_6328;
++
++ return platform_device_register(&bcm63xx_hsspi_device);
++}
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+@@ -0,0 +1,20 @@
++#ifndef BCM63XX_DEV_HSSPI_H
++#define BCM63XX_DEV_HSSPI_H
++
++#include <linux/types.h>
++#include <bcm63xx_io.h>
++#include <bcm63xx_regs.h>
++
++int __init bcm63xx_hsspi_register(void);
++
++struct bcm63xx_hsspi_pdata {
++ int bus_num;
++ u32 speed_hz;
++};
++
++#define bcm_hsspi_readl(o) bcm_rset_readl(RSET_HSSPI, (o))
++#define bcm_hsspi_writel(v, o) bcm_rset_writel(RSET_HSSPI, (v), (o))
++
++#define HSSPI_PLL_HZ_6328 133333333
++
++#endif /* BCM63XX_DEV_HSSPI_H */
+++ /dev/null
-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
-@@ -886,6 +886,9 @@ static int __devinit m25p_probe(struct s
- dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
- }
-
-+ if (data && data->pp_data)
-+ memcpy(&ppdata, data->pp_data, sizeof(ppdata));
-+
- info = (void *)id->driver_data;
-
- if (info->jedec_id) {
---- a/include/linux/spi/flash.h
-+++ b/include/linux/spi/flash.h
-@@ -12,6 +12,7 @@ struct mtd_part_parser_data;
- * with chips that can't be queried for JEDEC or other IDs
- * @part_probe_types: optional list of MTD parser names to use for
- * partitioning
-+ * @pp_data: optional partition parser data.
- *
- * @max_transfer_len: option maximum read/write length limitation for
- * SPI controllers not able to transfer any length commands.
-@@ -30,6 +31,7 @@ struct flash_platform_data {
- char *type;
-
- const char **part_probe_types;
-+ struct mtd_part_parser_data *pp_data;
-
- unsigned int max_transfer_len;
- /* we'll likely add more ... use JEDEC IDs, etc */
--- /dev/null
+From 4b27423676485d05bcd6fc6f3809164fb8f9d22d Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 Nov 2011 12:19:55 +0100
+Subject: [PATCH 30/60] SPI: MIPS: BCM63XX: Add HSSPI driver
+
+Add a driver for the High Speed SPI controller found on newer BCM63XX SoCs.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 2 +
+ drivers/spi/Kconfig | 7 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-bcm63xx-hsspi.c | 427 ++++++++++++++++++++
+ 4 files changed, 437 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/spi/spi-bcm63xx-hsspi.c
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+@@ -17,4 +17,6 @@ struct bcm63xx_hsspi_pdata {
+
+ #define HSSPI_PLL_HZ_6328 133333333
+
++#define HSSPI_BUFFER_LEN 512
++
+ #endif /* BCM63XX_DEV_HSSPI_H */
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -100,6 +100,13 @@ config SPI_BCM63XX
+ help
+ Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
+
++config SPI_BCM63XX_HSSPI
++ tristate "Broadcom BCM63XX HS SPI controller driver"
++ depends on BCM63XX
++ help
++ This enables support for the High Speed SPI controller present on
++ newer Broadcom BCM63XX SoCs.
++
+ config SPI_BITBANG
+ tristate "Utilities for Bitbanging SPI masters"
+ help
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
+ obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
+ obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
+ obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
++obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o
+ obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o
+ obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
+ obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
+--- /dev/null
++++ b/drivers/spi/spi-bcm63xx-hsspi.c
+@@ -0,0 +1,427 @@
++/*
++ * Broadcom BCM63XX High Speed SPI Controller driver
++ *
++ * Copyright 2000-2010 Broadcom Corporation
++ * Copyright 2012 Jonas Gorski <jonas.gorski@gmail.com>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/spi/spi.h>
++#include <linux/workqueue.h>
++
++#include <bcm63xx_regs.h>
++#include <bcm63xx_dev_hsspi.h>
++
++#define HSSPI_OP_CODE_SHIFT 13
++#define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT)
++#define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT)
++#define HSSPI_OP_WRITE (2 << HSSPI_OP_CODE_SHIFT)
++#define HSSPI_OP_READ (3 << HSSPI_OP_CODE_SHIFT)
++
++#define HSSPI_MAX_PREPEND_LEN 15
++
++#define HSSPI_MAX_SYNC_CLOCK 30000000
++
++struct bcm63xx_hsspi {
++ struct completion done;
++ struct spi_transfer *curr_trans;
++
++ struct platform_device *pdev;
++ struct clk *clk;
++ void __iomem *regs;
++ u8 __iomem *fifo;
++
++ u32 speed_hz;
++ int irq;
++};
++
++static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, int hz,
++ int profile)
++{
++ u32 reg;
++
++ reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
++ bcm_hsspi_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
++ HSSPI_PROFILE_CLK_CTRL_REG(profile));
++
++ reg = bcm_hsspi_readl(HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
++ if (hz > HSSPI_MAX_SYNC_CLOCK)
++ reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
++ else
++ reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
++ bcm_hsspi_writel(reg, HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
++}
++
++static int bcm63xx_hsspi_do_txrx(struct spi_device *spi,
++ struct spi_transfer *t1,
++ struct spi_transfer *t2)
++{
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
++ u8 chip_select = spi->chip_select;
++ u16 opcode = 0;
++ int len, prepend_size = 0;
++
++ init_completion(&bs->done);
++
++ bs->curr_trans = t2 ? t2 : t1;
++ bcm63xx_hsspi_set_clk(bs, bs->curr_trans->speed_hz, chip_select);
++
++ if (t2 && !t2->tx_buf)
++ prepend_size = t1->len;
++
++ bcm_hsspi_writel(prepend_size << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
++ 2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
++ 2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
++ HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
++
++ if (t1->rx_buf && t1->tx_buf)
++ opcode = HSSPI_OP_READ_WRITE;
++ else if (t1->rx_buf || (t2 && t2->rx_buf))
++ opcode = HSSPI_OP_READ;
++ else if (t1->tx_buf)
++ opcode = HSSPI_OP_WRITE;
++
++ if (opcode == HSSPI_OP_READ && t2)
++ len = t2->len;
++ else
++ len = t1->len;
++
++ if (t1->tx_buf) {
++ memcpy_toio(bs->fifo + 2, t1->tx_buf, t1->len);
++ if (t2 && t2->tx_buf) {
++ memcpy_toio(bs->fifo + 2 + t1->len,
++ t2->tx_buf, t2->len);
++ len += t2->len;
++ }
++ }
++
++ opcode |= len;
++ memcpy_toio(bs->fifo, &opcode, sizeof(opcode));
++
++ /* enable interrupt */
++ bcm_hsspi_writel(HSSPI_PING0_CMD_DONE, HSSPI_INT_MASK_REG);
++
++ /* start the transfer */
++ bcm_hsspi_writel(chip_select << PINGPONG_CMD_SS_SHIFT |
++ chip_select << PINGPONG_CMD_PROFILE_SHIFT |
++ PINGPONG_COMMAND_START_NOW,
++ HSSPI_PINGPONG_COMMAND_REG(0));
++
++ if (wait_for_completion_timeout(&bs->done, HZ) == 0) {
++ dev_err(&bs->pdev->dev, "transfer timed out!\n");
++ return -ETIMEDOUT;
++ }
++
++ return t1->len + (t2 ? t2->len : 0);
++}
++
++static int bcm63xx_hsspi_setup(struct spi_device *spi)
++{
++ u32 reg;
++
++ if (spi->bits_per_word != 8)
++ return -EINVAL;
++
++ if (spi->max_speed_hz == 0)
++ return -EINVAL;
++
++ reg = bcm_hsspi_readl(HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
++ reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
++ if (spi->mode & SPI_CPHA)
++ reg |= SIGNAL_CTRL_LAUNCH_RISING;
++ else
++ reg |= SIGNAL_CTRL_LATCH_RISING;
++ bcm_hsspi_writel(reg, HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
++
++ return 0;
++}
++
++static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
++ struct spi_message *msg)
++{
++ struct spi_transfer *t, *prev = NULL;
++ struct spi_device *spi = msg->spi;
++ u32 reg;
++ int ret = -EINVAL;
++ int len = 0;
++
++ /* check if we are able to make these transfers */
++ list_for_each_entry(t, &msg->transfers, transfer_list) {
++ if (!t->tx_buf && !t->rx_buf)
++ goto out;
++
++ if (t->speed_hz == 0)
++ t->speed_hz = spi->max_speed_hz;
++
++ if (t->speed_hz > spi->max_speed_hz)
++ goto out;
++
++ if (t->len > HSSPI_BUFFER_LEN)
++ goto out;
++
++ /*
++ * This controller does not support keeping the chip select
++ * active between transfers.
++ * This logic currently supports combining:
++ * write then read with no cs_change (e.g. m25p80 RDSR)
++ * write then write with no cs_change (e.g. m25p80 PP)
++ */
++ if (prev && prev->tx_buf && !prev->cs_change && !t->cs_change) {
++ /*
++ * reject if we have to combine two tx transfers and
++ * their combined length is bigger than the buffer
++ */
++ if (prev->tx_buf && t->tx_buf &&
++ (prev->len + t->len) > HSSPI_BUFFER_LEN)
++ goto out;
++ /*
++ * reject if we need write more than 15 bytes in read
++ * then write.
++ */
++ if (prev->tx_buf && t->rx_buf &&
++ prev->len > HSSPI_MAX_PREPEND_LEN)
++ goto out;
++ }
++
++ }
++
++ /* setup clock polarity */
++ reg = bcm_hsspi_readl(HSSPI_GLOBAL_CTRL_REG);
++ reg &= ~GLOBAL_CTRL_CLK_POLARITY;
++ if (spi->mode & SPI_CPOL)
++ reg |= GLOBAL_CTRL_CLK_POLARITY;
++ bcm_hsspi_writel(reg, HSSPI_GLOBAL_CTRL_REG);
++
++ list_for_each_entry(t, &msg->transfers, transfer_list) {
++ if (prev && prev->tx_buf && !prev->cs_change && !t->cs_change) {
++ /* combine write with following transfer */
++ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, t);
++ if (ret < 0)
++ goto out;
++
++ len += ret;
++ prev = NULL;
++ continue;
++ }
++
++ /* write the previous pending transfer */
++ if (prev != NULL) {
++ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, NULL);
++ if (ret < 0)
++ goto out;
++
++ len += ret;
++ }
++
++ prev = t;
++ }
++
++ /* do last pending transfer */
++ if (prev != NULL) {
++ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, NULL);
++ if (ret < 0)
++ goto out;
++ len += ret;
++ }
++
++ msg->actual_length = len;
++ ret = 0;
++out:
++ msg->status = ret;
++ spi_finalize_current_message(master);
++ return 0;
++}
++
++static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
++{
++ struct spi_master *master = (struct spi_master *)dev_id;
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
++
++ if (bcm_hsspi_readl(HSSPI_INT_STATUS_MASKED_REG) == 0)
++ return IRQ_NONE;
++
++ bcm_hsspi_writel(HSSPI_INT_CLEAR_ALL, HSSPI_INT_STATUS_REG);
++ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
++
++ if (bs->curr_trans && bs->curr_trans->rx_buf)
++ memcpy_fromio(bs->curr_trans->rx_buf, bs->fifo,
++ bs->curr_trans->len);
++ complete(&bs->done);
++
++ return IRQ_HANDLED;
++}
++
++static int __devinit bcm63xx_hsspi_probe(struct platform_device *pdev)
++{
++
++ struct spi_master *master;
++ struct bcm63xx_hsspi *bs;
++ struct resource *res_mem;
++ void __iomem *regs;
++ struct device *dev = &pdev->dev;
++ struct bcm63xx_hsspi_pdata *pdata = pdev->dev.platform_data;
++ struct clk *clk;
++ int irq;
++ int ret;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(dev, "no irq\n");
++ return -ENXIO;
++ }
++
++ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ regs = devm_request_and_ioremap(dev, res_mem);
++ if (!regs) {
++ dev_err(dev, "unable to ioremap regs\n");
++ return -ENXIO;
++ }
++
++ clk = clk_get(dev, "hsspi");
++
++ if (IS_ERR(clk)) {
++ ret = PTR_ERR(clk);
++ goto out_release;
++ }
++
++ clk_prepare_enable(clk);
++
++ master = spi_alloc_master(&pdev->dev, sizeof(*bs));
++ if (!master) {
++ ret = -ENOMEM;
++ goto out_disable_clk;
++ }
++
++ bs = spi_master_get_devdata(master);
++ bs->pdev = pdev;
++ bs->clk = clk;
++ bs->regs = regs;
++
++ master->bus_num = pdata->bus_num;
++ master->num_chipselect = 8;
++ master->setup = bcm63xx_hsspi_setup;
++ master->transfer_one_message = bcm63xx_hsspi_transfer_one;
++ master->mode_bits = SPI_CPOL | SPI_CPHA;
++
++ bs->speed_hz = pdata->speed_hz;
++ bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
++
++ platform_set_drvdata(pdev, master);
++
++ bs->curr_trans = NULL;
++
++ /* Initialize the hardware */
++ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
++
++ /* clean up any pending interrupts */
++ bcm_hsspi_writel(HSSPI_INT_CLEAR_ALL, HSSPI_INT_STATUS_REG);
++
++ bcm_hsspi_writel(bcm_hsspi_readl(HSSPI_GLOBAL_CTRL_REG) |
++ GLOBAL_CTRL_CLK_GATE_SSOFF,
++ HSSPI_GLOBAL_CTRL_REG);
++
++ ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
++ pdev->name, master);
++
++ if (ret)
++ goto out_put_master;
++
++ /* register and we are done */
++ ret = spi_register_master(master);
++ if (ret)
++ goto out_free_irq;
++
++ return 0;
++
++out_free_irq:
++ devm_free_irq(dev, bs->irq, master);
++out_put_master:
++ spi_master_put(master);
++out_disable_clk:
++ clk_disable_unprepare(clk);
++ clk_put(clk);
++out_release:
++ devm_ioremap_release(dev, regs);
++
++ return ret;
++}
++
++
++static int __exit bcm63xx_hsspi_remove(struct platform_device *pdev)
++{
++ struct spi_master *master = platform_get_drvdata(pdev);
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
++
++ spi_unregister_master(master);
++
++ /* reset the hardware and block queue progress */
++ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
++ clk_disable_unprepare(bs->clk);
++ clk_put(bs->clk);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int bcm63xx_hsspi_suspend(struct platform_device *pdev,
++ pm_message_t mesg)
++{
++ struct spi_master *master = platform_get_drvdata(pdev);
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
++
++ spi_master_suspend(master);
++ clk_disable(bs->clk);
++
++ return 0;
++}
++
++static int bcm63xx_hsspi_resume(struct platform_device *pdev)
++{
++ struct spi_master *master = platform_get_drvdata(pdev);
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
++
++ clk_enable(bs->clk);
++ spi_master_resume(master);
++
++ return 0;
++}
++
++static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = {
++ .suspend = bcm63xx_hsspi_suspend,
++ .resume = bcm63xx_hsspi_resume,
++};
++
++#define BCM63XX_HSSPI_PM_OPS (&bcm63xx_hsspi_pm_ops)
++#else
++#define BCM63XX_HSSPI_PM_OPS NULL
++#endif
++
++
++
++static struct platform_driver bcm63xx_hsspi_driver = {
++ .driver = {
++ .name = "bcm63xx-hsspi",
++ .owner = THIS_MODULE,
++ .pm = BCM63XX_HSSPI_PM_OPS,
++ },
++ .probe = bcm63xx_hsspi_probe,
++ .remove = __exit_p(bcm63xx_hsspi_remove),
++};
++
++module_platform_driver(bcm63xx_hsspi_driver);
++
++MODULE_ALIAS("platform:bcm63xx_hsspi");
++MODULE_DESCRIPTION("Broadcom BCM63xx HS SPI Controller driver");
++MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com>");
++MODULE_LICENSE("GPL");
--- /dev/null
+From d135d94b3d1fe599d13e7198d5f502912d694c13 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 3 Jul 2011 15:00:38 +0200
+Subject: [PATCH 29/60] MIPS: BCM63XX: Register SPI flash if present
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/dev-flash.c | 33 +++++++++++++++++++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 +
+ 2 files changed, 33 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -16,9 +16,12 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/physmap.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
+
+ #include <bcm63xx_cpu.h>
+ #include <bcm63xx_dev_flash.h>
++#include <bcm63xx_dev_hsspi.h>
+ #include <bcm63xx_regs.h>
+ #include <bcm63xx_io.h>
+
+@@ -55,6 +58,21 @@ static struct platform_device mtd_dev =
+ },
+ };
+
++static struct flash_platform_data bcm63xx_flash_data = {
++ .part_probe_types = bcm63xx_part_types,
++};
++
++static struct spi_board_info bcm63xx_spi_flash_info[] = {
++ {
++ .bus_num = 0,
++ .chip_select = 0,
++ .mode = 0,
++ .max_speed_hz = 781000,
++ .modalias = "m25p80",
++ .platform_data = &bcm63xx_flash_data,
++ },
++};
++
+ static int __init bcm63xx_detect_flash_type(void)
+ {
+ u32 val;
+@@ -62,6 +80,11 @@ static int __init bcm63xx_detect_flash_t
+ switch (bcm63xx_get_cpu_id()) {
+ case BCM6328_CPU_ID:
+ val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
++ if (val & STRAPBUS_6328_HSSPI_CLK_FAST)
++ bcm63xx_spi_flash_info[0].max_speed_hz = 33333334;
++ else
++ bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
++
+ if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
+ return BCM63XX_FLASH_TYPE_SERIAL;
+ else
+@@ -79,6 +102,9 @@ static int __init bcm63xx_detect_flash_t
+ return BCM63XX_FLASH_TYPE_SERIAL;
+ 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;
+@@ -110,8 +136,11 @@ int __init bcm63xx_flash_register(void)
+
+ return platform_device_register(&mtd_dev);
+ case BCM63XX_FLASH_TYPE_SERIAL:
+- pr_warn("unsupported serial flash detected\n");
+- return -ENODEV;
++ if (BCMCPU_IS_6328())
++ bcm63xx_flash_data.max_transfer_len = HSSPI_BUFFER_LEN;
++
++ return spi_register_board_info(bcm63xx_spi_flash_info,
++ ARRAY_SIZE(bcm63xx_spi_flash_info));
+ case BCM63XX_FLASH_TYPE_NAND:
+ pr_warn("unsupported NAND flash detected\n");
+ return -ENODEV;
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -555,6 +555,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
+@@ -1240,6 +1241,7 @@
+ #define SERDES_PCIE_EXD_EN (1 << 15)
+
+ #define MISC_STRAPBUS_6328_REG 0x240
++#define STRAPBUS_6328_HSSPI_CLK_FAST (1 << 4)
+ #define STRAPBUS_6328_FCVO_SHIFT 7
+ #define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
+ #define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)
+++ /dev/null
-From f888824d352df894ab721a5ca067b0313500efe7 Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Thu, 3 May 2012 12:17:54 +0200
-Subject: [PATCH 38/59] MIPS: BCM63XX: store the flash type in global variable
-
----
- arch/mips/bcm63xx/dev-flash.c | 36 +++++++++++++------
- .../include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 2 +
- 2 files changed, 26 insertions(+), 12 deletions(-)
-
---- a/arch/mips/bcm63xx/dev-flash.c
-+++ b/arch/mips/bcm63xx/dev-flash.c
-@@ -25,6 +25,8 @@
- #include <bcm63xx_regs.h>
- #include <bcm63xx_io.h>
-
-+int bcm63xx_attached_flash = -1;
-+
- static struct mtd_partition mtd_partitions[] = {
- {
- .name = "cfe",
-@@ -86,20 +88,23 @@ static int __init bcm63xx_detect_flash_t
- bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
-
- if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
-- return BCM63XX_FLASH_TYPE_SERIAL;
-+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
- else
-- return BCM63XX_FLASH_TYPE_NAND;
-+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
-+ break;
- case BCM6338_CPU_ID:
- case BCM6345_CPU_ID:
- case BCM6348_CPU_ID:
- /* no way to auto detect so assume parallel */
-- return BCM63XX_FLASH_TYPE_PARALLEL;
-+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
-+ break;
- case BCM6358_CPU_ID:
- val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
- if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL)
-- return BCM63XX_FLASH_TYPE_PARALLEL;
-+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
- else
-- return BCM63XX_FLASH_TYPE_SERIAL;
-+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
-+ break;
- case BCM6368_CPU_ID:
- val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
- if (val & STRAPBUS_6368_SPI_CLK_FAST)
-@@ -107,25 +112,32 @@ static int __init bcm63xx_detect_flash_t
-
- switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
- case STRAPBUS_6368_BOOT_SEL_NAND:
-- return BCM63XX_FLASH_TYPE_NAND;
-+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
-+ break;
- case STRAPBUS_6368_BOOT_SEL_SERIAL:
-- return BCM63XX_FLASH_TYPE_SERIAL;
-+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
-+ break;
- case STRAPBUS_6368_BOOT_SEL_PARALLEL:
-- return BCM63XX_FLASH_TYPE_PARALLEL;
-+ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
-+ break;
-+ default:
-+ return -EINVAL;
- }
- default:
- return -EINVAL;
- }
-+
-+ return 0;
- }
-
- int __init bcm63xx_flash_register(void)
- {
-- int flash_type;
- u32 val;
-
-- flash_type = bcm63xx_detect_flash_type();
-
-- switch (flash_type) {
-+ bcm63xx_detect_flash_type();
-+
-+ switch (bcm63xx_attached_flash) {
- case BCM63XX_FLASH_TYPE_PARALLEL:
- /* read base address of boot chip select (0) */
- val = bcm_mpi_readl(MPI_CSBASE_REG(0));
-@@ -146,7 +158,7 @@ int __init bcm63xx_flash_register(void)
- return -ENODEV;
- default:
- pr_err("flash detection failed for BCM%x: %d\n",
-- bcm63xx_get_cpu_id(), flash_type);
-+ bcm63xx_get_cpu_id(), bcm63xx_attached_flash);
- return -ENODEV;
- }
- }
---- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
-+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
-@@ -7,6 +7,8 @@ enum {
- BCM63XX_FLASH_TYPE_NAND,
- };
-
-+extern int bcm63xx_attached_flash;
-+
- int __init bcm63xx_flash_register(void);
-
- #endif /* __BCM63XX_FLASH_H */
+++ /dev/null
-From fb6f6f58db9ae9cf27ab01f5f09cfbc5c078a7b8 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 66/80] BCM63XX: add a fixup for ath9k devices
-
----
- arch/mips/bcm63xx/Makefile | 2 +-
- arch/mips/bcm63xx/pci-ath9k-fixup.c | 190 ++++++++++++++++++++
- .../include/asm/mach-bcm63xx/pci_ath9k_fixup.h | 7 +
- 3 files changed, 198 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
-@@ -1,7 +1,7 @@
- obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o setup.o \
- timer.o dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o \
- dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
-- dev-usb-ohci.o dev-wdt.o
-+ dev-usb-ohci.o dev-wdt.o pci-ath9k-fixup.o
- obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-
- obj-y += boards/
---- /dev/null
-+++ b/arch/mips/bcm63xx/pci-ath9k-fixup.c
-@@ -0,0 +1,190 @@
-+/*
-+ * Broadcom BCM63XX Ath9k EEPROM fixup helper.
-+ *
-+ * Copytight (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
-+ *
-+ * Based on
-+ *
-+ * Atheros AP94 reference board PCI initialization
-+ *
-+ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ */
-+
-+#include <linux/pci.h>
-+#include <linux/delay.h>
-+#include <linux/ath9k_platform.h>
-+
-+#include <bcm63xx_cpu.h>
-+#include <bcm63xx_io.h>
-+#include <bcm63xx_nvram.h>
-+#include <bcm63xx_dev_pci.h>
-+#include <bcm63xx_dev_flash.h>
-+#include <bcm63xx_dev_hsspi.h>
-+#include <pci_ath9k_fixup.h>
-+
-+struct ath9k_fixup {
-+ unsigned slot;
-+ u8 mac[ETH_ALEN];
-+ struct ath9k_platform_data pdata;
-+};
-+
-+static int ath9k_num_fixups;
-+static struct ath9k_fixup ath9k_fixups[2] = {
-+ {
-+ .slot = 255,
-+ .pdata = {
-+ .led_pin = -1,
-+ },
-+ },
-+ {
-+ .slot = 255,
-+ .pdata = {
-+ .led_pin = -1,
-+ },
-+ },
-+};
-+
-+static u16 *bcm63xx_read_eeprom(u16 *eeprom, u32 offset)
-+{
-+ u32 addr;
-+
-+ if (BCMCPU_IS_6328()) {
-+ addr = 0x18000000;
-+ } else {
-+ addr = bcm_mpi_readl(MPI_CSBASE_REG(0));
-+ addr &= MPI_CSBASE_BASE_MASK;
-+ }
-+
-+ switch (bcm63xx_attached_flash) {
-+ case BCM63XX_FLASH_TYPE_PARALLEL:
-+ memcpy(eeprom, (void *)KSEG1ADDR(addr + offset), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
-+ return eeprom;
-+ case BCM63XX_FLASH_TYPE_SERIAL:
-+ /* the first megabyte is memory mapped */
-+ if (offset < 0x100000) {
-+ memcpy(eeprom, (void *)KSEG1ADDR(addr + offset), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
-+ return eeprom;
-+ }
-+
-+ if (BCMCPU_IS_6328()) {
-+ /* we can change the memory mapped megabyte */
-+ bcm_hsspi_writel(offset & 0xf00000, 0x18);
-+ memcpy(eeprom, (void *)KSEG1ADDR(addr + (offset & 0xfffff)), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
-+ bcm_hsspi_writel(0, 0x18);
-+ return eeprom;
-+ }
-+ /* can't do anything here without talking to the SPI controller. */
-+ case BCM63XX_FLASH_TYPE_NAND:
-+ default:
-+ return NULL;
-+ }
-+}
-+
-+static void ath9k_pci_fixup(struct pci_dev *dev)
-+{
-+ void __iomem *mem;
-+ struct ath9k_platform_data *pdata = NULL;
-+ u16 *cal_data = NULL;
-+ u16 cmd;
-+ u32 bar0;
-+ u32 val;
-+ unsigned i;
-+
-+ for (i = 0; i < ath9k_num_fixups; i++) {
-+ if (ath9k_fixups[i].slot != PCI_SLOT(dev->devfn))
-+ continue;
-+
-+ cal_data = ath9k_fixups[i].pdata.eeprom_data;
-+ pdata = &ath9k_fixups[i].pdata;
-+ break;
-+ }
-+
-+ if (cal_data == NULL)
-+ return;
-+
-+ if (*cal_data != 0xa55a) {
-+ pr_err("pci %s: invalid calibration data\n", pci_name(dev));
-+ return;
-+ }
-+
-+ pr_info("pci %s: fixup device configuration\n", pci_name(dev));
-+
-+ switch (bcm63xx_get_cpu_id()) {
-+ case BCM6328_CPU_ID:
-+ val = BCM_PCIE_MEM_BASE_PA;
-+ break;
-+ case BCM6348_CPU_ID:
-+ case BCM6358_CPU_ID:
-+ case BCM6368_CPU_ID:
-+ val = BCM_PCI_MEM_BASE_PA;
-+ break;
-+ default:
-+ BUG();
-+ }
-+
-+ mem = ioremap(val, 0x10000);
-+ if (!mem) {
-+ pr_err("pci %s: ioremap error\n", pci_name(dev));
-+ return;
-+ }
-+
-+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
-+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
-+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, val);
-+
-+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
-+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
-+ pci_write_config_word(dev, PCI_COMMAND, cmd);
-+
-+ /* set offset to first reg address */
-+ cal_data += 3;
-+ while(*cal_data != 0xffff) {
-+ u32 reg;
-+ reg = *cal_data++;
-+ val = *cal_data++;
-+ val |= (*cal_data++) << 16;
-+
-+ writel(val, mem + reg);
-+ udelay(100);
-+ }
-+
-+ pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
-+ dev->vendor = val & 0xffff;
-+ dev->device = (val >> 16) & 0xffff;
-+
-+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
-+ dev->revision = val & 0xff;
-+ dev->class = val >> 8; /* upper 3 bytes */
-+
-+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
-+ cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
-+ pci_write_config_word(dev, PCI_COMMAND, cmd);
-+
-+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
-+
-+ iounmap(mem);
-+
-+ dev->dev.platform_data = pdata;
-+}
-+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
-+
-+void __init pci_enable_ath9k_fixup(unsigned slot, u32 offset)
-+{
-+ if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups))
-+ return;
-+
-+ ath9k_fixups[ath9k_num_fixups].slot = slot;
-+
-+ if (!bcm63xx_read_eeprom(ath9k_fixups[ath9k_num_fixups].pdata.eeprom_data, offset))
-+ return;
-+
-+ if (bcm63xx_nvram_get_mac_address(ath9k_fixups[ath9k_num_fixups].mac))
-+ return;
-+
-+ ath9k_fixups[ath9k_num_fixups].pdata.macaddr = ath9k_fixups[ath9k_num_fixups].mac;
-+ ath9k_num_fixups++;
-+}
---- /dev/null
-+++ b/arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
-@@ -0,0 +1,7 @@
-+#ifndef _PCI_ATH9K_FIXUP
-+#define _PCI_ATH9K_FIXUP
-+
-+
-+void pci_enable_ath9k_fixup(unsigned slot, u32 offset) __init;
-+
-+#endif /* _PCI_ATH9K_FIXUP */
--- /dev/null
+From 5b753c1d01c6af23d7d37d37d9de30da8a971084 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 May 2012 22:51:08 +0200
+Subject: [PATCH 60/79] MIPS: BCM63XX: move nvram related functions into their
+ own file
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/Makefile | 6 +-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 74 +++--------------
+ arch/mips/bcm63xx/nvram.c | 84 ++++++++++++++++++++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h | 34 ++++++++
+ .../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 17 ----
+ 5 files changed, 134 insertions(+), 81 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/nvram.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,6 +1,6 @@
+-obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+- dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o dev-pcmcia.o \
+- dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
++obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o setup.o \
++ timer.o dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o \
++ dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
+ dev-usb-ohci.o dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -21,6 +21,7 @@
+ #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>
+@@ -41,8 +42,6 @@
+ #define CFE_OFFSET_64K 0x10000
+ #define CFE_OFFSET_128K 0x20000
+
+-static struct bcm963xx_nvram nvram;
+-static unsigned int mac_addr_used;
+ static struct board_info board;
+
+ /*
+@@ -696,50 +695,16 @@ const char *board_get_name(void)
+ return board.name;
+ }
+
+-/*
+- * register & return a new board mac address
+- */
+-static int board_get_mac_address(u8 *mac)
+-{
+- u8 *p;
+- int count;
+-
+- if (mac_addr_used >= nvram.mac_addr_count) {
+- printk(KERN_ERR PFX "not enough mac address\n");
+- return -ENODEV;
+- }
+-
+- memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
+- p = mac + ETH_ALEN - 1;
+- count = mac_addr_used;
+-
+- while (count--) {
+- do {
+- (*p)++;
+- if (*p != 0)
+- break;
+- p--;
+- } while (p != mac);
+- }
+-
+- if (p == mac) {
+- printk(KERN_ERR PFX "unable to fetch mac address\n");
+- return -ENODEV;
+- }
+-
+- mac_addr_used++;
+- return 0;
+-}
+-
+ static void __init boardid_fixup(u8 *boot_addr)
+ {
+ struct bcm_tag *tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_64K);
++ char *board_name = (char *)bcm63xx_nvram_get_name();
+
+ /* check if bcm_tag is at 64k offset */
+- if (strncmp(nvram.name, tag->boardid, BOARDID_LEN) != 0) {
++ if (strncmp(board_name, tag->boardid, BOARDID_LEN) != 0) {
+ /* else try 128k */
+ tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_128K);
+- if (strncmp(nvram.name, tag->boardid, BOARDID_LEN) != 0) {
++ if (strncmp(board_name, tag->boardid, BOARDID_LEN) != 0) {
+ /* No tag found */
+ printk(KERN_DEBUG "No bcm_tag found!\n");
+ return;
+@@ -749,9 +714,9 @@ static void __init boardid_fixup(u8 *boo
+ if (tag->information1[0] != '+')
+ return;
+
+- strncpy(nvram.name, &tag->information1[1], BOARDID_LEN);
++ strncpy(board_name, &tag->information1[1], BOARDID_LEN);
+
+- printk(KERN_INFO "Overriding boardid with '%s'\n", nvram.name);
++ printk(KERN_INFO "Overriding boardid with '%s'\n", board_name);
+ }
+
+ /*
+@@ -759,9 +724,10 @@ static void __init boardid_fixup(u8 *boo
+ */
+ void __init board_prom_init(void)
+ {
+- unsigned int check_len, i;
+- u8 *boot_addr, *cfe, *p;
++ unsigned int i;
++ u8 *boot_addr, *cfe;
+ char cfe_version[32];
++ char *board_name;
+ u32 val;
+
+ /* read base address of boot chip select (0)
+@@ -786,32 +752,19 @@ void __init board_prom_init(void)
+ strcpy(cfe_version, "unknown");
+ printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
+
+- /* extract nvram data */
+- memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
+-
+- /* check checksum before using data */
+- if (nvram.version <= 4)
+- check_len = offsetof(struct bcm963xx_nvram, checksum_old);
+- else
+- check_len = sizeof(nvram);
+- val = 0;
+- p = (u8 *)&nvram;
+- while (check_len--)
+- val += *p;
+- if (val) {
+- printk(KERN_ERR PFX "invalid nvram checksum\n");
++ if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET))
+ return;
+- }
+
+ if (strcmp(cfe_version, "unknown") != 0) {
+ /* cfe present */
+ boardid_fixup(boot_addr);
+ }
+
++ board_name = bcm63xx_nvram_get_name();
+ /* find board by name */
+ for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
+- if (strncmp(nvram.name, bcm963xx_boards[i]->name,
+- sizeof(nvram.name)))
++ if (strncmp(board_name, bcm963xx_boards[i]->name,
++ BCM63XX_NVRAM_NAMELEN))
+ continue;
+ /* copy, board desc array is marked initdata */
+ memcpy(&board, bcm963xx_boards[i], sizeof(board));
+@@ -821,7 +774,7 @@ void __init board_prom_init(void)
+ /* bail out if board is not found, will complain later */
+ if (!board.name[0]) {
+ char name[17];
+- memcpy(name, nvram.name, 16);
++ memcpy(name, board_name, 16);
+ name[16] = 0;
+ printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
+ name);
+@@ -914,15 +867,15 @@ int __init board_register_devices(void)
+ bcm63xx_pcmcia_register();
+
+ if (board.has_enet0 &&
+- !board_get_mac_address(board.enet0.mac_addr))
++ !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
+ bcm63xx_enet_register(0, &board.enet0);
+
+ if (board.has_enet1 &&
+- !board_get_mac_address(board.enet1.mac_addr))
++ !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
+ bcm63xx_enet_register(1, &board.enet1);
+
+ if (board.has_enetsw &&
+- !board_get_mac_address(board.enetsw.mac_addr))
++ !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
+ bcm63xx_enetsw_register(&board.enetsw);
+
+ if (board.has_ehci0)
+@@ -938,7 +891,7 @@ int __init board_register_devices(void)
+ * do this after registering enet devices
+ */
+ #ifdef CONFIG_SSB_PCIHOST
+- if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
++ if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ if (ssb_arch_register_fallback_sprom(
+--- /dev/null
++++ b/arch/mips/bcm63xx/nvram.c
+@@ -0,0 +1,84 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
++ */
++
++#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
++
++#include <linux/init.h>
++#include <linux/export.h>
++#include <linux/kernel.h>
++
++#include <bcm63xx_nvram.h>
++
++static struct bcm963xx_nvram nvram;
++static int mac_addr_used;
++
++int __init bcm63xx_nvram_init(void *addr)
++{
++ unsigned int check_len;
++ u8 *p;
++ u32 val;
++
++ /* extract nvram data */
++ memcpy(&nvram, addr, sizeof(nvram));
++
++ /* check checksum before using data */
++ if (nvram.version <= 4)
++ check_len = offsetof(struct bcm963xx_nvram, checksum_old);
++ else
++ check_len = sizeof(nvram);
++ val = 0;
++ p = (u8 *)&nvram;
++
++ while (check_len--)
++ val += *p;
++ if (val) {
++ pr_err("invalid nvram checksum\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++u8 *bcm63xx_nvram_get_name(void)
++{
++ return nvram.name;
++}
++EXPORT_SYMBOL(bcm63xx_nvram_get_name);
++
++int bcm63xx_nvram_get_mac_address(u8 *mac)
++{
++ u8 *p;
++ int count;
++
++ if (mac_addr_used >= nvram.mac_addr_count) {
++ pr_err("not enough mac address\n");
++ return -ENODEV;
++ }
++
++ memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
++ p = mac + ETH_ALEN - 1;
++ count = mac_addr_used;
++
++ while (count--) {
++ do {
++ (*p)++;
++ if (*p != 0)
++ break;
++ p--;
++ } while (p != mac);
++ }
++
++ if (p == mac) {
++ pr_err("unable to fetch mac address\n");
++ return -ENODEV;
++ }
++
++ mac_addr_used++;
++ return 0;
++}
++EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+@@ -0,0 +1,34 @@
++#ifndef BCM63XX_NVRAM_H
++#define BCM63XX_NVRAM_H
++
++#include <linux/if_ether.h>
++
++#define BCM63XX_NVRAM_NAMELEN 16
++
++/*
++ * nvram structure
++ */
++struct bcm963xx_nvram {
++ u32 version;
++ u8 reserved1[256];
++ u8 name[BCM63XX_NVRAM_NAMELEN];
++ u32 main_tp_number;
++ u32 psi_size;
++ u32 mac_addr_count;
++ u8 mac_addr_base[ETH_ALEN];
++ u8 reserved2[2];
++ u32 checksum_old;
++ u8 reserved3[720];
++ u32 checksum_high;
++};
++
++int __init bcm63xx_nvram_init(void *);
++
++u8 *bcm63xx_nvram_get_name(void);
++
++/*
++ * register & return a new board mac address
++ */
++int bcm63xx_nvram_get_mac_address(u8 *mac);
++
++#endif /* BCM63XX_NVRAM_H */
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -15,23 +15,6 @@
+ #define BCM963XX_NVRAM_OFFSET 0x580
+
+ /*
+- * nvram structure
+- */
+-struct bcm963xx_nvram {
+- u32 version;
+- u8 reserved1[256];
+- u8 name[16];
+- u32 main_tp_number;
+- u32 psi_size;
+- u32 mac_addr_count;
+- u8 mac_addr_base[6];
+- u8 reserved2[2];
+- u32 checksum_old;
+- u8 reserved3[720];
+- u32 checksum_high;
+-};
+-
+-/*
+ * board definition
+ */
+ struct board_info {
--- /dev/null
+From ffbeb183bf0e9e12fd607c5352f48420c32f588f Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 May 2012 23:04:17 +0200
+Subject: [PATCH 61/79] MIPS: BCM63XX: export PSI size from nvram
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/nvram.c | 11 +++++++++++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h | 2 ++
+ 2 files changed, 13 insertions(+)
+
+--- a/arch/mips/bcm63xx/nvram.c
++++ b/arch/mips/bcm63xx/nvram.c
+@@ -14,6 +14,8 @@
+
+ #include <bcm63xx_nvram.h>
+
++#define BCM63XX_DEFAULT_PSI_SIZE 64
++
+ static struct bcm963xx_nvram nvram;
+ static int mac_addr_used;
+
+@@ -82,3 +84,12 @@ int bcm63xx_nvram_get_mac_address(u8 *ma
+ return 0;
+ }
+ EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
++
++int bcm63xx_nvram_get_psi_size(void)
++{
++ if (nvram.psi_size > 0)
++ return nvram.psi_size;
++
++ return BCM63XX_DEFAULT_PSI_SIZE;
++}
++EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+@@ -31,4 +31,6 @@ u8 *bcm63xx_nvram_get_name(void);
+ */
+ int bcm63xx_nvram_get_mac_address(u8 *mac);
+
++int bcm63xx_nvram_get_psi_size(void);
++
+ #endif /* BCM63XX_NVRAM_H */
+++ /dev/null
-From 8ab86c5dc38ad4de1442e50e0adbc354d9184d71 Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Tue, 1 May 2012 14:38:41 +0200
-Subject: [PATCH 68/79] MTD: bcm63xxpart: allow passing a caldata offset
-
-Allow bcm63xxpart to receive a caldata offset if calibration data is
-contained in flash.
----
- drivers/mtd/bcm63xxpart.c | 47 ++++++++++++++++++++++++++++++++++++++--
- include/linux/mtd/partitions.h | 2 ++
- 2 files changed, 47 insertions(+), 2 deletions(-)
-
---- a/drivers/mtd/bcm63xxpart.c
-+++ b/drivers/mtd/bcm63xxpart.c
-@@ -80,6 +80,8 @@ static int bcm63xx_parse_cfe_partitions(
- 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;
-@@ -94,6 +96,23 @@ static int bcm63xx_parse_cfe_partitions(
- nvramlen = bcm63xx_nvram_get_psi_size() * 1024;
- nvramlen = roundup(nvramlen, cfe_erasesize);
-
-+ 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));
- if (!buf)
-@@ -144,7 +163,7 @@ static int bcm63xx_parse_cfe_partitions(
- rootfsaddr = 0;
- spareaddr = cfelen;
- }
-- sparelen = master->size - spareaddr - nvramlen;
-+ sparelen = master->size - spareaddr - nvramlen - caldatalen1 - caldatalen2;
-
- /* Determine number of partitions */
- if (rootfslen > 0)
-@@ -153,6 +172,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) {
-@@ -190,6 +215,23 @@ 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].size = nvramlen;
-@@ -198,7 +240,8 @@ 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 = master->size - cfelen - nvramlen;
-+ parts[curpart].size = master->size - cfelen - nvramlen
-+ - caldatalen1 - caldatalen2;
-
- 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
-@@ -58,10 +58,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;
- };
-
+++ /dev/null
-From 977f8a30103b9c4992cab8f49357fe0d4274004f Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Thu, 3 May 2012 14:55:26 +0200
-Subject: [PATCH 69/80] MIPS: BCM63XX: pass caldata info to flash
-
----
- arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
- arch/mips/bcm63xx/dev-flash.c | 9 ++++++++-
- arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 4 +++-
- 3 files changed, 12 insertions(+), 3 deletions(-)
-
---- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
-+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -912,7 +912,7 @@ int __init board_register_devices(void)
- if (board.num_spis)
- spi_register_board_info(board.spis, board.num_spis);
-
-- bcm63xx_flash_register();
-+ bcm63xx_flash_register(board.has_caldata, board.caldata);
-
- /* count number of LEDs defined by this device */
- while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
---- a/arch/mips/bcm63xx/dev-flash.c
-+++ b/arch/mips/bcm63xx/dev-flash.c
-@@ -35,12 +35,15 @@ static struct mtd_partition mtd_partitio
- }
- };
-
-+static struct mtd_part_parser_data bcm63xx_parser_data;
-+
- static const char *bcm63xx_part_types[] = { "bcm63xxpart", "RedBoot", NULL };
-
- static struct physmap_flash_data flash_data = {
- .width = 2,
- .parts = mtd_partitions,
- .part_probe_types = bcm63xx_part_types,
-+ .pp_data = &bcm63xx_parser_data,
- };
-
- static struct resource mtd_resources[] = {
-@@ -62,6 +65,7 @@ static struct platform_device mtd_dev =
-
- static struct flash_platform_data bcm63xx_flash_data = {
- .part_probe_types = bcm63xx_part_types,
-+ .pp_data = &bcm63xx_parser_data,
- };
-
- static struct spi_board_info bcm63xx_spi_flash_info[] = {
-@@ -130,10 +134,13 @@ static int __init bcm63xx_detect_flash_t
- return 0;
- }
-
--int __init bcm63xx_flash_register(void)
-+int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata)
- {
- u32 val;
-+ unsigned int i;
-
-+ for (i = 0; i < num_caldata; i++)
-+ bcm63xx_parser_data.caldata[i] = caldata[i].caldata_offset;
-
- bcm63xx_detect_flash_type();
-
---- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
-+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
-@@ -1,6 +1,8 @@
- #ifndef __BCM63XX_FLASH_H
- #define __BCM63XX_FLASH_H
-
-+#include <board_bcm963xx.h>
-+
- enum {
- BCM63XX_FLASH_TYPE_PARALLEL,
- BCM63XX_FLASH_TYPE_SERIAL,
-@@ -9,6 +11,6 @@ enum {
-
- extern int bcm63xx_attached_flash;
-
--int __init bcm63xx_flash_register(void);
-+int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata);
-
- #endif /* __BCM63XX_FLASH_H */
--- /dev/null
+From 658afad639a9456e1bb6fe5bba0032f3c0c3f699 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 1 May 2012 14:10:39 +0200
+Subject: [PATCH 62/79] MTD: bcm63xxpart: use nvram for PSI size
+
+---
+ drivers/mtd/bcm63xxpart.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -32,6 +32,7 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+
++#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
+ #include <asm/mach-bcm63xx/bcm963xx_tag.h>
+ #include <asm/mach-bcm63xx/board_bcm963xx.h>
+
+@@ -90,7 +91,8 @@ static int bcm63xx_parse_cfe_partitions(
+ BCM63XX_CFE_BLOCK_SIZE);
+
+ cfelen = cfe_erasesize;
+- nvramlen = cfe_erasesize;
++ nvramlen = bcm63xx_nvram_get_psi_size() * 1024;
++ nvramlen = roundup(nvramlen, cfe_erasesize);
+
+ /* Allocate memory for buffer */
+ buf = vmalloc(sizeof(struct bcm_tag));
--- /dev/null
+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
+@@ -84,6 +84,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 **probe_type;
+ const char **part_types;
+ int err = 0;
+@@ -173,8 +174,9 @@ static int physmap_flash_probe(struct pl
+ goto err_out;
+
+ 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, 0,
++ mtd_device_parse_register(info->cmtd, part_types, pp_data,
+ physmap_data->parts, physmap_data->nr_parts);
+ return 0;
+
+--- a/include/linux/mtd/physmap.h
++++ b/include/linux/mtd/physmap.h
+@@ -32,6 +32,7 @@ struct physmap_flash_data {
+ char *probe_type;
+ struct mtd_partition *parts;
+ const char **part_probe_types;
++ struct mtd_part_parser_data *pp_data;
+ };
+
+ #endif /* __LINUX_MTD_PHYSMAP__ */
+++ /dev/null
-From 6d5c5bb13db3fd8e3dd0b82742b3957f41a4a3ac Mon Sep 17 00:00:00 2001
-From: Jonas Gorski <jonas.gorski@gmail.com>
-Date: Thu, 24 May 2012 20:38:58 +0200
-Subject: [PATCH] bcm63xx_enet: reset port link state in bcm_enetsw_open
-
-bcm_enetsw_open disables all ports, but does not reset their link state.
-This results in connected ports staying disabled after a ifdown/ifup
-cycle, since bcm_enetsw_phy_poll only enables them if their current state
-is different from the stored link state.
-
-Fix this by also resetting the port link state.
-
-Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
----
- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
-+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
-@@ -2214,6 +2214,8 @@ static int bcm_enetsw_open(struct net_de
- enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
- ENETSW_PTCTRL_TXDIS_MASK,
- ENETSW_PTCTRL_REG(i));
-+
-+ priv->sw_port_link[i] = 0;
- }
-
- /* reset mib */
--- /dev/null
+From 5131195413b62df73dfd394fea272830ea8c4e1a 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 67/80] BCM63XX: allow providing fixup data in board data
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 10 +++++++++-
+ arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 10 ++++++++++
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -33,6 +33,7 @@
+ #include <bcm63xx_dev_usb_ehci.h>
+ #include <board_bcm963xx.h>
+ #include <bcm_tag.h>
++#include <pci_ath9k_fixup.h>
+
+ #define PFX "board_bcm963xx: "
+
+@@ -856,6 +857,7 @@ int __init board_register_devices(void)
+ {
+ int button_count = 0;
+ int led_count = 0;
++ int i;
+
+ if (board.has_uart0)
+ bcm63xx_uart_register(0);
+@@ -891,7 +893,8 @@ int __init board_register_devices(void)
+ * do this after registering enet devices
+ */
+ #ifdef CONFIG_SSB_PCIHOST
+- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
++ if (!board.has_caldata &&
++ !bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ if (ssb_arch_register_fallback_sprom(
+@@ -931,5 +934,9 @@ int __init board_register_devices(void)
+ platform_device_register(&bcm63xx_gpio_keys_device);
+ }
+
++ /* register any fixups */
++ for (i = 0; i < board.has_caldata; i++)
++ pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset);
++
+ return 0;
+ }
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -7,6 +7,7 @@
+ #include <linux/leds.h>
+ #include <bcm63xx_dev_enet.h>
+ #include <bcm63xx_dev_dsp.h>
++#include <pci_ath9k_fixup.h>
+
+ /*
+ * flash mapping
+@@ -14,6 +15,11 @@
+ #define BCM963XX_CFE_VERSION_OFFSET 0x570
+ #define BCM963XX_NVRAM_OFFSET 0x580
+
++struct ath9k_caldata {
++ unsigned int slot;
++ u32 caldata_offset;
++};
++
+ /*
+ * board definition
+ */
+@@ -32,6 +38,10 @@ struct board_info {
+ unsigned int has_dsp:1;
+ unsigned int has_uart0:1;
+ unsigned int has_uart1:1;
++ unsigned int has_caldata:2;
++
++ /* wifi calibration data config */
++ struct ath9k_caldata caldata[2];
+
+ /* ethernet config */
+ struct bcm63xx_enet_platform_data enet0;
--- /dev/null
+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
+@@ -886,6 +886,9 @@ static int __devinit m25p_probe(struct s
+ dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
+ }
+
++ if (data && data->pp_data)
++ memcpy(&ppdata, data->pp_data, sizeof(ppdata));
++
+ info = (void *)id->driver_data;
+
+ if (info->jedec_id) {
+--- a/include/linux/spi/flash.h
++++ b/include/linux/spi/flash.h
+@@ -12,6 +12,7 @@ struct mtd_part_parser_data;
+ * with chips that can't be queried for JEDEC or other IDs
+ * @part_probe_types: optional list of MTD parser names to use for
+ * partitioning
++ * @pp_data: optional partition parser data.
+ *
+ * @max_transfer_len: option maximum read/write length limitation for
+ * SPI controllers not able to transfer any length commands.
+@@ -30,6 +31,7 @@ struct flash_platform_data {
+ char *type;
+
+ const char **part_probe_types;
++ struct mtd_part_parser_data *pp_data;
+
+ unsigned int max_transfer_len;
+ /* we'll likely add more ... use JEDEC IDs, etc */
--- /dev/null
+From f888824d352df894ab721a5ca067b0313500efe7 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 3 May 2012 12:17:54 +0200
+Subject: [PATCH 38/59] MIPS: BCM63XX: store the flash type in global variable
+
+---
+ arch/mips/bcm63xx/dev-flash.c | 36 +++++++++++++------
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 2 +
+ 2 files changed, 26 insertions(+), 12 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -25,6 +25,8 @@
+ #include <bcm63xx_regs.h>
+ #include <bcm63xx_io.h>
+
++int bcm63xx_attached_flash = -1;
++
+ static struct mtd_partition mtd_partitions[] = {
+ {
+ .name = "cfe",
+@@ -86,20 +88,23 @@ static int __init bcm63xx_detect_flash_t
+ bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
+
+ if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
+- return BCM63XX_FLASH_TYPE_SERIAL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
+ else
+- return BCM63XX_FLASH_TYPE_NAND;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
++ break;
+ case BCM6338_CPU_ID:
+ case BCM6345_CPU_ID:
+ case BCM6348_CPU_ID:
+ /* no way to auto detect so assume parallel */
+- return BCM63XX_FLASH_TYPE_PARALLEL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
++ break;
+ case BCM6358_CPU_ID:
+ val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
+ if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL)
+- return BCM63XX_FLASH_TYPE_PARALLEL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
+ else
+- return BCM63XX_FLASH_TYPE_SERIAL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
++ break;
+ case BCM6368_CPU_ID:
+ val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
+ if (val & STRAPBUS_6368_SPI_CLK_FAST)
+@@ -107,25 +112,32 @@ static int __init bcm63xx_detect_flash_t
+
+ switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
+ case STRAPBUS_6368_BOOT_SEL_NAND:
+- return BCM63XX_FLASH_TYPE_NAND;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
++ break;
+ case STRAPBUS_6368_BOOT_SEL_SERIAL:
+- return BCM63XX_FLASH_TYPE_SERIAL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
++ break;
+ case STRAPBUS_6368_BOOT_SEL_PARALLEL:
+- return BCM63XX_FLASH_TYPE_PARALLEL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
++ break;
++ default:
++ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
++
++ return 0;
+ }
+
+ int __init bcm63xx_flash_register(void)
+ {
+- int flash_type;
+ u32 val;
+
+- flash_type = bcm63xx_detect_flash_type();
+
+- switch (flash_type) {
++ bcm63xx_detect_flash_type();
++
++ switch (bcm63xx_attached_flash) {
+ case BCM63XX_FLASH_TYPE_PARALLEL:
+ /* read base address of boot chip select (0) */
+ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+@@ -146,7 +158,7 @@ int __init bcm63xx_flash_register(void)
+ return -ENODEV;
+ default:
+ pr_err("flash detection failed for BCM%x: %d\n",
+- bcm63xx_get_cpu_id(), flash_type);
++ bcm63xx_get_cpu_id(), bcm63xx_attached_flash);
+ return -ENODEV;
+ }
+ }
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+@@ -7,6 +7,8 @@ enum {
+ BCM63XX_FLASH_TYPE_NAND,
+ };
+
++extern int bcm63xx_attached_flash;
++
+ int __init bcm63xx_flash_register(void);
+
+ #endif /* __BCM63XX_FLASH_H */
--- /dev/null
+From fb6f6f58db9ae9cf27ab01f5f09cfbc5c078a7b8 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 66/80] BCM63XX: add a fixup for ath9k devices
+
+---
+ arch/mips/bcm63xx/Makefile | 2 +-
+ arch/mips/bcm63xx/pci-ath9k-fixup.c | 190 ++++++++++++++++++++
+ .../include/asm/mach-bcm63xx/pci_ath9k_fixup.h | 7 +
+ 3 files changed, 198 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
+@@ -1,7 +1,7 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o setup.o \
+ timer.o dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o \
+ dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
+- dev-usb-ohci.o dev-wdt.o
++ dev-usb-ohci.o dev-wdt.o pci-ath9k-fixup.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- /dev/null
++++ b/arch/mips/bcm63xx/pci-ath9k-fixup.c
+@@ -0,0 +1,190 @@
++/*
++ * Broadcom BCM63XX Ath9k EEPROM fixup helper.
++ *
++ * Copytight (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
++ *
++ * Based on
++ *
++ * Atheros AP94 reference board PCI initialization
++ *
++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/ath9k_platform.h>
++
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_io.h>
++#include <bcm63xx_nvram.h>
++#include <bcm63xx_dev_pci.h>
++#include <bcm63xx_dev_flash.h>
++#include <bcm63xx_dev_hsspi.h>
++#include <pci_ath9k_fixup.h>
++
++struct ath9k_fixup {
++ unsigned slot;
++ u8 mac[ETH_ALEN];
++ struct ath9k_platform_data pdata;
++};
++
++static int ath9k_num_fixups;
++static struct ath9k_fixup ath9k_fixups[2] = {
++ {
++ .slot = 255,
++ .pdata = {
++ .led_pin = -1,
++ },
++ },
++ {
++ .slot = 255,
++ .pdata = {
++ .led_pin = -1,
++ },
++ },
++};
++
++static u16 *bcm63xx_read_eeprom(u16 *eeprom, u32 offset)
++{
++ u32 addr;
++
++ if (BCMCPU_IS_6328()) {
++ addr = 0x18000000;
++ } else {
++ addr = bcm_mpi_readl(MPI_CSBASE_REG(0));
++ addr &= MPI_CSBASE_BASE_MASK;
++ }
++
++ switch (bcm63xx_attached_flash) {
++ case BCM63XX_FLASH_TYPE_PARALLEL:
++ memcpy(eeprom, (void *)KSEG1ADDR(addr + offset), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
++ return eeprom;
++ case BCM63XX_FLASH_TYPE_SERIAL:
++ /* the first megabyte is memory mapped */
++ if (offset < 0x100000) {
++ memcpy(eeprom, (void *)KSEG1ADDR(addr + offset), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
++ return eeprom;
++ }
++
++ if (BCMCPU_IS_6328()) {
++ /* we can change the memory mapped megabyte */
++ bcm_hsspi_writel(offset & 0xf00000, 0x18);
++ memcpy(eeprom, (void *)KSEG1ADDR(addr + (offset & 0xfffff)), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
++ bcm_hsspi_writel(0, 0x18);
++ return eeprom;
++ }
++ /* can't do anything here without talking to the SPI controller. */
++ case BCM63XX_FLASH_TYPE_NAND:
++ default:
++ return NULL;
++ }
++}
++
++static void ath9k_pci_fixup(struct pci_dev *dev)
++{
++ void __iomem *mem;
++ struct ath9k_platform_data *pdata = NULL;
++ u16 *cal_data = NULL;
++ u16 cmd;
++ u32 bar0;
++ u32 val;
++ unsigned i;
++
++ for (i = 0; i < ath9k_num_fixups; i++) {
++ if (ath9k_fixups[i].slot != PCI_SLOT(dev->devfn))
++ continue;
++
++ cal_data = ath9k_fixups[i].pdata.eeprom_data;
++ pdata = &ath9k_fixups[i].pdata;
++ break;
++ }
++
++ if (cal_data == NULL)
++ return;
++
++ if (*cal_data != 0xa55a) {
++ pr_err("pci %s: invalid calibration data\n", pci_name(dev));
++ return;
++ }
++
++ pr_info("pci %s: fixup device configuration\n", pci_name(dev));
++
++ switch (bcm63xx_get_cpu_id()) {
++ case BCM6328_CPU_ID:
++ val = BCM_PCIE_MEM_BASE_PA;
++ break;
++ case BCM6348_CPU_ID:
++ case BCM6358_CPU_ID:
++ case BCM6368_CPU_ID:
++ val = BCM_PCI_MEM_BASE_PA;
++ break;
++ default:
++ BUG();
++ }
++
++ mem = ioremap(val, 0x10000);
++ if (!mem) {
++ pr_err("pci %s: ioremap error\n", pci_name(dev));
++ return;
++ }
++
++ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
++ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, val);
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++ /* set offset to first reg address */
++ cal_data += 3;
++ while(*cal_data != 0xffff) {
++ u32 reg;
++ reg = *cal_data++;
++ val = *cal_data++;
++ val |= (*cal_data++) << 16;
++
++ writel(val, mem + reg);
++ udelay(100);
++ }
++
++ pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
++ dev->vendor = val & 0xffff;
++ dev->device = (val >> 16) & 0xffff;
++
++ pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
++ dev->revision = val & 0xff;
++ dev->class = val >> 8; /* upper 3 bytes */
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
++
++ iounmap(mem);
++
++ dev->dev.platform_data = pdata;
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
++
++void __init pci_enable_ath9k_fixup(unsigned slot, u32 offset)
++{
++ if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups))
++ return;
++
++ ath9k_fixups[ath9k_num_fixups].slot = slot;
++
++ if (!bcm63xx_read_eeprom(ath9k_fixups[ath9k_num_fixups].pdata.eeprom_data, offset))
++ return;
++
++ if (bcm63xx_nvram_get_mac_address(ath9k_fixups[ath9k_num_fixups].mac))
++ return;
++
++ ath9k_fixups[ath9k_num_fixups].pdata.macaddr = ath9k_fixups[ath9k_num_fixups].mac;
++ ath9k_num_fixups++;
++}
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
+@@ -0,0 +1,7 @@
++#ifndef _PCI_ATH9K_FIXUP
++#define _PCI_ATH9K_FIXUP
++
++
++void pci_enable_ath9k_fixup(unsigned slot, u32 offset) __init;
++
++#endif /* _PCI_ATH9K_FIXUP */
--- /dev/null
+From 8ab86c5dc38ad4de1442e50e0adbc354d9184d71 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 1 May 2012 14:38:41 +0200
+Subject: [PATCH 68/79] MTD: bcm63xxpart: allow passing a caldata offset
+
+Allow bcm63xxpart to receive a caldata offset if calibration data is
+contained in flash.
+---
+ drivers/mtd/bcm63xxpart.c | 47 ++++++++++++++++++++++++++++++++++++++--
+ include/linux/mtd/partitions.h | 2 ++
+ 2 files changed, 47 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -80,6 +80,8 @@ static int bcm63xx_parse_cfe_partitions(
+ 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;
+@@ -94,6 +96,23 @@ static int bcm63xx_parse_cfe_partitions(
+ nvramlen = bcm63xx_nvram_get_psi_size() * 1024;
+ nvramlen = roundup(nvramlen, cfe_erasesize);
+
++ 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));
+ if (!buf)
+@@ -144,7 +163,7 @@ static int bcm63xx_parse_cfe_partitions(
+ rootfsaddr = 0;
+ spareaddr = cfelen;
+ }
+- sparelen = master->size - spareaddr - nvramlen;
++ sparelen = master->size - spareaddr - nvramlen - caldatalen1 - caldatalen2;
+
+ /* Determine number of partitions */
+ if (rootfslen > 0)
+@@ -153,6 +172,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) {
+@@ -190,6 +215,23 @@ 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].size = nvramlen;
+@@ -198,7 +240,8 @@ 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 = master->size - cfelen - nvramlen;
++ parts[curpart].size = master->size - cfelen - nvramlen
++ - caldatalen1 - caldatalen2;
+
+ 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
+@@ -58,10 +58,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;
+ };
+
--- /dev/null
+From 977f8a30103b9c4992cab8f49357fe0d4274004f Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 3 May 2012 14:55:26 +0200
+Subject: [PATCH 69/80] MIPS: BCM63XX: pass caldata info to flash
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
+ arch/mips/bcm63xx/dev-flash.c | 9 ++++++++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 4 +++-
+ 3 files changed, 12 insertions(+), 3 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -912,7 +912,7 @@ int __init board_register_devices(void)
+ if (board.num_spis)
+ spi_register_board_info(board.spis, board.num_spis);
+
+- bcm63xx_flash_register();
++ bcm63xx_flash_register(board.has_caldata, board.caldata);
+
+ /* count number of LEDs defined by this device */
+ while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -35,12 +35,15 @@ static struct mtd_partition mtd_partitio
+ }
+ };
+
++static struct mtd_part_parser_data bcm63xx_parser_data;
++
+ static const char *bcm63xx_part_types[] = { "bcm63xxpart", "RedBoot", NULL };
+
+ static struct physmap_flash_data flash_data = {
+ .width = 2,
+ .parts = mtd_partitions,
+ .part_probe_types = bcm63xx_part_types,
++ .pp_data = &bcm63xx_parser_data,
+ };
+
+ static struct resource mtd_resources[] = {
+@@ -62,6 +65,7 @@ static struct platform_device mtd_dev =
+
+ static struct flash_platform_data bcm63xx_flash_data = {
+ .part_probe_types = bcm63xx_part_types,
++ .pp_data = &bcm63xx_parser_data,
+ };
+
+ static struct spi_board_info bcm63xx_spi_flash_info[] = {
+@@ -130,10 +134,13 @@ static int __init bcm63xx_detect_flash_t
+ return 0;
+ }
+
+-int __init bcm63xx_flash_register(void)
++int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata)
+ {
+ u32 val;
++ unsigned int i;
+
++ for (i = 0; i < num_caldata; i++)
++ bcm63xx_parser_data.caldata[i] = caldata[i].caldata_offset;
+
+ bcm63xx_detect_flash_type();
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+@@ -1,6 +1,8 @@
+ #ifndef __BCM63XX_FLASH_H
+ #define __BCM63XX_FLASH_H
+
++#include <board_bcm963xx.h>
++
+ enum {
+ BCM63XX_FLASH_TYPE_PARALLEL,
+ BCM63XX_FLASH_TYPE_SERIAL,
+@@ -9,6 +11,6 @@ enum {
+
+ extern int bcm63xx_attached_flash;
+
+-int __init bcm63xx_flash_register(void);
++int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata);
+
+ #endif /* __BCM63XX_FLASH_H */
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -2015,6 +2015,80 @@ static struct board_info __initdata boar
+@@ -2015,6 +2015,78 @@ static struct board_info __initdata boar
#endif
/*
+ [4] = {
+ .used = 1,
+ .phy_id = 0x12,
-+ .external_phy = 1,
+ .name = "port0",
+ },
+
+ [5] = {
+ .used = 1,
+ .phy_id = 0x11,
-+ .external_phy = 1,
+ .name = "port3",
+ },
+ },
* all boards
*/
static const struct board_info __initdata *bcm963xx_boards[] = {
-@@ -2063,6 +2137,10 @@ static const struct board_info __initdat
+@@ -2063,6 +2135,10 @@ static const struct board_info __initdat
&board_HW553,
&board_spw303v,
#endif
};
static void __init nb4_nvram_fixup(void)
-@@ -2244,12 +2322,25 @@ void __init board_prom_init(void)
+@@ -2244,12 +2320,25 @@ void __init board_prom_init(void)
bcm63xx_pci_enabled = 1;
if (BCMCPU_IS_6348())
val |= GPIO_MODE_6348_G2_PCI;
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -2086,6 +2086,72 @@ static struct board_info __initdata boar
+@@ -2084,6 +2084,72 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_ehci0 = 1,
};
#endif
/*
-@@ -2140,6 +2206,7 @@ static const struct board_info __initdat
+@@ -2138,6 +2204,7 @@ static const struct board_info __initdat
#ifdef CONFIG_BCM63XX_CPU_6368
&board_96368mvwg,
* known 6338 boards
*/
#ifdef CONFIG_BCM63XX_CPU_6338
-@@ -2158,6 +2232,9 @@ static struct board_info __initdata boar
+@@ -2156,6 +2230,9 @@ static struct board_info __initdata boar
* all boards
*/
static const struct board_info __initdata *bcm963xx_boards[] = {
#endif
/*
-@@ -2234,6 +2304,7 @@ static struct board_info __initdata boar
+@@ -2232,6 +2302,7 @@ static struct board_info __initdata boar
static const struct board_info __initdata *bcm963xx_boards[] = {
#ifdef CONFIG_BCM63XX_CPU_6328
&board_96328avng,
#endif
/*
-@@ -2305,6 +2408,7 @@ static const struct board_info __initdat
+@@ -2303,6 +2406,7 @@ static const struct board_info __initdat
#ifdef CONFIG_BCM63XX_CPU_6328
&board_96328avng,
&board_963281TAN,
#endif
/*
-@@ -2438,6 +2489,7 @@ static const struct board_info __initdat
+@@ -2436,6 +2487,7 @@ static const struct board_info __initdat
&board_ct536_ct5621,
&board_96348A_122,
&board_CPVA502plus,
static struct board_info __initdata board_HW553 = {
.name = "HW553",
.expected_cpu_id = 0x6358,
-@@ -2504,6 +2616,7 @@ static const struct board_info __initdat
+@@ -2502,6 +2614,7 @@ static const struct board_info __initdat
&board_nb4_ser_r2,
&board_nb4_fxc_r1,
&board_nb4_fxc_r2,
#endif
/*
-@@ -2619,6 +2684,7 @@ static const struct board_info __initdat
+@@ -2617,6 +2682,7 @@ static const struct board_info __initdat
&board_ct6373_1,
&board_HW553,
&board_spw303v,
#include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h>
#include <linux/spi/74x164.h>
-@@ -2831,7 +2832,7 @@ static void __init nb4_nvram_fixup(void)
+@@ -2829,7 +2830,7 @@ static void __init nb4_nvram_fixup(void)
* bcm4318 WLAN work
*/
#ifdef CONFIG_SSB_PCIHOST
.revision = 0x02,
.board_rev = 0x17,
.country_code = 0x0,
-@@ -2851,6 +2852,7 @@ static struct ssb_sprom bcm63xx_sprom =
+@@ -2849,6 +2850,7 @@ static struct ssb_sprom bcm63xx_sprom =
.boardflags_lo = 0x2848,
.boardflags_hi = 0x0000,
};