]> git.karo-electronics.de Git - karo-tx-redboot.git/blobdiff - packages/devs/eth/arm/tx25karo/v1_0/include/devs_eth_arm_tx25.inl
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / eth / arm / tx25karo / v1_0 / include / devs_eth_arm_tx25.inl
diff --git a/packages/devs/eth/arm/tx25karo/v1_0/include/devs_eth_arm_tx25.inl b/packages/devs/eth/arm/tx25karo/v1_0/include/devs_eth_arm_tx25.inl
new file mode 100644 (file)
index 0000000..ac80aeb
--- /dev/null
@@ -0,0 +1,508 @@
+//==========================================================================
+//
+//      devs_eth_arm_tx25.inl
+//
+//      Board ethernet I/O definitions.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
+
+#include <cyg/hal/hal_intr.h>           // CYGNUM_HAL_INTERRUPT_ETHR
+#include <cyg/hal/hal_if.h>
+
+#ifdef CYGPKG_REDBOOT
+#include <pkgconf/redboot.h>
+#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+#include <redboot.h>
+#include <flash_config.h>
+#endif
+#endif
+
+
+#ifdef __WANT_DEVS
+
+#ifdef CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
+
+#ifdef CYGPKG_DEVS_ETH_PHY
+
+static char  mxc_fec_name[] = "mxc_fec";
+
+#define OCR_SHIFT(bit)         (((bit) * 2) % 32)
+#define OCR_MASK(bit)          (3 << (OCR_SHIFT(bit)))
+#define OCR_VAL(bit,val)       (((val) << (OCR_SHIFT(bit))) & (OCR_MASK(bit)))
+#define GPR_SHIFT(bit)         (bit)
+#define GPR_MASK(bit)          (1 << (GPR_SHIFT(bit)))
+#define GPR_VAL(bit,val)       (((val) << (GPR_SHIFT(bit))) & (GPR_MASK(bit)))
+
+#ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
+//
+// Verify that the given ESA is valid for this platform
+//
+static char oui[3] = CYGDAT_DEVS_ETH_ARM_TX25KARO_OUI;
+
+bool
+cyg_plf_redboot_esa_validate(unsigned char *val)
+{
+       return (val[0] == oui[0]) && (val[1] == oui[1]) && (val[2] == oui[2]);
+}
+#endif
+
+extern int tx25_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN]);
+
+static inline CYG_ADDRESS MX25_GPIO_ADDR(int bank)
+{
+       switch (bank) {
+       case 1:
+               return GPIO1_BASE_ADDR;
+       case 2:
+               return GPIO2_BASE_ADDR;
+       case 3:
+               return GPIO3_BASE_ADDR;
+       case 4:
+               return GPIO4_BASE_ADDR;
+       }
+       return ~0;
+}
+
+/*
+TX27 -> TX25 GPIO cross reference
+                               TX27  GP  Fkt GPIO         Pad             IOMUXC SW_PAD  SW_PAD strap
+                               GPIO  ALT ALT                                      OFFSET  CTRL    MUX   option
+FEC_MDC                        PD9       5       0       GPIO3_5  FEC_MDC         0x1c8   0x3c0
+FEC_MDIO               PD8       5       0       GPIO3_6  FEC_MDIO        0x1cc   0x3c4                 
+FEC_RX_CLK             PD14  -   -       NC                                                                             REGOFF: 0
+FEC_RX_DV              PD13  -   -       NC                                                                             
+FEC_RXD0               PD12  5   0       GPIO3_10 FEC_RDATA0  0x1dc   0x3d4             MODE0: 1
+FEC_RXD1               PD5       5       0       GPIO3_11 FEC_RDATA1  0x1e0   0x3d8             MODE1: 1
+FEC_RXD2               PD6       -       -       NC       PULLUP                                                        MODE2: 1
+FEC_RXD3               PD7       -       -       NC                                                                             INTSEL: 0
+FEC_RX_ER              PD4       5       5       GPIO4_10 D10             0x09c   0x294
+FEC_TX_CLK             PD11  5   0       GPIO3_13 FEC_TX_CLK  0x1e8   0x3e0             
+FEC_TX_EN              PF23  5   0       GPIO3_9  FEC_TX_EN   0x1d8   0x3d0
+FEC_TXD0               PD0       5       0       GPIO3_7  FEC_TDATA0  0x1d0   0x3c8
+FEC_TXD1               PD1       5       0       GPIO3_8  FEC_TDATA1  0x1d4   0x3cc
+FEC_TXD2               PD2       -       -       NC
+FEC_TXD3               PD3       -       -       NC
+FEC_COL                        PD15  5   0       GPIO3_12 FEC_RX_DV   0x1e4   0x3dc             RMII:  1
+FEC_CRS                        PD10  -   -       NC                                                                             PHYAD4: 0
+FEC_TX_ER              PD16  5   5       GPIO4_8  D12             0x094   0x28c
+                                                         GPIO2_5  A19             0x024   0x240  0x518  FEC_RX_ER
+FEC_RESET~             PB30  5   5       GPIO4_7  D13             0x090   0x288
+FEC_ENABLE             PB27  5   5       GPIO4_9  D11             0x098   0x290
+*/
+
+static inline void tx25_write_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset, CYG_WORD32 val)
+{
+       if (net_debug) diag_printf("Writing %08x to reg %08x\n", val, base_addr + offset);
+       HAL_WRITE_UINT32(base_addr + offset, val);
+}
+
+static inline CYG_WORD32 tx25_read_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset)
+{
+       CYG_WORD32 val;
+       HAL_READ_UINT32(base_addr + offset, val);
+       if (net_debug) diag_printf("Read %08x from reg %08x\n", val, base_addr + offset);
+       return val;
+}
+
+static inline void tx25_set_reg(CYG_ADDRWORD base_addr, CYG_WORD32 offset,
+                               CYG_WORD32 set_mask, CYG_WORD32 clr_mask)
+{
+       CYG_WORD32 val;
+       HAL_READ_UINT32(base_addr + offset, val);
+       if (net_debug) diag_printf("Changing reg %08x from %08x to %08x\n",
+                                                          base_addr + offset, val,
+                                                          (val & ~clr_mask) | set_mask);
+       val = (val & ~clr_mask) | set_mask;
+       HAL_WRITE_UINT32(base_addr + offset, val);
+}
+
+static struct tx25_gpio_setup {
+       cyg_uint16 iomux_addr;
+       cyg_uint8 on_func;
+       cyg_uint8 off_func;
+       cyg_uint8 grp;
+       cyg_uint8 shift;
+} tx25_fec_gpio_data[] = {
+       /* iomux, func, gpfn, gpgrp, gpshift */
+       { 0x1c8,    0, 0x15,    3,     5, },
+       { 0x1cc,    0, 0x15,    3,     6, },
+       { 0x1dc,    0, 0x15,    3,    10, },
+       { 0x1e0,    0, 0x15,    3,    11, },
+       { 0x09c, 0x85,    5,    4,    10, },
+       { 0x1e8,    0, 0x15,    3,    13, },
+       { 0x1d8,    0, 0x15,    3,     9, },
+       { 0x1d0,    0, 0x15,    3,     7, },
+       { 0x1d4,    0, 0x15,    3,     8, },
+       { 0x1e4, 0x80, 0x15,    3,    12, },
+       { 0x024, 0x05, 0x05,    2,     5, }, /* RX_ER signal; make sure it's a GPIO _without_ SION! */
+       { 0x094, 0x85,    5,    4,     8, },
+       { 0x090,    5,    5,    4,     7, },
+       { 0x098,    5,    5,    4,     9, },
+};
+
+static struct tx25_gpio_setup tx25_fec_strap_pins[] = {
+       { 0x1dc,    0, 0x15,   3, 10, },
+       { 0x1e0,    0, 0x15,   3, 11, },
+       { 0x1e4,    0, 0x15,   3, 12, },
+};
+
+static inline void tx25_phy_power_off(void)
+{
+       int i;
+
+       if (net_debug) diag_printf("Switching PHY POWER off\n");
+
+#if 1
+       for (i = 0; i < NUM_ELEMS(tx25_fec_gpio_data); i++) {
+               struct tx25_gpio_setup *gs = &tx25_fec_gpio_data[i];
+
+               if (net_debug) diag_printf("%s: GPIO%d_%d[%d] is %d\n", __FUNCTION__,
+                                                                  gs->grp, gs->shift, i,
+                                                                  gpio_tst_bit(gs->grp, gs->shift));
+       }
+#endif
+       /* deassert all pins attached to the PHY */
+       for (i = 0; i < NUM_ELEMS(tx25_fec_gpio_data); i++) {
+               struct tx25_gpio_setup *gs = &tx25_fec_gpio_data[i];
+
+               tx25_write_reg(IOMUXC_BASE_ADDR, gs->iomux_addr,
+                              gs->off_func);
+               if (gs->on_func & 0x80) {
+                       /* configure as input */
+                       tx25_set_reg(MX25_GPIO_ADDR(gs->grp),
+                                                GPIO_GDIR, 0, 1 << gs->shift);
+               } else {
+                       /* configure as output */
+                       tx25_set_reg(MX25_GPIO_ADDR(gs->grp),
+                                                GPIO_DR, 0, 1 << gs->shift);
+                       tx25_set_reg(MX25_GPIO_ADDR(gs->grp),
+                                                GPIO_GDIR, 1 << gs->shift, 0);
+               }
+               tx25_write_reg(IOMUXC_BASE_ADDR, gs->iomux_addr,
+                              gs->off_func);
+       }
+       for (i = 0; i < NUM_ELEMS(tx25_fec_gpio_data); i++) {
+               struct tx25_gpio_setup *gs = &tx25_fec_gpio_data[i];
+
+               if (!(gs->on_func & 0x80) && gpio_tst_bit(gs->grp, gs->shift)) {
+                       if (net_debug) diag_printf("%s: GPIO%d_%d[%d] is not low\n", __FUNCTION__,
+                                                                          gs->grp, gs->shift, i);
+               }
+       }
+       if (net_debug) diag_printf("PHY POWER off done\n");
+}
+
+static bool tx25_fec_init(struct cyg_netdevtab_entry *tab)
+{
+       cyg_bool esa_set;
+       int ok;
+
+       /* Check, whether MAC address is enabled */
+       ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
+                                                                        "fec_esa", &esa_set, CONFIG_BOOL);
+       if (!(ok && esa_set)) {
+               diag_printf("FEC disabled; set fec_esa=true to enable networking\n");
+               tx25_phy_power_off();
+               return false;
+       }
+       /* call init function in devs/eth/fec/current/if_fec.c */
+       return mxc_fec_init(tab);
+}
+
+static void tx25_fec_phy_init(void)
+{
+       int i;
+       int phy_reset_delay = 100;
+
+       /*
+        * make sure the ETH PHY strap pins are pulled to the right voltage
+        * before deasserting the PHY reset GPIO
+        * REGOFF:   PD14
+        * RMII:     PD15
+        * nINTSEL:  PD7
+        * MODE0:    PD12
+        * MODE1:    PD5
+        * MODE2:    PD6
+        * PHYAD0:   -
+        * PHYAD1:   GND
+        * PHYAD2:   GND
+        * PHYAD3:   -
+        * PHYAD4:   PD10
+        */
+       // assert FEC PHY Reset (PB30) and switch PHY power on
+       /* PB22, PB27, PB30 => GPIO out */
+#if 0
+       tx25_phy_power_off();
+#endif
+#if 0
+       tx25_write_reg(IOMUXC_BASE_ADDR, IOMUXC_GPIO1_7, 0x11);
+       tx25_write_reg(IOMUXC_BASE_ADDR, IOMUXC_NANDF_CS1, 0x14);
+#endif
+#if 0
+       while (1) {
+#if 0
+               gpio_set_bit(4, 9);
+#else
+               tx25_set_reg(MX25_GPIO_ADDR(4), GPIO_DR, 1 << 9, 0);
+#endif
+               tx25_read_reg(MX25_GPIO_ADDR(4), GPIO_DR);
+               HAL_DELAY_US(1000000);
+#if 0
+               gpio_clr_bit(4, 9);
+#else
+               tx25_set_reg(MX25_GPIO_ADDR(4), GPIO_DR, 0, 1 << 9);
+#endif
+               tx25_read_reg(MX25_GPIO_ADDR(4), GPIO_DR);
+               HAL_DELAY_US(1000000);
+       }
+#endif
+       /* Switch PHY power on and assert PHY reset */
+       if (net_debug) diag_printf("Switching PHY POWER on\n");
+       gpio_clr_bit(4, 7);
+       gpio_set_bit(4, 9);
+
+       /* wait for 22ms for LAN8700 to power up */
+       phy_reset_delay = 22000;
+
+       /* configure FEC strap pins to their required values */
+       for (i = 0; i < NUM_ELEMS(tx25_fec_strap_pins); i++) {
+               struct tx25_gpio_setup *gs = &tx25_fec_strap_pins[i];
+
+               if (net_debug) diag_printf("Asserting GPIO%d_%d\n", gs->grp,
+                                                                  gs->shift);
+#if 0
+               tx25_set_reg(MX25_GPIO_ADDR(gs->grp),
+                                        GPIO_GDIR, 1 << gs->shift, 0);
+               tx25_set_reg(MX25_GPIO_ADDR(gs->grp),
+                                        GPIO_DR, 1 << gs->shift, 0);
+               tx25_write_reg(IOMUXC_BASE_ADDR, gs->iomux_addr,
+                                          gs->off_func);
+#else
+               gpio_set_bit(gs->grp, gs->shift);
+#endif
+       }
+#if 0
+       for (i = 0; i < NUM_ELEMS(tx25_fec_gpio_data); i++) {
+               struct tx25_gpio_setup *gs = &tx25_fec_gpio_data[i];
+               int j;
+               int strap = 0;
+
+               for (j = 0; j < NUM_ELEMS(tx25_fec_strap_pins); j++) {
+                       struct tx25_gpio_setup *sp = &tx25_fec_strap_pins[j];
+
+                       if (gs->grp == sp->grp && gs->shift == sp->shift) {
+                               strap = 1;
+                               break;
+                       }
+               }
+               if (strap || gs->on_func & 0x80) {
+                       if (!gpio_tst_bit(gs->grp, gs->shift)) {
+                               if (net_debug) diag_printf("GPIO%d_%d[%d] is low instead of high\n",
+                                                                                  gs->grp, gs->shift, i);
+                       }
+               } else {
+                       if (gpio_tst_bit(gs->grp, gs->shift)) {
+                               if (net_debug) diag_printf("GPIO%d_%d[%d] is high instead of low\n",
+                                                                                  gs->grp, gs->shift, i);
+                       }
+               }
+       }
+#endif
+       /* wait for 100us according to LAN8700 spec. before ... */
+       HAL_DELAY_US(phy_reset_delay);
+
+       /* ... deasserting FEC PHY reset */
+       if (net_debug) diag_printf("Releasing PHY RESET\n");
+       tx25_set_reg(MX25_GPIO_ADDR(4), GPIO_DR, 1 << 7, 0);
+#if 0
+       for (i = 0; i < NUM_ELEMS(tx25_fec_gpio_data); i++) {
+               struct tx25_gpio_setup *gs = &tx25_fec_gpio_data[i];
+               int j;
+               int strap = 0;
+
+               for (j = 0; j < NUM_ELEMS(tx25_fec_strap_pins); j++) {
+                       struct tx25_gpio_setup *sp = &tx25_fec_strap_pins[j];
+
+                       if (gs->grp == sp->grp && gs->shift == sp->shift) {
+                               strap = 1;
+                               break;
+                       }
+               }
+               if (strap || gs->on_func & 0x80) {
+                       if (!gpio_tst_bit(gs->grp, gs->shift)) {
+                               if (net_debug) diag_printf("GPIO%d_%d[%d] is low instead of high\n",
+                                                                                  gs->grp, gs->shift, i);
+                       }
+               } else {
+                       if (gpio_tst_bit(gs->grp, gs->shift)) {
+                               if (net_debug) diag_printf("GPIO%d_%d[%d] is high instead of low\n",
+                                                                                  gs->grp, gs->shift, i);
+                       }
+               }
+       }
+#endif
+       /* configure all FEC pins to their required functions */
+       for (i = 0; i < NUM_ELEMS(tx25_fec_gpio_data); i++) {
+               struct tx25_gpio_setup *gs = &tx25_fec_gpio_data[i];
+
+               tx25_write_reg(IOMUXC_BASE_ADDR, gs->iomux_addr,
+                                          gs->on_func & ~0x80);
+       }
+}
+
+ETH_PHY_REG_LEVEL_ACCESS_FUNS(eth0_phy, 
+                              tx25_fec_phy_init,
+                              mxc_fec_phy_reset,
+                              mxc_fec_phy_write,
+                              mxc_fec_phy_read);
+
+#define SOC_MAC_ADDR_LOCK_BIT  2
+
+cyg_bool _tx25_provide_fec_esa(unsigned char *addr)
+{
+       cyg_bool enabled;
+       int ok;
+
+       ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
+                                        "fec_esa", &enabled, CONFIG_BOOL);
+       if (ok && enabled) {
+#ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
+               cyg_uint8 addr2[ETHER_ADDR_LEN];
+
+               addr[0] = readl(SOC_MAC_ADDR_BASE + 0x0);
+               addr[1] = readl(SOC_MAC_ADDR_BASE + 0x4);
+               addr[2] = readl(SOC_MAC_ADDR_BASE + 0x8);
+               addr[3] = readl(SOC_MAC_ADDR_BASE + 0xC);
+               addr[4] = readl(SOC_MAC_ADDR_BASE + 0x10);
+               addr[5] = readl(SOC_MAC_ADDR_BASE + 0x14);
+
+               if (cyg_plf_redboot_esa_validate(addr)) {
+                       diag_printf("Ethernet FEC MAC address from fuse bank: ");
+                       diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+                                   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+                       CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
+                                                                               "fec_esa_data", addr2, CONFIG_ESA);
+                       if (memcmp(addr, addr2, sizeof(addr)) != 0) {
+                               CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_SET,
+                                                                                       "fec_esa_data", addr, CONFIG_ESA);
+                       }
+#ifdef SOC_MAC_ADDR_LOCK_BIT
+                       if ((readl(SOC_MAC_ADDR_BASE - 0x68) & SOC_MAC_ADDR_LOCK_BIT) == 0) {
+                               tx25_mac_addr_program(addr);
+                       }
+#endif // SOC_MAC_ADDR_LOCK_BIT
+                       return true;
+               }
+#endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
+
+               CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
+                                                                       "fec_esa_data", addr, CONFIG_ESA);
+
+               diag_printf("Ethernet FEC MAC address from fconfig: ");
+               diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+                           addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+#ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
+               if (cyg_plf_redboot_esa_validate(addr)) {
+                       tx25_mac_addr_program(addr);
+                       return true;
+               }
+
+               diag_printf("** Error: Invalid MAC address: ");
+               diag_printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+                           addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+#ifdef SOC_MAC_ADDR_LOCK_BIT
+               if ((readl(SOC_MAC_ADDR_BASE - 0x68) & SOC_MAC_ADDR_LOCK_BIT) == 0) {
+                       diag_printf("Use 'fconfig fec_esa_data' to set the MAC address\n");
+                       return false;
+               } else {
+                       diag_printf("Using MAC address from fconfig\n");
+               }
+#else
+               diag_printf("Using MAC address from fconfig\n");
+#endif // SOC_MAC_ADDR_LOCK_BIT
+#endif // CYGSEM_REDBOOT_PLF_ESA_VALIDATE
+               return true;
+       }
+       return false;
+}
+
+static mxc_fec_priv_t mxc_fec_private = {
+       .phy = &eth0_phy,                             // PHY access routines
+       .provide_esa = _tx25_provide_fec_esa,
+};
+
+ETH_DRV_SC(mxc_fec_sc,
+                  &mxc_fec_private, // Driver specific data
+           mxc_fec_name,
+           mxc_fec_start,
+           mxc_fec_stop,
+           mxc_fec_control,
+           mxc_fec_can_send,
+           mxc_fec_send,
+           mxc_fec_recv,
+           mxc_fec_deliver,     // "pseudoDSR" called from fast net thread
+           mxc_fec_poll,        // poll function, encapsulates ISR and DSR
+           mxc_fec_int_vector);
+
+NETDEVTAB_ENTRY(mxc_fec_netdev,
+                mxc_fec_name,
+                tx25_fec_init,
+                &mxc_fec_sc);
+#endif
+
+#if defined(CYGPKG_REDBOOT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG)
+RedBoot_config_option("Set FEC network hardware address [MAC]",
+                      fec_esa,
+                      ALWAYS_ENABLED, true,
+                      CONFIG_BOOL, false
+                     );
+RedBoot_config_option("FEC network hardware address [MAC]",
+                      fec_esa_data,
+                      "fec_esa", true,
+                      CONFIG_ESA, 0
+                     );
+#endif // CYGPKG_REDBOOT && CYGSEM_REDBOOT_FLASH_CONFIG
+
+#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
+// Note that this section *is* active in an application, outside RedBoot,
+// where the above section is not included.
+
+#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
+#endif // CYGPKG_DEVS_ETH_ARM_MXCBOARD_ETH0
+
+#endif // __WANT_DEVS