diff --git a/board/freescale/twr-k60n512/board.c b/board/freescale/twr-k60n512/board.c
index 2f338d6f362139aa03a03629ea99329f5051edac..cc65300fcb88f06334be459e3cb1cc0fc0684e73 100644
--- a/board/freescale/twr-k60n512/board.c
+++ b/board/freescale/twr-k60n512/board.c
@@ -24,15 +24,62 @@
*/
#include <common.h>
+#include <netdev.h>
+
+#include <asm/arch/kinetis_gpio.h>
DECLARE_GLOBAL_DATA_PTR;
+/*
+ * GPIO pin configuration table for TWR-K60N512
+ *
+ * This table does not list all GPIO pins that will be configured. See also
+ * the code in `gpio_init()` and in the drivers (for example, the UART driver).
+ */
+static const struct kinetis_gpio_pin_config twr_k60n512_gpio[] = {
+#ifdef CONFIG_MCFFEC
+ /* A.5 = RMII0_RXER */
+ {{KINETIS_GPIO_PORT_A, 5}, KINETIS_GPIO_CONFIG_PULLDOWN(4)},
+ /* A.12 = RMII0_RXD1 */
+ {{KINETIS_GPIO_PORT_A, 12}, KINETIS_GPIO_CONFIG_MUX(4)},
+ /* A.13 = RMII0_RXD0 */
+ {{KINETIS_GPIO_PORT_A, 13}, KINETIS_GPIO_CONFIG_MUX(4)},
+ /* A.14 = RMII0_CRS_DV */
+ {{KINETIS_GPIO_PORT_A, 14}, KINETIS_GPIO_CONFIG_MUX(4)},
+ /* A.15 = RMII0_TXEN */
+ {{KINETIS_GPIO_PORT_A, 15}, KINETIS_GPIO_CONFIG_MUX(4)},
+ /* A.16 = RMII0_TXD0 */
+ {{KINETIS_GPIO_PORT_A, 16}, KINETIS_GPIO_CONFIG_MUX(4)},
+ /* A.17 = RMII0_TXD1 */
+ {{KINETIS_GPIO_PORT_A, 17}, KINETIS_GPIO_CONFIG_MUX(4)},
+ /* B.0 = RMII0_MDIO */
+ {{KINETIS_GPIO_PORT_B, 0}, KINETIS_GPIO_CONFIG_MUX(4)},
+ /* B.1 = RMII0_MDC */
+ {{KINETIS_GPIO_PORT_B, 1}, KINETIS_GPIO_CONFIG_MUX(4)},
+#endif /* CONFIG_MCFFEC */
+};
+
+/*
+ * Configure all necessary GPIO pins
+ */
+static void gpio_init(void)
+{
+ /*
+ * Configure GPIO pins using the `twr_k60n512_gpio[]` table
+ */
+ kinetis_gpio_config_table(twr_k60n512_gpio, ARRAY_SIZE(twr_k60n512_gpio));
+}
+
/*
* Early hardware init.
*/
int board_init(void)
{
- /* TBD */
+ /*
+ * Enable GPIO pins
+ */
+ gpio_init();
+
return 0;
}
@@ -65,3 +112,13 @@ int dram_init(void)
return 0;
}
+#ifdef CONFIG_MCFFEC
+/*
+ * Register the Ethernet driver
+ */
+int board_eth_init(bd_t *bis)
+{
+ return mcffec_initialize(bis);
+}
+#endif
+
diff --git a/cpu/arm_cortexm3/kinetis/Makefile b/cpu/arm_cortexm3/kinetis/Makefile
index 5cce1c2fe4e50542a95288bcc0c8fb5d81dd4c59..cbf80aeeda10616e9b96902a96b7e7ebff4d3914 100644
--- a/cpu/arm_cortexm3/kinetis/Makefile
+++ b/cpu/arm_cortexm3/kinetis/Makefile
@@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).a
-COBJS := clock.o cpu.o envm.o wdt.o
+COBJS := clock.o cpu.o envm.o eth.o soc.o wdt.o
SOBJS :=
SRCS := $(COBJS:.o=.c)
diff --git a/cpu/arm_cortexm3/kinetis/clock.c b/cpu/arm_cortexm3/kinetis/clock.c
index 30b4253f2d2900e0b334535a0302415fe478bd18..d08cbe7063d4a17b006d2d4afd5d1c8bfcfca60e 100644
--- a/cpu/arm_cortexm3/kinetis/clock.c
+++ b/cpu/arm_cortexm3/kinetis/clock.c
@@ -510,6 +510,11 @@ void clock_init(void)
* Set the bus clock rate (used for many peripherals)
*/
clock_val[CLOCK_PCLK] = KINETIS_PCLK_RATE;
+
+ /*
+ * The MAC internal module clock is OSC0ERCLK
+ */
+ clock_val[CLOCK_MACCLK] = KINETIS_EXTAL_RATE;
}
/*
diff --git a/cpu/arm_cortexm3/kinetis/eth.c b/cpu/arm_cortexm3/kinetis/eth.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b4b37eefb1ac342f818a6831217ac9bbb1465a0
--- /dev/null
+++ b/cpu/arm_cortexm3/kinetis/eth.c
@@ -0,0 +1,43 @@
+/*
+ * (C) Copyright 2011
+ *
+ * Alexander Potashev, Emcraft Systems, aspotashev@emcraft.com
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#include <asm/arch/kinetis.h>
+
+#if defined(CONFIG_CMD_NET)
+/*
+ * This function is called by the `mcffec.c` driver with setclear=1
+ * on FEC initialization, and with setclear=0 on FEC halt.
+ *
+ * Someone might think that we could put the clock gate enable/disable code
+ * for Ethernet here. But this thought is wrong, because the Ethernet module
+ * clocking must be enabled even when resetting the Ethernet module (otherwise
+ * we get an exception.) In the `fec_halt()` function, a MAC reset may be
+ * attempted before calling `fecpin_setclear(dev, 1)`, therefore the clock for
+ * the Ethernet module must be enabled somewhere else.
+ * We do this in `cortex_m3_soc_init()`.
+ */
+int fecpin_setclear(struct eth_device *dev, int setclear)
+{
+ return 0;
+}
+#endif /* CONFIG_CMD_NET */
diff --git a/cpu/arm_cortexm3/kinetis/soc.c b/cpu/arm_cortexm3/kinetis/soc.c
new file mode 100644
index 0000000000000000000000000000000000000000..c7da4a9e4a5a238d4e1a338bd09defd9e0c3125a
--- /dev/null
+++ b/cpu/arm_cortexm3/kinetis/soc.c
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2011
+ *
+ * Alexander Potashev, Emcraft Systems, aspotashev@emcraft.com
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#include "soc.h"
+
+/*
+ * Memory Protection Unit (MPU) register map
+ *
+ * See Chapter 18 of the K60 Reference Manual (page 409)
+ */
+struct kinetis_mpu_regs {
+ u32 cesr; /* Control/Error Status Register */
+};
+
+/*
+ * MPU registers base
+ */
+#define KINETIS_MPU_BASE (KINETIS_AIPS0PERIPH_BASE + 0x0000D000)
+#define KINETIS_MPU ((volatile struct kinetis_mpu_regs *) \
+ KINETIS_MPU_BASE)
+
+/*
+ * SoC configuration code that cannot be put into drivers
+ */
+#ifdef CONFIG_ARMCORTEXM3_SOC_INIT
+void cortex_m3_soc_init(void)
+{
+#ifdef CONFIG_MCFFEC
+ /*
+ * Enable the clock on the Ethernet module of the MCU
+ */
+ kinetis_periph_enable(KINETIS_CG_ENET, 1);
+#endif /* CONFIG_MCFFEC */
+
+ /*
+ * Disable the MPU to let the Ethernet module access the SRAM
+ */
+ KINETIS_MPU->cesr = 0;
+}
+#endif
diff --git a/drivers/gpio/kinetis_gpio.c b/drivers/gpio/kinetis_gpio.c
index c53f052690bfb351ed4146a8c8d2b2f7b22e043f..713f86026cbfcf314828d525693daeb5c962778b 100644
--- a/drivers/gpio/kinetis_gpio.c
+++ b/drivers/gpio/kinetis_gpio.c
@@ -119,3 +119,23 @@ out:
return rv;
}
+/*
+ * Configure a set of GPIO pins using the given configuration table.
+ * Returns 0 on success.
+ */
+int kinetis_gpio_config_table(
+ const struct kinetis_gpio_pin_config *table, unsigned int len)
+{
+ unsigned int i;
+ int rv;
+
+ for (i = 0; i < len; i ++) {
+ rv = kinetis_gpio_config(&table[i].dsc, table[i].regval);
+ if (rv != 0)
+ goto out;
+ }
+
+ rv = 0;
+out:
+ return rv;
+}
diff --git a/include/asm-arm/arch-kinetis/kinetis.h b/include/asm-arm/arch-kinetis/kinetis.h
index 18676ecede2c6d3f2ba50a6ee82070ff155c3a32..aa73f6a5e09b3f60b0e2856a85e2933bc04001d9 100644
--- a/include/asm-arm/arch-kinetis/kinetis.h
+++ b/include/asm-arm/arch-kinetis/kinetis.h
@@ -86,6 +86,8 @@ typedef u32 kinetis_clock_gate_t;
#define KINETIS_CG_PORTC KINETIS_MKCG(4, 11) /* SIM_SCGC5[11] */
#define KINETIS_CG_PORTD KINETIS_MKCG(4, 12) /* SIM_SCGC5[12] */
#define KINETIS_CG_PORTE KINETIS_MKCG(4, 13) /* SIM_SCGC5[13] */
+/* ENET */
+#define KINETIS_CG_ENET KINETIS_MKCG(1, 0) /* SIM_SCGC2[0] */
/*
* Enable or disable the clock on a peripheral device (timers, UARTs, USB, etc)
@@ -99,6 +101,7 @@ enum clock {
CLOCK_SYSTICK, /* Systimer clock frequency expressed in Hz */
CLOCK_CCLK, /* Core clock frequency expressed in Hz */
CLOCK_PCLK, /* Bus clock frequency expressed in Hz */
+ CLOCK_MACCLK, /* MAC module clock frequency expressed in Hz */
CLOCK_END /* for internal usage */
};
diff --git a/include/asm-arm/arch-kinetis/kinetis_gpio.h b/include/asm-arm/arch-kinetis/kinetis_gpio.h
index f9e49928f50cf933d066515d52e16498f1d4ef61..0f9b542737d4dbca916cfacc725533fa2fad4510 100644
--- a/include/asm-arm/arch-kinetis/kinetis_gpio.h
+++ b/include/asm-arm/arch-kinetis/kinetis_gpio.h
@@ -27,6 +27,9 @@
*/
/* Pin Mux Control (selects pin function) */
#define KINETIS_GPIO_CONFIG_MUX_BITS 8
+/* Pull Enable (pull-down by default) */
+#define LPC178X_GPIO_CONFIG_PE_BIT 1
+#define LPC178X_GPIO_CONFIG_PE_MSK (1 << LPC178X_GPIO_CONFIG_PE_BIT)
/*
* These macros should be used to compute the value for the second argument of
@@ -36,6 +39,8 @@
/* The simplest macro that only allow to configure the MUX bits */
#define KINETIS_GPIO_CONFIG_MUX(mux) \
(mux << KINETIS_GPIO_CONFIG_MUX_BITS)
+#define KINETIS_GPIO_CONFIG_PULLDOWN(mux) \
+ ((mux << KINETIS_GPIO_CONFIG_MUX_BITS) | LPC178X_GPIO_CONFIG_PE_MSK)
/*
* TBD: similar macros with more options
*/
@@ -70,10 +75,22 @@ struct kinetis_gpio_dsc {
unsigned int pin; /* GPIO pin */
};
+struct kinetis_gpio_pin_config {
+ struct kinetis_gpio_dsc dsc;
+ u32 regval; /* Value for writing into the PCR register */
+};
+
/*
* Configure the specified GPIO pin.
* Returns 0 on success, -EINVAL otherwise.
*/
int kinetis_gpio_config(const struct kinetis_gpio_dsc *dsc, u32 regval);
+/*
+ * Configure a set of GPIO pins using the given configuration table.
+ * Returns 0 on success.
+ */
+extern int kinetis_gpio_config_table(
+ const struct kinetis_gpio_pin_config *table, unsigned int len);
+
#endif /* _KINETIS_GPIO_H_ */
diff --git a/include/configs/twr-k60n512.h b/include/configs/twr-k60n512.h
index 9093999d0787243214cb8ac38198e2386a7787a7..1e9aadf386161e2accbc4e9793982d0a60100362 100644
--- a/include/configs/twr-k60n512.h
+++ b/include/configs/twr-k60n512.h
@@ -66,6 +66,11 @@
*/
#define CONFIG_ARCH_CPU_INIT
+/*
+ * This ensures that the SoC-specific cortex_m3_soc_init() gets invoked.
+ */
+#define CONFIG_ARMCORTEXM3_SOC_INIT
+
/*
* Clock configuration (see cpu/arm_cortexm3/kinetis/clock.c for details)
*/
@@ -188,7 +193,36 @@
/*
* Ethernet configuration
*/
-/* TBD */
+#define CONFIG_MCFFEC
+/* Only the RMII mode is possible on the TWR-K60N512 board */
+#undef CONFIG_MCFFEC_MII
+#define CONFIG_NET_MULTI
+#define CONFIG_MII
+#define CONFIG_MII_INIT
+/*
+ * The value of CONFIG_SYS_FEC0_PINMUX does not matter.
+ * This configuration option is required by the `mcffec.c` driver.
+ */
+#define CONFIG_SYS_FEC0_PINMUX 0
+#define CONFIG_SYS_FEC0_IOBASE 0x400C0000
+#define CONFIG_SYS_FEC0_MIIBASE CONFIG_SYS_FEC0_IOBASE
+/*
+ * Ethernet buffer descriptor tables should be aligned on 512-byte boundaries
+ */
+#define CONFIG_SYS_CACHELINE_SIZE 512
+#define MCFFEC_TOUT_LOOP 1000000
+#define CONFIG_SYS_DISCOVER_PHY
+#define CONFIG_SYS_RX_ETH_BUFFER 8
+/*
+ * Options for the MDC clock
+ */
+/* Internal MAC clock rate */
+#define CONFIG_MCFFEC_MAC_CLK clock_get(CLOCK_MACCLK)
+/*
+ * We limit the MDC rate to 800 kHz, because the rate of 2.5 MHz leads to data
+ * corruption when reading the PHY registers.
+ */
+#define CONFIG_MCFFEC_MII_SPEED_LIMIT 800000
/*
* Console I/O buffer size
@@ -236,7 +270,7 @@
#undef CONFIG_CMD_IMLS
#undef CONFIG_CMD_LOADS
#undef CONFIG_CMD_MISC
-#undef CONFIG_CMD_NET
+#define CONFIG_CMD_NET
#undef CONFIG_CMD_NFS
#undef CONFIG_CMD_SOURCE
#undef CONFIG_CMD_XIMG
@@ -274,8 +308,8 @@
"addip=setenv bootargs ${bootargs} " \
"ip=${ipaddr}:${serverip}:${gatewayip}:" \
"${netmask}:${hostname}:eth0:off\0" \
- "ethaddr=C0:B1:3C:88:88:88\0" \
- "ipaddr=172.17.4.206\0" \
+ "ethaddr=C0:B1:3C:77:88:99\0" \
+ "ipaddr=172.17.6.35\0" \
"serverip=172.17.0.1\0" \
"image=k60/uImage\0" \
"netboot=tftp ${image};run addip;bootm\0"