リビジョン | 92a190aaab3536d695c51e0739f925910eb49889 (tree) |
---|---|
日時 | 2014-02-07 23:16:46 |
作者 | Alexey Brodkin <Alexey.Brodkin@syno...> |
コミッター | Tom Rini |
net/designware - switch driver to phylib usage
With this change driver will benefit from existing phylib and thus
custom phy functionality implemented in the driver will go away:
instead of 4.
rich functionality of phylib.
"board_phy_config".
Note that after this change some previously used config options
(driver-specific PHY configuration) will be obsolete and they are simply
substituted with similar options of phylib.
For example:
by default.
explicitly CONFIG_PHY_ADDR board config option has to be used, otherwise
automatically the first discovered on MDIO bus phy will be used
I believe there's no need now in "doc/README.designware_eth" because
user only needs to instantiate the driver with "designware_initialize"
whose prototype exists in "include/netdev.h".
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Vipin Kumar <vipin.kumar@st.com>
Cc: Stefan Roese <sr@denx.de>
Cc: Mischa Jonker <mjonker@synopsys.com>
Cc: Shiraz Hashim <shiraz.hashim@st.com>
Cc: Albert ARIBAUD <albert.u.boot@aribaud.net>
Cc: Amit Virdi <amit.virdi@st.com>
Cc: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
@@ -41,12 +41,12 @@ int board_eth_init(bd_t *bis) | ||
41 | 41 | if (CONFIG_DW_PORTS & 1) { |
42 | 42 | static const unsigned short pins[] = P_RMII0; |
43 | 43 | if (!peripheral_request_list(pins, "emac0")) |
44 | - ret += designware_initialize(0, EMAC0_MACCFG, 1, 0); | |
44 | + ret += designware_initialize(EMAC0_MACCFG, 0); | |
45 | 45 | } |
46 | 46 | if (CONFIG_DW_PORTS & 2) { |
47 | 47 | static const unsigned short pins[] = P_RMII1; |
48 | 48 | if (!peripheral_request_list(pins, "emac1")) |
49 | - ret += designware_initialize(1, EMAC1_MACCFG, 1, 0); | |
49 | + ret += designware_initialize(EMAC1_MACCFG, 0); | |
50 | 50 | } |
51 | 51 | |
52 | 52 | return ret; |
@@ -53,8 +53,7 @@ int board_eth_init(bd_t *bis) | ||
53 | 53 | |
54 | 54 | #if defined(CONFIG_DESIGNWARE_ETH) |
55 | 55 | u32 interface = PHY_INTERFACE_MODE_MII; |
56 | - if (designware_initialize(0, CONFIG_SPEAR_ETHBASE, CONFIG_DW0_PHY, | |
57 | - interface) >= 0) | |
56 | + if (designware_initialize(CONFIG_SPEAR_ETHBASE, interface) >= 0) | |
58 | 57 | ret++; |
59 | 58 | #endif |
60 | 59 | return ret; |
@@ -54,8 +54,7 @@ int board_eth_init(bd_t *bis) | ||
54 | 54 | |
55 | 55 | #if defined(CONFIG_DESIGNWARE_ETH) |
56 | 56 | u32 interface = PHY_INTERFACE_MODE_MII; |
57 | - if (designware_initialize(0, CONFIG_SPEAR_ETHBASE, CONFIG_DW0_PHY, | |
58 | - interface) >= 0) | |
57 | + if (designware_initialize(CONFIG_SPEAR_ETHBASE, interface) >= 0) | |
59 | 58 | ret++; |
60 | 59 | #endif |
61 | 60 | #if defined(CONFIG_MACB) |
@@ -65,8 +65,7 @@ int board_eth_init(bd_t *bis) | ||
65 | 65 | |
66 | 66 | #if defined(CONFIG_DESIGNWARE_ETH) |
67 | 67 | u32 interface = PHY_INTERFACE_MODE_MII; |
68 | - if (designware_initialize(0, CONFIG_SPEAR_ETHBASE, CONFIG_DW0_PHY, | |
69 | - interface) >= 0) | |
68 | + if (designware_initialize(CONFIG_SPEAR_ETHBASE, interface) >= 0) | |
70 | 69 | ret++; |
71 | 70 | #endif |
72 | 71 | #if defined(CONFIG_MACB) |
@@ -51,8 +51,7 @@ int board_eth_init(bd_t *bis) | ||
51 | 51 | #if defined(CONFIG_DW_AUTONEG) |
52 | 52 | interface = PHY_INTERFACE_MODE_GMII; |
53 | 53 | #endif |
54 | - if (designware_initialize(0, CONFIG_SPEAR_ETHBASE, CONFIG_DW0_PHY, | |
55 | - interface) >= 0) | |
54 | + if (designware_initialize(CONFIG_SPEAR_ETHBASE, interface) >= 0) | |
56 | 55 | ret++; |
57 | 56 | #endif |
58 | 57 | return ret; |
@@ -67,31 +67,32 @@ void board_nand_init(void) | ||
67 | 67 | fsmc_nand_init(nand); |
68 | 68 | } |
69 | 69 | |
70 | -int designware_board_phy_init(struct eth_device *dev, int phy_addr, | |
71 | - int (*mii_write)(struct eth_device *, u8, u8, u16), | |
72 | - int dw_reset_phy(struct eth_device *)) | |
70 | +int board_phy_config(struct phy_device *phydev) | |
73 | 71 | { |
74 | 72 | /* Extended PHY control 1, select GMII */ |
75 | - mii_write(dev, phy_addr, 23, 0x0020); | |
73 | + phy_write(phydev, MDIO_DEVAD_NONE, 23, 0x0020); | |
76 | 74 | |
77 | 75 | /* Software reset necessary after GMII mode selction */ |
78 | - dw_reset_phy(dev); | |
76 | + phy_reset(phydev); | |
79 | 77 | |
80 | 78 | /* Enable extended page register access */ |
81 | - mii_write(dev, phy_addr, 31, 0x0001); | |
79 | + phy_write(phydev, MDIO_DEVAD_NONE, 31, 0x0001); | |
82 | 80 | |
83 | 81 | /* 17e: Enhanced LED behavior, needs to be written twice */ |
84 | - mii_write(dev, phy_addr, 17, 0x09ff); | |
85 | - mii_write(dev, phy_addr, 17, 0x09ff); | |
82 | + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x09ff); | |
83 | + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x09ff); | |
86 | 84 | |
87 | 85 | /* 16e: Enhanced LED method select */ |
88 | - mii_write(dev, phy_addr, 16, 0xe0ea); | |
86 | + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0xe0ea); | |
89 | 87 | |
90 | 88 | /* Disable extended page register access */ |
91 | - mii_write(dev, phy_addr, 31, 0x0000); | |
89 | + phy_write(phydev, MDIO_DEVAD_NONE, 31, 0x0000); | |
92 | 90 | |
93 | 91 | /* Enable clock output pin */ |
94 | - mii_write(dev, phy_addr, 18, 0x0049); | |
92 | + phy_write(phydev, MDIO_DEVAD_NONE, 18, 0x0049); | |
93 | + | |
94 | + if (phydev->drv->config) | |
95 | + phydev->drv->config(phydev); | |
95 | 96 | |
96 | 97 | return 0; |
97 | 98 | } |
@@ -100,7 +101,7 @@ int board_eth_init(bd_t *bis) | ||
100 | 101 | { |
101 | 102 | int ret = 0; |
102 | 103 | |
103 | - if (designware_initialize(0, CONFIG_SPEAR_ETHBASE, CONFIG_PHY_ADDR, | |
104 | + if (designware_initialize(CONFIG_SPEAR_ETHBASE, | |
104 | 105 | PHY_INTERFACE_MODE_GMII) >= 0) |
105 | 106 | ret++; |
106 | 107 |
@@ -1,25 +0,0 @@ | ||
1 | -This driver supports Designware Ethernet Controller provided by Synopsis. | |
2 | - | |
3 | -The driver is enabled by CONFIG_DESIGNWARE_ETH. | |
4 | - | |
5 | -The driver has been developed and tested on SPEAr platforms. By default, the | |
6 | -MDIO interface works at 100/Full. #defining the below options in board | |
7 | -configuration file changes this behavior. | |
8 | - | |
9 | -Call an subroutine from respective board/.../board.c | |
10 | -designware_initialize(u32 id, ulong base_addr, u32 phy_addr); | |
11 | - | |
12 | -The various options suported by the driver are | |
13 | -1. CONFIG_DW_ALTDESCRIPTOR | |
14 | - Define this to use the Alternate/Enhanced Descriptor configurations. | |
15 | -1. CONFIG_DW_AUTONEG | |
16 | - Define this to autonegotiate with the host before proceeding with mac | |
17 | - level configuration. This obviates the definitions of CONFIG_DW_SPEED10M | |
18 | - and CONFIG_DW_DUPLEXHALF. | |
19 | -2. CONFIG_DW_SPEED10M | |
20 | - Define this to change the default behavior from 100Mbps to 10Mbps. | |
21 | -3. CONFIG_DW_DUPLEXHALF | |
22 | - Define this to change the default behavior from Full Duplex to Half. | |
23 | -4. CONFIG_DW_SEARCH_PHY | |
24 | - Define this to search the phy address. This would overwrite the value | |
25 | - passed as 3rd arg from designware_initialize routine. |
@@ -17,7 +17,75 @@ | ||
17 | 17 | #include <asm/io.h> |
18 | 18 | #include "designware.h" |
19 | 19 | |
20 | -static int configure_phy(struct eth_device *dev); | |
20 | +#if !defined(CONFIG_PHYLIB) | |
21 | +# error "DesignWare Ether MAC requires PHYLIB - missing CONFIG_PHYLIB" | |
22 | +#endif | |
23 | + | |
24 | +static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) | |
25 | +{ | |
26 | + struct eth_mac_regs *mac_p = bus->priv; | |
27 | + ulong start; | |
28 | + u16 miiaddr; | |
29 | + int timeout = CONFIG_MDIO_TIMEOUT; | |
30 | + | |
31 | + miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | | |
32 | + ((reg << MIIREGSHIFT) & MII_REGMSK); | |
33 | + | |
34 | + writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); | |
35 | + | |
36 | + start = get_timer(0); | |
37 | + while (get_timer(start) < timeout) { | |
38 | + if (!(readl(&mac_p->miiaddr) & MII_BUSY)) | |
39 | + return readl(&mac_p->miidata); | |
40 | + udelay(10); | |
41 | + }; | |
42 | + | |
43 | + return -1; | |
44 | +} | |
45 | + | |
46 | +static int dw_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, | |
47 | + u16 val) | |
48 | +{ | |
49 | + struct eth_mac_regs *mac_p = bus->priv; | |
50 | + ulong start; | |
51 | + u16 miiaddr; | |
52 | + int ret = -1, timeout = CONFIG_MDIO_TIMEOUT; | |
53 | + | |
54 | + writel(val, &mac_p->miidata); | |
55 | + miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | | |
56 | + ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE; | |
57 | + | |
58 | + writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); | |
59 | + | |
60 | + start = get_timer(0); | |
61 | + while (get_timer(start) < timeout) { | |
62 | + if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { | |
63 | + ret = 0; | |
64 | + break; | |
65 | + } | |
66 | + udelay(10); | |
67 | + }; | |
68 | + | |
69 | + return ret; | |
70 | +} | |
71 | + | |
72 | +static int dw_mdio_init(char *name, struct eth_mac_regs *mac_regs_p) | |
73 | +{ | |
74 | + struct mii_dev *bus = mdio_alloc(); | |
75 | + | |
76 | + if (!bus) { | |
77 | + printf("Failed to allocate MDIO bus\n"); | |
78 | + return -1; | |
79 | + } | |
80 | + | |
81 | + bus->read = dw_mdio_read; | |
82 | + bus->write = dw_mdio_write; | |
83 | + sprintf(bus->name, name); | |
84 | + | |
85 | + bus->priv = (void *)mac_regs_p; | |
86 | + | |
87 | + return mdio_register(bus); | |
88 | +} | |
21 | 89 | |
22 | 90 | static void tx_descs_init(struct eth_device *dev) |
23 | 91 | { |
@@ -83,53 +151,59 @@ static void rx_descs_init(struct eth_device *dev) | ||
83 | 151 | priv->rx_currdescnum = 0; |
84 | 152 | } |
85 | 153 | |
86 | -static void descs_init(struct eth_device *dev) | |
154 | +static int dw_write_hwaddr(struct eth_device *dev) | |
87 | 155 | { |
88 | - tx_descs_init(dev); | |
89 | - rx_descs_init(dev); | |
156 | + struct dw_eth_dev *priv = dev->priv; | |
157 | + struct eth_mac_regs *mac_p = priv->mac_regs_p; | |
158 | + u32 macid_lo, macid_hi; | |
159 | + u8 *mac_id = &dev->enetaddr[0]; | |
160 | + | |
161 | + macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) + | |
162 | + (mac_id[3] << 24); | |
163 | + macid_hi = mac_id[4] + (mac_id[5] << 8); | |
164 | + | |
165 | + writel(macid_hi, &mac_p->macaddr0hi); | |
166 | + writel(macid_lo, &mac_p->macaddr0lo); | |
167 | + | |
168 | + return 0; | |
90 | 169 | } |
91 | 170 | |
92 | -static int mac_reset(struct eth_device *dev) | |
171 | +static void dw_adjust_link(struct eth_mac_regs *mac_p, | |
172 | + struct phy_device *phydev) | |
93 | 173 | { |
94 | - struct dw_eth_dev *priv = dev->priv; | |
95 | - struct eth_mac_regs *mac_p = priv->mac_regs_p; | |
96 | - struct eth_dma_regs *dma_p = priv->dma_regs_p; | |
174 | + u32 conf = readl(&mac_p->conf) | FRAMEBURSTENABLE | DISABLERXOWN; | |
97 | 175 | |
98 | - ulong start; | |
99 | - int timeout = CONFIG_MACRESET_TIMEOUT; | |
176 | + if (!phydev->link) { | |
177 | + printf("%s: No link.\n", phydev->dev->name); | |
178 | + return; | |
179 | + } | |
100 | 180 | |
101 | - writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode); | |
181 | + if (phydev->speed != 1000) | |
182 | + conf |= MII_PORTSELECT; | |
102 | 183 | |
103 | - if (priv->interface != PHY_INTERFACE_MODE_RGMII) | |
104 | - writel(MII_PORTSELECT, &mac_p->conf); | |
184 | + if (phydev->speed == 100) | |
185 | + conf |= FES_100; | |
105 | 186 | |
106 | - start = get_timer(0); | |
107 | - while (get_timer(start) < timeout) { | |
108 | - if (!(readl(&dma_p->busmode) & DMAMAC_SRST)) | |
109 | - return 0; | |
187 | + if (phydev->duplex) | |
188 | + conf |= FULLDPLXMODE; | |
110 | 189 | |
111 | - /* Try again after 10usec */ | |
112 | - udelay(10); | |
113 | - }; | |
190 | + writel(conf, &mac_p->conf); | |
114 | 191 | |
115 | - return -1; | |
192 | + printf("Speed: %d, %s duplex%s\n", phydev->speed, | |
193 | + (phydev->duplex) ? "full" : "half", | |
194 | + (phydev->port == PORT_FIBRE) ? ", fiber mode" : ""); | |
116 | 195 | } |
117 | 196 | |
118 | -static int dw_write_hwaddr(struct eth_device *dev) | |
197 | +static void dw_eth_halt(struct eth_device *dev) | |
119 | 198 | { |
120 | 199 | struct dw_eth_dev *priv = dev->priv; |
121 | 200 | struct eth_mac_regs *mac_p = priv->mac_regs_p; |
122 | - u32 macid_lo, macid_hi; | |
123 | - u8 *mac_id = &dev->enetaddr[0]; | |
201 | + struct eth_dma_regs *dma_p = priv->dma_regs_p; | |
124 | 202 | |
125 | - macid_lo = mac_id[0] + (mac_id[1] << 8) + \ | |
126 | - (mac_id[2] << 16) + (mac_id[3] << 24); | |
127 | - macid_hi = mac_id[4] + (mac_id[5] << 8); | |
203 | + writel(readl(&mac_p->conf) & ~(RXENABLE | TXENABLE), &mac_p->conf); | |
204 | + writel(readl(&dma_p->opmode) & ~(RXSTART | TXSTART), &dma_p->opmode); | |
128 | 205 | |
129 | - writel(macid_hi, &mac_p->macaddr0hi); | |
130 | - writel(macid_lo, &mac_p->macaddr0lo); | |
131 | - | |
132 | - return 0; | |
206 | + phy_shutdown(priv->phydev); | |
133 | 207 | } |
134 | 208 | |
135 | 209 | static int dw_eth_init(struct eth_device *dev, bd_t *bis) |
@@ -137,55 +211,43 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis) | ||
137 | 211 | struct dw_eth_dev *priv = dev->priv; |
138 | 212 | struct eth_mac_regs *mac_p = priv->mac_regs_p; |
139 | 213 | struct eth_dma_regs *dma_p = priv->dma_regs_p; |
140 | - u32 conf; | |
214 | + unsigned int start; | |
141 | 215 | |
142 | - if (priv->phy_configured != 1) | |
143 | - configure_phy(dev); | |
216 | + writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode); | |
144 | 217 | |
145 | - /* Print link status only once */ | |
146 | - if (!priv->link_printed) { | |
147 | - printf("ENET Speed is %d Mbps - %s duplex connection\n", | |
148 | - priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL"); | |
149 | - priv->link_printed = 1; | |
150 | - } | |
218 | + start = get_timer(0); | |
219 | + while (readl(&dma_p->busmode) & DMAMAC_SRST) { | |
220 | + if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) | |
221 | + return -1; | |
151 | 222 | |
152 | - /* Reset ethernet hardware */ | |
153 | - if (mac_reset(dev) < 0) | |
154 | - return -1; | |
223 | + mdelay(100); | |
224 | + }; | |
155 | 225 | |
156 | - /* Resore the HW MAC address as it has been lost during MAC reset */ | |
226 | + /* Soft reset above clears HW address registers. | |
227 | + * So we have to set it here once again */ | |
157 | 228 | dw_write_hwaddr(dev); |
158 | 229 | |
159 | - writel(FIXEDBURST | PRIORXTX_41 | BURST_16, | |
160 | - &dma_p->busmode); | |
161 | - | |
162 | - writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD | | |
163 | - TXSECONDFRAME, &dma_p->opmode); | |
230 | + rx_descs_init(dev); | |
231 | + tx_descs_init(dev); | |
164 | 232 | |
165 | - conf = FRAMEBURSTENABLE | DISABLERXOWN; | |
233 | + writel(FIXEDBURST | PRIORXTX_41 | BURST_16, &dma_p->busmode); | |
166 | 234 | |
167 | - if (priv->speed != 1000) | |
168 | - conf |= MII_PORTSELECT; | |
235 | + writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD, | |
236 | + &dma_p->opmode); | |
169 | 237 | |
170 | - if ((priv->interface != PHY_INTERFACE_MODE_MII) && | |
171 | - (priv->interface != PHY_INTERFACE_MODE_GMII)) { | |
238 | + writel(readl(&dma_p->opmode) | RXSTART | TXSTART, &dma_p->opmode); | |
172 | 239 | |
173 | - if (priv->speed == 100) | |
174 | - conf |= FES_100; | |
240 | + /* Start up the PHY */ | |
241 | + if (phy_startup(priv->phydev)) { | |
242 | + printf("Could not initialize PHY %s\n", | |
243 | + priv->phydev->dev->name); | |
244 | + return -1; | |
175 | 245 | } |
176 | 246 | |
177 | - if (priv->duplex == FULL) | |
178 | - conf |= FULLDPLXMODE; | |
179 | - | |
180 | - writel(conf, &mac_p->conf); | |
247 | + dw_adjust_link(mac_p, priv->phydev); | |
181 | 248 | |
182 | - descs_init(dev); | |
183 | - | |
184 | - /* | |
185 | - * Start/Enable xfer at dma as well as mac level | |
186 | - */ | |
187 | - writel(readl(&dma_p->opmode) | RXSTART, &dma_p->opmode); | |
188 | - writel(readl(&dma_p->opmode) | TXSTART, &dma_p->opmode); | |
249 | + if (!priv->phydev->link) | |
250 | + return -1; | |
189 | 251 | |
190 | 252 | writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf); |
191 | 253 |
@@ -267,251 +329,30 @@ static int dw_eth_recv(struct eth_device *dev) | ||
267 | 329 | return length; |
268 | 330 | } |
269 | 331 | |
270 | -static void dw_eth_halt(struct eth_device *dev) | |
271 | -{ | |
272 | - struct dw_eth_dev *priv = dev->priv; | |
273 | - | |
274 | - mac_reset(dev); | |
275 | - priv->tx_currdescnum = priv->rx_currdescnum = 0; | |
276 | -} | |
277 | - | |
278 | -static int eth_mdio_read(struct eth_device *dev, u8 addr, u8 reg, u16 *val) | |
332 | +static int dw_phy_init(struct eth_device *dev) | |
279 | 333 | { |
280 | 334 | struct dw_eth_dev *priv = dev->priv; |
281 | - struct eth_mac_regs *mac_p = priv->mac_regs_p; | |
282 | - ulong start; | |
283 | - u32 miiaddr; | |
284 | - int timeout = CONFIG_MDIO_TIMEOUT; | |
285 | - | |
286 | - miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \ | |
287 | - ((reg << MIIREGSHIFT) & MII_REGMSK); | |
288 | - | |
289 | - writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); | |
290 | - | |
291 | - start = get_timer(0); | |
292 | - while (get_timer(start) < timeout) { | |
293 | - if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { | |
294 | - *val = readl(&mac_p->miidata); | |
295 | - return 0; | |
296 | - } | |
335 | + struct phy_device *phydev; | |
336 | + int mask = 0xffffffff; | |
297 | 337 | |
298 | - /* Try again after 10usec */ | |
299 | - udelay(10); | |
300 | - }; | |
301 | - | |
302 | - return -1; | |
303 | -} | |
304 | - | |
305 | -static int eth_mdio_write(struct eth_device *dev, u8 addr, u8 reg, u16 val) | |
306 | -{ | |
307 | - struct dw_eth_dev *priv = dev->priv; | |
308 | - struct eth_mac_regs *mac_p = priv->mac_regs_p; | |
309 | - ulong start; | |
310 | - u32 miiaddr; | |
311 | - int ret = -1, timeout = CONFIG_MDIO_TIMEOUT; | |
312 | - u16 value; | |
313 | - | |
314 | - writel(val, &mac_p->miidata); | |
315 | - miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \ | |
316 | - ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE; | |
317 | - | |
318 | - writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); | |
319 | - | |
320 | - start = get_timer(0); | |
321 | - while (get_timer(start) < timeout) { | |
322 | - if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { | |
323 | - ret = 0; | |
324 | - break; | |
325 | - } | |
326 | - | |
327 | - /* Try again after 10usec */ | |
328 | - udelay(10); | |
329 | - }; | |
330 | - | |
331 | - /* Needed as a fix for ST-Phy */ | |
332 | - eth_mdio_read(dev, addr, reg, &value); | |
333 | - | |
334 | - return ret; | |
335 | -} | |
336 | - | |
337 | -#if defined(CONFIG_DW_SEARCH_PHY) | |
338 | -static int find_phy(struct eth_device *dev) | |
339 | -{ | |
340 | - int phy_addr = 0; | |
341 | - u16 ctrl, oldctrl; | |
342 | - | |
343 | - do { | |
344 | - eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl); | |
345 | - oldctrl = ctrl & BMCR_ANENABLE; | |
346 | - | |
347 | - ctrl ^= BMCR_ANENABLE; | |
348 | - eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl); | |
349 | - eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl); | |
350 | - ctrl &= BMCR_ANENABLE; | |
351 | - | |
352 | - if (ctrl == oldctrl) { | |
353 | - phy_addr++; | |
354 | - } else { | |
355 | - ctrl ^= BMCR_ANENABLE; | |
356 | - eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl); | |
357 | - | |
358 | - return phy_addr; | |
359 | - } | |
360 | - } while (phy_addr < 32); | |
361 | - | |
362 | - return -1; | |
363 | -} | |
338 | +#ifdef CONFIG_PHY_ADDR | |
339 | + mask = 1 << CONFIG_PHY_ADDR; | |
364 | 340 | #endif |
365 | 341 | |
366 | -static int dw_reset_phy(struct eth_device *dev) | |
367 | -{ | |
368 | - struct dw_eth_dev *priv = dev->priv; | |
369 | - u16 ctrl; | |
370 | - ulong start; | |
371 | - int timeout = CONFIG_PHYRESET_TIMEOUT; | |
372 | - u32 phy_addr = priv->address; | |
373 | - | |
374 | - eth_mdio_write(dev, phy_addr, MII_BMCR, BMCR_RESET); | |
375 | - | |
376 | - start = get_timer(0); | |
377 | - while (get_timer(start) < timeout) { | |
378 | - eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl); | |
379 | - if (!(ctrl & BMCR_RESET)) | |
380 | - break; | |
381 | - | |
382 | - /* Try again after 10usec */ | |
383 | - udelay(10); | |
384 | - }; | |
385 | - | |
386 | - if (get_timer(start) >= CONFIG_PHYRESET_TIMEOUT) | |
342 | + phydev = phy_find_by_mask(priv->bus, mask, priv->interface); | |
343 | + if (!phydev) | |
387 | 344 | return -1; |
388 | 345 | |
389 | -#ifdef CONFIG_PHY_RESET_DELAY | |
390 | - udelay(CONFIG_PHY_RESET_DELAY); | |
391 | -#endif | |
392 | - return 0; | |
393 | -} | |
346 | + phydev->supported &= PHY_GBIT_FEATURES; | |
347 | + phydev->advertising = phydev->supported; | |
394 | 348 | |
395 | -/* | |
396 | - * Add weak default function for board specific PHY configuration | |
397 | - */ | |
398 | -int __weak designware_board_phy_init(struct eth_device *dev, int phy_addr, | |
399 | - int (*mii_write)(struct eth_device *, u8, u8, u16), | |
400 | - int dw_reset_phy(struct eth_device *)) | |
401 | -{ | |
402 | - return 0; | |
403 | -} | |
349 | + priv->phydev = phydev; | |
350 | + phy_config(phydev); | |
404 | 351 | |
405 | -static int configure_phy(struct eth_device *dev) | |
406 | -{ | |
407 | - struct dw_eth_dev *priv = dev->priv; | |
408 | - int phy_addr; | |
409 | - u16 bmcr; | |
410 | -#if defined(CONFIG_DW_AUTONEG) | |
411 | - u16 bmsr; | |
412 | - u32 timeout; | |
413 | - ulong start; | |
414 | -#endif | |
415 | - | |
416 | -#if defined(CONFIG_DW_SEARCH_PHY) | |
417 | - phy_addr = find_phy(dev); | |
418 | - if (phy_addr >= 0) | |
419 | - priv->address = phy_addr; | |
420 | - else | |
421 | - return -1; | |
422 | -#else | |
423 | - phy_addr = priv->address; | |
424 | -#endif | |
425 | - | |
426 | - /* | |
427 | - * Some boards need board specific PHY initialization. This is | |
428 | - * after the main driver init code but before the auto negotiation | |
429 | - * is run. | |
430 | - */ | |
431 | - if (designware_board_phy_init(dev, phy_addr, | |
432 | - eth_mdio_write, dw_reset_phy) < 0) | |
433 | - return -1; | |
434 | - | |
435 | - if (dw_reset_phy(dev) < 0) | |
436 | - return -1; | |
437 | - | |
438 | -#if defined(CONFIG_DW_AUTONEG) | |
439 | - /* Set Auto-Neg Advertisement capabilities to 10/100 half/full */ | |
440 | - eth_mdio_write(dev, phy_addr, MII_ADVERTISE, 0x1E1); | |
441 | - | |
442 | - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; | |
443 | -#else | |
444 | - bmcr = BMCR_SPEED100 | BMCR_FULLDPLX; | |
445 | - | |
446 | -#if defined(CONFIG_DW_SPEED10M) | |
447 | - bmcr &= ~BMCR_SPEED100; | |
448 | -#endif | |
449 | -#if defined(CONFIG_DW_DUPLEXHALF) | |
450 | - bmcr &= ~BMCR_FULLDPLX; | |
451 | -#endif | |
452 | -#endif | |
453 | - if (eth_mdio_write(dev, phy_addr, MII_BMCR, bmcr) < 0) | |
454 | - return -1; | |
455 | - | |
456 | - /* Read the phy status register and populate priv structure */ | |
457 | -#if defined(CONFIG_DW_AUTONEG) | |
458 | - timeout = CONFIG_AUTONEG_TIMEOUT; | |
459 | - start = get_timer(0); | |
460 | - puts("Waiting for PHY auto negotiation to complete"); | |
461 | - while (get_timer(start) < timeout) { | |
462 | - eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr); | |
463 | - if (bmsr & BMSR_ANEGCOMPLETE) { | |
464 | - priv->phy_configured = 1; | |
465 | - break; | |
466 | - } | |
467 | - | |
468 | - /* Print dot all 1s to show progress */ | |
469 | - if ((get_timer(start) % 1000) == 0) | |
470 | - putc('.'); | |
471 | - | |
472 | - /* Try again after 1msec */ | |
473 | - udelay(1000); | |
474 | - }; | |
475 | - | |
476 | - if (!(bmsr & BMSR_ANEGCOMPLETE)) | |
477 | - puts(" TIMEOUT!\n"); | |
478 | - else | |
479 | - puts(" done\n"); | |
480 | -#else | |
481 | - priv->phy_configured = 1; | |
482 | -#endif | |
483 | - | |
484 | - priv->speed = miiphy_speed(dev->name, phy_addr); | |
485 | - priv->duplex = miiphy_duplex(dev->name, phy_addr); | |
486 | - | |
487 | - return 0; | |
488 | -} | |
489 | - | |
490 | -#if defined(CONFIG_MII) | |
491 | -static int dw_mii_read(const char *devname, u8 addr, u8 reg, u16 *val) | |
492 | -{ | |
493 | - struct eth_device *dev; | |
494 | - | |
495 | - dev = eth_get_dev_by_name(devname); | |
496 | - if (dev) | |
497 | - eth_mdio_read(dev, addr, reg, val); | |
498 | - | |
499 | - return 0; | |
500 | -} | |
501 | - | |
502 | -static int dw_mii_write(const char *devname, u8 addr, u8 reg, u16 val) | |
503 | -{ | |
504 | - struct eth_device *dev; | |
505 | - | |
506 | - dev = eth_get_dev_by_name(devname); | |
507 | - if (dev) | |
508 | - eth_mdio_write(dev, addr, reg, val); | |
509 | - | |
510 | - return 0; | |
352 | + return 1; | |
511 | 353 | } |
512 | -#endif | |
513 | 354 | |
514 | -int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface) | |
355 | +int designware_initialize(ulong base_addr, u32 interface) | |
515 | 356 | { |
516 | 357 | struct eth_device *dev; |
517 | 358 | struct dw_eth_dev *priv; |
@@ -533,19 +374,14 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface) | ||
533 | 374 | memset(dev, 0, sizeof(struct eth_device)); |
534 | 375 | memset(priv, 0, sizeof(struct dw_eth_dev)); |
535 | 376 | |
536 | - sprintf(dev->name, "mii%d", id); | |
377 | + sprintf(dev->name, "dwmac.%lx", base_addr); | |
537 | 378 | dev->iobase = (int)base_addr; |
538 | 379 | dev->priv = priv; |
539 | 380 | |
540 | - eth_getenv_enetaddr_by_index("eth", id, &dev->enetaddr[0]); | |
541 | - | |
542 | 381 | priv->dev = dev; |
543 | 382 | priv->mac_regs_p = (struct eth_mac_regs *)base_addr; |
544 | 383 | priv->dma_regs_p = (struct eth_dma_regs *)(base_addr + |
545 | 384 | DW_DMA_BASE_OFFSET); |
546 | - priv->address = phy_addr; | |
547 | - priv->phy_configured = 0; | |
548 | - priv->interface = interface; | |
549 | 385 | |
550 | 386 | dev->init = dw_eth_init; |
551 | 387 | dev->send = dw_eth_send; |
@@ -555,8 +391,10 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface) | ||
555 | 391 | |
556 | 392 | eth_register(dev); |
557 | 393 | |
558 | -#if defined(CONFIG_MII) | |
559 | - miiphy_register(dev->name, dw_mii_read, dw_mii_write); | |
560 | -#endif | |
561 | - return 1; | |
394 | + priv->interface = interface; | |
395 | + | |
396 | + dw_mdio_init(dev->name, priv->mac_regs_p); | |
397 | + priv->bus = miiphy_get_dev_by_name(dev->name); | |
398 | + | |
399 | + return dw_phy_init(dev); | |
562 | 400 | } |
@@ -16,8 +16,6 @@ | ||
16 | 16 | |
17 | 17 | #define CONFIG_MACRESET_TIMEOUT (3 * CONFIG_SYS_HZ) |
18 | 18 | #define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ) |
19 | -#define CONFIG_PHYRESET_TIMEOUT (3 * CONFIG_SYS_HZ) | |
20 | -#define CONFIG_AUTONEG_TIMEOUT (5 * CONFIG_SYS_HZ) | |
21 | 19 | |
22 | 20 | struct eth_mac_regs { |
23 | 21 | u32 conf; /* 0x00 */ |
@@ -217,14 +215,9 @@ struct dmamacdescr { | ||
217 | 215 | #endif |
218 | 216 | |
219 | 217 | struct dw_eth_dev { |
220 | - u32 address; | |
221 | 218 | u32 interface; |
222 | - u32 speed; | |
223 | - u32 duplex; | |
224 | 219 | u32 tx_currdescnum; |
225 | 220 | u32 rx_currdescnum; |
226 | - u32 phy_configured; | |
227 | - u32 link_printed; | |
228 | 221 | |
229 | 222 | struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM]; |
230 | 223 | struct dmamacdescr rx_mac_descrtable[CONFIG_RX_DESCR_NUM]; |
@@ -236,15 +229,8 @@ struct dw_eth_dev { | ||
236 | 229 | struct eth_dma_regs *dma_regs_p; |
237 | 230 | |
238 | 231 | struct eth_device *dev; |
232 | + struct phy_device *phydev; | |
233 | + struct mii_dev *bus; | |
239 | 234 | }; |
240 | 235 | |
241 | -/* Speed specific definitions */ | |
242 | -#define SPEED_10M 1 | |
243 | -#define SPEED_100M 2 | |
244 | -#define SPEED_1000M 3 | |
245 | - | |
246 | -/* Duplex mode specific definitions */ | |
247 | -#define HALF_DUPLEX 1 | |
248 | -#define FULL_DUPLEX 2 | |
249 | - | |
250 | 236 | #endif |
@@ -72,12 +72,13 @@ | ||
72 | 72 | #define CONFIG_NET_MULTI |
73 | 73 | #define CONFIG_HOSTNAME "bf609-ezkit" |
74 | 74 | #define CONFIG_DESIGNWARE_ETH |
75 | +#define CONFIG_PHY_ADDR 1 | |
75 | 76 | #define CONFIG_DW_PORTS 1 |
76 | -#define CONFIG_DW_AUTONEG | |
77 | 77 | #define CONFIG_DW_ALTDESCRIPTOR |
78 | 78 | #define CONFIG_CMD_NET |
79 | 79 | #define CONFIG_CMD_MII |
80 | 80 | #define CONFIG_MII |
81 | +#define CONFIG_PHYLIB | |
81 | 82 | |
82 | 83 | /* i2c Settings */ |
83 | 84 | #define CONFIG_BFIN_TWI_I2C |
@@ -17,11 +17,9 @@ | ||
17 | 17 | /* Ethernet driver configuration */ |
18 | 18 | #define CONFIG_MII |
19 | 19 | #define CONFIG_DESIGNWARE_ETH |
20 | -#define CONFIG_DW_SEARCH_PHY | |
21 | -#define CONFIG_DW0_PHY 1 | |
22 | 20 | #define CONFIG_NET_MULTI |
21 | +#define CONFIG_PHYLIB | |
23 | 22 | #define CONFIG_PHY_RESET_DELAY 10000 /* in usec */ |
24 | -#define CONFIG_DW_AUTONEG | |
25 | 23 | #define CONFIG_PHY_GIGE /* Include GbE speed/duplex detection */ |
26 | 24 | |
27 | 25 | /* USBD driver configuration */ |
@@ -37,6 +37,9 @@ | ||
37 | 37 | #define CONFIG_SYS_FSMC_NAND_8BIT |
38 | 38 | #define CONFIG_SYS_NAND_BASE 0xD2000000 |
39 | 39 | |
40 | +/* Ethernet PHY configuration */ | |
41 | +#define CONFIG_PHY_NATSEMI | |
42 | + | |
40 | 43 | /* Environment Settings */ |
41 | 44 | #define CONFIG_EXTRA_ENV_SETTINGS CONFIG_EXTRA_ENV_USBTTY |
42 | 45 |
@@ -36,7 +36,7 @@ int calxedaxgmac_initialize(u32 id, ulong base_addr); | ||
36 | 36 | int cs8900_initialize(u8 dev_num, int base_addr); |
37 | 37 | int davinci_emac_initialize(void); |
38 | 38 | int dc21x4x_initialize(bd_t *bis); |
39 | -int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface); | |
39 | +int designware_initialize(ulong base_addr, u32 interface); | |
40 | 40 | int dm9000_initialize(bd_t *bis); |
41 | 41 | int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr); |
42 | 42 | int e1000_initialize(bd_t *bis); |