radio.c 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158
  1. /*
  2. Broadcom B43legacy wireless driver
  3. Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
  4. Stefano Brivio <st3@riseup.net>
  5. Michael Buesch <mbuesch@freenet.de>
  6. Danny van Dyk <kugelfang@gentoo.org>
  7. Andreas Jaggi <andreas.jaggi@waterwave.ch>
  8. Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
  9. Some parts of the code in this file are derived from the ipw2200
  10. driver Copyright(c) 2003 - 2004 Intel Corporation.
  11. This program is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; either version 2 of the License, or
  14. (at your option) any later version.
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU General Public License for more details.
  19. You should have received a copy of the GNU General Public License
  20. along with this program; see the file COPYING. If not, write to
  21. the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
  22. Boston, MA 02110-1301, USA.
  23. */
  24. #include <linux/delay.h>
  25. #include "b43legacy.h"
  26. #include "main.h"
  27. #include "phy.h"
  28. #include "radio.h"
  29. #include "ilt.h"
  30. /* Table for b43legacy_radio_calibrationvalue() */
  31. static const u16 rcc_table[16] = {
  32. 0x0002, 0x0003, 0x0001, 0x000F,
  33. 0x0006, 0x0007, 0x0005, 0x000F,
  34. 0x000A, 0x000B, 0x0009, 0x000F,
  35. 0x000E, 0x000F, 0x000D, 0x000F,
  36. };
  37. /* Reverse the bits of a 4bit value.
  38. * Example: 1101 is flipped 1011
  39. */
  40. static u16 flip_4bit(u16 value)
  41. {
  42. u16 flipped = 0x0000;
  43. B43legacy_BUG_ON(!((value & ~0x000F) == 0x0000));
  44. flipped |= (value & 0x0001) << 3;
  45. flipped |= (value & 0x0002) << 1;
  46. flipped |= (value & 0x0004) >> 1;
  47. flipped |= (value & 0x0008) >> 3;
  48. return flipped;
  49. }
  50. /* Get the freq, as it has to be written to the device. */
  51. static inline
  52. u16 channel2freq_bg(u8 channel)
  53. {
  54. /* Frequencies are given as frequencies_bg[index] + 2.4GHz
  55. * Starting with channel 1
  56. */
  57. static const u16 frequencies_bg[14] = {
  58. 12, 17, 22, 27,
  59. 32, 37, 42, 47,
  60. 52, 57, 62, 67,
  61. 72, 84,
  62. };
  63. if (unlikely(channel < 1 || channel > 14)) {
  64. printk(KERN_INFO "b43legacy: Channel %d is out of range\n",
  65. channel);
  66. dump_stack();
  67. return 2412;
  68. }
  69. return frequencies_bg[channel - 1];
  70. }
  71. void b43legacy_radio_lock(struct b43legacy_wldev *dev)
  72. {
  73. u32 status;
  74. status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
  75. status |= B43legacy_SBF_RADIOREG_LOCK;
  76. b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
  77. mmiowb();
  78. udelay(10);
  79. }
  80. void b43legacy_radio_unlock(struct b43legacy_wldev *dev)
  81. {
  82. u32 status;
  83. b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */
  84. status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
  85. status &= ~B43legacy_SBF_RADIOREG_LOCK;
  86. b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
  87. mmiowb();
  88. }
  89. u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset)
  90. {
  91. struct b43legacy_phy *phy = &dev->phy;
  92. switch (phy->type) {
  93. case B43legacy_PHYTYPE_B:
  94. if (phy->radio_ver == 0x2053) {
  95. if (offset < 0x70)
  96. offset += 0x80;
  97. else if (offset < 0x80)
  98. offset += 0x70;
  99. } else if (phy->radio_ver == 0x2050)
  100. offset |= 0x80;
  101. else
  102. B43legacy_WARN_ON(1);
  103. break;
  104. case B43legacy_PHYTYPE_G:
  105. offset |= 0x80;
  106. break;
  107. default:
  108. B43legacy_BUG_ON(1);
  109. }
  110. b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset);
  111. return b43legacy_read16(dev, B43legacy_MMIO_RADIO_DATA_LOW);
  112. }
  113. void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val)
  114. {
  115. b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset);
  116. mmiowb();
  117. b43legacy_write16(dev, B43legacy_MMIO_RADIO_DATA_LOW, val);
  118. }
  119. static void b43legacy_set_all_gains(struct b43legacy_wldev *dev,
  120. s16 first, s16 second, s16 third)
  121. {
  122. struct b43legacy_phy *phy = &dev->phy;
  123. u16 i;
  124. u16 start = 0x08;
  125. u16 end = 0x18;
  126. u16 offset = 0x0400;
  127. u16 tmp;
  128. if (phy->rev <= 1) {
  129. offset = 0x5000;
  130. start = 0x10;
  131. end = 0x20;
  132. }
  133. for (i = 0; i < 4; i++)
  134. b43legacy_ilt_write(dev, offset + i, first);
  135. for (i = start; i < end; i++)
  136. b43legacy_ilt_write(dev, offset + i, second);
  137. if (third != -1) {
  138. tmp = ((u16)third << 14) | ((u16)third << 6);
  139. b43legacy_phy_write(dev, 0x04A0,
  140. (b43legacy_phy_read(dev, 0x04A0) & 0xBFBF)
  141. | tmp);
  142. b43legacy_phy_write(dev, 0x04A1,
  143. (b43legacy_phy_read(dev, 0x04A1) & 0xBFBF)
  144. | tmp);
  145. b43legacy_phy_write(dev, 0x04A2,
  146. (b43legacy_phy_read(dev, 0x04A2) & 0xBFBF)
  147. | tmp);
  148. }
  149. b43legacy_dummy_transmission(dev);
  150. }
  151. static void b43legacy_set_original_gains(struct b43legacy_wldev *dev)
  152. {
  153. struct b43legacy_phy *phy = &dev->phy;
  154. u16 i;
  155. u16 tmp;
  156. u16 offset = 0x0400;
  157. u16 start = 0x0008;
  158. u16 end = 0x0018;
  159. if (phy->rev <= 1) {
  160. offset = 0x5000;
  161. start = 0x0010;
  162. end = 0x0020;
  163. }
  164. for (i = 0; i < 4; i++) {
  165. tmp = (i & 0xFFFC);
  166. tmp |= (i & 0x0001) << 1;
  167. tmp |= (i & 0x0002) >> 1;
  168. b43legacy_ilt_write(dev, offset + i, tmp);
  169. }
  170. for (i = start; i < end; i++)
  171. b43legacy_ilt_write(dev, offset + i, i - start);
  172. b43legacy_phy_write(dev, 0x04A0,
  173. (b43legacy_phy_read(dev, 0x04A0) & 0xBFBF)
  174. | 0x4040);
  175. b43legacy_phy_write(dev, 0x04A1,
  176. (b43legacy_phy_read(dev, 0x04A1) & 0xBFBF)
  177. | 0x4040);
  178. b43legacy_phy_write(dev, 0x04A2,
  179. (b43legacy_phy_read(dev, 0x04A2) & 0xBFBF)
  180. | 0x4000);
  181. b43legacy_dummy_transmission(dev);
  182. }
  183. /* Synthetic PU workaround */
  184. static void b43legacy_synth_pu_workaround(struct b43legacy_wldev *dev,
  185. u8 channel)
  186. {
  187. struct b43legacy_phy *phy = &dev->phy;
  188. might_sleep();
  189. if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6)
  190. /* We do not need the workaround. */
  191. return;
  192. if (channel <= 10)
  193. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL,
  194. channel2freq_bg(channel + 4));
  195. else
  196. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL,
  197. channel2freq_bg(channel));
  198. msleep(1);
  199. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL,
  200. channel2freq_bg(channel));
  201. }
  202. u8 b43legacy_radio_aci_detect(struct b43legacy_wldev *dev, u8 channel)
  203. {
  204. struct b43legacy_phy *phy = &dev->phy;
  205. u8 ret = 0;
  206. u16 saved;
  207. u16 rssi;
  208. u16 temp;
  209. int i;
  210. int j = 0;
  211. saved = b43legacy_phy_read(dev, 0x0403);
  212. b43legacy_radio_selectchannel(dev, channel, 0);
  213. b43legacy_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5);
  214. if (phy->aci_hw_rssi)
  215. rssi = b43legacy_phy_read(dev, 0x048A) & 0x3F;
  216. else
  217. rssi = saved & 0x3F;
  218. /* clamp temp to signed 5bit */
  219. if (rssi > 32)
  220. rssi -= 64;
  221. for (i = 0; i < 100; i++) {
  222. temp = (b43legacy_phy_read(dev, 0x047F) >> 8) & 0x3F;
  223. if (temp > 32)
  224. temp -= 64;
  225. if (temp < rssi)
  226. j++;
  227. if (j >= 20)
  228. ret = 1;
  229. }
  230. b43legacy_phy_write(dev, 0x0403, saved);
  231. return ret;
  232. }
  233. u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)
  234. {
  235. struct b43legacy_phy *phy = &dev->phy;
  236. u8 ret[13];
  237. unsigned int channel = phy->channel;
  238. unsigned int i;
  239. unsigned int j;
  240. unsigned int start;
  241. unsigned int end;
  242. unsigned long phylock_flags;
  243. if (!((phy->type == B43legacy_PHYTYPE_G) && (phy->rev > 0)))
  244. return 0;
  245. b43legacy_phy_lock(dev, phylock_flags);
  246. b43legacy_radio_lock(dev);
  247. b43legacy_phy_write(dev, 0x0802,
  248. b43legacy_phy_read(dev, 0x0802) & 0xFFFC);
  249. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  250. b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
  251. & 0x7FFF);
  252. b43legacy_set_all_gains(dev, 3, 8, 1);
  253. start = (channel - 5 > 0) ? channel - 5 : 1;
  254. end = (channel + 5 < 14) ? channel + 5 : 13;
  255. for (i = start; i <= end; i++) {
  256. if (abs(channel - i) > 2)
  257. ret[i-1] = b43legacy_radio_aci_detect(dev, i);
  258. }
  259. b43legacy_radio_selectchannel(dev, channel, 0);
  260. b43legacy_phy_write(dev, 0x0802,
  261. (b43legacy_phy_read(dev, 0x0802) & 0xFFFC)
  262. | 0x0003);
  263. b43legacy_phy_write(dev, 0x0403,
  264. b43legacy_phy_read(dev, 0x0403) & 0xFFF8);
  265. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  266. b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
  267. | 0x8000);
  268. b43legacy_set_original_gains(dev);
  269. for (i = 0; i < 13; i++) {
  270. if (!ret[i])
  271. continue;
  272. end = (i + 5 < 13) ? i + 5 : 13;
  273. for (j = i; j < end; j++)
  274. ret[j] = 1;
  275. }
  276. b43legacy_radio_unlock(dev);
  277. b43legacy_phy_unlock(dev, phylock_flags);
  278. return ret[channel - 1];
  279. }
  280. /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
  281. void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val)
  282. {
  283. b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset);
  284. mmiowb();
  285. b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_DATA, (u16)val);
  286. }
  287. /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
  288. s16 b43legacy_nrssi_hw_read(struct b43legacy_wldev *dev, u16 offset)
  289. {
  290. u16 val;
  291. b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset);
  292. val = b43legacy_phy_read(dev, B43legacy_PHY_NRSSILT_DATA);
  293. return (s16)val;
  294. }
  295. /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
  296. void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val)
  297. {
  298. u16 i;
  299. s16 tmp;
  300. for (i = 0; i < 64; i++) {
  301. tmp = b43legacy_nrssi_hw_read(dev, i);
  302. tmp -= val;
  303. tmp = limit_value(tmp, -32, 31);
  304. b43legacy_nrssi_hw_write(dev, i, tmp);
  305. }
  306. }
  307. /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
  308. void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev)
  309. {
  310. struct b43legacy_phy *phy = &dev->phy;
  311. s16 i;
  312. s16 delta;
  313. s32 tmp;
  314. delta = 0x1F - phy->nrssi[0];
  315. for (i = 0; i < 64; i++) {
  316. tmp = (i - delta) * phy->nrssislope;
  317. tmp /= 0x10000;
  318. tmp += 0x3A;
  319. tmp = limit_value(tmp, 0, 0x3F);
  320. phy->nrssi_lt[i] = tmp;
  321. }
  322. }
  323. static void b43legacy_calc_nrssi_offset(struct b43legacy_wldev *dev)
  324. {
  325. struct b43legacy_phy *phy = &dev->phy;
  326. u16 backup[20] = { 0 };
  327. s16 v47F;
  328. u16 i;
  329. u16 saved = 0xFFFF;
  330. backup[0] = b43legacy_phy_read(dev, 0x0001);
  331. backup[1] = b43legacy_phy_read(dev, 0x0811);
  332. backup[2] = b43legacy_phy_read(dev, 0x0812);
  333. backup[3] = b43legacy_phy_read(dev, 0x0814);
  334. backup[4] = b43legacy_phy_read(dev, 0x0815);
  335. backup[5] = b43legacy_phy_read(dev, 0x005A);
  336. backup[6] = b43legacy_phy_read(dev, 0x0059);
  337. backup[7] = b43legacy_phy_read(dev, 0x0058);
  338. backup[8] = b43legacy_phy_read(dev, 0x000A);
  339. backup[9] = b43legacy_phy_read(dev, 0x0003);
  340. backup[10] = b43legacy_radio_read16(dev, 0x007A);
  341. backup[11] = b43legacy_radio_read16(dev, 0x0043);
  342. b43legacy_phy_write(dev, 0x0429,
  343. b43legacy_phy_read(dev, 0x0429) & 0x7FFF);
  344. b43legacy_phy_write(dev, 0x0001,
  345. (b43legacy_phy_read(dev, 0x0001) & 0x3FFF)
  346. | 0x4000);
  347. b43legacy_phy_write(dev, 0x0811,
  348. b43legacy_phy_read(dev, 0x0811) | 0x000C);
  349. b43legacy_phy_write(dev, 0x0812,
  350. (b43legacy_phy_read(dev, 0x0812) & 0xFFF3)
  351. | 0x0004);
  352. b43legacy_phy_write(dev, 0x0802,
  353. b43legacy_phy_read(dev, 0x0802) & ~(0x1 | 0x2));
  354. if (phy->rev >= 6) {
  355. backup[12] = b43legacy_phy_read(dev, 0x002E);
  356. backup[13] = b43legacy_phy_read(dev, 0x002F);
  357. backup[14] = b43legacy_phy_read(dev, 0x080F);
  358. backup[15] = b43legacy_phy_read(dev, 0x0810);
  359. backup[16] = b43legacy_phy_read(dev, 0x0801);
  360. backup[17] = b43legacy_phy_read(dev, 0x0060);
  361. backup[18] = b43legacy_phy_read(dev, 0x0014);
  362. backup[19] = b43legacy_phy_read(dev, 0x0478);
  363. b43legacy_phy_write(dev, 0x002E, 0);
  364. b43legacy_phy_write(dev, 0x002F, 0);
  365. b43legacy_phy_write(dev, 0x080F, 0);
  366. b43legacy_phy_write(dev, 0x0810, 0);
  367. b43legacy_phy_write(dev, 0x0478,
  368. b43legacy_phy_read(dev, 0x0478) | 0x0100);
  369. b43legacy_phy_write(dev, 0x0801,
  370. b43legacy_phy_read(dev, 0x0801) | 0x0040);
  371. b43legacy_phy_write(dev, 0x0060,
  372. b43legacy_phy_read(dev, 0x0060) | 0x0040);
  373. b43legacy_phy_write(dev, 0x0014,
  374. b43legacy_phy_read(dev, 0x0014) | 0x0200);
  375. }
  376. b43legacy_radio_write16(dev, 0x007A,
  377. b43legacy_radio_read16(dev, 0x007A) | 0x0070);
  378. b43legacy_radio_write16(dev, 0x007A,
  379. b43legacy_radio_read16(dev, 0x007A) | 0x0080);
  380. udelay(30);
  381. v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F);
  382. if (v47F >= 0x20)
  383. v47F -= 0x40;
  384. if (v47F == 31) {
  385. for (i = 7; i >= 4; i--) {
  386. b43legacy_radio_write16(dev, 0x007B, i);
  387. udelay(20);
  388. v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8)
  389. & 0x003F);
  390. if (v47F >= 0x20)
  391. v47F -= 0x40;
  392. if (v47F < 31 && saved == 0xFFFF)
  393. saved = i;
  394. }
  395. if (saved == 0xFFFF)
  396. saved = 4;
  397. } else {
  398. b43legacy_radio_write16(dev, 0x007A,
  399. b43legacy_radio_read16(dev, 0x007A)
  400. & 0x007F);
  401. b43legacy_phy_write(dev, 0x0814,
  402. b43legacy_phy_read(dev, 0x0814) | 0x0001);
  403. b43legacy_phy_write(dev, 0x0815,
  404. b43legacy_phy_read(dev, 0x0815) & 0xFFFE);
  405. b43legacy_phy_write(dev, 0x0811,
  406. b43legacy_phy_read(dev, 0x0811) | 0x000C);
  407. b43legacy_phy_write(dev, 0x0812,
  408. b43legacy_phy_read(dev, 0x0812) | 0x000C);
  409. b43legacy_phy_write(dev, 0x0811,
  410. b43legacy_phy_read(dev, 0x0811) | 0x0030);
  411. b43legacy_phy_write(dev, 0x0812,
  412. b43legacy_phy_read(dev, 0x0812) | 0x0030);
  413. b43legacy_phy_write(dev, 0x005A, 0x0480);
  414. b43legacy_phy_write(dev, 0x0059, 0x0810);
  415. b43legacy_phy_write(dev, 0x0058, 0x000D);
  416. if (phy->analog == 0)
  417. b43legacy_phy_write(dev, 0x0003, 0x0122);
  418. else
  419. b43legacy_phy_write(dev, 0x000A,
  420. b43legacy_phy_read(dev, 0x000A)
  421. | 0x2000);
  422. b43legacy_phy_write(dev, 0x0814,
  423. b43legacy_phy_read(dev, 0x0814) | 0x0004);
  424. b43legacy_phy_write(dev, 0x0815,
  425. b43legacy_phy_read(dev, 0x0815) & 0xFFFB);
  426. b43legacy_phy_write(dev, 0x0003,
  427. (b43legacy_phy_read(dev, 0x0003) & 0xFF9F)
  428. | 0x0040);
  429. b43legacy_radio_write16(dev, 0x007A,
  430. b43legacy_radio_read16(dev, 0x007A)
  431. | 0x000F);
  432. b43legacy_set_all_gains(dev, 3, 0, 1);
  433. b43legacy_radio_write16(dev, 0x0043,
  434. (b43legacy_radio_read16(dev, 0x0043)
  435. & 0x00F0) | 0x000F);
  436. udelay(30);
  437. v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F);
  438. if (v47F >= 0x20)
  439. v47F -= 0x40;
  440. if (v47F == -32) {
  441. for (i = 0; i < 4; i++) {
  442. b43legacy_radio_write16(dev, 0x007B, i);
  443. udelay(20);
  444. v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >>
  445. 8) & 0x003F);
  446. if (v47F >= 0x20)
  447. v47F -= 0x40;
  448. if (v47F > -31 && saved == 0xFFFF)
  449. saved = i;
  450. }
  451. if (saved == 0xFFFF)
  452. saved = 3;
  453. } else
  454. saved = 0;
  455. }
  456. b43legacy_radio_write16(dev, 0x007B, saved);
  457. if (phy->rev >= 6) {
  458. b43legacy_phy_write(dev, 0x002E, backup[12]);
  459. b43legacy_phy_write(dev, 0x002F, backup[13]);
  460. b43legacy_phy_write(dev, 0x080F, backup[14]);
  461. b43legacy_phy_write(dev, 0x0810, backup[15]);
  462. }
  463. b43legacy_phy_write(dev, 0x0814, backup[3]);
  464. b43legacy_phy_write(dev, 0x0815, backup[4]);
  465. b43legacy_phy_write(dev, 0x005A, backup[5]);
  466. b43legacy_phy_write(dev, 0x0059, backup[6]);
  467. b43legacy_phy_write(dev, 0x0058, backup[7]);
  468. b43legacy_phy_write(dev, 0x000A, backup[8]);
  469. b43legacy_phy_write(dev, 0x0003, backup[9]);
  470. b43legacy_radio_write16(dev, 0x0043, backup[11]);
  471. b43legacy_radio_write16(dev, 0x007A, backup[10]);
  472. b43legacy_phy_write(dev, 0x0802,
  473. b43legacy_phy_read(dev, 0x0802) | 0x1 | 0x2);
  474. b43legacy_phy_write(dev, 0x0429,
  475. b43legacy_phy_read(dev, 0x0429) | 0x8000);
  476. b43legacy_set_original_gains(dev);
  477. if (phy->rev >= 6) {
  478. b43legacy_phy_write(dev, 0x0801, backup[16]);
  479. b43legacy_phy_write(dev, 0x0060, backup[17]);
  480. b43legacy_phy_write(dev, 0x0014, backup[18]);
  481. b43legacy_phy_write(dev, 0x0478, backup[19]);
  482. }
  483. b43legacy_phy_write(dev, 0x0001, backup[0]);
  484. b43legacy_phy_write(dev, 0x0812, backup[2]);
  485. b43legacy_phy_write(dev, 0x0811, backup[1]);
  486. }
  487. void b43legacy_calc_nrssi_slope(struct b43legacy_wldev *dev)
  488. {
  489. struct b43legacy_phy *phy = &dev->phy;
  490. u16 backup[18] = { 0 };
  491. u16 tmp;
  492. s16 nrssi0;
  493. s16 nrssi1;
  494. switch (phy->type) {
  495. case B43legacy_PHYTYPE_B:
  496. backup[0] = b43legacy_radio_read16(dev, 0x007A);
  497. backup[1] = b43legacy_radio_read16(dev, 0x0052);
  498. backup[2] = b43legacy_radio_read16(dev, 0x0043);
  499. backup[3] = b43legacy_phy_read(dev, 0x0030);
  500. backup[4] = b43legacy_phy_read(dev, 0x0026);
  501. backup[5] = b43legacy_phy_read(dev, 0x0015);
  502. backup[6] = b43legacy_phy_read(dev, 0x002A);
  503. backup[7] = b43legacy_phy_read(dev, 0x0020);
  504. backup[8] = b43legacy_phy_read(dev, 0x005A);
  505. backup[9] = b43legacy_phy_read(dev, 0x0059);
  506. backup[10] = b43legacy_phy_read(dev, 0x0058);
  507. backup[11] = b43legacy_read16(dev, 0x03E2);
  508. backup[12] = b43legacy_read16(dev, 0x03E6);
  509. backup[13] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT);
  510. tmp = b43legacy_radio_read16(dev, 0x007A);
  511. tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
  512. b43legacy_radio_write16(dev, 0x007A, tmp);
  513. b43legacy_phy_write(dev, 0x0030, 0x00FF);
  514. b43legacy_write16(dev, 0x03EC, 0x7F7F);
  515. b43legacy_phy_write(dev, 0x0026, 0x0000);
  516. b43legacy_phy_write(dev, 0x0015,
  517. b43legacy_phy_read(dev, 0x0015) | 0x0020);
  518. b43legacy_phy_write(dev, 0x002A, 0x08A3);
  519. b43legacy_radio_write16(dev, 0x007A,
  520. b43legacy_radio_read16(dev, 0x007A)
  521. | 0x0080);
  522. nrssi0 = (s16)b43legacy_phy_read(dev, 0x0027);
  523. b43legacy_radio_write16(dev, 0x007A,
  524. b43legacy_radio_read16(dev, 0x007A)
  525. & 0x007F);
  526. if (phy->analog >= 2)
  527. b43legacy_write16(dev, 0x03E6, 0x0040);
  528. else if (phy->analog == 0)
  529. b43legacy_write16(dev, 0x03E6, 0x0122);
  530. else
  531. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
  532. b43legacy_read16(dev,
  533. B43legacy_MMIO_CHANNEL_EXT) & 0x2000);
  534. b43legacy_phy_write(dev, 0x0020, 0x3F3F);
  535. b43legacy_phy_write(dev, 0x0015, 0xF330);
  536. b43legacy_radio_write16(dev, 0x005A, 0x0060);
  537. b43legacy_radio_write16(dev, 0x0043,
  538. b43legacy_radio_read16(dev, 0x0043)
  539. & 0x00F0);
  540. b43legacy_phy_write(dev, 0x005A, 0x0480);
  541. b43legacy_phy_write(dev, 0x0059, 0x0810);
  542. b43legacy_phy_write(dev, 0x0058, 0x000D);
  543. udelay(20);
  544. nrssi1 = (s16)b43legacy_phy_read(dev, 0x0027);
  545. b43legacy_phy_write(dev, 0x0030, backup[3]);
  546. b43legacy_radio_write16(dev, 0x007A, backup[0]);
  547. b43legacy_write16(dev, 0x03E2, backup[11]);
  548. b43legacy_phy_write(dev, 0x0026, backup[4]);
  549. b43legacy_phy_write(dev, 0x0015, backup[5]);
  550. b43legacy_phy_write(dev, 0x002A, backup[6]);
  551. b43legacy_synth_pu_workaround(dev, phy->channel);
  552. if (phy->analog != 0)
  553. b43legacy_write16(dev, 0x03F4, backup[13]);
  554. b43legacy_phy_write(dev, 0x0020, backup[7]);
  555. b43legacy_phy_write(dev, 0x005A, backup[8]);
  556. b43legacy_phy_write(dev, 0x0059, backup[9]);
  557. b43legacy_phy_write(dev, 0x0058, backup[10]);
  558. b43legacy_radio_write16(dev, 0x0052, backup[1]);
  559. b43legacy_radio_write16(dev, 0x0043, backup[2]);
  560. if (nrssi0 == nrssi1)
  561. phy->nrssislope = 0x00010000;
  562. else
  563. phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
  564. if (nrssi0 <= -4) {
  565. phy->nrssi[0] = nrssi0;
  566. phy->nrssi[1] = nrssi1;
  567. }
  568. break;
  569. case B43legacy_PHYTYPE_G:
  570. if (phy->radio_rev >= 9)
  571. return;
  572. if (phy->radio_rev == 8)
  573. b43legacy_calc_nrssi_offset(dev);
  574. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  575. b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
  576. & 0x7FFF);
  577. b43legacy_phy_write(dev, 0x0802,
  578. b43legacy_phy_read(dev, 0x0802) & 0xFFFC);
  579. backup[7] = b43legacy_read16(dev, 0x03E2);
  580. b43legacy_write16(dev, 0x03E2,
  581. b43legacy_read16(dev, 0x03E2) | 0x8000);
  582. backup[0] = b43legacy_radio_read16(dev, 0x007A);
  583. backup[1] = b43legacy_radio_read16(dev, 0x0052);
  584. backup[2] = b43legacy_radio_read16(dev, 0x0043);
  585. backup[3] = b43legacy_phy_read(dev, 0x0015);
  586. backup[4] = b43legacy_phy_read(dev, 0x005A);
  587. backup[5] = b43legacy_phy_read(dev, 0x0059);
  588. backup[6] = b43legacy_phy_read(dev, 0x0058);
  589. backup[8] = b43legacy_read16(dev, 0x03E6);
  590. backup[9] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT);
  591. if (phy->rev >= 3) {
  592. backup[10] = b43legacy_phy_read(dev, 0x002E);
  593. backup[11] = b43legacy_phy_read(dev, 0x002F);
  594. backup[12] = b43legacy_phy_read(dev, 0x080F);
  595. backup[13] = b43legacy_phy_read(dev,
  596. B43legacy_PHY_G_LO_CONTROL);
  597. backup[14] = b43legacy_phy_read(dev, 0x0801);
  598. backup[15] = b43legacy_phy_read(dev, 0x0060);
  599. backup[16] = b43legacy_phy_read(dev, 0x0014);
  600. backup[17] = b43legacy_phy_read(dev, 0x0478);
  601. b43legacy_phy_write(dev, 0x002E, 0);
  602. b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, 0);
  603. switch (phy->rev) {
  604. case 4: case 6: case 7:
  605. b43legacy_phy_write(dev, 0x0478,
  606. b43legacy_phy_read(dev,
  607. 0x0478) | 0x0100);
  608. b43legacy_phy_write(dev, 0x0801,
  609. b43legacy_phy_read(dev,
  610. 0x0801) | 0x0040);
  611. break;
  612. case 3: case 5:
  613. b43legacy_phy_write(dev, 0x0801,
  614. b43legacy_phy_read(dev,
  615. 0x0801) & 0xFFBF);
  616. break;
  617. }
  618. b43legacy_phy_write(dev, 0x0060,
  619. b43legacy_phy_read(dev, 0x0060)
  620. | 0x0040);
  621. b43legacy_phy_write(dev, 0x0014,
  622. b43legacy_phy_read(dev, 0x0014)
  623. | 0x0200);
  624. }
  625. b43legacy_radio_write16(dev, 0x007A,
  626. b43legacy_radio_read16(dev, 0x007A)
  627. | 0x0070);
  628. b43legacy_set_all_gains(dev, 0, 8, 0);
  629. b43legacy_radio_write16(dev, 0x007A,
  630. b43legacy_radio_read16(dev, 0x007A)
  631. & 0x00F7);
  632. if (phy->rev >= 2) {
  633. b43legacy_phy_write(dev, 0x0811,
  634. (b43legacy_phy_read(dev, 0x0811)
  635. & 0xFFCF) | 0x0030);
  636. b43legacy_phy_write(dev, 0x0812,
  637. (b43legacy_phy_read(dev, 0x0812)
  638. & 0xFFCF) | 0x0010);
  639. }
  640. b43legacy_radio_write16(dev, 0x007A,
  641. b43legacy_radio_read16(dev, 0x007A)
  642. | 0x0080);
  643. udelay(20);
  644. nrssi0 = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F);
  645. if (nrssi0 >= 0x0020)
  646. nrssi0 -= 0x0040;
  647. b43legacy_radio_write16(dev, 0x007A,
  648. b43legacy_radio_read16(dev, 0x007A)
  649. & 0x007F);
  650. if (phy->analog >= 2)
  651. b43legacy_phy_write(dev, 0x0003,
  652. (b43legacy_phy_read(dev, 0x0003)
  653. & 0xFF9F) | 0x0040);
  654. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
  655. b43legacy_read16(dev,
  656. B43legacy_MMIO_CHANNEL_EXT) | 0x2000);
  657. b43legacy_radio_write16(dev, 0x007A,
  658. b43legacy_radio_read16(dev, 0x007A)
  659. | 0x000F);
  660. b43legacy_phy_write(dev, 0x0015, 0xF330);
  661. if (phy->rev >= 2) {
  662. b43legacy_phy_write(dev, 0x0812,
  663. (b43legacy_phy_read(dev, 0x0812)
  664. & 0xFFCF) | 0x0020);
  665. b43legacy_phy_write(dev, 0x0811,
  666. (b43legacy_phy_read(dev, 0x0811)
  667. & 0xFFCF) | 0x0020);
  668. }
  669. b43legacy_set_all_gains(dev, 3, 0, 1);
  670. if (phy->radio_rev == 8)
  671. b43legacy_radio_write16(dev, 0x0043, 0x001F);
  672. else {
  673. tmp = b43legacy_radio_read16(dev, 0x0052) & 0xFF0F;
  674. b43legacy_radio_write16(dev, 0x0052, tmp | 0x0060);
  675. tmp = b43legacy_radio_read16(dev, 0x0043) & 0xFFF0;
  676. b43legacy_radio_write16(dev, 0x0043, tmp | 0x0009);
  677. }
  678. b43legacy_phy_write(dev, 0x005A, 0x0480);
  679. b43legacy_phy_write(dev, 0x0059, 0x0810);
  680. b43legacy_phy_write(dev, 0x0058, 0x000D);
  681. udelay(20);
  682. nrssi1 = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F);
  683. if (nrssi1 >= 0x0020)
  684. nrssi1 -= 0x0040;
  685. if (nrssi0 == nrssi1)
  686. phy->nrssislope = 0x00010000;
  687. else
  688. phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
  689. if (nrssi0 >= -4) {
  690. phy->nrssi[0] = nrssi1;
  691. phy->nrssi[1] = nrssi0;
  692. }
  693. if (phy->rev >= 3) {
  694. b43legacy_phy_write(dev, 0x002E, backup[10]);
  695. b43legacy_phy_write(dev, 0x002F, backup[11]);
  696. b43legacy_phy_write(dev, 0x080F, backup[12]);
  697. b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL,
  698. backup[13]);
  699. }
  700. if (phy->rev >= 2) {
  701. b43legacy_phy_write(dev, 0x0812,
  702. b43legacy_phy_read(dev, 0x0812)
  703. & 0xFFCF);
  704. b43legacy_phy_write(dev, 0x0811,
  705. b43legacy_phy_read(dev, 0x0811)
  706. & 0xFFCF);
  707. }
  708. b43legacy_radio_write16(dev, 0x007A, backup[0]);
  709. b43legacy_radio_write16(dev, 0x0052, backup[1]);
  710. b43legacy_radio_write16(dev, 0x0043, backup[2]);
  711. b43legacy_write16(dev, 0x03E2, backup[7]);
  712. b43legacy_write16(dev, 0x03E6, backup[8]);
  713. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[9]);
  714. b43legacy_phy_write(dev, 0x0015, backup[3]);
  715. b43legacy_phy_write(dev, 0x005A, backup[4]);
  716. b43legacy_phy_write(dev, 0x0059, backup[5]);
  717. b43legacy_phy_write(dev, 0x0058, backup[6]);
  718. b43legacy_synth_pu_workaround(dev, phy->channel);
  719. b43legacy_phy_write(dev, 0x0802,
  720. b43legacy_phy_read(dev, 0x0802) | 0x0003);
  721. b43legacy_set_original_gains(dev);
  722. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  723. b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
  724. | 0x8000);
  725. if (phy->rev >= 3) {
  726. b43legacy_phy_write(dev, 0x0801, backup[14]);
  727. b43legacy_phy_write(dev, 0x0060, backup[15]);
  728. b43legacy_phy_write(dev, 0x0014, backup[16]);
  729. b43legacy_phy_write(dev, 0x0478, backup[17]);
  730. }
  731. b43legacy_nrssi_mem_update(dev);
  732. b43legacy_calc_nrssi_threshold(dev);
  733. break;
  734. default:
  735. B43legacy_BUG_ON(1);
  736. }
  737. }
  738. void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
  739. {
  740. struct b43legacy_phy *phy = &dev->phy;
  741. s32 threshold;
  742. s32 a;
  743. s32 b;
  744. s16 tmp16;
  745. u16 tmp_u16;
  746. switch (phy->type) {
  747. case B43legacy_PHYTYPE_B: {
  748. if (phy->radio_ver != 0x2050)
  749. return;
  750. if (!(dev->dev->bus->sprom.r1.boardflags_lo &
  751. B43legacy_BFL_RSSI))
  752. return;
  753. if (phy->radio_rev >= 6) {
  754. threshold = (phy->nrssi[1] - phy->nrssi[0]) * 32;
  755. threshold += 20 * (phy->nrssi[0] + 1);
  756. threshold /= 40;
  757. } else
  758. threshold = phy->nrssi[1] - 5;
  759. threshold = limit_value(threshold, 0, 0x3E);
  760. b43legacy_phy_read(dev, 0x0020); /* dummy read */
  761. b43legacy_phy_write(dev, 0x0020, (((u16)threshold) << 8)
  762. | 0x001C);
  763. if (phy->radio_rev >= 6) {
  764. b43legacy_phy_write(dev, 0x0087, 0x0E0D);
  765. b43legacy_phy_write(dev, 0x0086, 0x0C0B);
  766. b43legacy_phy_write(dev, 0x0085, 0x0A09);
  767. b43legacy_phy_write(dev, 0x0084, 0x0808);
  768. b43legacy_phy_write(dev, 0x0083, 0x0808);
  769. b43legacy_phy_write(dev, 0x0082, 0x0604);
  770. b43legacy_phy_write(dev, 0x0081, 0x0302);
  771. b43legacy_phy_write(dev, 0x0080, 0x0100);
  772. }
  773. break;
  774. }
  775. case B43legacy_PHYTYPE_G:
  776. if (!phy->gmode ||
  777. !(dev->dev->bus->sprom.r1.boardflags_lo &
  778. B43legacy_BFL_RSSI)) {
  779. tmp16 = b43legacy_nrssi_hw_read(dev, 0x20);
  780. if (tmp16 >= 0x20)
  781. tmp16 -= 0x40;
  782. if (tmp16 < 3)
  783. b43legacy_phy_write(dev, 0x048A,
  784. (b43legacy_phy_read(dev,
  785. 0x048A) & 0xF000) | 0x09EB);
  786. else
  787. b43legacy_phy_write(dev, 0x048A,
  788. (b43legacy_phy_read(dev,
  789. 0x048A) & 0xF000) | 0x0AED);
  790. } else {
  791. if (phy->interfmode ==
  792. B43legacy_RADIO_INTERFMODE_NONWLAN) {
  793. a = 0xE;
  794. b = 0xA;
  795. } else if (!phy->aci_wlan_automatic &&
  796. phy->aci_enable) {
  797. a = 0x13;
  798. b = 0x12;
  799. } else {
  800. a = 0xE;
  801. b = 0x11;
  802. }
  803. a = a * (phy->nrssi[1] - phy->nrssi[0]);
  804. a += (phy->nrssi[0] << 6);
  805. if (a < 32)
  806. a += 31;
  807. else
  808. a += 32;
  809. a = a >> 6;
  810. a = limit_value(a, -31, 31);
  811. b = b * (phy->nrssi[1] - phy->nrssi[0]);
  812. b += (phy->nrssi[0] << 6);
  813. if (b < 32)
  814. b += 31;
  815. else
  816. b += 32;
  817. b = b >> 6;
  818. b = limit_value(b, -31, 31);
  819. tmp_u16 = b43legacy_phy_read(dev, 0x048A) & 0xF000;
  820. tmp_u16 |= ((u32)b & 0x0000003F);
  821. tmp_u16 |= (((u32)a & 0x0000003F) << 6);
  822. b43legacy_phy_write(dev, 0x048A, tmp_u16);
  823. }
  824. break;
  825. default:
  826. B43legacy_BUG_ON(1);
  827. }
  828. }
  829. /* Stack implementation to save/restore values from the
  830. * interference mitigation code.
  831. * It is save to restore values in random order.
  832. */
  833. static void _stack_save(u32 *_stackptr, size_t *stackidx,
  834. u8 id, u16 offset, u16 value)
  835. {
  836. u32 *stackptr = &(_stackptr[*stackidx]);
  837. B43legacy_WARN_ON(!((offset & 0xE000) == 0x0000));
  838. B43legacy_WARN_ON(!((id & 0xF8) == 0x00));
  839. *stackptr = offset;
  840. *stackptr |= ((u32)id) << 13;
  841. *stackptr |= ((u32)value) << 16;
  842. (*stackidx)++;
  843. B43legacy_WARN_ON(!(*stackidx < B43legacy_INTERFSTACK_SIZE));
  844. }
  845. static u16 _stack_restore(u32 *stackptr,
  846. u8 id, u16 offset)
  847. {
  848. size_t i;
  849. B43legacy_WARN_ON(!((offset & 0xE000) == 0x0000));
  850. B43legacy_WARN_ON(!((id & 0xF8) == 0x00));
  851. for (i = 0; i < B43legacy_INTERFSTACK_SIZE; i++, stackptr++) {
  852. if ((*stackptr & 0x00001FFF) != offset)
  853. continue;
  854. if (((*stackptr & 0x00007000) >> 13) != id)
  855. continue;
  856. return ((*stackptr & 0xFFFF0000) >> 16);
  857. }
  858. B43legacy_BUG_ON(1);
  859. return 0;
  860. }
  861. #define phy_stacksave(offset) \
  862. do { \
  863. _stack_save(stack, &stackidx, 0x1, (offset), \
  864. b43legacy_phy_read(dev, (offset))); \
  865. } while (0)
  866. #define phy_stackrestore(offset) \
  867. do { \
  868. b43legacy_phy_write(dev, (offset), \
  869. _stack_restore(stack, 0x1, \
  870. (offset))); \
  871. } while (0)
  872. #define radio_stacksave(offset) \
  873. do { \
  874. _stack_save(stack, &stackidx, 0x2, (offset), \
  875. b43legacy_radio_read16(dev, (offset))); \
  876. } while (0)
  877. #define radio_stackrestore(offset) \
  878. do { \
  879. b43legacy_radio_write16(dev, (offset), \
  880. _stack_restore(stack, 0x2, \
  881. (offset))); \
  882. } while (0)
  883. #define ilt_stacksave(offset) \
  884. do { \
  885. _stack_save(stack, &stackidx, 0x3, (offset), \
  886. b43legacy_ilt_read(dev, (offset))); \
  887. } while (0)
  888. #define ilt_stackrestore(offset) \
  889. do { \
  890. b43legacy_ilt_write(dev, (offset), \
  891. _stack_restore(stack, 0x3, \
  892. (offset))); \
  893. } while (0)
  894. static void
  895. b43legacy_radio_interference_mitigation_enable(struct b43legacy_wldev *dev,
  896. int mode)
  897. {
  898. struct b43legacy_phy *phy = &dev->phy;
  899. u16 tmp;
  900. u16 flipped;
  901. u32 tmp32;
  902. size_t stackidx = 0;
  903. u32 *stack = phy->interfstack;
  904. switch (mode) {
  905. case B43legacy_RADIO_INTERFMODE_NONWLAN:
  906. if (phy->rev != 1) {
  907. b43legacy_phy_write(dev, 0x042B,
  908. b43legacy_phy_read(dev, 0x042B)
  909. | 0x0800);
  910. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  911. b43legacy_phy_read(dev,
  912. B43legacy_PHY_G_CRS) & ~0x4000);
  913. break;
  914. }
  915. radio_stacksave(0x0078);
  916. tmp = (b43legacy_radio_read16(dev, 0x0078) & 0x001E);
  917. flipped = flip_4bit(tmp);
  918. if (flipped < 10 && flipped >= 8)
  919. flipped = 7;
  920. else if (flipped >= 10)
  921. flipped -= 3;
  922. flipped = flip_4bit(flipped);
  923. flipped = (flipped << 1) | 0x0020;
  924. b43legacy_radio_write16(dev, 0x0078, flipped);
  925. b43legacy_calc_nrssi_threshold(dev);
  926. phy_stacksave(0x0406);
  927. b43legacy_phy_write(dev, 0x0406, 0x7E28);
  928. b43legacy_phy_write(dev, 0x042B,
  929. b43legacy_phy_read(dev, 0x042B) | 0x0800);
  930. b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
  931. b43legacy_phy_read(dev,
  932. B43legacy_PHY_RADIO_BITFIELD) | 0x1000);
  933. phy_stacksave(0x04A0);
  934. b43legacy_phy_write(dev, 0x04A0,
  935. (b43legacy_phy_read(dev, 0x04A0) & 0xC0C0)
  936. | 0x0008);
  937. phy_stacksave(0x04A1);
  938. b43legacy_phy_write(dev, 0x04A1,
  939. (b43legacy_phy_read(dev, 0x04A1) & 0xC0C0)
  940. | 0x0605);
  941. phy_stacksave(0x04A2);
  942. b43legacy_phy_write(dev, 0x04A2,
  943. (b43legacy_phy_read(dev, 0x04A2) & 0xC0C0)
  944. | 0x0204);
  945. phy_stacksave(0x04A8);
  946. b43legacy_phy_write(dev, 0x04A8,
  947. (b43legacy_phy_read(dev, 0x04A8) & 0xC0C0)
  948. | 0x0803);
  949. phy_stacksave(0x04AB);
  950. b43legacy_phy_write(dev, 0x04AB,
  951. (b43legacy_phy_read(dev, 0x04AB) & 0xC0C0)
  952. | 0x0605);
  953. phy_stacksave(0x04A7);
  954. b43legacy_phy_write(dev, 0x04A7, 0x0002);
  955. phy_stacksave(0x04A3);
  956. b43legacy_phy_write(dev, 0x04A3, 0x287A);
  957. phy_stacksave(0x04A9);
  958. b43legacy_phy_write(dev, 0x04A9, 0x2027);
  959. phy_stacksave(0x0493);
  960. b43legacy_phy_write(dev, 0x0493, 0x32F5);
  961. phy_stacksave(0x04AA);
  962. b43legacy_phy_write(dev, 0x04AA, 0x2027);
  963. phy_stacksave(0x04AC);
  964. b43legacy_phy_write(dev, 0x04AC, 0x32F5);
  965. break;
  966. case B43legacy_RADIO_INTERFMODE_MANUALWLAN:
  967. if (b43legacy_phy_read(dev, 0x0033) & 0x0800)
  968. break;
  969. phy->aci_enable = 1;
  970. phy_stacksave(B43legacy_PHY_RADIO_BITFIELD);
  971. phy_stacksave(B43legacy_PHY_G_CRS);
  972. if (phy->rev < 2)
  973. phy_stacksave(0x0406);
  974. else {
  975. phy_stacksave(0x04C0);
  976. phy_stacksave(0x04C1);
  977. }
  978. phy_stacksave(0x0033);
  979. phy_stacksave(0x04A7);
  980. phy_stacksave(0x04A3);
  981. phy_stacksave(0x04A9);
  982. phy_stacksave(0x04AA);
  983. phy_stacksave(0x04AC);
  984. phy_stacksave(0x0493);
  985. phy_stacksave(0x04A1);
  986. phy_stacksave(0x04A0);
  987. phy_stacksave(0x04A2);
  988. phy_stacksave(0x048A);
  989. phy_stacksave(0x04A8);
  990. phy_stacksave(0x04AB);
  991. if (phy->rev == 2) {
  992. phy_stacksave(0x04AD);
  993. phy_stacksave(0x04AE);
  994. } else if (phy->rev >= 3) {
  995. phy_stacksave(0x04AD);
  996. phy_stacksave(0x0415);
  997. phy_stacksave(0x0416);
  998. phy_stacksave(0x0417);
  999. ilt_stacksave(0x1A00 + 0x2);
  1000. ilt_stacksave(0x1A00 + 0x3);
  1001. }
  1002. phy_stacksave(0x042B);
  1003. phy_stacksave(0x048C);
  1004. b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
  1005. b43legacy_phy_read(dev,
  1006. B43legacy_PHY_RADIO_BITFIELD) & ~0x1000);
  1007. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  1008. (b43legacy_phy_read(dev,
  1009. B43legacy_PHY_G_CRS)
  1010. & 0xFFFC) | 0x0002);
  1011. b43legacy_phy_write(dev, 0x0033, 0x0800);
  1012. b43legacy_phy_write(dev, 0x04A3, 0x2027);
  1013. b43legacy_phy_write(dev, 0x04A9, 0x1CA8);
  1014. b43legacy_phy_write(dev, 0x0493, 0x287A);
  1015. b43legacy_phy_write(dev, 0x04AA, 0x1CA8);
  1016. b43legacy_phy_write(dev, 0x04AC, 0x287A);
  1017. b43legacy_phy_write(dev, 0x04A0,
  1018. (b43legacy_phy_read(dev, 0x04A0)
  1019. & 0xFFC0) | 0x001A);
  1020. b43legacy_phy_write(dev, 0x04A7, 0x000D);
  1021. if (phy->rev < 2)
  1022. b43legacy_phy_write(dev, 0x0406, 0xFF0D);
  1023. else if (phy->rev == 2) {
  1024. b43legacy_phy_write(dev, 0x04C0, 0xFFFF);
  1025. b43legacy_phy_write(dev, 0x04C1, 0x00A9);
  1026. } else {
  1027. b43legacy_phy_write(dev, 0x04C0, 0x00C1);
  1028. b43legacy_phy_write(dev, 0x04C1, 0x0059);
  1029. }
  1030. b43legacy_phy_write(dev, 0x04A1,
  1031. (b43legacy_phy_read(dev, 0x04A1)
  1032. & 0xC0FF) | 0x1800);
  1033. b43legacy_phy_write(dev, 0x04A1,
  1034. (b43legacy_phy_read(dev, 0x04A1)
  1035. & 0xFFC0) | 0x0015);
  1036. b43legacy_phy_write(dev, 0x04A8,
  1037. (b43legacy_phy_read(dev, 0x04A8)
  1038. & 0xCFFF) | 0x1000);
  1039. b43legacy_phy_write(dev, 0x04A8,
  1040. (b43legacy_phy_read(dev, 0x04A8)
  1041. & 0xF0FF) | 0x0A00);
  1042. b43legacy_phy_write(dev, 0x04AB,
  1043. (b43legacy_phy_read(dev, 0x04AB)
  1044. & 0xCFFF) | 0x1000);
  1045. b43legacy_phy_write(dev, 0x04AB,
  1046. (b43legacy_phy_read(dev, 0x04AB)
  1047. & 0xF0FF) | 0x0800);
  1048. b43legacy_phy_write(dev, 0x04AB,
  1049. (b43legacy_phy_read(dev, 0x04AB)
  1050. & 0xFFCF) | 0x0010);
  1051. b43legacy_phy_write(dev, 0x04AB,
  1052. (b43legacy_phy_read(dev, 0x04AB)
  1053. & 0xFFF0) | 0x0005);
  1054. b43legacy_phy_write(dev, 0x04A8,
  1055. (b43legacy_phy_read(dev, 0x04A8)
  1056. & 0xFFCF) | 0x0010);
  1057. b43legacy_phy_write(dev, 0x04A8,
  1058. (b43legacy_phy_read(dev, 0x04A8)
  1059. & 0xFFF0) | 0x0006);
  1060. b43legacy_phy_write(dev, 0x04A2,
  1061. (b43legacy_phy_read(dev, 0x04A2)
  1062. & 0xF0FF) | 0x0800);
  1063. b43legacy_phy_write(dev, 0x04A0,
  1064. (b43legacy_phy_read(dev, 0x04A0)
  1065. & 0xF0FF) | 0x0500);
  1066. b43legacy_phy_write(dev, 0x04A2,
  1067. (b43legacy_phy_read(dev, 0x04A2)
  1068. & 0xFFF0) | 0x000B);
  1069. if (phy->rev >= 3) {
  1070. b43legacy_phy_write(dev, 0x048A,
  1071. b43legacy_phy_read(dev, 0x048A)
  1072. & ~0x8000);
  1073. b43legacy_phy_write(dev, 0x0415,
  1074. (b43legacy_phy_read(dev, 0x0415)
  1075. & 0x8000) | 0x36D8);
  1076. b43legacy_phy_write(dev, 0x0416,
  1077. (b43legacy_phy_read(dev, 0x0416)
  1078. & 0x8000) | 0x36D8);
  1079. b43legacy_phy_write(dev, 0x0417,
  1080. (b43legacy_phy_read(dev, 0x0417)
  1081. & 0xFE00) | 0x016D);
  1082. } else {
  1083. b43legacy_phy_write(dev, 0x048A,
  1084. b43legacy_phy_read(dev, 0x048A)
  1085. | 0x1000);
  1086. b43legacy_phy_write(dev, 0x048A,
  1087. (b43legacy_phy_read(dev, 0x048A)
  1088. & 0x9FFF) | 0x2000);
  1089. tmp32 = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
  1090. B43legacy_UCODEFLAGS_OFFSET);
  1091. if (!(tmp32 & 0x800)) {
  1092. tmp32 |= 0x800;
  1093. b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
  1094. B43legacy_UCODEFLAGS_OFFSET,
  1095. tmp32);
  1096. }
  1097. }
  1098. if (phy->rev >= 2)
  1099. b43legacy_phy_write(dev, 0x042B,
  1100. b43legacy_phy_read(dev, 0x042B)
  1101. | 0x0800);
  1102. b43legacy_phy_write(dev, 0x048C,
  1103. (b43legacy_phy_read(dev, 0x048C)
  1104. & 0xF0FF) | 0x0200);
  1105. if (phy->rev == 2) {
  1106. b43legacy_phy_write(dev, 0x04AE,
  1107. (b43legacy_phy_read(dev, 0x04AE)
  1108. & 0xFF00) | 0x007F);
  1109. b43legacy_phy_write(dev, 0x04AD,
  1110. (b43legacy_phy_read(dev, 0x04AD)
  1111. & 0x00FF) | 0x1300);
  1112. } else if (phy->rev >= 6) {
  1113. b43legacy_ilt_write(dev, 0x1A00 + 0x3, 0x007F);
  1114. b43legacy_ilt_write(dev, 0x1A00 + 0x2, 0x007F);
  1115. b43legacy_phy_write(dev, 0x04AD,
  1116. b43legacy_phy_read(dev, 0x04AD)
  1117. & 0x00FF);
  1118. }
  1119. b43legacy_calc_nrssi_slope(dev);
  1120. break;
  1121. default:
  1122. B43legacy_BUG_ON(1);
  1123. }
  1124. }
  1125. static void
  1126. b43legacy_radio_interference_mitigation_disable(struct b43legacy_wldev *dev,
  1127. int mode)
  1128. {
  1129. struct b43legacy_phy *phy = &dev->phy;
  1130. u32 tmp32;
  1131. u32 *stack = phy->interfstack;
  1132. switch (mode) {
  1133. case B43legacy_RADIO_INTERFMODE_NONWLAN:
  1134. if (phy->rev != 1) {
  1135. b43legacy_phy_write(dev, 0x042B,
  1136. b43legacy_phy_read(dev, 0x042B)
  1137. & ~0x0800);
  1138. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  1139. b43legacy_phy_read(dev,
  1140. B43legacy_PHY_G_CRS) | 0x4000);
  1141. break;
  1142. }
  1143. phy_stackrestore(0x0078);
  1144. b43legacy_calc_nrssi_threshold(dev);
  1145. phy_stackrestore(0x0406);
  1146. b43legacy_phy_write(dev, 0x042B,
  1147. b43legacy_phy_read(dev, 0x042B) & ~0x0800);
  1148. if (!dev->bad_frames_preempt)
  1149. b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
  1150. b43legacy_phy_read(dev,
  1151. B43legacy_PHY_RADIO_BITFIELD)
  1152. & ~(1 << 11));
  1153. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  1154. b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
  1155. | 0x4000);
  1156. phy_stackrestore(0x04A0);
  1157. phy_stackrestore(0x04A1);
  1158. phy_stackrestore(0x04A2);
  1159. phy_stackrestore(0x04A8);
  1160. phy_stackrestore(0x04AB);
  1161. phy_stackrestore(0x04A7);
  1162. phy_stackrestore(0x04A3);
  1163. phy_stackrestore(0x04A9);
  1164. phy_stackrestore(0x0493);
  1165. phy_stackrestore(0x04AA);
  1166. phy_stackrestore(0x04AC);
  1167. break;
  1168. case B43legacy_RADIO_INTERFMODE_MANUALWLAN:
  1169. if (!(b43legacy_phy_read(dev, 0x0033) & 0x0800))
  1170. break;
  1171. phy->aci_enable = 0;
  1172. phy_stackrestore(B43legacy_PHY_RADIO_BITFIELD);
  1173. phy_stackrestore(B43legacy_PHY_G_CRS);
  1174. phy_stackrestore(0x0033);
  1175. phy_stackrestore(0x04A3);
  1176. phy_stackrestore(0x04A9);
  1177. phy_stackrestore(0x0493);
  1178. phy_stackrestore(0x04AA);
  1179. phy_stackrestore(0x04AC);
  1180. phy_stackrestore(0x04A0);
  1181. phy_stackrestore(0x04A7);
  1182. if (phy->rev >= 2) {
  1183. phy_stackrestore(0x04C0);
  1184. phy_stackrestore(0x04C1);
  1185. } else
  1186. phy_stackrestore(0x0406);
  1187. phy_stackrestore(0x04A1);
  1188. phy_stackrestore(0x04AB);
  1189. phy_stackrestore(0x04A8);
  1190. if (phy->rev == 2) {
  1191. phy_stackrestore(0x04AD);
  1192. phy_stackrestore(0x04AE);
  1193. } else if (phy->rev >= 3) {
  1194. phy_stackrestore(0x04AD);
  1195. phy_stackrestore(0x0415);
  1196. phy_stackrestore(0x0416);
  1197. phy_stackrestore(0x0417);
  1198. ilt_stackrestore(0x1A00 + 0x2);
  1199. ilt_stackrestore(0x1A00 + 0x3);
  1200. }
  1201. phy_stackrestore(0x04A2);
  1202. phy_stackrestore(0x04A8);
  1203. phy_stackrestore(0x042B);
  1204. phy_stackrestore(0x048C);
  1205. tmp32 = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
  1206. B43legacy_UCODEFLAGS_OFFSET);
  1207. if (tmp32 & 0x800) {
  1208. tmp32 &= ~0x800;
  1209. b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
  1210. B43legacy_UCODEFLAGS_OFFSET,
  1211. tmp32);
  1212. }
  1213. b43legacy_calc_nrssi_slope(dev);
  1214. break;
  1215. default:
  1216. B43legacy_BUG_ON(1);
  1217. }
  1218. }
  1219. #undef phy_stacksave
  1220. #undef phy_stackrestore
  1221. #undef radio_stacksave
  1222. #undef radio_stackrestore
  1223. #undef ilt_stacksave
  1224. #undef ilt_stackrestore
  1225. int b43legacy_radio_set_interference_mitigation(struct b43legacy_wldev *dev,
  1226. int mode)
  1227. {
  1228. struct b43legacy_phy *phy = &dev->phy;
  1229. int currentmode;
  1230. if ((phy->type != B43legacy_PHYTYPE_G) ||
  1231. (phy->rev == 0) || (!phy->gmode))
  1232. return -ENODEV;
  1233. phy->aci_wlan_automatic = 0;
  1234. switch (mode) {
  1235. case B43legacy_RADIO_INTERFMODE_AUTOWLAN:
  1236. phy->aci_wlan_automatic = 1;
  1237. if (phy->aci_enable)
  1238. mode = B43legacy_RADIO_INTERFMODE_MANUALWLAN;
  1239. else
  1240. mode = B43legacy_RADIO_INTERFMODE_NONE;
  1241. break;
  1242. case B43legacy_RADIO_INTERFMODE_NONE:
  1243. case B43legacy_RADIO_INTERFMODE_NONWLAN:
  1244. case B43legacy_RADIO_INTERFMODE_MANUALWLAN:
  1245. break;
  1246. default:
  1247. return -EINVAL;
  1248. }
  1249. currentmode = phy->interfmode;
  1250. if (currentmode == mode)
  1251. return 0;
  1252. if (currentmode != B43legacy_RADIO_INTERFMODE_NONE)
  1253. b43legacy_radio_interference_mitigation_disable(dev,
  1254. currentmode);
  1255. if (mode == B43legacy_RADIO_INTERFMODE_NONE) {
  1256. phy->aci_enable = 0;
  1257. phy->aci_hw_rssi = 0;
  1258. } else
  1259. b43legacy_radio_interference_mitigation_enable(dev, mode);
  1260. phy->interfmode = mode;
  1261. return 0;
  1262. }
  1263. u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev)
  1264. {
  1265. u16 reg;
  1266. u16 index;
  1267. u16 ret;
  1268. reg = b43legacy_radio_read16(dev, 0x0060);
  1269. index = (reg & 0x001E) >> 1;
  1270. ret = rcc_table[index] << 1;
  1271. ret |= (reg & 0x0001);
  1272. ret |= 0x0020;
  1273. return ret;
  1274. }
  1275. #define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))
  1276. static u16 b43legacy_get_812_value(struct b43legacy_wldev *dev, u8 lpd)
  1277. {
  1278. struct b43legacy_phy *phy = &dev->phy;
  1279. u16 loop_or = 0;
  1280. u16 adj_loopback_gain = phy->loopback_gain[0];
  1281. u8 loop;
  1282. u16 extern_lna_control;
  1283. if (!phy->gmode)
  1284. return 0;
  1285. if (!has_loopback_gain(phy)) {
  1286. if (phy->rev < 7 || !(dev->dev->bus->sprom.r1.boardflags_lo
  1287. & B43legacy_BFL_EXTLNA)) {
  1288. switch (lpd) {
  1289. case LPD(0, 1, 1):
  1290. return 0x0FB2;
  1291. case LPD(0, 0, 1):
  1292. return 0x00B2;
  1293. case LPD(1, 0, 1):
  1294. return 0x30B2;
  1295. case LPD(1, 0, 0):
  1296. return 0x30B3;
  1297. default:
  1298. B43legacy_BUG_ON(1);
  1299. }
  1300. } else {
  1301. switch (lpd) {
  1302. case LPD(0, 1, 1):
  1303. return 0x8FB2;
  1304. case LPD(0, 0, 1):
  1305. return 0x80B2;
  1306. case LPD(1, 0, 1):
  1307. return 0x20B2;
  1308. case LPD(1, 0, 0):
  1309. return 0x20B3;
  1310. default:
  1311. B43legacy_BUG_ON(1);
  1312. }
  1313. }
  1314. } else {
  1315. if (phy->radio_rev == 8)
  1316. adj_loopback_gain += 0x003E;
  1317. else
  1318. adj_loopback_gain += 0x0026;
  1319. if (adj_loopback_gain >= 0x46) {
  1320. adj_loopback_gain -= 0x46;
  1321. extern_lna_control = 0x3000;
  1322. } else if (adj_loopback_gain >= 0x3A) {
  1323. adj_loopback_gain -= 0x3A;
  1324. extern_lna_control = 0x2000;
  1325. } else if (adj_loopback_gain >= 0x2E) {
  1326. adj_loopback_gain -= 0x2E;
  1327. extern_lna_control = 0x1000;
  1328. } else {
  1329. adj_loopback_gain -= 0x10;
  1330. extern_lna_control = 0x0000;
  1331. }
  1332. for (loop = 0; loop < 16; loop++) {
  1333. u16 tmp = adj_loopback_gain - 6 * loop;
  1334. if (tmp < 6)
  1335. break;
  1336. }
  1337. loop_or = (loop << 8) | extern_lna_control;
  1338. if (phy->rev >= 7 && dev->dev->bus->sprom.r1.boardflags_lo
  1339. & B43legacy_BFL_EXTLNA) {
  1340. if (extern_lna_control)
  1341. loop_or |= 0x8000;
  1342. switch (lpd) {
  1343. case LPD(0, 1, 1):
  1344. return 0x8F92;
  1345. case LPD(0, 0, 1):
  1346. return (0x8092 | loop_or);
  1347. case LPD(1, 0, 1):
  1348. return (0x2092 | loop_or);
  1349. case LPD(1, 0, 0):
  1350. return (0x2093 | loop_or);
  1351. default:
  1352. B43legacy_BUG_ON(1);
  1353. }
  1354. } else {
  1355. switch (lpd) {
  1356. case LPD(0, 1, 1):
  1357. return 0x0F92;
  1358. case LPD(0, 0, 1):
  1359. case LPD(1, 0, 1):
  1360. return (0x0092 | loop_or);
  1361. case LPD(1, 0, 0):
  1362. return (0x0093 | loop_or);
  1363. default:
  1364. B43legacy_BUG_ON(1);
  1365. }
  1366. }
  1367. }
  1368. return 0;
  1369. }
  1370. u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev)
  1371. {
  1372. struct b43legacy_phy *phy = &dev->phy;
  1373. u16 backup[21] = { 0 };
  1374. u16 ret;
  1375. u16 i;
  1376. u16 j;
  1377. u32 tmp1 = 0;
  1378. u32 tmp2 = 0;
  1379. backup[0] = b43legacy_radio_read16(dev, 0x0043);
  1380. backup[14] = b43legacy_radio_read16(dev, 0x0051);
  1381. backup[15] = b43legacy_radio_read16(dev, 0x0052);
  1382. backup[1] = b43legacy_phy_read(dev, 0x0015);
  1383. backup[16] = b43legacy_phy_read(dev, 0x005A);
  1384. backup[17] = b43legacy_phy_read(dev, 0x0059);
  1385. backup[18] = b43legacy_phy_read(dev, 0x0058);
  1386. if (phy->type == B43legacy_PHYTYPE_B) {
  1387. backup[2] = b43legacy_phy_read(dev, 0x0030);
  1388. backup[3] = b43legacy_read16(dev, 0x03EC);
  1389. b43legacy_phy_write(dev, 0x0030, 0x00FF);
  1390. b43legacy_write16(dev, 0x03EC, 0x3F3F);
  1391. } else {
  1392. if (phy->gmode) {
  1393. backup[4] = b43legacy_phy_read(dev, 0x0811);
  1394. backup[5] = b43legacy_phy_read(dev, 0x0812);
  1395. backup[6] = b43legacy_phy_read(dev, 0x0814);
  1396. backup[7] = b43legacy_phy_read(dev, 0x0815);
  1397. backup[8] = b43legacy_phy_read(dev,
  1398. B43legacy_PHY_G_CRS);
  1399. backup[9] = b43legacy_phy_read(dev, 0x0802);
  1400. b43legacy_phy_write(dev, 0x0814,
  1401. (b43legacy_phy_read(dev, 0x0814)
  1402. | 0x0003));
  1403. b43legacy_phy_write(dev, 0x0815,
  1404. (b43legacy_phy_read(dev, 0x0815)
  1405. & 0xFFFC));
  1406. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  1407. (b43legacy_phy_read(dev,
  1408. B43legacy_PHY_G_CRS) & 0x7FFF));
  1409. b43legacy_phy_write(dev, 0x0802,
  1410. (b43legacy_phy_read(dev, 0x0802)
  1411. & 0xFFFC));
  1412. if (phy->rev > 1) { /* loopback gain enabled */
  1413. backup[19] = b43legacy_phy_read(dev, 0x080F);
  1414. backup[20] = b43legacy_phy_read(dev, 0x0810);
  1415. if (phy->rev >= 3)
  1416. b43legacy_phy_write(dev, 0x080F,
  1417. 0xC020);
  1418. else
  1419. b43legacy_phy_write(dev, 0x080F,
  1420. 0x8020);
  1421. b43legacy_phy_write(dev, 0x0810, 0x0000);
  1422. }
  1423. b43legacy_phy_write(dev, 0x0812,
  1424. b43legacy_get_812_value(dev,
  1425. LPD(0, 1, 1)));
  1426. if (phy->rev < 7 ||
  1427. !(dev->dev->bus->sprom.r1.boardflags_lo
  1428. & B43legacy_BFL_EXTLNA))
  1429. b43legacy_phy_write(dev, 0x0811, 0x01B3);
  1430. else
  1431. b43legacy_phy_write(dev, 0x0811, 0x09B3);
  1432. }
  1433. }
  1434. b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO,
  1435. (b43legacy_read16(dev, B43legacy_MMIO_PHY_RADIO)
  1436. | 0x8000));
  1437. backup[10] = b43legacy_phy_read(dev, 0x0035);
  1438. b43legacy_phy_write(dev, 0x0035,
  1439. (b43legacy_phy_read(dev, 0x0035) & 0xFF7F));
  1440. backup[11] = b43legacy_read16(dev, 0x03E6);
  1441. backup[12] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT);
  1442. /* Initialization */
  1443. if (phy->analog == 0)
  1444. b43legacy_write16(dev, 0x03E6, 0x0122);
  1445. else {
  1446. if (phy->analog >= 2)
  1447. b43legacy_phy_write(dev, 0x0003,
  1448. (b43legacy_phy_read(dev, 0x0003)
  1449. & 0xFFBF) | 0x0040);
  1450. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
  1451. (b43legacy_read16(dev,
  1452. B43legacy_MMIO_CHANNEL_EXT) | 0x2000));
  1453. }
  1454. ret = b43legacy_radio_calibrationvalue(dev);
  1455. if (phy->type == B43legacy_PHYTYPE_B)
  1456. b43legacy_radio_write16(dev, 0x0078, 0x0026);
  1457. if (phy->gmode)
  1458. b43legacy_phy_write(dev, 0x0812,
  1459. b43legacy_get_812_value(dev,
  1460. LPD(0, 1, 1)));
  1461. b43legacy_phy_write(dev, 0x0015, 0xBFAF);
  1462. b43legacy_phy_write(dev, 0x002B, 0x1403);
  1463. if (phy->gmode)
  1464. b43legacy_phy_write(dev, 0x0812,
  1465. b43legacy_get_812_value(dev,
  1466. LPD(0, 0, 1)));
  1467. b43legacy_phy_write(dev, 0x0015, 0xBFA0);
  1468. b43legacy_radio_write16(dev, 0x0051,
  1469. (b43legacy_radio_read16(dev, 0x0051)
  1470. | 0x0004));
  1471. if (phy->radio_rev == 8)
  1472. b43legacy_radio_write16(dev, 0x0043, 0x001F);
  1473. else {
  1474. b43legacy_radio_write16(dev, 0x0052, 0x0000);
  1475. b43legacy_radio_write16(dev, 0x0043,
  1476. (b43legacy_radio_read16(dev, 0x0043)
  1477. & 0xFFF0) | 0x0009);
  1478. }
  1479. b43legacy_phy_write(dev, 0x0058, 0x0000);
  1480. for (i = 0; i < 16; i++) {
  1481. b43legacy_phy_write(dev, 0x005A, 0x0480);
  1482. b43legacy_phy_write(dev, 0x0059, 0xC810);
  1483. b43legacy_phy_write(dev, 0x0058, 0x000D);
  1484. if (phy->gmode)
  1485. b43legacy_phy_write(dev, 0x0812,
  1486. b43legacy_get_812_value(dev,
  1487. LPD(1, 0, 1)));
  1488. b43legacy_phy_write(dev, 0x0015, 0xAFB0);
  1489. udelay(10);
  1490. if (phy->gmode)
  1491. b43legacy_phy_write(dev, 0x0812,
  1492. b43legacy_get_812_value(dev,
  1493. LPD(1, 0, 1)));
  1494. b43legacy_phy_write(dev, 0x0015, 0xEFB0);
  1495. udelay(10);
  1496. if (phy->gmode)
  1497. b43legacy_phy_write(dev, 0x0812,
  1498. b43legacy_get_812_value(dev,
  1499. LPD(1, 0, 0)));
  1500. b43legacy_phy_write(dev, 0x0015, 0xFFF0);
  1501. udelay(20);
  1502. tmp1 += b43legacy_phy_read(dev, 0x002D);
  1503. b43legacy_phy_write(dev, 0x0058, 0x0000);
  1504. if (phy->gmode)
  1505. b43legacy_phy_write(dev, 0x0812,
  1506. b43legacy_get_812_value(dev,
  1507. LPD(1, 0, 1)));
  1508. b43legacy_phy_write(dev, 0x0015, 0xAFB0);
  1509. }
  1510. tmp1++;
  1511. tmp1 >>= 9;
  1512. udelay(10);
  1513. b43legacy_phy_write(dev, 0x0058, 0x0000);
  1514. for (i = 0; i < 16; i++) {
  1515. b43legacy_radio_write16(dev, 0x0078, (flip_4bit(i) << 1)
  1516. | 0x0020);
  1517. backup[13] = b43legacy_radio_read16(dev, 0x0078);
  1518. udelay(10);
  1519. for (j = 0; j < 16; j++) {
  1520. b43legacy_phy_write(dev, 0x005A, 0x0D80);
  1521. b43legacy_phy_write(dev, 0x0059, 0xC810);
  1522. b43legacy_phy_write(dev, 0x0058, 0x000D);
  1523. if (phy->gmode)
  1524. b43legacy_phy_write(dev, 0x0812,
  1525. b43legacy_get_812_value(dev,
  1526. LPD(1, 0, 1)));
  1527. b43legacy_phy_write(dev, 0x0015, 0xAFB0);
  1528. udelay(10);
  1529. if (phy->gmode)
  1530. b43legacy_phy_write(dev, 0x0812,
  1531. b43legacy_get_812_value(dev,
  1532. LPD(1, 0, 1)));
  1533. b43legacy_phy_write(dev, 0x0015, 0xEFB0);
  1534. udelay(10);
  1535. if (phy->gmode)
  1536. b43legacy_phy_write(dev, 0x0812,
  1537. b43legacy_get_812_value(dev,
  1538. LPD(1, 0, 0)));
  1539. b43legacy_phy_write(dev, 0x0015, 0xFFF0);
  1540. udelay(10);
  1541. tmp2 += b43legacy_phy_read(dev, 0x002D);
  1542. b43legacy_phy_write(dev, 0x0058, 0x0000);
  1543. if (phy->gmode)
  1544. b43legacy_phy_write(dev, 0x0812,
  1545. b43legacy_get_812_value(dev,
  1546. LPD(1, 0, 1)));
  1547. b43legacy_phy_write(dev, 0x0015, 0xAFB0);
  1548. }
  1549. tmp2++;
  1550. tmp2 >>= 8;
  1551. if (tmp1 < tmp2)
  1552. break;
  1553. }
  1554. /* Restore the registers */
  1555. b43legacy_phy_write(dev, 0x0015, backup[1]);
  1556. b43legacy_radio_write16(dev, 0x0051, backup[14]);
  1557. b43legacy_radio_write16(dev, 0x0052, backup[15]);
  1558. b43legacy_radio_write16(dev, 0x0043, backup[0]);
  1559. b43legacy_phy_write(dev, 0x005A, backup[16]);
  1560. b43legacy_phy_write(dev, 0x0059, backup[17]);
  1561. b43legacy_phy_write(dev, 0x0058, backup[18]);
  1562. b43legacy_write16(dev, 0x03E6, backup[11]);
  1563. if (phy->analog != 0)
  1564. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[12]);
  1565. b43legacy_phy_write(dev, 0x0035, backup[10]);
  1566. b43legacy_radio_selectchannel(dev, phy->channel, 1);
  1567. if (phy->type == B43legacy_PHYTYPE_B) {
  1568. b43legacy_phy_write(dev, 0x0030, backup[2]);
  1569. b43legacy_write16(dev, 0x03EC, backup[3]);
  1570. } else {
  1571. if (phy->gmode) {
  1572. b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO,
  1573. (b43legacy_read16(dev,
  1574. B43legacy_MMIO_PHY_RADIO) & 0x7FFF));
  1575. b43legacy_phy_write(dev, 0x0811, backup[4]);
  1576. b43legacy_phy_write(dev, 0x0812, backup[5]);
  1577. b43legacy_phy_write(dev, 0x0814, backup[6]);
  1578. b43legacy_phy_write(dev, 0x0815, backup[7]);
  1579. b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
  1580. backup[8]);
  1581. b43legacy_phy_write(dev, 0x0802, backup[9]);
  1582. if (phy->rev > 1) {
  1583. b43legacy_phy_write(dev, 0x080F, backup[19]);
  1584. b43legacy_phy_write(dev, 0x0810, backup[20]);
  1585. }
  1586. }
  1587. }
  1588. if (i >= 15)
  1589. ret = backup[13];
  1590. return ret;
  1591. }
  1592. static inline
  1593. u16 freq_r3A_value(u16 frequency)
  1594. {
  1595. u16 value;
  1596. if (frequency < 5091)
  1597. value = 0x0040;
  1598. else if (frequency < 5321)
  1599. value = 0x0000;
  1600. else if (frequency < 5806)
  1601. value = 0x0080;
  1602. else
  1603. value = 0x0040;
  1604. return value;
  1605. }
  1606. void b43legacy_radio_set_tx_iq(struct b43legacy_wldev *dev)
  1607. {
  1608. static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
  1609. static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
  1610. u16 tmp = b43legacy_radio_read16(dev, 0x001E);
  1611. int i;
  1612. int j;
  1613. for (i = 0; i < 5; i++) {
  1614. for (j = 0; j < 5; j++) {
  1615. if (tmp == (data_high[i] | data_low[j])) {
  1616. b43legacy_phy_write(dev, 0x0069, (i - j) << 8 |
  1617. 0x00C0);
  1618. return;
  1619. }
  1620. }
  1621. }
  1622. }
  1623. int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev,
  1624. u8 channel,
  1625. int synthetic_pu_workaround)
  1626. {
  1627. struct b43legacy_phy *phy = &dev->phy;
  1628. if (channel == 0xFF) {
  1629. switch (phy->type) {
  1630. case B43legacy_PHYTYPE_B:
  1631. case B43legacy_PHYTYPE_G:
  1632. channel = B43legacy_RADIO_DEFAULT_CHANNEL_BG;
  1633. break;
  1634. default:
  1635. B43legacy_WARN_ON(1);
  1636. }
  1637. }
  1638. /* TODO: Check if channel is valid - return -EINVAL if not */
  1639. if (synthetic_pu_workaround)
  1640. b43legacy_synth_pu_workaround(dev, channel);
  1641. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL,
  1642. channel2freq_bg(channel));
  1643. if (channel == 14) {
  1644. if (dev->dev->bus->sprom.r1.country_code == 5) /* JAPAN) */
  1645. b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
  1646. B43legacy_UCODEFLAGS_OFFSET,
  1647. b43legacy_shm_read32(dev,
  1648. B43legacy_SHM_SHARED,
  1649. B43legacy_UCODEFLAGS_OFFSET)
  1650. & ~(1 << 7));
  1651. else
  1652. b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
  1653. B43legacy_UCODEFLAGS_OFFSET,
  1654. b43legacy_shm_read32(dev,
  1655. B43legacy_SHM_SHARED,
  1656. B43legacy_UCODEFLAGS_OFFSET)
  1657. | (1 << 7));
  1658. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
  1659. b43legacy_read16(dev,
  1660. B43legacy_MMIO_CHANNEL_EXT) | (1 << 11));
  1661. } else
  1662. b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
  1663. b43legacy_read16(dev,
  1664. B43legacy_MMIO_CHANNEL_EXT) & 0xF7BF);
  1665. phy->channel = channel;
  1666. /*XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
  1667. * that 2000 usecs might suffice. */
  1668. msleep(8);
  1669. return 0;
  1670. }
  1671. void b43legacy_radio_set_txantenna(struct b43legacy_wldev *dev, u32 val)
  1672. {
  1673. u16 tmp;
  1674. val <<= 8;
  1675. tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0022) & 0xFCFF;
  1676. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0022, tmp | val);
  1677. tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x03A8) & 0xFCFF;
  1678. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x03A8, tmp | val);
  1679. tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0054) & 0xFCFF;
  1680. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0054, tmp | val);
  1681. }
  1682. /* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
  1683. static u16 b43legacy_get_txgain_base_band(u16 txpower)
  1684. {
  1685. u16 ret;
  1686. B43legacy_WARN_ON(txpower > 63);
  1687. if (txpower >= 54)
  1688. ret = 2;
  1689. else if (txpower >= 49)
  1690. ret = 4;
  1691. else if (txpower >= 44)
  1692. ret = 5;
  1693. else
  1694. ret = 6;
  1695. return ret;
  1696. }
  1697. /* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
  1698. static u16 b43legacy_get_txgain_freq_power_amp(u16 txpower)
  1699. {
  1700. u16 ret;
  1701. B43legacy_WARN_ON(txpower > 63);
  1702. if (txpower >= 32)
  1703. ret = 0;
  1704. else if (txpower >= 25)
  1705. ret = 1;
  1706. else if (txpower >= 20)
  1707. ret = 2;
  1708. else if (txpower >= 12)
  1709. ret = 3;
  1710. else
  1711. ret = 4;
  1712. return ret;
  1713. }
  1714. /* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
  1715. static u16 b43legacy_get_txgain_dac(u16 txpower)
  1716. {
  1717. u16 ret;
  1718. B43legacy_WARN_ON(txpower > 63);
  1719. if (txpower >= 54)
  1720. ret = txpower - 53;
  1721. else if (txpower >= 49)
  1722. ret = txpower - 42;
  1723. else if (txpower >= 44)
  1724. ret = txpower - 37;
  1725. else if (txpower >= 32)
  1726. ret = txpower - 32;
  1727. else if (txpower >= 25)
  1728. ret = txpower - 20;
  1729. else if (txpower >= 20)
  1730. ret = txpower - 13;
  1731. else if (txpower >= 12)
  1732. ret = txpower - 8;
  1733. else
  1734. ret = txpower;
  1735. return ret;
  1736. }
  1737. void b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower)
  1738. {
  1739. struct b43legacy_phy *phy = &dev->phy;
  1740. u16 pamp;
  1741. u16 base;
  1742. u16 dac;
  1743. u16 ilt;
  1744. txpower = limit_value(txpower, 0, 63);
  1745. pamp = b43legacy_get_txgain_freq_power_amp(txpower);
  1746. pamp <<= 5;
  1747. pamp &= 0x00E0;
  1748. b43legacy_phy_write(dev, 0x0019, pamp);
  1749. base = b43legacy_get_txgain_base_band(txpower);
  1750. base &= 0x000F;
  1751. b43legacy_phy_write(dev, 0x0017, base | 0x0020);
  1752. ilt = b43legacy_ilt_read(dev, 0x3001);
  1753. ilt &= 0x0007;
  1754. dac = b43legacy_get_txgain_dac(txpower);
  1755. dac <<= 3;
  1756. dac |= ilt;
  1757. b43legacy_ilt_write(dev, 0x3001, dac);
  1758. phy->txpwr_offset = txpower;
  1759. /* TODO: FuncPlaceholder (Adjust BB loft cancel) */
  1760. }
  1761. void b43legacy_radio_set_txpower_bg(struct b43legacy_wldev *dev,
  1762. u16 baseband_attenuation,
  1763. u16 radio_attenuation,
  1764. u16 txpower)
  1765. {
  1766. struct b43legacy_phy *phy = &dev->phy;
  1767. if (baseband_attenuation == 0xFFFF)
  1768. baseband_attenuation = phy->bbatt;
  1769. if (radio_attenuation == 0xFFFF)
  1770. radio_attenuation = phy->rfatt;
  1771. if (txpower == 0xFFFF)
  1772. txpower = phy->txctl1;
  1773. phy->bbatt = baseband_attenuation;
  1774. phy->rfatt = radio_attenuation;
  1775. phy->txctl1 = txpower;
  1776. B43legacy_WARN_ON(baseband_attenuation > 11);
  1777. if (phy->radio_rev < 6)
  1778. B43legacy_WARN_ON(radio_attenuation > 9);
  1779. else
  1780. B43legacy_WARN_ON(radio_attenuation > 31);
  1781. B43legacy_WARN_ON(txpower > 7);
  1782. b43legacy_phy_set_baseband_attenuation(dev, baseband_attenuation);
  1783. b43legacy_radio_write16(dev, 0x0043, radio_attenuation);
  1784. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0064,
  1785. radio_attenuation);
  1786. if (phy->radio_ver == 0x2050)
  1787. b43legacy_radio_write16(dev, 0x0052,
  1788. (b43legacy_radio_read16(dev, 0x0052)
  1789. & ~0x0070) | ((txpower << 4) & 0x0070));
  1790. /* FIXME: The spec is very weird and unclear here. */
  1791. if (phy->type == B43legacy_PHYTYPE_G)
  1792. b43legacy_phy_lo_adjust(dev, 0);
  1793. }
  1794. u16 b43legacy_default_baseband_attenuation(struct b43legacy_wldev *dev)
  1795. {
  1796. struct b43legacy_phy *phy = &dev->phy;
  1797. if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)
  1798. return 0;
  1799. return 2;
  1800. }
  1801. u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
  1802. {
  1803. struct b43legacy_phy *phy = &dev->phy;
  1804. u16 att = 0xFFFF;
  1805. switch (phy->radio_ver) {
  1806. case 0x2053:
  1807. switch (phy->radio_rev) {
  1808. case 1:
  1809. att = 6;
  1810. break;
  1811. }
  1812. break;
  1813. case 0x2050:
  1814. switch (phy->radio_rev) {
  1815. case 0:
  1816. att = 5;
  1817. break;
  1818. case 1:
  1819. if (phy->type == B43legacy_PHYTYPE_G) {
  1820. if (is_bcm_board_vendor(dev) &&
  1821. dev->dev->bus->boardinfo.type == 0x421 &&
  1822. dev->dev->bus->boardinfo.rev >= 30)
  1823. att = 3;
  1824. else if (is_bcm_board_vendor(dev) &&
  1825. dev->dev->bus->boardinfo.type == 0x416)
  1826. att = 3;
  1827. else
  1828. att = 1;
  1829. } else {
  1830. if (is_bcm_board_vendor(dev) &&
  1831. dev->dev->bus->boardinfo.type == 0x421 &&
  1832. dev->dev->bus->boardinfo.rev >= 30)
  1833. att = 7;
  1834. else
  1835. att = 6;
  1836. }
  1837. break;
  1838. case 2:
  1839. if (phy->type == B43legacy_PHYTYPE_G) {
  1840. if (is_bcm_board_vendor(dev) &&
  1841. dev->dev->bus->boardinfo.type == 0x421 &&
  1842. dev->dev->bus->boardinfo.rev >= 30)
  1843. att = 3;
  1844. else if (is_bcm_board_vendor(dev) &&
  1845. dev->dev->bus->boardinfo.type ==
  1846. 0x416)
  1847. att = 5;
  1848. else if (dev->dev->bus->chip_id == 0x4320)
  1849. att = 4;
  1850. else
  1851. att = 3;
  1852. } else
  1853. att = 6;
  1854. break;
  1855. case 3:
  1856. att = 5;
  1857. break;
  1858. case 4:
  1859. case 5:
  1860. att = 1;
  1861. break;
  1862. case 6:
  1863. case 7:
  1864. att = 5;
  1865. break;
  1866. case 8:
  1867. att = 0x1A;
  1868. break;
  1869. case 9:
  1870. default:
  1871. att = 5;
  1872. }
  1873. }
  1874. if (is_bcm_board_vendor(dev) &&
  1875. dev->dev->bus->boardinfo.type == 0x421) {
  1876. if (dev->dev->bus->boardinfo.rev < 0x43)
  1877. att = 2;
  1878. else if (dev->dev->bus->boardinfo.rev < 0x51)
  1879. att = 3;
  1880. }
  1881. if (att == 0xFFFF)
  1882. att = 5;
  1883. return att;
  1884. }
  1885. u16 b43legacy_default_txctl1(struct b43legacy_wldev *dev)
  1886. {
  1887. struct b43legacy_phy *phy = &dev->phy;
  1888. if (phy->radio_ver != 0x2050)
  1889. return 0;
  1890. if (phy->radio_rev == 1)
  1891. return 3;
  1892. if (phy->radio_rev < 6)
  1893. return 2;
  1894. if (phy->radio_rev == 8)
  1895. return 1;
  1896. return 0;
  1897. }
  1898. void b43legacy_radio_turn_on(struct b43legacy_wldev *dev)
  1899. {
  1900. struct b43legacy_phy *phy = &dev->phy;
  1901. int err;
  1902. u8 channel;
  1903. might_sleep();
  1904. if (phy->radio_on)
  1905. return;
  1906. switch (phy->type) {
  1907. case B43legacy_PHYTYPE_B:
  1908. case B43legacy_PHYTYPE_G:
  1909. b43legacy_phy_write(dev, 0x0015, 0x8000);
  1910. b43legacy_phy_write(dev, 0x0015, 0xCC00);
  1911. b43legacy_phy_write(dev, 0x0015,
  1912. (phy->gmode ? 0x00C0 : 0x0000));
  1913. if (phy->radio_off_context.valid) {
  1914. /* Restore the RFover values. */
  1915. b43legacy_phy_write(dev, B43legacy_PHY_RFOVER,
  1916. phy->radio_off_context.rfover);
  1917. b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
  1918. phy->radio_off_context.rfoverval);
  1919. phy->radio_off_context.valid = 0;
  1920. }
  1921. channel = phy->channel;
  1922. err = b43legacy_radio_selectchannel(dev,
  1923. B43legacy_RADIO_DEFAULT_CHANNEL_BG, 1);
  1924. err |= b43legacy_radio_selectchannel(dev, channel, 0);
  1925. B43legacy_WARN_ON(err);
  1926. break;
  1927. default:
  1928. B43legacy_BUG_ON(1);
  1929. }
  1930. phy->radio_on = 1;
  1931. b43legacy_leds_update(dev, 0);
  1932. }
  1933. void b43legacy_radio_turn_off(struct b43legacy_wldev *dev)
  1934. {
  1935. struct b43legacy_phy *phy = &dev->phy;
  1936. if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) {
  1937. u16 rfover, rfoverval;
  1938. rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER);
  1939. rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL);
  1940. phy->radio_off_context.rfover = rfover;
  1941. phy->radio_off_context.rfoverval = rfoverval;
  1942. phy->radio_off_context.valid = 1;
  1943. b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C);
  1944. b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
  1945. rfoverval & 0xFF73);
  1946. } else
  1947. b43legacy_phy_write(dev, 0x0015, 0xAA00);
  1948. phy->radio_on = 0;
  1949. b43legacydbg(dev->wl, "Radio initialized\n");
  1950. b43legacy_leds_update(dev, 0);
  1951. }
  1952. void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev)
  1953. {
  1954. struct b43legacy_phy *phy = &dev->phy;
  1955. switch (phy->type) {
  1956. case B43legacy_PHYTYPE_B:
  1957. case B43legacy_PHYTYPE_G:
  1958. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0058,
  1959. 0x7F7F);
  1960. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x005a,
  1961. 0x7F7F);
  1962. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0070,
  1963. 0x7F7F);
  1964. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0072,
  1965. 0x7F7F);
  1966. break;
  1967. }
  1968. }