radio.c 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156
  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. }
  1932. void b43legacy_radio_turn_off(struct b43legacy_wldev *dev)
  1933. {
  1934. struct b43legacy_phy *phy = &dev->phy;
  1935. if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) {
  1936. u16 rfover, rfoverval;
  1937. rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER);
  1938. rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL);
  1939. phy->radio_off_context.rfover = rfover;
  1940. phy->radio_off_context.rfoverval = rfoverval;
  1941. phy->radio_off_context.valid = 1;
  1942. b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C);
  1943. b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
  1944. rfoverval & 0xFF73);
  1945. } else
  1946. b43legacy_phy_write(dev, 0x0015, 0xAA00);
  1947. phy->radio_on = 0;
  1948. b43legacydbg(dev->wl, "Radio initialized\n");
  1949. }
  1950. void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev)
  1951. {
  1952. struct b43legacy_phy *phy = &dev->phy;
  1953. switch (phy->type) {
  1954. case B43legacy_PHYTYPE_B:
  1955. case B43legacy_PHYTYPE_G:
  1956. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0058,
  1957. 0x7F7F);
  1958. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x005a,
  1959. 0x7F7F);
  1960. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0070,
  1961. 0x7F7F);
  1962. b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0072,
  1963. 0x7F7F);
  1964. break;
  1965. }
  1966. }