1 //==========================================================================
3 // devs_eth_arm_tx27.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>
46 #include <pkgconf/redboot.h>
47 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
49 #include <flash_config.h>
56 #ifdef CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
58 #ifdef CYGPKG_DEVS_ETH_PHY
60 static char mxc_fec_name[] = "mxc_fec";
62 #define OCR_SHIFT(bit) (((bit) * 2) % 32)
63 #define OCR_MASK(bit) (3 << (OCR_SHIFT(bit)))
64 #define OCR_VAL(bit,val) (((val) << (OCR_SHIFT(bit))) & (OCR_MASK(bit)))
65 #define GPR_SHIFT(bit) (bit)
66 #define GPR_MASK(bit) (1 << (GPR_SHIFT(bit)))
67 #define GPR_VAL(bit,val) (((val) << (GPR_SHIFT(bit))) & (GPR_MASK(bit)))
69 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
71 // Verify that the given ESA is valid for this platform
73 static char oui[3] = CYGDAT_DEVS_ETH_ARM_TX27KARO_OUI;
76 cyg_plf_redboot_esa_validate(unsigned char *val)
78 return (val[0] == oui[0]) && (val[1] == oui[1]) && (val[2] == oui[2]);
82 extern int tx27_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN]);
84 static inline void tx27_set_reg(unsigned long addr, CYG_WORD32 set, CYG_WORD32 clr)
87 HAL_READ_UINT32(addr, val);
88 //diag_printf("Changing reg %08lx from %08x to %08x\n", addr, val, (val & ~clr) | set);
89 val = (val & ~clr) | set;
90 HAL_WRITE_UINT32(addr, val);
93 static inline void tx27_phy_power_off(void)
95 if (net_debug) diag_printf("Switching PHY POWER off\n");
98 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR1, 0xffffffff, 0);
99 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DR, 0, 0xffff);
100 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, 0xffff, 0);
101 tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, 0xffff, 0);
104 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR2, OCR_MASK(16), 0);
105 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DR, 0, GPR_MASK(16));
106 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, GPR_MASK(16), 0);
107 tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, GPR_MASK(16), 0);
110 tx27_set_reg(SOC_GPIOF_BASE + GPIO_OCR2, OCR_MASK(23), 0);
111 tx27_set_reg(SOC_GPIOF_BASE + GPIO_DR, 0, GPR_MASK(23));
112 tx27_set_reg(SOC_GPIOF_BASE + GPIO_DDIR, GPR_MASK(23), 0);
113 tx27_set_reg(SOC_GPIOF_BASE + GPIO_GIUS, GPR_MASK(23), 0);
115 tx27_set_reg(SOC_GPIOB_BASE + GPIO_DR, 0, GPR_MASK(27) | GPR_MASK(30));
118 static bool mxc_fec_init(struct cyg_netdevtab_entry *tab);
119 static bool tx27_fec_init(struct cyg_netdevtab_entry *tab)
124 /* Check, whether MAC address is enabled */
125 ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
126 "fec_esa", &esa_set, CONFIG_BOOL);
127 if (!(ok && esa_set)) {
128 diag_printf("FEC disabled; set fec_esa=true to enable networking\n");
131 return mxc_fec_init(tab);
134 static void tx27_fec_phy_init(void)
138 int phy_reset_delay = 100;
140 ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
141 "fec_esa", &esa_set, CONFIG_BOOL);
142 if (!(ok && esa_set)) {
143 tx27_phy_power_off();
148 * make sure the ETH PHY strap pins are pulled to the right voltage
149 * before deasserting the PHY reset GPIO
162 // assert FEC PHY Reset (PB30) and switch PHY power on
163 /* PB22, PB27, PB30 => GPIO out */
165 if (!gpio_tst_bit(1, 27)) {
166 if (net_debug) diag_printf("Switching PHY POWER on\n");
167 tx27_set_reg(SOC_GPIOB_BASE + GPIO_DR, GPR_MASK(27), GPR_MASK(30));
168 /* wait for 22ms for LAN8700 to power up */
169 phy_reset_delay = 22000;
171 if (net_debug) diag_printf("Asserting PHY RESET\n");
172 tx27_set_reg(SOC_GPIOB_BASE + GPIO_DR, 0, GPR_MASK(30));
175 const unsigned int phy_mode_mask = 0x10e0;
176 // deassert PD0-15 (except 5,6,7,12 => PHY MODE[0..2], INTSEL)
177 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR1, 0xffffffff, 0);
178 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DR, phy_mode_mask, ~phy_mode_mask);
179 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, 0xffff, 0);
180 tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, 0xffff, 0);
183 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR2, OCR_MASK(16), 0);
184 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DR, 0, GPR_MASK(16));
185 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, GPR_MASK(16), 0);
186 tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, GPR_MASK(16), 0);
189 tx27_set_reg(SOC_GPIOF_BASE + GPIO_OCR2, OCR_MASK(23), 0);
190 tx27_set_reg(SOC_GPIOF_BASE + GPIO_DR, 0, GPR_MASK(23));
191 tx27_set_reg(SOC_GPIOF_BASE + GPIO_DDIR, GPR_MASK(23), 0);
192 tx27_set_reg(SOC_GPIOF_BASE + GPIO_GIUS, GPR_MASK(23), 0);
194 /* wait for 100us according to LAN8700 spec. before ... */
195 HAL_DELAY_US(phy_reset_delay);
197 /* ... deasserting FEC PHY reset */
198 if (net_debug) diag_printf("Releasing PHY RESET\n");
199 tx27_set_reg(SOC_GPIOB_BASE + GPIO_DR, GPR_MASK(30), 0);
201 // program PF23 as FEC_TXEN
202 tx27_set_reg(SOC_GPIOF_BASE + GPIO_OCR2, 0, OCR_MASK(23));
203 tx27_set_reg(SOC_GPIOF_BASE + GPIO_DDIR, GPR_MASK(23), 0);
204 tx27_set_reg(SOC_GPIOF_BASE + GPIO_GIUS, GPR_MASK(23), 0);
206 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR2, 0, OCR_MASK(16));
207 tx27_set_reg(SOC_GPIOD_BASE + GPIO_OCR1, 0, 0x000C00FF);
208 tx27_set_reg(SOC_GPIOD_BASE + GPIO_ICONFA1, 0, 0xFFF0FF00);
209 tx27_set_reg(SOC_GPIOD_BASE + GPIO_GPR, GPR_MASK(8), 0);
210 tx27_set_reg(SOC_GPIOD_BASE + GPIO_DDIR, 0x0001020F, 0x0001FFFF);
211 tx27_set_reg(SOC_GPIOD_BASE + GPIO_GIUS, 0x0001FEFF, 0x0001FFFF);
214 ETH_PHY_REG_LEVEL_ACCESS_FUNS(eth0_phy,
220 cyg_bool _tx27_provide_fec_esa(unsigned char *addr)
225 ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
226 "fec_esa", &enabled, CONFIG_BOOL);
228 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
229 cyg_uint8 addr2[ETHER_ADDR_LEN];
231 addr[0] = readl(SOC_FEC_MAC_BASE2 + 0x0);
232 addr[1] = readl(SOC_FEC_MAC_BASE2 + 0x4);
233 addr[2] = readl(SOC_FEC_MAC_BASE2 + 0x8);
234 addr[3] = readl(SOC_FEC_MAC_BASE2 + 0xC);
235 addr[4] = readl(SOC_FEC_MAC_BASE2 + 0x10);
236 addr[5] = readl(SOC_FEC_MAC_BASE2 + 0x14);
238 if (cyg_plf_redboot_esa_validate(addr)) {
239 diag_printf("Ethernet FEC MAC address from fuse bank: ");
240 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
241 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
242 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
243 "fec_esa_data", addr2, CONFIG_ESA);
244 if (memcmp(addr, addr2, sizeof(addr)) != 0) {
245 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_SET,
246 "fec_esa_data", addr, CONFIG_ESA);
248 #ifdef SOC_MAC_ADDR_LOCK
249 if ((readl(SOC_FEC_MAC_BASE2 - 0x14) & SOC_MAC_ADDR_LOCK) == 0) {
250 tx27_mac_addr_program(addr);
252 #endif // SOC_MAC_ADDR_LOCK
255 #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
257 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
258 "fec_esa_data", addr, CONFIG_ESA);
260 diag_printf("Ethernet FEC MAC address from fconfig: ");
261 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
262 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
264 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
265 if (cyg_plf_redboot_esa_validate(addr)) {
266 tx27_mac_addr_program(addr);
270 diag_printf("** Error: Invalid MAC address: ");
271 diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
272 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
274 #ifdef SOC_MAC_ADDR_LOCK
275 if ((readl(SOC_FEC_MAC_BASE2 - 0x14) & SOC_MAC_ADDR_LOCK) == 0) {
276 diag_printf("Use 'fconfig fec_esa_data' to set the MAC address\n");
279 diag_printf("Using MAC address from fconfig\n");
282 diag_printf("Using MAC address from fconfig\n");
283 #endif // SOC_MAC_ADDR_LOCK
284 #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
290 static mxc_fec_priv_t mxc_fec_private = {
291 .phy = ð0_phy, // PHY access routines
292 .provide_esa = _tx27_provide_fec_esa,
295 ETH_DRV_SC(mxc_fec_sc,
296 &mxc_fec_private, // Driver specific data
304 mxc_fec_deliver, // "pseudoDSR" called from fast net thread
305 mxc_fec_poll, // poll function, encapsulates ISR and DSR
308 NETDEVTAB_ENTRY(mxc_fec_netdev,
314 #if defined(CYGPKG_REDBOOT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG)
315 RedBoot_config_option("Set FEC network hardware address [MAC]",
317 ALWAYS_ENABLED, true,
320 RedBoot_config_option("FEC network hardware address [MAC]",
325 #endif // CYGPKG_REDBOOT && CYGSEM_REDBOOT_FLASH_CONFIG
327 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
328 // Note that this section *is* active in an application, outside RedBoot,
329 // where the above section is not included.
331 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
332 #endif // CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
334 #endif // __WANT_DEVS