]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/devs/eth/arm/tx53karo/v1_0/include/devs_eth_arm_tx53.inl
TX53 Release 2011-12-20
[karo-tx-redboot.git] / packages / devs / eth / arm / tx53karo / v1_0 / include / devs_eth_arm_tx53.inl
1 //==========================================================================
2 //
3 //      devs_eth_arm_tx53.inl
4 //
5 //      Board ethernet I/O definitions.
6 //
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.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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 //===========================================================================
41
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>
45
46 #ifdef CYGPKG_REDBOOT
47 #include <pkgconf/redboot.h>
48 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
49 #include <redboot.h>
50 #include <flash_config.h>
51 #endif
52 #endif
53
54
55 #ifdef __WANT_DEVS
56
57 #ifdef CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
58
59 #ifdef CYGPKG_DEVS_ETH_PHY
60
61 static char  mxc_fec_name[] = "mxc_fec";
62
63 #define FEC_POWER_GPIO                                  MX53_GPIO_NR(3, 20)
64 #define FEC_RESET_GPIO                                  MX53_GPIO_NR(7, 6)
65
66 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
67 //
68 // Verify that the given ESA is valid for this platform
69 //
70 static char oui[3] = CYGDAT_DEVS_ETH_ARM_TX53KARO_OUI;
71
72 bool
73 cyg_plf_redboot_esa_validate(unsigned char *val)
74 {
75         return (val[0] == oui[0]) && (val[1] == oui[1]) && (val[2] == oui[2]);
76 }
77 #endif
78
79 extern int tx53_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN]);
80
81 static inline void tx53_write_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset, CYG_WORD32 val)
82 {
83         if (net_debug) {
84                 diag_printf("Changing reg %08x from %08x to %08x\n",
85                                         base_addr + offset, readl(base_addr + offset), val);
86         }
87         HAL_WRITE_UINT32(base_addr + offset, val);
88 }
89
90 static inline CYG_WORD32 tx53_read_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset)
91 {
92         CYG_WORD32 val;
93
94         HAL_READ_UINT32(base_addr + offset, val);
95         if (net_debug) diag_printf("Read %08x from reg %08x\n", val, base_addr + offset);
96         return val;
97 }
98
99 static inline void tx53_set_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset,
100                                                                 CYG_WORD32 set_mask, CYG_WORD32 clr_mask)
101 {
102         CYG_WORD32 val;
103
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);
109 }
110
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,
123
124         /* PHY reset */
125         MX53_PAD_PATA_DA_0__GPIO_7_6 | IOMUX_CONFIG_SION,
126         /* PHY power */
127         MX53_PAD_EIM_D20__GPIO_3_20 | IOMUX_CONFIG_SION,
128 };
129
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,
141 };
142
143 static struct tx53_gpio_setup {
144         unsigned gpio:9,
145                 dir:1,
146                 level:1;
147 } tx53_fec_gpio_data[] = {
148         /*                                       dir,
149          *                               gpio,   level */
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 */
162 };
163
164 static inline void tx53_phy_gpio_init(void)
165 {
166         int i;
167
168         if (net_debug)
169                 diag_printf("Initializing PHY GPIOs\n");
170
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];
174
175                 if (gs->dir)
176                         gpio_direction_output(gs->gpio, gs->level);
177                 else
178                         gpio_direction_input(gs->gpio);
179         }
180
181         /* configure all FEC pads as GPIO */
182         mx53_iomux_setup_pads(tx53_fec_gpio_pads, CYG_NELEM(tx53_fec_gpio_pads));
183
184         for (i = 0; i < CYG_NELEM(tx53_fec_gpio_data); i++) {
185                 struct tx53_gpio_setup *gs = &tx53_fec_gpio_data[i];
186
187                 if (gs->dir) {
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");
192                         }
193                 }
194         }
195         if (net_debug)
196                 diag_printf("PHY GPIO init done\n");
197 }
198
199 static bool mxc_fec_init(struct cyg_netdevtab_entry *tab);
200 static bool tx53_fec_init(struct cyg_netdevtab_entry *tab)
201 {
202         cyg_bool esa_set;
203         int ok;
204
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");
210                 return false;
211         }
212         return mxc_fec_init(tab);
213 }
214
215 static void tx53_fec_phy_init(void)
216 {
217         const int phy_reset_delay = 25000;      /* wait for 25ms for LAN8710 to power up */
218
219         /*
220          * make sure the ETH PHY strap pins are pulled to the right voltage
221          * before deasserting the PHY reset GPIO
222          */
223         /* assert FEC PHY Reset (GPIO2_14) and switch PHY power on (GPIO1_3) */
224
225         tx53_phy_gpio_init();
226
227         if (net_debug)
228                 diag_printf("Switching PHY POWER on\n");
229         gpio_set_value(FEC_RESET_GPIO, 0);
230         gpio_set_value(FEC_POWER_GPIO, 1);
231
232         if (!gpio_get_value(FEC_POWER_GPIO)) {
233                 diag_printf("**Failed to switch PHY power on\n");
234         }
235
236         if (gpio_get_value(FEC_RESET_GPIO)) {
237                 diag_printf("**Failed to assert PHY reset\n");
238         }
239
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");
247         }
248
249         /* configure all FEC pins to their required functions */
250         mx53_iomux_setup_pads(tx53_fec_pads, CYG_NELEM(tx53_fec_pads));
251 }
252
253 ETH_PHY_REG_LEVEL_ACCESS_FUNS(eth0_phy,
254                                                           tx53_fec_phy_init,
255                                                           mxc_fec_phy_reset,
256                                                           mxc_fec_phy_write,
257                                                           mxc_fec_phy_read);
258
259 cyg_bool _tx53_provide_fec_esa(unsigned char *addr)
260 {
261         cyg_bool enabled;
262         int ok;
263
264         ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
265                                          "fec_esa", &enabled, CONFIG_BOOL);
266         if (ok && enabled) {
267 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
268                 cyg_uint8 addr2[ETHER_ADDR_LEN];
269
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);
276
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);
286                         }
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);
292                         }
293 #endif // SOC_MAC_ADDR_LOCK_FUSE
294                         return true;
295                 }
296 #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
297
298                 CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
299                                                                         "fec_esa_data", addr, CONFIG_ESA);
300
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]);
304
305 #ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
306                 if (cyg_plf_redboot_esa_validate(addr)) {
307                         tx53_mac_addr_program(addr);
308                         return true;
309                 }
310
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]);
314
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);
321
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");
327                         return false;
328                 } else {
329                         diag_printf("Using MAC address from fconfig\n");
330                 }
331 #else
332                 diag_printf("Using MAC address from fconfig\n");
333 #endif // SOC_MAC_ADDR_LOCK_FUSE
334 #endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
335                 return true;
336         }
337         return false;
338 }
339
340 static mxc_fec_priv_t mxc_fec_private = {
341         .phy = &eth0_phy,                                                         // PHY access routines
342         .provide_esa = _tx53_provide_fec_esa,
343 };
344
345 ETH_DRV_SC(mxc_fec_sc,
346                    &mxc_fec_private, // Driver specific data
347                    mxc_fec_name,
348                    mxc_fec_start,
349                    mxc_fec_stop,
350                    mxc_fec_control,
351                    mxc_fec_can_send,
352                    mxc_fec_send,
353                    mxc_fec_recv,
354                    mxc_fec_deliver,             // "pseudoDSR" called from fast net thread
355                    mxc_fec_poll,                // poll function, encapsulates ISR and DSR
356                    mxc_fec_int_vector);
357
358 NETDEVTAB_ENTRY(mxc_fec_netdev,
359                                 mxc_fec_name,
360                                 tx53_fec_init,
361                                 &mxc_fec_sc);
362 #endif
363
364 #if defined(CYGPKG_REDBOOT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG)
365 RedBoot_config_option("Set FEC network hardware address [MAC]",
366                                           fec_esa,
367                                           ALWAYS_ENABLED, true,
368                                           CONFIG_BOOL, true
369                                          );
370 RedBoot_config_option("FEC network hardware address [MAC]",
371                                           fec_esa_data,
372                                           "fec_esa", true,
373                                           CONFIG_ESA, 0
374                                          );
375 #endif // CYGPKG_REDBOOT && CYGSEM_REDBOOT_FLASH_CONFIG
376
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.
380
381 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
382 #endif // CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
383
384 #endif // __WANT_DEVS