]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - packages/devs/eth/fec/v2_0/src/if_fec.c
TX51 pre-release
[karo-tx-redboot.git] / packages / devs / eth / fec / v2_0 / src / if_fec.c
index 5d157e8b4746e61d2258cd18f174aeaa6df5c508..c2b6e61641ae15c30ac96fa8456b084c4fadaa39 100644 (file)
 #include <cyg/io/eth/eth_drv.h>
 #include <cyg/io/eth/netdev.h>
 
-#ifdef CYGPKG_DEVS_ETH_PHY
-/* generic PHY device access functions */
-void mxc_fec_phy_init(void);
-void mxc_fec_phy_reset(void);
-bool mxc_fec_phy_read(int reg, int unit, unsigned short *data);
-void mxc_fec_phy_write(int reg, int unit, unsigned short data);
-
-#include <cyg/io/eth_phy.h>
-#endif
 static bool mxc_fec_init(struct cyg_netdevtab_entry *tab);
 
 #include <cyg/io/fec.h>
@@ -100,16 +91,16 @@ static bool mxc_fec_init(struct cyg_netdevtab_entry *tab);
 
 #include <redboot.h>
 
-#include <cyg/hal/hal_mm.h>
+#include <cyg/hal/plf_mmap.h>
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
 #include <flash_config.h>
 #endif
 
 
-#define MII_REG_CR          0  /* Control Register                         */
-#define MII_REG_SR          1  /* Status Register                          */
-#define MII_REG_PHYIR1      2  /* PHY Identification Register 1            */
-#define MII_REG_PHYIR2      3  /* PHY Identification Register 2            */
+#define MII_REG_CR                     0  /* Control Register                                             */
+#define MII_REG_SR                     1  /* Status Register                                              */
+#define MII_REG_PHYIR1         2  /* PHY Identification Register 1                        */
+#define MII_REG_PHYIR2         3  /* PHY Identification Register 2                        */
 
 static void mxc_fec_phy_status(mxc_fec_priv_t *dev, unsigned short value, bool show);
 
@@ -127,13 +118,13 @@ static mxc_fec_priv_t  mxc_fec_private;
 
 /*!
  * Global variable which defines the buffer descriptors for receive frames
- *     comment:: it must aligned by 128-bits.
+ *     comment:: it must aligned by 128-bits.
  */
 static mxc_fec_bd_t mxc_fec_rx_bd[FEC_BD_RX_NUM] __attribute__ ((aligned(32)));
 
 /*!
  * Global variable which defines the buffer descriptors for transmit frames
- *     comment:: it must aligned by 128-bits.
+ *     comment:: it must aligned by 128-bits.
  */
 static mxc_fec_bd_t mxc_fec_tx_bd[FEC_BD_TX_NUM] __attribute__ ((aligned(32)));
 
@@ -147,8 +138,8 @@ static unsigned char mxc_fec_rx_buf[FEC_BD_RX_NUM][2048] __attribute__ ((aligned
  */
 static unsigned char mxc_fec_tx_buf[FEC_BD_TX_NUM][2048] __attribute__ ((aligned(32)));
 
-#if 0
-static void dump_packet (unsigned char *pkt, size_t len)
+#if 1
+static void dump_packet(const unsigned char *pkt, size_t len)
 {
        int i;
 
@@ -171,44 +162,49 @@ static void dump_packet (unsigned char *pkt, size_t len)
 }
 #endif
 
-#define mxc_fec_reg_read(hw_reg,reg) _mxc_fec_reg_read(&(hw_reg)->reg, #reg)
-static inline unsigned long _mxc_fec_reg_read(volatile unsigned long *addr,
-                                                                                         const char *reg)
+static inline volatile void *fec_reg_addr(volatile void *base, unsigned int reg)
+{
+       return (volatile void *)((unsigned long)base + reg);
+}
+
+#define mxc_fec_reg_read(hw_reg,reg) _mxc_fec_reg_read(hw_reg, reg, #reg)
+static inline unsigned long _mxc_fec_reg_read(volatile void *base, unsigned int reg,
+                                                                                       const char *name)
 {
-       unsigned long val = readl(addr);
+       unsigned long val = readl(fec_reg_addr(base, reg));
 
-       if (net_debug) diag_printf("Read %08lx from FEC reg %s[%p]\n",
-                                  val, reg, addr);
+       if (net_debug) diag_printf("Read %08lx from FEC reg %s[%03x]\n",
+                                  val, name, reg);
        return val;
 }
 
-#define mxc_fec_reg_write(hw_reg,reg,val) _mxc_fec_reg_write(&(hw_reg)->reg, val, #reg)
-static inline void _mxc_fec_reg_write(volatile unsigned long *addr,
-                                                                         unsigned long val, const char *reg)
+#define mxc_fec_reg_write(hw_reg,reg,val) _mxc_fec_reg_write(hw_reg, reg, val, #reg)
+static inline void _mxc_fec_reg_write(volatile void *base, unsigned int reg,
+                                                                         unsigned long val, const char *name)
 {
-       if (net_debug) diag_printf("Writing %08lx to FEC reg %s[%p]\n",
-                                  val, reg, addr);
-       writel(val, addr);
+       if (net_debug) diag_printf("Writing %08lx to FEC reg %s[%03x]\n",
+                                                       val, name, reg);
+       writel(val, fec_reg_addr(base, reg));
 }
 
-#define mxc_fec_reg_read16(hw_reg,reg) _mxc_fec_reg_read16(&(hw_reg)->reg, #reg)
-static inline unsigned short _mxc_fec_reg_read16(volatile unsigned short *addr,
-                                                                                               const char *reg)
+#define mxc_fec_reg_read16(hw_reg,reg) _mxc_fec_reg_read16(hw_reg, reg, #reg)
+static inline unsigned short _mxc_fec_reg_read16(volatile void *base, unsigned int reg,
+                                                                                               const char *name)
 {
-       unsigned short val = readw(addr);
+       unsigned short val = readw(fec_reg_addr(base, reg));
 
-       if (net_debug) diag_printf("Read %04x from FEC reg %s[%p]\n",
-                                  val, reg, addr);
+       if (net_debug) diag_printf("Read %04x from FEC reg %s[%03x]\n",
+                                                       val, name, reg);
        return val;
 }
 
-#define mxc_fec_reg_write16(hw_reg,reg,val) _mxc_fec_reg_write16(&(hw_reg)->reg, val, #reg)
-static inline void _mxc_fec_reg_write16(volatile unsigned short *addr,
-                                                                               unsigned short val, const char *reg)
+#define mxc_fec_reg_write16(hw_reg,reg,val) _mxc_fec_reg_write16(hw_reg, reg, val, #reg)
+static inline void _mxc_fec_reg_write16(volatile void *base, unsigned int reg,
+                                                                               unsigned short val, const char *name)
 {
-       if (net_debug) diag_printf("Writing %04x to FEC reg %s[%p]\n",
-                                  val, reg, addr);
-       writew(val, addr);
+       if (net_debug) diag_printf("Writing %04x to FEC reg %s[%03x]\n",
+                                                       val, name, reg);
+       writew(val, fec_reg_addr(base, reg));
 }
 
 /*!
@@ -221,7 +217,7 @@ mxc_fec_mii_read(volatile mxc_fec_reg_t *hw_reg, unsigned char phy_addr, unsigne
        unsigned long waiting = FEC_MII_TIMEOUT;
 
        if (net_debug) diag_printf("%s: Trying to read phy[%02x] reg %04x\n",
-                                  __FUNCTION__, phy_addr, reg_addr);
+                                                       __FUNCTION__, phy_addr, reg_addr);
        if (mxc_fec_reg_read(hw_reg, eir) & FEC_EVENT_MII) {
                if (net_debug) diag_printf("%s: Clearing EIR_EVENT_MII\n", __FUNCTION__);
                mxc_fec_reg_write(hw_reg, eir, FEC_EVENT_MII);
@@ -237,15 +233,15 @@ mxc_fec_mii_read(volatile mxc_fec_reg_t *hw_reg, unsigned char phy_addr, unsigne
                }
                if (--waiting == 0) {
                        diag_printf("%s: Read from PHY at addr %d reg 0x%02x timed out: EIR=%08lx\n",
-                                   __FUNCTION__, phy_addr, reg_addr,
-                                   mxc_fec_reg_read(hw_reg, eir));
+                                               __FUNCTION__, phy_addr, reg_addr,
+                                               mxc_fec_reg_read(hw_reg, eir));
                        return -1;
                }
                hal_delay_us(FEC_MII_TICK);
        }
        *value = FEC_MII_GET_DATA(mxc_fec_reg_read(hw_reg, mmfr));
        if (net_debug) diag_printf("%s: Read %04x from phy[%02x] reg %04x\n", __FUNCTION__,
-                                  *value, phy_addr, reg_addr);
+                                                       *value, phy_addr, reg_addr);
        return 0;
 }
 
@@ -277,8 +273,8 @@ mxc_fec_mii_write(volatile mxc_fec_reg_t *hw_reg, unsigned char phy_addr, unsign
                }
                if (--waiting == 0) {
                        diag_printf("%s: Write to PHY at addr %d reg 0x%02x timed out: EIR=%08lx\n",
-                                   __FUNCTION__, phy_addr, reg_addr,
-                                   mxc_fec_reg_read(hw_reg, eir));
+                                               __FUNCTION__, phy_addr, reg_addr,
+                                               mxc_fec_reg_read(hw_reg, eir));
                        return -1;
                }
                hal_delay_us(FEC_MII_TICK);
@@ -375,7 +371,7 @@ mxc_fec_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_l
 {
        /*TODO:: Add support */
        diag_printf("mxc_fec_control: key=0x%08lx, data=%p, data_len=0x%08x\n",
-                   key, data, data_length);
+                               key, data, data_length);
        return 0;
 }
 
@@ -439,7 +435,7 @@ mxc_fec_can_send(struct eth_drv_sc *sc)
  */
 static void
 mxc_fec_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total,
-                        unsigned long key)
+                       unsigned long key)
 {
        mxc_fec_priv_t *dev = sc ? sc->driver_private : NULL;
        volatile mxc_fec_reg_t *hw_reg = dev ? dev->hw_reg : NULL;
@@ -478,7 +474,6 @@ mxc_fec_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int
                return;
        }
        p->length = off;
-       //p->status &= ~(BD_TX_ST_LAST | BD_TX_ST_RDY | BD_TX_ST_TC | BD_TX_ST_ABC);
        p->status &= ~BD_TX_ST_ABC;
        p->status |= BD_TX_ST_LAST | BD_TX_ST_RDY | BD_TX_ST_TC;
        if (p->status & BD_TX_ST_WRAP) {
@@ -498,7 +493,7 @@ mxc_fec_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int
 static void
 mxc_fec_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
 {
-        mxc_fec_priv_t *priv = sc ? sc->driver_private : NULL;
+       mxc_fec_priv_t *priv = sc ? sc->driver_private : NULL;
        mxc_fec_bd_t *p;
        unsigned long vaddr;
 
@@ -526,8 +521,9 @@ mxc_fec_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
                return;
        }
        vaddr = hal_ioremap_nocache((unsigned long)p->data);
-       /*TODO::D_CACHE invalid this data buffer*/
+       /*TODO::D_CACHE invalidate this data buffer*/
        memcpy((void *)sg_list->buf, (void *)vaddr, p->length - 4);
+       if (net_debug) dump_packet((void *)sg_list->buf, p->length - 4);
 }
 
 static void
@@ -571,7 +567,7 @@ mxc_fec_check_rx_bd(struct eth_drv_sc *sc)
                } else {
                        sc->funs->eth_drv->recv(sc, p->length - 4);
                }
-skip_next:
+       skip_next:
                p->status = (p->status & BD_RX_ST_WRAP) | BD_RX_ST_EMPTY;
 
                if (p->status & BD_RX_ST_WRAP) {
@@ -636,8 +632,8 @@ mxc_fec_int_vector(struct eth_drv_sc *sc)
 {
        /*TODO::
         *      get FEC interrupt number
-        */
-       return -1;
+        */
+       return -1;
 }
 
 /*!
@@ -680,6 +676,7 @@ mxc_fec_chip_init(mxc_fec_priv_t *dev)
 {
        volatile mxc_fec_reg_t *hw_reg = dev->hw_reg;
        unsigned long ipg_clk;
+       unsigned long clkdiv;
 
        mxc_fec_reg_write(hw_reg, ecr, mxc_fec_reg_read(hw_reg, ecr) | FEC_RESET);
        while (mxc_fec_reg_read(hw_reg, ecr) & FEC_RESET) {
@@ -690,8 +687,8 @@ mxc_fec_chip_init(mxc_fec_priv_t *dev)
        mxc_fec_reg_write(hw_reg, eir, ~0);
 
        mxc_fec_reg_write(hw_reg, rcr,
-                                         (mxc_fec_reg_read(hw_reg, rcr) & ~0x3F) |
-                                         FEC_RCR_FCE | FEC_RCR_MII_MODE);
+                                       (mxc_fec_reg_read(hw_reg, rcr) & ~0x3F) |
+                                       FEC_RCR_FCE | FEC_RCR_MII_MODE);
 
        mxc_fec_reg_write(hw_reg, tcr, mxc_fec_reg_read(hw_reg, tcr) | FEC_TCR_FDEN);
        mxc_fec_reg_write(hw_reg, mibc, mxc_fec_reg_read(hw_reg, mibc) | FEC_MIB_DISABLE);
@@ -702,12 +699,13 @@ mxc_fec_chip_init(mxc_fec_priv_t *dev)
        mxc_fec_reg_write(hw_reg, galr, 0);
 
        ipg_clk = get_main_clock(IPG_CLK);
-
-       mxc_fec_reg_write(hw_reg, mscr,
-                                         (mxc_fec_reg_read(hw_reg, mscr) & ~0x7e) |
-                                         (((ipg_clk + 499999) / 2500000 / 2) << 1));
-       if (net_debug) diag_printf("mscr set to %08lx for ipg_clk %ld\n",
-                                  mxc_fec_reg_read(hw_reg, mscr), ipg_clk);
+       clkdiv = ((ipg_clk + 499999) / 2500000 / 2) << 1;
+#if 1
+       mxc_fec_reg_write(hw_reg, mscr, (mxc_fec_reg_read(hw_reg, mscr) & ~0x7e) |
+                                       clkdiv);
+#endif
+       if (net_debug) diag_printf("mscr set to %08lx(%08lx) for ipg_clk %ld\n",
+                                                       clkdiv, mxc_fec_reg_read(hw_reg, mscr), ipg_clk);
 
        mxc_fec_reg_write(hw_reg, emrbr, 2048 - 16);
        mxc_fec_reg_write(hw_reg, erdsr, hal_virt_to_phy((unsigned long)dev->rx_bd));
@@ -752,18 +750,18 @@ static void mxc_fec_phy_status(mxc_fec_priv_t *dev, unsigned short value, bool s
                dev->status &= ~FEC_STATUS_FULL_DPLX;
        }
        if (value & PHY_DIAG_RATE) {
-                dev->status |= FEC_STATUS_100M;
-        } else {
-                dev->status &= ~FEC_STATUS_100M;
-        }
+               dev->status |= FEC_STATUS_100M;
+       } else {
+               dev->status &= ~FEC_STATUS_100M;
+       }
 #endif
        if (!show) {
                return;
        }
        if (dev->status & FEC_STATUS_LINK_ON) {
                diag_printf("FEC: [ %s ] [ %s ]:\n",
-                           (dev->status & FEC_STATUS_FULL_DPLX) ? "FULL_DUPLEX" : "HALF_DUPLEX",
-                           (dev->status & FEC_STATUS_100M) ? "100 Mbps" : "10 Mbps");
+                                       (dev->status & FEC_STATUS_FULL_DPLX) ? "FULL_DUPLEX" : "HALF_DUPLEX",
+                                       (dev->status & FEC_STATUS_100M) ? "100 Mbps" : "10 Mbps");
        } else {
                diag_printf("FEC: no cable\n");
        }
@@ -814,7 +812,7 @@ mxc_fec_phy_init(mxc_fec_priv_t *dev)
 
        timeout = FEC_COMMON_TIMEOUT;
        while (timeout-- &&
-              mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_STATUS_REG, &value) == 0) {
+               mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_STATUS_REG, &value) == 0) {
                if (value & PHY_STATUS_LINK_ST) {
                        if (net_debug) diag_printf("PHY Status: %04x\n", value);
                        break;
@@ -842,7 +840,8 @@ mxc_fec_phy_init(mxc_fec_priv_t *dev)
                diag_printf("[Warning] FEC not connect right PHY: ID=%lx\n", id);
        }
 
-       mxc_fec_mii_write(dev->hw_reg, dev->phy_addr, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG|PHY_CTRL_FULL_DPLX);
+       mxc_fec_mii_write(dev->hw_reg, dev->phy_addr, PHY_CTRL_REG,
+                                       PHY_CTRL_AUTO_NEG | PHY_CTRL_FULL_DPLX);
 
 #ifdef CYGPKG_HAL_ARM_MX27ADS
        mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_MODE_REG, &value);
@@ -850,7 +849,8 @@ mxc_fec_phy_init(mxc_fec_priv_t *dev)
        mxc_fec_mii_write(dev->hw_reg, dev->phy_addr, PHY_MODE_REG, value);
 #endif
 
-#if defined(CYGPKG_HAL_ARM_MX51) || defined (CYGPKG_HAL_ARM_MX25_3STACK) || defined (CYGPKG_HAL_ARM_MX35_3STACK) || defined (CYGPKG_HAL_ARM_MX27_3STACK)
+#if defined(CYGPKG_HAL_ARM_MX51) || defined(CYGPKG_HAL_ARM_MX25_3STACK) || \
+       defined(CYGPKG_HAL_ARM_MX35_3STACK) || defined(CYGPKG_HAL_ARM_MX27_3STACK)
        mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_AUTO_NEG_EXP_REG, &value);
        /* Wait for packet to arrive */
        while (((value & PHY_AUTO_NEG_NEW_PAGE) == 0) && (timeout != 0)) {
@@ -886,12 +886,13 @@ mxc_fec_phy_init(mxc_fec_priv_t *dev)
        }
        if (value & PHY_DIAG_DPLX) {
                dev->status |= FEC_STATUS_100M;
-        } else {
+       } else {
                dev->status &= ~FEC_STATUS_100M;
        }
 #endif
 
-#if defined(CYGPKG_HAL_ARM_MX51) || defined (CYGPKG_HAL_ARM_MX25_3STACK) || defined (CYGPKG_HAL_ARM_MX35_3STACK)
+#if defined(CYGPKG_HAL_ARM_MX51) || defined(CYGPKG_HAL_ARM_MX25_3STACK) || \
+       defined(CYGPKG_HAL_ARM_MX35_3STACK)
        mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_AUTO_NEG_REG, &value);
        if (value & PHY_AUTO_10BASET) {
                dev->status &= ~FEC_STATUS_100M;
@@ -925,6 +926,7 @@ static int mxc_fec_discover_phy(mxc_fec_priv_t *fep, unsigned char def_addr)
        unsigned char phy_addr = def_addr;
        unsigned long id = 0;
        int i;
+
        for (i = 0; i < 32; i++) {
                unsigned short mii_reg;
 
@@ -1057,7 +1059,7 @@ mxc_fec_init(struct cyg_netdevtab_entry *tab)
                return false;
        }
 
-       private->hw_reg = (void *)SOC_FEC_BASE;
+       private->hw_reg = (volatile void *)SOC_FEC_BASE;
        private->tx_busy = 0;
        private->status = 0;
 
@@ -1092,24 +1094,24 @@ mxc_fec_init(struct cyg_netdevtab_entry *tab)
  * Global variable which defines the FEC driver,
  */
 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);
+               &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);
 
 /*!
  * Global variable which defines the FEC device
  */
 NETDEVTAB_ENTRY(mxc_fec_netdev,
-                mxc_fec_name,
-                mxc_fec_init,
-                &mxc_fec_sc);
+                               mxc_fec_name,
+                               mxc_fec_init,
+                               &mxc_fec_sc);
 
 #endif // CYGPKG_DEVS_ETH_PHY