| 1 | --- a/drivers/ssb/main.c |
| 2 | +++ b/drivers/ssb/main.c |
| 3 | @@ -1192,10 +1192,10 @@ void ssb_device_enable(struct ssb_device |
| 4 | } |
| 5 | EXPORT_SYMBOL(ssb_device_enable); |
| 6 | |
| 7 | -/* Wait for a bit in a register to get set or unset. |
| 8 | +/* Wait for bitmask in a register to get set or cleared. |
| 9 | * timeout is in units of ten-microseconds */ |
| 10 | -static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask, |
| 11 | - int timeout, int set) |
| 12 | +static int ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask, |
| 13 | + int timeout, int set) |
| 14 | { |
| 15 | int i; |
| 16 | u32 val; |
| 17 | @@ -1203,7 +1203,7 @@ static int ssb_wait_bit(struct ssb_devic |
| 18 | for (i = 0; i < timeout; i++) { |
| 19 | val = ssb_read32(dev, reg); |
| 20 | if (set) { |
| 21 | - if (val & bitmask) |
| 22 | + if ((val & bitmask) == bitmask) |
| 23 | return 0; |
| 24 | } else { |
| 25 | if (!(val & bitmask)) |
| 26 | @@ -1220,20 +1220,38 @@ static int ssb_wait_bit(struct ssb_devic |
| 27 | |
| 28 | void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags) |
| 29 | { |
| 30 | - u32 reject; |
| 31 | + u32 reject, val; |
| 32 | |
| 33 | if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET) |
| 34 | return; |
| 35 | |
| 36 | reject = ssb_tmslow_reject_bitmask(dev); |
| 37 | - ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK); |
| 38 | - ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1); |
| 39 | - ssb_wait_bit(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0); |
| 40 | - ssb_write32(dev, SSB_TMSLOW, |
| 41 | - SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | |
| 42 | - reject | SSB_TMSLOW_RESET | |
| 43 | - core_specific_flags); |
| 44 | - ssb_flush_tmslow(dev); |
| 45 | + |
| 46 | + if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_CLOCK) { |
| 47 | + ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK); |
| 48 | + ssb_wait_bits(dev, SSB_TMSLOW, reject, 1000, 1); |
| 49 | + ssb_wait_bits(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0); |
| 50 | + |
| 51 | + if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) { |
| 52 | + val = ssb_read32(dev, SSB_IMSTATE); |
| 53 | + val |= SSB_IMSTATE_REJECT; |
| 54 | + ssb_write32(dev, SSB_IMSTATE, val); |
| 55 | + ssb_wait_bits(dev, SSB_IMSTATE, SSB_IMSTATE_BUSY, 1000, |
| 56 | + 0); |
| 57 | + } |
| 58 | + |
| 59 | + ssb_write32(dev, SSB_TMSLOW, |
| 60 | + SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | |
| 61 | + reject | SSB_TMSLOW_RESET | |
| 62 | + core_specific_flags); |
| 63 | + ssb_flush_tmslow(dev); |
| 64 | + |
| 65 | + if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) { |
| 66 | + val = ssb_read32(dev, SSB_IMSTATE); |
| 67 | + val &= ~SSB_IMSTATE_REJECT; |
| 68 | + ssb_write32(dev, SSB_IMSTATE, val); |
| 69 | + } |
| 70 | + } |
| 71 | |
| 72 | ssb_write32(dev, SSB_TMSLOW, |
| 73 | reject | SSB_TMSLOW_RESET | |
| 74 | --- a/drivers/ssb/pci.c |
| 75 | +++ b/drivers/ssb/pci.c |
| 76 | @@ -468,10 +468,14 @@ static void sprom_extract_r45(struct ssb |
| 77 | SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); |
| 78 | SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); |
| 79 | SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); |
| 80 | + SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0); |
| 81 | + SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0); |
| 82 | } else { |
| 83 | SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0); |
| 84 | SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); |
| 85 | SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); |
| 86 | + SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); |
| 87 | + SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0); |
| 88 | } |
| 89 | SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, |
| 90 | SSB_SPROM4_ANTAVAIL_A_SHIFT); |
| 91 | @@ -641,7 +645,7 @@ static int sprom_extract(struct ssb_bus |
| 92 | break; |
| 93 | default: |
| 94 | ssb_printk(KERN_WARNING PFX "Unsupported SPROM" |
| 95 | - " revision %d detected. Will extract" |
| 96 | + " revision %d detected. Will extract" |
| 97 | " v1\n", out->revision); |
| 98 | out->revision = 1; |
| 99 | sprom_extract_r123(out, in); |
| 100 | --- a/include/linux/ssb/ssb_regs.h |
| 101 | +++ b/include/linux/ssb/ssb_regs.h |
| 102 | @@ -85,6 +85,8 @@ |
| 103 | #define SSB_IMSTATE_AP_RSV 0x00000030 /* Reserved */ |
| 104 | #define SSB_IMSTATE_IBE 0x00020000 /* In Band Error */ |
| 105 | #define SSB_IMSTATE_TO 0x00040000 /* Timeout */ |
| 106 | +#define SSB_IMSTATE_BUSY 0x01800000 /* Busy (Backplane rev >= 2.3 only) */ |
| 107 | +#define SSB_IMSTATE_REJECT 0x02000000 /* Reject (Backplane rev >= 2.3 only) */ |
| 108 | #define SSB_INTVEC 0x0F94 /* SB Interrupt Mask */ |
| 109 | #define SSB_INTVEC_PCI 0x00000001 /* Enable interrupts for PCI */ |
| 110 | #define SSB_INTVEC_ENET0 0x00000002 /* Enable interrupts for enet 0 */ |
| 111 | @@ -97,7 +99,6 @@ |
| 112 | #define SSB_TMSLOW_RESET 0x00000001 /* Reset */ |
| 113 | #define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */ |
| 114 | #define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */ |
| 115 | -#define SSB_TMSLOW_PHYCLK 0x00000010 /* MAC PHY Clock Control Enable */ |
| 116 | #define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */ |
| 117 | #define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */ |
| 118 | #define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */ |
| 119 | @@ -268,6 +269,8 @@ |
| 120 | /* SPROM Revision 4 */ |
| 121 | #define SSB_SPROM4_BFLLO 0x0044 /* Boardflags (low 16 bits) */ |
| 122 | #define SSB_SPROM4_BFLHI 0x0046 /* Board Flags Hi */ |
| 123 | +#define SSB_SPROM4_BFL2LO 0x0048 /* Board flags 2 (low 16 bits) */ |
| 124 | +#define SSB_SPROM4_BFL2HI 0x004A /* Board flags 2 Hi */ |
| 125 | #define SSB_SPROM4_IL0MAC 0x004C /* 6 byte MAC address for a/b/g/n */ |
| 126 | #define SSB_SPROM4_CCODE 0x0052 /* Country Code (2 bytes) */ |
| 127 | #define SSB_SPROM4_GPIOA 0x0056 /* Gen. Purpose IO # 0 and 1 */ |
| 128 | @@ -358,6 +361,8 @@ |
| 129 | #define SSB_SPROM5_CCODE 0x0044 /* Country Code (2 bytes) */ |
| 130 | #define SSB_SPROM5_BFLLO 0x004A /* Boardflags (low 16 bits) */ |
| 131 | #define SSB_SPROM5_BFLHI 0x004C /* Board Flags Hi */ |
| 132 | +#define SSB_SPROM5_BFL2LO 0x004E /* Board flags 2 (low 16 bits) */ |
| 133 | +#define SSB_SPROM5_BFL2HI 0x0050 /* Board flags 2 Hi */ |
| 134 | #define SSB_SPROM5_IL0MAC 0x0052 /* 6 byte MAC address for a/b/g/n */ |
| 135 | #define SSB_SPROM5_GPIOA 0x0076 /* Gen. Purpose IO # 0 and 1 */ |
| 136 | #define SSB_SPROM5_GPIOA_P0 0x00FF /* Pin 0 */ |
| 137 | |