bcma: add support for chipcommon B core
authorHauke Mehrtens <hauke@hauke-m.de>
Mon, 8 Sep 2014 20:53:36 +0000 (22:53 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 9 Sep 2014 19:33:05 +0000 (15:33 -0400)
This core is used on BCM4708 to configure the PCIe and USB3 PHYs and it
contains the addresses to the Device Management unit. This will be used
by the PCIe driver first.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/bcma/Makefile
drivers/bcma/bcma_private.h
drivers/bcma/driver_chipcommon_b.c [new file with mode: 0644]
drivers/bcma/main.c
drivers/bcma/scan.c
include/linux/bcma/bcma.h
include/linux/bcma/bcma_driver_chipcommon.h

index 91290f7f61b8c2b903d874345b6c32896da6114a..838b4b9d352ffc1d6c7790426bde8502712cc8dc 100644 (file)
@@ -1,5 +1,6 @@
 bcma-y                                 += main.o scan.o core.o sprom.o
 bcma-y                                 += driver_chipcommon.o driver_chipcommon_pmu.o
+bcma-y                                 += driver_chipcommon_b.o
 bcma-$(CONFIG_BCMA_SFLASH)             += driver_chipcommon_sflash.o
 bcma-$(CONFIG_BCMA_NFLASH)             += driver_chipcommon_nflash.o
 bcma-y                                 += driver_pci.o
index 09b632ad0fe20ec97f3452df80e0cc525e7bfdd3..b40be43c6f31e77f65d1ee7cd0a683e2cb454db6 100644 (file)
@@ -50,6 +50,10 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
 extern struct platform_device bcma_pflash_dev;
 #endif /* CONFIG_BCMA_DRIVER_MIPS */
 
+/* driver_chipcommon_b.c */
+int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb);
+void bcma_core_chipcommon_b_free(struct bcma_drv_cc_b *ccb);
+
 /* driver_chipcommon_pmu.c */
 u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc);
 u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc);
diff --git a/drivers/bcma/driver_chipcommon_b.c b/drivers/bcma/driver_chipcommon_b.c
new file mode 100644 (file)
index 0000000..c20b5f4
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Broadcom specific AMBA
+ * ChipCommon B Unit driver
+ *
+ * Copyright 2014, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include <linux/export.h>
+#include <linux/bcma/bcma.h>
+
+static bool bcma_wait_reg(struct bcma_bus *bus, void __iomem *addr, u32 mask,
+                         u32 value, int timeout)
+{
+       unsigned long deadline = jiffies + timeout;
+       u32 val;
+
+       do {
+               val = readl(addr);
+               if ((val & mask) == value)
+                       return true;
+               cpu_relax();
+               udelay(10);
+       } while (!time_after_eq(jiffies, deadline));
+
+       bcma_err(bus, "Timeout waiting for register %p\n", addr);
+
+       return false;
+}
+
+void bcma_chipco_b_mii_write(struct bcma_drv_cc_b *ccb, u32 offset, u32 value)
+{
+       struct bcma_bus *bus = ccb->core->bus;
+
+       writel(offset, ccb->mii + 0x00);
+       bcma_wait_reg(bus, ccb->mii + 0x00, 0x0100, 0x0000, 100);
+       writel(value, ccb->mii + 0x04);
+       bcma_wait_reg(bus, ccb->mii + 0x00, 0x0100, 0x0000, 100);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_b_mii_write);
+
+int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb)
+{
+       if (ccb->setup_done)
+               return 0;
+
+       ccb->setup_done = 1;
+       ccb->mii = ioremap_nocache(ccb->core->addr_s[1], BCMA_CORE_SIZE);
+       if (!ccb->mii)
+               return -ENOMEM;
+
+       return 0;
+}
+
+void bcma_core_chipcommon_b_free(struct bcma_drv_cc_b *ccb)
+{
+       if (ccb->mii)
+               iounmap(ccb->mii);
+}
index 297a2d46985ae5bcfc702c006536a996cfbf647f..c421403cab4348a098e3881f239662b4f6c709d0 100644 (file)
@@ -173,6 +173,7 @@ static int bcma_register_devices(struct bcma_bus *bus)
                switch (core->id.id) {
                case BCMA_CORE_4706_CHIPCOMMON:
                case BCMA_CORE_CHIPCOMMON:
+               case BCMA_CORE_NS_CHIPCOMMON_B:
                case BCMA_CORE_PCI:
                case BCMA_CORE_PCIE:
                case BCMA_CORE_PCIE2:
@@ -287,6 +288,13 @@ int bcma_bus_register(struct bcma_bus *bus)
                bcma_core_chipcommon_init(&bus->drv_cc);
        }
 
+       /* Init CC core */
+       core = bcma_find_core(bus, BCMA_CORE_NS_CHIPCOMMON_B);
+       if (core) {
+               bus->drv_cc_b.core = core;
+               bcma_core_chipcommon_b_init(&bus->drv_cc_b);
+       }
+
        /* Init MIPS core */
        core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
        if (core) {
@@ -341,6 +349,8 @@ void bcma_bus_unregister(struct bcma_bus *bus)
        else if (err)
                bcma_err(bus, "Can not unregister GPIO driver: %i\n", err);
 
+       bcma_core_chipcommon_b_free(&bus->drv_cc_b);
+
        cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
        cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
        cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
index 06be7282cbc4bf2e8bb0d1b80665757e99ed2061..b3a403c136fb4477722b2889284691f04064a825 100644 (file)
@@ -314,6 +314,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
                /* Some specific cores don't need wrappers */
                switch (core->id.id) {
                case BCMA_CORE_4706_MAC_GBIT_COMMON:
+               case BCMA_CORE_NS_CHIPCOMMON_B:
                /* Not used yet: case BCMA_CORE_OOB_ROUTER: */
                        break;
                default:
index 7fc16c991291558460323914b2ad4a7e1aa8f3e3..6345979176709cdda4301545f5d166c32b38230f 100644 (file)
@@ -335,6 +335,7 @@ struct bcma_bus {
        u8 num;
 
        struct bcma_drv_cc drv_cc;
+       struct bcma_drv_cc_b drv_cc_b;
        struct bcma_drv_pci drv_pci[2];
        struct bcma_drv_pcie2 drv_pcie2;
        struct bcma_drv_mips drv_mips;
index 63d105cd14a33fc60048c28c9c3b07ef4f4136ef..db6fa217f98bf3f1276ac659c61e50099da739e4 100644 (file)
@@ -644,6 +644,12 @@ struct bcma_drv_cc {
 #endif
 };
 
+struct bcma_drv_cc_b {
+       struct bcma_device *core;
+       u8 setup_done:1;
+       void __iomem *mii;
+};
+
 /* Register access */
 #define bcma_cc_read32(cc, offset) \
        bcma_read32((cc)->core, offset)
@@ -699,4 +705,6 @@ extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid);
 
 extern u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc);
 
+void bcma_chipco_b_mii_write(struct bcma_drv_cc_b *ccb, u32 offset, u32 value);
+
 #endif /* LINUX_BCMA_DRIVER_CC_H_ */