1 //==========================================================================
3 // devs_eth_arm_tx51.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/mx51_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 MX51_GPIO_ADDR(bank) (GPIO1_BASE_ADDR + (((bank) - 1) << 14))
64 #define FEC_POWER_GPIO 1, 3
65 #define FEC_RESET_GPIO 2, 14
67 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
69 // Verify that the given ESA is valid for this platform
71 static char oui[3] = CYGDAT_DEVS_ETH_ARM_TX51KARO_OUI;
74 cyg_plf_redboot_esa_validate(unsigned char *val)
76 return (val[0] == oui[0]) && (val[1] == oui[1]) && (val[2] == oui[2]);
80 extern int tx51_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN]);
82 static inline void tx51_write_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset, CYG_WORD32 val)
85 diag_printf("Changing reg %08x from %08x to %08x\n",
86 base_addr + offset, readl(base_addr + offset), val);
88 HAL_WRITE_UINT32(base_addr + offset, val);
91 static inline CYG_WORD32 tx51_read_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset)
95 HAL_READ_UINT32(base_addr + offset, val);
96 if (net_debug) diag_printf("Read %08x from reg %08x\n", val, base_addr + offset);
100 static inline void tx51_set_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset,
101 CYG_WORD32 set_mask, CYG_WORD32 clr_mask)
105 HAL_READ_UINT32(base_addr + offset, val);
106 if (net_debug) diag_printf("Changing reg %08x from %08x to %08x\n", base_addr + offset, val,
107 (val & ~clr_mask) | set_mask);
108 val = (val & ~clr_mask) | set_mask;
109 HAL_WRITE_UINT32(base_addr + offset, val);
112 static struct tx51_gpio_setup {
113 cyg_uint32 iomux_addr;
118 } tx51_fec_gpio_data[] = {
119 /* iomux reg offset, func, gpgrp, */
120 /* gpiofn, gpshift, */
121 { IOMUXC_SW_MUX_CTL_PAD_NANDF_CS3, 0x12, 0x13, 3, 19, }, /* MDC */
122 { IOMUXC_SW_MUX_CTL_PAD_EIM_EB2, 0x13, 0x11, 2, 22, }, /* MDIO */
123 { IOMUXC_SW_MUX_CTL_PAD_NANDF_RB3, 0x11, 0x13, 3, 11, }, /* RXC */
124 { IOMUXC_SW_MUX_CTL_PAD_NANDF_D11, 0x12, 0x13, 3, 29, }, /* RDV */
125 { IOMUXC_SW_MUX_CTL_PAD_NANDF_D9, 0x12, 0x13, 3, 31, }, /* RXD0 */
126 { IOMUXC_SW_MUX_CTL_PAD_EIM_EB3, 0x13, 0x11, 2, 23, }, /* RXD1 */
127 { IOMUXC_SW_MUX_CTL_PAD_EIM_CS2, 0x13, 0x11, 2, 27, }, /* RXD2 */
128 { IOMUXC_SW_MUX_CTL_PAD_EIM_CS3, 0x13, 0x11, 2, 28, }, /* RXD3 */
129 { IOMUXC_SW_MUX_CTL_PAD_EIM_CS4, 0x13, 0x11, 2, 29, }, /* RX_ER */
130 { IOMUXC_SW_MUX_CTL_PAD_NANDF_RDY_INT, 0x11, 0x13, 3, 24, }, /* TXC */
131 { IOMUXC_SW_MUX_CTL_PAD_NANDF_CS7, 0x11, 0x13, 3, 23, }, /* TXE */
132 { IOMUXC_SW_MUX_CTL_PAD_NANDF_D8, 0x12, 0x13, 4, 0, }, /* TXD0 */
133 { IOMUXC_SW_MUX_CTL_PAD_NANDF_CS4, 0x12, 0x13, 3, 20, }, /* TXD1 */
134 { IOMUXC_SW_MUX_CTL_PAD_NANDF_CS5, 0x12, 0x13, 3, 21, }, /* TXD2 */
135 { IOMUXC_SW_MUX_CTL_PAD_NANDF_CS6, 0x12, 0x13, 3, 22, }, /* TXD3 */
136 { IOMUXC_SW_MUX_CTL_PAD_NANDF_RB2, 0x11, 0x13, 3, 10, }, /* COL */
137 { IOMUXC_SW_MUX_CTL_PAD_EIM_CS5, 0x13, 0x11, 2, 30, }, /* CRS */
138 { IOMUXC_SW_MUX_CTL_PAD_NANDF_CS2, 0x13, 0x13, 3, 18, }, /* TX_ER */
141 static struct tx51_gpio_setup tx51_fec_pwr_pins[] = {
142 { IOMUXC_SW_MUX_CTL_PAD_EIM_A20, 0x11, 0x11, 2, 14, }, /* PHY reset */
143 { IOMUXC_SW_MUX_CTL_PAD_GPIO1_3, 0x10, 0x10, 1, 3, }, /* PHY power enable */
146 static struct tx51_gpio_setup tx51_fec_strap_pins[] = {
147 { IOMUXC_SW_MUX_CTL_PAD_GPIO1_3, 0x10, 0x10, 1, 3, }, /* PHY Power enable */
148 { IOMUXC_SW_MUX_CTL_PAD_NANDF_D9, 0x12, 0x13, 3, 31, }, /* Mode[0] */
149 { IOMUXC_SW_MUX_CTL_PAD_EIM_EB3, 0x13, 0x11, 2, 23, }, /* Mode[1] */
150 { IOMUXC_SW_MUX_CTL_PAD_EIM_CS2, 0x13, 0x11, 2, 27, }, /* Mode[2] */
151 { IOMUXC_SW_MUX_CTL_PAD_EIM_CS3, 0x13, 0x11, 2, 28, }, /* nINTSEL */
154 static inline void tx51_phy_power_off(void)
158 if (net_debug) diag_printf("Switching PHY POWER off\n");
160 for (i = 0; i < NUM_ELEMS(tx51_fec_gpio_data); i++) {
161 struct tx51_gpio_setup *gs = &tx51_fec_gpio_data[i];
163 if (net_debug) diag_printf("%s: GPIO%d_%d[%d] is %d\n", __FUNCTION__,
164 gs->grp, gs->shift, i,
165 gpio_tst_bit(gs->grp, gs->shift));
168 /* deassert all pins attached to the PHY */
169 for (i = 0; i < NUM_ELEMS(tx51_fec_pwr_pins); i++) {
170 struct tx51_gpio_setup *gs = &tx51_fec_pwr_pins[i];
172 tx51_set_reg(MX51_GPIO_ADDR(gs->grp),
173 GPIO_DR, 0, 1 << gs->shift);
174 tx51_set_reg(MX51_GPIO_ADDR(gs->grp),
175 GPIO_GDIR, 1 << gs->shift, 0);
177 for (i = 0; i < NUM_ELEMS(tx51_fec_gpio_data); i++) {
178 struct tx51_gpio_setup *gs = &tx51_fec_gpio_data[i];
180 tx51_set_reg(MX51_GPIO_ADDR(gs->grp),
181 GPIO_GDIR, 0, 1 << gs->shift);
183 tx51_set_reg(MX51_GPIO_ADDR(gs->grp),
184 GPIO_DR, 0, 1 << gs->shift);
185 tx51_set_reg(MX51_GPIO_ADDR(gs->grp),
186 GPIO_GDIR, 1 << gs->shift, 0);
188 tx51_write_reg(0, gs->iomux_addr, gs->off_func);
190 for (i = 0; i < NUM_ELEMS(tx51_fec_gpio_data); i++) {
191 struct tx51_gpio_setup *gs = &tx51_fec_gpio_data[i];
193 if (gpio_tst_bit(gs->grp, gs->shift)) {
194 diag_printf("%s: GPIO%d_%d[%d] is not low\n", __FUNCTION__,
195 gs->grp, gs->shift, i);
198 if (net_debug) diag_printf("PHY POWER off done\n");
201 static bool mxc_fec_init(struct cyg_netdevtab_entry *tab);
202 static bool tx51_fec_init(struct cyg_netdevtab_entry *tab)
208 /* Check, whether MAC address is enabled */
209 ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
210 "fec_esa", &esa_set, CONFIG_BOOL);
216 if (!(ok && esa_set)) {
217 diag_printf("FEC disabled; set fec_esa=true to enable networking\n");
221 return mxc_fec_init(tab);
224 static void tx51_fec_phy_init(void)
227 int phy_reset_delay = 100;
234 * make sure the ETH PHY strap pins are pulled to the right voltage
235 * before deasserting the PHY reset GPIO
237 /* assert FEC PHY Reset (GPIO2_14) and switch PHY power on (GPIO1_3) */
240 tx51_phy_power_off();
243 if (!gpio_tst_bit(1, 3)) {
244 if (0 || net_debug) diag_printf("Switching PHY POWER on\n");
247 /* wait for 22ms for LAN8700 to power up */
248 phy_reset_delay = 22000;
250 if (!gpio_tst_bit(1, 3)) {
251 diag_printf("**Failed to switch PHY power on: GPIO1_PSR[%08lx]=%08x\n",
252 MX51_GPIO_ADDR(1) + GPIO_PSR,
253 tx51_read_reg(MX51_GPIO_ADDR(1), GPIO_PSR));
257 if (gpio_tst_bit(2, 14)) {
258 diag_printf("**Failed to assert PHY reset: GPIO2_PSR[%08lx]=%08x\n",
259 MX51_GPIO_ADDR(2) + GPIO_PSR,
260 tx51_read_reg(MX51_GPIO_ADDR(2), GPIO_PSR));
264 if (0 || net_debug) diag_printf("Asserting PHY RESET\n");
267 if (gpio_tst_bit(2, 14)) {
268 diag_printf("**Failed to assert PHY reset: GPIO2_PSR[%08lx]=%08x\n",
269 MX51_GPIO_ADDR(2) + GPIO_PSR,
270 tx51_read_reg(MX51_GPIO_ADDR(2), GPIO_PSR));
274 for (i = 0; i < NUM_ELEMS(tx51_fec_gpio_data); i++) {
275 struct tx51_gpio_setup *gs = &tx51_fec_gpio_data[i];
279 for (j = 0; j < NUM_ELEMS(tx51_fec_strap_pins); j++) {
280 struct tx51_gpio_setup *sp = &tx51_fec_strap_pins[j];
282 if (gs->grp == sp->grp && gs->shift == sp->shift) {
288 gpio_set_bit(gs->grp, gs->shift);
289 if (net_debug) diag_printf("Setting GPIO%d_%d[%d] high\n",
290 gs->grp, gs->shift, i);
292 gpio_clr_bit(gs->grp, gs->shift);
293 if (net_debug) diag_printf("Setting GPIO%d_%d[%d] low\n",
294 gs->grp, gs->shift, i);
296 tx51_set_reg(MX51_GPIO_ADDR(gs->grp),
297 GPIO_GDIR, 1 << gs->shift, 0);
298 tx51_write_reg(0, gs->iomux_addr,
302 /* configure FEC strap pins to their required values */
303 for (i = 0; i < NUM_ELEMS(tx51_fec_strap_pins); i++) {
304 struct tx51_gpio_setup *gs = &tx51_fec_strap_pins[i];
306 if (net_debug) diag_printf("Asserting GPIO%d_%d\n", gs->grp,
308 tx51_set_reg(MX51_GPIO_ADDR(gs->grp),
309 GPIO_GDIR, 1 << gs->shift, 0);
310 tx51_set_reg(MX51_GPIO_ADDR(gs->grp),
311 GPIO_DR, 1 << gs->shift, 0);
312 tx51_write_reg(0, gs->iomux_addr,
314 gpio_set_bit(gs->grp, gs->shift);
315 if (!gpio_tst_bit(gs->grp, gs->shift)) {
316 diag_printf("**Failed to assert GPIO%d_%d: GPIO%d_PSR[%08lx]=%08x\n",
317 gs->grp, gs->shift, gs->grp,
318 MX51_GPIO_ADDR(gs->grp) + GPIO_PSR,
319 tx51_read_reg(MX51_GPIO_ADDR(gs->grp), GPIO_PSR));
323 for (i = 0; i < NUM_ELEMS(tx51_fec_gpio_data); i++) {
324 struct tx51_gpio_setup *gs = &tx51_fec_gpio_data[i];
328 for (j = 0; j < NUM_ELEMS(tx51_fec_strap_pins); j++) {
329 struct tx51_gpio_setup *sp = &tx51_fec_strap_pins[j];
331 if (gs->grp == sp->grp && gs->shift == sp->shift) {
337 if (!gpio_tst_bit(gs->grp, gs->shift)) {
338 diag_printf("GPIO%d_%d[%d] is low instead of high\n",
339 gs->grp, gs->shift, i);
342 if (gpio_tst_bit(gs->grp, gs->shift)) {
343 diag_printf("GPIO%d_%d[%d] is high instead of low\n",
344 gs->grp, gs->shift, i);
348 /* wait for 100us according to LAN8700 spec. before ... */
349 HAL_DELAY_US(phy_reset_delay);
350 /* ... deasserting FEC PHY reset */
351 if (0 || net_debug) diag_printf("Releasing PHY RESET\n");
353 if (!gpio_tst_bit(2, 14)) {
354 diag_printf("**Failed to release PHY reset\n");
357 /* configure all FEC pins to their required functions */
358 for (i = 0; i < NUM_ELEMS(tx51_fec_gpio_data); i++) {
359 struct tx51_gpio_setup *gs = &tx51_fec_gpio_data[i];
361 tx51_write_reg(0, gs->iomux_addr, gs->on_func);
367 ETH_PHY_REG_LEVEL_ACCESS_FUNS(eth0_phy,
373 cyg_bool _tx51_provide_fec_esa(unsigned char *addr)
378 ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
379 "fec_esa", &enabled, CONFIG_BOOL);
381 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
382 cyg_uint8 addr2[ETHER_ADDR_LEN];
384 addr[0] = readl(SOC_FEC_MAC_BASE + 0x14);
385 addr[1] = readl(SOC_FEC_MAC_BASE + 0x10);
386 addr[2] = readl(SOC_FEC_MAC_BASE + 0xC);
387 addr[3] = readl(SOC_FEC_MAC_BASE + 0x8);
388 addr[4] = readl(SOC_FEC_MAC_BASE + 0x4);
389 addr[5] = readl(SOC_FEC_MAC_BASE + 0x0);
391 if (cyg_plf_redboot_esa_validate(addr)) {
392 diag_printf("Ethernet FEC MAC address from fuse bank: ");
393 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
394 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
395 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
396 "fec_esa_data", addr2, CONFIG_ESA);
397 if (memcmp(addr, addr2, sizeof(addr)) != 0) {
398 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_SET,
399 "fec_esa_data", addr, CONFIG_ESA);
401 #ifdef SOC_MAC_ADDR_LOCK_FUSE
402 if ((readl(IIM_BASE_ADDR + 0x800 + SOC_MAC_ADDR_FUSE_BANK * 0x400 +
403 SOC_MAC_ADDR_LOCK_FUSE * 4) &
404 SOC_MAC_ADDR_LOCK_BIT) == 0) {
405 tx51_mac_addr_program(addr);
407 #endif // SOC_MAC_ADDR_LOCK_FUSE
410 #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
412 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
413 "fec_esa_data", addr, CONFIG_ESA);
415 diag_printf("Ethernet FEC MAC address from fconfig: ");
416 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
417 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
419 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
420 if (cyg_plf_redboot_esa_validate(addr)) {
421 tx51_mac_addr_program(addr);
425 diag_printf("** Error: Invalid MAC address: ");
426 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
427 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
429 writel(addr[0], SOC_FEC_MAC_BASE + 0x14);
430 writel(addr[1], SOC_FEC_MAC_BASE + 0x10);
431 writel(addr[2], SOC_FEC_MAC_BASE + 0xC);
432 writel(addr[3], SOC_FEC_MAC_BASE + 0x8);
433 writel(addr[4], SOC_FEC_MAC_BASE + 0x4);
434 writel(addr[5], SOC_FEC_MAC_BASE + 0x0);
436 #ifdef SOC_MAC_ADDR_LOCK_FUSE
437 if ((readl(IIM_BASE_ADDR + 0x800 + SOC_MAC_ADDR_FUSE_BANK * 0x400 +
438 SOC_MAC_ADDR_LOCK_FUSE * 4) &
439 SOC_MAC_ADDR_LOCK_BIT) == 0) {
440 diag_printf("Use 'fconfig fec_esa_data' to set the MAC address\n");
443 diag_printf("Using MAC address from fconfig\n");
446 diag_printf("Using MAC address from fconfig\n");
447 #endif // SOC_MAC_ADDR_LOCK_FUSE
448 #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
454 static mxc_fec_priv_t mxc_fec_private = {
455 .phy = ð0_phy, // PHY access routines
456 .provide_esa = _tx51_provide_fec_esa,
459 ETH_DRV_SC(mxc_fec_sc,
460 &mxc_fec_private, // Driver specific data
468 mxc_fec_deliver, // "pseudoDSR" called from fast net thread
469 mxc_fec_poll, // poll function, encapsulates ISR and DSR
472 NETDEVTAB_ENTRY(mxc_fec_netdev,
478 #if defined(CYGPKG_REDBOOT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG)
479 RedBoot_config_option("Set FEC network hardware address [MAC]",
481 ALWAYS_ENABLED, true,
484 RedBoot_config_option("FEC network hardware address [MAC]",
489 #endif // CYGPKG_REDBOOT && CYGSEM_REDBOOT_FLASH_CONFIG
491 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
492 // Note that this section *is* active in an application, outside RedBoot,
493 // where the above section is not included.
495 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
496 #endif // CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
498 #endif // __WANT_DEVS