Patchwork [U-Boot,v4,3/3] arm: at91: add at91sam9n12ek board support

login
register
mail settings
Submitter Wu, Josh
Date April 17, 2013, 9:42 a.m.
Message ID <1366191764-17549-4-git-send-email-josh.wu@atmel.com>
Download mbox | patch
Permalink /patch/237184/
State Accepted
Delegated to: Andreas BieƟmann
Headers show

Comments

Wu, Josh - April 17, 2013, 9:42 a.m.
Add support for following features:
  - nand boot, with PMECC 2bit ECC for 512 bytes sector
  - SPI flash boot
  - SD card boot
  - LCD support

Signed-off-by: Josh Wu <josh.wu@atmel.com>
---
changes since v3:
  - use 9N12 cpu macro to select plla clock in clock.c

changes since v2:
  - remove redudent blank line in the end of at91sam9n12_devices.c.

 MAINTAINERS                                       |    3 +
 arch/arm/cpu/arm926ejs/at91/Makefile              |    1 +
 arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c |  177 ++++++++++++++++
 arch/arm/cpu/arm926ejs/at91/clock.c               |    4 +-
 board/atmel/at91sam9n12ek/Makefile                |   52 +++++
 board/atmel/at91sam9n12ek/at91sam9n12ek.c         |  228 ++++++++++++++++++++
 boards.cfg                                        |    3 +
 include/configs/at91sam9n12ek.h                   |  232 +++++++++++++++++++++
 8 files changed, 698 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c
 create mode 100644 board/atmel/at91sam9n12ek/Makefile
 create mode 100644 board/atmel/at91sam9n12ek/at91sam9n12ek.c
 create mode 100644 include/configs/at91sam9n12ek.h

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index bbab5fe..642d318 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1017,6 +1017,9 @@  Richard Woodruff <r-woodruff2@ti.com>
 
 	omap2420h4	ARM1136EJS
 
+Josh Wu <josh.wu@atmel.com>
+	at91sam9n12ek	ARM926EJS (AT91SAM9N12 SoC)
+
 Ilya Yanok <yanok@emcraft.com>
 
 	mcx		ARM ARMV7 (AM35x SoC)
diff --git a/arch/arm/cpu/arm926ejs/at91/Makefile b/arch/arm/cpu/arm926ejs/at91/Makefile
index 346e58f..c4408f6 100644
--- a/arch/arm/cpu/arm926ejs/at91/Makefile
+++ b/arch/arm/cpu/arm926ejs/at91/Makefile
@@ -35,6 +35,7 @@  COBJS-$(CONFIG_AT91SAM9263)	+= at91sam9263_devices.o
 COBJS-$(CONFIG_AT91SAM9RL)	+= at91sam9rl_devices.o
 COBJS-$(CONFIG_AT91SAM9M10G45)	+= at91sam9m10g45_devices.o
 COBJS-$(CONFIG_AT91SAM9G45)	+= at91sam9m10g45_devices.o
+COBJS-$(CONFIG_AT91SAM9N12)	+= at91sam9n12_devices.o
 COBJS-$(CONFIG_AT91SAM9X5)	+= at91sam9x5_devices.o
 COBJS-$(CONFIG_AT91_EFLASH)	+= eflash.o
 COBJS-$(CONFIG_AT91_LED)	+= led.o
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c b/arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c
new file mode 100644
index 0000000..6eaeac0
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c
@@ -0,0 +1,177 @@ 
+/*
+ * (C) Copyright 2013 Atmel Corporation
+ * Josh Wu <josh.wu@atmel.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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/io.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_pio.h>
+
+unsigned int has_lcdc()
+{
+	return 1;
+}
+
+void at91_serial0_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 0, 1);		/* TXD0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 1, 0);		/* RXD0 */
+	writel(1 << ATMEL_ID_USART0, &pmc->pcer);
+}
+
+void at91_serial1_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 5, 1);		/* TXD1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 6, 0);		/* RXD1 */
+	writel(1 << ATMEL_ID_USART1, &pmc->pcer);
+}
+
+void at91_serial2_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 7, 1);		/* TXD2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 8, 0);		/* RXD2 */
+	writel(1 << ATMEL_ID_USART2, &pmc->pcer);
+}
+
+void at91_serial3_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_b_periph(AT91_PIO_PORTC, 22, 1);		/* TXD3 */
+	at91_set_b_periph(AT91_PIO_PORTC, 23, 0);		/* RXD3 */
+	writel(1 << ATMEL_ID_USART3, &pmc->pcer);
+}
+
+void at91_seriald_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 10, 1);		/* DTXD */
+	at91_set_a_periph(AT91_PIO_PORTA, 9, 0);		/* DRXD */
+	writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+}
+
+#ifdef CONFIG_ATMEL_SPI
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 11, 0);	/* SPI0_MISO */
+	at91_set_a_periph(AT91_PIO_PORTA, 12, 0);	/* SPI0_MOSI */
+	at91_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* SPI0_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI0, &pmc->pcer);
+
+	if (cs_mask & (1 << 0))
+		at91_set_pio_output(AT91_PIO_PORTA, 14, 1);
+	if (cs_mask & (1 << 1))
+		at91_set_pio_output(AT91_PIO_PORTA, 7, 1);
+	if (cs_mask & (1 << 2))
+		at91_set_pio_output(AT91_PIO_PORTA, 1, 1);
+	if (cs_mask & (1 << 3))
+		at91_set_pio_output(AT91_PIO_PORTB, 3, 1);
+}
+
+void at91_spi1_hw_init(unsigned long cs_mask)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_b_periph(AT91_PIO_PORTA, 21, 0);	/* SPI1_MISO */
+	at91_set_b_periph(AT91_PIO_PORTA, 22, 0);	/* SPI1_MOSI */
+	at91_set_b_periph(AT91_PIO_PORTA, 23, 0);	/* SPI1_SPCK */
+
+	/* Enable clock */
+	writel(1 << ATMEL_ID_SPI1, &pmc->pcer);
+
+	if (cs_mask & (1 << 0))
+		at91_set_pio_output(AT91_PIO_PORTA, 8, 1);
+	if (cs_mask & (1 << 1))
+		at91_set_pio_output(AT91_PIO_PORTA, 0, 1);
+	if (cs_mask & (1 << 2))
+		at91_set_pio_output(AT91_PIO_PORTA, 31, 1);
+	if (cs_mask & (1 << 3))
+		at91_set_pio_output(AT91_PIO_PORTA, 30, 1);
+}
+#endif
+
+void at91_mci_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTA, 17, 0);	/* MCCK */
+	at91_set_a_periph(AT91_PIO_PORTA, 16, 0);	/* MCCDA */
+	at91_set_a_periph(AT91_PIO_PORTA, 15, 0);	/* MCDA0 */
+	at91_set_a_periph(AT91_PIO_PORTA, 18, 0);	/* MCDA1 */
+	at91_set_a_periph(AT91_PIO_PORTA, 19, 0);	/* MCDA2 */
+	at91_set_a_periph(AT91_PIO_PORTA, 20, 0);	/* MCDA3 */
+
+	writel(1 << ATMEL_ID_HSMCI0, &pmc->pcer);
+}
+
+#ifdef CONFIG_LCD
+void at91_lcd_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	at91_set_a_periph(AT91_PIO_PORTC, 24, 0);	/* LCDDPWR */
+	at91_set_a_periph(AT91_PIO_PORTC, 26, 0);	/* LCDVSYNC */
+	at91_set_a_periph(AT91_PIO_PORTC, 27, 0);	/* LCDHSYNC */
+	at91_set_a_periph(AT91_PIO_PORTC, 28, 0);	/* LCDDOTCK */
+	at91_set_a_periph(AT91_PIO_PORTC, 29, 0);	/* LCDDEN */
+	at91_set_a_periph(AT91_PIO_PORTC, 30, 0);	/* LCDDOTCK */
+
+	at91_set_a_periph(AT91_PIO_PORTC, 0, 0);	/* LCDD0 */
+	at91_set_a_periph(AT91_PIO_PORTC, 1, 0);	/* LCDD1 */
+	at91_set_a_periph(AT91_PIO_PORTC, 2, 0);	/* LCDD2 */
+	at91_set_a_periph(AT91_PIO_PORTC, 3, 0);	/* LCDD3 */
+	at91_set_a_periph(AT91_PIO_PORTC, 4, 0);	/* LCDD4 */
+	at91_set_a_periph(AT91_PIO_PORTC, 5, 0);	/* LCDD5 */
+	at91_set_a_periph(AT91_PIO_PORTC, 6, 0);	/* LCDD6 */
+	at91_set_a_periph(AT91_PIO_PORTC, 7, 0);	/* LCDD7 */
+	at91_set_a_periph(AT91_PIO_PORTC, 8, 0);	/* LCDD8 */
+	at91_set_a_periph(AT91_PIO_PORTC, 9, 0);	/* LCDD9 */
+	at91_set_a_periph(AT91_PIO_PORTC, 10, 0);	/* LCDD10 */
+	at91_set_a_periph(AT91_PIO_PORTC, 11, 0);	/* LCDD11 */
+	at91_set_a_periph(AT91_PIO_PORTC, 12, 0);	/* LCDD12 */
+	at91_set_a_periph(AT91_PIO_PORTC, 13, 0);	/* LCDD13 */
+	at91_set_a_periph(AT91_PIO_PORTC, 14, 0);	/* LCDD14 */
+	at91_set_a_periph(AT91_PIO_PORTC, 15, 0);	/* LCDD15 */
+	at91_set_a_periph(AT91_PIO_PORTC, 16, 0);	/* LCDD16 */
+	at91_set_a_periph(AT91_PIO_PORTC, 17, 0);	/* LCDD17 */
+	at91_set_a_periph(AT91_PIO_PORTC, 18, 0);	/* LCDD18 */
+	at91_set_a_periph(AT91_PIO_PORTC, 19, 0);	/* LCDD19 */
+	at91_set_a_periph(AT91_PIO_PORTC, 20, 0);	/* LCDD20 */
+	at91_set_a_periph(AT91_PIO_PORTC, 21, 0);	/* LCDD21 */
+	at91_set_a_periph(AT91_PIO_PORTC, 22, 0);	/* LCDD22 */
+	at91_set_a_periph(AT91_PIO_PORTC, 23, 0);	/* LCDD23 */
+
+	writel(1 << ATMEL_ID_LCDC, &pmc->pcer);
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/at91/clock.c b/arch/arm/cpu/arm926ejs/at91/clock.c
index f825388..5b4923f 100644
--- a/arch/arm/cpu/arm926ejs/at91/clock.c
+++ b/arch/arm/cpu/arm926ejs/at91/clock.c
@@ -156,7 +156,7 @@  int at91_clock_init(unsigned long main_clock)
 	 */
 	mckr = readl(&pmc->mckr);
 #if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
-		|| defined(CONFIG_AT91SAM9X5)
+		|| defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
 	/* plla divisor by 2 */
 	gd->arch.plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
 #endif
@@ -171,7 +171,7 @@  int at91_clock_init(unsigned long main_clock)
 	if (mckr & AT91_PMC_MCKR_MDIV_MASK)
 		freq /= 2;			/* processor clock division */
 #elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
-		|| defined(CONFIG_AT91SAM9X5)
+		|| defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
 	/* mdiv <==> divisor
 	 *  0   <==>   1
 	 *  1   <==>   2
diff --git a/board/atmel/at91sam9n12ek/Makefile b/board/atmel/at91sam9n12ek/Makefile
new file mode 100644
index 0000000..3aa67d5
--- /dev/null
+++ b/board/atmel/at91sam9n12ek/Makefile
@@ -0,0 +1,52 @@ 
+#
+# (C) Copyright 2003-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2008
+# Stelian Pop <stelian.pop@leadtechdesign.com>
+# Lead Tech Design <www.leadtechdesign.com>
+#
+# (C) Copyright 2013
+# Josh Wu <josh.wu@atmel.com>
+# Atmel corporation <www.atmel.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS-y	+= at91sam9n12ek.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/atmel/at91sam9n12ek/at91sam9n12ek.c b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
new file mode 100644
index 0000000..8752794
--- /dev/null
+++ b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
@@ -0,0 +1,228 @@ 
+/*
+ * (C) Copyright 2013 Atmel Corporation
+ * Josh Wu <josh.wu@atmel.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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/io.h>
+#include <asm/arch/at91sam9x5_matrix.h>
+#include <asm/arch/at91sam9_smc.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/clk.h>
+#include <lcd.h>
+#include <atmel_hlcdc.h>
+#include <atmel_mci.h>
+
+#ifdef CONFIG_LCD_INFO
+#include <nand.h>
+#include <version.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Miscelaneous platform dependent initialisations
+ */
+#ifdef CONFIG_NAND_ATMEL
+static void at91sam9n12ek_nand_hw_init(void)
+{
+	struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
+	struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
+	unsigned long csa;
+
+	/* Assign CS3 to NAND/SmartMedia Interface */
+	csa = readl(&matrix->ebicsa);
+	csa |= AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA;
+	/* Configure databus */
+	csa &= ~AT91_MATRIX_NFD0_ON_D16; /* nandflash connect to D0~D15 */
+	/* Configure IO drive */
+	csa &= ~AT91_MATRIX_EBI_EBI_IOSR_NORMAL;
+
+	writel(csa, &matrix->ebicsa);
+
+	/* Configure SMC CS3 for NAND/SmartMedia */
+	writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(0) |
+		AT91_SMC_SETUP_NRD(2) | AT91_SMC_SETUP_NCS_RD(0),
+		&smc->cs[3].setup);
+	writel(AT91_SMC_PULSE_NWE(3) | AT91_SMC_PULSE_NCS_WR(5) |
+		AT91_SMC_PULSE_NRD(4) | AT91_SMC_PULSE_NCS_RD(6),
+		&smc->cs[3].pulse);
+	writel(AT91_SMC_CYCLE_NWE(5) | AT91_SMC_CYCLE_NRD(7),
+		&smc->cs[3].cycle);
+	writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
+		AT91_SMC_MODE_EXNW_DISABLE |
+#ifdef CONFIG_SYS_NAND_DBW_16
+		AT91_SMC_MODE_DBW_16 |
+#else /* CONFIG_SYS_NAND_DBW_8 */
+		AT91_SMC_MODE_DBW_8 |
+#endif
+		AT91_SMC_MODE_TDF_CYCLE(1),
+		&smc->cs[3].mode);
+
+	/* Configure RDY/BSY pin */
+	at91_set_pio_input(AT91_PIO_PORTD, 5, 1);
+
+	/* Configure ENABLE pin for NandFlash */
+	at91_set_pio_output(AT91_PIO_PORTD, 4, 1);
+
+	at91_set_a_periph(AT91_PIO_PORTD, 0, 1);    /* NAND OE */
+	at91_set_a_periph(AT91_PIO_PORTD, 1, 1);    /* NAND WE */
+	at91_set_a_periph(AT91_PIO_PORTD, 2, 1);    /* ALE */
+	at91_set_a_periph(AT91_PIO_PORTD, 3, 1);    /* CLE */
+}
+#endif
+
+#ifdef CONFIG_LCD
+vidinfo_t panel_info = {
+	.vl_col = 480,
+	.vl_row = 272,
+	.vl_clk = 9000000,
+	.vl_bpix = LCD_BPP,
+	.vl_sync = 0,
+	.vl_tft = 1,
+	.vl_hsync_len = 5,
+	.vl_left_margin = 8,
+	.vl_right_margin = 43,
+	.vl_vsync_len = 10,
+	.vl_upper_margin = 4,
+	.vl_lower_margin = 12,
+	.mmio = ATMEL_BASE_LCDC,
+};
+
+void lcd_enable(void)
+{
+	at91_set_pio_output(AT91_PIO_PORTC, 25, 0);	/* power up */
+}
+
+void lcd_disable(void)
+{
+	at91_set_pio_output(AT91_PIO_PORTC, 25, 1);	/* power down */
+}
+
+#ifdef CONFIG_LCD_INFO
+void lcd_show_board_info(void)
+{
+	ulong dram_size, nand_size;
+	int i;
+	char temp[32];
+
+	lcd_printf("%s\n", U_BOOT_VERSION);
+	lcd_printf("ATMEL Corp\n");
+	lcd_printf("at91@atmel.com\n");
+	lcd_printf("%s CPU at %s MHz\n",
+		ATMEL_CPU_NAME,
+		strmhz(temp, get_cpu_clk_rate()));
+
+	dram_size = 0;
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
+		dram_size += gd->bd->bi_dram[i].size;
+	nand_size = 0;
+	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+		nand_size += nand_info[i].size;
+	lcd_printf("  %ld MB SDRAM, %ld MB NAND\n",
+		dram_size >> 20,
+		nand_size >> 20);
+}
+#endif /* CONFIG_LCD_INFO */
+#endif /* CONFIG_LCD */
+
+/* SPI chip select control */
+#ifdef CONFIG_ATMEL_SPI
+#include <spi.h>
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	return bus == 0 && cs < 2;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	switch (slave->cs) {
+	case 0:
+		at91_set_pio_output(AT91_PIO_PORTA, 14, 0);
+		break;
+	case 1:
+		at91_set_pio_output(AT91_PIO_PORTA, 7, 0);
+		break;
+	}
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	switch (slave->cs) {
+	case 0:
+		at91_set_pio_output(AT91_PIO_PORTA, 14, 1);
+		break;
+	case 1:
+		at91_set_pio_output(AT91_PIO_PORTA, 7, 1);
+		break;
+	}
+}
+#endif /* CONFIG_ATMEL_SPI */
+
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+int board_mmc_init(bd_t *bd)
+{
+	at91_mci_hw_init();
+
+	return atmel_mci_init((void *)ATMEL_BASE_HSMCI0);
+}
+#endif
+
+int board_early_init_f(void)
+{
+	/* Enable clocks for all PIOs */
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	writel((1 << ATMEL_ID_PIOAB) | (1 << ATMEL_ID_PIOCD), &pmc->pcer);
+
+	at91_seriald_hw_init();
+	return 0;
+}
+
+int board_init(void)
+{
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+#ifdef CONFIG_NAND_ATMEL
+	at91sam9n12ek_nand_hw_init();
+#endif
+
+#ifdef CONFIG_ATMEL_SPI
+	at91_spi0_hw_init(1 << 0);
+#endif
+
+#ifdef CONFIG_LCD
+	at91_lcd_hw_init();
+#endif
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
+					CONFIG_SYS_SDRAM_SIZE);
+	return 0;
+}
diff --git a/boards.cfg b/boards.cfg
index f785da8..a71dbfa 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -106,6 +106,9 @@  at91sam9x5ek_mmc             arm         arm926ejs   at91sam9x5ek        atmel
 at91sam9xeek_dataflash_cs0   arm         arm926ejs   at91sam9260ek       atmel          at91        at91sam9260ek:AT91SAM9XE,SYS_USE_DATAFLASH_CS0
 at91sam9xeek_dataflash_cs1   arm         arm926ejs   at91sam9260ek       atmel          at91        at91sam9260ek:AT91SAM9XE,SYS_USE_DATAFLASH_CS1
 at91sam9xeek_nandflash       arm         arm926ejs   at91sam9260ek       atmel          at91        at91sam9260ek:AT91SAM9XE,SYS_USE_NANDFLASH
+at91sam9n12ek_nandflash      arm         arm926ejs   at91sam9n12ek       atmel          at91        at91sam9n12ek:AT91SAM9N12,SYS_USE_NANDFLASH
+at91sam9n12ek_spiflash       arm         arm926ejs   at91sam9n12ek       atmel          at91        at91sam9n12ek:AT91SAM9N12,SYS_USE_SPIFLASH
+at91sam9n12ek_mmc            arm         arm926ejs   at91sam9n12ek       atmel          at91        at91sam9n12ek:AT91SAM9N12,SYS_USE_MMC
 snapper9260                  arm         arm926ejs   -                   bluewater      at91        snapper9260:AT91SAM9260
 snapper9g20                  arm         arm926ejs   snapper9260         bluewater      at91        snapper9260:AT91SAM9G20
 vl_ma2sc                     arm         arm926ejs   vl_ma2sc            BuS            at91
diff --git a/include/configs/at91sam9n12ek.h b/include/configs/at91sam9n12ek.h
new file mode 100644
index 0000000..8d2673d
--- /dev/null
+++ b/include/configs/at91sam9n12ek.h
@@ -0,0 +1,232 @@ 
+/*
+ * (C) Copyright 2013 Atmel Corporation.
+ * Josh Wu <josh.wu@atmel.com>
+ *
+ * Configuation settings for the AT91SAM9N12-EK boards.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#ifndef __AT91SAM9N12_CONFIG_H_
+#define __AT91SAM9N12_CONFIG_H_
+
+/*
+ * SoC must be defined first, before hardware.h is included.
+ * In this case SoC is defined in boards.cfg.
+ */
+#include <asm/hardware.h>
+
+#define CONFIG_SYS_TEXT_BASE		0x26f00000
+
+#define CONFIG_ARM926EJS
+#define CONFIG_AT91FAMILY
+
+/* ARM asynchronous clock */
+#define CONFIG_SYS_AT91_SLOW_CLOCK	32768		/* slow clock xtal */
+#define CONFIG_SYS_AT91_MAIN_CLOCK	16000000	/* main clock xtal */
+#define CONFIG_SYS_HZ			1000
+
+/* Misc CPU related */
+#define CONFIG_CMDLINE_TAG		/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_DISPLAY_CPUINFO
+
+#define CONFIG_OF_LIBFDT
+
+/* general purpose I/O */
+#define CONFIG_AT91_GPIO
+
+/* serial console */
+#define CONFIG_ATMEL_USART
+#define CONFIG_USART_BASE		ATMEL_BASE_DBGU
+#define CONFIG_USART_ID			ATMEL_ID_SYS
+#define CONFIG_BAUDRATE			115200
+
+/* LCD */
+#define CONFIG_LCD
+#define LCD_BPP				LCD_COLOR16
+#define LCD_OUTPUT_BPP			24
+#define CONFIG_LCD_LOGO
+#define CONFIG_LCD_INFO
+#define CONFIG_LCD_INFO_BELOW_LOGO
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_ATMEL_HLCD
+#define CONFIG_ATMEL_LCD_RGB565
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+
+#define CONFIG_BOOTDELAY		3
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+/* NOR flash - no real flash on this board */
+#define CONFIG_SYS_NO_FLASH
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+#undef CONFIG_CMD_FPGA
+
+#define CONFIG_CMD_BOOTZ
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_SYS_SDRAM_BASE		0x20000000
+#define CONFIG_SYS_SDRAM_SIZE		0x08000000
+
+/*
+ * Initial stack pointer: 4k - GENERATED_GBL_DATA_SIZE in internal SRAM,
+ * leaving the correct space for initial global data structure above
+ * that address while providing maximum stack area below.
+ */
+# define CONFIG_SYS_INIT_SP_ADDR \
+	(ATMEL_BASE_SRAM + 0x1000 - GENERATED_GBL_DATA_SIZE)
+
+/* DataFlash */
+#ifdef CONFIG_CMD_SF
+#define CONFIG_ATMEL_SPI
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_ATMEL
+#define CONFIG_SF_DEFAULT_SPEED		30000000
+#define CONFIG_ENV_SPI_MODE		SPI_MODE_3
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_3
+#endif
+
+/* NAND flash */
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_NAND_ATMEL
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0x40000000
+#define CONFIG_SYS_NAND_MASK_ALE	(1 << 21)
+#define CONFIG_SYS_NAND_MASK_CLE	(1 << 22)
+#define CONFIG_SYS_NAND_ENABLE_PIN	AT91_PIO_PORTD, 4
+#define CONFIG_SYS_NAND_READY_PIN	AT91_PIO_PORTD, 5
+
+/* PMECC & PMERRLOC */
+#define CONFIG_ATMEL_NAND_HWECC
+#define CONFIG_ATMEL_NAND_HW_PMECC
+#define CONFIG_PMECC_CAP		2
+#define CONFIG_PMECC_SECTOR_SIZE	512
+#define CONFIG_PMECC_INDEX_TABLE_OFFSET	0x8000
+#endif
+
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_MTD_DEVICE
+#define CONFIG_CMD_MTDPARTS
+#define MTDIDS_DEFAULT			"nand0=atmel_nand"
+#define MTDPARTS_DEFAULT						\
+	"mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,"		\
+	"256k(env),256k(env_redundant),256k(spare),"			\
+	"512k(dtb),6M(kernel)ro,-(rootfs)"
+
+#define CONFIG_EXTRA_ENV_SETTINGS                                       \
+	"console=console=ttyS0,115200\0"                                \
+	"mtdparts="MTDPARTS_DEFAULT"\0"					\
+	"bootargs_nand=rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs rw\0"\
+	"bootargs_mmc=root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait\0"
+
+/* MMC */
+#ifdef CONFIG_CMD_MMC
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_GENERIC_ATMEL_MCI
+#endif
+
+/* FAT */
+#ifdef CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+#endif
+
+#define CONFIG_SYS_LOAD_ADDR		0x22000000 /* load address */
+
+#define CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
+#define CONFIG_SYS_MEMTEST_END		0x26e00000
+
+#ifdef CONFIG_SYS_USE_SPIFLASH
+
+/* bootstrap + u-boot + env + linux in dataflash on CS0 */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET		0x5000
+#define CONFIG_ENV_SIZE			0x3000
+#define CONFIG_ENV_SECT_SIZE		0x1000
+#define CONFIG_BOOTCOMMAND						\
+	"setenv bootargs ${console} ${mtdparts} ${bootargs_nand};"	\
+	"sf probe 0; sf read 0x22000000 0x100000 0x300000; "		\
+	"bootm 0x22000000"
+
+#elif defined(CONFIG_SYS_USE_NANDFLASH)
+
+/* bootstrap + u-boot + env + linux in nandflash */
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_OFFSET		0xc0000
+#define CONFIG_ENV_OFFSET_REDUND	0x100000
+#define CONFIG_ENV_SIZE			0x20000		/* 1 sector = 128 kB */
+#define CONFIG_BOOTCOMMAND						\
+	"setenv bootargs ${console} ${mtdparts} ${bootargs_nand};"	\
+	"nand read 0x21000000 0x180000 0x080000;"			\
+	"nand read 0x22000000 0x200000 0x400000;"			\
+	"bootm 0x22000000 - 0x21000000"
+
+#else /* CONFIG_SYS_USE_MMC */
+
+/* bootstrap + u-boot + env + linux in mmc */
+#define CONFIG_ENV_IS_IN_MMC
+/* For FAT system, most cases it should be in the reserved sector */
+#define CONFIG_ENV_OFFSET		0x2000
+#define CONFIG_ENV_SIZE			0x1000
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#define CONFIG_BOOTCOMMAND						\
+	"setenv bootargs ${console} ${mtdparts} ${bootargs_mmc};"	\
+	"fatload mmc 0:1 0x21000000 dtb;"				\
+	"fatload mmc 0:1 0x22000000 uImage;"				\
+	"bootm 0x22000000 - 0x21000000"
+
+#endif
+
+#define CONFIG_SYS_PROMPT	"U-Boot> "
+#define CONFIG_SYS_CBSIZE	256
+#define CONFIG_SYS_MAXARGS	16
+#define CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) \
+					+ 16)
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_HUSH_PARSER
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_SYS_MALLOC_LEN	(4 * 1024 * 1024)
+#define CONFIG_STACKSIZE	(32 * 1024)	/* regular stack */
+
+#endif