1 //==========================================================================
3 // devs_eth_arm_tx53.inl
5 // Board ethernet I/O definitions.
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //===========================================================================
42 #include <cyg/hal/hal_intr.h> // CYGNUM_HAL_INTERRUPT_ETHR
43 #include <cyg/hal/hal_if.h>
44 #include <cyg/hal/mx53_iomux.h>
47 #include <pkgconf/redboot.h>
48 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
50 #include <flash_config.h>
57 #ifdef CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
59 #ifdef CYGPKG_DEVS_ETH_PHY
61 static char mxc_fec_name[] = "mxc_fec";
63 #define FEC_POWER_GPIO MX53_GPIO_NR(3, 20)
64 #define FEC_RESET_GPIO MX53_GPIO_NR(7, 6)
66 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
68 // Verify that the given ESA is valid for this platform
70 static char oui[3] = CYGDAT_DEVS_ETH_ARM_TX53KARO_OUI;
73 cyg_plf_redboot_esa_validate(unsigned char *val)
75 return (val[0] == oui[0]) && (val[1] == oui[1]) && (val[2] == oui[2]);
79 extern int tx53_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN]);
81 static inline void tx53_write_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset, CYG_WORD32 val)
84 diag_printf("Changing reg %08x from %08x to %08x\n",
85 base_addr + offset, readl(base_addr + offset), val);
87 HAL_WRITE_UINT32(base_addr + offset, val);
90 static inline CYG_WORD32 tx53_read_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset)
94 HAL_READ_UINT32(base_addr + offset, val);
95 if (net_debug) diag_printf("Read %08x from reg %08x\n", val, base_addr + offset);
99 static inline void tx53_set_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset,
100 CYG_WORD32 set_mask, CYG_WORD32 clr_mask)
104 HAL_READ_UINT32(base_addr + offset, val);
105 if (net_debug) diag_printf("Changing reg %08x from %08x to %08x\n", base_addr + offset, val,
106 (val & ~clr_mask) | set_mask);
107 val = (val & ~clr_mask) | set_mask;
108 HAL_WRITE_UINT32(base_addr + offset, val);
111 static iomux_v3_cfg_t tx53_fec_gpio_pads[] = {
112 /* setup FEC PHY pins for GPIO function (with SION set) */
113 MX53_PAD_FEC_REF_CLK__GPIO_1_23 | IOMUX_CONFIG_SION,
114 MX53_PAD_FEC_MDC__GPIO_1_31 | IOMUX_CONFIG_SION,
115 MX53_PAD_FEC_MDIO__GPIO_1_22 | IOMUX_CONFIG_SION,
116 MX53_PAD_FEC_RXD0__GPIO_1_27 | IOMUX_CONFIG_SION,
117 MX53_PAD_FEC_RXD1__GPIO_1_26 | IOMUX_CONFIG_SION,
118 MX53_PAD_FEC_RX_ER__GPIO_1_24 | IOMUX_CONFIG_SION,
119 MX53_PAD_FEC_TX_EN__GPIO_1_28 | IOMUX_CONFIG_SION,
120 MX53_PAD_FEC_TXD0__GPIO_1_30 | IOMUX_CONFIG_SION,
121 MX53_PAD_FEC_TXD1__GPIO_1_29 | IOMUX_CONFIG_SION,
122 MX53_PAD_FEC_CRS_DV__GPIO_1_25 | IOMUX_CONFIG_SION,
125 MX53_PAD_PATA_DA_0__GPIO_7_6 | IOMUX_CONFIG_SION,
127 MX53_PAD_EIM_D20__GPIO_3_20 | IOMUX_CONFIG_SION,
130 static iomux_v3_cfg_t tx53_fec_pads[] = {
131 MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
132 MX53_PAD_FEC_MDC__FEC_MDC,
133 MX53_PAD_FEC_MDIO__FEC_MDIO,
134 MX53_PAD_FEC_RXD0__FEC_RDATA_0,
135 MX53_PAD_FEC_RXD1__FEC_RDATA_1,
136 MX53_PAD_FEC_RX_ER__FEC_RX_ER,
137 MX53_PAD_FEC_TX_EN__FEC_TX_EN,
138 MX53_PAD_FEC_TXD0__FEC_TDATA_0,
139 MX53_PAD_FEC_TXD1__FEC_TDATA_1,
140 MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
143 static struct tx53_gpio_setup {
147 } tx53_fec_gpio_data[] = {
150 { FEC_RESET_GPIO, 1, 0, }, /* PHY reset */
151 { FEC_POWER_GPIO, 1, 1, }, /* PHY power enable */
152 { MX53_GPIO_NR(1, 23), 0, }, /* ENET_CLK */
153 { MX53_GPIO_NR(1, 31), 1, 0, }, /* MDC */
154 { MX53_GPIO_NR(1, 22), 1, 0, }, /* MDIO */
155 { MX53_GPIO_NR(1, 27), 1, 1, }, /* Mode0/RXD0 */
156 { MX53_GPIO_NR(1, 26), 1, 1, }, /* Mode1/RXD1 */
157 { MX53_GPIO_NR(1, 24), 0, }, /* RX_ER */
158 { MX53_GPIO_NR(1, 28), 1, 0, }, /* TX_EN */
159 { MX53_GPIO_NR(1, 30), 1, 0, }, /* TXD0 */
160 { MX53_GPIO_NR(1, 29), 1, 0, }, /* TXD1 */
161 { MX53_GPIO_NR(1, 25), 1, 1, }, /* Mode2/CRS_DV */
164 static inline void tx53_phy_gpio_init(void)
169 diag_printf("Initializing PHY GPIOs\n");
171 /* setup all pins attached to the PHY to the required level */
172 for (i = 0; i < CYG_NELEM(tx53_fec_gpio_data); i++) {
173 struct tx53_gpio_setup *gs = &tx53_fec_gpio_data[i];
176 gpio_direction_output(gs->gpio, gs->level);
178 gpio_direction_input(gs->gpio);
181 /* configure all FEC pads as GPIO */
182 mx53_iomux_setup_pads(tx53_fec_gpio_pads, CYG_NELEM(tx53_fec_gpio_pads));
184 for (i = 0; i < CYG_NELEM(tx53_fec_gpio_data); i++) {
185 struct tx53_gpio_setup *gs = &tx53_fec_gpio_data[i];
188 if (gs->level ^ gpio_get_value(gs->gpio)) {
189 diag_printf("%s: GPIO%d_%d[%d] is not %s\n", __FUNCTION__,
190 gs->gpio / GPIO_NUM_PIN, gs->gpio % GPIO_NUM_PIN,
191 i, gs->level ? "HIGH" : "LOW");
196 diag_printf("PHY GPIO init done\n");
199 static bool mxc_fec_init(struct cyg_netdevtab_entry *tab);
200 static bool tx53_fec_init(struct cyg_netdevtab_entry *tab)
205 /* Check, whether MAC address is enabled */
206 ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
207 "fec_esa", &esa_set, CONFIG_BOOL);
208 if (!(ok && esa_set)) {
209 diag_printf("FEC disabled; set fec_esa=true to enable networking\n");
212 return mxc_fec_init(tab);
215 static void tx53_fec_phy_init(void)
217 const int phy_reset_delay = 25000; /* wait for 25ms for LAN8710 to power up */
220 * make sure the ETH PHY strap pins are pulled to the right voltage
221 * before deasserting the PHY reset GPIO
223 /* assert FEC PHY Reset (GPIO2_14) and switch PHY power on (GPIO1_3) */
225 tx53_phy_gpio_init();
228 diag_printf("Switching PHY POWER on\n");
229 gpio_set_value(FEC_RESET_GPIO, 0);
230 gpio_set_value(FEC_POWER_GPIO, 1);
232 if (!gpio_get_value(FEC_POWER_GPIO)) {
233 diag_printf("**Failed to switch PHY power on\n");
236 if (gpio_get_value(FEC_RESET_GPIO)) {
237 diag_printf("**Failed to assert PHY reset\n");
240 /* wait for 100us according to LAN8710 spec. before ... */
241 HAL_DELAY_US(phy_reset_delay);
242 /* ... deasserting FEC PHY reset */
243 if (net_debug) diag_printf("Releasing PHY RESET\n");
244 gpio_set_value(FEC_RESET_GPIO, 1);
245 if (!gpio_get_value(FEC_RESET_GPIO)) {
246 diag_printf("**Failed to release PHY reset\n");
249 /* configure all FEC pins to their required functions */
250 mx53_iomux_setup_pads(tx53_fec_pads, CYG_NELEM(tx53_fec_pads));
253 ETH_PHY_REG_LEVEL_ACCESS_FUNS(eth0_phy,
259 cyg_bool _tx53_provide_fec_esa(unsigned char *addr)
264 ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
265 "fec_esa", &enabled, CONFIG_BOOL);
267 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
268 cyg_uint8 addr2[ETHER_ADDR_LEN];
270 addr[0] = readl(SOC_FEC_MAC_BASE + 0x00);
271 addr[1] = readl(SOC_FEC_MAC_BASE + 0x04);
272 addr[2] = readl(SOC_FEC_MAC_BASE + 0x08);
273 addr[3] = readl(SOC_FEC_MAC_BASE + 0x0c);
274 addr[4] = readl(SOC_FEC_MAC_BASE + 0x10);
275 addr[5] = readl(SOC_FEC_MAC_BASE + 0x14);
277 if (cyg_plf_redboot_esa_validate(addr)) {
278 diag_printf("Ethernet FEC MAC address from fuse bank: ");
279 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
280 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
281 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
282 "fec_esa_data", addr2, CONFIG_ESA);
283 if (memcmp(addr, addr2, sizeof(addr)) != 0) {
284 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_SET,
285 "fec_esa_data", addr, CONFIG_ESA);
287 #ifdef SOC_MAC_ADDR_LOCK_FUSE
288 if ((readl(IIM_BASE_ADDR + 0x800 + SOC_MAC_ADDR_FUSE_BANK * 0x400 +
289 SOC_MAC_ADDR_LOCK_FUSE * 4) &
290 SOC_MAC_ADDR_LOCK_BIT) == 0) {
291 tx53_mac_addr_program(addr);
293 #endif // SOC_MAC_ADDR_LOCK_FUSE
296 #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
298 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
299 "fec_esa_data", addr, CONFIG_ESA);
301 diag_printf("Ethernet FEC MAC address from fconfig: ");
302 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
303 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
305 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
306 if (cyg_plf_redboot_esa_validate(addr)) {
307 tx53_mac_addr_program(addr);
311 diag_printf("** Error: Invalid MAC address: ");
312 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
313 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
315 writel(addr[0], SOC_FEC_MAC_BASE + 0x00);
316 writel(addr[1], SOC_FEC_MAC_BASE + 0x04);
317 writel(addr[2], SOC_FEC_MAC_BASE + 0x08);
318 writel(addr[3], SOC_FEC_MAC_BASE + 0x0c);
319 writel(addr[4], SOC_FEC_MAC_BASE + 0x10);
320 writel(addr[5], SOC_FEC_MAC_BASE + 0x14);
322 #ifdef SOC_MAC_ADDR_LOCK_FUSE
323 if ((readl(IIM_BASE_ADDR + 0x800 + SOC_MAC_ADDR_FUSE_BANK * 0x400 +
324 SOC_MAC_ADDR_LOCK_FUSE * 4) &
325 SOC_MAC_ADDR_LOCK_BIT) == 0) {
326 diag_printf("Use 'fconfig fec_esa_data' to set the MAC address\n");
329 diag_printf("Using MAC address from fconfig\n");
332 diag_printf("Using MAC address from fconfig\n");
333 #endif // SOC_MAC_ADDR_LOCK_FUSE
334 #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
340 static mxc_fec_priv_t mxc_fec_private = {
341 .phy = ð0_phy, // PHY access routines
342 .provide_esa = _tx53_provide_fec_esa,
345 ETH_DRV_SC(mxc_fec_sc,
346 &mxc_fec_private, // Driver specific data
354 mxc_fec_deliver, // "pseudoDSR" called from fast net thread
355 mxc_fec_poll, // poll function, encapsulates ISR and DSR
358 NETDEVTAB_ENTRY(mxc_fec_netdev,
364 #if defined(CYGPKG_REDBOOT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG)
365 RedBoot_config_option("Set FEC network hardware address [MAC]",
367 ALWAYS_ENABLED, true,
370 RedBoot_config_option("FEC network hardware address [MAC]",
375 #endif // CYGPKG_REDBOOT && CYGSEM_REDBOOT_FLASH_CONFIG
377 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
378 // Note that this section *is* active in an application, outside RedBoot,
379 // where the above section is not included.
381 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
382 #endif // CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
384 #endif // __WANT_DEVS