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"