diff options
-rw-r--r-- | drivers/ssb/main.c | 16 | ||||
-rw-r--r-- | include/linux/ssb/ssb_regs.h | 2 |
2 files changed, 17 insertions, 1 deletions
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 775c579817b4..06c0b6d5250d 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -1220,7 +1220,7 @@ static int ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask, | |||
1220 | 1220 | ||
1221 | void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags) | 1221 | void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags) |
1222 | { | 1222 | { |
1223 | u32 reject; | 1223 | u32 reject, val; |
1224 | 1224 | ||
1225 | if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET) | 1225 | if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET) |
1226 | return; | 1226 | return; |
@@ -1229,12 +1229,26 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags) | |||
1229 | ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK); | 1229 | ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK); |
1230 | ssb_wait_bits(dev, SSB_TMSLOW, reject, 1000, 1); | 1230 | ssb_wait_bits(dev, SSB_TMSLOW, reject, 1000, 1); |
1231 | ssb_wait_bits(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0); | 1231 | ssb_wait_bits(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0); |
1232 | |||
1233 | if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) { | ||
1234 | val = ssb_read32(dev, SSB_IMSTATE); | ||
1235 | val |= SSB_IMSTATE_REJECT; | ||
1236 | ssb_write32(dev, SSB_IMSTATE, val); | ||
1237 | ssb_wait_bits(dev, SSB_IMSTATE, SSB_IMSTATE_BUSY, 1000, 0); | ||
1238 | } | ||
1239 | |||
1232 | ssb_write32(dev, SSB_TMSLOW, | 1240 | ssb_write32(dev, SSB_TMSLOW, |
1233 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | | 1241 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | |
1234 | reject | SSB_TMSLOW_RESET | | 1242 | reject | SSB_TMSLOW_RESET | |
1235 | core_specific_flags); | 1243 | core_specific_flags); |
1236 | ssb_flush_tmslow(dev); | 1244 | ssb_flush_tmslow(dev); |
1237 | 1245 | ||
1246 | if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) { | ||
1247 | val = ssb_read32(dev, SSB_IMSTATE); | ||
1248 | val &= ~SSB_IMSTATE_REJECT; | ||
1249 | ssb_write32(dev, SSB_IMSTATE, val); | ||
1250 | } | ||
1251 | |||
1238 | ssb_write32(dev, SSB_TMSLOW, | 1252 | ssb_write32(dev, SSB_TMSLOW, |
1239 | reject | SSB_TMSLOW_RESET | | 1253 | reject | SSB_TMSLOW_RESET | |
1240 | core_specific_flags); | 1254 | core_specific_flags); |
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 9b1125bea1fc..402955ae48ce 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h | |||
@@ -85,6 +85,8 @@ | |||
85 | #define SSB_IMSTATE_AP_RSV 0x00000030 /* Reserved */ | 85 | #define SSB_IMSTATE_AP_RSV 0x00000030 /* Reserved */ |
86 | #define SSB_IMSTATE_IBE 0x00020000 /* In Band Error */ | 86 | #define SSB_IMSTATE_IBE 0x00020000 /* In Band Error */ |
87 | #define SSB_IMSTATE_TO 0x00040000 /* Timeout */ | 87 | #define SSB_IMSTATE_TO 0x00040000 /* Timeout */ |
88 | #define SSB_IMSTATE_BUSY 0x01800000 /* Busy (Backplane rev >= 2.3 only) */ | ||
89 | #define SSB_IMSTATE_REJECT 0x02000000 /* Reject (Backplane rev >= 2.3 only) */ | ||
88 | #define SSB_INTVEC 0x0F94 /* SB Interrupt Mask */ | 90 | #define SSB_INTVEC 0x0F94 /* SB Interrupt Mask */ |
89 | #define SSB_INTVEC_PCI 0x00000001 /* Enable interrupts for PCI */ | 91 | #define SSB_INTVEC_PCI 0x00000001 /* Enable interrupts for PCI */ |
90 | #define SSB_INTVEC_ENET0 0x00000002 /* Enable interrupts for enet 0 */ | 92 | #define SSB_INTVEC_ENET0 0x00000002 /* Enable interrupts for enet 0 */ |