bcm63xx: add kernel 5.10 support

Runtime-tested on Comtrend AR-5387un.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
This commit is contained in:
Álvaro Fernández Rojas 2021-02-17 19:07:23 +01:00
parent 5bb9954826
commit f323dec4f8
141 changed files with 21640 additions and 0 deletions

View File

@ -11,6 +11,7 @@ BOARDNAME:=Broadcom BCM63xx
SUBTARGETS:=generic smp
FEATURES:=squashfs usb atm pci pcmcia usbgadget
KERNEL_PATCHVER:=5.4
KERNEL_TESTING_PATCHVER:=5.10
define Target/Description
Build firmware images for Broadcom based xDSL/routers

View File

@ -0,0 +1,229 @@
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_MMAP_RND_BITS_MAX=15
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_BCM6345_EXT_IRQ=y
CONFIG_BCM6345_PERIPH_IRQ=y
CONFIG_BCM63XX=y
CONFIG_BCM63XX_CPU_3368=y
CONFIG_BCM63XX_CPU_6318=y
CONFIG_BCM63XX_CPU_63268=y
CONFIG_BCM63XX_CPU_6328=y
CONFIG_BCM63XX_CPU_6338=y
CONFIG_BCM63XX_CPU_6345=y
CONFIG_BCM63XX_CPU_6348=y
CONFIG_BCM63XX_CPU_6358=y
CONFIG_BCM63XX_CPU_6362=y
CONFIG_BCM63XX_CPU_6368=y
CONFIG_BCM63XX_EHCI=y
CONFIG_BCM63XX_ENET=y
CONFIG_BCM63XX_OHCI=y
CONFIG_BCM63XX_PHY=y
CONFIG_BCM63XX_WDT=y
CONFIG_BCMA=y
CONFIG_BCMA_BLOCKIO=y
# CONFIG_BCMA_DEBUG is not set
# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
# CONFIG_BCMA_DRIVER_MIPS is not set
CONFIG_BCMA_DRIVER_PCI=y
# CONFIG_BCMA_DRIVER_PCI_HOSTMODE is not set
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
# CONFIG_BCMA_HOST_SOC is not set
CONFIG_BCM_NET_PHYLIB=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BOARD_BCM63XX_DT=y
CONFIG_BOARD_BCM963XX=y
CONFIG_BOARD_LIVEBOX=y
CONFIG_CEVT_R4K=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_CPU_BMIPS=y
CONFIG_CPU_BMIPS32_3300=y
CONFIG_CPU_BMIPS4350=y
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_MIPS32=y
CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
CONFIG_CPU_NO_EFFICIENT_FFS=y
CONFIG_CPU_R4K_CACHE_TLB=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_CPUFREQ=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CRASH_CORE=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2
CONFIG_CRYPTO_RNG2=y
CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DTC=y
CONFIG_EARLY_PRINTK=y
CONFIG_FIXED_PHY=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_LIB_ASHLDI3=y
CONFIG_GENERIC_LIB_ASHRDI3=y
CONFIG_GENERIC_LIB_CMPDI2=y
CONFIG_GENERIC_LIB_LSHRDI3=y
CONFIG_GENERIC_LIB_UCMPDI2=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_PINCTRL_GROUPS=y
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_BCM63XX=y
CONFIG_GPIO_GENERIC=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_BCM2835=y
CONFIG_HZ=250
CONFIG_HZ_250=y
CONFIG_HZ_PERIODIC=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_MIPS_CPU=y
CONFIG_IRQ_WORK=y
CONFIG_KEXEC=y
CONFIG_KEXEC_CORE=y
CONFIG_LEDS_BCM6328=y
CONFIG_LEDS_BCM6358=y
CONFIG_LEDS_GPIO=y
CONFIG_LIBFDT=y
CONFIG_LLD_VERSION=0
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MEMFD_CREATE=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MIPS=y
CONFIG_MIPS_ASID_BITS=8
CONFIG_MIPS_ASID_SHIFT=0
CONFIG_MIPS_CBPF_JIT=y
CONFIG_MIPS_CLOCK_VSYSCALL=y
# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set
# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
CONFIG_MIPS_CMDLINE_FROM_DTB=y
# CONFIG_MIPS_ELF_APPENDED_DTB is not set
CONFIG_MIPS_EXTERNAL_TIMER=y
CONFIG_MIPS_L1_CACHE_SHIFT=4
CONFIG_MIPS_L1_CACHE_SHIFT_4=y
CONFIG_MIPS_LD_CAN_LINK_VDSO=y
# CONFIG_MIPS_NO_APPENDED_DTB is not set
CONFIG_MIPS_RAW_APPENDED_DTB=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MTD_BCM63XX_PARTS=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_BE_BYTE_SWAP=y
# CONFIG_MTD_CFI_GEOMETRY is not set
# CONFIG_MTD_CFI_NOSWAP is not set
CONFIG_MTD_CFI_STAA=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_PARSER_IMAGETAG=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_SPI_NOR=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
CONFIG_NVMEM=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_NET=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DRIVERS_LEGACY=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_BCM6318=y
CONFIG_PINCTRL_BCM63268=y
CONFIG_PINCTRL_BCM6328=y
CONFIG_PINCTRL_BCM6348=y
CONFIG_PINCTRL_BCM6358=y
CONFIG_PINCTRL_BCM6362=y
CONFIG_PINCTRL_BCM6368=y
CONFIG_PINCTRL_BCM63XX=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_REGMAP=y
CONFIG_REGMAP_MMIO=y
CONFIG_RELAY=y
CONFIG_RTL8366_SMI=y
CONFIG_RTL8367_PHY=y
# CONFIG_SERIAL_8250 is not set
CONFIG_SERIAL_BCM63XX=y
CONFIG_SERIAL_BCM63XX_CONSOLE=y
CONFIG_SPI=y
CONFIG_SPI_BCM63XX=y
CONFIG_SPI_BCM63XX_HSSPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SRCU=y
CONFIG_SSB=y
CONFIG_SSB_B43_PCI_BRIDGE=y
CONFIG_SSB_BLOCKIO=y
# CONFIG_SSB_DRIVER_MIPS is not set
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_PCIHOST=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_SPROM=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_SWCONFIG=y
CONFIG_SWCONFIG_B53=y
CONFIG_SWCONFIG_B53_MMAP_DRIVER=y
CONFIG_SWCONFIG_B53_PHY_DRIVER=y
CONFIG_SWCONFIG_B53_PHY_FIXUP=y
CONFIG_SWCONFIG_B53_SPI_DRIVER=y
CONFIG_SWPHY=y
CONFIG_SYNC_R4K=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_SYS_HAS_CPU_BMIPS=y
CONFIG_SYS_HAS_CPU_BMIPS32_3300=y
CONFIG_SYS_HAS_CPU_BMIPS4350=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y
CONFIG_SYS_SUPPORTS_SMP=y
CONFIG_TARGET_ISA_REV=0
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TINY_SRCU=y
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_WEAK_ORDERING=y

View File

@ -0,0 +1,55 @@
From 9cbfea02c1dbee0afb9128f065e6e793672b9ff7 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:02 +0800
Subject: [PATCH 1/7] bcm63xx_enet: batch process rx path
Use netif_receive_skb_list to batch process rx skb.
Tested on BCM6328 320 MHz using iperf3 -M 512, increasing performance
by 12.5%.
Before:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-30.00 sec 120 MBytes 33.7 Mbits/sec 277 sender
[ 4] 0.00-30.00 sec 120 MBytes 33.5 Mbits/sec receiver
After:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-30.00 sec 136 MBytes 37.9 Mbits/sec 203 sender
[ 4] 0.00-30.00 sec 135 MBytes 37.7 Mbits/sec receiver
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -297,10 +297,12 @@ static void bcm_enet_refill_rx_timer(str
static int bcm_enet_receive_queue(struct net_device *dev, int budget)
{
struct bcm_enet_priv *priv;
+ struct list_head rx_list;
struct device *kdev;
int processed;
priv = netdev_priv(dev);
+ INIT_LIST_HEAD(&rx_list);
kdev = &priv->pdev->dev;
processed = 0;
@@ -391,10 +393,12 @@ static int bcm_enet_receive_queue(struct
skb->protocol = eth_type_trans(skb, dev);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
- netif_receive_skb(skb);
+ list_add_tail(&skb->list, &rx_list);
} while (--budget > 0);
+ netif_receive_skb_list(&rx_list);
+
if (processed || !priv->rx_desc_count) {
bcm_enet_refill_rx(dev);

View File

@ -0,0 +1,68 @@
From 4c59b0f5543db80abbbe9efdd9b25e7899501db5 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:03 +0800
Subject: [PATCH 2/7] bcm63xx_enet: add BQL support
Add Byte Queue Limits support to reduce/remove bufferbloat in
bcm63xx_enet.
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -417,9 +417,11 @@ static int bcm_enet_receive_queue(struct
static int bcm_enet_tx_reclaim(struct net_device *dev, int force)
{
struct bcm_enet_priv *priv;
+ unsigned int bytes;
int released;
priv = netdev_priv(dev);
+ bytes = 0;
released = 0;
while (priv->tx_desc_count < priv->tx_ring_size) {
@@ -456,10 +458,13 @@ static int bcm_enet_tx_reclaim(struct ne
if (desc->len_stat & DMADESC_UNDER_MASK)
dev->stats.tx_errors++;
+ bytes += skb->len;
dev_kfree_skb(skb);
released++;
}
+ netdev_completed_queue(dev, released, bytes);
+
if (netif_queue_stopped(dev) && released)
netif_wake_queue(dev);
@@ -626,6 +631,8 @@ bcm_enet_start_xmit(struct sk_buff *skb,
desc->len_stat = len_stat;
wmb();
+ netdev_sent_queue(dev, skb->len);
+
/* kick tx dma */
enet_dmac_writel(priv, priv->dma_chan_en_mask,
ENETDMAC_CHANCFG, priv->tx_chan);
@@ -1169,6 +1176,7 @@ static int bcm_enet_stop(struct net_devi
kdev = &priv->pdev->dev;
netif_stop_queue(dev);
+ netdev_reset_queue(dev);
napi_disable(&priv->napi);
if (priv->has_phy)
phy_stop(dev->phydev);
@@ -2338,6 +2346,7 @@ static int bcm_enetsw_stop(struct net_de
del_timer_sync(&priv->swphy_poll);
netif_stop_queue(dev);
+ netdev_reset_queue(dev);
napi_disable(&priv->napi);
del_timer_sync(&priv->rx_timeout);

View File

@ -0,0 +1,26 @@
From 375281d3a6dcabaa98f489ee412aedca6d99dffb Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:04 +0800
Subject: [PATCH 3/7] bcm63xx_enet: add xmit_more support
Support bulking hardware TX queue by using netdev_xmit_more().
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -634,7 +634,8 @@ bcm_enet_start_xmit(struct sk_buff *skb,
netdev_sent_queue(dev, skb->len);
/* kick tx dma */
- enet_dmac_writel(priv, priv->dma_chan_en_mask,
+ if (!netdev_xmit_more() || !priv->tx_desc_count)
+ enet_dmac_writel(priv, priv->dma_chan_en_mask,
ENETDMAC_CHANCFG, priv->tx_chan);
/* stop queue if no more desc available */

View File

@ -0,0 +1,45 @@
From c4a207865e7ea310dc146ff4aa1b0aa0c78d3fe1 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:05 +0800
Subject: [PATCH 4/7] bcm63xx_enet: alloc rx skb with NET_IP_ALIGN
Use netdev_alloc_skb_ip_align on newer SoCs with integrated switch
(enetsw) when refilling RX. Increases packet processing performance
by 30% (with netif_receive_skb_list).
Non-enetsw SoCs cannot function with the extra pad so continue to use
the regular netdev_alloc_skb.
Tested on BCM6328 320 MHz and iperf3 -M 512 to measure packet/sec
performance.
Before:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-30.00 sec 120 MBytes 33.7 Mbits/sec 277 sender
[ 4] 0.00-30.00 sec 120 MBytes 33.5 Mbits/sec receiver
After (+netif_receive_skb_list):
[ 4] 0.00-30.00 sec 155 MBytes 43.3 Mbits/sec 354 sender
[ 4] 0.00-30.00 sec 154 MBytes 43.1 Mbits/sec receiver
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -237,7 +237,10 @@ static int bcm_enet_refill_rx(struct net
desc = &priv->rx_desc_cpu[desc_idx];
if (!priv->rx_skb[desc_idx]) {
- skb = netdev_alloc_skb(dev, priv->rx_skb_size);
+ if (priv->enet_is_sw)
+ skb = netdev_alloc_skb_ip_align(dev, priv->rx_skb_size);
+ else
+ skb = netdev_alloc_skb(dev, priv->rx_skb_size);
if (!skb)
break;
priv->rx_skb[desc_idx] = skb;

View File

@ -0,0 +1,142 @@
From 3d0b72654b0c8304424503e7560ee8635dd56340 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:06 +0800
Subject: [PATCH 5/7] bcm63xx_enet: consolidate rx SKB ring cleanup code
The rx SKB ring use the same code for cleanup at various points.
Combine them into a function to reduce lines of code.
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 72 ++++++--------------
1 file changed, 22 insertions(+), 50 deletions(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -860,6 +860,24 @@ static void bcm_enet_adjust_link(struct
priv->pause_tx ? "tx" : "off");
}
+static void bcm_enet_free_rx_skb_ring(struct device *kdev, struct bcm_enet_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->rx_ring_size; i++) {
+ struct bcm_enet_desc *desc;
+
+ if (!priv->rx_skb[i])
+ continue;
+
+ desc = &priv->rx_desc_cpu[i];
+ dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
+ DMA_FROM_DEVICE);
+ kfree_skb(priv->rx_skb[i]);
+ }
+ kfree(priv->rx_skb);
+}
+
/*
* open callback, allocate dma rings & buffers and start rx operation
*/
@@ -1084,18 +1102,7 @@ static int bcm_enet_open(struct net_devi
return 0;
out:
- for (i = 0; i < priv->rx_ring_size; i++) {
- struct bcm_enet_desc *desc;
-
- if (!priv->rx_skb[i])
- continue;
-
- desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
- DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
- }
- kfree(priv->rx_skb);
+ bcm_enet_free_rx_skb_ring(kdev, priv);
out_free_tx_skb:
kfree(priv->tx_skb);
@@ -1174,7 +1181,6 @@ static int bcm_enet_stop(struct net_devi
{
struct bcm_enet_priv *priv;
struct device *kdev;
- int i;
priv = netdev_priv(dev);
kdev = &priv->pdev->dev;
@@ -1203,20 +1209,9 @@ static int bcm_enet_stop(struct net_devi
bcm_enet_tx_reclaim(dev, 1);
/* free the rx skb ring */
- for (i = 0; i < priv->rx_ring_size; i++) {
- struct bcm_enet_desc *desc;
-
- if (!priv->rx_skb[i])
- continue;
-
- desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
- DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
- }
+ bcm_enet_free_rx_skb_ring(kdev, priv);
/* free remaining allocated memory */
- kfree(priv->rx_skb);
kfree(priv->tx_skb);
dma_free_coherent(kdev, priv->rx_desc_alloc_size,
priv->rx_desc_cpu, priv->rx_desc_dma);
@@ -2303,18 +2298,7 @@ static int bcm_enetsw_open(struct net_de
return 0;
out:
- for (i = 0; i < priv->rx_ring_size; i++) {
- struct bcm_enet_desc *desc;
-
- if (!priv->rx_skb[i])
- continue;
-
- desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
- DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
- }
- kfree(priv->rx_skb);
+ bcm_enet_free_rx_skb_ring(kdev, priv);
out_free_tx_skb:
kfree(priv->tx_skb);
@@ -2343,7 +2327,6 @@ static int bcm_enetsw_stop(struct net_de
{
struct bcm_enet_priv *priv;
struct device *kdev;
- int i;
priv = netdev_priv(dev);
kdev = &priv->pdev->dev;
@@ -2366,20 +2349,9 @@ static int bcm_enetsw_stop(struct net_de
bcm_enet_tx_reclaim(dev, 1);
/* free the rx skb ring */
- for (i = 0; i < priv->rx_ring_size; i++) {
- struct bcm_enet_desc *desc;
-
- if (!priv->rx_skb[i])
- continue;
-
- desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
- DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
- }
+ bcm_enet_free_rx_skb_ring(kdev, priv);
/* free remaining allocated memory */
- kfree(priv->rx_skb);
kfree(priv->tx_skb);
dma_free_coherent(kdev, priv->rx_desc_alloc_size,
priv->rx_desc_cpu, priv->rx_desc_dma);

View File

@ -0,0 +1,347 @@
From d27de0ef5ef995df2cc5f5c006c0efcf0a62b6af Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:07 +0800
Subject: [PATCH 6/7] bcm63xx_enet: convert to build_skb
We can increase the efficiency of rx path by using buffers to receive
packets then build SKBs around them just before passing into the network
stack. In contrast, preallocating SKBs too early reduces CPU cache
efficiency.
Check if we're in NAPI context when refilling RX. Normally we're almost
always running in NAPI context. Dispatch to napi_alloc_frag directly
instead of relying on netdev_alloc_frag which does the same but
with the overhead of local_bh_disable/enable.
Tested on BCM6328 320 MHz and iperf3 -M 512 to measure packet/sec
performance. Included netif_receive_skb_list and NET_IP_ALIGN
optimizations.
Before:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 49.9 MBytes 41.9 Mbits/sec 197 sender
[ 4] 0.00-10.00 sec 49.3 MBytes 41.3 Mbits/sec receiver
After:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-30.00 sec 171 MBytes 47.8 Mbits/sec 272 sender
[ 4] 0.00-30.00 sec 170 MBytes 47.6 Mbits/sec receiver
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 111 ++++++++++---------
drivers/net/ethernet/broadcom/bcm63xx_enet.h | 14 ++-
2 files changed, 71 insertions(+), 54 deletions(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -220,7 +220,7 @@ static void bcm_enet_mdio_write_mii(stru
/*
* refill rx queue
*/
-static int bcm_enet_refill_rx(struct net_device *dev)
+static int bcm_enet_refill_rx(struct net_device *dev, bool napi_mode)
{
struct bcm_enet_priv *priv;
@@ -228,29 +228,29 @@ static int bcm_enet_refill_rx(struct net
while (priv->rx_desc_count < priv->rx_ring_size) {
struct bcm_enet_desc *desc;
- struct sk_buff *skb;
- dma_addr_t p;
int desc_idx;
u32 len_stat;
desc_idx = priv->rx_dirty_desc;
desc = &priv->rx_desc_cpu[desc_idx];
- if (!priv->rx_skb[desc_idx]) {
- if (priv->enet_is_sw)
- skb = netdev_alloc_skb_ip_align(dev, priv->rx_skb_size);
+ if (!priv->rx_buf[desc_idx]) {
+ void *buf;
+
+ if (likely(napi_mode))
+ buf = napi_alloc_frag(priv->rx_frag_size);
else
- skb = netdev_alloc_skb(dev, priv->rx_skb_size);
- if (!skb)
+ buf = netdev_alloc_frag(priv->rx_frag_size);
+ if (unlikely(!buf))
break;
- priv->rx_skb[desc_idx] = skb;
- p = dma_map_single(&priv->pdev->dev, skb->data,
- priv->rx_skb_size,
- DMA_FROM_DEVICE);
- desc->address = p;
+ priv->rx_buf[desc_idx] = buf;
+ desc->address = dma_map_single(&priv->pdev->dev,
+ buf + priv->rx_buf_offset,
+ priv->rx_buf_size,
+ DMA_FROM_DEVICE);
}
- len_stat = priv->rx_skb_size << DMADESC_LENGTH_SHIFT;
+ len_stat = priv->rx_buf_size << DMADESC_LENGTH_SHIFT;
len_stat |= DMADESC_OWNER_MASK;
if (priv->rx_dirty_desc == priv->rx_ring_size - 1) {
len_stat |= (DMADESC_WRAP_MASK >> priv->dma_desc_shift);
@@ -290,7 +290,7 @@ static void bcm_enet_refill_rx_timer(str
struct net_device *dev = priv->net_dev;
spin_lock(&priv->rx_lock);
- bcm_enet_refill_rx(dev);
+ bcm_enet_refill_rx(dev, false);
spin_unlock(&priv->rx_lock);
}
@@ -320,6 +320,7 @@ static int bcm_enet_receive_queue(struct
int desc_idx;
u32 len_stat;
unsigned int len;
+ void *buf;
desc_idx = priv->rx_curr_desc;
desc = &priv->rx_desc_cpu[desc_idx];
@@ -365,16 +366,14 @@ static int bcm_enet_receive_queue(struct
}
/* valid packet */
- skb = priv->rx_skb[desc_idx];
+ buf = priv->rx_buf[desc_idx];
len = (len_stat & DMADESC_LENGTH_MASK) >> DMADESC_LENGTH_SHIFT;
/* don't include FCS */
len -= 4;
if (len < copybreak) {
- struct sk_buff *nskb;
-
- nskb = napi_alloc_skb(&priv->napi, len);
- if (!nskb) {
+ skb = napi_alloc_skb(&priv->napi, len);
+ if (unlikely(!skb)) {
/* forget packet, just rearm desc */
dev->stats.rx_dropped++;
continue;
@@ -382,14 +381,21 @@ static int bcm_enet_receive_queue(struct
dma_sync_single_for_cpu(kdev, desc->address,
len, DMA_FROM_DEVICE);
- memcpy(nskb->data, skb->data, len);
+ memcpy(skb->data, buf + priv->rx_buf_offset, len);
dma_sync_single_for_device(kdev, desc->address,
len, DMA_FROM_DEVICE);
- skb = nskb;
} else {
- dma_unmap_single(&priv->pdev->dev, desc->address,
- priv->rx_skb_size, DMA_FROM_DEVICE);
- priv->rx_skb[desc_idx] = NULL;
+ dma_unmap_single(kdev, desc->address,
+ priv->rx_buf_size, DMA_FROM_DEVICE);
+ priv->rx_buf[desc_idx] = NULL;
+
+ skb = build_skb(buf, priv->rx_frag_size);
+ if (unlikely(!skb)) {
+ skb_free_frag(buf);
+ dev->stats.rx_dropped++;
+ continue;
+ }
+ skb_reserve(skb, priv->rx_buf_offset);
}
skb_put(skb, len);
@@ -403,7 +409,7 @@ static int bcm_enet_receive_queue(struct
netif_receive_skb_list(&rx_list);
if (processed || !priv->rx_desc_count) {
- bcm_enet_refill_rx(dev);
+ bcm_enet_refill_rx(dev, true);
/* kick rx dma */
enet_dmac_writel(priv, priv->dma_chan_en_mask,
@@ -860,22 +866,22 @@ static void bcm_enet_adjust_link(struct
priv->pause_tx ? "tx" : "off");
}
-static void bcm_enet_free_rx_skb_ring(struct device *kdev, struct bcm_enet_priv *priv)
+static void bcm_enet_free_rx_buf_ring(struct device *kdev, struct bcm_enet_priv *priv)
{
int i;
for (i = 0; i < priv->rx_ring_size; i++) {
struct bcm_enet_desc *desc;
- if (!priv->rx_skb[i])
+ if (!priv->rx_buf[i])
continue;
desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
+ dma_unmap_single(kdev, desc->address, priv->rx_buf_size,
DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
+ skb_free_frag(priv->rx_buf[i]);
}
- kfree(priv->rx_skb);
+ kfree(priv->rx_buf);
}
/*
@@ -987,10 +993,10 @@ static int bcm_enet_open(struct net_devi
priv->tx_curr_desc = 0;
spin_lock_init(&priv->tx_lock);
- /* init & fill rx ring with skbs */
- priv->rx_skb = kcalloc(priv->rx_ring_size, sizeof(struct sk_buff *),
+ /* init & fill rx ring with buffers */
+ priv->rx_buf = kcalloc(priv->rx_ring_size, sizeof(void *),
GFP_KERNEL);
- if (!priv->rx_skb) {
+ if (!priv->rx_buf) {
ret = -ENOMEM;
goto out_free_tx_skb;
}
@@ -1007,8 +1013,8 @@ static int bcm_enet_open(struct net_devi
enet_dmac_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
ENETDMAC_BUFALLOC, priv->rx_chan);
- if (bcm_enet_refill_rx(dev)) {
- dev_err(kdev, "cannot allocate rx skb queue\n");
+ if (bcm_enet_refill_rx(dev, false)) {
+ dev_err(kdev, "cannot allocate rx buffer queue\n");
ret = -ENOMEM;
goto out;
}
@@ -1102,7 +1108,7 @@ static int bcm_enet_open(struct net_devi
return 0;
out:
- bcm_enet_free_rx_skb_ring(kdev, priv);
+ bcm_enet_free_rx_buf_ring(kdev, priv);
out_free_tx_skb:
kfree(priv->tx_skb);
@@ -1208,8 +1214,8 @@ static int bcm_enet_stop(struct net_devi
/* force reclaim of all tx buffers */
bcm_enet_tx_reclaim(dev, 1);
- /* free the rx skb ring */
- bcm_enet_free_rx_skb_ring(kdev, priv);
+ /* free the rx buffer ring */
+ bcm_enet_free_rx_buf_ring(kdev, priv);
/* free remaining allocated memory */
kfree(priv->tx_skb);
@@ -1633,9 +1639,12 @@ static int bcm_enet_change_mtu(struct ne
* align rx buffer size to dma burst len, account FCS since
* it's appended
*/
- priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
+ priv->rx_buf_size = ALIGN(actual_mtu + ETH_FCS_LEN,
priv->dma_maxburst * 4);
+ priv->rx_frag_size = SKB_DATA_ALIGN(priv->rx_buf_offset + priv->rx_buf_size) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
dev->mtu = new_mtu;
return 0;
}
@@ -1720,6 +1729,7 @@ static int bcm_enet_probe(struct platfor
priv->enet_is_sw = false;
priv->dma_maxburst = BCMENET_DMA_MAXBURST;
+ priv->rx_buf_offset = NET_SKB_PAD;
ret = bcm_enet_change_mtu(dev, dev->mtu);
if (ret)
@@ -2137,7 +2147,7 @@ static int bcm_enetsw_open(struct net_de
priv->tx_skb = kcalloc(priv->tx_ring_size, sizeof(struct sk_buff *),
GFP_KERNEL);
if (!priv->tx_skb) {
- dev_err(kdev, "cannot allocate rx skb queue\n");
+ dev_err(kdev, "cannot allocate tx skb queue\n");
ret = -ENOMEM;
goto out_free_tx_ring;
}
@@ -2147,11 +2157,11 @@ static int bcm_enetsw_open(struct net_de
priv->tx_curr_desc = 0;
spin_lock_init(&priv->tx_lock);
- /* init & fill rx ring with skbs */
- priv->rx_skb = kcalloc(priv->rx_ring_size, sizeof(struct sk_buff *),
+ /* init & fill rx ring with buffers */
+ priv->rx_buf = kcalloc(priv->rx_ring_size, sizeof(void *),
GFP_KERNEL);
- if (!priv->rx_skb) {
- dev_err(kdev, "cannot allocate rx skb queue\n");
+ if (!priv->rx_buf) {
+ dev_err(kdev, "cannot allocate rx buffer queue\n");
ret = -ENOMEM;
goto out_free_tx_skb;
}
@@ -2198,8 +2208,8 @@ static int bcm_enetsw_open(struct net_de
enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
ENETDMA_BUFALLOC_REG(priv->rx_chan));
- if (bcm_enet_refill_rx(dev)) {
- dev_err(kdev, "cannot allocate rx skb queue\n");
+ if (bcm_enet_refill_rx(dev, false)) {
+ dev_err(kdev, "cannot allocate rx buffer queue\n");
ret = -ENOMEM;
goto out;
}
@@ -2298,7 +2308,7 @@ static int bcm_enetsw_open(struct net_de
return 0;
out:
- bcm_enet_free_rx_skb_ring(kdev, priv);
+ bcm_enet_free_rx_buf_ring(kdev, priv);
out_free_tx_skb:
kfree(priv->tx_skb);
@@ -2348,8 +2358,8 @@ static int bcm_enetsw_stop(struct net_de
/* force reclaim of all tx buffers */
bcm_enet_tx_reclaim(dev, 1);
- /* free the rx skb ring */
- bcm_enet_free_rx_skb_ring(kdev, priv);
+ /* free the rx buffer ring */
+ bcm_enet_free_rx_buf_ring(kdev, priv);
/* free remaining allocated memory */
kfree(priv->tx_skb);
@@ -2648,6 +2658,7 @@ static int bcm_enetsw_probe(struct platf
priv->rx_ring_size = BCMENET_DEF_RX_DESC;
priv->tx_ring_size = BCMENET_DEF_TX_DESC;
priv->dma_maxburst = BCMENETSW_DMA_MAXBURST;
+ priv->rx_buf_offset = NET_SKB_PAD + NET_IP_ALIGN;
pd = dev_get_platdata(&pdev->dev);
if (pd) {
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
@@ -230,11 +230,17 @@ struct bcm_enet_priv {
/* next dirty rx descriptor to refill */
int rx_dirty_desc;
- /* size of allocated rx skbs */
- unsigned int rx_skb_size;
+ /* size of allocated rx buffers */
+ unsigned int rx_buf_size;
- /* list of skb given to hw for rx */
- struct sk_buff **rx_skb;
+ /* allocated rx buffer offset */
+ unsigned int rx_buf_offset;
+
+ /* size of allocated rx frag */
+ unsigned int rx_frag_size;
+
+ /* list of buffer given to hw for rx */
+ void **rx_buf;
/* used when rx skb allocation failed, so we defer rx queue
* refill */

View File

@ -0,0 +1,40 @@
From ae2259eebeacb7753e3043278957b45840123972 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:08 +0800
Subject: [PATCH 7/7] bcm63xx_enet: improve rx loop
Use existing rx processed count to track against budget, thereby making
budget decrement operation redundant.
rx_desc_count can be calculated outside the rx loop, making the loop a
bit smaller.
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -339,7 +339,6 @@ static int bcm_enet_receive_queue(struct
priv->rx_curr_desc++;
if (priv->rx_curr_desc == priv->rx_ring_size)
priv->rx_curr_desc = 0;
- priv->rx_desc_count--;
/* if the packet does not have start of packet _and_
* end of packet flag set, then just recycle it */
@@ -404,9 +403,10 @@ static int bcm_enet_receive_queue(struct
dev->stats.rx_bytes += len;
list_add_tail(&skb->list, &rx_list);
- } while (--budget > 0);
+ } while (processed < budget);
netif_receive_skb_list(&rx_list);
+ priv->rx_desc_count -= processed;
if (processed || !priv->rx_desc_count) {
bcm_enet_refill_rx(dev, true);

View File

@ -0,0 +1,35 @@
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1104,6 +1104,8 @@ static int bcm_enet_open(struct net_devi
else
bcm_enet_adjust_link(dev);
+ netdev_reset_queue(dev);
+
netif_start_queue(dev);
return 0;
@@ -1192,7 +1194,6 @@ static int bcm_enet_stop(struct net_devi
kdev = &priv->pdev->dev;
netif_stop_queue(dev);
- netdev_reset_queue(dev);
napi_disable(&priv->napi);
if (priv->has_phy)
phy_stop(dev->phydev);
@@ -2262,6 +2263,7 @@ static int bcm_enetsw_open(struct net_de
enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
ENETDMAC_IRMASK, priv->tx_chan);
+ netdev_reset_queue(dev);
netif_carrier_on(dev);
netif_start_queue(dev);
@@ -2343,7 +2345,6 @@ static int bcm_enetsw_stop(struct net_de
del_timer_sync(&priv->swphy_poll);
netif_stop_queue(dev);
- netdev_reset_queue(dev);
napi_disable(&priv->napi);
del_timer_sync(&priv->rx_timeout);

View File

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

View File

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

View File

@ -0,0 +1,151 @@
From ac9b0b574d54be28b300bf99ffe092a2c589484f Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:21 +0100
Subject: [PATCH 03/11] MIPS: BCM63XX: move code touching the USB private
register
This patch moves the code touching the USB private register in the
bcm63xx USB gadget driver to arch/mips/bcm63xx/usb-common.c in
preparation for adding support for OHCI and EHCI host controllers which
will also touch the USB private register.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/usb-common.c | 53 ++++++++++++++++++++
.../include/asm/mach-bcm63xx/bcm63xx_usb_priv.h | 9 ++++
drivers/usb/gadget/bcm63xx_udc.c | 27 ++--------
4 files changed, 67 insertions(+), 24 deletions(-)
create mode 100644 arch/mips/bcm63xx/usb-common.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -2,7 +2,7 @@
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
setup.o timer.o dev-enet.o dev-flash.o dev-pcmcia.o \
dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o dev-wdt.o \
- dev-usb-usbd.o
+ dev-usb-usbd.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/usb-common.c
@@ -0,0 +1,53 @@
+/*
+ * Broadcom BCM63xx common USB device configuration code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com>
+ * Copyright (C) 2012 Broadcom Corporation
+ *
+ */
+#include <linux/export.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_usb_priv.h>
+
+void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
+{
+ u32 val;
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
+ if (is_device) {
+ val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
+ val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ } else {
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ }
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ if (is_device)
+ val |= USBH_PRIV_SWAP_USBD_MASK;
+ else
+ val &= ~USBH_PRIV_SWAP_USBD_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+}
+EXPORT_SYMBOL(bcm63xx_usb_priv_select_phy_mode);
+
+void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on)
+{
+ u32 val;
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
+ if (is_on)
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ else
+ val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+}
+EXPORT_SYMBOL(bcm63xx_usb_priv_select_pullup);
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
@@ -0,0 +1,9 @@
+#ifndef BCM63XX_USB_PRIV_H_
+#define BCM63XX_USB_PRIV_H_
+
+#include <linux/types.h>
+
+void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device);
+void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on);
+
+#endif /* BCM63XX_USB_PRIV_H_ */
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -36,6 +36,7 @@
#include <bcm63xx_dev_usb_usbd.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
+#include <bcm63xx_usb_priv.h>
#define DRV_MODULE_NAME "bcm63xx_udc"
@@ -880,22 +881,7 @@ static void bcm63xx_select_phy_mode(stru
bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG);
}
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
- if (is_device) {
- val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
- val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- } else {
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- }
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
-
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
- if (is_device)
- val |= USBH_PRIV_SWAP_USBD_MASK;
- else
- val &= ~USBH_PRIV_SWAP_USBD_MASK;
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+ bcm63xx_usb_priv_select_phy_mode(portmask, is_device);
}
/**
@@ -909,14 +895,9 @@ static void bcm63xx_select_phy_mode(stru
*/
static void bcm63xx_select_pullup(struct bcm63xx_udc *udc, bool is_on)
{
- u32 val, portmask = BIT(udc->pd->port_no);
+ u32 portmask = BIT(udc->pd->port_no);
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
- if (is_on)
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- else
- val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+ bcm63xx_usb_priv_select_pullup(portmask, is_on);
}
/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,226 @@
From ab2f33e35e35905a76204138143875251f3e1088 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:07:42 +0200
Subject: [PATCH 01/13] pinctrl: add bcm63xx base code
Setup directory and add a helper for bcm63xx pinctrl support.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/Kconfig | 1 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/bcm63xx/Kconfig | 3 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c | 142 ++++++++++++++++++++++++++++++
drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h | 14 +++
7 files changed, 163 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/Kconfig
create mode 100644 drivers/pinctrl/bcm63xx/Makefile
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -377,6 +377,7 @@ config PINCTRL_OCELOT
source "drivers/pinctrl/actions/Kconfig"
source "drivers/pinctrl/aspeed/Kconfig"
source "drivers/pinctrl/bcm/Kconfig"
+source "drivers/pinctrl/bcm63xx/Kconfig"
source "drivers/pinctrl/berlin/Kconfig"
source "drivers/pinctrl/freescale/Kconfig"
source "drivers/pinctrl/intel/Kconfig"
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_PINCTRL_EQUILIBRIUM) += p
obj-y += actions/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-y += bcm/
+obj-y += bcm63xx/
obj-$(CONFIG_PINCTRL_BERLIN) += berlin/
obj-y += freescale/
obj-$(CONFIG_X86) += intel/
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -0,0 +1,3 @@
+config PINCTRL_BCM63XX
+ bool
+ select GPIO_GENERIC
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
@@ -0,0 +1,155 @@
+/*
+ * 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) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/gpio/driver.h>
+#include <linux/of_irq.h>
+
+#include "pinctrl-bcm63xx.h"
+#include "../core.h"
+
+#define BANK_SIZE sizeof(u32)
+#define PINS_PER_BANK (BANK_SIZE * BITS_PER_BYTE)
+
+#ifdef CONFIG_OF
+static int bcm63xx_gpio_of_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
+{
+ struct gpio_chip *base = gpiochip_get_data(gc);
+ int pin = gpiospec->args[0];
+
+ if (gc != &base[pin / PINS_PER_BANK])
+ return -EINVAL;
+
+ pin = pin % PINS_PER_BANK;
+
+ if (pin >= gc->ngpio)
+ return -EINVAL;
+
+ if (flags)
+ *flags = gpiospec->args[1];
+
+ return pin;
+}
+#endif
+
+static int bcm63xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ struct gpio_chip *base = gpiochip_get_data(chip);
+ char irq_name[7]; /* "gpioXX" */
+
+ /* FIXME: this is ugly */
+ sprintf(irq_name, "gpio%d", gpio + PINS_PER_BANK * (chip - base));
+ return of_irq_get_byname(chip->of_node, irq_name);
+}
+
+static int bcm63xx_setup_gpio(struct device *dev, struct gpio_chip *gc,
+ void __iomem *dirout, void __iomem *data,
+ size_t sz, int ngpio)
+
+{
+ int banks, chips, i, ret = -EINVAL;
+
+ chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
+ banks = sz / BANK_SIZE;
+
+ for (i = 0; i < chips; i++) {
+ int offset, pins;
+ int reg_offset;
+ char *label;
+
+ label = devm_kasprintf(dev, GFP_KERNEL, "bcm63xx-gpio.%i", i);
+ if (!label)
+ return -ENOMEM;
+
+ offset = i * PINS_PER_BANK;
+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
+
+ /* the registers are treated like a huge big endian register */
+ reg_offset = (banks - i - 1) * BANK_SIZE;
+
+ ret = bgpio_init(&gc[i], dev, BANK_SIZE, data + reg_offset,
+ NULL, NULL, dirout + reg_offset, NULL,
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+ if (ret)
+ return ret;
+
+ gc[i].request = gpiochip_generic_request;
+ gc[i].free = gpiochip_generic_free;
+
+ if (of_get_property(dev->of_node, "interrupt-names", NULL))
+ gc[i].to_irq = bcm63xx_gpio_to_irq;
+
+#ifdef CONFIG_OF
+ gc[i].of_gpio_n_cells = 2;
+ gc[i].of_xlate = bcm63xx_gpio_of_xlate;
+#endif
+
+ gc[i].label = label;
+ gc[i].ngpio = pins;
+
+ devm_gpiochip_add_data(dev, &gc[i], gc);
+ }
+
+ return 0;
+}
+
+static void bcm63xx_setup_pinranges(struct gpio_chip *gc, const char *name,
+ int ngpio)
+{
+ int i, chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
+
+ for (i = 0; i < chips; i++) {
+ int offset, pins;
+
+ offset = i * PINS_PER_BANK;
+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
+
+ gpiochip_add_pin_range(&gc[i], name, 0, offset, pins);
+ }
+}
+
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
+ struct pinctrl_desc *desc,
+ void *priv, struct gpio_chip *gc,
+ int ngpio)
+{
+ struct pinctrl_dev *pctldev;
+ struct resource *res;
+ void __iomem *dirout, *data;
+ size_t sz;
+ int ret;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirout");
+ dirout = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dirout))
+ return ERR_CAST(dirout);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+ data = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data))
+ return ERR_CAST(data);
+
+ sz = resource_size(res);
+
+ ret = bcm63xx_setup_gpio(&pdev->dev, gc, dirout, data, sz, ngpio);
+ if (ret)
+ return ERR_PTR(ret);
+
+ pctldev = devm_pinctrl_register(&pdev->dev, desc, priv);
+ if (IS_ERR(pctldev))
+ return pctldev;
+
+ bcm63xx_setup_pinranges(gc, pinctrl_dev_get_devname(pctldev), ngpio);
+
+ dev_info(&pdev->dev, "registered at mmio %p\n", dirout);
+
+ return pctldev;
+}
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
@@ -0,0 +1,14 @@
+#ifndef __PINCTRL_BCM63XX
+#define __PINCTRL_BCM63XX
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
+ struct pinctrl_desc *desc,
+ void *priv, struct gpio_chip *gc,
+ int ngpio);
+
+#endif

View File

@ -0,0 +1,78 @@
From 4bdd40849632608d5cb7d3a64380cd76e7eea07b Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:33:56 +0200
Subject: [PATCH 02/16] Documentation: add BCM6328 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6328 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6328-pinctrl.txt | 61 ++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.txt
@@ -0,0 +1,61 @@
+* Broadcom BCM6328 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6328-pinctrl".
+- reg: Register specifies of dirout, dat, mode, mux registers.
+- reg-names: Must be "dirout", "dat", "mode", "mux".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6328-pinctrl";
+ reg = <0x10000080 0x8>,
+ <0x10000088 0x8>,
+ <0x10000098 0x4>,
+ <0x1000009c 0xc>;
+ reg-names = "dirout", "dat", "mode", "mux";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led
+gpio1 1 led
+gpio2 2 led
+gpio3 3 led
+gpio4 4 led
+gpio5 5 led
+gpio6 6 led, serial_led_data
+gpio7 7 led, serial_led_clk
+gpio8 8 led
+gpio9 9 led
+gpio10 10 led
+gpio11 11 led
+gpio12 12 led
+gpio13 13 led
+gpio14 14 led
+gpio15 15 led
+gpio16 16 led, pcie_clkreq
+gpio17 17 led
+gpio18 18 led
+gpio19 19 led
+gpio20 20 led
+gpio21 21 led
+gpio22 22 led
+gpio23 23 led
+gpio24 24 -
+gpio25 25 ephy0_act_led
+gpio26 26 ephy1_act_led
+gpio27 27 ephy2_act_led
+gpio28 28 ephy3_act_led
+gpio29 29 -
+gpio30 30 -
+gpio31 31 -
+hsspi_cs1 - hsspi_cs1
+usb_port1 - usb_host_port, usb_device_port

View File

@ -0,0 +1,495 @@
From 393e9753f6492c1fdf55891ddee60d955ae8b119 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:12:50 +0200
Subject: [PATCH 03/16] pinctrl: add a pincontrol driver for BCM6328
Add a pincontrol driver for BCM6328. BCM628 supports muxing 32 pins as
GPIOs, as LEDs for the integrated LED controller, or various other
functions. Its pincontrol mux registers also control other aspects, like
switching the second USB port between host and device mode.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c | 456 ++++++++++++++++++++++++++++++
3 files changed, 464 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -1,3 +1,10 @@
config PINCTRL_BCM63XX
bool
select GPIO_GENERIC
+
+config PINCTRL_BCM6328
+ bool "BCM6328 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
+obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c
@@ -0,0 +1,456 @@
+/*
+ * 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) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6328_MUX_LO_REG 0x4
+#define BCM6328_MUX_HI_REG 0x0
+#define BCM6328_MUX_OTHER_REG 0x8
+
+#define BCM6328_NGPIO 32
+
+struct bcm6328_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6328_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ unsigned mode_val:1;
+ unsigned mux_val:2;
+};
+
+struct bcm6328_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+ void __iomem *mux[3];
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio;
+};
+
+static const struct pinctrl_pin_desc bcm6328_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+
+ /*
+ * No idea where they really are; so let's put them according
+ * to their mux offsets.
+ */
+ PINCTRL_PIN(36, "hsspi_cs1"),
+ PINCTRL_PIN(38, "usb_p2"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+
+static unsigned hsspi_cs1_pins[] = { 36 };
+static unsigned usb_port1_pins[] = { 38 };
+
+#define BCM6328_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6328_pingroup bcm6328_groups[] = {
+ BCM6328_GROUP(gpio0),
+ BCM6328_GROUP(gpio1),
+ BCM6328_GROUP(gpio2),
+ BCM6328_GROUP(gpio3),
+ BCM6328_GROUP(gpio4),
+ BCM6328_GROUP(gpio5),
+ BCM6328_GROUP(gpio6),
+ BCM6328_GROUP(gpio7),
+ BCM6328_GROUP(gpio8),
+ BCM6328_GROUP(gpio9),
+ BCM6328_GROUP(gpio10),
+ BCM6328_GROUP(gpio11),
+ BCM6328_GROUP(gpio12),
+ BCM6328_GROUP(gpio13),
+ BCM6328_GROUP(gpio14),
+ BCM6328_GROUP(gpio15),
+ BCM6328_GROUP(gpio16),
+ BCM6328_GROUP(gpio17),
+ BCM6328_GROUP(gpio18),
+ BCM6328_GROUP(gpio19),
+ BCM6328_GROUP(gpio20),
+ BCM6328_GROUP(gpio21),
+ BCM6328_GROUP(gpio22),
+ BCM6328_GROUP(gpio23),
+ BCM6328_GROUP(gpio24),
+ BCM6328_GROUP(gpio25),
+ BCM6328_GROUP(gpio26),
+ BCM6328_GROUP(gpio27),
+ BCM6328_GROUP(gpio28),
+ BCM6328_GROUP(gpio29),
+ BCM6328_GROUP(gpio30),
+ BCM6328_GROUP(gpio31),
+
+ BCM6328_GROUP(hsspi_cs1),
+ BCM6328_GROUP(usb_port1),
+};
+
+/* GPIO_MODE */
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+/* PINMUX_SEL */
+static const char * const serial_led_data_groups[] = {
+ "gpio6",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio7",
+};
+
+static const char * const inet_act_led_groups[] = {
+ "gpio11",
+};
+
+static const char * const pcie_clkreq_groups[] = {
+ "gpio16",
+};
+
+static const char * const ephy0_act_led_groups[] = {
+ "gpio25",
+};
+
+static const char * const ephy1_act_led_groups[] = {
+ "gpio26",
+};
+
+static const char * const ephy2_act_led_groups[] = {
+ "gpio27",
+};
+
+static const char * const ephy3_act_led_groups[] = {
+ "gpio28",
+};
+
+static const char * const hsspi_cs1_groups[] = {
+ "hsspi_cs1"
+};
+
+static const char * const usb_host_port_groups[] = {
+ "usb_port1",
+};
+
+static const char * const usb_device_port_groups[] = {
+ "usb_port1",
+};
+
+#define BCM6328_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mode_val = 1, \
+ }
+
+#define BCM6328_MUX_FUN(n, mux) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mux_val = mux, \
+ }
+
+static const struct bcm6328_function bcm6328_funcs[] = {
+ BCM6328_MODE_FUN(led),
+ BCM6328_MUX_FUN(serial_led_data, 2),
+ BCM6328_MUX_FUN(serial_led_clk, 2),
+ BCM6328_MUX_FUN(inet_act_led, 1),
+ BCM6328_MUX_FUN(pcie_clkreq, 2),
+ BCM6328_MUX_FUN(ephy0_act_led, 1),
+ BCM6328_MUX_FUN(ephy1_act_led, 1),
+ BCM6328_MUX_FUN(ephy2_act_led, 1),
+ BCM6328_MUX_FUN(ephy3_act_led, 1),
+ BCM6328_MUX_FUN(hsspi_cs1, 2),
+ BCM6328_MUX_FUN(usb_host_port, 1),
+ BCM6328_MUX_FUN(usb_device_port, 2),
+};
+
+static int bcm6328_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6328_groups);
+}
+
+static const char *bcm6328_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6328_groups[group].name;
+}
+
+static int bcm6328_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6328_groups[group].pins;
+ *num_pins = bcm6328_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6328_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6328_funcs);
+}
+
+static const char *bcm6328_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6328_funcs[selector].name;
+}
+
+static int bcm6328_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6328_funcs[selector].groups;
+ *num_groups = bcm6328_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6328_rmw_mux(struct bcm6328_pinctrl *pctl, unsigned pin,
+ u32 mode, u32 mux)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ if (pin < 32) {
+ reg = __raw_readl(pctl->mode);
+ reg &= ~BIT(pin);
+ if (mode)
+ reg |= BIT(pin);
+ __raw_writel(reg, pctl->mode);
+ }
+
+ reg = __raw_readl(pctl->mux[pin / 16]);
+ reg &= ~(3UL << ((pin % 16) * 2));
+ reg |= mux << ((pin % 16) * 2);
+ __raw_writel(reg, pctl->mux[pin / 16]);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static int bcm6328_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6328_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6328_pingroup *grp = &bcm6328_groups[group];
+ const struct bcm6328_function *f = &bcm6328_funcs[selector];
+
+ bcm6328_rmw_mux(pctl, grp->pins[0], f->mode_val, f->mux_val);
+
+ return 0;
+}
+
+static int bcm6328_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6328_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm6328_rmw_mux(pctl, offset, 0, 0);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6328_pctl_ops = {
+ .get_groups_count = bcm6328_pinctrl_get_group_count,
+ .get_group_name = bcm6328_pinctrl_get_group_name,
+ .get_group_pins = bcm6328_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6328_pmx_ops = {
+ .get_functions_count = bcm6328_pinctrl_get_func_count,
+ .get_function_name = bcm6328_pinctrl_get_func_name,
+ .get_function_groups = bcm6328_pinctrl_get_groups,
+ .set_mux = bcm6328_pinctrl_set_mux,
+ .gpio_request_enable = bcm6328_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6328_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6328_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode, *mux;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mux");
+ mux = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mux))
+ return PTR_ERR(mux);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+ pctl->mux[0] = mux + BCM6328_MUX_LO_REG;
+ pctl->mux[1] = mux + BCM6328_MUX_HI_REG;
+ pctl->mux[2] = mux + BCM6328_MUX_OTHER_REG;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6328_pctl_ops;
+ pctl->desc.pmxops = &bcm6328_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6328_pins);
+ pctl->desc.pins = bcm6328_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ &pctl->gpio, BCM6328_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6328_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6328-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6328_pinctrl_driver = {
+ .probe = bcm6328_pinctrl_probe,
+ .driver = {
+ .name = "bcm6328-pinctrl",
+ .of_match_table = bcm6328_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6328_pinctrl_driver);

View File

@ -0,0 +1,49 @@
From 962c46bf7f43df730e2d3698930e77958cc6b191 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:35:45 +0200
Subject: [PATCH 04/16] Documentation: add BCM6348 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6348 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6348-pinctrl.txt | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6348-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6348-pinctrl.txt
@@ -0,0 +1,32 @@
+* Broadcom BCM6348 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6348-pinctrl".
+- reg: register Specifiers of dirout, dat, mode registers.
+- reg-names: Must be "dirout", "dat", "mode".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@fffe0080 {
+ compatible = "brcm,bcm6348-pinctrl";
+ reg = <0xfffe0080 0x8>,
+ <0xfffe0088 0x8>,
+ <0xfffe0098 0x4>;
+ reg-names = "dirout", "dat", "mode";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+group0 32-36 ext_mii, utopia, diag
+group1 22-31 ext_ephy, mii_snoop, mii_pccard,
+ spi_master_uart, utopia, diag
+group2 16-21 pci, diag
+group3 8-15 ext_mii, utopia
+group4 0-7 ext_ephy, mii_snoop, legacy_led, diag

View File

@ -0,0 +1,431 @@
From 45444cb631555e2dc16b95d779b10aa075c7482e Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:14:13 +0200
Subject: [PATCH 05/16] pinctrl: add a pincontrol driver for BCM6348
Add a pincotrol driver for BCM6348. BCM6348 allow muxing five groups of
up to ten gpios into fourteen potential functions. It does not allow
muxing individual pins. Some functions require more than one group to be
muxed to the same function.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c | 391 ++++++++++++++++++++++++++++++
3 files changed, 399 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -8,3 +8,10 @@ config PINCTRL_BCM6328
select PINCONF
select PINCTRL_BCM63XX
select GENERIC_PINCONF
+
+config PINCTRL_BCM6348
+ bool "BCM6348 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
+obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c
@@ -0,0 +1,391 @@
+/*
+ * 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) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6348_NGPIO 37
+
+#define MAX_GROUP 4
+#define PINS_PER_GROUP 8
+#define PIN_TO_GROUP(pin) (MAX_GROUP - ((pin) / PINS_PER_GROUP))
+#define GROUP_SHIFT(pin) (PIN_TO_GROUP(pin) * 4)
+#define GROUP_MASK(pin) (0xf << GROUP_SHIFT(pin))
+
+struct bcm6348_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6348_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+ unsigned int value;
+};
+
+struct bcm6348_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6348_PIN(a, b, group) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(group), \
+ }
+
+static const struct pinctrl_pin_desc bcm6348_pins[] = {
+ BCM6348_PIN(0, "gpio0", 4),
+ BCM6348_PIN(1, "gpio1", 4),
+ BCM6348_PIN(2, "gpio2", 4),
+ BCM6348_PIN(3, "gpio3", 4),
+ BCM6348_PIN(4, "gpio4", 4),
+ BCM6348_PIN(5, "gpio5", 4),
+ BCM6348_PIN(6, "gpio6", 4),
+ BCM6348_PIN(7, "gpio7", 4),
+ BCM6348_PIN(8, "gpio8", 3),
+ BCM6348_PIN(9, "gpio9", 3),
+ BCM6348_PIN(10, "gpio10", 3),
+ BCM6348_PIN(11, "gpio11", 3),
+ BCM6348_PIN(12, "gpio12", 3),
+ BCM6348_PIN(13, "gpio13", 3),
+ BCM6348_PIN(14, "gpio14", 3),
+ BCM6348_PIN(15, "gpio15", 3),
+ BCM6348_PIN(16, "gpio16", 2),
+ BCM6348_PIN(17, "gpio17", 2),
+ BCM6348_PIN(18, "gpio18", 2),
+ BCM6348_PIN(19, "gpio19", 2),
+ BCM6348_PIN(20, "gpio20", 2),
+ BCM6348_PIN(21, "gpio21", 2),
+ BCM6348_PIN(22, "gpio22", 1),
+ BCM6348_PIN(23, "gpio23", 1),
+ BCM6348_PIN(24, "gpio24", 1),
+ BCM6348_PIN(25, "gpio25", 1),
+ BCM6348_PIN(26, "gpio26", 1),
+ BCM6348_PIN(27, "gpio27", 1),
+ BCM6348_PIN(28, "gpio28", 1),
+ BCM6348_PIN(29, "gpio29", 1),
+ BCM6348_PIN(30, "gpio30", 1),
+ BCM6348_PIN(31, "gpio31", 1),
+ BCM6348_PIN(32, "gpio32", 0),
+ BCM6348_PIN(33, "gpio33", 0),
+ BCM6348_PIN(34, "gpio34", 0),
+ BCM6348_PIN(35, "gpio35", 0),
+ BCM6348_PIN(36, "gpio36", 0),
+};
+
+enum bcm6348_muxes {
+ BCM6348_MUX_GPIO = 0,
+ BCM6348_MUX_EXT_EPHY,
+ BCM6348_MUX_MII_SNOOP,
+ BCM6348_MUX_LEGACY_LED,
+ BCM6348_MUX_MII_PCCARD,
+ BCM6348_MUX_PCI,
+ BCM6348_MUX_SPI_MASTER_UART,
+ BCM6348_MUX_EXT_MII,
+ BCM6348_MUX_UTOPIA,
+ BCM6348_MUX_DIAG,
+};
+
+static unsigned group0_pins[] = {
+ 32, 33, 34, 35, 36,
+};
+
+static unsigned group1_pins[] = {
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+};
+
+static unsigned group2_pins[] = {
+ 16, 17, 18, 19, 20, 21,
+};
+
+static unsigned group3_pins[] = {
+ 8, 9, 10, 11, 12, 13, 14, 15,
+};
+
+static unsigned group4_pins[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+};
+
+#define BCM6348_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ } \
+
+static struct bcm6348_pingroup bcm6348_groups[] = {
+ BCM6348_GROUP(group0),
+ BCM6348_GROUP(group1),
+ BCM6348_GROUP(group2),
+ BCM6348_GROUP(group3),
+ BCM6348_GROUP(group4),
+};
+
+static const char * const ext_mii_groups[] = {
+ "group0",
+ "group3",
+};
+
+static const char * const ext_ephy_groups[] = {
+ "group1",
+ "group4"
+};
+
+static const char * const mii_snoop_groups[] = {
+ "group1",
+ "group4",
+};
+
+static const char * const legacy_led_groups[] = {
+ "group4",
+};
+
+static const char * const mii_pccard_groups[] = {
+ "group1",
+};
+
+static const char * const pci_groups[] = {
+ "group2",
+};
+
+static const char * const spi_master_uart_groups[] = {
+ "group1",
+};
+
+static const char * const utopia_groups[] = {
+ "group0",
+ "group1",
+ "group3",
+};
+
+static const char * const diag_groups[] = {
+ "group0",
+ "group1",
+ "group2",
+ "group4",
+};
+
+#define BCM6348_FUN(n, f) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .value = BCM6348_MUX_##f, \
+ }
+
+static const struct bcm6348_function bcm6348_funcs[] = {
+ BCM6348_FUN(ext_mii, EXT_MII),
+ BCM6348_FUN(ext_ephy, EXT_EPHY),
+ BCM6348_FUN(mii_snoop, MII_SNOOP),
+ BCM6348_FUN(legacy_led, LEGACY_LED),
+ BCM6348_FUN(mii_pccard, MII_PCCARD),
+ BCM6348_FUN(pci, PCI),
+ BCM6348_FUN(spi_master_uart, SPI_MASTER_UART),
+ BCM6348_FUN(utopia, UTOPIA),
+ BCM6348_FUN(diag, DIAG),
+};
+
+static int bcm6348_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6348_groups);
+}
+
+static const char *bcm6348_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6348_groups[group].name;
+}
+
+static int bcm6348_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6348_groups[group].pins;
+ *num_pins = bcm6348_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6348_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6348_funcs);
+}
+
+static const char *bcm6348_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6348_funcs[selector].name;
+}
+
+static int bcm6348_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6348_funcs[selector].groups;
+ *num_groups = bcm6348_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6348_rmw_mux(struct bcm6348_pinctrl *pctl, u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+
+ reg = __raw_readl(pctl->mode);
+ reg &= ~mask;
+ reg |= val & mask;
+ __raw_writel(reg, pctl->mode);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static int bcm6348_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6348_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6348_pingroup *grp = &bcm6348_groups[group];
+ const struct bcm6348_function *f = &bcm6348_funcs[selector];
+ u32 mask, val;
+
+ /*
+ * pins n..(n+7) share the same group, so we only need to look at
+ * the first pin.
+ */
+ mask = GROUP_MASK(grp->pins[0]);
+ val = f->value << GROUP_SHIFT(grp->pins[0]);
+
+ bcm6348_rmw_mux(pctl, mask, val);
+
+ return 0;
+}
+
+static int bcm6348_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6348_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pin_desc *desc;
+ u32 mask;
+
+ /* don't reconfigure if already muxed */
+ desc = pin_desc_get(pctldev, offset);
+ if (desc->mux_usecount)
+ return 0;
+
+ mask = GROUP_MASK(offset);
+
+ /* disable all functions using this pin */
+ bcm6348_rmw_mux(pctl, mask, 0);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6348_pctl_ops = {
+ .get_groups_count = bcm6348_pinctrl_get_group_count,
+ .get_group_name = bcm6348_pinctrl_get_group_name,
+ .get_group_pins = bcm6348_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6348_pmx_ops = {
+ .get_functions_count = bcm6348_pinctrl_get_func_count,
+ .get_function_name = bcm6348_pinctrl_get_func_name,
+ .get_function_groups = bcm6348_pinctrl_get_groups,
+ .set_mux = bcm6348_pinctrl_set_mux,
+ .gpio_request_enable = bcm6348_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6348_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6348_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+
+ /* disable all muxes by default */
+ __raw_writel(0, pctl->mode);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6348_pctl_ops;
+ pctl->desc.pmxops = &bcm6348_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6348_pins);
+ pctl->desc.pins = bcm6348_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6348_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6348_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6348-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6348_pinctrl_driver = {
+ .probe = bcm6348_pinctrl_probe,
+ .driver = {
+ .name = "bcm6348-pinctrl",
+ .of_match_table = bcm6348_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6348_pinctrl_driver);

View File

@ -0,0 +1,61 @@
From c7c8fa7f5b5ee9bea751fa7bdae8ff4acde8f26e Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:00 +0200
Subject: [PATCH 06/16] Documentation: add BCM6358 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6358 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6358-pinctrl.txt | 44 ++++++++++++++++++++++
1 file changed, 44 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.txt
@@ -0,0 +1,44 @@
+* Broadcom BCM6358 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6358-pinctrl".
+- reg: Register specifiers of dirout, dat registers.
+- reg-names: Must be "dirout", "dat".
+- brcm,gpiomode: Phandle to the shared gpiomode register.
+- gpio-controller: Identifies this node as a gpio-controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@fffe0080 {
+ compatible = "brcm,bcm6358-pinctrl";
+ reg = <0xfffe0080 0x8>,
+ <0xfffe0088 0x8>,
+ <0xfffe0098 0x4>;
+ reg-names = "dirout", "dat";
+ brcm,gpiomode = <&gpiomode>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+gpiomode: syscon@fffe0098 {
+ compatible = "brcm,bcm6358-gpiomode", "syscon";
+ reg = <0xfffe0098 0x4>;
+ native-endian;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+ebi_cs_grp 30-31 ebi_cs
+uart1_grp 28-31 uart1
+spi_cs_grp 32-33 spi_cs
+async_modem_grp 12-15 async_modem
+legacy_led_grp 9-15 legacy_led
+serial_led_grp 6-7 serial_led
+led_grp 0-3 led
+utopia_grp 12-15, 22-31 utopia
+pwm_syn_clk_grp 8 pwm_syn_clk
+sys_irq_grp 5 sys_irq

View File

@ -0,0 +1,436 @@
From fb00ef462f3f8b70ea8902151cc72810fe90b999 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:16:01 +0200
Subject: [PATCH 07/16] pinctrl: add a pincontrol driver for BCM6358
Add a pincotrol driver for BCM6358. BCM6358 allow overlaying different
functions onto the GPIO pins. It does not support configuring individual
pins but only whole groups. These groups may overlap, and still require
the directions to be set correctly in the GPIO register. In addition the
functions register controls other, not directly mux related functions.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 8 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c | 393 ++++++++++++++++++++++++++++++
3 files changed, 402 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -15,3 +15,11 @@ config PINCTRL_BCM6348
select PINCONF
select PINCTRL_BCM63XX
select GENERIC_PINCONF
+
+config PINCTRL_BCM6358
+ bool "BCM6358 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
+ select MFD_SYSCON
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
+obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c
@@ -0,0 +1,393 @@
+/*
+ * 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) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+/* GPIO_MODE register */
+#define BCM6358_MODE_MUX_NONE 0
+
+/* overlays on gpio pins */
+#define BCM6358_MODE_MUX_EBI_CS BIT(5)
+#define BCM6358_MODE_MUX_UART1 BIT(6)
+#define BCM6358_MODE_MUX_SPI_CS BIT(7)
+#define BCM6358_MODE_MUX_ASYNC_MODEM BIT(8)
+#define BCM6358_MODE_MUX_LEGACY_LED BIT(9)
+#define BCM6358_MODE_MUX_SERIAL_LED BIT(10)
+#define BCM6358_MODE_MUX_LED BIT(11)
+#define BCM6358_MODE_MUX_UTOPIA BIT(12)
+#define BCM6358_MODE_MUX_CLKRST BIT(13)
+#define BCM6358_MODE_MUX_PWM_SYN_CLK BIT(14)
+#define BCM6358_MODE_MUX_SYS_IRQ BIT(15)
+
+#define BCM6358_NGPIO 40
+
+struct bcm6358_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+
+ const u16 mode_val;
+
+ /* non-GPIO function muxes require the gpio direction to be set */
+ const u16 direction;
+};
+
+struct bcm6358_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+};
+
+struct bcm6358_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ struct regmap_field *overlays;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6358_GPIO_PIN(a, b, bit1, bit2, bit3) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(BCM6358_MODE_MUX_##bit1 | \
+ BCM6358_MODE_MUX_##bit2 | \
+ BCM6358_MODE_MUX_##bit3), \
+ }
+
+static const struct pinctrl_pin_desc bcm6358_pins[] = {
+ BCM6358_GPIO_PIN(0, "gpio0", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(1, "gpio1", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(2, "gpio2", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(3, "gpio3", LED, NONE, NONE),
+ PINCTRL_PIN(4, "gpio4"),
+ BCM6358_GPIO_PIN(5, "gpio5", SYS_IRQ, NONE, NONE),
+ BCM6358_GPIO_PIN(6, "gpio6", SERIAL_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(7, "gpio7", SERIAL_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(8, "gpio8", PWM_SYN_CLK, NONE, NONE),
+ BCM6358_GPIO_PIN(9, "gpio09", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(10, "gpio10", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(11, "gpio11", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(12, "gpio12", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(13, "gpio13", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(14, "gpio14", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(15, "gpio15", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ BCM6358_GPIO_PIN(22, "gpio22", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(23, "gpio23", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(24, "gpio24", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(25, "gpio25", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(26, "gpio26", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(27, "gpio27", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(28, "gpio28", UTOPIA, UART1, NONE),
+ BCM6358_GPIO_PIN(29, "gpio29", UTOPIA, UART1, NONE),
+ BCM6358_GPIO_PIN(30, "gpio30", UTOPIA, UART1, EBI_CS),
+ BCM6358_GPIO_PIN(31, "gpio31", UTOPIA, UART1, EBI_CS),
+ BCM6358_GPIO_PIN(32, "gpio32", SPI_CS, NONE, NONE),
+ BCM6358_GPIO_PIN(33, "gpio33", SPI_CS, NONE, NONE),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+};
+
+static unsigned ebi_cs_grp_pins[] = { 30, 31 };
+
+static unsigned uart1_grp_pins[] = { 28, 29, 30, 31 };
+
+static unsigned spi_cs_grp_pins[] = { 32, 33 };
+
+static unsigned async_modem_grp_pins[] = { 12, 13, 14, 15 };
+
+static unsigned serial_led_grp_pins[] = { 6, 7 };
+
+static unsigned legacy_led_grp_pins[] = { 9, 10, 11, 12, 13, 14, 15 };
+
+static unsigned led_grp_pins[] = { 0, 1, 2, 3 };
+
+static unsigned utopia_grp_pins[] = {
+ 12, 13, 14, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+};
+
+static unsigned pwm_syn_clk_grp_pins[] = { 8 };
+
+static unsigned sys_irq_grp_pins[] = { 5 };
+
+#define BCM6358_GPIO_MUX_GROUP(n, bit, dir) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ .mode_val = BCM6358_MODE_MUX_##bit, \
+ .direction = dir, \
+ }
+
+static const struct bcm6358_pingroup bcm6358_groups[] = {
+ BCM6358_GPIO_MUX_GROUP(ebi_cs_grp, EBI_CS, 0x3),
+ BCM6358_GPIO_MUX_GROUP(uart1_grp, UART1, 0x2),
+ BCM6358_GPIO_MUX_GROUP(spi_cs_grp, SPI_CS, 0x6),
+ BCM6358_GPIO_MUX_GROUP(async_modem_grp, ASYNC_MODEM, 0x6),
+ BCM6358_GPIO_MUX_GROUP(legacy_led_grp, LEGACY_LED, 0x7f),
+ BCM6358_GPIO_MUX_GROUP(serial_led_grp, SERIAL_LED, 0x3),
+ BCM6358_GPIO_MUX_GROUP(led_grp, LED, 0xf),
+ BCM6358_GPIO_MUX_GROUP(utopia_grp, UTOPIA, 0x000f),
+ BCM6358_GPIO_MUX_GROUP(pwm_syn_clk_grp, PWM_SYN_CLK, 0x1),
+ BCM6358_GPIO_MUX_GROUP(sys_irq_grp, SYS_IRQ, 0x1),
+};
+
+static const char * const ebi_cs_groups[] = {
+ "ebi_cs_grp"
+};
+
+static const char * const uart1_groups[] = {
+ "uart1_grp"
+};
+
+static const char * const spi_cs_2_3_groups[] = {
+ "spi_cs_2_3_grp"
+};
+
+static const char * const async_modem_groups[] = {
+ "async_modem_grp"
+};
+
+static const char * const legacy_led_groups[] = {
+ "legacy_led_grp",
+};
+
+static const char * const serial_led_groups[] = {
+ "serial_led_grp",
+};
+
+static const char * const led_groups[] = {
+ "led_grp",
+};
+
+static const char * const clkrst_groups[] = {
+ "clkrst_grp",
+};
+
+static const char * const pwm_syn_clk_groups[] = {
+ "pwm_syn_clk_grp",
+};
+
+static const char * const sys_irq_groups[] = {
+ "sys_irq_grp",
+};
+
+#define BCM6358_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ }
+
+static const struct bcm6358_function bcm6358_funcs[] = {
+ BCM6358_FUN(ebi_cs),
+ BCM6358_FUN(uart1),
+ BCM6358_FUN(spi_cs_2_3),
+ BCM6358_FUN(async_modem),
+ BCM6358_FUN(legacy_led),
+ BCM6358_FUN(serial_led),
+ BCM6358_FUN(led),
+ BCM6358_FUN(clkrst),
+ BCM6358_FUN(pwm_syn_clk),
+ BCM6358_FUN(sys_irq),
+};
+
+static int bcm6358_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6358_groups);
+}
+
+static const char *bcm6358_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6358_groups[group].name;
+}
+
+static int bcm6358_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6358_groups[group].pins;
+ *num_pins = bcm6358_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6358_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6358_funcs);
+}
+
+static const char *bcm6358_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6358_funcs[selector].name;
+}
+
+static int bcm6358_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6358_funcs[selector].groups;
+ *num_groups = bcm6358_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static int bcm6358_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6358_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6358_pingroup *grp = &bcm6358_groups[group];
+ u32 val = grp->mode_val;
+ u32 mask = val;
+ unsigned pin;
+
+ for (pin = 0; pin < grp->num_pins; pin++)
+ mask |= (unsigned long)bcm6358_pins[pin].drv_data;
+
+ regmap_field_update_bits(pctl->overlays, mask, val);
+
+ for (pin = 0; pin < grp->num_pins; pin++) {
+ int hw_gpio = bcm6358_pins[pin].number;
+ struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
+
+ if (grp->direction & BIT(pin))
+ gc->direction_output(gc, hw_gpio % 32, 0);
+ else
+ gc->direction_input(gc, hw_gpio % 32);
+ }
+
+ return 0;
+}
+
+static int bcm6358_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6358_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ u32 mask;
+
+ mask = (unsigned long)bcm6358_pins[offset].drv_data;
+ if (!mask)
+ return 0;
+
+ /* disable all functions using this pin */
+ return regmap_field_update_bits(pctl->overlays, mask, 0);
+}
+
+static struct pinctrl_ops bcm6358_pctl_ops = {
+ .get_groups_count = bcm6358_pinctrl_get_group_count,
+ .get_group_name = bcm6358_pinctrl_get_group_name,
+ .get_group_pins = bcm6358_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6358_pmx_ops = {
+ .get_functions_count = bcm6358_pinctrl_get_func_count,
+ .get_function_name = bcm6358_pinctrl_get_func_name,
+ .get_function_groups = bcm6358_pinctrl_get_groups,
+ .set_mux = bcm6358_pinctrl_set_mux,
+ .gpio_request_enable = bcm6358_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6358_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6358_pinctrl *pctl;
+ struct regmap *mode;
+ struct reg_field overlays = REG_FIELD(0, 0, 15);
+
+ if (pdev->dev.of_node)
+ mode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "brcm,gpiomode");
+ else
+ mode = syscon_regmap_lookup_by_pdevname("syscon.fffe0098");
+
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->overlays = devm_regmap_field_alloc(&pdev->dev, mode, overlays);
+ if (IS_ERR(pctl->overlays))
+ return PTR_ERR(pctl->overlays);
+
+ /* disable all muxes by default */
+ regmap_field_write(pctl->overlays, 0);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6358_pctl_ops;
+ pctl->desc.pmxops = &bcm6358_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6358_pins);
+ pctl->desc.pins = bcm6358_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6358_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6358_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6358-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6358_pinctrl_driver = {
+ .probe = bcm6358_pinctrl_probe,
+ .driver = {
+ .name = "bcm6358-pinctrl",
+ .of_match_table = bcm6358_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6358_pinctrl_driver);

View File

@ -0,0 +1,96 @@
From ba03ea8ada2ca71c9095d96a1e4085c2c5cf0e69 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:18 +0200
Subject: [PATCH 08/16] Documentation: add BCM6362 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6362 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6362-pinctrl.txt | 79 ++++++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.txt
@@ -0,0 +1,79 @@
+* Broadcom BCM6362 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6362-pinctrl"
+- reg: Register specifiers of dirout, dat, led, mode, ctrl, basemode registers.
+- reg-names: Must be "dirout", "dat", "led", "mode", "ctrl", "basemode".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6362-pinctrl";
+ reg = <0x10000080 0x8>,
+ <0x10000088 0x8>,
+ <0x10000090 0x4>,
+ <0x10000098 0x4>,
+ <0x1000009c 0x4>,
+ <0x100000b8 0x4>;
+ reg-names = "dirout", "dat", "led",
+ "mode", "ctrl", "basemode";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led, usb_device_led
+gpio1 1 led, sys_irq
+gpio2 2 led, serial_led_clk
+gpio3 3 led, serial_led_data
+gpio4 4 led, robosw_led_data
+gpio5 5 led, robosw_led_clk
+gpio6 6 led, robosw_led0
+gpio7 7 led, robosw_led1
+gpio8 8 led, inet_led
+gpio9 9 led, spi_cs2
+gpio10 10 led, spi_cs3
+gpio11 11 led, ntr_pulse
+gpio12 12 led, uart1_scts
+gpio13 13 led, uart1_srts
+gpio14 14 led, uart1_sdin
+gpio15 15 led, uart1_sdout
+gpio16 16 led, adsl_spi_miso
+gpio17 17 led, adsl_spi_mosi
+gpio18 18 led, adsl_spi_clk
+gpio19 19 led, adsl_spi_cs
+gpio20 20 led, ephy0_led
+gpio21 21 led, ephy1_led
+gpio22 22 led, ephy2_led
+gpio23 23 led, ephy3_led
+gpio24 24 ext_irq0
+gpio25 25 ext_irq1
+gpio26 26 ext_irq2
+gpio27 27 ext_irq3
+gpio28 28 -
+gpio29 29 -
+gpio30 30 -
+gpio31 31 -
+gpio32 32 wifi
+gpio33 33 wifi
+gpio34 34 wifi
+gpio35 35 wifi
+gpio36 36 wifi
+gpio37 37 wifi
+gpio38 38 wifi
+gpio39 39 wifi
+gpio40 40 wifi
+gpio41 41 wifi
+gpio42 42 wifi
+gpio43 43 wifi
+gpio44 44 wifi
+gpio45 45 wifi
+gpio46 46 wifi
+gpio47 47 wifi
+nand_grp 8, 12-23, 27 nand

View File

@ -0,0 +1,733 @@
From eea6b96701d734095e2f823f3a82d9b063f553ae Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:17:20 +0200
Subject: [PATCH 09/16] pinctrl: add a pincontrol driver for BCM6362
Add a pincotrol driver for BCM6362. BCM6362 allows muxing individual
GPIO pins to the LED controller, to be available by the integrated
wifi, or other functions. It also supports overlay groups, of which
only NAND is documented.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c | 692 ++++++++++++++++++++++++++++++
3 files changed, 700 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -23,3 +23,10 @@ config PINCTRL_BCM6358
select PINCTRL_BCM63XX
select GENERIC_PINCONF
select MFD_SYSCON
+
+config PINCTRL_BCM6362
+ bool "BCM6362 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
+obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
@@ -0,0 +1,692 @@
+/*
+ * 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) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6362_NGPIO 48
+
+/* GPIO_BASEMODE register */
+#define BASEMODE_NAND BIT(2)
+
+enum bcm6362_pinctrl_reg {
+ BCM6362_LEDCTRL,
+ BCM6362_MODE,
+ BCM6362_CTRL,
+ BCM6362_BASEMODE,
+};
+
+struct bcm6362_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6362_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ enum bcm6362_pinctrl_reg reg;
+ u32 basemode_mask;
+};
+
+struct bcm6362_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *led;
+ void __iomem *mode;
+ void __iomem *ctrl;
+ void __iomem *basemode;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6362_PIN(a, b, mask) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(mask), \
+ }
+
+static const struct pinctrl_pin_desc bcm6362_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ BCM6362_PIN(8, "gpio8", BASEMODE_NAND),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ BCM6362_PIN(12, "gpio12", BASEMODE_NAND),
+ BCM6362_PIN(13, "gpio13", BASEMODE_NAND),
+ BCM6362_PIN(14, "gpio14", BASEMODE_NAND),
+ BCM6362_PIN(15, "gpio15", BASEMODE_NAND),
+ BCM6362_PIN(16, "gpio16", BASEMODE_NAND),
+ BCM6362_PIN(17, "gpio17", BASEMODE_NAND),
+ BCM6362_PIN(18, "gpio18", BASEMODE_NAND),
+ BCM6362_PIN(19, "gpio19", BASEMODE_NAND),
+ BCM6362_PIN(20, "gpio20", BASEMODE_NAND),
+ BCM6362_PIN(21, "gpio21", BASEMODE_NAND),
+ BCM6362_PIN(22, "gpio22", BASEMODE_NAND),
+ BCM6362_PIN(23, "gpio23", BASEMODE_NAND),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ BCM6362_PIN(27, "gpio27", BASEMODE_NAND),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned gpio32_pins[] = { 32 };
+static unsigned gpio33_pins[] = { 33 };
+static unsigned gpio34_pins[] = { 34 };
+static unsigned gpio35_pins[] = { 35 };
+static unsigned gpio36_pins[] = { 36 };
+static unsigned gpio37_pins[] = { 37 };
+static unsigned gpio38_pins[] = { 38 };
+static unsigned gpio39_pins[] = { 39 };
+static unsigned gpio40_pins[] = { 40 };
+static unsigned gpio41_pins[] = { 41 };
+static unsigned gpio42_pins[] = { 42 };
+static unsigned gpio43_pins[] = { 43 };
+static unsigned gpio44_pins[] = { 44 };
+static unsigned gpio45_pins[] = { 45 };
+static unsigned gpio46_pins[] = { 46 };
+static unsigned gpio47_pins[] = { 47 };
+
+static unsigned nand_grp_pins[] = {
+ 8, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 27,
+};
+
+#define BCM6362_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6362_pingroup bcm6362_groups[] = {
+ BCM6362_GROUP(gpio0),
+ BCM6362_GROUP(gpio1),
+ BCM6362_GROUP(gpio2),
+ BCM6362_GROUP(gpio3),
+ BCM6362_GROUP(gpio4),
+ BCM6362_GROUP(gpio5),
+ BCM6362_GROUP(gpio6),
+ BCM6362_GROUP(gpio7),
+ BCM6362_GROUP(gpio8),
+ BCM6362_GROUP(gpio9),
+ BCM6362_GROUP(gpio10),
+ BCM6362_GROUP(gpio11),
+ BCM6362_GROUP(gpio12),
+ BCM6362_GROUP(gpio13),
+ BCM6362_GROUP(gpio14),
+ BCM6362_GROUP(gpio15),
+ BCM6362_GROUP(gpio16),
+ BCM6362_GROUP(gpio17),
+ BCM6362_GROUP(gpio18),
+ BCM6362_GROUP(gpio19),
+ BCM6362_GROUP(gpio20),
+ BCM6362_GROUP(gpio21),
+ BCM6362_GROUP(gpio22),
+ BCM6362_GROUP(gpio23),
+ BCM6362_GROUP(gpio24),
+ BCM6362_GROUP(gpio25),
+ BCM6362_GROUP(gpio26),
+ BCM6362_GROUP(gpio27),
+ BCM6362_GROUP(gpio28),
+ BCM6362_GROUP(gpio29),
+ BCM6362_GROUP(gpio30),
+ BCM6362_GROUP(gpio31),
+ BCM6362_GROUP(gpio32),
+ BCM6362_GROUP(gpio33),
+ BCM6362_GROUP(gpio34),
+ BCM6362_GROUP(gpio35),
+ BCM6362_GROUP(gpio36),
+ BCM6362_GROUP(gpio37),
+ BCM6362_GROUP(gpio38),
+ BCM6362_GROUP(gpio39),
+ BCM6362_GROUP(gpio40),
+ BCM6362_GROUP(gpio41),
+ BCM6362_GROUP(gpio42),
+ BCM6362_GROUP(gpio43),
+ BCM6362_GROUP(gpio44),
+ BCM6362_GROUP(gpio45),
+ BCM6362_GROUP(gpio46),
+ BCM6362_GROUP(gpio47),
+ BCM6362_GROUP(nand_grp),
+};
+
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+static const char * const usb_device_led_groups[] = {
+ "gpio0",
+};
+
+static const char * const sys_irq_groups[] = {
+ "gpio1",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio2",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio3",
+};
+
+static const char * const robosw_led_data_groups[] = {
+ "gpio4",
+};
+
+static const char * const robosw_led_clk_groups[] = {
+ "gpio5",
+};
+
+static const char * const robosw_led0_groups[] = {
+ "gpio6",
+};
+
+static const char * const robosw_led1_groups[] = {
+ "gpio7",
+};
+
+static const char * const inet_led_groups[] = {
+ "gpio8",
+};
+
+static const char * const spi_cs2_groups[] = {
+ "gpio9",
+};
+
+static const char * const spi_cs3_groups[] = {
+ "gpio10",
+};
+
+static const char * const ntr_pulse_groups[] = {
+ "gpio11",
+};
+
+static const char * const uart1_scts_groups[] = {
+ "gpio12",
+};
+
+static const char * const uart1_srts_groups[] = {
+ "gpio13",
+};
+
+static const char * const uart1_sdin_groups[] = {
+ "gpio14",
+};
+
+static const char * const uart1_sdout_groups[] = {
+ "gpio15",
+};
+
+static const char * const adsl_spi_miso_groups[] = {
+ "gpio16",
+};
+
+static const char * const adsl_spi_mosi_groups[] = {
+ "gpio17",
+};
+
+static const char * const adsl_spi_clk_groups[] = {
+ "gpio18",
+};
+
+static const char * const adsl_spi_cs_groups[] = {
+ "gpio19",
+};
+
+static const char * const ephy0_led_groups[] = {
+ "gpio20",
+};
+
+static const char * const ephy1_led_groups[] = {
+ "gpio21",
+};
+
+static const char * const ephy2_led_groups[] = {
+ "gpio22",
+};
+
+static const char * const ephy3_led_groups[] = {
+ "gpio23",
+};
+
+static const char * const ext_irq0_groups[] = {
+ "gpio24",
+};
+
+static const char * const ext_irq1_groups[] = {
+ "gpio25",
+};
+
+static const char * const ext_irq2_groups[] = {
+ "gpio26",
+};
+
+static const char * const ext_irq3_groups[] = {
+ "gpio27",
+};
+
+static const char * const wifi_groups[] = {
+ "gpio32",
+ "gpio33",
+ "gpio34",
+ "gpio35",
+ "gpio36",
+ "gpio37",
+ "gpio38",
+ "gpio39",
+ "gpio40",
+ "gpio41",
+ "gpio42",
+ "gpio43",
+ "gpio44",
+ "gpio45",
+ "gpio46",
+ "gpio47",
+};
+
+static const char * const nand_groups[] = {
+ "nand_grp",
+};
+
+#define BCM6362_LED_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_LEDCTRL, \
+ }
+
+#define BCM6362_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_MODE, \
+ }
+
+#define BCM6362_CTRL_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_CTRL, \
+ }
+
+#define BCM6362_BASEMODE_FUN(n, mask) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_BASEMODE, \
+ .basemode_mask = (mask), \
+ }
+
+static const struct bcm6362_function bcm6362_funcs[] = {
+ BCM6362_LED_FUN(led),
+ BCM6362_MODE_FUN(usb_device_led),
+ BCM6362_MODE_FUN(sys_irq),
+ BCM6362_MODE_FUN(serial_led_clk),
+ BCM6362_MODE_FUN(serial_led_data),
+ BCM6362_MODE_FUN(robosw_led_data),
+ BCM6362_MODE_FUN(robosw_led_clk),
+ BCM6362_MODE_FUN(robosw_led0),
+ BCM6362_MODE_FUN(robosw_led1),
+ BCM6362_MODE_FUN(inet_led),
+ BCM6362_MODE_FUN(spi_cs2),
+ BCM6362_MODE_FUN(spi_cs3),
+ BCM6362_MODE_FUN(ntr_pulse),
+ BCM6362_MODE_FUN(uart1_scts),
+ BCM6362_MODE_FUN(uart1_srts),
+ BCM6362_MODE_FUN(uart1_sdin),
+ BCM6362_MODE_FUN(uart1_sdout),
+ BCM6362_MODE_FUN(adsl_spi_miso),
+ BCM6362_MODE_FUN(adsl_spi_mosi),
+ BCM6362_MODE_FUN(adsl_spi_clk),
+ BCM6362_MODE_FUN(adsl_spi_cs),
+ BCM6362_MODE_FUN(ephy0_led),
+ BCM6362_MODE_FUN(ephy1_led),
+ BCM6362_MODE_FUN(ephy2_led),
+ BCM6362_MODE_FUN(ephy3_led),
+ BCM6362_MODE_FUN(ext_irq0),
+ BCM6362_MODE_FUN(ext_irq1),
+ BCM6362_MODE_FUN(ext_irq2),
+ BCM6362_MODE_FUN(ext_irq3),
+ BCM6362_CTRL_FUN(wifi),
+ BCM6362_BASEMODE_FUN(nand, BASEMODE_NAND),
+};
+
+static int bcm6362_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6362_groups);
+}
+
+static const char *bcm6362_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6362_groups[group].name;
+}
+
+static int bcm6362_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6362_groups[group].pins;
+ *num_pins = bcm6362_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6362_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6362_funcs);
+}
+
+static const char *bcm6362_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6362_funcs[selector].name;
+}
+
+static int bcm6362_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6362_funcs[selector].groups;
+ *num_groups = bcm6362_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6362_rmw_mux(struct bcm6362_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= val & mask;
+ __raw_writel(tmp, reg);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static void bcm6362_set_gpio(struct bcm6362_pinctrl *pctl, unsigned pin)
+{
+ const struct pinctrl_pin_desc *desc = &bcm6362_pins[pin];
+ u32 mask = BIT(pin % 32);
+
+ if (desc->drv_data)
+ bcm6362_rmw_mux(pctl, pctl->basemode, (u32)desc->drv_data, 0);
+
+ if (pin < 32) {
+ /* base mode 0 => gpio 1 => mux function */
+ bcm6362_rmw_mux(pctl, pctl->mode, mask, 0);
+
+ /* pins 0-23 might be muxed to led */
+ if (pin < 24)
+ bcm6362_rmw_mux(pctl, pctl->led, mask, 0);
+ } else {
+ /* ctrl reg 0 => wifi function 1 => gpio */
+ bcm6362_rmw_mux(pctl, pctl->ctrl, mask, mask);
+ }
+}
+
+static int bcm6362_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6362_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6362_pingroup *grp = &bcm6362_groups[group];
+ const struct bcm6362_function *f = &bcm6362_funcs[selector];
+ unsigned i;
+ void __iomem *reg;
+ u32 val, mask;
+
+ for (i = 0; i < grp->num_pins; i++)
+ bcm6362_set_gpio(pctl, grp->pins[i]);
+
+ switch (f->reg) {
+ case BCM6362_LEDCTRL:
+ reg = pctl->led;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM6362_MODE:
+ reg = pctl->ctrl;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM6362_CTRL:
+ reg = pctl->ctrl;
+ mask = BIT(grp->pins[0]);
+ val = 0;
+ break;
+ case BCM6362_BASEMODE:
+ reg = pctl->basemode;
+ mask = f->basemode_mask;
+ val = f->basemode_mask;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ bcm6362_rmw_mux(pctl, reg, mask, val);
+
+ return 0;
+}
+
+static int bcm6362_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6362_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm6362_set_gpio(pctl, offset);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6362_pctl_ops = {
+ .get_groups_count = bcm6362_pinctrl_get_group_count,
+ .get_group_name = bcm6362_pinctrl_get_group_name,
+ .get_group_pins = bcm6362_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6362_pmx_ops = {
+ .get_functions_count = bcm6362_pinctrl_get_func_count,
+ .get_function_name = bcm6362_pinctrl_get_func_name,
+ .get_function_groups = bcm6362_pinctrl_get_groups,
+ .set_mux = bcm6362_pinctrl_set_mux,
+ .gpio_request_enable = bcm6362_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6362_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6362_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *led, *mode, *ctrl, *basemode;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "led");
+ led = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(led))
+ return PTR_ERR(led);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
+ ctrl = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basemode");
+ basemode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->led = led;
+ pctl->mode = mode;
+ pctl->ctrl = ctrl;
+ pctl->basemode = basemode;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6362_pctl_ops;
+ pctl->desc.pmxops = &bcm6362_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6362_pins);
+ pctl->desc.pins = bcm6362_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6362_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6362_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6362-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6362_pinctrl_driver = {
+ .probe = bcm6362_pinctrl_probe,
+ .driver = {
+ .name = "bcm6362-pinctrl",
+ .of_match_table = bcm6362_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6362_pinctrl_driver);

View File

@ -0,0 +1,84 @@
From 30594cf9bfff176a9e4b14c50dcd8b9d0cc3edec Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:51 +0200
Subject: [PATCH 10/16] Documentation: add BCM6368 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6368 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6368-pinctrl.txt | 67 ++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.txt
@@ -0,0 +1,67 @@
+* Broadcom BCM6368 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6368-pinctrl".
+- reg: Register specifiers of dirout, dat, mode registers.
+- reg-names: Must be "dirout", "dat", "mode".
+- brcm,gpiobasemode: Phandle to the gpio basemode register.
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6368-pinctrl";
+ reg = <0x10000080 0x08>,
+ <0x10000088 0x08>,
+ <0x10000098 0x04>;
+ reg-names = "dirout", "dat", "mode";
+ brcm,gpiobasemode = <&gpiobasemode>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+gpiobasemode: syscon@100000b8 {
+ compatible = "brcm,bcm6368-gpiobasemode", "syscon";
+ reg = <0x100000b8 4>;
+ native-endian;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 analog_afe0
+gpio1 1 analog_afe1
+gpio2 2 sys_irq
+gpio3 3 serial_led_data
+gpio4 4 serial_led_clk
+gpio5 5 inet_led
+gpio6 6 ephy0_led
+gpio7 7 ephy1_led
+gpio8 8 ephy2_led
+gpio9 9 ephy3_led
+gpio10 10 robosw_led_data
+gpio11 11 robosw_led_clk
+gpio12 12 robosw_led0
+gpio13 13 robosw_led1
+gpio14 14 usb_device_led
+gpio15 15 -
+gpio16 16 pci_req1
+gpio17 17 pci_gnt1
+gpio18 18 pci_intb
+gpio19 19 pci_req0
+gpio20 20 pci_gnt0
+gpio21 21 -
+gpio22 22 pcmcia_cd1
+gpio23 23 pcmcia_cd2
+gpio24 24 pcmcia_vs1
+gpio25 25 pcmcia_vs2
+gpio26 26 ebi_cs2
+gpio27 27 ebi_cs3
+gpio28 28 spi_cs2
+gpio29 29 spi_cs3
+gpio30 30 spi_cs4
+gpio31 31 spi_cs5
+uart1_grp 30-33 uart1

View File

@ -0,0 +1,620 @@
From 90be3cb4f1a45b8be4a4ec264cd66c2f8e893fcb Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:18:25 +0200
Subject: [PATCH 11/16] pinctrl: add a pincontrol driver for BCM6368
Add a pincontrol driver for BCM6368. BCM6368 allows muxing the first 32
GPIOs onto alternative functions. Not all are documented.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 15 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c | 573 ++++++++++++++++++++++++++++++
3 files changed, 589 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -30,3 +30,18 @@ config PINCTRL_BCM6362
select PINCONF
select PINCTRL_BCM63XX
select GENERIC_PINCONF
+
+config PINCTRL_BCM6368
+ bool "BCM6368 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
+ select MFD_SYSCON
+
+config PINCTRL_BCM63268
+ bool "BCM63268 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
+obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
@@ -0,0 +1,573 @@
+/*
+ * 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) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6368_NGPIO 38
+
+#define BCM6368_BASEMODE_MASK 0x7
+#define BCM6368_BASEMODE_GPIO 0x0
+#define BCM6368_BASEMODE_UART1 0x1
+
+struct bcm6368_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6368_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ unsigned dir_out:16;
+ unsigned basemode:3;
+};
+
+struct bcm6368_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+ struct regmap_field *overlay;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6368_BASEMODE_PIN(a, b) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)true \
+ }
+
+static const struct pinctrl_pin_desc bcm6368_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ BCM6368_BASEMODE_PIN(30, "gpio30"),
+ BCM6368_BASEMODE_PIN(31, "gpio31"),
+ BCM6368_BASEMODE_PIN(32, "gpio32"),
+ BCM6368_BASEMODE_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned uart1_grp_pins[] = { 30, 31, 32, 33 };
+
+#define BCM6368_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6368_pingroup bcm6368_groups[] = {
+ BCM6368_GROUP(gpio0),
+ BCM6368_GROUP(gpio1),
+ BCM6368_GROUP(gpio2),
+ BCM6368_GROUP(gpio3),
+ BCM6368_GROUP(gpio4),
+ BCM6368_GROUP(gpio5),
+ BCM6368_GROUP(gpio6),
+ BCM6368_GROUP(gpio7),
+ BCM6368_GROUP(gpio8),
+ BCM6368_GROUP(gpio9),
+ BCM6368_GROUP(gpio10),
+ BCM6368_GROUP(gpio11),
+ BCM6368_GROUP(gpio12),
+ BCM6368_GROUP(gpio13),
+ BCM6368_GROUP(gpio14),
+ BCM6368_GROUP(gpio15),
+ BCM6368_GROUP(gpio16),
+ BCM6368_GROUP(gpio17),
+ BCM6368_GROUP(gpio18),
+ BCM6368_GROUP(gpio19),
+ BCM6368_GROUP(gpio20),
+ BCM6368_GROUP(gpio21),
+ BCM6368_GROUP(gpio22),
+ BCM6368_GROUP(gpio23),
+ BCM6368_GROUP(gpio24),
+ BCM6368_GROUP(gpio25),
+ BCM6368_GROUP(gpio26),
+ BCM6368_GROUP(gpio27),
+ BCM6368_GROUP(gpio28),
+ BCM6368_GROUP(gpio29),
+ BCM6368_GROUP(gpio30),
+ BCM6368_GROUP(gpio31),
+ BCM6368_GROUP(uart1_grp),
+};
+
+static const char * const analog_afe_0_groups[] = {
+ "gpio0",
+};
+
+static const char * const analog_afe_1_groups[] = {
+ "gpio1",
+};
+
+static const char * const sys_irq_groups[] = {
+ "gpio2",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio3",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio4",
+};
+
+static const char * const inet_led_groups[] = {
+ "gpio5",
+};
+
+static const char * const ephy0_led_groups[] = {
+ "gpio6",
+};
+
+static const char * const ephy1_led_groups[] = {
+ "gpio7",
+};
+
+static const char * const ephy2_led_groups[] = {
+ "gpio8",
+};
+
+static const char * const ephy3_led_groups[] = {
+ "gpio9",
+};
+
+static const char * const robosw_led_data_groups[] = {
+ "gpio10",
+};
+
+static const char * const robosw_led_clk_groups[] = {
+ "gpio11",
+};
+
+static const char * const robosw_led0_groups[] = {
+ "gpio12",
+};
+
+static const char * const robosw_led1_groups[] = {
+ "gpio13",
+};
+
+static const char * const usb_device_led_groups[] = {
+ "gpio14",
+};
+
+static const char * const pci_req1_groups[] = {
+ "gpio16",
+};
+
+static const char * const pci_gnt1_groups[] = {
+ "gpio17",
+};
+
+static const char * const pci_intb_groups[] = {
+ "gpio18",
+};
+
+static const char * const pci_req0_groups[] = {
+ "gpio19",
+};
+
+static const char * const pci_gnt0_groups[] = {
+ "gpio20",
+};
+
+static const char * const pcmcia_cd1_groups[] = {
+ "gpio22",
+};
+
+static const char * const pcmcia_cd2_groups[] = {
+ "gpio23",
+};
+
+static const char * const pcmcia_vs1_groups[] = {
+ "gpio24",
+};
+
+static const char * const pcmcia_vs2_groups[] = {
+ "gpio25",
+};
+
+static const char * const ebi_cs2_groups[] = {
+ "gpio26",
+};
+
+static const char * const ebi_cs3_groups[] = {
+ "gpio27",
+};
+
+static const char * const spi_cs2_groups[] = {
+ "gpio28",
+};
+
+static const char * const spi_cs3_groups[] = {
+ "gpio29",
+};
+
+static const char * const spi_cs4_groups[] = {
+ "gpio30",
+};
+
+static const char * const spi_cs5_groups[] = {
+ "gpio31",
+};
+
+static const char * const uart1_groups[] = {
+ "uart1_grp",
+};
+
+#define BCM6368_FUN(n, out) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .dir_out = out, \
+ }
+
+#define BCM6368_BASEMODE_FUN(n, val, out) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .basemode = BCM6368_BASEMODE_##val, \
+ .dir_out = out, \
+ }
+
+static const struct bcm6368_function bcm6368_funcs[] = {
+ BCM6368_FUN(analog_afe_0, 1),
+ BCM6368_FUN(analog_afe_1, 1),
+ BCM6368_FUN(sys_irq, 1),
+ BCM6368_FUN(serial_led_data, 1),
+ BCM6368_FUN(serial_led_clk, 1),
+ BCM6368_FUN(inet_led, 1),
+ BCM6368_FUN(ephy0_led, 1),
+ BCM6368_FUN(ephy1_led, 1),
+ BCM6368_FUN(ephy2_led, 1),
+ BCM6368_FUN(ephy3_led, 1),
+ BCM6368_FUN(robosw_led_data, 1),
+ BCM6368_FUN(robosw_led_clk, 1),
+ BCM6368_FUN(robosw_led0, 1),
+ BCM6368_FUN(robosw_led1, 1),
+ BCM6368_FUN(usb_device_led, 1),
+ BCM6368_FUN(pci_req1, 0),
+ BCM6368_FUN(pci_gnt1, 0),
+ BCM6368_FUN(pci_intb, 0),
+ BCM6368_FUN(pci_req0, 0),
+ BCM6368_FUN(pci_gnt0, 0),
+ BCM6368_FUN(pcmcia_cd1, 0),
+ BCM6368_FUN(pcmcia_cd2, 0),
+ BCM6368_FUN(pcmcia_vs1, 0),
+ BCM6368_FUN(pcmcia_vs2, 0),
+ BCM6368_FUN(ebi_cs2, 1),
+ BCM6368_FUN(ebi_cs3, 1),
+ BCM6368_FUN(spi_cs2, 1),
+ BCM6368_FUN(spi_cs3, 1),
+ BCM6368_FUN(spi_cs4, 1),
+ BCM6368_FUN(spi_cs5, 1),
+ BCM6368_BASEMODE_FUN(uart1, UART1, 0x6),
+};
+
+static int bcm6368_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6368_groups);
+}
+
+static const char *bcm6368_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6368_groups[group].name;
+}
+
+static int bcm6368_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6368_groups[group].pins;
+ *num_pins = bcm6368_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6368_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6368_funcs);
+}
+
+static const char *bcm6368_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6368_funcs[selector].name;
+}
+
+static int bcm6368_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6368_funcs[selector].groups;
+ *num_groups = bcm6368_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6368_rmw_mux(struct bcm6368_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ u32 tmp;
+
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= (val & mask);
+ __raw_writel(tmp, reg);
+}
+
+static int bcm6368_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6368_pingroup *grp = &bcm6368_groups[group];
+ const struct bcm6368_function *fun = &bcm6368_funcs[selector];
+ unsigned long flags;
+ int i, pin;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ if (fun->basemode) {
+ u32 mask = 0;
+
+ for (i = 0; i < grp->num_pins; i++) {
+ pin = grp->pins[i];
+ if (pin < 32)
+ mask |= BIT(pin);
+ }
+
+ bcm6368_rmw_mux(pctl, pctl->mode, mask, 0);
+ regmap_field_write(pctl->overlay, fun->basemode);
+ } else {
+ pin = grp->pins[0];
+
+ if (bcm6368_pins[pin].drv_data)
+ regmap_field_write(pctl->overlay,
+ BCM6368_BASEMODE_GPIO);
+
+ bcm6368_rmw_mux(pctl, pctl->mode, BIT(pin), BIT(pin));
+ }
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ for (pin = 0; pin < grp->num_pins; pin++) {
+ int hw_gpio = bcm6368_pins[pin].number;
+ struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
+
+ if (fun->dir_out & BIT(pin))
+ gc->direction_output(gc, hw_gpio % 32, 0);
+ else
+ gc->direction_input(gc, hw_gpio % 32);
+ }
+
+ return 0;
+}
+
+static int bcm6368_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned long flags;
+
+ if (offset >= 32 && !bcm6368_pins[offset].drv_data)
+ return 0;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ /* disable all functions using this pin */
+ if (offset < 32)
+ bcm6368_rmw_mux(pctl, pctl->mode, BIT(offset), 0);
+
+ if (bcm6368_pins[offset].drv_data)
+ regmap_field_write(pctl->overlay, BCM6368_BASEMODE_GPIO);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6368_pctl_ops = {
+ .get_groups_count = bcm6368_pinctrl_get_group_count,
+ .get_group_name = bcm6368_pinctrl_get_group_name,
+ .get_group_pins = bcm6368_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6368_pmx_ops = {
+ .get_functions_count = bcm6368_pinctrl_get_func_count,
+ .get_function_name = bcm6368_pinctrl_get_func_name,
+ .get_function_groups = bcm6368_pinctrl_get_groups,
+ .set_mux = bcm6368_pinctrl_set_mux,
+ .gpio_request_enable = bcm6368_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6368_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6368_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode;
+ struct regmap *basemode;
+ struct reg_field overlay = REG_FIELD(0, 0, 3);
+
+ if (pdev->dev.of_node)
+ basemode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "brcm,gpiobasemode");
+ else
+ basemode = syscon_regmap_lookup_by_pdevname("syscon.b00000b8");
+
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->overlay = devm_regmap_field_alloc(&pdev->dev, basemode, overlay);
+ if (IS_ERR(pctl->overlay))
+ return PTR_ERR(pctl->overlay);
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+
+ /* disable all muxes by default */
+ __raw_writel(0, pctl->mode);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6368_pctl_ops;
+ pctl->desc.pmxops = &bcm6368_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6368_pins);
+ pctl->desc.pins = bcm6368_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6368_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6368_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6368-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6368_pinctrl_driver = {
+ .probe = bcm6368_pinctrl_probe,
+ .driver = {
+ .name = "bcm6368-pinctrl",
+ .of_match_table = bcm6368_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6368_pinctrl_driver);

View File

@ -0,0 +1,106 @@
From 28cc80e4ada5d73d5305fd268297825cd8d01936 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:37:08 +0200
Subject: [PATCH 12/16] Documentation: add BCM63268 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in the BCM63268
family SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm63268-pinctrl.txt | 88 ++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.txt
@@ -0,0 +1,88 @@
+* Broadcom BCM63268 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6362-pinctrl".
+- reg: Register specifiers of dirout, dat, led, mode, ctrl, basemode registers.
+- reg-names: Must be "dirout", "dat", "led", "mode", "ctrl", "basemode".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@100000c0 {
+ compatible = "brcm,bcm63268-pinctrl";
+ reg = <0x100000c0 0x8>,
+ <0x100000c8 0x8>,
+ <0x100000d0 0x4>,
+ <0x100000d8 0x4>,
+ <0x100000dc 0x4>,
+ <0x100000f8 0x4>;
+ reg-names = "dirout", "dat", "led", "mode",
+ "ctrl", "basemode";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led, serial_led_clk
+gpio1 1 led, serial_led_data
+gpio2 2 led,
+gpio3 3 led,
+gpio4 4 led,
+gpio5 5 led,
+gpio6 6 led,
+gpio7 7 led,
+gpio8 8 led, hsspi_cs6
+gpio9 9 led, hsspi_cs7
+gpio10 10 led, uart1_scts
+gpio11 11 led, uart1_srts
+gpio12 12 led, uart1_sdin
+gpio13 13 led, uart1_sdout
+gpio14 14 led, ntr_pulse_in
+gpio15 15 led, dsl_ntr_pulse_out
+gpio16 16 led, hsspi_cs4
+gpio17 17 led, hsspi_cs5
+gpio18 18 led, adsl_spi_miso
+gpio19 19 led, adsl_spi_mosi
+gpio20 20 led,
+gpio21 21 led,
+gpio22 22 led, vreg_clk
+gpio23 23 led, pcie_clkreq_b
+gpio24 24 uart1_scts
+gpio25 25 uart1_srts
+gpio26 26 uart1_sdin
+gpio27 27 uart1_sdout
+gpio28 28 ntr_pulse_in
+gpio29 29 dsl_ntr_pulse_out
+gpio30 30 switch_led_clk
+gpio31 31 switch_led_data
+gpio32 32 wifi
+gpio33 33 wifi
+gpio34 34 wifi
+gpio35 35 wifi
+gpio36 36 wifi
+gpio37 37 wifi
+gpio38 38 wifi
+gpio39 39 wifi
+gpio40 40 wifi
+gpio41 41 wifi
+gpio42 42 wifi
+gpio43 43 wifi
+gpio44 44 wifi
+gpio45 45 wifi
+gpio46 46 wifi
+gpio47 47 wifi
+gpio48 48 wifi
+gpio49 49 wifi
+gpio50 50 wifi
+gpio51 51 wifi
+nand_grp 2-7,24-31 nand
+dect_pd_grp 8-9 dect_pd
+vdsl_phy0_grp 10-11 vdsl_phy0
+vdsl_phy1_grp 12-13 vdsl_phy1
+vdsl_phy2_grp 24-25 vdsl_phy2
+vdsl_phy3_grp 26-27 vdsl_phy3

View File

@ -0,0 +1,736 @@
From 8665d3ea63649cc155286c75f83f694a930580e5 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:19:12 +0200
Subject: [PATCH 13/16] pinctrl: add a pincontrol driver for BCM63268
Add a pincontrol driver for BCM63268. BCM63268 allows muxing GPIOs
to different functions. Depending on the mux, these are either single
pin configurations or whole pin groups.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c | 710 +++++++++++++++++++++++++++++
2 files changed, 711 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
+obj-$(CONFIG_PINCTRL_BCM63268) += pinctrl-bcm63268.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c
@@ -0,0 +1,710 @@
+/*
+ * 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) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM63268_NGPIO 52
+
+/* GPIO_BASEMODE register */
+#define BASEMODE_NAND BIT(2) /* GPIOs 2-7, 24-31 */
+#define BASEMODE_GPIO35 BIT(4) /* GPIO 35 */
+#define BASEMODE_DECTPD BIT(5) /* GPIOs 8/9 */
+#define BASEMODE_VDSL_PHY_0 BIT(6) /* GPIOs 10/11 */
+#define BASEMODE_VDSL_PHY_1 BIT(7) /* GPIOs 12/13 */
+#define BASEMODE_VDSL_PHY_2 BIT(8) /* GPIOs 24/25 */
+#define BASEMODE_VDSL_PHY_3 BIT(9) /* GPIOs 26/27 */
+
+enum bcm63268_pinctrl_reg {
+ BCM63268_LEDCTRL,
+ BCM63268_MODE,
+ BCM63268_CTRL,
+ BCM63268_BASEMODE,
+};
+
+struct bcm63268_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm63268_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ enum bcm63268_pinctrl_reg reg;
+ u32 mask;
+};
+
+struct bcm63268_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *led;
+ void __iomem *mode;
+ void __iomem *ctrl;
+ void __iomem *basemode;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM63268_PIN(a, b, basemode) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(basemode) \
+ }
+
+static const struct pinctrl_pin_desc bcm63268_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ BCM63268_PIN(2, "gpio2", BASEMODE_NAND),
+ BCM63268_PIN(3, "gpio3", BASEMODE_NAND),
+ BCM63268_PIN(4, "gpio4", BASEMODE_NAND),
+ BCM63268_PIN(5, "gpio5", BASEMODE_NAND),
+ BCM63268_PIN(6, "gpio6", BASEMODE_NAND),
+ BCM63268_PIN(7, "gpio7", BASEMODE_NAND),
+ BCM63268_PIN(8, "gpio8", BASEMODE_DECTPD),
+ BCM63268_PIN(9, "gpio9", BASEMODE_DECTPD),
+ BCM63268_PIN(10, "gpio10", BASEMODE_VDSL_PHY_0),
+ BCM63268_PIN(11, "gpio11", BASEMODE_VDSL_PHY_0),
+ BCM63268_PIN(12, "gpio12", BASEMODE_VDSL_PHY_1),
+ BCM63268_PIN(13, "gpio13", BASEMODE_VDSL_PHY_1),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ BCM63268_PIN(24, "gpio24", BASEMODE_NAND | BASEMODE_VDSL_PHY_2),
+ BCM63268_PIN(25, "gpio25", BASEMODE_NAND | BASEMODE_VDSL_PHY_2),
+ BCM63268_PIN(26, "gpio26", BASEMODE_NAND | BASEMODE_VDSL_PHY_3),
+ BCM63268_PIN(27, "gpio27", BASEMODE_NAND | BASEMODE_VDSL_PHY_3),
+ BCM63268_PIN(28, "gpio28", BASEMODE_NAND),
+ BCM63268_PIN(29, "gpio29", BASEMODE_NAND),
+ BCM63268_PIN(30, "gpio30", BASEMODE_NAND),
+ BCM63268_PIN(31, "gpio31", BASEMODE_NAND),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+ PINCTRL_PIN(48, "gpio48"),
+ PINCTRL_PIN(49, "gpio49"),
+ PINCTRL_PIN(50, "gpio50"),
+ PINCTRL_PIN(51, "gpio51"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned gpio32_pins[] = { 32 };
+static unsigned gpio33_pins[] = { 33 };
+static unsigned gpio34_pins[] = { 34 };
+static unsigned gpio35_pins[] = { 35 };
+static unsigned gpio36_pins[] = { 36 };
+static unsigned gpio37_pins[] = { 37 };
+static unsigned gpio38_pins[] = { 38 };
+static unsigned gpio39_pins[] = { 39 };
+static unsigned gpio40_pins[] = { 40 };
+static unsigned gpio41_pins[] = { 41 };
+static unsigned gpio42_pins[] = { 42 };
+static unsigned gpio43_pins[] = { 43 };
+static unsigned gpio44_pins[] = { 44 };
+static unsigned gpio45_pins[] = { 45 };
+static unsigned gpio46_pins[] = { 46 };
+static unsigned gpio47_pins[] = { 47 };
+static unsigned gpio48_pins[] = { 48 };
+static unsigned gpio49_pins[] = { 49 };
+static unsigned gpio50_pins[] = { 50 };
+static unsigned gpio51_pins[] = { 51 };
+
+static unsigned nand_grp_pins[] = {
+ 2, 3, 4, 5, 6, 7, 24,
+ 25, 26, 27, 28, 29, 30, 31,
+};
+
+static unsigned dectpd_grp_pins[] = { 8, 9 };
+static unsigned vdsl_phy0_grp_pins[] = { 10, 11 };
+static unsigned vdsl_phy1_grp_pins[] = { 12, 13 };
+static unsigned vdsl_phy2_grp_pins[] = { 24, 25 };
+static unsigned vdsl_phy3_grp_pins[] = { 26, 27 };
+
+#define BCM63268_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm63268_pingroup bcm63268_groups[] = {
+ BCM63268_GROUP(gpio0),
+ BCM63268_GROUP(gpio1),
+ BCM63268_GROUP(gpio2),
+ BCM63268_GROUP(gpio3),
+ BCM63268_GROUP(gpio4),
+ BCM63268_GROUP(gpio5),
+ BCM63268_GROUP(gpio6),
+ BCM63268_GROUP(gpio7),
+ BCM63268_GROUP(gpio8),
+ BCM63268_GROUP(gpio9),
+ BCM63268_GROUP(gpio10),
+ BCM63268_GROUP(gpio11),
+ BCM63268_GROUP(gpio12),
+ BCM63268_GROUP(gpio13),
+ BCM63268_GROUP(gpio14),
+ BCM63268_GROUP(gpio15),
+ BCM63268_GROUP(gpio16),
+ BCM63268_GROUP(gpio17),
+ BCM63268_GROUP(gpio18),
+ BCM63268_GROUP(gpio19),
+ BCM63268_GROUP(gpio20),
+ BCM63268_GROUP(gpio21),
+ BCM63268_GROUP(gpio22),
+ BCM63268_GROUP(gpio23),
+ BCM63268_GROUP(gpio24),
+ BCM63268_GROUP(gpio25),
+ BCM63268_GROUP(gpio26),
+ BCM63268_GROUP(gpio27),
+ BCM63268_GROUP(gpio28),
+ BCM63268_GROUP(gpio29),
+ BCM63268_GROUP(gpio30),
+ BCM63268_GROUP(gpio31),
+ BCM63268_GROUP(gpio32),
+ BCM63268_GROUP(gpio33),
+ BCM63268_GROUP(gpio34),
+ BCM63268_GROUP(gpio35),
+ BCM63268_GROUP(gpio36),
+ BCM63268_GROUP(gpio37),
+ BCM63268_GROUP(gpio38),
+ BCM63268_GROUP(gpio39),
+ BCM63268_GROUP(gpio40),
+ BCM63268_GROUP(gpio41),
+ BCM63268_GROUP(gpio42),
+ BCM63268_GROUP(gpio43),
+ BCM63268_GROUP(gpio44),
+ BCM63268_GROUP(gpio45),
+ BCM63268_GROUP(gpio46),
+ BCM63268_GROUP(gpio47),
+ BCM63268_GROUP(gpio48),
+ BCM63268_GROUP(gpio49),
+ BCM63268_GROUP(gpio50),
+ BCM63268_GROUP(gpio51),
+
+ /* multi pin groups */
+ BCM63268_GROUP(nand_grp),
+ BCM63268_GROUP(dectpd_grp),
+ BCM63268_GROUP(vdsl_phy0_grp),
+ BCM63268_GROUP(vdsl_phy1_grp),
+ BCM63268_GROUP(vdsl_phy2_grp),
+ BCM63268_GROUP(vdsl_phy3_grp),
+};
+
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio0",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio1",
+};
+
+static const char * const hsspi_cs4_groups[] = {
+ "gpio16",
+};
+
+static const char * const hsspi_cs5_groups[] = {
+ "gpio17",
+};
+
+static const char * const hsspi_cs6_groups[] = {
+ "gpio8",
+};
+
+static const char * const hsspi_cs7_groups[] = {
+ "gpio9",
+};
+
+static const char * const uart1_scts_groups[] = {
+ "gpio10",
+ "gpio24",
+};
+
+static const char * const uart1_srts_groups[] = {
+ "gpio11",
+ "gpio25",
+};
+
+static const char * const uart1_sdin_groups[] = {
+ "gpio12",
+ "gpio26",
+};
+
+static const char * const uart1_sdout_groups[] = {
+ "gpio13",
+ "gpio27",
+};
+
+static const char * const ntr_pulse_in_groups[] = {
+ "gpio14",
+ "gpio28",
+};
+
+static const char * const dsl_ntr_pulse_out_groups[] = {
+ "gpio15",
+ "gpio29",
+};
+
+static const char * const adsl_spi_miso_groups[] = {
+ "gpio18",
+};
+
+static const char * const adsl_spi_mosi_groups[] = {
+ "gpio19",
+};
+
+static const char * const vreg_clk_groups[] = {
+ "gpio22",
+};
+
+static const char * const pcie_clkreq_b_groups[] = {
+ "gpio23",
+};
+
+static const char * const switch_led_clk_groups[] = {
+ "gpio30",
+};
+
+static const char * const switch_led_data_groups[] = {
+ "gpio31",
+};
+
+static const char * const wifi_groups[] = {
+ "gpio32",
+ "gpio33",
+ "gpio34",
+ "gpio35",
+ "gpio36",
+ "gpio37",
+ "gpio38",
+ "gpio39",
+ "gpio40",
+ "gpio41",
+ "gpio42",
+ "gpio43",
+ "gpio44",
+ "gpio45",
+ "gpio46",
+ "gpio47",
+ "gpio48",
+ "gpio49",
+ "gpio50",
+ "gpio51",
+};
+
+static const char * const nand_groups[] = {
+ "nand_grp",
+};
+
+static const char * const dectpd_groups[] = {
+ "dectpd_grp",
+};
+
+static const char * const vdsl_phy_override_0_groups[] = {
+ "vdsl_phy_override_0_grp",
+};
+
+static const char * const vdsl_phy_override_1_groups[] = {
+ "vdsl_phy_override_1_grp",
+};
+
+static const char * const vdsl_phy_override_2_groups[] = {
+ "vdsl_phy_override_2_grp",
+};
+
+static const char * const vdsl_phy_override_3_groups[] = {
+ "vdsl_phy_override_3_grp",
+};
+
+#define BCM63268_LED_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_LEDCTRL, \
+ }
+
+#define BCM63268_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_MODE, \
+ }
+
+#define BCM63268_CTRL_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_CTRL, \
+ }
+
+#define BCM63268_BASEMODE_FUN(n, val) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_BASEMODE, \
+ .mask = val, \
+ }
+
+static const struct bcm63268_function bcm63268_funcs[] = {
+ BCM63268_LED_FUN(led),
+ BCM63268_MODE_FUN(serial_led_clk),
+ BCM63268_MODE_FUN(serial_led_data),
+ BCM63268_MODE_FUN(hsspi_cs6),
+ BCM63268_MODE_FUN(hsspi_cs7),
+ BCM63268_MODE_FUN(uart1_scts),
+ BCM63268_MODE_FUN(uart1_srts),
+ BCM63268_MODE_FUN(uart1_sdin),
+ BCM63268_MODE_FUN(uart1_sdout),
+ BCM63268_MODE_FUN(ntr_pulse_in),
+ BCM63268_MODE_FUN(dsl_ntr_pulse_out),
+ BCM63268_MODE_FUN(hsspi_cs4),
+ BCM63268_MODE_FUN(hsspi_cs5),
+ BCM63268_MODE_FUN(adsl_spi_miso),
+ BCM63268_MODE_FUN(adsl_spi_mosi),
+ BCM63268_MODE_FUN(vreg_clk),
+ BCM63268_MODE_FUN(pcie_clkreq_b),
+ BCM63268_MODE_FUN(switch_led_clk),
+ BCM63268_MODE_FUN(switch_led_data),
+ BCM63268_CTRL_FUN(wifi),
+ BCM63268_BASEMODE_FUN(nand, BASEMODE_NAND),
+ BCM63268_BASEMODE_FUN(dectpd, BASEMODE_DECTPD),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_0, BASEMODE_VDSL_PHY_0),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_1, BASEMODE_VDSL_PHY_1),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_2, BASEMODE_VDSL_PHY_2),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_3, BASEMODE_VDSL_PHY_3),
+};
+
+static int bcm63268_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm63268_groups);
+}
+
+static const char *bcm63268_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm63268_groups[group].name;
+}
+
+static int bcm63268_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm63268_groups[group].pins;
+ *num_pins = bcm63268_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm63268_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm63268_funcs);
+}
+
+static const char *bcm63268_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm63268_funcs[selector].name;
+}
+
+static int bcm63268_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm63268_funcs[selector].groups;
+ *num_groups = bcm63268_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm63268_rmw_mux(struct bcm63268_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= val;
+ __raw_writel(tmp, reg);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static void bcm63268_set_gpio(struct bcm63268_pinctrl *pctl, unsigned pin)
+{
+ const struct pinctrl_pin_desc *desc = &bcm63268_pins[pin];
+ u32 basemode = (unsigned long)desc->drv_data;
+ u32 mask = BIT(pin % 32);
+
+ if (basemode)
+ bcm63268_rmw_mux(pctl, pctl->basemode, basemode, 0);
+
+ if (pin < 32) {
+ /* base mode: 0 => gpio, 1 => mux function */
+ bcm63268_rmw_mux(pctl, pctl->mode, mask, 0);
+
+ /* pins 0-23 might be muxed to led */
+ if (pin < 24)
+ bcm63268_rmw_mux(pctl, pctl->led, mask, 0);
+ } else if (pin < 52) {
+ /* ctrl reg: 0 => wifi function, 1 => gpio */
+ bcm63268_rmw_mux(pctl, pctl->ctrl, mask, mask);
+ }
+}
+
+static int bcm63268_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm63268_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm63268_pingroup *grp = &bcm63268_groups[group];
+ const struct bcm63268_function *f = &bcm63268_funcs[selector];
+ unsigned i;
+ void __iomem *reg;
+ u32 val, mask;
+
+ for (i = 0; i < grp->num_pins; i++)
+ bcm63268_set_gpio(pctl, grp->pins[i]);
+
+ switch (f->reg) {
+ case BCM63268_LEDCTRL:
+ reg = pctl->led;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM63268_MODE:
+ reg = pctl->mode;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM63268_CTRL:
+ reg = pctl->ctrl;
+ mask = BIT(grp->pins[0]);
+ val = 0;
+ break;
+ case BCM63268_BASEMODE:
+ reg = pctl->basemode;
+ mask = f->mask;
+ val = f->mask;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ bcm63268_rmw_mux(pctl, reg, mask, val);
+
+ return 0;
+}
+
+static int bcm63268_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm63268_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm63268_set_gpio(pctl, offset);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm63268_pctl_ops = {
+ .get_groups_count = bcm63268_pinctrl_get_group_count,
+ .get_group_name = bcm63268_pinctrl_get_group_name,
+ .get_group_pins = bcm63268_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm63268_pmx_ops = {
+ .get_functions_count = bcm63268_pinctrl_get_func_count,
+ .get_function_name = bcm63268_pinctrl_get_func_name,
+ .get_function_groups = bcm63268_pinctrl_get_groups,
+ .set_mux = bcm63268_pinctrl_set_mux,
+ .gpio_request_enable = bcm63268_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm63268_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm63268_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *led, *mode, *ctrl, *basemode;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "led");
+ led = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(led))
+ return PTR_ERR(led);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
+ ctrl = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basemode");
+ basemode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->led = led;
+ pctl->mode = mode;
+ pctl->ctrl = ctrl;
+ pctl->basemode = basemode;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm63268_pctl_ops;
+ pctl->desc.pmxops = &bcm63268_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm63268_pins);
+ pctl->desc.pins = bcm63268_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM63268_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm63268_pinctrl_match[] = {
+ { .compatible = "brcm,bcm63268-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm63268_pinctrl_driver = {
+ .probe = bcm63268_pinctrl_probe,
+ .driver = {
+ .name = "bcm63268-pinctrl",
+ .of_match_table = bcm63268_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm63268_pinctrl_driver);

View File

@ -0,0 +1,161 @@
From e058fa1969019c2f6705c53c4130e364a877d4e6 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sun, 26 Nov 2017 12:07:31 +0100
Subject: [PATCH] gpio: fix device tree gpio hogs on dual role gpio/pincontrol
controllers
For dual role gpio and pincontrol controller, the device registration
path is often:
pinctrl_register(...);
gpiochip_add_data(...);
gpiochip_add_pin_range(...);
If the device tree node has any gpio-hogs, the code will try to apply them
in the gpiochip_add_data step, but fail as they cannot be requested, as the
ranges are missing. But we also cannot first add the pinranges, as the
appropriate data structures are only initialized in gpiochip_add_data.
To fix this, defer gpio-hogs to the time pin ranges get added instead of
directly at chip request time, if the gpio-chip has a request method.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/gpio/gpiolib-of.c | 20 +++++++++++++++-----
drivers/gpio/gpiolib.c | 5 +++--
drivers/gpio/gpiolib.h | 8 ++++++++
3 files changed, 26 insertions(+), 7 deletions(-)
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -644,23 +644,30 @@ static struct gpio_desc *of_parse_own_gp
* of_gpiochip_add_hog - Add all hogs in a hog device node
* @chip: gpio chip to act on
* @hog: device node describing the hogs
+ * @start: first gpio to check
+ * @num: number of gpios to check
*
* Returns error if it fails otherwise 0 on success.
*/
-static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog)
+static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog,
+ unsigned int start, unsigned int num)
{
enum gpiod_flags dflags;
struct gpio_desc *desc;
unsigned long lflags;
const char *name;
unsigned int i;
- int ret;
+ int ret, hwgpio;
for (i = 0;; i++) {
desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags);
if (IS_ERR(desc))
break;
+ hwgpio = gpio_chip_hwgpio(desc);
+ if (hwgpio < start || hwgpio >= (start + num))
+ continue;
+
ret = gpiod_hog(desc, name, lflags, dflags);
if (ret < 0)
return ret;
@@ -676,12 +683,15 @@ static int of_gpiochip_add_hog(struct gp
/**
* of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
* @chip: gpio chip to act on
+ * @start: first gpio to check
+ * @num: number of gpios to check
*
- * This is only used by of_gpiochip_add to request/set GPIO initial
- * configuration.
+ * This is used by of_gpiochip_add, gpiochip_add_pingroup_range and
+ * gpiochip_add_pin_range to request/set GPIO initial configuration.
* It returns error if it fails otherwise 0 on success.
*/
-static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
+int of_gpiochip_scan_gpios(struct gpio_chip *chip, unsigned int start,
+ unsigned int num)
{
struct device_node *np;
int ret;
@@ -690,7 +700,7 @@ static int of_gpiochip_scan_gpios(struct
if (!of_property_read_bool(np, "gpio-hog"))
continue;
- ret = of_gpiochip_add_hog(chip, np);
+ ret = of_gpiochip_add_hog(chip, np, start, num);
if (ret < 0) {
of_node_put(np);
return ret;
@@ -756,7 +766,7 @@ static int of_gpio_notify(struct notifie
if (chip == NULL)
return NOTIFY_OK; /* not for us */
- ret = of_gpiochip_add_hog(chip, rd->dn);
+ ret = of_gpiochip_add_hog(chip, rd->dn, 0, chip->ngpio);
if (ret < 0) {
pr_err("%s: failed to add hogs for %pOF\n", __func__,
rd->dn);
@@ -1028,9 +1038,11 @@ int of_gpiochip_add(struct gpio_chip *ch
of_node_get(chip->of_node);
- ret = of_gpiochip_scan_gpios(chip);
- if (ret)
- of_node_put(chip->of_node);
+ if (!chip->request) {
+ ret = of_gpiochip_scan_gpios(chip, 0, chip->ngpio);
+ if (ret)
+ of_node_put(chip->of_node);
+ }
return ret;
}
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1886,7 +1886,8 @@ int gpiochip_add_pingroup_range(struct g
list_add_tail(&pin_range->node, &gdev->pin_ranges);
- return 0;
+ return of_gpiochip_scan_gpios(gc, gpio_offset,
+ pin_range->range.npins);
}
EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
@@ -1943,7 +1944,7 @@ int gpiochip_add_pin_range(struct gpio_c
list_add_tail(&pin_range->node, &gdev->pin_ranges);
- return 0;
+ return of_gpiochip_scan_gpios(gc, gpio_offset, npins);
}
EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
--- a/drivers/gpio/gpiolib-of.h
+++ b/drivers/gpio/gpiolib-of.h
@@ -13,6 +13,8 @@ struct gpio_desc *of_find_gpio(struct de
unsigned long *lookupflags);
int of_gpiochip_add(struct gpio_chip *gc);
void of_gpiochip_remove(struct gpio_chip *gc);
+int of_gpiochip_scan_gpios(struct gpio_chip *chip, unsigned int start,
+ unsigned int num);
int of_gpio_get_count(struct device *dev, const char *con_id);
bool of_gpio_need_valid_mask(const struct gpio_chip *gc);
#else
@@ -25,6 +27,12 @@ static inline struct gpio_desc *of_find_
}
static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
+static inline int of_gpiochip_scan_gpios(struct gpio_chip *chip,
+ unsigned int start,
+ unsigned int num)
+{
+ return 0;
+}
static inline int of_gpio_get_count(struct device *dev, const char *con_id)
{
return 0;

View File

@ -0,0 +1,68 @@
From: Adrian Schmutzler <freifunk@adrianschmutzler.de>
Date: Fri, 03 Apr 2020 19:50:03 +0200
Subject: add removed helper syscon_regmap_lookup_by_pdevname
The helper syscon_regmap_lookup_by_pdevname has been removed in 29d14b668d2f
("mfd: Remove unused helper syscon_regmap_lookup_by_pdevname") due to lack
of users.
Thus, we have to maintain it locally.
This patch includes a fix due to changes in driver_find_device;
kernel commit: 92ce7e83b4e5 ("driver_find_device: Unify the match function
with class_find_device()")
Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -205,6 +205,27 @@ struct regmap *syscon_regmap_lookup_by_c
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
+static int syscon_match_pdevname(struct device *dev, const void *data)
+{
+ return !strcmp(dev_name(dev), (const char *)data);
+}
+
+struct regmap *syscon_regmap_lookup_by_pdevname(const char *s)
+{
+ struct device *dev;
+ struct syscon *syscon;
+
+ dev = driver_find_device(&syscon_driver.driver, NULL, (void *)s,
+ syscon_match_pdevname);
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ syscon = dev_get_drvdata(dev);
+
+ return syscon->regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_pdevname);
+
struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
const char *property)
{
--- a/include/linux/mfd/syscon.h
+++ b/include/linux/mfd/syscon.h
@@ -20,6 +20,7 @@ struct device_node;
extern struct regmap *device_node_to_regmap(struct device_node *np);
extern struct regmap *syscon_node_to_regmap(struct device_node *np);
extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s);
+extern struct regmap *syscon_regmap_lookup_by_pdevname(const char *s);
extern struct regmap *syscon_regmap_lookup_by_phandle(
struct device_node *np,
const char *property);
@@ -43,6 +44,11 @@ static inline struct regmap *syscon_regm
{
return ERR_PTR(-ENOTSUPP);
}
+
+static inline struct regmap *syscon_regmap_lookup_by_pdevname(const char *s)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
static inline struct regmap *syscon_regmap_lookup_by_phandle(
struct device_node *np,

View File

@ -0,0 +1,11 @@
--- a/drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
@@ -566,7 +566,7 @@ static int bcm6362_pinctrl_set_mux(struc
val = BIT(grp->pins[0]);
break;
case BCM6362_MODE:
- reg = pctl->ctrl;
+ reg = pctl->mode;
mask = BIT(grp->pins[0]);
val = BIT(grp->pins[0]);
break;

View File

@ -0,0 +1,66 @@
From 6ac09efa8f0e189ffe7dd7b0889289de56ee44cc Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 19 Jan 2014 12:18:03 +0100
Subject: [PATCH] USB: EHCI: allow limiting ports for ehci-platform
In the same way as the ohci platform driver allows limiting ports,
enable the same for ehci. This prevents a mismatch in the available
ports between ehci/ohci on USB 2.0 controllers.
This is needed if the USB host controller always reports the maximum
number of ports regardless of the number of available ports (because
one might be set to be usb device).
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
drivers/usb/host/ehci-hcd.c | 4 ++++
drivers/usb/host/ehci-platform.c | 2 ++
drivers/usb/host/ehci.h | 1 +
include/linux/usb/ehci_pdriver.h | 1 +
4 files changed, 8 insertions(+)
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -678,6 +678,10 @@ int ehci_setup(struct usb_hcd *hcd)
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ if (ehci->num_ports) {
+ ehci->hcs_params &= ~0xf; /* bits 3:0, ports on HC */
+ ehci->hcs_params |= ehci->num_ports;
+ }
ehci->sbrn = HCD_USB2;
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -65,6 +65,9 @@ static int ehci_platform_reset(struct us
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+ if (pdata->num_ports && pdata->num_ports <= 15)
+ ehci->num_ports = pdata->num_ports;
+
if (pdata->pre_setup) {
retval = pdata->pre_setup(hcd);
if (retval < 0)
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -203,6 +203,7 @@ struct ehci_hcd { /* one per controlle
u32 command;
/* SILICON QUIRKS */
+ unsigned int num_ports;
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -43,6 +43,7 @@ struct usb_hcd;
*/
struct usb_ehci_pdata {
int caps_offset;
+ unsigned int num_ports;
unsigned has_tt:1;
unsigned has_synopsys_hc_bug:1;
unsigned big_endian_desc:1;

View File

@ -0,0 +1,484 @@
From 5a50cb0d53344a2429831b00925d6183d4d332e1 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 9 Mar 2014 03:54:05 +0100
Subject: [PATCH 40/44] MIPS: BCM63XX: move device registration code into its
own file
Move device registration code into its own file to allow sharing it
between board implementations.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/Makefile | 1 +
arch/mips/bcm63xx/boards/board_bcm963xx.c | 188 +-------------------------
arch/mips/bcm63xx/boards/board_common.c | 215 ++++++++++++++++++++++++++++++
arch/mips/bcm63xx/boards/board_common.h | 8 ++
4 files changed, 223 insertions(+), 183 deletions(-)
create mode 100644 arch/mips/bcm63xx/boards/board_common.c
create mode 100644 arch/mips/bcm63xx/boards/board_common.h
--- a/arch/mips/bcm63xx/boards/Makefile
+++ b/arch/mips/bcm63xx/boards/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-y += board_common.o
obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -9,32 +9,20 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/ssb/ssb.h>
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
-#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
#include <bcm63xx_nvram.h>
-#include <bcm63xx_dev_pci.h>
-#include <bcm63xx_dev_enet.h>
-#include <bcm63xx_dev_flash.h>
-#include <bcm63xx_dev_hsspi.h>
-#include <bcm63xx_dev_pcmcia.h>
-#include <bcm63xx_dev_spi.h>
-#include <bcm63xx_dev_usb_ehci.h>
-#include <bcm63xx_dev_usb_ohci.h>
-#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
+#include "board_common.h"
+
#include <uapi/linux/bcm933xx_hcs.h>
#define HCS_OFFSET_128K 0x20000
-static struct board_info board;
-
/*
* known 3368 boards
*/
@@ -679,52 +667,6 @@ static const struct board_info __initcon
};
/*
- * Register a sane SPROMv2 to make the on-board
- * bcm4318 WLAN work
- */
-#ifdef CONFIG_SSB_PCIHOST
-static struct ssb_sprom bcm63xx_sprom = {
- .revision = 0x02,
- .board_rev = 0x17,
- .country_code = 0x0,
- .ant_available_bg = 0x3,
- .pa0b0 = 0x15ae,
- .pa0b1 = 0xfa85,
- .pa0b2 = 0xfe8d,
- .pa1b0 = 0xffff,
- .pa1b1 = 0xffff,
- .pa1b2 = 0xffff,
- .gpio0 = 0xff,
- .gpio1 = 0xff,
- .gpio2 = 0xff,
- .gpio3 = 0xff,
- .maxpwr_bg = 0x004c,
- .itssi_bg = 0x00,
- .boardflags_lo = 0x2848,
- .boardflags_hi = 0x0000,
-};
-
-int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
-{
- if (bus->bustype == SSB_BUSTYPE_PCI) {
- memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
- return 0;
- } else {
- pr_err("unable to fill SPROM for given bustype\n");
- return -EINVAL;
- }
-}
-#endif /* CONFIG_SSB_PCIHOST */
-
-/*
- * return board name for /proc/cpuinfo
- */
-const char *board_get_name(void)
-{
- return board.name;
-}
-
-/*
* early init callback, read nvram data from flash and checksum it
*/
void __init board_prom_init(void)
@@ -783,137 +725,15 @@ void __init board_prom_init(void)
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
continue;
/* copy, board desc array is marked initdata */
- memcpy(&board, bcm963xx_boards[i], sizeof(board));
+ board_early_setup(bcm963xx_boards[i]);
break;
}
- /* bail out if board is not found, will complain later */
- if (!board.name[0]) {
+ /* warn if board is not found, will complain later */
+ if (i == ARRAY_SIZE(bcm963xx_boards)) {
char name[17];
memcpy(name, board_name, 16);
name[16] = 0;
pr_err("unknown bcm963xx board: %s\n", name);
- return;
- }
-
- /* setup pin multiplexing depending on board enabled device,
- * this has to be done this early since PCI init is done
- * inside arch_initcall */
- val = 0;
-
-#ifdef CONFIG_PCI
- if (board.has_pci) {
- bcm63xx_pci_enabled = 1;
- if (BCMCPU_IS_6348())
- val |= GPIO_MODE_6348_G2_PCI;
- }
-#endif /* CONFIG_PCI */
-
- if (board.has_pccard) {
- if (BCMCPU_IS_6348())
- val |= GPIO_MODE_6348_G1_MII_PCCARD;
- }
-
- if (board.has_enet0 && !board.enet0.use_internal_phy) {
- if (BCMCPU_IS_6348())
- val |= GPIO_MODE_6348_G3_EXT_MII |
- GPIO_MODE_6348_G0_EXT_MII;
- }
-
- if (board.has_enet1 && !board.enet1.use_internal_phy) {
- if (BCMCPU_IS_6348())
- val |= GPIO_MODE_6348_G3_EXT_MII |
- GPIO_MODE_6348_G0_EXT_MII;
- }
-
- bcm_gpio_writel(val, GPIO_MODE_REG);
-}
-
-/*
- * second stage init callback, good time to panic if we couldn't
- * identify on which board we're running since early printk is working
- */
-void __init board_setup(void)
-{
- if (!board.name[0])
- panic("unable to detect bcm963xx board");
- pr_info("board name: %s\n", board.name);
-
- /* make sure we're running on expected cpu */
- if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
- panic("unexpected CPU for bcm963xx board");
-}
-
-static struct gpio_led_platform_data bcm63xx_led_data;
-
-static struct platform_device bcm63xx_gpio_leds = {
- .name = "leds-gpio",
- .id = 0,
- .dev.platform_data = &bcm63xx_led_data,
-};
-
-/*
- * third stage init callback, register all board devices.
- */
-int __init board_register_devices(void)
-{
- if (board.has_uart0)
- bcm63xx_uart_register(0);
-
- if (board.has_uart1)
- bcm63xx_uart_register(1);
-
- if (board.has_pccard)
- bcm63xx_pcmcia_register();
-
- if (board.has_enet0 &&
- !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
- bcm63xx_enet_register(0, &board.enet0);
-
- if (board.has_enet1 &&
- !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
- bcm63xx_enet_register(1, &board.enet1);
-
- if (board.has_enetsw &&
- !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
- bcm63xx_enetsw_register(&board.enetsw);
-
- if (board.has_usbd)
- bcm63xx_usbd_register(&board.usbd);
-
- if (board.has_ehci0)
- bcm63xx_ehci_register();
-
- if (board.has_ohci0)
- bcm63xx_ohci_register();
-
- /* Generate MAC address for WLAN and register our SPROM,
- * do this after registering enet devices
- */
-#ifdef CONFIG_SSB_PCIHOST
- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
- memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- if (ssb_arch_register_fallback_sprom(
- &bcm63xx_get_fallback_sprom) < 0)
- pr_err("failed to register fallback SPROM\n");
}
-#endif /* CONFIG_SSB_PCIHOST */
-
- bcm63xx_spi_register();
-
- bcm63xx_hsspi_register();
-
- bcm63xx_flash_register();
-
- bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
- bcm63xx_led_data.leds = board.leds;
-
- platform_device_register(&bcm63xx_gpio_leds);
-
- if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
- gpio_request_one(board.ephy_reset_gpio,
- board.ephy_reset_gpio_flags, "ephy-reset");
-
- return 0;
}
--- /dev/null
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -0,0 +1,214 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/ssb/ssb.h>
+#include <asm/addrspace.h>
+#include <bcm63xx_board.h>
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_dev_uart.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_nvram.h>
+#include <bcm63xx_gpio.h>
+#include <bcm63xx_dev_pci.h>
+#include <bcm63xx_dev_enet.h>
+#include <bcm63xx_dev_flash.h>
+#include <bcm63xx_dev_hsspi.h>
+#include <bcm63xx_dev_pcmcia.h>
+#include <bcm63xx_dev_spi.h>
+#include <bcm63xx_dev_usb_ehci.h>
+#include <bcm63xx_dev_usb_ohci.h>
+#include <bcm63xx_dev_usb_usbd.h>
+#include <board_bcm963xx.h>
+
+#define PFX "board: "
+
+static struct board_info board;
+
+/*
+ * Register a sane SPROMv2 to make the on-board
+ * bcm4318 WLAN work
+ */
+#ifdef CONFIG_SSB_PCIHOST
+static struct ssb_sprom bcm63xx_sprom = {
+ .revision = 0x02,
+ .board_rev = 0x17,
+ .country_code = 0x0,
+ .ant_available_bg = 0x3,
+ .pa0b0 = 0x15ae,
+ .pa0b1 = 0xfa85,
+ .pa0b2 = 0xfe8d,
+ .pa1b0 = 0xffff,
+ .pa1b1 = 0xffff,
+ .pa1b2 = 0xffff,
+ .gpio0 = 0xff,
+ .gpio1 = 0xff,
+ .gpio2 = 0xff,
+ .gpio3 = 0xff,
+ .maxpwr_bg = 0x004c,
+ .itssi_bg = 0x00,
+ .boardflags_lo = 0x2848,
+ .boardflags_hi = 0x0000,
+};
+
+int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+{
+ if (bus->bustype == SSB_BUSTYPE_PCI) {
+ memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
+ return 0;
+ } else {
+ printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+ return -EINVAL;
+ }
+}
+#endif
+
+/*
+ * return board name for /proc/cpuinfo
+ */
+const char *board_get_name(void)
+{
+ return board.name;
+}
+
+/*
+ * setup board for device registration
+ */
+void __init board_early_setup(const struct board_info *target)
+{
+ u32 val;
+
+ memcpy(&board, target, sizeof(board));
+
+ /* setup pin multiplexing depending on board enabled device,
+ * this has to be done this early since PCI init is done
+ * inside arch_initcall */
+ val = 0;
+
+#ifdef CONFIG_PCI
+ if (board.has_pci) {
+ bcm63xx_pci_enabled = 1;
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G2_PCI;
+ }
+#endif
+
+ if (board.has_pccard) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G1_MII_PCCARD;
+ }
+
+ if (board.has_enet0 && !board.enet0.use_internal_phy) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G3_EXT_MII |
+ GPIO_MODE_6348_G0_EXT_MII;
+ }
+
+ if (board.has_enet1 && !board.enet1.use_internal_phy) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G3_EXT_MII |
+ GPIO_MODE_6348_G0_EXT_MII;
+ }
+
+ bcm_gpio_writel(val, GPIO_MODE_REG);
+}
+
+
+/*
+ * second stage init callback, good time to panic if we couldn't
+ * identify on which board we're running since early printk is working
+ */
+void __init board_setup(void)
+{
+ if (!board.name[0])
+ panic("unable to detect bcm963xx board");
+ printk(KERN_INFO PFX "board name: %s\n", board.name);
+
+ /* make sure we're running on expected cpu */
+ if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
+ panic("unexpected CPU for bcm963xx board");
+}
+
+static struct gpio_led_platform_data bcm63xx_led_data;
+
+static struct platform_device bcm63xx_gpio_leds = {
+ .name = "leds-gpio",
+ .id = 0,
+ .dev.platform_data = &bcm63xx_led_data,
+};
+
+/*
+ * third stage init callback, register all board devices.
+ */
+int __init board_register_devices(void)
+{
+ if (board.has_uart0)
+ bcm63xx_uart_register(0);
+
+ if (board.has_uart1)
+ bcm63xx_uart_register(1);
+
+ if (board.has_pccard)
+ bcm63xx_pcmcia_register();
+
+ if (board.has_enet0 &&
+ !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
+ bcm63xx_enet_register(0, &board.enet0);
+
+ if (board.has_enet1 &&
+ !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
+ bcm63xx_enet_register(1, &board.enet1);
+
+ if (board.has_enetsw &&
+ !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
+ bcm63xx_enetsw_register(&board.enetsw);
+
+ if (board.has_usbd)
+ bcm63xx_usbd_register(&board.usbd);
+
+ if (board.has_ehci0)
+ bcm63xx_ehci_register();
+
+ if (board.has_ohci0)
+ bcm63xx_ohci_register();
+
+ /* Generate MAC address for WLAN and register our SPROM,
+ * do this after registering enet devices
+ */
+#ifdef CONFIG_SSB_PCIHOST
+ if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ if (ssb_arch_register_fallback_sprom(
+ &bcm63xx_get_fallback_sprom) < 0)
+ pr_err(PFX "failed to register fallback SPROM\n");
+ }
+#endif
+
+ bcm63xx_spi_register();
+
+ bcm63xx_hsspi_register();
+
+ bcm63xx_flash_register();
+
+ bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
+ bcm63xx_led_data.leds = board.leds;
+
+ platform_device_register(&bcm63xx_gpio_leds);
+
+ if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
+ gpio_request_one(board.ephy_reset_gpio,
+ board.ephy_reset_gpio_flags, "ephy-reset");
+
+ return 0;
+}
--- /dev/null
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -0,0 +1,8 @@
+#ifndef __BOARD_COMMON_H
+#define __BOARD_COMMON_H
+
+#include <board_bcm963xx.h>
+
+void board_early_setup(const struct board_info *board);
+
+#endif /* __BOARD_COMMON_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,20 @@
--- a/drivers/irqchip/irq-bcm6345-periph.c
+++ b/drivers/irqchip/irq-bcm6345-periph.c
@@ -52,7 +52,7 @@ static void bcm6345_periph_irq_handle(st
{
struct intc_data *data = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
- struct intc_block *block;
+ struct intc_block *block = NULL;
unsigned int irq = irq_desc_get_irq(desc);
unsigned int idx;
@@ -62,7 +62,7 @@ static void bcm6345_periph_irq_handle(st
if (irq == data->block[idx].parent_irq)
block = &data->block[idx];
- for (idx = 0; idx < data->num_words; idx++) {
+ for (idx = 0; block && idx < data->num_words; idx++) {
int base = idx * IRQS_PER_WORD;
unsigned long pending;
int hw_irq;

View File

@ -0,0 +1,28 @@
--- a/drivers/irqchip/irq-bcm6345-ext.c
+++ b/drivers/irqchip/irq-bcm6345-ext.c
@@ -271,21 +271,19 @@ static int __init bcm6345_ext_intc_of_in
for (i = 0; i < num_irqs; i++) {
irqs[i] = irq_of_parse_and_map(node, i);
- if (!irqs[i]) {
- ret = -ENOMEM;
- goto out_unmap;
- }
+ if (!irqs[i])
+ return -ENOMEM;
}
base = of_iomap(node, 0);
if (!base)
- goto out_unmap;
+ return -ENXIO;
ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift,
toggle_clear_on_ack);
if (!ret)
return 0;
-out_unmap:
+
iounmap(base);
for (i = 0; i < num_irqs; i++)

View File

@ -0,0 +1,20 @@
--- a/drivers/irqchip/irq-bcm6345-periph.c
+++ b/drivers/irqchip/irq-bcm6345-periph.c
@@ -186,6 +186,8 @@ static int bcm6345_periph_set_affinity(s
}
raw_spin_unlock_irqrestore(&priv->lock, flags);
+ irq_data_update_effective_affinity(data, cpumask_of(cpu));
+
return 0;
}
#endif
@@ -197,6 +199,8 @@ static int bcm6345_periph_map(struct irq
irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
+
return 0;
}

View File

@ -0,0 +1,12 @@
--- a/drivers/irqchip/irq-bcm6345-periph.c
+++ b/drivers/irqchip/irq-bcm6345-periph.c
@@ -240,6 +240,9 @@ static int __init __bcm6345_periph_intc_
/* route all interrupts to line 0 by default */
if (i == 0)
block->mask_cache[w] = 0xffffffff;
+
+ /* mask all interrupts */
+ __raw_writel(0, block->en_reg[w]);
}
irq_set_handler_data(block->parent_irq, data);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,84 @@
From 1cacd0f7b0d35f8e3d3f8a69ecb3b5e436d6b9e8 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 22 Dec 2013 13:25:25 +0100
Subject: [PATCH 52/56] MIPS: BCM63XX: fixup mapped SPI flash access on boot
Some bootloaders leave the flash access in an invalid state with dual
read enabled; fix it by disabling it and falling back to simple fast
reads.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/dev-flash.c | 51 ++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -16,6 +16,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
+#include <linux/mtd/spi-nor.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_flash.h>
@@ -111,9 +112,59 @@ static int __init bcm63xx_detect_flash_t
}
}
+#define HSSPI_FLASH_CTRL_REG 0x14
+#define FLASH_CTRL_READ_OPCODE_MASK 0xff
+#define FLASH_CTRL_ADDR_BYTES_MASK (0x3 << 8)
+#define FLASH_CTRL_ADDR_BYTES_2 (0 << 8)
+#define FLASH_CTRL_ADDR_BYTES_3 (1 << 8)
+#define FLASH_CTRL_ADDR_BYTES_4 (2 << 8)
+#define FLASH_CTRL_DUMMY_BYTES_SHIFT 10
+#define FLASH_CTRL_DUMMY_BYTES_MASK (0x3 << FLASH_CTRL_DUMMY_BYTES_SHIFT)
+#define FLASH_CTRL_MB_EN (1 << 23)
+
void __init bcm63xx_flash_detect(void)
{
flash_type = bcm63xx_detect_flash_type();
+
+ /* ensure flash mapping has sane values */
+ if (flash_type == BCM63XX_FLASH_TYPE_SERIAL &&
+ (BCMCPU_IS_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6362() ||
+ BCMCPU_IS_63268())) {
+ u32 val = bcm_rset_readl(RSET_HSSPI, HSSPI_FLASH_CTRL_REG);
+
+ if (val & FLASH_CTRL_MB_EN) {
+ /* cfe might configure non working dual-io mode */
+ val &= ~FLASH_CTRL_MB_EN;
+ val &= ~FLASH_CTRL_READ_OPCODE_MASK;
+ val &= ~FLASH_CTRL_DUMMY_BYTES_MASK;
+ val |= 1 << FLASH_CTRL_DUMMY_BYTES_SHIFT;
+
+ switch (val & FLASH_CTRL_ADDR_BYTES_MASK) {
+ case FLASH_CTRL_ADDR_BYTES_3:
+ val |= SPINOR_OP_READ_FAST;
+ break;
+ case FLASH_CTRL_ADDR_BYTES_4:
+ val |= SPINOR_OP_READ_FAST_4B;
+ break;
+ case FLASH_CTRL_ADDR_BYTES_2:
+ default:
+ pr_warn("unsupported address byte mode (%x), not fixing up\n",
+ val & FLASH_CTRL_ADDR_BYTES_MASK);
+ return;
+ }
+ } else {
+ /* ensure dummy bytes is set to 1 for _FAST reads */
+ u8 cmd = val & FLASH_CTRL_READ_OPCODE_MASK;
+
+ if (cmd != SPINOR_OP_READ_FAST && cmd != SPINOR_OP_READ_FAST_4B)
+ return;
+
+ val &= ~FLASH_CTRL_DUMMY_BYTES_MASK;
+ val |= 1 << FLASH_CTRL_DUMMY_BYTES_SHIFT;
+ }
+
+ bcm_rset_writel(RSET_HSSPI, val, HSSPI_FLASH_CTRL_REG);
+ }
}
int __init bcm63xx_flash_register(void)

View File

@ -0,0 +1,44 @@
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -168,7 +168,11 @@ static struct clk clk_swpkt_usb = {
*/
static void enetsw_set(struct clk *clk, int enable)
{
- if (BCMCPU_IS_6328()) {
+ if (BCMCPU_IS_6318()) {
+ bcm_hwclock_set(CKCTL_6318_ROBOSW250_EN |
+ CKCTL_6318_ROBOSW025_EN, enable);
+ bcm_ub_hwclock_set(UB_CKCTL_6318_ROBOSW_EN, enable);
+ } else if (BCMCPU_IS_6328()) {
bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
} else if (BCMCPU_IS_6362()) {
bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
@@ -220,18 +224,22 @@ static struct clk clk_pcm = {
*/
static void usbh_set(struct clk *clk, int enable)
{
- if (BCMCPU_IS_6328())
+ if (BCMCPU_IS_6318()) {
+ bcm_hwclock_set(CKCTL_6318_USB_EN, enable);
+ bcm_ub_hwclock_set(UB_CKCTL_6318_USB_EN, enable);
+ } else if (BCMCPU_IS_6328()) {
bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
- else if (BCMCPU_IS_6348())
+ } else if (BCMCPU_IS_6348()) {
bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
- else if (BCMCPU_IS_6362())
+ } else if (BCMCPU_IS_6362()) {
bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
- else if (BCMCPU_IS_6368())
+ } else if (BCMCPU_IS_6368()) {
bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
- else if (BCMCPU_IS_63268())
+ } else if (BCMCPU_IS_63268()) {
bcm_hwclock_set(CKCTL_63268_USBH_EN, enable);
- else
+ } else {
return;
+ }
if (enable)
msleep(100);

View File

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

View File

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

View File

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

View File

@ -0,0 +1,108 @@
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -40,6 +40,7 @@ struct board_info {
/* USB config */
struct bcm63xx_usbd_platform_data usbd;
+ unsigned int num_usbh_ports:2;
/* GPIO LEDs */
struct gpio_led leds[5];
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
@@ -1,6 +1,6 @@
#ifndef BCM63XX_DEV_USB_EHCI_H_
#define BCM63XX_DEV_USB_EHCI_H_
-int bcm63xx_ehci_register(void);
+int bcm63xx_ehci_register(unsigned int num_ports);
#endif /* BCM63XX_DEV_USB_EHCI_H_ */
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
@@ -1,6 +1,6 @@
#ifndef BCM63XX_DEV_USB_OHCI_H_
#define BCM63XX_DEV_USB_OHCI_H_
-int bcm63xx_ohci_register(void);
+int bcm63xx_ohci_register(unsigned int num_ports);
#endif /* BCM63XX_DEV_USB_OHCI_H_ */
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -165,6 +165,8 @@ static struct platform_device bcm63xx_gp
*/
int __init board_register_devices(void)
{
+ int usbh_ports = 0;
+
if (board.has_uart0)
bcm63xx_uart_register(0);
@@ -186,14 +188,21 @@ int __init board_register_devices(void)
!board_get_mac_address(board.enetsw.mac_addr))
bcm63xx_enetsw_register(&board.enetsw);
+ if ((board.has_ohci0 || board.has_ehci0)) {
+ usbh_ports = board.num_usbh_ports;
+
+ if (!usbh_ports || WARN_ON(usbh_ports > 1 && board.has_usbd))
+ usbh_ports = 1;
+ }
+
if (board.has_usbd)
bcm63xx_usbd_register(&board.usbd);
if (board.has_ehci0)
- bcm63xx_ehci_register();
+ bcm63xx_ehci_register(usbh_ports);
if (board.has_ohci0)
- bcm63xx_ohci_register();
+ bcm63xx_ohci_register(usbh_ports);
/* Generate MAC address for WLAN and register our SPROM,
* do this after registering enet devices
--- a/arch/mips/bcm63xx/dev-usb-ehci.c
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
@@ -79,12 +79,14 @@ static struct platform_device bcm63xx_eh
},
};
-int __init bcm63xx_ehci_register(void)
+int __init bcm63xx_ehci_register(unsigned int num_ports)
{
if (!BCMCPU_IS_6318() && !BCMCPU_IS_6328() && !BCMCPU_IS_6358() &&
!BCMCPU_IS_6362() && !BCMCPU_IS_6368() && !BCMCPU_IS_63268())
return 0;
+ bcm63xx_ehci_pdata.num_ports = num_ports;
+
ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
ehci_resources[0].end = ehci_resources[0].start;
ehci_resources[0].end += RSET_EHCI_SIZE - 1;
--- a/arch/mips/bcm63xx/dev-usb-ohci.c
+++ b/arch/mips/bcm63xx/dev-usb-ohci.c
@@ -62,7 +62,6 @@ static struct usb_ohci_pdata bcm63xx_ohc
.big_endian_desc = 1,
.big_endian_mmio = 1,
.no_big_frame_no = 1,
- .num_ports = 1,
.power_on = bcm63xx_ohci_power_on,
.power_off = bcm63xx_ohci_power_off,
.power_suspend = bcm63xx_ohci_power_off,
@@ -80,11 +79,13 @@ static struct platform_device bcm63xx_oh
},
};
-int __init bcm63xx_ohci_register(void)
+int __init bcm63xx_ohci_register(unsigned int num_ports)
{
if (BCMCPU_IS_6345() || BCMCPU_IS_6338())
return -ENODEV;
+ bcm63xx_ohci_pdata.num_ports = num_ports;
+
ohci_resources[0].start = bcm63xx_regset_address(RSET_OHCI0);
ohci_resources[0].end = ohci_resources[0].start;
ohci_resources[0].end += RSET_OHCI_SIZE - 1;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,140 @@
From 83131acbfb59760a19f3711c09526e191c8aad54 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 29 Jul 2014 21:52:56 +0200
Subject: [PATCH 03/10] MIPS: BCM63XX: make fallback sprom optional
Some devices do not provide enough mac addresses to populate wifi in
addition to ethernet.
Use having pci enabled as a rough heuristic which boards should have it
enabled.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 12 ++++++++++++
arch/mips/bcm63xx/boards/board_common.c | 5 +++--
arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 1 +
3 files changed, 16 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -63,6 +63,7 @@ static struct board_info __initdata boar
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_usbd = 0,
.usbd = {
@@ -213,6 +214,7 @@ static struct board_info __initdata boar
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -259,6 +261,7 @@ static struct board_info __initdata boar
.has_pccard = 1,
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -310,6 +313,7 @@ static struct board_info __initdata boar
.has_pccard = 1,
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -360,6 +364,7 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -411,6 +416,7 @@ static struct board_info __initdata boar
.has_pccard = 1,
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -430,6 +436,7 @@ static struct board_info __initdata boar
.expected_cpu_id = 0x6348,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -451,6 +458,7 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -472,6 +480,7 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -500,6 +509,7 @@ static struct board_info __initdata boar
.has_pccard = 1,
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -551,6 +561,7 @@ static struct board_info __initdata boar
.has_pccard = 1,
.has_pci = 1,
.has_uart0 = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
@@ -617,6 +628,7 @@ static struct board_info __initdata boar
.has_ehci0 = 1,
.has_ohci0 = 1,
.has_pci = 1,
+ .use_fallback_sprom = 1,
.has_enet0 = 1,
.enet0 = {
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -183,8 +183,9 @@ int __init board_register_devices(void)
* do this after registering enet devices
*/
- if (board_get_mac_address(board.fallback_sprom.mac_addr) ||
- bcm63xx_register_fallback_sprom(&board.fallback_sprom))
+ if (board.use_fallback_sprom &&
+ (board_get_mac_address(board.fallback_sprom.mac_addr) ||
+ bcm63xx_register_fallback_sprom(&board.fallback_sprom)))
pr_err(PFX "failed to register fallback SPROM\n");
bcm63xx_spi_register();
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -33,6 +33,7 @@ struct board_info {
unsigned int has_usbd:1;
unsigned int has_uart0:1;
unsigned int has_uart1:1;
+ unsigned int use_fallback_sprom:1;
/* ethernet config */
struct bcm63xx_enet_platform_data enet0;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,78 @@
--- a/arch/mips/bcm63xx/sprom.c
+++ b/arch/mips/bcm63xx/sprom.c
@@ -384,6 +384,7 @@ static __initconst u16 bcm4331_sprom[] =
struct fallback_sprom_match {
u8 pci_bus;
u8 pci_dev;
+ int override_devid;
struct ssb_sprom sprom;
};
@@ -399,6 +400,8 @@ int bcm63xx_get_fallback_ssb_sprom(struc
fallback_sprom.pci_bus, fallback_sprom.pci_dev,
bus->host_pci->bus->number,
PCI_SLOT(bus->host_pci->devfn));
+ if (fallback_sprom.override_devid)
+ bus->host_pci->device = fallback_sprom.sprom.dev_id;
memcpy(out, &fallback_sprom.sprom, sizeof(struct ssb_sprom));
return 0;
} else {
@@ -418,6 +421,8 @@ int bcm63xx_get_fallback_bcma_sprom(stru
fallback_sprom.pci_bus, fallback_sprom.pci_dev,
bus->host_pci->bus->number,
PCI_SLOT(bus->host_pci->devfn));
+ if (fallback_sprom.override_devid)
+ bus->host_pci->device = fallback_sprom.sprom.dev_id;
memcpy(out, &fallback_sprom.sprom, sizeof(struct ssb_sprom));
return 0;
} else {
@@ -965,6 +970,37 @@ static int sprom_extract(struct ssb_spro
return 0;
}
+int sprom_override_devid(struct fallback_sprom_data *data,
+ struct ssb_sprom *out, const u16 *in)
+{
+ switch (data->type) {
+#if defined(CONFIG_SSB_PCIHOST)
+ case SPROM_BCM4306:
+ case SPROM_BCM4318:
+ case SPROM_BCM4321:
+ case SPROM_BCM4322:
+ case SPROM_BCM43222:
+ SPEX(dev_id, SSB_SPROM1_PID, 0xFFFF, 0);
+ return !!out->dev_id;
+#endif /* CONFIG_SSB_PCIHOST */
+#if defined(CONFIG_BCMA_HOST_PCI)
+ case SPROM_BCM4313:
+ case SPROM_BCM43131:
+ case SPROM_BCM43217:
+ case SPROM_BCM43225:
+ case SPROM_BCM43227:
+ case SPROM_BCM43228:
+ case SPROM_BCM4331:
+ SPEX(dev_id, 0x0060, 0xFFFF, 0);
+ return !!out->dev_id;
+#endif /* CONFIG_BCMA_HOST_PCI */
+ case SPROM_DEFAULT:
+ return 0;
+ }
+
+ return 0;
+}
+
void sprom_apply_fixups(u16 *sprom, struct sprom_fixup *fixups, int n)
{
unsigned int i;
@@ -1056,6 +1092,11 @@ int __init bcm63xx_register_fallback_spr
data->num_board_fixups);
sprom_extract(&fallback_sprom.sprom, template_sprom, size);
+
+ fallback_sprom.override_devid =
+ sprom_override_devid(data, &fallback_sprom.sprom, template_sprom);
+ } else {
+ fallback_sprom.override_devid = 0;
}
memcpy(fallback_sprom.sprom.il0mac, data->mac_addr, ETH_ALEN);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,178 @@
From dbe94a8daaa63ef81b7414f2a17bca8e36dd6daa Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 20 Feb 2015 19:55:32 +0100
Subject: [PATCH 1/6] gpio: add a simple GPIO driver for bcm63xx
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
drivers/gpio/Kconfig | 8 +++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-bcm63xx.c | 135 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 131 insertions(+)
create mode 100644 drivers/gpio/gpio-bcm63xx.c
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -193,6 +193,13 @@ config GPIO_BCM_XGS_IPROC
help
Say yes here to enable GPIO support for Broadcom XGS iProc SoCs.
+config GPIO_BCM63XX
+ bool "Broadcom BCM63XX GPIO"
+ depends on MIPS || COMPILE_TEST
+ select GPIO_GENERIC
+ help
+ Turn on GPIO support for Broadcom BCM63XX xDSL chips.
+
config GPIO_BRCMSTB
tristate "BRCMSTB GPIO support"
default y if (ARCH_BRCMSTB || BMIPS_GENERIC)
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_GPIO_ASPEED_SGPIO) += gpio
obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BCM_XGS_IPROC) += gpio-xgs-iproc.o
+obj-$(CONFIG_GPIO_BCM63XX) += gpio-bcm63xx.o
obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
obj-$(CONFIG_GPIO_BD71828) += gpio-bd71828.o
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
--- /dev/null
+++ b/drivers/gpio/gpio-bcm63xx.c
@@ -0,0 +1,135 @@
+/*
+ * Driver for BCM63XX memory-mapped GPIO controllers, based on
+ * Generic driver for memory-mapped GPIO controllers.
+ *
+ * Copyright 2008 MontaVista Software, Inc.
+ * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
+ * Copyright 2015 Jonas Gorski <jogo@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/log2.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+
+static int bcm63xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ char irq_name[7]; /* "gpioXX" */
+
+ sprintf(irq_name, "gpio%d", gpio);
+ return of_irq_get_byname(chip->of_node, irq_name);
+}
+
+static int bcm63xx_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *dat_r, *dirout_r;
+ void __iomem *dat;
+ void __iomem *dirout;
+ unsigned long sz;
+ int err;
+ struct gpio_chip *gc;
+ struct bgpio_pdata *pdata = dev_get_platdata(dev);
+
+ dirout_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dat_r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!dat_r || !dirout_r)
+ return -EINVAL;
+
+ if (resource_size(dat_r) != resource_size(dirout_r))
+ return -EINVAL;
+
+ sz = resource_size(dat_r);
+
+ dat = devm_ioremap_resource(dev, dat_r);
+ if (IS_ERR(dat))
+ return PTR_ERR(dat);
+
+ dirout = devm_ioremap_resource(dev, dirout_r);
+ if (IS_ERR(dirout))
+ return PTR_ERR(dirout);
+
+ gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
+ if (!gc)
+ return -ENOMEM;
+
+ err = bgpio_init(gc, dev, sz, dat, NULL, NULL, dirout, NULL,
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+ if (err)
+ return err;
+
+ platform_set_drvdata(pdev, gc);
+
+ if (dev->of_node) {
+ int id = of_alias_get_id(dev->of_node, "gpio");
+ u32 ngpios;
+
+ if (id >= 0)
+ gc->label = devm_kasprintf(dev, GFP_KERNEL,
+ "bcm63xx-gpio.%d", id);
+
+ if (!of_property_read_u32(dev->of_node, "ngpios", &ngpios))
+ gc->ngpio = ngpios;
+
+ if (of_get_property(dev->of_node, "interrupt-names", NULL))
+ gc->to_irq = bcm63xx_gpio_to_irq;
+
+ } else if (pdata) {
+ gc->base = pdata->base;
+ if (pdata->ngpio > 0)
+ gc->ngpio = pdata->ngpio;
+ }
+
+ return gpiochip_add(gc);
+}
+
+static int bcm63xx_gpio_remove(struct platform_device *pdev)
+{
+ struct gpio_chip *gc = platform_get_drvdata(pdev);
+
+ gpiochip_remove(gc);
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id bcm63xx_gpio_of_match[] = {
+ { .compatible = "brcm,bcm6345-gpio" },
+ { },
+};
+#endif
+
+static struct platform_driver bcm63xx_gpio_driver = {
+ .probe = bcm63xx_gpio_probe,
+ .remove = bcm63xx_gpio_remove,
+ .driver = {
+ .name = "bcm63xx-gpio",
+ .of_match_table = of_match_ptr(bcm63xx_gpio_of_match),
+ },
+};
+
+module_platform_driver(bcm63xx_gpio_driver);
+
+MODULE_DESCRIPTION("Driver for BCM63XX memory-mapped GPIO controllers");
+MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
+MODULE_LICENSE("GPL");

View File

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

View File

@ -0,0 +1,129 @@
From d13bdf92ec885105cf107183f8464c40e5f3b93b Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 21 Feb 2015 17:21:59 +0100
Subject: [PATCH 4/6] MIPS: BCM63XX: register lookup for ephy-reset gpio
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
arch/mips/bcm63xx/boards/board_common.c | 7 +++--
arch/mips/bcm63xx/gpio.c | 32 ++++++++++++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 2 ++
.../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 5 +--
5 files changed, 42 insertions(+), 6 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -32,7 +32,7 @@ static struct board_info __initdata boar
.expected_cpu_id = 0x3368,
.ephy_reset_gpio = 36,
- .ephy_reset_gpio_flags = GPIOF_INIT_HIGH,
+ .ephy_reset_gpio_flags = GPIO_ACTIVE_LOW,
.has_pci = 1,
.has_uart0 = 1,
.has_uart1 = 1,
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -247,9 +247,10 @@ int __init board_register_devices(void)
platform_device_register(&bcm63xx_gpio_leds);
- if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
- gpio_request_one(board.ephy_reset_gpio,
- board.ephy_reset_gpio_flags, "ephy-reset");
+ if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags) {
+ bcm63xx_gpio_ephy_reset(board.ephy_reset_gpio,
+ board.ephy_reset_gpio_flags);
+ }
return 0;
}
--- a/arch/mips/bcm63xx/gpio.c
+++ b/arch/mips/bcm63xx/gpio.c
@@ -8,15 +8,23 @@
* Copyright (C) Jonas Gorski <jogo@openwrt.org>
*/
+#include <asm/addrspace.h>
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_gpio.h>
#include <bcm63xx_regs.h>
+static const char * const gpio_chip_labels[] = {
+ "bcm63xx-gpio.0",
+ "bcm63xx-gpio.1",
+};
+
static void __init bcm63xx_gpio_init_one(int id, int dir, int data, int ngpio)
{
struct resource res[2];
@@ -64,3 +72,25 @@ int __init bcm63xx_gpio_init(void)
return 0;
}
+
+static struct gpiod_lookup_table ephy_reset = {
+ .dev_id = "bcm63xx_enet-0",
+ .table = {
+ { /* filled at runtime */ },
+ { },
+ },
+};
+
+
+void bcm63xx_gpio_ephy_reset(int hw_gpio, enum gpio_lookup_flags flags)
+{
+ if (ephy_reset.table[0].key)
+ return;
+
+ ephy_reset.table[0].key = gpio_chip_labels[hw_gpio / 32];
+ ephy_reset.table[0].chip_hwnum = hw_gpio % 32;
+ ephy_reset.table[0].con_id = "reset";
+ ephy_reset.table[0].flags = flags;
+
+ gpiod_add_lookup_table(&ephy_reset);
+}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
@@ -3,9 +3,11 @@
#define BCM63XX_GPIO_H
#include <linux/init.h>
+#include <linux/gpio/machine.h>
#include <bcm63xx_cpu.h>
int __init bcm63xx_gpio_init(void);
+void bcm63xx_gpio_ephy_reset(int hw_gpio, enum gpio_lookup_flags flags);
static inline unsigned long bcm63xx_gpio_count(void)
{
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
#include <linux/leds.h>
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_usb_usbd.h>
@@ -50,8 +51,8 @@ struct board_info {
/* External PHY reset GPIO */
unsigned int ephy_reset_gpio;
- /* External PHY reset GPIO flags from gpio.h */
- unsigned long ephy_reset_gpio_flags;
+ /* External PHY reset GPIO flags from gpio/machine.h */
+ enum gpio_lookup_flags ephy_reset_gpio_flags;
/* fallback sprom config */
struct fallback_sprom_data fallback_sprom;

View File

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

View File

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

View File

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

View File

@ -0,0 +1,96 @@
From 8439e5d2e69f54a532bb5f8ec001b4b5a3035574 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:38:05 +0200
Subject: [PATCH 14/16] Documentation: add BCM6318 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6318 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6318-pinctrl.txt | 79 ++++++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.txt
@@ -0,0 +1,79 @@
+* Broadcom BCM6318 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6318-pinctrl".
+- regs: Register specifiers of dirout, dat, mode, mux, and pad registers.
+- reg-names: Must be "dirout", "dat", "mode", "mux", "pad".
+- gpio-controller: Identifies this node as a gpio controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6318-pinctrl";
+ reg = <0x10000080 0x08>,
+ <0x10000088 0x08>,
+ <0x10000098 0x04>,
+ <0x1000009c 0x0c>,
+ <0x100000d4 0x18>;
+ reg-names = "dirout", "dat", "mode", "mux", "pad";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led, ephy0_spd_led
+gpio1 1 led, ephy1_spd_led
+gpio2 2 led, ephy2_spd_led
+gpio3 3 led, ephy3_spd_led
+gpio4 4 led, ephy0_act_led
+gpio5 5 led, ephy1_act_led
+gpio6 6 led, ephy2_act_led, serial_led_data
+gpio7 7 led, ephy3_act_led, serial_led_clk
+gpio8 8 led, inet_act_led
+gpio9 9 led, inet_fail_led
+gpio10 10 led, dsl_led
+gpio11 11 led, post_fail_led
+gpio12 12 led, wlan_wps_led
+gpio13 13 led, usb_pwron, usb_device_led
+gpio14 14 led
+gpio15 15 led
+gpio16 16 led
+gpio17 17 led
+gpio18 18 led
+gpio19 19 led
+gpio20 20 led
+gpio21 21 led
+gpio22 22 led
+gpio23 23 led
+gpio24 24 -
+gpio25 25 -
+gpio26 26 -
+gpio27 27 -
+gpio28 28 -
+gpio29 29 -
+gpio30 30 -
+gpio31 31 -
+gpio32 32 -
+gpio33 33 -
+gpio34 34 -
+gpio35 35 -
+gpio36 36 -
+gpio37 37 -
+gpio38 38 -
+gpio39 39 -
+gpio40 40 usb_active
+gpio41 41 -
+gpio42 42 -
+gpio43 43 -
+gpio44 44 -
+gpio45 45 -
+gpio46 46 -
+gpio47 47 -
+gpio48 48 -
+gpio49 49 -

View File

@ -0,0 +1,609 @@
From bd9c250ef85e6f99aa5d59b21abb87d0a48f2f61 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:20:39 +0200
Subject: [PATCH 15/16] pinctrl: add a pincontrol driver for BCM6318
Add a pincontrol driver for BCM6318. BCM6318 allows muxing most GPIOs
to different functions. BCM6318 is similar to BCM6328 with the addition
of a pad register, and the GPIO meaning of the mux register changes
based on the GPIO number.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6318.c | 564 ++++++++++++++++++++++++++++++
3 files changed, 572 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6318.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -2,6 +2,13 @@ config PINCTRL_BCM63XX
bool
select GPIO_GENERIC
+config PINCTRL_BCM6318
+ bool "BCM6318 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
+
config PINCTRL_BCM6328
bool "BCM6328 pincontrol driver" if COMPILE_TEST
select PINMUX
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
+obj-$(CONFIG_PINCTRL_BCM6318) += pinctrl-bcm6318.o
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6318.c
@@ -0,0 +1,564 @@
+/*
+ * 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) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6318_NGPIO 50
+
+struct bcm6318_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6318_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ unsigned mode_val:1;
+ unsigned mux_val:2;
+};
+
+struct bcm6318_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+ void __iomem *mux[3];
+ void __iomem *pad[6];
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+static const struct pinctrl_pin_desc bcm6318_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+ PINCTRL_PIN(48, "gpio48"),
+ PINCTRL_PIN(49, "gpio49"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned gpio32_pins[] = { 32 };
+static unsigned gpio33_pins[] = { 33 };
+static unsigned gpio34_pins[] = { 34 };
+static unsigned gpio35_pins[] = { 35 };
+static unsigned gpio36_pins[] = { 36 };
+static unsigned gpio37_pins[] = { 37 };
+static unsigned gpio38_pins[] = { 38 };
+static unsigned gpio39_pins[] = { 39 };
+static unsigned gpio40_pins[] = { 40 };
+static unsigned gpio41_pins[] = { 41 };
+static unsigned gpio42_pins[] = { 42 };
+static unsigned gpio43_pins[] = { 43 };
+static unsigned gpio44_pins[] = { 44 };
+static unsigned gpio45_pins[] = { 45 };
+static unsigned gpio46_pins[] = { 46 };
+static unsigned gpio47_pins[] = { 47 };
+static unsigned gpio48_pins[] = { 48 };
+static unsigned gpio49_pins[] = { 49 };
+
+#define BCM6318_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6318_pingroup bcm6318_groups[] = {
+ BCM6318_GROUP(gpio0),
+ BCM6318_GROUP(gpio1),
+ BCM6318_GROUP(gpio2),
+ BCM6318_GROUP(gpio3),
+ BCM6318_GROUP(gpio4),
+ BCM6318_GROUP(gpio5),
+ BCM6318_GROUP(gpio6),
+ BCM6318_GROUP(gpio7),
+ BCM6318_GROUP(gpio8),
+ BCM6318_GROUP(gpio9),
+ BCM6318_GROUP(gpio10),
+ BCM6318_GROUP(gpio11),
+ BCM6318_GROUP(gpio12),
+ BCM6318_GROUP(gpio13),
+ BCM6318_GROUP(gpio14),
+ BCM6318_GROUP(gpio15),
+ BCM6318_GROUP(gpio16),
+ BCM6318_GROUP(gpio17),
+ BCM6318_GROUP(gpio18),
+ BCM6318_GROUP(gpio19),
+ BCM6318_GROUP(gpio20),
+ BCM6318_GROUP(gpio21),
+ BCM6318_GROUP(gpio22),
+ BCM6318_GROUP(gpio23),
+ BCM6318_GROUP(gpio24),
+ BCM6318_GROUP(gpio25),
+ BCM6318_GROUP(gpio26),
+ BCM6318_GROUP(gpio27),
+ BCM6318_GROUP(gpio28),
+ BCM6318_GROUP(gpio29),
+ BCM6318_GROUP(gpio30),
+ BCM6318_GROUP(gpio31),
+ BCM6318_GROUP(gpio32),
+ BCM6318_GROUP(gpio33),
+ BCM6318_GROUP(gpio34),
+ BCM6318_GROUP(gpio35),
+ BCM6318_GROUP(gpio36),
+ BCM6318_GROUP(gpio37),
+ BCM6318_GROUP(gpio38),
+ BCM6318_GROUP(gpio39),
+ BCM6318_GROUP(gpio40),
+ BCM6318_GROUP(gpio41),
+ BCM6318_GROUP(gpio42),
+ BCM6318_GROUP(gpio43),
+ BCM6318_GROUP(gpio44),
+ BCM6318_GROUP(gpio45),
+ BCM6318_GROUP(gpio46),
+ BCM6318_GROUP(gpio47),
+ BCM6318_GROUP(gpio48),
+ BCM6318_GROUP(gpio49),
+};
+
+/* GPIO_MODE */
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+/* PINMUX_SEL */
+static const char * const ephy0_spd_led_groups[] = {
+ "gpio0",
+};
+
+static const char * const ephy1_spd_led_groups[] = {
+ "gpio1",
+};
+
+static const char * const ephy2_spd_led_groups[] = {
+ "gpio2",
+};
+
+static const char * const ephy3_spd_led_groups[] = {
+ "gpio3",
+};
+
+static const char * const ephy0_act_led_groups[] = {
+ "gpio4",
+};
+
+static const char * const ephy1_act_led_groups[] = {
+ "gpio5",
+};
+
+static const char * const ephy2_act_led_groups[] = {
+ "gpio6",
+};
+
+static const char * const ephy3_act_led_groups[] = {
+ "gpio7",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio6",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio7",
+};
+
+static const char * const inet_act_led_groups[] = {
+ "gpio8",
+};
+
+static const char * const inet_fail_led_groups[] = {
+ "gpio9",
+};
+
+static const char * const dsl_led_groups[] = {
+ "gpio10",
+};
+
+static const char * const post_fail_led_groups[] = {
+ "gpio11",
+};
+
+static const char * const wlan_wps_led_groups[] = {
+ "gpio12",
+};
+
+static const char * const usb_pwron_groups[] = {
+ "gpio13",
+};
+
+static const char * const usb_device_led_groups[] = {
+ "gpio13",
+};
+
+static const char * const usb_active_groups[] = {
+ "gpio40",
+};
+
+#define BCM6318_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mode_val = 1, \
+ }
+
+#define BCM6318_MUX_FUN(n, mux) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mux_val = mux, \
+ }
+
+static const struct bcm6318_function bcm6318_funcs[] = {
+ BCM6318_MODE_FUN(led),
+ BCM6318_MUX_FUN(ephy0_spd_led, 1),
+ BCM6318_MUX_FUN(ephy1_spd_led, 1),
+ BCM6318_MUX_FUN(ephy2_spd_led, 1),
+ BCM6318_MUX_FUN(ephy3_spd_led, 1),
+ BCM6318_MUX_FUN(ephy0_act_led, 1),
+ BCM6318_MUX_FUN(ephy1_act_led, 1),
+ BCM6318_MUX_FUN(ephy2_act_led, 1),
+ BCM6318_MUX_FUN(ephy3_act_led, 1),
+ BCM6318_MUX_FUN(serial_led_data, 3),
+ BCM6318_MUX_FUN(serial_led_clk, 3),
+ BCM6318_MUX_FUN(inet_act_led, 1),
+ BCM6318_MUX_FUN(inet_fail_led, 1),
+ BCM6318_MUX_FUN(dsl_led, 1),
+ BCM6318_MUX_FUN(post_fail_led, 1),
+ BCM6318_MUX_FUN(wlan_wps_led, 1),
+ BCM6318_MUX_FUN(usb_pwron, 1),
+ BCM6318_MUX_FUN(usb_device_led, 2),
+ BCM6318_MUX_FUN(usb_active, 2),
+};
+
+static int bcm6318_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6318_groups);
+}
+
+static const char *bcm6318_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6318_groups[group].name;
+}
+
+static int bcm6318_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6318_groups[group].pins;
+ *num_pins = bcm6318_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6318_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6318_funcs);
+}
+
+static const char *bcm6318_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6318_funcs[selector].name;
+}
+
+static int bcm6318_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6318_funcs[selector].groups;
+ *num_groups = bcm6318_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6318_rmw_mux(struct bcm6318_pinctrl *pctl, unsigned pin,
+ u32 mode, u32 mux)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ if (pin < 32) {
+ reg = __raw_readl(pctl->mode);
+ reg &= ~BIT(pin);
+ if (mode)
+ reg |= BIT(pin);
+ __raw_writel(reg, pctl->mode);
+ }
+
+ if (pin < 48) {
+ reg = __raw_readl(pctl->mux[pin / 16]);
+ reg &= ~(3UL << ((pin % 16) * 2));
+ reg |= mux << ((pin % 16) * 2);
+ __raw_writel(reg, pctl->mux[pin / 16]);
+ }
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static void bcm6318_set_pad(struct bcm6318_pinctrl *pctl, unsigned pin, u8 val)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ reg = __raw_readl(pctl->pad[pin / 8]);
+ reg &= ~(0xfUL << ((pin % 8) * 4));
+ reg |= val << ((pin % 8) * 4);
+ __raw_writel(reg, pctl->pad[pin / 8]);
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static int bcm6318_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6318_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6318_pingroup *grp = &bcm6318_groups[group];
+ const struct bcm6318_function *f = &bcm6318_funcs[selector];
+
+ bcm6318_rmw_mux(pctl, grp->pins[0], f->mode_val, f->mux_val);
+
+ return 0;
+}
+
+static int bcm6318_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6318_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ if (offset < 13) {
+ /* GPIOs 0-12 use mux 0 as GPIO function */
+ bcm6318_rmw_mux(pctl, offset, 0, 0);
+ } else if (offset < 42) {
+ /* GPIOs 13-41 use mux 3 as GPIO function */
+ bcm6318_rmw_mux(pctl, offset, 0, 3);
+
+ /* FIXME: revert to old value for non gpio? */
+ bcm6318_set_pad(pctl, offset, 0);
+ } else {
+ /* no idea, really */
+ }
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6318_pctl_ops = {
+ .get_groups_count = bcm6318_pinctrl_get_group_count,
+ .get_group_name = bcm6318_pinctrl_get_group_name,
+ .get_group_pins = bcm6318_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6318_pmx_ops = {
+ .get_functions_count = bcm6318_pinctrl_get_func_count,
+ .get_function_name = bcm6318_pinctrl_get_func_name,
+ .get_function_groups = bcm6318_pinctrl_get_groups,
+ .set_mux = bcm6318_pinctrl_set_mux,
+ .gpio_request_enable = bcm6318_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6318_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6318_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode, *mux, *pad;
+ unsigned i;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mux");
+ mux = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mux))
+ return PTR_ERR(mux);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pad");
+ pad = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pad))
+ return PTR_ERR(pad);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+
+ for (i = 0; i < 3; i++)
+ pctl->mux[i] = mux + (i * 4);
+
+ for (i = 0; i < 6; i++)
+ pctl->pad[i] = pad + (i * 4);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6318_pctl_ops;
+ pctl->desc.pmxops = &bcm6318_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6318_pins);
+ pctl->desc.pins = bcm6318_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6318_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6318_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6318-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6318_pinctrl_driver = {
+ .probe = bcm6318_pinctrl_probe,
+ .driver = {
+ .name = "bcm6318-pinctrl",
+ .of_match_table = bcm6318_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6318_pinctrl_driver);

View File

@ -0,0 +1,65 @@
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -25,6 +25,8 @@ config BCM63XX_CPU_6318
select HAVE_PCI
select BCM63XX_OHCI
select BCM63XX_EHCI
+ select PINCTRL
+ select PINCTRL_BCM6318
config BCM63XX_CPU_6328
bool "support 6328 CPU"
@@ -32,6 +34,8 @@ config BCM63XX_CPU_6328
select HAVE_PCI
select BCM63XX_OHCI
select BCM63XX_EHCI
+ select PINCTRL
+ select PINCTRL_BCM6328
config BCM63XX_CPU_6338
bool "support 6338 CPU"
@@ -47,6 +51,8 @@ config BCM63XX_CPU_6348
select SYS_HAS_CPU_BMIPS32_3300
select HAVE_PCI
select BCM63XX_OHCI
+ select PINCTRL
+ select PINCTRL_BCM6348
config BCM63XX_CPU_6358
bool "support 6358 CPU"
@@ -54,6 +60,8 @@ config BCM63XX_CPU_6358
select HAVE_PCI
select BCM63XX_OHCI
select BCM63XX_EHCI
+ select PINCTRL
+ select PINCTRL_BCM6358
config BCM63XX_CPU_6362
bool "support 6362 CPU"
@@ -61,6 +69,8 @@ config BCM63XX_CPU_6362
select HAVE_PCI
select BCM63XX_OHCI
select BCM63XX_EHCI
+ select PINCTRL
+ select PINCTRL_BCM6362
config BCM63XX_CPU_6368
bool "support 6368 CPU"
@@ -68,6 +78,8 @@ config BCM63XX_CPU_6368
select HAVE_PCI
select BCM63XX_OHCI
select BCM63XX_EHCI
+ select PINCTRL
+ select PINCTRL_BCM6368
config BCM63XX_CPU_63268
bool "support 63268 CPU"
@@ -75,6 +87,8 @@ config BCM63XX_CPU_63268
select HAVE_PCI
select BCM63XX_OHCI
select BCM63XX_EHCI
+ select PINCTRL
+ select PINCTRL_BCM63268
endmenu
source "arch/mips/bcm63xx/boards/Kconfig"

View File

@ -0,0 +1,105 @@
From cad8f63047c0691e8185d3c9c6a2705b83310c9c Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Mon, 31 Jul 2017 20:10:36 +0200
Subject: [PATCH] MIPS: BCM63XX: add clkdev lookups for device tree
---
arch/mips/bcm63xx/clk.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -489,6 +489,8 @@ static struct clk_lookup bcm3368_clks[]
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
+ CLKDEV_INIT("fff8c100.serial", "refclk", &clk_periph),
+ CLKDEV_INIT("fff8c120.serial", "refclk", &clk_periph),
/* gated clocks */
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
@@ -505,7 +507,9 @@ static struct clk_lookup bcm6318_clks[]
/* fixed rate clocks */
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
+ CLKDEV_INIT("10000100.serial", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
+ CLKDEV_INIT("10003000.spi", "pll", &clk_hsspi_pll),
/* gated clocks */
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
@@ -519,7 +523,10 @@ static struct clk_lookup bcm6328_clks[]
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
+ CLKDEV_INIT("10000100.serial", "refclk", &clk_periph),
+ CLKDEV_INIT("10000120.serial", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
+ CLKDEV_INIT("10001000.spi", "pll", &clk_hsspi_pll),
/* gated clocks */
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
@@ -532,6 +539,7 @@ static struct clk_lookup bcm6338_clks[]
/* fixed rate clocks */
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
+ CLKDEV_INIT("fffe0300.serial", "refclk", &clk_periph),
/* gated clocks */
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
@@ -546,6 +554,7 @@ static struct clk_lookup bcm6345_clks[]
/* fixed rate clocks */
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
+ CLKDEV_INIT("fffe0300.serial", "refclk", &clk_periph),
/* gated clocks */
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
@@ -560,6 +569,7 @@ static struct clk_lookup bcm6348_clks[]
/* fixed rate clocks */
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
+ CLKDEV_INIT("fffe0300.serial", "refclk", &clk_periph),
/* gated clocks */
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
@@ -576,6 +586,8 @@ static struct clk_lookup bcm6358_clks[]
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
+ CLKDEV_INIT("fffe0100.serial", "refclk", &clk_periph),
+ CLKDEV_INIT("fffe0120.serial", "refclk", &clk_periph),
/* gated clocks */
CLKDEV_INIT(NULL, "enet0", &clk_enet0),
CLKDEV_INIT(NULL, "enet1", &clk_enet1),
@@ -595,7 +607,10 @@ static struct clk_lookup bcm6362_clks[]
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
+ CLKDEV_INIT("10000100.serial", "refclk", &clk_periph),
+ CLKDEV_INIT("10000120.serial", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
+ CLKDEV_INIT("10001000.spi", "pll", &clk_hsspi_pll),
/* gated clocks */
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
@@ -611,6 +626,8 @@ static struct clk_lookup bcm6368_clks[]
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
+ CLKDEV_INIT("10000100.serial", "refclk", &clk_periph),
+ CLKDEV_INIT("10000120.serial", "refclk", &clk_periph),
/* gated clocks */
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
CLKDEV_INIT(NULL, "usbh", &clk_usbh),
@@ -625,7 +642,10 @@ static struct clk_lookup bcm63268_clks[]
CLKDEV_INIT(NULL, "periph", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
+ CLKDEV_INIT("10000180.serial", "refclk", &clk_periph),
+ CLKDEV_INIT("100001a0.serial", "refclk", &clk_periph),
CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
+ CLKDEV_INIT("10001000.spi", "pll", &clk_hsspi_pll),
/* gated clocks */
CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
CLKDEV_INIT(NULL, "usbh", &clk_usbh),

View File

@ -0,0 +1,172 @@
From 39d2882058345b5994680b8731848a0343878019 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sat, 4 Feb 2017 12:58:50 +0100
Subject: [PATCH 7/8] MIPS: BCM63XX: do not register SPI controllers
We now register them through DT, so no need to keep them here.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 7 -------
1 file changed, 7 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -27,9 +27,7 @@
#include <bcm63xx_dev_pci.h>
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_flash.h>
-#include <bcm63xx_dev_hsspi.h>
#include <bcm63xx_dev_pcmcia.h>
-#include <bcm63xx_dev_spi.h>
#include <bcm63xx_dev_usb_ehci.h>
#include <bcm63xx_dev_usb_ohci.h>
#include <bcm63xx_dev_usb_usbd.h>
@@ -236,10 +234,6 @@ int __init board_register_devices(void)
bcm63xx_register_fallback_sprom(&board.fallback_sprom)))
pr_err(PFX "failed to register fallback SPROM\n");
- bcm63xx_spi_register();
-
- bcm63xx_hsspi_register();
-
bcm63xx_flash_register();
bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
setup.o timer.o dev-enet.o dev-flash.o dev-pcmcia.o \
- dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o dev-wdt.o \
+ dev-rng.o dev-uart.o dev-wdt.o \
dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o usb-common.o \
sprom.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
--- a/arch/mips/bcm63xx/dev-hsspi.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <bcm63xx_cpu.h>
-#include <bcm63xx_dev_hsspi.h>
-#include <bcm63xx_regs.h>
-
-static struct resource spi_resources[] = {
- {
- .start = -1, /* filled at runtime */
- .end = -1, /* filled at runtime */
- .flags = IORESOURCE_MEM,
- },
- {
- .start = -1, /* filled at runtime */
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device bcm63xx_hsspi_device = {
- .name = "bcm63xx-hsspi",
- .id = 0,
- .num_resources = ARRAY_SIZE(spi_resources),
- .resource = spi_resources,
-};
-
-int __init bcm63xx_hsspi_register(void)
-{
- if (!BCMCPU_IS_6318() && !BCMCPU_IS_6328() && !BCMCPU_IS_6362() &&
- !BCMCPU_IS_63268())
- return -ENODEV;
-
- spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
- spi_resources[0].end = spi_resources[0].start;
- spi_resources[0].end += RSET_HSSPI_SIZE - 1;
- spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI);
-
- return platform_device_register(&bcm63xx_hsspi_device);
-}
--- a/arch/mips/bcm63xx/dev-spi.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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) 2009-2011 Florian Fainelli <florian@openwrt.org>
- * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-
-#include <bcm63xx_cpu.h>
-#include <bcm63xx_dev_spi.h>
-#include <bcm63xx_regs.h>
-
-static struct resource spi_resources[] = {
- {
- .start = -1, /* filled at runtime */
- .end = -1, /* filled at runtime */
- .flags = IORESOURCE_MEM,
- },
- {
- .start = -1, /* filled at runtime */
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device bcm63xx_spi_device = {
- .id = -1,
- .num_resources = ARRAY_SIZE(spi_resources),
- .resource = spi_resources,
-};
-
-int __init bcm63xx_spi_register(void)
-{
- if (BCMCPU_IS_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6345())
- return -ENODEV;
-
- spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
- spi_resources[0].end = spi_resources[0].start;
- spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
-
- if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
- bcm63xx_spi_device.name = "bcm6348-spi",
- spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1;
- }
-
- if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() ||
- BCMCPU_IS_6368() || BCMCPU_IS_63268()) {
- bcm63xx_spi_device.name = "bcm6358-spi",
- spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
- }
-
- return platform_device_register(&bcm63xx_spi_device);
-}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef BCM63XX_DEV_HSSPI_H
-#define BCM63XX_DEV_HSSPI_H
-
-#include <linux/types.h>
-
-int bcm63xx_hsspi_register(void);
-
-#endif /* BCM63XX_DEV_HSSPI_H */

View File

@ -0,0 +1,259 @@
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
setup.o timer.o dev-enet.o dev-flash.o dev-pcmcia.o \
- dev-rng.o dev-uart.o dev-wdt.o \
+ dev-rng.o dev-wdt.o \
dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o usb-common.o \
sprom.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
--- a/arch/mips/bcm63xx/dev-uart.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <bcm63xx_cpu.h>
-
-static struct resource uart0_resources[] = {
- {
- /* start & end filled at runtime */
- .flags = IORESOURCE_MEM,
- },
- {
- /* start filled at runtime */
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource uart1_resources[] = {
- {
- /* start & end filled at runtime */
- .flags = IORESOURCE_MEM,
- },
- {
- /* start filled at runtime */
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device bcm63xx_uart_devices[] = {
- {
- .name = "bcm63xx_uart",
- .id = 0,
- .num_resources = ARRAY_SIZE(uart0_resources),
- .resource = uart0_resources,
- },
-
- {
- .name = "bcm63xx_uart",
- .id = 1,
- .num_resources = ARRAY_SIZE(uart1_resources),
- .resource = uart1_resources,
- }
-};
-
-int __init bcm63xx_uart_register(unsigned int id)
-{
- if (id >= ARRAY_SIZE(bcm63xx_uart_devices))
- return -ENODEV;
-
- if (id == 1 && (!BCMCPU_IS_3368() && !BCMCPU_IS_6358() &&
- !BCMCPU_IS_6368()))
- return -ENODEV;
-
- if (id == 0) {
- uart0_resources[0].start = bcm63xx_regset_address(RSET_UART0);
- uart0_resources[0].end = uart0_resources[0].start +
- RSET_UART_SIZE - 1;
- uart0_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0);
- }
-
- if (id == 1) {
- uart1_resources[0].start = bcm63xx_regset_address(RSET_UART1);
- uart1_resources[0].end = uart1_resources[0].start +
- RSET_UART_SIZE - 1;
- uart1_resources[1].start = bcm63xx_get_irq_number(IRQ_UART1);
- }
-
- return platform_device_register(&bcm63xx_uart_devices[id]);
-}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_uart.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef BCM63XX_DEV_UART_H_
-#define BCM63XX_DEV_UART_H_
-
-int bcm63xx_uart_register(unsigned int id);
-
-#endif /* BCM63XX_DEV_UART_H_ */
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -32,8 +32,6 @@ struct board_info {
unsigned int has_ohci0:1;
unsigned int has_ehci0:1;
unsigned int has_usbd:1;
- unsigned int has_uart0:1;
- unsigned int has_uart1:1;
unsigned int use_fallback_sprom:1;
/* ethernet config */
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -20,7 +20,6 @@
#include <asm/prom.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
-#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
#include <bcm63xx_gpio.h>
@@ -188,12 +187,6 @@ int __init board_register_devices(void)
bcm63xx_gpio_init();
- if (board.has_uart0)
- bcm63xx_uart_register(0);
-
- if (board.has_uart1)
- bcm63xx_uart_register(1);
-
if (board.has_pccard)
bcm63xx_pcmcia_register();
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -34,8 +34,6 @@ static struct board_info __initdata boar
.ephy_reset_gpio = 36,
.ephy_reset_gpio_flags = GPIO_ACTIVE_LOW,
.has_pci = 1,
- .has_uart0 = 1,
- .has_uart1 = 1,
.has_enet0 = 1,
.enet0 = {
@@ -62,7 +60,6 @@ static struct board_info __initdata boar
.expected_cpu_id = 0x6328,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_usbd = 0,
@@ -111,7 +108,6 @@ static struct board_info __initdata boar
.expected_cpu_id = 0x6338,
.has_ohci0 = 1,
- .has_uart0 = 1,
.has_enet0 = 1,
.enet0 = {
@@ -153,8 +149,6 @@ static struct board_info __initdata boar
.name = "96338W",
.expected_cpu_id = 0x6338,
- .has_uart0 = 1,
-
.has_enet0 = 1,
.enet0 = {
.force_speed_100 = 1,
@@ -199,8 +193,6 @@ static struct board_info __initdata boar
static struct board_info __initdata board_96345gw2 = {
.name = "96345GW2",
.expected_cpu_id = 0x6345,
-
- .has_uart0 = 1,
};
#endif /* CONFIG_BCM63XX_CPU_6345 */
@@ -213,7 +205,6 @@ static struct board_info __initdata boar
.expected_cpu_id = 0x6348,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -260,7 +251,6 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pccard = 1,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -312,7 +302,6 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pccard = 1,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -363,7 +352,6 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -415,7 +403,6 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pccard = 1,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -457,7 +444,6 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -479,7 +465,6 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -508,7 +493,6 @@ static struct board_info __initdata boar
.has_ohci0 = 1,
.has_pccard = 1,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -560,7 +544,6 @@ static struct board_info __initdata boar
.num_usbh_ports = 2,
.has_pccard = 1,
.has_pci = 1,
- .has_uart0 = 1,
.use_fallback_sprom = 1,
.has_enet0 = 1,
@@ -606,7 +589,6 @@ static struct board_info __initdata boar
.has_ehci0 = 1,
.has_ohci0 = 1,
.has_pci = 1,
- .has_uart0 = 1,
.has_enet0 = 1,
.enet0 = {

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