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