rtw_eeprom.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. *
  19. ******************************************************************************/
  20. #define _RTW_EEPROM_C_
  21. #include <drv_conf.h>
  22. #include <osdep_service.h>
  23. #include <drv_types.h>
  24. void up_clk(_adapter* padapter, u16 *x)
  25. {
  26. _func_enter_;
  27. *x = *x | _EESK;
  28. rtw_write8(padapter, EE_9346CR, (u8)*x);
  29. rtw_udelay_os(CLOCK_RATE);
  30. _func_exit_;
  31. }
  32. void down_clk(_adapter * padapter, u16 *x )
  33. {
  34. _func_enter_;
  35. *x = *x & ~_EESK;
  36. rtw_write8(padapter, EE_9346CR, (u8)*x);
  37. rtw_udelay_os(CLOCK_RATE);
  38. _func_exit_;
  39. }
  40. void shift_out_bits(_adapter * padapter, u16 data, u16 count)
  41. {
  42. u16 x,mask;
  43. _func_enter_;
  44. if(padapter->bSurpriseRemoved==_TRUE){
  45. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  46. goto out;
  47. }
  48. mask = 0x01 << (count - 1);
  49. x = rtw_read8(padapter, EE_9346CR);
  50. x &= ~(_EEDO | _EEDI);
  51. do
  52. {
  53. x &= ~_EEDI;
  54. if(data & mask)
  55. x |= _EEDI;
  56. if(padapter->bSurpriseRemoved==_TRUE){
  57. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  58. goto out;
  59. }
  60. rtw_write8(padapter, EE_9346CR, (u8)x);
  61. rtw_udelay_os(CLOCK_RATE);
  62. up_clk(padapter, &x);
  63. down_clk(padapter, &x);
  64. mask = mask >> 1;
  65. } while(mask);
  66. if(padapter->bSurpriseRemoved==_TRUE){
  67. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  68. goto out;
  69. }
  70. x &= ~_EEDI;
  71. rtw_write8(padapter, EE_9346CR, (u8)x);
  72. out:
  73. _func_exit_;
  74. }
  75. u16 shift_in_bits (_adapter * padapter)
  76. {
  77. u16 x,d=0,i;
  78. _func_enter_;
  79. if(padapter->bSurpriseRemoved==_TRUE){
  80. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  81. goto out;
  82. }
  83. x = rtw_read8(padapter, EE_9346CR);
  84. x &= ~( _EEDO | _EEDI);
  85. d = 0;
  86. for(i=0; i<16; i++)
  87. {
  88. d = d << 1;
  89. up_clk(padapter, &x);
  90. if(padapter->bSurpriseRemoved==_TRUE){
  91. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  92. goto out;
  93. }
  94. x = rtw_read8(padapter, EE_9346CR);
  95. x &= ~(_EEDI);
  96. if(x & _EEDO)
  97. d |= 1;
  98. down_clk(padapter, &x);
  99. }
  100. out:
  101. _func_exit_;
  102. return d;
  103. }
  104. void standby(_adapter * padapter )
  105. {
  106. u8 x;
  107. _func_enter_;
  108. x = rtw_read8(padapter, EE_9346CR);
  109. x &= ~(_EECS | _EESK);
  110. rtw_write8(padapter, EE_9346CR,x);
  111. rtw_udelay_os(CLOCK_RATE);
  112. x |= _EECS;
  113. rtw_write8(padapter, EE_9346CR, x);
  114. rtw_udelay_os(CLOCK_RATE);
  115. _func_exit_;
  116. }
  117. u16 wait_eeprom_cmd_done(_adapter* padapter)
  118. {
  119. u8 x;
  120. u16 i,res=_FALSE;
  121. _func_enter_;
  122. standby(padapter );
  123. for (i=0; i<200; i++)
  124. {
  125. x = rtw_read8(padapter, EE_9346CR);
  126. if (x & _EEDO){
  127. res=_TRUE;
  128. goto exit;
  129. }
  130. rtw_udelay_os(CLOCK_RATE);
  131. }
  132. exit:
  133. _func_exit_;
  134. return res;
  135. }
  136. void eeprom_clean(_adapter * padapter)
  137. {
  138. u16 x;
  139. _func_enter_;
  140. if(padapter->bSurpriseRemoved==_TRUE){
  141. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  142. goto out;
  143. }
  144. x = rtw_read8(padapter, EE_9346CR);
  145. if(padapter->bSurpriseRemoved==_TRUE){
  146. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  147. goto out;
  148. }
  149. x &= ~(_EECS | _EEDI);
  150. rtw_write8(padapter, EE_9346CR, (u8)x);
  151. if(padapter->bSurpriseRemoved==_TRUE){
  152. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  153. goto out;
  154. }
  155. up_clk(padapter, &x);
  156. if(padapter->bSurpriseRemoved==_TRUE){
  157. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  158. goto out;
  159. }
  160. down_clk(padapter, &x);
  161. out:
  162. _func_exit_;
  163. }
  164. void eeprom_write16(_adapter * padapter, u16 reg, u16 data)
  165. {
  166. u8 x;
  167. #ifdef CONFIG_RTL8712
  168. u8 tmp8_ori,tmp8_new,tmp8_clk_ori,tmp8_clk_new;
  169. tmp8_ori=rtw_read8(padapter, 0x102502f1);
  170. tmp8_new=tmp8_ori & 0xf7;
  171. if(tmp8_ori != tmp8_new){
  172. rtw_write8(padapter, 0x102502f1, tmp8_new);
  173. RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x102502f1=====\n"));
  174. }
  175. tmp8_clk_ori=rtw_read8(padapter,0x10250003);
  176. tmp8_clk_new=tmp8_clk_ori|0x20;
  177. if(tmp8_clk_new!=tmp8_clk_ori){
  178. RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x10250003=====\n"));
  179. rtw_write8(padapter, 0x10250003, tmp8_clk_new);
  180. }
  181. #endif
  182. _func_enter_;
  183. x = rtw_read8(padapter, EE_9346CR);
  184. x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
  185. x |= _EEM1 | _EECS;
  186. rtw_write8(padapter, EE_9346CR, x);
  187. shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
  188. if(padapter->EepromAddressSize==8) //CF+ and SDIO
  189. shift_out_bits(padapter, 0, 6);
  190. else //USB
  191. shift_out_bits(padapter, 0, 4);
  192. standby( padapter);
  193. // Commented out by rcnjko, 2004.0
  194. // // Erase this particular word. Write the erase opcode and register
  195. // // number in that order. The opcode is 3bits in length; reg is 6 bits long.
  196. // shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3);
  197. // shift_out_bits(Adapter, reg, Adapter->EepromAddressSize);
  198. //
  199. // if (wait_eeprom_cmd_done(Adapter ) == FALSE)
  200. // {
  201. // return;
  202. // }
  203. standby(padapter );
  204. // write the new word to the EEPROM
  205. // send the write opcode the EEPORM
  206. shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
  207. // select which word in the EEPROM that we are writing to.
  208. shift_out_bits(padapter, reg, padapter->EepromAddressSize);
  209. // write the data to the selected EEPROM word.
  210. shift_out_bits(padapter, data, 16);
  211. if (wait_eeprom_cmd_done(padapter ) == _FALSE)
  212. {
  213. goto exit;
  214. }
  215. standby(padapter );
  216. shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
  217. shift_out_bits(padapter, reg, 4);
  218. eeprom_clean(padapter );
  219. exit:
  220. #ifdef CONFIG_RTL8712
  221. if(tmp8_clk_new!=tmp8_clk_ori)
  222. rtw_write8(padapter, 0x10250003, tmp8_clk_ori);
  223. if(tmp8_new!=tmp8_ori)
  224. rtw_write8(padapter, 0x102502f1, tmp8_ori);
  225. #endif
  226. _func_exit_;
  227. return;
  228. }
  229. u16 eeprom_read16(_adapter * padapter, u16 reg) //ReadEEprom
  230. {
  231. u16 x;
  232. u16 data=0;
  233. #ifdef CONFIG_RTL8712
  234. u8 tmp8_ori,tmp8_new,tmp8_clk_ori,tmp8_clk_new;
  235. tmp8_ori= rtw_read8(padapter, 0x102502f1);
  236. tmp8_new = tmp8_ori & 0xf7;
  237. if(tmp8_ori != tmp8_new){
  238. rtw_write8(padapter, 0x102502f1, tmp8_new);
  239. RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x102502f1=====\n"));
  240. }
  241. tmp8_clk_ori=rtw_read8(padapter,0x10250003);
  242. tmp8_clk_new=tmp8_clk_ori|0x20;
  243. if(tmp8_clk_new!=tmp8_clk_ori){
  244. RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x10250003=====\n"));
  245. rtw_write8(padapter, 0x10250003, tmp8_clk_new);
  246. }
  247. #endif
  248. _func_enter_;
  249. if(padapter->bSurpriseRemoved==_TRUE){
  250. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  251. goto out;
  252. }
  253. // select EEPROM, reset bits, set _EECS
  254. x = rtw_read8(padapter, EE_9346CR);
  255. if(padapter->bSurpriseRemoved==_TRUE){
  256. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  257. goto out;
  258. }
  259. x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
  260. x |= _EEM1 | _EECS;
  261. rtw_write8(padapter, EE_9346CR, (unsigned char)x);
  262. // write the read opcode and register number in that order
  263. // The opcode is 3bits in length, reg is 6 bits long
  264. shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
  265. shift_out_bits(padapter, reg, padapter->EepromAddressSize);
  266. // Now read the data (16 bits) in from the selected EEPROM word
  267. data = shift_in_bits(padapter);
  268. eeprom_clean(padapter);
  269. out:
  270. #ifdef CONFIG_RTL8712
  271. if(tmp8_clk_new!=tmp8_clk_ori)
  272. rtw_write8(padapter, 0x10250003, tmp8_clk_ori);
  273. if(tmp8_new!=tmp8_ori)
  274. rtw_write8(padapter, 0x102502f1, tmp8_ori);
  275. #endif
  276. _func_exit_;
  277. return data;
  278. }
  279. //From even offset
  280. void eeprom_read_sz(_adapter * padapter, u16 reg, u8* data, u32 sz)
  281. {
  282. u16 x, data16;
  283. u32 i;
  284. _func_enter_;
  285. if(padapter->bSurpriseRemoved==_TRUE){
  286. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  287. goto out;
  288. }
  289. // select EEPROM, reset bits, set _EECS
  290. x = rtw_read8(padapter, EE_9346CR);
  291. if(padapter->bSurpriseRemoved==_TRUE){
  292. RT_TRACE(_module_rtl871x_eeprom_c_,_drv_err_,("padapter->bSurpriseRemoved==_TRUE"));
  293. goto out;
  294. }
  295. x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
  296. x |= _EEM1 | _EECS;
  297. rtw_write8(padapter, EE_9346CR, (unsigned char)x);
  298. // write the read opcode and register number in that order
  299. // The opcode is 3bits in length, reg is 6 bits long
  300. shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
  301. shift_out_bits(padapter, reg, padapter->EepromAddressSize);
  302. for(i=0; i<sz; i+=2)
  303. {
  304. data16 = shift_in_bits(padapter);
  305. data[i] = data16 & 0xff;
  306. data[i+1] = data16 >>8;
  307. }
  308. eeprom_clean(padapter);
  309. out:
  310. _func_exit_;
  311. }
  312. //addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg)
  313. u8 eeprom_read(_adapter * padapter, u32 addr_off, u8 sz, u8* rbuf)
  314. {
  315. u8 quotient, remainder, addr_2align_odd;
  316. u16 reg, stmp , i=0, idx = 0;
  317. _func_enter_;
  318. reg = (u16)(addr_off >> 1);
  319. addr_2align_odd = (u8)(addr_off & 0x1);
  320. if(addr_2align_odd) //read that start at high part: e.g 1,3,5,7,9,...
  321. {
  322. stmp = eeprom_read16(padapter, reg);
  323. rbuf[idx++] = (u8) ((stmp>>8)&0xff); //return hogh-part of the short
  324. reg++; sz--;
  325. }
  326. quotient = sz >> 1;
  327. remainder = sz & 0x1;
  328. for( i=0 ; i < quotient; i++)
  329. {
  330. stmp = eeprom_read16(padapter, reg+i);
  331. rbuf[idx++] = (u8) (stmp&0xff);
  332. rbuf[idx++] = (u8) ((stmp>>8)&0xff);
  333. }
  334. reg = reg+i;
  335. if(remainder){ //end of read at lower part of short : 0,2,4,6,...
  336. stmp = eeprom_read16(padapter, reg);
  337. rbuf[idx] = (u8)(stmp & 0xff);
  338. }
  339. _func_exit_;
  340. return _TRUE;
  341. }
  342. VOID read_eeprom_content(_adapter * padapter)
  343. {
  344. _func_enter_;
  345. _func_exit_;
  346. }