This patch add support for FEC MII access via bit banging.

Signed-Off-By: Steve Bennett <[EMAIL PROTECTED]>

diff -urN uClinux-dist.orig/linux-2.6.x/drivers/net/Kconfig 
uClinux-dist/linux-2.6.x/drivers/net/Kconfig
--- uClinux-dist.orig/linux-2.6.x/drivers/net/Kconfig   2006-11-30 
12:03:18.000000000 +1000
+++ uClinux-dist/linux-2.6.x/drivers/net/Kconfig        2007-05-11 
16:12:16.000000000 +1000
@@ -1909,6 +1909,14 @@
          Say Y here if you want to use the built-in 10/100 Fast ethernet
          controller on some Motorola ColdFire processors.
 
+config FEC_MII_BIT_BANG
+       bool "FEC MII bit bang interface"
+       depends on FEC && (WILDFIRE || WILDFIREMOD)
+       help
+         Say Y here if you want to use the MII bit banging interfaces.
+         The bit banging interfaces will use two digital IO lines
+         instead of the built in MII module.
+       
 config FEC2
        bool "Second FEC ethernet controller (on some ColdFire CPUs)"
        depends on FEC
diff -urN uClinux-dist.orig/linux-2.6.x/drivers/net/Makefile 
uClinux-dist/linux-2.6.x/drivers/net/Makefile
--- uClinux-dist.orig/linux-2.6.x/drivers/net/Makefile  2006-11-30 
12:03:18.000000000 +1000
+++ uClinux-dist/linux-2.6.x/drivers/net/Makefile       2007-05-11 
16:12:16.000000000 +1000
@@ -91,6 +91,7 @@
 obj-$(CONFIG_OPEN_ETH) += open_eth.o
 obj-$(CONFIG_MTIP1000_ETH) += mtip1000.o
 obj-$(CONFIG_FEC) += fec.o
+obj-$(CONFIG_FEC_MII_BIT_BANG) += fec_mii_bit_bang.o
 obj-$(CONFIG_ARM_ETHERH) += 8390.o
 obj-$(CONFIG_WD80x3) += wd.o 8390.o
 obj-$(CONFIG_EL2) += 3c503.o 8390.o
diff -urN uClinux-dist.orig/linux-2.6.x/drivers/net/fec.c 
uClinux-dist/linux-2.6.x/drivers/net/fec.c
--- uClinux-dist.orig/linux-2.6.x/drivers/net/fec.c     2007-01-17 
15:58:59.000000000 +1000
+++ uClinux-dist/linux-2.6.x/drivers/net/fec.c  2007-05-11 16:12:16.000000000 
+1000
@@ -60,6 +60,10 @@
 #include "commproc.h"
 #endif
 
+#if defined(CONFIG_FEC_MII_BIT_BANG)
+#include "fec_mii_bit_bang.h"
+#endif
+
 #if defined(CONFIG_FEC2)
 #define        FEC_MAX_PORTS   2
 #else
@@ -745,6 +749,19 @@
 
        spin_lock_irqsave(&fep->lock,flags);
 
+#if defined(CONFIG_FEC_MII_BIT_BANG)
+       /* If bit banging the MII just do it and don't bother
+        * adding it to the queue.  once we have the result
+        * call the function to parse it.
+        */
+       {
+               uint mii_result;
+               mii_result = mii_bit_bang_do(regval);
+               if (func != NULL) {
+                       func(mii_result, dev);
+               }
+       }
+#else
        if ((mip = mii_free) != NULL) {
                mii_free = mip->mii_next;
                mip->mii_regval = regval;
@@ -762,6 +779,7 @@
        else {
                retval = 1;
        }
+#endif
 
        spin_unlock_irqrestore(&fep->lock,flags);
 
@@ -1159,6 +1177,28 @@
 };
 
 /* ------------------------------------------------------------------------- */
+/* ST Microelectronics STE100P phy                                           */
+
+/* register definitions for the STE100P */
+
+static phy_cmd_t const phy_cmd_ste100p_config[] = {
+               { mk_mii_read(MII_REG_CR), mii_parse_cr },
+               { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+               { mk_mii_end, }
+       };
+static phy_cmd_t const phy_cmd_ste100p_startup[] = {
+               { mk_mii_read(MII_REG_SR), mii_parse_sr },
+               { mk_mii_end, }
+       };
+
+static phy_info_t phy_info_ste100p = {
+       .id = 0x1c04001,
+       .name = "STE100P",
+       .config = phy_cmd_ste100p_config,
+       .startup = phy_cmd_ste100p_startup,
+};
+
+/* ------------------------------------------------------------------------- */
 /* register definitions for the DP83848 */
 
 #define MII_DP8384X_PHYSTST    16  /* PHY Status Register */
@@ -1226,6 +1266,7 @@
        &phy_info_am79c874,
        &phy_info_ks8721bl,
        &phy_info_dp83848,
+       &phy_info_ste100p,
        NULL
 };
 
@@ -1423,7 +1464,9 @@
 
                gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);
                gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);
+#if !defined(CONFIG_FEC_MII_BIT_BANG)
                *gpio_paspar |= 0x0f00;
+#endif
                *gpio_pehlpar = 0xc0;
        }
 #endif
@@ -2469,6 +2512,10 @@
        /* setup MII interface */
        fec_set_mii(dev, fep);
 
+#if defined(CONFIG_FEC_MII_BIT_BANG)
+       mii_bit_bang_setup();
+#endif
+
        /* Clear and enable interrupts */
        fecp->fec_ievent = 0xffc00000;
        fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
diff -urN uClinux-dist.orig/linux-2.6.x/drivers/net/fec_mii_bit_bang.c 
uClinux-dist/linux-2.6.x/drivers/net/fec_mii_bit_bang.c
--- uClinux-dist.orig/linux-2.6.x/drivers/net/fec_mii_bit_bang.c        
1970-01-01 10:00:00.000000000 +1000
+++ uClinux-dist/linux-2.6.x/drivers/net/fec_mii_bit_bang.c     2007-05-11 
16:12:16.000000000 +1000
@@ -0,0 +1,335 @@
+/****************************************************************************/
+
+/*
+ *     fec_mii_bit_bang.c  --  Interface for bit banging the MII used in
+ *                              FEC module
+ *
+ *     (C) Copyright 2005, Intec Automation,
+ *                         Mike Lavender ([EMAIL PROTECTED])
+ *
+
+     This program 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 of the License, or
+     (at your option) any later version.
+
+     This program 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 this program; if not, write to the Free Software
+     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+/* ------------------------------------------------------------------------- */
+
+/****************************************************************************/
+
+/****************************************************************************/
+
+/*
+ * Includes
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+#include "fec_mii_bit_bang.h"
+
+/****************************************************************************/
+
+/*
+ * Defines and Macros
+ */
+
+#define        READING_MII(x)  (((x) & 0xf0000000) == 0x60000000)
+
+#if defined(CONFIG_WILDFIREMOD)
+
+#define MDIO_INDEX 4   // PIN 4
+#define MDC_INDEX  7   // PIN 7
+
+static inline void mii_bb_init(void)
+{
+       /* Set lines to Digital IO */
+       MCF5282_GPIO_PEPAR &= ~((1 << (MDIO_INDEX * 2)) | (1 << (MDC_INDEX  * 
2)));
+
+       /* Set clock as output */
+       MCF5282_GPIO_DDRE |= (1 << MDC_INDEX);
+}
+
+static inline int mii_bb_data(void)
+{
+       return !!(MCF5282_GPIO_PORTEP & (1 << MDIO_INDEX));
+}
+
+static inline void mii_bb_set_data(int value)
+{
+       if (value) {
+               MCF5282_GPIO_PORTE |= (1 << MDIO_INDEX);
+       }
+       else {
+               MCF5282_GPIO_PORTE &= ~(1 << MDIO_INDEX);
+       }
+}
+
+static inline void mii_bb_set_clock(int value)
+{
+       if (value) {
+               MCF5282_GPIO_PORTE |= (1 << MDC_INDEX);
+       }
+       else {
+               MCF5282_GPIO_PORTE &= ~(1 << MDC_INDEX);
+       }
+}
+
+static inline void mii_bb_data_as_output(void)
+{
+       MCF5282_GPIO_DDRE |= (1 << MDIO_INDEX);
+}
+
+static inline void mii_bb_data_as_input(void)
+{
+       MCF5282_GPIO_DDRE &= ~(1 << MDIO_INDEX);
+}
+
+#elif defined(CONFIG_WILDFIRE)
+
+#define MDIO_INDEX 6   // PIN 6
+#define MDC_INDEX  5   // PIN 5
+
+static inline void mii_bb_init(void)
+{
+       /* Set lines to Digital IO */
+       MCF5282_GPIO_PQSPAR &= ~((1 << MDIO_INDEX) | (1 << MDC_INDEX));
+
+       /* Set clock as output */
+       MCF5282_GPIO_DDRQS |= (1 << MDC_INDEX);
+}
+
+static inline int mii_bb_data(void)
+{
+       return !!(MCF5282_GPIO_PORTQSP & (1 << MDIO_INDEX));
+}
+
+static inline void mii_bb_set_data(int value)
+{
+       if (value) {
+               MCF5282_GPIO_PORTQS |= (1 << MDIO_INDEX);
+       }
+       else {
+               MCF5282_GPIO_PORTQS &= ~(1 << MDIO_INDEX);
+       }
+}
+
+static inline void mii_bb_set_clock(int value)
+{
+       if (value) {
+               MCF5282_GPIO_PORTQS |= (1 << MDC_INDEX);
+       }
+       else {
+               MCF5282_GPIO_PORTQS &= ~(1 << MDC_INDEX);
+       }
+}
+
+static inline void mii_bb_data_as_output(void)
+{
+       MCF5282_GPIO_DDRQS |= (1 << MDIO_INDEX);
+}
+
+static inline void mii_bb_data_as_input(void)
+{
+       MCF5282_GPIO_DDRQS &= ~(1 << MDIO_INDEX);
+}
+
+#else
+
+#error don't know how to bitbang mii on this platform
+
+#endif
+
+/****************************************************************************/
+
+/*
+ * Global variables
+ */
+
+
+/****************************************************************************/
+
+/*
+ * Implementation
+ */
+
+/*
+ * Read a single bit from the MII bus and then set the clock.
+ */
+static int
+write_clock_and_read_data(int clock)
+{
+       unsigned char data;
+
+       mii_bb_data_as_input();
+       data = mii_bb_data();
+       mii_bb_set_clock(clock);
+
+       udelay(1);
+
+       return data;
+}
+
+
+/*
+ * Write a single bit on the MII bus by first setting the clock
+ * and then writing the data.
+ */
+static void
+write_clock_and_data(int clock, int data)
+{
+       mii_bb_data_as_output();
+       mii_bb_set_clock(clock);
+       mii_bb_set_data(data);
+
+       udelay(1);
+}
+
+/**
+ * Write a single bit while toggling the clock
+ * from low to high
+ */
+static inline void
+write_data(int data)
+{
+       write_clock_and_data(0, data);
+       write_clock_and_data(1, data);
+}
+
+
+static void
+mii_preamble(void)
+{
+       int i;
+
+       for (i = 0; i < 36; i++) {
+               write_data(1);
+       }
+}
+
+
+static uint
+mii_bit_bang_readreg(int regval)
+{
+       int  bit;
+       uint result;
+       uint id   = (regval >> 23) & 0x1f;
+       uint addr = (regval >> 18) & 0x1f;
+
+       // Preamble.
+       mii_preamble();
+
+       // Setup:  Write 0, 1 to MDIO.
+       write_data(0);
+       write_data(1);
+
+       // Opcode:  Write 1, 0 to MDIO.
+       write_data(1);
+       write_data(0);
+
+       // 5 which-port bits
+       for (bit = 4; bit >= 0; bit--) {
+               write_data((id >> bit) & 1);
+       }
+
+       // 5 register bits
+       for (bit = 4; bit >= 0; bit--) {
+               write_data((addr >> bit) & 1);
+       }
+
+       // Turn around
+       (void)write_clock_and_read_data(0);
+       (void)write_clock_and_read_data(1);
+       (void)write_clock_and_read_data(0);
+
+       // 16 data bits
+       result = 0;
+       for (bit = 15; bit >= 0; bit--) {
+               (void)write_clock_and_read_data(1);
+               result |= write_clock_and_read_data(0) << bit;
+       }
+
+       return result;
+}
+
+static void
+mii_bit_bang_writereg(int regval)
+{
+       uint id   = (regval >> 23) & 0x1f;
+       uint addr = (regval >> 18) & 0x1f;
+       uint data = regval & 0xffff;
+       int  bit;
+
+       // Preamble.
+       mii_preamble();
+
+       // ST (whatever that means):  Write 0, 1 to MDIO.
+       write_data(0);
+       write_data(1);
+
+       // Opcode:  Write 0, 1 to MDIO.
+       write_data(0);
+       write_data(1);
+
+       // 5 which-port bits
+       for (bit = 4; bit >= 0; bit--) {
+               write_data((id >> bit) & 1);
+       }
+
+       // 5 register bits
+       for (bit = 4; bit >= 0; bit--) {
+               write_data((addr >> bit) & 1);
+       }
+
+       // Turn around
+       write_data(1);
+       write_data(0);
+
+       // 16 data bits
+       for (bit = 15; bit >= 0; bit--) {
+               write_data((data >> bit) & 1);
+       }
+}
+
+/*
+ * Called by the fec module (fec_enet_init) if bit banging the
+ * MII is configured.  Will setup the pins required to bit bang
+ * and any internal data.
+ */
+void
+mii_bit_bang_setup(void)
+{
+       mii_bb_init();
+
+       /* drive the clock and data low for now */
+       mii_bb_set_data(0);
+       mii_bb_set_clock(0);
+
+       /* Make the data an output to begin with */
+       mii_bb_data_as_output();
+}
+
+
+/*
+ * Execute an MII register read or write.  If the request is
+ * a read then return the register value otherwise return 0.
+ */
+uint
+mii_bit_bang_do(int regval)
+{
+       if (READING_MII(regval)) {
+               return mii_bit_bang_readreg(regval);
+       } else {
+               mii_bit_bang_writereg(regval);
+               return 0;
+       }
+}
diff -urN uClinux-dist.orig/linux-2.6.x/drivers/net/fec_mii_bit_bang.h 
uClinux-dist/linux-2.6.x/drivers/net/fec_mii_bit_bang.h
--- uClinux-dist.orig/linux-2.6.x/drivers/net/fec_mii_bit_bang.h        
1970-01-01 10:00:00.000000000 +1000
+++ uClinux-dist/linux-2.6.x/drivers/net/fec_mii_bit_bang.h     2007-05-11 
16:12:16.000000000 +1000
@@ -0,0 +1,37 @@
+/****************************************************************************/
+
+/*
+ *     fec_mii_bit_bang.h  --  Interface for bit banging the MII used in
+ *                              FEC module
+ *
+ *     (C) Copyright 2005, Intec Automation,
+ *                         Mike Lavender ([EMAIL PROTECTED])
+ */
+
+/****************************************************************************/
+#ifndef FEC_MII_BIT_BANG_H
+#define        FEC_MII_BIT_BANG_H
+/****************************************************************************/
+
+/* Bit banging the MII interface: On some boards the MII lines are
+ * multiplexed with other signals like UART3 on the MCF5282.  This
+ * configuration will use two digital IO pins to talk to the PHY
+ * instead of the integrated MII module
+ */
+
+/*
+ * Called by the fec module (fec_enet_init) if bit banging the
+ * MII is configured.  Will setup the pins required to bit bang
+ * and any internal data.
+ */
+void
+mii_bit_bang_setup(void);
+
+/*
+ * Execute an MII register read or write.  If the request is
+ * a read then return the register value otherwise return 0.
+ */
+uint
+mii_bit_bang_do(int regval);
+
+#endif /* FEC_MII_BIT_BANG_H */
_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to