admmod.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484
  1. /******************************************************************************
  2. Copyright (c) 2004, Infineon Technologies. All rights reserved.
  3. No Warranty
  4. Because the program is licensed free of charge, there is no warranty for
  5. the program, to the extent permitted by applicable law. Except when
  6. otherwise stated in writing the copyright holders and/or other parties
  7. provide the program "as is" without warranty of any kind, either
  8. expressed or implied, including, but not limited to, the implied
  9. warranties of merchantability and fitness for a particular purpose. The
  10. entire risk as to the quality and performance of the program is with
  11. you. should the program prove defective, you assume the cost of all
  12. necessary servicing, repair or correction.
  13. In no event unless required by applicable law or agreed to in writing
  14. will any copyright holder, or any other party who may modify and/or
  15. redistribute the program as permitted above, be liable to you for
  16. damages, including any general, special, incidental or consequential
  17. damages arising out of the use or inability to use the program
  18. (including but not limited to loss of data or data being rendered
  19. inaccurate or losses sustained by you or third parties or a failure of
  20. the program to operate with any other programs), even if such holder or
  21. other party has been advised of the possibility of such damages.
  22. ******************************************************************************
  23. Module : admmod.c
  24. Date : 2004-09-01
  25. Description : JoeLin
  26. Remarks:
  27. Revision:
  28. MarsLin, add to support VLAN
  29. *****************************************************************************/
  30. //000001.joelin 2005/06/02 add"ADM6996_MDC_MDIO_MODE" define,
  31. // if define ADM6996_MDC_MDIO_MODE==> ADM6996LC and ADM6996I will be in MDIO/MDC(SMI)(16 bit) mode,
  32. // amazon should contrl ADM6996 by MDC/MDIO pin
  33. // if undef ADM6996_MDC_MDIO_MODE==> ADM6996 will be in EEProm(32 bit) mode,
  34. // amazon should contrl ADM6996 by GPIO15,16,17,18 pin
  35. /* 507281:linmars 2005/07/28 support MDIO/EEPROM config mode */
  36. /* 509201:linmars remove driver testing codes */
  37. #include <linux/module.h>
  38. #include <linux/string.h>
  39. #include <linux/proc_fs.h>
  40. #include <linux/delay.h>
  41. #include <asm/uaccess.h>
  42. #include <linux/init.h>
  43. #include <linux/ioctl.h>
  44. #include <asm/atomic.h>
  45. #include <asm-mips/amazon/amazon.h>
  46. #include <asm-mips/amazon/adm6996.h>
  47. //#include <linux/amazon/adm6996.h>
  48. unsigned int ifx_sw_conf[ADM_SW_MAX_PORT_NUM+1] = \
  49. {ADM_SW_PORT0_CONF, ADM_SW_PORT1_CONF, ADM_SW_PORT2_CONF, \
  50. ADM_SW_PORT3_CONF, ADM_SW_PORT4_CONF, ADM_SW_PORT5_CONF};
  51. unsigned int ifx_sw_bits[8] = \
  52. {0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
  53. unsigned int ifx_sw_vlan_port[6] = {0, 2, 4, 6, 7, 8};
  54. //050613:fchang
  55. /* 507281:linmars start */
  56. #ifdef CONFIG_SWITCH_ADM6996_MDIO
  57. #define ADM6996_MDC_MDIO_MODE 1 //000001.joelin
  58. #else
  59. #undef ADM6996_MDC_MDIO_MODE
  60. #endif
  61. /* 507281:linmars end */
  62. #define adm6996i 0
  63. #define adm6996lc 1
  64. #define adm6996l 2
  65. unsigned int adm6996_mode=adm6996i;
  66. /*
  67. initialize GPIO pins.
  68. output mode, low
  69. */
  70. void ifx_gpio_init(void)
  71. {
  72. //GPIO16,17,18 direction:output
  73. //GPIO16,17,18 output 0
  74. AMAZON_SW_REG(AMAZON_GPIO_P1_DIR) |= (GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
  75. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT) =AMAZON_SW_REG(AMAZON_GPIO_P1_IN)& ~(GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
  76. }
  77. /* read one bit from mdio port */
  78. int ifx_sw_mdio_readbit(void)
  79. {
  80. //int val;
  81. //val = (AMAZON_SW_REG(GPIO_conf0_REG) & GPIO0_INPUT_MASK) >> 8;
  82. //return val;
  83. //GPIO16
  84. return AMAZON_SW_REG(AMAZON_GPIO_P1_IN)&1;
  85. }
  86. /*
  87. MDIO mode selection
  88. 1 -> output
  89. 0 -> input
  90. switch input/output mode of GPIO 0
  91. */
  92. void ifx_mdio_mode(int mode)
  93. {
  94. // AMAZON_SW_REG(GPIO_conf0_REG) = mode ? GPIO_ENABLEBITS :
  95. // ((GPIO_ENABLEBITS | MDIO_INPUT) & ~MDIO_OUTPUT_EN);
  96. mode?(AMAZON_SW_REG(AMAZON_GPIO_P1_DIR)|=GPIO_MDIO):
  97. (AMAZON_SW_REG(AMAZON_GPIO_P1_DIR)&=~GPIO_MDIO);
  98. /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_DIR);
  99. mode?(r|=GPIO_MDIO):(r&=~GPIO_MDIO);
  100. AMAZON_SW_REG(AMAZON_GPIO_P1_DIR)=r;*/
  101. }
  102. void ifx_mdc_hi(void)
  103. {
  104. //GPIO_SET_HI(GPIO_MDC);
  105. //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDC;
  106. /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
  107. r|=GPIO_MDC;
  108. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
  109. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)|GPIO_MDC;
  110. }
  111. void ifx_mdio_hi(void)
  112. {
  113. //GPIO_SET_HI(GPIO_MDIO);
  114. //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDIO;
  115. /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
  116. r|=GPIO_MDIO;
  117. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
  118. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)|GPIO_MDIO;
  119. }
  120. void ifx_mdcs_hi(void)
  121. {
  122. //GPIO_SET_HI(GPIO_MDCS);
  123. //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)|=GPIO_MDCS;
  124. /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
  125. r|=GPIO_MDCS;
  126. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
  127. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)|GPIO_MDCS;
  128. }
  129. void ifx_mdc_lo(void)
  130. {
  131. //GPIO_SET_LOW(GPIO_MDC);
  132. //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDC;
  133. /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
  134. r&=~GPIO_MDC;
  135. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
  136. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)&(~GPIO_MDC);
  137. }
  138. void ifx_mdio_lo(void)
  139. {
  140. //GPIO_SET_LOW(GPIO_MDIO);
  141. //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDIO;
  142. /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
  143. r&=~GPIO_MDIO;
  144. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
  145. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)&(~GPIO_MDIO);
  146. }
  147. void ifx_mdcs_lo(void)
  148. {
  149. //GPIO_SET_LOW(GPIO_MDCS);
  150. //AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)&=~GPIO_MDCS;
  151. /*int r=AMAZON_SW_REG(AMAZON_GPIO_P1_OUT);
  152. r&=~GPIO_MDCS;
  153. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=r;*/
  154. AMAZON_SW_REG(AMAZON_GPIO_P1_OUT)=AMAZON_SW_REG(AMAZON_GPIO_P1_IN)&(~GPIO_MDCS);
  155. }
  156. /*
  157. mdc pulse
  158. 0 -> 1 -> 0
  159. */
  160. static void ifx_sw_mdc_pulse(void)
  161. {
  162. ifx_mdc_lo();
  163. udelay(ADM_SW_MDC_DOWN_DELAY);
  164. ifx_mdc_hi();
  165. udelay(ADM_SW_MDC_UP_DELAY);
  166. ifx_mdc_lo();
  167. }
  168. /*
  169. mdc toggle
  170. 1 -> 0
  171. */
  172. static void ifx_sw_mdc_toggle(void)
  173. {
  174. ifx_mdc_hi();
  175. udelay(ADM_SW_MDC_UP_DELAY);
  176. ifx_mdc_lo();
  177. udelay(ADM_SW_MDC_DOWN_DELAY);
  178. }
  179. /*
  180. enable eeprom write
  181. For ATC 93C66 type EEPROM; accessing ADM6996 internal EEPROM type registers
  182. */
  183. static void ifx_sw_eeprom_write_enable(void)
  184. {
  185. unsigned int op;
  186. ifx_mdcs_lo();
  187. ifx_mdc_lo();
  188. ifx_mdio_hi();
  189. udelay(ADM_SW_CS_DELAY);
  190. /* enable chip select */
  191. ifx_mdcs_hi();
  192. udelay(ADM_SW_CS_DELAY);
  193. /* start bit */
  194. ifx_mdio_hi();
  195. ifx_sw_mdc_pulse();
  196. /* eeprom write enable */
  197. op = ADM_SW_BIT_MASK_4;
  198. while (op)
  199. {
  200. if (op & ADM_SW_EEPROM_WRITE_ENABLE)
  201. ifx_mdio_hi();
  202. else
  203. ifx_mdio_lo();
  204. ifx_sw_mdc_pulse();
  205. op >>= 1;
  206. }
  207. op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 3);
  208. while (op)
  209. {
  210. ifx_mdio_lo();
  211. ifx_sw_mdc_pulse();
  212. op >>= 1;
  213. }
  214. /* disable chip select */
  215. ifx_mdcs_lo();
  216. udelay(ADM_SW_CS_DELAY);
  217. ifx_sw_mdc_pulse();
  218. }
  219. /*
  220. disable eeprom write
  221. */
  222. static void ifx_sw_eeprom_write_disable(void)
  223. {
  224. unsigned int op;
  225. ifx_mdcs_lo();
  226. ifx_mdc_lo();
  227. ifx_mdio_hi();
  228. udelay(ADM_SW_CS_DELAY);
  229. /* enable chip select */
  230. ifx_mdcs_hi();
  231. udelay(ADM_SW_CS_DELAY);
  232. /* start bit */
  233. ifx_mdio_hi();
  234. ifx_sw_mdc_pulse();
  235. /* eeprom write disable */
  236. op = ADM_SW_BIT_MASK_4;
  237. while (op)
  238. {
  239. if (op & ADM_SW_EEPROM_WRITE_DISABLE)
  240. ifx_mdio_hi();
  241. else
  242. ifx_mdio_lo();
  243. ifx_sw_mdc_pulse();
  244. op >>= 1;
  245. }
  246. op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 3);
  247. while (op)
  248. {
  249. ifx_mdio_lo();
  250. ifx_sw_mdc_pulse();
  251. op >>= 1;
  252. }
  253. /* disable chip select */
  254. ifx_mdcs_lo();
  255. udelay(ADM_SW_CS_DELAY);
  256. ifx_sw_mdc_pulse();
  257. }
  258. /*
  259. read registers from ADM6996
  260. serial registers start at 0x200 (addr bit 9 = 1b)
  261. EEPROM registers -> 16bits; Serial registers -> 32bits
  262. */
  263. #ifdef ADM6996_MDC_MDIO_MODE //smi mode//000001.joelin
  264. static int ifx_sw_read_adm6996i_smi(unsigned int addr, unsigned int *dat)
  265. {
  266. addr=(addr<<16)&0x3ff0000;
  267. AMAZON_SW_REG(AMAZON_SW_MDIO_ACC) =(0xC0000000|addr);
  268. while ((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC))&0x80000000){};
  269. *dat=((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC))&0x0FFFF);
  270. return 0;
  271. }
  272. #endif
  273. static int ifx_sw_read_adm6996i(unsigned int addr, unsigned int *dat)
  274. {
  275. unsigned int op;
  276. ifx_gpio_init();
  277. ifx_mdcs_hi();
  278. udelay(ADM_SW_CS_DELAY);
  279. ifx_mdcs_lo();
  280. ifx_mdc_lo();
  281. ifx_mdio_lo();
  282. udelay(ADM_SW_CS_DELAY);
  283. /* preamble, 32 bit 1 */
  284. ifx_mdio_hi();
  285. op = ADM_SW_BIT_MASK_32;
  286. while (op)
  287. {
  288. ifx_sw_mdc_pulse();
  289. op >>= 1;
  290. }
  291. /* command start (01b) */
  292. op = ADM_SW_BIT_MASK_2;
  293. while (op)
  294. {
  295. if (op & ADM_SW_SMI_START)
  296. ifx_mdio_hi();
  297. else
  298. ifx_mdio_lo();
  299. ifx_sw_mdc_pulse();
  300. op >>= 1;
  301. }
  302. /* read command (10b) */
  303. op = ADM_SW_BIT_MASK_2;
  304. while (op)
  305. {
  306. if (op & ADM_SW_SMI_READ)
  307. ifx_mdio_hi();
  308. else
  309. ifx_mdio_lo();
  310. ifx_sw_mdc_pulse();
  311. op >>= 1;
  312. }
  313. /* send address A9 ~ A0 */
  314. op = ADM_SW_BIT_MASK_10;
  315. while (op)
  316. {
  317. if (op & addr)
  318. ifx_mdio_hi();
  319. else
  320. ifx_mdio_lo();
  321. ifx_sw_mdc_pulse();
  322. op >>= 1;
  323. }
  324. /* turnaround bits */
  325. op = ADM_SW_BIT_MASK_2;
  326. ifx_mdio_hi();
  327. while (op)
  328. {
  329. ifx_sw_mdc_pulse();
  330. op >>= 1;
  331. }
  332. udelay(ADM_SW_MDC_DOWN_DELAY);
  333. /* set MDIO pin to input mode */
  334. ifx_mdio_mode(ADM_SW_MDIO_INPUT);
  335. /* start read data */
  336. *dat = 0;
  337. //adm6996i op = ADM_SW_BIT_MASK_32;
  338. op = ADM_SW_BIT_MASK_16;//adm6996i
  339. while (op)
  340. {
  341. *dat <<= 1;
  342. if (ifx_sw_mdio_readbit()) *dat |= 1;
  343. ifx_sw_mdc_toggle();
  344. op >>= 1;
  345. }
  346. /* set MDIO to output mode */
  347. ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
  348. /* dummy clock */
  349. op = ADM_SW_BIT_MASK_4;
  350. ifx_mdio_lo();
  351. while(op)
  352. {
  353. ifx_sw_mdc_pulse();
  354. op >>= 1;
  355. }
  356. ifx_mdc_lo();
  357. ifx_mdio_lo();
  358. ifx_mdcs_hi();
  359. /* EEPROM registers */
  360. //adm6996i if (!(addr & 0x200))
  361. //adm6996i {
  362. //adm6996i if (addr % 2)
  363. //adm6996i *dat >>= 16;
  364. //adm6996i else
  365. //adm6996i *dat &= 0xffff;
  366. //adm6996i }
  367. return 0;
  368. }
  369. //adm6996
  370. static int ifx_sw_read_adm6996l(unsigned int addr, unsigned int *dat)
  371. {
  372. unsigned int op;
  373. ifx_gpio_init();
  374. ifx_mdcs_hi();
  375. udelay(ADM_SW_CS_DELAY);
  376. ifx_mdcs_lo();
  377. ifx_mdc_lo();
  378. ifx_mdio_lo();
  379. udelay(ADM_SW_CS_DELAY);
  380. /* preamble, 32 bit 1 */
  381. ifx_mdio_hi();
  382. op = ADM_SW_BIT_MASK_32;
  383. while (op)
  384. {
  385. ifx_sw_mdc_pulse();
  386. op >>= 1;
  387. }
  388. /* command start (01b) */
  389. op = ADM_SW_BIT_MASK_2;
  390. while (op)
  391. {
  392. if (op & ADM_SW_SMI_START)
  393. ifx_mdio_hi();
  394. else
  395. ifx_mdio_lo();
  396. ifx_sw_mdc_pulse();
  397. op >>= 1;
  398. }
  399. /* read command (10b) */
  400. op = ADM_SW_BIT_MASK_2;
  401. while (op)
  402. {
  403. if (op & ADM_SW_SMI_READ)
  404. ifx_mdio_hi();
  405. else
  406. ifx_mdio_lo();
  407. ifx_sw_mdc_pulse();
  408. op >>= 1;
  409. }
  410. /* send address A9 ~ A0 */
  411. op = ADM_SW_BIT_MASK_10;
  412. while (op)
  413. {
  414. if (op & addr)
  415. ifx_mdio_hi();
  416. else
  417. ifx_mdio_lo();
  418. ifx_sw_mdc_pulse();
  419. op >>= 1;
  420. }
  421. /* turnaround bits */
  422. op = ADM_SW_BIT_MASK_2;
  423. ifx_mdio_hi();
  424. while (op)
  425. {
  426. ifx_sw_mdc_pulse();
  427. op >>= 1;
  428. }
  429. udelay(ADM_SW_MDC_DOWN_DELAY);
  430. /* set MDIO pin to input mode */
  431. ifx_mdio_mode(ADM_SW_MDIO_INPUT);
  432. /* start read data */
  433. *dat = 0;
  434. op = ADM_SW_BIT_MASK_32;
  435. while (op)
  436. {
  437. *dat <<= 1;
  438. if (ifx_sw_mdio_readbit()) *dat |= 1;
  439. ifx_sw_mdc_toggle();
  440. op >>= 1;
  441. }
  442. /* set MDIO to output mode */
  443. ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
  444. /* dummy clock */
  445. op = ADM_SW_BIT_MASK_4;
  446. ifx_mdio_lo();
  447. while(op)
  448. {
  449. ifx_sw_mdc_pulse();
  450. op >>= 1;
  451. }
  452. ifx_mdc_lo();
  453. ifx_mdio_lo();
  454. ifx_mdcs_hi();
  455. /* EEPROM registers */
  456. if (!(addr & 0x200))
  457. {
  458. if (addr % 2)
  459. *dat >>= 16;
  460. else
  461. *dat &= 0xffff;
  462. }
  463. return 0;
  464. }
  465. static int ifx_sw_read(unsigned int addr, unsigned int *dat)
  466. {
  467. #ifdef ADM6996_MDC_MDIO_MODE //smi mode ////000001.joelin
  468. ifx_sw_read_adm6996i_smi(addr,dat);
  469. #else
  470. if (adm6996_mode==adm6996i) ifx_sw_read_adm6996i(addr,dat);
  471. else ifx_sw_read_adm6996l(addr,dat);
  472. #endif
  473. return 0;
  474. }
  475. /*
  476. write register to ADM6996 eeprom registers
  477. */
  478. //for adm6996i -start
  479. #ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
  480. static int ifx_sw_write_adm6996i_smi(unsigned int addr, unsigned int dat)
  481. {
  482. AMAZON_SW_REG(AMAZON_SW_MDIO_ACC) = ((addr<<16)&0x3ff0000)|dat|0x80000000;
  483. while ((AMAZON_SW_REG(AMAZON_SW_MDIO_ACC))&0x80000000){};
  484. return 0;
  485. }
  486. #endif //ADM6996_MDC_MDIO_MODE //000001.joelin
  487. static int ifx_sw_write_adm6996i(unsigned int addr, unsigned int dat)
  488. {
  489. unsigned int op;
  490. ifx_gpio_init();
  491. ifx_mdcs_hi();
  492. udelay(ADM_SW_CS_DELAY);
  493. ifx_mdcs_lo();
  494. ifx_mdc_lo();
  495. ifx_mdio_lo();
  496. udelay(ADM_SW_CS_DELAY);
  497. /* preamble, 32 bit 1 */
  498. ifx_mdio_hi();
  499. op = ADM_SW_BIT_MASK_32;
  500. while (op)
  501. {
  502. ifx_sw_mdc_pulse();
  503. op >>= 1;
  504. }
  505. /* command start (01b) */
  506. op = ADM_SW_BIT_MASK_2;
  507. while (op)
  508. {
  509. if (op & ADM_SW_SMI_START)
  510. ifx_mdio_hi();
  511. else
  512. ifx_mdio_lo();
  513. ifx_sw_mdc_pulse();
  514. op >>= 1;
  515. }
  516. /* write command (01b) */
  517. op = ADM_SW_BIT_MASK_2;
  518. while (op)
  519. {
  520. if (op & ADM_SW_SMI_WRITE)
  521. ifx_mdio_hi();
  522. else
  523. ifx_mdio_lo();
  524. ifx_sw_mdc_pulse();
  525. op >>= 1;
  526. }
  527. /* send address A9 ~ A0 */
  528. op = ADM_SW_BIT_MASK_10;
  529. while (op)
  530. {
  531. if (op & addr)
  532. ifx_mdio_hi();
  533. else
  534. ifx_mdio_lo();
  535. ifx_sw_mdc_pulse();
  536. op >>= 1;
  537. }
  538. /* turnaround bits */
  539. op = ADM_SW_BIT_MASK_2;
  540. ifx_mdio_hi();
  541. while (op)
  542. {
  543. ifx_sw_mdc_pulse();
  544. op >>= 1;
  545. }
  546. udelay(ADM_SW_MDC_DOWN_DELAY);
  547. /* set MDIO pin to output mode */
  548. ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
  549. /* start write data */
  550. op = ADM_SW_BIT_MASK_16;
  551. while (op)
  552. {
  553. if (op & dat)
  554. ifx_mdio_hi();
  555. else
  556. ifx_mdio_lo();
  557. ifx_sw_mdc_toggle();
  558. op >>= 1;
  559. }
  560. // /* set MDIO to output mode */
  561. // ifx_mdio_mode(ADM_SW_MDIO_OUTPUT);
  562. /* dummy clock */
  563. op = ADM_SW_BIT_MASK_4;
  564. ifx_mdio_lo();
  565. while(op)
  566. {
  567. ifx_sw_mdc_pulse();
  568. op >>= 1;
  569. }
  570. ifx_mdc_lo();
  571. ifx_mdio_lo();
  572. ifx_mdcs_hi();
  573. /* EEPROM registers */
  574. //adm6996i if (!(addr & 0x200))
  575. //adm6996i {
  576. //adm6996i if (addr % 2)
  577. //adm6996i *dat >>= 16;
  578. //adm6996i else
  579. //adm6996i *dat &= 0xffff;
  580. //adm6996i }
  581. return 0;
  582. }
  583. //for adm6996i-end
  584. static int ifx_sw_write_adm6996l(unsigned int addr, unsigned int dat)
  585. {
  586. unsigned int op;
  587. ifx_gpio_init();
  588. /* enable write */
  589. ifx_sw_eeprom_write_enable();
  590. /* chip select */
  591. ifx_mdcs_hi();
  592. udelay(ADM_SW_CS_DELAY);
  593. /* issue write command */
  594. /* start bit */
  595. ifx_mdio_hi();
  596. ifx_sw_mdc_pulse();
  597. /* EEPROM write command */
  598. op = ADM_SW_BIT_MASK_2;
  599. while (op)
  600. {
  601. if (op & ADM_SW_EEPROM_WRITE)
  602. ifx_mdio_hi();
  603. else
  604. ifx_mdio_lo();
  605. ifx_sw_mdc_pulse();
  606. op >>= 1;
  607. }
  608. /* send address A7 ~ A0 */
  609. op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 1);
  610. while (op)
  611. {
  612. if (op & addr)
  613. ifx_mdio_hi();
  614. else
  615. ifx_mdio_lo();
  616. ifx_sw_mdc_toggle();
  617. op >>= 1;
  618. }
  619. /* start write data */
  620. op = ADM_SW_BIT_MASK_16;
  621. while (op)
  622. {
  623. if (op & dat)
  624. ifx_mdio_hi();
  625. else
  626. ifx_mdio_lo();
  627. ifx_sw_mdc_toggle();
  628. op >>= 1;
  629. }
  630. /* disable cs & wait 1 clock */
  631. ifx_mdcs_lo();
  632. udelay(ADM_SW_CS_DELAY);
  633. ifx_sw_mdc_toggle();
  634. ifx_sw_eeprom_write_disable();
  635. return 0;
  636. }
  637. static int ifx_sw_write(unsigned int addr, unsigned int dat)
  638. {
  639. #ifdef ADM6996_MDC_MDIO_MODE //smi mode ////000001.joelin
  640. ifx_sw_write_adm6996i_smi(addr,dat);
  641. #else //000001.joelin
  642. if (adm6996_mode==adm6996i) ifx_sw_write_adm6996i(addr,dat);
  643. else ifx_sw_write_adm6996l(addr,dat);
  644. #endif //000001.joelin
  645. return 0;
  646. }
  647. /*
  648. do switch PHY reset
  649. */
  650. int ifx_sw_reset(void)
  651. {
  652. /* reset PHY */
  653. ifx_sw_write(ADM_SW_PHY_RESET, 0);
  654. return 0;
  655. }
  656. /* 509201:linmars start */
  657. #if 0
  658. /*
  659. check port status
  660. */
  661. int ifx_check_port_status(int port)
  662. {
  663. unsigned int val;
  664. if ((port < 0) || (port > ADM_SW_MAX_PORT_NUM))
  665. {
  666. ifx_printf(("error on port number (%d)!!\n", port));
  667. return -1;
  668. }
  669. ifx_sw_read(ifx_sw_conf[port], &val);
  670. if (ifx_sw_conf[port]%2) val >>= 16;
  671. /* only 16bits are effective */
  672. val &= 0xFFFF;
  673. ifx_printf(("Port %d status (%.8x): \n", port, val));
  674. if (val & ADM_SW_PORT_FLOWCTL)
  675. ifx_printf(("\t802.3x flow control supported!\n"));
  676. else
  677. ifx_printf(("\t802.3x flow control not supported!\n"));
  678. if (val & ADM_SW_PORT_AN)
  679. ifx_printf(("\tAuto negotiation ON!\n"));
  680. else
  681. ifx_printf(("\tAuto negotiation OFF!\n"));
  682. if (val & ADM_SW_PORT_100M)
  683. ifx_printf(("\tLink at 100M!\n"));
  684. else
  685. ifx_printf(("\tLink at 10M!\n"));
  686. if (val & ADM_SW_PORT_FULL)
  687. ifx_printf(("\tFull duplex!\n"));
  688. else
  689. ifx_printf(("\tHalf duplex!\n"));
  690. if (val & ADM_SW_PORT_DISABLE)
  691. ifx_printf(("\tPort disabled!\n"));
  692. else
  693. ifx_printf(("\tPort enabled!\n"));
  694. if (val & ADM_SW_PORT_TOS)
  695. ifx_printf(("\tTOS enabled!\n"));
  696. else
  697. ifx_printf(("\tTOS disabled!\n"));
  698. if (val & ADM_SW_PORT_PPRI)
  699. ifx_printf(("\tPort priority first!\n"));
  700. else
  701. ifx_printf(("\tVLAN or TOS priority first!\n"));
  702. if (val & ADM_SW_PORT_MDIX)
  703. ifx_printf(("\tAuto MDIX!\n"));
  704. else
  705. ifx_printf(("\tNo auto MDIX\n"));
  706. ifx_printf(("\tPVID: %d\n", \
  707. ((val >> ADM_SW_PORT_PVID_SHIFT)&ifx_sw_bits[ADM_SW_PORT_PVID_BITS])));
  708. return 0;
  709. }
  710. /*
  711. initialize a VLAN
  712. clear all VLAN bits
  713. */
  714. int ifx_sw_vlan_init(int vlanid)
  715. {
  716. ifx_sw_write(ADM_SW_VLAN0_CONF + vlanid, 0);
  717. return 0;
  718. }
  719. /*
  720. add a port to certain vlan
  721. */
  722. int ifx_sw_vlan_add(int port, int vlanid)
  723. {
  724. int reg = 0;
  725. if ((port < 0) || (port > ADM_SW_MAX_PORT_NUM) || (vlanid < 0) ||
  726. (vlanid > ADM_SW_MAX_VLAN_NUM))
  727. {
  728. ifx_printf(("Port number or VLAN number ERROR!!\n"));
  729. return -1;
  730. }
  731. ifx_sw_read(ADM_SW_VLAN0_CONF + vlanid, &reg);
  732. reg |= (1 << ifx_sw_vlan_port[port]);
  733. ifx_sw_write(ADM_SW_VLAN0_CONF + vlanid, reg);
  734. return 0;
  735. }
  736. /*
  737. delete a given port from certain vlan
  738. */
  739. int ifx_sw_vlan_del(int port, int vlanid)
  740. {
  741. unsigned int reg = 0;
  742. if ((port < 0) || (port > ADM_SW_MAX_PORT_NUM) || (vlanid < 0) || (vlanid > ADM_SW_MAX_VLAN_NUM))
  743. {
  744. ifx_printf(("Port number or VLAN number ERROR!!\n"));
  745. return -1;
  746. }
  747. ifx_sw_read(ADM_SW_VLAN0_CONF + vlanid, &reg);
  748. reg &= ~(1 << ifx_sw_vlan_port[port]);
  749. ifx_sw_write(ADM_SW_VLAN0_CONF + vlanid, reg);
  750. return 0;
  751. }
  752. /*
  753. default VLAN setting
  754. port 0~3 as untag port and PVID = 1
  755. VLAN1: port 0~3 and port 5 (MII)
  756. */
  757. static int ifx_sw_init(void)
  758. {
  759. ifx_printf(("Setting default ADM6996 registers... \n"));
  760. /* MAC clone, 802.1q based VLAN */
  761. ifx_sw_write(ADM_SW_VLAN_MODE, 0xff30);
  762. /* auto MDIX, PVID=1, untag */
  763. ifx_sw_write(ADM_SW_PORT0_CONF, 0x840f);
  764. ifx_sw_write(ADM_SW_PORT1_CONF, 0x840f);
  765. ifx_sw_write(ADM_SW_PORT2_CONF, 0x840f);
  766. ifx_sw_write(ADM_SW_PORT3_CONF, 0x840f);
  767. /* auto MDIX, PVID=2, untag */
  768. ifx_sw_write(ADM_SW_PORT5_CONF, 0x880f);
  769. /* port 0~3 & 5 as VLAN1 */
  770. ifx_sw_write(ADM_SW_VLAN0_CONF+1, 0x0155);
  771. return 0;
  772. }
  773. #endif
  774. /* 509201:linmars end */
  775. int adm_open(struct inode *node, struct file *filp)
  776. {
  777. return 0;
  778. }
  779. ssize_t adm_read(struct file *filep, char *buf, size_t count, loff_t *ppos)
  780. {
  781. return count;
  782. }
  783. ssize_t adm_write(struct file *filep, const char *buf, size_t count, loff_t *ppos)
  784. {
  785. return count;
  786. }
  787. /* close */
  788. int adm_release(struct inode *inode, struct file *filp)
  789. {
  790. return 0;
  791. }
  792. /* IOCTL function */
  793. int adm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long args)
  794. {
  795. PREGRW uREGRW;
  796. unsigned int rtval;
  797. unsigned int val; //6996i
  798. unsigned int control[6] ; //6996i
  799. unsigned int status[6] ; //6996i
  800. PMACENTRY mMACENTRY;//adm6996i
  801. PPROTOCOLFILTER uPROTOCOLFILTER ;///adm6996i
  802. if (_IOC_TYPE(cmd) != ADM_MAGIC)
  803. {
  804. printk("adm_ioctl: IOC_TYPE(%x) != ADM_MAGIC(%x)! \n", _IOC_TYPE(cmd), ADM_MAGIC);
  805. return (-EINVAL);
  806. }
  807. if(_IOC_NR(cmd) >= KEY_IOCTL_MAX_KEY)
  808. {
  809. printk(KERN_WARNING "adm_ioctl: IOC_NR(%x) invalid! \n", _IOC_NR(cmd));
  810. return (-EINVAL);
  811. }
  812. switch (cmd)
  813. {
  814. case ADM_IOCTL_REGRW:
  815. {
  816. uREGRW = (PREGRW)kmalloc(sizeof(REGRW), GFP_KERNEL);
  817. rtval = copy_from_user(uREGRW, (PREGRW)args, sizeof(REGRW));
  818. if (rtval != 0)
  819. {
  820. printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
  821. return (-EFAULT);
  822. }
  823. switch(uREGRW->mode)
  824. {
  825. case REG_READ:
  826. uREGRW->value = 0x12345678;//inl(uREGRW->addr);
  827. copy_to_user((PREGRW)args, uREGRW, sizeof(REGRW));
  828. break;
  829. case REG_WRITE:
  830. //outl(uREGRW->value, uREGRW->addr);
  831. break;
  832. default:
  833. printk("No such Register Read/Write function!! \n");
  834. return (-EFAULT);
  835. }
  836. kfree(uREGRW);
  837. break;
  838. }
  839. case ADM_SW_IOCTL_REGRW:
  840. {
  841. unsigned int val = 0xff;
  842. uREGRW = (PREGRW)kmalloc(sizeof(REGRW), GFP_KERNEL);
  843. rtval = copy_from_user(uREGRW, (PREGRW)args, sizeof(REGRW));
  844. if (rtval != 0)
  845. {
  846. printk("ADM_IOCTL_REGRW: copy from user FAILED!! \n");
  847. return (-EFAULT);
  848. }
  849. switch(uREGRW->mode)
  850. {
  851. case REG_READ:
  852. ifx_sw_read(uREGRW->addr, &val);
  853. uREGRW->value = val;
  854. copy_to_user((PREGRW)args, uREGRW, sizeof(REGRW));
  855. break;
  856. case REG_WRITE:
  857. ifx_sw_write(uREGRW->addr, uREGRW->value);
  858. break;
  859. default:
  860. printk("No such Register Read/Write function!! \n");
  861. return (-EFAULT);
  862. }
  863. kfree(uREGRW);
  864. break;
  865. }
  866. /* 509201:linmars start */
  867. #if 0
  868. case ADM_SW_IOCTL_PORTSTS:
  869. for (rtval = 0; rtval < ADM_SW_MAX_PORT_NUM+1; rtval++)
  870. ifx_check_port_status(rtval);
  871. break;
  872. case ADM_SW_IOCTL_INIT:
  873. ifx_sw_init();
  874. break;
  875. #endif
  876. /* 509201:linmars end */
  877. //adm6996i
  878. case ADM_SW_IOCTL_MACENTRY_ADD:
  879. case ADM_SW_IOCTL_MACENTRY_DEL:
  880. case ADM_SW_IOCTL_MACENTRY_GET_INIT:
  881. case ADM_SW_IOCTL_MACENTRY_GET_MORE:
  882. mMACENTRY = (PMACENTRY)kmalloc(sizeof(MACENTRY), GFP_KERNEL);
  883. rtval = copy_from_user(mMACENTRY, (PMACENTRY)args, sizeof(MACENTRY));
  884. if (rtval != 0)
  885. {
  886. printk("ADM_SW_IOCTL_MACENTRY: copy from user FAILED!! \n");
  887. return (-EFAULT);
  888. }
  889. control[0]=(mMACENTRY->mac_addr[1]<<8)+mMACENTRY->mac_addr[0] ;
  890. control[1]=(mMACENTRY->mac_addr[3]<<8)+mMACENTRY->mac_addr[2] ;
  891. control[2]=(mMACENTRY->mac_addr[5]<<8)+mMACENTRY->mac_addr[4] ;
  892. control[3]=(mMACENTRY->fid&0xf)+((mMACENTRY->portmap&0x3f)<<4);
  893. if (((mMACENTRY->info_type)&0x01)) control[4]=(mMACENTRY->ctrl.info_ctrl)+0x1000; //static ,info control
  894. else control[4]=((mMACENTRY->ctrl.age_timer)&0xff);//not static ,agetimer
  895. if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT) {
  896. //initial the pointer to the first address
  897. val=0x8000;//busy ,status5[15]
  898. while(val&0x8000){ //check busy ?
  899. ifx_sw_read(0x125, &val);
  900. }
  901. control[5]=0x030;//initial the first address
  902. ifx_sw_write(0x11f,control[5]);
  903. val=0x8000;//busy ,status5[15]
  904. while(val&0x8000){ //check busy ?
  905. ifx_sw_read(0x125, &val);
  906. }
  907. } //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)
  908. if (cmd==ADM_SW_IOCTL_MACENTRY_ADD) control[5]=0x07;//create a new address
  909. else if (cmd==ADM_SW_IOCTL_MACENTRY_DEL) control[5]=0x01f;//erased an existed address
  910. else if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
  911. control[5]=0x02c;//search by the mac address field
  912. val=0x8000;//busy ,status5[15]
  913. while(val&0x8000){ //check busy ?
  914. ifx_sw_read(0x125, &val);
  915. }
  916. ifx_sw_write(0x11a,control[0]);
  917. ifx_sw_write(0x11b,control[1]);
  918. ifx_sw_write(0x11c,control[2]);
  919. ifx_sw_write(0x11d,control[3]);
  920. ifx_sw_write(0x11e,control[4]);
  921. ifx_sw_write(0x11f,control[5]);
  922. val=0x8000;//busy ,status5[15]
  923. while(val&0x8000){ //check busy ?
  924. ifx_sw_read(0x125, &val);
  925. }
  926. val=((val&0x7000)>>12);//result ,status5[14:12]
  927. mMACENTRY->result=val;
  928. if (!val) {
  929. printk(" Command OK!! \n");
  930. if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE)) {
  931. ifx_sw_read(0x120,&(status[0]));
  932. ifx_sw_read(0x121,&(status[1]));
  933. ifx_sw_read(0x122,&(status[2]));
  934. ifx_sw_read(0x123,&(status[3]));
  935. ifx_sw_read(0x124,&(status[4]));
  936. ifx_sw_read(0x125,&(status[5]));
  937. mMACENTRY->mac_addr[0]=(status[0]&0x00ff) ;
  938. mMACENTRY->mac_addr[1]=(status[0]&0xff00)>>8 ;
  939. mMACENTRY->mac_addr[2]=(status[1]&0x00ff) ;
  940. mMACENTRY->mac_addr[3]=(status[1]&0xff00)>>8 ;
  941. mMACENTRY->mac_addr[4]=(status[2]&0x00ff) ;
  942. mMACENTRY->mac_addr[5]=(status[2]&0xff00)>>8 ;
  943. mMACENTRY->fid=(status[3]&0xf);
  944. mMACENTRY->portmap=((status[3]>>4)&0x3f);
  945. if (status[5]&0x2) {//static info_ctrl //status5[1]????
  946. mMACENTRY->ctrl.info_ctrl=(status[4]&0x00ff);
  947. mMACENTRY->info_type=1;
  948. }
  949. else {//not static age_timer
  950. mMACENTRY->ctrl.age_timer=(status[4]&0x00ff);
  951. mMACENTRY->info_type=0;
  952. }
  953. //status5[13]???? mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
  954. mMACENTRY->occupy=(status[5]&0x02000)>>13;//status5[13] ???
  955. mMACENTRY->bad=(status[5]&0x04)>>2;//status5[2]
  956. }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
  957. }
  958. else if (val==0x001)
  959. printk(" All Entry Used!! \n");
  960. else if (val==0x002)
  961. printk(" Entry Not Found!! \n");
  962. else if (val==0x003)
  963. printk(" Try Next Entry!! \n");
  964. else if (val==0x005)
  965. printk(" Command Error!! \n");
  966. else
  967. printk(" UnKnown Error!! \n");
  968. copy_to_user((PMACENTRY)args, mMACENTRY,sizeof(MACENTRY));
  969. break;
  970. case ADM_SW_IOCTL_FILTER_ADD:
  971. case ADM_SW_IOCTL_FILTER_DEL:
  972. case ADM_SW_IOCTL_FILTER_GET:
  973. uPROTOCOLFILTER = (PPROTOCOLFILTER)kmalloc(sizeof(PROTOCOLFILTER), GFP_KERNEL);
  974. rtval = copy_from_user(uPROTOCOLFILTER, (PPROTOCOLFILTER)args, sizeof(PROTOCOLFILTER));
  975. if (rtval != 0)
  976. {
  977. printk("ADM_SW_IOCTL_FILTER_ADD: copy from user FAILED!! \n");
  978. return (-EFAULT);
  979. }
  980. if(cmd==ADM_SW_IOCTL_FILTER_DEL) { //delete filter
  981. uPROTOCOLFILTER->ip_p=00; //delet filter
  982. uPROTOCOLFILTER->action=00; //delete filter
  983. } //delete filter
  984. ifx_sw_read(((uPROTOCOLFILTER->protocol_filter_num/2)+0x68), &val);//rx68~rx6b,protocol filter0~7
  985. if (((uPROTOCOLFILTER->protocol_filter_num)%2)==00){
  986. if(cmd==ADM_SW_IOCTL_FILTER_GET) uPROTOCOLFILTER->ip_p= val&0x00ff;//get filter ip_p
  987. else val=(val&0xff00)|(uPROTOCOLFILTER->ip_p);//set filter ip_p
  988. }
  989. else {
  990. if(cmd==ADM_SW_IOCTL_FILTER_GET) uPROTOCOLFILTER->ip_p= (val>>8);//get filter ip_p
  991. else val=(val&0x00ff)|((uPROTOCOLFILTER->ip_p)<<8);//set filter ip_p
  992. }
  993. if(cmd!=ADM_SW_IOCTL_FILTER_GET) ifx_sw_write(((uPROTOCOLFILTER->protocol_filter_num/2)+0x68), val);//write rx68~rx6b,protocol filter0~7
  994. ifx_sw_read(0x95, &val); //protocol filter action
  995. if(cmd==ADM_SW_IOCTL_FILTER_GET) {
  996. uPROTOCOLFILTER->action= ((val>>(uPROTOCOLFILTER->protocol_filter_num*2))&0x3);//get filter action
  997. copy_to_user((PPROTOCOLFILTER)args, uPROTOCOLFILTER, sizeof(PROTOCOLFILTER));
  998. }
  999. else {
  1000. val=(val&(~(0x03<<(uPROTOCOLFILTER->protocol_filter_num*2))))|(((uPROTOCOLFILTER->action)&0x03)<<(uPROTOCOLFILTER->protocol_filter_num*2));
  1001. // printk("%d----\n",val);
  1002. ifx_sw_write(0x95, val); //write protocol filter action
  1003. }
  1004. break;
  1005. //adm6996i
  1006. /* others */
  1007. default:
  1008. return -EFAULT;
  1009. }
  1010. /* end of switch */
  1011. return 0;
  1012. }
  1013. /* Santosh: handle IGMP protocol filter ADD/DEL/GET */
  1014. int adm_process_protocol_filter_request (unsigned int cmd, PPROTOCOLFILTER uPROTOCOLFILTER)
  1015. {
  1016. unsigned int val; //6996i
  1017. if(cmd==ADM_SW_IOCTL_FILTER_DEL) { //delete filter
  1018. uPROTOCOLFILTER->ip_p=00; //delet filter
  1019. uPROTOCOLFILTER->action=00; //delete filter
  1020. } //delete filter
  1021. ifx_sw_read(((uPROTOCOLFILTER->protocol_filter_num/2)+0x68), &val);//rx68~rx6b,protocol filter0~7
  1022. if (((uPROTOCOLFILTER->protocol_filter_num)%2)==00){
  1023. if(cmd==ADM_SW_IOCTL_FILTER_GET) uPROTOCOLFILTER->ip_p= val&0x00ff;//get filter ip_p
  1024. else val=(val&0xff00)|(uPROTOCOLFILTER->ip_p);//set filter ip_p
  1025. }
  1026. else {
  1027. if(cmd==ADM_SW_IOCTL_FILTER_GET) uPROTOCOLFILTER->ip_p= (val>>8);//get filter ip_p
  1028. else val=(val&0x00ff)|((uPROTOCOLFILTER->ip_p)<<8);//set filter ip_p
  1029. }
  1030. if(cmd!=ADM_SW_IOCTL_FILTER_GET) ifx_sw_write(((uPROTOCOLFILTER->protocol_filter_num/2)+0x68), val);//write rx68~rx6b,protocol filter0~7
  1031. ifx_sw_read(0x95, &val); //protocol filter action
  1032. if(cmd==ADM_SW_IOCTL_FILTER_GET) {
  1033. uPROTOCOLFILTER->action= ((val>>(uPROTOCOLFILTER->protocol_filter_num*2))&0x3);//get filter action
  1034. }
  1035. else {
  1036. val=(val&(~(0x03<<(uPROTOCOLFILTER->protocol_filter_num*2))))|(((uPROTOCOLFILTER->action)&0x03)<<(uPROTOCOLFILTER->protocol_filter_num*2));
  1037. ifx_sw_write(0x95, val); //write protocol filter action
  1038. }
  1039. return 0;
  1040. }
  1041. /* Santosh: function for MAC ENTRY ADD/DEL/GET */
  1042. int adm_process_mac_table_request (unsigned int cmd, PMACENTRY mMACENTRY)
  1043. {
  1044. unsigned int rtval;
  1045. unsigned int val; //6996i
  1046. unsigned int control[6] ; //6996i
  1047. unsigned int status[6] ; //6996i
  1048. // printk ("adm_process_mac_table_request: enter\n");
  1049. control[0]=(mMACENTRY->mac_addr[1]<<8)+mMACENTRY->mac_addr[0] ;
  1050. control[1]=(mMACENTRY->mac_addr[3]<<8)+mMACENTRY->mac_addr[2] ;
  1051. control[2]=(mMACENTRY->mac_addr[5]<<8)+mMACENTRY->mac_addr[4] ;
  1052. control[3]=(mMACENTRY->fid&0xf)+((mMACENTRY->portmap&0x3f)<<4);
  1053. if (((mMACENTRY->info_type)&0x01)) control[4]=(mMACENTRY->ctrl.info_ctrl)+0x1000; //static ,info control
  1054. else control[4]=((mMACENTRY->ctrl.age_timer)&0xff);//not static ,agetimer
  1055. if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT) {
  1056. //initial the pointer to the first address
  1057. val=0x8000;//busy ,status5[15]
  1058. while(val&0x8000){ //check busy ?
  1059. ifx_sw_read(0x125, &val);
  1060. }
  1061. control[5]=0x030;//initial the first address
  1062. ifx_sw_write(0x11f,control[5]);
  1063. val=0x8000;//busy ,status5[15]
  1064. while(val&0x8000){ //check busy ?
  1065. ifx_sw_read(0x125, &val);
  1066. }
  1067. } //if (cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)
  1068. if (cmd==ADM_SW_IOCTL_MACENTRY_ADD) control[5]=0x07;//create a new address
  1069. else if (cmd==ADM_SW_IOCTL_MACENTRY_DEL) control[5]=0x01f;//erased an existed address
  1070. else if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
  1071. control[5]=0x02c;//search by the mac address field
  1072. val=0x8000;//busy ,status5[15]
  1073. while(val&0x8000){ //check busy ?
  1074. ifx_sw_read(0x125, &val);
  1075. }
  1076. ifx_sw_write(0x11a,control[0]);
  1077. ifx_sw_write(0x11b,control[1]);
  1078. ifx_sw_write(0x11c,control[2]);
  1079. ifx_sw_write(0x11d,control[3]);
  1080. ifx_sw_write(0x11e,control[4]);
  1081. ifx_sw_write(0x11f,control[5]);
  1082. val=0x8000;//busy ,status5[15]
  1083. while(val&0x8000){ //check busy ?
  1084. ifx_sw_read(0x125, &val);
  1085. }
  1086. val=((val&0x7000)>>12);//result ,status5[14:12]
  1087. mMACENTRY->result=val;
  1088. if (!val) {
  1089. printk(" Command OK!! \n");
  1090. if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE)) {
  1091. ifx_sw_read(0x120,&(status[0]));
  1092. ifx_sw_read(0x121,&(status[1]));
  1093. ifx_sw_read(0x122,&(status[2]));
  1094. ifx_sw_read(0x123,&(status[3]));
  1095. ifx_sw_read(0x124,&(status[4]));
  1096. ifx_sw_read(0x125,&(status[5]));
  1097. mMACENTRY->mac_addr[0]=(status[0]&0x00ff) ;
  1098. mMACENTRY->mac_addr[1]=(status[0]&0xff00)>>8 ;
  1099. mMACENTRY->mac_addr[2]=(status[1]&0x00ff) ;
  1100. mMACENTRY->mac_addr[3]=(status[1]&0xff00)>>8 ;
  1101. mMACENTRY->mac_addr[4]=(status[2]&0x00ff) ;
  1102. mMACENTRY->mac_addr[5]=(status[2]&0xff00)>>8 ;
  1103. mMACENTRY->fid=(status[3]&0xf);
  1104. mMACENTRY->portmap=((status[3]>>4)&0x3f);
  1105. if (status[5]&0x2) {//static info_ctrl //status5[1]????
  1106. mMACENTRY->ctrl.info_ctrl=(status[4]&0x00ff);
  1107. mMACENTRY->info_type=1;
  1108. }
  1109. else {//not static age_timer
  1110. mMACENTRY->ctrl.age_timer=(status[4]&0x00ff);
  1111. mMACENTRY->info_type=0;
  1112. }
  1113. //status5[13]???? mMACENTRY->occupy=(status[5]&0x02)>>1;//status5[1]
  1114. mMACENTRY->occupy=(status[5]&0x02000)>>13;//status5[13] ???
  1115. mMACENTRY->bad=(status[5]&0x04)>>2;//status5[2]
  1116. }//if ((cmd==ADM_SW_IOCTL_MACENTRY_GET_INIT)||(cmd==ADM_SW_IOCTL_MACENTRY_GET_MORE))
  1117. }
  1118. else if (val==0x001)
  1119. printk(" All Entry Used!! \n");
  1120. else if (val==0x002)
  1121. printk(" Entry Not Found!! \n");
  1122. else if (val==0x003)
  1123. printk(" Try Next Entry!! \n");
  1124. else if (val==0x005)
  1125. printk(" Command Error!! \n");
  1126. else
  1127. printk(" UnKnown Error!! \n");
  1128. // printk ("adm_process_mac_table_request: Exit\n");
  1129. return 0;
  1130. }
  1131. /* Santosh: End of function for MAC ENTRY ADD/DEL*/
  1132. struct file_operations adm_ops =
  1133. {
  1134. read: adm_read,
  1135. write: adm_write,
  1136. open: adm_open,
  1137. release: adm_release,
  1138. ioctl: adm_ioctl
  1139. };
  1140. int adm_proc(char *buf, char **start, off_t offset, int count, int *eof, void *data)
  1141. {
  1142. int len = 0;
  1143. len += sprintf(buf+len, " ************ Registers ************ \n");
  1144. *eof = 1;
  1145. return len;
  1146. }
  1147. int __init init_adm6996_module(void)
  1148. {
  1149. unsigned int val = 000;
  1150. unsigned int val1 = 000;
  1151. printk("Loading ADM6996 driver... \n");
  1152. /* if running on adm5120 */
  1153. /* set GPIO 0~2 as adm6996 control pins */
  1154. //outl(0x003f3f00, 0x12000028);
  1155. /* enable switch port 5 (MII) as RMII mode (5120MAC <-> 6996MAC) */
  1156. //outl(0x18a, 0x12000030);
  1157. /* group adm5120 port 1 ~ 5 as VLAN0, port 5 & 6(CPU) as VLAN1 */
  1158. //outl(0x417e, 0x12000040);
  1159. /* end adm5120 fixup */
  1160. #ifdef ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
  1161. register_chrdev(69, "adm6996", &adm_ops);
  1162. AMAZON_SW_REG(AMAZON_SW_MDIO_CFG) = 0x27be;
  1163. AMAZON_SW_REG(AMAZON_SW_EPHY) = 0xfc;
  1164. adm6996_mode=adm6996i;
  1165. ifx_sw_read(0xa0, &val);
  1166. ifx_sw_read(0xa1, &val1);
  1167. val=((val1&0x0f)<<16)|val;
  1168. printk ("\nADM6996 SMI Mode-");
  1169. printk ("Chip ID:%5x \n ", val);
  1170. #else //000001.joelin
  1171. AMAZON_SW_REG(AMAZON_SW_MDIO_CFG) = 0x2c50;
  1172. AMAZON_SW_REG(AMAZON_SW_EPHY) = 0xff;
  1173. AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL0) &= ~(GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
  1174. AMAZON_SW_REG(AMAZON_GPIO_P1_ALTSEL1) &= ~(GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
  1175. AMAZON_SW_REG(AMAZON_GPIO_P1_OD) |= (GPIO_MDIO|GPIO_MDCS|GPIO_MDC);
  1176. ifx_gpio_init();
  1177. register_chrdev(69, "adm6996", &adm_ops);
  1178. mdelay(100);
  1179. /* create proc entries */
  1180. // create_proc_read_entry("admide", 0, NULL, admide_proc, NULL);
  1181. //joelin adm6996i support start
  1182. adm6996_mode=adm6996i;
  1183. ifx_sw_read(0xa0, &val);
  1184. adm6996_mode=adm6996l;
  1185. ifx_sw_read(0x200, &val1);
  1186. // printk ("\n %0x \n",val1);
  1187. if ((val&0xfff0)==0x1020) {
  1188. printk ("\n ADM6996I .. \n");
  1189. adm6996_mode=adm6996i;
  1190. }
  1191. else if ((val1&0xffffff00)==0x71000) {//71010 or 71020
  1192. printk ("\n ADM6996LC .. \n");
  1193. adm6996_mode=adm6996lc;
  1194. }
  1195. else {
  1196. printk ("\n ADM6996L .. \n");
  1197. adm6996_mode=adm6996l;
  1198. }
  1199. #endif //ADM6996_MDC_MDIO_MODE //smi mode //000001.joelin
  1200. if ((adm6996_mode==adm6996lc)||(adm6996_mode==adm6996i)){
  1201. #if 0 /* removed by MarsLin */
  1202. ifx_sw_write(0x29,0xc000);
  1203. ifx_sw_write(0x30,0x0985);
  1204. #else
  1205. ifx_sw_read(0xa0, &val);
  1206. if (val == 0x1021) // for both 6996LC and 6996I, only AB version need the patch
  1207. ifx_sw_write(0x29, 0x9000);
  1208. ifx_sw_write(0x30,0x0985);
  1209. #endif
  1210. }
  1211. //joelin adm6996i support end
  1212. return 0;
  1213. }
  1214. void __exit cleanup_adm6996_module(void)
  1215. {
  1216. printk("Free ADM device driver... \n");
  1217. unregister_chrdev(69, "adm6996");
  1218. /* remove proc entries */
  1219. // remove_proc_entry("admide", NULL);
  1220. }
  1221. /* MarsLin, add start */
  1222. #if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
  1223. #define SET_BIT(reg, mask) reg |= (mask)
  1224. #define CLEAR_BIT(reg, mask) reg &= (~mask)
  1225. static int ifx_hw_reset(void)
  1226. {
  1227. CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL0),0x2000);
  1228. CLEAR_BIT((*AMAZON_GPIO_P0_ALTSEL1),0x2000);
  1229. SET_BIT((*AMAZON_GPIO_P0_OD),0x2000);
  1230. SET_BIT((*AMAZON_GPIO_P0_DIR), 0x2000);
  1231. CLEAR_BIT((*AMAZON_GPIO_P0_OUT), 0x2000);
  1232. mdelay(500);
  1233. SET_BIT((*AMAZON_GPIO_P0_OUT), 0x2000);
  1234. cleanup_adm6996_module();
  1235. return init_adm6996_module();
  1236. }
  1237. int (*adm6996_hw_reset)(void) = ifx_hw_reset;
  1238. EXPORT_SYMBOL(adm6996_hw_reset);
  1239. EXPORT_SYMBOL(adm6996_mode);
  1240. int (*adm6996_sw_read)(unsigned int addr, unsigned int *data) = ifx_sw_read;
  1241. EXPORT_SYMBOL(adm6996_sw_read);
  1242. int (*adm6996_sw_write)(unsigned int addr, unsigned int data) = ifx_sw_write;
  1243. EXPORT_SYMBOL(adm6996_sw_write);
  1244. #endif
  1245. /* MarsLin, add end */
  1246. /* Santosh: for IGMP proxy/snooping, Begin */
  1247. EXPORT_SYMBOL (adm_process_mac_table_request);
  1248. EXPORT_SYMBOL (adm_process_protocol_filter_request);
  1249. /* Santosh: for IGMP proxy/snooping, End */
  1250. MODULE_DESCRIPTION("ADMtek 6996 Driver");
  1251. MODULE_AUTHOR("Joe Lin <[email protected]>");
  1252. MODULE_LICENSE("GPL");
  1253. module_init(init_adm6996_module);
  1254. module_exit(cleanup_adm6996_module);