Hi,
Here is fixed and reworked proposal on introducing AI support with
existing SSB bus codebase. Patches are made agains latest
wireless-testing git as of writing.
http://www.znau.edu.ua/temp/ssb-ai-linux-wireless-testing/2011-02-17-ssb-add-AI-support.tar.bz2
I dont anymore abuse bus abstraction with ops (it was plain wrong as I
see now), just introduced AI over SSB support with appropriate helpers.
Code presented is tested with SSB on PCIE host, plain SSB, AI on
embeddables (for these pmu rev.5/6 and mips74k support patches are
required but that is a whole another story).
Stil looking for testground to test AI code
(014-ssb-add-AI-on-pci-host-support.patch) on PCIE host (ordered some hw
but will get one closely to feb. fall).
Here is dmesg for SSB on PCIE host (BCM4312):
[root@localhost ~]# dmesg | grep -E "[Bb]roadcom|ssb|b43"
b43-pci-bridge 0000:04:00.0: PCI INT A -> GSI 18 (level, low) -> IRQ 18
b43-pci-bridge 0000:04:00.0: setting latency timer to 64
ssb: Core 0 found: ChipCommon (cc 0x800, rev 0x16, vendor 0x4243)
ssb: Core 1 found: IEEE 802.11 (cc 0x812, rev 0x0F, vendor 0x4243)
ssb: Core 2 found: PCMCIA (cc 0x80D, rev 0x0A, vendor 0x4243)
ssb: Core 3 found: PCI-E (cc 0x820, rev 0x09, vendor 0x4243)
ssb: chipcommon status is 0x10
ssb: Found rev 1 PMU (capabilities 0x02A62F01)
ssb: SPROM offset is 0x1000
ssb: SPROM revision 8 detected.
ssb: Sonics Silicon Backplane (SB type) found on PCI device 0000:04:00.0
b43-phy0: Broadcom 4312 WLAN found (core revision 15)
Registered led device: b43-phy0::tx
Registered led device: b43-phy0::rx
Registered led device: b43-phy0::radio
Broadcom 43xx driver loaded [ Features: PNL, Firmware-ID: FW13 ]
Here is dmesg for SSB on embeddable (BCM5354):
root@OpenWrt:/# dmesg | grep -E "[Bb]roadcom|ssb|b4[34]"
CPU revision is: 00029029 (Broadcom BMIPS3300)
ssb: Core 0 found: ChipCommon (cc 0x800, rev 0x14, vendor 0x4243)
ssb: Core 1 found: Fast Ethernet (cc 0x806, rev 0x09, vendor 0x4243)
ssb: Core 2 found: MIPS 3302 (cc 0x816, rev 0x08, vendor 0x4243)
ssb: Core 3 found: USB 2.0 Host (cc 0x819, rev 0x02, vendor 0x4243)
ssb: Core 4 found: MEMC SDRAM (cc 0x80F, rev 0x04, vendor 0x4243)
ssb: Core 5 found: IEEE 802.11 (cc 0x812, rev 0x0D, vendor 0x4243)
ssb: Core 6 found: Roboswitch (cc 0x81C, rev 0x02, vendor 0x4243)
ssb: chipcommon status is 0x0
ssb: Found rev 0 PMU (capabilities 0x04A63400)
ssb: Initializing MIPS core...
ssb: set_irq: core 0x0806, irq 4 => 4
ssb: set_irq: core 0x0816, irq 5 => 2
ssb: set_irq: core 0x0812, irq 2 => 5
ssb: after irq reconfiguration
ssb: core 0x0800, irq : 2(S) 3* 4 5 6 D I
ssb: core 0x0806, irq : 2(S) 3 4* 5 6 D I
ssb: core 0x0816, irq : 2(S)* 3 4 5 6 D I
ssb: core 0x0819, irq : 2(S) 3 4 5 6* D I
ssb: core 0x080f, irq : 2(S) 3 4 5 6 D I*
ssb: core 0x0812, irq : 2(S) 3 4 5* 6 D I
ssb: core 0x081c, irq : 2(S) 3 4 5 6 D I*
ssb: Sonics Silicon Backplane (SB type) found at address 0x18000000
b44: b44.c:v2.0
b44 ssb0:0: eth0: Broadcom 44xx/47xx 10/100BaseT Ethernet 00:90:4c:c0:00:00
b43-phy0: Broadcom 5354 WLAN found (core revision 13)
Broadcom 43xx driver loaded [ Features: P, Firmware-ID: FW13 ]
b44 ssb0:0: eth0: Link is up at 100 Mbps, full duplex
b44 ssb0:0: eth0: Flow control is off for TX and off for RX
b44 ssb0:0: eth0: powering down PHY
b44 ssb0:0: eth0: Link is up at 100 Mbps, full duplex
b44 ssb0:0: eth0: Flow control is off for TX and off for RX
ehci_hcd ssb0:1: SSB EHCI Controller
ehci_hcd ssb0:1: new USB bus registered, assigned bus number 1
ehci_hcd ssb0:1: irq 6, io mem 0x18003800
ehci_hcd ssb0:1: USB 0.0 started, EHCI 1.00
Here is dmesg for AI on embeddable (BCM4716):
root@OpenWrt:/# dmesg | grep -E "ssb|b43|[Bb]roadcom"
ssb: Core 0 found: ChipCommon (cc 0x800, rev 0x1F, vendor 0x04BF)
ssb: Core 1 found: IEEE 802.11 (cc 0x812, rev 0x11, vendor 0x04BF)
ssb: Core 2 found: Gigabit MAC (cc 0x82D, rev 0x00, vendor 0x04BF)
ssb: Core 3 found: MIPS 74K (cc 0x82C, rev 0x01, vendor 0x04A7)
ssb: Core 4 found: USB 2.0 Host (cc 0x819, rev 0x04, vendor 0x04BF)
ssb: Core 5 found: PCI-E (cc 0x820, rev 0x0E, vendor 0x04BF)
ssb: Core 6 found: DDR1/2 memory controller (cc 0x82E, rev 0x01, vendor 0x04BF)
ssb: Core 7 found: Internal Memory (cc 0x80E, rev 0x07, vendor 0x04BF)
ssb: Core 8 found: I2S (cc 0x834, rev 0x00, vendor 0x04BF)
ssb: Found END of erom after 9 cores
ssb: chipcommon status is 0x800
ssb: Found rev 5 PMU (capabilities 0x11242C05)
ssb: Initializing MIPS core...
ssb: ssb_pmu5_clock: p1=1, p2=1, ndiv=48(0x30), m3=8, fc=960, clock=120
ssb: set_irq: core 0x0812, irq 3 => 3
ssb: set_irq: core 0x082d, irq 4 => 4
ssb: set_irq: core 0x0819, irq 5 => 5
ssb: after irq reconfiguration
ssb: core 0x0800, irq : 2(S)* 3 4 5 6 D I
ssb: core 0x0812, irq : 2(S) 3* 4 5 6 D I
ssb: core 0x082d, irq : 2(S) 3 4* 5 6 D I
ssb: core 0x082c, irq : 2(S) 3 4 5 6 D I*
ssb: core 0x0819, irq : 2(S) 3 4 5* 6 D I
ssb: core 0x0820, irq : 2(S) 3 4 5 6* D I
ssb: core 0x082e, irq : 2(S)* 3 4 5 6 D I
ssb: core 0x080e, irq : 2(S) 3 4 5 6 D I*
ssb: core 0x0834, irq : 2(S)* 3 4 5 6 D I
ssb: Sonics Silicon Backplane (AI type) found at address 0x18000000
ssb: ssb_pmu5_clock: p1=1, p2=1, ndiv=48(0x30), m1=2, fc=960, clock=480
ssb: ssb_pmu5_clock: p1=1, p2=1, ndiv=48(0x30), m3=8, fc=960, clock=120
wl0: Broadcom BCM4329 802.11 Wireless Controller 5.10.56.27
ehci_hcd ssb0:2: SSB EHCI Controller
ehci_hcd ssb0:2: new USB bus registered, assigned bus number 1
ehci_hcd ssb0:2: irq 5, io mem 0x18004000
ehci_hcd ssb0:2: USB 0.0 started, EHCI 1.00
Have nice day,
George
Hi,
> Oh, wait a second right here. That's not how Linux development works.
> We want the technically superior solution, not just something that
> works to get stuff working no matter what.
>
> If your patchset works, that's pretty cool. So thanks a lot for getting
> something to the users that works. Nothing stops distributions from
> picking up those patches and distributing it to endusers.
> That doesn't mean we have to adopt it to the mainline, though.
Well, my point here is somewhat different. As I've wrote earlier few
days ago till the time when (or better say if?) we get some tech. docs
on AI, software wise it look very much similat to SB.
Yes, it might be not SSB at all, and might more AMBA or some other
hardware solution.
Actually, software wise at current level of knowledge that goes from
sources available it pretty much the same backplanes where whole num of
registers used to control bus itself 4 for SSB and 2 for AI (I omit here
regs used for identification but they are more chipcommon core ones'
rather than bus property, and also omit those we don't use at all cause
we don't need em or just dont know wth they are).
There are much more differences between PCI and PCIE but we still dont
have two different buses, and here honestly I don't know if PCI project
was forked when PCIE support was added or not.
I wish Broadcom could get us more tech. details on AI or if not then
just name it SSB2 to avoid arguing on confusion caused by <SSB AI> ;)
Have nice day,
George
On Sat, 2011-02-19 at 01:42 +0200, George Kashperko wrote:
> I wish Broadcom could get us more tech. details on AI or if not then
> just name it SSB2 to avoid arguing on confusion caused by <SSB AI> ;)
You're actually suggesting to name the "AI" implementation "SSB2" to
avoid a naming confusion? I hope this is a misunderstanding.
--
Greetings Michael.
On Fri, 2011-02-18 at 00:20 +0200, George Kashperko wrote:
> +static const char *ssb_chipco_chiptype_name(struct ssb_bus *bus)
> +{
> + switch (bus->chipco.chiptype) {
> + case SSB_CHIPCO_SB:
> + return "SB";
> + default:
> + return "UNKNOWN";
> + }
> +}
The term "chip" doesn't seem to be appropriate here.
SSB (and probably AI, too. I don't know), does not have to be on-chip.
There are plenty of old SSB based boards where the SSB bus is wired
across the board.
--
Greetings Michael.
From: George Kashperko <[email protected]>
Reintroduce ssb device enable, disable, is_enabled, admatch base and size
routines as device helpers. This is required for transparent support for AI-style
SB buses later on. As soon as exported routines were just replaced by device
helpers with appropriate inline accessors these changes won't impact
any ssb-related code.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/main.c | 23 ++++++++++++---------
drivers/ssb/scan.c | 1
drivers/ssb/ssb_private.h | 2 +
include/linux/ssb/ssb.h | 39 +++++++++++++++++++++++++++++-------
4 files changed, 48 insertions(+), 17 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/main.c 2011-02-17 14:02:39.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/main.c 2011-02-17 14:02:57.000000000 +0200
@@ -1136,7 +1136,7 @@ static u32 ssb_tmslow_reject_bitmask(str
return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23);
}
-int ssb_device_is_enabled(struct ssb_device *dev)
+static int ssb_device_is_enabled_sb(struct ssb_device *dev)
{
u32 val;
u32 reject;
@@ -1147,7 +1147,6 @@ int ssb_device_is_enabled(struct ssb_dev
return (val == SSB_TMSLOW_CLOCK);
}
-EXPORT_SYMBOL(ssb_device_is_enabled);
static void ssb_flush_tmslow(struct ssb_device *dev)
{
@@ -1161,7 +1160,7 @@ static void ssb_flush_tmslow(struct ssb_
udelay(1);
}
-void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)
+static void ssb_device_enable_sb(struct ssb_device *dev, u32 core_specific_flags)
{
u32 val;
@@ -1190,7 +1189,6 @@ void ssb_device_enable(struct ssb_device
core_specific_flags);
ssb_flush_tmslow(dev);
}
-EXPORT_SYMBOL(ssb_device_enable);
/* Wait for a bit in a register to get set or unset.
* timeout is in units of ten-microseconds */
@@ -1218,7 +1216,7 @@ static int ssb_wait_bit(struct ssb_devic
return -ETIMEDOUT;
}
-void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
+static void ssb_device_disable_sb(struct ssb_device *dev, u32 core_specific_flags)
{
u32 reject;
@@ -1240,7 +1238,6 @@ void ssb_device_disable(struct ssb_devic
core_specific_flags);
ssb_flush_tmslow(dev);
}
-EXPORT_SYMBOL(ssb_device_disable);
u32 ssb_dma_translation(struct ssb_device *dev)
{
@@ -1312,7 +1309,7 @@ error:
}
EXPORT_SYMBOL(ssb_bus_powerup);
-u32 ssb_admatch_base(struct ssb_device *dev, u32 adm)
+static u32 ssb_admatch_base_sb(struct ssb_device *dev, u32 adm)
{
u32 base = 0;
@@ -1336,9 +1333,8 @@ u32 ssb_admatch_base(struct ssb_device *
return base;
}
-EXPORT_SYMBOL(ssb_admatch_base);
-u32 ssb_admatch_size(struct ssb_device *dev, u32 adm)
+static u32 ssb_admatch_size_sb(struct ssb_device *dev, u32 adm)
{
u32 size = 0;
@@ -1363,7 +1359,14 @@ u32 ssb_admatch_size(struct ssb_device *
return size;
}
-EXPORT_SYMBOL(ssb_admatch_size);
+
+const struct ssb_bus_helpers ssb_helpers_sb = {
+ .device_is_enabled = ssb_device_is_enabled_sb,
+ .device_enable = ssb_device_enable_sb,
+ .device_disable = ssb_device_disable_sb,
+ .admatch_base = ssb_admatch_base_sb,
+ .admatch_size = ssb_admatch_size_sb,
+};
static int __init ssb_modinit(void)
{
--- linux-wireless-testing.orig/drivers/ssb/scan.c 2011-02-08 00:22:45.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 14:02:57.000000000 +0200
@@ -351,6 +351,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
dev->core_index = i;
dev->bus = bus;
dev->ops = bus->ops;
+ dev->helpers = &ssb_helpers_sb;
printk(KERN_DEBUG PFX
"Core %d found: %s "
--- linux-wireless-testing.orig/drivers/ssb/ssb_private.h 2011-02-08 00:22:45.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/ssb_private.h 2011-02-17 14:02:57.000000000 +0200
@@ -206,4 +206,6 @@ static inline void b43_pci_ssb_bridge_ex
}
#endif /* CONFIG_SSB_B43_PCI_BRIDGE */
+extern const struct ssb_bus_helpers ssb_helpers_sb;
+
#endif /* LINUX_SSB_PRIVATE_H_ */
--- linux-wireless-testing.orig/include/linux/ssb/ssb.h 2011-02-17 14:02:39.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb.h 2011-02-17 14:02:57.000000000 +0200
@@ -121,6 +121,15 @@ struct ssb_bus_ops {
#endif
};
+/* Bus implementation-specific device helpers */
+struct ssb_bus_helpers {
+ int (*device_is_enabled)(struct ssb_device *dev);
+ void (*device_enable)(struct ssb_device *dev, u32 core_specific_flags);
+ void (*device_disable)(struct ssb_device *dev, u32 core_specific_flags);
+ u32 (*admatch_base)(struct ssb_device *dev, u32 adm);
+ u32 (*admatch_size)(struct ssb_device *dev, u32 adm);
+};
+
/* Core-ID values. */
#define SSB_DEV_CHIPCOMMON 0x800
@@ -170,6 +179,7 @@ struct ssb_device {
/* Having a copy of the ops pointer in each dev struct
* is an optimization. */
const struct ssb_bus_ops *ops;
+ const struct ssb_bus_helpers *helpers;
struct device *dev, *dma_dev;
@@ -416,12 +426,31 @@ extern int ssb_bus_resume(struct ssb_bus
extern u32 ssb_clockspeed(struct ssb_bus *bus);
/* Is the device enabled in hardware? */
-int ssb_device_is_enabled(struct ssb_device *dev);
+static inline int ssb_device_is_enabled(struct ssb_device *dev)
+{
+ return dev->helpers->device_is_enabled(dev);
+}
/* Enable a device and pass device-specific SSB_TMSLOW flags.
* If no device-specific flags are available, use 0. */
-void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags);
+static inline void ssb_device_enable(struct ssb_device *dev,
+ u32 core_specific_flags)
+{
+ return dev->helpers->device_enable(dev, core_specific_flags);
+}
/* Disable a device in hardware and pass SSB_TMSLOW flags (if any). */
-void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
+static inline void ssb_device_disable(struct ssb_device *dev,
+ u32 core_specific_flags)
+{
+ return dev->helpers->device_disable(dev, core_specific_flags);
+}
+static inline u32 ssb_admatch_base(struct ssb_device *dev, u32 adm)
+{
+ return dev->helpers->admatch_base(dev, adm);
+}
+static inline u32 ssb_admatch_size(struct ssb_device *dev, u32 adm)
+{
+ return dev->helpers->admatch_size(dev, adm);
+}
/* Device MMIO register read/write functions. */
@@ -519,10 +548,6 @@ extern int ssb_bus_may_powerdown(struct
extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
-/* Various helper functions */
-extern u32 ssb_admatch_base(struct ssb_device *dev, u32 adm);
-extern u32 ssb_admatch_size(struct ssb_device *dev, u32 adm);
-
/* PCI device mapping and fixup routines.
* Called from the architecture pcibios init code.
* These are only available on SSB_EMBEDDED configurations. */
Hi,
> I don't want to get involved in the debate over abstraction, but FWIW, the
> patchset does work for PCI-based SSB devices.
>
> Larry
>
Could you please let me know if you tried last code I've posted, as my
original RFC was indeed embeddables' targeted and won't work for
SSB-over-PCI.
Last code I've posted I've tested on SSB over PCIE host and it was
pretty much working.
Have nice day,
George
Hi,
> On Sat, 2011-02-19 at 01:42 +0200, George Kashperko wrote:
> > I wish Broadcom could get us more tech. details on AI or if not then
> > just name it SSB2 to avoid arguing on confusion caused by <SSB AI> ;)
>
> You're actually suggesting to name the "AI" implementation "SSB2" to
> avoid a naming confusion? I hope this is a misunderstanding.
>
Nop, that was just clumsy attempt to ask for .dpf's :p
Have nice day,
George
From: George Kashperko <[email protected]>
Major differences between AI/SB from drivers' perespective is control
and state flags handling. These long term used to be TMSLOW/TMSHIGH ones
and in order to be handled transparently should be abstracted by some
indirect access handlers. This patch forces use of ssb_core_ctl_flags
and ssb_core_state_flags introduced earlier. TMSLOW/TMSHIGH defines outside
ssb code (b43, ssb gige and ohci drivers) were renamed to reflect actual
meaning, flags' definitions moved to low two bytes. Common TMSLOW/TMSHIGH
defines moved to ssb_private.h in order to limit their use by internal
SB-specic code only.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/net/b44.c | 2
drivers/net/wireless/b43/b43.h | 32 +++++-----
drivers/net/wireless/b43/dma.c | 4 -
drivers/net/wireless/b43/main.c | 60 ++++++-------------
drivers/net/wireless/b43/phy_g.c | 2
drivers/net/wireless/b43/phy_n.c | 18 +----
drivers/net/wireless/b43legacy/b43legacy.h | 20 +++---
drivers/net/wireless/b43legacy/dma.c | 4 -
drivers/net/wireless/b43legacy/main.c | 51 +++++-----------
drivers/net/wireless/b43legacy/phy.c | 2
drivers/ssb/driver_gige.c | 18 ++---
drivers/ssb/main.c | 16 +++--
drivers/ssb/ssb_private.h | 24 +++++++
drivers/usb/host/ohci-ssb.c | 4 -
include/linux/ssb/ssb.h | 4 -
include/linux/ssb/ssb_driver_gige.h | 12 +--
include/linux/ssb/ssb_regs.h | 42 ++++++-------
17 files changed, 153 insertions(+), 162 deletions(-)
--- linux-wireless-testing.orig/drivers/net/b44.c 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/b44.c 2011-02-17 14:17:32.000000000 +0200
@@ -1568,7 +1568,7 @@ static void b44_setup_wol_pci(struct b44
u16 val;
if (bp->sdev->bus->bustype != SSB_BUSTYPE_SSB) {
- bw32(bp, SSB_TMSLOW, br32(bp, SSB_TMSLOW) | SSB_TMSLOW_PE);
+ ssb_core_ctl_flags(bp->sdev, ~0, SSB_CORECTL_PE);
pci_read_config_word(bp->sdev->bus->host_pci, SSB_PMCSR, &val);
pci_write_config_word(bp->sdev->bus->host_pci, SSB_PMCSR, val | SSB_PE);
}
--- linux-wireless-testing.orig/drivers/net/wireless/b43/b43.h 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43/b43.h 2011-02-17 14:20:28.000000000 +0200
@@ -414,22 +414,22 @@ enum {
#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */
#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */
-/* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
-#define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
-#define B43_TMSLOW_PHY_BANDWIDTH 0x00C00000 /* PHY band width and clock speed mask (N-PHY only) */
-#define B43_TMSLOW_PHY_BANDWIDTH_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */
-#define B43_TMSLOW_PHY_BANDWIDTH_20MHZ 0x00400000 /* 20 MHz bandwidth, 80 MHz PHY */
-#define B43_TMSLOW_PHY_BANDWIDTH_40MHZ 0x00800000 /* 40 MHz bandwidth, 160 MHz PHY */
-#define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select (rev >= 5) */
-#define B43_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Control Enable (rev >= 5) */
-#define B43_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */
-#define B43_TMSLOW_PHYCLKEN 0x00040000 /* PHY Clock Enable */
-
-/* 802.11 core specific TM State High (SSB_TMSHIGH) flags */
-#define B43_TMSHIGH_DUALBAND_PHY 0x00080000 /* Dualband PHY available */
-#define B43_TMSHIGH_FCLOCK 0x00040000 /* Fast Clock Available (rev >= 5) */
-#define B43_TMSHIGH_HAVE_5GHZ_PHY 0x00020000 /* 5 GHz PHY available (rev >= 5) */
-#define B43_TMSHIGH_HAVE_2GHZ_PHY 0x00010000 /* 2.4 GHz PHY available (rev >= 5) */
+/* 802.11 core specific control flags */
+#define B43_CORECTL_GMODE 0x2000 /* G Mode Enable */
+#define B43_CORECTL_PHY_BANDWIDTH 0x00C0 /* PHY band width and clock speed mask (N-PHY only) */
+#define B43_CORECTL_PHY_BANDWIDTH_10MHZ 0x0000 /* 10 MHz bandwidth, 40 MHz PHY */
+#define B43_CORECTL_PHY_BANDWIDTH_20MHZ 0x0040 /* 20 MHz bandwidth, 80 MHz PHY */
+#define B43_CORECTL_PHY_BANDWIDTH_40MHZ 0x0080 /* 40 MHz bandwidth, 160 MHz PHY */
+#define B43_CORECTL_PLLREFSEL 0x0020 /* PLL Frequency Reference Select (rev >= 5) */
+#define B43_CORECTL_MACPHYCLKEN 0x0010 /* MAC PHY Clock Control Enable (rev >= 5) */
+#define B43_CORECTL_PHYRESET 0x0008 /* PHY Reset */
+#define B43_CORECTL_PHYCLKEN 0x0004 /* PHY Clock Enable */
+
+/* 802.11 core specific state flags */
+#define B43_CORESTAT_DUALBAND_PHY 0x0008 /* Dualband PHY available */
+#define B43_CORESTAT_FCLOCK 0x0004 /* Fast Clock Available (rev >= 5) */
+#define B43_CORESTAT_HAVE_5GHZ_PHY 0x0002 /* 5 GHz PHY available (rev >= 5) */
+#define B43_CORESTAT_HAVE_2GHZ_PHY 0x0001 /* 2.4 GHz PHY available (rev >= 5) */
/* Generic-Interrupt reasons. */
#define B43_IRQ_MAC_SUSPENDED 0x00000001
--- linux-wireless-testing.orig/drivers/net/wireless/b43/dma.c 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43/dma.c 2011-02-17 14:17:32.000000000 +0200
@@ -786,8 +786,8 @@ static u64 supported_dma_mask(struct b43
u32 tmp;
u16 mmio_base;
- tmp = b43_read32(dev, SSB_TMSHIGH);
- if (tmp & SSB_TMSHIGH_DMA64)
+ tmp = ssb_core_state_flags(dev->dev);
+ if (tmp & SSB_CORESTAT_DMA64)
return DMA_BIT_MASK(64);
mmio_base = b43_dmacontroller_base(0, 0);
b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
--- linux-wireless-testing.orig/drivers/net/wireless/b43/main.c 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43/main.c 2011-02-17 14:22:30.000000000 +0200
@@ -1145,26 +1145,19 @@ void b43_power_saving_ctl_bits(struct b4
void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
{
- u32 tmslow;
u32 macctl;
- flags |= B43_TMSLOW_PHYCLKEN;
- flags |= B43_TMSLOW_PHYRESET;
+ flags |= B43_CORECTL_PHYCLKEN;
+ flags |= B43_CORECTL_PHYRESET;
if (dev->phy.type == B43_PHYTYPE_N)
- flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
+ flags |= B43_CORECTL_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
ssb_device_enable(dev->dev, flags);
msleep(2); /* Wait for the PLL to turn on. */
/* Now take the PHY out of Reset again */
- tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
- tmslow |= SSB_TMSLOW_FGC;
- tmslow &= ~B43_TMSLOW_PHYRESET;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
+ ssb_core_ctl_flags(dev->dev, ~B43_CORECTL_PHYRESET, SSB_CORECTL_FGC);
msleep(1);
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
+ ssb_core_ctl_flags(dev->dev, ~SSB_CORECTL_FGC, 0);
msleep(1);
/* Turn Analog ON, but only if we already know the PHY-type.
@@ -1176,7 +1169,7 @@ void b43_wireless_core_reset(struct b43_
macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl &= ~B43_MACCTL_GMODE;
- if (flags & B43_TMSLOW_GMODE)
+ if (flags & B43_CORECTL_GMODE)
macctl |= B43_MACCTL_GMODE;
macctl |= B43_MACCTL_IHR_ENABLED;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
@@ -2108,11 +2101,11 @@ static int b43_try_request_fw(struct b43
struct b43_firmware *fw = &ctx->dev->fw;
const u8 rev = ctx->dev->dev->id.revision;
const char *filename;
- u32 tmshigh;
+ u32 state;
int err;
/* Get microcode */
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
+ state = ssb_core_state_flags(dev->dev);
if ((rev >= 5) && (rev <= 10))
filename = "ucode5";
else if ((rev >= 11) && (rev <= 12))
@@ -2151,7 +2144,7 @@ static int b43_try_request_fw(struct b43
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
- if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
+ if (state & B43_CORESTAT_HAVE_2GHZ_PHY)
filename = "a0g1initvals5";
else
filename = "a0g0initvals5";
@@ -2195,7 +2188,7 @@ static int b43_try_request_fw(struct b43
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
- if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
+ if (state & B43_CORESTAT_HAVE_2GHZ_PHY)
filename = "a0g1bsinitvals5";
else
filename = "a0g0bsinitvals5";
@@ -2841,7 +2834,7 @@ static int b43_chip_init(struct b43_wlde
{
struct b43_phy *phy = &dev->phy;
int err;
- u32 value32, macctl;
+ u32 macctl;
u16 value16;
/* Initialize the MAC control */
@@ -2919,9 +2912,7 @@ static int b43_chip_init(struct b43_wlde
b43_write32(dev, B43_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
b43_write32(dev, B43_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
- value32 = ssb_read32(dev->dev, SSB_TMSLOW);
- value32 |= 0x00100000;
- ssb_write32(dev->dev, SSB_TMSLOW, value32);
+ ssb_core_ctl_flags(dev->dev, ~0, B43_CORECTL_MACPHYCLKEN);
b43_write16(dev, B43_MMIO_POWERUP_DELAY,
dev->dev->bus->chipco.fast_pwrup_delay);
@@ -3443,19 +3434,12 @@ static void b43_op_set_tsf(struct ieee80
static void b43_put_phy_into_reset(struct b43_wldev *dev)
{
struct ssb_device *sdev = dev->dev;
- u32 tmslow;
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~B43_TMSLOW_GMODE;
- tmslow |= B43_TMSLOW_PHYRESET;
- tmslow |= SSB_TMSLOW_FGC;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_core_ctl_flags(sdev, ~B43_CORECTL_GMODE,
+ B43_CORECTL_PHYRESET | SSB_CORECTL_FGC);
msleep(1);
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~SSB_TMSLOW_FGC;
- tmslow |= B43_TMSLOW_PHYRESET;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_core_ctl_flags(sdev, ~SSB_CORECTL_FGC, B43_CORECTL_PHYRESET);
msleep(1);
}
@@ -4328,7 +4312,7 @@ static int b43_wireless_core_init(struct
if (err)
goto out;
if (!ssb_device_is_enabled(dev->dev)) {
- tmp = phy->gmode ? B43_TMSLOW_GMODE : 0;
+ tmp = phy->gmode ? B43_CORECTL_GMODE : 0;
b43_wireless_core_reset(dev, tmp);
}
@@ -4755,17 +4739,17 @@ static int b43_wireless_core_attach(stru
}
/* Get the PHY type. */
if (dev->dev->id.revision >= 5) {
- u32 tmshigh;
+ u32 state;
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
- have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
- have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
+ state = ssb_core_state_flags(dev->dev);
+ have_2ghz_phy = !!(state & B43_CORESTAT_HAVE_2GHZ_PHY);
+ have_5ghz_phy = !!(state & B43_CORESTAT_HAVE_5GHZ_PHY);
} else
B43_WARN_ON(1);
dev->phy.gmode = have_2ghz_phy;
dev->phy.radio_on = 1;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
+ tmp = dev->phy.gmode ? B43_CORECTL_GMODE : 0;
b43_wireless_core_reset(dev, tmp);
err = b43_phy_versioning(dev);
@@ -4814,7 +4798,7 @@ static int b43_wireless_core_attach(stru
goto err_powerdown;
dev->phy.gmode = have_2ghz_phy;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
+ tmp = dev->phy.gmode ? B43_CORECTL_GMODE : 0;
b43_wireless_core_reset(dev, tmp);
err = b43_validate_chipaccess(dev);
--- linux-wireless-testing.orig/drivers/net/wireless/b43/phy_g.c 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43/phy_g.c 2011-02-17 14:17:32.000000000 +0200
@@ -2537,7 +2537,7 @@ static int b43_gphy_op_prepare_hardware(
b43_wireless_core_reset(dev, 0);
b43_phy_initg(dev);
phy->gmode = 1;
- b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
+ b43_wireless_core_reset(dev, B43_CORECTL_GMODE);
}
return 0;
--- linux-wireless-testing.orig/drivers/net/wireless/b43/phy_n.c 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43/phy_n.c 2011-02-17 14:23:41.000000000 +0200
@@ -604,17 +604,11 @@ static void b43_nphy_tx_lp_fbw(struct b4
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
{
- u32 tmslow;
-
if (dev->phy.type != B43_PHYTYPE_N)
return;
- tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
- if (force)
- tmslow |= SSB_TMSLOW_FGC;
- else
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+ ssb_core_ctl_flags(dev->dev, ~SSB_CORECTL_FGC,
+ force ? SSB_CORECTL_FGC : 0);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
@@ -3387,12 +3381,8 @@ static int b43_nphy_cal_rx_iq(struct b43
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on)
{
- u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
- if (on)
- tmslow |= B43_TMSLOW_MACPHYCLKEN;
- else
- tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+ ssb_core_ctl_flags(dev->dev, ~B43_CORECTL_MACPHYCLKEN,
+ on ? B43_CORECTL_MACPHYCLKEN : 0);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
--- linux-wireless-testing.orig/drivers/net/wireless/b43legacy/b43legacy.h 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43legacy/b43legacy.h 2011-02-17 14:17:32.000000000 +0200
@@ -218,16 +218,16 @@
#define B43legacy_MACCMD_CCA 0x00000008 /* Clear channel assessment */
#define B43legacy_MACCMD_BGNOISE 0x00000010 /* Background noise */
-/* 802.11 core specific TM State Low flags */
-#define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
-#define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */
-#define B43legacy_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Ctrl Enbl */
-#define B43legacy_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */
-#define B43legacy_TMSLOW_PHYCLKEN 0x00040000 /* PHY Clock Enable */
-
-/* 802.11 core specific TM State High flags */
-#define B43legacy_TMSHIGH_FCLOCK 0x00040000 /* Fast Clock Available */
-#define B43legacy_TMSHIGH_GPHY 0x00010000 /* G-PHY avail (rev >= 5) */
+/* 802.11 core specific control flags */
+#define B43legacy_CORECTL_GMODE 0x2000 /* G Mode Enable */
+#define B43legacy_CORECTL_PLLREFSEL 0x0020 /* PLL Freq Ref Select */
+#define B43legacy_CORECTL_MACPHYCLKEN 0x0010 /* MAC PHY Clock Ctrl Enbl */
+#define B43legacy_CORECTL_PHYRESET 0x0008 /* PHY Reset */
+#define B43legacy_CORECTL_PHYCLKEN 0x0004 /* PHY Clock Enable */
+
+/* 802.11 core specific state flags */
+#define B43legacy_CORESTAT_FCLOCK 0x0004 /* Fast Clock Available */
+#define B43legacy_CORESTAT_GPHY 0x0001 /* G-PHY avail (rev >= 5) */
#define B43legacy_UCODEFLAG_AUTODIV 0x0001
--- linux-wireless-testing.orig/drivers/net/wireless/b43legacy/dma.c 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43legacy/dma.c 2011-02-17 14:17:32.000000000 +0200
@@ -845,8 +845,8 @@ static u64 supported_dma_mask(struct b43
u32 tmp;
u16 mmio_base;
- tmp = b43legacy_read32(dev, SSB_TMSHIGH);
- if (tmp & SSB_TMSHIGH_DMA64)
+ tmp = ssb_core_state_flags(dev->dev);
+ if (tmp & SSB_CORESTAT_DMA64)
return DMA_BIT_MASK(64);
mmio_base = b43legacy_dmacontroller_base(0, 0);
b43legacy_write32(dev,
--- linux-wireless-testing.orig/drivers/net/wireless/b43legacy/main.c 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43legacy/main.c 2011-02-17 14:17:32.000000000 +0200
@@ -697,24 +697,18 @@ static void b43legacy_switch_analog(stru
void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags)
{
- u32 tmslow;
u32 macctl;
- flags |= B43legacy_TMSLOW_PHYCLKEN;
- flags |= B43legacy_TMSLOW_PHYRESET;
+ flags |= B43legacy_CORECTL_PHYCLKEN;
+ flags |= B43legacy_CORECTL_PHYRESET;
ssb_device_enable(dev->dev, flags);
msleep(2); /* Wait for the PLL to turn on. */
/* Now take the PHY out of Reset again */
- tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
- tmslow |= SSB_TMSLOW_FGC;
- tmslow &= ~B43legacy_TMSLOW_PHYRESET;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
+ ssb_core_ctl_flags(dev->dev, ~B43legacy_CORECTL_PHYRESET,
+ SSB_CORECTL_FGC);
msleep(1);
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
+ ssb_core_ctl_flags(dev->dev, ~SSB_CORECTL_FGC, 0);
msleep(1);
/* Turn Analog ON */
@@ -722,7 +716,7 @@ void b43legacy_wireless_core_reset(struc
macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
macctl &= ~B43legacy_MACCTL_GMODE;
- if (flags & B43legacy_TMSLOW_GMODE) {
+ if (flags & B43legacy_CORECTL_GMODE) {
macctl |= B43legacy_MACCTL_GMODE;
dev->phy.gmode = 1;
} else
@@ -1564,10 +1558,10 @@ static int b43legacy_request_firmware(st
struct b43legacy_firmware *fw = &dev->fw;
const u8 rev = dev->dev->id.revision;
const char *filename;
- u32 tmshigh;
+ u32 state;
int err;
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
+ state = ssb_core_state_flags(dev->dev);
if (!fw->ucode) {
if (rev == 2)
filename = "ucode2";
@@ -2233,9 +2227,7 @@ static int b43legacy_chip_init(struct b4
b43legacy_write32(dev, B43legacy_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
- value32 = ssb_read32(dev->dev, SSB_TMSLOW);
- value32 |= 0x00100000;
- ssb_write32(dev->dev, SSB_TMSLOW, value32);
+ ssb_core_ctl_flags(dev->dev, ~0, B43legacy_CORECTL_MACPHYCLKEN);
b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY,
dev->dev->bus->chipco.fast_pwrup_delay);
@@ -2525,19 +2517,12 @@ static int find_wldev_for_phymode(struct
static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev)
{
struct ssb_device *sdev = dev->dev;
- u32 tmslow;
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~B43legacy_TMSLOW_GMODE;
- tmslow |= B43legacy_TMSLOW_PHYRESET;
- tmslow |= SSB_TMSLOW_FGC;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_core_ctl_flags(sdev, ~B43legacy_CORECTL_GMODE,
+ B43legacy_CORECTL_PHYRESET | SSB_CORECTL_FGC);
msleep(1);
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~SSB_TMSLOW_FGC;
- tmslow |= B43legacy_TMSLOW_PHYRESET;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_core_ctl_flags(sdev, ~SSB_CORECTL_FGC, B43legacy_CORECTL_PHYRESET);
msleep(1);
}
@@ -3258,7 +3243,7 @@ static int b43legacy_wireless_core_init(
if (err)
goto out;
if (!ssb_device_is_enabled(dev->dev)) {
- tmp = phy->gmode ? B43legacy_TMSLOW_GMODE : 0;
+ tmp = phy->gmode ? B43legacy_CORECTL_GMODE : 0;
b43legacy_wireless_core_reset(dev, tmp);
}
@@ -3640,10 +3625,10 @@ static int b43legacy_wireless_core_attac
}
/* Get the PHY type. */
if (dev->dev->id.revision >= 5) {
- u32 tmshigh;
+ u32 state;
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
- have_gphy = !!(tmshigh & B43legacy_TMSHIGH_GPHY);
+ state = ssb_core_state_flags(dev->dev);
+ have_gphy = !!(state & B43legacy_CORESTAT_GPHY);
if (!have_gphy)
have_bphy = 1;
} else if (dev->dev->id.revision == 4)
@@ -3653,7 +3638,7 @@ static int b43legacy_wireless_core_attac
dev->phy.gmode = (have_gphy || have_bphy);
dev->phy.radio_on = 1;
- tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
+ tmp = dev->phy.gmode ? B43legacy_CORECTL_GMODE : 0;
b43legacy_wireless_core_reset(dev, tmp);
err = b43legacy_phy_versioning(dev);
@@ -3679,7 +3664,7 @@ static int b43legacy_wireless_core_attac
}
}
dev->phy.gmode = (have_gphy || have_bphy);
- tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
+ tmp = dev->phy.gmode ? B43legacy_CORECTL_GMODE : 0;
b43legacy_wireless_core_reset(dev, tmp);
err = b43legacy_validate_chipaccess(dev);
--- linux-wireless-testing.orig/drivers/net/wireless/b43legacy/phy.c 2011-02-08 00:22:30.000000000 +0200
+++ linux-wireless-testing/drivers/net/wireless/b43legacy/phy.c 2011-02-17 14:17:32.000000000 +0200
@@ -148,7 +148,7 @@ void b43legacy_phy_calibrate(struct b43l
if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) {
b43legacy_wireless_core_reset(dev, 0);
b43legacy_phy_initg(dev);
- b43legacy_wireless_core_reset(dev, B43legacy_TMSLOW_GMODE);
+ b43legacy_wireless_core_reset(dev, B43legacy_CORECTL_GMODE);
}
phy->calibrated = 1;
}
--- linux-wireless-testing.orig/drivers/ssb/driver_gige.c 2011-02-17 14:02:39.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/driver_gige.c 2011-02-17 14:17:32.000000000 +0200
@@ -169,7 +169,7 @@ static int ssb_gige_pci_write_config(str
static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
{
struct ssb_gige *dev;
- u32 base, tmslow, tmshigh;
+ u32 base, ctl, state;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -217,19 +217,17 @@ static int ssb_gige_probe(struct ssb_dev
/* Check if we have an RGMII or GMII PHY-bus.
* On RGMII do not bypass the DLLs */
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmshigh = ssb_read32(sdev, SSB_TMSHIGH);
- if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) {
- tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS;
- tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS;
+ state = ssb_core_state_flags(sdev);
+ ctl = SSB_GIGE_CORECTL_DLLEN;
+ if (state & SSB_GIGE_CORESTAT_RGMII) {
dev->has_rgmii = 1;
} else {
- tmslow |= SSB_GIGE_TMSLOW_TXBYPASS;
- tmslow |= SSB_GIGE_TMSLOW_RXBYPASS;
+ ctl |= SSB_GIGE_CORECTL_TXBYPASS;
+ ctl |= SSB_GIGE_CORECTL_RXBYPASS;
dev->has_rgmii = 0;
}
- tmslow |= SSB_GIGE_TMSLOW_DLLEN;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_core_ctl_flags(sdev, ~(SSB_GIGE_CORECTL_TXBYPASS |
+ SSB_GIGE_CORECTL_RXBYPASS), ctl);
ssb_set_drvdata(sdev, dev);
register_pci_controller(&dev->pci_controller);
--- linux-wireless-testing.orig/drivers/ssb/main.c 2011-02-17 14:16:39.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/main.c 2011-02-17 14:17:32.000000000 +0200
@@ -1165,6 +1165,7 @@ static void ssb_device_enable_sb(struct
u32 val;
ssb_device_disable(dev, core_specific_flags);
+ core_specific_flags <<= SSB_TMSLOW_FLAGS_SHIFT;
ssb_write32(dev, SSB_TMSLOW,
SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK |
SSB_TMSLOW_FGC | core_specific_flags);
@@ -1223,6 +1224,9 @@ static void ssb_device_disable_sb(struct
if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET)
return;
+ SSB_WARN_ON(core_specific_flags & 0xFFFF0000);
+
+ core_specific_flags <<= SSB_TMSLOW_FLAGS_SHIFT;
reject = ssb_tmslow_reject_bitmask(dev);
ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1);
@@ -1362,17 +1366,21 @@ static u32 ssb_admatch_size_sb(struct ss
static u32 ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask, u32 val)
{
- if (~mask || val) {
- u32 tmp = (ssb_read32(dev, SSB_TMSLOW) & mask) | val;
+ mask = ~mask;
+ SSB_WARN_ON((mask | val) & 0xFFFF0000);
+ if (mask || val) {
+ u32 tmp = (ssb_read32(dev, SSB_TMSLOW) &
+ ~(mask << SSB_TMSLOW_FLAGS_SHIFT)) |
+ (val << SSB_TMSLOW_FLAGS_SHIFT);
ssb_write32(dev, SSB_TMSLOW, tmp);
}
- return ssb_read32(dev, SSB_TMSLOW);
+ return ssb_read32(dev, SSB_TMSLOW) >> SSB_TMSLOW_FLAGS_SHIFT;
}
static u32 ssb_core_state_flags_sb(struct ssb_device *dev)
{
- return ssb_read32(dev, SSB_TMSHIGH);
+ return ssb_read32(dev, SSB_TMSHIGH) >> SSB_TMSHIGH_FLAGS_SHIFT;
}
const struct ssb_bus_helpers ssb_helpers_sb = {
--- linux-wireless-testing.orig/drivers/ssb/ssb_private.h 2011-02-17 14:05:12.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/ssb_private.h 2011-02-17 14:17:32.000000000 +0200
@@ -208,4 +208,28 @@ static inline void b43_pci_ssb_bridge_ex
extern const struct ssb_bus_helpers ssb_helpers_sb;
+/* SB-style bus core control and state registers */
+#define SSB_TMSLOW 0x0F98 /* SB Target State Low */
+#define SSB_TMSLOW_RESET 0x00000001 /* Reset */
+#define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */
+#define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */
+#define SSB_TMSLOW_PHYCLK 0x00000010 /* MAC PHY Clock Control Enable */
+#define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */
+#define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */
+#define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */
+#define SSB_TMSLOW_BE 0x80000000 /* BIST Enable */
+#define SSB_TMSLOW_FLAGS_SHIFT 16 /* Flags shift for TMSLOW
+ * register of SB-style buses */
+#define SSB_TMSHIGH 0x0F9C /* SB Target State High */
+#define SSB_TMSHIGH_SERR 0x00000001 /* S-error */
+#define SSB_TMSHIGH_INT 0x00000002 /* Interrupt */
+#define SSB_TMSHIGH_BUSY 0x00000004 /* Busy */
+#define SSB_TMSHIGH_TO 0x00000020 /* Timeout. Backplane rev >= 2.3 only */
+#define SSB_TMSHIGH_DMA64 0x10000000 /* 64bit DMA supported */
+#define SSB_TMSHIGH_GCR 0x20000000 /* Gated Clock Request */
+#define SSB_TMSHIGH_BISTF 0x40000000 /* BIST Failed */
+#define SSB_TMSHIGH_BISTD 0x80000000 /* BIST Done */
+#define SSB_TMSHIGH_FLAGS_SHIFT 16 /* Flags shift for TMSHIGH
+ * register of SB-style buses */
+
#endif /* LINUX_SSB_PRIVATE_H_ */
--- linux-wireless-testing.orig/drivers/usb/host/ohci-ssb.c 2011-02-17 14:02:39.000000000 +0200
+++ linux-wireless-testing/drivers/usb/host/ohci-ssb.c 2011-02-17 14:17:32.000000000 +0200
@@ -18,7 +18,7 @@
#include <linux/ssb/ssb.h>
-#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
+#define SSB_OHCI_CORECTL_HOSTMODE (1 << 13)
struct ssb_ohci_device {
struct ohci_hcd ohci; /* _must_ be at the beginning. */
@@ -115,7 +115,7 @@ static int ssb_ohci_attach(struct ssb_de
if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
/* Put the device into host-mode. */
- flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+ flags |= SSB_OHCI_CORECTL_HOSTMODE;
ssb_device_enable(dev, flags);
} else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
u32 tmp;
--- linux-wireless-testing.orig/include/linux/ssb/ssb_driver_gige.h 2011-02-08 00:22:50.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb_driver_gige.h 2011-02-17 14:17:32.000000000 +0200
@@ -19,12 +19,12 @@
#define SSB_GIGE_SHIM_MAOCPSI 0x0C10 /* PCI to OCP: MaocpSI Control (32bit) */
#define SSB_GIGE_SHIM_SIOCPMA 0x0C14 /* PCI to OCP: SiocpMa Control (32bit) */
-/* TM Status High flags */
-#define SSB_GIGE_TMSHIGH_RGMII 0x00010000 /* Have an RGMII PHY-bus */
-/* TM Status Low flags */
-#define SSB_GIGE_TMSLOW_TXBYPASS 0x00080000 /* TX bypass (no delay) */
-#define SSB_GIGE_TMSLOW_RXBYPASS 0x00100000 /* RX bypass (no delay) */
-#define SSB_GIGE_TMSLOW_DLLEN 0x01000000 /* Enable DLL controls */
+/* Gige core control flags */
+#define SSB_GIGE_CORESTAT_RGMII 0x0001 /* Have an RGMII PHY-bus */
+/* Gige core status flags */
+#define SSB_GIGE_CORECTL_TXBYPASS 0x0008 /* TX bypass (no delay) */
+#define SSB_GIGE_CORECTL_RXBYPASS 0x0010 /* RX bypass (no delay) */
+#define SSB_GIGE_CORECTL_DLLEN 0x0100 /* Enable DLL controls */
/* Boardflags (low) */
#define SSB_GIGE_BFL_ROBOSWITCH 0x0010
--- linux-wireless-testing.orig/include/linux/ssb/ssb.h 2011-02-17 14:16:39.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb.h 2011-02-17 14:17:32.000000000 +0200
@@ -432,14 +432,14 @@ static inline int ssb_device_is_enabled(
{
return dev->helpers->device_is_enabled(dev);
}
-/* Enable a device and pass device-specific SSB_TMSLOW flags.
+/* Enable a device and pass device-specific SSB_CORECTL flags.
* If no device-specific flags are available, use 0. */
static inline void ssb_device_enable(struct ssb_device *dev,
u32 core_specific_flags)
{
return dev->helpers->device_enable(dev, core_specific_flags);
}
-/* Disable a device in hardware and pass SSB_TMSLOW flags (if any). */
+/* Disable a device in hardware and pass SSB_CORECTL flags (if any). */
static inline void ssb_device_disable(struct ssb_device *dev,
u32 core_specific_flags)
{
--- linux-wireless-testing.orig/include/linux/ssb/ssb_regs.h 2011-02-17 13:49:24.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb_regs.h 2011-02-17 14:17:32.000000000 +0200
@@ -58,6 +58,24 @@
#define SSB_BAR0_MAX_RETRIES 50
+/* AI/SB independent core control and status flags for use with
+ * core_ctl_flags, core_state_flags, device_enable, device_disable
+ * ssb device helpers.
+ * Use instead of core-dependant SSB_TMSLO_xx and SSB_TMSHIGH_xx defines
+ */
+/* SSB SB TMSLOW/SSB AI IOCTL */
+#define SSB_CORECTL_CLOCK 0x0001 /* Clock Enable */
+#define SSB_CORECTL_FGC 0x0002 /* Force Gated Clocks On */
+#define SSB_CORECTL_PE 0x4000 /* Power Management Enable */
+#define SSB_CORECTL_BE 0x8000 /* BIST Enable */
+#define SSB_CORECTL_CORE_BITS 0x3FFC /* Core-specific flags mask */
+/* SSB SB TMSHIGH/SSB AI IOSTAT */
+#define SSB_CORESTAT_DMA64 0x1000 /* 64-bit DMA engine */
+#define SSB_CORESTAT_GCR 0x2000 /* Gated Clock Request */
+#define SSB_CORESTAT_BISTF 0x4000 /* BIST Failed */
+#define SSB_CORESTAT_BISTD 0x8000 /* BIST Done */
+#define SSB_CORESTAT_CORE_BITS 0x0FFF /* Core-specific flags mask */
+
/* Silicon backplane configuration register definitions */
#define SSB_IPSFLAG 0x0F08
#define SSB_IPSFLAG_IRQ1 0x0000003F /* which sbflags get routed to mips interrupt 1 */
@@ -93,26 +111,10 @@
#define SSB_INTVEC_USB 0x00000010 /* Enable interrupts for usb */
#define SSB_INTVEC_EXTIF 0x00000020 /* Enable interrupts for external i/f */
#define SSB_INTVEC_ENET1 0x00000040 /* Enable interrupts for enet 1 */
-#define SSB_TMSLOW 0x0F98 /* SB Target State Low */
-#define SSB_TMSLOW_RESET 0x00000001 /* Reset */
-#define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */
-#define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */
-#define SSB_TMSLOW_PHYCLK 0x00000010 /* MAC PHY Clock Control Enable */
-#define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */
-#define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */
-#define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */
-#define SSB_TMSLOW_BE 0x80000000 /* BIST Enable */
-#define SSB_TMSHIGH 0x0F9C /* SB Target State High */
-#define SSB_TMSHIGH_SERR 0x00000001 /* S-error */
-#define SSB_TMSHIGH_INT 0x00000002 /* Interrupt */
-#define SSB_TMSHIGH_BUSY 0x00000004 /* Busy */
-#define SSB_TMSHIGH_TO 0x00000020 /* Timeout. Backplane rev >= 2.3 only */
-#define SSB_TMSHIGH_COREFL 0x1FFF0000 /* Core specific flags */
-#define SSB_TMSHIGH_COREFL_SHIFT 16
-#define SSB_TMSHIGH_DMA64 0x10000000 /* 64bit DMA supported */
-#define SSB_TMSHIGH_GCR 0x20000000 /* Gated Clock Request */
-#define SSB_TMSHIGH_BISTF 0x40000000 /* BIST Failed */
-#define SSB_TMSHIGH_BISTD 0x80000000 /* BIST Done */
+/*
+ * SSB_TMSLOW and SSB_TMSHIGH registers' definitions moved out to ssb_private.h
+ * use SSB_CORECTL, SSB_CORESTAT or own core-specific flags' defines instead.
+ */
#define SSB_BWA0 0x0FA0
#define SSB_IMCFGLO 0x0FA8
#define SSB_IMCFGLO_SERTO 0x00000007 /* Service timeout */
Hi,
> I should probably note that in my opinion ssb_bus is not the right place
> to put ops that are supposed to abstract the SSB bus, too. ;)
> _No_ SSB structure is the right place to put an ops pointer that is
> supposed to abstract the SSB bus.
Well, can't put it over ssb_bus struct yet :)
Have nice day,
George
On Sat, 2011-02-19 at 01:15 +0200, George Kashperko wrote:
> > On Fri, 2011-02-18 at 00:08 +0200, George Kashperko wrote:
> > > const struct ssb_bus_ops *ops;
> > > + const struct ssb_bus_helpers *helpers;
> >
> > Uhm, well. "helpers"... . Seems like a pretty generic term.
> >
> > I think this is still violating abstraction layering. Not as much
> > as your previous attempt, but still...
> >
> > You're putting the ops structure that is supposed to abstract
> > the ssb bus into the ssb_device data structure. That should ring a bell.
> >
> Reconsidered it already while arranging patches for Openwrt (the reason
> helpers were in device struct was to speedup access but these aint
> called often therefore they are in ssb_bus now). Also moved
I should probably note that in my opinion ssb_bus is not the right place
to put ops that are supposed to abstract the SSB bus, too. ;)
_No_ SSB structure is the right place to put an ops pointer that is
supposed to abstract the SSB bus.
--
Greetings Michael.
Hi,
> There are plenty of examples in the kernel where code was simply forked
> for the development of a new technology. Look at b43/b43legacy or
> ext2/3/4 just for a few examples. The forks were made on purpose
> to avoid maintainability nightmares. Yes, at first sight, some code had
> to be duplicated. But I don't see that as an issue. The two codebases
> will diverge quickly from each other as development is done.
Does this mean RFC subject in its current state is rejected ?
> So I'm supporting Henry in that SSB is legacy and EOL. Let's simply
> start over and don't carry old cruft over.
>
> Note that this does not mean that we need to duplicate the MIPS,
> common and probably pci core drivers. A hybrid module can be done,
> if that's desired to avoid code duplication.
Well, any plans or even maybe ETA on this ?
> And I also think that you're worrying _way_ too much about a few
> if/else statements in the drivers. (Look at the TMSLOW discussion).
> The SSB/AI->driver interface is trivial and tiny. There will be maybe
> 10 if/else statements. It's really _not_ worth introducing major
> abstraction code in the SSB and AI code to avoid a few if/else
> statements in the drivers.
> The bulk of the SSB->driver interface _is_ already abstracted inside
> of the drivers (b43_read/write...). The rest is negligible.
Well, not like I really worry alot about those if/elses :)
Just in this particular case of SSB in its current design I don't really
see much differences in where bus implementation-specific management
must be abstracted if only AI support over SSB is implemented. If there
will be just b43 relying on such an abstraction then no doubt lets do it
in b43 driver. But its not.
> And if it turns out _afterwards_ that we could avoid a few if/else
> statements by introducing some additional abstraction layer, this
> thing can be introduced _afterwards_.
Almost exactly what I thought working on AI over SSB.
> PS: Could you please stop stripping the CC list.
>
Sorry for that.
Have nice day,
George
On Fri, 2011-02-18 at 14:39 +0200, George Kashperko wrote:
> Does this mean RFC subject in its current state is rejected ?
I am not in charge to reject anything.
But I just noticed that you sent the patches to the list. So I'll
have a look at it. You should improve your CC lists in general
for all your mails. Most of us don't have the time to read all
mail on the list, so it's always a good idea to maintain a CC list
of people who already commented on the RFC for patch submissions.
> > So I'm supporting Henry in that SSB is legacy and EOL. Let's simply
> > start over and don't carry old cruft over.
> >
> > Note that this does not mean that we need to duplicate the MIPS,
> > common and probably pci core drivers. A hybrid module can be done,
> > if that's desired to avoid code duplication.
> Well, any plans or even maybe ETA on this ?
No.
> > And I also think that you're worrying _way_ too much about a few
> > if/else statements in the drivers. (Look at the TMSLOW discussion).
> > The SSB/AI->driver interface is trivial and tiny. There will be maybe
> > 10 if/else statements. It's really _not_ worth introducing major
> > abstraction code in the SSB and AI code to avoid a few if/else
> > statements in the drivers.
> > The bulk of the SSB->driver interface _is_ already abstracted inside
> > of the drivers (b43_read/write...). The rest is negligible.
> Well, not like I really worry alot about those if/elses :)
> Just in this particular case of SSB in its current design I don't really
> see much differences in where bus implementation-specific management
> must be abstracted if only AI support over SSB is implemented. If there
> will be just b43 relying on such an abstraction then no doubt lets do it
> in b43 driver. But its not.
You should also look into the future.
I don't know what broadcom's plans are, but a rough guess would be
that AI will diverge more and more from SSB, so that more and more
hacks will be needed.
So I'm in favor of making a clean cut.
--
Greetings Michael.
Hi,
> This just reinforces what Michael said about name confusion.
>
> Michael's proposal of separating SSB and AXI, and decoupling the device
> drivers from the bus routines, is going to be much more maintainable in
> the long run. AXI is going to be far more widespread than SSB ever was,
> and it would be really unfortunate if we carry the SSB baggage forward.
>
> I've been poking around at disentangling the sb and ai routines in
> drivers/staging/brcm80211/utils/{aiutils,sbutils,siutils}.c. I don't
> have anything to put out for comments yet, but it's enough to convince
> me that it's the right direction.
>
> - Henry
>
Yes, in long run the best might be is to move core management layer out
of SSB, lighten it leaving just bus-management code, then intdroduce AI
bus and might UBUS as well at some point (btw any tips from Broadcom
when we could see it implemented in HW ?). To make life bits easier
there could be some basic bus-level lib as plenty of shared things
between there 2 (or 3?) buses. E. g. let these buses share some common
(de)initialization, identification, parts of core switching code. Let
core-management code exist under any of these buses independently of the
parent bus implementation...
With such approach device (de)initialization, sub-core addressing,
state/control management could be done in dedicated bus-specific
routines or with some common-interface routines abstracting
bus-implementation specific registers management with means of dedicated
ops/helers (whatever it called). First approach in long run will make
drivers to abstract this bus-specific management under some dedicated
routines with if/else's or fn tables. Second approach is generally the
same as already there in AI patches (and again the same as it will be in
dedicated cores drivers' code with first way but replicated for those
cores drivers' who exist on both SSB and AI like it is now for mips,
pcie, w11, etc.).
Yes, AI, lets say, over SBB, makes some confusion and this confusion
could be avoided with separate SSB/AI bus drivers but in current SSB
design state its 99% of copy-pasting SSB code with changing nothing
other than &ops pointers and ssb_ prefixes with something like bcmai_ or
similar which honestly makes no sense to me considering than the goal is
to <avoid confusion>. Pretty much sure there will be even more confusion
than before.
It could take some time to get separate-bus confuse-less design clean
and working, whereas AI-hw not being supported more than year since
introduction will keep unsupported another +- half a year. Well this
isn't actually a problem as well as I dont see a problem with doing that
with making AI support introduced with SSB layer in way I proposed.
Making AI supported with SSB code base doesn't close the way in evolving
SSB and AI code in either direction, isn't it ? Also there is
opportunity offered by Broadcom (see post by Roland Vossen earlier in
the thread) - we could have Broadcom-supplied AI lib module not to touch
SSB code at all but this might will require plenty of bus-abstraction in
b43 and will do hard time for newer AI-based embedabbles, but those aint
supported with newer kernels anyway.
I could get working on separated SSB/AI code in approx mid. march
(unfortunately too short on time till that cause of current work
schedule) if there will be no volunteers or we could work on that
together.
Have nice day,
George
Hi,
> On 02/18/2011 05:47 PM, George Kashperko wrote:
> > Hi,
> >
> >> I don't want to get involved in the debate over abstraction, but FWIW, the
> >> patchset does work for PCI-based SSB devices.
> >>
> >> Larry
> >>
> > Could you please let me know if you tried last code I've posted, as my
> > original RFC was indeed embeddables' targeted and won't work for
> > SSB-over-PCI.
> > Last code I've posted I've tested on SSB over PCIE host and it was
> > pretty much working.
>
> I tested the 14 patches you posted on 2/17/2011 that arrived about 10:20 UTC.
>
> Larry
>
Ohh, I skrewed again -.-
Donno how but I decided It didn't work for you. I'm too much sleepy, but
can't go sleep till coffee let me off. Sorry.
Have nice day,
George
From: George Kashperko <[email protected]>
Move SB-specific code to separate file.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/Kconfig | 11 +
drivers/ssb/Makefile | 1
drivers/ssb/driver_mipscore.c | 11 -
drivers/ssb/main.c | 188 --------------------
drivers/ssb/scan.c | 74 --------
drivers/ssb/ssb_private.h | 32 ---
drivers/ssb/ssb_sb.c | 289 ++++++++++++++++++++++++++++++++
drivers/ssb/ssb_sb.h | 52 +++++
8 files changed, 361 insertions(+), 297 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/driver_mipscore.c 2011-02-17 16:00:21.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/driver_mipscore.c 2011-02-17 15:55:25.000000000 +0200
@@ -52,16 +52,6 @@ static inline u32 ssb_irqflag(struct ssb
return dev->bus->mipscore.irqflag(dev);
}
-static u32 ssb_irqflag_sb(struct ssb_device *dev)
-{
- u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
- if (tpsflag && tpsflag != SSB_TPSFLAG_BPFLAG)
- return tpsflag;
- else
- /* not irq supported */
- return -1;
-}
-
static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag)
{
struct ssb_bus *bus = rdev->bus;
@@ -246,7 +236,6 @@ void ssb_mipscore_init(struct ssb_mipsco
ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
bus = mcore->dev->bus;
- bus->mipscore.irqflag = ssb_irqflag_sb;
hz = ssb_clockspeed(bus);
if (!hz)
hz = 100000000;
--- linux-wireless-testing.orig/drivers/ssb/Kconfig 2011-02-17 16:00:21.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/Kconfig 2011-02-17 16:00:43.000000000 +0200
@@ -9,6 +9,7 @@ menu "Sonics Silicon Backplane"
config SSB
tristate "Sonics Silicon Backplane support"
depends on SSB_POSSIBLE
+ select SSB_BUS_SB
help
Support for the Sonics Silicon Backplane bus.
You only need to enable this option, if you are
@@ -21,6 +22,16 @@ config SSB
If unsure, say N.
+config SSB_BUS_SB_POSSIBLE
+ bool
+ default y if SSB
+
+config SSB_BUS_SB
+ bool "SB style bus"
+ depends on SSB_BUS_SB_POSSIBLE
+ help
+ Sonics Silicon Backplane SB-style bus
+
# Common SPROM support routines
config SSB_SPROM
bool
--- linux-wireless-testing.orig/drivers/ssb/main.c 2011-02-17 16:00:21.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/main.c 2011-02-17 16:00:43.000000000 +0200
@@ -1129,88 +1129,10 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
}
EXPORT_SYMBOL(ssb_clockspeed);
-static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)
-{
- u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV;
-
- /* The REJECT bit changed position in TMSLOW between
- * Backplane revisions. */
- switch (rev) {
- case SSB_IDLOW_SSBREV_22:
- return SSB_TMSLOW_REJECT_22;
- case SSB_IDLOW_SSBREV_23:
- return SSB_TMSLOW_REJECT_23;
- case SSB_IDLOW_SSBREV_24: /* TODO - find the proper REJECT bits */
- case SSB_IDLOW_SSBREV_25: /* same here */
- case SSB_IDLOW_SSBREV_26: /* same here */
- case SSB_IDLOW_SSBREV_27: /* same here */
- return SSB_TMSLOW_REJECT_23; /* this is a guess */
- default:
- printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
- WARN_ON(1);
- }
- return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23);
-}
-
-static int ssb_device_is_enabled_sb(struct ssb_device *dev)
-{
- u32 val;
- u32 reject;
-
- reject = ssb_tmslow_reject_bitmask(dev);
- val = ssb_read32(dev, SSB_TMSLOW);
- val &= SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET | reject;
-
- return (val == SSB_TMSLOW_CLOCK);
-}
-
-static void ssb_flush_tmslow(struct ssb_device *dev)
-{
- /* Make _really_ sure the device has finished the TMSLOW
- * register write transaction, as we risk running into
- * a machine check exception otherwise.
- * Do this by reading the register back to commit the
- * PCI write and delay an additional usec for the device
- * to react to the change. */
- ssb_read32(dev, SSB_TMSLOW);
- udelay(1);
-}
-
-static void ssb_device_enable_sb(struct ssb_device *dev, u32 core_specific_flags)
-{
- u32 val;
-
- ssb_device_disable(dev, core_specific_flags);
- core_specific_flags <<= SSB_TMSLOW_FLAGS_SHIFT;
- ssb_write32(dev, SSB_TMSLOW,
- SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK |
- SSB_TMSLOW_FGC | core_specific_flags);
- ssb_flush_tmslow(dev);
-
- /* Clear SERR if set. This is a hw bug workaround. */
- if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_SERR)
- ssb_write32(dev, SSB_TMSHIGH, 0);
-
- val = ssb_read32(dev, SSB_IMSTATE);
- if (val & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {
- val &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);
- ssb_write32(dev, SSB_IMSTATE, val);
- }
-
- ssb_write32(dev, SSB_TMSLOW,
- SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC |
- core_specific_flags);
- ssb_flush_tmslow(dev);
-
- ssb_write32(dev, SSB_TMSLOW, SSB_TMSLOW_CLOCK |
- core_specific_flags);
- ssb_flush_tmslow(dev);
-}
-
/* Wait for a bit in a register to get set or unset.
* timeout is in units of ten-microseconds */
-static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
- int timeout, int set)
+int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
+ int timeout, int set)
{
int i;
u32 val;
@@ -1233,32 +1155,6 @@ static int ssb_wait_bit(struct ssb_devic
return -ETIMEDOUT;
}
-static void ssb_device_disable_sb(struct ssb_device *dev, u32 core_specific_flags)
-{
- u32 reject;
-
- if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET)
- return;
-
- SSB_WARN_ON(core_specific_flags & 0xFFFF0000);
-
- core_specific_flags <<= SSB_TMSLOW_FLAGS_SHIFT;
- reject = ssb_tmslow_reject_bitmask(dev);
- ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
- ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1);
- ssb_wait_bit(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
- ssb_write32(dev, SSB_TMSLOW,
- SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
- reject | SSB_TMSLOW_RESET |
- core_specific_flags);
- ssb_flush_tmslow(dev);
-
- ssb_write32(dev, SSB_TMSLOW,
- reject | SSB_TMSLOW_RESET |
- core_specific_flags);
- ssb_flush_tmslow(dev);
-}
-
u32 ssb_dma_translation(struct ssb_device *dev)
{
switch (dev->bus->bustype) {
@@ -1329,86 +1225,6 @@ error:
}
EXPORT_SYMBOL(ssb_bus_powerup);
-static u32 ssb_admatch_base_sb(struct ssb_device *dev, u32 adm)
-{
- u32 base = 0;
-
- adm = ssb_read32(dev, adm);
-
- switch (adm & SSB_ADM_TYPE) {
- case SSB_ADM_TYPE0:
- base = (adm & SSB_ADM_BASE0);
- break;
- case SSB_ADM_TYPE1:
- SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
- base = (adm & SSB_ADM_BASE1);
- break;
- case SSB_ADM_TYPE2:
- SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
- base = (adm & SSB_ADM_BASE2);
- break;
- default:
- SSB_WARN_ON(1);
- }
-
- return base;
-}
-
-static u32 ssb_admatch_size_sb(struct ssb_device *dev, u32 adm)
-{
- u32 size = 0;
-
- adm = ssb_read32(dev, adm);
-
- switch (adm & SSB_ADM_TYPE) {
- case SSB_ADM_TYPE0:
- size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT);
- break;
- case SSB_ADM_TYPE1:
- SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
- size = ((adm & SSB_ADM_SZ1) >> SSB_ADM_SZ1_SHIFT);
- break;
- case SSB_ADM_TYPE2:
- SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
- size = ((adm & SSB_ADM_SZ2) >> SSB_ADM_SZ2_SHIFT);
- break;
- default:
- SSB_WARN_ON(1);
- }
- size = (1 << (size + 1));
-
- return size;
-}
-
-static u32 ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask, u32 val)
-{
- mask = ~mask;
- SSB_WARN_ON((mask | val) & 0xFFFF0000);
- if (mask || val) {
- u32 tmp = (ssb_read32(dev, SSB_TMSLOW) &
- ~(mask << SSB_TMSLOW_FLAGS_SHIFT)) |
- (val << SSB_TMSLOW_FLAGS_SHIFT);
- ssb_write32(dev, SSB_TMSLOW, tmp);
- }
-
- return ssb_read32(dev, SSB_TMSLOW) >> SSB_TMSLOW_FLAGS_SHIFT;
-}
-
-static u32 ssb_core_state_flags_sb(struct ssb_device *dev)
-{
- return ssb_read32(dev, SSB_TMSHIGH) >> SSB_TMSHIGH_FLAGS_SHIFT;
-}
-
-const struct ssb_bus_helpers ssb_helpers_sb = {
- .device_is_enabled = ssb_device_is_enabled_sb,
- .device_enable = ssb_device_enable_sb,
- .device_disable = ssb_device_disable_sb,
- .admatch_base = ssb_admatch_base_sb,
- .admatch_size = ssb_admatch_size_sb,
- .core_ctl_flags = ssb_core_ctl_flags_sb,
- .core_state_flags = ssb_core_state_flags_sb,
-};
-
static int __init ssb_modinit(void)
{
int err;
--- linux-wireless-testing.orig/drivers/ssb/Makefile 2011-02-17 16:00:21.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/Makefile 2011-02-17 16:00:43.000000000 +0200
@@ -1,5 +1,6 @@
# core
ssb-y += main.o scan.o
+ssb-$(CONFIG_SSB_BUS_SB) += ssb_sb.o
ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o
ssb-$(CONFIG_SSB_SPROM) += sprom.o
--- linux-wireless-testing.orig/drivers/ssb/scan.c 2011-02-17 16:00:21.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 16:00:47.000000000 +0200
@@ -157,8 +157,7 @@ static u8 chipid_to_nrcores(u16 chipid)
return 1;
}
-static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx,
- u16 offset)
+u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, u16 offset)
{
u32 lo, hi;
@@ -184,42 +183,6 @@ static u32 scan_read32(struct ssb_bus *b
return readl(bus->mmio + offset);
}
-static int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
-{
- switch (bus->bustype) {
- case SSB_BUSTYPE_SSB:
- break;
- case SSB_BUSTYPE_PCI:
- return ssb_pci_switch_coreidx(bus, coreidx);
- case SSB_BUSTYPE_PCMCIA:
- return ssb_pcmcia_switch_coreidx(bus, coreidx);
- case SSB_BUSTYPE_SDIO:
- return ssb_sdio_scan_switch_coreidx(bus, coreidx);
- }
- return 0;
-}
-
-void ssb_iounmap_sb(struct ssb_bus *bus)
-{
- switch (bus->bustype) {
- case SSB_BUSTYPE_SSB:
- case SSB_BUSTYPE_PCMCIA:
- iounmap(bus->mmio);
- break;
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- pci_iounmap(bus->host_pci, bus->mmio);
-#else
- SSB_BUG_ON(1); /* Can't reach this code. */
-#endif
- break;
- case SSB_BUSTYPE_SDIO:
- break;
- }
- bus->mmio = NULL;
- bus->mapped_device = NULL;
-}
-
static void __iomem *ssb_ioremap(struct ssb_bus *bus,
unsigned long baseaddr)
{
@@ -407,41 +370,6 @@ static int ssb_bus_detect(struct ssb_bus
return chiptype == SSB_CHIPCO_SB ? 0 : -ENODEV;
}
-static int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr)
-{
- u32 idhi;
- int dev_i, i;
- struct ssb_device *dev;
- int nr_80211_cores = 0;
- int err;
-
- /* Fetch basic information about each core/device */
- for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
- err = scan_switchcore(bus, i);
- if (err)
- return err;
- dev = &(bus->devices[dev_i]);
-
- idhi = scan_read32(bus, i, SSB_IDHIGH);
- dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
- dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
- dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >>
- SSB_IDHIGH_RCHI_SHIFT;
- dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
- dev->core_index = i;
- dev->bus = bus;
- dev->ops = bus->ops;
- dev->helpers = &ssb_helpers_sb;
-
- if (ssb_bus_check_core(dev, &nr_80211_cores, i) < 0)
- continue;
-
- dev_i++;
- }
- bus->nr_devices = dev_i;
- return 0;
-}
-
int ssb_bus_scan(struct ssb_bus *bus, unsigned long baseaddr)
{
int err = -ENOMEM;
--- linux-wireless-testing.orig/drivers/ssb/ssb_private.h 2011-02-17 16:00:21.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/ssb_private.h 2011-02-17 16:00:43.000000000 +0200
@@ -3,6 +3,7 @@
#include <linux/ssb/ssb.h>
#include <linux/types.h>
+#include "ssb_sb.h"
#define PFX "ssb: "
@@ -29,6 +30,9 @@ static inline int __ssb_do_nothing(int x
# define SSB_BUG_ON(x) __ssb_do_nothing(unlikely(!!(x)))
#endif
+/* main.c */
+extern int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
+ int timeout, int set);
/* pci.c */
#ifdef CONFIG_SSB_PCIHOST
@@ -159,9 +163,9 @@ static inline int ssb_sdio_init(struct s
extern const char *ssb_core_name(u16 coreid);
extern int ssb_bus_scan(struct ssb_bus *bus,
unsigned long baseaddr);
-extern void ssb_iounmap_sb(struct ssb_bus *bus);
extern int ssb_bus_check_core(struct ssb_device *dev, int *nr_80211_cores,
int corenum);
+extern u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, u16 offset);
static inline void ssb_iounmap(struct ssb_bus *bus)
{
ssb_iounmap_sb(bus);
@@ -212,30 +216,4 @@ static inline void b43_pci_ssb_bridge_ex
}
#endif /* CONFIG_SSB_B43_PCI_BRIDGE */
-extern const struct ssb_bus_helpers ssb_helpers_sb;
-
-/* SB-style bus core control and state registers */
-#define SSB_TMSLOW 0x0F98 /* SB Target State Low */
-#define SSB_TMSLOW_RESET 0x00000001 /* Reset */
-#define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */
-#define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */
-#define SSB_TMSLOW_PHYCLK 0x00000010 /* MAC PHY Clock Control Enable */
-#define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */
-#define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */
-#define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */
-#define SSB_TMSLOW_BE 0x80000000 /* BIST Enable */
-#define SSB_TMSLOW_FLAGS_SHIFT 16 /* Flags shift for TMSLOW
- * register of SB-style buses */
-#define SSB_TMSHIGH 0x0F9C /* SB Target State High */
-#define SSB_TMSHIGH_SERR 0x00000001 /* S-error */
-#define SSB_TMSHIGH_INT 0x00000002 /* Interrupt */
-#define SSB_TMSHIGH_BUSY 0x00000004 /* Busy */
-#define SSB_TMSHIGH_TO 0x00000020 /* Timeout. Backplane rev >= 2.3 only */
-#define SSB_TMSHIGH_DMA64 0x10000000 /* 64bit DMA supported */
-#define SSB_TMSHIGH_GCR 0x20000000 /* Gated Clock Request */
-#define SSB_TMSHIGH_BISTF 0x40000000 /* BIST Failed */
-#define SSB_TMSHIGH_BISTD 0x80000000 /* BIST Done */
-#define SSB_TMSHIGH_FLAGS_SHIFT 16 /* Flags shift for TMSHIGH
- * register of SB-style buses */
-
#endif /* LINUX_SSB_PRIVATE_H_ */
--- linux-wireless-testing.orig/drivers/ssb/ssb_sb.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-wireless-testing/drivers/ssb/ssb_sb.c 2011-02-17 16:01:30.000000000 +0200
@@ -0,0 +1,289 @@
+/*
+ * Sonics Silicon Backplane
+ * SB-specific Subsystem core
+ *
+ * Copyright 2005, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <[email protected]>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/ssb/ssb.h>
+#include <linux/delay.h>
+
+#include "ssb_private.h"
+
+
+static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)
+{
+ u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV;
+
+ /* The REJECT bit changed position in TMSLOW between
+ * Backplane revisions. */
+ switch (rev) {
+ case SSB_IDLOW_SSBREV_22:
+ return SSB_TMSLOW_REJECT_22;
+ case SSB_IDLOW_SSBREV_23:
+ return SSB_TMSLOW_REJECT_23;
+ case SSB_IDLOW_SSBREV_24: /* TODO - find the proper REJECT bits */
+ case SSB_IDLOW_SSBREV_25: /* same here */
+ case SSB_IDLOW_SSBREV_26: /* same here */
+ case SSB_IDLOW_SSBREV_27: /* same here */
+ return SSB_TMSLOW_REJECT_23; /* this is a guess */
+ default:
+ printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
+ WARN_ON(1);
+ }
+ return SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23;
+}
+
+static int ssb_device_is_enabled_sb(struct ssb_device *dev)
+{
+ u32 val;
+ u32 reject;
+
+ reject = ssb_tmslow_reject_bitmask(dev);
+ val = ssb_read32(dev, SSB_TMSLOW);
+ val &= SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET | reject;
+
+ return (val == SSB_TMSLOW_CLOCK);
+}
+
+static void ssb_flush_tmslow(struct ssb_device *dev)
+{
+ /* Make _really_ sure the device has finished the TMSLOW
+ * register write transaction, as we risk running into
+ * a machine check exception otherwise.
+ * Do this by reading the register back to commit the
+ * PCI write and delay an additional usec for the device
+ * to react to the change. */
+ ssb_read32(dev, SSB_TMSLOW);
+ udelay(1);
+}
+
+static void ssb_device_disable_sb(struct ssb_device *dev,
+ u32 core_specific_flags)
+{
+ u32 reject;
+
+ if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET)
+ return;
+
+ SSB_WARN_ON(core_specific_flags & 0xFFFF0000);
+
+ core_specific_flags <<= SSB_TMSLOW_FLAGS_SHIFT;
+ reject = ssb_tmslow_reject_bitmask(dev);
+ ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
+ ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1);
+ ssb_wait_bit(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
+ ssb_write32(dev, SSB_TMSLOW,
+ SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
+ reject | SSB_TMSLOW_RESET |
+ core_specific_flags);
+ ssb_flush_tmslow(dev);
+
+ ssb_write32(dev, SSB_TMSLOW,
+ reject | SSB_TMSLOW_RESET |
+ core_specific_flags);
+ ssb_flush_tmslow(dev);
+}
+
+
+static void ssb_device_enable_sb(struct ssb_device *dev,
+ u32 core_specific_flags)
+{
+ u32 val;
+
+ ssb_device_disable_sb(dev, core_specific_flags);
+ core_specific_flags <<= SSB_TMSLOW_FLAGS_SHIFT;
+ ssb_write32(dev, SSB_TMSLOW,
+ SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK |
+ SSB_TMSLOW_FGC | core_specific_flags);
+ ssb_flush_tmslow(dev);
+
+ /* Clear SERR if set. This is a hw bug workaround. */
+ if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_SERR)
+ ssb_write32(dev, SSB_TMSHIGH, 0);
+
+ val = ssb_read32(dev, SSB_IMSTATE);
+ if (val & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {
+ val &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);
+ ssb_write32(dev, SSB_IMSTATE, val);
+ }
+
+ ssb_write32(dev, SSB_TMSLOW,
+ SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC |
+ core_specific_flags);
+ ssb_flush_tmslow(dev);
+
+ ssb_write32(dev, SSB_TMSLOW, SSB_TMSLOW_CLOCK |
+ core_specific_flags);
+ ssb_flush_tmslow(dev);
+}
+
+static u32 ssb_admatch_base_sb(struct ssb_device *dev, u32 adm)
+{
+ u32 base = 0;
+
+ adm = ssb_read32(dev, adm);
+
+ switch (adm & SSB_ADM_TYPE) {
+ case SSB_ADM_TYPE0:
+ base = (adm & SSB_ADM_BASE0);
+ break;
+ case SSB_ADM_TYPE1:
+ SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
+ base = (adm & SSB_ADM_BASE1);
+ break;
+ case SSB_ADM_TYPE2:
+ SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
+ base = (adm & SSB_ADM_BASE2);
+ break;
+ default:
+ SSB_WARN_ON(1);
+ }
+
+ return base;
+}
+
+static u32 ssb_admatch_size_sb(struct ssb_device *dev, u32 adm)
+{
+ u32 size = 0;
+
+ adm = ssb_read32(dev, adm);
+
+ switch (adm & SSB_ADM_TYPE) {
+ case SSB_ADM_TYPE0:
+ size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT);
+ break;
+ case SSB_ADM_TYPE1:
+ SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
+ size = ((adm & SSB_ADM_SZ1) >> SSB_ADM_SZ1_SHIFT);
+ break;
+ case SSB_ADM_TYPE2:
+ SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
+ size = ((adm & SSB_ADM_SZ2) >> SSB_ADM_SZ2_SHIFT);
+ break;
+ default:
+ SSB_WARN_ON(1);
+ }
+ size = (1 << (size + 1));
+
+ return size;
+}
+
+static u32 ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask, u32 val)
+{
+ mask = ~mask;
+ SSB_WARN_ON((mask | val) & 0xFFFF0000);
+ if (mask || val) {
+ u32 tmp = (ssb_read32(dev, SSB_TMSLOW) &
+ ~(mask << SSB_TMSLOW_FLAGS_SHIFT)) |
+ (val << SSB_TMSLOW_FLAGS_SHIFT);
+ ssb_write32(dev, SSB_TMSLOW, tmp);
+ }
+
+ return ssb_read32(dev, SSB_TMSLOW) >> SSB_TMSLOW_FLAGS_SHIFT;
+}
+
+static u32 ssb_core_state_flags_sb(struct ssb_device *dev)
+{
+ return ssb_read32(dev, SSB_TMSHIGH) >> SSB_TMSHIGH_FLAGS_SHIFT;
+}
+
+const struct ssb_bus_helpers ssb_helpers_sb = {
+ .device_is_enabled = ssb_device_is_enabled_sb,
+ .device_enable = ssb_device_enable_sb,
+ .device_disable = ssb_device_disable_sb,
+ .admatch_base = ssb_admatch_base_sb,
+ .admatch_size = ssb_admatch_size_sb,
+ .core_ctl_flags = ssb_core_ctl_flags_sb,
+ .core_state_flags = ssb_core_state_flags_sb,
+};
+
+#ifdef CONFIG_SSB_DRIVER_MIPS
+static u32 ssb_irqflag_sb(struct ssb_device *dev)
+{
+ u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+ if (tpsflag && tpsflag != SSB_TPSFLAG_BPFLAG)
+ return tpsflag;
+ else
+ /* not irq supported */
+ return -1;
+}
+#endif /* CONFIG_SSB_DRIVER_MIPS */
+
+int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
+{
+ switch (bus->bustype) {
+ case SSB_BUSTYPE_SSB:
+ break;
+ case SSB_BUSTYPE_PCI:
+ return ssb_pci_switch_coreidx(bus, coreidx);
+ case SSB_BUSTYPE_PCMCIA:
+ return ssb_pcmcia_switch_coreidx(bus, coreidx);
+ case SSB_BUSTYPE_SDIO:
+ return ssb_sdio_scan_switch_coreidx(bus, coreidx);
+ }
+ return 0;
+}
+
+void ssb_iounmap_sb(struct ssb_bus *bus)
+{
+ switch (bus->bustype) {
+ case SSB_BUSTYPE_SSB:
+ case SSB_BUSTYPE_PCMCIA:
+ iounmap(bus->mmio);
+ break;
+#ifdef CONFIG_SSB_PCIHOST
+ case SSB_BUSTYPE_PCI:
+ pci_iounmap(bus->host_pci, bus->mmio);
+#else
+ SSB_BUG_ON(1); /* Can't reach this code. */
+#endif
+ break;
+ case SSB_BUSTYPE_SDIO:
+ break;
+ }
+ bus->mmio = NULL;
+ bus->mapped_device = NULL;
+}
+
+int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr)
+{
+ u32 idhi;
+ int dev_i, i;
+ struct ssb_device *dev;
+ int nr_80211_cores = 0;
+ int err;
+
+#ifdef CONFIG_SSB_DRIVER_MIPS
+ bus->mipscore.irqflag = ssb_irqflag_sb;
+#endif /* CONFIG_SSB_DRIVER_MIPS */
+
+ /* Fetch basic information about each core/device */
+ for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
+ err = scan_switchcore(bus, i);
+ if (err)
+ return err;
+ dev = &(bus->devices[dev_i]);
+
+ idhi = scan_read32(bus, i, SSB_IDHIGH);
+ dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+ dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
+ dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >>
+ SSB_IDHIGH_RCHI_SHIFT;
+ dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
+ dev->core_index = i;
+ dev->bus = bus;
+ dev->ops = bus->ops;
+ dev->helpers = &ssb_helpers_sb;
+
+ if (ssb_bus_check_core(dev, &nr_80211_cores, i) < 0)
+ continue;
+
+ dev_i++;
+ }
+ bus->nr_devices = dev_i;
+ return 0;
+}
--- linux-wireless-testing.orig/drivers/ssb/ssb_sb.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-wireless-testing/drivers/ssb/ssb_sb.h 2011-02-17 15:55:25.000000000 +0200
@@ -0,0 +1,52 @@
+#ifndef LINUX_SSB_SB_H_
+#define LINUX_SSB_SB_H_
+
+#ifdef CONFIG_SSB_BUS_SB
+
+/* SB-style bus core control and state registers */
+#define SSB_TMSLOW 0x0F98 /* SB Target State Low */
+#define SSB_TMSLOW_RESET 0x00000001 /* Reset */
+#define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */
+#define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */
+#define SSB_TMSLOW_PHYCLK 0x00000010 /* MAC PHY Clock Control Enable */
+#define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */
+#define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */
+#define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */
+#define SSB_TMSLOW_BE 0x80000000 /* BIST Enable */
+#define SSB_TMSLOW_FLAGS_SHIFT 16 /* Flags shift for TMSLOW
+ * register of SB-style buses */
+#define SSB_TMSHIGH 0x0F9C /* SB Target State High */
+#define SSB_TMSHIGH_SERR 0x00000001 /* S-error */
+#define SSB_TMSHIGH_INT 0x00000002 /* Interrupt */
+#define SSB_TMSHIGH_BUSY 0x00000004 /* Busy */
+#define SSB_TMSHIGH_TO 0x00000020 /* Timeout. Backplane rev >= 2.3 only */
+#define SSB_TMSHIGH_DMA64 0x10000000 /* 64bit DMA supported */
+#define SSB_TMSHIGH_GCR 0x20000000 /* Gated Clock Request */
+#define SSB_TMSHIGH_BISTF 0x40000000 /* BIST Failed */
+#define SSB_TMSHIGH_BISTD 0x80000000 /* BIST Done */
+#define SSB_TMSHIGH_FLAGS_SHIFT 16 /* Flags shift for TMSHIGH
+ * register of SB-style buses */
+
+extern int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr);
+extern int scan_switchcore(struct ssb_bus *bus, u8 coreidx);
+extern void ssb_iounmap_sb(struct ssb_bus *bus);
+
+#else /* CONFIG_SSB_BUS_SB */
+
+static inline int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
+{
+ return 0;
+}
+
+static inline void ssb_iounmap_sb(struct ssb_bus *bus)
+{
+}
+
+static inline int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_SSB_BUS_SB */
+
+#endif /* !LINUX_SSB_SB_H_ */
From: George Kashperko <[email protected]>
Move direct master/slave wrappers registers' queries into SSB management code.
Indirect requests to SB management code for wrappers' base/size rather than
direct access to backplane-specific registers will let adding AI-style SSB
buses support without need to alter drivers' code later on.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/driver_gige.c | 2 +-
drivers/ssb/main.c | 8 ++++++--
drivers/usb/host/ohci-ssb.c | 8 ++++----
include/linux/ssb/ssb.h | 4 ++--
4 files changed, 13 insertions(+), 9 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/driver_gige.c 2011-02-08 00:22:45.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/driver_gige.c 2011-02-17 14:00:33.000000000 +0200
@@ -193,7 +193,7 @@ static int ssb_gige_probe(struct ssb_dev
ssb_device_enable(sdev, 0);
/* Setup BAR0. This is a 64k MMIO region. */
- base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1));
+ base = ssb_admatch_base(sdev, SSB_ADMATCH1);
gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base);
gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0);
--- linux-wireless-testing.orig/drivers/ssb/main.c 2011-02-08 00:22:45.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/main.c 2011-02-17 14:00:33.000000000 +0200
@@ -1312,10 +1312,12 @@ error:
}
EXPORT_SYMBOL(ssb_bus_powerup);
-u32 ssb_admatch_base(u32 adm)
+u32 ssb_admatch_base(struct ssb_device *dev, u32 adm)
{
u32 base = 0;
+ adm = ssb_read32(dev, adm);
+
switch (adm & SSB_ADM_TYPE) {
case SSB_ADM_TYPE0:
base = (adm & SSB_ADM_BASE0);
@@ -1336,10 +1338,12 @@ u32 ssb_admatch_base(u32 adm)
}
EXPORT_SYMBOL(ssb_admatch_base);
-u32 ssb_admatch_size(u32 adm)
+u32 ssb_admatch_size(struct ssb_device *dev, u32 adm)
{
u32 size = 0;
+ adm = ssb_read32(dev, adm);
+
switch (adm & SSB_ADM_TYPE) {
case SSB_ADM_TYPE0:
size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT);
--- linux-wireless-testing.orig/drivers/usb/host/ohci-ssb.c 2011-02-08 00:22:48.000000000 +0200
+++ linux-wireless-testing/drivers/usb/host/ohci-ssb.c 2011-02-17 14:00:33.000000000 +0200
@@ -107,7 +107,7 @@ static int ssb_ohci_attach(struct ssb_de
struct ssb_ohci_device *ohcidev;
struct usb_hcd *hcd;
int err = -ENOMEM;
- u32 tmp, flags = 0;
+ u32 flags = 0;
if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
@@ -118,6 +118,7 @@ static int ssb_ohci_attach(struct ssb_de
flags |= SSB_OHCI_TMSLOW_HOSTMODE;
ssb_device_enable(dev, flags);
} else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+ u32 tmp;
/*
* USB 2.0 special considerations:
*
@@ -163,9 +164,8 @@ static int ssb_ohci_attach(struct ssb_de
ohcidev = hcd_to_ssb_ohci(hcd);
ohcidev->enable_flags = flags;
- tmp = ssb_read32(dev, SSB_ADMATCH0);
- hcd->rsrc_start = ssb_admatch_base(tmp);
- hcd->rsrc_len = ssb_admatch_size(tmp);
+ hcd->rsrc_start = ssb_admatch_base(dev, SSB_ADMATCH0);
+ hcd->rsrc_len = ssb_admatch_size(dev, SSB_ADMATCH0);
hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs)
goto err_put_hcd;
--- linux-wireless-testing.orig/include/linux/ssb/ssb.h 2011-02-08 00:22:50.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb.h 2011-02-17 14:00:33.000000000 +0200
@@ -520,8 +520,8 @@ extern int ssb_bus_powerup(struct ssb_bu
/* Various helper functions */
-extern u32 ssb_admatch_base(u32 adm);
-extern u32 ssb_admatch_size(u32 adm);
+extern u32 ssb_admatch_base(struct ssb_device *dev, u32 adm);
+extern u32 ssb_admatch_size(struct ssb_device *dev, u32 adm);
/* PCI device mapping and fixup routines.
* Called from the architecture pcibios init code.
On Fri, 2011-02-18 at 09:39 +0200, George Kashperko wrote:
> > This just reinforces what Michael said about name confusion.
> >
> > Michael's proposal of separating SSB and AXI, and decoupling the device
> > drivers from the bus routines, is going to be much more maintainable in
> > the long run. AXI is going to be far more widespread than SSB ever was,
> > and it would be really unfortunate if we carry the SSB baggage forward.
> >
> > I've been poking around at disentangling the sb and ai routines in
> > drivers/staging/brcm80211/utils/{aiutils,sbutils,siutils}.c. I don't
> > have anything to put out for comments yet, but it's enough to convince
> > me that it's the right direction.
> Yes, AI, lets say, over SBB, makes some confusion and this confusion
> could be avoided with separate SSB/AI bus drivers but in current SSB
> design state its 99% of copy-pasting SSB code with changing nothing
> other than &ops pointers and ssb_ prefixes with something like bcmai_ or
> similar which honestly makes no sense to me considering than the goal is
> to <avoid confusion>. Pretty much sure there will be even more confusion
> than before.
There are plenty of examples in the kernel where code was simply forked
for the development of a new technology. Look at b43/b43legacy or
ext2/3/4 just for a few examples. The forks were made on purpose
to avoid maintainability nightmares. Yes, at first sight, some code had
to be duplicated. But I don't see that as an issue. The two codebases
will diverge quickly from each other as development is done.
So I'm supporting Henry in that SSB is legacy and EOL. Let's simply
start over and don't carry old cruft over.
Note that this does not mean that we need to duplicate the MIPS,
common and probably pci core drivers. A hybrid module can be done,
if that's desired to avoid code duplication.
And I also think that you're worrying _way_ too much about a few
if/else statements in the drivers. (Look at the TMSLOW discussion).
The SSB/AI->driver interface is trivial and tiny. There will be maybe
10 if/else statements. It's really _not_ worth introducing major
abstraction code in the SSB and AI code to avoid a few if/else
statements in the drivers.
The bulk of the SSB->driver interface _is_ already abstracted inside
of the drivers (b43_read/write...). The rest is negligible.
And if it turns out _afterwards_ that we could avoid a few if/else
statements by introducing some additional abstraction layer, this
thing can be introduced _afterwards_.
PS: Could you please stop stripping the CC list.
--
Greetings Michael.
On 02/18/2011 05:27 PM, Michael Büsch wrote:
> On Sat, 2011-02-19 at 01:07 +0200, George Kashperko wrote:
>> Starting from the clean page means another months of no support for
>> AI-based hw.
>
> Oh, wait a second right here. That's not how Linux development works.
> We want the technically superior solution, not just something that
> works to get stuff working no matter what.
>
> If your patchset works, that's pretty cool. So thanks a lot for getting
> something to the users that works. Nothing stops distributions from
> picking up those patches and distributing it to endusers.
> That doesn't mean we have to adopt it to the mainline, though.
I don't want to get involved in the debate over abstraction, but FWIW, the
patchset does work for PCI-based SSB devices.
Larry
On Fri, 2011-02-18 at 00:31 +0200, George Kashperko wrote:
> +#define SSB_AI_BASE 0x18100000U /* base for AI registers */
#define MOON_EARTH_BASE 1337
That probably is my major point against this patchset. It just
merges things that don't belong to each other.
Is this the base on moon or earth?
If it's the earth base, why the hell do we prefix the define with MOON?
That naming confusion continues throughout the whole patchset.
SSB is end of life, so we should not try to support the new AI hardware
by making SSB AI aware. Just fork SSB and let legacy SSB die as the
existing hardware dies. It deserves it. Mercy killing for software!
_Currently_ it may look like a good idea to use one software base
for the two busses, but the cruft will hurt you in the future.
And the future begins one day after this hack was merged.
--
Greetings Michael.
Hi,
> You should improve your CC lists in general
> for all your mails. Most of us don't have the time to read all
> mail on the list, so it's always a good idea to maintain a CC list
> of people who already commented on the RFC for patch submissions.
Apologises for that.
Have nice day,
George
From: Bernhard Loos <[email protected]>
Add MIPS74K device id defines.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/scan.c | 8 ++++++++
include/linux/ssb/ssb.h | 4 ++++
2 files changed, 12 insertions(+)
--- linux-wireless-testing.orig/drivers/ssb/scan.c 2011-02-17 14:53:03.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 14:53:28.000000000 +0200
@@ -90,6 +90,14 @@ const char *ssb_core_name(u16 coreid)
return "ARM 1176";
case SSB_DEV_ARM_7TDMI:
return "ARM 7TDMI";
+ case SSB_DEV_ETHERNET_GMAC:
+ return "Gigabit MAC";
+ case SSB_DEV_MIPS_74K:
+ return "MIPS 74K";
+ case SSB_DEV_DDR_CTRLR:
+ return "DDR1/2 memory controller";
+ case SSB_DEV_I2S:
+ return "I2S";
}
return "UNKNOWN";
}
--- linux-wireless-testing.orig/include/linux/ssb/ssb.h 2011-02-17 14:28:49.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb.h 2011-02-17 14:53:28.000000000 +0200
@@ -166,6 +166,10 @@ struct ssb_bus_helpers {
#define SSB_DEV_MINI_MACPHY 0x823
#define SSB_DEV_ARM_1176 0x824
#define SSB_DEV_ARM_7TDMI 0x825
+#define SSB_DEV_ETHERNET_GMAC 0x82D
+#define SSB_DEV_MIPS_74K 0x82C
+#define SSB_DEV_DDR_CTRLR 0x82E
+#define SSB_DEV_I2S 0x834
/* Vendor-ID values */
#define SSB_VENDOR_BROADCOM 0x4243
Hi,
> On Fri, 2011-02-18 at 00:08 +0200, George Kashperko wrote:
> > const struct ssb_bus_ops *ops;
> > + const struct ssb_bus_helpers *helpers;
>
> Uhm, well. "helpers"... . Seems like a pretty generic term.
>
> I think this is still violating abstraction layering. Not as much
> as your previous attempt, but still...
>
> You're putting the ops structure that is supposed to abstract
> the ssb bus into the ssb_device data structure. That should ring a bell.
>
Reconsidered it already while arranging patches for Openwrt (the reason
helpers were in device struct was to speedup access but these aint
called often therefore they are in ssb_bus now). Also moved
chipco.chipid into ssb_bus struct, could rename it also right away if
only I get up fresh and with good idea how to name it properly or maybe
you will suggest nice one.
Have nice day,
George
From: George Kashperko <[email protected]>
SB- and AI-style buses read irq flags from different locations.
SB-ones read them from TPSFLAG whereas AI-ones from core oob register.
In order to support both SB- and AI-style buses transparently
irq flag accessor is implemented as ssb mips core op.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/driver_mipscore.c | 6 ++++++
include/linux/ssb/ssb_driver_mips.h | 3 +++
2 files changed, 9 insertions(+)
--- linux-wireless-testing.orig/drivers/ssb/driver_mipscore.c 2011-02-08 00:22:45.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/driver_mipscore.c 2011-02-17 14:05:27.000000000 +0200
@@ -49,6 +49,11 @@ static const u32 ipsflag_irq_shift[] = {
static inline u32 ssb_irqflag(struct ssb_device *dev)
{
+ return dev->bus->mipscore.irqflag(dev);
+}
+
+static u32 ssb_irqflag_sb(struct ssb_device *dev)
+{
u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
if (tpsflag)
return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
@@ -241,6 +246,7 @@ void ssb_mipscore_init(struct ssb_mipsco
ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
bus = mcore->dev->bus;
+ bus->mipscore.irqflag = ssb_irqflag_sb;
hz = ssb_clockspeed(bus);
if (!hz)
hz = 100000000;
--- linux-wireless-testing.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-08 00:22:50.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb_driver_mips.h 2011-02-17 14:05:27.000000000 +0200
@@ -23,6 +23,9 @@ struct ssb_mipscore {
u8 flash_buswidth;
u32 flash_window;
u32 flash_window_size;
+
+ /* mips core implementation-specific irq flag helper */
+ u32 (*irqflag)(struct ssb_device *dev);
};
extern void ssb_mipscore_init(struct ssb_mipscore *mcore);
On Fri, 2011-02-18 at 00:08 +0200, George Kashperko wrote:
> const struct ssb_bus_ops *ops;
> + const struct ssb_bus_helpers *helpers;
Uhm, well. "helpers"... . Seems like a pretty generic term.
I think this is still violating abstraction layering. Not as much
as your previous attempt, but still...
You're putting the ops structure that is supposed to abstract
the ssb bus into the ssb_device data structure. That should ring a bell.
--
Greetings Michael.
From: George Kashperko <[email protected]>
Diagnostic messages in main.c with chip type info.
Move piece of code out of ssb_bus_scan to introduce basic bus detection
routine for later extension with AI-style bus detection.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/main.c | 34 +++++++++----
drivers/ssb/scan.c | 51 +++++++++++++-------
include/linux/ssb/ssb_driver_chipcommon.h | 12 ++++
3 files changed, 72 insertions(+), 25 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/main.c 2011-02-17 15:48:23.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/main.c 2011-02-17 15:48:51.000000000 +0200
@@ -850,6 +850,16 @@ err_disable_xtal:
return err;
}
+static const char *ssb_chipco_chiptype_name(struct ssb_bus *bus)
+{
+ switch (bus->chipco.chiptype) {
+ case SSB_CHIPCO_SB:
+ return "SB";
+ default:
+ return "UNKNOWN";
+ }
+}
+
#ifdef CONFIG_SSB_PCIHOST
int ssb_bus_pcibus_register(struct ssb_bus *bus,
struct pci_dev *host_pci)
@@ -862,11 +872,14 @@ int ssb_bus_pcibus_register(struct ssb_b
err = ssb_bus_register(bus, ssb_pci_get_invariants, 0);
if (!err) {
- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
- "PCI device %s\n", dev_name(&host_pci->dev));
+ ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane "
+ "(%s type) found on PCI device %s\n",
+ ssb_chipco_chiptype_name(bus),
+ dev_name(&host_pci->dev));
} else {
ssb_printk(KERN_ERR PFX "Failed to register PCI version"
- " of SSB with error %d\n", err);
+ " of SSB (%s type) with error %d\n",
+ ssb_chipco_chiptype_name(bus), err);
}
return err;
@@ -887,8 +900,9 @@ int ssb_bus_pcmciabus_register(struct ss
err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr);
if (!err) {
- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
- "PCMCIA device %s\n", pcmcia_dev->devname);
+ ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane "
+ "(%s type) found on PCMCIA device %s\n",
+ ssb_chipco_chiptype_name(bus), pcmcia_dev->devname);
}
return err;
@@ -909,8 +923,9 @@ int ssb_bus_sdiobus_register(struct ssb_
err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0);
if (!err) {
- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
- "SDIO device %s\n", sdio_func_id(func));
+ ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane "
+ "(%s type) found on SDIO device %s\n",
+ ssb_chipco_chiptype_name(bus), sdio_func_id(func));
}
return err;
@@ -929,8 +944,9 @@ int ssb_bus_ssbbus_register(struct ssb_b
err = ssb_bus_register(bus, get_invariants, baseaddr);
if (!err) {
- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at "
- "address 0x%08lX\n", baseaddr);
+ ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane "
+ "(%s type) found at address 0x%08lX\n",
+ ssb_chipco_chiptype_name(bus), baseaddr);
}
return err;
--- linux-wireless-testing.orig/drivers/ssb/scan.c 2011-02-17 15:48:23.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 15:50:23.000000000 +0200
@@ -355,24 +355,11 @@ int ssb_bus_check_core(struct ssb_device
return 0;
}
-int ssb_bus_scan(struct ssb_bus *bus,
- unsigned long baseaddr)
+/* Detect bus type and major bus information */
+static int ssb_bus_detect(struct ssb_bus *bus)
{
- int err = -ENOMEM;
- void __iomem *mmio;
u32 idhi, cc, rev, tmp;
- int dev_i, i;
- struct ssb_device *dev;
- int nr_80211_cores = 0;
-
- mmio = ssb_ioremap(bus, baseaddr);
- if (!mmio)
- goto out;
- bus->mmio = mmio;
-
- err = scan_switchcore(bus, 0); /* Switch to first core */
- if (err)
- goto err_unmap;
+ enum ssb_chipco_chiptype chiptype = SSB_CHIPCO_SB;
idhi = scan_read32(bus, 0, SSB_IDHIGH);
cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
@@ -383,6 +370,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
if (cc == SSB_DEV_CHIPCOMMON) {
tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID);
+ chiptype = SSB_CHIPCO_TYPE(tmp);
bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
SSB_CHIPCO_REVSHIFT;
@@ -412,8 +400,39 @@ int ssb_bus_scan(struct ssb_bus *bus,
ssb_printk(KERN_ERR PFX
"More than %d ssb cores found (%d)\n",
SSB_MAX_NR_CORES, bus->nr_devices);
+ return -ENOMEM;
+ }
+
+ bus->chipco.chiptype = chiptype;
+ return chiptype == SSB_CHIPCO_SB ? 0 : -ENODEV;
+}
+
+int ssb_bus_scan(struct ssb_bus *bus, unsigned long baseaddr)
+{
+ int err = -ENOMEM;
+ void __iomem *mmio;
+ u32 idhi;
+ int dev_i, i;
+ struct ssb_device *dev;
+ int nr_80211_cores = 0;
+
+ mmio = ssb_ioremap(bus, baseaddr);
+ if (!mmio)
+ goto out;
+ bus->mmio = mmio;
+
+ err = scan_switchcore(bus, 0); /* Switch to first core */
+ if (err)
+ goto err_unmap;
+
+ err = ssb_bus_detect(bus);
+ if (err) {
+ ssb_printk(KERN_ERR PFX
+ "ERROR: Unknown SSB chip type %d detected\n",
+ bus->chipco.chiptype);
goto err_unmap;
}
+
if (bus->bustype == SSB_BUSTYPE_SSB) {
/* Now that we know the number of cores,
* remap the whole IO space for all cores.
--- linux-wireless-testing.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-17 15:48:23.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-17 15:48:45.000000000 +0200
@@ -16,6 +16,9 @@
/** ChipCommon core registers. **/
#define SSB_CHIPCO_CHIPID 0x0000
+#define SSB_CHIPCO_TYPE_MASK 0xF0000000
+#define SSB_CHIPCO_TYPE_SHIFT 28
+#define SSB_CHIPCO_TYPE_SB 0
#define SSB_CHIPCO_IDMASK 0x0000FFFF
#define SSB_CHIPCO_REVMASK 0x000F0000
#define SSB_CHIPCO_REVSHIFT 16
@@ -248,6 +251,9 @@
#define SSB_CHIPCO_PLLCTL_ADDR 0x0660
#define SSB_CHIPCO_PLLCTL_DATA 0x0664
+/** ChipCommon core registers identification macro helpers **/
+#define SSB_CHIPCO_TYPE(cid) (((cid) & SSB_CHIPCO_TYPE_MASK) >> \
+ SSB_CHIPCO_TYPE_SHIFT)
/** PMU PLL registers */
@@ -575,10 +581,16 @@ struct ssb_chipcommon_pmu {
u32 crystalfreq; /* The active crystal frequency (in kHz) */
};
+/* Chipcommon implementation type */
+enum ssb_chipco_chiptype {
+ SSB_CHIPCO_SB = SSB_CHIPCO_TYPE(SSB_CHIPCO_TYPE_SB), /* SB-style bus */
+};
+
struct ssb_chipcommon {
struct ssb_device *dev;
u32 capabilities;
u32 status;
+ enum ssb_chipco_chiptype chiptype;
/* Fast Powerup Delay constant */
u16 fast_pwrup_delay;
struct ssb_chipcommon_pmu pmu;
From: George Kashperko <[email protected]>
Introduce iounmap helper for transparent resource
releasing by bus implementation-specific management code.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/scan.c | 2 +-
drivers/ssb/ssb_private.h | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/scan.c 2011-02-17 14:45:04.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 14:45:31.000000000 +0200
@@ -199,7 +199,7 @@ static int scan_switchcore(struct ssb_bu
return 0;
}
-void ssb_iounmap(struct ssb_bus *bus)
+void ssb_iounmap_sb(struct ssb_bus *bus)
{
switch (bus->bustype) {
case SSB_BUSTYPE_SSB:
--- linux-wireless-testing.orig/drivers/ssb/ssb_private.h 2011-02-17 14:34:02.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/ssb_private.h 2011-02-17 14:45:31.000000000 +0200
@@ -159,9 +159,13 @@ static inline int ssb_sdio_init(struct s
extern const char *ssb_core_name(u16 coreid);
extern int ssb_bus_scan(struct ssb_bus *bus,
unsigned long baseaddr);
-extern void ssb_iounmap(struct ssb_bus *ssb);
+extern void ssb_iounmap_sb(struct ssb_bus *bus);
extern int ssb_bus_check_core(struct ssb_device *dev, int *nr_80211_cores,
int corenum);
+static inline void ssb_iounmap(struct ssb_bus *bus)
+{
+ ssb_iounmap_sb(bus);
+}
/* sprom.c */
On Sat, 2011-02-19 at 01:07 +0200, George Kashperko wrote:
> Starting from the clean page means another months of no support for
> AI-based hw.
Oh, wait a second right here. That's not how Linux development works.
We want the technically superior solution, not just something that
works to get stuff working no matter what.
If your patchset works, that's pretty cool. So thanks a lot for getting
something to the users that works. Nothing stops distributions from
picking up those patches and distributing it to endusers.
That doesn't mean we have to adopt it to the mainline, though.
> Going cp ssb bcmai; sed s/ssb/bcmai way will make whole
> messup.
Forking and developing a separate solution is not equivalent
to applying cp and sed commands to the codebase.
> Ah, well, there might is another 4th way to go if Broadcom will finally
> support their bus with their brand code but honestly (no offence to
> Broadcom here, just my personal subjective opinion) I dont think I will
> be happy to see this code after all that I've already seen.
As Henry already replied to this thread, I'm pretty sure that Broadcom
is interested in bringing the technically superior solution to the
mainline.
I do agree, however, that their current "SB" and "BCMAI" code
doesn't look superior to your patchset, though. ;)
--
Greetings Michael.
On 02/18/2011 06:08 PM, George Kashperko wrote:
> Hi,
>
>> On 02/18/2011 05:47 PM, George Kashperko wrote:
>>> Hi,
>>>
>>>> I don't want to get involved in the debate over abstraction, but FWIW, the
>>>> patchset does work for PCI-based SSB devices.
>>>>
>>>> Larry
>>>>
>>> Could you please let me know if you tried last code I've posted, as my
>>> original RFC was indeed embeddables' targeted and won't work for
>>> SSB-over-PCI.
>>> Last code I've posted I've tested on SSB over PCIE host and it was
>>> pretty much working.
>>
>> I tested the 14 patches you posted on 2/17/2011 that arrived about 10:20 UTC.
>>
>> Larry
>>
> Ohh, I skrewed again -.-
> Donno how but I decided It didn't work for you. I'm too much sleepy, but
> can't go sleep till coffee let me off. Sorry.
The first set of patches you posed didn't build due to the MIPS problem, but the
second set built and worked.
Larry
From: George Kashperko <[email protected]>
Add support for AI-style bus.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/Kconfig | 11
drivers/ssb/Makefile | 1
drivers/ssb/main.c | 2
drivers/ssb/scan.c | 47 +-
drivers/ssb/ssb_ai.c | 407 ++++++++++++++++++++
drivers/ssb/ssb_ai.h | 79 +++
drivers/ssb/ssb_private.h | 6
include/linux/ssb/ssb.h | 44 ++
include/linux/ssb/ssb_driver_chipcommon.h | 3
include/linux/ssb/ssb_regs.h | 1
10 files changed, 593 insertions(+), 8 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/Kconfig 2011-02-17 15:56:58.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/Kconfig 2011-02-17 15:57:14.000000000 +0200
@@ -32,6 +32,17 @@ config SSB_BUS_SB
help
Sonics Silicon Backplane SB-style bus
+config SSB_BUS_AI_POSSIBLE
+ bool
+ default y if SSB && EXPERIMENTAL
+
+config SSB_BUS_AI
+ bool "AI style bus"
+ depends on SSB_BUS_AI_POSSIBLE
+ default n
+ help
+ Broadcom AI-style bus
+
# Common SPROM support routines
config SSB_SPROM
bool
--- linux-wireless-testing.orig/drivers/ssb/main.c 2011-02-17 15:56:58.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/main.c 2011-02-17 15:57:14.000000000 +0200
@@ -855,6 +855,8 @@ static const char *ssb_chipco_chiptype_n
switch (bus->chipco.chiptype) {
case SSB_CHIPCO_SB:
return "SB";
+ case SSB_CHIPCO_AI:
+ return "AI";
default:
return "UNKNOWN";
}
--- linux-wireless-testing.orig/drivers/ssb/Makefile 2011-02-17 15:56:58.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/Makefile 2011-02-17 15:57:14.000000000 +0200
@@ -1,6 +1,7 @@
# core
ssb-y += main.o scan.o
ssb-$(CONFIG_SSB_BUS_SB) += ssb_sb.o
+ssb-$(CONFIG_SSB_BUS_AI) += ssb_ai.o
ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o
ssb-$(CONFIG_SSB_SPROM) += sprom.o
--- linux-wireless-testing.orig/drivers/ssb/scan.c 2011-02-17 15:57:09.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 15:57:14.000000000 +0200
@@ -326,19 +326,48 @@ int ssb_bus_check_core(struct ssb_device
return 0;
}
+static inline bool ssb_can_read_idhi(void)
+{
+#ifdef CONFIG_MIPS
+ return cpu_data[0].cputype != CPU_74K;
+#else
+ return true;
+#endif
+}
+
/* Detect bus type and major bus information */
static int ssb_bus_detect(struct ssb_bus *bus)
{
- u32 idhi, cc, rev, tmp;
+ u32 idhi, rev, tmp;
+ bool have_chipcommon = true;
enum ssb_chipco_chiptype chiptype = SSB_CHIPCO_SB;
- idhi = scan_read32(bus, 0, SSB_IDHIGH);
- cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
- rev = (idhi & SSB_IDHIGH_RCLO);
- rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
+ /* the problem goes like this:
+ * if we access the normal core id backplane registers on an AI soc,
+ * the thing hangs.
+ * To figure out, if we have an AI soc, we have to look in a
+ * chipcommon register.
+ * The 4710 doesn't have a chipcommon but we can't figure this out
+ * without scanning the cores, and we don't know, if we have to use
+ * the AI or normal method.
+ * All known AI socs have a 74k cpu, so let's take this as an
+ * indicator that we have a chipcommon core and hope for the best.
+ */
+ rev = 0;
+ if (ssb_can_read_idhi()) {
+ idhi = scan_read32(bus, 0, SSB_IDHIGH);
+ if (((idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT) !=
+ SSB_DEV_CHIPCOMMON) {
+ have_chipcommon = false;
+ } else {
+ rev = (idhi & SSB_IDHIGH_RCLO);
+ rev |= (idhi & SSB_IDHIGH_RCHI) >>
+ SSB_IDHIGH_RCHI_SHIFT;
+ }
+ }
bus->nr_devices = 0;
- if (cc == SSB_DEV_CHIPCOMMON) {
+ if (have_chipcommon) {
tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID);
chiptype = SSB_CHIPCO_TYPE(tmp);
@@ -375,7 +404,8 @@ static int ssb_bus_detect(struct ssb_bus
}
bus->chipco.chiptype = chiptype;
- return chiptype == SSB_CHIPCO_SB ? 0 : -ENODEV;
+ return (chiptype == SSB_CHIPCO_SB ||
+ chiptype == SSB_CHIPCO_AI) ? 0 : -ENODEV;
}
int ssb_bus_scan(struct ssb_bus *bus, unsigned long baseaddr)
@@ -416,6 +446,9 @@ int ssb_bus_scan(struct ssb_bus *bus, un
case SSB_CHIPCO_SB:
err = ssb_bus_scan_sb(bus, baseaddr);
break;
+ case SSB_CHIPCO_AI:
+ err = ssb_bus_scan_ai(bus, baseaddr);
+ break;
default:
SSB_WARN_ON(1);
err = -ENODEV;
--- linux-wireless-testing.orig/drivers/ssb/ssb_ai.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-wireless-testing/drivers/ssb/ssb_ai.c 2011-02-17 15:57:14.000000000 +0200
@@ -0,0 +1,407 @@
+/*
+ * Sonics Silicon Backplane
+ * AI Specific Subsystem core
+ *
+ * Copyright 2011, George Kashperko <[email protected]>
+ * Copyright 2010, Bernhard Loos <[email protected]>
+ * Copyright (C) 2006 Broadcom Corporation.
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/delay.h>
+#include <linux/ssb/ssb.h>
+#include <linux/ssb/ssb_regs.h>
+
+#include "ssb_private.h"
+#include "ssb_ai.h"
+
+
+static inline u32 ssb_airead32(struct ssb_device *dev, u16 offset)
+{
+ return dev->ai.ops->read32(dev, offset);
+}
+
+static inline void ssb_aiwrite32(struct ssb_device *dev, u16 offset, u32 value)
+{
+ dev->ai.ops->write32(dev, offset, value);
+}
+
+static u32 ssb_ssb_airead32(struct ssb_device *dev, u16 offset)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ return readl(bus->ai.mmio + offset);
+}
+
+static void ssb_ssb_aiwrite32(struct ssb_device *dev, u16 offset, u32 value)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ return writel(value, bus->ai.mmio + offset);
+}
+
+struct ssb_bus_aiops ssb_ssb_aiops = {
+ .read32 = ssb_ssb_airead32,
+ .write32 = ssb_ssb_aiwrite32,
+};
+
+/* The 47162a0 hangs when reading its registers */
+static inline bool ssb_bcm47162a0_quirk(struct ssb_device *dev)
+{
+ return dev->bus->chip_id == 47162 && dev->bus->chip_rev == 0 &&
+ dev->id.coreid == SSB_DEV_MIPS_74K;
+}
+
+static u32 ssb_core_ctl_flags_ai(struct ssb_device *dev, u32 mask, u32 val)
+{
+ if (ssb_bcm47162a0_quirk(dev)) {
+ ssb_printk(KERN_ERR PFX "%s: Accessing MIPS DMP register "
+ "(IOCTL) on 47162a0", __func__);
+ return 0;
+ }
+
+ SSB_WARN_ON((~mask | val) & 0xFFFF0000);
+
+ if (~mask || val) {
+ u32 tmp = (ssb_airead32(dev, SSB_AI_IOCTL) & mask) | val;
+ ssb_aiwrite32(dev, SSB_AI_IOCTL, tmp);
+ }
+
+ return ssb_airead32(dev, SSB_AI_IOCTL);
+}
+
+static u32 ssb_core_state_flags_ai(struct ssb_device *dev)
+{
+ if (ssb_bcm47162a0_quirk(dev)) {
+ ssb_printk(KERN_ERR PFX "%s: Accessing MIPS DMP register "
+ "(IOSTAT) on 47162a0", __func__);
+ return 0;
+ }
+ return ssb_airead32(dev, SSB_AI_IOSTAT);
+}
+
+#ifdef CONFIG_SSB_DRIVER_MIPS
+/* return -1 if no irq is supported */
+static u32 ssb_irqflag_ai(struct ssb_device *dev)
+{
+ u32 flag;
+
+ if (ssb_bcm47162a0_quirk(dev))
+ return dev->core_index;
+
+ flag = ssb_airead32(dev, SSB_AI_oobselouta30) & 0x1F;
+
+ if (flag && flag != 0x1F)
+ return flag;
+ else
+ /* not irq supported */
+ return -1;
+}
+#endif /* CONFIG_SSB_DRIVER_MIPS */
+
+static int ssb_device_is_enabled_ai(struct ssb_device *dev)
+{
+ return (ssb_airead32(dev, SSB_AI_RESETCTL) &
+ SSB_AI_RESETCTL_RESET) == 0;
+}
+
+static void ssb_aiioctl_write(struct ssb_device *dev, u32 flags)
+{
+ u32 dummy;
+ ssb_aiwrite32(dev, SSB_AI_IOCTL, flags);
+ dummy = ssb_airead32(dev, SSB_AI_IOCTL);
+ udelay(1);
+}
+
+static void ssb_device_disable_ai(struct ssb_device *dev,
+ u32 core_specific_flags)
+{
+ SSB_WARN_ON(core_specific_flags & 0xFFFF0000);
+ if (ssb_airead32(dev, SSB_AI_RESETCTL) & SSB_AI_RESETCTL_RESET)
+ return;
+ ssb_aiioctl_write(dev, core_specific_flags);
+ udelay(9);
+ ssb_aiwrite32(dev, SSB_AI_RESETCTL, SSB_AI_RESETCTL_RESET);
+ udelay(1);
+}
+
+static void ssb_device_enable_ai(struct ssb_device *dev,
+ u32 core_specific_flags)
+{
+ ssb_device_disable_ai(dev, core_specific_flags);
+
+ ssb_aiioctl_write(dev, core_specific_flags | SSB_CORECTL_FGC |
+ SSB_CORECTL_CLOCK);
+ ssb_aiwrite32(dev, SSB_AI_RESETCTL, 0);
+ udelay(1);
+
+ ssb_aiioctl_write(dev, core_specific_flags | SSB_CORECTL_CLOCK);
+}
+
+static u32 ssb_admatch_base_ai(struct ssb_device *dev, u32 adm)
+{
+ switch (adm) {
+ case SSB_ADMATCH0:
+ return dev->ai.core[0].base;
+ case SSB_ADMATCH1:
+ return dev->ai.core[1].base;
+ default:
+ printk(KERN_ERR PFX "Need to parse the erom again "
+ "to find addr space %d\n",
+ adm & SSB_ADM_TYPE);
+ return 0;
+ }
+}
+
+static u32 ssb_admatch_size_ai(struct ssb_device *dev, u32 adm)
+{
+ switch (adm) {
+ case SSB_ADMATCH0:
+ return dev->ai.core[0].size;
+ case SSB_ADMATCH1:
+ return dev->ai.core[1].size;
+ default:
+ printk(KERN_ERR PFX "Need to parse the erom again "
+ "to find addr space %d size\n",
+ adm & SSB_ADM_TYPE);
+ return 0;
+ }
+}
+
+const struct ssb_bus_helpers ssb_helpers_ai = {
+ .device_is_enabled = ssb_device_is_enabled_ai,
+ .device_enable = ssb_device_enable_ai,
+ .device_disable = ssb_device_disable_ai,
+ .admatch_base = ssb_admatch_base_ai,
+ .admatch_size = ssb_admatch_size_ai,
+ .core_ctl_flags = ssb_core_ctl_flags_ai,
+ .core_state_flags = ssb_core_state_flags_ai,
+};
+
+void ssb_iounmap_ai(struct ssb_bus *bus)
+{
+ switch (bus->bustype) {
+ case SSB_BUSTYPE_SSB:
+ iounmap(bus->mmio);
+ iounmap(bus->ai.mmio);
+ break;
+ default:
+ break;
+ }
+ bus->mmio = NULL;
+ bus->ai.mmio = NULL;
+ bus->mapped_device = NULL;
+ bus->ai.mapped_device = NULL;
+}
+
+static u32 get_erom_ent(struct ssb_bus *bus, u32 **eromptr, u32 mask, u32 match)
+{
+ u32 ent;
+
+ while (1) {
+ ent = readl(*eromptr);
+ (*eromptr)++;
+
+ if (mask == 0)
+ break;
+
+ if ((ent & SSB_EROM_VALID) == 0)
+ continue;
+
+ if (ent == (SSB_EROM_END | SSB_EROM_VALID))
+ break;
+
+ if ((ent & mask) == match)
+ break;
+ }
+ return ent;
+}
+
+static u32 get_adress_space_descriptor(struct ssb_bus *bus, u32 **eromptr,
+ uint st, u32 *addrl, u32 *sizel)
+{
+ u32 asd, sz, szd, expect;
+
+ expect = SSB_EROM_ASD | st;
+ if (st == SSB_EROM_ASD_ST_SWRAP)
+ expect |= 1 << SSB_EROM_ASD_SP_SHIFT;
+
+ asd = get_erom_ent(bus, eromptr, SSB_EROM_ASD_SP_MASK | SSB_EROM_TAG |
+ SSB_EROM_ASD_ST_MASK, expect);
+
+ *addrl = asd & SSB_EROM_ASD_ADDR_MASK;
+
+ /* 64bit addresses are not supported */
+ BUG_ON(asd & SSB_EROM_ASD_AG32);
+
+ sz = asd & SSB_EROM_ASD_SZ_MASK;
+ if (sz == SSB_EROM_ASD_SZ_SZD) {
+ szd = get_erom_ent(bus, eromptr, 0, 0);
+ *sizel = szd & SSB_EROM_ASD_SZ_MASK;
+ } else
+ *sizel = SSB_EROM_ASD_SZ_BASE << (sz >> SSB_EROM_ASD_SZ_SHIFT);
+
+ return asd;
+}
+
+int ssb_bus_scan_ai(struct ssb_bus *bus, unsigned long baseaddr)
+{
+ int dev_i = 0, nr_80211_cores = 0;
+ struct ssb_device *dev;
+ u32 erombase;
+ u32 __iomem *eromptr, *eromend;
+
+ erombase = scan_read32(bus, 0, SSB_CHIPCO_EROM);
+
+ switch (bus->bustype) {
+ case SSB_BUSTYPE_SSB:
+ bus->ai.ops = &ssb_ssb_aiops;
+ eromptr = ioremap(erombase, SSB_CORE_SIZE);
+ if (!eromptr)
+ return -ENOMEM;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ eromend = eromptr + SSB_CORE_SIZE / sizeof(u32);
+
+#ifdef CONFIG_SSB_DRIVER_MIPS
+ bus->mipscore.irqflag = ssb_irqflag_ai;
+#endif /* CONFIG_SSB_DRIVER_MIPS */
+
+ while (eromptr < eromend) {
+ u32 cia, cib, asd, sizel, addrl, nmw, nsp;
+
+ dev = &(bus->devices[dev_i]);
+
+ cia = get_erom_ent(bus, &eromptr, SSB_EROM_TAG, SSB_EROM_CI);
+ if (cia == (SSB_EROM_END | SSB_EROM_VALID)) {
+ ssb_dprintk(KERN_INFO PFX
+ "Found END of erom after %d cores\n",
+ dev_i);
+ if (dev_i != bus->nr_devices)
+ ssb_printk(KERN_WARNING PFX
+ "Expected %d cores but got %d\n",
+ bus->nr_devices, dev_i);
+ break;
+ }
+ cib = get_erom_ent(bus, &eromptr, 0, 0);
+ if ((cib & SSB_EROM_TAG) != SSB_EROM_CI) {
+ ssb_printk(KERN_ERR PFX "CIA not followed by CIB\n");
+ return -EIO;
+ }
+
+ dev->id.coreid = SSB_EROM_CIA_CID(cia);
+ dev->id.vendor = SSB_EROM_CIA_MFG(cia);
+ dev->id.revision = SSB_EROM_CIB_REV(cib);
+ dev->core_index = dev_i;
+ dev->bus = bus;
+ dev->helpers = &ssb_helpers_ai;
+ dev->ops = bus->ops;
+ dev->ai.ops = bus->ai.ops;
+
+ nmw = SSB_EROM_CIB_NMW(cib);
+ nsp = SSB_EROM_CIB_NSP(cib);
+
+ if (((dev->id.coreid == SSB_DEV_DEFAULT) &&
+ (dev->id.vendor == SSB_VENDOR_ARM)) ||
+ (nmw == 0 && SSB_EROM_CIB_NSW(cib) == 0) || (nsp == 0))
+ continue;
+
+ /* see if it is a bridge */
+ if ((SSB_EROM_ASD_ST_MASK &
+ get_erom_ent(bus, &eromptr, SSB_EROM_TAG, SSB_EROM_ASD)) ==
+ SSB_EROM_ASD_ST_BRIDGE)
+ /* don't record bridges */
+ continue;
+ else
+ eromptr--;
+
+ /* First Slave Address Descriptor should be port 0:
+ * the main register space for the core
+ */
+ asd = get_adress_space_descriptor(bus, &eromptr,
+ SSB_EROM_ASD_ST_SLAVE,
+ &addrl, &sizel);
+ if (sizel != SSB_CORE_SIZE ||
+ addrl != SSB_ENUM_BASE + SSB_CORE_SIZE * dev_i) {
+ ssb_printk(KERN_ERR PFX
+ "Malformed or unsupported register address "
+ "space descriptor for core %d:\n"
+ "\texpected 0x%x, got 0x%x, size 0x%x\n",
+ dev_i, SSB_ENUM_BASE + SSB_CORE_SIZE * dev_i,
+ addrl, sizel);
+ return -EIO;
+ }
+
+ dev->ai.core[0].base = addrl;
+ dev->ai.core[0].size = sizel;
+
+ /* Try to get one more Slave Address Descriptor in port 0 */
+ asd = get_erom_ent(bus, &eromptr, SSB_EROM_VALID,
+ SSB_EROM_VALID) & (SSB_EROM_ASD_SP_MASK |
+ SSB_EROM_ASD_ST_MASK |
+ SSB_EROM_TAG);
+ eromptr--;
+ if (asd == SSB_EROM_ASD) {
+ asd = get_adress_space_descriptor(bus, &eromptr,
+ SSB_EROM_ASD_ST_SLAVE,
+ &addrl, &sizel);
+ if (sizel != SSB_CORE_SIZE) {
+ ssb_printk(KERN_ERR PFX
+ "Malformed or unsupported ai "
+ "address space descriptor for "
+ "core %d:\n\texpected 0x%x size, "
+ "got 0x%x size\n",
+ dev_i, SSB_CORE_SIZE, sizel);
+ return -EIO;
+ }
+ dev->ai.core[1].base = addrl;
+ dev->ai.core[1].size = sizel;
+ }
+
+ if (nmw)
+ asd = get_adress_space_descriptor(bus, &eromptr,
+ SSB_EROM_ASD_ST_MWRAP,
+ &addrl, &sizel);
+ else
+ asd = get_adress_space_descriptor(bus, &eromptr,
+ SSB_EROM_ASD_ST_SWRAP,
+ &addrl, &sizel);
+
+ if (sizel != SSB_CORE_SIZE ||
+ addrl != SSB_AI_BASE + SSB_CORE_SIZE * dev_i) {
+ ssb_printk(KERN_ERR PFX
+ "Malformed or unsupported ai "
+ "address space descriptor for "
+ "core %d:\n\texpected 0x%x, "
+ "got 0x%x, size 0x%x\n",
+ dev_i, SSB_AI_BASE + SSB_CORE_SIZE * dev_i,
+ addrl, sizel);
+ return -EIO;
+ }
+
+ if (ssb_bus_check_core(dev, &nr_80211_cores, dev_i) < 0)
+ continue;
+
+ dev_i++;
+ }
+ bus->nr_devices = dev_i;
+
+ if (eromptr >= eromend)
+ ssb_printk(KERN_WARNING PFX
+ "Reached end of erom without finding END");
+
+ if (bus->bustype == SSB_BUSTYPE_SSB && dev_i) {
+ /* remap as we got final num of cores */
+ bus->ai.mmio = ioremap(SSB_AI_BASE, SSB_CORE_SIZE * dev_i);
+ if (!bus->ai.mmio)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
--- linux-wireless-testing.orig/drivers/ssb/ssb_ai.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-wireless-testing/drivers/ssb/ssb_ai.h 2011-02-17 15:57:14.000000000 +0200
@@ -0,0 +1,79 @@
+#ifndef LINUX_SSB_AI_H_
+#define LINUX_SSB_AI_H_
+
+#ifdef CONFIG_SSB_BUS_AI
+
+#define SSB_AI_BASE 0x18100000U /* base for AI registers */
+
+/* EROM parsing defines */
+#define SSB_EROM_VALID 1
+#define SSB_EROM_END 0x0E
+#define SSB_EROM_TAG 0x0E
+
+/* Adress Space Descriptor */
+#define SSB_EROM_ASD 0x4
+#define SSB_EROM_ASD_SP_MASK 0x00000F00
+#define SSB_EROM_ASD_SP_SHIFT 8
+#define SSB_EROM_ASD_ST_MASK 0x000000c0
+#define SSB_EROM_ASD_ST_SLAVE 0x00000000
+#define SSB_EROM_ASD_ST_BRIDGE 0x00000040
+#define SSB_EROM_ASD_ST_MWRAP 0x000000C0
+#define SSB_EROM_ASD_ST_SWRAP 0x00000080
+#define SSB_EROM_ASD_ADDR_MASK 0xFFFFF000
+#define SSB_EROM_ASD_AG32 0x00000008
+#define SSB_EROM_ASD_SZ_MASK 0x00000030
+#define SSB_EROM_ASD_SZ_SZD 0x00000030
+#define SSB_EROM_ASD_SZ_SHIFT 4
+#define SSB_EROM_ASD_SZ_BASE 0x00001000
+#define SSB_EROM_CI 0
+#define SSB_EROM_CIA_CID_MASK 0x000FFF00
+#define SSB_EROM_CIA_CID_SHIFT 8
+#define SSB_EROM_CIA_MFG_MASK 0xFFF00000
+#define SSB_EROM_CIA_MFG_SHIFT 20
+#define SSB_EROM_CIB_REV_MASK 0xFF000000
+#define SSB_EROM_CIB_REV_SHIFT 24
+#define SSB_EROM_CIB_NMW_MASK 0x0007C000
+#define SSB_EROM_CIB_NMW_SHIFT 14
+#define SSB_EROM_CIB_NSW_MASK 0x00F80000
+#define SSB_EROM_CIB_NSW_SHIFT 19
+#define SSB_EROM_CIB_NSP_MASK 0x00003E00
+#define SSB_EROM_CIB_NSP_SHIFT 9
+
+/* Adress Space Descriptor macro defs */
+#define SSB_EROM_CIA_CID(cia) (((cia) & SSB_EROM_CIA_CID_MASK) >> \
+ SSB_EROM_CIA_CID_SHIFT)
+#define SSB_EROM_CIA_MFG(cia) (((cia) & SSB_EROM_CIA_MFG_MASK) >> \
+ SSB_EROM_CIA_MFG_SHIFT)
+#define SSB_EROM_CIB_REV(cib) (((cib) & SSB_EROM_CIB_REV_MASK) >> \
+ SSB_EROM_CIB_REV_SHIFT)
+#define SSB_EROM_CIB_NMW(cib) (((cib) & SSB_EROM_CIB_NMW_MASK) >> \
+ SSB_EROM_CIB_NMW_SHIFT)
+#define SSB_EROM_CIB_NSW(cib) (((cib) & SSB_EROM_CIB_NSW_MASK) >> \
+ SSB_EROM_CIB_NSW_SHIFT)
+#define SSB_EROM_CIB_NSP(cib) (((cib) & SSB_EROM_CIB_NSP_MASK) >> \
+ SSB_EROM_CIB_NSP_SHIFT)
+
+/* AI config space registers */
+#define SSB_AI_oobselouta30 0x100
+#define SSB_AI_IOCTL 0x408 /* maybe 0x40C for big endian */
+#define SSB_AI_IOSTAT 0x500
+#define SSB_AI_RESETCTL 0x800 /* maybe 0x804 for big endian */
+#define SSB_AI_RESETCTL_RESET 1
+
+extern void ssb_iounmap_ai(struct ssb_bus *bus);
+extern int ssb_bus_scan_ai(struct ssb_bus *bus, unsigned long baseaddr);
+
+#else /* CONFIG_SSB_BUS_AI */
+
+static inline void ssb_iounmap_ai(struct ssb_bus *bus)
+{
+}
+
+static inline int ssb_bus_scan_ai(struct ssb_bus *bus, unsigned long baseaddr)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_SSB_BUS_AI */
+
+#endif /* !LINUX_SSB_AI_H_ */
--- linux-wireless-testing.orig/drivers/ssb/ssb_private.h 2011-02-17 15:56:58.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/ssb_private.h 2011-02-17 15:57:14.000000000 +0200
@@ -4,6 +4,7 @@
#include <linux/ssb/ssb.h>
#include <linux/types.h>
#include "ssb_sb.h"
+#include "ssb_ai.h"
#define PFX "ssb: "
@@ -168,7 +169,10 @@ extern int ssb_bus_check_core(struct ssb
extern u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, u16 offset);
static inline void ssb_iounmap(struct ssb_bus *bus)
{
- ssb_iounmap_sb(bus);
+ if (bus->chipco.chiptype == SSB_CHIPCO_AI)
+ ssb_iounmap_ai(bus);
+ else
+ ssb_iounmap_sb(bus);
}
--- linux-wireless-testing.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-17 15:51:11.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-17 15:57:14.000000000 +0200
@@ -19,6 +19,7 @@
#define SSB_CHIPCO_TYPE_MASK 0xF0000000
#define SSB_CHIPCO_TYPE_SHIFT 28
#define SSB_CHIPCO_TYPE_SB 0
+#define SSB_CHIPCO_TYPE_AI 0x10000000
#define SSB_CHIPCO_IDMASK 0x0000FFFF
#define SSB_CHIPCO_REVMASK 0x000F0000
#define SSB_CHIPCO_REVSHIFT 16
@@ -173,6 +174,7 @@
#define SSB_CHIPCO_SYSCLKCTL_CLKDIV 0xFFFF0000 /* ClkDiv (ILP = 1/(4+divisor)) */
#define SSB_CHIPCO_SYSCLKCTL_CLKDIV_SHIFT 16
#define SSB_CHIPCO_CLKSTSTR 0x00C4 /* Rev >= 3 only */
+#define SSB_CHIPCO_EROM 0x00FC /* EROM for AI socs */
#define SSB_CHIPCO_PCMCIA_CFG 0x0100
#define SSB_CHIPCO_PCMCIA_MEMWAIT 0x0104
#define SSB_CHIPCO_PCMCIA_ATTRWAIT 0x0108
@@ -584,6 +586,7 @@ struct ssb_chipcommon_pmu {
/* Chipcommon implementation type */
enum ssb_chipco_chiptype {
SSB_CHIPCO_SB = SSB_CHIPCO_TYPE(SSB_CHIPCO_TYPE_SB), /* SB-style bus */
+ SSB_CHIPCO_AI = SSB_CHIPCO_TYPE(SSB_CHIPCO_TYPE_AI), /* AI-style bus */
};
struct ssb_chipcommon {
--- linux-wireless-testing.orig/include/linux/ssb/ssb.h 2011-02-17 15:57:09.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb.h 2011-02-17 15:57:14.000000000 +0200
@@ -104,6 +104,46 @@ struct ssb_boardinfo {
struct ssb_device;
+#ifdef CONFIG_SSB_BUS_AI
+/* max no of AI addrspaces */
+#define SSB_AI_MAX_ADDRSPACES 2
+
+struct ssb_bus_aiops {
+ u32 (*read32)(struct ssb_device *dev, u16 offset);
+ void (*write32)(struct ssb_device *dev, u16 offset, u32 value);
+};
+
+struct ssb_aiaddrspace {
+ u32 base;
+ u32 size;
+};
+
+/* AI-style bus device-specific data */
+struct ssb_aidevice {
+ /** Internal stuff, don't use directly **/
+ struct ssb_bus_aiops *ops;
+ /* device cores */
+ struct ssb_aiaddrspace core[SSB_AI_MAX_ADDRSPACES];
+};
+
+/* AI-style bus-specific data */
+struct ssb_aibus {
+ /** Internal stuff, don't use directly **/
+ struct ssb_bus_aiops *ops;
+ /* core wrapper IO area */
+ void __iomem *mmio;
+ /* core, which wrapper is currently mapped into the MMIO window */
+ struct ssb_device *mapped_device;
+};
+#else /* CONFIG_SSB_BUS_AI */
+struct ssb_aidevice {
+};
+
+struct ssb_aibus {
+};
+#endif /* CONFIG_SSB_BUS_AI */
+
+
/* Lowlevel read/write operations on the device MMIO.
* Internal, don't use that outside of ssb. */
struct ssb_bus_ops {
@@ -170,9 +210,11 @@ struct ssb_bus_helpers {
#define SSB_DEV_MIPS_74K 0x82C
#define SSB_DEV_DDR_CTRLR 0x82E
#define SSB_DEV_I2S 0x834
+#define SSB_DEV_DEFAULT 0xFFF
/* Vendor-ID values */
#define SSB_VENDOR_BROADCOM 0x4243
+#define SSB_VENDOR_ARM 0x043B
/* Some kernel subsystems poke with dev->drvdata, so we must use the
* following ugly workaround to get from struct device to struct ssb_device */
@@ -198,6 +240,7 @@ struct ssb_device {
/* Internal-only stuff follows. */
void *drvdata; /* Per-device data */
void *devtypedata; /* Per-devicetype (eg 802.11) data */
+ struct ssb_aidevice ai; /* AI-specific device data */
};
/* Go from struct device to struct ssb_device. */
@@ -364,6 +407,7 @@ struct ssb_bus {
/* Internal-only stuff follows. Do not touch. */
struct list_head list;
+ struct ssb_aibus ai; /* AI-specific bus data */
#ifdef CONFIG_SSB_DEBUG
/* Is the bus already powered up? */
bool powered_up;
--- linux-wireless-testing.orig/include/linux/ssb/ssb_regs.h 2011-02-17 15:40:20.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb_regs.h 2011-02-17 15:57:14.000000000 +0200
@@ -54,6 +54,7 @@
#define SSB_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */
#define SSB_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
#define SSB_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
+#define SSB_BAR0_WIN2 0xAC /* backplane addres space accessed by second 4KB of BAR0 */
#define SSB_BAR0_MAX_RETRIES 50
On Thu, 2011-02-17 at 17:58 +0200, George Kashperko wrote:
> Hi,
>
> Here is fixed and reworked proposal on introducing AI support with
> existing SSB bus codebase. Patches are made agains latest
> wireless-testing git as of writing.
> http://www.znau.edu.ua/temp/ssb-ai-linux-wireless-testing/2011-02-17-ssb-add-AI-support.tar.bz2
Please submit the patches to the list so we can comment on them.
--
Greetings Michael.
On 02/18/2011 05:47 PM, George Kashperko wrote:
> Hi,
>
>> I don't want to get involved in the debate over abstraction, but FWIW, the
>> patchset does work for PCI-based SSB devices.
>>
>> Larry
>>
> Could you please let me know if you tried last code I've posted, as my
> original RFC was indeed embeddables' targeted and won't work for
> SSB-over-PCI.
> Last code I've posted I've tested on SSB over PCIE host and it was
> pretty much working.
I tested the 14 patches you posted on 2/17/2011 that arrived about 10:20 UTC.
Larry
From: George Kashperko <[email protected]>
Modify irqflag routine to reuse tpsflag value rather than
reading TPSFLAG register once again. Change default "not
supported" value from 0x3F to -1.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/driver_mipscore.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/driver_mipscore.c 2011-02-17 14:07:23.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/driver_mipscore.c 2011-02-17 14:11:09.000000000 +0200
@@ -54,12 +54,12 @@ static inline u32 ssb_irqflag(struct ssb
static u32 ssb_irqflag_sb(struct ssb_device *dev)
{
- u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
- if (tpsflag)
- return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+ u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+ if (tpsflag && tpsflag != SSB_TPSFLAG_BPFLAG)
+ return tpsflag;
else
/* not irq supported */
- return 0x3f;
+ return -1;
}
static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag)
@@ -90,7 +90,7 @@ unsigned int ssb_mips_irq(struct ssb_dev
unsigned int irq;
irqflag = ssb_irqflag(dev);
- if (irqflag == 0x3f)
+ if (irqflag == -1)
return 6;
ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG);
for (irq = 1; irq <= 4; irq++) {
On 02/17/2011 07:58 AM, George Kashperko wrote:
> Here is dmesg for AI on embeddable (BCM4716):
> root@OpenWrt:/# dmesg | grep -E "ssb|b43|[Bb]roadcom"
> ssb: Core 0 found: ChipCommon (cc 0x800, rev 0x1F, vendor 0x04BF)
> ssb: Core 1 found: IEEE 802.11 (cc 0x812, rev 0x11, vendor 0x04BF)
> ssb: Core 2 found: Gigabit MAC (cc 0x82D, rev 0x00, vendor 0x04BF)
> ssb: Core 3 found: MIPS 74K (cc 0x82C, rev 0x01, vendor 0x04A7)
> ssb: Core 4 found: USB 2.0 Host (cc 0x819, rev 0x04, vendor 0x04BF)
> ssb: Core 5 found: PCI-E (cc 0x820, rev 0x0E, vendor 0x04BF)
> ssb: Core 6 found: DDR1/2 memory controller (cc 0x82E, rev 0x01, vendor 0x04BF)
> ssb: Core 7 found: Internal Memory (cc 0x80E, rev 0x07, vendor 0x04BF)
> ssb: Core 8 found: I2S (cc 0x834, rev 0x00, vendor 0x04BF)
> ssb: Found END of erom after 9 cores
> ssb: chipcommon status is 0x800
> ssb: Found rev 5 PMU (capabilities 0x11242C05)
> ssb: Initializing MIPS core...
> ssb: ssb_pmu5_clock: p1=1, p2=1, ndiv=48(0x30), m3=8, fc=960, clock=120
> ssb: set_irq: core 0x0812, irq 3 => 3
> ssb: set_irq: core 0x082d, irq 4 => 4
> ssb: set_irq: core 0x0819, irq 5 => 5
> ssb: after irq reconfiguration
> ssb: core 0x0800, irq : 2(S)* 3 4 5 6 D I
> ssb: core 0x0812, irq : 2(S) 3* 4 5 6 D I
> ssb: core 0x082d, irq : 2(S) 3 4* 5 6 D I
> ssb: core 0x082c, irq : 2(S) 3 4 5 6 D I*
> ssb: core 0x0819, irq : 2(S) 3 4 5* 6 D I
> ssb: core 0x0820, irq : 2(S) 3 4 5 6* D I
> ssb: core 0x082e, irq : 2(S)* 3 4 5 6 D I
> ssb: core 0x080e, irq : 2(S) 3 4 5 6 D I*
> ssb: core 0x0834, irq : 2(S)* 3 4 5 6 D I
> ssb: Sonics Silicon Backplane (AI type) found at address 0x18000000
This just reinforces what Michael said about name confusion.
Michael's proposal of separating SSB and AXI, and decoupling the device
drivers from the bus routines, is going to be much more maintainable in
the long run. AXI is going to be far more widespread than SSB ever was,
and it would be really unfortunate if we carry the SSB baggage forward.
I've been poking around at disentangling the sb and ai routines in
drivers/staging/brcm80211/utils/{aiutils,sbutils,siutils}.c. I don't
have anything to put out for comments yet, but it's enough to convince
me that it's the right direction.
- Henry
From: George Kashperko <[email protected]>
Move piece of code out of ssb_bus_scan to introduce
SB-specific bus scan routine.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/scan.c | 67 ++++++++++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 26 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/scan.c 2011-02-17 15:51:11.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 15:53:21.000000000 +0200
@@ -407,14 +407,45 @@ static int ssb_bus_detect(struct ssb_bus
return chiptype == SSB_CHIPCO_SB ? 0 : -ENODEV;
}
-int ssb_bus_scan(struct ssb_bus *bus, unsigned long baseaddr)
+static int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr)
{
- int err = -ENOMEM;
- void __iomem *mmio;
u32 idhi;
int dev_i, i;
struct ssb_device *dev;
int nr_80211_cores = 0;
+ int err;
+
+ /* Fetch basic information about each core/device */
+ for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
+ err = scan_switchcore(bus, i);
+ if (err)
+ return err;
+ dev = &(bus->devices[dev_i]);
+
+ idhi = scan_read32(bus, i, SSB_IDHIGH);
+ dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+ dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
+ dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >>
+ SSB_IDHIGH_RCHI_SHIFT;
+ dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
+ dev->core_index = i;
+ dev->bus = bus;
+ dev->ops = bus->ops;
+ dev->helpers = &ssb_helpers_sb;
+
+ if (ssb_bus_check_core(dev, &nr_80211_cores, i) < 0)
+ continue;
+
+ dev_i++;
+ }
+ bus->nr_devices = dev_i;
+ return 0;
+}
+
+int ssb_bus_scan(struct ssb_bus *bus, unsigned long baseaddr)
+{
+ int err = -ENOMEM;
+ void __iomem *mmio;
mmio = ssb_ioremap(bus, baseaddr);
if (!mmio)
@@ -445,31 +476,15 @@ int ssb_bus_scan(struct ssb_bus *bus, un
bus->mmio = mmio;
}
- /* Fetch basic information about each core/device */
- for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
- err = scan_switchcore(bus, i);
- if (err)
- goto err_unmap;
- dev = &(bus->devices[dev_i]);
-
- idhi = scan_read32(bus, i, SSB_IDHIGH);
- dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
- dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
- dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
- dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
- dev->core_index = i;
- dev->bus = bus;
- dev->ops = bus->ops;
- dev->helpers = &ssb_helpers_sb;
-
- if (ssb_bus_check_core(dev, &nr_80211_cores, i) < 0)
- continue;
-
- dev_i++;
+ switch (bus->chipco.chiptype) {
+ case SSB_CHIPCO_SB:
+ err = ssb_bus_scan_sb(bus, baseaddr);
+ break;
+ default:
+ SSB_WARN_ON(1);
+ err = -ENODEV;
}
- bus->nr_devices = dev_i;
- err = 0;
out:
return err;
err_unmap:
From: George Kashperko <[email protected]>
Add support for AI-style bus on PCI host. This is preliminary
and untested yet.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/ssb_ai.c | 100 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 100 insertions(+)
--- linux-wireless-testing.orig/drivers/ssb/ssb_ai.c 2011-02-17 16:01:51.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/ssb_ai.c 2011-02-17 16:04:43.000000000 +0200
@@ -48,6 +48,93 @@ struct ssb_bus_aiops ssb_ssb_aiops = {
.write32 = ssb_ssb_aiwrite32,
};
+#ifdef CONFIG_SSB_PCIHOST
+#define SSB_VERBOSE_PCICOREAISWITCH_DEBUG 0
+static int ssb_pci_switch_aicoreidx(struct ssb_bus *bus, u8 coreidx)
+{
+ int err;
+ int attempts = 0;
+ u32 cur_core;
+
+ while (true) {
+ err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN2,
+ (coreidx * SSB_CORE_SIZE) +
+ SSB_AI_BASE);
+ if (err)
+ goto error;
+ err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN2,
+ &cur_core);
+ if (err)
+ goto error;
+ cur_core = (cur_core - SSB_AI_BASE)
+ / SSB_CORE_SIZE;
+ if (cur_core == coreidx)
+ break;
+
+ if (attempts++ > SSB_BAR0_MAX_RETRIES)
+ goto error;
+ udelay(10);
+ }
+ return 0;
+error:
+ ssb_printk(KERN_ERR PFX "Failed to switch to AI core %u\n", coreidx);
+ return -ENODEV;
+}
+
+static int ssb_pci_switch_aicore(struct ssb_bus *bus,
+ struct ssb_device *dev)
+{
+ int err;
+ unsigned long flags;
+
+#if SSB_VERBOSE_PCICOREAISWITCH_DEBUG
+ ssb_printk(KERN_INFO PFX
+ "Switching to %s AI core, index %d\n",
+ ssb_core_name(dev->id.coreid),
+ dev->core_index);
+#endif
+
+ spin_lock_irqsave(&bus->bar_lock, flags);
+ err = ssb_pci_switch_aicoreidx(bus, dev->core_index);
+ if (!err)
+ bus->ai.mapped_device = dev;
+ spin_unlock_irqrestore(&bus->bar_lock, flags);
+
+ return err;
+}
+
+static u32 ssb_pci_airead32(struct ssb_device *dev, u16 offset)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ if (unlikely(!bus->powered_up))
+ return 0xFFFFFFFF;
+ if (unlikely(bus->ai.mapped_device != dev)) {
+ if (unlikely(ssb_pci_switch_aicore(bus, dev)))
+ return 0xFFFFFFFF;
+ }
+ return ioread32(bus->ai.mmio + offset);
+}
+
+static void ssb_pci_aiwrite32(struct ssb_device *dev, u16 offset, u32 value)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ if (unlikely(!bus->powered_up))
+ return;
+ if (unlikely(bus->ai.mapped_device != dev)) {
+ if (unlikely(ssb_pci_switch_aicore(bus, dev)))
+ return;
+ }
+ iowrite32(value, bus->ai.mmio + offset);
+}
+
+struct ssb_bus_aiops ssb_pci_aiops = {
+ .read32 = ssb_pci_airead32,
+ .write32 = ssb_pci_aiwrite32,
+};
+#endif /* CONFIG_SSB_PCIHOST */
+
/* The 47162a0 hangs when reading its registers */
static inline bool ssb_bcm47162a0_quirk(struct ssb_device *dev)
{
@@ -188,6 +275,10 @@ void ssb_iounmap_ai(struct ssb_bus *bus)
iounmap(bus->mmio);
iounmap(bus->ai.mmio);
break;
+#ifdef CONFIG_SSB_PCIHOST
+ case SSB_BUSTYPE_PCI:
+ pci_iounmap(bus->host_pci, bus->mmio);
+#endif
default:
break;
}
@@ -263,6 +354,15 @@ int ssb_bus_scan_ai(struct ssb_bus *bus,
if (!eromptr)
return -ENOMEM;
break;
+#ifdef CONFIG_SSB_PCIHOST
+ case SSB_BUSTYPE_PCI:
+ bus->ai.ops = &ssb_pci_aiops;
+ /* point second bar0 window at the EROM */
+ pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN2, erombase);
+ eromptr = bus->mmio;
+ bus->ai.mmio = bus->mmio + 0x1000;
+ break;
+#endif /* CONFIG_SSB_PCIHOST */
default:
return -ENODEV;
}
From: George Kashperko <[email protected]>
Introduce helpers for SB core control and state flags' management. SB-style
buses provide access to these flags at two high octets of TMSLOW and TMSHIGH
registers whereas AI-ones implement these flags in two low octets of IOCTRL
and IOSTAT registers.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/main.c | 17 +++++++++++++++++
include/linux/ssb/ssb.h | 10 ++++++++++
2 files changed, 27 insertions(+)
--- linux-wireless-testing.orig/drivers/ssb/main.c 2011-02-17 14:05:12.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/main.c 2011-02-17 14:15:25.000000000 +0200
@@ -1360,12 +1360,29 @@ static u32 ssb_admatch_size_sb(struct ss
return size;
}
+static u32 ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask, u32 val)
+{
+ if (~mask || val) {
+ u32 tmp = (ssb_read32(dev, SSB_TMSLOW) & mask) | val;
+ ssb_write32(dev, SSB_TMSLOW, tmp);
+ }
+
+ return ssb_read32(dev, SSB_TMSLOW);
+}
+
+static u32 ssb_core_state_flags_sb(struct ssb_device *dev)
+{
+ return ssb_read32(dev, SSB_TMSHIGH);
+}
+
const struct ssb_bus_helpers ssb_helpers_sb = {
.device_is_enabled = ssb_device_is_enabled_sb,
.device_enable = ssb_device_enable_sb,
.device_disable = ssb_device_disable_sb,
.admatch_base = ssb_admatch_base_sb,
.admatch_size = ssb_admatch_size_sb,
+ .core_ctl_flags = ssb_core_ctl_flags_sb,
+ .core_state_flags = ssb_core_state_flags_sb,
};
static int __init ssb_modinit(void)
--- linux-wireless-testing.orig/include/linux/ssb/ssb.h 2011-02-17 14:05:12.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb.h 2011-02-17 14:15:25.000000000 +0200
@@ -128,6 +128,8 @@ struct ssb_bus_helpers {
void (*device_disable)(struct ssb_device *dev, u32 core_specific_flags);
u32 (*admatch_base)(struct ssb_device *dev, u32 adm);
u32 (*admatch_size)(struct ssb_device *dev, u32 adm);
+ u32 (*core_ctl_flags)(struct ssb_device *dev, u32 mask, u32 val);
+ u32 (*core_state_flags)(struct ssb_device *dev);
};
@@ -451,6 +453,14 @@ static inline u32 ssb_admatch_size(struc
{
return dev->helpers->admatch_size(dev, adm);
}
+static inline u32 ssb_core_ctl_flags(struct ssb_device *dev, u32 mask, u32 val)
+{
+ return dev->helpers->core_ctl_flags(dev, mask, val);
+}
+static inline u32 ssb_core_state_flags(struct ssb_device *dev)
+{
+ return dev->helpers->core_state_flags(dev);
+}
/* Device MMIO register read/write functions. */
From: George Kashperko <[email protected]>
Move part of the SB-style bus scan code into separate routine
in order to reuse it later with AI-style bus scan.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/scan.c | 173 +++++++++++++++++++-----------------
drivers/ssb/ssb_private.h | 2
2 files changed, 94 insertions(+), 81 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/scan.c 2011-02-17 14:05:12.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 14:32:49.000000000 +0200
@@ -265,6 +265,96 @@ static int we_support_multiple_80211_cor
return 0;
}
+/* returns 0 if the core is ok and -1 if the core should be ignored */
+int ssb_bus_check_core(struct ssb_device *dev, int *nr_80211_cores, int corenum)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ printk(KERN_DEBUG PFX
+ "Core %d found: %s "
+ "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
+ corenum, ssb_core_name(dev->id.coreid),
+ dev->id.coreid, dev->id.revision, dev->id.vendor);
+
+ switch (dev->id.coreid) {
+ case SSB_DEV_80211:
+ (*nr_80211_cores)++;
+ if (*nr_80211_cores > 1) {
+ if (!we_support_multiple_80211_cores(bus)) {
+ ssb_dprintk(KERN_INFO PFX "Ignoring additional "
+ "802.11 core\n");
+ return -1;
+ }
+ }
+ break;
+ case SSB_DEV_EXTIF:
+#ifdef CONFIG_SSB_DRIVER_EXTIF
+ if (bus->extif.dev) {
+ ssb_printk(KERN_WARNING PFX
+ "WARNING: Multiple EXTIFs found\n");
+ break;
+ }
+ bus->extif.dev = dev;
+#endif /* CONFIG_SSB_DRIVER_EXTIF */
+ break;
+ case SSB_DEV_CHIPCOMMON:
+ if (bus->chipco.dev) {
+ ssb_printk(KERN_WARNING PFX
+ "WARNING: Multiple ChipCommon found\n");
+ break;
+ }
+ bus->chipco.dev = dev;
+ break;
+ case SSB_DEV_MIPS:
+ case SSB_DEV_MIPS_3302:
+#ifdef CONFIG_SSB_DRIVER_MIPS
+ if (bus->mipscore.dev) {
+ ssb_printk(KERN_WARNING PFX
+ "WARNING: Multiple MIPS cores found\n");
+ break;
+ }
+ bus->mipscore.dev = dev;
+#endif /* CONFIG_SSB_DRIVER_MIPS */
+ break;
+ case SSB_DEV_PCI:
+ case SSB_DEV_PCIE:
+#ifdef CONFIG_SSB_DRIVER_PCICORE
+ if (bus->bustype == SSB_BUSTYPE_PCI) {
+ /* Ignore PCI cores on PCI-E cards.
+ * Ignore PCI-E cores on PCI cards. */
+ if (dev->id.coreid == SSB_DEV_PCI) {
+ if (pci_is_pcie(bus->host_pci))
+ return -1;
+ } else {
+ if (!pci_is_pcie(bus->host_pci))
+ return -1;
+ }
+ }
+ if (bus->pcicore.dev) {
+ ssb_printk(KERN_WARNING PFX
+ "WARNING: Multiple PCI(E) cores found\n");
+ break;
+ }
+ bus->pcicore.dev = dev;
+#endif /* CONFIG_SSB_DRIVER_PCICORE */
+ break;
+ case SSB_DEV_ETHERNET:
+ if (bus->bustype == SSB_BUSTYPE_PCI) {
+ if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM &&
+ (bus->host_pci->device & 0xFF00) == 0x4300) {
+ /* This is a dangling ethernet core on a
+ * wireless device. Ignore it. */
+ return -1;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
int ssb_bus_scan(struct ssb_bus *bus,
unsigned long baseaddr)
{
@@ -353,87 +443,8 @@ int ssb_bus_scan(struct ssb_bus *bus,
dev->ops = bus->ops;
dev->helpers = &ssb_helpers_sb;
- printk(KERN_DEBUG PFX
- "Core %d found: %s "
- "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
- i, ssb_core_name(dev->id.coreid),
- dev->id.coreid, dev->id.revision, dev->id.vendor);
-
- switch (dev->id.coreid) {
- case SSB_DEV_80211:
- nr_80211_cores++;
- if (nr_80211_cores > 1) {
- if (!we_support_multiple_80211_cores(bus)) {
- ssb_dprintk(KERN_INFO PFX "Ignoring additional "
- "802.11 core\n");
- continue;
- }
- }
- break;
- case SSB_DEV_EXTIF:
-#ifdef CONFIG_SSB_DRIVER_EXTIF
- if (bus->extif.dev) {
- ssb_printk(KERN_WARNING PFX
- "WARNING: Multiple EXTIFs found\n");
- break;
- }
- bus->extif.dev = dev;
-#endif /* CONFIG_SSB_DRIVER_EXTIF */
- break;
- case SSB_DEV_CHIPCOMMON:
- if (bus->chipco.dev) {
- ssb_printk(KERN_WARNING PFX
- "WARNING: Multiple ChipCommon found\n");
- break;
- }
- bus->chipco.dev = dev;
- break;
- case SSB_DEV_MIPS:
- case SSB_DEV_MIPS_3302:
-#ifdef CONFIG_SSB_DRIVER_MIPS
- if (bus->mipscore.dev) {
- ssb_printk(KERN_WARNING PFX
- "WARNING: Multiple MIPS cores found\n");
- break;
- }
- bus->mipscore.dev = dev;
-#endif /* CONFIG_SSB_DRIVER_MIPS */
- break;
- case SSB_DEV_PCI:
- case SSB_DEV_PCIE:
-#ifdef CONFIG_SSB_DRIVER_PCICORE
- if (bus->bustype == SSB_BUSTYPE_PCI) {
- /* Ignore PCI cores on PCI-E cards.
- * Ignore PCI-E cores on PCI cards. */
- if (dev->id.coreid == SSB_DEV_PCI) {
- if (pci_is_pcie(bus->host_pci))
- continue;
- } else {
- if (!pci_is_pcie(bus->host_pci))
- continue;
- }
- }
- if (bus->pcicore.dev) {
- ssb_printk(KERN_WARNING PFX
- "WARNING: Multiple PCI(E) cores found\n");
- break;
- }
- bus->pcicore.dev = dev;
-#endif /* CONFIG_SSB_DRIVER_PCICORE */
- break;
- case SSB_DEV_ETHERNET:
- if (bus->bustype == SSB_BUSTYPE_PCI) {
- if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM &&
- (bus->host_pci->device & 0xFF00) == 0x4300) {
- /* This is a dangling ethernet core on a
- * wireless device. Ignore it. */
- continue;
- }
- }
- break;
- default:
- break;
- }
+ if (ssb_bus_check_core(dev, &nr_80211_cores, i) < 0)
+ continue;
dev_i++;
}
--- linux-wireless-testing.orig/drivers/ssb/ssb_private.h 2011-02-17 14:28:49.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/ssb_private.h 2011-02-17 14:29:06.000000000 +0200
@@ -160,6 +160,8 @@ extern const char *ssb_core_name(u16 cor
extern int ssb_bus_scan(struct ssb_bus *bus,
unsigned long baseaddr);
extern void ssb_iounmap(struct ssb_bus *ssb);
+extern int ssb_bus_check_core(struct ssb_device *dev, int *nr_80211_cores,
+ int corenum);
/* sprom.c */
Hi,
> On Fri, 2011-02-18 at 00:31 +0200, George Kashperko wrote:
> > +#define SSB_AI_BASE 0x18100000U /* base for AI registers */
>
> #define MOON_EARTH_BASE 1337
>
> That probably is my major point against this patchset. It just
> merges things that don't belong to each other.
> Is this the base on moon or earth?
> If it's the earth base, why the hell do we prefix the define with MOON?
>
> That naming confusion continues throughout the whole patchset.
>
> SSB is end of life, so we should not try to support the new AI hardware
> by making SSB AI aware. Just fork SSB and let legacy SSB die as the
> existing hardware dies. It deserves it. Mercy killing for software!
>
> _Currently_ it may look like a good idea to use one software base
> for the two busses, but the cruft will hurt you in the future.
> And the future begins one day after this hack was merged.
>
Well, if that was year ago I would agree with you. Now I doubt it.
Starting from the clean page means another months of no support for
AI-based hw. Going cp ssb bcmai; sed s/ssb/bcmai way will make whole
messup. Making AI over SSB causing confusion.
Either way here for me looks wrong, but among them I would better choose
on going 1+3 rather just 1st one alone.
Ah, well, there might is another 4th way to go if Broadcom will finally
support their bus with their brand code but honestly (no offence to
Broadcom here, just my personal subjective opinion) I dont think I will
be happy to see this code after all that I've already seen.
Clean page is the best. The best is the enemy for the good.
Have nice day,
George