aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h12
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.c447
2 files changed, 309 insertions, 150 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 1fca1f9c48fe..57fcaafcf7dd 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -526,8 +526,16 @@ struct bcm43xx_radioinfo {
526 526
527 /* Current Interference Mitigation mode */ 527 /* Current Interference Mitigation mode */
528 int interfmode; 528 int interfmode;
529 /* Stack of saved values from the Interference Mitigation code */ 529 /* Stack of saved values from the Interference Mitigation code.
530 u16 interfstack[20]; 530 * Each value in the stack is layed out as follows:
531 * bit 0-11: offset
532 * bit 12-15: register ID
533 * bit 16-32: value
534 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
535 */
536#define BCM43xx_INTERFSTACK_SIZE 26
537 u32 interfstack[BCM43xx_INTERFSTACK_SIZE];
538
531 /* Saved values from the NRSSI Slope calculation */ 539 /* Saved values from the NRSSI Slope calculation */
532 s16 nrssi[2]; 540 s16 nrssi[2];
533 s32 nrssislope; 541 s32 nrssislope;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
index 4e8d8c936ab4..63aae43ba838 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -879,24 +879,76 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm)
879 } 879 }
880} 880}
881 881
882/* Helper macros to save on and restore values from the radio->interfstack */ 882/* Stack implementation to save/restore values from the
883#ifdef stack_save 883 * interference mitigation code.
884# undef stack_save 884 * It is save to restore values in random order.
885#endif 885 */
886#ifdef stack_restore 886static void _stack_save(u32 *_stackptr, size_t *stackidx,
887# undef stack_restore 887 u8 id, u16 offset, u16 value)
888#endif 888{
889#define stack_save(value) \ 889 u32 *stackptr = &(_stackptr[*stackidx]);
890
891 assert((offset & 0xF000) == 0x0000);
892 assert((id & 0xF0) == 0x00);
893 *stackptr = offset;
894 *stackptr |= ((u32)id) << 12;
895 *stackptr |= ((u32)value) << 16;
896 (*stackidx)++;
897 assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
898}
899
900static u16 _stack_restore(u32 *stackptr,
901 u8 id, u16 offset)
902{
903 size_t i;
904
905 assert((offset & 0xF000) == 0x0000);
906 assert((id & 0xF0) == 0x00);
907 for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
908 if ((*stackptr & 0x00000FFF) != offset)
909 continue;
910 if (((*stackptr & 0x0000F000) >> 12) != id)
911 continue;
912 return ((*stackptr & 0xFFFF0000) >> 16);
913 }
914 assert(0);
915
916 return 0;
917}
918
919#define phy_stacksave(offset) \
890 do { \ 920 do { \
891 assert(i < ARRAY_SIZE(radio->interfstack)); \ 921 _stack_save(stack, &stackidx, 0x1, (offset), \
892 stack[i++] = (value); \ 922 bcm43xx_phy_read(bcm, (offset))); \
923 } while (0)
924#define phy_stackrestore(offset) \
925 do { \
926 bcm43xx_phy_write(bcm, (offset), \
927 _stack_restore(stack, 0x1, \
928 (offset))); \
929 } while (0)
930#define radio_stacksave(offset) \
931 do { \
932 _stack_save(stack, &stackidx, 0x2, (offset), \
933 bcm43xx_radio_read16(bcm, (offset))); \
934 } while (0)
935#define radio_stackrestore(offset) \
936 do { \
937 bcm43xx_radio_write16(bcm, (offset), \
938 _stack_restore(stack, 0x2, \
939 (offset))); \
940 } while (0)
941#define ilt_stacksave(offset) \
942 do { \
943 _stack_save(stack, &stackidx, 0x3, (offset), \
944 bcm43xx_ilt_read(bcm, (offset))); \
945 } while (0)
946#define ilt_stackrestore(offset) \
947 do { \
948 bcm43xx_ilt_write(bcm, (offset), \
949 _stack_restore(stack, 0x3, \
950 (offset))); \
893 } while (0) 951 } while (0)
894
895#define stack_restore() \
896 ({ \
897 assert(i < ARRAY_SIZE(radio->interfstack)); \
898 stack[i++]; \
899 })
900 952
901static void 953static void
902bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, 954bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
@@ -904,144 +956,231 @@ bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
904{ 956{
905 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 957 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
906 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); 958 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
907 int i = 0;
908 u16 *stack = radio->interfstack;
909 u16 tmp, flipped; 959 u16 tmp, flipped;
960 u32 tmp32;
961 size_t stackidx = 0;
962 u32 *stack = radio->interfstack;
910 963
911 switch (mode) { 964 switch (mode) {
912 case BCM43xx_RADIO_INTERFMODE_NONWLAN: 965 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
913 if (phy->rev != 1) { 966 if (phy->rev != 1) {
914 bcm43xx_phy_write(bcm, 0x042B, 967 bcm43xx_phy_write(bcm, 0x042B,
915 bcm43xx_phy_read(bcm, 0x042B) & 0x0800); 968 bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
916 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, 969 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
917 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000); 970 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000);
918 break; 971 break;
919 } 972 }
973 radio_stacksave(0x0078);
920 tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); 974 tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);
921 flipped = flip_4bit(tmp); 975 flipped = flip_4bit(tmp);
922 if ((flipped >> 1) >= 4) 976 if (flipped < 10 && flipped >= 8)
923 tmp = flipped - 3; 977 flipped = 7;
924 tmp = flip_4bit(tmp); 978 else if (flipped >= 10)
925 bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); 979 flipped -= 3;
980 flipped = flip_4bit(flipped);
981 flipped = (flipped << 1) | 0x0020;
982 bcm43xx_radio_write16(bcm, 0x0078, flipped);
926 983
927 bcm43xx_calc_nrssi_threshold(bcm); 984 bcm43xx_calc_nrssi_threshold(bcm);
928 985
929 if (bcm->current_core->rev < 5) { 986 phy_stacksave(0x0406);
930 stack_save(bcm43xx_phy_read(bcm, 0x0406)); 987 bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
931 bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
932 } else {
933 stack_save(bcm43xx_phy_read(bcm, 0x04C0));
934 stack_save(bcm43xx_phy_read(bcm, 0x04C1));
935 bcm43xx_phy_write(bcm, 0x04C0, 0x3E04);
936 bcm43xx_phy_write(bcm, 0x04C1, 0x0640);
937 }
938 988
939 bcm43xx_phy_write(bcm, 0x042B, 989 bcm43xx_phy_write(bcm, 0x042B,
940 bcm43xx_phy_read(bcm, 0x042B) | 0x0800); 990 bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
941 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, 991 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
942 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000); 992 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
943 993
944 stack_save(bcm43xx_phy_read(bcm, 0x04A0)); 994 phy_stacksave(0x04A0);
945 bcm43xx_phy_write(bcm, 0x04A0, 995 bcm43xx_phy_write(bcm, 0x04A0,
946 (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); 996 (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);
947 stack_save(bcm43xx_phy_read(bcm, 0x04A1)); 997 phy_stacksave(0x04A1);
948 bcm43xx_phy_write(bcm, 0x04A1, 998 bcm43xx_phy_write(bcm, 0x04A1,
949 (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); 999 (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);
950 stack_save(bcm43xx_phy_read(bcm, 0x04A2)); 1000 phy_stacksave(0x04A2);
951 bcm43xx_phy_write(bcm, 0x04A2, 1001 bcm43xx_phy_write(bcm, 0x04A2,
952 (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); 1002 (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);
953 stack_save(bcm43xx_phy_read(bcm, 0x04A8)); 1003 phy_stacksave(0x04A8);
954 bcm43xx_phy_write(bcm, 0x04A8, 1004 bcm43xx_phy_write(bcm, 0x04A8,
955 (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0403); 1005 (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);
956 stack_save(bcm43xx_phy_read(bcm, 0x04AB)); 1006 phy_stacksave(0x04AB);
957 bcm43xx_phy_write(bcm, 0x04AB, 1007 bcm43xx_phy_write(bcm, 0x04AB,
958 (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0504); 1008 (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);
959 1009
960 stack_save(bcm43xx_phy_read(bcm, 0x04A7)); 1010 phy_stacksave(0x04A7);
961 bcm43xx_phy_write(bcm, 0x04A7, 0x0002); 1011 bcm43xx_phy_write(bcm, 0x04A7, 0x0002);
962 stack_save(bcm43xx_phy_read(bcm, 0x04A3)); 1012 phy_stacksave(0x04A3);
963 bcm43xx_phy_write(bcm, 0x04A3, 0x287A); 1013 bcm43xx_phy_write(bcm, 0x04A3, 0x287A);
964 stack_save(bcm43xx_phy_read(bcm, 0x04A9)); 1014 phy_stacksave(0x04A9);
965 bcm43xx_phy_write(bcm, 0x04A9, 0x2027); 1015 bcm43xx_phy_write(bcm, 0x04A9, 0x2027);
966 stack_save(bcm43xx_phy_read(bcm, 0x0493)); 1016 phy_stacksave(0x0493);
967 bcm43xx_phy_write(bcm, 0x0493, 0x32F5); 1017 bcm43xx_phy_write(bcm, 0x0493, 0x32F5);
968 stack_save(bcm43xx_phy_read(bcm, 0x04AA)); 1018 phy_stacksave(0x04AA);
969 bcm43xx_phy_write(bcm, 0x04AA, 0x2027); 1019 bcm43xx_phy_write(bcm, 0x04AA, 0x2027);
970 stack_save(bcm43xx_phy_read(bcm, 0x04AC)); 1020 phy_stacksave(0x04AC);
971 bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); 1021 bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);
972 break; 1022 break;
973 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: 1023 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
974 if (bcm43xx_phy_read(bcm, 0x0033) == 0x0800) 1024 if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)
975 break; 1025 break;
976 1026
977 radio->aci_enable = 1; 1027 radio->aci_enable = 1;
978 1028
979 stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)); 1029 phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
980 stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)); 1030 phy_stacksave(BCM43xx_PHY_G_CRS);
981 if (bcm->current_core->rev < 5) { 1031 if (phy->rev < 2) {
982 stack_save(bcm43xx_phy_read(bcm, 0x0406)); 1032 phy_stacksave(0x0406);
983 } else { 1033 } else {
984 stack_save(bcm43xx_phy_read(bcm, 0x04C0)); 1034 phy_stacksave(0x04C0);
985 stack_save(bcm43xx_phy_read(bcm, 0x04C1)); 1035 phy_stacksave(0x04C1);
986 } 1036 }
987 stack_save(bcm43xx_phy_read(bcm, 0x0033)); 1037 phy_stacksave(0x0033);
988 stack_save(bcm43xx_phy_read(bcm, 0x04A7)); 1038 phy_stacksave(0x04A7);
989 stack_save(bcm43xx_phy_read(bcm, 0x04A3)); 1039 phy_stacksave(0x04A3);
990 stack_save(bcm43xx_phy_read(bcm, 0x04A9)); 1040 phy_stacksave(0x04A9);
991 stack_save(bcm43xx_phy_read(bcm, 0x04AA)); 1041 phy_stacksave(0x04AA);
992 stack_save(bcm43xx_phy_read(bcm, 0x04AC)); 1042 phy_stacksave(0x04AC);
993 stack_save(bcm43xx_phy_read(bcm, 0x0493)); 1043 phy_stacksave(0x0493);
994 stack_save(bcm43xx_phy_read(bcm, 0x04A1)); 1044 phy_stacksave(0x04A1);
995 stack_save(bcm43xx_phy_read(bcm, 0x04A0)); 1045 phy_stacksave(0x04A0);
996 stack_save(bcm43xx_phy_read(bcm, 0x04A2)); 1046 phy_stacksave(0x04A2);
997 stack_save(bcm43xx_phy_read(bcm, 0x048A)); 1047 phy_stacksave(0x048A);
998 stack_save(bcm43xx_phy_read(bcm, 0x04A8)); 1048 phy_stacksave(0x04A8);
999 stack_save(bcm43xx_phy_read(bcm, 0x04AB)); 1049 phy_stacksave(0x04AB);
1050 if (phy->rev == 2) {
1051 phy_stacksave(0x04AD);
1052 phy_stacksave(0x04AE);
1053 } else if (phy->rev >= 3) {
1054 phy_stacksave(0x04AD);
1055 phy_stacksave(0x0415);
1056 phy_stacksave(0x0416);
1057 phy_stacksave(0x0417);
1058 ilt_stacksave(0x1A00 + 0x2);
1059 ilt_stacksave(0x1A00 + 0x3);
1060 }
1061 phy_stacksave(0x042B);
1062 phy_stacksave(0x048C);
1000 1063
1001 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, 1064 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
1002 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & 0xEFFF); 1065 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
1066 & ~0x1000);
1003 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, 1067 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1004 (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xEFFF) | 0x0002); 1068 (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
1069 & 0xFFFC) | 0x0002);
1005 1070
1006 bcm43xx_phy_write(bcm, 0x04A7, 0x0800); 1071 bcm43xx_phy_write(bcm, 0x0033, 0x0800);
1007 bcm43xx_phy_write(bcm, 0x04A3, 0x287A); 1072 bcm43xx_phy_write(bcm, 0x04A3, 0x2027);
1008 bcm43xx_phy_write(bcm, 0x04A9, 0x2027); 1073 bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);
1009 bcm43xx_phy_write(bcm, 0x0493, 0x32F5); 1074 bcm43xx_phy_write(bcm, 0x0493, 0x287A);
1010 bcm43xx_phy_write(bcm, 0x04AA, 0x2027); 1075 bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);
1011 bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); 1076 bcm43xx_phy_write(bcm, 0x04AC, 0x287A);
1012 1077
1013 bcm43xx_phy_write(bcm, 0x04A0, 1078 bcm43xx_phy_write(bcm, 0x04A0,
1014 (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFC0) | 0x001A); 1079 (bcm43xx_phy_read(bcm, 0x04A0)
1015 if (bcm->current_core->rev < 5) { 1080 & 0xFFC0) | 0x001A);
1016 bcm43xx_phy_write(bcm, 0x0406, 0x280D); 1081 bcm43xx_phy_write(bcm, 0x04A7, 0x000D);
1017 } else { 1082
1018 bcm43xx_phy_write(bcm, 0x04C0, 0x0640); 1083 if (phy->rev < 2) {
1084 bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);
1085 } else if (phy->rev == 2) {
1086 bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);
1019 bcm43xx_phy_write(bcm, 0x04C1, 0x00A9); 1087 bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);
1088 } else {
1089 bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);
1090 bcm43xx_phy_write(bcm, 0x04C1, 0x0059);
1020 } 1091 }
1021 1092
1022 bcm43xx_phy_write(bcm, 0x04A1, 1093 bcm43xx_phy_write(bcm, 0x04A1,
1023 (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0FF) | 0x1800); 1094 (bcm43xx_phy_read(bcm, 0x04A1)
1095 & 0xC0FF) | 0x1800);
1024 bcm43xx_phy_write(bcm, 0x04A1, 1096 bcm43xx_phy_write(bcm, 0x04A1,
1025 (bcm43xx_phy_read(bcm, 0x04A1) & 0xFFC0) | 0x0016); 1097 (bcm43xx_phy_read(bcm, 0x04A1)
1026 bcm43xx_phy_write(bcm, 0x04A2, 1098 & 0xFFC0) | 0x0015);
1027 (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0900);
1028 bcm43xx_phy_write(bcm, 0x04A0,
1029 (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0700);
1030 bcm43xx_phy_write(bcm, 0x04A2,
1031 (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x000D);
1032 bcm43xx_phy_write(bcm, 0x04A8, 1099 bcm43xx_phy_write(bcm, 0x04A8,
1033 (bcm43xx_phy_read(bcm, 0x04A8) & 0xCFFF) | 0x1000); 1100 (bcm43xx_phy_read(bcm, 0x04A8)
1101 & 0xCFFF) | 0x1000);
1034 bcm43xx_phy_write(bcm, 0x04A8, 1102 bcm43xx_phy_write(bcm, 0x04A8,
1035 (bcm43xx_phy_read(bcm, 0x04A8) & 0xF0FF) | 0x0A00); 1103 (bcm43xx_phy_read(bcm, 0x04A8)
1104 & 0xF0FF) | 0x0A00);
1036 bcm43xx_phy_write(bcm, 0x04AB, 1105 bcm43xx_phy_write(bcm, 0x04AB,
1037 (bcm43xx_phy_read(bcm, 0x04AB) & 0xCFFF) | 0x1000); 1106 (bcm43xx_phy_read(bcm, 0x04AB)
1107 & 0xCFFF) | 0x1000);
1038 bcm43xx_phy_write(bcm, 0x04AB, 1108 bcm43xx_phy_write(bcm, 0x04AB,
1039 (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0800); 1109 (bcm43xx_phy_read(bcm, 0x04AB)
1110 & 0xF0FF) | 0x0800);
1040 bcm43xx_phy_write(bcm, 0x04AB, 1111 bcm43xx_phy_write(bcm, 0x04AB,
1041 (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFCF) | 0x0010); 1112 (bcm43xx_phy_read(bcm, 0x04AB)
1113 & 0xFFCF) | 0x0010);
1042 bcm43xx_phy_write(bcm, 0x04AB, 1114 bcm43xx_phy_write(bcm, 0x04AB,
1043 (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFF0) | 0x0006); 1115 (bcm43xx_phy_read(bcm, 0x04AB)
1116 & 0xFFF0) | 0x0005);
1117 bcm43xx_phy_write(bcm, 0x04A8,
1118 (bcm43xx_phy_read(bcm, 0x04A8)
1119 & 0xFFCF) | 0x0010);
1120 bcm43xx_phy_write(bcm, 0x04A8,
1121 (bcm43xx_phy_read(bcm, 0x04A8)
1122 & 0xFFF0) | 0x0006);
1123 bcm43xx_phy_write(bcm, 0x04A2,
1124 (bcm43xx_phy_read(bcm, 0x04A2)
1125 & 0xF0FF) | 0x0800);
1126 bcm43xx_phy_write(bcm, 0x04A0,
1127 (bcm43xx_phy_read(bcm, 0x04A0)
1128 & 0xF0FF) | 0x0500);
1129 bcm43xx_phy_write(bcm, 0x04A2,
1130 (bcm43xx_phy_read(bcm, 0x04A2)
1131 & 0xFFF0) | 0x000B);
1044 1132
1133 if (phy->rev >= 3) {
1134 bcm43xx_phy_write(bcm, 0x048A,
1135 bcm43xx_phy_read(bcm, 0x048A)
1136 & ~0x8000);
1137 bcm43xx_phy_write(bcm, 0x0415,
1138 (bcm43xx_phy_read(bcm, 0x0415)
1139 & 0x8000) | 0x36D8);
1140 bcm43xx_phy_write(bcm, 0x0416,
1141 (bcm43xx_phy_read(bcm, 0x0416)
1142 & 0x8000) | 0x36D8);
1143 bcm43xx_phy_write(bcm, 0x0417,
1144 (bcm43xx_phy_read(bcm, 0x0417)
1145 & 0xFE00) | 0x016D);
1146 } else {
1147 bcm43xx_phy_write(bcm, 0x048A,
1148 bcm43xx_phy_read(bcm, 0x048A)
1149 | 0x1000);
1150 bcm43xx_phy_write(bcm, 0x048A,
1151 (bcm43xx_phy_read(bcm, 0x048A)
1152 & 0x9FFF) | 0x2000);
1153 tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1154 BCM43xx_UCODEFLAGS_OFFSET);
1155 if (!(tmp32 & 0x800)) {
1156 tmp32 |= 0x800;
1157 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1158 BCM43xx_UCODEFLAGS_OFFSET,
1159 tmp32);
1160 }
1161 }
1162 if (phy->rev >= 2) {
1163 bcm43xx_phy_write(bcm, 0x042B,
1164 bcm43xx_phy_read(bcm, 0x042B)
1165 | 0x0800);
1166 }
1167 bcm43xx_phy_write(bcm, 0x048C,
1168 (bcm43xx_phy_read(bcm, 0x048C)
1169 & 0xF0FF) | 0x0200);
1170 if (phy->rev == 2) {
1171 bcm43xx_phy_write(bcm, 0x04AE,
1172 (bcm43xx_phy_read(bcm, 0x04AE)
1173 & 0xFF00) | 0x007F);
1174 bcm43xx_phy_write(bcm, 0x04AD,
1175 (bcm43xx_phy_read(bcm, 0x04AD)
1176 & 0x00FF) | 0x1300);
1177 } else if (phy->rev >= 6) {
1178 bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);
1179 bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);
1180 bcm43xx_phy_write(bcm, 0x04AD,
1181 bcm43xx_phy_read(bcm, 0x04AD)
1182 & 0x00FF);
1183 }
1045 bcm43xx_calc_nrssi_slope(bcm); 1184 bcm43xx_calc_nrssi_slope(bcm);
1046 break; 1185 break;
1047 default: 1186 default:
@@ -1055,9 +1194,8 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
1055{ 1194{
1056 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); 1195 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1057 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); 1196 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1058 int i = 0; 1197 u32 tmp32;
1059 u16 *stack = radio->interfstack; 1198 u32 *stack = radio->interfstack;
1060 u16 tmp, flipped;
1061 1199
1062 switch (mode) { 1200 switch (mode) {
1063 case BCM43xx_RADIO_INTERFMODE_NONWLAN: 1201 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
@@ -1065,71 +1203,80 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
1065 bcm43xx_phy_write(bcm, 0x042B, 1203 bcm43xx_phy_write(bcm, 0x042B,
1066 bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); 1204 bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
1067 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, 1205 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1068 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); 1206 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
1069 break; 1207 break;
1070 } 1208 }
1071 tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); 1209 phy_stackrestore(0x0078);
1072 flipped = flip_4bit(tmp);
1073 if ((flipped >> 1) >= 0x000C)
1074 tmp = flipped + 3;
1075 tmp = flip_4bit(tmp);
1076 bcm43xx_radio_write16(bcm, 0x0078, tmp << 1);
1077
1078 bcm43xx_calc_nrssi_threshold(bcm); 1210 bcm43xx_calc_nrssi_threshold(bcm);
1079 1211 phy_stackrestore(0x0406);
1080 if (bcm->current_core->rev < 5) {
1081 bcm43xx_phy_write(bcm, 0x0406, stack_restore());
1082 } else {
1083 bcm43xx_phy_write(bcm, 0x04C0, stack_restore());
1084 bcm43xx_phy_write(bcm, 0x04C1, stack_restore());
1085 }
1086 bcm43xx_phy_write(bcm, 0x042B, 1212 bcm43xx_phy_write(bcm, 0x042B,
1087 bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); 1213 bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
1088 1214 if (!bcm->bad_frames_preempt) {
1089 if (!bcm->bad_frames_preempt)
1090 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, 1215 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
1091 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & ~(1 << 11)); 1216 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
1217 & ~(1 << 11));
1218 }
1092 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, 1219 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1093 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); 1220 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
1094 bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); 1221 phy_stackrestore(0x04A0);
1095 bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); 1222 phy_stackrestore(0x04A1);
1096 bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); 1223 phy_stackrestore(0x04A2);
1097 bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); 1224 phy_stackrestore(0x04A8);
1098 bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); 1225 phy_stackrestore(0x04AB);
1099 bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); 1226 phy_stackrestore(0x04A7);
1100 bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); 1227 phy_stackrestore(0x04A3);
1101 bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); 1228 phy_stackrestore(0x04A9);
1102 bcm43xx_phy_write(bcm, 0x0493, stack_restore()); 1229 phy_stackrestore(0x0493);
1103 bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); 1230 phy_stackrestore(0x04AA);
1104 bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); 1231 phy_stackrestore(0x04AC);
1105 break; 1232 break;
1106 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: 1233 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
1107 if (bcm43xx_phy_read(bcm, 0x0033) != 0x0800) 1234 if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))
1108 break; 1235 break;
1109 1236
1110 radio->aci_enable = 0; 1237 radio->aci_enable = 0;
1111 1238
1112 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, stack_restore()); 1239 phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
1113 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, stack_restore()); 1240 phy_stackrestore(BCM43xx_PHY_G_CRS);
1114 if (bcm->current_core->rev < 5) { 1241 phy_stackrestore(0x0033);
1115 bcm43xx_phy_write(bcm, 0x0406, stack_restore()); 1242 phy_stackrestore(0x04A3);
1116 } else { 1243 phy_stackrestore(0x04A9);
1117 bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); 1244 phy_stackrestore(0x0493);
1118 bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); 1245 phy_stackrestore(0x04AA);
1246 phy_stackrestore(0x04AC);
1247 phy_stackrestore(0x04A0);
1248 phy_stackrestore(0x04A7);
1249 if (phy->rev >= 2) {
1250 phy_stackrestore(0x04C0);
1251 phy_stackrestore(0x04C1);
1252 } else
1253 phy_stackrestore(0x0406);
1254 phy_stackrestore(0x04A1);
1255 phy_stackrestore(0x04AB);
1256 phy_stackrestore(0x04A8);
1257 if (phy->rev == 2) {
1258 phy_stackrestore(0x04AD);
1259 phy_stackrestore(0x04AE);
1260 } else if (phy->rev >= 3) {
1261 phy_stackrestore(0x04AD);
1262 phy_stackrestore(0x0415);
1263 phy_stackrestore(0x0416);
1264 phy_stackrestore(0x0417);
1265 ilt_stackrestore(0x1A00 + 0x2);
1266 ilt_stackrestore(0x1A00 + 0x3);
1267 }
1268 phy_stackrestore(0x04A2);
1269 phy_stackrestore(0x04A8);
1270 phy_stackrestore(0x042B);
1271 phy_stackrestore(0x048C);
1272 tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1273 BCM43xx_UCODEFLAGS_OFFSET);
1274 if (tmp32 & 0x800) {
1275 tmp32 &= ~0x800;
1276 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1277 BCM43xx_UCODEFLAGS_OFFSET,
1278 tmp32);
1119 } 1279 }
1120 bcm43xx_phy_write(bcm, 0x0033, stack_restore());
1121 bcm43xx_phy_write(bcm, 0x04A7, stack_restore());
1122 bcm43xx_phy_write(bcm, 0x04A3, stack_restore());
1123 bcm43xx_phy_write(bcm, 0x04A9, stack_restore());
1124 bcm43xx_phy_write(bcm, 0x04AA, stack_restore());
1125 bcm43xx_phy_write(bcm, 0x04AC, stack_restore());
1126 bcm43xx_phy_write(bcm, 0x0493, stack_restore());
1127 bcm43xx_phy_write(bcm, 0x04A1, stack_restore());
1128 bcm43xx_phy_write(bcm, 0x04A0, stack_restore());
1129 bcm43xx_phy_write(bcm, 0x04A2, stack_restore());
1130 bcm43xx_phy_write(bcm, 0x04A8, stack_restore());
1131 bcm43xx_phy_write(bcm, 0x04AB, stack_restore());
1132
1133 bcm43xx_calc_nrssi_slope(bcm); 1280 bcm43xx_calc_nrssi_slope(bcm);
1134 break; 1281 break;
1135 default: 1282 default:
@@ -1137,8 +1284,12 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
1137 } 1284 }
1138} 1285}
1139 1286
1140#undef stack_save 1287#undef phy_stacksave
1141#undef stack_restore 1288#undef phy_stackrestore
1289#undef radio_stacksave
1290#undef radio_stackrestore
1291#undef ilt_stacksave
1292#undef ilt_stackrestore
1142 1293
1143int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, 1294int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,
1144 int mode) 1295 int mode)