MDIO R/W working
[mw/milkymist.git] / software / libnet / mdio.c
1 /*
2  * Milkymist VJ SoC (Software)
3  * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <hw/minimac.h>
19 #include <net/mdio.h>
20
21 static void delay()
22 {
23         volatile int i;
24         for(i=0;i<1000;i++);
25 }
26
27 static void raw_write(unsigned int word, int bitcount)
28 {
29         word <<= 32 - bitcount;
30         while(bitcount > 0) {
31                 if(word & 0x80000000) {
32                         CSR_MINIMAC_MDIO = MINIMAC_MDIO_CLK|MINIMAC_MDIO_DO|MINIMAC_MDIO_OE;
33                         delay();
34                         CSR_MINIMAC_MDIO = MINIMAC_MDIO_DO|MINIMAC_MDIO_OE;
35                         delay();
36                 } else {
37                         CSR_MINIMAC_MDIO = MINIMAC_MDIO_CLK|MINIMAC_MDIO_OE;
38                         delay();
39                         CSR_MINIMAC_MDIO = MINIMAC_MDIO_OE;
40                         delay();
41                 }
42                 word <<= 1;
43                 bitcount--;
44         }
45 }
46
47 static unsigned int raw_read()
48 {
49         unsigned int word;
50         unsigned int i;
51
52         word = 0;
53         for(i=0;i<16;i++) {
54                 word <<= 1;
55                 CSR_MINIMAC_MDIO = MINIMAC_MDIO_CLK;
56                 delay();
57                 CSR_MINIMAC_MDIO = 0;
58                 delay();
59                 if(CSR_MINIMAC_MDIO & MINIMAC_MDIO_DI)
60                         word |= 1;
61         }
62         return word;
63 }
64
65 static void raw_turnaround()
66 {
67         CSR_MINIMAC_MDIO = MINIMAC_MDIO_CLK;
68         delay();
69         CSR_MINIMAC_MDIO = 0;
70         delay();
71         CSR_MINIMAC_MDIO = MINIMAC_MDIO_CLK;
72         delay();
73         CSR_MINIMAC_MDIO = 0;
74         delay();
75 }
76
77 void mdio_write(int phyadr, int reg, int val)
78 {
79         CSR_MINIMAC_MDIO = MINIMAC_MDIO_OE;
80         raw_write(0xffffffff, 32); /* < sync */
81         raw_write(0x05, 4); /* < start + write */
82         raw_write(phyadr, 5);
83         raw_write(reg, 5);
84         raw_write(0x02, 2); /* < turnaround */
85         raw_write(val, 16);
86         raw_turnaround();
87 }
88
89 int mdio_read(int phyadr, int reg)
90 {
91         int r;
92         
93         CSR_MINIMAC_MDIO = MINIMAC_MDIO_OE;
94         raw_write(0xffffffff, 32); /* < sync */
95         raw_write(0x06, 4); /* < start + read */
96         raw_write(phyadr, 5);
97         raw_write(reg, 5);
98         raw_turnaround();
99         r = raw_read();
100         raw_turnaround();
101         
102         return r;
103 }
104