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