1
2
3
4
5
6
7
8#include <common.h>
9#include <miiphy.h>
10#include <phy.h>
11#include <asm/io.h>
12#include <fsl_memac.h>
13#include <fm_eth.h>
14
15#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
16#define memac_out_32(a, v) out_le32(a, v)
17#define memac_clrbits_32(a, v) clrbits_le32(a, v)
18#define memac_setbits_32(a, v) setbits_le32(a, v)
19#else
20#define memac_out_32(a, v) out_be32(a, v)
21#define memac_clrbits_32(a, v) clrbits_be32(a, v)
22#define memac_setbits_32(a, v) setbits_be32(a, v)
23#endif
24
25static u32 memac_in_32(u32 *reg)
26{
27#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
28 return in_le32(reg);
29#else
30 return in_be32(reg);
31#endif
32}
33
34
35
36
37
38
39int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
40 int regnum, u16 value)
41{
42 u32 mdio_ctl;
43 struct memac_mdio_controller *regs = bus->priv;
44 u32 c45 = 1;
45
46 if (dev_addr == MDIO_DEVAD_NONE) {
47 c45 = 0;
48 dev_addr = regnum & 0x1f;
49 memac_clrbits_32(®s->mdio_stat, MDIO_STAT_ENC);
50 } else
51 memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC);
52
53
54 while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
55 ;
56
57
58 mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
59 memac_out_32(®s->mdio_ctl, mdio_ctl);
60
61
62 if (c45)
63 memac_out_32(®s->mdio_addr, regnum & 0xffff);
64
65
66 while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
67 ;
68
69
70 memac_out_32(®s->mdio_data, MDIO_DATA(value));
71
72
73 while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY)
74 ;
75
76 return 0;
77}
78
79
80
81
82
83
84int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
85 int regnum)
86{
87 u32 mdio_ctl;
88 struct memac_mdio_controller *regs = bus->priv;
89 u32 c45 = 1;
90
91 if (dev_addr == MDIO_DEVAD_NONE) {
92 if (!strcmp(bus->name, DEFAULT_FM_TGEC_MDIO_NAME))
93 return 0xffff;
94 c45 = 0;
95 dev_addr = regnum & 0x1f;
96 memac_clrbits_32(®s->mdio_stat, MDIO_STAT_ENC);
97 } else
98 memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC);
99
100
101 while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
102 ;
103
104
105 mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
106 memac_out_32(®s->mdio_ctl, mdio_ctl);
107
108
109 if (c45)
110 memac_out_32(®s->mdio_addr, regnum & 0xffff);
111
112
113 while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
114 ;
115
116
117 mdio_ctl |= MDIO_CTL_READ;
118 memac_out_32(®s->mdio_ctl, mdio_ctl);
119
120
121 while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY)
122 ;
123
124
125 if (memac_in_32(®s->mdio_stat) & MDIO_STAT_RD_ER)
126 return 0xffff;
127
128 return memac_in_32(®s->mdio_data) & 0xffff;
129}
130
131int memac_mdio_reset(struct mii_dev *bus)
132{
133 return 0;
134}
135
136int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
137{
138 struct mii_dev *bus = mdio_alloc();
139
140 if (!bus) {
141 printf("Failed to allocate FM TGEC MDIO bus\n");
142 return -1;
143 }
144
145 bus->read = memac_mdio_read;
146 bus->write = memac_mdio_write;
147 bus->reset = memac_mdio_reset;
148 strcpy(bus->name, info->name);
149
150 bus->priv = info->regs;
151
152
153
154
155
156
157
158
159
160
161
162
163
164 memac_setbits_32(
165 &((struct memac_mdio_controller *)info->regs)->mdio_stat,
166 MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
167
168 return mdio_register(bus);
169}
170