Commit 9fafe7dab9bc8a9e33e1ba5e28a3ec870d689b82
Committed by
Albert ARIBAUD
1 parent
8682aba7da
Exists in
master
and in
55 other branches
net: phy: make board_phy_config responsible for calling drv->config
Boards may have things they want done before or after normal phy config. Letting the boards call drv->config allows them more flexibilty. Boards affected by this change are corenet_ds and mpc8544ds. Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com> Acked-by: Dirk Behme <dirk.behme@de.bosch.com>
Showing 3 changed files with 6 additions and 3 deletions Inline Diff
board/freescale/corenet_ds/eth_p4080.c
1 | /* | 1 | /* |
2 | * Copyright 2009-2011 Freescale Semiconductor, Inc. | 2 | * Copyright 2009-2011 Freescale Semiconductor, Inc. |
3 | * | 3 | * |
4 | * See file CREDITS for list of people who contributed to this | 4 | * See file CREDITS for list of people who contributed to this |
5 | * project. | 5 | * project. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as | 8 | * modify it under the terms of the GNU General Public License as |
9 | * published by the Free Software Foundation; either version 2 of | 9 | * published by the Free Software Foundation; either version 2 of |
10 | * the License, or (at your option) any later version. | 10 | * the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
20 | * MA 02111-1307 USA | 20 | * MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <common.h> | 23 | #include <common.h> |
24 | #include <command.h> | 24 | #include <command.h> |
25 | #include <netdev.h> | 25 | #include <netdev.h> |
26 | #include <asm/mmu.h> | 26 | #include <asm/mmu.h> |
27 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
28 | #include <asm/cache.h> | 28 | #include <asm/cache.h> |
29 | #include <asm/immap_85xx.h> | 29 | #include <asm/immap_85xx.h> |
30 | #include <asm/fsl_law.h> | 30 | #include <asm/fsl_law.h> |
31 | #include <asm/fsl_ddr_sdram.h> | 31 | #include <asm/fsl_ddr_sdram.h> |
32 | #include <asm/fsl_serdes.h> | 32 | #include <asm/fsl_serdes.h> |
33 | #include <asm/fsl_portals.h> | 33 | #include <asm/fsl_portals.h> |
34 | #include <asm/fsl_liodn.h> | 34 | #include <asm/fsl_liodn.h> |
35 | #include <malloc.h> | 35 | #include <malloc.h> |
36 | #include <fm_eth.h> | 36 | #include <fm_eth.h> |
37 | #include <fsl_mdio.h> | 37 | #include <fsl_mdio.h> |
38 | #include <miiphy.h> | 38 | #include <miiphy.h> |
39 | #include <phy.h> | 39 | #include <phy.h> |
40 | 40 | ||
41 | #include "../common/ngpixis.h" | 41 | #include "../common/ngpixis.h" |
42 | #include "../common/fman.h" | 42 | #include "../common/fman.h" |
43 | #include <asm/fsl_dtsec.h> | 43 | #include <asm/fsl_dtsec.h> |
44 | 44 | ||
45 | #define EMI_NONE 0xffffffff | 45 | #define EMI_NONE 0xffffffff |
46 | #define EMI_MASK 0xf0000000 | 46 | #define EMI_MASK 0xf0000000 |
47 | #define EMI1_RGMII 0x0 | 47 | #define EMI1_RGMII 0x0 |
48 | #define EMI1_SLOT3 0x80000000 /* bank1 EFGH */ | 48 | #define EMI1_SLOT3 0x80000000 /* bank1 EFGH */ |
49 | #define EMI1_SLOT4 0x40000000 /* bank2 ABCD */ | 49 | #define EMI1_SLOT4 0x40000000 /* bank2 ABCD */ |
50 | #define EMI1_SLOT5 0xc0000000 /* bank3 ABCD */ | 50 | #define EMI1_SLOT5 0xc0000000 /* bank3 ABCD */ |
51 | #define EMI2_SLOT4 0x10000000 /* bank2 ABCD */ | 51 | #define EMI2_SLOT4 0x10000000 /* bank2 ABCD */ |
52 | #define EMI2_SLOT5 0x30000000 /* bank3 ABCD */ | 52 | #define EMI2_SLOT5 0x30000000 /* bank3 ABCD */ |
53 | #define EMI1_MASK 0xc0000000 | 53 | #define EMI1_MASK 0xc0000000 |
54 | #define EMI2_MASK 0x30000000 | 54 | #define EMI2_MASK 0x30000000 |
55 | 55 | ||
56 | static int mdio_mux[NUM_FM_PORTS]; | 56 | static int mdio_mux[NUM_FM_PORTS]; |
57 | 57 | ||
58 | static char *mdio_names[16] = { | 58 | static char *mdio_names[16] = { |
59 | "P4080DS_MDIO0", | 59 | "P4080DS_MDIO0", |
60 | "P4080DS_MDIO1", | 60 | "P4080DS_MDIO1", |
61 | NULL, | 61 | NULL, |
62 | "P4080DS_MDIO3", | 62 | "P4080DS_MDIO3", |
63 | "P4080DS_MDIO4", | 63 | "P4080DS_MDIO4", |
64 | NULL, NULL, NULL, | 64 | NULL, NULL, NULL, |
65 | "P4080DS_MDIO8", | 65 | "P4080DS_MDIO8", |
66 | NULL, NULL, NULL, | 66 | NULL, NULL, NULL, |
67 | "P4080DS_MDIO12", | 67 | "P4080DS_MDIO12", |
68 | NULL, NULL, NULL, | 68 | NULL, NULL, NULL, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static char *p4080ds_mdio_name_for_muxval(u32 muxval) | 71 | static char *p4080ds_mdio_name_for_muxval(u32 muxval) |
72 | { | 72 | { |
73 | return mdio_names[(muxval & EMI_MASK) >> 28]; | 73 | return mdio_names[(muxval & EMI_MASK) >> 28]; |
74 | } | 74 | } |
75 | 75 | ||
76 | struct mii_dev *mii_dev_for_muxval(u32 muxval) | 76 | struct mii_dev *mii_dev_for_muxval(u32 muxval) |
77 | { | 77 | { |
78 | struct mii_dev *bus; | 78 | struct mii_dev *bus; |
79 | char *name = p4080ds_mdio_name_for_muxval(muxval); | 79 | char *name = p4080ds_mdio_name_for_muxval(muxval); |
80 | 80 | ||
81 | if (!name) { | 81 | if (!name) { |
82 | printf("No bus for muxval %x\n", muxval); | 82 | printf("No bus for muxval %x\n", muxval); |
83 | return NULL; | 83 | return NULL; |
84 | } | 84 | } |
85 | 85 | ||
86 | bus = miiphy_get_dev_by_name(name); | 86 | bus = miiphy_get_dev_by_name(name); |
87 | 87 | ||
88 | if (!bus) { | 88 | if (!bus) { |
89 | printf("No bus by name %s\n", name); | 89 | printf("No bus by name %s\n", name); |
90 | return NULL; | 90 | return NULL; |
91 | } | 91 | } |
92 | 92 | ||
93 | return bus; | 93 | return bus; |
94 | } | 94 | } |
95 | 95 | ||
96 | #if defined(CONFIG_SYS_P4080_ERRATUM_SERDES9) && defined(CONFIG_PHY_TERANETICS) | 96 | #if defined(CONFIG_SYS_P4080_ERRATUM_SERDES9) && defined(CONFIG_PHY_TERANETICS) |
97 | int board_phy_config(struct phy_device *phydev) | 97 | int board_phy_config(struct phy_device *phydev) |
98 | { | 98 | { |
99 | if (phydev->drv->config) | ||
100 | phydev->drv->config(phydev); | ||
99 | if (phydev->drv->uid == PHY_UID_TN2020) { | 101 | if (phydev->drv->uid == PHY_UID_TN2020) { |
100 | unsigned long timeout = 1 * 1000; /* 1 seconds */ | 102 | unsigned long timeout = 1 * 1000; /* 1 seconds */ |
101 | enum srds_prtcl device; | 103 | enum srds_prtcl device; |
102 | 104 | ||
103 | /* | 105 | /* |
104 | * Wait for the XAUI to come out of reset. This is when it | 106 | * Wait for the XAUI to come out of reset. This is when it |
105 | * starts transmitting alignment signals. | 107 | * starts transmitting alignment signals. |
106 | */ | 108 | */ |
107 | while (--timeout) { | 109 | while (--timeout) { |
108 | int reg = phy_read(phydev, MDIO_MMD_PHYXS, MDIO_CTRL1); | 110 | int reg = phy_read(phydev, MDIO_MMD_PHYXS, MDIO_CTRL1); |
109 | if (reg < 0) { | 111 | if (reg < 0) { |
110 | printf("TN2020: Error reading from PHY at " | 112 | printf("TN2020: Error reading from PHY at " |
111 | "address %u\n", phydev->addr); | 113 | "address %u\n", phydev->addr); |
112 | break; | 114 | break; |
113 | } | 115 | } |
114 | /* | 116 | /* |
115 | * Note that we've never actually seen | 117 | * Note that we've never actually seen |
116 | * MDIO_CTRL1_RESET set to 1. | 118 | * MDIO_CTRL1_RESET set to 1. |
117 | */ | 119 | */ |
118 | if ((reg & MDIO_CTRL1_RESET) == 0) | 120 | if ((reg & MDIO_CTRL1_RESET) == 0) |
119 | break; | 121 | break; |
120 | udelay(1000); | 122 | udelay(1000); |
121 | } | 123 | } |
122 | 124 | ||
123 | if (!timeout) { | 125 | if (!timeout) { |
124 | printf("TN2020: Timeout waiting for PHY at address %u " | 126 | printf("TN2020: Timeout waiting for PHY at address %u " |
125 | " to reset.\n", phydev->addr); | 127 | " to reset.\n", phydev->addr); |
126 | } | 128 | } |
127 | 129 | ||
128 | switch (phydev->addr) { | 130 | switch (phydev->addr) { |
129 | case CONFIG_SYS_FM1_10GEC1_PHY_ADDR: | 131 | case CONFIG_SYS_FM1_10GEC1_PHY_ADDR: |
130 | device = XAUI_FM1; | 132 | device = XAUI_FM1; |
131 | break; | 133 | break; |
132 | case CONFIG_SYS_FM2_10GEC1_PHY_ADDR: | 134 | case CONFIG_SYS_FM2_10GEC1_PHY_ADDR: |
133 | device = XAUI_FM2; | 135 | device = XAUI_FM2; |
134 | break; | 136 | break; |
135 | default: | 137 | default: |
136 | device = NONE; | 138 | device = NONE; |
137 | } | 139 | } |
138 | 140 | ||
139 | serdes_reset_rx(device); | 141 | serdes_reset_rx(device); |
140 | } | 142 | } |
141 | 143 | ||
142 | return 0; | 144 | return 0; |
143 | } | 145 | } |
144 | #endif | 146 | #endif |
145 | 147 | ||
146 | struct p4080ds_mdio { | 148 | struct p4080ds_mdio { |
147 | u32 muxval; | 149 | u32 muxval; |
148 | struct mii_dev *realbus; | 150 | struct mii_dev *realbus; |
149 | }; | 151 | }; |
150 | 152 | ||
151 | static void p4080ds_mux_mdio(u32 muxval) | 153 | static void p4080ds_mux_mdio(u32 muxval) |
152 | { | 154 | { |
153 | ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR); | 155 | ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR); |
154 | uint gpioval = in_be32(&pgpio->gpdat) & ~(EMI_MASK); | 156 | uint gpioval = in_be32(&pgpio->gpdat) & ~(EMI_MASK); |
155 | gpioval |= muxval; | 157 | gpioval |= muxval; |
156 | 158 | ||
157 | out_be32(&pgpio->gpdat, gpioval); | 159 | out_be32(&pgpio->gpdat, gpioval); |
158 | } | 160 | } |
159 | 161 | ||
160 | static int p4080ds_mdio_read(struct mii_dev *bus, int addr, int devad, | 162 | static int p4080ds_mdio_read(struct mii_dev *bus, int addr, int devad, |
161 | int regnum) | 163 | int regnum) |
162 | { | 164 | { |
163 | struct p4080ds_mdio *priv = bus->priv; | 165 | struct p4080ds_mdio *priv = bus->priv; |
164 | 166 | ||
165 | p4080ds_mux_mdio(priv->muxval); | 167 | p4080ds_mux_mdio(priv->muxval); |
166 | 168 | ||
167 | return priv->realbus->read(priv->realbus, addr, devad, regnum); | 169 | return priv->realbus->read(priv->realbus, addr, devad, regnum); |
168 | } | 170 | } |
169 | 171 | ||
170 | static int p4080ds_mdio_write(struct mii_dev *bus, int addr, int devad, | 172 | static int p4080ds_mdio_write(struct mii_dev *bus, int addr, int devad, |
171 | int regnum, u16 value) | 173 | int regnum, u16 value) |
172 | { | 174 | { |
173 | struct p4080ds_mdio *priv = bus->priv; | 175 | struct p4080ds_mdio *priv = bus->priv; |
174 | 176 | ||
175 | p4080ds_mux_mdio(priv->muxval); | 177 | p4080ds_mux_mdio(priv->muxval); |
176 | 178 | ||
177 | return priv->realbus->write(priv->realbus, addr, devad, regnum, value); | 179 | return priv->realbus->write(priv->realbus, addr, devad, regnum, value); |
178 | } | 180 | } |
179 | 181 | ||
180 | static int p4080ds_mdio_reset(struct mii_dev *bus) | 182 | static int p4080ds_mdio_reset(struct mii_dev *bus) |
181 | { | 183 | { |
182 | struct p4080ds_mdio *priv = bus->priv; | 184 | struct p4080ds_mdio *priv = bus->priv; |
183 | 185 | ||
184 | return priv->realbus->reset(priv->realbus); | 186 | return priv->realbus->reset(priv->realbus); |
185 | } | 187 | } |
186 | 188 | ||
187 | static int p4080ds_mdio_init(char *realbusname, u32 muxval) | 189 | static int p4080ds_mdio_init(char *realbusname, u32 muxval) |
188 | { | 190 | { |
189 | struct p4080ds_mdio *pmdio; | 191 | struct p4080ds_mdio *pmdio; |
190 | struct mii_dev *bus = mdio_alloc(); | 192 | struct mii_dev *bus = mdio_alloc(); |
191 | 193 | ||
192 | if (!bus) { | 194 | if (!bus) { |
193 | printf("Failed to allocate P4080DS MDIO bus\n"); | 195 | printf("Failed to allocate P4080DS MDIO bus\n"); |
194 | return -1; | 196 | return -1; |
195 | } | 197 | } |
196 | 198 | ||
197 | pmdio = malloc(sizeof(*pmdio)); | 199 | pmdio = malloc(sizeof(*pmdio)); |
198 | if (!pmdio) { | 200 | if (!pmdio) { |
199 | printf("Failed to allocate P4080DS private data\n"); | 201 | printf("Failed to allocate P4080DS private data\n"); |
200 | free(bus); | 202 | free(bus); |
201 | return -1; | 203 | return -1; |
202 | } | 204 | } |
203 | 205 | ||
204 | bus->read = p4080ds_mdio_read; | 206 | bus->read = p4080ds_mdio_read; |
205 | bus->write = p4080ds_mdio_write; | 207 | bus->write = p4080ds_mdio_write; |
206 | bus->reset = p4080ds_mdio_reset; | 208 | bus->reset = p4080ds_mdio_reset; |
207 | sprintf(bus->name, p4080ds_mdio_name_for_muxval(muxval)); | 209 | sprintf(bus->name, p4080ds_mdio_name_for_muxval(muxval)); |
208 | 210 | ||
209 | pmdio->realbus = miiphy_get_dev_by_name(realbusname); | 211 | pmdio->realbus = miiphy_get_dev_by_name(realbusname); |
210 | 212 | ||
211 | if (!pmdio->realbus) { | 213 | if (!pmdio->realbus) { |
212 | printf("No bus with name %s\n", realbusname); | 214 | printf("No bus with name %s\n", realbusname); |
213 | free(bus); | 215 | free(bus); |
214 | free(pmdio); | 216 | free(pmdio); |
215 | return -1; | 217 | return -1; |
216 | } | 218 | } |
217 | 219 | ||
218 | pmdio->muxval = muxval; | 220 | pmdio->muxval = muxval; |
219 | bus->priv = pmdio; | 221 | bus->priv = pmdio; |
220 | 222 | ||
221 | return mdio_register(bus); | 223 | return mdio_register(bus); |
222 | } | 224 | } |
223 | 225 | ||
224 | void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa, | 226 | void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa, |
225 | enum fm_port port, int offset) | 227 | enum fm_port port, int offset) |
226 | { | 228 | { |
227 | if (mdio_mux[port] == EMI1_RGMII) | 229 | if (mdio_mux[port] == EMI1_RGMII) |
228 | fdt_set_phy_handle(blob, prop, pa, "phy_rgmii"); | 230 | fdt_set_phy_handle(blob, prop, pa, "phy_rgmii"); |
229 | 231 | ||
230 | if (mdio_mux[port] == EMI1_SLOT3) { | 232 | if (mdio_mux[port] == EMI1_SLOT3) { |
231 | int idx = port - FM2_DTSEC1 + 5; | 233 | int idx = port - FM2_DTSEC1 + 5; |
232 | char phy[16]; | 234 | char phy[16]; |
233 | 235 | ||
234 | sprintf(phy, "phy%d_slot3", idx); | 236 | sprintf(phy, "phy%d_slot3", idx); |
235 | 237 | ||
236 | fdt_set_phy_handle(blob, prop, pa, phy); | 238 | fdt_set_phy_handle(blob, prop, pa, phy); |
237 | } | 239 | } |
238 | } | 240 | } |
239 | 241 | ||
240 | void fdt_fixup_board_enet(void *fdt) | 242 | void fdt_fixup_board_enet(void *fdt) |
241 | { | 243 | { |
242 | int i; | 244 | int i; |
243 | 245 | ||
244 | /* | 246 | /* |
245 | * P4080DS can be configured in many different ways, supporting a number | 247 | * P4080DS can be configured in many different ways, supporting a number |
246 | * of combinations of ethernet devices and phy types. In order to | 248 | * of combinations of ethernet devices and phy types. In order to |
247 | * have just one device tree for all of those configurations, we fix up | 249 | * have just one device tree for all of those configurations, we fix up |
248 | * the tree here. By default, the device tree configures FM1 and FM2 | 250 | * the tree here. By default, the device tree configures FM1 and FM2 |
249 | * for SGMII, and configures XAUI on both 10G interfaces. So we have | 251 | * for SGMII, and configures XAUI on both 10G interfaces. So we have |
250 | * a number of different variables to track: | 252 | * a number of different variables to track: |
251 | * | 253 | * |
252 | * 1) Whether the device is configured at all. Whichever devices are | 254 | * 1) Whether the device is configured at all. Whichever devices are |
253 | * not enabled should be disabled by setting the "status" property | 255 | * not enabled should be disabled by setting the "status" property |
254 | * to "disabled". | 256 | * to "disabled". |
255 | * 2) What the PHY interface is. If this is an RGMII connection, | 257 | * 2) What the PHY interface is. If this is an RGMII connection, |
256 | * we should change the "phy-connection-type" property to | 258 | * we should change the "phy-connection-type" property to |
257 | * "rgmii" | 259 | * "rgmii" |
258 | * 3) Which PHY is being used. Because the MDIO buses are muxed, | 260 | * 3) Which PHY is being used. Because the MDIO buses are muxed, |
259 | * we need to redirect the "phy-handle" property to point at the | 261 | * we need to redirect the "phy-handle" property to point at the |
260 | * PHY on the right slot/bus. | 262 | * PHY on the right slot/bus. |
261 | */ | 263 | */ |
262 | 264 | ||
263 | /* We've got six MDIO nodes that may or may not need to exist */ | 265 | /* We've got six MDIO nodes that may or may not need to exist */ |
264 | fdt_status_disabled_by_alias(fdt, "emi1_slot3"); | 266 | fdt_status_disabled_by_alias(fdt, "emi1_slot3"); |
265 | fdt_status_disabled_by_alias(fdt, "emi1_slot4"); | 267 | fdt_status_disabled_by_alias(fdt, "emi1_slot4"); |
266 | fdt_status_disabled_by_alias(fdt, "emi1_slot5"); | 268 | fdt_status_disabled_by_alias(fdt, "emi1_slot5"); |
267 | fdt_status_disabled_by_alias(fdt, "emi2_slot4"); | 269 | fdt_status_disabled_by_alias(fdt, "emi2_slot4"); |
268 | fdt_status_disabled_by_alias(fdt, "emi2_slot5"); | 270 | fdt_status_disabled_by_alias(fdt, "emi2_slot5"); |
269 | 271 | ||
270 | for (i = 0; i < NUM_FM_PORTS; i++) { | 272 | for (i = 0; i < NUM_FM_PORTS; i++) { |
271 | switch (mdio_mux[i]) { | 273 | switch (mdio_mux[i]) { |
272 | case EMI1_SLOT3: | 274 | case EMI1_SLOT3: |
273 | fdt_status_okay_by_alias(fdt, "emi1_slot3"); | 275 | fdt_status_okay_by_alias(fdt, "emi1_slot3"); |
274 | break; | 276 | break; |
275 | case EMI1_SLOT4: | 277 | case EMI1_SLOT4: |
276 | fdt_status_okay_by_alias(fdt, "emi1_slot4"); | 278 | fdt_status_okay_by_alias(fdt, "emi1_slot4"); |
277 | break; | 279 | break; |
278 | case EMI1_SLOT5: | 280 | case EMI1_SLOT5: |
279 | fdt_status_okay_by_alias(fdt, "emi1_slot5"); | 281 | fdt_status_okay_by_alias(fdt, "emi1_slot5"); |
280 | break; | 282 | break; |
281 | case EMI2_SLOT4: | 283 | case EMI2_SLOT4: |
282 | fdt_status_okay_by_alias(fdt, "emi2_slot4"); | 284 | fdt_status_okay_by_alias(fdt, "emi2_slot4"); |
283 | break; | 285 | break; |
284 | case EMI2_SLOT5: | 286 | case EMI2_SLOT5: |
285 | fdt_status_okay_by_alias(fdt, "emi2_slot5"); | 287 | fdt_status_okay_by_alias(fdt, "emi2_slot5"); |
286 | break; | 288 | break; |
287 | } | 289 | } |
288 | } | 290 | } |
289 | } | 291 | } |
290 | 292 | ||
291 | enum board_slots { | 293 | enum board_slots { |
292 | SLOT1 = 1, | 294 | SLOT1 = 1, |
293 | SLOT2, | 295 | SLOT2, |
294 | SLOT3, | 296 | SLOT3, |
295 | SLOT4, | 297 | SLOT4, |
296 | SLOT5, | 298 | SLOT5, |
297 | SLOT6, | 299 | SLOT6, |
298 | }; | 300 | }; |
299 | 301 | ||
300 | int board_eth_init(bd_t *bis) | 302 | int board_eth_init(bd_t *bis) |
301 | { | 303 | { |
302 | #ifdef CONFIG_FMAN_ENET | 304 | #ifdef CONFIG_FMAN_ENET |
303 | ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR); | 305 | ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR); |
304 | int i; | 306 | int i; |
305 | struct fsl_pq_mdio_info dtsec_mdio_info; | 307 | struct fsl_pq_mdio_info dtsec_mdio_info; |
306 | struct tgec_mdio_info tgec_mdio_info; | 308 | struct tgec_mdio_info tgec_mdio_info; |
307 | 309 | ||
308 | u8 lane_to_slot[] = { | 310 | u8 lane_to_slot[] = { |
309 | SLOT1, /* 0 - Bank 1:A */ | 311 | SLOT1, /* 0 - Bank 1:A */ |
310 | SLOT1, /* 1 - Bank 1:B */ | 312 | SLOT1, /* 1 - Bank 1:B */ |
311 | SLOT2, /* 2 - Bank 1:C */ | 313 | SLOT2, /* 2 - Bank 1:C */ |
312 | SLOT2, /* 3 - Bank 1:D */ | 314 | SLOT2, /* 3 - Bank 1:D */ |
313 | SLOT3, /* 4 - Bank 1:E */ | 315 | SLOT3, /* 4 - Bank 1:E */ |
314 | SLOT3, /* 5 - Bank 1:F */ | 316 | SLOT3, /* 5 - Bank 1:F */ |
315 | SLOT3, /* 6 - Bank 1:G */ | 317 | SLOT3, /* 6 - Bank 1:G */ |
316 | SLOT3, /* 7 - Bank 1:H */ | 318 | SLOT3, /* 7 - Bank 1:H */ |
317 | SLOT6, /* 8 - Bank 1:I */ | 319 | SLOT6, /* 8 - Bank 1:I */ |
318 | SLOT6, /* 9 - Bank 1:J */ | 320 | SLOT6, /* 9 - Bank 1:J */ |
319 | SLOT4, /* 10 - Bank 2:A */ | 321 | SLOT4, /* 10 - Bank 2:A */ |
320 | SLOT4, /* 11 - Bank 2:B */ | 322 | SLOT4, /* 11 - Bank 2:B */ |
321 | SLOT4, /* 12 - Bank 2:C */ | 323 | SLOT4, /* 12 - Bank 2:C */ |
322 | SLOT4, /* 13 - Bank 2:D */ | 324 | SLOT4, /* 13 - Bank 2:D */ |
323 | SLOT5, /* 14 - Bank 3:A */ | 325 | SLOT5, /* 14 - Bank 3:A */ |
324 | SLOT5, /* 15 - Bank 3:B */ | 326 | SLOT5, /* 15 - Bank 3:B */ |
325 | SLOT5, /* 16 - Bank 3:C */ | 327 | SLOT5, /* 16 - Bank 3:C */ |
326 | SLOT5, /* 17 - Bank 3:D */ | 328 | SLOT5, /* 17 - Bank 3:D */ |
327 | }; | 329 | }; |
328 | 330 | ||
329 | /* Initialize the mdio_mux array so we can recognize empty elements */ | 331 | /* Initialize the mdio_mux array so we can recognize empty elements */ |
330 | for (i = 0; i < NUM_FM_PORTS; i++) | 332 | for (i = 0; i < NUM_FM_PORTS; i++) |
331 | mdio_mux[i] = EMI_NONE; | 333 | mdio_mux[i] = EMI_NONE; |
332 | 334 | ||
333 | /* The first 4 GPIOs are outputs to control MDIO bus muxing */ | 335 | /* The first 4 GPIOs are outputs to control MDIO bus muxing */ |
334 | out_be32(&pgpio->gpdir, EMI_MASK); | 336 | out_be32(&pgpio->gpdir, EMI_MASK); |
335 | 337 | ||
336 | dtsec_mdio_info.regs = | 338 | dtsec_mdio_info.regs = |
337 | (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR; | 339 | (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR; |
338 | dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME; | 340 | dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME; |
339 | 341 | ||
340 | /* Register the 1G MDIO bus */ | 342 | /* Register the 1G MDIO bus */ |
341 | fsl_pq_mdio_init(bis, &dtsec_mdio_info); | 343 | fsl_pq_mdio_init(bis, &dtsec_mdio_info); |
342 | 344 | ||
343 | tgec_mdio_info.regs = | 345 | tgec_mdio_info.regs = |
344 | (struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR; | 346 | (struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR; |
345 | tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME; | 347 | tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME; |
346 | 348 | ||
347 | /* Register the 10G MDIO bus */ | 349 | /* Register the 10G MDIO bus */ |
348 | fm_tgec_mdio_init(bis, &tgec_mdio_info); | 350 | fm_tgec_mdio_init(bis, &tgec_mdio_info); |
349 | 351 | ||
350 | /* Register the 6 muxing front-ends to the MDIO buses */ | 352 | /* Register the 6 muxing front-ends to the MDIO buses */ |
351 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII); | 353 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII); |
352 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT3); | 354 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT3); |
353 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4); | 355 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4); |
354 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT5); | 356 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT5); |
355 | p4080ds_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, EMI2_SLOT4); | 357 | p4080ds_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, EMI2_SLOT4); |
356 | p4080ds_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, EMI2_SLOT5); | 358 | p4080ds_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, EMI2_SLOT5); |
357 | 359 | ||
358 | fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR); | 360 | fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR); |
359 | fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR); | 361 | fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR); |
360 | fm_info_set_phy_address(FM1_DTSEC3, CONFIG_SYS_FM1_DTSEC3_PHY_ADDR); | 362 | fm_info_set_phy_address(FM1_DTSEC3, CONFIG_SYS_FM1_DTSEC3_PHY_ADDR); |
361 | fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR); | 363 | fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR); |
362 | fm_info_set_phy_address(FM1_10GEC1, CONFIG_SYS_FM1_10GEC1_PHY_ADDR); | 364 | fm_info_set_phy_address(FM1_10GEC1, CONFIG_SYS_FM1_10GEC1_PHY_ADDR); |
363 | 365 | ||
364 | #if (CONFIG_SYS_NUM_FMAN == 2) | 366 | #if (CONFIG_SYS_NUM_FMAN == 2) |
365 | fm_info_set_phy_address(FM2_DTSEC1, CONFIG_SYS_FM2_DTSEC1_PHY_ADDR); | 367 | fm_info_set_phy_address(FM2_DTSEC1, CONFIG_SYS_FM2_DTSEC1_PHY_ADDR); |
366 | fm_info_set_phy_address(FM2_DTSEC2, CONFIG_SYS_FM2_DTSEC2_PHY_ADDR); | 368 | fm_info_set_phy_address(FM2_DTSEC2, CONFIG_SYS_FM2_DTSEC2_PHY_ADDR); |
367 | fm_info_set_phy_address(FM2_DTSEC3, CONFIG_SYS_FM2_DTSEC3_PHY_ADDR); | 369 | fm_info_set_phy_address(FM2_DTSEC3, CONFIG_SYS_FM2_DTSEC3_PHY_ADDR); |
368 | fm_info_set_phy_address(FM2_DTSEC4, CONFIG_SYS_FM2_DTSEC4_PHY_ADDR); | 370 | fm_info_set_phy_address(FM2_DTSEC4, CONFIG_SYS_FM2_DTSEC4_PHY_ADDR); |
369 | fm_info_set_phy_address(FM2_10GEC1, CONFIG_SYS_FM2_10GEC1_PHY_ADDR); | 371 | fm_info_set_phy_address(FM2_10GEC1, CONFIG_SYS_FM2_10GEC1_PHY_ADDR); |
370 | #endif | 372 | #endif |
371 | 373 | ||
372 | for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { | 374 | for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { |
373 | int idx = i - FM1_DTSEC1, lane, slot; | 375 | int idx = i - FM1_DTSEC1, lane, slot; |
374 | switch (fm_info_get_enet_if(i)) { | 376 | switch (fm_info_get_enet_if(i)) { |
375 | case PHY_INTERFACE_MODE_SGMII: | 377 | case PHY_INTERFACE_MODE_SGMII: |
376 | lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx); | 378 | lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx); |
377 | if (lane < 0) | 379 | if (lane < 0) |
378 | break; | 380 | break; |
379 | slot = lane_to_slot[lane]; | 381 | slot = lane_to_slot[lane]; |
380 | switch (slot) { | 382 | switch (slot) { |
381 | case SLOT3: | 383 | case SLOT3: |
382 | mdio_mux[i] = EMI1_SLOT3; | 384 | mdio_mux[i] = EMI1_SLOT3; |
383 | fm_info_set_mdio(i, | 385 | fm_info_set_mdio(i, |
384 | mii_dev_for_muxval(mdio_mux[i])); | 386 | mii_dev_for_muxval(mdio_mux[i])); |
385 | break; | 387 | break; |
386 | case SLOT4: | 388 | case SLOT4: |
387 | mdio_mux[i] = EMI1_SLOT4; | 389 | mdio_mux[i] = EMI1_SLOT4; |
388 | fm_info_set_mdio(i, | 390 | fm_info_set_mdio(i, |
389 | mii_dev_for_muxval(mdio_mux[i])); | 391 | mii_dev_for_muxval(mdio_mux[i])); |
390 | break; | 392 | break; |
391 | case SLOT5: | 393 | case SLOT5: |
392 | mdio_mux[i] = EMI1_SLOT5; | 394 | mdio_mux[i] = EMI1_SLOT5; |
393 | fm_info_set_mdio(i, | 395 | fm_info_set_mdio(i, |
394 | mii_dev_for_muxval(mdio_mux[i])); | 396 | mii_dev_for_muxval(mdio_mux[i])); |
395 | break; | 397 | break; |
396 | }; | 398 | }; |
397 | break; | 399 | break; |
398 | case PHY_INTERFACE_MODE_RGMII: | 400 | case PHY_INTERFACE_MODE_RGMII: |
399 | fm_info_set_phy_address(i, 0); | 401 | fm_info_set_phy_address(i, 0); |
400 | mdio_mux[i] = EMI1_RGMII; | 402 | mdio_mux[i] = EMI1_RGMII; |
401 | fm_info_set_mdio(i, | 403 | fm_info_set_mdio(i, |
402 | mii_dev_for_muxval(mdio_mux[i])); | 404 | mii_dev_for_muxval(mdio_mux[i])); |
403 | break; | 405 | break; |
404 | default: | 406 | default: |
405 | break; | 407 | break; |
406 | } | 408 | } |
407 | } | 409 | } |
408 | 410 | ||
409 | for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) { | 411 | for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) { |
410 | int idx = i - FM1_10GEC1, lane, slot; | 412 | int idx = i - FM1_10GEC1, lane, slot; |
411 | switch (fm_info_get_enet_if(i)) { | 413 | switch (fm_info_get_enet_if(i)) { |
412 | case PHY_INTERFACE_MODE_XGMII: | 414 | case PHY_INTERFACE_MODE_XGMII: |
413 | lane = serdes_get_first_lane(XAUI_FM1 + idx); | 415 | lane = serdes_get_first_lane(XAUI_FM1 + idx); |
414 | if (lane < 0) | 416 | if (lane < 0) |
415 | break; | 417 | break; |
416 | slot = lane_to_slot[lane]; | 418 | slot = lane_to_slot[lane]; |
417 | switch (slot) { | 419 | switch (slot) { |
418 | case SLOT4: | 420 | case SLOT4: |
419 | mdio_mux[i] = EMI2_SLOT4; | 421 | mdio_mux[i] = EMI2_SLOT4; |
420 | fm_info_set_mdio(i, | 422 | fm_info_set_mdio(i, |
421 | mii_dev_for_muxval(mdio_mux[i])); | 423 | mii_dev_for_muxval(mdio_mux[i])); |
422 | break; | 424 | break; |
423 | case SLOT5: | 425 | case SLOT5: |
424 | mdio_mux[i] = EMI2_SLOT5; | 426 | mdio_mux[i] = EMI2_SLOT5; |
425 | fm_info_set_mdio(i, | 427 | fm_info_set_mdio(i, |
426 | mii_dev_for_muxval(mdio_mux[i])); | 428 | mii_dev_for_muxval(mdio_mux[i])); |
427 | break; | 429 | break; |
428 | }; | 430 | }; |
429 | break; | 431 | break; |
430 | default: | 432 | default: |
431 | break; | 433 | break; |
432 | } | 434 | } |
433 | } | 435 | } |
434 | 436 | ||
435 | #if (CONFIG_SYS_NUM_FMAN == 2) | 437 | #if (CONFIG_SYS_NUM_FMAN == 2) |
436 | for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) { | 438 | for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) { |
437 | int idx = i - FM2_DTSEC1, lane, slot; | 439 | int idx = i - FM2_DTSEC1, lane, slot; |
438 | switch (fm_info_get_enet_if(i)) { | 440 | switch (fm_info_get_enet_if(i)) { |
439 | case PHY_INTERFACE_MODE_SGMII: | 441 | case PHY_INTERFACE_MODE_SGMII: |
440 | lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx); | 442 | lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx); |
441 | if (lane < 0) | 443 | if (lane < 0) |
442 | break; | 444 | break; |
443 | slot = lane_to_slot[lane]; | 445 | slot = lane_to_slot[lane]; |
444 | switch (slot) { | 446 | switch (slot) { |
445 | case SLOT3: | 447 | case SLOT3: |
446 | mdio_mux[i] = EMI1_SLOT3; | 448 | mdio_mux[i] = EMI1_SLOT3; |
447 | fm_info_set_mdio(i, | 449 | fm_info_set_mdio(i, |
448 | mii_dev_for_muxval(mdio_mux[i])); | 450 | mii_dev_for_muxval(mdio_mux[i])); |
449 | break; | 451 | break; |
450 | case SLOT4: | 452 | case SLOT4: |
451 | mdio_mux[i] = EMI1_SLOT4; | 453 | mdio_mux[i] = EMI1_SLOT4; |
452 | fm_info_set_mdio(i, | 454 | fm_info_set_mdio(i, |
453 | mii_dev_for_muxval(mdio_mux[i])); | 455 | mii_dev_for_muxval(mdio_mux[i])); |
454 | break; | 456 | break; |
455 | case SLOT5: | 457 | case SLOT5: |
456 | mdio_mux[i] = EMI1_SLOT5; | 458 | mdio_mux[i] = EMI1_SLOT5; |
457 | fm_info_set_mdio(i, | 459 | fm_info_set_mdio(i, |
458 | mii_dev_for_muxval(mdio_mux[i])); | 460 | mii_dev_for_muxval(mdio_mux[i])); |
459 | break; | 461 | break; |
460 | }; | 462 | }; |
461 | break; | 463 | break; |
462 | case PHY_INTERFACE_MODE_RGMII: | 464 | case PHY_INTERFACE_MODE_RGMII: |
463 | fm_info_set_phy_address(i, 0); | 465 | fm_info_set_phy_address(i, 0); |
464 | mdio_mux[i] = EMI1_RGMII; | 466 | mdio_mux[i] = EMI1_RGMII; |
465 | fm_info_set_mdio(i, | 467 | fm_info_set_mdio(i, |
466 | mii_dev_for_muxval(mdio_mux[i])); | 468 | mii_dev_for_muxval(mdio_mux[i])); |
467 | break; | 469 | break; |
468 | default: | 470 | default: |
469 | break; | 471 | break; |
470 | } | 472 | } |
471 | } | 473 | } |
472 | 474 | ||
473 | for (i = FM2_10GEC1; i < FM2_10GEC1 + CONFIG_SYS_NUM_FM2_10GEC; i++) { | 475 | for (i = FM2_10GEC1; i < FM2_10GEC1 + CONFIG_SYS_NUM_FM2_10GEC; i++) { |
474 | int idx = i - FM2_10GEC1, lane, slot; | 476 | int idx = i - FM2_10GEC1, lane, slot; |
475 | switch (fm_info_get_enet_if(i)) { | 477 | switch (fm_info_get_enet_if(i)) { |
476 | case PHY_INTERFACE_MODE_XGMII: | 478 | case PHY_INTERFACE_MODE_XGMII: |
477 | lane = serdes_get_first_lane(XAUI_FM2 + idx); | 479 | lane = serdes_get_first_lane(XAUI_FM2 + idx); |
478 | if (lane < 0) | 480 | if (lane < 0) |
479 | break; | 481 | break; |
480 | slot = lane_to_slot[lane]; | 482 | slot = lane_to_slot[lane]; |
481 | switch (slot) { | 483 | switch (slot) { |
482 | case SLOT4: | 484 | case SLOT4: |
483 | mdio_mux[i] = EMI2_SLOT4; | 485 | mdio_mux[i] = EMI2_SLOT4; |
484 | fm_info_set_mdio(i, | 486 | fm_info_set_mdio(i, |
485 | mii_dev_for_muxval(mdio_mux[i])); | 487 | mii_dev_for_muxval(mdio_mux[i])); |
486 | break; | 488 | break; |
487 | case SLOT5: | 489 | case SLOT5: |
488 | mdio_mux[i] = EMI2_SLOT5; | 490 | mdio_mux[i] = EMI2_SLOT5; |
489 | fm_info_set_mdio(i, | 491 | fm_info_set_mdio(i, |
490 | mii_dev_for_muxval(mdio_mux[i])); | 492 | mii_dev_for_muxval(mdio_mux[i])); |
491 | break; | 493 | break; |
492 | }; | 494 | }; |
493 | break; | 495 | break; |
494 | default: | 496 | default: |
495 | break; | 497 | break; |
496 | } | 498 | } |
497 | } | 499 | } |
498 | #endif | 500 | #endif |
499 | 501 | ||
500 | cpu_eth_init(bis); | 502 | cpu_eth_init(bis); |
501 | #endif /* CONFIG_FMAN_ENET */ | 503 | #endif /* CONFIG_FMAN_ENET */ |
502 | 504 | ||
503 | return pci_eth_init(bis); | 505 | return pci_eth_init(bis); |
504 | } | 506 | } |
505 | 507 |
board/freescale/mpc8544ds/mpc8544ds.c
1 | /* | 1 | /* |
2 | * Copyright 2007,2009-2010 Freescale Semiconductor, Inc. | 2 | * Copyright 2007,2009-2010 Freescale Semiconductor, Inc. |
3 | * | 3 | * |
4 | * See file CREDITS for list of people who contributed to this | 4 | * See file CREDITS for list of people who contributed to this |
5 | * project. | 5 | * project. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as | 8 | * modify it under the terms of the GNU General Public License as |
9 | * published by the Free Software Foundation; either version 2 of | 9 | * published by the Free Software Foundation; either version 2 of |
10 | * the License, or (at your option) any later version. | 10 | * the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
20 | * MA 02111-1307 USA | 20 | * MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <common.h> | 23 | #include <common.h> |
24 | #include <command.h> | 24 | #include <command.h> |
25 | #include <pci.h> | 25 | #include <pci.h> |
26 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
27 | #include <asm/mmu.h> | 27 | #include <asm/mmu.h> |
28 | #include <asm/immap_85xx.h> | 28 | #include <asm/immap_85xx.h> |
29 | #include <asm/fsl_pci.h> | 29 | #include <asm/fsl_pci.h> |
30 | #include <asm/fsl_ddr_sdram.h> | 30 | #include <asm/fsl_ddr_sdram.h> |
31 | #include <asm/fsl_serdes.h> | 31 | #include <asm/fsl_serdes.h> |
32 | #include <asm/io.h> | 32 | #include <asm/io.h> |
33 | #include <miiphy.h> | 33 | #include <miiphy.h> |
34 | #include <libfdt.h> | 34 | #include <libfdt.h> |
35 | #include <fdt_support.h> | 35 | #include <fdt_support.h> |
36 | #include <fsl_mdio.h> | 36 | #include <fsl_mdio.h> |
37 | #include <tsec.h> | 37 | #include <tsec.h> |
38 | #include <netdev.h> | 38 | #include <netdev.h> |
39 | 39 | ||
40 | #include "../common/sgmii_riser.h" | 40 | #include "../common/sgmii_riser.h" |
41 | 41 | ||
42 | int checkboard (void) | 42 | int checkboard (void) |
43 | { | 43 | { |
44 | volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | 44 | volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); |
45 | volatile fsl_lbc_t *lbc = LBC_BASE_ADDR; | 45 | volatile fsl_lbc_t *lbc = LBC_BASE_ADDR; |
46 | volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR); | 46 | volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR); |
47 | u8 vboot; | 47 | u8 vboot; |
48 | u8 *pixis_base = (u8 *)PIXIS_BASE; | 48 | u8 *pixis_base = (u8 *)PIXIS_BASE; |
49 | 49 | ||
50 | if ((uint)&gur->porpllsr != 0xe00e0000) { | 50 | if ((uint)&gur->porpllsr != 0xe00e0000) { |
51 | printf("immap size error %lx\n",(ulong)&gur->porpllsr); | 51 | printf("immap size error %lx\n",(ulong)&gur->porpllsr); |
52 | } | 52 | } |
53 | printf ("Board: MPC8544DS, Sys ID: 0x%02x, " | 53 | printf ("Board: MPC8544DS, Sys ID: 0x%02x, " |
54 | "Sys Ver: 0x%02x, FPGA Ver: 0x%02x, ", | 54 | "Sys Ver: 0x%02x, FPGA Ver: 0x%02x, ", |
55 | in_8(pixis_base + PIXIS_ID), in_8(pixis_base + PIXIS_VER), | 55 | in_8(pixis_base + PIXIS_ID), in_8(pixis_base + PIXIS_VER), |
56 | in_8(pixis_base + PIXIS_PVER)); | 56 | in_8(pixis_base + PIXIS_PVER)); |
57 | 57 | ||
58 | vboot = in_8(pixis_base + PIXIS_VBOOT); | 58 | vboot = in_8(pixis_base + PIXIS_VBOOT); |
59 | if (vboot & PIXIS_VBOOT_FMAP) | 59 | if (vboot & PIXIS_VBOOT_FMAP) |
60 | printf ("vBank: %d\n", ((vboot & PIXIS_VBOOT_FBANK) >> 6)); | 60 | printf ("vBank: %d\n", ((vboot & PIXIS_VBOOT_FBANK) >> 6)); |
61 | else | 61 | else |
62 | puts ("Promjet\n"); | 62 | puts ("Promjet\n"); |
63 | 63 | ||
64 | lbc->ltesr = 0xffffffff; /* Clear LBC error interrupts */ | 64 | lbc->ltesr = 0xffffffff; /* Clear LBC error interrupts */ |
65 | lbc->lteir = 0xffffffff; /* Enable LBC error interrupts */ | 65 | lbc->lteir = 0xffffffff; /* Enable LBC error interrupts */ |
66 | ecm->eedr = 0xffffffff; /* Clear ecm errors */ | 66 | ecm->eedr = 0xffffffff; /* Clear ecm errors */ |
67 | ecm->eeer = 0xffffffff; /* Enable ecm errors */ | 67 | ecm->eeer = 0xffffffff; /* Enable ecm errors */ |
68 | 68 | ||
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | 71 | ||
72 | #ifdef CONFIG_PCI1 | 72 | #ifdef CONFIG_PCI1 |
73 | static struct pci_controller pci1_hose; | 73 | static struct pci_controller pci1_hose; |
74 | #endif | 74 | #endif |
75 | 75 | ||
76 | #ifdef CONFIG_PCIE3 | 76 | #ifdef CONFIG_PCIE3 |
77 | static struct pci_controller pcie3_hose; | 77 | static struct pci_controller pcie3_hose; |
78 | #endif | 78 | #endif |
79 | 79 | ||
80 | void pci_init_board(void) | 80 | void pci_init_board(void) |
81 | { | 81 | { |
82 | volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | 82 | volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); |
83 | struct fsl_pci_info pci_info; | 83 | struct fsl_pci_info pci_info; |
84 | u32 devdisr, pordevsr, io_sel; | 84 | u32 devdisr, pordevsr, io_sel; |
85 | u32 porpllsr, pci_agent, pci_speed, pci_32, pci_arb, pci_clk_sel; | 85 | u32 porpllsr, pci_agent, pci_speed, pci_32, pci_arb, pci_clk_sel; |
86 | int first_free_busno = 0; | 86 | int first_free_busno = 0; |
87 | 87 | ||
88 | int pcie_ep, pcie_configured; | 88 | int pcie_ep, pcie_configured; |
89 | 89 | ||
90 | devdisr = in_be32(&gur->devdisr); | 90 | devdisr = in_be32(&gur->devdisr); |
91 | pordevsr = in_be32(&gur->pordevsr); | 91 | pordevsr = in_be32(&gur->pordevsr); |
92 | porpllsr = in_be32(&gur->porpllsr); | 92 | porpllsr = in_be32(&gur->porpllsr); |
93 | io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> 19; | 93 | io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> 19; |
94 | 94 | ||
95 | debug (" pci_init_board: devdisr=%x, io_sel=%x\n", devdisr, io_sel); | 95 | debug (" pci_init_board: devdisr=%x, io_sel=%x\n", devdisr, io_sel); |
96 | 96 | ||
97 | puts("\n"); | 97 | puts("\n"); |
98 | 98 | ||
99 | #ifdef CONFIG_PCIE3 | 99 | #ifdef CONFIG_PCIE3 |
100 | pcie_configured = is_serdes_configured(PCIE3); | 100 | pcie_configured = is_serdes_configured(PCIE3); |
101 | 101 | ||
102 | if (pcie_configured && !(devdisr & MPC85xx_DEVDISR_PCIE3)){ | 102 | if (pcie_configured && !(devdisr & MPC85xx_DEVDISR_PCIE3)){ |
103 | /* contains both PCIE3 MEM & IO space */ | 103 | /* contains both PCIE3 MEM & IO space */ |
104 | set_next_law(CONFIG_SYS_PCIE3_MEM_PHYS, LAW_SIZE_4M, | 104 | set_next_law(CONFIG_SYS_PCIE3_MEM_PHYS, LAW_SIZE_4M, |
105 | LAW_TRGT_IF_PCIE_3); | 105 | LAW_TRGT_IF_PCIE_3); |
106 | SET_STD_PCIE_INFO(pci_info, 3); | 106 | SET_STD_PCIE_INFO(pci_info, 3); |
107 | pcie_ep = fsl_setup_hose(&pcie3_hose, pci_info.regs); | 107 | pcie_ep = fsl_setup_hose(&pcie3_hose, pci_info.regs); |
108 | 108 | ||
109 | /* outbound memory */ | 109 | /* outbound memory */ |
110 | pci_set_region(&pcie3_hose.regions[0], | 110 | pci_set_region(&pcie3_hose.regions[0], |
111 | CONFIG_SYS_PCIE3_MEM_BUS2, | 111 | CONFIG_SYS_PCIE3_MEM_BUS2, |
112 | CONFIG_SYS_PCIE3_MEM_PHYS2, | 112 | CONFIG_SYS_PCIE3_MEM_PHYS2, |
113 | CONFIG_SYS_PCIE3_MEM_SIZE2, | 113 | CONFIG_SYS_PCIE3_MEM_SIZE2, |
114 | PCI_REGION_MEM); | 114 | PCI_REGION_MEM); |
115 | 115 | ||
116 | pcie3_hose.region_count = 1; | 116 | pcie3_hose.region_count = 1; |
117 | 117 | ||
118 | printf("PCIE3: connected to ULI as %s (base addr %lx)\n", | 118 | printf("PCIE3: connected to ULI as %s (base addr %lx)\n", |
119 | pcie_ep ? "Endpoint" : "Root Complex", | 119 | pcie_ep ? "Endpoint" : "Root Complex", |
120 | pci_info.regs); | 120 | pci_info.regs); |
121 | first_free_busno = fsl_pci_init_port(&pci_info, | 121 | first_free_busno = fsl_pci_init_port(&pci_info, |
122 | &pcie3_hose, first_free_busno); | 122 | &pcie3_hose, first_free_busno); |
123 | 123 | ||
124 | /* | 124 | /* |
125 | * Activate ULI1575 legacy chip by performing a fake | 125 | * Activate ULI1575 legacy chip by performing a fake |
126 | * memory access. Needed to make ULI RTC work. | 126 | * memory access. Needed to make ULI RTC work. |
127 | */ | 127 | */ |
128 | in_be32((u32 *)CONFIG_SYS_PCIE3_MEM_BUS); | 128 | in_be32((u32 *)CONFIG_SYS_PCIE3_MEM_BUS); |
129 | } else { | 129 | } else { |
130 | printf("PCIE3: disabled\n"); | 130 | printf("PCIE3: disabled\n"); |
131 | } | 131 | } |
132 | puts("\n"); | 132 | puts("\n"); |
133 | #else | 133 | #else |
134 | setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE3); /* disable */ | 134 | setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE3); /* disable */ |
135 | #endif | 135 | #endif |
136 | 136 | ||
137 | #ifdef CONFIG_PCIE1 | 137 | #ifdef CONFIG_PCIE1 |
138 | SET_STD_PCIE_INFO(pci_info, 1); | 138 | SET_STD_PCIE_INFO(pci_info, 1); |
139 | first_free_busno = fsl_pcie_init_ctrl(first_free_busno, devdisr, PCIE1, &pci_info); | 139 | first_free_busno = fsl_pcie_init_ctrl(first_free_busno, devdisr, PCIE1, &pci_info); |
140 | #else | 140 | #else |
141 | setbits_be32(&gur->devdisr, _DEVDISR_PCIE1); /* disable */ | 141 | setbits_be32(&gur->devdisr, _DEVDISR_PCIE1); /* disable */ |
142 | #endif | 142 | #endif |
143 | 143 | ||
144 | #ifdef CONFIG_PCIE2 | 144 | #ifdef CONFIG_PCIE2 |
145 | SET_STD_PCIE_INFO(pci_info, 2); | 145 | SET_STD_PCIE_INFO(pci_info, 2); |
146 | first_free_busno = fsl_pcie_init_ctrl(first_free_busno, devdisr, PCIE2, &pci_info); | 146 | first_free_busno = fsl_pcie_init_ctrl(first_free_busno, devdisr, PCIE2, &pci_info); |
147 | #else | 147 | #else |
148 | setbits_be32(&gur->devdisr, _DEVDISR_PCIE2); /* disable */ | 148 | setbits_be32(&gur->devdisr, _DEVDISR_PCIE2); /* disable */ |
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | #ifdef CONFIG_PCI1 | 151 | #ifdef CONFIG_PCI1 |
152 | pci_speed = 66666000; | 152 | pci_speed = 66666000; |
153 | pci_32 = 1; | 153 | pci_32 = 1; |
154 | pci_arb = pordevsr & MPC85xx_PORDEVSR_PCI1_ARB; | 154 | pci_arb = pordevsr & MPC85xx_PORDEVSR_PCI1_ARB; |
155 | pci_clk_sel = porpllsr & MPC85xx_PORDEVSR_PCI1_SPD; | 155 | pci_clk_sel = porpllsr & MPC85xx_PORDEVSR_PCI1_SPD; |
156 | 156 | ||
157 | if (!(devdisr & MPC85xx_DEVDISR_PCI1)) { | 157 | if (!(devdisr & MPC85xx_DEVDISR_PCI1)) { |
158 | SET_STD_PCI_INFO(pci_info, 1); | 158 | SET_STD_PCI_INFO(pci_info, 1); |
159 | set_next_law(pci_info.mem_phys, | 159 | set_next_law(pci_info.mem_phys, |
160 | law_size_bits(pci_info.mem_size), pci_info.law); | 160 | law_size_bits(pci_info.mem_size), pci_info.law); |
161 | set_next_law(pci_info.io_phys, | 161 | set_next_law(pci_info.io_phys, |
162 | law_size_bits(pci_info.io_size), pci_info.law); | 162 | law_size_bits(pci_info.io_size), pci_info.law); |
163 | 163 | ||
164 | pci_agent = fsl_setup_hose(&pci1_hose, pci_info.regs); | 164 | pci_agent = fsl_setup_hose(&pci1_hose, pci_info.regs); |
165 | printf("PCI: %d bit, %s MHz, %s, %s, %s (base address %lx)\n", | 165 | printf("PCI: %d bit, %s MHz, %s, %s, %s (base address %lx)\n", |
166 | (pci_32) ? 32 : 64, | 166 | (pci_32) ? 32 : 64, |
167 | (pci_speed == 33333000) ? "33" : | 167 | (pci_speed == 33333000) ? "33" : |
168 | (pci_speed == 66666000) ? "66" : "unknown", | 168 | (pci_speed == 66666000) ? "66" : "unknown", |
169 | pci_clk_sel ? "sync" : "async", | 169 | pci_clk_sel ? "sync" : "async", |
170 | pci_agent ? "agent" : "host", | 170 | pci_agent ? "agent" : "host", |
171 | pci_arb ? "arbiter" : "external-arbiter", | 171 | pci_arb ? "arbiter" : "external-arbiter", |
172 | pci_info.regs); | 172 | pci_info.regs); |
173 | 173 | ||
174 | first_free_busno = fsl_pci_init_port(&pci_info, | 174 | first_free_busno = fsl_pci_init_port(&pci_info, |
175 | &pci1_hose, first_free_busno); | 175 | &pci1_hose, first_free_busno); |
176 | } else { | 176 | } else { |
177 | printf("PCI: disabled\n"); | 177 | printf("PCI: disabled\n"); |
178 | } | 178 | } |
179 | 179 | ||
180 | puts("\n"); | 180 | puts("\n"); |
181 | #else | 181 | #else |
182 | setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCI1); /* disable */ | 182 | setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCI1); /* disable */ |
183 | #endif | 183 | #endif |
184 | } | 184 | } |
185 | 185 | ||
186 | int last_stage_init(void) | 186 | int last_stage_init(void) |
187 | { | 187 | { |
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | 191 | ||
192 | unsigned long | 192 | unsigned long |
193 | get_board_sys_clk(ulong dummy) | 193 | get_board_sys_clk(ulong dummy) |
194 | { | 194 | { |
195 | u8 i, go_bit, rd_clks; | 195 | u8 i, go_bit, rd_clks; |
196 | ulong val = 0; | 196 | ulong val = 0; |
197 | u8 *pixis_base = (u8 *)PIXIS_BASE; | 197 | u8 *pixis_base = (u8 *)PIXIS_BASE; |
198 | 198 | ||
199 | go_bit = in_8(pixis_base + PIXIS_VCTL); | 199 | go_bit = in_8(pixis_base + PIXIS_VCTL); |
200 | go_bit &= 0x01; | 200 | go_bit &= 0x01; |
201 | 201 | ||
202 | rd_clks = in_8(pixis_base + PIXIS_VCFGEN0); | 202 | rd_clks = in_8(pixis_base + PIXIS_VCFGEN0); |
203 | rd_clks &= 0x1C; | 203 | rd_clks &= 0x1C; |
204 | 204 | ||
205 | /* | 205 | /* |
206 | * Only if both go bit and the SCLK bit in VCFGEN0 are set | 206 | * Only if both go bit and the SCLK bit in VCFGEN0 are set |
207 | * should we be using the AUX register. Remember, we also set the | 207 | * should we be using the AUX register. Remember, we also set the |
208 | * GO bit to boot from the alternate bank on the on-board flash | 208 | * GO bit to boot from the alternate bank on the on-board flash |
209 | */ | 209 | */ |
210 | 210 | ||
211 | if (go_bit) { | 211 | if (go_bit) { |
212 | if (rd_clks == 0x1c) | 212 | if (rd_clks == 0x1c) |
213 | i = in_8(pixis_base + PIXIS_AUX); | 213 | i = in_8(pixis_base + PIXIS_AUX); |
214 | else | 214 | else |
215 | i = in_8(pixis_base + PIXIS_SPD); | 215 | i = in_8(pixis_base + PIXIS_SPD); |
216 | } else { | 216 | } else { |
217 | i = in_8(pixis_base + PIXIS_SPD); | 217 | i = in_8(pixis_base + PIXIS_SPD); |
218 | } | 218 | } |
219 | 219 | ||
220 | i &= 0x07; | 220 | i &= 0x07; |
221 | 221 | ||
222 | switch (i) { | 222 | switch (i) { |
223 | case 0: | 223 | case 0: |
224 | val = 33333333; | 224 | val = 33333333; |
225 | break; | 225 | break; |
226 | case 1: | 226 | case 1: |
227 | val = 40000000; | 227 | val = 40000000; |
228 | break; | 228 | break; |
229 | case 2: | 229 | case 2: |
230 | val = 50000000; | 230 | val = 50000000; |
231 | break; | 231 | break; |
232 | case 3: | 232 | case 3: |
233 | val = 66666666; | 233 | val = 66666666; |
234 | break; | 234 | break; |
235 | case 4: | 235 | case 4: |
236 | val = 83000000; | 236 | val = 83000000; |
237 | break; | 237 | break; |
238 | case 5: | 238 | case 5: |
239 | val = 100000000; | 239 | val = 100000000; |
240 | break; | 240 | break; |
241 | case 6: | 241 | case 6: |
242 | val = 133333333; | 242 | val = 133333333; |
243 | break; | 243 | break; |
244 | case 7: | 244 | case 7: |
245 | val = 166666666; | 245 | val = 166666666; |
246 | break; | 246 | break; |
247 | } | 247 | } |
248 | 248 | ||
249 | return val; | 249 | return val; |
250 | } | 250 | } |
251 | 251 | ||
252 | 252 | ||
253 | #define MIIM_CIS8204_SLED_CON 0x1b | 253 | #define MIIM_CIS8204_SLED_CON 0x1b |
254 | #define MIIM_CIS8204_SLEDCON_INIT 0x1115 | 254 | #define MIIM_CIS8204_SLEDCON_INIT 0x1115 |
255 | /* | 255 | /* |
256 | * Hack to write all 4 PHYs with the LED values | 256 | * Hack to write all 4 PHYs with the LED values |
257 | */ | 257 | */ |
258 | int board_phy_config(struct phy_device *phydev) | 258 | int board_phy_config(struct phy_device *phydev) |
259 | { | 259 | { |
260 | static int do_once; | 260 | static int do_once; |
261 | uint phyid; | 261 | uint phyid; |
262 | struct mii_dev *bus = phydev->bus; | 262 | struct mii_dev *bus = phydev->bus; |
263 | 263 | ||
264 | if (phydev->drv->config) | ||
265 | phydev->drv->config(phydev); | ||
264 | if (do_once) | 266 | if (do_once) |
265 | return 0; | 267 | return 0; |
266 | 268 | ||
267 | for (phyid = 0; phyid < 4; phyid++) | 269 | for (phyid = 0; phyid < 4; phyid++) |
268 | bus->write(bus, phyid, MDIO_DEVAD_NONE, MIIM_CIS8204_SLED_CON, | 270 | bus->write(bus, phyid, MDIO_DEVAD_NONE, MIIM_CIS8204_SLED_CON, |
269 | MIIM_CIS8204_SLEDCON_INIT); | 271 | MIIM_CIS8204_SLEDCON_INIT); |
270 | 272 | ||
271 | do_once = 1; | 273 | do_once = 1; |
272 | 274 | ||
273 | return 0; | 275 | return 0; |
274 | } | 276 | } |
275 | 277 | ||
276 | 278 | ||
277 | int board_eth_init(bd_t *bis) | 279 | int board_eth_init(bd_t *bis) |
278 | { | 280 | { |
279 | #ifdef CONFIG_TSEC_ENET | 281 | #ifdef CONFIG_TSEC_ENET |
280 | struct fsl_pq_mdio_info mdio_info; | 282 | struct fsl_pq_mdio_info mdio_info; |
281 | struct tsec_info_struct tsec_info[2]; | 283 | struct tsec_info_struct tsec_info[2]; |
282 | int num = 0; | 284 | int num = 0; |
283 | 285 | ||
284 | #ifdef CONFIG_TSEC1 | 286 | #ifdef CONFIG_TSEC1 |
285 | SET_STD_TSEC_INFO(tsec_info[num], 1); | 287 | SET_STD_TSEC_INFO(tsec_info[num], 1); |
286 | if (is_serdes_configured(SGMII_TSEC1)) { | 288 | if (is_serdes_configured(SGMII_TSEC1)) { |
287 | puts("eTSEC1 is in sgmii mode.\n"); | 289 | puts("eTSEC1 is in sgmii mode.\n"); |
288 | tsec_info[num].flags |= TSEC_SGMII; | 290 | tsec_info[num].flags |= TSEC_SGMII; |
289 | } | 291 | } |
290 | num++; | 292 | num++; |
291 | #endif | 293 | #endif |
292 | #ifdef CONFIG_TSEC3 | 294 | #ifdef CONFIG_TSEC3 |
293 | SET_STD_TSEC_INFO(tsec_info[num], 3); | 295 | SET_STD_TSEC_INFO(tsec_info[num], 3); |
294 | if (is_serdes_configured(SGMII_TSEC3)) { | 296 | if (is_serdes_configured(SGMII_TSEC3)) { |
295 | puts("eTSEC3 is in sgmii mode.\n"); | 297 | puts("eTSEC3 is in sgmii mode.\n"); |
296 | tsec_info[num].flags |= TSEC_SGMII; | 298 | tsec_info[num].flags |= TSEC_SGMII; |
297 | } | 299 | } |
298 | num++; | 300 | num++; |
299 | #endif | 301 | #endif |
300 | 302 | ||
301 | if (!num) { | 303 | if (!num) { |
302 | printf("No TSECs initialized\n"); | 304 | printf("No TSECs initialized\n"); |
303 | 305 | ||
304 | return 0; | 306 | return 0; |
305 | } | 307 | } |
306 | 308 | ||
307 | if (is_serdes_configured(SGMII_TSEC1) || | 309 | if (is_serdes_configured(SGMII_TSEC1) || |
308 | is_serdes_configured(SGMII_TSEC3)) { | 310 | is_serdes_configured(SGMII_TSEC3)) { |
309 | fsl_sgmii_riser_init(tsec_info, num); | 311 | fsl_sgmii_riser_init(tsec_info, num); |
310 | } | 312 | } |
311 | 313 | ||
312 | mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR; | 314 | mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR; |
313 | mdio_info.name = DEFAULT_MII_NAME; | 315 | mdio_info.name = DEFAULT_MII_NAME; |
314 | fsl_pq_mdio_init(bis, &mdio_info); | 316 | fsl_pq_mdio_init(bis, &mdio_info); |
315 | 317 | ||
316 | tsec_eth_init(bis, tsec_info, num); | 318 | tsec_eth_init(bis, tsec_info, num); |
317 | #endif | 319 | #endif |
318 | return pci_eth_init(bis); | 320 | return pci_eth_init(bis); |
319 | } | 321 | } |
320 | 322 | ||
321 | #if defined(CONFIG_OF_BOARD_SETUP) | 323 | #if defined(CONFIG_OF_BOARD_SETUP) |
322 | void ft_board_setup(void *blob, bd_t *bd) | 324 | void ft_board_setup(void *blob, bd_t *bd) |
323 | { | 325 | { |
324 | ft_cpu_setup(blob, bd); | 326 | ft_cpu_setup(blob, bd); |
325 | 327 | ||
326 | FT_FSL_PCI_SETUP; | 328 | FT_FSL_PCI_SETUP; |
327 | 329 | ||
328 | #ifdef CONFIG_FSL_SGMII_RISER | 330 | #ifdef CONFIG_FSL_SGMII_RISER |
329 | fsl_sgmii_riser_fdt_fixup(blob); | 331 | fsl_sgmii_riser_fdt_fixup(blob); |
330 | #endif | 332 | #endif |
331 | } | 333 | } |
332 | #endif | 334 | #endif |
333 | 335 |
drivers/net/phy/phy.c
1 | /* | 1 | /* |
2 | * Generic PHY Management code | 2 | * Generic PHY Management code |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License as | 5 | * modify it under the terms of the GNU General Public License as |
6 | * published by the Free Software Foundation; either version 2 of | 6 | * published by the Free Software Foundation; either version 2 of |
7 | * the License, or (at your option) any later version. | 7 | * the License, or (at your option) any later version. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, | 9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
17 | * MA 02111-1307 USA | 17 | * MA 02111-1307 USA |
18 | * | 18 | * |
19 | * | 19 | * |
20 | * Copyright 2011 Freescale Semiconductor, Inc. | 20 | * Copyright 2011 Freescale Semiconductor, Inc. |
21 | * author Andy Fleming | 21 | * author Andy Fleming |
22 | * | 22 | * |
23 | * Based loosely off of Linux's PHY Lib | 23 | * Based loosely off of Linux's PHY Lib |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <config.h> | 26 | #include <config.h> |
27 | #include <common.h> | 27 | #include <common.h> |
28 | #include <malloc.h> | 28 | #include <malloc.h> |
29 | #include <net.h> | 29 | #include <net.h> |
30 | #include <command.h> | 30 | #include <command.h> |
31 | #include <miiphy.h> | 31 | #include <miiphy.h> |
32 | #include <phy.h> | 32 | #include <phy.h> |
33 | #include <errno.h> | 33 | #include <errno.h> |
34 | 34 | ||
35 | /* Generic PHY support and helper functions */ | 35 | /* Generic PHY support and helper functions */ |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * genphy_config_advert - sanitize and advertise auto-negotation parameters | 38 | * genphy_config_advert - sanitize and advertise auto-negotation parameters |
39 | * @phydev: target phy_device struct | 39 | * @phydev: target phy_device struct |
40 | * | 40 | * |
41 | * Description: Writes MII_ADVERTISE with the appropriate values, | 41 | * Description: Writes MII_ADVERTISE with the appropriate values, |
42 | * after sanitizing the values to make sure we only advertise | 42 | * after sanitizing the values to make sure we only advertise |
43 | * what is supported. Returns < 0 on error, 0 if the PHY's advertisement | 43 | * what is supported. Returns < 0 on error, 0 if the PHY's advertisement |
44 | * hasn't changed, and > 0 if it has changed. | 44 | * hasn't changed, and > 0 if it has changed. |
45 | */ | 45 | */ |
46 | int genphy_config_advert(struct phy_device *phydev) | 46 | int genphy_config_advert(struct phy_device *phydev) |
47 | { | 47 | { |
48 | u32 advertise; | 48 | u32 advertise; |
49 | int oldadv, adv; | 49 | int oldadv, adv; |
50 | int err, changed = 0; | 50 | int err, changed = 0; |
51 | 51 | ||
52 | /* Only allow advertising what | 52 | /* Only allow advertising what |
53 | * this PHY supports */ | 53 | * this PHY supports */ |
54 | phydev->advertising &= phydev->supported; | 54 | phydev->advertising &= phydev->supported; |
55 | advertise = phydev->advertising; | 55 | advertise = phydev->advertising; |
56 | 56 | ||
57 | /* Setup standard advertisement */ | 57 | /* Setup standard advertisement */ |
58 | oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE); | 58 | oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE); |
59 | 59 | ||
60 | if (adv < 0) | 60 | if (adv < 0) |
61 | return adv; | 61 | return adv; |
62 | 62 | ||
63 | adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | | 63 | adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | |
64 | ADVERTISE_PAUSE_ASYM); | 64 | ADVERTISE_PAUSE_ASYM); |
65 | if (advertise & ADVERTISED_10baseT_Half) | 65 | if (advertise & ADVERTISED_10baseT_Half) |
66 | adv |= ADVERTISE_10HALF; | 66 | adv |= ADVERTISE_10HALF; |
67 | if (advertise & ADVERTISED_10baseT_Full) | 67 | if (advertise & ADVERTISED_10baseT_Full) |
68 | adv |= ADVERTISE_10FULL; | 68 | adv |= ADVERTISE_10FULL; |
69 | if (advertise & ADVERTISED_100baseT_Half) | 69 | if (advertise & ADVERTISED_100baseT_Half) |
70 | adv |= ADVERTISE_100HALF; | 70 | adv |= ADVERTISE_100HALF; |
71 | if (advertise & ADVERTISED_100baseT_Full) | 71 | if (advertise & ADVERTISED_100baseT_Full) |
72 | adv |= ADVERTISE_100FULL; | 72 | adv |= ADVERTISE_100FULL; |
73 | if (advertise & ADVERTISED_Pause) | 73 | if (advertise & ADVERTISED_Pause) |
74 | adv |= ADVERTISE_PAUSE_CAP; | 74 | adv |= ADVERTISE_PAUSE_CAP; |
75 | if (advertise & ADVERTISED_Asym_Pause) | 75 | if (advertise & ADVERTISED_Asym_Pause) |
76 | adv |= ADVERTISE_PAUSE_ASYM; | 76 | adv |= ADVERTISE_PAUSE_ASYM; |
77 | 77 | ||
78 | if (adv != oldadv) { | 78 | if (adv != oldadv) { |
79 | err = phy_write(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE, adv); | 79 | err = phy_write(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE, adv); |
80 | 80 | ||
81 | if (err < 0) | 81 | if (err < 0) |
82 | return err; | 82 | return err; |
83 | changed = 1; | 83 | changed = 1; |
84 | } | 84 | } |
85 | 85 | ||
86 | /* Configure gigabit if it's supported */ | 86 | /* Configure gigabit if it's supported */ |
87 | if (phydev->supported & (SUPPORTED_1000baseT_Half | | 87 | if (phydev->supported & (SUPPORTED_1000baseT_Half | |
88 | SUPPORTED_1000baseT_Full)) { | 88 | SUPPORTED_1000baseT_Full)) { |
89 | oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000); | 89 | oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000); |
90 | 90 | ||
91 | if (adv < 0) | 91 | if (adv < 0) |
92 | return adv; | 92 | return adv; |
93 | 93 | ||
94 | adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); | 94 | adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); |
95 | if (advertise & SUPPORTED_1000baseT_Half) | 95 | if (advertise & SUPPORTED_1000baseT_Half) |
96 | adv |= ADVERTISE_1000HALF; | 96 | adv |= ADVERTISE_1000HALF; |
97 | if (advertise & SUPPORTED_1000baseT_Full) | 97 | if (advertise & SUPPORTED_1000baseT_Full) |
98 | adv |= ADVERTISE_1000FULL; | 98 | adv |= ADVERTISE_1000FULL; |
99 | 99 | ||
100 | if (adv != oldadv) { | 100 | if (adv != oldadv) { |
101 | err = phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, | 101 | err = phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, |
102 | adv); | 102 | adv); |
103 | 103 | ||
104 | if (err < 0) | 104 | if (err < 0) |
105 | return err; | 105 | return err; |
106 | changed = 1; | 106 | changed = 1; |
107 | } | 107 | } |
108 | } | 108 | } |
109 | 109 | ||
110 | return changed; | 110 | return changed; |
111 | } | 111 | } |
112 | 112 | ||
113 | 113 | ||
114 | /** | 114 | /** |
115 | * genphy_setup_forced - configures/forces speed/duplex from @phydev | 115 | * genphy_setup_forced - configures/forces speed/duplex from @phydev |
116 | * @phydev: target phy_device struct | 116 | * @phydev: target phy_device struct |
117 | * | 117 | * |
118 | * Description: Configures MII_BMCR to force speed/duplex | 118 | * Description: Configures MII_BMCR to force speed/duplex |
119 | * to the values in phydev. Assumes that the values are valid. | 119 | * to the values in phydev. Assumes that the values are valid. |
120 | */ | 120 | */ |
121 | int genphy_setup_forced(struct phy_device *phydev) | 121 | int genphy_setup_forced(struct phy_device *phydev) |
122 | { | 122 | { |
123 | int err; | 123 | int err; |
124 | int ctl = 0; | 124 | int ctl = 0; |
125 | 125 | ||
126 | phydev->pause = phydev->asym_pause = 0; | 126 | phydev->pause = phydev->asym_pause = 0; |
127 | 127 | ||
128 | if (SPEED_1000 == phydev->speed) | 128 | if (SPEED_1000 == phydev->speed) |
129 | ctl |= BMCR_SPEED1000; | 129 | ctl |= BMCR_SPEED1000; |
130 | else if (SPEED_100 == phydev->speed) | 130 | else if (SPEED_100 == phydev->speed) |
131 | ctl |= BMCR_SPEED100; | 131 | ctl |= BMCR_SPEED100; |
132 | 132 | ||
133 | if (DUPLEX_FULL == phydev->duplex) | 133 | if (DUPLEX_FULL == phydev->duplex) |
134 | ctl |= BMCR_FULLDPLX; | 134 | ctl |= BMCR_FULLDPLX; |
135 | 135 | ||
136 | err = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl); | 136 | err = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl); |
137 | 137 | ||
138 | return err; | 138 | return err; |
139 | } | 139 | } |
140 | 140 | ||
141 | 141 | ||
142 | /** | 142 | /** |
143 | * genphy_restart_aneg - Enable and Restart Autonegotiation | 143 | * genphy_restart_aneg - Enable and Restart Autonegotiation |
144 | * @phydev: target phy_device struct | 144 | * @phydev: target phy_device struct |
145 | */ | 145 | */ |
146 | int genphy_restart_aneg(struct phy_device *phydev) | 146 | int genphy_restart_aneg(struct phy_device *phydev) |
147 | { | 147 | { |
148 | int ctl; | 148 | int ctl; |
149 | 149 | ||
150 | ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); | 150 | ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); |
151 | 151 | ||
152 | if (ctl < 0) | 152 | if (ctl < 0) |
153 | return ctl; | 153 | return ctl; |
154 | 154 | ||
155 | ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); | 155 | ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); |
156 | 156 | ||
157 | /* Don't isolate the PHY if we're negotiating */ | 157 | /* Don't isolate the PHY if we're negotiating */ |
158 | ctl &= ~(BMCR_ISOLATE); | 158 | ctl &= ~(BMCR_ISOLATE); |
159 | 159 | ||
160 | ctl = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl); | 160 | ctl = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl); |
161 | 161 | ||
162 | return ctl; | 162 | return ctl; |
163 | } | 163 | } |
164 | 164 | ||
165 | 165 | ||
166 | /** | 166 | /** |
167 | * genphy_config_aneg - restart auto-negotiation or write BMCR | 167 | * genphy_config_aneg - restart auto-negotiation or write BMCR |
168 | * @phydev: target phy_device struct | 168 | * @phydev: target phy_device struct |
169 | * | 169 | * |
170 | * Description: If auto-negotiation is enabled, we configure the | 170 | * Description: If auto-negotiation is enabled, we configure the |
171 | * advertising, and then restart auto-negotiation. If it is not | 171 | * advertising, and then restart auto-negotiation. If it is not |
172 | * enabled, then we write the BMCR. | 172 | * enabled, then we write the BMCR. |
173 | */ | 173 | */ |
174 | int genphy_config_aneg(struct phy_device *phydev) | 174 | int genphy_config_aneg(struct phy_device *phydev) |
175 | { | 175 | { |
176 | int result; | 176 | int result; |
177 | 177 | ||
178 | if (AUTONEG_ENABLE != phydev->autoneg) | 178 | if (AUTONEG_ENABLE != phydev->autoneg) |
179 | return genphy_setup_forced(phydev); | 179 | return genphy_setup_forced(phydev); |
180 | 180 | ||
181 | result = genphy_config_advert(phydev); | 181 | result = genphy_config_advert(phydev); |
182 | 182 | ||
183 | if (result < 0) /* error */ | 183 | if (result < 0) /* error */ |
184 | return result; | 184 | return result; |
185 | 185 | ||
186 | if (result == 0) { | 186 | if (result == 0) { |
187 | /* Advertisment hasn't changed, but maybe aneg was never on to | 187 | /* Advertisment hasn't changed, but maybe aneg was never on to |
188 | * begin with? Or maybe phy was isolated? */ | 188 | * begin with? Or maybe phy was isolated? */ |
189 | int ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); | 189 | int ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); |
190 | 190 | ||
191 | if (ctl < 0) | 191 | if (ctl < 0) |
192 | return ctl; | 192 | return ctl; |
193 | 193 | ||
194 | if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE)) | 194 | if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE)) |
195 | result = 1; /* do restart aneg */ | 195 | result = 1; /* do restart aneg */ |
196 | } | 196 | } |
197 | 197 | ||
198 | /* Only restart aneg if we are advertising something different | 198 | /* Only restart aneg if we are advertising something different |
199 | * than we were before. */ | 199 | * than we were before. */ |
200 | if (result > 0) | 200 | if (result > 0) |
201 | result = genphy_restart_aneg(phydev); | 201 | result = genphy_restart_aneg(phydev); |
202 | 202 | ||
203 | return result; | 203 | return result; |
204 | } | 204 | } |
205 | 205 | ||
206 | /** | 206 | /** |
207 | * genphy_update_link - update link status in @phydev | 207 | * genphy_update_link - update link status in @phydev |
208 | * @phydev: target phy_device struct | 208 | * @phydev: target phy_device struct |
209 | * | 209 | * |
210 | * Description: Update the value in phydev->link to reflect the | 210 | * Description: Update the value in phydev->link to reflect the |
211 | * current link value. In order to do this, we need to read | 211 | * current link value. In order to do this, we need to read |
212 | * the status register twice, keeping the second value. | 212 | * the status register twice, keeping the second value. |
213 | */ | 213 | */ |
214 | int genphy_update_link(struct phy_device *phydev) | 214 | int genphy_update_link(struct phy_device *phydev) |
215 | { | 215 | { |
216 | unsigned int mii_reg; | 216 | unsigned int mii_reg; |
217 | 217 | ||
218 | /* | 218 | /* |
219 | * Wait if the link is up, and autonegotiation is in progress | 219 | * Wait if the link is up, and autonegotiation is in progress |
220 | * (ie - we're capable and it's not done) | 220 | * (ie - we're capable and it's not done) |
221 | */ | 221 | */ |
222 | mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); | 222 | mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); |
223 | 223 | ||
224 | /* | 224 | /* |
225 | * If we already saw the link up, and it hasn't gone down, then | 225 | * If we already saw the link up, and it hasn't gone down, then |
226 | * we don't need to wait for autoneg again | 226 | * we don't need to wait for autoneg again |
227 | */ | 227 | */ |
228 | if (phydev->link && mii_reg & BMSR_LSTATUS) | 228 | if (phydev->link && mii_reg & BMSR_LSTATUS) |
229 | return 0; | 229 | return 0; |
230 | 230 | ||
231 | if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) { | 231 | if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) { |
232 | int i = 0; | 232 | int i = 0; |
233 | 233 | ||
234 | printf("%s Waiting for PHY auto negotiation to complete", | 234 | printf("%s Waiting for PHY auto negotiation to complete", |
235 | phydev->dev->name); | 235 | phydev->dev->name); |
236 | while (!(mii_reg & BMSR_ANEGCOMPLETE)) { | 236 | while (!(mii_reg & BMSR_ANEGCOMPLETE)) { |
237 | /* | 237 | /* |
238 | * Timeout reached ? | 238 | * Timeout reached ? |
239 | */ | 239 | */ |
240 | if (i > PHY_ANEG_TIMEOUT) { | 240 | if (i > PHY_ANEG_TIMEOUT) { |
241 | printf(" TIMEOUT !\n"); | 241 | printf(" TIMEOUT !\n"); |
242 | phydev->link = 0; | 242 | phydev->link = 0; |
243 | return 0; | 243 | return 0; |
244 | } | 244 | } |
245 | 245 | ||
246 | if (ctrlc()) { | 246 | if (ctrlc()) { |
247 | puts("user interrupt!\n"); | 247 | puts("user interrupt!\n"); |
248 | phydev->link = 0; | 248 | phydev->link = 0; |
249 | return -EINTR; | 249 | return -EINTR; |
250 | } | 250 | } |
251 | 251 | ||
252 | if ((i++ % 500) == 0) | 252 | if ((i++ % 500) == 0) |
253 | printf("."); | 253 | printf("."); |
254 | 254 | ||
255 | udelay(1000); /* 1 ms */ | 255 | udelay(1000); /* 1 ms */ |
256 | mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); | 256 | mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); |
257 | } | 257 | } |
258 | printf(" done\n"); | 258 | printf(" done\n"); |
259 | phydev->link = 1; | 259 | phydev->link = 1; |
260 | } else { | 260 | } else { |
261 | /* Read the link a second time to clear the latched state */ | 261 | /* Read the link a second time to clear the latched state */ |
262 | mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); | 262 | mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); |
263 | 263 | ||
264 | if (mii_reg & BMSR_LSTATUS) | 264 | if (mii_reg & BMSR_LSTATUS) |
265 | phydev->link = 1; | 265 | phydev->link = 1; |
266 | else | 266 | else |
267 | phydev->link = 0; | 267 | phydev->link = 0; |
268 | } | 268 | } |
269 | 269 | ||
270 | return 0; | 270 | return 0; |
271 | } | 271 | } |
272 | 272 | ||
273 | /* | 273 | /* |
274 | * Generic function which updates the speed and duplex. If | 274 | * Generic function which updates the speed and duplex. If |
275 | * autonegotiation is enabled, it uses the AND of the link | 275 | * autonegotiation is enabled, it uses the AND of the link |
276 | * partner's advertised capabilities and our advertised | 276 | * partner's advertised capabilities and our advertised |
277 | * capabilities. If autonegotiation is disabled, we use the | 277 | * capabilities. If autonegotiation is disabled, we use the |
278 | * appropriate bits in the control register. | 278 | * appropriate bits in the control register. |
279 | * | 279 | * |
280 | * Stolen from Linux's mii.c and phy_device.c | 280 | * Stolen from Linux's mii.c and phy_device.c |
281 | */ | 281 | */ |
282 | static int genphy_parse_link(struct phy_device *phydev) | 282 | static int genphy_parse_link(struct phy_device *phydev) |
283 | { | 283 | { |
284 | int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); | 284 | int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); |
285 | 285 | ||
286 | /* We're using autonegotiation */ | 286 | /* We're using autonegotiation */ |
287 | if (mii_reg & BMSR_ANEGCAPABLE) { | 287 | if (mii_reg & BMSR_ANEGCAPABLE) { |
288 | u32 lpa = 0; | 288 | u32 lpa = 0; |
289 | u32 gblpa = 0; | 289 | u32 gblpa = 0; |
290 | 290 | ||
291 | /* Check for gigabit capability */ | 291 | /* Check for gigabit capability */ |
292 | if (mii_reg & BMSR_ERCAP) { | 292 | if (mii_reg & BMSR_ERCAP) { |
293 | /* We want a list of states supported by | 293 | /* We want a list of states supported by |
294 | * both PHYs in the link | 294 | * both PHYs in the link |
295 | */ | 295 | */ |
296 | gblpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000); | 296 | gblpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000); |
297 | gblpa &= phy_read(phydev, | 297 | gblpa &= phy_read(phydev, |
298 | MDIO_DEVAD_NONE, MII_CTRL1000) << 2; | 298 | MDIO_DEVAD_NONE, MII_CTRL1000) << 2; |
299 | } | 299 | } |
300 | 300 | ||
301 | /* Set the baseline so we only have to set them | 301 | /* Set the baseline so we only have to set them |
302 | * if they're different | 302 | * if they're different |
303 | */ | 303 | */ |
304 | phydev->speed = SPEED_10; | 304 | phydev->speed = SPEED_10; |
305 | phydev->duplex = DUPLEX_HALF; | 305 | phydev->duplex = DUPLEX_HALF; |
306 | 306 | ||
307 | /* Check the gigabit fields */ | 307 | /* Check the gigabit fields */ |
308 | if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { | 308 | if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { |
309 | phydev->speed = SPEED_1000; | 309 | phydev->speed = SPEED_1000; |
310 | 310 | ||
311 | if (gblpa & PHY_1000BTSR_1000FD) | 311 | if (gblpa & PHY_1000BTSR_1000FD) |
312 | phydev->duplex = DUPLEX_FULL; | 312 | phydev->duplex = DUPLEX_FULL; |
313 | 313 | ||
314 | /* We're done! */ | 314 | /* We're done! */ |
315 | return 0; | 315 | return 0; |
316 | } | 316 | } |
317 | 317 | ||
318 | lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE); | 318 | lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE); |
319 | lpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA); | 319 | lpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA); |
320 | 320 | ||
321 | if (lpa & (LPA_100FULL | LPA_100HALF)) { | 321 | if (lpa & (LPA_100FULL | LPA_100HALF)) { |
322 | phydev->speed = SPEED_100; | 322 | phydev->speed = SPEED_100; |
323 | 323 | ||
324 | if (lpa & LPA_100FULL) | 324 | if (lpa & LPA_100FULL) |
325 | phydev->duplex = DUPLEX_FULL; | 325 | phydev->duplex = DUPLEX_FULL; |
326 | 326 | ||
327 | } else if (lpa & LPA_10FULL) | 327 | } else if (lpa & LPA_10FULL) |
328 | phydev->duplex = DUPLEX_FULL; | 328 | phydev->duplex = DUPLEX_FULL; |
329 | } else { | 329 | } else { |
330 | u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); | 330 | u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); |
331 | 331 | ||
332 | phydev->speed = SPEED_10; | 332 | phydev->speed = SPEED_10; |
333 | phydev->duplex = DUPLEX_HALF; | 333 | phydev->duplex = DUPLEX_HALF; |
334 | 334 | ||
335 | if (bmcr & BMCR_FULLDPLX) | 335 | if (bmcr & BMCR_FULLDPLX) |
336 | phydev->duplex = DUPLEX_FULL; | 336 | phydev->duplex = DUPLEX_FULL; |
337 | 337 | ||
338 | if (bmcr & BMCR_SPEED1000) | 338 | if (bmcr & BMCR_SPEED1000) |
339 | phydev->speed = SPEED_1000; | 339 | phydev->speed = SPEED_1000; |
340 | else if (bmcr & BMCR_SPEED100) | 340 | else if (bmcr & BMCR_SPEED100) |
341 | phydev->speed = SPEED_100; | 341 | phydev->speed = SPEED_100; |
342 | } | 342 | } |
343 | 343 | ||
344 | return 0; | 344 | return 0; |
345 | } | 345 | } |
346 | 346 | ||
347 | int genphy_config(struct phy_device *phydev) | 347 | int genphy_config(struct phy_device *phydev) |
348 | { | 348 | { |
349 | int val; | 349 | int val; |
350 | u32 features; | 350 | u32 features; |
351 | 351 | ||
352 | /* For now, I'll claim that the generic driver supports | 352 | /* For now, I'll claim that the generic driver supports |
353 | * all possible port types */ | 353 | * all possible port types */ |
354 | features = (SUPPORTED_TP | SUPPORTED_MII | 354 | features = (SUPPORTED_TP | SUPPORTED_MII |
355 | | SUPPORTED_AUI | SUPPORTED_FIBRE | | 355 | | SUPPORTED_AUI | SUPPORTED_FIBRE | |
356 | SUPPORTED_BNC); | 356 | SUPPORTED_BNC); |
357 | 357 | ||
358 | /* Do we support autonegotiation? */ | 358 | /* Do we support autonegotiation? */ |
359 | val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); | 359 | val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); |
360 | 360 | ||
361 | if (val < 0) | 361 | if (val < 0) |
362 | return val; | 362 | return val; |
363 | 363 | ||
364 | if (val & BMSR_ANEGCAPABLE) | 364 | if (val & BMSR_ANEGCAPABLE) |
365 | features |= SUPPORTED_Autoneg; | 365 | features |= SUPPORTED_Autoneg; |
366 | 366 | ||
367 | if (val & BMSR_100FULL) | 367 | if (val & BMSR_100FULL) |
368 | features |= SUPPORTED_100baseT_Full; | 368 | features |= SUPPORTED_100baseT_Full; |
369 | if (val & BMSR_100HALF) | 369 | if (val & BMSR_100HALF) |
370 | features |= SUPPORTED_100baseT_Half; | 370 | features |= SUPPORTED_100baseT_Half; |
371 | if (val & BMSR_10FULL) | 371 | if (val & BMSR_10FULL) |
372 | features |= SUPPORTED_10baseT_Full; | 372 | features |= SUPPORTED_10baseT_Full; |
373 | if (val & BMSR_10HALF) | 373 | if (val & BMSR_10HALF) |
374 | features |= SUPPORTED_10baseT_Half; | 374 | features |= SUPPORTED_10baseT_Half; |
375 | 375 | ||
376 | if (val & BMSR_ESTATEN) { | 376 | if (val & BMSR_ESTATEN) { |
377 | val = phy_read(phydev, MDIO_DEVAD_NONE, MII_ESTATUS); | 377 | val = phy_read(phydev, MDIO_DEVAD_NONE, MII_ESTATUS); |
378 | 378 | ||
379 | if (val < 0) | 379 | if (val < 0) |
380 | return val; | 380 | return val; |
381 | 381 | ||
382 | if (val & ESTATUS_1000_TFULL) | 382 | if (val & ESTATUS_1000_TFULL) |
383 | features |= SUPPORTED_1000baseT_Full; | 383 | features |= SUPPORTED_1000baseT_Full; |
384 | if (val & ESTATUS_1000_THALF) | 384 | if (val & ESTATUS_1000_THALF) |
385 | features |= SUPPORTED_1000baseT_Half; | 385 | features |= SUPPORTED_1000baseT_Half; |
386 | } | 386 | } |
387 | 387 | ||
388 | phydev->supported = features; | 388 | phydev->supported = features; |
389 | phydev->advertising = features; | 389 | phydev->advertising = features; |
390 | 390 | ||
391 | genphy_config_aneg(phydev); | 391 | genphy_config_aneg(phydev); |
392 | 392 | ||
393 | return 0; | 393 | return 0; |
394 | } | 394 | } |
395 | 395 | ||
396 | int genphy_startup(struct phy_device *phydev) | 396 | int genphy_startup(struct phy_device *phydev) |
397 | { | 397 | { |
398 | genphy_update_link(phydev); | 398 | genphy_update_link(phydev); |
399 | genphy_parse_link(phydev); | 399 | genphy_parse_link(phydev); |
400 | 400 | ||
401 | return 0; | 401 | return 0; |
402 | } | 402 | } |
403 | 403 | ||
404 | int genphy_shutdown(struct phy_device *phydev) | 404 | int genphy_shutdown(struct phy_device *phydev) |
405 | { | 405 | { |
406 | return 0; | 406 | return 0; |
407 | } | 407 | } |
408 | 408 | ||
409 | static struct phy_driver genphy_driver = { | 409 | static struct phy_driver genphy_driver = { |
410 | .uid = 0xffffffff, | 410 | .uid = 0xffffffff, |
411 | .mask = 0xffffffff, | 411 | .mask = 0xffffffff, |
412 | .name = "Generic PHY", | 412 | .name = "Generic PHY", |
413 | .features = 0, | 413 | .features = 0, |
414 | .config = genphy_config, | 414 | .config = genphy_config, |
415 | .startup = genphy_startup, | 415 | .startup = genphy_startup, |
416 | .shutdown = genphy_shutdown, | 416 | .shutdown = genphy_shutdown, |
417 | }; | 417 | }; |
418 | 418 | ||
419 | static LIST_HEAD(phy_drivers); | 419 | static LIST_HEAD(phy_drivers); |
420 | 420 | ||
421 | int phy_init(void) | 421 | int phy_init(void) |
422 | { | 422 | { |
423 | #ifdef CONFIG_PHY_ATHEROS | 423 | #ifdef CONFIG_PHY_ATHEROS |
424 | phy_atheros_init(); | 424 | phy_atheros_init(); |
425 | #endif | 425 | #endif |
426 | #ifdef CONFIG_PHY_BROADCOM | 426 | #ifdef CONFIG_PHY_BROADCOM |
427 | phy_broadcom_init(); | 427 | phy_broadcom_init(); |
428 | #endif | 428 | #endif |
429 | #ifdef CONFIG_PHY_DAVICOM | 429 | #ifdef CONFIG_PHY_DAVICOM |
430 | phy_davicom_init(); | 430 | phy_davicom_init(); |
431 | #endif | 431 | #endif |
432 | #ifdef CONFIG_PHY_LXT | 432 | #ifdef CONFIG_PHY_LXT |
433 | phy_lxt_init(); | 433 | phy_lxt_init(); |
434 | #endif | 434 | #endif |
435 | #ifdef CONFIG_PHY_MARVELL | 435 | #ifdef CONFIG_PHY_MARVELL |
436 | phy_marvell_init(); | 436 | phy_marvell_init(); |
437 | #endif | 437 | #endif |
438 | #ifdef CONFIG_PHY_MICREL | 438 | #ifdef CONFIG_PHY_MICREL |
439 | phy_micrel_init(); | 439 | phy_micrel_init(); |
440 | #endif | 440 | #endif |
441 | #ifdef CONFIG_PHY_NATSEMI | 441 | #ifdef CONFIG_PHY_NATSEMI |
442 | phy_natsemi_init(); | 442 | phy_natsemi_init(); |
443 | #endif | 443 | #endif |
444 | #ifdef CONFIG_PHY_REALTEK | 444 | #ifdef CONFIG_PHY_REALTEK |
445 | phy_realtek_init(); | 445 | phy_realtek_init(); |
446 | #endif | 446 | #endif |
447 | #ifdef CONFIG_PHY_SMSC | 447 | #ifdef CONFIG_PHY_SMSC |
448 | phy_smsc_init(); | 448 | phy_smsc_init(); |
449 | #endif | 449 | #endif |
450 | #ifdef CONFIG_PHY_TERANETICS | 450 | #ifdef CONFIG_PHY_TERANETICS |
451 | phy_teranetics_init(); | 451 | phy_teranetics_init(); |
452 | #endif | 452 | #endif |
453 | #ifdef CONFIG_PHY_VITESSE | 453 | #ifdef CONFIG_PHY_VITESSE |
454 | phy_vitesse_init(); | 454 | phy_vitesse_init(); |
455 | #endif | 455 | #endif |
456 | 456 | ||
457 | return 0; | 457 | return 0; |
458 | } | 458 | } |
459 | 459 | ||
460 | int phy_register(struct phy_driver *drv) | 460 | int phy_register(struct phy_driver *drv) |
461 | { | 461 | { |
462 | INIT_LIST_HEAD(&drv->list); | 462 | INIT_LIST_HEAD(&drv->list); |
463 | list_add_tail(&drv->list, &phy_drivers); | 463 | list_add_tail(&drv->list, &phy_drivers); |
464 | 464 | ||
465 | return 0; | 465 | return 0; |
466 | } | 466 | } |
467 | 467 | ||
468 | int phy_probe(struct phy_device *phydev) | 468 | int phy_probe(struct phy_device *phydev) |
469 | { | 469 | { |
470 | int err = 0; | 470 | int err = 0; |
471 | 471 | ||
472 | phydev->advertising = phydev->supported = phydev->drv->features; | 472 | phydev->advertising = phydev->supported = phydev->drv->features; |
473 | phydev->mmds = phydev->drv->mmds; | 473 | phydev->mmds = phydev->drv->mmds; |
474 | 474 | ||
475 | if (phydev->drv->probe) | 475 | if (phydev->drv->probe) |
476 | err = phydev->drv->probe(phydev); | 476 | err = phydev->drv->probe(phydev); |
477 | 477 | ||
478 | return err; | 478 | return err; |
479 | } | 479 | } |
480 | 480 | ||
481 | static struct phy_driver *generic_for_interface(phy_interface_t interface) | 481 | static struct phy_driver *generic_for_interface(phy_interface_t interface) |
482 | { | 482 | { |
483 | #ifdef CONFIG_PHYLIB_10G | 483 | #ifdef CONFIG_PHYLIB_10G |
484 | if (is_10g_interface(interface)) | 484 | if (is_10g_interface(interface)) |
485 | return &gen10g_driver; | 485 | return &gen10g_driver; |
486 | #endif | 486 | #endif |
487 | 487 | ||
488 | return &genphy_driver; | 488 | return &genphy_driver; |
489 | } | 489 | } |
490 | 490 | ||
491 | struct phy_driver *get_phy_driver(struct phy_device *phydev, | 491 | struct phy_driver *get_phy_driver(struct phy_device *phydev, |
492 | phy_interface_t interface) | 492 | phy_interface_t interface) |
493 | { | 493 | { |
494 | struct list_head *entry; | 494 | struct list_head *entry; |
495 | int phy_id = phydev->phy_id; | 495 | int phy_id = phydev->phy_id; |
496 | struct phy_driver *drv = NULL; | 496 | struct phy_driver *drv = NULL; |
497 | 497 | ||
498 | list_for_each(entry, &phy_drivers) { | 498 | list_for_each(entry, &phy_drivers) { |
499 | drv = list_entry(entry, struct phy_driver, list); | 499 | drv = list_entry(entry, struct phy_driver, list); |
500 | if ((drv->uid & drv->mask) == (phy_id & drv->mask)) | 500 | if ((drv->uid & drv->mask) == (phy_id & drv->mask)) |
501 | return drv; | 501 | return drv; |
502 | } | 502 | } |
503 | 503 | ||
504 | /* If we made it here, there's no driver for this PHY */ | 504 | /* If we made it here, there's no driver for this PHY */ |
505 | return generic_for_interface(interface); | 505 | return generic_for_interface(interface); |
506 | } | 506 | } |
507 | 507 | ||
508 | struct phy_device *phy_device_create(struct mii_dev *bus, int addr, int phy_id, | 508 | struct phy_device *phy_device_create(struct mii_dev *bus, int addr, int phy_id, |
509 | phy_interface_t interface) | 509 | phy_interface_t interface) |
510 | { | 510 | { |
511 | struct phy_device *dev; | 511 | struct phy_device *dev; |
512 | 512 | ||
513 | /* We allocate the device, and initialize the | 513 | /* We allocate the device, and initialize the |
514 | * default values */ | 514 | * default values */ |
515 | dev = malloc(sizeof(*dev)); | 515 | dev = malloc(sizeof(*dev)); |
516 | if (!dev) { | 516 | if (!dev) { |
517 | printf("Failed to allocate PHY device for %s:%d\n", | 517 | printf("Failed to allocate PHY device for %s:%d\n", |
518 | bus->name, addr); | 518 | bus->name, addr); |
519 | return NULL; | 519 | return NULL; |
520 | } | 520 | } |
521 | 521 | ||
522 | memset(dev, 0, sizeof(*dev)); | 522 | memset(dev, 0, sizeof(*dev)); |
523 | 523 | ||
524 | dev->duplex = -1; | 524 | dev->duplex = -1; |
525 | dev->link = 1; | 525 | dev->link = 1; |
526 | dev->interface = interface; | 526 | dev->interface = interface; |
527 | 527 | ||
528 | dev->autoneg = AUTONEG_ENABLE; | 528 | dev->autoneg = AUTONEG_ENABLE; |
529 | 529 | ||
530 | dev->addr = addr; | 530 | dev->addr = addr; |
531 | dev->phy_id = phy_id; | 531 | dev->phy_id = phy_id; |
532 | dev->bus = bus; | 532 | dev->bus = bus; |
533 | 533 | ||
534 | dev->drv = get_phy_driver(dev, interface); | 534 | dev->drv = get_phy_driver(dev, interface); |
535 | 535 | ||
536 | phy_probe(dev); | 536 | phy_probe(dev); |
537 | 537 | ||
538 | bus->phymap[addr] = dev; | 538 | bus->phymap[addr] = dev; |
539 | 539 | ||
540 | return dev; | 540 | return dev; |
541 | } | 541 | } |
542 | 542 | ||
543 | /** | 543 | /** |
544 | * get_phy_id - reads the specified addr for its ID. | 544 | * get_phy_id - reads the specified addr for its ID. |
545 | * @bus: the target MII bus | 545 | * @bus: the target MII bus |
546 | * @addr: PHY address on the MII bus | 546 | * @addr: PHY address on the MII bus |
547 | * @phy_id: where to store the ID retrieved. | 547 | * @phy_id: where to store the ID retrieved. |
548 | * | 548 | * |
549 | * Description: Reads the ID registers of the PHY at @addr on the | 549 | * Description: Reads the ID registers of the PHY at @addr on the |
550 | * @bus, stores it in @phy_id and returns zero on success. | 550 | * @bus, stores it in @phy_id and returns zero on success. |
551 | */ | 551 | */ |
552 | int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id) | 552 | int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id) |
553 | { | 553 | { |
554 | int phy_reg; | 554 | int phy_reg; |
555 | 555 | ||
556 | /* Grab the bits from PHYIR1, and put them | 556 | /* Grab the bits from PHYIR1, and put them |
557 | * in the upper half */ | 557 | * in the upper half */ |
558 | phy_reg = bus->read(bus, addr, devad, MII_PHYSID1); | 558 | phy_reg = bus->read(bus, addr, devad, MII_PHYSID1); |
559 | 559 | ||
560 | if (phy_reg < 0) | 560 | if (phy_reg < 0) |
561 | return -EIO; | 561 | return -EIO; |
562 | 562 | ||
563 | *phy_id = (phy_reg & 0xffff) << 16; | 563 | *phy_id = (phy_reg & 0xffff) << 16; |
564 | 564 | ||
565 | /* Grab the bits from PHYIR2, and put them in the lower half */ | 565 | /* Grab the bits from PHYIR2, and put them in the lower half */ |
566 | phy_reg = bus->read(bus, addr, devad, MII_PHYSID2); | 566 | phy_reg = bus->read(bus, addr, devad, MII_PHYSID2); |
567 | 567 | ||
568 | if (phy_reg < 0) | 568 | if (phy_reg < 0) |
569 | return -EIO; | 569 | return -EIO; |
570 | 570 | ||
571 | *phy_id |= (phy_reg & 0xffff); | 571 | *phy_id |= (phy_reg & 0xffff); |
572 | 572 | ||
573 | return 0; | 573 | return 0; |
574 | } | 574 | } |
575 | 575 | ||
576 | /** | 576 | /** |
577 | * get_phy_device - reads the specified PHY device and returns its @phy_device struct | 577 | * get_phy_device - reads the specified PHY device and returns its @phy_device struct |
578 | * @bus: the target MII bus | 578 | * @bus: the target MII bus |
579 | * @addr: PHY address on the MII bus | 579 | * @addr: PHY address on the MII bus |
580 | * | 580 | * |
581 | * Description: Reads the ID registers of the PHY at @addr on the | 581 | * Description: Reads the ID registers of the PHY at @addr on the |
582 | * @bus, then allocates and returns the phy_device to represent it. | 582 | * @bus, then allocates and returns the phy_device to represent it. |
583 | */ | 583 | */ |
584 | struct phy_device *get_phy_device(struct mii_dev *bus, int addr, | 584 | struct phy_device *get_phy_device(struct mii_dev *bus, int addr, |
585 | phy_interface_t interface) | 585 | phy_interface_t interface) |
586 | { | 586 | { |
587 | u32 phy_id = 0x1fffffff; | 587 | u32 phy_id = 0x1fffffff; |
588 | int i; | 588 | int i; |
589 | int r; | 589 | int r; |
590 | 590 | ||
591 | /* If we have one, return the existing device, with new interface */ | 591 | /* If we have one, return the existing device, with new interface */ |
592 | if (bus->phymap[addr]) { | 592 | if (bus->phymap[addr]) { |
593 | bus->phymap[addr]->interface = interface; | 593 | bus->phymap[addr]->interface = interface; |
594 | 594 | ||
595 | return bus->phymap[addr]; | 595 | return bus->phymap[addr]; |
596 | } | 596 | } |
597 | 597 | ||
598 | /* Try Standard (ie Clause 22) access */ | 598 | /* Try Standard (ie Clause 22) access */ |
599 | r = get_phy_id(bus, addr, MDIO_DEVAD_NONE, &phy_id); | 599 | r = get_phy_id(bus, addr, MDIO_DEVAD_NONE, &phy_id); |
600 | if (r) | 600 | if (r) |
601 | return NULL; | 601 | return NULL; |
602 | 602 | ||
603 | /* If the PHY ID is mostly f's, we didn't find anything */ | 603 | /* If the PHY ID is mostly f's, we didn't find anything */ |
604 | if ((phy_id & 0x1fffffff) != 0x1fffffff) | 604 | if ((phy_id & 0x1fffffff) != 0x1fffffff) |
605 | return phy_device_create(bus, addr, phy_id, interface); | 605 | return phy_device_create(bus, addr, phy_id, interface); |
606 | 606 | ||
607 | /* Otherwise we have to try Clause 45 */ | 607 | /* Otherwise we have to try Clause 45 */ |
608 | for (i = 1; i < 5; i++) { | 608 | for (i = 1; i < 5; i++) { |
609 | r = get_phy_id(bus, addr, i, &phy_id); | 609 | r = get_phy_id(bus, addr, i, &phy_id); |
610 | if (r) | 610 | if (r) |
611 | return NULL; | 611 | return NULL; |
612 | 612 | ||
613 | /* If the phy_id is mostly Fs, there is no device there */ | 613 | /* If the phy_id is mostly Fs, there is no device there */ |
614 | if ((phy_id & 0x1fffffff) != 0x1fffffff) | 614 | if ((phy_id & 0x1fffffff) != 0x1fffffff) |
615 | break; | 615 | break; |
616 | } | 616 | } |
617 | 617 | ||
618 | return phy_device_create(bus, addr, phy_id, interface); | 618 | return phy_device_create(bus, addr, phy_id, interface); |
619 | } | 619 | } |
620 | 620 | ||
621 | int phy_reset(struct phy_device *phydev) | 621 | int phy_reset(struct phy_device *phydev) |
622 | { | 622 | { |
623 | int reg; | 623 | int reg; |
624 | int timeout = 500; | 624 | int timeout = 500; |
625 | int devad = MDIO_DEVAD_NONE; | 625 | int devad = MDIO_DEVAD_NONE; |
626 | 626 | ||
627 | #ifdef CONFIG_PHYLIB_10G | 627 | #ifdef CONFIG_PHYLIB_10G |
628 | /* If it's 10G, we need to issue reset through one of the MMDs */ | 628 | /* If it's 10G, we need to issue reset through one of the MMDs */ |
629 | if (is_10g_interface(phydev->interface)) { | 629 | if (is_10g_interface(phydev->interface)) { |
630 | if (!phydev->mmds) | 630 | if (!phydev->mmds) |
631 | gen10g_discover_mmds(phydev); | 631 | gen10g_discover_mmds(phydev); |
632 | 632 | ||
633 | devad = ffs(phydev->mmds) - 1; | 633 | devad = ffs(phydev->mmds) - 1; |
634 | } | 634 | } |
635 | #endif | 635 | #endif |
636 | 636 | ||
637 | reg = phy_read(phydev, devad, MII_BMCR); | 637 | reg = phy_read(phydev, devad, MII_BMCR); |
638 | if (reg < 0) { | 638 | if (reg < 0) { |
639 | debug("PHY status read failed\n"); | 639 | debug("PHY status read failed\n"); |
640 | return -1; | 640 | return -1; |
641 | } | 641 | } |
642 | 642 | ||
643 | reg |= BMCR_RESET; | 643 | reg |= BMCR_RESET; |
644 | 644 | ||
645 | if (phy_write(phydev, devad, MII_BMCR, reg) < 0) { | 645 | if (phy_write(phydev, devad, MII_BMCR, reg) < 0) { |
646 | debug("PHY reset failed\n"); | 646 | debug("PHY reset failed\n"); |
647 | return -1; | 647 | return -1; |
648 | } | 648 | } |
649 | 649 | ||
650 | #ifdef CONFIG_PHY_RESET_DELAY | 650 | #ifdef CONFIG_PHY_RESET_DELAY |
651 | udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */ | 651 | udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */ |
652 | #endif | 652 | #endif |
653 | /* | 653 | /* |
654 | * Poll the control register for the reset bit to go to 0 (it is | 654 | * Poll the control register for the reset bit to go to 0 (it is |
655 | * auto-clearing). This should happen within 0.5 seconds per the | 655 | * auto-clearing). This should happen within 0.5 seconds per the |
656 | * IEEE spec. | 656 | * IEEE spec. |
657 | */ | 657 | */ |
658 | while ((reg & BMCR_RESET) && timeout--) { | 658 | while ((reg & BMCR_RESET) && timeout--) { |
659 | reg = phy_read(phydev, devad, MII_BMCR); | 659 | reg = phy_read(phydev, devad, MII_BMCR); |
660 | 660 | ||
661 | if (reg < 0) { | 661 | if (reg < 0) { |
662 | debug("PHY status read failed\n"); | 662 | debug("PHY status read failed\n"); |
663 | return -1; | 663 | return -1; |
664 | } | 664 | } |
665 | udelay(1000); | 665 | udelay(1000); |
666 | } | 666 | } |
667 | 667 | ||
668 | if (reg & BMCR_RESET) { | 668 | if (reg & BMCR_RESET) { |
669 | puts("PHY reset timed out\n"); | 669 | puts("PHY reset timed out\n"); |
670 | return -1; | 670 | return -1; |
671 | } | 671 | } |
672 | 672 | ||
673 | return 0; | 673 | return 0; |
674 | } | 674 | } |
675 | 675 | ||
676 | int miiphy_reset(const char *devname, unsigned char addr) | 676 | int miiphy_reset(const char *devname, unsigned char addr) |
677 | { | 677 | { |
678 | struct mii_dev *bus = miiphy_get_dev_by_name(devname); | 678 | struct mii_dev *bus = miiphy_get_dev_by_name(devname); |
679 | struct phy_device *phydev; | 679 | struct phy_device *phydev; |
680 | 680 | ||
681 | /* | 681 | /* |
682 | * miiphy_reset was only used on standard PHYs, so we'll fake it here. | 682 | * miiphy_reset was only used on standard PHYs, so we'll fake it here. |
683 | * If later code tries to connect with the right interface, this will | 683 | * If later code tries to connect with the right interface, this will |
684 | * be corrected by get_phy_device in phy_connect() | 684 | * be corrected by get_phy_device in phy_connect() |
685 | */ | 685 | */ |
686 | phydev = get_phy_device(bus, addr, PHY_INTERFACE_MODE_MII); | 686 | phydev = get_phy_device(bus, addr, PHY_INTERFACE_MODE_MII); |
687 | 687 | ||
688 | return phy_reset(phydev); | 688 | return phy_reset(phydev); |
689 | } | 689 | } |
690 | 690 | ||
691 | struct phy_device *phy_connect(struct mii_dev *bus, int addr, | 691 | struct phy_device *phy_connect(struct mii_dev *bus, int addr, |
692 | struct eth_device *dev, | 692 | struct eth_device *dev, |
693 | phy_interface_t interface) | 693 | phy_interface_t interface) |
694 | { | 694 | { |
695 | struct phy_device *phydev; | 695 | struct phy_device *phydev; |
696 | 696 | ||
697 | /* Reset the bus */ | 697 | /* Reset the bus */ |
698 | if (bus->reset) | 698 | if (bus->reset) |
699 | bus->reset(bus); | 699 | bus->reset(bus); |
700 | 700 | ||
701 | /* Wait 15ms to make sure the PHY has come out of hard reset */ | 701 | /* Wait 15ms to make sure the PHY has come out of hard reset */ |
702 | udelay(15000); | 702 | udelay(15000); |
703 | 703 | ||
704 | phydev = get_phy_device(bus, addr, interface); | 704 | phydev = get_phy_device(bus, addr, interface); |
705 | 705 | ||
706 | if (!phydev) { | 706 | if (!phydev) { |
707 | printf("Could not get PHY for %s:%d\n", bus->name, addr); | 707 | printf("Could not get PHY for %s:%d\n", bus->name, addr); |
708 | 708 | ||
709 | return NULL; | 709 | return NULL; |
710 | } | 710 | } |
711 | 711 | ||
712 | /* Soft Reset the PHY */ | 712 | /* Soft Reset the PHY */ |
713 | phy_reset(phydev); | 713 | phy_reset(phydev); |
714 | 714 | ||
715 | if (phydev->dev) | 715 | if (phydev->dev) |
716 | printf("%s:%d is connected to %s. Reconnecting to %s\n", | 716 | printf("%s:%d is connected to %s. Reconnecting to %s\n", |
717 | bus->name, addr, phydev->dev->name, dev->name); | 717 | bus->name, addr, phydev->dev->name, dev->name); |
718 | 718 | ||
719 | phydev->dev = dev; | 719 | phydev->dev = dev; |
720 | 720 | ||
721 | debug("%s connected to %s\n", dev->name, phydev->drv->name); | 721 | debug("%s connected to %s\n", dev->name, phydev->drv->name); |
722 | 722 | ||
723 | return phydev; | 723 | return phydev; |
724 | } | 724 | } |
725 | 725 | ||
726 | int phy_startup(struct phy_device *phydev) | 726 | int phy_startup(struct phy_device *phydev) |
727 | { | 727 | { |
728 | if (phydev->drv->startup) | 728 | if (phydev->drv->startup) |
729 | phydev->drv->startup(phydev); | 729 | phydev->drv->startup(phydev); |
730 | 730 | ||
731 | return 0; | 731 | return 0; |
732 | } | 732 | } |
733 | 733 | ||
734 | static int __board_phy_config(struct phy_device *phydev) | 734 | static int __board_phy_config(struct phy_device *phydev) |
735 | { | 735 | { |
736 | if (phydev->drv->config) | ||
737 | return phydev->drv->config(phydev); | ||
736 | return 0; | 738 | return 0; |
737 | } | 739 | } |
738 | 740 | ||
739 | int board_phy_config(struct phy_device *phydev) | 741 | int board_phy_config(struct phy_device *phydev) |
740 | __attribute__((weak, alias("__board_phy_config"))); | 742 | __attribute__((weak, alias("__board_phy_config"))); |
741 | 743 | ||
742 | int phy_config(struct phy_device *phydev) | 744 | int phy_config(struct phy_device *phydev) |
743 | { | 745 | { |
744 | if (phydev->drv->config) | ||
745 | phydev->drv->config(phydev); | ||
746 | |||
747 | /* Invoke an optional board-specific helper */ | 746 | /* Invoke an optional board-specific helper */ |
748 | board_phy_config(phydev); | 747 | board_phy_config(phydev); |
749 | 748 | ||
750 | return 0; | 749 | return 0; |
751 | } | 750 | } |
752 | 751 | ||
753 | int phy_shutdown(struct phy_device *phydev) | 752 | int phy_shutdown(struct phy_device *phydev) |
754 | { | 753 | { |
755 | if (phydev->drv->shutdown) | 754 | if (phydev->drv->shutdown) |
756 | phydev->drv->shutdown(phydev); | 755 | phydev->drv->shutdown(phydev); |
757 | 756 | ||
758 | return 0; | 757 | return 0; |