mirror of https://github.com/hak5/openwrt.git
brcm47xx: add support for pcie host controller on bcma based SoCs.
This also adds minimal support for the BCMA43224 pcie wireless card. SVN-Revision: 29843lede-17.01
parent
0665e400a0
commit
26d4e1876c
|
@ -0,0 +1,133 @@
|
|||
From 8a0e33bd81eafd86252acf7d7ff1bd5362208d7a Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 21 Jan 2012 18:48:38 +0100
|
||||
Subject: [PATCH 33/34] b43: add workaround for b43 on pcie bus of bcm4716.
|
||||
|
||||
bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
|
||||
transactions. As a fix, a read after write is performed on certain
|
||||
places in the code. Older chips and the newer 5357 family don't require
|
||||
this fix.
|
||||
This code is based on the brcmsmac driver.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/net/wireless/b43/b43.h | 25 +++++++++++++++++++++++++
|
||||
drivers/net/wireless/b43/bus.h | 10 ++++++++++
|
||||
drivers/net/wireless/b43/phy_common.c | 6 ++++++
|
||||
drivers/net/wireless/b43/phy_n.c | 10 +++++-----
|
||||
4 files changed, 46 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/b43/b43.h
|
||||
+++ b/drivers/net/wireless/b43/b43.h
|
||||
@@ -1016,6 +1016,31 @@ static inline bool b43_using_pio_transfe
|
||||
return dev->__using_pio_transfers;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
|
||||
+ * transactions. As a fix, a read after write is performed on certain places
|
||||
+ * in the code. Older chips and the newer 5357 family don't require this fix.
|
||||
+ */
|
||||
+#ifdef CONFIG_BCM47XX
|
||||
+#include <asm/mach-bcm47xx/bcm47xx.h>
|
||||
+static inline void b43_wflush16(struct b43_wldev *dev, u16 offset, u16 value)
|
||||
+{
|
||||
+ if (b43_bus_host_is_pci(dev->dev) &&
|
||||
+ (bcm47xx_bus.bcma.bus.chipinfo.id == 0x4716 ||
|
||||
+ bcm47xx_bus.bcma.bus.chipinfo.id == 0x5300)) {
|
||||
+ b43_write16(dev, offset, value);
|
||||
+ b43_read16(dev, offset);
|
||||
+ } else {
|
||||
+ b43_write16(dev, offset, value);
|
||||
+ }
|
||||
+}
|
||||
+#else
|
||||
+static inline void b43_wflush16(struct b43_wldev *dev, u16 offset, u16 value)
|
||||
+{
|
||||
+ b43_write16(dev, offset, value);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/* Message printing */
|
||||
__printf(2, 3) void b43info(struct b43_wl *wl, const char *fmt, ...);
|
||||
__printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
|
||||
--- a/drivers/net/wireless/b43/bus.h
|
||||
+++ b/drivers/net/wireless/b43/bus.h
|
||||
@@ -60,6 +60,16 @@ static inline bool b43_bus_host_is_sdio(
|
||||
return (dev->bus_type == B43_BUS_SSB &&
|
||||
dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
|
||||
}
|
||||
+static inline bool b43_bus_host_is_pci(struct b43_bus_dev *dev)
|
||||
+{
|
||||
+ if (dev->bus_type == B43_BUS_SSB)
|
||||
+ return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
|
||||
+#ifdef CONFIG_B43_BCMA
|
||||
+ if (dev->bus_type == B43_BUS_BCMA)
|
||||
+ return (dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI);
|
||||
+#endif
|
||||
+ return false;
|
||||
+}
|
||||
|
||||
struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
|
||||
struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
|
||||
--- a/drivers/net/wireless/b43/phy_common.c
|
||||
+++ b/drivers/net/wireless/b43/phy_common.c
|
||||
@@ -251,6 +251,12 @@ void b43_phy_write(struct b43_wldev *dev
|
||||
{
|
||||
assert_mac_suspended(dev);
|
||||
dev->phy.ops->phy_write(dev, reg, value);
|
||||
+#ifdef CONFIG_BCM47XX
|
||||
+ if (b43_bus_host_is_pci(dev->dev) && reg == 0x72) {
|
||||
+ b43_read16(dev, B43_MMIO_PHY_VER);
|
||||
+ return;
|
||||
+ }
|
||||
+#endif
|
||||
if (++dev->phy.writes_counter == B43_MAX_WRITES_IN_ROW) {
|
||||
b43_read16(dev, B43_MMIO_PHY_VER);
|
||||
dev->phy.writes_counter = 0;
|
||||
--- a/drivers/net/wireless/b43/phy_n.c
|
||||
+++ b/drivers/net/wireless/b43/phy_n.c
|
||||
@@ -4104,14 +4104,14 @@ static inline void check_phyreg(struct b
|
||||
static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
check_phyreg(dev, reg);
|
||||
- b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
+ b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
return b43_read16(dev, B43_MMIO_PHY_DATA);
|
||||
}
|
||||
|
||||
static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||
{
|
||||
check_phyreg(dev, reg);
|
||||
- b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
+ b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
b43_write16(dev, B43_MMIO_PHY_DATA, value);
|
||||
}
|
||||
|
||||
@@ -4119,7 +4119,7 @@ static void b43_nphy_op_maskset(struct b
|
||||
u16 set)
|
||||
{
|
||||
check_phyreg(dev, reg);
|
||||
- b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
+ b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
b43_write16(dev, B43_MMIO_PHY_DATA,
|
||||
(b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
|
||||
}
|
||||
@@ -4131,7 +4131,7 @@ static u16 b43_nphy_op_radio_read(struct
|
||||
/* N-PHY needs 0x100 for read access */
|
||||
reg |= 0x100;
|
||||
|
||||
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
|
||||
+ b43_wflush16(dev, B43_MMIO_RADIO_CONTROL, reg);
|
||||
return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
|
||||
}
|
||||
|
||||
@@ -4140,7 +4140,7 @@ static void b43_nphy_op_radio_write(stru
|
||||
/* Register 1 is a 32-bit register. */
|
||||
B43_WARN_ON(reg == 1);
|
||||
|
||||
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
|
||||
+ b43_wflush16(dev, B43_MMIO_RADIO_CONTROL, reg);
|
||||
b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,61 @@
|
|||
From 7b9116eeaf44c0d368b5eeaa06eb101465284596 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Wed, 11 Jan 2012 15:26:11 +0100
|
||||
Subject: [PATCH 23/31] bcma: add the core unit number
|
||||
|
||||
Some SoCs have two pcie or gmac cores and we need to know the number of
|
||||
the specific core on the bus. This is the case for the BCM4706.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/scan.c | 14 ++++++++++++++
|
||||
include/linux/bcma/bcma.h | 1 +
|
||||
2 files changed, 15 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/scan.c
|
||||
+++ b/drivers/bcma/scan.c
|
||||
@@ -212,6 +212,17 @@ static struct bcma_device *bcma_find_cor
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid)
|
||||
+{
|
||||
+ struct bcma_device *core;
|
||||
+
|
||||
+ list_for_each_entry_reverse(core, &bus->cores, list) {
|
||||
+ if (core->id.id == coreid)
|
||||
+ return core;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
struct bcma_device_id *match, int core_num,
|
||||
struct bcma_device *core)
|
||||
@@ -407,6 +418,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
||||
bcma_scan_switch_core(bus, erombase);
|
||||
|
||||
while (eromptr < eromend) {
|
||||
+ struct bcma_device *other_core;
|
||||
struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
|
||||
if (!core)
|
||||
return -ENOMEM;
|
||||
@@ -426,6 +438,8 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
||||
|
||||
core->core_index = core_num++;
|
||||
bus->nr_cores++;
|
||||
+ other_core = bcma_find_core_reverse(bus, core->id.id);
|
||||
+ core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
|
||||
|
||||
pr_info("Core %d found: %s "
|
||||
"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
|
||||
--- a/include/linux/bcma/bcma.h
|
||||
+++ b/include/linux/bcma/bcma.h
|
||||
@@ -136,6 +136,7 @@ struct bcma_device {
|
||||
bool dev_registered;
|
||||
|
||||
u8 core_index;
|
||||
+ u8 core_unit;
|
||||
|
||||
u32 addr;
|
||||
u32 addr1;
|
|
@ -0,0 +1,334 @@
|
|||
From 300efafa8e1381a208c723bb9d03d46bf29f1ec0 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 14 Jan 2012 20:02:15 +0100
|
||||
Subject: [PATCH 24/31] bcma: constants for PCI and use them
|
||||
|
||||
There are loots of magic numbers used in the PCIe code. These constants
|
||||
are from the Broadcom SDK and will also used in the host controller.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/driver_pci.c | 124 +++++++++++++++++++---------------
|
||||
include/linux/bcma/bcma_driver_pci.h | 85 +++++++++++++++++++++++
|
||||
2 files changed, 155 insertions(+), 54 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright 2005, Broadcom Corporation
|
||||
* Copyright 2006, 2007, Michael Buesch <m@bues.ch>
|
||||
+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
@@ -18,38 +19,39 @@
|
||||
|
||||
static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
|
||||
{
|
||||
- pcicore_write32(pc, 0x130, address);
|
||||
- pcicore_read32(pc, 0x130);
|
||||
- return pcicore_read32(pc, 0x134);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
|
||||
+ pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
|
||||
+ return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
|
||||
{
|
||||
- pcicore_write32(pc, 0x130, address);
|
||||
- pcicore_read32(pc, 0x130);
|
||||
- pcicore_write32(pc, 0x134, data);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
|
||||
+ pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
|
||||
{
|
||||
- const u16 mdio_control = 0x128;
|
||||
- const u16 mdio_data = 0x12C;
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
- v = (1 << 30); /* Start of Transaction */
|
||||
- v |= (1 << 28); /* Write Transaction */
|
||||
- v |= (1 << 17); /* Turnaround */
|
||||
- v |= (0x1F << 18);
|
||||
+ v = BCMA_CORE_PCI_MDIODATA_START;
|
||||
+ v |= BCMA_CORE_PCI_MDIODATA_WRITE;
|
||||
+ v |= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
|
||||
+ BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
|
||||
+ v |= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR <<
|
||||
+ BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
|
||||
+ v |= BCMA_CORE_PCI_MDIODATA_TA;
|
||||
v |= (phy << 4);
|
||||
- pcicore_write32(pc, mdio_data, v);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
|
||||
|
||||
udelay(10);
|
||||
for (i = 0; i < 200; i++) {
|
||||
- v = pcicore_read32(pc, mdio_control);
|
||||
- if (v & 0x100 /* Trans complete */)
|
||||
+ v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
|
||||
+ if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
@@ -57,79 +59,84 @@ static void bcma_pcie_mdio_set_phy(struc
|
||||
|
||||
static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
|
||||
{
|
||||
- const u16 mdio_control = 0x128;
|
||||
- const u16 mdio_data = 0x12C;
|
||||
int max_retries = 10;
|
||||
u16 ret = 0;
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
- v = 0x80; /* Enable Preamble Sequence */
|
||||
- v |= 0x2; /* MDIO Clock Divisor */
|
||||
- pcicore_write32(pc, mdio_control, v);
|
||||
+ /* enable mdio access to SERDES */
|
||||
+ v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
|
||||
+ v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
|
||||
|
||||
if (pc->core->id.rev >= 10) {
|
||||
max_retries = 200;
|
||||
bcma_pcie_mdio_set_phy(pc, device);
|
||||
+ v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
|
||||
+ BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
|
||||
+ v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
|
||||
+ } else {
|
||||
+ v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
|
||||
+ v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
|
||||
}
|
||||
|
||||
- v = (1 << 30); /* Start of Transaction */
|
||||
- v |= (1 << 29); /* Read Transaction */
|
||||
- v |= (1 << 17); /* Turnaround */
|
||||
- if (pc->core->id.rev < 10)
|
||||
- v |= (u32)device << 22;
|
||||
- v |= (u32)address << 18;
|
||||
- pcicore_write32(pc, mdio_data, v);
|
||||
+ v = BCMA_CORE_PCI_MDIODATA_START;
|
||||
+ v |= BCMA_CORE_PCI_MDIODATA_READ;
|
||||
+ v |= BCMA_CORE_PCI_MDIODATA_TA;
|
||||
+
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
|
||||
/* Wait for the device to complete the transaction */
|
||||
udelay(10);
|
||||
for (i = 0; i < max_retries; i++) {
|
||||
- v = pcicore_read32(pc, mdio_control);
|
||||
- if (v & 0x100 /* Trans complete */) {
|
||||
+ v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
|
||||
+ if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) {
|
||||
udelay(10);
|
||||
- ret = pcicore_read32(pc, mdio_data);
|
||||
+ ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA);
|
||||
break;
|
||||
}
|
||||
msleep(1);
|
||||
}
|
||||
- pcicore_write32(pc, mdio_control, 0);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
|
||||
u8 address, u16 data)
|
||||
{
|
||||
- const u16 mdio_control = 0x128;
|
||||
- const u16 mdio_data = 0x12C;
|
||||
int max_retries = 10;
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
- v = 0x80; /* Enable Preamble Sequence */
|
||||
- v |= 0x2; /* MDIO Clock Divisor */
|
||||
- pcicore_write32(pc, mdio_control, v);
|
||||
+ /* enable mdio access to SERDES */
|
||||
+ v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
|
||||
+ v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
|
||||
|
||||
if (pc->core->id.rev >= 10) {
|
||||
max_retries = 200;
|
||||
bcma_pcie_mdio_set_phy(pc, device);
|
||||
+ v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
|
||||
+ BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
|
||||
+ v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
|
||||
+ } else {
|
||||
+ v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
|
||||
+ v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
|
||||
}
|
||||
|
||||
- v = (1 << 30); /* Start of Transaction */
|
||||
- v |= (1 << 28); /* Write Transaction */
|
||||
- v |= (1 << 17); /* Turnaround */
|
||||
- if (pc->core->id.rev < 10)
|
||||
- v |= (u32)device << 22;
|
||||
- v |= (u32)address << 18;
|
||||
+ v = BCMA_CORE_PCI_MDIODATA_START;
|
||||
+ v |= BCMA_CORE_PCI_MDIODATA_WRITE;
|
||||
+ v |= BCMA_CORE_PCI_MDIODATA_TA;
|
||||
v |= data;
|
||||
- pcicore_write32(pc, mdio_data, v);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
|
||||
/* Wait for the device to complete the transaction */
|
||||
udelay(10);
|
||||
for (i = 0; i < max_retries; i++) {
|
||||
- v = pcicore_read32(pc, mdio_control);
|
||||
- if (v & 0x100 /* Trans complete */)
|
||||
+ v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
|
||||
+ if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
- pcicore_write32(pc, mdio_control, 0);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
@@ -138,20 +145,29 @@ static void bcma_pcie_mdio_write(struct
|
||||
|
||||
static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
|
||||
{
|
||||
- return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ tmp = bcma_pcie_read(pc, BCMA_CORE_PCI_PLP_STATUSREG);
|
||||
+ if (tmp & BCMA_CORE_PCI_PLP_POLARITYINV_STAT)
|
||||
+ return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE |
|
||||
+ BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY;
|
||||
+ else
|
||||
+ return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE;
|
||||
}
|
||||
|
||||
static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
|
||||
{
|
||||
- const u8 serdes_pll_device = 0x1D;
|
||||
- const u8 serdes_rx_device = 0x1F;
|
||||
u16 tmp;
|
||||
|
||||
- bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */,
|
||||
- bcma_pcicore_polarity_workaround(pc));
|
||||
- tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */);
|
||||
- if (tmp & 0x4000)
|
||||
- bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000);
|
||||
+ bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX,
|
||||
+ BCMA_CORE_PCI_SERDES_RX_CTRL,
|
||||
+ bcma_pcicore_polarity_workaround(pc));
|
||||
+ tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
|
||||
+ BCMA_CORE_PCI_SERDES_PLL_CTRL);
|
||||
+ if (tmp & BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN)
|
||||
+ bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
|
||||
+ BCMA_CORE_PCI_SERDES_PLL_CTRL,
|
||||
+ tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
--- a/include/linux/bcma/bcma_driver_pci.h
|
||||
+++ b/include/linux/bcma/bcma_driver_pci.h
|
||||
@@ -53,6 +53,35 @@ struct pci_dev;
|
||||
#define BCMA_CORE_PCI_SBTOPCI1_MASK 0xFC000000
|
||||
#define BCMA_CORE_PCI_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */
|
||||
#define BCMA_CORE_PCI_SBTOPCI2_MASK 0xC0000000
|
||||
+#define BCMA_CORE_PCI_CONFIG_ADDR 0x0120 /* pcie config space access */
|
||||
+#define BCMA_CORE_PCI_CONFIG_DATA 0x0124 /* pcie config space access */
|
||||
+#define BCMA_CORE_PCI_MDIO_CONTROL 0x0128 /* controls the mdio access */
|
||||
+#define BCMA_CORE_PCI_MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
|
||||
+#define BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL 0x2
|
||||
+#define BCMA_CORE_PCI_MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */
|
||||
+#define BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */
|
||||
+#define BCMA_CORE_PCI_MDIO_DATA 0x012c /* Data to the mdio access */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_MASK 0x0000ffff /* data 2 bytes */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_TA 0x00020000 /* Turnaround */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift (rev < 10) */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_REGADDR_MASK_OLD 0x003c0000 /* Regaddr Mask (rev < 10) */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift (rev < 10) */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_REGADDR_SHF 18 /* Regaddr shift */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK 0x0f800000 /* Physmedia devaddr Mask */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_WRITE 0x10000000 /* write Transaction */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_READ 0x20000000 /* Read Transaction */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_START 0x40000000 /* start of Transaction */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */
|
||||
+#define BCMA_CORE_PCI_MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */
|
||||
+#define BCMA_CORE_PCI_PCIEIND_ADDR 0x0130 /* indirect access to the internal register */
|
||||
+#define BCMA_CORE_PCI_PCIEIND_DATA 0x0134 /* Data to/from the internal regsiter */
|
||||
+#define BCMA_CORE_PCI_CLKREQENCTRL 0x0138 /* >= rev 6, Clkreq rdma control */
|
||||
#define BCMA_CORE_PCI_PCICFG0 0x0400 /* PCI config space 0 (rev >= 8) */
|
||||
#define BCMA_CORE_PCI_PCICFG1 0x0500 /* PCI config space 1 (rev >= 8) */
|
||||
#define BCMA_CORE_PCI_PCICFG2 0x0600 /* PCI config space 2 (rev >= 8) */
|
||||
@@ -72,6 +101,62 @@ struct pci_dev;
|
||||
#define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */
|
||||
#define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */
|
||||
|
||||
+/* PCIE protocol PHY diagnostic registers */
|
||||
+#define BCMA_CORE_PCI_PLP_MODEREG 0x200 /* Mode */
|
||||
+#define BCMA_CORE_PCI_PLP_STATUSREG 0x204 /* Status */
|
||||
+#define BCMA_CORE_PCI_PLP_POLARITYINV_STAT 0x10 /* Status reg PCIE_PLP_STATUSREG */
|
||||
+#define BCMA_CORE_PCI_PLP_LTSSMCTRLREG 0x208 /* LTSSM control */
|
||||
+#define BCMA_CORE_PCI_PLP_LTLINKNUMREG 0x20c /* Link Training Link number */
|
||||
+#define BCMA_CORE_PCI_PLP_LTLANENUMREG 0x210 /* Link Training Lane number */
|
||||
+#define BCMA_CORE_PCI_PLP_LTNFTSREG 0x214 /* Link Training N_FTS */
|
||||
+#define BCMA_CORE_PCI_PLP_ATTNREG 0x218 /* Attention */
|
||||
+#define BCMA_CORE_PCI_PLP_ATTNMASKREG 0x21C /* Attention Mask */
|
||||
+#define BCMA_CORE_PCI_PLP_RXERRCTR 0x220 /* Rx Error */
|
||||
+#define BCMA_CORE_PCI_PLP_RXFRMERRCTR 0x224 /* Rx Framing Error */
|
||||
+#define BCMA_CORE_PCI_PLP_RXERRTHRESHREG 0x228 /* Rx Error threshold */
|
||||
+#define BCMA_CORE_PCI_PLP_TESTCTRLREG 0x22C /* Test Control reg */
|
||||
+#define BCMA_CORE_PCI_PLP_SERDESCTRLOVRDREG 0x230 /* SERDES Control Override */
|
||||
+#define BCMA_CORE_PCI_PLP_TIMINGOVRDREG 0x234 /* Timing param override */
|
||||
+#define BCMA_CORE_PCI_PLP_RXTXSMDIAGREG 0x238 /* RXTX State Machine Diag */
|
||||
+#define BCMA_CORE_PCI_PLP_LTSSMDIAGREG 0x23C /* LTSSM State Machine Diag */
|
||||
+
|
||||
+/* PCIE protocol DLLP diagnostic registers */
|
||||
+#define BCMA_CORE_PCI_DLLP_LCREG 0x100 /* Link Control */
|
||||
+#define BCMA_CORE_PCI_DLLP_LSREG 0x104 /* Link Status */
|
||||
+#define BCMA_CORE_PCI_DLLP_LAREG 0x108 /* Link Attention */
|
||||
+#define BCMA_CORE_PCI_DLLP_LSREG_LINKUP (1 << 16)
|
||||
+#define BCMA_CORE_PCI_DLLP_LAMASKREG 0x10C /* Link Attention Mask */
|
||||
+#define BCMA_CORE_PCI_DLLP_NEXTTXSEQNUMREG 0x110 /* Next Tx Seq Num */
|
||||
+#define BCMA_CORE_PCI_DLLP_ACKEDTXSEQNUMREG 0x114 /* Acked Tx Seq Num */
|
||||
+#define BCMA_CORE_PCI_DLLP_PURGEDTXSEQNUMREG 0x118 /* Purged Tx Seq Num */
|
||||
+#define BCMA_CORE_PCI_DLLP_RXSEQNUMREG 0x11C /* Rx Sequence Number */
|
||||
+#define BCMA_CORE_PCI_DLLP_LRREG 0x120 /* Link Replay */
|
||||
+#define BCMA_CORE_PCI_DLLP_LACKTOREG 0x124 /* Link Ack Timeout */
|
||||
+#define BCMA_CORE_PCI_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */
|
||||
+#define BCMA_CORE_PCI_DLLP_RTRYWPREG 0x12C /* Retry buffer write ptr */
|
||||
+#define BCMA_CORE_PCI_DLLP_RTRYRPREG 0x130 /* Retry buffer Read ptr */
|
||||
+#define BCMA_CORE_PCI_DLLP_RTRYPPREG 0x134 /* Retry buffer Purged ptr */
|
||||
+#define BCMA_CORE_PCI_DLLP_RTRRWREG 0x138 /* Retry buffer Read/Write */
|
||||
+#define BCMA_CORE_PCI_DLLP_ECTHRESHREG 0x13C /* Error Count Threshold */
|
||||
+#define BCMA_CORE_PCI_DLLP_TLPERRCTRREG 0x140 /* TLP Error Counter */
|
||||
+#define BCMA_CORE_PCI_DLLP_ERRCTRREG 0x144 /* Error Counter */
|
||||
+#define BCMA_CORE_PCI_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter */
|
||||
+#define BCMA_CORE_PCI_DLLP_TESTREG 0x14C /* Test */
|
||||
+#define BCMA_CORE_PCI_DLLP_PKTBIST 0x150 /* Packet BIST */
|
||||
+#define BCMA_CORE_PCI_DLLP_PCIE11 0x154 /* DLLP PCIE 1.1 reg */
|
||||
+
|
||||
+/* SERDES RX registers */
|
||||
+#define BCMA_CORE_PCI_SERDES_RX_CTRL 1 /* Rx cntrl */
|
||||
+#define BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */
|
||||
+#define BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */
|
||||
+#define BCMA_CORE_PCI_SERDES_RX_TIMER1 2 /* Rx Timer1 */
|
||||
+#define BCMA_CORE_PCI_SERDES_RX_CDR 6 /* CDR */
|
||||
+#define BCMA_CORE_PCI_SERDES_RX_CDRBW 7 /* CDR BW */
|
||||
+
|
||||
+/* SERDES PLL registers */
|
||||
+#define BCMA_CORE_PCI_SERDES_PLL_CTRL 1 /* PLL control reg */
|
||||
+#define BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */
|
||||
+
|
||||
/* PCIcore specific boardflags */
|
||||
#define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
From 01d8709c311858c37e02c96464ea4dc954334210 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 14 Jan 2012 20:03:09 +0100
|
||||
Subject: [PATCH 25/31] bcma: export bcma_pcie_read()
|
||||
|
||||
This will be needed by the host controller.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/bcma_private.h | 2 ++
|
||||
drivers/bcma/driver_pci.c | 2 +-
|
||||
2 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -46,6 +46,8 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr
|
||||
int bcma_sflash_init(struct bcma_drv_cc *cc);
|
||||
#endif /* CONFIG_BCMA_SFLASH */
|
||||
|
||||
+u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
|
||||
+
|
||||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
/* host_pci.c */
|
||||
extern int __init bcma_host_pci_init(void);
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -17,7 +17,7 @@
|
||||
* R/W ops.
|
||||
**************************************************/
|
||||
|
||||
-static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
|
||||
+u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
|
||||
{
|
||||
pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
|
||||
pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
|
|
@ -0,0 +1,111 @@
|
|||
From 3cd3138f2ef77e18abc99737c6740f35d61dbbb3 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 15 Jan 2012 23:05:05 +0100
|
||||
Subject: [PATCH 26/32] bcma: make some functions __devinit
|
||||
|
||||
bcma_core_pci_hostmode_init() has to be in __devinit as it will call a
|
||||
function in that section and so all functions calling it also have to
|
||||
be in __devinit.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/bcma_private.h | 4 ++--
|
||||
drivers/bcma/driver_pci.c | 6 +++---
|
||||
drivers/bcma/driver_pci_host.c | 2 +-
|
||||
drivers/bcma/host_pci.c | 4 ++--
|
||||
drivers/bcma/main.c | 2 +-
|
||||
include/linux/bcma/bcma_driver_pci.h | 2 +-
|
||||
6 files changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -13,7 +13,7 @@
|
||||
struct bcma_bus;
|
||||
|
||||
/* main.c */
|
||||
-int bcma_bus_register(struct bcma_bus *bus);
|
||||
+int __devinit bcma_bus_register(struct bcma_bus *bus);
|
||||
void bcma_bus_unregister(struct bcma_bus *bus);
|
||||
int __init bcma_bus_early_register(struct bcma_bus *bus,
|
||||
struct bcma_device *core_cc,
|
||||
@@ -55,7 +55,7 @@ extern void __exit bcma_host_pci_exit(vo
|
||||
#endif /* CONFIG_BCMA_HOST_PCI */
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
-void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
||||
+void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
||||
#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
|
||||
#endif
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -174,12 +174,12 @@ static void bcma_pcicore_serdes_workarou
|
||||
* Init.
|
||||
**************************************************/
|
||||
|
||||
-static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
|
||||
+static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
bcma_pcicore_serdes_workaround(pc);
|
||||
}
|
||||
|
||||
-static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
||||
+static bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
||||
{
|
||||
struct bcma_bus *bus = pc->core->bus;
|
||||
u16 chipid_top;
|
||||
@@ -204,7 +204,7 @@ static bool bcma_core_pci_is_in_hostmode
|
||||
return true;
|
||||
}
|
||||
|
||||
-void bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
+void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
if (pc->setup_done)
|
||||
return;
|
||||
--- a/drivers/bcma/driver_pci_host.c
|
||||
+++ b/drivers/bcma/driver_pci_host.c
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "bcma_private.h"
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
-void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
+void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
pr_err("No support for PCI core in hostmode yet\n");
|
||||
}
|
||||
--- a/drivers/bcma/host_pci.c
|
||||
+++ b/drivers/bcma/host_pci.c
|
||||
@@ -154,8 +154,8 @@ const struct bcma_host_ops bcma_host_pci
|
||||
.awrite32 = bcma_host_pci_awrite32,
|
||||
};
|
||||
|
||||
-static int bcma_host_pci_probe(struct pci_dev *dev,
|
||||
- const struct pci_device_id *id)
|
||||
+static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
|
||||
+ const struct pci_device_id *id)
|
||||
{
|
||||
struct bcma_bus *bus;
|
||||
int err = -ENOMEM;
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -132,7 +132,7 @@ static void bcma_unregister_cores(struct
|
||||
}
|
||||
}
|
||||
|
||||
-int bcma_bus_register(struct bcma_bus *bus)
|
||||
+int __devinit bcma_bus_register(struct bcma_bus *bus)
|
||||
{
|
||||
int err;
|
||||
struct bcma_device *core;
|
||||
--- a/include/linux/bcma/bcma_driver_pci.h
|
||||
+++ b/include/linux/bcma/bcma_driver_pci.h
|
||||
@@ -169,7 +169,7 @@ struct bcma_drv_pci {
|
||||
#define pcicore_read32(pc, offset) bcma_read32((pc)->core, offset)
|
||||
#define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val)
|
||||
|
||||
-extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
|
||||
+extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc);
|
||||
extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
|
||||
struct bcma_device *core, bool enable);
|
||||
|
|
@ -0,0 +1,845 @@
|
|||
From 47d0e8c2743729b4248585d33b55b6aaeac008d5 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 8 Jan 2012 16:53:15 +0100
|
||||
Subject: [PATCH 25/34] bcma: add PCIe host controller
|
||||
|
||||
Some SoCs have a PCIe host controller to make it possible to attach
|
||||
some other devices to it, like an other Wifi card.
|
||||
This code was tested with an Netgear WNDR3400 (bcm4716 based), but
|
||||
should work with all bcma based SoCs.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
arch/mips/pci/pci-bcm47xx.c | 49 +++-
|
||||
drivers/bcma/bcma_private.h | 1 +
|
||||
drivers/bcma/driver_pci.c | 38 +--
|
||||
drivers/bcma/driver_pci_host.c | 576 +++++++++++++++++++++++++++++++++-
|
||||
include/linux/bcma/bcma_driver_pci.h | 34 ++
|
||||
include/linux/bcma/bcma_regs.h | 27 ++
|
||||
6 files changed, 686 insertions(+), 39 deletions(-)
|
||||
|
||||
--- a/arch/mips/pci/pci-bcm47xx.c
|
||||
+++ b/arch/mips/pci/pci-bcm47xx.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/ssb/ssb.h>
|
||||
+#include <linux/bcma/bcma.h>
|
||||
#include <bcm47xx.h>
|
||||
|
||||
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
@@ -32,15 +33,12 @@ int __init pcibios_map_irq(const struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int pcibios_plat_dev_init(struct pci_dev *dev)
|
||||
-{
|
||||
#ifdef CONFIG_BCM47XX_SSB
|
||||
+static int bcm47xx_pcibios_plat_dev_init_ssb(struct pci_dev *dev)
|
||||
+{
|
||||
int res;
|
||||
u8 slot, pin;
|
||||
|
||||
- if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
|
||||
- return 0;
|
||||
-
|
||||
res = ssb_pcibios_plat_dev_init(dev);
|
||||
if (res < 0) {
|
||||
printk(KERN_ALERT "PCI: Failed to init device %s\n",
|
||||
@@ -60,6 +58,47 @@ int pcibios_plat_dev_init(struct pci_dev
|
||||
}
|
||||
|
||||
dev->irq = res;
|
||||
+ return 0;
|
||||
+}
|
||||
#endif
|
||||
+
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+static int bcm47xx_pcibios_plat_dev_init_bcma(struct pci_dev *dev)
|
||||
+{
|
||||
+ int res;
|
||||
+
|
||||
+ res = bcma_core_pci_plat_dev_init(dev);
|
||||
+ if (res < 0) {
|
||||
+ printk(KERN_ALERT "PCI: Failed to init device %s\n",
|
||||
+ pci_name(dev));
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ res = bcma_core_pci_pcibios_map_irq(dev);
|
||||
+
|
||||
+ /* IRQ-0 and IRQ-1 are software interrupts. */
|
||||
+ if (res < 2) {
|
||||
+ printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n",
|
||||
+ pci_name(dev));
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ dev->irq = res;
|
||||
return 0;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+int pcibios_plat_dev_init(struct pci_dev *dev)
|
||||
+{
|
||||
+#ifdef CONFIG_BCM47XX_SSB
|
||||
+ if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_SSB)
|
||||
+ return bcm47xx_pcibios_plat_dev_init_ssb(dev);
|
||||
+ else
|
||||
+#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA)
|
||||
+ return bcm47xx_pcibios_plat_dev_init_bcma(dev);
|
||||
+ else
|
||||
+#endif
|
||||
+ return 0;
|
||||
+}
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -55,6 +55,7 @@ extern void __exit bcma_host_pci_exit(vo
|
||||
#endif /* CONFIG_BCMA_HOST_PCI */
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
+bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
|
||||
void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
||||
#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -2,7 +2,7 @@
|
||||
* Broadcom specific AMBA
|
||||
* PCI Core
|
||||
*
|
||||
- * Copyright 2005, Broadcom Corporation
|
||||
+ * Copyright 2005, 2011, Broadcom Corporation
|
||||
* Copyright 2006, 2007, Michael Buesch <m@bues.ch>
|
||||
* Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
@@ -179,47 +179,19 @@ static void __devinit bcma_core_pci_clie
|
||||
bcma_pcicore_serdes_workaround(pc);
|
||||
}
|
||||
|
||||
-static bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
||||
-{
|
||||
- struct bcma_bus *bus = pc->core->bus;
|
||||
- u16 chipid_top;
|
||||
-
|
||||
- chipid_top = (bus->chipinfo.id & 0xFF00);
|
||||
- if (chipid_top != 0x4700 &&
|
||||
- chipid_top != 0x5300)
|
||||
- return false;
|
||||
-
|
||||
-#ifdef CONFIG_SSB_DRIVER_PCICORE
|
||||
- if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
|
||||
- return false;
|
||||
-#endif /* CONFIG_SSB_DRIVER_PCICORE */
|
||||
-
|
||||
-#if 0
|
||||
- /* TODO: on BCMA we use address from EROM instead of magic formula */
|
||||
- u32 tmp;
|
||||
- return !mips_busprobe32(tmp, (bus->mmio +
|
||||
- (pc->core->core_index * BCMA_CORE_SIZE)));
|
||||
-#endif
|
||||
-
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
if (pc->setup_done)
|
||||
return;
|
||||
|
||||
- if (bcma_core_pci_is_in_hostmode(pc)) {
|
||||
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
+ pc->hostmode = bcma_core_pci_is_in_hostmode(pc);
|
||||
+ if (pc->hostmode)
|
||||
bcma_core_pci_hostmode_init(pc);
|
||||
-#else
|
||||
- pr_err("Driver compiled without support for hostmode PCI\n");
|
||||
#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
- } else {
|
||||
- bcma_core_pci_clientmode_init(pc);
|
||||
- }
|
||||
|
||||
- pc->setup_done = true;
|
||||
+ if (!pc->hostmode)
|
||||
+ bcma_core_pci_clientmode_init(pc);
|
||||
}
|
||||
|
||||
int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
|
||||
--- a/drivers/bcma/driver_pci_host.c
|
||||
+++ b/drivers/bcma/driver_pci_host.c
|
||||
@@ -2,13 +2,587 @@
|
||||
* Broadcom specific AMBA
|
||||
* PCI Core in hostmode
|
||||
*
|
||||
+ * Copyright 2005 - 2011, Broadcom Corporation
|
||||
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
|
||||
+ * Copyright 2011, 2012, 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>
|
||||
+#include <asm/paccess.h>
|
||||
+
|
||||
+/* Probe a 32bit value on the bus and catch bus exceptions.
|
||||
+ * Returns nonzero on a bus exception.
|
||||
+ * This is MIPS specific */
|
||||
+#define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr)))
|
||||
+
|
||||
+/* Assume one-hot slot wiring */
|
||||
+#define BCMA_PCI_SLOT_MAX 16
|
||||
+#define PCI_CONFIG_SPACE_SIZE 256
|
||||
+
|
||||
+bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ struct bcma_bus *bus = pc->core->bus;
|
||||
+ u16 chipid_top;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ chipid_top = (bus->chipinfo.id & 0xFF00);
|
||||
+ if (chipid_top != 0x4700 &&
|
||||
+ chipid_top != 0x5300)
|
||||
+ return false;
|
||||
+
|
||||
+ if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
|
||||
+ pr_info("This PCI core is disabled and not working\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ bcma_core_enable(pc->core, 0);
|
||||
+
|
||||
+ return !mips_busprobe32(tmp, pc->core->io_addr);
|
||||
+}
|
||||
+
|
||||
+static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address)
|
||||
+{
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address);
|
||||
+ pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR);
|
||||
+ return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA);
|
||||
+}
|
||||
+
|
||||
+static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address,
|
||||
+ u32 data)
|
||||
+{
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address);
|
||||
+ pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data);
|
||||
+}
|
||||
+
|
||||
+static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
+ unsigned int func, unsigned int off)
|
||||
+{
|
||||
+ u32 addr = 0;
|
||||
+
|
||||
+ /* Issue config commands only when the data link is up (atleast
|
||||
+ * one external pcie device is present).
|
||||
+ */
|
||||
+ if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG)
|
||||
+ & BCMA_CORE_PCI_DLLP_LSREG_LINKUP))
|
||||
+ goto out;
|
||||
+
|
||||
+ /* Type 0 transaction */
|
||||
+ /* Slide the PCI window to the appropriate slot */
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);
|
||||
+ /* Calculate the address */
|
||||
+ addr = pc->host_controller->host_cfg_addr;
|
||||
+ addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT);
|
||||
+ addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT);
|
||||
+ addr |= (off & ~3);
|
||||
+
|
||||
+out:
|
||||
+ return addr;
|
||||
+}
|
||||
+
|
||||
+static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
+ unsigned int func, unsigned int off,
|
||||
+ void *buf, int len)
|
||||
+{
|
||||
+ int err = -EINVAL;
|
||||
+ u32 addr, val;
|
||||
+ void __iomem *mmio = 0;
|
||||
+
|
||||
+ WARN_ON(!pc->hostmode);
|
||||
+ if (unlikely(len != 1 && len != 2 && len != 4))
|
||||
+ goto out;
|
||||
+ if (dev == 0) {
|
||||
+ /* we support only two functions on device 0 */
|
||||
+ if (func > 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* accesses to config registers with offsets >= 256
|
||||
+ * requires indirect access.
|
||||
+ */
|
||||
+ if (off >= PCI_CONFIG_SPACE_SIZE) {
|
||||
+ addr = (func << 12);
|
||||
+ addr |= (off & 0x0FFF);
|
||||
+ val = bcma_pcie_read_config(pc, addr);
|
||||
+ } else {
|
||||
+ addr = BCMA_CORE_PCI_PCICFG0;
|
||||
+ addr |= (func << 8);
|
||||
+ addr |= (off & 0xfc);
|
||||
+ val = pcicore_read32(pc, addr);
|
||||
+ }
|
||||
+ } else {
|
||||
+ addr = bcma_get_cfgspace_addr(pc, dev, func, off);
|
||||
+ if (unlikely(!addr))
|
||||
+ goto out;
|
||||
+ err = -ENOMEM;
|
||||
+ mmio = ioremap_nocache(addr, len);
|
||||
+ if (!mmio)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (mips_busprobe32(val, mmio)) {
|
||||
+ val = 0xffffffff;
|
||||
+ goto unmap;
|
||||
+ }
|
||||
+
|
||||
+ val = readl(mmio);
|
||||
+ }
|
||||
+ val >>= (8 * (off & 3));
|
||||
+
|
||||
+ switch (len) {
|
||||
+ case 1:
|
||||
+ *((u8 *)buf) = (u8)val;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ *((u16 *)buf) = (u16)val;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ *((u32 *)buf) = (u32)val;
|
||||
+ break;
|
||||
+ }
|
||||
+ err = 0;
|
||||
+unmap:
|
||||
+ if (mmio)
|
||||
+ iounmap(mmio);
|
||||
+out:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
+ unsigned int func, unsigned int off,
|
||||
+ const void *buf, int len)
|
||||
+{
|
||||
+ int err = -EINVAL;
|
||||
+ u32 addr = 0, val = 0;
|
||||
+ void __iomem *mmio = 0;
|
||||
+ u16 chipid = pc->core->bus->chipinfo.id;
|
||||
+
|
||||
+ WARN_ON(!pc->hostmode);
|
||||
+ if (unlikely(len != 1 && len != 2 && len != 4))
|
||||
+ goto out;
|
||||
+ if (dev == 0) {
|
||||
+ /* accesses to config registers with offsets >= 256
|
||||
+ * requires indirect access.
|
||||
+ */
|
||||
+ if (off < PCI_CONFIG_SPACE_SIZE) {
|
||||
+ addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
|
||||
+ addr |= (func << 8);
|
||||
+ addr |= (off & 0xfc);
|
||||
+ mmio = ioremap_nocache(addr, len);
|
||||
+ if (!mmio)
|
||||
+ goto out;
|
||||
+ }
|
||||
+ } else {
|
||||
+ addr = bcma_get_cfgspace_addr(pc, dev, func, off);
|
||||
+ if (unlikely(!addr))
|
||||
+ goto out;
|
||||
+ err = -ENOMEM;
|
||||
+ mmio = ioremap_nocache(addr, len);
|
||||
+ if (!mmio)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (mips_busprobe32(val, mmio)) {
|
||||
+ val = 0xffffffff;
|
||||
+ goto unmap;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ switch (len) {
|
||||
+ case 1:
|
||||
+ val = readl(mmio);
|
||||
+ val &= ~(0xFF << (8 * (off & 3)));
|
||||
+ val |= *((const u8 *)buf) << (8 * (off & 3));
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ val = readl(mmio);
|
||||
+ val &= ~(0xFFFF << (8 * (off & 3)));
|
||||
+ val |= *((const u16 *)buf) << (8 * (off & 3));
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ val = *((const u32 *)buf);
|
||||
+ break;
|
||||
+ }
|
||||
+ if (dev == 0 && !addr) {
|
||||
+ /* accesses to config registers with offsets >= 256
|
||||
+ * requires indirect access.
|
||||
+ */
|
||||
+ addr = (func << 12);
|
||||
+ addr |= (off & 0x0FFF);
|
||||
+ bcma_pcie_write_config(pc, addr, val);
|
||||
+ } else {
|
||||
+ writel(val, mmio);
|
||||
+
|
||||
+ if (chipid == 0x4716 || chipid == 0x4748)
|
||||
+ readl(mmio);
|
||||
+ }
|
||||
+
|
||||
+ err = 0;
|
||||
+unmap:
|
||||
+ if (mmio)
|
||||
+ iounmap(mmio);
|
||||
+out:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus,
|
||||
+ unsigned int devfn,
|
||||
+ int reg, int size, u32 *val)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ int err;
|
||||
+ struct bcma_drv_pci *pc;
|
||||
+ struct bcma_drv_pci_host *pc_host;
|
||||
+
|
||||
+ pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops);
|
||||
+ pc = pc_host->pdev;
|
||||
+
|
||||
+ spin_lock_irqsave(&pc_host->cfgspace_lock, flags);
|
||||
+ err = bcma_extpci_read_config(pc, PCI_SLOT(devfn),
|
||||
+ PCI_FUNC(devfn), reg, val, size);
|
||||
+ spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags);
|
||||
+
|
||||
+ return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
|
||||
+}
|
||||
+
|
||||
+static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus,
|
||||
+ unsigned int devfn,
|
||||
+ int reg, int size, u32 val)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ int err;
|
||||
+ struct bcma_drv_pci *pc;
|
||||
+ struct bcma_drv_pci_host *pc_host;
|
||||
+
|
||||
+ pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops);
|
||||
+ pc = pc_host->pdev;
|
||||
+
|
||||
+ spin_lock_irqsave(&pc_host->cfgspace_lock, flags);
|
||||
+ err = bcma_extpci_write_config(pc, PCI_SLOT(devfn),
|
||||
+ PCI_FUNC(devfn), reg, &val, size);
|
||||
+ spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags);
|
||||
+
|
||||
+ return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
|
||||
+}
|
||||
+
|
||||
+/* return cap_offset if requested capability exists in the PCI config space */
|
||||
+static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc,
|
||||
+ unsigned int dev,
|
||||
+ unsigned int func, u8 req_cap_id,
|
||||
+ unsigned char *buf, u32 *buflen)
|
||||
+{
|
||||
+ u8 cap_id;
|
||||
+ u8 cap_ptr = 0;
|
||||
+ u32 bufsize;
|
||||
+ u8 byte_val;
|
||||
+
|
||||
+ /* check for Header type 0 */
|
||||
+ bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val,
|
||||
+ sizeof(u8));
|
||||
+ if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
|
||||
+ return cap_ptr;
|
||||
+
|
||||
+ /* check if the capability pointer field exists */
|
||||
+ bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val,
|
||||
+ sizeof(u8));
|
||||
+ if (!(byte_val & PCI_STATUS_CAP_LIST))
|
||||
+ return cap_ptr;
|
||||
+
|
||||
+ /* check if the capability pointer is 0x00 */
|
||||
+ bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr,
|
||||
+ sizeof(u8));
|
||||
+ if (cap_ptr == 0x00)
|
||||
+ return cap_ptr;
|
||||
+
|
||||
+ /* loop thr'u the capability list and see if the requested capabilty
|
||||
+ * exists */
|
||||
+ bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8));
|
||||
+ while (cap_id != req_cap_id) {
|
||||
+ bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr,
|
||||
+ sizeof(u8));
|
||||
+ if (cap_ptr == 0x00)
|
||||
+ return cap_ptr;
|
||||
+ bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id,
|
||||
+ sizeof(u8));
|
||||
+ }
|
||||
+
|
||||
+ /* found the caller requested capability */
|
||||
+ if ((buf != NULL) && (buflen != NULL)) {
|
||||
+ u8 cap_data;
|
||||
+
|
||||
+ bufsize = *buflen;
|
||||
+ if (!bufsize)
|
||||
+ return cap_ptr;
|
||||
+
|
||||
+ *buflen = 0;
|
||||
+
|
||||
+ /* copy the cpability data excluding cap ID and next ptr */
|
||||
+ cap_data = cap_ptr + 2;
|
||||
+ if ((bufsize + cap_data) > PCI_CONFIG_SPACE_SIZE)
|
||||
+ bufsize = PCI_CONFIG_SPACE_SIZE - cap_data;
|
||||
+ *buflen = bufsize;
|
||||
+ while (bufsize--) {
|
||||
+ bcma_extpci_read_config(pc, dev, func, cap_data, buf,
|
||||
+ sizeof(u8));
|
||||
+ cap_data++;
|
||||
+ buf++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return cap_ptr;
|
||||
+}
|
||||
+
|
||||
+/* If the root port is capable of returning Config Request
|
||||
+ * Retry Status (CRS) Completion Status to software then
|
||||
+ * enable the feature.
|
||||
+ */
|
||||
+static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ u8 cap_ptr, root_ctrl, root_cap, dev;
|
||||
+ u16 val16;
|
||||
+ int i;
|
||||
+
|
||||
+ cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL,
|
||||
+ NULL);
|
||||
+ root_cap = cap_ptr + PCI_EXP_RTCAP;
|
||||
+ bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16));
|
||||
+ if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) {
|
||||
+ /* Enable CRS software visibility */
|
||||
+ root_ctrl = cap_ptr + PCI_EXP_RTCTL;
|
||||
+ val16 = PCI_EXP_RTCTL_CRSSVE;
|
||||
+ bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16,
|
||||
+ sizeof(u16));
|
||||
+
|
||||
+ /* Initiate a configuration request to read the vendor id
|
||||
+ * field of the device function's config space header after
|
||||
+ * 100 ms wait time from the end of Reset. If the device is
|
||||
+ * not done with its internal initialization, it must at
|
||||
+ * least return a completion TLP, with a completion status
|
||||
+ * of "Configuration Request Retry Status (CRS)". The root
|
||||
+ * complex must complete the request to the host by returning
|
||||
+ * a read-data value of 0001h for the Vendor ID field and
|
||||
+ * all 1s for any additional bytes included in the request.
|
||||
+ * Poll using the config reads for max wait time of 1 sec or
|
||||
+ * until we receive the successful completion status. Repeat
|
||||
+ * the procedure for all the devices.
|
||||
+ */
|
||||
+ for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) {
|
||||
+ for (i = 0; i < 100000; i++) {
|
||||
+ bcma_extpci_read_config(pc, dev, 0,
|
||||
+ PCI_VENDOR_ID, &val16,
|
||||
+ sizeof(val16));
|
||||
+ if (val16 != 0x1)
|
||||
+ break;
|
||||
+ udelay(10);
|
||||
+ }
|
||||
+ if (val16 == 0x1)
|
||||
+ pr_err("PCI: Broken device in slot %d\n", dev);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
|
||||
void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
- pr_err("No support for PCI core in hostmode yet\n");
|
||||
+ struct bcma_bus *bus = pc->core->bus;
|
||||
+ struct bcma_drv_pci_host *pc_host;
|
||||
+ u32 tmp;
|
||||
+ u32 pci_membase_1G;
|
||||
+ unsigned long io_map_base;
|
||||
+
|
||||
+ pr_info("PCIEcore in host mode found\n");
|
||||
+
|
||||
+ pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
|
||||
+ if (!pc_host) {
|
||||
+ pr_err("can not allocate memory");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ pc->host_controller = pc_host;
|
||||
+ pc_host->pci_controller.io_resource = &pc_host->io_resource;
|
||||
+ pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
|
||||
+ pc_host->pci_controller.pci_ops = &pc_host->pci_ops;
|
||||
+ pc_host->pdev = pc;
|
||||
+
|
||||
+ pci_membase_1G = BCMA_SOC_PCI_DMA;
|
||||
+ pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG;
|
||||
+
|
||||
+ pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config;
|
||||
+ pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config;
|
||||
+
|
||||
+ pc_host->mem_resource.name = "BCMA PCIcore external memory",
|
||||
+ pc_host->mem_resource.start = BCMA_SOC_PCI_DMA;
|
||||
+ pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1;
|
||||
+ pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
|
||||
+
|
||||
+ pc_host->io_resource.name = "BCMA PCIcore external I/O",
|
||||
+ pc_host->io_resource.start = 0x100;
|
||||
+ pc_host->io_resource.end = 0x7FF;
|
||||
+ pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
|
||||
+
|
||||
+ /* Reset RC */
|
||||
+ udelay(3000);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
|
||||
+ udelay(1000);
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
|
||||
+ BCMA_CORE_PCI_CTL_RST_OE);
|
||||
+
|
||||
+ /* 64 MB I/O access window. On 4716, use
|
||||
+ * sbtopcie0 to access the device registers. We
|
||||
+ * can't use address match 2 (1 GB window) region
|
||||
+ * as mips can't generate 64-bit address on the
|
||||
+ * backplane.
|
||||
+ */
|
||||
+ if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) {
|
||||
+ pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
|
||||
+ pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
|
||||
+ BCMA_SOC_PCI_MEM_SZ - 1;
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
||||
+ BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM);
|
||||
+ } else if (bus->chipinfo.id == 0x5300) {
|
||||
+ tmp = BCMA_CORE_PCI_SBTOPCI_MEM;
|
||||
+ tmp |= BCMA_CORE_PCI_SBTOPCI_PREF;
|
||||
+ tmp |= BCMA_CORE_PCI_SBTOPCI_BURST;
|
||||
+ if (pc->core->core_unit == 0) {
|
||||
+ pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
|
||||
+ pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
|
||||
+ BCMA_SOC_PCI_MEM_SZ - 1;
|
||||
+ pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
||||
+ tmp | BCMA_SOC_PCI_MEM);
|
||||
+ } else if (pc->core->core_unit == 1) {
|
||||
+ pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
|
||||
+ pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
|
||||
+ BCMA_SOC_PCI_MEM_SZ - 1;
|
||||
+ pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
|
||||
+ pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
||||
+ tmp | BCMA_SOC_PCI1_MEM);
|
||||
+ }
|
||||
+ } else
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
||||
+ BCMA_CORE_PCI_SBTOPCI_IO);
|
||||
+
|
||||
+ /* 64 MB configuration access window */
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);
|
||||
+
|
||||
+ /* 1 GB memory access window */
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2,
|
||||
+ BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G);
|
||||
+
|
||||
+
|
||||
+ /* As per PCI Express Base Spec 1.1 we need to wait for
|
||||
+ * at least 100 ms from the end of a reset (cold/warm/hot)
|
||||
+ * before issuing configuration requests to PCI Express
|
||||
+ * devices.
|
||||
+ */
|
||||
+ udelay(100000);
|
||||
+
|
||||
+ bcma_core_pci_enable_crs(pc);
|
||||
+
|
||||
+ /* Enable PCI bridge BAR0 memory & master access */
|
||||
+ tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
|
||||
+ bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp));
|
||||
+
|
||||
+ /* Enable PCI interrupts */
|
||||
+ pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA);
|
||||
+
|
||||
+ /* Ok, ready to run, register it to the system.
|
||||
+ * The following needs change, if we want to port hostmode
|
||||
+ * to non-MIPS platform. */
|
||||
+ io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM,
|
||||
+ 0x04000000);
|
||||
+ pc_host->pci_controller.io_map_base = io_map_base;
|
||||
+ set_io_port_base(pc_host->pci_controller.io_map_base);
|
||||
+ /* Give some time to the PCI controller to configure itself with the new
|
||||
+ * values. Not waiting at this point causes crashes of the machine. */
|
||||
+ mdelay(10);
|
||||
+ register_pci_controller(&pc_host->pci_controller);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+/* Early PCI fixup for a device on the PCI-core bridge. */
|
||||
+static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev)
|
||||
+{
|
||||
+ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
|
||||
+ /* This is not a device on the PCI-core bridge. */
|
||||
+ return;
|
||||
+ }
|
||||
+ if (PCI_SLOT(dev->devfn) != 0)
|
||||
+ return;
|
||||
+
|
||||
+ pr_info("PCI: Fixing up bridge %s\n", pci_name(dev));
|
||||
+
|
||||
+ /* Enable PCI bridge bus mastering and memory space */
|
||||
+ pci_set_master(dev);
|
||||
+ if (pcibios_enable_device(dev, ~0) < 0) {
|
||||
+ pr_err("PCI: BCMA bridge enable failed\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Enable PCI bridge BAR1 prefetch and burst */
|
||||
+ pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3);
|
||||
+}
|
||||
+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge);
|
||||
+
|
||||
+/* Early PCI fixup for all PCI-cores to set the correct memory address. */
|
||||
+static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
|
||||
+{
|
||||
+ struct resource *res;
|
||||
+ int pos;
|
||||
+
|
||||
+ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
|
||||
+ /* This is not a device on the PCI-core bridge. */
|
||||
+ return;
|
||||
+ }
|
||||
+ if (PCI_SLOT(dev->devfn) == 0)
|
||||
+ return;
|
||||
+
|
||||
+ pr_info("PCI: Fixing up addresses %s\n", pci_name(dev));
|
||||
+
|
||||
+ for (pos = 0; pos < 6; pos++) {
|
||||
+ res = &dev->resource[pos];
|
||||
+ if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
|
||||
+ pci_assign_resource(dev, pos);
|
||||
+ }
|
||||
+}
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
|
||||
+
|
||||
+/* This function is called when doing a pci_enable_device().
|
||||
+ * We must first check if the device is a device on the PCI-core bridge. */
|
||||
+int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
|
||||
+{
|
||||
+ struct bcma_drv_pci_host *pc_host;
|
||||
+
|
||||
+ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
|
||||
+ /* This is not a device on the PCI-core bridge. */
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
|
||||
+ pci_ops);
|
||||
+
|
||||
+ pr_info("PCI: Fixing up device %s\n", pci_name(dev));
|
||||
+
|
||||
+ /* Fix up interrupt lines */
|
||||
+ dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
|
||||
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(bcma_core_pci_plat_dev_init);
|
||||
+
|
||||
+/* PCI device IRQ mapping. */
|
||||
+int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
|
||||
+{
|
||||
+ struct bcma_drv_pci_host *pc_host;
|
||||
+
|
||||
+ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
|
||||
+ /* This is not a device on the PCI-core bridge. */
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
|
||||
+ pci_ops);
|
||||
+ return bcma_core_mips_irq(pc_host->pdev->core) + 2;
|
||||
}
|
||||
+EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
|
||||
--- a/include/linux/bcma/bcma_driver_pci.h
|
||||
+++ b/include/linux/bcma/bcma_driver_pci.h
|
||||
@@ -160,9 +160,40 @@ struct pci_dev;
|
||||
/* PCIcore specific boardflags */
|
||||
#define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */
|
||||
|
||||
+/* PCIE Config space accessing MACROS */
|
||||
+#define BCMA_CORE_PCI_CFG_BUS_SHIFT 24 /* Bus shift */
|
||||
+#define BCMA_CORE_PCI_CFG_SLOT_SHIFT 19 /* Slot/Device shift */
|
||||
+#define BCMA_CORE_PCI_CFG_FUN_SHIFT 16 /* Function shift */
|
||||
+#define BCMA_CORE_PCI_CFG_OFF_SHIFT 0 /* Register shift */
|
||||
+
|
||||
+#define BCMA_CORE_PCI_CFG_BUS_MASK 0xff /* Bus mask */
|
||||
+#define BCMA_CORE_PCI_CFG_SLOT_MASK 0x1f /* Slot/Device mask */
|
||||
+#define BCMA_CORE_PCI_CFG_FUN_MASK 7 /* Function mask */
|
||||
+#define BCMA_CORE_PCI_CFG_OFF_MASK 0xfff /* Register mask */
|
||||
+
|
||||
+/* PCIE Root Capability Register bits (Host mode only) */
|
||||
+#define BCMA_CORE_PCI_RC_CRS_VISIBILITY 0x0001
|
||||
+
|
||||
+struct bcma_drv_pci;
|
||||
+
|
||||
+struct bcma_drv_pci_host {
|
||||
+ struct bcma_drv_pci *pdev;
|
||||
+
|
||||
+ u32 host_cfg_addr;
|
||||
+ spinlock_t cfgspace_lock;
|
||||
+
|
||||
+ struct pci_controller pci_controller;
|
||||
+ struct pci_ops pci_ops;
|
||||
+ struct resource mem_resource;
|
||||
+ struct resource io_resource;
|
||||
+};
|
||||
+
|
||||
struct bcma_drv_pci {
|
||||
struct bcma_device *core;
|
||||
u8 setup_done:1;
|
||||
+ u8 hostmode:1;
|
||||
+
|
||||
+ struct bcma_drv_pci_host *host_controller;
|
||||
};
|
||||
|
||||
/* Register access */
|
||||
@@ -173,4 +204,7 @@ extern void __devinit bcma_core_pci_init
|
||||
extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
|
||||
struct bcma_device *core, bool enable);
|
||||
|
||||
+extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
|
||||
+extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
|
||||
+
|
||||
#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
|
||||
--- a/include/linux/bcma/bcma_regs.h
|
||||
+++ b/include/linux/bcma/bcma_regs.h
|
||||
@@ -56,4 +56,31 @@
|
||||
#define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
|
||||
#define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
|
||||
|
||||
+/* SiliconBackplane Address Map.
|
||||
+ * All regions may not exist on all chips.
|
||||
+ */
|
||||
+#define BCMA_SOC_SDRAM_BASE 0x00000000U /* Physical SDRAM */
|
||||
+#define BCMA_SOC_PCI_MEM 0x08000000U /* Host Mode sb2pcitranslation0 (64 MB) */
|
||||
+#define BCMA_SOC_PCI_MEM_SZ (64 * 1024 * 1024)
|
||||
+#define BCMA_SOC_PCI_CFG 0x0c000000U /* Host Mode sb2pcitranslation1 (64 MB) */
|
||||
+#define BCMA_SOC_SDRAM_SWAPPED 0x10000000U /* Byteswapped Physical SDRAM */
|
||||
+#define BCMA_SOC_SDRAM_R2 0x80000000U /* Region 2 for sdram (512 MB) */
|
||||
+
|
||||
+
|
||||
+#define BCMA_SOC_PCI_DMA 0x40000000U /* Client Mode sb2pcitranslation2 (1 GB) */
|
||||
+#define BCMA_SOC_PCI_DMA2 0x80000000U /* Client Mode sb2pcitranslation2 (1 GB) */
|
||||
+#define BCMA_SOC_PCI_DMA_SZ 0x40000000U /* Client Mode sb2pcitranslation2 size in bytes */
|
||||
+#define BCMA_SOC_PCIE_DMA_L32 0x00000000U /* PCIE Client Mode sb2pcitranslation2
|
||||
+ * (2 ZettaBytes), low 32 bits
|
||||
+ */
|
||||
+#define BCMA_SOC_PCIE_DMA_H32 0x80000000U /* PCIE Client Mode sb2pcitranslation2
|
||||
+ * (2 ZettaBytes), high 32 bits
|
||||
+ */
|
||||
+
|
||||
+#define BCMA_SOC_PCI1_MEM 0x40000000U /* Host Mode sb2pcitranslation0 (64 MB) */
|
||||
+#define BCMA_SOC_PCI1_CFG 0x44000000U /* Host Mode sb2pcitranslation1 (64 MB) */
|
||||
+#define BCMA_SOC_PCIE1_DMA_H32 0xc0000000U /* PCIE Client Mode sb2pcitranslation2
|
||||
+ * (2 ZettaBytes), high 32 bits
|
||||
+ */
|
||||
+
|
||||
#endif /* LINUX_BCMA_REGS_H_ */
|
|
@ -0,0 +1,59 @@
|
|||
From eecd733c14952b074d7488934a4f3dc83c9c426b Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 14 Jan 2012 16:29:51 +0100
|
||||
Subject: [PATCH 28/32] bcma: add bus num counter
|
||||
|
||||
If we have two bcma buses on one computer the second will not work
|
||||
without this patch. Now each bus gets an own number.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/main.c | 12 +++++++++++-
|
||||
include/linux/bcma/bcma.h | 1 +
|
||||
2 files changed, 12 insertions(+), 1 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -13,6 +13,12 @@
|
||||
MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
+/* contains the number the next bus should get. */
|
||||
+static unsigned int bcma_bus_next_num = 0;
|
||||
+
|
||||
+/* bcma_buses_mutex locks the bcma_bus_next_num */
|
||||
+static DEFINE_MUTEX(bcma_buses_mutex);
|
||||
+
|
||||
static int bcma_bus_match(struct device *dev, struct device_driver *drv);
|
||||
static int bcma_device_probe(struct device *dev);
|
||||
static int bcma_device_remove(struct device *dev);
|
||||
@@ -93,7 +99,7 @@ static int bcma_register_cores(struct bc
|
||||
|
||||
core->dev.release = bcma_release_core_dev;
|
||||
core->dev.bus = &bcma_bus_type;
|
||||
- dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
|
||||
+ dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
|
||||
|
||||
switch (bus->hosttype) {
|
||||
case BCMA_HOSTTYPE_PCI:
|
||||
@@ -137,6 +143,10 @@ int __devinit bcma_bus_register(struct b
|
||||
int err;
|
||||
struct bcma_device *core;
|
||||
|
||||
+ mutex_lock(&bcma_buses_mutex);
|
||||
+ bus->num = bcma_bus_next_num++;
|
||||
+ mutex_unlock(&bcma_buses_mutex);
|
||||
+
|
||||
/* Scan for devices (cores) */
|
||||
err = bcma_bus_scan(bus);
|
||||
if (err) {
|
||||
--- a/include/linux/bcma/bcma.h
|
||||
+++ b/include/linux/bcma/bcma.h
|
||||
@@ -197,6 +197,7 @@ struct bcma_bus {
|
||||
struct list_head cores;
|
||||
u8 nr_cores;
|
||||
u8 init_done:1;
|
||||
+ u8 num;
|
||||
|
||||
struct bcma_drv_cc drv_cc;
|
||||
struct bcma_drv_pci drv_pci;
|
|
@ -0,0 +1,24 @@
|
|||
From 699c57a18b40ffbe1763915acdc1a3e4fb539d01 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Fri, 13 Jan 2012 17:42:15 +0100
|
||||
Subject: [PATCH 29/32] bcma: add new PCI ID
|
||||
|
||||
This ID was found on the PCIe wireless card on the board of a Netgear
|
||||
WNDR3400 using a bcm4716. The device with this ID is identified by b43
|
||||
as "Broadcom 43224 WLAN".
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/host_pci.c | 1 +
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/host_pci.c
|
||||
+++ b/drivers/bcma/host_pci.c
|
||||
@@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
|
||||
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0xa8d8) },
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
|
|
@ -0,0 +1,63 @@
|
|||
From 1cd3d0de72e42161fe0df355c5429459265aeef0 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 14 Jan 2012 16:11:17 +0100
|
||||
Subject: [PATCH 30/32] bcma: add extra sprom check
|
||||
|
||||
This check is needed on the BCM43224 device as it says in the
|
||||
capabilities it has an sprom but is extra check says it has not.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/sprom.c | 8 ++++++++
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 16 ++++++++++++++++
|
||||
2 files changed, 24 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/sprom.c
|
||||
+++ b/drivers/bcma/sprom.c
|
||||
@@ -210,6 +210,7 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
||||
{
|
||||
u16 offset;
|
||||
u16 *sprom;
|
||||
+ u32 sromctrl;
|
||||
int err = 0;
|
||||
|
||||
if (!bus->drv_cc.core)
|
||||
@@ -220,6 +221,13 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
+ if (bus->drv_cc.core->id.rev >= 32) {
|
||||
+ sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
|
||||
+ if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
|
||||
+ random_ether_addr(bus->sprom.il0mac);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
|
||||
GFP_KERNEL);
|
||||
if (!sprom)
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -239,6 +239,22 @@
|
||||
#define BCMA_CC_FLASH_CFG 0x0128
|
||||
#define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */
|
||||
#define BCMA_CC_FLASH_WAITCNT 0x012C
|
||||
+#define BCMA_CC_SROM_CONTROL 0x0190
|
||||
+#define BCMA_CC_SROM_CONTROL_START 0x80000000
|
||||
+#define BCMA_CC_SROM_CONTROL_BUSY 0x80000000
|
||||
+#define BCMA_CC_SROM_CONTROL_OPCODE 0x60000000
|
||||
+#define BCMA_CC_SROM_CONTROL_OP_READ 0x00000000
|
||||
+#define BCMA_CC_SROM_CONTROL_OP_WRITE 0x20000000
|
||||
+#define BCMA_CC_SROM_CONTROL_OP_WRDIS 0x40000000
|
||||
+#define BCMA_CC_SROM_CONTROL_OP_WREN 0x60000000
|
||||
+#define BCMA_CC_SROM_CONTROL_OTPSEL 0x00000010
|
||||
+#define BCMA_CC_SROM_CONTROL_LOCK 0x00000008
|
||||
+#define BCMA_CC_SROM_CONTROL_SIZE_MASK 0x00000006
|
||||
+#define BCMA_CC_SROM_CONTROL_SIZE_1K 0x00000000
|
||||
+#define BCMA_CC_SROM_CONTROL_SIZE_4K 0x00000002
|
||||
+#define BCMA_CC_SROM_CONTROL_SIZE_16K 0x00000004
|
||||
+#define BCMA_CC_SROM_CONTROL_SIZE_SHIFT 1
|
||||
+#define BCMA_CC_SROM_CONTROL_PRESENT 0x00000001
|
||||
/* 0x1E0 is defined as shared BCMA_CLKCTLST */
|
||||
#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
|
||||
#define BCMA_CC_UART0_DATA 0x0300
|
|
@ -0,0 +1,52 @@
|
|||
From efe89df0326b777563d197b8cf1c25209a31ceb0 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 21 Jan 2012 18:47:42 +0100
|
||||
Subject: [PATCH 32/34] bcma: complete workaround for BCMA43224
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/driver_chipcommon_pmu.c | 15 +++++++++++----
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 5 +++++
|
||||
2 files changed, 16 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/driver_chipcommon_pmu.c
|
||||
+++ b/drivers/bcma/driver_chipcommon_pmu.c
|
||||
@@ -141,12 +141,19 @@ void bcma_pmu_workarounds(struct bcma_dr
|
||||
/* BCM4331 workaround is SPROM-related, we put it in sprom.c */
|
||||
break;
|
||||
case 43224:
|
||||
+ case 43421:
|
||||
+ /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
|
||||
if (bus->chipinfo.rev == 0) {
|
||||
- pr_err("Workarounds for 43224 rev 0 not fully "
|
||||
- "implemented\n");
|
||||
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
|
||||
+ bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
|
||||
+ BCMA_CCTRL_43224_GPIO_TOGGLE,
|
||||
+ BCMA_CCTRL_43224_GPIO_TOGGLE);
|
||||
+ bcma_chipco_chipctl_maskset(cc, 0,
|
||||
+ BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
|
||||
+ BCMA_CCTRL_43224A0_12MA_LED_DRIVE);
|
||||
} else {
|
||||
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
|
||||
+ bcma_chipco_chipctl_maskset(cc, 0,
|
||||
+ BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
|
||||
+ BCMA_CCTRL_43224B0_12MA_LED_DRIVE);
|
||||
}
|
||||
break;
|
||||
case 43225:
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -374,6 +374,11 @@
|
||||
#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */
|
||||
#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */
|
||||
|
||||
+/* 43224 chip-specific ChipControl register bits */
|
||||
+#define BCMA_CCTRL_43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */
|
||||
+#define BCMA_CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
|
||||
+#define BCMA_CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
|
||||
+
|
||||
#define BCMA_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */
|
||||
#define BCMA_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */
|
||||
#define BCMA_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */
|
|
@ -1,18 +0,0 @@
|
|||
--- a/arch/mips/pci/pci.c
|
||||
+++ b/arch/mips/pci/pci.c
|
||||
@@ -185,12 +185,10 @@ static int pcibios_enable_resources(stru
|
||||
if ((idx == PCI_ROM_RESOURCE) &&
|
||||
(!(r->flags & IORESOURCE_ROM_ENABLE)))
|
||||
continue;
|
||||
- if (!r->start && r->end) {
|
||||
- printk(KERN_ERR "PCI: Device %s not available "
|
||||
- "because of resource collisions\n",
|
||||
+ if (!r->start && r->end)
|
||||
+ printk(KERN_WARNING "PCI: Device %s resource"
|
||||
+ "collisions detected. Ignoring...\n",
|
||||
pci_name(dev));
|
||||
- return -EINVAL;
|
||||
- }
|
||||
if (r->flags & IORESOURCE_IO)
|
||||
cmd |= PCI_COMMAND_IO;
|
||||
if (r->flags & IORESOURCE_MEM)
|
Loading…
Reference in New Issue