From: George Kashperko <george@xxxxxxxxxxx> Separate SB-specific code in single file. Signed-off-by: George Kashperko <george@xxxxxxxxxxx> --- drivers/ssb/Kconfig | 11 + drivers/ssb/Makefile | 1 drivers/ssb/driver_mipscore.c | 10 drivers/ssb/main.c | 248 +--------------------- drivers/ssb/scan.c | 39 --- drivers/ssb/ssb_private.h | 48 ++-- drivers/ssb/ssb_sb.c | 281 ++++++++++++++++++++++++++ drivers/ssb/ssb_sb.h | 28 ++ include/linux/ssb/ssb_driver_mips.h | 1 9 files changed, 360 insertions(+), 307 deletions(-) --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-08 16:08:31.000000000 +0200 +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-08 16:08:22.000000000 +0200 @@ -47,16 +47,6 @@ static const u32 ipsflag_irq_shift[] = { SSB_IPSFLAG_IRQ4_SHIFT, }; -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; - else - /* not irq supported */ - return 0x3f; -} - static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) { struct ssb_bus *bus = rdev->bus; --- linux-next-20110203.orig/drivers/ssb/Kconfig 2011-02-08 16:08:31.000000000 +0200 +++ linux-next-20110203/drivers/ssb/Kconfig 2011-02-08 15:48:41.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-next-20110203.orig/drivers/ssb/main.c 2011-02-08 16:08:31.000000000 +0200 +++ linux-next-20110203/drivers/ssb/main.c 2011-02-08 15:48:41.000000000 +0200 @@ -49,8 +49,6 @@ static bool ssb_is_early_boot = 1; static void ssb_buses_lock(void); static void ssb_buses_unlock(void); -static const struct ssb_bus_ops ssb_ssb_ops; - #ifdef CONFIG_SSB_PCIHOST struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev) @@ -593,7 +591,7 @@ error: return err; } -static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset) +u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; @@ -601,7 +599,7 @@ static u8 ssb_ssb_read8(struct ssb_devic return readb(bus->mmio + offset); } -static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) +u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; @@ -609,7 +607,7 @@ static u16 ssb_ssb_read16(struct ssb_dev return readw(bus->mmio + offset); } -static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset) +u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; @@ -618,8 +616,8 @@ static u32 ssb_ssb_read32(struct ssb_dev } #ifdef CONFIG_SSB_BLOCKIO -static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer, - size_t count, u16 offset, u8 reg_width) +void ssb_ssb_block_read(struct ssb_device *dev, void *buffer, + size_t count, u16 offset, u8 reg_width) { struct ssb_bus *bus = dev->bus; void __iomem *addr; @@ -666,7 +664,7 @@ static void ssb_ssb_block_read(struct ss } #endif /* CONFIG_SSB_BLOCKIO */ -static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value) +void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value) { struct ssb_bus *bus = dev->bus; @@ -674,7 +672,7 @@ static void ssb_ssb_write8(struct ssb_de writeb(value, bus->mmio + offset); } -static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) +void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) { struct ssb_bus *bus = dev->bus; @@ -682,7 +680,7 @@ static void ssb_ssb_write16(struct ssb_d writew(value, bus->mmio + offset); } -static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value) +void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value) { struct ssb_bus *bus = dev->bus; @@ -691,8 +689,8 @@ static void ssb_ssb_write32(struct ssb_d } #ifdef CONFIG_SSB_BLOCKIO -static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer, - size_t count, u16 offset, u8 reg_width) +void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer, + size_t count, u16 offset, u8 reg_width) { struct ssb_bus *bus = dev->bus; void __iomem *addr; @@ -928,7 +926,6 @@ int ssb_bus_ssbbus_register(struct ssb_b int err; bus->bustype = SSB_BUSTYPE_SSB; - bus->ops = &ssb_ssb_ops; err = ssb_bus_register(bus, get_invariants, baseaddr); if (!err) { @@ -1117,89 +1114,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; @@ -1222,33 +1140,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) { @@ -1319,121 +1210,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 void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask, - u32 val, u32 *res) -{ - u32 tmp; - - SSB_WARN_ON((mask | val) & 0xFFFF0000); - - if (mask || val) { - tmp = (ssb_read32(dev, SSB_TMSLOW) & - ~(mask << SSB_TMSLOW_FLAGS_SHIFT)) | - (val << SSB_TMSLOW_FLAGS_SHIFT); - ssb_write32(dev, SSB_TMSLOW, tmp); - } - - /* readback */ - tmp = ssb_read32(dev, SSB_TMSLOW) >> SSB_TMSLOW_FLAGS_SHIFT; - udelay(1); - - if (res) - *res = tmp; -} - -static u32 ssb_core_state_flags_sb(struct ssb_device *dev, u32 mask, u32 val) -{ - u32 tmp; - - SSB_WARN_ON((mask | val) & 0xFFFF0000); - - if (mask || val) { - tmp = (ssb_read32(dev, SSB_TMSHIGH) & - ~(mask << SSB_TMSHIGH_FLAGS_SHIFT)) | - (val << SSB_TMSHIGH_FLAGS_SHIFT); - ssb_write32(dev, SSB_TMSHIGH, tmp); - } - - /* readback */ - tmp = ssb_read32(dev, SSB_TMSHIGH) >> SSB_TMSHIGH_FLAGS_SHIFT; - udelay(1); - - return tmp; -} - -/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ -static const struct ssb_bus_ops ssb_ssb_ops = { - .read8 = ssb_ssb_read8, - .read16 = ssb_ssb_read16, - .read32 = ssb_ssb_read32, - .write8 = ssb_ssb_write8, - .write16 = ssb_ssb_write16, - .write32 = ssb_ssb_write32, -#ifdef CONFIG_SSB_BLOCKIO - .block_read = ssb_ssb_block_read, - .block_write = ssb_ssb_block_write, -#endif - .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, - .irqflag = ssb_irqflag_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-next-20110203.orig/drivers/ssb/Makefile 2011-02-08 16:08:31.000000000 +0200 +++ linux-next-20110203/drivers/ssb/Makefile 2011-02-08 15:48:41.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-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 16:08:31.000000000 +0200 +++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 15:48:41.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,7 +183,7 @@ static u32 scan_read32(struct ssb_bus *b return readl(bus->mmio + offset); } -static int scan_switchcore(struct ssb_bus *bus, u8 coreidx) +int scan_switchcore(struct ssb_bus *bus, u8 coreidx) { switch (bus->bustype) { case SSB_BUSTYPE_SSB: @@ -405,40 +404,6 @@ static int ssb_bus_detect(struct ssb_bus return chiptype != SSB_CHIPCO_SB; } -int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr) -{ - int err; - u32 idhi; - int dev_i, i; - struct ssb_device *dev; - int nr_80211_cores = 0; - - /* 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; - - 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) { --- linux-next-20110203.orig/drivers/ssb/ssb_private.h 2011-02-08 16:08:31.000000000 +0200 +++ linux-next-20110203/drivers/ssb/ssb_private.h 2011-02-08 15:48:41.000000000 +0200 @@ -205,33 +205,35 @@ static inline void b43_pci_ssb_bridge_ex } #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ +/* device mmio access helpers */ +extern u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset); +extern u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset); +extern u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset); +extern void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value); +extern void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value); +extern void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value); +#ifdef CONFIG_SSB_BLOCKIO +extern void ssb_ssb_block_read(struct ssb_device *dev, void *buffer, + size_t count, u16 offset, u8 reg_width); +extern void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer, + size_t count, u16 offset, u8 reg_width); +#endif /* CONFIG_SSB_BLOCKIO */ +extern int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask, + int timeout, int set); /* Search support routines */ +extern u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, u16 offset); +extern int scan_switchcore(struct ssb_bus *bus, u8 coreidx); extern int ssb_bus_check_core(struct ssb_device *dev, int *nr_80211_cores, int corenum); -/* 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 */ +#ifdef CONFIG_SSB_BUS_SB +extern int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr); +#else /* CONFIG_SSB_BUS_SB */ +static inline int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr) +{ + return -ENODEV; +} +#endif /* CONFIG_SSB_BUS_SB */ #endif /* LINUX_SSB_PRIVATE_H_ */ --- linux-next-20110203.orig/drivers/ssb/ssb_sb.c 1970-01-01 03:00:00.000000000 +0300 +++ linux-next-20110203/drivers/ssb/ssb_sb.c 2011-02-08 16:08:43.000000000 +0200 @@ -0,0 +1,281 @@ +/* + * Sonics Silicon Backplane + * Subsystem core + * + * Copyright 2005, Broadcom Corporation + * Copyright 2006, 2007, Michael Buesch <mb@xxxxxxxxx> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include <linux/ssb/ssb.h> +#include <linux/delay.h> + +#include "ssb_private.h" +#include "ssb_sb.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_irqflag_sb(struct ssb_device *dev) +{ + u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); + if (tpsflag) + return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; + else + /* not irq supported */ + return 0x3f; +} + +static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask, + u32 val, u32 *res) +{ + u32 tmp; + + SSB_WARN_ON((mask | val) & 0xFFFF0000); + + if (mask || val) { + tmp = (ssb_read32(dev, SSB_TMSLOW) & + ~(mask << SSB_TMSLOW_FLAGS_SHIFT)) | + (val << SSB_TMSLOW_FLAGS_SHIFT); + ssb_write32(dev, SSB_TMSLOW, tmp); + } + + /* readback */ + tmp = ssb_read32(dev, SSB_TMSLOW) >> SSB_TMSLOW_FLAGS_SHIFT; + udelay(1); + + if (res) + *res = tmp; +} + +static u32 ssb_core_state_flags_sb(struct ssb_device *dev, u32 mask, u32 val) +{ + u32 tmp; + + SSB_WARN_ON((mask | val) & 0xFFFF0000); + + if (mask || val) { + tmp = (ssb_read32(dev, SSB_TMSHIGH) & + ~(mask << SSB_TMSHIGH_FLAGS_SHIFT)) | + (val << SSB_TMSHIGH_FLAGS_SHIFT); + ssb_write32(dev, SSB_TMSHIGH, tmp); + } + + /* readback */ + tmp = ssb_read32(dev, SSB_TMSHIGH) >> SSB_TMSHIGH_FLAGS_SHIFT; + udelay(1); + + return tmp; +} + +/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ +static const struct ssb_bus_ops ssb_ssb_ops = { + .read8 = ssb_ssb_read8, + .read16 = ssb_ssb_read16, + .read32 = ssb_ssb_read32, + .write8 = ssb_ssb_write8, + .write16 = ssb_ssb_write16, + .write32 = ssb_ssb_write32, +#ifdef CONFIG_SSB_BLOCKIO + .block_read = ssb_ssb_block_read, + .block_write = ssb_ssb_block_write, +#endif + .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, + .irqflag = ssb_irqflag_sb, + .core_ctl_flags = ssb_core_ctl_flags_sb, + .core_state_flags = ssb_core_state_flags_sb, +}; + +int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr) +{ + int err; + u32 idhi; + int dev_i, i; + struct ssb_device *dev; + int nr_80211_cores = 0; + + /* 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; + + if (ssb_bus_check_core(dev, &nr_80211_cores, i) < 0) + continue; + + dev_i++; + } + bus->nr_devices = dev_i; + return 0; +} + --- linux-next-20110203.orig/drivers/ssb/ssb_sb.h 1970-01-01 03:00:00.000000000 +0300 +++ linux-next-20110203/drivers/ssb/ssb_sb.h 2011-02-08 15:48:41.000000000 +0200 @@ -0,0 +1,28 @@ +#ifndef LINUX_SSB_SB_H_ +#define LINUX_SSB_SB_H_ + +/* 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_SB_H_ */ --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-08 16:08:31.000000000 +0200 +++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-08 15:48:41.000000000 +0200 @@ -29,7 +29,6 @@ extern void ssb_mipscore_init(struct ssb extern u32 ssb_cpu_clock(struct ssb_mipscore *mcore); extern unsigned int ssb_mips_irq(struct ssb_device *dev); -extern u32 ssb_irqflag_sb(struct ssb_device *dev); #else /* CONFIG_SSB_DRIVER_MIPS */ -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html