Commit 078813d21db0600d440625327a1728c32e9fcc90
Committed by
Stefano Babic
1 parent
953ab736af
Exists in
master
and in
50 other branches
udoo: Add ethernet support (FEC + Micrel KSZ9031).
Add Ethernet and networking support on uDoo board (FEC +phy Micrel KSZ9031). Ethernet speed is currently limited to 10/100Mbps. Signed-off-by: Giuseppe Pagano <giuseppe.pagano@seco.com> Tested-by: Fabio Estevam <fabio.estevam@freescale.com> CC: Stefano Babic <sbabic@denx.de> CC: Fabio Estevam <fabio.estevam@freescale.com>
Showing 3 changed files with 161 additions and 0 deletions Side-by-side Diff
board/udoo/udoo.c
... | ... | @@ -9,6 +9,7 @@ |
9 | 9 | #include <asm/arch/clock.h> |
10 | 10 | #include <asm/arch/imx-regs.h> |
11 | 11 | #include <asm/arch/iomux.h> |
12 | +#include <malloc.h> | |
12 | 13 | #include <asm/arch/mx6-pins.h> |
13 | 14 | #include <asm/errno.h> |
14 | 15 | #include <asm/gpio.h> |
... | ... | @@ -18,6 +19,9 @@ |
18 | 19 | #include <asm/arch/crm_regs.h> |
19 | 20 | #include <asm/io.h> |
20 | 21 | #include <asm/arch/sys_proto.h> |
22 | +#include <micrel.h> | |
23 | +#include <miiphy.h> | |
24 | +#include <netdev.h> | |
21 | 25 | |
22 | 26 | DECLARE_GLOBAL_DATA_PTR; |
23 | 27 | |
... | ... | @@ -25,6 +29,9 @@ |
25 | 29 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ |
26 | 30 | PAD_CTL_SRE_FAST | PAD_CTL_HYS) |
27 | 31 | |
32 | +#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ | |
33 | + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) | |
34 | + | |
28 | 35 | #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \ |
29 | 36 | PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ |
30 | 37 | PAD_CTL_SRE_FAST | PAD_CTL_HYS) |
... | ... | @@ -58,6 +65,99 @@ |
58 | 65 | MX6_PAD_EIM_D19__GPIO3_IO19, |
59 | 66 | }; |
60 | 67 | |
68 | +int mx6_rgmii_rework(struct phy_device *phydev) | |
69 | +{ | |
70 | + /* | |
71 | + * Bug: Apparently uDoo does not works with Gigabit switches... | |
72 | + * Limiting speed to 10/100Mbps, and setting master mode, seems to | |
73 | + * be the only way to have a successfull PHY auto negotiation. | |
74 | + * How to fix: Understand why Linux kernel do not have this issue. | |
75 | + */ | |
76 | + phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0x1c00); | |
77 | + | |
78 | + /* control data pad skew - devaddr = 0x02, register = 0x04 */ | |
79 | + ksz9031_phy_extended_write(phydev, 0x02, | |
80 | + MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, | |
81 | + MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000); | |
82 | + /* rx data pad skew - devaddr = 0x02, register = 0x05 */ | |
83 | + ksz9031_phy_extended_write(phydev, 0x02, | |
84 | + MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, | |
85 | + MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000); | |
86 | + /* tx data pad skew - devaddr = 0x02, register = 0x05 */ | |
87 | + ksz9031_phy_extended_write(phydev, 0x02, | |
88 | + MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, | |
89 | + MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000); | |
90 | + /* gtx and rx clock pad skew - devaddr = 0x02, register = 0x08 */ | |
91 | + ksz9031_phy_extended_write(phydev, 0x02, | |
92 | + MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, | |
93 | + MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x03FF); | |
94 | + return 0; | |
95 | +} | |
96 | + | |
97 | +static iomux_v3_cfg_t const enet_pads1[] = { | |
98 | + MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
99 | + MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
100 | + MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
101 | + MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
102 | + MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
103 | + MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
104 | + MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
105 | + MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
106 | + MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
107 | + MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
108 | + /* RGMII reset */ | |
109 | + MX6_PAD_EIM_D23__GPIO3_IO23 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
110 | + /* Ethernet power supply */ | |
111 | + MX6_PAD_EIM_EB3__GPIO2_IO31 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
112 | + /* pin 32 - 1 - (MODE0) all */ | |
113 | + MX6_PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
114 | + /* pin 31 - 1 - (MODE1) all */ | |
115 | + MX6_PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
116 | + /* pin 28 - 1 - (MODE2) all */ | |
117 | + MX6_PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
118 | + /* pin 27 - 1 - (MODE3) all */ | |
119 | + MX6_PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
120 | + /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */ | |
121 | + MX6_PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
122 | +}; | |
123 | + | |
124 | +static iomux_v3_cfg_t const enet_pads2[] = { | |
125 | + MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
126 | + MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
127 | + MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
128 | + MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
129 | + MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
130 | +}; | |
131 | + | |
132 | +static void setup_iomux_enet(void) | |
133 | +{ | |
134 | + imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1)); | |
135 | + udelay(20); | |
136 | + gpio_direction_output(IMX_GPIO_NR(2, 31), 1); /* Power supply on */ | |
137 | + | |
138 | + gpio_direction_output(IMX_GPIO_NR(3, 23), 0); /* assert PHY rst */ | |
139 | + | |
140 | + gpio_direction_output(IMX_GPIO_NR(6, 24), 1); | |
141 | + gpio_direction_output(IMX_GPIO_NR(6, 25), 1); | |
142 | + gpio_direction_output(IMX_GPIO_NR(6, 27), 1); | |
143 | + gpio_direction_output(IMX_GPIO_NR(6, 28), 1); | |
144 | + gpio_direction_output(IMX_GPIO_NR(6, 29), 1); | |
145 | + udelay(1000); | |
146 | + | |
147 | + gpio_set_value(IMX_GPIO_NR(3, 23), 1); /* deassert PHY rst */ | |
148 | + | |
149 | + /* Need 100ms delay to exit from reset. */ | |
150 | + udelay(1000 * 100); | |
151 | + | |
152 | + gpio_free(IMX_GPIO_NR(6, 24)); | |
153 | + gpio_free(IMX_GPIO_NR(6, 25)); | |
154 | + gpio_free(IMX_GPIO_NR(6, 27)); | |
155 | + gpio_free(IMX_GPIO_NR(6, 28)); | |
156 | + gpio_free(IMX_GPIO_NR(6, 29)); | |
157 | + | |
158 | + imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2)); | |
159 | +} | |
160 | + | |
61 | 161 | static void setup_iomux_uart(void) |
62 | 162 | { |
63 | 163 | imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads)); |
... | ... | @@ -77,6 +177,37 @@ |
77 | 177 | return 1; /* Always present */ |
78 | 178 | } |
79 | 179 | |
180 | +int board_eth_init(bd_t *bis) | |
181 | +{ | |
182 | + uint32_t base = IMX_FEC_BASE; | |
183 | + struct mii_dev *bus = NULL; | |
184 | + struct phy_device *phydev = NULL; | |
185 | + int ret; | |
186 | + | |
187 | + setup_iomux_enet(); | |
188 | + | |
189 | +#ifdef CONFIG_FEC_MXC | |
190 | + bus = fec_get_miibus(base, -1); | |
191 | + if (!bus) | |
192 | + return 0; | |
193 | + /* scan phy 4,5,6,7 */ | |
194 | + phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII); | |
195 | + | |
196 | + if (!phydev) { | |
197 | + free(bus); | |
198 | + return 0; | |
199 | + } | |
200 | + printf("using phy at %d\n", phydev->addr); | |
201 | + ret = fec_probe(bis, -1, base, bus, phydev); | |
202 | + if (ret) { | |
203 | + printf("FEC MXC: %s:failed\n", __func__); | |
204 | + free(phydev); | |
205 | + free(bus); | |
206 | + } | |
207 | +#endif | |
208 | + return 0; | |
209 | +} | |
210 | + | |
80 | 211 | int board_mmc_init(bd_t *bis) |
81 | 212 | { |
82 | 213 | imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads)); |
... | ... | @@ -90,6 +221,15 @@ |
90 | 221 | { |
91 | 222 | setup_iomux_wdog(); |
92 | 223 | setup_iomux_uart(); |
224 | + | |
225 | + return 0; | |
226 | +} | |
227 | + | |
228 | +int board_phy_config(struct phy_device *phydev) | |
229 | +{ | |
230 | + mx6_rgmii_rework(phydev); | |
231 | + if (phydev->drv->config) | |
232 | + phydev->drv->config(phydev); | |
93 | 233 | |
94 | 234 | return 0; |
95 | 235 | } |
include/configs/udoo.h
... | ... | @@ -34,6 +34,22 @@ |
34 | 34 | #define CONFIG_MXC_UART |
35 | 35 | #define CONFIG_MXC_UART_BASE UART2_BASE |
36 | 36 | |
37 | +/* Network support */ | |
38 | + | |
39 | +#define CONFIG_CMD_PING | |
40 | +#define CONFIG_CMD_DHCP | |
41 | +#define CONFIG_CMD_MII | |
42 | +#define CONFIG_CMD_NET | |
43 | +#define CONFIG_FEC_MXC | |
44 | +#define CONFIG_MII | |
45 | +#define IMX_FEC_BASE ENET_BASE_ADDR | |
46 | +#define CONFIG_FEC_XCV_TYPE RGMII | |
47 | +#define CONFIG_ETHPRIME "FEC" | |
48 | +#define CONFIG_FEC_MXC_PHYADDR 6 | |
49 | +#define CONFIG_PHYLIB | |
50 | +#define CONFIG_PHY_MICREL | |
51 | +#define CONFIG_PHY_MICREL_KSZ9031 | |
52 | + | |
37 | 53 | /* allow to overwrite serial and ethaddr */ |
38 | 54 | #define CONFIG_ENV_OVERWRITE |
39 | 55 | #define CONFIG_CONS_INDEX 1 |
include/micrel.h
... | ... | @@ -15,6 +15,11 @@ |
15 | 15 | #define MII_KSZ9031_MOD_DATA_POST_INC_RW 0x8000 |
16 | 16 | #define MII_KSZ9031_MOD_DATA_POST_INC_W 0xC000 |
17 | 17 | |
18 | +#define MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW 0x4 | |
19 | +#define MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW 0x5 | |
20 | +#define MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW 0x6 | |
21 | +#define MII_KSZ9031_EXT_RGMII_CLOCK_SKEW 0x8 | |
22 | + | |
18 | 23 | struct phy_device; |
19 | 24 | int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val); |
20 | 25 | int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum); |