summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Wu <josh.wu@atmel.com>2012-10-22 15:49:04 +0800
committerJosh Wu <josh.wu@atmel.com>2012-10-22 15:49:04 +0800
commitd09dc68d74844b44b89a1311f60055351952fb0e (patch)
tree6d4bf5d6962bfa3c5d4597d8fbcdb7e2fd840266
parent6528ff0109d81c1f21d20f9f1370782bccf87bcb (diff)
parent3cda03c7fa4413eef2ee250b5936a88c25dbc1be (diff)
Merge branch 'josh/sama5ek/v2012.10-rc1' into josh/sama5ek/v2012.10
Conflicts: drivers/mtd/spi/atmel.c
-rw-r--r--arch/arm/cpu/armv7/at91/Makefile53
-rw-r--r--arch/arm/cpu/armv7/at91/at91sama5_devices.c278
-rw-r--r--arch/arm/cpu/armv7/at91/clock.c116
-rw-r--r--arch/arm/cpu/armv7/at91/cpu.c99
-rw-r--r--arch/arm/cpu/armv7/at91/lowlevel_init.S274
-rw-r--r--arch/arm/cpu/armv7/at91/reset.c45
-rw-r--r--arch/arm/cpu/armv7/at91/timer.c136
-rw-r--r--arch/arm/include/asm/arch-at91/at91_pio.h25
-rw-r--r--arch/arm/include/asm/arch-at91/at91_pmc.h16
-rw-r--r--arch/arm/include/asm/arch-at91/at91sama5.h219
-rw-r--r--arch/arm/include/asm/arch-at91/at91sama5_smc.h135
-rw-r--r--arch/arm/include/asm/arch-at91/clk.h1
-rw-r--r--arch/arm/include/asm/arch-at91/hardware.h2
-rw-r--r--arch/arm/include/asm/mach-types.h1
-rw-r--r--board/atmel/at91sama5ek/Makefile48
-rw-r--r--board/atmel/at91sama5ek/at91sama5ek.c298
-rw-r--r--board/atmel/at91sama5ek/config.mk1
-rw-r--r--boards.cfg3
-rw-r--r--drivers/mmc/gen_atmel_mci.c11
-rw-r--r--drivers/mtd/nand/nand_ids.c1
-rw-r--r--drivers/mtd/spi/atmel.c309
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/gmacb.c622
-rw-r--r--drivers/net/gmacb.h266
-rw-r--r--drivers/net/macb.c6
-rw-r--r--drivers/usb/host/ohci-at91.c8
-rw-r--r--drivers/video/atmel_lcdfb.c192
-rw-r--r--include/atmel_9x5_lcdc.h223
-rw-r--r--include/atmel_mci.h2
-rw-r--r--include/configs/at91sama5ek.h283
-rw-r--r--include/netdev.h1
31 files changed, 3655 insertions, 20 deletions
diff --git a/arch/arm/cpu/armv7/at91/Makefile b/arch/arm/cpu/armv7/at91/Makefile
new file mode 100644
index 0000000000..5ad88b395e
--- /dev/null
+++ b/arch/arm/cpu/armv7/at91/Makefile
@@ -0,0 +1,53 @@
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# 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$(SOC).o
+
+COBJS-$(CONFIG_AT91SAMA5) += at91sama5_devices.o
+COBJS-y += clock.o
+COBJS-y += cpu.o
+COBJS-y += reset.o
+COBJS-y += timer.o
+
+ifndef CONFIG_SKIP_LOWLEVEL_INIT
+SOBJS-y := lowlevel_init.o
+endif
+
+SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/armv7/at91/at91sama5_devices.c b/arch/arm/cpu/armv7/at91/at91sama5_devices.c
new file mode 100644
index 0000000000..167b9f5bb3
--- /dev/null
+++ b/arch/arm/cpu/armv7/at91/at91sama5_devices.c
@@ -0,0 +1,278 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.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/arch/at91sama5.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/gpio.h>
+#include <asm/io.h>
+
+/*
+ * if CONFIG_AT91_GPIO_PULLUP ist set, keep pullups on on all
+ * peripheral pins. Good to have if hardware is soldered optionally
+ * or in case of SPI no slave is selected. Avoid lines to float
+ * needlessly. Use a short local PUP define.
+ *
+ * Due to errata "TXD floats when CTS is inactive" pullups are always
+ * on for TXD pins.
+ */
+#ifdef CONFIG_AT91_GPIO_PULLUP
+# define PUP CONFIG_AT91_GPIO_PULLUP
+#else
+# define PUP 0
+#endif
+
+#define CIDR 0x40
+#define EXID 0x44
+
+unsigned int get_chip_id(void)
+{
+ return readl(ATMEL_BASE_DBGU + CIDR);
+}
+
+unsigned int get_extension_chip_id(void)
+{
+ return readl(ATMEL_BASE_DBGU + EXID);
+}
+
+unsigned int has_emac()
+{
+ return cpu_is_at91sama5d31() || cpu_is_at91sama5d35();
+}
+
+unsigned int has_gmac()
+{
+ return !cpu_is_at91sama5d31();
+}
+
+unsigned int has_lcdc()
+{
+ return !cpu_is_at91sama5d35();
+}
+
+char *get_cpu_name()
+{
+ unsigned int extension_id = get_extension_chip_id();
+
+ if (cpu_is_at91sama5())
+ switch (extension_id) {
+ case ARCH_EXID_AT91SAMA5D31:
+ return CONFIG_SYS_AT91_D31_CPU_NAME;
+ case ARCH_EXID_AT91SAMA5D33:
+ return CONFIG_SYS_AT91_D33_CPU_NAME;
+ case ARCH_EXID_AT91SAMA5D34:
+ return CONFIG_SYS_AT91_D34_CPU_NAME;
+ case ARCH_EXID_AT91SAMA5D35:
+ return CONFIG_SYS_AT91_D35_CPU_NAME;
+ default:
+ return CONFIG_SYS_AT91_UNKNOWN_CPU;
+ }
+ else
+ return CONFIG_SYS_AT91_UNKNOWN_CPU;
+}
+
+void at91_serial0_hw_init(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTD, 18, 1); /* TXD0 */
+ at91_set_a_periph(AT91_PIO_PORTD, 17, PUP); /* RXD0 */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_USART0);
+}
+
+void at91_serial1_hw_init(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTB, 28, 0); /* TXD1 */
+ at91_set_a_periph(AT91_PIO_PORTB, 29, PUP); /* RXD1 */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_USART1);
+}
+
+void at91_serial2_hw_init(void)
+{
+ at91_set_b_periph(AT91_PIO_PORTE, 26, 1); /* TXD2 */
+ at91_set_b_periph(AT91_PIO_PORTE, 25, PUP); /* RXD2 */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_USART2);
+}
+
+void at91_seriald_hw_init(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTB, 30, 0); /* DRXD */
+ at91_set_a_periph(AT91_PIO_PORTB, 31, 1); /* DTXD */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_SYS);
+}
+
+#if defined(CONFIG_ATMEL_SPI)
+void at91_spi0_hw_init(unsigned long cs_mask)
+{
+ at91_set_a_periph(AT91_PIO_PORTD, 10, 0); /* SPI0_MISO */
+ at91_set_a_periph(AT91_PIO_PORTD, 11, 0); /* SPI0_MOSI */
+ at91_set_a_periph(AT91_PIO_PORTD, 12, 0); /* SPI0_SPCK */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_SPI0);
+
+ if (cs_mask & (1 << 0))
+ at91_set_a_periph(AT91_PIO_PORTD, 13, 0);
+ if (cs_mask & (1 << 1))
+ at91_set_b_periph(AT91_PIO_PORTD, 14, 0);
+ if (cs_mask & (1 << 2))
+ at91_set_b_periph(AT91_PIO_PORTD, 15, 0);
+ if (cs_mask & (1 << 3))
+ at91_set_b_periph(AT91_PIO_PORTD, 16, 0);
+ if (cs_mask & (1 << 4))
+ at91_set_pio_output(AT91_PIO_PORTD, 13, 0);
+ if (cs_mask & (1 << 5))
+ at91_set_pio_output(AT91_PIO_PORTD, 14, 0);
+ if (cs_mask & (1 << 6))
+ at91_set_pio_output(AT91_PIO_PORTD, 15, 0);
+ if (cs_mask & (1 << 7))
+ at91_set_pio_output(AT91_PIO_PORTD, 16, 0);
+}
+#endif
+
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+void at91_mci_hw_init(void)
+{
+ at91_set_pio_output(AT91_PIO_PORTB, 10, 0); /* MCI0 Power */
+
+ at91_set_a_periph(AT91_PIO_PORTD, 0, 0); /* MCI0 CMD */
+ at91_set_a_periph(AT91_PIO_PORTD, 1, 0); /* MCI0 DA0 */
+ at91_set_a_periph(AT91_PIO_PORTD, 2, 0); /* MCI0 DA1 */
+ at91_set_a_periph(AT91_PIO_PORTD, 3, 0); /* MCI0 DA2 */
+ at91_set_a_periph(AT91_PIO_PORTD, 4, 0); /* MCI0 DA3 */
+#ifdef CONFIG_ATMEL_MCI_8BIT
+ at91_set_a_periph(AT91_PIO_PORTD, 5, 0); /* MCI0 DA4 */
+ at91_set_a_periph(AT91_PIO_PORTD, 6, 0); /* MCI0 DA5 */
+ at91_set_a_periph(AT91_PIO_PORTD, 7, 0); /* MCI0 DA6 */
+ at91_set_a_periph(AT91_PIO_PORTD, 8, 0); /* MCI0 DA7 */
+#endif
+ at91_set_a_periph(AT91_PIO_PORTD, 9, 0); /* MCI0 CLK */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_MCI0);
+
+ /* Pin muxing for MCI1 */
+ at91_set_pio_output(AT91_PIO_PORTB, 12, 0); /* MCI1 Power */
+
+ at91_set_a_periph(AT91_PIO_PORTB, 19, 0); /* MCI1 CMD */
+ at91_set_a_periph(AT91_PIO_PORTB, 20, 0); /* MCI1 DA0 */
+ at91_set_a_periph(AT91_PIO_PORTB, 21, 0); /* MCI1 DA1 */
+ at91_set_a_periph(AT91_PIO_PORTB, 22, 0); /* MCI1 DA2 */
+ at91_set_a_periph(AT91_PIO_PORTB, 23, 0); /* MCI1 DA3 */
+ at91_set_a_periph(AT91_PIO_PORTB, 24, 0); /* MCI1 CLK */
+}
+#endif
+
+#ifdef CONFIG_MACB
+void at91_macb_hw_init(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTC, 7, 0); /* ETXCK_EREFCK */
+ at91_set_a_periph(AT91_PIO_PORTC, 5, 0); /* ERXDV */
+ at91_set_a_periph(AT91_PIO_PORTC, 2, 0); /* ERX0 */
+ at91_set_a_periph(AT91_PIO_PORTC, 3, 0); /* ERX1 */
+ at91_set_a_periph(AT91_PIO_PORTC, 6, 0); /* ERXER */
+ at91_set_a_periph(AT91_PIO_PORTC, 4, 0); /* ETXEN */
+ at91_set_a_periph(AT91_PIO_PORTC, 0, 0); /* ETX0 */
+ at91_set_a_periph(AT91_PIO_PORTC, 1, 0); /* ETX1 */
+ at91_set_a_periph(AT91_PIO_PORTC, 9, 0); /* EMDIO */
+ at91_set_a_periph(AT91_PIO_PORTC, 8, 0); /* EMDC */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_EMAC);
+}
+#endif
+
+#ifdef CONFIG_GMACB
+void at91_gmacb_hw_init(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTB, 0, 0); /* GTX0 */
+ at91_set_a_periph(AT91_PIO_PORTB, 1, 0); /* GTX1 */
+ at91_set_a_periph(AT91_PIO_PORTB, 2, 0); /* GTX2 */
+ at91_set_a_periph(AT91_PIO_PORTB, 3, 0); /* GTX3 */
+ at91_set_a_periph(AT91_PIO_PORTB, 4, 0); /* GRX0 */
+ at91_set_a_periph(AT91_PIO_PORTB, 5, 0); /* GRX1 */
+ at91_set_a_periph(AT91_PIO_PORTB, 6, 0); /* GRX2 */
+ at91_set_a_periph(AT91_PIO_PORTB, 7, 0); /* GRX3 */
+ at91_set_a_periph(AT91_PIO_PORTB, 8, 0); /* GTXCK */
+ at91_set_a_periph(AT91_PIO_PORTB, 9, 0); /* GTXEN */
+
+ at91_set_a_periph(AT91_PIO_PORTB, 11, 0); /* GRXCK */
+ at91_set_a_periph(AT91_PIO_PORTB, 13, 0); /* GRXER */
+
+ at91_set_a_periph(AT91_PIO_PORTB, 16, 0); /* GMDC */
+ at91_set_a_periph(AT91_PIO_PORTB, 17, 0); /* GMDIO */
+ at91_set_a_periph(AT91_PIO_PORTB, 18, 0); /* G125CK */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_GMAC);
+}
+#endif
+
+#ifdef CONFIG_LCD
+void at91_lcd_hw_init(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTA, 24, 0); /* LCDPWM */
+ at91_set_a_periph(AT91_PIO_PORTA, 25, 0); /* LCDDISP */
+ at91_set_a_periph(AT91_PIO_PORTA, 26, 0); /* LCDVSYNC */
+ at91_set_a_periph(AT91_PIO_PORTA, 27, 0); /* LCDHSYNC */
+ at91_set_a_periph(AT91_PIO_PORTA, 28, 0); /* LCDDOTCK */
+ at91_set_a_periph(AT91_PIO_PORTA, 29, 0); /* LCDDEN */
+
+ at91_set_a_periph(AT91_PIO_PORTA, 0, 0); /* LCDD0 */
+ at91_set_a_periph(AT91_PIO_PORTA, 1, 0); /* LCDD1 */
+ at91_set_a_periph(AT91_PIO_PORTA, 2, 0); /* LCDD2 */
+ at91_set_a_periph(AT91_PIO_PORTA, 3, 0); /* LCDD3 */
+ at91_set_a_periph(AT91_PIO_PORTA, 4, 0); /* LCDD4 */
+ at91_set_a_periph(AT91_PIO_PORTA, 5, 0); /* LCDD5 */
+ at91_set_a_periph(AT91_PIO_PORTA, 6, 0); /* LCDD6 */
+ at91_set_a_periph(AT91_PIO_PORTA, 7, 0); /* LCDD7 */
+ at91_set_a_periph(AT91_PIO_PORTA, 8, 0); /* LCDD8 */
+ at91_set_a_periph(AT91_PIO_PORTA, 9, 0); /* LCDD9 */
+ at91_set_a_periph(AT91_PIO_PORTA, 10, 0); /* LCDD10 */
+ at91_set_a_periph(AT91_PIO_PORTA, 11, 0); /* LCDD11 */
+ at91_set_a_periph(AT91_PIO_PORTA, 12, 0); /* LCDD12 */
+ at91_set_a_periph(AT91_PIO_PORTA, 13, 0); /* LCDD13 */
+ at91_set_a_periph(AT91_PIO_PORTA, 14, 0); /* LCDD14 */
+ at91_set_a_periph(AT91_PIO_PORTA, 15, 0); /* LCDD15 */
+ at91_set_c_periph(AT91_PIO_PORTC, 14, 0); /* LCDD16 */
+ at91_set_c_periph(AT91_PIO_PORTC, 13, 0); /* LCDD17 */
+ at91_set_c_periph(AT91_PIO_PORTC, 12, 0); /* LCDD18 */
+ at91_set_c_periph(AT91_PIO_PORTC, 11, 0); /* LCDD19 */
+ at91_set_c_periph(AT91_PIO_PORTC, 10, 0); /* LCDD20 */
+ at91_set_c_periph(AT91_PIO_PORTC, 15, 0); /* LCDD21 */
+ at91_set_c_periph(AT91_PIO_PORTE, 27, 0); /* LCDD22 */
+ at91_set_c_periph(AT91_PIO_PORTE, 28, 0); /* LCDD23 */
+
+ /* Enable clock */
+ at91_periph_clk_enable(ATMEL_ID_LCDC);
+}
+#endif
diff --git a/arch/arm/cpu/armv7/at91/clock.c b/arch/arm/cpu/armv7/at91/clock.c
new file mode 100644
index 0000000000..dad7357f4e
--- /dev/null
+++ b/arch/arm/cpu/armv7/at91/clock.c
@@ -0,0 +1,116 @@
+/*
+ * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
+ *
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+
+#if !defined(CONFIG_AT91FAMILY)
+# error You need to define CONFIG_AT91FAMILY in your board config!
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static unsigned long at91_css_to_rate(unsigned long css)
+{
+ switch (css) {
+ case AT91_PMC_MCKR_CSS_SLOW:
+ return CONFIG_SYS_AT91_SLOW_CLOCK;
+ case AT91_PMC_MCKR_CSS_MAIN:
+ return gd->main_clk_rate_hz;
+ case AT91_PMC_MCKR_CSS_PLLA:
+ return gd->plla_rate_hz;
+ case AT91_PMC_MCKR_CSS_PLLB:
+ return gd->pllb_rate_hz;
+ }
+
+ return 0;
+}
+
+static u32 at91_pll_rate(u32 freq, u32 reg)
+{
+ unsigned mul, div;
+
+ div = reg & 0xff;
+ mul = (reg >> 18) & 0x7ff;
+ if (div && mul) {
+ freq /= div;
+ freq *= mul + 1;
+ } else
+ freq = 0;
+
+ return freq;
+}
+
+int at91_clock_init(unsigned long main_clock)
+{
+ unsigned freq, mckr;
+ at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
+ unsigned tmp;
+ /*
+ * When the bootloader initialized the main oscillator correctly,
+ * there's no problem using the cycle counter. But if it didn't,
+ * or when using oscillator bypass mode, we must be told the speed
+ * of the main clock.
+ */
+ if (!main_clock) {
+ do {
+ tmp = readl(&pmc->mcfr);
+ } while (!(tmp & AT91_PMC_MCFR_MAINRDY));
+ tmp &= AT91_PMC_MCFR_MAINF_MASK;
+ main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
+ }
+#endif
+ gd->main_clk_rate_hz = main_clock;
+
+ /* report if PLLA is more than mildly overclocked */
+ gd->plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
+
+ /*
+ * MCK and CPU derive from one of those primary clocks.
+ * For now, assume this parentage won't change.
+ */
+ mckr = readl(&pmc->mckr);
+
+ /* plla divisor by 2 */
+ gd->plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
+
+ gd->mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
+ freq = gd->mck_rate_hz;
+
+ freq /= (1 << ((mckr & (AT91_PMC_MCKR_PRES_MASK << 2)) >> 4)); /* prescale */
+
+ gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
+ (AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4)
+ ? freq / 3
+ : freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
+
+ gd->cpu_clk_rate_hz = freq;
+
+ return 0;
+}
+
+void at91_periph_clk_enable(int id)
+{
+ struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+ /* do we need sanity check for id ? */
+
+ if (id > 31)
+ writel(1 << (id - 32), &pmc->pcer1);
+ else
+ writel(1 << id, &pmc->pcer);
+}
diff --git a/arch/arm/cpu/armv7/at91/cpu.c b/arch/arm/cpu/armv7/at91/cpu.c
new file mode 100644
index 0000000000..98102576f2
--- /dev/null
+++ b/arch/arm/cpu/armv7/at91/cpu.c
@@ -0,0 +1,99 @@
+/*
+ * (C) Copyright 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.de
+ * (C) Copyright 2009
+ * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_pit.h>
+#include <asm/arch/at91_gpbr.h>
+#include <asm/arch/clk.h>
+
+#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
+#define CONFIG_SYS_AT91_MAIN_CLOCK 0
+#endif
+
+int arch_cpu_init(void)
+{
+ return at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
+}
+
+void arch_preboot_os(void)
+{
+ ulong cpiv;
+ at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT;
+
+ cpiv = AT91_PIT_MR_PIV_MASK(readl(&pit->piir));
+
+ /*
+ * Disable PITC
+ * Add 0x1000 to current counter to stop it faster
+ * without waiting for wrapping back to 0
+ */
+ writel(cpiv + 0x1000, &pit->mr);
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+ char buf[32];
+
+ printf("CPU: %s\n", get_cpu_name());
+ printf("Crystal frequency: %8s MHz\n",
+ strmhz(buf, get_main_clk_rate()));
+ printf("CPU clock : %8s MHz\n",
+ strmhz(buf, get_cpu_clk_rate()));
+ printf("Master clock : %8s MHz\n",
+ strmhz(buf, get_mck_clk_rate()));
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_BOOTCOUNT_LIMIT
+/*
+ * We combine the BOOTCOUNT_MAGIC and bootcount in one 32-bit register.
+ * This is done so we need to use only one of the four GPBR registers.
+ */
+void bootcount_store (ulong a)
+{
+ at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
+
+ writel((BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff),
+ &gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
+}
+
+ulong bootcount_load (void)
+{
+ at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
+
+ ulong val = readl(&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
+ if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
+ return 0;
+ else
+ return val & 0x0000ffff;
+}
+
+#endif /* CONFIG_BOOTCOUNT_LIMIT */
diff --git a/arch/arm/cpu/armv7/at91/lowlevel_init.S b/arch/arm/cpu/armv7/at91/lowlevel_init.S
new file mode 100644
index 0000000000..d102195273
--- /dev/null
+++ b/arch/arm/cpu/armv7/at91/lowlevel_init.S
@@ -0,0 +1,274 @@
+/*
+ * Memory Setup stuff - taken from blob memsetup.S
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
+ * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+ *
+ * Copyright (C) 2008 Ronetix Ilko Iliev (www.ronetix.at)
+ * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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 <config.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_wdt.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/at91_matrix.h>
+#include <asm/arch/at91sam9_sdramc.h>
+#include <asm/arch/at91sam9_smc.h>
+#include <asm/arch/at91_rstc.h>
+#ifdef CONFIG_ATMEL_LEGACY
+#include <asm/arch/at91sam9_matrix.h>
+#endif
+#ifndef CONFIG_SYS_MATRIX_EBICSA_VAL
+#define CONFIG_SYS_MATRIX_EBICSA_VAL CONFIG_SYS_MATRIX_EBI0CSA_VAL
+#endif
+
+_TEXT_BASE:
+ .word CONFIG_SYS_TEXT_BASE
+
+.globl lowlevel_init
+.type lowlevel_init,function
+lowlevel_init:
+
+ mov r5, pc /* r5 = POS1 + 4 current */
+POS1:
+ ldr r0, =POS1 /* r0 = POS1 compile */
+ ldr r2, _TEXT_BASE
+ sub r0, r0, r2 /* r0 = POS1-_TEXT_BASE (POS1 relative) */
+ sub r5, r5, r0 /* r0 = CONFIG_SYS_TEXT_BASE-1 */
+ sub r5, r5, #4 /* r1 = text base - current */
+
+ /* memory control configuration 1 */
+ ldr r0, =SMRDATA
+ ldr r2, =SMRDATA1
+ ldr r1, _TEXT_BASE
+ sub r0, r0, r1
+ sub r2, r2, r1
+ add r0, r0, r5
+ add r2, r2, r5
+0:
+ /* the address */
+ ldr r1, [r0], #4
+ /* the value */
+ ldr r3, [r0], #4
+ str r3, [r1]
+ cmp r2, r0
+ bne 0b
+
+/* ----------------------------------------------------------------------------
+ * PMC Init Step 1.
+ * ----------------------------------------------------------------------------
+ * - Check if the PLL is already initialized
+ * ----------------------------------------------------------------------------
+ */
+ ldr r1, =(AT91_ASM_PMC_MCKR)
+ ldr r0, [r1]
+ and r0, r0, #3
+ cmp r0, #0
+ bne PLL_setup_end
+
+/* ---------------------------------------------------------------------------
+ * - Enable the Main Oscillator
+ * ---------------------------------------------------------------------------
+ */
+ ldr r1, =(AT91_ASM_PMC_MOR)
+ ldr r2, =(AT91_ASM_PMC_SR)
+ /* Main oscillator Enable register PMC_MOR: */
+ ldr r0, =CONFIG_SYS_MOR_VAL
+ str r0, [r1]
+
+ /* Reading the PMC Status to detect when the Main Oscillator is enabled */
+ mov r4, #AT91_PMC_IXR_MOSCS
+MOSCS_Loop:
+ ldr r3, [r2]
+ and r3, r4, r3
+ cmp r3, #AT91_PMC_IXR_MOSCS
+ bne MOSCS_Loop
+
+/* ----------------------------------------------------------------------------
+ * PMC Init Step 2.
+ * ----------------------------------------------------------------------------
+ * Setup PLLA
+ * ----------------------------------------------------------------------------
+ */
+ ldr r1, =(AT91_ASM_PMC_PLLAR)
+ ldr r0, =CONFIG_SYS_PLLAR_VAL
+ str r0, [r1]
+
+ /* Reading the PMC Status register to detect when the PLLA is locked */
+ mov r4, #AT91_PMC_IXR_LOCKA
+MOSCS_Loop1:
+ ldr r3, [r2]
+ and r3, r4, r3
+ cmp r3, #AT91_PMC_IXR_LOCKA
+ bne MOSCS_Loop1
+
+/* ----------------------------------------------------------------------------
+ * PMC Init Step 3.
+ * ----------------------------------------------------------------------------
+ * - Switch on the Main Oscillator
+ * ----------------------------------------------------------------------------
+ */
+ ldr r1, =(AT91_ASM_PMC_MCKR)
+
+ /* -Master Clock Controller register PMC_MCKR */
+ ldr r0, =CONFIG_SYS_MCKR1_VAL
+ str r0, [r1]
+
+ /* Reading the PMC Status to detect when the Master clock is ready */
+ mov r4, #AT91_PMC_IXR_MCKRDY
+MCKRDY_Loop:
+ ldr r3, [r2]
+ and r3, r4, r3
+ cmp r3, #AT91_PMC_IXR_MCKRDY
+ bne MCKRDY_Loop
+
+ ldr r0, =CONFIG_SYS_MCKR2_VAL
+ str r0, [r1]
+
+ /* Reading the PMC Status to detect when the Master clock is ready */
+ mov r4, #AT91_PMC_IXR_MCKRDY
+MCKRDY_Loop1:
+ ldr r3, [r2]
+ and r3, r4, r3
+ cmp r3, #AT91_PMC_IXR_MCKRDY
+ bne MCKRDY_Loop1
+PLL_setup_end:
+
+/* ----------------------------------------------------------------------------
+ * - memory control configuration 2
+ * ----------------------------------------------------------------------------
+ */
+ ldr r0, =(AT91_ASM_SDRAMC_TR)
+ ldr r1, [r0]
+ cmp r1, #0
+ bne SDRAM_setup_end
+
+ ldr r0, =SMRDATA1
+ ldr r2, =SMRDATA2
+ ldr r1, _TEXT_BASE
+ sub r0, r0, r1
+ sub r2, r2, r1
+ add r0, r0, r5
+ add r2, r2, r5
+2:
+ /* the address */
+ ldr r1, [r0], #4
+ /* the value */
+ ldr r3, [r0], #4
+ str r3, [r1]
+ cmp r2, r0
+ bne 2b
+
+SDRAM_setup_end:
+ /* everything is fine now */
+ mov pc, lr
+
+ .ltorg
+
+SMRDATA:
+ .word AT91_ASM_WDT_MR
+ .word CONFIG_SYS_WDTC_WDMR_VAL
+ /* configure PIOx as EBI0 D[16-31] */
+#if defined(CONFIG_AT91SAM9263)
+ .word AT91_ASM_PIOD_PDR
+ .word CONFIG_SYS_PIOD_PDR_VAL1
+ .word AT91_ASM_PIOD_PUDR
+ .word CONFIG_SYS_PIOD_PPUDR_VAL
+ .word AT91_ASM_PIOD_ASR
+ .word CONFIG_SYS_PIOD_PPUDR_VAL
+#elif defined(CONFIG_AT91SAM9260) || defined(CONFIG_AT91SAM9261) \
+ || defined(CONFIG_AT91SAM9G20)
+ .word AT91_ASM_PIOC_PDR
+ .word CONFIG_SYS_PIOC_PDR_VAL1
+ .word AT91_ASM_PIOC_PUDR
+ .word CONFIG_SYS_PIOC_PPUDR_VAL
+#endif
+ .word AT91_ASM_MATRIX_CSA0
+ .word CONFIG_SYS_MATRIX_EBICSA_VAL
+
+ /* flash */
+ .word AT91_ASM_SMC_MODE0
+ .word CONFIG_SYS_SMC0_MODE0_VAL
+
+ .word AT91_ASM_SMC_CYCLE0
+ .word CONFIG_SYS_SMC0_CYCLE0_VAL
+
+ .word AT91_ASM_SMC_PULSE0
+ .word CONFIG_SYS_SMC0_PULSE0_VAL
+
+ .word AT91_ASM_SMC_SETUP0
+ .word CONFIG_SYS_SMC0_SETUP0_VAL
+
+SMRDATA1:
+ .word AT91_ASM_SDRAMC_MR
+ .word CONFIG_SYS_SDRC_MR_VAL1
+ .word AT91_ASM_SDRAMC_TR
+ .word CONFIG_SYS_SDRC_TR_VAL1
+ .word AT91_ASM_SDRAMC_CR
+ .word CONFIG_SYS_SDRC_CR_VAL
+ .word AT91_ASM_SDRAMC_MDR
+ .word CONFIG_SYS_SDRC_MDR_VAL
+ .word AT91_ASM_SDRAMC_MR
+ .word CONFIG_SYS_SDRC_MR_VAL2
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL1
+ .word AT91_ASM_SDRAMC_MR
+ .word CONFIG_SYS_SDRC_MR_VAL3
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL2
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL3
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL4
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL5
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL6
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL7
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL8
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL9
+ .word AT91_ASM_SDRAMC_MR
+ .word CONFIG_SYS_SDRC_MR_VAL4
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL10
+ .word AT91_ASM_SDRAMC_MR
+ .word CONFIG_SYS_SDRC_MR_VAL5
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL11
+ .word AT91_ASM_SDRAMC_TR
+ .word CONFIG_SYS_SDRC_TR_VAL2
+ .word CONFIG_SYS_SDRAM_BASE
+ .word CONFIG_SYS_SDRAM_VAL12
+ /* User reset enable*/
+ .word AT91_ASM_RSTC_MR
+ .word CONFIG_SYS_RSTC_RMR_VAL
+#ifdef CONFIG_SYS_MATRIX_MCFG_REMAP
+ /* MATRIX_MCFG - REMAP all masters */
+ .word AT91_ASM_MATRIX_MCFG
+ .word 0x1FF
+#endif
+SMRDATA2:
+ .word 0
diff --git a/arch/arm/cpu/armv7/at91/reset.c b/arch/arm/cpu/armv7/at91/reset.c
new file mode 100644
index 0000000000..f6a7cb7a86
--- /dev/null
+++ b/arch/arm/cpu/armv7/at91/reset.c
@@ -0,0 +1,45 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.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/hardware.h>
+#include <asm/arch/at91_rstc.h>
+
+/* Reset the cpu by telling the reset controller to do so */
+void reset_cpu(ulong ignored)
+{
+ at91_rstc_t *rstc = (at91_rstc_t *) ATMEL_BASE_RSTC;
+
+ writel(AT91_RSTC_KEY
+ | AT91_RSTC_CR_PROCRST /* Processor Reset */
+ | AT91_RSTC_CR_PERRST /* Peripheral Reset */
+#ifdef CONFIG_AT91RESET_EXTRST
+ | AT91_RSTC_CR_EXTRST /* External Reset (assert nRST pin) */
+#endif
+ , &rstc->cr);
+ /* never reached */
+ while (1)
+ ;
+}
diff --git a/arch/arm/cpu/armv7/at91/timer.c b/arch/arm/cpu/armv7/at91/timer.c
new file mode 100644
index 0000000000..f70ce83f08
--- /dev/null
+++ b/arch/arm/cpu/armv7/at91/timer.c
@@ -0,0 +1,136 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.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/hardware.h>
+#include <asm/arch/at91_pit.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+#include <div64.h>
+
+#if !defined(CONFIG_AT91FAMILY)
+# error You need to define CONFIG_AT91FAMILY in your board config!
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * We're using the AT91CAP9/SAM9 PITC in 32 bit mode, by
+ * setting the 20 bit counter period to its maximum (0xfffff).
+ * (See the relevant data sheets to understand that this really works)
+ *
+ * We do also mimic the typical powerpc way of incrementing
+ * two 32 bit registers called tbl and tbu.
+ *
+ * Those registers increment at 1/16 the main clock rate.
+ */
+
+#define TIMER_LOAD_VAL 0xfffff
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+ tick *= CONFIG_SYS_HZ;
+ do_div(tick, gd->timer_rate_hz);
+
+ return tick;
+}
+
+static inline unsigned long long usec_to_tick(unsigned long long usec)
+{
+ usec *= gd->timer_rate_hz;
+ do_div(usec, 1000000);
+
+ return usec;
+}
+
+/*
+ * Use the PITC in full 32 bit incrementing mode
+ */
+int timer_init(void)
+{
+ at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
+ at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT;
+
+ /* Enable PITC Clock */
+ writel(1 << ATMEL_ID_SYS, &pmc->pcer);
+
+ /* Enable PITC */
+ writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr);
+
+ gd->timer_rate_hz = gd->mck_rate_hz / 16;
+ gd->tbu = gd->tbl = 0;
+
+ return 0;
+}
+
+/*
+ * Get the current 64 bit timer tick count
+ */
+unsigned long long get_ticks(void)
+{
+ at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT;
+
+ ulong now = readl(&pit->piir);
+
+ /* increment tbu if tbl has rolled over */
+ if (now < gd->tbl)
+ gd->tbu++;
+ gd->tbl = now;
+ return (((unsigned long long)gd->tbu) << 32) | gd->tbl;
+}
+
+void __udelay(unsigned long usec)
+{
+ unsigned long long start;
+ ulong tmo;
+
+ start = get_ticks(); /* get current timestamp */
+ tmo = usec_to_tick(usec); /* convert usecs to ticks */
+ while ((get_ticks() - start) < tmo)
+ ; /* loop till time has passed */
+}
+
+/*
+ * get_timer(base) can be used to check for timeouts or
+ * to measure elasped time relative to an event:
+ *
+ * ulong start_time = get_timer(0) sets start_time to the current
+ * time value.
+ * get_timer(start_time) returns the time elapsed since then.
+ *
+ * The time is used in CONFIG_SYS_HZ units!
+ */
+ulong get_timer(ulong base)
+{
+ return tick_to_time(get_ticks()) - base;
+}
+
+/*
+ * Return the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+ return gd->timer_rate_hz;
+}
diff --git a/arch/arm/include/asm/arch-at91/at91_pio.h b/arch/arm/include/asm/arch-at91/at91_pio.h
index 0483c9820e..3252516200 100644
--- a/arch/arm/include/asm/arch-at91/at91_pio.h
+++ b/arch/arm/include/asm/arch-at91/at91_pio.h
@@ -180,11 +180,36 @@ int at91_get_pio_value(unsigned port, unsigned pin);
#define PIO_PUER 0x64 /* Pull-up Enable Register */
#define PIO_PUSR 0x68 /* Pull-up Status Register */
#define PIO_ASR 0x70 /* Peripheral A Select Register */
+#define PIO_ABCDSR1 0x70 /* Peripheral ABCD Select Register 1 */
#define PIO_BSR 0x74 /* Peripheral B Select Register */
+#define PIO_ABCDSR2 0x74 /* Peripheral ABCD Select Register 2 */
#define PIO_ABSR 0x78 /* AB Status Register */
+#define PIO_IFSCDR 0x80 /* Input Filter Slow Clock Disable Register */
+#define PIO_IFSCER 0x84 /* Input Filter Slow Clock Enable Register */
+#define PIO_IFSCSR 0x88 /* Input Filter Slow Clock Status Register */
+#define PIO_SCDR 0x8c /* Slow Clock Divider Debouncing Register */
+#define PIO_SCDR_DIV (0x3fff << 0) /* Slow Clock Divider Mask */
+#define PIO_PPDDR 0x90 /* Pad Pull-down Disable Register */
+#define PIO_PPDER 0x94 /* Pad Pull-down Enable Register */
+#define PIO_PPDSR 0x98 /* Pad Pull-down Status Register */
#define PIO_OWER 0xa0 /* Output Write Enable Register */
#define PIO_OWDR 0xa4 /* Output Write Disable Register */
#define PIO_OWSR 0xa8 /* Output Write Status Register */
+#define PIO_AIMER 0xb0 /* Additional Interrupt Modes Enable Register */
+#define PIO_AIMDR 0xb4 /* Additional Interrupt Modes Disable Register */
+#define PIO_AIMMR 0xb8 /* Additional Interrupt Modes Mask Register */
+#define PIO_ESR 0xc0 /* Edge Select Register */
+#define PIO_LSR 0xc4 /* Level Select Register */
+#define PIO_ELSR 0xc8 /* Edge/Level Status Register */
+#define PIO_FELLSR 0xd0 /* Falling Edge/Low Level Select Register */
+#define PIO_REHLSR 0xd4 /* Rising Edge/ High Level Select Register */
+#define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */
+#define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */
+
+#define ABCDSR_PERIPH_A 0x0
+#define ABCDSR_PERIPH_B 0x1
+#define ABCDSR_PERIPH_C 0x2
+#define ABCDSR_PERIPH_D 0x3
#endif
#endif
diff --git a/arch/arm/include/asm/arch-at91/at91_pmc.h b/arch/arm/include/asm/arch-at91/at91_pmc.h
index 086cb9b34e..ca529778b7 100644
--- a/arch/arm/include/asm/arch-at91/at91_pmc.h
+++ b/arch/arm/include/asm/arch-at91/at91_pmc.h
@@ -43,19 +43,29 @@ typedef struct at91_pmc {
u32 mckr; /* 0x30 Master Clock Register */
u32 reserved1;
u32 usb; /* 0x38 USB Clock Register */
- u32 reserved2;
+ u32 smd; /* 0x3C Soft Modem Clock Register */
u32 pck[4]; /* 0x40 Programmable Clock Register 0 - 3 */
u32 reserved3[4];
u32 ier; /* 0x60 Interrupt Enable Register */
u32 idr; /* 0x64 Interrupt Disable Register */
u32 sr; /* 0x68 Status Register */
u32 imr; /* 0x6C Interrupt Mask Register */
- u32 reserved4[4];
+ u32 fsmr; /* 0x70 Fast Startup Mode Register */
+ u32 fspr; /* 0x74 Fast Startup Polarity Register */
+ u32 focr; /* 0x78 Fault Output Clear Register */
+ u32 reserved4;
u32 pllicpr; /* 0x80 Change Pump Current Register (SAM9) */
u32 reserved5[21];
u32 wpmr; /* 0xE4 Write Protect Mode Register (CAP0) */
u32 wpsr; /* 0xE8 Write Protect Status Register (CAP0) */
- u32 reserved8[5];
+ u32 reserved6[4];
+ u32 ver; /* 0xFC Version register */
+ u32 reserved[3];
+ u32 pcer1; /* 0x100 Periperial Clock Enable Register 1 */
+ u32 pcdr1; /* 0x104 Periperial Clock Disable Register 1 */
+ u32 pcsr1; /* 0x108 Periperial Clcok Status Register 1 */
+ u32 pcr; /* 0x10C Periperial Control Register */
+ u32 ocr; /* 0x110 Oscillator Calibration Register */
} at91_pmc_t;
#endif /* end not assembly */
diff --git a/arch/arm/include/asm/arch-at91/at91sama5.h b/arch/arm/include/asm/arch-at91/at91sama5.h
new file mode 100644
index 0000000000..38b9e9c7d9
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/at91sama5.h
@@ -0,0 +1,219 @@
+/*
+ * Chip-specific header file for the AT91SAMA5 family
+ *
+ * (C) 2012 Atmel Corporation.
+ *
+ * Definitions for the SoC:
+ * AT91SAMA5
+ *
+ * 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.
+ */
+
+#ifndef AT91SAMA5_H
+#define AT91SAMA5_H
+
+/*
+ * defines to be used in other places
+ */
+#define CONFIG_ARMV7 /* ARM A5 Core */
+#define CONFIG_AT91FAMILY /* it's a member of AT91 */
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define ATMEL_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */
+#define ATMEL_ID_SYS 1 /* System Controller Interrupt */
+#define ATMEL_ID_DBGU 2 /* Debug Unit Interrupt */
+#define ATMEL_ID_PIT 3 /* Periodic Interval Timer Interrupt */
+#define ATMEL_ID_WDT 4 /* Watchdog timer Interrupt */
+#define ATMEL_ID_SMC 5 /* Multi-bit ECC Interrupt */
+#define ATMEL_ID_PIOA 6 /* Parallel I/O Controller A */
+#define ATMEL_ID_PIOB 7 /* Parallel I/O Controller B */
+#define ATMEL_ID_PIOC 8 /* Parallel I/O Controller C */
+#define ATMEL_ID_PIOD 9 /* Parallel I/O Controller D */
+#define ATMEL_ID_PIOE 10 /* Parallel I/O Controller E */
+#define ATMEL_ID_SMD 11 /* SMD Soft Modem */
+#define ATMEL_ID_USART0 12 /* USART 0 */
+#define ATMEL_ID_USART1 13 /* USART 1 */
+#define ATMEL_ID_USART2 14 /* USART 2 */
+#define ATMEL_ID_USART3 15 /* USART 3 */
+#define ATMEL_ID_UART0 16
+#define ATMEL_ID_UART1 17
+#define ATMEL_ID_TWI0 18 /* Two-Wire Interface 0 */
+#define ATMEL_ID_TWI1 19 /* Two-Wire Interface 1 */
+#define ATMEL_ID_TWI2 20 /* Two-Wire Interface 2 */
+#define ATMEL_ID_MCI0 21 /* High Speed Multimedia Card Interface 0 */
+#define ATMEL_ID_MCI1 22 /* */
+#define ATMEL_ID_MCI2 23 /* */
+#define ATMEL_ID_SPI0 24 /* Serial Peripheral Interface 0 */
+#define ATMEL_ID_SPI1 25 /* Serial Peripheral Interface 1 */
+#define ATMEL_ID_TC0 26 /* */
+#define ATMEL_ID_TC1 27 /* */
+#define ATMEL_ID_PWMC 28 /* Pulse Width Modulation Controller */
+#define ATMEL_ID_TSC 29 /* Touch Screen ADC Controller */
+#define ATMEL_ID_DMA0 30 /* DMA Controller */
+#define ATMEL_ID_DMA1 31 /* DMA Controller */
+#define ATMEL_ID_UHPHS 32 /* USB Host High Speed */
+#define ATMEL_ID_UDPHS 33 /* USB Device High Speed */
+#define ATMEL_ID_GMAC 34
+#define ATMEL_ID_EMAC 35 /* Ethernet MAC */
+#define ATMEL_ID_LCDC 36 /* LCD Controller */
+#define ATMEL_ID_ISI 37 /* Image Sensor Interface */
+#define ATMEL_ID_SSC0 38 /* Synchronous Serial Controller 0 */
+#define ATMEL_ID_SSC1 39 /* Synchronous Serial Controller 1 */
+#define ATMEL_ID_CAN0 40
+#define ATMEL_ID_CAN1 41
+#define ATMEL_ID_SHA 42
+#define ATMEL_ID_AES 43
+#define ATMEL_ID_TDES 44
+#define ATMEL_ID_TRNG 45
+#define ATMEL_ID_ARM 46
+#define ATMEL_ID_IRQ0 47 /* Advanced Interrupt Controller */
+#define ATMEL_ID_FUSE 48
+#define ATMEL_ID_MPDDRC 49
+
+/* sama5 series chip id definitions */
+#define ARCH_ID_AT91SAMA5 0x8a5c07c1
+#define ARCH_EXID_AT91SAMA5D31 0x00444300
+#define ARCH_EXID_AT91SAMA5D33 0x00414300
+#define ARCH_EXID_AT91SAMA5D34 0x00414301
+#define ARCH_EXID_AT91SAMA5D35 0x00584300
+
+#define cpu_is_at91sama5() (get_chip_id() == ARCH_ID_AT91SAMA5)
+#define cpu_is_at91sama5d31() (cpu_is_at91sama5() && \
+ (get_extension_chip_id() == ARCH_EXID_AT91SAMA5D31))
+#define cpu_is_at91sama5d33() (cpu_is_at91sama5() && \
+ (get_extension_chip_id() == ARCH_EXID_AT91SAMA5D33))
+#define cpu_is_at91sama5d34() (cpu_is_at91sama5() && \
+ (get_extension_chip_id() == ARCH_EXID_AT91SAMA5D34))
+#define cpu_is_at91sama5d35() (cpu_is_at91sama5() && \
+ (get_extension_chip_id() == ARCH_EXID_AT91SAMA5D35))
+
+/*
+ * User Peripherals physical base addresses.
+ */
+#define ATMEL_BASE_MCI0 0xf0000000
+#define ATMEL_BASE_SPI0 0xf0004000
+#define ATMEL_BASE_SSC0 0xf000C000
+#define ATMEL_BASE_TC2 0xf0010000
+#define ATMEL_BASE_TWI0 0xf0014000
+#define ATMEL_BASE_TWI1 0xf0018000
+#define ATMEL_BASE_USART0 0xf001c000
+#define ATMEL_BASE_USART1 0xf0020000
+#define ATMEL_BASE_UART0 0xf0024000
+#define ATMEL_BASE_GMAC 0xf0028000
+#define ATMEL_BASE_PWMC 0xf002c000
+#define ATMEL_BASE_LCDC 0xf0030000
+#define ATMEL_BASE_ISI 0xf0034000
+#define ATMEL_BASE_SFR 0xf0038000
+/* Reserved: 0xf003c000 - 0xf8000000 */
+#define ATMEL_BASE_MCI1 0xf8000000
+#define ATMEL_BASE_MCI2 0xf8004000
+#define ATMEL_BASE_SPI1 0xf8008000
+#define ATMEL_BASE_SSC1 0xf800c000
+#define ATMEL_BASE_CAN1 0xf8010000
+#define ATMEL_BASE_TC3 0xf8014000
+#define ATMEL_BASE_TSADC 0xf8018000
+#define ATMEL_BASE_TWI2 0xf801c000
+#define ATMEL_BASE_USART2 0xf8020000
+#define ATMEL_BASE_USART3 0xf8024000
+#define ATMEL_BASE_UART1 0xf8028000
+#define ATMEL_BASE_EMAC 0xf802c000
+#define ATMEL_BASE_UDHPS 0xf8030000
+#define ATMEL_BASE_SHA 0xf8034000
+#define ATMEL_BASE_AES 0xf8038000
+#define ATMEL_BASE_TDES 0xf803c000
+#define ATMEL_BASE_TRNG 0xf8040000
+/* Reserved: 0xf804400 - 0xffffc00 */
+
+/*
+ * System Peripherals physical base addresses.
+ */
+#define ATMEL_BASE_SYS 0xffffc000
+#define ATMEL_BASE_SMC 0xffffc000
+#define ATMEL_BASE_PMECC (ATMEL_BASE_SMC + 0x070)
+#define ATMEL_BASE_PMERRLOC (ATMEL_BASE_SMC + 0x500)
+#define ATMEL_BASE_FUSE 0xffffe400
+#define ATMEL_BASE_DMAC0 0xffffe600
+#define ATMEL_BASE_DMAC1 0xffffe800
+#define ATMEL_BASE_MPDDRC 0xffffea00
+#define ATMEL_BASE_MATRIX 0xffffec00
+#define ATMEL_BASE_DBGU 0xffffee00
+#define ATMEL_BASE_AIC 0xfffff000
+#define ATMEL_BASE_PIOA 0xfffff200
+#define ATMEL_BASE_PIOB 0xfffff400
+#define ATMEL_BASE_PIOC 0xfffff600
+#define ATMEL_BASE_PIOD 0xfffff800
+#define ATMEL_BASE_PIOE 0xfffffa00
+#define ATMEL_BASE_PMC 0xfffffc00
+#define ATMEL_BASE_RSTC 0xfffffe00
+#define ATMEL_BASE_SHDWN 0xfffffe10
+#define ATMEL_BASE_PIT 0xfffffe30
+#define ATMEL_BASE_WDT 0xfffffe40
+#define ATMEL_BASE_SCKCR 0xfffffe50
+#define ATMEL_BASE_GPBR 0xfffffe60
+#define ATMEL_BASE_RTC 0xfffffeb0
+/* Reserved: 0xfffffee0 - 0xffffffff */
+
+/*
+ * Internal Memory.
+ */
+#define ATMEL_BASE_ROM 0x00100000 /* Internal ROM base address */
+#define ATMEL_BASE_SRAM 0x00200000 /* Internal ROM base address */
+#define ATMEL_BASE_SRAM0 0x00300000 /* Internal SRAM base address */
+#define ATMEL_BASE_SRAM1 0x00310000 /* Internal SRAM base address */
+#define ATMEL_BASE_SMD 0x00400000 /* Internal ROM base address */
+#define ATMEL_BASE_UDPHS_FIFO 0x00500000 /* USB Device HS controller */
+#define ATMEL_BASE_OHCI 0x00600000 /* USB Host controller (OHCI) */
+#define ATMEL_BASE_EHCI 0x00700000 /* USB Host controller (EHCI) */
+#define ATMEL_BASE_AXI 0x00800000 /* Video Decoder Controller */
+#define ATMEL_BASE_DAP 0x00900000 /* Video Decoder Controller */
+
+/*
+ * External memory
+ */
+#define ATMEL_BASE_CS0 0x10000000
+#define ATMEL_BASE_DDRCS 0x20000000
+#define ATMEL_BASE_CS1 0x40000000
+#define ATMEL_BASE_CS2 0x50000000
+#define ATMEL_BASE_CS3 0x60000000
+
+/*
+ * Other misc defines
+ */
+#define ATMEL_PIO_PORTS 5
+#define CPU_HAS_PIO3
+
+/*
+ * PMECC table in ROM
+ */
+#define ATMEL_PMECC_INDEX_OFFSET_512 0x10000
+#define ATMEL_PMECC_INDEX_OFFSET_1024 0x18000
+#define ATMEL_PMECC_ALPHA_OFFSET_512 0x10000
+#define ATMEL_PMECC_ALPHA_OFFSET_1024 0x18000
+
+/*
+ * Cpu Name
+ */
+#define CONFIG_SYS_AT91_D31_CPU_NAME "AT91SAMA5D31"
+#define CONFIG_SYS_AT91_D33_CPU_NAME "AT91SAMA5D33"
+#define CONFIG_SYS_AT91_D34_CPU_NAME "AT91SAMA5D34"
+#define CONFIG_SYS_AT91_D35_CPU_NAME "AT91SAMA5D35"
+#define CONFIG_SYS_AT91_UNKNOWN_CPU "Unknown CPU type"
+
+/*
+ * AT91SAMA5 specific prototypes
+ */
+#ifndef __ASSEMBLY__
+unsigned int get_chip_id(void);
+unsigned int get_extension_chip_id(void);
+unsigned int has_emac(void);
+unsigned int has_gmac(void);
+unsigned int has_lcdc(void);
+char *get_cpu_name(void);
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/arch-at91/at91sama5_smc.h b/arch/arm/include/asm/arch-at91/at91sama5_smc.h
new file mode 100644
index 0000000000..22370e0b8f
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/at91sama5_smc.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2012 Atmel Corporation.
+ *
+ * Static Memory Controllers (SMC) - System peripherals registers.
+ * Based on AT91SAMA5 datasheet.
+ *
+ * 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.
+ */
+
+#ifndef AT91SAMA5_SMC_H
+#define AT91SAMA5_SMC_H
+
+#ifdef __ASSEMBLY__
+
+#define AT91_ASM_SMC_SETUP0 (ATMEL_BASE_SMC + 0x600)
+#define AT91_ASM_SMC_PULSE0 (ATMEL_BASE_SMC + 0x604)
+#define AT91_ASM_SMC_CYCLE0 (ATMEL_BASE_SMC + 0x608)
+#define AT91_ASM_SMC_MODE0 (ATMEL_BASE_SMC + 0x60C)
+
+#else
+
+typedef struct at91_cs {
+ u32 reserved[96];
+ u32 setup; /* 0x600 SMC Setup Register */
+ u32 pulse; /* 0x604 SMC Pulse Register */
+ u32 cycle; /* 0x608 SMC Cycle Register */
+ u32 timings; /* 0x60C SMC Cycle Register */
+ u32 mode; /* 0x610 SMC Mode Register */
+} at91_cs_t;
+
+typedef struct at91_smc {
+ at91_cs_t cs[4];
+} at91_smc_t;
+
+#endif /* __ASSEMBLY__ */
+
+#define AT91_SMC_SETUP_NWE(x) (x & 0x3f)
+#define AT91_SMC_SETUP_NCS_WR(x) ((x & 0x3f) << 8)
+#define AT91_SMC_SETUP_NRD(x) ((x & 0x3f) << 16)
+#define AT91_SMC_SETUP_NCS_RD(x) ((x & 0x3f) << 24)
+
+#define AT91_SMC_PULSE_NWE(x) (x & 0x3f)
+#define AT91_SMC_PULSE_NCS_WR(x) ((x & 0x3f) << 8)
+#define AT91_SMC_PULSE_NRD(x) ((x & 0x3f) << 16)
+#define AT91_SMC_PULSE_NCS_RD(x) ((x & 0x3f) << 24)
+
+#define AT91_SMC_CYCLE_NWE(x) (x & 0x1ff)
+#define AT91_SMC_CYCLE_NRD(x) ((x & 0x1ff) << 16)
+
+#define AT91_SMC_TIMINGS_TCLR(x) (x & 0xf)
+#define AT91_SMC_TIMINGS_TADL(x) ((x & 0xf) << 4)
+#define AT91_SMC_TIMINGS_TAR(x) ((x & 0xf) << 8)
+#define AT91_SMC_TIMINGS_OCMS(x) ((x & 0x1) << 12)
+#define AT91_SMC_TIMINGS_TRR(x) ((x & 0xf) << 16)
+#define AT91_SMC_TIMINGS_TWB(x) ((x & 0xf) << 24)
+#define AT91_SMC_TIMINGS_RBNSEL(x) ((x & 0xf) << 28)
+#define AT91_SMC_TIMINGS_NFSEL(x) ((x & 0x1) << 31)
+
+#define AT91_SMC_MODE_RM_NCS 0x00000000
+#define AT91_SMC_MODE_RM_NRD 0x00000001
+#define AT91_SMC_MODE_WM_NCS 0x00000000
+#define AT91_SMC_MODE_WM_NWE 0x00000002
+
+#define AT91_SMC_MODE_EXNW_DISABLE 0x00000000
+#define AT91_SMC_MODE_EXNW_FROZEN 0x00000020
+#define AT91_SMC_MODE_EXNW_READY 0x00000030
+
+#define AT91_SMC_MODE_BAT 0x00000100
+#define AT91_SMC_MODE_DBW_8 0x00000000
+#define AT91_SMC_MODE_DBW_16 0x00001000
+#define AT91_SMC_MODE_DBW_32 0x00002000
+#define AT91_SMC_MODE_TDF_CYCLE(x) ((x & 0xf) << 16)
+#define AT91_SMC_MODE_TDF 0x00100000
+#define AT91_SMC_MODE_PMEN 0x01000000
+#define AT91_SMC_MODE_PS_4 0x00000000
+#define AT91_SMC_MODE_PS_8 0x10000000
+#define AT91_SMC_MODE_PS_16 0x20000000
+#define AT91_SMC_MODE_PS_32 0x30000000
+
+#ifdef CONFIG_AT91_LEGACY
+
+#define AT91_SMC_SETUP(n) (AT91_SMC + 0x00 + ((n)*0x10)) /* Setup Register for CS n */
+#define AT91_SMC_NWESETUP (0x3f << 0) /* NWE Setup Length */
+#define AT91_SMC_NWESETUP_(x) ((x) << 0)
+#define AT91_SMC_NCS_WRSETUP (0x3f << 8) /* NCS Setup Length in Write Access */
+#define AT91_SMC_NCS_WRSETUP_(x) ((x) << 8)
+#define AT91_SMC_NRDSETUP (0x3f << 16) /* NRD Setup Length */
+#define AT91_SMC_NRDSETUP_(x) ((x) << 16)
+#define AT91_SMC_NCS_RDSETUP (0x3f << 24) /* NCS Setup Length in Read Access */
+#define AT91_SMC_NCS_RDSETUP_(x) ((x) << 24)
+
+#define AT91_SMC_PULSE(n) (AT91_SMC + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */
+#define AT91_SMC_NWEPULSE (0x7f << 0) /* NWE Pulse Length */
+#define AT91_SMC_NWEPULSE_(x) ((x) << 0)
+#define AT91_SMC_NCS_WRPULSE (0x7f << 8) /* NCS Pulse Length in Write Access */
+#define AT91_SMC_NCS_WRPULSE_(x)((x) << 8)
+#define AT91_SMC_NRDPULSE (0x7f << 16) /* NRD Pulse Length */
+#define AT91_SMC_NRDPULSE_(x) ((x) << 16)
+#define AT91_SMC_NCS_RDPULSE (0x7f << 24) /* NCS Pulse Length in Read Access */
+#define AT91_SMC_NCS_RDPULSE_(x)((x) << 24)
+
+#define AT91_SMC_CYCLE(n) (AT91_SMC + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */
+#define AT91_SMC_NWECYCLE (0x1ff << 0 ) /* Total Write Cycle Length */
+#define AT91_SMC_NWECYCLE_(x) ((x) << 0)
+#define AT91_SMC_NRDCYCLE (0x1ff << 16) /* Total Read Cycle Length */
+#define AT91_SMC_NRDCYCLE_(x) ((x) << 16)
+
+#define AT91_SMC_MODE(n) (AT91_SMC + 0x0c + ((n)*0x10)) /* Mode Register for CS n */
+#define AT91_SMC_READMODE (1 << 0) /* Read Mode */
+#define AT91_SMC_WRITEMODE (1 << 1) /* Write Mode */
+#define AT91_SMC_EXNWMODE (3 << 4) /* NWAIT Mode */
+#define AT91_SMC_EXNWMODE_DISABLE (0 << 4)
+#define AT91_SMC_EXNWMODE_FROZEN (2 << 4)
+#define AT91_SMC_EXNWMODE_READY (3 << 4)
+#define AT91_SMC_BAT (1 << 8) /* Byte Access Type */
+#define AT91_SMC_BAT_SELECT (0 << 8)
+#define AT91_SMC_BAT_WRITE (1 << 8)
+#define AT91_SMC_DBW (3 << 12) /* Data Bus Width */
+#define AT91_SMC_DBW_8 (0 << 12)
+#define AT91_SMC_DBW_16 (1 << 12)
+#define AT91_SMC_DBW_32 (2 << 12)
+#define AT91_SMC_TDF (0xf << 16) /* Data Float Time. */
+#define AT91_SMC_TDF_(x) ((x) << 16)
+#define AT91_SMC_TDFMODE (1 << 20) /* TDF Optimization - Enabled */
+#define AT91_SMC_PMEN (1 << 24) /* Page Mode Enabled */
+#define AT91_SMC_PS (3 << 28) /* Page Size */
+#define AT91_SMC_PS_4 (0 << 28)
+#define AT91_SMC_PS_8 (1 << 28)
+#define AT91_SMC_PS_16 (2 << 28)
+#define AT91_SMC_PS_32 (3 << 28)
+#endif
+#endif
diff --git a/arch/arm/include/asm/arch-at91/clk.h b/arch/arm/include/asm/arch-at91/clk.h
index 1e8522b839..bc43c0ca53 100644
--- a/arch/arm/include/asm/arch-at91/clk.h
+++ b/arch/arm/include/asm/arch-at91/clk.h
@@ -95,4 +95,5 @@ static inline unsigned long get_mci_clk_rate(void)
}
int at91_clock_init(unsigned long main_clock);
+void at91_periph_clk_enable(int id);
#endif /* __ASM_ARM_ARCH_CLK_H__ */
diff --git a/arch/arm/include/asm/arch-at91/hardware.h b/arch/arm/include/asm/arch-at91/hardware.h
index 4c4ee703a6..dac322da1e 100644
--- a/arch/arm/include/asm/arch-at91/hardware.h
+++ b/arch/arm/include/asm/arch-at91/hardware.h
@@ -39,6 +39,8 @@
# include <asm/arch/at91sam9g45.h>
#elif defined(CONFIG_AT91SAM9X5)
# include <asm/arch/at91sam9x5.h>
+#elif defined(CONFIG_AT91SAMA5)
+# include <asm/arch/at91sama5.h>
#elif defined(CONFIG_AT91CAP9)
# include <asm/arch/at91cap9.h>
#elif defined(CONFIG_AT91X40)
diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
index a676b6d905..ddbf238da1 100644
--- a/arch/arm/include/asm/mach-types.h
+++ b/arch/arm/include/asm/mach-types.h
@@ -987,6 +987,7 @@ extern unsigned int __machine_arch_type;
#define MACH_TYPE_VIT_IBOX 3371
#define MACH_TYPE_DM6441_ESP 3372
#define MACH_TYPE_AT91SAM9X5EK 3373
+#define MACH_TYPE_AT91SAMA5EK 3373
#define MACH_TYPE_LIBRA 3374
#define MACH_TYPE_EASYCRRH 3375
#define MACH_TYPE_TRIPEL 3376
diff --git a/board/atmel/at91sama5ek/Makefile b/board/atmel/at91sama5ek/Makefile
new file mode 100644
index 0000000000..bfb26b149d
--- /dev/null
+++ b/board/atmel/at91sama5ek/Makefile
@@ -0,0 +1,48 @@
+#
+# (C) Copyright 2003-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2008
+# Stelian Pop <stelian@popies.net>
+# Lead Tech Design <www.leadtechdesign.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 += at91sama5ek.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/at91sama5ek/at91sama5ek.c b/board/atmel/at91sama5ek/at91sama5ek.c
new file mode 100644
index 0000000000..4dc5a5b3da
--- /dev/null
+++ b/board/atmel/at91sama5ek/at91sama5ek.c
@@ -0,0 +1,298 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.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 <mmc.h>
+#include <asm/io.h>
+#include <asm/arch/at91sama5_smc.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/clk.h>
+#include <lcd.h>
+#include <atmel_lcdc.h>
+#if defined(CONFIG_RESET_PHY_R) && defined(CONFIG_MACB)
+#include <net.h>
+#endif
+#include <netdev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Miscelaneous platform dependent initialisations
+ */
+
+#ifdef CONFIG_CMD_NAND
+void at91sama5ek_nand_hw_init(void)
+{
+ struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
+
+ at91_periph_clk_enable(ATMEL_ID_SMC);
+
+ /* Configure SMC CS3 for NAND/SmartMedia */
+ writel(AT91_SMC_SETUP_NWE(2) | AT91_SMC_SETUP_NCS_WR(1) |
+ AT91_SMC_SETUP_NRD(2) | AT91_SMC_SETUP_NCS_RD(1),
+ &smc->cs[3].setup);
+ writel(AT91_SMC_PULSE_NWE(3) | AT91_SMC_PULSE_NCS_WR(5) |
+ AT91_SMC_PULSE_NRD(3) | AT91_SMC_PULSE_NCS_RD(5),
+ &smc->cs[3].pulse);
+ writel(AT91_SMC_CYCLE_NWE(8) | AT91_SMC_CYCLE_NRD(8),
+ &smc->cs[3].cycle);
+ writel(AT91_SMC_TIMINGS_TCLR(3) | AT91_SMC_TIMINGS_TADL(10) |
+ AT91_SMC_TIMINGS_TAR(3) | AT91_SMC_TIMINGS_TRR(4) |
+ AT91_SMC_TIMINGS_TWB(5) | AT91_SMC_TIMINGS_RBNSEL(3)|
+ AT91_SMC_TIMINGS_NFSEL(1), &smc->cs[3].timings);
+ 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(3),
+ &smc->cs[3].mode);
+}
+#endif
+
+#ifdef CONFIG_CMD_USB
+static void at91sama5ek_usb_hw_init(void)
+{
+ at91_set_pio_output(AT91_PIO_PORTD, 25, 0);
+ at91_set_pio_output(AT91_PIO_PORTD, 26, 0);
+ at91_set_pio_output(AT91_PIO_PORTD, 27, 0);
+}
+#endif
+
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+static void at91sama5ek_mci_hw_init(void)
+{
+ at91_mci_hw_init();
+}
+#endif
+
+#ifdef CONFIG_MACB
+static void at91sama5ek_macb_hw_init(void)
+{
+ at91_macb_hw_init();
+}
+#endif
+
+#ifdef CONFIG_GMACB
+static void at91sama5ek_gmacb_hw_init(void)
+{
+ at91_gmacb_hw_init();
+}
+#endif
+
+#ifdef CONFIG_LCD
+
+vidinfo_t panel_info = {
+ vl_col: 800,
+ vl_row: 480,
+ vl_clk: 24000000,
+ vl_sync: ATMEL_LCDC_INVLINE_NORMAL |
+ ATMEL_LCDC_INVFRAME_NORMAL,
+ vl_bpix: LCD_BPP,
+ vl_tft: 1,
+ vl_hsync_len: 128,
+ vl_left_margin: 64,
+ vl_right_margin:64,
+ vl_vsync_len: 2,
+ vl_upper_margin:22,
+ vl_lower_margin:21,
+ mmio : ATMEL_BASE_LCDC,
+};
+
+
+void lcd_enable(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTA, 29, 1); /* power up */
+}
+
+void lcd_disable(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTA, 29, 0); /* power down */
+}
+
+static void at91sama5ek_lcd_hw_init(void)
+{
+ gd->fb_base = CONFIG_AT91SAMA5_LCD_BASE;
+
+ at91_lcd_hw_init();
+}
+
+#ifdef CONFIG_LCD_INFO
+#include <nand.h>
+#include <version.h>
+
+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 ("(C) 2012 ATMEL Corp\n");
+ lcd_printf ("at91support@atmel.com\n");
+ lcd_printf ("%s CPU at %s MHz\n",
+ get_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;
+#ifdef CONFIG_CMD_NAND
+ for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+ nand_size += nand_info[i].size;
+#endif
+ lcd_printf (" %ld MB SDRAM, %ld MB NAND\n",
+ dram_size >> 20,
+ nand_size >> 20 );
+}
+#endif /* CONFIG_LCD_INFO */
+#endif
+
+int board_early_init_f(void)
+{
+#ifdef CONFIG_USART1
+ at91_serial1_hw_init();
+#else
+ at91_seriald_hw_init();
+#endif
+ return 0;
+}
+
+int board_init(void)
+{
+ /* Enable Ctrlc */
+ console_init_f();
+
+ /* arch number of AT91SAMA5EK-Board */
+#if defined CONFIG_AT91SAMA5EK
+ gd->bd->bi_arch_number = MACH_TYPE_AT91SAMA5EK;
+#endif
+
+ /* adress of boot parameters */
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+#ifdef CONFIG_CMD_NAND
+ at91sama5ek_nand_hw_init();
+#endif
+#ifdef CONFIG_CMD_USB
+ at91sama5ek_usb_hw_init();
+#endif
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+ at91sama5ek_mci_hw_init();
+#endif
+#ifdef CONFIG_SYS_USE_DATAFLASH
+ at91_spi0_hw_init(1 << 0);
+#endif
+#ifdef CONFIG_ATMEL_SPI
+ at91_spi0_hw_init(1 << 4);
+#endif
+#ifdef CONFIG_MACB
+ if(has_emac())
+ at91sama5ek_macb_hw_init();
+#endif
+#ifdef CONFIG_GMACB
+ if (has_gmac())
+ at91sama5ek_gmacb_hw_init();
+#endif
+#ifdef CONFIG_LCD
+ if (has_lcdc())
+ at91sama5ek_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;
+}
+
+#ifdef CONFIG_RESET_PHY_R
+void reset_phy(void)
+{
+}
+#endif
+
+int board_eth_init(bd_t *bis)
+{
+ int rc = 0;
+#ifdef CONFIG_MACB
+ if (has_emac())
+ rc = macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0x00);
+#endif
+#ifdef CONFIG_GMACB
+ if (has_gmac())
+ rc = gmacb_eth_initialize(0, (void *)ATMEL_BASE_GMAC, 0x00);
+#endif
+ return rc;
+}
+
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+int board_mmc_init(bd_t *bis)
+{
+ int rc = 0;
+
+ rc = atmel_mci_init((void *)ATMEL_BASE_MCI0);
+
+ return rc;
+}
+#endif
+
+/* 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 < 4;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ switch(slave->cs) {
+ case 0:
+ default:
+ at91_set_pio_output(AT91_PIO_PORTD, 13, 0);
+ break;
+ }
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ switch(slave->cs) {
+ case 0:
+ default:
+ at91_set_pio_output(AT91_PIO_PORTD, 13, 1);
+ break;
+ }
+}
+#endif /* CONFIG_ATMEL_SPI */
diff --git a/board/atmel/at91sama5ek/config.mk b/board/atmel/at91sama5ek/config.mk
new file mode 100644
index 0000000000..6589a12a93
--- /dev/null
+++ b/board/atmel/at91sama5ek/config.mk
@@ -0,0 +1 @@
+CONFIG_SYS_TEXT_BASE = 0x26f00000
diff --git a/boards.cfg b/boards.cfg
index 7c1fc7427a..7472da7f19 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -94,6 +94,9 @@ at91sam9g20ek_dataflash_cs0 arm arm926ejs at91sam9260ek atmel
at91sam9g20ek_dataflash_cs1 arm arm926ejs at91sam9260ek atmel at91 at91sam9260ek:AT91SAM9G20,SYS_USE_DATAFLASH_CS1
at91sam9g20ek_nandflash arm arm926ejs at91sam9260ek atmel at91 at91sam9260ek:AT91SAM9G20,SYS_USE_NANDFLASH
at91sam9m10g45ek_nandflash arm arm926ejs at91sam9m10g45ek atmel at91 at91sam9m10g45ek:AT91SAM9M10G45,SYS_USE_NANDFLASH
+at91sama5ek_nandflash arm armv7 at91sama5ek atmel at91 at91sama5ek:AT91SAMA5,SYS_USE_NANDFLASH
+at91sama5ek_serialflash arm armv7 at91sama5ek atmel at91 at91sama5ek:AT91SAMA5,SYS_USE_SERIALFLASH
+at91sama5ek_sdcard arm armv7 at91sama5ek atmel at91 at91sama5ek:AT91SAMA5,SYS_USE_MMC
at91sam9rlek_dataflash arm arm926ejs at91sam9rlek atmel at91 at91sam9rlek:AT91SAM9RL,SYS_USE_DATAFLASH
at91sam9rlek_nandflash arm arm926ejs at91sam9rlek atmel at91 at91sam9rlek:AT91SAM9RL,SYS_USE_NANDFLASH
at91sam9x5ek_nandflash arm arm926ejs at91sam9x5ek atmel at91 at91sam9x5ek:AT91SAM9X5,SYS_USE_NANDFLASH
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index 4968c5e491..1e104f6fe1 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -83,10 +83,17 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
blklen &= 0xfffc;
/* On some platforms RDPROOF and WRPROOF are ignored */
+#ifdef CONFIG_AT91SAMA5
+ writel((MMCI_BF(CLKDIV, clkdiv)
+ | MMCI_BIT(RDPROOF)
+ | MMCI_BIT(WRPROOF)), &mci->mr);
+ writel((blklen << 16), &mci->blkr);
+#else
writel((MMCI_BF(CLKDIV, clkdiv)
| MMCI_BF(BLKLEN, blklen)
| MMCI_BIT(RDPROOF)
| MMCI_BIT(WRPROOF)), &mci->mr);
+#endif
initialized = 1;
}
@@ -183,6 +190,10 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
/* Figure out the transfer arguments */
cmdr = mci_encode_cmd(cmd, data, &error_flags);
+ if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK)
+ || (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK))
+ writel(data->blocks | mmc->read_bl_len << 16, &mci->blkr);
+
/* Send the command */
writel(cmd->cmdarg, &mci->argr);
writel(cmdr, &mci->cmdr);
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 39535497f8..0e69ac8ba0 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -107,6 +107,7 @@ const struct nand_flash_dev nand_flash_ids[] = {
/* 8 Gigabit */
{"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS},
{"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS},
+ {"NAND 1GiB 3,3V 8-bit", 0x38, 0, 1024, 0, LP_OPTIONS},
{"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16},
{"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, LP_OPTIONS16},
diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c
index 006f6d5d04..2f5e83f040 100644
--- a/drivers/mtd/spi/atmel.c
+++ b/drivers/mtd/spi/atmel.c
@@ -25,6 +25,33 @@
#define AT45_STATUS_P2_PAGE_SIZE (1 << 0)
#define AT45_STATUS_READY (1 << 7)
+/* AT25-specific commands */
+#define CMD_AT25_READ_STATUS 0x05
+#define CMD_AT25_WRITE_STATUS 0x01
+
+#define CMD_AT25_BYTE_PAGE_PROGRAM 0x02
+#define CMD_AT25_ERASE_BLOCK_4K 0x20
+#define CMD_AT25_ERASE_BLOCK_32K 0x52
+#define CMD_AT25_ERASE_BLOCK_64K 0xD8
+
+#define CMD_AT25_WRITE_ENABLE 0x06
+#define CMD_AT25_WRITE_DISABLE 0x04
+
+/* AT25 status register bits */
+#define AT25_STATUS_READYBUSY (1 << 0)
+#define AT25_STATUS_READYBUSY_READY (0 << 0)
+#define AT25_STATUS_READYBUSY_BUSY (1 << 0)
+#define AT25_ERASE_PROGRAM_ERROR (1 << 5)
+#define AT25_STATUS_SWP (3 << 2)
+#define AT25_STATUS_SWP_PROTECTALL (3 << 2)
+#define AT25_STATUS_SWP_PROTECTSOME (1 << 2)
+#define AT25_STATUS_SWP_PROTECTNONE (0 << 2)
+#define AT25_STATUS_SPRL (1 << 7)
+#define AT25_STATUS_SPRL_UNLOCKED (0 << 7)
+#define AT25_STATUS_SPRL_LOCKED (1 << 7)
+
+#define BLOCK_SIZE_4K (4 * 1024)
+
/* DataFlash family IDs, as obtained from the second idcode byte */
#define DF_FAMILY_AT26F 0
#define DF_FAMILY_AT45 1
@@ -111,10 +138,10 @@ static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
},
{
.idcode1 = 0x47,
- .l2_page_size = 8,
- .pages_per_block = 16,
- .blocks_per_sector = 16,
- .nr_sectors = 64,
+ .l2_page_size = 8, /* 256 bytes per page */
+ .pages_per_block = 16, /* 4k bytes per block */
+ .blocks_per_sector = 16, /* 64k bytes per sector*/
+ .nr_sectors = 64, /* 64 sectors */
.name = "AT25DF321",
},
};
@@ -178,6 +205,20 @@ static void at45_build_address(struct atmel_spi_flash *asf, u8 *cmd, u32 offset)
cmd[2] = byte_addr;
}
+static int dataflash_read_fast_p2(struct spi_flash *flash,
+ u32 offset, size_t len, void *buf)
+{
+ u8 cmd[5];
+
+ cmd[0] = CMD_READ_ARRAY_FAST;
+ cmd[1] = offset >> 16;
+ cmd[2] = offset >> 8;
+ cmd[3] = offset;
+ cmd[4] = 0x00;
+
+ return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
+}
+
static int dataflash_read_fast_at45(struct spi_flash *flash,
u32 offset, size_t len, void *buf)
{
@@ -336,7 +377,7 @@ out:
/*
* TODO: the two erase funcs (_p2/_at45) should get unified ...
*/
-static int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len)
+int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len)
{
struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
unsigned long page_size;
@@ -395,7 +436,7 @@ out:
return ret;
}
-static int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len)
+int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len)
{
struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
unsigned long page_addr;
@@ -458,10 +499,259 @@ out:
return ret;
}
+static int at25_read_status(struct spi_flash *flash)
+{
+ struct spi_slave *spi = flash->spi;
+ int ret;
+ u8 cmd = CMD_AT25_READ_STATUS;
+ u8 status;
+
+ ret = spi_flash_cmd_read(spi, &cmd, 1, &status, 1);
+
+ if (ret < 0) {
+ debug("SF: Error occured when read AT25 status\n");
+ return ret;
+ } else
+ return status;
+}
+
+static int at25_wait_ready(struct spi_flash *flash, unsigned long timeout)
+{
+ unsigned long timebase;
+ int ret;
+ u8 status;
+
+ timebase = get_timer(0);
+
+ do {
+ ret = at25_read_status(flash);
+ if (ret < 0)
+ return -1;
+ else
+ status = ret;
+
+ if ((status & AT25_STATUS_READYBUSY)
+ == AT25_STATUS_READYBUSY_READY)
+ break;
+ } while (get_timer(timebase) < timeout);
+
+ if ((status & AT25_STATUS_READYBUSY) == AT25_STATUS_READYBUSY_READY)
+ return 0;
+
+ /* Timed out */
+ return -1;
+}
+
+static int at25_write_status(struct spi_flash *flash, u8 data)
+{
+ struct spi_slave *spi = flash->spi;
+ u8 cmd = CMD_AT25_WRITE_STATUS;
+
+ return spi_flash_cmd_write(spi, &cmd, 1, &data, 1);
+}
+
+static int at25_write_enable(struct spi_flash *flash, int is_enable)
+{
+ struct spi_slave *spi = flash->spi;
+ int ret;
+ u8 cmd;
+
+ if (is_enable)
+ cmd = CMD_AT25_WRITE_ENABLE;
+ else
+ cmd = CMD_AT25_WRITE_DISABLE;
+
+ ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
+ if (ret)
+ return -1;
+
+ /* Deactivate CS */
+ spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+
+ return 0;
+}
+
+static int at25_unprotect(struct spi_flash *flash)
+{
+ int ret;
+ u8 status;
+
+ ret = at25_read_status(flash);
+ if (ret < 0)
+ debug("SF: Read AT25 status failed\n");
+ else
+ status = ret;
+
+ if ((status & AT25_STATUS_SWP) == AT25_STATUS_SWP_PROTECTNONE) {
+ /* Protection already disabled */
+ return 0;
+ }
+
+ /* Check if sector protection registers are locked */
+ if ((status & AT25_STATUS_SPRL) == AT25_STATUS_SPRL_LOCKED) {
+ /* Unprotect sector protection registers. */
+ at25_write_enable(flash, 1);
+ at25_write_status(flash, 0);
+ }
+
+ /* Perform a global unprotect command */
+ at25_write_enable(flash, 1);
+ at25_write_status(flash, 0);
+
+ /* Check the new status */
+ status = at25_read_status(flash);
+ if (ret < 0)
+ return -1;
+
+ if ((status & (AT25_STATUS_SPRL | AT25_STATUS_SWP)) != 0) {
+ debug("SF: Unprotect AT25 failed\n");
+ return -1;
+ } else
+ return 0;
+}
+
+int dataflash_erase_block_at25(struct spi_flash *flash, u32 offset)
+{
+ /* Using 4k block erase. */
+ u32 addr = offset;
+ int ret;
+ u8 cmd[4];
+
+ if (offset % BLOCK_SIZE_4K != 0)
+ return -1;
+
+ ret = at25_write_enable(flash, 1);
+ if (ret < 0) {
+ debug("SF: Enable write AT25 failed\n");
+ return ret;
+ }
+
+ cmd[0] = CMD_AT25_ERASE_BLOCK_4K;
+ cmd[1] = addr >> 16;
+ cmd[2] = addr >> 8;
+ cmd[3] = addr;
+ ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
+ if (ret < 0) {
+ debug("SF: AT25 4k block erase failed\n");
+ return ret;
+ }
+
+ ret = at25_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+ if (ret < 0) {
+ debug("SF: AT25 4k block erase timed out\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int dataflash_erase_at25(struct spi_flash *flash, u32 offset, size_t len)
+{
+ int ret;
+ u32 addr;
+
+ /*
+ * TODO: This function currently uses 4k block erase only. We can
+ * probably speed things up by using 32k/64k block erase or chip
+ * erase when possible.
+ */
+
+ if (offset % BLOCK_SIZE_4K || len % BLOCK_SIZE_4K) {
+ debug("SF: Erase offset/length not multiple of block size\n");
+ return -1;
+ }
+
+ ret = spi_claim_bus(flash->spi);
+ if (ret) {
+ debug("SF: Unable to claim SPI bus\n");
+ return ret;
+ }
+
+ ret = at25_unprotect(flash);
+ if (ret < 0)
+ goto out;
+
+ /* Use 4k block erase. */
+ for (addr = offset; addr < offset + len; addr += BLOCK_SIZE_4K) {
+ if (offset % BLOCK_SIZE_4K != 0)
+ addr = (addr >> 12) << 12; /* 4k size align. */
+
+ ret = dataflash_erase_block_at25(flash, addr);
+ if (ret < 0)
+ goto out;
+ }
+
+ debug("SF: AT25: Successfully erased %zu bytes @ 0x%x\n",
+ len, offset);
+ ret = 0;
+out:
+ spi_release_bus(flash->spi);
+ return ret;
+}
+
+int dataflash_write_at25(struct spi_flash *flash,
+ u32 offset, size_t len, const void *buf)
+{
+ struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
+ unsigned long page_size;
+ size_t chunk_len;
+ size_t actual;
+ int ret;
+ u8 status;
+ u32 addr;
+ u8 cmd[4];
+ u8 *data = (u8 *)buf;
+
+ page_size = 1 << (asf->params->l2_page_size);
+
+ ret = spi_claim_bus(flash->spi);
+ if (ret) {
+ debug("SF: Unable to claim SPI bus\n");
+ return ret;
+ }
+
+ ret = at25_read_status(flash);
+ if (ret < 0)
+ goto out;
+ else
+ status = ret;
+
+ /* Using page programming. */
+ for (actual = 0; actual < len; actual += chunk_len, data += chunk_len) {
+ chunk_len = min(page_size, len - actual);
+ /* using page programming. */
+ ret = at25_write_enable(flash, 1);
+ if (ret < 0)
+ goto out;
+
+ addr = offset + actual;
+ cmd[0] = CMD_AT25_BYTE_PAGE_PROGRAM;
+ cmd[1] = addr >> 16;
+ cmd[2] = addr >> 8;
+ cmd[3] = addr;
+
+ ret = spi_flash_cmd_write(flash->spi, cmd, 4, data, chunk_len);
+ if (ret < 0) {
+ debug("SF: Page programming AT25 failed\n");
+ goto out;
+ }
+
+ ret = at25_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+ if (ret < 0) {
+ debug("SF: AT25 page programming timed out\n");
+ goto out;
+ }
+ }
+
+out:
+ spi_release_bus(flash->spi);
+ return 0;
+}
+
struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
{
const struct atmel_spi_flash_params *params;
- unsigned page_size;
+ unsigned long page_size;
unsigned int family;
struct atmel_spi_flash *asf;
unsigned int i;
@@ -513,7 +803,7 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
asf->flash.erase = dataflash_erase_at45;
page_size += 1 << (params->l2_page_size - 5);
} else {
- asf->flash.read = spi_flash_cmd_read_fast;
+ asf->flash.read = dataflash_read_fast_p2;
asf->flash.write = dataflash_write_p2;
asf->flash.erase = dataflash_erase_p2;
}
@@ -542,6 +832,9 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
* params->blocks_per_sector
* params->nr_sectors;
+ debug("SF: Detected %s with page size %lu, total %u bytes\n",
+ params->name, page_size, asf->flash.size);
+
return &asf->flash;
err:
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index e4abac7c8f..b1da93f8f2 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -52,6 +52,7 @@ COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
COBJS-$(CONFIG_LAN91C96) += lan91c96.o
COBJS-$(CONFIG_MACB) += macb.o
+COBJS-$(CONFIG_GMACB) += gmacb.o
COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o
COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o
diff --git a/drivers/net/gmacb.c b/drivers/net/gmacb.c
new file mode 100644
index 0000000000..af1f552ab0
--- /dev/null
+++ b/drivers/net/gmacb.c
@@ -0,0 +1,622 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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>
+
+/*
+ * The u-boot networking stack is a little weird. It seems like the
+ * networking core allocates receive buffers up front without any
+ * regard to the hardware that's supposed to actually receive those
+ * packets.
+ *
+ * The MACB receives packets into 128-byte receive buffers, so the
+ * buffers allocated by the core isn't very practical to use. We'll
+ * allocate our own, but we need one such buffer in case a packet
+ * wraps around the DMA ring so that we have to copy it.
+ *
+ * Therefore, define CONFIG_SYS_RX_ETH_BUFFER to 1 in the board-specific
+ * configuration header. This way, the core allocates one RX buffer
+ * and one TX buffer, each of which can hold a ethernet packet of
+ * maximum size.
+ *
+ * For some reason, the networking core unconditionally specifies a
+ * 32-byte packet "alignment" (which really should be called
+ * "padding"). MACB shouldn't need that, but we'll refrain from any
+ * core modifications here...
+ */
+
+#include <net.h>
+#include <netdev.h>
+#include <malloc.h>
+#include <miiphy.h>
+
+#include <linux/mii.h>
+#include <asm/io.h>
+#include <asm/dma-mapping.h>
+#include <asm/arch/clk.h>
+
+#include "gmacb.h"
+
+#define barrier() asm volatile("" ::: "memory")
+
+#define CONFIG_SYS_MACB_RX_BUFFER_SIZE 4096
+#define CONFIG_SYS_MACB_RX_RING_SIZE (CONFIG_SYS_MACB_RX_BUFFER_SIZE / 128)
+#define CONFIG_SYS_MACB_TX_RING_SIZE 16
+#define CONFIG_SYS_MACB_TX_TIMEOUT 1000
+#define CONFIG_SYS_MACB_AUTONEG_TIMEOUT 5000000
+
+struct macb_dma_desc {
+ u32 addr;
+ u32 ctrl;
+} __attribute__ ((packed, aligned(8)));
+
+#define RXADDR_USED 0x00000001
+#define RXADDR_WRAP 0x00000002
+
+#define RXBUF_FRMLEN_MASK 0x00001fff
+#define RXBUF_FRAME_START 0x00004000
+#define RXBUF_FRAME_END 0x00008000
+#define RXBUF_TYPEID_MATCH 0x00400000
+#define RXBUF_ADDR4_MATCH 0x06000000
+#define RXBUF_ADDR3_MATCH 0x04000000
+#define RXBUF_ADDR2_MATCH 0x02000000
+#define RXBUF_ADDR1_MATCH 0x00000000
+#define RXBUF_BROADCAST 0x80000000
+
+#define TXBUF_FRMLEN_MASK 0x00003fff
+#define TXBUF_FRAME_END 0x00008000
+#define TXBUF_NOCRC 0x00010000
+#define TXBUF_FCS_ERR 0x00700000
+#define TXBUF_COL 0x04000000
+#define TXBUF_FRAME_COR 0x08000000
+#define TXBUF_UNDERRUN 0x10000000
+#define TXBUF_MAXRETRY 0x20000000
+#define TXBUF_WRAP 0x40000000
+#define TXBUF_USED 0x80000000
+
+struct macb_device {
+ void *regs;
+
+ unsigned int rx_tail;
+ unsigned int tx_head;
+ unsigned int tx_tail;
+
+ void *rx_buffer;
+ void *tx_buffer;
+ struct macb_dma_desc *rx_ring;
+ struct macb_dma_desc *tx_ring;
+
+ unsigned long rx_buffer_dma;
+ unsigned long rx_ring_dma;
+ unsigned long tx_ring_dma;
+
+ const struct device *dev;
+ struct eth_device netdev;
+ unsigned short phy_addr;
+};
+#define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
+
+static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
+{
+ unsigned long netctl;
+ unsigned long netstat;
+ unsigned long frame;
+
+ netctl = macb_readl(macb, NCR);
+ netctl |= MACB_BIT(MPE);
+ macb_writel(macb, NCR, netctl);
+
+ frame = (MACB_BF(CLTTO, 1)
+ | MACB_BF(OP, 1)
+ | MACB_BF(PHYA, macb->phy_addr)
+ | MACB_BF(REGA, reg)
+ | MACB_BF(WTN, 2)
+ | MACB_BF(DATA, value));
+ macb_writel(macb, MAN, frame);
+
+ do {
+ netstat = macb_readl(macb, NSR);
+ } while (!(netstat & MACB_BIT(IDLE)));
+
+ netctl = macb_readl(macb, NCR);
+ netctl &= ~MACB_BIT(MPE);
+ macb_writel(macb, NCR, netctl);
+}
+
+static u16 macb_mdio_read(struct macb_device *macb, u8 reg)
+{
+ unsigned long netctl;
+ unsigned long netstat;
+ unsigned long frame;
+
+ netctl = macb_readl(macb, NCR);
+ netctl |= MACB_BIT(MPE);
+ macb_writel(macb, NCR, netctl);
+
+ frame = (MACB_BF(CLTTO, 1)
+ | MACB_BF(OP, 2)
+ | MACB_BF(PHYA, macb->phy_addr)
+ | MACB_BF(REGA, reg)
+ | MACB_BF(WTN, 2));
+ macb_writel(macb, MAN, frame);
+
+ do {
+ netstat = macb_readl(macb, NSR);
+ } while (!(netstat & MACB_BIT(IDLE)));
+
+ frame = macb_readl(macb, MAN);
+
+ netctl = macb_readl(macb, NCR);
+ netctl &= ~MACB_BIT(MPE);
+ macb_writel(macb, NCR, netctl);
+
+ return MACB_BFEXT(DATA, frame);
+}
+
+#if defined(CONFIG_CMD_MII)
+
+int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
+{
+ struct eth_device *dev = eth_get_dev_by_name(devname);
+ struct macb_device *macb = to_macb(dev);
+
+ if ( macb->phy_addr != phy_adr )
+ return -1;
+
+ *value = macb_mdio_read(macb, reg);
+
+ return 0;
+}
+
+int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+{
+ struct eth_device *dev = eth_get_dev_by_name(devname);
+ struct macb_device *macb = to_macb(dev);
+
+ if ( macb->phy_addr != phy_adr )
+ return -1;
+
+ macb_mdio_write(macb, reg, value);
+
+ return 0;
+}
+#endif
+
+
+#if defined(CONFIG_CMD_NET)
+
+static int macb_send(struct eth_device *netdev, volatile void *packet,
+ int length)
+{
+ struct macb_device *macb = to_macb(netdev);
+ unsigned long paddr, ctrl;
+ unsigned int tx_head = macb->tx_head;
+ int i;
+
+ paddr = dma_map_single(packet, length, DMA_TO_DEVICE);
+
+ macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | macb_readl(macb, NCR));
+ ctrl = length & TXBUF_FRMLEN_MASK;
+ ctrl |= TXBUF_FRAME_END;
+ if (tx_head == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) {
+ ctrl |= TXBUF_WRAP;
+ macb->tx_head = 0;
+ } else
+ macb->tx_head++;
+
+ macb->tx_ring[tx_head].ctrl = ctrl;
+ macb->tx_ring[tx_head].addr = paddr;
+ barrier();
+
+ macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
+
+ /*
+ * I guess this is necessary because the networking core may
+ * re-use the transmit buffer as soon as we return...
+ */
+ for (i = 0; i <= CONFIG_SYS_MACB_TX_TIMEOUT; i++) {
+ barrier();
+ ctrl = macb->tx_ring[tx_head].ctrl;
+ if (ctrl & TXBUF_USED)
+ break;
+ udelay(1);
+ }
+
+ dma_unmap_single(packet, length, paddr);
+
+ if (i <= CONFIG_SYS_MACB_TX_TIMEOUT) {
+ if (ctrl & TXBUF_UNDERRUN)
+ printf("%s: TX underrun\n", netdev->name);
+ } else {
+ printf("%s: TX timeout\n", netdev->name);
+ }
+
+ /* No one cares anyway */
+ return 0;
+}
+
+static void reclaim_rx_buffers(struct macb_device *macb,
+ unsigned int new_tail)
+{
+ unsigned int i;
+
+ i = macb->rx_tail;
+ while (i > new_tail) {
+ macb->rx_ring[i].addr &= ~RXADDR_USED;
+ i++;
+ if (i > CONFIG_SYS_MACB_RX_RING_SIZE)
+ i = 0;
+ }
+
+ while (i < new_tail) {
+ macb->rx_ring[i].addr &= ~RXADDR_USED;
+ i++;
+ }
+
+ barrier();
+ macb->rx_tail = new_tail;
+}
+
+static int macb_recv(struct eth_device *netdev)
+{
+ struct macb_device *macb = to_macb(netdev);
+ unsigned int rx_tail = macb->rx_tail;
+ void *buffer;
+ int length;
+ int wrapped = 0;
+ u32 status;
+
+ for (;;) {
+ if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED))
+ return -1;
+
+ status = macb->rx_ring[rx_tail].ctrl;
+ if (status & RXBUF_FRAME_START) {
+ if (rx_tail != macb->rx_tail)
+ reclaim_rx_buffers(macb, rx_tail);
+ wrapped = 0;
+ }
+
+ if (status & RXBUF_FRAME_END) {
+ buffer = macb->rx_buffer + 128 * macb->rx_tail;
+ length = status & RXBUF_FRMLEN_MASK;
+ if (wrapped) {
+ unsigned int headlen, taillen;
+
+ headlen = 128 * (CONFIG_SYS_MACB_RX_RING_SIZE
+ - macb->rx_tail);
+ taillen = length - headlen;
+ memcpy((void *)NetRxPackets[0],
+ buffer, headlen);
+ memcpy((void *)NetRxPackets[0] + headlen,
+ macb->rx_buffer, taillen);
+ buffer = (void *)NetRxPackets[0];
+ }
+
+ NetReceive(buffer, length);
+ if (++rx_tail >= CONFIG_SYS_MACB_RX_RING_SIZE)
+ rx_tail = 0;
+ reclaim_rx_buffers(macb, rx_tail);
+ } else {
+ if (++rx_tail >= CONFIG_SYS_MACB_RX_RING_SIZE) {
+ wrapped = 1;
+ rx_tail = 0;
+ }
+ }
+ barrier();
+ }
+
+ return 0;
+}
+
+static void macb_phy_reset(struct macb_device *macb)
+{
+ struct eth_device *netdev = &macb->netdev;
+ int i;
+ u16 status, adv;
+
+ adv = ADVERTISE_CSMA | ADVERTISE_ALL;
+ macb_mdio_write(macb, MII_ADVERTISE, adv);
+ printf("%s: Starting autonegotiation...\n", netdev->name);
+ macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE
+ | BMCR_ANRESTART));
+
+ for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) {
+ status = macb_mdio_read(macb, MII_BMSR);
+ if (status & BMSR_ANEGCOMPLETE)
+ break;
+ udelay(100);
+ }
+
+ if (status & BMSR_ANEGCOMPLETE)
+ printf("%s: Autonegotiation complete\n", netdev->name);
+ else
+ printf("%s: Autonegotiation timed out (status=0x%04x)\n",
+ netdev->name, status);
+}
+
+#ifdef CONFIG_MACB_SEARCH_PHY
+static int macb_phy_find(struct macb_device *macb)
+{
+ int i;
+ u16 phy_id;
+
+ /* Search for PHY... */
+ for (i = 0; i < 32; i++) {
+ macb->phy_addr = i;
+ phy_id = macb_mdio_read(macb, MII_PHYSID1);
+ if (phy_id != 0xffff) {
+ printf("%s: PHY present at %d\n", macb->netdev.name, i);
+ return 1;
+ }
+ }
+
+ /* PHY isn't up to snuff */
+ printf("%s: PHY not found", macb->netdev.name);
+
+ return 0;
+}
+#endif /* CONFIG_MACB_SEARCH_PHY */
+
+
+static int macb_phy_init(struct macb_device *macb)
+{
+ struct eth_device *netdev = &macb->netdev;
+ u32 ncfgr;
+ u16 phy_id, status, adv, lpa;
+ int media, speed, duplex;
+ int i;
+
+#ifdef CONFIG_MACB_SEARCH_PHY
+ /* Auto-detect phy_addr */
+ if (!macb_phy_find(macb)) {
+ return 0;
+ }
+#endif /* CONFIG_MACB_SEARCH_PHY */
+
+ /* Check if the PHY is up to snuff... */
+ phy_id = macb_mdio_read(macb, MII_PHYSID1);
+ if (phy_id == 0xffff) {
+ printf("%s: No PHY present\n", netdev->name);
+ return 0;
+ }
+
+ /* Timing configuration for KSZ9021RN PHY */
+ macb_mdio_write(macb, 11, 260 | 0x8000);
+ macb_mdio_write(macb, 12, 0xF2F4);
+ macb_mdio_write(macb, 11, 261 | 0x8000);
+ macb_mdio_write(macb, 12, 0x2222);
+
+ status = macb_mdio_read(macb, MII_BMSR);
+ if (!(status & BMSR_LSTATUS)) {
+ /* Try to re-negotiate if we don't have link already. */
+ macb_phy_reset(macb);
+ for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) {
+ status = macb_mdio_read(macb, MII_BMSR);
+ if (status & BMSR_LSTATUS)
+ break;
+ udelay(100);
+ }
+ }
+
+ if (!(status & BMSR_LSTATUS)) {
+ printf("%s: link down (status: 0x%04x)\n",
+ netdev->name, status);
+ return 0;
+ } else {
+ /* Judge whether work in 1000Base-T mode */
+ adv = macb_mdio_read(macb, MII_STAT1000);
+ lpa = macb_mdio_read(macb, MII_CTRL1000);
+ if (adv & (1 << 11)) {
+ speed = 1000;
+
+ if (lpa & (1 << 9)) {
+ duplex = 1;
+ } else {
+ duplex = 0;
+ }
+
+ printf("%s: link up, %dMbps %s-duplex (lpa: 0x%04x)\n",
+ netdev->name,
+ speed,
+ duplex ? "full" : "half",
+ lpa);
+
+ ncfgr = macb_readl(macb, NCFGR);
+ ncfgr &= ~(MACB_BIT(GBE) | MACB_BIT (SPD) | MACB_BIT(FD));
+ if (speed)
+ ncfgr |= MACB_BIT(GBE);
+ if (duplex)
+ ncfgr |= MACB_BIT(FD);
+ macb_writel(macb, NCFGR, ncfgr);
+ } else {
+ /* Judge whether work in 100Base-T mode */
+ adv = macb_mdio_read(macb, MII_ADVERTISE);
+ lpa = macb_mdio_read(macb, MII_LPA);
+ media = mii_nway_result(lpa & adv);
+ speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
+ ? 1 : 0);
+ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+
+ printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
+ netdev->name,
+ speed? "100" : "10",
+ duplex ? "full" : "half",
+ lpa);
+
+ ncfgr = macb_readl(macb, NCFGR);
+ ncfgr &= ~(MACB_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD));
+ if (speed)
+ ncfgr |= MACB_BIT(SPD);
+ if (duplex)
+ ncfgr |= MACB_BIT(FD);
+ macb_writel(macb, NCFGR, ncfgr);
+ }
+ }
+
+ return 1;
+}
+
+static int macb_init(struct eth_device *netdev, bd_t *bd)
+{
+ struct macb_device *macb = to_macb(netdev);
+ unsigned long paddr;
+ int i;
+
+ /*
+ * macb_halt should have been called at some point before now,
+ * so we'll assume the controller is idle.
+ */
+
+ /* initialize DMA descriptors */
+ paddr = macb->rx_buffer_dma;
+ for (i = 0; i < CONFIG_SYS_MACB_RX_RING_SIZE; i++) {
+ if (i == (CONFIG_SYS_MACB_RX_RING_SIZE - 1))
+ paddr |= RXADDR_WRAP;
+ macb->rx_ring[i].addr = paddr;
+ macb->rx_ring[i].ctrl = 0;
+ paddr += 128;
+ }
+ for (i = 0; i < CONFIG_SYS_MACB_TX_RING_SIZE; i++) {
+ macb->tx_ring[i].addr = 0;
+ if (i == (CONFIG_SYS_MACB_TX_RING_SIZE - 1))
+ macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP;
+ else
+ macb->tx_ring[i].ctrl = TXBUF_USED;
+ }
+ macb->rx_tail = macb->tx_head = macb->tx_tail = 0;
+
+ macb_writel(macb, RBQB, macb->rx_ring_dma);
+ macb_writel(macb, TBQB, macb->tx_ring_dma);
+
+ /* choose RMII or MII mode. This depends on the board */
+#ifdef CONFIG_RGMII
+#if defined(CONFIG_AT91SAMA5)
+ macb_writel(macb, UR, MACB_BIT(RGMII));
+#else
+ macb_writel(macb, UR, 0);
+#endif
+#endif /* CONFIG_RGMII */
+
+ if (!macb_phy_init(macb))
+ return -1;
+
+ /* Enable TX and RX */
+ macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE));
+
+ return 0;
+}
+
+static void macb_halt(struct eth_device *netdev)
+{
+ struct macb_device *macb = to_macb(netdev);
+ u32 ncr, tsr;
+
+ /* Halt the controller and wait for any ongoing transmission to end. */
+ ncr = macb_readl(macb, NCR);
+ ncr |= MACB_BIT(THALT);
+ macb_writel(macb, NCR, ncr);
+
+ do {
+ tsr = macb_readl(macb, TSR);
+ } while (tsr & MACB_BIT(TGO));
+
+ /* Disable TX and RX, and clear statistics */
+ macb_writel(macb, NCR, MACB_BIT(CLRSTAT));
+}
+
+static int macb_write_hwaddr(struct eth_device *dev)
+{
+ struct macb_device *macb = to_macb(dev);
+ u32 hwaddr_bottom;
+ u16 hwaddr_top;
+
+ /* set hardware address */
+ hwaddr_bottom = dev->enetaddr[0] | dev->enetaddr[1] << 8 |
+ dev->enetaddr[2] << 16 | dev->enetaddr[3] << 24;
+ macb_writel(macb, SA1B, hwaddr_bottom);
+ hwaddr_top = dev->enetaddr[4] | dev->enetaddr[5] << 8;
+ macb_writel(macb, SA1T, hwaddr_top);
+ return 0;
+}
+
+int gmacb_eth_initialize(int id, void *regs, unsigned int phy_addr)
+{
+ struct macb_device *macb;
+ struct eth_device *netdev;
+ unsigned long macb_hz;
+ u32 ncfgr;
+
+ macb = malloc(sizeof(struct macb_device));
+ if (!macb) {
+ printf("Error: Failed to allocate memory for MACB%d\n", id);
+ return -1;
+ }
+ memset(macb, 0, sizeof(struct macb_device));
+
+ netdev = &macb->netdev;
+
+ macb->rx_buffer = dma_alloc_coherent(CONFIG_SYS_MACB_RX_BUFFER_SIZE,
+ &macb->rx_buffer_dma);
+
+ macb->rx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_RX_RING_SIZE
+ * sizeof(struct macb_dma_desc),
+ &macb->rx_ring_dma);
+ macb->tx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_TX_RING_SIZE
+ * sizeof(struct macb_dma_desc),
+ &macb->tx_ring_dma);
+
+ macb->regs = regs;
+ macb->phy_addr = phy_addr;
+
+ sprintf(netdev->name, "gmacb%d", id);
+ netdev->init = macb_init;
+ netdev->halt = macb_halt;
+ netdev->send = macb_send;
+ netdev->recv = macb_recv;
+ netdev->write_hwaddr = macb_write_hwaddr;
+
+ /*
+ * Do some basic initialization so that we at least can talk
+ * to the PHY
+ */
+ macb_hz = get_macb_pclk_rate(id);
+ if (macb_hz < 20000000)
+ ncfgr = MACB_BF(CLK, GMACB_CLK_DIV8);
+ else if (macb_hz < 40000000)
+ ncfgr = MACB_BF(CLK, GMACB_CLK_DIV16);
+ else if (macb_hz < 80000000)
+ ncfgr = MACB_BF(CLK, GMACB_CLK_DIV32);
+ else if (macb_hz < 120000000)
+ ncfgr = MACB_BF(CLK, GMACB_CLK_DIV48);
+ else
+ ncfgr = MACB_BF(CLK, GMACB_CLK_DIV64);
+
+ macb_writel(macb, NCFGR, ncfgr);
+
+ /* Configuration the Datapath 64 bit */
+ macb_writel(macb, NCFGR, MACB_BF(DBW, 1) | macb_readl(macb, NCFGR));
+
+ eth_register(netdev);
+
+#if defined(CONFIG_CMD_MII)
+ miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write);
+#endif
+ return 0;
+}
+
+#endif
diff --git a/drivers/net/gmacb.h b/drivers/net/gmacb.h
new file mode 100644
index 0000000000..cd755bccc3
--- /dev/null
+++ b/drivers/net/gmacb.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * 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 __DRIVERS_GMACB_H__
+#define __DRIVERS_GMACB_H__
+
+/* MACB register offsets */
+#define GMACB_NCR 0x0000
+#define GMACB_NCFGR 0x0004
+#define GMACB_NSR 0x0008
+#define GMACB_UR 0x000c
+#define GMACB_DCFGR 0x0010
+#define GMACB_TSR 0x0014
+#define GMACB_RBQB 0x0018
+#define GMACB_TBQB 0x001c
+#define GMACB_RSR 0x0020
+#define GMACB_ISR 0x0024
+#define GMACB_IER 0x0028
+#define GMACB_IDR 0x002c
+#define GMACB_IMR 0x0030
+#define GMACB_MAN 0x0034
+#define GMACB_RPQ 0x0038
+#define GMACB_TPQ 0x003c
+#define GMACB_TPSF 0x0040
+#define GMACB_RPSF 0x0044
+#define GMACB_HRB 0x0080
+#define GMACB_HRT 0x0084
+#define GMACB_SA1B 0x0088
+#define GMACB_SA1T 0x008c
+#define GMACB_SA2B 0x0090
+#define GMACB_SA2T 0x0094
+#define GMACB_SA3B 0x0098
+#define GMACB_SA3T 0x009c
+#define GMACB_SA4B 0x00a0
+#define GMACB_SA4T 0x00a4
+#define GMACB_TIDM1 0x00a8
+#define GMACB_TIDM2 0x00ac
+#define GMACB_TIDM3 0x00b0
+#define GMACB_TIDM4 0x00b4
+#define GMACB_WOL 0x00b8
+#define GMACB_IPGS 0x00bc
+#define GMACB_SVLAN 0x00c0
+#define GMACB_TPFCP 0x00c4
+#define GMACB_SAMB1 0x00c8
+#define GMACB_SAMT1 0x00cc
+
+#define GMACB_FT 0x0108
+#define GMACB_BCFT 0x010c
+
+
+
+
+ /* Bitfields in NCR */
+#define GMACB_LB_OFFSET 0
+#define GMACB_LB_SIZE 1
+#define GMACB_LBL_OFFSET 1
+#define GMACB_LBL_SIZE 1
+#define GMACB_RE_OFFSET 2
+#define GMACB_RE_SIZE 1
+#define GMACB_TE_OFFSET 3
+#define GMACB_TE_SIZE 1
+#define GMACB_MPE_OFFSET 4
+#define GMACB_MPE_SIZE 1
+#define GMACB_CLRSTAT_OFFSET 5
+#define GMACB_CLRSTAT_SIZE 1
+#define GMACB_INCSTAT_OFFSET 6
+#define GMACB_INCSTAT_SIZE 1
+#define GMACB_WESTAT_OFFSET 7
+#define GMACB_WESTAT_SIZE 1
+#define GMACB_BP_OFFSET 8
+#define GMACB_BP_SIZE 1
+#define GMACB_TSTART_OFFSET 9
+#define GMACB_TSTART_SIZE 1
+#define GMACB_THALT_OFFSET 10
+#define GMACB_THALT_SIZE 1
+#define GMACB_NCR_TPF_OFFSET 11
+#define GMACB_NCR_TPF_SIZE 1
+#define GMACB_TZQ_OFFSET 12
+#define GMACB_TZQ_SIZE 1
+
+ /* Bitfields in NCFGR */
+#define GMACB_SPD_OFFSET 0
+#define GMACB_SPD_SIZE 1
+#define GMACB_FD_OFFSET 1
+#define GMACB_FD_SIZE 1
+#define GMACB_DNVLAN_OFFSET 2
+#define GMACB_DNVLAN_SIZE 1
+#define GMACB_JFRAME_OFFSET 3
+#define GMACB_JFRAME_SIZE 1
+#define GMACB_CAF_OFFSET 4
+#define GMACB_CAF_SIZE 1
+#define GMACB_NBC_OFFSET 5
+#define GMACB_NBC_SIZE 1
+#define GMACB_NCFGR_MTI_OFFSET 6
+#define GMACB_NCFGR_MTI_SIZE 1
+#define GMACB_UNI_OFFSET 7
+#define GMACB_UNI_SIZE 1
+#define MACB_MAXFS_OFFSET 8
+#define MACB_MAXFS_SIZE 1
+#define GMACB_GBE_OFFSET 10
+#define GMACB_GBE_SIZE 1
+#define GMACB_PIS_OFFSET 11
+#define GMACB_PIS_SIZE 1
+#define GMACB_RTY_OFFSET 12
+#define GMACB_RTY_SIZE 1
+#define GMACB_PEN_OFFSET 13
+#define GMACB_PEN_SIZE 1
+#define GMACB_RXBUFO_OFFSET 14
+#define GMACB_RXBUFO_SIZE 2
+#define GMACB_LFERD_OFFSET 16
+#define GMACB_LFERD_SIZE 1
+#define GMACB_RFCS_OFFSET 17
+#define GMACB_RFCS_SIZE 1
+#define GMACB_CLK_OFFSET 18
+#define GMACB_CLK_SIZE 3
+#define GMACB_DBW_OFFSET 21
+#define GMACB_DBW_SIZE 2
+
+ /* Bitfields in NSR */
+#define GMACB_NSR_LINK_OFFSET 0
+#define GMACB_NSR_LINK_SIZE 1
+#define GMACB_MDIO_OFFSET 1
+#define GMACB_MDIO_SIZE 1
+#define GMACB_IDLE_OFFSET 2
+#define GMACB_IDLE_SIZE 1
+
+ /* Bitfields in TSR */
+#define GMACB_UBR_OFFSET 0
+#define GMACB_UBR_SIZE 1
+#define GMACB_COL_OFFSET 1
+#define GMACB_COL_SIZE 1
+#define GMACB_TSR_RLE_OFFSET 2
+#define GMACB_TSR_RLE_SIZE 1
+#define GMACB_TGO_OFFSET 3
+#define GMACB_TGO_SIZE 1
+#define GMACB_BEX_OFFSET 4
+#define GMACB_BEX_SIZE 1
+#define GMACB_COMP_OFFSET 5
+#define GMACB_COMP_SIZE 1
+#define GMACB_UND_OFFSET 6
+#define GMACB_UND_SIZE 1
+
+ /* Bitfields in RSR */
+#define GMACB_BNA_OFFSET 0
+#define GMACB_BNA_SIZE 1
+#define GMACB_REC_OFFSET 1
+#define GMACB_REC_SIZE 1
+#define GMACB_OVR_OFFSET 2
+#define GMACB_OVR_SIZE 1
+
+ /* Bitfields in ISR/IER/IDR/IMR */
+#define GMACB_MFD_OFFSET 0
+#define GMACB_MFD_SIZE 1
+#define GMACB_RCOMP_OFFSET 1
+#define GMACB_RCOMP_SIZE 1
+#define GMACB_RXUBR_OFFSET 2
+#define GMACB_RXUBR_SIZE 1
+#define GMACB_TXUBR_OFFSET 3
+#define GMACB_TXUBR_SIZE 1
+#define GMACB_ISR_TUND_OFFSET 4
+#define GMACB_ISR_TUND_SIZE 1
+#define GMACB_ISR_RLE_OFFSET 5
+#define GMACB_ISR_RLE_SIZE 1
+#define GMACB_TXERR_OFFSET 6
+#define GMACB_TXERR_SIZE 1
+#define GMACB_TCOMP_OFFSET 7
+#define GMACB_TCOMP_SIZE 1
+#define GMACB_ISR_LINK_OFFSET 9
+#define GMACB_ISR_LINK_SIZE 1
+#define GMACB_ISR_ROVR_OFFSET 10
+#define GMACB_ISR_ROVR_SIZE 1
+#define GMACB_HRESP_OFFSET 11
+#define GMACB_HRESP_SIZE 1
+#define GMACB_PFR_OFFSET 12
+#define GMACB_PFR_SIZE 1
+#define GMACB_PTZ_OFFSET 13
+#define GMACB_PTZ_SIZE 1
+
+ /* Bitfields in MAN */
+#define GMACB_DATA_OFFSET 0
+#define GMACB_DATA_SIZE 16
+#define GMACB_WTN_OFFSET 16
+#define GMACB_WTN_SIZE 2
+#define GMACB_REGA_OFFSET 18
+#define GMACB_REGA_SIZE 5
+#define GMACB_PHYA_OFFSET 23
+#define GMACB_PHYA_SIZE 5
+#define GMACB_OP_OFFSET 28
+#define GMACB_OP_SIZE 2
+#define GMACB_CLTTO_OFFSET 30
+#define GMACB_CLTTO_SIZE 1
+#define GMACB_WZO_OFFSET 31
+#define GMACB_WZO_SIZE 1
+
+ /* Bitfields in US */
+#define GMACB_GMII_OFFSET 0
+#define GMACB_GMII_SIZE 1
+
+ /* Bitfields in USRIO (AT91) */
+#define GMACB_RGMII_OFFSET 0
+#define GMACB_RGMII_SIZE 1
+
+ /* Bitfields in WOL */
+#define GMACB_IP_OFFSET 0
+#define GMACB_IP_SIZE 16
+#define GMACB_MAG_OFFSET 16
+#define GMACB_MAG_SIZE 1
+#define GMACB_ARP_OFFSET 17
+#define GMACB_ARP_SIZE 1
+#define GMACB_SA1_OFFSET 18
+#define GMACB_SA1_SIZE 1
+#define GMACB_WOL_MTI_OFFSET 19
+#define GMACB_WOL_MTI_SIZE 1
+
+ /* Constants for CLK */
+#define GMACB_CLK_DIV8 0
+#define GMACB_CLK_DIV16 1
+#define GMACB_CLK_DIV32 2
+#define GMACB_CLK_DIV48 3
+#define GMACB_CLK_DIV64 4
+
+/* Constants for MAN register */
+#define GMACB_MAN_SOF 1
+#define GMACB_MAN_WRITE 1
+#define GMACB_MAN_READ 2
+#define GMACB_MAN_CODE 2
+
+/* Bit manipulation macros */
+#define MACB_BIT(name) \
+ (1 << GMACB_##name##_OFFSET)
+#define MACB_BF(name,value) \
+ (((value) & ((1 << GMACB_##name##_SIZE) - 1)) \
+ << GMACB_##name##_OFFSET)
+#define MACB_BFEXT(name,value)\
+ (((value) >> GMACB_##name##_OFFSET) \
+ & ((1 << GMACB_##name##_SIZE) - 1))
+#define MACB_BFINS(name,value,old) \
+ (((old) & ~(((1 << GMACB_##name##_SIZE) - 1) \
+ << GMACB_##name##_OFFSET)) \
+ | MACB_BF(name,value))
+
+/* Register access macros */
+#define macb_readl(port,reg) \
+ readl((port)->regs + GMACB_##reg)
+#define macb_writel(port,reg,value) \
+ writel((value), (port)->regs + GMACB_##reg)
+
+#endif /* __DRIVERS_MACB_H__ */
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0e1ced71c5..f05a566521 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -471,7 +471,8 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \
defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \
- defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5)
+ defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5) || \
+ defined(CONFIG_AT91SAMA5)
macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
#else
macb_writel(macb, USRIO, 0);
@@ -480,7 +481,8 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \
defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \
- defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5)
+ defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5) || \
+ defined(CONFIG_AT91SAMA5)
macb_writel(macb, USRIO, MACB_BIT(CLKEN));
#else
macb_writel(macb, USRIO, MACB_BIT(MII));
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 9532dd9ef6..48de03d36b 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -41,7 +41,8 @@ int usb_cpu_init(void)
writel(get_pllb_init(), &pmc->pllbr);
while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB)
;
-#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45)
+#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
+ || defined(CONFIG_AT91SAMA5)
/* Enable UPLL */
writel(readl(&pmc->uckr) | AT91_PMC_UPLLEN | AT91_PMC_BIASEN,
&pmc->uckr);
@@ -52,8 +53,13 @@ int usb_cpu_init(void)
writel(AT91_PMC_USBS_USB_UPLL | AT91_PMC_USBDIV_10, &pmc->usb);
#endif
+#if defined(CONFIG_AT91SAMA5)
/* Enable USB host clock. */
+ writel(1 << (ATMEL_ID_UHP - 32), &pmc->pcer1);
+#else
writel(1 << ATMEL_ID_UHP, &pmc->pcer);
+#endif
+
#ifdef CONFIG_AT91SAM9261
writel(ATMEL_PMC_UHP | AT91_PMC_HCK0, &pmc->scer);
#else
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index c02ffd8036..860cbcc4d2 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -28,6 +28,9 @@
#include <asm/arch/clk.h>
#include <lcd.h>
#include <atmel_lcdc.h>
+#if defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAMA5)
+#include <atmel_9x5_lcdc.h>
+#endif
int lcd_line_length;
int lcd_color_fg;
@@ -66,10 +69,187 @@ void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
#endif
}
+#if defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAMA5)
+void lcd_9x5_ctrl_init(void *lcdbase)
+{
+ unsigned long value;
+ lcd_dma_desc *desc;
+
+ if (!has_lcdc())
+ return; /* No lcdc */
+
+ /* Disable DISP signal */
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_DISPDIS);
+ while ((lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDSR)
+ & LCDC_LCDSR_DISPSTS))
+ udelay(1);
+ /* Disable synchronization */
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_SYNCDIS);
+ while ((lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDSR)
+ & LCDC_LCDSR_LCDSTS))
+ udelay(1);
+ /* Disable pixel clock */
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_CLKDIS);
+ while ((lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDSR)
+ & LCDC_LCDSR_CLKSTS))
+ udelay(1);
+ /* Disable PWM */
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_PWMDIS);
+ while ((lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDSR)
+ & LCDC_LCDSR_PWMSTS))
+ udelay(1);
+
+ /* Set pixel clock */
+ value = get_lcdc_clk_rate(0) / panel_info.vl_clk;
+ if (get_lcdc_clk_rate(0) % panel_info.vl_clk)
+ value++;
+
+ if (value < 1) {
+ /* Using system clock as pixel clock */
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCFG0,
+ LCDC_LCDCFG0_CLKDIV(0)
+ | LCDC_LCDCFG0_CGDISHCR
+ | LCDC_LCDCFG0_CGDISHEO
+ | LCDC_LCDCFG0_CGDISOVR1
+ | LCDC_LCDCFG0_CGDISBASE
+ | LCDC_LCDCFG0_CLKPOL
+ | LCDC_LCDCFG0_CLKSEL);
+
+ } else {
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCFG0,
+ LCDC_LCDCFG0_CLKDIV(value - 2)
+ | LCDC_LCDCFG0_CGDISHCR
+ | LCDC_LCDCFG0_CGDISHEO
+ | LCDC_LCDCFG0_CGDISOVR1
+ | LCDC_LCDCFG0_CGDISBASE
+ | LCDC_LCDCFG0_CLKPOL);
+ }
+
+ /* Initialize control register 5 */
+ value = 0;
+
+ value |= LCDC_LCDCFG5_HSPOL;
+ value |= LCDC_LCDCFG5_VSPOL;
+
+#ifndef LCD_OUTPUT_BPP
+ /* Output is 24bpp */
+ value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
+#else
+ switch (LCD_OUTPUT_BPP) {
+ case 12:
+ value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
+ break;
+ case 16:
+ value |= LCDC_LCDCFG5_MODE_OUTPUT_16BPP;
+ break;
+ case 18:
+ value |= LCDC_LCDCFG5_MODE_OUTPUT_18BPP;
+ break;
+ case 24:
+ value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
+ break;
+ default:
+ BUG();
+ break;
+ }
+#endif
+
+ value |= LCDC_LCDCFG5_GUARDTIME(ATMEL_LCDC_GUARD_TIME);
+ value |= (LCDC_LCDCFG5_DISPDLY | LCDC_LCDCFG5_VSPDLYS);
+
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCFG5, value);
+
+ /* Vertical & Horizontal Timing */
+ value = LCDC_LCDCFG1_VSPW(panel_info.vl_vsync_len - 1);
+ value |= LCDC_LCDCFG1_HSPW(panel_info.vl_hsync_len - 1);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCFG1, value);
+
+ value = LCDC_LCDCFG2_VBPW(panel_info.vl_lower_margin);
+ value |= LCDC_LCDCFG2_VFPW(panel_info.vl_upper_margin - 1);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCFG2, value);
+
+ value = LCDC_LCDCFG3_HBPW(panel_info.vl_right_margin - 1);
+ value |= LCDC_LCDCFG3_HFPW(panel_info.vl_left_margin - 1);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCFG3, value);
+
+ /* Display size */
+ value = LCDC_LCDCFG4_RPF(panel_info.vl_row - 1);
+ value |= LCDC_LCDCFG4_PPL(panel_info.vl_col - 1);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCFG4, value);
+
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASECFG0,
+ LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO);
+
+ switch (NBITS(panel_info.vl_bpix)) {
+ case 16:
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASECFG1,
+ LCDC_BASECFG1_RGBMODE_16BPP_RGB_565);
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASECFG2,
+ LCDC_BASECFG2_XSTRIDE(0));
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASECFG3, 0);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASECFG4, LCDC_BASECFG4_DMA);
+
+ /* Disable all interrupts */
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDIDR, ~0UL);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASEIDR, ~0UL);
+
+ /* Setup the DMA descriptor, this descriptor will loop to itself */
+ desc = (lcd_dma_desc *)(lcdbase - 16);
+
+ desc->address = (u32)lcdbase;
+ /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
+ desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN
+ | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH;
+ desc->next = (u32)desc;
+
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASEADDR, desc->address);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASECTRL, desc->control);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASENEXT, desc->next);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_BASECHER, LCDC_BASECHER_CHEN
+ | LCDC_BASECHER_UPDATEEN);
+
+ /* Enable LCD */
+ value = lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDEN);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDEN, value
+ | LCDC_LCDEN_CLKEN);
+ while (!(lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDSR)
+ & LCDC_LCDSR_CLKSTS))
+ udelay(1);
+ value = lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDEN);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDEN, value
+ | LCDC_LCDEN_SYNCEN);
+ while (!(lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDSR)
+ & LCDC_LCDSR_LCDSTS))
+ udelay(1);
+ value = lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDEN);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDEN, value
+ | LCDC_LCDEN_DISPEN);
+ while (!(lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDSR)
+ & LCDC_LCDSR_DISPSTS))
+ udelay(1);
+ value = lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDEN);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDEN, value
+ | LCDC_LCDEN_PWMEN);
+ while (!(lcdc_readl(panel_info.mmio, ATMEL_LCDC_LCDSR)
+ & LCDC_LCDSR_PWMSTS))
+ udelay(1);
+}
+#endif
+
void lcd_ctrl_init(void *lcdbase)
{
unsigned long value;
+#if defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAMA5)
+ return lcd_9x5_ctrl_init(lcdbase);
+#endif
+
/* Turn off the LCD controller and the DMA controller */
lcdc_writel(panel_info.mmio, ATMEL_LCDC_PWRCON,
ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET);
@@ -96,7 +276,8 @@ void lcd_ctrl_init(void *lcdbase)
value = (value / 2) - 1;
if (!value) {
- lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCON1,
+ ATMEL_LCDC_BYPASS);
} else
lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCON1,
value << ATMEL_LCDC_CLKVAL_OFFSET);
@@ -143,18 +324,19 @@ void lcd_ctrl_init(void *lcdbase)
/* Set contrast */
value = ATMEL_LCDC_PS_DIV8 |
+ ATMEL_LCDC_POL_POSITIVE |
ATMEL_LCDC_ENA_PWMENABLE;
- if (!panel_info.vl_cont_pol_low)
- value |= ATMEL_LCDC_POL_POSITIVE;
lcdc_writel(panel_info.mmio, ATMEL_LCDC_CONTRAST_CTR, value);
- lcdc_writel(panel_info.mmio, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
+ lcdc_writel(panel_info.mmio, ATMEL_LCDC_CONTRAST_VAL,
+ ATMEL_LCDC_CVAL_DEFAULT);
/* Set framebuffer DMA base address and pixel offset */
lcdc_writel(panel_info.mmio, ATMEL_LCDC_DMABADDR1, (u_long)lcdbase);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_DMACON, ATMEL_LCDC_DMAEN);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_PWRCON,
- (ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+ (ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET)
+ | ATMEL_LCDC_PWR);
}
ulong calc_fbsize(void)
diff --git a/include/atmel_9x5_lcdc.h b/include/atmel_9x5_lcdc.h
new file mode 100644
index 0000000000..6bd8cfeebe
--- /dev/null
+++ b/include/atmel_9x5_lcdc.h
@@ -0,0 +1,223 @@
+/*
+ * Header file for AT91/AT32 SAM9X5 LCD Controller
+ *
+ * Data structure and register user interface
+ *
+ * Copyright (C) 2010 Atmel Corporation
+ *
+ * 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 __ATMEL_9X5_LCDC_H__
+#define __ATMEL_9X5_LCDC_H__
+
+/* Atmel 9x5 lcdc hardware registers */
+#define ATMEL_LCDC_LCDCFG0 0x0000
+#define LCDC_LCDCFG0_CLKPOL (0x1 << 0)
+#define LCDC_LCDCFG0_CLKSEL (0x1 << 2)
+#define LCDC_LCDCFG0_CLKPWMSEL (0x1 << 3)
+#define LCDC_LCDCFG0_CGDISBASE (0x1 << 8)
+#define LCDC_LCDCFG0_CGDISOVR1 (0x1 << 9)
+#define LCDC_LCDCFG0_CGDISHEO (0x1 << 11)
+#define LCDC_LCDCFG0_CGDISHCR (0x1 << 12)
+#define LCDC_LCDCFG0_CLKDIV_Pos 16
+#define LCDC_LCDCFG0_CLKDIV_Msk (0xff << LCDC_LCDCFG0_CLKDIV_Pos)
+#define LCDC_LCDCFG0_CLKDIV(value) \
+ ((LCDC_LCDCFG0_CLKDIV_Msk & ((value) << LCDC_LCDCFG0_CLKDIV_Pos)))
+
+#define ATMEL_LCDC_LCDCFG1 0x0004
+#define LCDC_LCDCFG1_HSPW_Pos 0
+#define LCDC_LCDCFG1_HSPW_Msk (0x3f << LCDC_LCDCFG1_HSPW_Pos)
+#define LCDC_LCDCFG1_HSPW(value) \
+ ((LCDC_LCDCFG1_HSPW_Msk & ((value) << LCDC_LCDCFG1_HSPW_Pos)))
+#define LCDC_LCDCFG1_VSPW_Pos 16
+#define LCDC_LCDCFG1_VSPW_Msk (0x3f << LCDC_LCDCFG1_VSPW_Pos)
+#define LCDC_LCDCFG1_VSPW(value) \
+ ((LCDC_LCDCFG1_VSPW_Msk & ((value) << LCDC_LCDCFG1_VSPW_Pos)))
+
+#define ATMEL_LCDC_LCDCFG2 0x0008
+#define LCDC_LCDCFG2_VFPW_Pos 0
+#define LCDC_LCDCFG2_VFPW_Msk (0x3f << LCDC_LCDCFG2_VFPW_Pos)
+#define LCDC_LCDCFG2_VFPW(value) \
+ ((LCDC_LCDCFG2_VFPW_Msk & ((value) << LCDC_LCDCFG2_VFPW_Pos)))
+#define LCDC_LCDCFG2_VBPW_Pos 16
+#define LCDC_LCDCFG2_VBPW_Msk (0x3f << LCDC_LCDCFG2_VBPW_Pos)
+#define LCDC_LCDCFG2_VBPW(value) \
+ ((LCDC_LCDCFG2_VBPW_Msk & ((value) << LCDC_LCDCFG2_VBPW_Pos)))
+
+#define ATMEL_LCDC_LCDCFG3 0x000C
+#define LCDC_LCDCFG3_HFPW_Pos 0
+#define LCDC_LCDCFG3_HFPW_Msk (0xff << LCDC_LCDCFG3_HFPW_Pos)
+#define LCDC_LCDCFG3_HFPW(value) \
+ ((LCDC_LCDCFG3_HFPW_Msk & ((value) << LCDC_LCDCFG3_HFPW_Pos)))
+#define LCDC_LCDCFG3_HBPW_Pos 16
+#define LCDC_LCDCFG3_HBPW_Msk (0xff << LCDC_LCDCFG3_HBPW_Pos)
+#define LCDC_LCDCFG3_HBPW(value) \
+ ((LCDC_LCDCFG3_HBPW_Msk & ((value) << LCDC_LCDCFG3_HBPW_Pos)))
+
+#define ATMEL_LCDC_LCDCFG4 0x0010
+#define LCDC_LCDCFG4_PPL_Pos 0
+#define LCDC_LCDCFG4_PPL_Msk (0x7ff << LCDC_LCDCFG4_PPL_Pos)
+#define LCDC_LCDCFG4_PPL(value) \
+ ((LCDC_LCDCFG4_PPL_Msk & ((value) << LCDC_LCDCFG4_PPL_Pos)))
+#define LCDC_LCDCFG4_RPF_Pos 16
+#define LCDC_LCDCFG4_RPF_Msk (0x7ff << LCDC_LCDCFG4_RPF_Pos)
+#define LCDC_LCDCFG4_RPF(value) \
+ ((LCDC_LCDCFG4_RPF_Msk & ((value) << LCDC_LCDCFG4_RPF_Pos)))
+
+#define ATMEL_LCDC_LCDCFG5 0x0014
+#define LCDC_LCDCFG5_HSPOL (0x1 << 0)
+#define LCDC_LCDCFG5_VSPOL (0x1 << 1)
+#define LCDC_LCDCFG5_VSPDLYS (0x1 << 2)
+#define LCDC_LCDCFG5_VSPDLYE (0x1 << 3)
+#define LCDC_LCDCFG5_DISPPOL (0x1 << 4)
+#define LCDC_LCDCFG5_SERIAL (0x1 << 5)
+#define LCDC_LCDCFG5_DITHER (0x1 << 6)
+#define LCDC_LCDCFG5_DISPDLY (0x1 << 7)
+#define LCDC_LCDCFG5_MODE_Pos 8
+#define LCDC_LCDCFG5_MODE_Msk (0x3 << LCDC_LCDCFG5_MODE_Pos)
+#define LCDC_LCDCFG5_MODE_OUTPUT_12BPP (0x0 << 8)
+#define LCDC_LCDCFG5_MODE_OUTPUT_16BPP (0x1 << 8)
+#define LCDC_LCDCFG5_MODE_OUTPUT_18BPP (0x2 << 8)
+#define LCDC_LCDCFG5_MODE_OUTPUT_24BPP (0x3 << 8)
+#define LCDC_LCDCFG5_VSPSU (0x1 << 12)
+#define LCDC_LCDCFG5_VSPHO (0x1 << 13)
+#define LCDC_LCDCFG5_GUARDTIME_Pos 16
+#define LCDC_LCDCFG5_GUARDTIME_Msk (0x1f << LCDC_LCDCFG5_GUARDTIME_Pos)
+#define LCDC_LCDCFG5_GUARDTIME(value) \
+ ((LCDC_LCDCFG5_GUARDTIME_Msk & ((value) << LCDC_LCDCFG5_GUARDTIME_Pos)))
+
+#define ATMEL_LCDC_LCDCFG6 0x0018
+#define LCDC_LCDCFG6_PWMPS_Pos 0
+#define LCDC_LCDCFG6_PWMPS_Msk (0x7 << LCDC_LCDCFG6_PWMPS_Pos)
+#define LCDC_LCDCFG6_PWMPS(value) \
+ ((LCDC_LCDCFG6_PWMPS_Msk & ((value) << LCDC_LCDCFG6_PWMPS_Pos)))
+#define LCDC_LCDCFG6_PWMPOL (0x1 << 4)
+#define LCDC_LCDCFG6_PWMCVAL_Pos 8
+#define LCDC_LCDCFG6_PWMCVAL_Msk (0xff << LCDC_LCDCFG6_PWMCVAL_Pos)
+#define LCDC_LCDCFG6_PWMCVAL(value) \
+ ((LCDC_LCDCFG6_PWMCVAL_Msk & ((value) << LCDC_LCDCFG6_PWMCVAL_Pos)))
+
+#define ATMEL_LCDC_LCDEN 0x0020
+#define LCDC_LCDEN_CLKEN (0x1 << 0)
+#define LCDC_LCDEN_SYNCEN (0x1 << 1)
+#define LCDC_LCDEN_DISPEN (0x1 << 2)
+#define LCDC_LCDEN_PWMEN (0x1 << 3)
+
+#define ATMEL_LCDC_LCDDIS 0x0024
+#define LCDC_LCDDIS_CLKDIS (0x1 << 0)
+#define LCDC_LCDDIS_SYNCDIS (0x1 << 1)
+#define LCDC_LCDDIS_DISPDIS (0x1 << 2)
+#define LCDC_LCDDIS_PWMDIS (0x1 << 3)
+#define LCDC_LCDDIS_CLKRST (0x1 << 8)
+#define LCDC_LCDDIS_SYNCRST (0x1 << 9)
+#define LCDC_LCDDIS_DISPRST (0x1 << 10)
+#define LCDC_LCDDIS_PWMRST (0x1 << 11)
+
+#define ATMEL_LCDC_LCDSR 0x0028
+
+#define LCDC_LCDSR_CLKSTS (0x1 << 0)
+#define LCDC_LCDSR_LCDSTS (0x1 << 1)
+#define LCDC_LCDSR_DISPSTS (0x1 << 2)
+#define LCDC_LCDSR_PWMSTS (0x1 << 3)
+#define LCDC_LCDSR_SIPSTS (0x1 << 4)
+
+#define ATMEL_LCDC_LCDIDR 0x0030
+#define LCDC_LCDIDR_SOFID (0x1 << 0)
+#define LCDC_LCDIDR_DISID (0x1 << 1)
+#define LCDC_LCDIDR_DISPID (0x1 << 2)
+#define LCDC_LCDIDR_FIFOERRID (0x1 << 4)
+#define LCDC_LCDIDR_BASEID (0x1 << 8)
+#define LCDC_LCDIDR_OVR1ID (0x1 << 9)
+#define LCDC_LCDIDR_HEOID (0x1 << 11)
+#define LCDC_LCDIDR_HCRID (0x1 << 12)
+
+#define ATMEL_LCDC_BASECHER 0x0040
+#define LCDC_BASECHER_CHEN (0x1 << 0)
+#define LCDC_BASECHER_UPDATEEN (0x1 << 1)
+#define LCDC_BASECHER_A2QEN (0x1 << 2)
+
+#define ATMEL_LCDC_BASEIDR 0x0050
+#define LCDC_BASEIDR_DMA (0x1 << 2)
+#define LCDC_BASEIDR_DSCR (0x1 << 3)
+#define LCDC_BASEIDR_ADD (0x1 << 4)
+#define LCDC_BASEIDR_DONE (0x1 << 5)
+#define LCDC_BASEIDR_OVR (0x1 << 6)
+
+#define ATMEL_LCDC_BASEADDR 0x0060
+
+#define ATMEL_LCDC_BASECTRL 0x0064
+#define LCDC_BASECTRL_DFETCH (0x1 << 0)
+#define LCDC_BASECTRL_LFETCH (0x1 << 1)
+#define LCDC_BASECTRL_DMAIEN (0x1 << 2)
+#define LCDC_BASECTRL_DSCRIEN (0x1 << 3)
+#define LCDC_BASECTRL_ADDIEN (0x1 << 4)
+#define LCDC_BASECTRL_DONEIEN (0x1 << 5)
+
+#define ATMEL_LCDC_BASENEXT 0x0068
+#define ATMEL_LCDC_BASECFG0 0x006C
+#define LCDC_BASECFG0_BLEN_Pos 4
+#define LCDC_BASECFG0_BLEN_AHB_SINGLE (0x0 << 4)
+#define LCDC_BASECFG0_BLEN_AHB_INCR4 (0x1 << 4)
+#define LCDC_BASECFG0_BLEN_AHB_INCR8 (0x2 << 4)
+#define LCDC_BASECFG0_BLEN_AHB_INCR16 (0x3 << 4)
+#define LCDC_BASECFG0_DLBO (0x1 << 8)
+
+#define ATMEL_LCDC_BASECFG1 0x0070
+#define LCDC_BASECFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
+#define LCDC_BASECFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
+#define LCDC_BASECFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
+#define LCDC_BASECFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
+#define LCDC_BASECFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
+#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
+#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
+#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
+#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
+#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
+#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
+#define LCDC_BASECFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
+#define LCDC_BASECFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
+#define LCDC_BASECFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
+
+#define ATMEL_LCDC_BASECFG2 0x0074
+#define LCDC_BASECFG2_XSTRIDE_Pos 0
+#define LCDC_BASECFG2_XSTRIDE_Msk (0xffffffff << LCDC_BASECFG2_XSTRIDE_Pos)
+#define LCDC_BASECFG2_XSTRIDE(value) \
+ ((LCDC_BASECFG2_XSTRIDE_Msk & ((value) << LCDC_BASECFG2_XSTRIDE_Pos)))
+
+#define ATMEL_LCDC_BASECFG3 0x0078
+#define LCDC_BASECFG3_BDEF_Pos 0
+#define LCDC_BASECFG3_BDEF_Msk (0xff << LCDC_BASECFG3_BDEF_Pos)
+#define LCDC_BASECFG3_BDEF(value) \
+ ((LCDC_BASECFG3_BDEF_Msk & ((value) << LCDC_BASECFG3_BDEF_Pos)))
+#define LCDC_BASECFG3_GDEF_Pos 8
+#define LCDC_BASECFG3_GDEF_Msk (0xff << LCDC_BASECFG3_GDEF_Pos)
+#define LCDC_BASECFG3_GDEF(value) \
+ ((LCDC_BASECFG3_GDEF_Msk & ((value) << LCDC_BASECFG3_GDEF_Pos)))
+#define LCDC_BASECFG3_RDEF_Pos 16
+#define LCDC_BASECFG3_RDEF_Msk (0xff << LCDC_BASECFG3_RDEF_Pos)
+#define LCDC_BASECFG3_RDEF(value) \
+ ((LCDC_BASECFG3_RDEF_Msk & ((value) << LCDC_BASECFG3_RDEF_Pos)))
+
+#define ATMEL_LCDC_BASECFG4 0x007C
+#define LCDC_BASECFG4_DMA (0x1 << 8)
+#define LCDC_BASECFG4_REP (0x1 << 9)
+
+typedef struct {
+ u32 address;
+ u32 control;
+ u32 next;
+} lcd_dma_desc;
+
+#endif /* __ATMEL_9X5_LCDC_H__ */
diff --git a/include/atmel_mci.h b/include/atmel_mci.h
index 3dd5d67be9..4455b32fc7 100644
--- a/include/atmel_mci.h
+++ b/include/atmel_mci.h
@@ -38,7 +38,7 @@ typedef struct atmel_mci {
u32 sdcr; /* 0x0c */
u32 argr; /* 0x10 */
u32 cmdr; /* 0x14 */
- u32 _18; /* 0x18 */
+ u32 blkr; /* 0x18 */
u32 _1c; /* 0x1c */
u32 rspr; /* 0x20 */
u32 rspr1; /* 0x24 */
diff --git a/include/configs/at91sama5ek.h b/include/configs/at91sama5ek.h
new file mode 100644
index 0000000000..842bd1e2f9
--- /dev/null
+++ b/include/configs/at91sama5ek.h
@@ -0,0 +1,283 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stelian Pop <stelian@popies.net>
+ * Lead Tech Design <www.leadtechdesign.com>
+ *
+ * Configuation settings for the AT91SAMA5EK board.
+ *
+ * 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 __CONFIG_H
+#define __CONFIG_H
+
+#include <asm/hardware.h>
+
+#define CONFIG_AT91_LEGACY
+
+/* ARM asynchronous clock */
+#define CONFIG_SYS_AT91_SLOW_CLOCK 32768
+#define CONFIG_SYS_AT91_MAIN_CLOCK 12000000 /* from 12 MHz crystal */
+#define CONFIG_SYS_HZ 1000
+
+#define CONFIG_AT91SAMA5EK
+#define CONFIG_AT91FAMILY
+#define CONFIG_ARCH_CPU_INIT
+#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
+
+#undef CONFIG_CMDLINE_TAG /* enable passing of ATAGs */
+#undef CONFIG_SETUP_MEMORY_TAGS
+#undef CONFIG_INITRD_TAG
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_DISPLAY_CPUINFO
+
+#define CONFIG_OF_LIBFDT /* Device Tree support */
+
+/* general purpose I/O */
+#define CONFIG_ATMEL_LEGACY /* required until (g)pio is fixed */
+#define CONFIG_AT91_GPIO
+#define CONFIG_AT91_GPIO_PULLUP 1 /* keep pullups on peripheral pins */
+
+/* serial console */
+#define CONFIG_ATMEL_USART
+#undef CONFIG_USART1
+#ifdef CONFIG_USART1
+#define CONFIG_USART_BASE ATMEL_BASE_USART1
+#define CONFIG_USART_ID ATMEL_ID_USART1
+#else
+#define CONFIG_USART_BASE ATMEL_BASE_DBGU
+#define CONFIG_USART_ID ATMEL_ID_DBGU
+#endif
+
+/*
+ * This needs to be defined for the OHCI code to work but it is defined as
+ * ATMEL_ID_UHPHS in the CPU specific header files.
+ */
+#define ATMEL_ID_UHP ATMEL_ID_UHPHS
+
+/*
+ * Specify the clock enable bit in the PMC_SCER register.
+ */
+ #define ATMEL_PMC_UHP AT91SAM926x_PMC_UHP
+
+/* LCD */
+#define CONFIG_LCD
+#define LCD_BPP LCD_COLOR16
+#define LCD_OUTPUT_BPP 24
+#define CONFIG_LCD_LOGO
+#undef LCD_TEST_PATTERN
+#define CONFIG_LCD_INFO
+#define CONFIG_LCD_INFO_BELOW_LOGO
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_ATMEL_LCD
+#define CONFIG_ATMEL_LCD_RGB565
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+
+/* board specific(not enough SRAM) */
+#define CONFIG_AT91SAMA5_LCD_BASE 0x23E00000
+
+/* LED */
+#if 0
+#define CONFIG_AT91_LED
+#define CONFIG_RED_LED AT91_PIN_PE24 /* this is the user1 led */
+#define CONFIG_GREEN_LED AT91_PIN_PE25 /* this is the user2 led */
+#endif
+
+#define CONFIG_BOOTDELAY 3
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+#undef CONFIG_CMD_BDI
+#undef CONFIG_CMD_FPGA
+#undef CONFIG_CMD_IMI
+#undef CONFIG_CMD_IMLS
+#undef CONFIG_CMD_AUTOSCRIPT
+#undef CONFIG_CMD_LOADS
+
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+
+/* SDRAM */
+#define CONFIG_NR_DRAM_BANKS 1
+#define CONFIG_SYS_SDRAM_BASE ATMEL_BASE_DDRCS
+#define CONFIG_SYS_SDRAM_SIZE 0x20000000
+
+#define CONFIG_SYS_INIT_SP_ADDR \
+ (CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+
+/* SerialFlash */
+#define CONFIG_CMD_SF
+
+#ifdef CONFIG_CMD_SF
+#define CONFIG_ATMEL_SPI
+#define CONFIG_SPI_FLASH 1
+#define CONFIG_SPI_FLASH_ATMEL 1
+#endif
+
+/* No NOR flash */
+#define CONFIG_SYS_NO_FLASH
+
+/* NAND flash */
+#define CONFIG_CMD_NAND
+
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_NAND_MAX_CHIPS 1
+#define CONFIG_NAND_ATMEL
+#define CONFIG_SYS_MAX_NAND_DEVICE 1
+#define CONFIG_SYS_NAND_BASE ATMEL_BASE_CS3
+#define CONFIG_SYS_NAND_DBW_8
+/* our ALE is AD21 */
+#define CONFIG_SYS_NAND_MASK_ALE (1 << 21)
+/* our CLE is AD22 */
+#define CONFIG_SYS_NAND_MASK_CLE (1 << 22)
+#define CONFIG_SYS_NAND_ONFI_DETECTION 1
+/* 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 ATMEL_PMECC_INDEX_OFFSET_512
+
+#define CONFIG_CMD_NAND_TRIMFFS
+#endif
+
+/* Ethernet Hardware */
+#define CONFIG_MACB
+#define CONFIG_RMII
+#define CONFIG_GMACB
+#define CONFIG_RGMII
+#define CONFIG_NET_MULTI
+#define CONFIG_NET_RETRY_COUNT 20
+#define CONFIG_RESET_PHY_R
+#define CONFIG_MACB_SEARCH_PHY
+
+/* MMC */
+#define CONFIG_CMD_MMC
+
+#ifdef CONFIG_CMD_MMC
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_GENERIC_ATMEL_MCI
+#undef CONFIG_ATMEL_MCI_8BIT
+#define ATMEL_BASE_MMCI ATMEL_BASE_MCI0
+#endif
+
+/* USB */
+#define CONFIG_CMD_USB
+
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_ATMEL
+#define CONFIG_USB_OHCI_NEW
+#define CONFIG_DOS_PARTITION
+#define CONFIG_SYS_USB_OHCI_CPU_INIT
+#define CONFIG_SYS_USB_OHCI_REGS_BASE ATMEL_BASE_OHCI
+#define CONFIG_SYS_USB_OHCI_SLOT_NAME "at91sama5"
+#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 3
+#define CONFIG_USB_STORAGE
+#endif
+
+#if defined(CONFIG_CMD_USB) || defined (CONFIG_CMD_MMC)
+#define CONFIG_CMD_FAT
+#endif
+
+#define CONFIG_SYS_LOAD_ADDR 0x22000000 /* load address */
+
+#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE
+#define CONFIG_SYS_MEMTEST_END 0x23e00000
+
+#ifdef CONFIG_SYS_USE_SERIALFLASH
+/* bootstrap + u-boot + env + linux in serial flash */
+#define CONFIG_ENV_IS_IN_SPI_FLASH 1
+#define CONFIG_SYS_MONITOR_BASE (0x10000000 + 0x8400)
+#define CONFIG_ENV_OFFSET 0x5000
+#define CONFIG_ENV_ADDR (0x10000000 + CONFIG_ENV_OFFSET)
+#define CONFIG_ENV_SIZE 0x3000
+#define CONFIG_ENV_SECT_SIZE 0x1000
+#define CONFIG_BOOTCOMMAND "sf probe 0; " \
+ "sf read 0x22000000 0x42000 0x300000; " \
+ "bootm 0x22000000"
+#elif CONFIG_SYS_USE_NANDFLASH
+/* bootstrap + u-boot + env in nandflash */
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_OFFSET 0xc0000
+#define CONFIG_ENV_OFFSET_REDUND 0x100000
+#define CONFIG_ENV_SIZE 0x20000
+#define CONFIG_BOOTCOMMAND "nand read 0x21000000 0x180000 0x80000;" \
+ "nand read 0x22000000 0x200000 0x600000;" \
+ "bootm 0x22000000 - 0x21000000"
+#elif CONFIG_SYS_USE_MMC
+/* bootstrap + u-boot + env in sd card */
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_OFFSET 0x2000
+#define CONFIG_ENV_OFFSET_REDUND 0x4000
+#define CONFIG_ENV_SIZE 0x2000
+#define CONFIG_BOOTCOMMAND "mmcinfo;fatload mmc 0:1 0x21000000 dtb;" \
+ "fatload mmc 0:1 0x22000000 uImage;" \
+ "bootm 0x22000000 - 0x21000000"
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#else
+#define CONIG_ENV_IS_NOWHERE
+#endif
+
+#ifdef CONFIG_SYS_USE_MMC
+#define CONFIG_BOOTARGS \
+ "console=ttyS0,115200 earlyprintk " \
+ "root=/dev/mmcblk0p2 " \
+ "rw rootfstype=ext2 rootdelay=2"
+#else
+#define CONFIG_BOOTARGS \
+ "console=ttyS0,115200 earlyprintk " \
+ "mtdparts=atmel_nand:8M(bootstrap/uboot/kernel)ro,-(rootfs)" \
+ "rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"
+#endif
+
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE {115200 , 19200, 38400, 57600, 9600 }
+
+#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
+#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_SYS_MALLOC_LEN (1024 * 1024)
+
+#ifdef CONFIG_USE_IRQ
+#error CONFIG_USE_IRQ not supported
+#endif
+
+#endif
diff --git a/include/netdev.h b/include/netdev.h
index b8d303d089..fff84bee81 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -73,6 +73,7 @@ int inca_switch_initialize(bd_t *bis);
int ks8695_eth_initialize(void);
int lan91c96_initialize(u8 dev_num, int base_addr);
int macb_eth_initialize(int id, void *regs, unsigned int phy_addr);
+int gmacb_eth_initialize(int id, void *regs, unsigned int phy_addr);
int mcdmafec_initialize(bd_t *bis);
int mcffec_initialize(bd_t *bis);
int mpc512x_fec_initialize(bd_t *bis);