Hi guys.
Starting this thread in order to discuss SSB AI support. Recently there
were discussion on this matter but unfortunately missed it therefore
starting new thread.
Recently was playing around making new kernels work on ASUS RT-N16
(bcm4716-based with AI style bus). Started with commits by Bernhard Loos
early 2010, and finally managed to get things work.
Currently with code modified/added mine bcm4716 have working usb
ehci/ohci and ethernet. Well, its pretty much everything the box have,
except wifi - currently i'm half-way done with porting bcm80211 nphy
code changes to b43 (Hopefully recent commits by Rafal Milecki will save
me from porting more, but haven't tried it yet).
All changes made were tested on SB-based hardware (two old bcm5354-based
boxes). Unfortunately have no access to other BCM hw I could test things
on, but I'm pretty much sure old hardware should not be affected by code
changes while newer ones have some chance to get supported.
Changes made are based on ASUS GPL sourcecodes for N16, bcm80211 staging
code and bcm-v4.sipsolutions.net researches.
I will post patches here as soon as get this message back in my emailer
to keep things in single thread.
Please note these changes are how things work for me. It's not commit
request or anything alike. Most of the changes are easy, while some
(well, actually just one - 5th patch with core state/control management
propagation) should be well thought of before applying. Actually things
with 5th patch could be done in completely backwards way - keep existing
TMSLOW/TMSHIGH defines intact with flags in two high bytes and do ">>
16" things in AI code instead of "<< 16" in SB code but again - its just
the way things work for me currently, not the way I could insist or
something on.
This is partial subset of changes to get newer BCM4716s' to work with
linux. If anyone is interested the whole set of patches will be
accessible in few hours via http - just left few things to manage with
them.
В Срд, 09/02/2011 в 22:50 +0100, Rafał Miłecki пишет:
> 2011/2/9 George Kashperko <[email protected]>:
> >> 2011/2/9 George Kashperko <[email protected]>:
> >> > 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 masked under some
> >> > indirect access handlers. This patch forces use of ssb_core_ctl_flags
> >> > and ssb_core_state_flags introduced early. 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 | 61 +++++++------------
> >> > 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 | 52 +++++-----------
> >> > drivers/net/wireless/b43legacy/phy.c | 2
> >> > drivers/ssb/driver_gige.c | 19 ++---
> >> > drivers/ssb/main.c | 20 ++++--
> >> > 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, 160 insertions(+), 162 deletions(-)
> >> > --- linux-next-20110203.orig/drivers/net/b44.c 2011-02-01 05:05:49.000000000 +0200
> >> > +++ linux-next-20110203/drivers/net/b44.c 2011-02-08 12:17:03.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, NULL);
> >> > 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-next-20110203.orig/drivers/net/wireless/b43/b43.h 2011-02-01 05:05:49.000000000 +0200
> >> > +++ linux-next-20110203/drivers/net/wireless/b43/b43.h 2011-02-08 12:17:03.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) */
> >>
> >> I don't know, I've doubts about it :/ That flags are quite messy, mask
> >> for them is 0x3FFC0000. Ideally we should shift it by 14 bits, but
> >> that would make writing code harder. Maaaaybe... Michael what do you
> >> think about this?
> >>
> >>
> >> > @@ -1213,6 +1214,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);
> >>
> >> Make it ~0x00003FFC, value 0x1 is not valid flag.
> > Actual mask for _core_ flags is 0xFFFF0000 for SB and 0x0000FFFF for AI.
>
> OK.
>
>
> > 0x3FFC is mask for core dependent flags.
> > SSB_CORECTL_CLOCK | SSB_CORECTL_FGC | SSB_CORECTL_PE | SSB_CORECTL_BE |
> > 0x3FFC = 0xFFFF
> > Therefore sanity check for SB is &0xFFFF0000, for AI is &0x0000FFFF
> > Layout of core flags in these 2 bytes is the same for AI and SB cores.
>
> You created WARN_ON against core_specific_flags, not sth like
> core_flags. That's why I think test should be against 0x3FFC, not
> 0xFFFF. Am I wrong? Or if we ever pass not-core-specific flags to
> ssb_device_disable/ssb_device_enable, we should rename variable from
> core_specific_flags to core_flags.
>
core_specific_flags is original param name for long time (think from the time ssb_device_enable/disable born but frankly never checked)
this name never reflected actual flags' meaning before AI, wont reflect
it after. Core specific flags are e. g. B43_TMSLOW_GMODE or
B43_TMSLOW_PHYRESET while SSB_TMSLOW_FGC/SSB_TMSLOW_CLOCK are core
independent ones present for all cores (at least for those with device
drivers you know :p)
We pass both core specific and core independent flags to get sertain
devices enabled/reset therefore just core_flags looks bits cleaner for
me, but actually see no reason to rename it as this would actually
change nothing for those who know what that flags are for and again
nothing for those who have no clue about them ;)
> >> Why don't you go ahead and make core flags u16?
> >>
> > Dont see any problems with this as other 2 bytes aint used currently in
> > any way.
>
> You do not see problems with making it u16, or problems with it being u32?
>
No problem at all with doing it u16 _if_ modify all the (B43|B44|GIGE|
etc)_TM(SLOW|HIGH) defines to use 2 bytes instead of 4.
В Срд, 09/02/2011 в 21:35 +0100, Rafał Miłecki пишет:
> 2011/2/9 George Kashperko <[email protected]>:
> > From: George Kashperko <[email protected]>
> >
> > Introduce handlers 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 | 36 ++++++++++++++++++++++++++++++++++++
> > include/linux/ssb/ssb.h | 14 +++++++++++++-
> > 2 files changed, 49 insertions(+), 1 deletion(-)
> > --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:58:50.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 17:07:11.000000000 +0200
> > @@ -1350,6 +1350,40 @@ static u32 ssb_admatch_size_sb(struct ss
> > return size;
> > }
> >
> > +static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
> > + u32 val, u32 *res)
> > +{
> > + u32 tmp;
> > +
> > + if (mask || val) {
> > + tmp = (ssb_read32(dev, SSB_TMSLOW) & ~mask) | val;
> > + ssb_write32(dev, SSB_TMSLOW, tmp);
> > + }
>
> Are you going to use that function for just reading SSB_TMSLOW? Why
> won't you use separated function then? Do you need separated function
> for sth so simple as "ssb_read32(dev, SSB_TMSLOW);" at all?
Will answer your question with another question ;)
What would you personally prefer (press "1" or "2" :p)?
1)
if (sb_bus)
ssb_write32(dev, (ssb_read32(dev, SSB_TMSLOW) & ~(mask << 16)) | (flags << 16));
else
ssb_write32(dev, (ssb_read32(dev, SSB_AI_IOCTL) & ~mask) | flags));
2)
ssb_core_ctl_flags(dev, mask, flags, NULL);
>
> > + /* readback */
> > + tmp = ssb_read32(dev, SSB_TMSLOW);
> > + udelay(1);
> > +
> > + if (res)
> > + *res = tmp;
> > +}
>
> Why are you returning value by writing to pointed place? Can't you
> simply return it? Does returning complicate code so much, it is worth
> using that non-common solution?
>
If retval would be some memory location or this register accessor will
be used 99% of time just for reading (like ssb_core_state_flags is) I
would just <return retval;> like usual. Declared it in such (don't
really think its complicated, maybe just unusual?) manner just to speed
up things a little bit as io access is somewhat different from direct
(and mostly cached) memory access. This way of doing things changes
almost nothing for SB buses as TMSLOW requires readback to flush changes
posted, whereas readback for SSB_AI_IOCTL is not required and thus
return without reading will save some cpu time.
Not really huge optimisation, I know. Espesially considering how much
often it would be called. If you don't like it feel free to change void
to u32. Personally I dont like that u32 *res anyway ;)
Have nice day,
George
W dniu 9 lutego 2011 21:35 użytkownik Rafał Miłecki <[email protected]> napisał:
> 2011/2/9 George Kashperko <[email protected]>:
>> From: George Kashperko <[email protected]>
>>
>> Introduce handlers 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 | 36 ++++++++++++++++++++++++++++++++++++
>> include/linux/ssb/ssb.h | 14 +++++++++++++-
>> 2 files changed, 49 insertions(+), 1 deletion(-)
>> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:58:50.000000000 +0200
>> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 17:07:11.000000000 +0200
>> @@ -1350,6 +1350,40 @@ static u32 ssb_admatch_size_sb(struct ss
>> return size;
>> }
>>
>> +static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
>> + u32 val, u32 *res)
>> +{
>> + u32 tmp;
>> +
>> + if (mask || val) {
>> + tmp = (ssb_read32(dev, SSB_TMSLOW) & ~mask) | val;
>> + ssb_write32(dev, SSB_TMSLOW, tmp);
>> + }
>
> Are you going to use that function for just reading SSB_TMSLOW? Why
> won't you use separated function then? Do you need separated function
> for sth so simple as "ssb_read32(dev, SSB_TMSLOW);" at all?
In b43 we used to implement mask other way:
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
{
b43_radio_write16(dev, offset,
(b43_radio_read16(dev, offset) & mask) | set);
}
I don't vote for any option, but I think we should one method everywhere.
(mask vs. ~mask)
--
Rafał
From: George Kashperko <[email protected]>
Separate SB-specific code in single file.
Signed-off-by: George Kashperko <[email protected]>
---
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 <[email protected]>
+ *
+ * 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 */
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 masked under some
indirect access handlers. This patch forces use of ssb_core_ctl_flags
and ssb_core_state_flags introduced early. 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 | 61 +++++++------------
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 | 52 +++++-----------
drivers/net/wireless/b43legacy/phy.c | 2
drivers/ssb/driver_gige.c | 19 ++---
drivers/ssb/main.c | 20 ++++--
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, 160 insertions(+), 162 deletions(-)
--- linux-next-20110203.orig/drivers/net/b44.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/b44.c 2011-02-08 12:17:03.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, NULL);
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-next-20110203.orig/drivers/net/wireless/b43/b43.h 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43/b43.h 2011-02-08 12:17:03.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-next-20110203.orig/drivers/net/wireless/b43/dma.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43/dma.c 2011-02-08 12:17:03.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, 0, 0);
+ 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-next-20110203.orig/drivers/net/wireless/b43/main.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43/main.c 2011-02-08 12:17:03.000000000 +0200
@@ -1145,26 +1145,20 @@ 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, NULL);
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, NULL);
msleep(1);
/* Turn Analog ON, but only if we already know the PHY-type.
@@ -1176,7 +1170,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 +2102,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, 0, 0);
if ((rev >= 5) && (rev <= 10))
filename = "ucode5";
else if ((rev >= 11) && (rev <= 12))
@@ -2151,7 +2145,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 +2189,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 +2835,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 +2913,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, NULL);
b43_write16(dev, B43_MMIO_POWERUP_DELAY,
dev->dev->bus->chipco.fast_pwrup_delay);
@@ -3443,19 +3435,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, NULL);
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, NULL);
msleep(1);
}
@@ -4328,7 +4313,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 +4740,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, 0, 0);
+ 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 +4799,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-next-20110203.orig/drivers/net/wireless/b43/phy_g.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43/phy_g.c 2011-02-08 12:17:03.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-next-20110203.orig/drivers/net/wireless/b43/phy_n.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43/phy_n.c 2011-02-08 12:17:03.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, NULL);
}
/* 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, NULL);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
--- linux-next-20110203.orig/drivers/net/wireless/b43legacy/b43legacy.h 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43legacy/b43legacy.h 2011-02-08 12:17:03.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-next-20110203.orig/drivers/net/wireless/b43legacy/dma.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43legacy/dma.c 2011-02-08 12:17:03.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, 0, 0);
+ if (tmp & SSB_CORESTAT_DMA64)
return DMA_BIT_MASK(64);
mmio_base = b43legacy_dmacontroller_base(0, 0);
b43legacy_write32(dev,
--- linux-next-20110203.orig/drivers/net/wireless/b43legacy/main.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43legacy/main.c 2011-02-08 12:27:40.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, NULL);
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, NULL);
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, 0, 0);
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, NULL);
b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY,
dev->dev->bus->chipco.fast_pwrup_delay);
@@ -2525,19 +2517,13 @@ 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, NULL);
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,
+ NULL);
msleep(1);
}
@@ -3258,7 +3244,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 +3626,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, 0, 0);
+ have_gphy = !!(state & B43legacy_CORESTAT_GPHY);
if (!have_gphy)
have_bphy = 1;
} else if (dev->dev->id.revision == 4)
@@ -3653,7 +3639,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 +3665,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-next-20110203.orig/drivers/net/wireless/b43legacy/phy.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/net/wireless/b43legacy/phy.c 2011-02-08 12:17:03.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-next-20110203.orig/drivers/ssb/driver_gige.c 2011-02-08 12:17:09.000000000 +0200
+++ linux-next-20110203/drivers/ssb/driver_gige.c 2011-02-08 12:17:03.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,18 @@ 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, 0, 0);
+ 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 |
+ SSB_GIGE_CORECTL_DLLEN, ctl, NULL);
ssb_set_drvdata(sdev, dev);
register_pci_controller(&dev->pci_controller);
--- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-08 12:17:14.000000000 +0200
+++ linux-next-20110203/drivers/ssb/main.c 2011-02-08 12:19:04.000000000 +0200
@@ -1154,6 +1154,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);
@@ -1213,6 +1214,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);
@@ -1355,13 +1359,17 @@ static void ssb_core_ctl_flags_sb(struct
{
u32 tmp;
+ SSB_WARN_ON((mask | val) & 0xFFFF0000);
+
if (mask || val) {
- tmp = (ssb_read32(dev, SSB_TMSLOW) & ~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);
+ tmp = ssb_read32(dev, SSB_TMSLOW) >> SSB_TMSLOW_FLAGS_SHIFT;
udelay(1);
if (res)
@@ -1372,13 +1380,17 @@ static u32 ssb_core_state_flags_sb(struc
{
u32 tmp;
+ SSB_WARN_ON((mask | val) & 0xFFFF0000);
+
if (mask || val) {
- tmp = (ssb_read32(dev, SSB_TMSHIGH) & ~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);
+ tmp = ssb_read32(dev, SSB_TMSHIGH) >> SSB_TMSHIGH_FLAGS_SHIFT;
udelay(1);
return tmp;
--- linux-next-20110203.orig/drivers/ssb/ssb_private.h 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/ssb/ssb_private.h 2011-02-08 12:17:03.000000000 +0200
@@ -206,4 +206,28 @@ static inline void b43_pci_ssb_bridge_ex
}
#endif /* CONFIG_SSB_B43_PCI_BRIDGE */
+/* 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-next-20110203.orig/drivers/usb/host/ohci-ssb.c 2011-02-08 12:17:09.000000000 +0200
+++ linux-next-20110203/drivers/usb/host/ohci-ssb.c 2011-02-08 12:17:03.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-next-20110203.orig/include/linux/ssb/ssb_driver_gige.h 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb_driver_gige.h 2011-02-08 12:17:03.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 0x00010000 /* Have an RGMII PHY-bus */
+/* Gige core status flags */
+#define SSB_GIGE_CORECTL_TXBYPASS 0x00080000 /* TX bypass (no delay) */
+#define SSB_GIGE_CORECTL_RXBYPASS 0x00100000 /* RX bypass (no delay) */
+#define SSB_GIGE_CORECTL_DLLEN 0x01000000 /* Enable DLL controls */
/* Boardflags (low) */
#define SSB_GIGE_BFL_ROBOSWITCH 0x0010
--- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-08 12:17:14.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-08 12:20:04.000000000 +0200
@@ -468,14 +468,14 @@ static inline int ssb_device_is_enabled(
{
return dev->ops->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->ops->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-next-20110203.orig/include/linux/ssb/ssb_regs.h 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb_regs.h 2011-02-08 12:17:03.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 */
2011/2/9 George Kashperko <[email protected]>:
>> 2011/2/9 George Kashperko <[email protected]>:
>> > 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 masked under some
>> > indirect access handlers. This patch forces use of ssb_core_ctl_flags
>> > and ssb_core_state_flags introduced early. 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 | 61 +++++++------------
>> > 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 | 52 +++++-----------
>> > drivers/net/wireless/b43legacy/phy.c | 2
>> > drivers/ssb/driver_gige.c | 19 ++---
>> > drivers/ssb/main.c | 20 ++++--
>> > 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, 160 insertions(+), 162 deletions(-)
>> > --- linux-next-20110203.orig/drivers/net/b44.c 2011-02-01 05:05:49.000000000 +0200
>> > +++ linux-next-20110203/drivers/net/b44.c 2011-02-08 12:17:03.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, NULL);
>> > 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-next-20110203.orig/drivers/net/wireless/b43/b43.h 2011-02-01 05:05:49.000000000 +0200
>> > +++ linux-next-20110203/drivers/net/wireless/b43/b43.h 2011-02-08 12:17:03.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) */
>>
>> I don't know, I've doubts about it :/ That flags are quite messy, mask
>> for them is 0x3FFC0000. Ideally we should shift it by 14 bits, but
>> that would make writing code harder. Maaaaybe... Michael what do you
>> think about this?
>>
>>
>> > @@ -1213,6 +1214,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);
>>
>> Make it ~0x00003FFC, value 0x1 is not valid flag.
> Actual mask for _core_ flags is 0xFFFF0000 for SB and 0x0000FFFF for AI.
OK.
> 0x3FFC is mask for core dependent flags.
> SSB_CORECTL_CLOCK | SSB_CORECTL_FGC | SSB_CORECTL_PE | SSB_CORECTL_BE |
> 0x3FFC = 0xFFFF
> Therefore sanity check for SB is &0xFFFF0000, for AI is &0x0000FFFF
> Layout of core flags in these 2 bytes is the same for AI and SB cores.
You created WARN_ON against core_specific_flags, not sth like
core_flags. That's why I think test should be against 0x3FFC, not
0xFFFF. Am I wrong? Or if we ever pass not-core-specific flags to
ssb_device_disable/ssb_device_enable, we should rename variable from
core_specific_flags to core_flags.
>> Why don't you go ahead and make core flags u16?
>>
> Dont see any problems with this as other 2 bytes aint used currently in
> any way.
You do not see problems with making it u16, or problems with it being u32?
--
Rafał
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-next-20110203.orig/drivers/ssb/driver_gige.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/ssb/driver_gige.c 2011-02-05 17:41:30.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-next-20110203.orig/drivers/ssb/main.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/ssb/main.c 2011-02-05 17:42:37.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-next-20110203.orig/drivers/usb/host/ohci-ssb.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/usb/host/ohci-ssb.c 2011-02-05 17:44:59.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-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-05 17:40:13.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 02/09/2011 12:23 PM, George Kashperko wrote:
> >
> >> On 02/09/2011 11:10 AM, George Kashperko wrote:
> >>>> On 02/09/2011 08:32 AM, George Kashperko wrote:
> >>>>> 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 device op.
> >>>>> Signed-off-by: George Kashperko <[email protected]>
> >>>>> ---
> >>>>> drivers/ssb/driver_mipscore.c | 2 +-
> >>>>> drivers/ssb/main.c | 1 +
> >>>>> include/linux/ssb/ssb.h | 5 +++++
> >>>>> include/linux/ssb/ssb_driver_mips.h | 1 +
> >>>>> 4 files changed, 8 insertions(+), 1 deletion(-)
> >>>>> --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-01 05:05:49.000000000 +0200
> >>>>> +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-07 16:39:46.000000000 +0200
> >>>>> @@ -47,7 +47,7 @@ static const u32 ipsflag_irq_shift[] = {
> >>>>> SSB_IPSFLAG_IRQ4_SHIFT,
> >>>>> };
> >>>>>
> >>>>> -static inline u32 ssb_irqflag(struct ssb_device *dev)
> >>>>> +u32 ssb_irqflag_sb(struct ssb_device *dev)
> >>>>> {
> >>>>> u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
> >>>>> if (tpsflag)
> >>>>> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:35:50.000000000 +0200
> >>>>> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:49:40.000000000 +0200
> >>>>> @@ -1367,6 +1367,7 @@ static const struct ssb_bus_ops ssb_ssb_
> >>>>> .device_disable = ssb_device_disable_sb,
> >>>>> .admatch_base = ssb_admatch_base_sb,
> >>>>> .admatch_size = ssb_admatch_size_sb,
> >>>>> + .irqflag = ssb_irqflag_sb,
> >>>>> };
> >>>>>
> >>>>> static int __init ssb_modinit(void)
> >>>>> --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-01 05:05:49.000000000 +0200
> >>>>> +++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-07 16:39:10.000000000 +0200
> >>>>> @@ -29,6 +29,7 @@ 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 */
> >>>>> --- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:35:50.000000000 +0200
> >>>>> +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:38:34.000000000 +0200
> >>>>> @@ -124,6 +124,7 @@ struct ssb_bus_ops {
> >>>>> 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 (*irqflag)(struct ssb_device *dev);
> >>>>> };
> >>>>>
> >>>>>
> >>>>> @@ -485,6 +486,10 @@ static inline u32 ssb_admatch_size(struc
> >>>>> {
> >>>>> return dev->ops->admatch_size(dev, adm);
> >>>>> }
> >>>>> +static inline u32 ssb_irqflag(struct ssb_device *dev)
> >>>>> +{
> >>>>> + return dev->ops->irqflag(dev);
> >>>>> +}
> >>>>>
> >>>>>
> >>>>> /* The SSB DMA API. Use this API for any DMA operation on the device.
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>
> >>>> This one fails to compile with the following error:
> >>>>
> >>>> drivers/ssb/main.c:1370:14: error: ‘ssb_irqflag_sb’ undeclared here (not in a
> >>>> function)
> >>>> make[1]: *** [drivers/ssb/main.o] Error 1
> >>>> make: *** [drivers/ssb/] Error 2
> >>>>
> >>>> Larry
> >>>> --
> >>>> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> >>>> the body of a message to [email protected]
> >>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
> >>>>
> >>> Well, might the problem here is again caused with mine wrong post of <[RFC9/11] SSB modify irqflag treatment>
> >>> Could you please remove that one and reaply whole set of patches again.
> >>> Sorry for inconveniences.
> >>
> >> That cannot be the problem with this one. Each patch in a series MUST compile
> >> correctly so that anyone that is bisecting the code always can build a kernel.
> >> The code doesn't necessarily have to work correctly - that would be nice, but it
> >> must compile. #3 fails this test.
> >>
> >> Larry
> >>
> > I do understand this. Every patch among these 11 (actually there are 21
> > patches to get things working with newer Broadcom's socs) I've tested
> > both compiling them and also flashing final images to two boxes -
> > bcm4716 and bcm5354 I own in order to ensure that old things are still
> > working as expected while new things didnt got bricked by changes I
> > made.
> > Just checked 3rd patch again - it applied and compiled cleanly for me,
> > and mine SB-based bcm5354 is still alive after reflash.
> >
> > ssb_irqflag_sb is declared as extern in ssb_driver_mips.h which is
> > included with ssb.h to main.c
> > Could you please verify if patch applied cleanly ? I'm much surprised
> > here as I can see no reason for <‘ssb_irqflag_sb’ undeclared here> error
> > in main.c other than patch failed to get applied to ssb_driver_mips.h
>
> It applied cleanly; however, you must consider the possibility that not everyone
> has CONFIG_SSB_DRIVER_MIPS defined. On my x86_64 system, I clearly do not. With
> the following change, it compiled:
>
> #ifdef CONFIG_SSB_DRIVER_MIPS
> .irqflag = ssb_irqflag_sb,
> #endif
>
> I haven't gone deeply enough into the code to see if that is the correct change,
> or not. If x86 hardware can run AI hardware, then it won't be.
>
> Larry
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Ohh lol. Seems im completely burrowed into mips stuff forgetting there
are things apart from mips :)
Will start reviewing code for other arch dependencies right now. Thanks
a lot for pointing it out for me.
There will be completely the same issue with 11th patch as AI code got
the same op struct with unconditional mips irqflag fn.
Are there any other issues with patch applying/compiling left ?
Have nice day,
George
Evening.
> On Thu, 2011-02-10 at 07:24 +0200, George Kashperko wrote:
> > Here is updated patchset for AI support code.
>
> So this patchset does only contain code for the embedded-AI case.
> There's no support for PCI devices so far. Are you going to
> add this, too? Or does it work with the existing PCI hostcode?
> Otherwise the argument that "brcm80211 can be ported
> to it, too" is foobar.
Well, I was saying about NPhy code from brcm80211 (did I really said
about brcm80211 awhole ? o.o Btw its good idea to try out - will get to
it later when get more free time besides work and actual hw to test it
on)
SSB embedded - yes until I could proove otherwise (pretty much sure it
will require some work on) with getting my hands over some AI-base hw.
Im lacking non-embedded AI hardware to test it on currently. Planning to
make a BOM with few SSB AI pci/pcmcia wireless cards to play around with
but this is for mid-spring when I get more free time for experiments.
> You AI ops seem to be wrong, too:
>
> +/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA).
> */
> +static struct ssb_bus_ops ssb_ops_ai = {
> + .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
Nothing wrong here. SSB AI bus does provides individual cores registers'
space access with regular mmio starting at SSB_ENUM_BASE with 0x1000 for
each core pretty much like SSB SB bus does. ssb_ai_(read|write)
accessors read bus-specific core registers from the SSB_AI_BASE again
with 0x1000 per core. Its looks like on SSB AI every core is wrapped by
AI hw therefore wrapper-to-bus regs (bus specific stuff like
control/state) are managed by wrapper io, while core specific registers
(like phy/dma/etc) accessed pretty much the same like for SSB SB.
> You're still calling the SSB-embedded routines. The comment also seems
> wrong. This is not a "plain SSB bus". It's an "AI" bus.
Here would be much appreciated for short comment on your understanding
of "plain SSB" term. Sure this would let us better understand each other
on the topic. Under "plain SSB" I mean SSB AI/SB bus interconnected with
system without intermediate PCI/SDIO/PCMCIA/etc bus - therefore no core
switching required and whole mmio addrspace for all the cores can be
accessed simultaneously. At least it looks as such for me from GPL'ed
sourcecodes from Broadcom. Unfortunately have no other better source of
knowledge of how is it working rather than these sources - that one
bcm5365p.pdf you posted yesterday (btw thanks alot for it - failed
trying to find it in web and finally gave up) is new for me, just
started looking through when catch free time.
> My proposal stays the same: If you want this merged, you'll have to
> maintain it (the whole thing) in the long term.
If this is the only option then sure but with one precaution - mine
background requires me to get working trips sometimes. I cant be online
during hat time due to sertain limitations I cant cover. It newer longs
more than 2-3 days and happens not really often. If this wont make
inconveniences for you then I will do my best to keep the thing working
and developed.
Have nice day,
George
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 | 172 +++++++++++++++++++-----------------
drivers/ssb/ssb_private.h | 6 +
2 files changed, 96 insertions(+), 82 deletions(-)
--- linux-next-20110203.orig/drivers/ssb/scan.c 2011-02-06 02:39:46.000000000 +0200
+++ linux-next-20110203/drivers/ssb/scan.c 2011-02-06 02:45:21.000000000 +0200
@@ -265,6 +265,95 @@ 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)
{
@@ -352,87 +441,8 @@ int ssb_bus_scan(struct ssb_bus *bus,
dev->bus = bus;
dev->ops = bus->ops;
- 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-next-20110203.orig/drivers/ssb/ssb_private.h 2011-02-06 02:39:46.000000000 +0200
+++ linux-next-20110203/drivers/ssb/ssb_private.h 2011-02-06 02:31:47.000000000 +0200
@@ -191,7 +191,6 @@ extern int ssb_devices_freeze(struct ssb
extern int ssb_devices_thaw(struct ssb_freeze_context *ctx);
-
/* b43_pci_bridge.c */
#ifdef CONFIG_SSB_B43_PCI_BRIDGE
extern int __init b43_pci_ssb_bridge_init(void);
@@ -206,6 +205,11 @@ static inline void b43_pci_ssb_bridge_ex
}
#endif /* CONFIG_SSB_B43_PCI_BRIDGE */
+
+/* Search support routines */
+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 */
On 02/09/2011 12:23 PM, George Kashperko wrote:
>
>> On 02/09/2011 11:10 AM, George Kashperko wrote:
>>>> On 02/09/2011 08:32 AM, George Kashperko wrote:
>>>>> 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 device op.
>>>>> Signed-off-by: George Kashperko <[email protected]>
>>>>> ---
>>>>> drivers/ssb/driver_mipscore.c | 2 +-
>>>>> drivers/ssb/main.c | 1 +
>>>>> include/linux/ssb/ssb.h | 5 +++++
>>>>> include/linux/ssb/ssb_driver_mips.h | 1 +
>>>>> 4 files changed, 8 insertions(+), 1 deletion(-)
>>>>> --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-01 05:05:49.000000000 +0200
>>>>> +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-07 16:39:46.000000000 +0200
>>>>> @@ -47,7 +47,7 @@ static const u32 ipsflag_irq_shift[] = {
>>>>> SSB_IPSFLAG_IRQ4_SHIFT,
>>>>> };
>>>>>
>>>>> -static inline u32 ssb_irqflag(struct ssb_device *dev)
>>>>> +u32 ssb_irqflag_sb(struct ssb_device *dev)
>>>>> {
>>>>> u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
>>>>> if (tpsflag)
>>>>> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:35:50.000000000 +0200
>>>>> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:49:40.000000000 +0200
>>>>> @@ -1367,6 +1367,7 @@ static const struct ssb_bus_ops ssb_ssb_
>>>>> .device_disable = ssb_device_disable_sb,
>>>>> .admatch_base = ssb_admatch_base_sb,
>>>>> .admatch_size = ssb_admatch_size_sb,
>>>>> + .irqflag = ssb_irqflag_sb,
>>>>> };
>>>>>
>>>>> static int __init ssb_modinit(void)
>>>>> --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-01 05:05:49.000000000 +0200
>>>>> +++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-07 16:39:10.000000000 +0200
>>>>> @@ -29,6 +29,7 @@ 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 */
>>>>> --- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:35:50.000000000 +0200
>>>>> +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:38:34.000000000 +0200
>>>>> @@ -124,6 +124,7 @@ struct ssb_bus_ops {
>>>>> 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 (*irqflag)(struct ssb_device *dev);
>>>>> };
>>>>>
>>>>>
>>>>> @@ -485,6 +486,10 @@ static inline u32 ssb_admatch_size(struc
>>>>> {
>>>>> return dev->ops->admatch_size(dev, adm);
>>>>> }
>>>>> +static inline u32 ssb_irqflag(struct ssb_device *dev)
>>>>> +{
>>>>> + return dev->ops->irqflag(dev);
>>>>> +}
>>>>>
>>>>>
>>>>> /* The SSB DMA API. Use this API for any DMA operation on the device.
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>
>>>> This one fails to compile with the following error:
>>>>
>>>> drivers/ssb/main.c:1370:14: error: ‘ssb_irqflag_sb’ undeclared here (not in a
>>>> function)
>>>> make[1]: *** [drivers/ssb/main.o] Error 1
>>>> make: *** [drivers/ssb/] Error 2
>>>>
>>>> Larry
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
>>>> the body of a message to [email protected]
>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>
>>> Well, might the problem here is again caused with mine wrong post of <[RFC9/11] SSB modify irqflag treatment>
>>> Could you please remove that one and reaply whole set of patches again.
>>> Sorry for inconveniences.
>>
>> That cannot be the problem with this one. Each patch in a series MUST compile
>> correctly so that anyone that is bisecting the code always can build a kernel.
>> The code doesn't necessarily have to work correctly - that would be nice, but it
>> must compile. #3 fails this test.
>>
>> Larry
>>
> I do understand this. Every patch among these 11 (actually there are 21
> patches to get things working with newer Broadcom's socs) I've tested
> both compiling them and also flashing final images to two boxes -
> bcm4716 and bcm5354 I own in order to ensure that old things are still
> working as expected while new things didnt got bricked by changes I
> made.
> Just checked 3rd patch again - it applied and compiled cleanly for me,
> and mine SB-based bcm5354 is still alive after reflash.
>
> ssb_irqflag_sb is declared as extern in ssb_driver_mips.h which is
> included with ssb.h to main.c
> Could you please verify if patch applied cleanly ? I'm much surprised
> here as I can see no reason for <‘ssb_irqflag_sb’ undeclared here> error
> in main.c other than patch failed to get applied to ssb_driver_mips.h
It applied cleanly; however, you must consider the possibility that not everyone
has CONFIG_SSB_DRIVER_MIPS defined. On my x86_64 system, I clearly do not. With
the following change, it compiled:
#ifdef CONFIG_SSB_DRIVER_MIPS
.irqflag = ssb_irqflag_sb,
#endif
I haven't gone deeply enough into the code to see if that is the correct change,
or not. If x86 hardware can run AI hardware, then it won't be.
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 | 2 +-
drivers/ssb/ssb_sb.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
--- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-08 16:14:57.000000000 +0200
+++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-08 16:15:24.000000000 +0200
@@ -75,7 +75,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++) {
--- linux-next-20110203.orig/drivers/ssb/ssb_sb.c 2011-02-08 16:14:57.000000000 +0200
+++ linux-next-20110203/drivers/ssb/ssb_sb.c 2011-02-08 16:15:24.000000000 +0200
@@ -175,10 +175,10 @@ static u32 ssb_irqflag_sb(struct ssb_dev
{
u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
if (tpsflag)
- return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+ return tpsflag & SSB_TPSFLAG_BPFLAG;
else
/* not irq supported */
- return 0x3f;
+ return -1;
}
static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
On 02/09/2011 08:46 AM, George Kashperko wrote:
> From: Bernhard Loos <[email protected]>
> Add support for AI-style ssb bus.
> Signed-off-by: George Kashperko <[email protected]>
> ---
> drivers/ssb/Kconfig | 13
> drivers/ssb/Makefile | 1
> drivers/ssb/main.c | 2
> drivers/ssb/scan.c | 42 +-
> drivers/ssb/ssb_ai.c | 381 ++++++++++++++++++++
> drivers/ssb/ssb_ai.h | 61 +++
> drivers/ssb/ssb_private.h | 9
> include/linux/ssb/ssb.h | 12
> include/linux/ssb/ssb_driver_chipcommon.h | 3
> 9 files changed, 516 insertions(+), 8 deletions(-)
> --- linux-next-20110203.orig/drivers/ssb/Kconfig 2011-02-08 16:14:57.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/Kconfig 2011-02-08 21:01:34.000000000 +0200
> @@ -9,7 +9,7 @@ menu "Sonics Silicon Backplane"
> config SSB
> tristate "Sonics Silicon Backplane support"
> depends on SSB_POSSIBLE
> - select SSB_BUS_SB
> + select SSB_BUS_SB if !SSB_BUS_AI
> help
> Support for the Sonics Silicon Backplane bus.
> You only need to enable this option, if you are
> @@ -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
> + Sonics Silicon Backplane AI-style bus
> +
> # Common SPROM support routines
> config SSB_SPROM
> bool
> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-08 18:55:26.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-08 21:01:34.000000000 +0200
> @@ -842,6 +842,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-next-20110203.orig/drivers/ssb/Makefile 2011-02-08 16:14:57.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/Makefile 2011-02-08 21:01:34.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-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 18:33:58.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 21:01:34.000000000 +0200
> @@ -212,6 +212,10 @@ void ssb_iounmap(struct ssb_bus *bus)
> case SSB_BUSTYPE_SSB:
> case SSB_BUSTYPE_PCMCIA:
> iounmap(bus->mmio);
> +#ifdef CONFIG_SSB_BUS_AI
> + if (bus->ai_mmio)
> + iounmap(bus->ai_mmio);
> +#endif
> break;
> case SSB_BUSTYPE_PCI:
> #ifdef CONFIG_SSB_PCIHOST
> @@ -364,18 +368,39 @@ int ssb_bus_check_core(struct ssb_device
> /* 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 (cpu_data[0].cputype != CPU_74K) {
> + 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);
> bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
> bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
> SSB_CHIPCO_REVSHIFT;
> @@ -409,7 +434,7 @@ static int ssb_bus_detect(struct ssb_bus
> }
>
> bus->chipco.chiptype = chiptype;
> - return chiptype != SSB_CHIPCO_SB;
> + return (chiptype != SSB_CHIPCO_SB && chiptype != SSB_CHIPCO_AI);
> }
>
> int ssb_bus_scan(struct ssb_bus *bus,
> @@ -451,6 +476,9 @@ int ssb_bus_scan(struct ssb_bus *bus,
> case SSB_CHIPCO_SB:
> err = ssb_bus_scan_sb(bus, baseaddr);
> break;
> + case SSB_CHIPCO_AI:
> + err = ssb_bus_scan_ai(bus);
> + break;
> default:
> SSB_WARN_ON(1);
> err = -ENODEV;
> --- linux-next-20110203.orig/drivers/ssb/ssb_ai.c 1970-01-01 03:00:00.000000000 +0300
> +++ linux-next-20110203/drivers/ssb/ssb_ai.c 2011-02-08 21:01:58.000000000 +0200
> @@ -0,0 +1,381 @@
> +/*
> + * Sonics Silicon Backplane
> + * AI Specific Subsystem core
> + *
> + * 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 void ssb_ai_write32(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);
> +}
> +
> +static u32 ssb_ai_read32(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);
> +}
> +
> +/* 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 void ssb_core_ctl_flags_ai(struct ssb_device *dev, u32 mask,
> + u32 val, u32 *res)
> +{
> + if (ssb_bcm47162a0_quirk(dev)) {
> + printk("%s: Accessing MIPS DMP register (IOCTL) on 47162a0",
> + __FUNCTION__);
> + if (res)
> + *res = 0;
> + return;
> + }
> +
> + if (mask || val) {
> + u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOCTL) & ~mask) | val;
> + ssb_ai_write32(dev, SSB_AI_IOCTL, tmp);
> + }
> +
> + if (res)
> + *res = ssb_ai_read32(dev, SSB_AI_IOCTL);
> +}
> +
> +static u32 ssb_core_state_flags_ai(struct ssb_device *dev, u32 mask, u32 val)
> +{
> + if (ssb_bcm47162a0_quirk(dev)) {
> + printk("%s: Accessing MIPS DMP register (IOSTAT) on 47162a0",
> + __FUNCTION__);
> + return 0;
> + }
> +
> + if (mask || val) {
> + u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOSTAT) & ~mask) | val;
> + ssb_ai_write32(dev, SSB_AI_IOSTAT, tmp);
> + }
> +
> + return ssb_ai_read32(dev, SSB_AI_IOSTAT);
> +}
> +
> +/* return -1 if no irq is supported */
> +static u32 ssb_irqflag_ai(struct ssb_device *dev)
> +{
> + u32 flag;
> +
> + /* The 47162a0 hangs when reading its registers */
> + if (ssb_bcm47162a0_quirk(dev))
> + return dev->core_index;
> +
> + flag = ssb_ai_read32(dev, SSB_AI_oobselouta30);
> +
> + if (flag)
> + return flag & 0x1F;
> + else
> + /* not irq supported */
> + return -1;
> +}
> +
> +static int ssb_device_is_enabled_ai(struct ssb_device *dev)
> +{
> + return (ssb_ai_read32(dev, SSB_AI_RESETCTL) &
> + SSB_AI_RESETCTL_RESET) == 0;
> +}
> +
> +static void ssb_ai_ioctl_write(struct ssb_device *dev, u32 flags)
> +{
> + u32 dummy;
> + ssb_ai_write32(dev, SSB_AI_IOCTL, flags);
> + dummy = ssb_ai_read32(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_ai_read32(dev, SSB_AI_RESETCTL) & SSB_AI_RESETCTL_RESET)
> + return;
> + ssb_ai_ioctl_write(dev, core_specific_flags);
> + udelay(9);
> + ssb_ai_write32(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_ai_ioctl_write(dev, core_specific_flags | SSB_CORECTL_FGC |
> + SSB_CORECTL_CLOCK);
> + ssb_ai_write32(dev, SSB_AI_RESETCTL, 0);
> + udelay(1);
> +
> + ssb_ai_ioctl_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->coresba;
> + case SSB_ADMATCH1:
> + return dev->coresba2;
> + 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->coresba_size;
> + case SSB_ADMATCH1:
> + return dev->coresba2_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;
> + }
> +}
> +
> +/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
> +static struct ssb_bus_ops ssb_ops_ai = {
> + .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_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,
> + .irqflag = ssb_irqflag_ai,
> + .core_ctl_flags = ssb_core_ctl_flags_ai,
> + .core_state_flags = ssb_core_state_flags_ai,
> +};
> +
> +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)
> +{
> + int dev_i = 0;
> + struct ssb_device *dev;
> + int nr_80211_cores = 0;
> + void __iomem *mmio;
> + u32 __iomem *eromptr;
> + u32 __iomem *eromend;
> +
> + bus->ops = &ssb_ops_ai;
> +
> + mmio = ioremap(SSB_AI_BASE, SSB_CORE_SIZE * bus->nr_devices);
> + if (!mmio)
> + return -ENOMEM;
> + bus->ai_mmio = mmio;
> +
> + eromptr = ioremap(scan_read32(bus, 0, SSB_CHIPCO_EROM), SSB_CORE_SIZE);
> + if (!eromptr)
> + return -ENOMEM;
> +
> + eromend = eromptr + SSB_CORE_SIZE / sizeof(u32);
> +
> + 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->ops = bus->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->coresba = addrl;
> + dev->coresba_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->coresba2 = addrl;
> + dev->coresba2_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");
> +
> + return 0;
> +}
> --- linux-next-20110203.orig/drivers/ssb/ssb_ai.h 1970-01-01 03:00:00.000000000 +0300
> +++ linux-next-20110203/drivers/ssb/ssb_ai.h 2011-02-08 21:01:34.000000000 +0200
> @@ -0,0 +1,61 @@
> +#ifndef LINUX_SSB_AI_H_
> +#define LINUX_SSB_AI_H_
> +
> +#define SSB_AI_BASE 0x18100000 /* 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
> +
> +#endif /* LINUX_SSB_AI_H_ */
> --- linux-next-20110203.orig/drivers/ssb/ssb_private.h 2011-02-08 16:14:57.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/ssb_private.h 2011-02-08 21:01:34.000000000 +0200
> @@ -236,4 +236,13 @@ static inline int ssb_bus_scan_sb(struct
> }
> #endif /* CONFIG_SSB_BUS_SB */
>
> +#ifdef CONFIG_SSB_BUS_AI
> +extern int ssb_bus_scan_ai(struct ssb_bus *bus);
> +#else /* CONFIG_SSB_BUS_AI */
> +static inline int ssb_bus_scan_ai(struct ssb_bus *bus)
> +{
> + return -ENODEV;
> +}
> +#endif /* CONFIG_SSB_BUS_AI */
> +
> #endif /* LINUX_SSB_PRIVATE_H_ */
> --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 13:49:32.000000000 +0200
> +++ linux-next-20110203/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 21:01:34.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-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-08 18:33:58.000000000 +0200
> +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-08 21:01:34.000000000 +0200
> @@ -168,9 +168,11 @@ struct ssb_bus_ops {
> #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 */
> @@ -192,6 +194,13 @@ struct ssb_device {
> u8 core_index;
> unsigned int irq;
>
> +#ifdef CONFIG_SSB_BUS_AI
> + /* backplane address and size for core */
> + u32 coresba, coresba_size;
> + /* address and size of core second register set (usbh20) */
> + u32 coresba2, coresba2_size;
> +#endif
> +
> /* Internal-only stuff follows. */
> void *drvdata; /* Per-device data */
> void *devtypedata; /* Per-devicetype (eg 802.11) data */
> @@ -283,6 +292,9 @@ enum ssb_bustype {
> struct ssb_bus {
> /* The MMIO area. */
> void __iomem *mmio;
> +#ifdef CONFIG_SSB_BUS_AI
> + void __iomem *ai_mmio;
> +#endif
>
> const struct ssb_bus_ops *ops;
>
>
>
After I used wiggle to fix this patch, the resulting stuff would not compile.
The messages are
CC [M] drivers/ssb/scan.o
drivers/ssb/scan.c: In function ?ssb_bus_detect?:
drivers/ssb/scan.c:379:6: error: ?cpu_data? undeclared (first use in this function)
drivers/ssb/scan.c:379:6: note: each undeclared identifier is reported only once
for each function it appears in
drivers/ssb/scan.c:379:29: error: ?CPU_74K? undeclared (first use in this function)
make[1]: *** [drivers/ssb/scan.o] Error 1
make: *** [drivers/ssb/] Error 2
Larry
On Wed, 2011-02-09 at 21:58 +0100, Rafał Miłecki wrote:
> I don't know, I've doubts about it :/ That flags are quite messy, mask
> for them is 0x3FFC0000. Ideally we should shift it by 14 bits, but
> that would make writing code harder. Maaaaybe... Michael what do you
> think about this?
I have no idea.
I already expressed my opinion on all this stuff.
One thing is for certain: If this is merged, George has to
adopt maintainership.
--
Greetings Michael.
On 02/09/2011 08:41 AM, George Kashperko wrote:
> 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 | 2 +-
> drivers/ssb/ssb_sb.c | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
> --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-08 16:14:57.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-08 16:15:24.000000000 +0200
> @@ -75,7 +75,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++) {
> --- linux-next-20110203.orig/drivers/ssb/ssb_sb.c 2011-02-08 16:14:57.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/ssb_sb.c 2011-02-08 16:15:24.000000000 +0200
> @@ -175,10 +175,10 @@ static u32 ssb_irqflag_sb(struct ssb_dev
> {
> u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
> if (tpsflag)
> - return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
> + return tpsflag & SSB_TPSFLAG_BPFLAG;
> else
> /* not irq supported */
> - return 0x3f;
> + return -1;
> }
>
> static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
This one does not apply with the following:
finger@larrylap:~/wireless-testing> quilt push
Applying patch patches/ssb_AI_9
patching file drivers/ssb/driver_mipscore.c
Hunk #1 succeeded at 85 (offset 10 lines).
can't find file to patch at input line 35
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|--- linux-next-20110203.orig/drivers/ssb/ssb_sb.c 2011-02-08
16:14:57.000000000 +0200
|+++ linux-next-20110203/drivers/ssb/ssb_sb.c 2011-02-08 16:15:24.000000000 +0200
--------------------------
No file to patch. Skipping patch.
1 out of 1 hunk ignored
Patch patches/ssb_AI_9 does not apply (enforce with -f)
Larry
2011/2/9 George Kashperko <[email protected]>:
> 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 masked under some
> indirect access handlers. This patch forces use of ssb_core_ctl_flags
> and ssb_core_state_flags introduced early. 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 | 61 +++++++------------
> 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 | 52 +++++-----------
> drivers/net/wireless/b43legacy/phy.c | 2
> drivers/ssb/driver_gige.c | 19 ++---
> drivers/ssb/main.c | 20 ++++--
> 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, 160 insertions(+), 162 deletions(-)
> --- linux-next-20110203.orig/drivers/net/b44.c 2011-02-01 05:05:49.000000000 +0200
> +++ linux-next-20110203/drivers/net/b44.c 2011-02-08 12:17:03.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, NULL);
> 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-next-20110203.orig/drivers/net/wireless/b43/b43.h 2011-02-01 05:05:49.000000000 +0200
> +++ linux-next-20110203/drivers/net/wireless/b43/b43.h 2011-02-08 12:17:03.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) */
I don't know, I've doubts about it :/ That flags are quite messy, mask
for them is 0x3FFC0000. Ideally we should shift it by 14 bits, but
that would make writing code harder. Maaaaybe... Michael what do you
think about this?
> @@ -1213,6 +1214,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);
Make it ~0x00003FFC, value 0x1 is not valid flag.
Why don't you go ahead and make core flags u16?
--
Rafał
Hi again.
Here is updated patchset for AI support code.
~ found one more mistake (one more thing I've missed out from patches
not published yet. serious one - guaranteed kernel oops right after sb
scan. hopefully will get time to share whole patchwork I've got these
weekends - mostly mips stuff, but also pmu code, dma/gmac driver, etc);
~ modified ssb_core_state_flags - now its easy and clean;
~ modified ssb_core_ctl_flags - now it accepts mask in way it works in
other ssb_/b43_ maskset helpers (btw still looking for better name for
it, maybe ssb_core_ctl_maskset if you like ?);
~ fixed compile time bugs caused by mips deps (again sorry for that,
Larry) - tested by compiling for x86_64 and cross compiling for mips;
~ cleaned things out to make checkpatch.pl happy;
mask and val for ssb_core_ctl_flags are still u32. Its retval same as
ssb_core_state_flags is u32 too. Not sure why but I like it in this way
even considering other 2 bytes of flags/core regs aint used currently by
any code known to me. Maybe it could be of some use later ? Anyway if
you insist I will make it u16.
Havent tested it on actual hw yet, just done with patchset and have no
time left cause of work. Will do this evening right after done with
working tasks.
In order to avoid wall'o'posts here is the link to .tar.bz2'ed patchset:
http://www.znau.edu.ua/temp/ssb-ai-linux-wireless-testing/2011-02-10T06-35/2011-02-10T06-35.tar.bz2
Individual patches are available here:
http://www.znau.edu.ua/temp/ssb-ai-linux-wireless-testing/2011-02-10T06-35/
Have nice day,
George
P. S.
Unfortunately will be away from web till evening, got a trip :/
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 device op.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/driver_mipscore.c | 2 +-
drivers/ssb/main.c | 1 +
include/linux/ssb/ssb.h | 5 +++++
include/linux/ssb/ssb_driver_mips.h | 1 +
4 files changed, 8 insertions(+), 1 deletion(-)
--- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-07 16:39:46.000000000 +0200
@@ -47,7 +47,7 @@ static const u32 ipsflag_irq_shift[] = {
SSB_IPSFLAG_IRQ4_SHIFT,
};
-static inline u32 ssb_irqflag(struct ssb_device *dev)
+u32 ssb_irqflag_sb(struct ssb_device *dev)
{
u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
if (tpsflag)
--- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:35:50.000000000 +0200
+++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:49:40.000000000 +0200
@@ -1367,6 +1367,7 @@ static const struct ssb_bus_ops ssb_ssb_
.device_disable = ssb_device_disable_sb,
.admatch_base = ssb_admatch_base_sb,
.admatch_size = ssb_admatch_size_sb,
+ .irqflag = ssb_irqflag_sb,
};
static int __init ssb_modinit(void)
--- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-01 05:05:49.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-07 16:39:10.000000000 +0200
@@ -29,6 +29,7 @@ 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 */
--- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:35:50.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:38:34.000000000 +0200
@@ -124,6 +124,7 @@ struct ssb_bus_ops {
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 (*irqflag)(struct ssb_device *dev);
};
@@ -485,6 +486,10 @@ static inline u32 ssb_admatch_size(struc
{
return dev->ops->admatch_size(dev, adm);
}
+static inline u32 ssb_irqflag(struct ssb_device *dev)
+{
+ return dev->ops->irqflag(dev);
+}
/* The SSB DMA API. Use this API for any DMA operation on the device.
W dniu 9 lutego 2011 22:51 użytkownik Michael Büsch <[email protected]> napisał:
> On Wed, 2011-02-09 at 22:35 +0100, Rafał Miłecki wrote:
>> What about proposed solution?
>
> Well, I'm not going to maintain it due to a lack of devices,
> knowledge of the AI and a serious lack of additional time.
>
> However, I'm certainly OK with you adopting maintainership
> if people think that the code looks sane and should be merged.
>
> One thing I really don't like is the name-confusion introduced
> by this. We will have functions with the ssb_...() prefix
> that don't necessarily operate on ssb devices, but on AI devices
> instead, depending on the actual magic behind the scenes.
> That's one of the major things I tried hard to avoid in the
> SSB design from day 0 on.
> It's what I hated most about Broadcom's SB implementation (there it
> is pci_...() functions, which operate on PCI, SB or whatever else
> depending on some serious magic).
>
> So my proposal doesn't change: Create two separate busses (SSB and AI)
> and port the device drivers to work on both. That also implies
> decoupling the built-in SSB device drivers (CC, MIPS, EXTIF, PCICORE)
> from the SSB implementation.
> The code duplication will negligible.
OK, I think I'll need some your help with better understanding SSB.
AFAIK SSB is "box" (ssb_bus) containing cores (ssb_devices).
How do we talk with SSB? Is this that magic "Hostbus"? What does it
mean? Do we use one of the cores of ssb_bus to talk? Is this why I see
"ssb: Core 2 found: PCI-E (cc 0x820, rev 0x02, vendor 0x4243)"? If
only one core can be selected at time, how is this possible we selecre
802.11 core and we are still able to talk with SSB?
What are the other cores for? Why do we need driver for chipcommon,
mipscore? Are that cores internally accessed by 80211 core?
What is that whole AI? Is that replacement for SSB? Does it also
contains cores? What AI and SSB share?
--
Rafał
On Wed, 2011-02-09 at 22:55 +0100, Rafał Miłecki wrote:
> I aksed about reading, you gave me examples of writing. I want to
> avoid such a non-readable disasters:
> u32 tmp;
> ssb_core_ctl_flags(dev, 0, 0, &tmp);
A good function name consists of:
"WHAT is done and WHERE is it done"
ssb_core_ctl_flags()
violates both of them. It doesn't specify what is done at all,
except that it might be something random with ctl flags.
And it lies about where it does it. It implies that it operates
on SSB. However, it might operate on SSB or AI.
--
Greetings Michael.
> On 02/09/2011 08:46 AM, George Kashperko wrote:
> > From: Bernhard Loos <[email protected]>
> > Add support for AI-style ssb bus.
> > Signed-off-by: George Kashperko <[email protected]>
> > ---
> > drivers/ssb/Kconfig | 13
> > drivers/ssb/Makefile | 1
> > drivers/ssb/main.c | 2
> > drivers/ssb/scan.c | 42 +-
> > drivers/ssb/ssb_ai.c | 381 ++++++++++++++++++++
> > drivers/ssb/ssb_ai.h | 61 +++
> > drivers/ssb/ssb_private.h | 9
> > include/linux/ssb/ssb.h | 12
> > include/linux/ssb/ssb_driver_chipcommon.h | 3
> > 9 files changed, 516 insertions(+), 8 deletions(-)
> > --- linux-next-20110203.orig/drivers/ssb/Kconfig 2011-02-08 16:14:57.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/Kconfig 2011-02-08 21:01:34.000000000 +0200
> > @@ -9,7 +9,7 @@ menu "Sonics Silicon Backplane"
> > config SSB
> > tristate "Sonics Silicon Backplane support"
> > depends on SSB_POSSIBLE
> > - select SSB_BUS_SB
> > + select SSB_BUS_SB if !SSB_BUS_AI
> > help
> > Support for the Sonics Silicon Backplane bus.
> > You only need to enable this option, if you are
> > @@ -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
> > + Sonics Silicon Backplane AI-style bus
> > +
> > # Common SPROM support routines
> > config SSB_SPROM
> > bool
> > --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-08 18:55:26.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/main.c 2011-02-08 21:01:34.000000000 +0200
> > @@ -842,6 +842,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-next-20110203.orig/drivers/ssb/Makefile 2011-02-08 16:14:57.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/Makefile 2011-02-08 21:01:34.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-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 18:33:58.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 21:01:34.000000000 +0200
> > @@ -212,6 +212,10 @@ void ssb_iounmap(struct ssb_bus *bus)
> > case SSB_BUSTYPE_SSB:
> > case SSB_BUSTYPE_PCMCIA:
> > iounmap(bus->mmio);
> > +#ifdef CONFIG_SSB_BUS_AI
> > + if (bus->ai_mmio)
> > + iounmap(bus->ai_mmio);
> > +#endif
> > break;
> > case SSB_BUSTYPE_PCI:
> > #ifdef CONFIG_SSB_PCIHOST
> > @@ -364,18 +368,39 @@ int ssb_bus_check_core(struct ssb_device
> > /* 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 (cpu_data[0].cputype != CPU_74K) {
> > + 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);
> > bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
> > bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
> > SSB_CHIPCO_REVSHIFT;
> > @@ -409,7 +434,7 @@ static int ssb_bus_detect(struct ssb_bus
> > }
> >
> > bus->chipco.chiptype = chiptype;
> > - return chiptype != SSB_CHIPCO_SB;
> > + return (chiptype != SSB_CHIPCO_SB && chiptype != SSB_CHIPCO_AI);
> > }
> >
> > int ssb_bus_scan(struct ssb_bus *bus,
> > @@ -451,6 +476,9 @@ int ssb_bus_scan(struct ssb_bus *bus,
> > case SSB_CHIPCO_SB:
> > err = ssb_bus_scan_sb(bus, baseaddr);
> > break;
> > + case SSB_CHIPCO_AI:
> > + err = ssb_bus_scan_ai(bus);
> > + break;
> > default:
> > SSB_WARN_ON(1);
> > err = -ENODEV;
> > --- linux-next-20110203.orig/drivers/ssb/ssb_ai.c 1970-01-01 03:00:00.000000000 +0300
> > +++ linux-next-20110203/drivers/ssb/ssb_ai.c 2011-02-08 21:01:58.000000000 +0200
> > @@ -0,0 +1,381 @@
> > +/*
> > + * Sonics Silicon Backplane
> > + * AI Specific Subsystem core
> > + *
> > + * 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 void ssb_ai_write32(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);
> > +}
> > +
> > +static u32 ssb_ai_read32(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);
> > +}
> > +
> > +/* 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 void ssb_core_ctl_flags_ai(struct ssb_device *dev, u32 mask,
> > + u32 val, u32 *res)
> > +{
> > + if (ssb_bcm47162a0_quirk(dev)) {
> > + printk("%s: Accessing MIPS DMP register (IOCTL) on 47162a0",
> > + __FUNCTION__);
> > + if (res)
> > + *res = 0;
> > + return;
> > + }
> > +
> > + if (mask || val) {
> > + u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOCTL) & ~mask) | val;
> > + ssb_ai_write32(dev, SSB_AI_IOCTL, tmp);
> > + }
> > +
> > + if (res)
> > + *res = ssb_ai_read32(dev, SSB_AI_IOCTL);
> > +}
> > +
> > +static u32 ssb_core_state_flags_ai(struct ssb_device *dev, u32 mask, u32 val)
> > +{
> > + if (ssb_bcm47162a0_quirk(dev)) {
> > + printk("%s: Accessing MIPS DMP register (IOSTAT) on 47162a0",
> > + __FUNCTION__);
> > + return 0;
> > + }
> > +
> > + if (mask || val) {
> > + u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOSTAT) & ~mask) | val;
> > + ssb_ai_write32(dev, SSB_AI_IOSTAT, tmp);
> > + }
> > +
> > + return ssb_ai_read32(dev, SSB_AI_IOSTAT);
> > +}
> > +
> > +/* return -1 if no irq is supported */
> > +static u32 ssb_irqflag_ai(struct ssb_device *dev)
> > +{
> > + u32 flag;
> > +
> > + /* The 47162a0 hangs when reading its registers */
> > + if (ssb_bcm47162a0_quirk(dev))
> > + return dev->core_index;
> > +
> > + flag = ssb_ai_read32(dev, SSB_AI_oobselouta30);
> > +
> > + if (flag)
> > + return flag & 0x1F;
> > + else
> > + /* not irq supported */
> > + return -1;
> > +}
> > +
> > +static int ssb_device_is_enabled_ai(struct ssb_device *dev)
> > +{
> > + return (ssb_ai_read32(dev, SSB_AI_RESETCTL) &
> > + SSB_AI_RESETCTL_RESET) == 0;
> > +}
> > +
> > +static void ssb_ai_ioctl_write(struct ssb_device *dev, u32 flags)
> > +{
> > + u32 dummy;
> > + ssb_ai_write32(dev, SSB_AI_IOCTL, flags);
> > + dummy = ssb_ai_read32(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_ai_read32(dev, SSB_AI_RESETCTL) & SSB_AI_RESETCTL_RESET)
> > + return;
> > + ssb_ai_ioctl_write(dev, core_specific_flags);
> > + udelay(9);
> > + ssb_ai_write32(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_ai_ioctl_write(dev, core_specific_flags | SSB_CORECTL_FGC |
> > + SSB_CORECTL_CLOCK);
> > + ssb_ai_write32(dev, SSB_AI_RESETCTL, 0);
> > + udelay(1);
> > +
> > + ssb_ai_ioctl_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->coresba;
> > + case SSB_ADMATCH1:
> > + return dev->coresba2;
> > + 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->coresba_size;
> > + case SSB_ADMATCH1:
> > + return dev->coresba2_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;
> > + }
> > +}
> > +
> > +/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
> > +static struct ssb_bus_ops ssb_ops_ai = {
> > + .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_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,
> > + .irqflag = ssb_irqflag_ai,
> > + .core_ctl_flags = ssb_core_ctl_flags_ai,
> > + .core_state_flags = ssb_core_state_flags_ai,
> > +};
> > +
> > +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)
> > +{
> > + int dev_i = 0;
> > + struct ssb_device *dev;
> > + int nr_80211_cores = 0;
> > + void __iomem *mmio;
> > + u32 __iomem *eromptr;
> > + u32 __iomem *eromend;
> > +
> > + bus->ops = &ssb_ops_ai;
> > +
> > + mmio = ioremap(SSB_AI_BASE, SSB_CORE_SIZE * bus->nr_devices);
> > + if (!mmio)
> > + return -ENOMEM;
> > + bus->ai_mmio = mmio;
> > +
> > + eromptr = ioremap(scan_read32(bus, 0, SSB_CHIPCO_EROM), SSB_CORE_SIZE);
> > + if (!eromptr)
> > + return -ENOMEM;
> > +
> > + eromend = eromptr + SSB_CORE_SIZE / sizeof(u32);
> > +
> > + 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->ops = bus->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->coresba = addrl;
> > + dev->coresba_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->coresba2 = addrl;
> > + dev->coresba2_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");
> > +
> > + return 0;
> > +}
> > --- linux-next-20110203.orig/drivers/ssb/ssb_ai.h 1970-01-01 03:00:00.000000000 +0300
> > +++ linux-next-20110203/drivers/ssb/ssb_ai.h 2011-02-08 21:01:34.000000000 +0200
> > @@ -0,0 +1,61 @@
> > +#ifndef LINUX_SSB_AI_H_
> > +#define LINUX_SSB_AI_H_
> > +
> > +#define SSB_AI_BASE 0x18100000 /* 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
> > +
> > +#endif /* LINUX_SSB_AI_H_ */
> > --- linux-next-20110203.orig/drivers/ssb/ssb_private.h 2011-02-08 16:14:57.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/ssb_private.h 2011-02-08 21:01:34.000000000 +0200
> > @@ -236,4 +236,13 @@ static inline int ssb_bus_scan_sb(struct
> > }
> > #endif /* CONFIG_SSB_BUS_SB */
> >
> > +#ifdef CONFIG_SSB_BUS_AI
> > +extern int ssb_bus_scan_ai(struct ssb_bus *bus);
> > +#else /* CONFIG_SSB_BUS_AI */
> > +static inline int ssb_bus_scan_ai(struct ssb_bus *bus)
> > +{
> > + return -ENODEV;
> > +}
> > +#endif /* CONFIG_SSB_BUS_AI */
> > +
> > #endif /* LINUX_SSB_PRIVATE_H_ */
> > --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 13:49:32.000000000 +0200
> > +++ linux-next-20110203/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 21:01:34.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-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-08 18:33:58.000000000 +0200
> > +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-08 21:01:34.000000000 +0200
> > @@ -168,9 +168,11 @@ struct ssb_bus_ops {
> > #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 */
> > @@ -192,6 +194,13 @@ struct ssb_device {
> > u8 core_index;
> > unsigned int irq;
> >
> > +#ifdef CONFIG_SSB_BUS_AI
> > + /* backplane address and size for core */
> > + u32 coresba, coresba_size;
> > + /* address and size of core second register set (usbh20) */
> > + u32 coresba2, coresba2_size;
> > +#endif
> > +
> > /* Internal-only stuff follows. */
> > void *drvdata; /* Per-device data */
> > void *devtypedata; /* Per-devicetype (eg 802.11) data */
> > @@ -283,6 +292,9 @@ enum ssb_bustype {
> > struct ssb_bus {
> > /* The MMIO area. */
> > void __iomem *mmio;
> > +#ifdef CONFIG_SSB_BUS_AI
> > + void __iomem *ai_mmio;
> > +#endif
> >
> > const struct ssb_bus_ops *ops;
> >
> >
> >
>
> This one also fails to apply:
>
> finger@larrylap:~/wireless-testing> quilt import ssb_AI_12
> Importing patch ssb_AI_12 (stored as patches/ssb_AI_12)
> finger@larrylap:~/wireless-testing> quilt push
> Applying patch patches/ssb_AI_12
> patching file drivers/ssb/Kconfig
> patching file drivers/ssb/main.c
> Hunk #1 succeeded at 841 (offset -1 lines).
> patching file drivers/ssb/Makefile
> patching file drivers/ssb/scan.c
> Hunk #1 succeeded at 204 (offset -8 lines).
> Hunk #2 succeeded at 360 (offset -8 lines).
> Hunk #3 succeeded at 426 (offset -8 lines).
> Hunk #4 succeeded at 468 (offset -8 lines).
> patching file drivers/ssb/ssb_ai.c
> patching file drivers/ssb/ssb_ai.h
> patching file drivers/ssb/ssb_private.h
> patching file include/linux/ssb/ssb_driver_chipcommon.h
> patching file include/linux/ssb/ssb.h
> Hunk #1 FAILED at 168.
> Hunk #2 succeeded at 188 (offset -4 lines).
> Hunk #3 succeeded at 286 (offset -4 lines).
> 1 out of 3 hunks FAILED -- rejects in file include/linux/ssb/ssb.h
> Patch patches/ssb_AI_12 does not apply (enforce with -f)
>
> Larry
>
Just found the source of unclean patch application.
In my serie 11th one is actually 16th -.-
To apply without reject I was to supply one more patch before 11th but I didn't. This one is for MIPS74k support and I completely missed that it is required for AI scan.
Sorry.
Missing part is attached. Please get it applied before 11th one.
From: George Kashperko <[email protected]>
Defines neccesary for upcoming MIPS 74K ssb core support.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/scan.c | 8 ++++++++
include/linux/ssb/ssb.h | 4 ++++
2 files changed, 12 insertions(+)
--- linux-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 17:32:03.000000000 +0200
+++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 18:25:39.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-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-08 18:25:22.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-08 18:25:55.000000000 +0200
@@ -164,6 +164,10 @@ struct ssb_bus_ops {
#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
В Срд, 09/02/2011 в 22:55 +0100, Rafał Miłecki пишет:
> W dniu 9 lutego 2011 22:03 użytkownik George Kashperko
> <[email protected]> napisał:
> >
> > В Срд, 09/02/2011 в 21:35 +0100, Rafał Miłecki пишет:
> >> 2011/2/9 George Kashperko <[email protected]>:
> >> > From: George Kashperko <[email protected]>
> >> >
> >> > Introduce handlers 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 | 36 ++++++++++++++++++++++++++++++++++++
> >> > include/linux/ssb/ssb.h | 14 +++++++++++++-
> >> > 2 files changed, 49 insertions(+), 1 deletion(-)
> >> > --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:58:50.000000000 +0200
> >> > +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 17:07:11.000000000 +0200
> >> > @@ -1350,6 +1350,40 @@ static u32 ssb_admatch_size_sb(struct ss
> >> > return size;
> >> > }
> >> >
> >> > +static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
> >> > + u32 val, u32 *res)
> >> > +{
> >> > + u32 tmp;
> >> > +
> >> > + if (mask || val) {
> >> > + tmp = (ssb_read32(dev, SSB_TMSLOW) & ~mask) | val;
> >> > + ssb_write32(dev, SSB_TMSLOW, tmp);
> >> > + }
> >>
> >> Are you going to use that function for just reading SSB_TMSLOW? Why
> >> won't you use separated function then? Do you need separated function
> >> for sth so simple as "ssb_read32(dev, SSB_TMSLOW);" at all?
> > Will answer your question with another question ;)
> > What would you personally prefer (press "1" or "2" :p)?
> > 1)
> > if (sb_bus)
> > ssb_write32(dev, (ssb_read32(dev, SSB_TMSLOW) & ~(mask << 16)) | (flags << 16));
> > else
> > ssb_write32(dev, (ssb_read32(dev, SSB_AI_IOCTL) & ~mask) | flags));
> > 2)
> > ssb_core_ctl_flags(dev, mask, flags, NULL);
>
> I aksed about reading, you gave me examples of writing. I want to
> avoid such a non-readable disasters:
> u32 tmp;
> ssb_core_ctl_flags(dev, 0, 0, &tmp);
>
On 02/09/2011 11:10 AM, George Kashperko wrote:
>> On 02/09/2011 08:32 AM, George Kashperko wrote:
>>> 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 device op.
>>> Signed-off-by: George Kashperko <[email protected]>
>>> ---
>>> drivers/ssb/driver_mipscore.c | 2 +-
>>> drivers/ssb/main.c | 1 +
>>> include/linux/ssb/ssb.h | 5 +++++
>>> include/linux/ssb/ssb_driver_mips.h | 1 +
>>> 4 files changed, 8 insertions(+), 1 deletion(-)
>>> --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-01 05:05:49.000000000 +0200
>>> +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-07 16:39:46.000000000 +0200
>>> @@ -47,7 +47,7 @@ static const u32 ipsflag_irq_shift[] = {
>>> SSB_IPSFLAG_IRQ4_SHIFT,
>>> };
>>>
>>> -static inline u32 ssb_irqflag(struct ssb_device *dev)
>>> +u32 ssb_irqflag_sb(struct ssb_device *dev)
>>> {
>>> u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
>>> if (tpsflag)
>>> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:35:50.000000000 +0200
>>> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:49:40.000000000 +0200
>>> @@ -1367,6 +1367,7 @@ static const struct ssb_bus_ops ssb_ssb_
>>> .device_disable = ssb_device_disable_sb,
>>> .admatch_base = ssb_admatch_base_sb,
>>> .admatch_size = ssb_admatch_size_sb,
>>> + .irqflag = ssb_irqflag_sb,
>>> };
>>>
>>> static int __init ssb_modinit(void)
>>> --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-01 05:05:49.000000000 +0200
>>> +++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-07 16:39:10.000000000 +0200
>>> @@ -29,6 +29,7 @@ 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 */
>>> --- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:35:50.000000000 +0200
>>> +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:38:34.000000000 +0200
>>> @@ -124,6 +124,7 @@ struct ssb_bus_ops {
>>> 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 (*irqflag)(struct ssb_device *dev);
>>> };
>>>
>>>
>>> @@ -485,6 +486,10 @@ static inline u32 ssb_admatch_size(struc
>>> {
>>> return dev->ops->admatch_size(dev, adm);
>>> }
>>> +static inline u32 ssb_irqflag(struct ssb_device *dev)
>>> +{
>>> + return dev->ops->irqflag(dev);
>>> +}
>>>
>>>
>>> /* The SSB DMA API. Use this API for any DMA operation on the device.
>>>
>>>
>>>
>>> --
>>
>> This one fails to compile with the following error:
>>
>> drivers/ssb/main.c:1370:14: error: ‘ssb_irqflag_sb’ undeclared here (not in a
>> function)
>> make[1]: *** [drivers/ssb/main.o] Error 1
>> make: *** [drivers/ssb/] Error 2
>>
>> Larry
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
> Well, might the problem here is again caused with mine wrong post of <[RFC9/11] SSB modify irqflag treatment>
> Could you please remove that one and reaply whole set of patches again.
> Sorry for inconveniences.
That cannot be the problem with this one. Each patch in a series MUST compile
correctly so that anyone that is bisecting the code always can build a kernel.
The code doesn't necessarily have to work correctly - that would be nice, but it
must compile. #3 fails this test.
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 | 2 +-
drivers/ssb/ssb_sb.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
--- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-08
16:14:57.000000000 +0200
+++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-08
16:15:24.000000000 +0200
@@ -75,7 +75,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++) {
--- linux-next-20110203.orig/drivers/ssb/ssb_sb.c 2011-02-08
16:14:57.000000000 +0200
+++ linux-next-20110203/drivers/ssb/ssb_sb.c 2011-02-08
16:15:24.000000000 +0200
@@ -175,10 +175,10 @@ static u32 ssb_irqflag_sb(struct ssb_dev
{
u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
if (tpsflag)
- return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+ return tpsflag & SSB_TPSFLAG_BPFLAG;
else
/* not irq supported */
- return 0x3f;
+ return -1;
}
static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
> On 02/09/2011 11:10 AM, George Kashperko wrote:
> >> On 02/09/2011 08:32 AM, George Kashperko wrote:
> >>> 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 device op.
> >>> Signed-off-by: George Kashperko <[email protected]>
> >>> ---
> >>> drivers/ssb/driver_mipscore.c | 2 +-
> >>> drivers/ssb/main.c | 1 +
> >>> include/linux/ssb/ssb.h | 5 +++++
> >>> include/linux/ssb/ssb_driver_mips.h | 1 +
> >>> 4 files changed, 8 insertions(+), 1 deletion(-)
> >>> --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-01 05:05:49.000000000 +0200
> >>> +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-07 16:39:46.000000000 +0200
> >>> @@ -47,7 +47,7 @@ static const u32 ipsflag_irq_shift[] = {
> >>> SSB_IPSFLAG_IRQ4_SHIFT,
> >>> };
> >>>
> >>> -static inline u32 ssb_irqflag(struct ssb_device *dev)
> >>> +u32 ssb_irqflag_sb(struct ssb_device *dev)
> >>> {
> >>> u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
> >>> if (tpsflag)
> >>> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:35:50.000000000 +0200
> >>> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:49:40.000000000 +0200
> >>> @@ -1367,6 +1367,7 @@ static const struct ssb_bus_ops ssb_ssb_
> >>> .device_disable = ssb_device_disable_sb,
> >>> .admatch_base = ssb_admatch_base_sb,
> >>> .admatch_size = ssb_admatch_size_sb,
> >>> + .irqflag = ssb_irqflag_sb,
> >>> };
> >>>
> >>> static int __init ssb_modinit(void)
> >>> --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-01 05:05:49.000000000 +0200
> >>> +++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-07 16:39:10.000000000 +0200
> >>> @@ -29,6 +29,7 @@ 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 */
> >>> --- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:35:50.000000000 +0200
> >>> +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:38:34.000000000 +0200
> >>> @@ -124,6 +124,7 @@ struct ssb_bus_ops {
> >>> 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 (*irqflag)(struct ssb_device *dev);
> >>> };
> >>>
> >>>
> >>> @@ -485,6 +486,10 @@ static inline u32 ssb_admatch_size(struc
> >>> {
> >>> return dev->ops->admatch_size(dev, adm);
> >>> }
> >>> +static inline u32 ssb_irqflag(struct ssb_device *dev)
> >>> +{
> >>> + return dev->ops->irqflag(dev);
> >>> +}
> >>>
> >>>
> >>> /* The SSB DMA API. Use this API for any DMA operation on the device.
> >>>
> >>>
> >>>
> >>> --
> >>
> >> This one fails to compile with the following error:
> >>
> >> drivers/ssb/main.c:1370:14: error: ‘ssb_irqflag_sb’ undeclared here (not in a
> >> function)
> >> make[1]: *** [drivers/ssb/main.o] Error 1
> >> make: *** [drivers/ssb/] Error 2
> >>
> >> Larry
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> >> the body of a message to [email protected]
> >> More majordomo info at http://vger.kernel.org/majordomo-info.html
> >>
> > Well, might the problem here is again caused with mine wrong post of <[RFC9/11] SSB modify irqflag treatment>
> > Could you please remove that one and reaply whole set of patches again.
> > Sorry for inconveniences.
>
> That cannot be the problem with this one. Each patch in a series MUST compile
> correctly so that anyone that is bisecting the code always can build a kernel.
> The code doesn't necessarily have to work correctly - that would be nice, but it
> must compile. #3 fails this test.
>
> Larry
>
I do understand this. Every patch among these 11 (actually there are 21
patches to get things working with newer Broadcom's socs) I've tested
both compiling them and also flashing final images to two boxes -
bcm4716 and bcm5354 I own in order to ensure that old things are still
working as expected while new things didnt got bricked by changes I
made.
Just checked 3rd patch again - it applied and compiled cleanly for me,
and mine SB-based bcm5354 is still alive after reflash.
ssb_irqflag_sb is declared as extern in ssb_driver_mips.h which is
included with ssb.h to main.c
Could you please verify if patch applied cleanly ? I'm much surprised
here as I can see no reason for <‘ssb_irqflag_sb’ undeclared here> error
in main.c other than patch failed to get applied to ssb_driver_mips.h
Have nice day,
George
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-next-20110203.orig/drivers/ssb/main.c 2011-02-08 13:34:23.000000000 +0200
+++ linux-next-20110203/drivers/ssb/main.c 2011-02-08 13:19:40.000000000 +0200
@@ -838,6 +838,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)
@@ -850,11 +860,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;
@@ -875,8 +888,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;
@@ -897,8 +911,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;
@@ -917,8 +932,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-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 13:34:23.000000000 +0200
+++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 13:33:43.000000000 +0200
@@ -354,24 +354,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;
@@ -411,8 +398,40 @@ 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;
+}
+
+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;
+
+ if (ssb_bus_detect(bus)) {
+ ssb_printk(KERN_ERR PFX
+ "ERROR: Unknown SSB chip type %d detected\n",
+ bus->chipco.chiptype);
+ err = -ENODEV;
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-next-20110203.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 13:34:23.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 13:19:40.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;
Hi,
After rethinking this I came to the same result as Michael that it would
bet better to have a extra module for the AI bus separated from the ssb.
I grepped for ssb_ in the b43 driver code and it should be doable to
change the api of ssb so that adding an other bus can be done without
any changes to ssb. After the SSB API was changed once.
Most of the ssb_* methods calls in the b43 driver are getting an
ssb_device struct so just a common struct for ssb and the ai bus is
needed and it must contain some function pointers to the needed functions.
Then the drivers integrated in the drivers/ssb must be extracted and
unbundled from the ssb code. One common header file with some common
structs for ssb and AI is needed and the rest can be separated.
If you need help with something, I would like to help you with these
things. I just ordered an Netgear WNR3500L. ;-)
Hauke
From: George Kashperko <[email protected]>
Introduce handlers 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 | 36 ++++++++++++++++++++++++++++++++++++
include/linux/ssb/ssb.h | 14 +++++++++++++-
2 files changed, 49 insertions(+), 1 deletion(-)
--- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:58:50.000000000 +0200
+++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 17:07:11.000000000 +0200
@@ -1350,6 +1350,40 @@ static u32 ssb_admatch_size_sb(struct ss
return size;
}
+static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
+ u32 val, u32 *res)
+{
+ u32 tmp;
+
+ if (mask || val) {
+ tmp = (ssb_read32(dev, SSB_TMSLOW) & ~mask) | val;
+ ssb_write32(dev, SSB_TMSLOW, tmp);
+ }
+
+ /* readback */
+ tmp = ssb_read32(dev, SSB_TMSLOW);
+ udelay(1);
+
+ if (res)
+ *res = tmp;
+}
+
+static u32 ssb_core_state_flags_sb(struct ssb_device *dev, u32 mask, u32 val)
+{
+ u32 tmp;
+
+ if (mask || val) {
+ tmp = (ssb_read32(dev, SSB_TMSHIGH) & ~mask) | val;
+ ssb_write32(dev, SSB_TMSHIGH, tmp);
+ }
+
+ /* readback */
+ tmp = ssb_read32(dev, SSB_TMSHIGH);
+ 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,
@@ -1368,6 +1402,8 @@ static const struct ssb_bus_ops ssb_ssb_
.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)
--- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:58:50.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 17:02:09.000000000 +0200
@@ -125,6 +125,9 @@ struct ssb_bus_ops {
u32 (*admatch_base)(struct ssb_device *dev, u32 adm);
u32 (*admatch_size)(struct ssb_device *dev, u32 adm);
u32 (*irqflag)(struct ssb_device *dev);
+ void (*core_ctl_flags)(struct ssb_device *dev, u32 mask,
+ u32 val, u32 *res);
+ u32 (*core_state_flags)(struct ssb_device *dev, u32 mask, u32 val);
};
@@ -490,7 +493,16 @@ static inline u32 ssb_irqflag(struct ssb
{
return dev->ops->irqflag(dev);
}
-
+static inline void ssb_core_ctl_flags(struct ssb_device *dev, u32 mask,
+ u32 val, u32 *res)
+{
+ return dev->ops->core_ctl_flags(dev, mask, val, res);
+}
+static inline u32 ssb_core_state_flags(struct ssb_device *dev, u32 mask,
+ u32 val)
+{
+ return dev->ops->core_state_flags(dev, mask, val);
+}
/* The SSB DMA API. Use this API for any DMA operation on the device.
* This API basically is a wrapper that calls the correct DMA API for
On Thu, 2011-02-10 at 07:24 +0200, George Kashperko wrote:
> Here is updated patchset for AI support code.
So this patchset does only contain code for the embedded-AI case.
There's no support for PCI devices so far. Are you going to
add this, too? Or does it work with the existing PCI hostcode?
Otherwise the argument that "brcm80211 can be ported
to it, too" is foobar.
You AI ops seem to be wrong, too:
+/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA).
*/
+static struct ssb_bus_ops ssb_ops_ai = {
+ .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
You're still calling the SSB-embedded routines. The comment also seems
wrong. This is not a "plain SSB bus". It's an "AI" bus.
My proposal stays the same: If you want this merged, you'll have to
maintain it (the whole thing) in the long term.
--
Greetings Michael.
> On 02/09/2011 08:32 AM, George Kashperko wrote:
> > 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 device op.
> > Signed-off-by: George Kashperko <[email protected]>
> > ---
> > drivers/ssb/driver_mipscore.c | 2 +-
> > drivers/ssb/main.c | 1 +
> > include/linux/ssb/ssb.h | 5 +++++
> > include/linux/ssb/ssb_driver_mips.h | 1 +
> > 4 files changed, 8 insertions(+), 1 deletion(-)
> > --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-01 05:05:49.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-07 16:39:46.000000000 +0200
> > @@ -47,7 +47,7 @@ static const u32 ipsflag_irq_shift[] = {
> > SSB_IPSFLAG_IRQ4_SHIFT,
> > };
> >
> > -static inline u32 ssb_irqflag(struct ssb_device *dev)
> > +u32 ssb_irqflag_sb(struct ssb_device *dev)
> > {
> > u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
> > if (tpsflag)
> > --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:35:50.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:49:40.000000000 +0200
> > @@ -1367,6 +1367,7 @@ static const struct ssb_bus_ops ssb_ssb_
> > .device_disable = ssb_device_disable_sb,
> > .admatch_base = ssb_admatch_base_sb,
> > .admatch_size = ssb_admatch_size_sb,
> > + .irqflag = ssb_irqflag_sb,
> > };
> >
> > static int __init ssb_modinit(void)
> > --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-01 05:05:49.000000000 +0200
> > +++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-07 16:39:10.000000000 +0200
> > @@ -29,6 +29,7 @@ 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 */
> > --- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:35:50.000000000 +0200
> > +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:38:34.000000000 +0200
> > @@ -124,6 +124,7 @@ struct ssb_bus_ops {
> > 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 (*irqflag)(struct ssb_device *dev);
> > };
> >
> >
> > @@ -485,6 +486,10 @@ static inline u32 ssb_admatch_size(struc
> > {
> > return dev->ops->admatch_size(dev, adm);
> > }
> > +static inline u32 ssb_irqflag(struct ssb_device *dev)
> > +{
> > + return dev->ops->irqflag(dev);
> > +}
> >
> >
> > /* The SSB DMA API. Use this API for any DMA operation on the device.
> >
> >
> >
> > --
>
> This one fails to compile with the following error:
>
> drivers/ssb/main.c:1370:14: error: ‘ssb_irqflag_sb’ undeclared here (not in a
> function)
> make[1]: *** [drivers/ssb/main.o] Error 1
> make: *** [drivers/ssb/] Error 2
>
> Larry
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Well, might the problem here is again caused with mine wrong post of <[RFC9/11] SSB modify irqflag treatment>
Could you please remove that one and reaply whole set of patches again.
Sorry for inconveniences.
Have nice day,
George
On Thu, 2011-02-10 at 19:40 +0200, George Kashperko wrote:
> Under "plain SSB" I mean SSB AI/SB bus interconnected with
A plain SSB bus is a plain SSB bus. Not AI, not PCI-SSB. It's plain SSB.
And that's exactly the kind of horrible confusion I am trying
to avoid. It would be completely avoided if SSB and AI bus
implementations were separated. You could _still_ implement a thin
abstraction layer on top of that to avoid if(ssb) ... else ...
code in drivers. Let's call it "hndbackplane" or something like that.
void hndbackplane_device_enable(struct dev)
{
if (device_is_ssb)
ssb_device_enable()
else
ai_device_enable()
}
And I want to say it once again: The code you added does only work
on embedded. If PCI support is to be added, the PCI-host code will
have to be changed, too. (Currently it will crash with NULL pointer
derefs on the ops)
You're actually abusing the ops structure. The ops structure is meant
to abstract the SSB backplane from its host bus. It is _not_ meant
to abstract the SSB backplane itself. Your patches mix that up. It's
an abstraction layer violation, which my proposal avoids completely.
In case I didn't say it clear enough in the past: Having SSB and AI
being separate busses does _not_ mean that they cannot share some
code. So the duplication of code is not an issue.
> system without intermediate PCI/SDIO/PCMCIA/etc bus - therefore no core
> switching required and whole mmio addrspace for all the cores can be
> accessed simultaneously. At least it looks as such for me from GPL'ed
> sourcecodes from Broadcom. Unfortunately have no other better source of
> knowledge of how is it working rather than these sources
It's pretty well understood how it works. Just read the documentation.
That is the PDF I provided and the b43 documentation wiki.
--
Greetings Michael.
Hi,
> 2011/2/10 Michael Büsch <[email protected]>:
> > You're actually abusing the ops structure. The ops structure is meant
> > to abstract the SSB backplane from its host bus. It is _not_ meant
> > to abstract the SSB backplane itself. Your patches mix that up. It's
> > an abstraction layer violation, which my proposal avoids completely.
>
> After some reading, learning, I think I generally agree with Michael.
>
> George: I like you consider separated bus driver now. Please let us
> know when you design something!
>
I've tried-out separate bus driver approach already. Didn't like it at
all tbh. Separate bus driver's .c files made me copy-paste main.c and
scan.c alot any modifications except for &ops pointers. If inlining AI
things with include "bcmai_main.c" "bcmai_scan.c" into main.c/scan.c
makes less copy-pasting and original SSB handlers' exporting but again
changing just &ops in respective handlers makes no sense for me.
Therefore I still think AI-layer buildup over SSB will be good if not
best.
Unfortunately my original code put too much messup into SSB with
overriding ops which was plain wrong as I see now. I've done with fixed
decision which keep bus-abstraction layer intact, overriding just
helpers which behaving different for SSB and AI. Currently its ready to
publish but I want to test it on actual hw before. Already tested on pci
attached SSB on and few embeddables with both SSB and AI. Atm looking
for some pci attached AI to test updated AI code.
Have nice day,
George
В Срд, 09/02/2011 в 22:01 +0100, Rafał Miłecki пишет:
> W dniu 9 lutego 2011 21:35 użytkownik Rafał Miłecki <[email protected]> napisał:
> > 2011/2/9 George Kashperko <[email protected]>:
> >> From: George Kashperko <[email protected]>
> >>
> >> Introduce handlers 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 | 36 ++++++++++++++++++++++++++++++++++++
> >> include/linux/ssb/ssb.h | 14 +++++++++++++-
> >> 2 files changed, 49 insertions(+), 1 deletion(-)
> >> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:58:50.000000000 +0200
> >> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 17:07:11.000000000 +0200
> >> @@ -1350,6 +1350,40 @@ static u32 ssb_admatch_size_sb(struct ss
> >> return size;
> >> }
> >>
> >> +static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
> >> + u32 val, u32 *res)
> >> +{
> >> + u32 tmp;
> >> +
> >> + if (mask || val) {
> >> + tmp = (ssb_read32(dev, SSB_TMSLOW) & ~mask) | val;
> >> + ssb_write32(dev, SSB_TMSLOW, tmp);
> >> + }
> >
> > Are you going to use that function for just reading SSB_TMSLOW? Why
> > won't you use separated function then? Do you need separated function
> > for sth so simple as "ssb_read32(dev, SSB_TMSLOW);" at all?
>
> In b43 we used to implement mask other way:
>
> void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
> {
> b43_radio_write16(dev, offset,
> (b43_radio_read16(dev, offset) & mask) | set);
> }
>
> I don't vote for any option, but I think we should one method everywhere.
> (mask vs. ~mask)
>
No doubt. Think this one should be changed.
В Срд, 09/02/2011 в 10:23 -0600, Larry Finger пишет:
> On 02/09/2011 08:41 AM, George Kashperko wrote:
> > 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 | 2 +-
> > drivers/ssb/ssb_sb.c | 4 ++--
> > 2 files changed, 3 insertions(+), 3 deletions(-)
> > --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-08 16:14:57.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-08 16:15:24.000000000 +0200
> > @@ -75,7 +75,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++) {
> > --- linux-next-20110203.orig/drivers/ssb/ssb_sb.c 2011-02-08 16:14:57.000000000 +0200
> > +++ linux-next-20110203/drivers/ssb/ssb_sb.c 2011-02-08 16:15:24.000000000 +0200
> > @@ -175,10 +175,10 @@ static u32 ssb_irqflag_sb(struct ssb_dev
> > {
> > u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
> > if (tpsflag)
> > - return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
> > + return tpsflag & SSB_TPSFLAG_BPFLAG;
> > else
> > /* not irq supported */
> > - return 0x3f;
> > + return -1;
> > }
> >
> > static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
>
> This one does not apply with the following:
>
> finger@larrylap:~/wireless-testing> quilt push
> Applying patch patches/ssb_AI_9
> patching file drivers/ssb/driver_mipscore.c
> Hunk #1 succeeded at 85 (offset 10 lines).
> can't find file to patch at input line 35
> Perhaps you used the wrong -p or --strip option?
> The text leading up to this was:
> --------------------------
> |--- linux-next-20110203.orig/drivers/ssb/ssb_sb.c 2011-02-08
> 16:14:57.000000000 +0200
> |+++ linux-next-20110203/drivers/ssb/ssb_sb.c 2011-02-08 16:15:24.000000000 +0200
> --------------------------
> No file to patch. Skipping patch.
> 1 out of 1 hunk ignored
> Patch patches/ssb_AI_9 does not apply (enforce with -f)
>
> Larry
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
My apologises for that. Already posted that <[RFC9/11] SSB modify
irqflag treatment> is my fault - it should be 10/11 not 9/11. You might
be missed my post with this note. Again sorry. I've reposted it right
after with proper sequence number. Please just rm it. 9th in sequence
should be <[RFC9/11] SSB separate SB-specific code>
Regarding issues with 3/11 and 11/11 - im looking into right now. Might
we have different git state.
Have nice day,
George
Hello guys,
We (Broadcom) internally discussed in what way we can get involved in
HDN/AI support.
We offer to write a AI library module that any driver module (eg, a new
AI bus driver, or b43, or brcm80211) can depend on. Similar to
mac80211.ko and cfg80211.ko, the library module only offers services to
interested driver modules, it does *not* claim any hardware itself.
This approach improves code sharing, and still offers the driver module
implementer plenty of flexibility. The AI library module code would have
to be distilled from brcm80211. We propose the name 'lib_ai'.
Please let me know how your thoughts.
Thanks, Roland.
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 | 68 +++++++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 27 deletions(-)
--- linux-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 15:40:18.000000000 +0200
+++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 15:41:20.000000000 +0200
@@ -405,16 +405,46 @@ static int ssb_bus_detect(struct ssb_bus
return chiptype != SSB_CHIPCO_SB;
}
-int ssb_bus_scan(struct ssb_bus *bus,
- unsigned long baseaddr)
+int ssb_bus_scan_sb(struct ssb_bus *bus, unsigned long baseaddr)
{
- int err = -ENOMEM;
- void __iomem *mmio;
+ 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)
+{
+ int err = -ENOMEM;
+ void __iomem *mmio;
+
mmio = ssb_ioremap(bus, baseaddr);
if (!mmio)
goto out;
@@ -444,30 +474,14 @@ int ssb_bus_scan(struct ssb_bus *bus,
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;
-
- 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:
On 02/09/2011 04:53 PM, Rafał Miłecki wrote:
> W dniu 9 lutego 2011 22:51 użytkownik Michael Büsch <[email protected]> napisał:
>> On Wed, 2011-02-09 at 22:35 +0100, Rafał Miłecki wrote:
>>> What about proposed solution?
>>
>> Well, I'm not going to maintain it due to a lack of devices,
>> knowledge of the AI and a serious lack of additional time.
>>
>> However, I'm certainly OK with you adopting maintainership
>> if people think that the code looks sane and should be merged.
>>
>> One thing I really don't like is the name-confusion introduced
>> by this. We will have functions with the ssb_...() prefix
>> that don't necessarily operate on ssb devices, but on AI devices
>> instead, depending on the actual magic behind the scenes.
>> That's one of the major things I tried hard to avoid in the
>> SSB design from day 0 on.
>> It's what I hated most about Broadcom's SB implementation (there it
>> is pci_...() functions, which operate on PCI, SB or whatever else
>> depending on some serious magic).
>>
>> So my proposal doesn't change: Create two separate busses (SSB and AI)
>> and port the device drivers to work on both. That also implies
>> decoupling the built-in SSB device drivers (CC, MIPS, EXTIF, PCICORE)
>> from the SSB implementation.
>> The code duplication will negligible.
>
> OK, I think I'll need some your help with better understanding SSB.
>
> AFAIK SSB is "box" (ssb_bus) containing cores (ssb_devices).
>
> How do we talk with SSB? Is this that magic "Hostbus"? What does it
> mean? Do we use one of the cores of ssb_bus to talk? Is this why I see
> "ssb: Core 2 found: PCI-E (cc 0x820, rev 0x02, vendor 0x4243)"? If
> only one core can be selected at time, how is this possible we selecre
> 802.11 core and we are still able to talk with SSB?
>
> What are the other cores for? Why do we need driver for chipcommon,
> mipscore? Are that cores internally accessed by 80211 core?
>
> What is that whole AI? Is that replacement for SSB? Does it also
> contains cores? What AI and SSB share?
Michael,
Do you have a copy of the BCM5365P for Rafal? The link in the specs
(http://voodoowarez.com/bcm5365p.pdf) is apparently no longer available. My
recollection is that it had a good description of the SSB.
Larry
On Wed, 2011-02-09 at 23:53 +0100, Rafał Miłecki wrote:
> OK, I think I'll need some your help with better understanding SSB.
>
> AFAIK SSB is "box" (ssb_bus) containing cores (ssb_devices).
SSB and AI are just simple interconnects that can be used on-chip
or on embedded boards. The devices connected to this interconnect
(or bus) are the "cores".
> How do we talk with SSB? Is this that magic "Hostbus"? What does it
> mean? Do we use one of the cores of ssb_bus to talk? Is this why I see
> "ssb: Core 2 found: PCI-E (cc 0x820, rev 0x02, vendor 0x4243)"? If
> only one core can be selected at time, how is this possible we selecre
> 802.11 core and we are still able to talk with SSB?
That completely depends on what hostbus we're on. It's completely hidden
by SSB's I/O ops. For the trivial case without any hostbus (embedded),
the cores
are simply mapped into MMIO one after another. For the PCI hostbus case,
the MMIO has to be remapped (through PCI config space) on each
core switch. (Core switches are completely hidden from the device
drivers). PCMCIA and SDIO are similar.
> What are the other cores for? Why do we need driver for chipcommon,
> mipscore? Are that cores internally accessed by 80211 core?
The chipcommon is a management core for the interconnect.
Device drivers are (mostly) distinct. There are a few exceptions.
Built-in device drivers (drivers/ssb/driver_....c) have some
interdependencies. However, b43, b44 and ssb-gige are completely
independent, for example.
> What is that whole AI? Is that replacement for SSB? Does it also
> contains cores? What AI and SSB share?
It is a replacement that shares some register API and design
decisions with SSB.
People who worked some time with broadcom stuff will recognize the
pattern: Take old stuff -> redesign it -> put lots of workarounds
and patching layers on top of it to be theoretically compatible
with old code -> fail at being fully compatible -> release it.
--
Greetings Michael.
> 2011/2/9 George Kashperko <[email protected]>:
> > 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 masked under some
> > indirect access handlers. This patch forces use of ssb_core_ctl_flags
> > and ssb_core_state_flags introduced early. 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 | 61 +++++++------------
> > 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 | 52 +++++-----------
> > drivers/net/wireless/b43legacy/phy.c | 2
> > drivers/ssb/driver_gige.c | 19 ++---
> > drivers/ssb/main.c | 20 ++++--
> > 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, 160 insertions(+), 162 deletions(-)
> > --- linux-next-20110203.orig/drivers/net/b44.c 2011-02-01 05:05:49.000000000 +0200
> > +++ linux-next-20110203/drivers/net/b44.c 2011-02-08 12:17:03.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, NULL);
> > 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-next-20110203.orig/drivers/net/wireless/b43/b43.h 2011-02-01 05:05:49.000000000 +0200
> > +++ linux-next-20110203/drivers/net/wireless/b43/b43.h 2011-02-08 12:17:03.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) */
>
> I don't know, I've doubts about it :/ That flags are quite messy, mask
> for them is 0x3FFC0000. Ideally we should shift it by 14 bits, but
> that would make writing code harder. Maaaaybe... Michael what do you
> think about this?
>
>
> > @@ -1213,6 +1214,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);
>
> Make it ~0x00003FFC, value 0x1 is not valid flag.
Actual mask for _core_ flags is 0xFFFF0000 for SB and 0x0000FFFF for AI.
0x3FFC is mask for core dependent flags.
SSB_CORECTL_CLOCK | SSB_CORECTL_FGC | SSB_CORECTL_PE | SSB_CORECTL_BE |
0x3FFC = 0xFFFF
Therefore sanity check for SB is &0xFFFF0000, for AI is &0x0000FFFF
Layout of core flags in these 2 bytes is the same for AI and SB cores.
>
> Why don't you go ahead and make core flags u16?
>
Dont see any problems with this as other 2 bytes aint used currently in
any way.
From: Bernhard Loos <[email protected]>
Add support for AI-style ssb bus.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/Kconfig | 13
drivers/ssb/Makefile | 1
drivers/ssb/main.c | 2
drivers/ssb/scan.c | 42 +-
drivers/ssb/ssb_ai.c | 381 ++++++++++++++++++++
drivers/ssb/ssb_ai.h | 61 +++
drivers/ssb/ssb_private.h | 9
include/linux/ssb/ssb.h | 12
include/linux/ssb/ssb_driver_chipcommon.h | 3
9 files changed, 516 insertions(+), 8 deletions(-)
--- linux-next-20110203.orig/drivers/ssb/Kconfig 2011-02-08 16:14:57.000000000 +0200
+++ linux-next-20110203/drivers/ssb/Kconfig 2011-02-08 21:01:34.000000000 +0200
@@ -9,7 +9,7 @@ menu "Sonics Silicon Backplane"
config SSB
tristate "Sonics Silicon Backplane support"
depends on SSB_POSSIBLE
- select SSB_BUS_SB
+ select SSB_BUS_SB if !SSB_BUS_AI
help
Support for the Sonics Silicon Backplane bus.
You only need to enable this option, if you are
@@ -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
+ Sonics Silicon Backplane AI-style bus
+
# Common SPROM support routines
config SSB_SPROM
bool
--- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-08 18:55:26.000000000 +0200
+++ linux-next-20110203/drivers/ssb/main.c 2011-02-08 21:01:34.000000000 +0200
@@ -842,6 +842,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-next-20110203.orig/drivers/ssb/Makefile 2011-02-08 16:14:57.000000000 +0200
+++ linux-next-20110203/drivers/ssb/Makefile 2011-02-08 21:01:34.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-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 18:33:58.000000000 +0200
+++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 21:01:34.000000000 +0200
@@ -212,6 +212,10 @@ void ssb_iounmap(struct ssb_bus *bus)
case SSB_BUSTYPE_SSB:
case SSB_BUSTYPE_PCMCIA:
iounmap(bus->mmio);
+#ifdef CONFIG_SSB_BUS_AI
+ if (bus->ai_mmio)
+ iounmap(bus->ai_mmio);
+#endif
break;
case SSB_BUSTYPE_PCI:
#ifdef CONFIG_SSB_PCIHOST
@@ -364,18 +368,39 @@ int ssb_bus_check_core(struct ssb_device
/* 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 (cpu_data[0].cputype != CPU_74K) {
+ 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);
bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
SSB_CHIPCO_REVSHIFT;
@@ -409,7 +434,7 @@ static int ssb_bus_detect(struct ssb_bus
}
bus->chipco.chiptype = chiptype;
- return chiptype != SSB_CHIPCO_SB;
+ return (chiptype != SSB_CHIPCO_SB && chiptype != SSB_CHIPCO_AI);
}
int ssb_bus_scan(struct ssb_bus *bus,
@@ -451,6 +476,9 @@ int ssb_bus_scan(struct ssb_bus *bus,
case SSB_CHIPCO_SB:
err = ssb_bus_scan_sb(bus, baseaddr);
break;
+ case SSB_CHIPCO_AI:
+ err = ssb_bus_scan_ai(bus);
+ break;
default:
SSB_WARN_ON(1);
err = -ENODEV;
--- linux-next-20110203.orig/drivers/ssb/ssb_ai.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-next-20110203/drivers/ssb/ssb_ai.c 2011-02-08 21:01:58.000000000 +0200
@@ -0,0 +1,381 @@
+/*
+ * Sonics Silicon Backplane
+ * AI Specific Subsystem core
+ *
+ * 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 void ssb_ai_write32(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);
+}
+
+static u32 ssb_ai_read32(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);
+}
+
+/* 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 void ssb_core_ctl_flags_ai(struct ssb_device *dev, u32 mask,
+ u32 val, u32 *res)
+{
+ if (ssb_bcm47162a0_quirk(dev)) {
+ printk("%s: Accessing MIPS DMP register (IOCTL) on 47162a0",
+ __FUNCTION__);
+ if (res)
+ *res = 0;
+ return;
+ }
+
+ if (mask || val) {
+ u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOCTL) & ~mask) | val;
+ ssb_ai_write32(dev, SSB_AI_IOCTL, tmp);
+ }
+
+ if (res)
+ *res = ssb_ai_read32(dev, SSB_AI_IOCTL);
+}
+
+static u32 ssb_core_state_flags_ai(struct ssb_device *dev, u32 mask, u32 val)
+{
+ if (ssb_bcm47162a0_quirk(dev)) {
+ printk("%s: Accessing MIPS DMP register (IOSTAT) on 47162a0",
+ __FUNCTION__);
+ return 0;
+ }
+
+ if (mask || val) {
+ u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOSTAT) & ~mask) | val;
+ ssb_ai_write32(dev, SSB_AI_IOSTAT, tmp);
+ }
+
+ return ssb_ai_read32(dev, SSB_AI_IOSTAT);
+}
+
+/* return -1 if no irq is supported */
+static u32 ssb_irqflag_ai(struct ssb_device *dev)
+{
+ u32 flag;
+
+ /* The 47162a0 hangs when reading its registers */
+ if (ssb_bcm47162a0_quirk(dev))
+ return dev->core_index;
+
+ flag = ssb_ai_read32(dev, SSB_AI_oobselouta30);
+
+ if (flag)
+ return flag & 0x1F;
+ else
+ /* not irq supported */
+ return -1;
+}
+
+static int ssb_device_is_enabled_ai(struct ssb_device *dev)
+{
+ return (ssb_ai_read32(dev, SSB_AI_RESETCTL) &
+ SSB_AI_RESETCTL_RESET) == 0;
+}
+
+static void ssb_ai_ioctl_write(struct ssb_device *dev, u32 flags)
+{
+ u32 dummy;
+ ssb_ai_write32(dev, SSB_AI_IOCTL, flags);
+ dummy = ssb_ai_read32(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_ai_read32(dev, SSB_AI_RESETCTL) & SSB_AI_RESETCTL_RESET)
+ return;
+ ssb_ai_ioctl_write(dev, core_specific_flags);
+ udelay(9);
+ ssb_ai_write32(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_ai_ioctl_write(dev, core_specific_flags | SSB_CORECTL_FGC |
+ SSB_CORECTL_CLOCK);
+ ssb_ai_write32(dev, SSB_AI_RESETCTL, 0);
+ udelay(1);
+
+ ssb_ai_ioctl_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->coresba;
+ case SSB_ADMATCH1:
+ return dev->coresba2;
+ 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->coresba_size;
+ case SSB_ADMATCH1:
+ return dev->coresba2_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;
+ }
+}
+
+/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
+static struct ssb_bus_ops ssb_ops_ai = {
+ .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_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,
+ .irqflag = ssb_irqflag_ai,
+ .core_ctl_flags = ssb_core_ctl_flags_ai,
+ .core_state_flags = ssb_core_state_flags_ai,
+};
+
+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)
+{
+ int dev_i = 0;
+ struct ssb_device *dev;
+ int nr_80211_cores = 0;
+ void __iomem *mmio;
+ u32 __iomem *eromptr;
+ u32 __iomem *eromend;
+
+ bus->ops = &ssb_ops_ai;
+
+ mmio = ioremap(SSB_AI_BASE, SSB_CORE_SIZE * bus->nr_devices);
+ if (!mmio)
+ return -ENOMEM;
+ bus->ai_mmio = mmio;
+
+ eromptr = ioremap(scan_read32(bus, 0, SSB_CHIPCO_EROM), SSB_CORE_SIZE);
+ if (!eromptr)
+ return -ENOMEM;
+
+ eromend = eromptr + SSB_CORE_SIZE / sizeof(u32);
+
+ 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->ops = bus->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->coresba = addrl;
+ dev->coresba_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->coresba2 = addrl;
+ dev->coresba2_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");
+
+ return 0;
+}
--- linux-next-20110203.orig/drivers/ssb/ssb_ai.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-next-20110203/drivers/ssb/ssb_ai.h 2011-02-08 21:01:34.000000000 +0200
@@ -0,0 +1,61 @@
+#ifndef LINUX_SSB_AI_H_
+#define LINUX_SSB_AI_H_
+
+#define SSB_AI_BASE 0x18100000 /* 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
+
+#endif /* LINUX_SSB_AI_H_ */
--- linux-next-20110203.orig/drivers/ssb/ssb_private.h 2011-02-08 16:14:57.000000000 +0200
+++ linux-next-20110203/drivers/ssb/ssb_private.h 2011-02-08 21:01:34.000000000 +0200
@@ -236,4 +236,13 @@ static inline int ssb_bus_scan_sb(struct
}
#endif /* CONFIG_SSB_BUS_SB */
+#ifdef CONFIG_SSB_BUS_AI
+extern int ssb_bus_scan_ai(struct ssb_bus *bus);
+#else /* CONFIG_SSB_BUS_AI */
+static inline int ssb_bus_scan_ai(struct ssb_bus *bus)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_SSB_BUS_AI */
+
#endif /* LINUX_SSB_PRIVATE_H_ */
--- linux-next-20110203.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 13:49:32.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 21:01:34.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-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-08 18:33:58.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-08 21:01:34.000000000 +0200
@@ -168,9 +168,11 @@ struct ssb_bus_ops {
#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 */
@@ -192,6 +194,13 @@ struct ssb_device {
u8 core_index;
unsigned int irq;
+#ifdef CONFIG_SSB_BUS_AI
+ /* backplane address and size for core */
+ u32 coresba, coresba_size;
+ /* address and size of core second register set (usbh20) */
+ u32 coresba2, coresba2_size;
+#endif
+
/* Internal-only stuff follows. */
void *drvdata; /* Per-device data */
void *devtypedata; /* Per-devicetype (eg 802.11) data */
@@ -283,6 +292,9 @@ enum ssb_bustype {
struct ssb_bus {
/* The MMIO area. */
void __iomem *mmio;
+#ifdef CONFIG_SSB_BUS_AI
+ void __iomem *ai_mmio;
+#endif
const struct ssb_bus_ops *ops;
Hi,
> Hi,
>
> After rethinking this I came to the same result as Michael that it would
> bet better to have a extra module for the AI bus separated from the ssb.
> I grepped for ssb_ in the b43 driver code and it should be doable to
> change the api of ssb so that adding an other bus can be done without
> any changes to ssb. After the SSB API was changed once.
Good way, already thinking of it but still need more planning for it.
> Most of the ssb_* methods calls in the b43 driver are getting an
> ssb_device struct so just a common struct for ssb and the ai bus is
> needed and it must contain some function pointers to the needed functions.
Well its almost the way I'm currently going. Unfortunately I was too
blinded with mips-only part of the bus implementation. Thanks to
Michael's feedback and to Larry trying to build it for x86_64 (ohh I
feel so much sorry for that, made you wasting your time while resulting
code will not be working for anything else rather than embeddables was
stupid from me. Again apologises for that - I was not seeing the whole
picture unfortunately).
> Then the drivers integrated in the drivers/ssb must be extracted and
> unbundled from the ssb code. One common header file with some common
> structs for ssb and AI is needed and the rest can be separated.
This one makes me think that SB and AI are much more SSB rather than SSB
SB and lets say BCM AI. There were too much messup in the code I've
posted, realised that too late. That messup and lack of SB-side
knowledge was preventing me from seeing where I'm wrong. I understand
now how scary it could have been looking for people who are familiar
with SB. Thanks to your feedback and few days of rest think I see the
clean way how let two buses coexists on single code base without
intrusing drivers too much and without messing bus abstration.
> If you need help with something, I would like to help you with these
> things. I just ordered an Netgear WNR3500L. ;-)
Heh, congrats with that one ;)
I own 5 N16'ths currently, imagine how was I happy when realised that
Openwrt can't be set up on those ;)
Have nice day,
George
Uf, I'm back after weekend.
W dniu 10 lutego 2011 00:30 użytkownik George Kashperko
<[email protected]> napisał:
>> What are the other cores for? Why do we need driver for chipcommon,
>> mipscore? Are that cores internally accessed by 80211 core?
>
> Prior to using any core, very same as b43 one, others (mipscore, usb,
> b44, etc.) must be set up properly.
> Therefore drivers exists. Chipcommon need setup as well - it handles
> cpu/mem/bus/clocks, power control, built-in uarts and might be much
> more. Its like "wrapper" core for indirect bus management.
> And I dont know if 80211 is talking directly to any other core except
> maybe chipcommon.
Thanks for explanation, but what about cores like internal memory, or
usb? What are they for?
--
Rafał
On 02/09/2011 08:46 AM, George Kashperko wrote:
> From: Bernhard Loos <[email protected]>
> Add support for AI-style ssb bus.
> Signed-off-by: George Kashperko <[email protected]>
> ---
> drivers/ssb/Kconfig | 13
> drivers/ssb/Makefile | 1
> drivers/ssb/main.c | 2
> drivers/ssb/scan.c | 42 +-
> drivers/ssb/ssb_ai.c | 381 ++++++++++++++++++++
> drivers/ssb/ssb_ai.h | 61 +++
> drivers/ssb/ssb_private.h | 9
> include/linux/ssb/ssb.h | 12
> include/linux/ssb/ssb_driver_chipcommon.h | 3
> 9 files changed, 516 insertions(+), 8 deletions(-)
> --- linux-next-20110203.orig/drivers/ssb/Kconfig 2011-02-08 16:14:57.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/Kconfig 2011-02-08 21:01:34.000000000 +0200
> @@ -9,7 +9,7 @@ menu "Sonics Silicon Backplane"
> config SSB
> tristate "Sonics Silicon Backplane support"
> depends on SSB_POSSIBLE
> - select SSB_BUS_SB
> + select SSB_BUS_SB if !SSB_BUS_AI
> help
> Support for the Sonics Silicon Backplane bus.
> You only need to enable this option, if you are
> @@ -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
> + Sonics Silicon Backplane AI-style bus
> +
> # Common SPROM support routines
> config SSB_SPROM
> bool
> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-08 18:55:26.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-08 21:01:34.000000000 +0200
> @@ -842,6 +842,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-next-20110203.orig/drivers/ssb/Makefile 2011-02-08 16:14:57.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/Makefile 2011-02-08 21:01:34.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-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 18:33:58.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 21:01:34.000000000 +0200
> @@ -212,6 +212,10 @@ void ssb_iounmap(struct ssb_bus *bus)
> case SSB_BUSTYPE_SSB:
> case SSB_BUSTYPE_PCMCIA:
> iounmap(bus->mmio);
> +#ifdef CONFIG_SSB_BUS_AI
> + if (bus->ai_mmio)
> + iounmap(bus->ai_mmio);
> +#endif
> break;
> case SSB_BUSTYPE_PCI:
> #ifdef CONFIG_SSB_PCIHOST
> @@ -364,18 +368,39 @@ int ssb_bus_check_core(struct ssb_device
> /* 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 (cpu_data[0].cputype != CPU_74K) {
> + 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);
> bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
> bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
> SSB_CHIPCO_REVSHIFT;
> @@ -409,7 +434,7 @@ static int ssb_bus_detect(struct ssb_bus
> }
>
> bus->chipco.chiptype = chiptype;
> - return chiptype != SSB_CHIPCO_SB;
> + return (chiptype != SSB_CHIPCO_SB && chiptype != SSB_CHIPCO_AI);
> }
>
> int ssb_bus_scan(struct ssb_bus *bus,
> @@ -451,6 +476,9 @@ int ssb_bus_scan(struct ssb_bus *bus,
> case SSB_CHIPCO_SB:
> err = ssb_bus_scan_sb(bus, baseaddr);
> break;
> + case SSB_CHIPCO_AI:
> + err = ssb_bus_scan_ai(bus);
> + break;
> default:
> SSB_WARN_ON(1);
> err = -ENODEV;
> --- linux-next-20110203.orig/drivers/ssb/ssb_ai.c 1970-01-01 03:00:00.000000000 +0300
> +++ linux-next-20110203/drivers/ssb/ssb_ai.c 2011-02-08 21:01:58.000000000 +0200
> @@ -0,0 +1,381 @@
> +/*
> + * Sonics Silicon Backplane
> + * AI Specific Subsystem core
> + *
> + * 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 void ssb_ai_write32(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);
> +}
> +
> +static u32 ssb_ai_read32(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);
> +}
> +
> +/* 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 void ssb_core_ctl_flags_ai(struct ssb_device *dev, u32 mask,
> + u32 val, u32 *res)
> +{
> + if (ssb_bcm47162a0_quirk(dev)) {
> + printk("%s: Accessing MIPS DMP register (IOCTL) on 47162a0",
> + __FUNCTION__);
> + if (res)
> + *res = 0;
> + return;
> + }
> +
> + if (mask || val) {
> + u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOCTL) & ~mask) | val;
> + ssb_ai_write32(dev, SSB_AI_IOCTL, tmp);
> + }
> +
> + if (res)
> + *res = ssb_ai_read32(dev, SSB_AI_IOCTL);
> +}
> +
> +static u32 ssb_core_state_flags_ai(struct ssb_device *dev, u32 mask, u32 val)
> +{
> + if (ssb_bcm47162a0_quirk(dev)) {
> + printk("%s: Accessing MIPS DMP register (IOSTAT) on 47162a0",
> + __FUNCTION__);
> + return 0;
> + }
> +
> + if (mask || val) {
> + u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOSTAT) & ~mask) | val;
> + ssb_ai_write32(dev, SSB_AI_IOSTAT, tmp);
> + }
> +
> + return ssb_ai_read32(dev, SSB_AI_IOSTAT);
> +}
> +
> +/* return -1 if no irq is supported */
> +static u32 ssb_irqflag_ai(struct ssb_device *dev)
> +{
> + u32 flag;
> +
> + /* The 47162a0 hangs when reading its registers */
> + if (ssb_bcm47162a0_quirk(dev))
> + return dev->core_index;
> +
> + flag = ssb_ai_read32(dev, SSB_AI_oobselouta30);
> +
> + if (flag)
> + return flag & 0x1F;
> + else
> + /* not irq supported */
> + return -1;
> +}
> +
> +static int ssb_device_is_enabled_ai(struct ssb_device *dev)
> +{
> + return (ssb_ai_read32(dev, SSB_AI_RESETCTL) &
> + SSB_AI_RESETCTL_RESET) == 0;
> +}
> +
> +static void ssb_ai_ioctl_write(struct ssb_device *dev, u32 flags)
> +{
> + u32 dummy;
> + ssb_ai_write32(dev, SSB_AI_IOCTL, flags);
> + dummy = ssb_ai_read32(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_ai_read32(dev, SSB_AI_RESETCTL) & SSB_AI_RESETCTL_RESET)
> + return;
> + ssb_ai_ioctl_write(dev, core_specific_flags);
> + udelay(9);
> + ssb_ai_write32(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_ai_ioctl_write(dev, core_specific_flags | SSB_CORECTL_FGC |
> + SSB_CORECTL_CLOCK);
> + ssb_ai_write32(dev, SSB_AI_RESETCTL, 0);
> + udelay(1);
> +
> + ssb_ai_ioctl_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->coresba;
> + case SSB_ADMATCH1:
> + return dev->coresba2;
> + 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->coresba_size;
> + case SSB_ADMATCH1:
> + return dev->coresba2_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;
> + }
> +}
> +
> +/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
> +static struct ssb_bus_ops ssb_ops_ai = {
> + .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_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,
> + .irqflag = ssb_irqflag_ai,
> + .core_ctl_flags = ssb_core_ctl_flags_ai,
> + .core_state_flags = ssb_core_state_flags_ai,
> +};
> +
> +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)
> +{
> + int dev_i = 0;
> + struct ssb_device *dev;
> + int nr_80211_cores = 0;
> + void __iomem *mmio;
> + u32 __iomem *eromptr;
> + u32 __iomem *eromend;
> +
> + bus->ops = &ssb_ops_ai;
> +
> + mmio = ioremap(SSB_AI_BASE, SSB_CORE_SIZE * bus->nr_devices);
> + if (!mmio)
> + return -ENOMEM;
> + bus->ai_mmio = mmio;
> +
> + eromptr = ioremap(scan_read32(bus, 0, SSB_CHIPCO_EROM), SSB_CORE_SIZE);
> + if (!eromptr)
> + return -ENOMEM;
> +
> + eromend = eromptr + SSB_CORE_SIZE / sizeof(u32);
> +
> + 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->ops = bus->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->coresba = addrl;
> + dev->coresba_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->coresba2 = addrl;
> + dev->coresba2_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");
> +
> + return 0;
> +}
> --- linux-next-20110203.orig/drivers/ssb/ssb_ai.h 1970-01-01 03:00:00.000000000 +0300
> +++ linux-next-20110203/drivers/ssb/ssb_ai.h 2011-02-08 21:01:34.000000000 +0200
> @@ -0,0 +1,61 @@
> +#ifndef LINUX_SSB_AI_H_
> +#define LINUX_SSB_AI_H_
> +
> +#define SSB_AI_BASE 0x18100000 /* 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
> +
> +#endif /* LINUX_SSB_AI_H_ */
> --- linux-next-20110203.orig/drivers/ssb/ssb_private.h 2011-02-08 16:14:57.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/ssb_private.h 2011-02-08 21:01:34.000000000 +0200
> @@ -236,4 +236,13 @@ static inline int ssb_bus_scan_sb(struct
> }
> #endif /* CONFIG_SSB_BUS_SB */
>
> +#ifdef CONFIG_SSB_BUS_AI
> +extern int ssb_bus_scan_ai(struct ssb_bus *bus);
> +#else /* CONFIG_SSB_BUS_AI */
> +static inline int ssb_bus_scan_ai(struct ssb_bus *bus)
> +{
> + return -ENODEV;
> +}
> +#endif /* CONFIG_SSB_BUS_AI */
> +
> #endif /* LINUX_SSB_PRIVATE_H_ */
> --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 13:49:32.000000000 +0200
> +++ linux-next-20110203/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 21:01:34.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-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-08 18:33:58.000000000 +0200
> +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-08 21:01:34.000000000 +0200
> @@ -168,9 +168,11 @@ struct ssb_bus_ops {
> #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 */
> @@ -192,6 +194,13 @@ struct ssb_device {
> u8 core_index;
> unsigned int irq;
>
> +#ifdef CONFIG_SSB_BUS_AI
> + /* backplane address and size for core */
> + u32 coresba, coresba_size;
> + /* address and size of core second register set (usbh20) */
> + u32 coresba2, coresba2_size;
> +#endif
> +
> /* Internal-only stuff follows. */
> void *drvdata; /* Per-device data */
> void *devtypedata; /* Per-devicetype (eg 802.11) data */
> @@ -283,6 +292,9 @@ enum ssb_bustype {
> struct ssb_bus {
> /* The MMIO area. */
> void __iomem *mmio;
> +#ifdef CONFIG_SSB_BUS_AI
> + void __iomem *ai_mmio;
> +#endif
>
> const struct ssb_bus_ops *ops;
>
>
>
This one also fails to apply:
finger@larrylap:~/wireless-testing> quilt import ssb_AI_12
Importing patch ssb_AI_12 (stored as patches/ssb_AI_12)
finger@larrylap:~/wireless-testing> quilt push
Applying patch patches/ssb_AI_12
patching file drivers/ssb/Kconfig
patching file drivers/ssb/main.c
Hunk #1 succeeded at 841 (offset -1 lines).
patching file drivers/ssb/Makefile
patching file drivers/ssb/scan.c
Hunk #1 succeeded at 204 (offset -8 lines).
Hunk #2 succeeded at 360 (offset -8 lines).
Hunk #3 succeeded at 426 (offset -8 lines).
Hunk #4 succeeded at 468 (offset -8 lines).
patching file drivers/ssb/ssb_ai.c
patching file drivers/ssb/ssb_ai.h
patching file drivers/ssb/ssb_private.h
patching file include/linux/ssb/ssb_driver_chipcommon.h
patching file include/linux/ssb/ssb.h
Hunk #1 FAILED at 168.
Hunk #2 succeeded at 188 (offset -4 lines).
Hunk #3 succeeded at 286 (offset -4 lines).
1 out of 3 hunks FAILED -- rejects in file include/linux/ssb/ssb.h
Patch patches/ssb_AI_12 does not apply (enforce with -f)
Larry
2011/2/9 George Kashperko <[email protected]>:
> From: George Kashperko <[email protected]>
>
> Introduce handlers 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 | 36 ++++++++++++++++++++++++++++++++++++
> include/linux/ssb/ssb.h | 14 +++++++++++++-
> 2 files changed, 49 insertions(+), 1 deletion(-)
> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:58:50.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 17:07:11.000000000 +0200
> @@ -1350,6 +1350,40 @@ static u32 ssb_admatch_size_sb(struct ss
> return size;
> }
>
> +static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
> + u32 val, u32 *res)
> +{
> + u32 tmp;
> +
> + if (mask || val) {
> + tmp = (ssb_read32(dev, SSB_TMSLOW) & ~mask) | val;
> + ssb_write32(dev, SSB_TMSLOW, tmp);
> + }
Are you going to use that function for just reading SSB_TMSLOW? Why
won't you use separated function then? Do you need separated function
for sth so simple as "ssb_read32(dev, SSB_TMSLOW);" at all?
> + /* readback */
> + tmp = ssb_read32(dev, SSB_TMSLOW);
> + udelay(1);
> +
> + if (res)
> + *res = tmp;
> +}
Why are you returning value by writing to pointed place? Can't you
simply return it? Does returning complicate code so much, it is worth
using that non-common solution?
--
Rafał
Switching general discussion to this thread.
W dniu 9 lutego 2011 22:12 użytkownik Michael Büsch <[email protected]> napisał:
> On Wed, 2011-02-09 at 21:58 +0100, Rafał Miłecki wrote:
>> I don't know, I've doubts about it :/ That flags are quite messy, mask
>> for them is 0x3FFC0000. Ideally we should shift it by 14 bits, but
>> that would make writing code harder. Maaaaybe... Michael what do you
>> think about this?
>
> I have no idea.
> I already expressed my opinion on all this stuff.
>
> One thing is for certain: If this is merged, George has to
> adopt maintainership.
What about proposed solution? Does it still look ugly for you with
that pointers to functions? It looks quite fine separated, similarly
to b43 and PHYs I think. Separated files and structs with pointers.
George: apart from few simple comparisons on beginning (like detecting
type of device and determining name in switch), do you need any more
(many?) tests in general code? Do you have many "if ssb_sb) {} else
{}"?
--
Rafał
> W dniu 9 lutego 2011 22:51 użytkownik Michael Büsch <[email protected]> napisał:
> > On Wed, 2011-02-09 at 22:35 +0100, Rafał Miłecki wrote:
> >> What about proposed solution?
> >
> > Well, I'm not going to maintain it due to a lack of devices,
> > knowledge of the AI and a serious lack of additional time.
> >
> > However, I'm certainly OK with you adopting maintainership
> > if people think that the code looks sane and should be merged.
> >
> > One thing I really don't like is the name-confusion introduced
> > by this. We will have functions with the ssb_...() prefix
> > that don't necessarily operate on ssb devices, but on AI devices
> > instead, depending on the actual magic behind the scenes.
> > That's one of the major things I tried hard to avoid in the
> > SSB design from day 0 on.
> > It's what I hated most about Broadcom's SB implementation (there it
> > is pci_...() functions, which operate on PCI, SB or whatever else
> > depending on some serious magic).
> >
> > So my proposal doesn't change: Create two separate busses (SSB and AI)
> > and port the device drivers to work on both. That also implies
> > decoupling the built-in SSB device drivers (CC, MIPS, EXTIF, PCICORE)
> > from the SSB implementation.
> > The code duplication will negligible.
>
> OK, I think I'll need some your help with better understanding SSB.
>
> AFAIK SSB is "box" (ssb_bus) containing cores (ssb_devices).
>
> How do we talk with SSB? Is this that magic "Hostbus"? What does it
> mean? Do we use one of the cores of ssb_bus to talk? Is this why I see
> "ssb: Core 2 found: PCI-E (cc 0x820, rev 0x02, vendor 0x4243)"? If
> only one core can be selected at time, how is this possible we selecre
> 802.11 core and we are still able to talk with SSB?
Not like I know how is that actually expressed in hardware. But here is
what I understood from broadcom's sources for SB/AI buses. Would be much
appreciated for comments on this or maybe some good and fat .pdf's (not
actually hope I will ever see one, seems its like top-secret stuff).
SB/AI cores - some hw interconnecting actual device to bus services.
Some cores (like b11, b44 etc) can talk to bus directly without
intermediate hw, others (like ohci on some bcm socs) wrapped by sumthing
working the way out to the cpu on behalf of device. Bus provides access
to each core and therefore to each final device by means of mmio. Some
of these registers are to manage device'-to-bus and versa workflow (like
tmslow/high, dma control regs, etc), others are solely device registers
(like mii phy access) to controler device itself. Each device registers'
set is mapped into memory one after another 4K space for each core.
For some systems (plain SSB bus) base is at SSB_ENUM_BASE, for others
(connected over e. g. PCI or PCMCIA) prior accessing device ssb code
must "ask" host bus to map ssb core registers' into cpu addrspace prior
accessing it.
When you see "Core xxx found" its ssb scan code iterating through cores'
register space. Either just +0x1000 mmio regs base or requesting
underlying bus to switch active core before probing next one and then
reading/parsing their IDHI register for identification data.
> What are the other cores for? Why do we need driver for chipcommon,
> mipscore? Are that cores internally accessed by 80211 core?
Prior to using any core, very same as b43 one, others (mipscore, usb,
b44, etc.) must be set up properly.
Therefore drivers exists. Chipcommon need setup as well - it handles
cpu/mem/bus/clocks, power control, built-in uarts and might be much
more. Its like "wrapper" core for indirect bus management.
And I dont know if 80211 is talking directly to any other core except
maybe chipcommon.
> What is that whole AI? Is that replacement for SSB? Does it also
> contains cores? What AI and SSB share?
>
While I was struggling with emailer in mine goddamn sloooooooow gnome
x-win terminal Michael already extremely precisely told what AI is ;)
Have nice day,
George
On Wed, 2011-02-09 at 23:03 +0200, George Kashperko wrote:
> 1)
> if (sb_bus)
> ssb_write32(dev, (ssb_read32(dev, SSB_TMSLOW) & ~(mask << 16)) | (flags << 16));
> else
> ssb_write32(dev, (ssb_read32(dev, SSB_AI_IOCTL) & ~mask) | flags));
> 2)
> ssb_core_ctl_flags(dev, mask, flags, NULL);
3) The non-obfuscated way; in the driver:
if (sb_bus)
ssb_write32(dev, (ssb_read32(dev, SSB_TMSLOW) & ~(mask << 16)) | (flags << 16));
else
ai_write32(dev, (ai_read32(dev, AI_IOCTL) & ~mask) | flags));
--
Greetings Michael.
From: George Kashperko <[email protected]>
Reintroduce ssb device enable, disable, is_enabled, admatch base and size
routines as device ops. This is required for transparent support for AI-style
SB buses later on. As soon as exported routines were just replaced by device
ops with appropriate inline accessor helpers these changes won't impact
any ssb-related code.
Signed-off-by: George Kashperko <[email protected]>
---
drivers/ssb/main.c | 52 ++++++++++++++++++++------------------
include/linux/ssb/ssb.h | 43 ++++++++++++++++++++++---------
2 files changed, 59 insertions(+), 36 deletions(-)
--- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:28:54.000000000 +0200
+++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:04:14.000000000 +0200
@@ -49,6 +49,8 @@ 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)
@@ -737,20 +739,6 @@ static void ssb_ssb_block_write(struct s
}
#endif /* CONFIG_SSB_BLOCKIO */
-/* 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
-};
-
static int ssb_fetch_invariants(struct ssb_bus *bus,
ssb_invariants_func_t get_invariants)
{
@@ -1136,7 +1124,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 +1135,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 +1148,8 @@ 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 +1178,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 +1205,8 @@ 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 +1228,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 +1299,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 +1323,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 +1349,25 @@ u32 ssb_admatch_size(struct ssb_device *
return size;
}
-EXPORT_SYMBOL(ssb_admatch_size);
+
+/* 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,
+};
static int __init ssb_modinit(void)
{
--- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:28:54.000000000 +0200
+++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:29:56.000000000 +0200
@@ -119,6 +119,11 @@ struct ssb_bus_ops {
void (*block_write)(struct ssb_device *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width);
#endif
+ 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);
};
@@ -415,14 +420,6 @@ 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);
-/* 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);
-/* Disable a device in hardware and pass SSB_TMSLOW flags (if any). */
-void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
-
/* Device MMIO register read/write functions. */
static inline u8 ssb_read8(struct ssb_device *dev, u16 offset)
@@ -462,6 +459,32 @@ static inline void ssb_block_write(struc
dev->ops->block_write(dev, buffer, count, offset, reg_width);
}
#endif /* CONFIG_SSB_BLOCKIO */
+/* Is the device enabled in hardware? */
+static inline int ssb_device_is_enabled(struct ssb_device *dev)
+{
+ return dev->ops->device_is_enabled(dev);
+}
+/* Enable a device and pass device-specific SSB_TMSLOW 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->ops->device_enable(dev, core_specific_flags);
+}
+/* Disable a device in hardware and pass SSB_TMSLOW flags (if any). */
+static inline void ssb_device_disable(struct ssb_device *dev,
+ u32 core_specific_flags)
+{
+ return dev->ops->device_disable(dev, core_specific_flags);
+}
+static inline u32 ssb_admatch_base(struct ssb_device *dev, u32 adm)
+{
+ return dev->ops->admatch_base(dev, adm);
+}
+static inline u32 ssb_admatch_size(struct ssb_device *dev, u32 adm)
+{
+ return dev->ops->admatch_size(dev, adm);
+}
/* The SSB DMA API. Use this API for any DMA operation on the device.
@@ -519,10 +542,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. */
On Wed, 2011-02-09 at 22:35 +0100, Rafał Miłecki wrote:
> What about proposed solution?
Well, I'm not going to maintain it due to a lack of devices,
knowledge of the AI and a serious lack of additional time.
However, I'm certainly OK with you adopting maintainership
if people think that the code looks sane and should be merged.
One thing I really don't like is the name-confusion introduced
by this. We will have functions with the ssb_...() prefix
that don't necessarily operate on ssb devices, but on AI devices
instead, depending on the actual magic behind the scenes.
That's one of the major things I tried hard to avoid in the
SSB design from day 0 on.
It's what I hated most about Broadcom's SB implementation (there it
is pci_...() functions, which operate on PCI, SB or whatever else
depending on some serious magic).
So my proposal doesn't change: Create two separate busses (SSB and AI)
and port the device drivers to work on both. That also implies
decoupling the built-in SSB device drivers (CC, MIPS, EXTIF, PCICORE)
from the SSB implementation.
The code duplication will negligible.
--
Greetings Michael.
> W dniu 9 lutego 2011 22:03 użytkownik George Kashperko
> <[email protected]> napisał:
> >
> > В Срд, 09/02/2011 в 21:35 +0100, Rafał Miłecki пишет:
> >> 2011/2/9 George Kashperko <[email protected]>:
> >> > From: George Kashperko <[email protected]>
> >> >
> >> > Introduce handlers 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 | 36 ++++++++++++++++++++++++++++++++++++
> >> > include/linux/ssb/ssb.h | 14 +++++++++++++-
> >> > 2 files changed, 49 insertions(+), 1 deletion(-)
> >> > --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:58:50.000000000 +0200
> >> > +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 17:07:11.000000000 +0200
> >> > @@ -1350,6 +1350,40 @@ static u32 ssb_admatch_size_sb(struct ss
> >> > return size;
> >> > }
> >> >
> >> > +static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
> >> > + u32 val, u32 *res)
> >> > +{
> >> > + u32 tmp;
> >> > +
> >> > + if (mask || val) {
> >> > + tmp = (ssb_read32(dev, SSB_TMSLOW) & ~mask) | val;
> >> > + ssb_write32(dev, SSB_TMSLOW, tmp);
> >> > + }
> >>
> >> Are you going to use that function for just reading SSB_TMSLOW? Why
> >> won't you use separated function then? Do you need separated function
> >> for sth so simple as "ssb_read32(dev, SSB_TMSLOW);" at all?
> > Will answer your question with another question ;)
> > What would you personally prefer (press "1" or "2" :p)?
> > 1)
> > if (sb_bus)
> > ssb_write32(dev, (ssb_read32(dev, SSB_TMSLOW) & ~(mask << 16)) | (flags << 16));
> > else
> > ssb_write32(dev, (ssb_read32(dev, SSB_AI_IOCTL) & ~mask) | flags));
> > 2)
> > ssb_core_ctl_flags(dev, mask, flags, NULL);
>
> I aksed about reading, you gave me examples of writing. I want to
> avoid such a non-readable disasters:
> u32 tmp;
> ssb_core_ctl_flags(dev, 0, 0, &tmp);
>
Okay. I will change it to behave like ssb_core_state_flags.
You are right it will be much cleaner.
Have nice day,
George
On 02/09/2011 08:32 AM, George Kashperko wrote:
> 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 device op.
> Signed-off-by: George Kashperko <[email protected]>
> ---
> drivers/ssb/driver_mipscore.c | 2 +-
> drivers/ssb/main.c | 1 +
> include/linux/ssb/ssb.h | 5 +++++
> include/linux/ssb/ssb_driver_mips.h | 1 +
> 4 files changed, 8 insertions(+), 1 deletion(-)
> --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-01 05:05:49.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-07 16:39:46.000000000 +0200
> @@ -47,7 +47,7 @@ static const u32 ipsflag_irq_shift[] = {
> SSB_IPSFLAG_IRQ4_SHIFT,
> };
>
> -static inline u32 ssb_irqflag(struct ssb_device *dev)
> +u32 ssb_irqflag_sb(struct ssb_device *dev)
> {
> u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
> if (tpsflag)
> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:35:50.000000000 +0200
> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:49:40.000000000 +0200
> @@ -1367,6 +1367,7 @@ static const struct ssb_bus_ops ssb_ssb_
> .device_disable = ssb_device_disable_sb,
> .admatch_base = ssb_admatch_base_sb,
> .admatch_size = ssb_admatch_size_sb,
> + .irqflag = ssb_irqflag_sb,
> };
>
> static int __init ssb_modinit(void)
> --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-01 05:05:49.000000000 +0200
> +++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-07 16:39:10.000000000 +0200
> @@ -29,6 +29,7 @@ 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 */
> --- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:35:50.000000000 +0200
> +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:38:34.000000000 +0200
> @@ -124,6 +124,7 @@ struct ssb_bus_ops {
> 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 (*irqflag)(struct ssb_device *dev);
> };
>
>
> @@ -485,6 +486,10 @@ static inline u32 ssb_admatch_size(struc
> {
> return dev->ops->admatch_size(dev, adm);
> }
> +static inline u32 ssb_irqflag(struct ssb_device *dev)
> +{
> + return dev->ops->irqflag(dev);
> +}
>
>
> /* The SSB DMA API. Use this API for any DMA operation on the device.
>
>
>
> --
This one fails to compile with the following error:
drivers/ssb/main.c:1370:14: error: ?ssb_irqflag_sb? undeclared here (not in a
function)
make[1]: *** [drivers/ssb/main.o] Error 1
make: *** [drivers/ssb/] Error 2
Larry
Hi,
> Uf, I'm back after weekend.
>
> W dniu 10 lutego 2011 00:30 użytkownik George Kashperko
> <[email protected]> napisał:
> >> What are the other cores for? Why do we need driver for chipcommon,
> >> mipscore? Are that cores internally accessed by 80211 core?
> >
> > Prior to using any core, very same as b43 one, others (mipscore, usb,
> > b44, etc.) must be set up properly.
> > Therefore drivers exists. Chipcommon need setup as well - it handles
> > cpu/mem/bus/clocks, power control, built-in uarts and might be much
> > more. Its like "wrapper" core for indirect bus management.
> > And I dont know if 80211 is talking directly to any other core except
> > maybe chipcommon.
>
> Thanks for explanation, but what about cores like internal memory, or
> usb? What are they for?
>
As for internal memory core dont really know. There is some asm magic in
Broadcom's code to set timings and maybe something else but I've never
looked it in depth, maybe some day later.
And usb core, well, its interface to usb host controller.
Have nice day,
George
В Срд, 09/02/2011 в 23:02 +0100, Michael Büsch пишет:
> On Wed, 2011-02-09 at 22:55 +0100, Rafał Miłecki wrote:
> > I aksed about reading, you gave me examples of writing. I want to
> > avoid such a non-readable disasters:
> > u32 tmp;
> > ssb_core_ctl_flags(dev, 0, 0, &tmp);
>
> A good function name consists of:
> "WHAT is done and WHERE is it done"
>
> ssb_core_ctl_flags()
> violates both of them. It doesn't specify what is done at all,
> except that it might be something random with ctl flags.
> And it lies about where it does it. It implies that it operates
> on SSB. However, it might operate on SSB or AI.
>
Well, have nothing to say here.
Tbh things like I see them looks like following.
1. possibility is to "mask" bus differences by dev ops. Obviously you
already have seen these patches. This will cover pretty much everyting
on behalf of end device drivers. Everything _if_ decide on control/state
flags treatment.
2. Make separate bus driver. Not a bad way either I'm sure. But still
device drivers are to manage those control/state flags but this time
with if/elses (or just with sumthing like b43_ctl_flags/b43_state_flags
which will do the same as ssb_core_control_flags atm). Tbh b43_ctl_flags
would be bad name for such a function as donno if it gonna flags >> 16
or not so better do things with plain ssb_read32/ssb_write32 :p
As it would be separate bus there will be few more structs for
ssb_ai_driver_register or whatever, not worse mentinning but still.
Apart from those flags' location everything else (dma, phy io, etc.)
will be pretty much the same. So the only difference from driver's
perespective here are
1. care control flags
2. care control flags, care bits more bus ops.
>From ssb code prespective for SB bus changes are little to nothing (does
it really matters that alot replacing extern fn1 with static inline
fn1(){ ops->fn_a1 }?) except that there will be 2 more files (ssb_ai.h,
ssb_ai.c 12k length both most of which is EROM scanning code - just take
a look at ssb_ai.c - 180 lines with copyrights and whitespace if you
delete that EROM dancing). Does that 180 lines really worse introducing
whole new bus ? Im not sure honestly but its like I see the things. And
ofcourse I dont insist on this vision.
Have nice day,
George
On 02/09/2011 01:26 PM, George Kashperko wrote:
>
>> On 02/09/2011 12:23 PM, George Kashperko wrote:
>>>
>>>> On 02/09/2011 11:10 AM, George Kashperko wrote:
>>>>>> On 02/09/2011 08:32 AM, George Kashperko wrote:
>>>>>>> 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 device op.
>>>>>>> Signed-off-by: George Kashperko <[email protected]>
>>>>>>> ---
>>>>>>> drivers/ssb/driver_mipscore.c | 2 +-
>>>>>>> drivers/ssb/main.c | 1 +
>>>>>>> include/linux/ssb/ssb.h | 5 +++++
>>>>>>> include/linux/ssb/ssb_driver_mips.h | 1 +
>>>>>>> 4 files changed, 8 insertions(+), 1 deletion(-)
>>>>>>> --- linux-next-20110203.orig/drivers/ssb/driver_mipscore.c 2011-02-01 05:05:49.000000000 +0200
>>>>>>> +++ linux-next-20110203/drivers/ssb/driver_mipscore.c 2011-02-07 16:39:46.000000000 +0200
>>>>>>> @@ -47,7 +47,7 @@ static const u32 ipsflag_irq_shift[] = {
>>>>>>> SSB_IPSFLAG_IRQ4_SHIFT,
>>>>>>> };
>>>>>>>
>>>>>>> -static inline u32 ssb_irqflag(struct ssb_device *dev)
>>>>>>> +u32 ssb_irqflag_sb(struct ssb_device *dev)
>>>>>>> {
>>>>>>> u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
>>>>>>> if (tpsflag)
>>>>>>> --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:35:50.000000000 +0200
>>>>>>> +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 16:49:40.000000000 +0200
>>>>>>> @@ -1367,6 +1367,7 @@ static const struct ssb_bus_ops ssb_ssb_
>>>>>>> .device_disable = ssb_device_disable_sb,
>>>>>>> .admatch_base = ssb_admatch_base_sb,
>>>>>>> .admatch_size = ssb_admatch_size_sb,
>>>>>>> + .irqflag = ssb_irqflag_sb,
>>>>>>> };
>>>>>>>
>>>>>>> static int __init ssb_modinit(void)
>>>>>>> --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_mips.h 2011-02-01 05:05:49.000000000 +0200
>>>>>>> +++ linux-next-20110203/include/linux/ssb/ssb_driver_mips.h 2011-02-07 16:39:10.000000000 +0200
>>>>>>> @@ -29,6 +29,7 @@ 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 */
>>>>>>> --- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-07 16:35:50.000000000 +0200
>>>>>>> +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-07 16:38:34.000000000 +0200
>>>>>>> @@ -124,6 +124,7 @@ struct ssb_bus_ops {
>>>>>>> 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 (*irqflag)(struct ssb_device *dev);
>>>>>>> };
>>>>>>>
>>>>>>>
>>>>>>> @@ -485,6 +486,10 @@ static inline u32 ssb_admatch_size(struc
>>>>>>> {
>>>>>>> return dev->ops->admatch_size(dev, adm);
>>>>>>> }
>>>>>>> +static inline u32 ssb_irqflag(struct ssb_device *dev)
>>>>>>> +{
>>>>>>> + return dev->ops->irqflag(dev);
>>>>>>> +}
>>>>>>>
>>>>>>>
>>>>>>> /* The SSB DMA API. Use this API for any DMA operation on the device.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>
>>>>>> This one fails to compile with the following error:
>>>>>>
>>>>>> drivers/ssb/main.c:1370:14: error: ‘ssb_irqflag_sb’ undeclared here (not in a
>>>>>> function)
>>>>>> make[1]: *** [drivers/ssb/main.o] Error 1
>>>>>> make: *** [drivers/ssb/] Error 2
>>>>>>
>>>>>> Larry
>>>>>> --
>>>>>> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
>>>>>> the body of a message to [email protected]
>>>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>>>
>>>>> Well, might the problem here is again caused with mine wrong post of <[RFC9/11] SSB modify irqflag treatment>
>>>>> Could you please remove that one and reaply whole set of patches again.
>>>>> Sorry for inconveniences.
>>>>
>>>> That cannot be the problem with this one. Each patch in a series MUST compile
>>>> correctly so that anyone that is bisecting the code always can build a kernel.
>>>> The code doesn't necessarily have to work correctly - that would be nice, but it
>>>> must compile. #3 fails this test.
>>>>
>>>> Larry
>>>>
>>> I do understand this. Every patch among these 11 (actually there are 21
>>> patches to get things working with newer Broadcom's socs) I've tested
>>> both compiling them and also flashing final images to two boxes -
>>> bcm4716 and bcm5354 I own in order to ensure that old things are still
>>> working as expected while new things didnt got bricked by changes I
>>> made.
>>> Just checked 3rd patch again - it applied and compiled cleanly for me,
>>> and mine SB-based bcm5354 is still alive after reflash.
>>>
>>> ssb_irqflag_sb is declared as extern in ssb_driver_mips.h which is
>>> included with ssb.h to main.c
>>> Could you please verify if patch applied cleanly ? I'm much surprised
>>> here as I can see no reason for <‘ssb_irqflag_sb’ undeclared here> error
>>> in main.c other than patch failed to get applied to ssb_driver_mips.h
>>
>> It applied cleanly; however, you must consider the possibility that not everyone
>> has CONFIG_SSB_DRIVER_MIPS defined. On my x86_64 system, I clearly do not. With
>> the following change, it compiled:
>>
>> #ifdef CONFIG_SSB_DRIVER_MIPS
>> .irqflag = ssb_irqflag_sb,
>> #endif
>>
>> I haven't gone deeply enough into the code to see if that is the correct change,
>> or not. If x86 hardware can run AI hardware, then it won't be.
>>
>> Larry
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
> Ohh lol. Seems im completely burrowed into mips stuff forgetting there
> are things apart from mips :)
> Will start reviewing code for other arch dependencies right now. Thanks
> a lot for pointing it out for me.
> There will be completely the same issue with 11th patch as AI code got
> the same op struct with unconditional mips irqflag fn.
>
> Are there any other issues with patch applying/compiling left ?
I had a couple of patch failures due to adding the MIPS conditional around
irqflag, but those were easily fixed. With all patches applied, including the
one from the previous email, I'm still getting
drivers/ssb/scan.c: In function ‘ssb_bus_detect’:
drivers/ssb/scan.c:387:6: error: ‘cpu_data’ undeclared (first use in this function)
drivers/ssb/scan.c:387:6: note: each undeclared identifier is reported only once
for each function it appears in
drivers/ssb/scan.c:387:29: error: ‘CPU_74K’ undeclared (first use in this function)
make[2]: *** [drivers/ssb/scan.o] Error 1
I haven't found the cause yet, but I'm sure it is MIPS related.
Larry
2011/2/10 Michael Büsch <[email protected]>:
> You're actually abusing the ops structure. The ops structure is meant
> to abstract the SSB backplane from its host bus. It is _not_ meant
> to abstract the SSB backplane itself. Your patches mix that up. It's
> an abstraction layer violation, which my proposal avoids completely.
After some reading, learning, I think I generally agree with Michael.
George: I like you consider separated bus driver now. Please let us
know when you design something!
--
Rafał
W dniu 9 lutego 2011 22:03 użytkownik George Kashperko
<[email protected]> napisał:
>
> В Срд, 09/02/2011 в 21:35 +0100, Rafał Miłecki пишет:
>> 2011/2/9 George Kashperko <[email protected]>:
>> > From: George Kashperko <[email protected]>
>> >
>> > Introduce handlers 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 | 36 ++++++++++++++++++++++++++++++++++++
>> > include/linux/ssb/ssb.h | 14 +++++++++++++-
>> > 2 files changed, 49 insertions(+), 1 deletion(-)
>> > --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-07 16:58:50.000000000 +0200
>> > +++ linux-next-20110203/drivers/ssb/main.c 2011-02-07 17:07:11.000000000 +0200
>> > @@ -1350,6 +1350,40 @@ static u32 ssb_admatch_size_sb(struct ss
>> > return size;
>> > }
>> >
>> > +static void ssb_core_ctl_flags_sb(struct ssb_device *dev, u32 mask,
>> > + u32 val, u32 *res)
>> > +{
>> > + u32 tmp;
>> > +
>> > + if (mask || val) {
>> > + tmp = (ssb_read32(dev, SSB_TMSLOW) & ~mask) | val;
>> > + ssb_write32(dev, SSB_TMSLOW, tmp);
>> > + }
>>
>> Are you going to use that function for just reading SSB_TMSLOW? Why
>> won't you use separated function then? Do you need separated function
>> for sth so simple as "ssb_read32(dev, SSB_TMSLOW);" at all?
> Will answer your question with another question ;)
> What would you personally prefer (press "1" or "2" :p)?
> 1)
> if (sb_bus)
> ssb_write32(dev, (ssb_read32(dev, SSB_TMSLOW) & ~(mask << 16)) | (flags << 16));
> else
> ssb_write32(dev, (ssb_read32(dev, SSB_AI_IOCTL) & ~mask) | flags));
> 2)
> ssb_core_ctl_flags(dev, mask, flags, NULL);
I aksed about reading, you gave me examples of writing. I want to
avoid such a non-readable disasters:
u32 tmp;
ssb_core_ctl_flags(dev, 0, 0, &tmp);
--
Rafał
В Срд, 09/02/2011 в 22:35 +0100, Rafał Miłecki пишет:
> Switching general discussion to this thread.
>
> W dniu 9 lutego 2011 22:12 użytkownik Michael Büsch <[email protected]> napisał:
> > On Wed, 2011-02-09 at 21:58 +0100, Rafał Miłecki wrote:
> >> I don't know, I've doubts about it :/ That flags are quite messy, mask
> >> for them is 0x3FFC0000. Ideally we should shift it by 14 bits, but
> >> that would make writing code harder. Maaaaybe... Michael what do you
> >> think about this?
> >
> > I have no idea.
> > I already expressed my opinion on all this stuff.
> >
> > One thing is for certain: If this is merged, George has to
> > adopt maintainership.
>
> What about proposed solution? Does it still look ugly for you with
> that pointers to functions? It looks quite fine separated, similarly
> to b43 and PHYs I think. Separated files and structs with pointers.
>
> George: apart from few simple comparisons on beginning (like detecting
> type of device and determining name in switch), do you need any more
> (many?) tests in general code? Do you have many "if ssb_sb) {} else
> {}"?
>
In current SB-only linux world ssb code provided services from drivers'
perespective pretty much starts with bus_powerup, device_enable, ....
driver life cycle ... device_disable, bus_powerdown (shortened fn names
for simplification). somewhere between ... and ... inside that driver's
lifecycle it could call _enable again to reset device and so on.
If you take a closer look at device_enable/disable you will see that
those two are pretty much all about reading and writing proper bits to
high 2 bytes of TMSLOW.
TMSLOW (and obviously TMSHIGH as well) are pretty much special. And
first one is so much special that we all use ssb_device_enable instead
of going simple non-obfiscated way of just ssb_read32 and ssb_write32
stuff we need to get that damn chip enabled/disabled/reset :P
Therefore I really dont see the reason why should one use if (ssb_sb)
do_smth_with_sb_ctl_flags(); else do_smth_with_ai_ctl_flags();
constructs instead of just do_smth_with_ctl_flags(); when accessing core
control and state registers which live in high 2 bytes of 0x0F98/0x0F9C
for SB and in low 2 bytes 0x408/0x500 while featuring _absolutely_ the
same bits meaning within that 2 bytes.
Have nice day,
George