summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2010-09-08 00:42:00 +0200
committerWolfgang Denk <wd@denx.de>2010-09-08 00:42:00 +0200
commitcf64fda38e3d71e9077e11c673bd9be449c680da (patch)
treea847fb6cd48330482642ff92e34a7329b339acd2
parent09b4a9cf4003599f2cd609587dfa5f0b754640ed (diff)
parent5c3dab97c751e43103813472283305cbfe70d3f0 (diff)
Merge branch 'at91' of git://git.denx.de/u-boot-atmel
-rw-r--r--Makefile2
-rw-r--r--arch/arm/cpu/arm926ejs/at91/Makefile1
-rw-r--r--arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c56
-rw-r--r--arch/arm/cpu/arm926ejs/at91/eflash.c271
-rw-r--r--arch/arm/cpu/arm926ejs/at91/reset.c21
-rw-r--r--arch/arm/cpu/arm926ejs/at91/timer.c5
-rw-r--r--arch/arm/include/asm/arch-at91/at91_common.h1
-rw-r--r--arch/arm/include/asm/arch-at91/at91_dbu.h41
-rw-r--r--arch/arm/include/asm/arch-at91/at91_eefc.h51
-rw-r--r--arch/arm/include/asm/arch-at91/at91_gpbr.h45
-rw-r--r--arch/arm/include/asm/arch-at91/at91_pit.h2
-rw-r--r--arch/arm/include/asm/arch-at91/at91_rtt.h36
-rw-r--r--arch/arm/include/asm/arch-at91/at91sam9260.h18
-rw-r--r--arch/arm/include/asm/arch-at91/clk.h5
-rw-r--r--arch/arm/include/asm/arch-at91/hardware.h1
-rw-r--r--board/esd/meesc/meesc.c116
-rw-r--r--board/eukrea/cpuat91/cpuat91.c53
-rw-r--r--doc/README.atmel_mci86
-rw-r--r--drivers/mmc/Makefile5
-rw-r--r--drivers/mmc/atmel_mci.h48
-rw-r--r--drivers/mmc/gen_atmel_mci.c353
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/at91sam9_rtt.c100
-rw-r--r--drivers/spi/atmel_spi.c13
-rw-r--r--include/configs/cpuat91.h53
-rw-r--r--include/configs/meesc.h26
-rw-r--r--include/configs/otc570.h1
-rw-r--r--include/mmc.h15
28 files changed, 1278 insertions, 148 deletions
diff --git a/Makefile b/Makefile
index 332c79a2bc..44cd35754d 100644
--- a/Makefile
+++ b/Makefile
@@ -1890,7 +1890,7 @@ CPUAT91_RAM_config \
CPUAT91_config : unconfig
@mkdir -p $(obj)include
@echo "#define CONFIG_$(@:_config=) 1" >$(obj)include/config.h
- @$(MKCONFIG) -n $@ -a cpuat91 arm arm920t cpuat91 eukrea at91rm9200
+ @$(MKCONFIG) -n $@ -a cpuat91 arm arm920t cpuat91 eukrea at91
#########################################################################
## ARM926EJ-S Systems
diff --git a/arch/arm/cpu/arm926ejs/at91/Makefile b/arch/arm/cpu/arm926ejs/at91/Makefile
index 4f467be91c..def3980b63 100644
--- a/arch/arm/cpu/arm926ejs/at91/Makefile
+++ b/arch/arm/cpu/arm926ejs/at91/Makefile
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_AT91SAM9263) += at91sam9263_devices.o
COBJS-$(CONFIG_AT91SAM9RL) += at91sam9rl_devices.o
COBJS-$(CONFIG_AT91SAM9M10G45) += at91sam9m10g45_devices.o
COBJS-$(CONFIG_AT91SAM9G45) += at91sam9m10g45_devices.o
+COBJS-$(CONFIG_AT91_EFLASH) += eflash.o
COBJS-$(CONFIG_AT91_LED) += led.o
COBJS-y += clock.o
COBJS-y += cpu.o
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c
index 77d49ab1c7..87b04426b9 100644
--- a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c
+++ b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c
@@ -28,12 +28,27 @@
#include <asm/arch/gpio.h>
#include <asm/arch/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
+
void at91_serial0_hw_init(void)
{
at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
at91_set_a_periph(AT91_PIO_PORTB, 4, 1); /* TXD0 */
- at91_set_a_periph(AT91_PIO_PORTB, 5, 0); /* RXD0 */
+ at91_set_a_periph(AT91_PIO_PORTB, 5, PUP); /* RXD0 */
writel(1 << AT91SAM9260_ID_US0, &pmc->pcer);
}
@@ -42,7 +57,7 @@ void at91_serial1_hw_init(void)
at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
at91_set_a_periph(AT91_PIO_PORTB, 6, 1); /* TXD1 */
- at91_set_a_periph(AT91_PIO_PORTB, 7, 0); /* RXD1 */
+ at91_set_a_periph(AT91_PIO_PORTB, 7, PUP); /* RXD1 */
writel(1 << AT91SAM9260_ID_US1, &pmc->pcer);
}
@@ -51,7 +66,7 @@ void at91_serial2_hw_init(void)
at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
at91_set_a_periph(AT91_PIO_PORTB, 8, 1); /* TXD2 */
- at91_set_a_periph(AT91_PIO_PORTB, 9, 0); /* RXD2 */
+ at91_set_a_periph(AT91_PIO_PORTB, 9, PUP); /* RXD2 */
writel(1 << AT91SAM9260_ID_US2, &pmc->pcer);
}
@@ -59,7 +74,7 @@ void at91_serial3_hw_init(void)
{
at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
- at91_set_a_periph(AT91_PIO_PORTB, 14, 0); /* DRXD */
+ at91_set_a_periph(AT91_PIO_PORTB, 14, PUP); /* DRXD */
at91_set_a_periph(AT91_PIO_PORTB, 15, 1); /* DTXD */
writel(1 << AT91_ID_SYS, &pmc->pcer);
}
@@ -88,9 +103,9 @@ void at91_spi0_hw_init(unsigned long cs_mask)
{
at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
- at91_set_a_periph(AT91_PIO_PORTA, 0, 0); /* SPI0_MISO */
- at91_set_a_periph(AT91_PIO_PORTA, 1, 0); /* SPI0_MOSI */
- at91_set_a_periph(AT91_PIO_PORTA, 2, 0); /* SPI0_SPCK */
+ at91_set_a_periph(AT91_PIO_PORTA, 0, PUP); /* SPI0_MISO */
+ at91_set_a_periph(AT91_PIO_PORTA, 1, PUP); /* SPI0_MOSI */
+ at91_set_a_periph(AT91_PIO_PORTA, 2, PUP); /* SPI0_SPCK */
/* Enable clock */
writel(1 << AT91SAM9260_ID_SPI0, &pmc->pcer);
@@ -125,9 +140,9 @@ void at91_spi1_hw_init(unsigned long cs_mask)
{
at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
- at91_set_a_periph(AT91_PIO_PORTB, 0, 0); /* SPI1_MISO */
- at91_set_a_periph(AT91_PIO_PORTB, 1, 0); /* SPI1_MOSI */
- at91_set_a_periph(AT91_PIO_PORTB, 2, 0); /* SPI1_SPCK */
+ at91_set_a_periph(AT91_PIO_PORTB, 0, PUP); /* SPI1_MISO */
+ at91_set_a_periph(AT91_PIO_PORTB, 1, PUP); /* SPI1_MOSI */
+ at91_set_a_periph(AT91_PIO_PORTB, 2, PUP); /* SPI1_SPCK */
/* Enable clock */
writel(1 << AT91SAM9260_ID_SPI1, &pmc->pcer);
@@ -194,3 +209,24 @@ void at91_macb_hw_init(void)
#endif
}
#endif
+
+#if defined(CONFIG_ATMEL_MCI) || defined(CONFIG_GENERIC_ATMEL_MCI)
+void at91_mci_hw_init(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTA, 8, 1); /* MCCK */
+#if defined(CONFIG_ATMEL_MCI_PORTB)
+ at91_set_b_periph(AT91_PIO_PORTA, 1, 1); /* MCCDB */
+ at91_set_b_periph(AT91_PIO_PORTA, 0, 1); /* MCDB0 */
+ at91_set_b_periph(AT91_PIO_PORTA, 5, 1); /* MCDB1 */
+ at91_set_b_periph(AT91_PIO_PORTA, 4, 1); /* MCDB2 */
+ at91_set_b_periph(AT91_PIO_PORTA, 3, 1); /* MCDB3 */
+#else
+ at91_set_a_periph(AT91_PIO_PORTA, 7, 1); /* MCCDA */
+ at91_set_a_periph(AT91_PIO_PORTA, 6, 1); /* MCDA0 */
+ at91_set_a_periph(AT91_PIO_PORTA, 9, 1); /* MCDA1 */
+ at91_set_a_periph(AT91_PIO_PORTA, 10, 1); /* MCDA2 */
+ at91_set_a_periph(AT91_PIO_PORTA, 11, 1); /* MCDA3 */
+#endif
+}
+#endif
+
diff --git a/arch/arm/cpu/arm926ejs/at91/eflash.c b/arch/arm/cpu/arm926ejs/at91/eflash.c
new file mode 100644
index 0000000000..2e851dbd2c
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/at91/eflash.c
@@ -0,0 +1,271 @@
+/*
+ * (C) Copyright 2010
+ * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.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
+ */
+
+/*
+ * this driver supports the enhanced embedded flash in the Atmel
+ * AT91SAM9XE devices with the following geometry:
+ *
+ * AT91SAM9XE128: 1 plane of 8 regions of 32 pages (total 256 pages)
+ * AT91SAM9XE256: 1 plane of 16 regions of 32 pages (total 512 pages)
+ * AT91SAM9XE512: 1 plane of 32 regions of 32 pages (total 1024 pages)
+ * (the exact geometry is read from the flash at runtime, so any
+ * future devices should already be covered)
+ *
+ * Regions can be write/erase protected.
+ * Whole (!) pages can be individually written with erase on the fly.
+ * Writing partial pages will corrupt the rest of the page.
+ *
+ * The flash is presented to u-boot with each region being a sector,
+ * having the following effects:
+ * Each sector can be hardware protected (protect on/off).
+ * Each page in a sector can be rewritten anytime.
+ * Since pages are erased when written, the "erase" does nothing.
+ * The first "CONFIG_EFLASH_PROTSECTORS" cannot be unprotected
+ * by u-Boot commands.
+ *
+ * Note: Redundant environment will not work in this flash since
+ * it does use partial page writes. Make sure the environent spans
+ * whole pages!
+ */
+
+/*
+ * optional TODOs (nice to have features):
+ *
+ * make the driver coexist with other NOR flash drivers
+ * (use an index into flash_info[], requires work
+ * in those other drivers, too)
+ * Make the erase command fill the sectors with 0xff
+ * (if the flashes grow larger in the future and
+ * someone puts a jffs2 into them)
+ * do a read-modify-write for partially programmed pages
+ */
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/io.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_eefc.h>
+#include <asm/arch/at91_dbu.h>
+
+/* checks to detect configuration errors */
+#if CONFIG_SYS_MAX_FLASH_BANKS!=1
+#error eflash: this driver can only handle 1 bank
+#endif
+
+/* global structure */
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
+static u32 pagesize;
+
+unsigned long flash_init (void)
+{
+ at91_eefc_t *eefc = (at91_eefc_t *) 0xfffffa00;
+ at91_dbu_t *dbu = (at91_dbu_t *) 0xfffff200;
+ u32 id, size, nplanes, planesize, nlocks;
+ u32 addr, i, tmp=0;
+
+ debug("eflash: init\n");
+
+ flash_info[0].flash_id = FLASH_UNKNOWN;
+
+ /* check if its an AT91ARM9XE SoC */
+ if ((readl(&dbu->cidr) & AT91_DBU_CID_ARCH_MASK) != AT91_DBU_CID_ARCH_9XExx) {
+ puts("eflash: not an AT91SAM9XE\n");
+ return 0;
+ }
+
+ /* now query the eflash for its structure */
+ writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GETD, &eefc->fcr);
+ while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+ ;
+ id = readl(&eefc->frr); /* word 0 */
+ size = readl(&eefc->frr); /* word 1 */
+ pagesize = readl(&eefc->frr); /* word 2 */
+ nplanes = readl(&eefc->frr); /* word 3 */
+ planesize = readl(&eefc->frr); /* word 4 */
+ debug("id=%08x size=%u pagesize=%u planes=%u planesize=%u\n",
+ id, size, pagesize, nplanes, planesize);
+ for (i=1; i<nplanes; i++) {
+ tmp = readl(&eefc->frr); /* words 5..4+nplanes-1 */
+ };
+ nlocks = readl(&eefc->frr); /* word 4+nplanes */
+ debug("nlocks=%u\n", nlocks);
+ /* since we are going to use the lock regions as sectors, check count */
+ if (nlocks > CONFIG_SYS_MAX_FLASH_SECT) {
+ printf("eflash: number of lock regions(%u) "\
+ "> CONFIG_SYS_MAX_FLASH_SECT. reducing...\n",
+ nlocks);
+ nlocks = CONFIG_SYS_MAX_FLASH_SECT;
+ }
+ flash_info[0].size = size;
+ flash_info[0].sector_count = nlocks;
+ flash_info[0].flash_id = id;
+
+ addr = AT91SAM9XE_FLASH_BASE;
+ for (i=0; i<nlocks; i++) {
+ tmp = readl(&eefc->frr); /* words 4+nplanes+1.. */
+ flash_info[0].start[i] = addr;
+ flash_info[0].protect[i] = 0;
+ addr += tmp;
+ };
+
+ /* now read the protection information for all regions */
+ writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
+ while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+ ;
+ for (i=0; i<flash_info[0].sector_count; i++) {
+ if (i%32 == 0)
+ tmp = readl(&eefc->frr);
+ flash_info[0].protect[i] = (tmp >> (i%32)) & 1;
+#if defined(CONFIG_EFLASH_PROTSECTORS)
+ if (i < CONFIG_EFLASH_PROTSECTORS)
+ flash_info[0].protect[i] = 1;
+#endif
+ }
+
+ return size;
+}
+
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+
+ puts("AT91SAM9XE embedded flash\n Size: ");
+ print_size(info->size, " in ");
+ printf("%d Sectors\n", info->sector_count);
+
+ printf(" Sector Start Addresses:");
+ for (i=0; i<info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ printf("\n ");
+ printf(" %08lX%s",
+ info->start[i],
+ info->protect[i] ? " (RO)" : " "
+ );
+ }
+ printf ("\n");
+ return;
+}
+
+int flash_real_protect (flash_info_t *info, long sector, int prot)
+{
+ at91_eefc_t *eefc = (at91_eefc_t *) 0xfffffa00;
+ u32 pagenum = (info->start[sector]-AT91SAM9XE_FLASH_BASE)/pagesize;
+ u32 i, tmp=0;
+
+ debug("protect sector=%ld prot=%d\n", sector, prot);
+
+#if defined(CONFIG_EFLASH_PROTSECTORS)
+ if (sector < CONFIG_EFLASH_PROTSECTORS) {
+ if (!prot) {
+ printf("eflash: sector %lu cannot be unprotected\n",
+ sector);
+ }
+ return 1; /* return anyway, caller does not care for result */
+ }
+#endif
+ if (prot) {
+ writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_SLB |
+ (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
+ } else {
+ writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_CLB |
+ (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
+ }
+ while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+ ;
+ /* now re-read the protection information for all regions */
+ writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
+ while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+ ;
+ for (i=0; i<info->sector_count; i++) {
+ if (i%32 == 0)
+ tmp = readl(&eefc->frr);
+ info->protect[i] = (tmp >> (i%32)) & 1;
+ }
+ return 0;
+}
+
+static u32 erase_write_page (u32 pagenum)
+{
+ at91_eefc_t *eefc = (at91_eefc_t *) 0xfffffa00;
+
+ debug("erase+write page=%u\n", pagenum);
+
+ /* give erase and write page command */
+ writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_EWP |
+ (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
+ while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
+ ;
+ /* return status */
+ return readl(&eefc->fsr)
+ & (AT91_EEFC_FSR_FCMDE | AT91_EEFC_FSR_FLOCKE);
+}
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ debug("erase first=%d last=%d\n", s_first, s_last);
+ puts("this flash does not need and support erasing!\n");
+ return 0;
+}
+
+/*
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ u32 pagenum;
+ u32 *src32, *dst32;
+ u32 i;
+
+ debug("write src=%08lx addr=%08lx cnt=%lx\n",
+ (ulong)src, addr, cnt);
+
+ /* REQUIRE addr to be on a page start, abort if not */
+ if (addr % pagesize) {
+ printf ("eflash: start %08lx is not on page start\n"\
+ " write aborted\n", addr);
+ return 1;
+ }
+
+ /* now start copying data */
+ pagenum = (addr-AT91SAM9XE_FLASH_BASE)/pagesize;
+ src32 = (u32 *) src;
+ dst32 = (u32 *) addr;
+ while (cnt > 0) {
+ i = pagesize / 4;
+ /* fill page buffer */
+ while (i--)
+ *dst32++ = *src32++;
+ /* write page */
+ if (erase_write_page(pagenum))
+ return 1;
+ pagenum++;
+ if (cnt > pagesize)
+ cnt -= pagesize;
+ else
+ cnt = 0;
+ }
+ return 0;
+}
+
diff --git a/arch/arm/cpu/arm926ejs/at91/reset.c b/arch/arm/cpu/arm926ejs/at91/reset.c
index 1b67e77887..d2569d8bae 100644
--- a/arch/arm/cpu/arm926ejs/at91/reset.c
+++ b/arch/arm/cpu/arm926ejs/at91/reset.c
@@ -27,18 +27,19 @@
#include <asm/arch/at91_rstc.h>
#include <asm/arch/io.h>
-/*
- * Reset the cpu by setting up the watchdog timer and let him time out.
- */
+/* Reset the cpu by telling the reset controller to do so */
void reset_cpu(ulong ignored)
{
at91_rstc_t *rstc = (at91_rstc_t *) AT91_RSTC_BASE;
- /* this is the way Linux does it */
-
- writel(AT91_RSTC_KEY | AT91_RSTC_CR_PROCRST | AT91_RSTC_CR_PERRST,
- &rstc->cr);
-
- while (1);
- /* Never reached */
+ 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/arm926ejs/at91/timer.c b/arch/arm/cpu/arm926ejs/at91/timer.c
index d21eebfb4e..8efc34bcf1 100644
--- a/arch/arm/cpu/arm926ejs/at91/timer.c
+++ b/arch/arm/cpu/arm926ejs/at91/timer.c
@@ -138,8 +138,5 @@ ulong get_timer(ulong base)
*/
ulong get_tbclk(void)
{
- ulong tbclk;
-
- tbclk = CONFIG_SYS_HZ;
- return tbclk;
+ return timer_freq;
}
diff --git a/arch/arm/include/asm/arch-at91/at91_common.h b/arch/arm/include/asm/arch-at91/at91_common.h
index 01840eede4..0067190a20 100644
--- a/arch/arm/include/asm/arch-at91/at91_common.h
+++ b/arch/arm/include/asm/arch-at91/at91_common.h
@@ -27,6 +27,7 @@
void at91_can_hw_init(void);
void at91_macb_hw_init(void);
+void at91_mci_hw_init(void);
void at91_serial_hw_init(void);
void at91_serial0_hw_init(void);
void at91_serial1_hw_init(void);
diff --git a/arch/arm/include/asm/arch-at91/at91_dbu.h b/arch/arm/include/asm/arch-at91/at91_dbu.h
new file mode 100644
index 0000000000..3429293535
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/at91_dbu.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.de
+ *
+ * Debug Unit
+ * Based on AT91SAM9XE 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 AT91_DBU_H
+#define AT91_DBU_H
+
+#ifndef __ASSEMBLY__
+
+typedef struct at91_dbu {
+ u32 cr; /* Control Register WO */
+ u32 mr; /* Mode Register RW */
+ u32 ier; /* Interrupt Enable Register WO */
+ u32 idr; /* Interrupt Disable Register WO */
+ u32 imr; /* Interrupt Mask Register RO */
+ u32 sr; /* Status Register RO */
+ u32 rhr; /* Receive Holding Register RO */
+ u32 thr; /* Transmit Holding Register WO */
+ u32 brgr; /* Baud Rate Generator Register RW */
+ u32 res1[7];/* 0x0024 - 0x003C Reserved */
+ u32 cidr; /* Chip ID Register RO */
+ u32 exid; /* Chip ID Extension Register RO */
+ u32 fnr; /* Force NTRST Register RW */
+} at91_dbu_t;
+
+#endif /* __ASSEMBLY__ */
+
+#define AT91_DBU_CID_ARCH_MASK 0x0ff00000
+#define AT91_DBU_CID_ARCH_9xx 0x01900000
+#define AT91_DBU_CID_ARCH_9XExx 0x02900000
+
+#endif
diff --git a/arch/arm/include/asm/arch-at91/at91_eefc.h b/arch/arm/include/asm/arch-at91/at91_eefc.h
new file mode 100644
index 0000000000..d45b3deca4
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/at91_eefc.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.de
+ *
+ * Enhanced Embedded Flash Controller
+ * Based on AT91SAM9XE 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 AT91_EEFC_H
+#define AT91_EEFC_H
+
+#ifndef __ASSEMBLY__
+
+typedef struct at91_eefc {
+ u32 fmr; /* Flash Mode Register RW */
+ u32 fcr; /* Flash Command Register WO */
+ u32 fsr; /* Flash Status Register RO */
+ u32 frr; /* Flash Result Register RO */
+} at91_eefc_t;
+
+#endif /* __ASSEMBLY__ */
+
+#define AT91_EEFC_FMR_FWS_MASK 0x00000f00
+#define AT91_EEFC_FMR_FRDY_BIT 0x00000001
+
+#define AT91_EEFC_FCR_KEY 0x5a000000
+#define AT91_EEFC_FCR_FARG_MASK 0x00ffff00
+#define AT91_EEFC_FCR_FARG_SHIFT 8
+#define AT91_EEFC_FCR_FCMD_GETD 0x0
+#define AT91_EEFC_FCR_FCMD_WP 0x1
+#define AT91_EEFC_FCR_FCMD_WPL 0x2
+#define AT91_EEFC_FCR_FCMD_EWP 0x3
+#define AT91_EEFC_FCR_FCMD_EWPL 0x4
+#define AT91_EEFC_FCR_FCMD_EA 0x5
+#define AT91_EEFC_FCR_FCMD_SLB 0x8
+#define AT91_EEFC_FCR_FCMD_CLB 0x9
+#define AT91_EEFC_FCR_FCMD_GLB 0xA
+#define AT91_EEFC_FCR_FCMD_SGPB 0xB
+#define AT91_EEFC_FCR_FCMD_CGPB 0xC
+#define AT91_EEFC_FCR_FCMD_GGPB 0xD
+
+#define AT91_EEFC_FSR_FRDY 1
+#define AT91_EEFC_FSR_FCMDE 2
+#define AT91_EEFC_FSR_FLOCKE 4
+
+#endif
diff --git a/arch/arm/include/asm/arch-at91/at91_gpbr.h b/arch/arm/include/asm/arch-at91/at91_gpbr.h
new file mode 100644
index 0000000000..cf1d790dd9
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/at91_gpbr.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.de
+ *
+ * General Purpose Backup Registers
+ * Based on AT91SAM9XE 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 AT91_GPBR_H
+#define AT91_GPBR_H
+
+/*
+ * The Atmel AT91SAM9 series has a small resource of 4 nonvolatile
+ * 32 Bit registers (buffered by the Vbu power).
+ *
+ * Please consider carefully before using this resource for tasks
+ * that do not really need nonvolatile registers. Maybe you can
+ * store information in EEPROM or FLASH instead.
+ *
+ * However, if you use a GPBR please document its use here and
+ * reference the define in your code!
+ *
+ * known typical uses of the GPBRs:
+ * GPBR[0]: offset for RTT timekeeping (u-boot, kernel)
+ * GPBR[1]: unused
+ * GPBR[2]: unused
+ * GPBR[3]: bootcount (u-boot)
+ */
+#define AT91_GPBR_INDEX_TIMEOFF 0
+#define AT91_GPBR_INDEX_BOOTCOUNT 3
+
+#ifndef __ASSEMBLY__
+
+typedef struct at91_gpbr {
+ u32 reg[4];
+} at91_gpbr_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/arm/include/asm/arch-at91/at91_pit.h b/arch/arm/include/asm/arch-at91/at91_pit.h
index 5615a0206c..61aca79418 100644
--- a/arch/arm/include/asm/arch-at91/at91_pit.h
+++ b/arch/arm/include/asm/arch-at91/at91_pit.h
@@ -25,7 +25,7 @@ typedef struct at91_pit {
#define AT91_PIT_MR_IEN 0x02000000
#define AT91_PIT_MR_EN 0x01000000
-#define AT91_PIT_MR_PIV_MASK (x & 0x000fffff)
+#define AT91_PIT_MR_PIV_MASK(x) (x & 0x000fffff)
#define AT91_PIT_MR_PIV(x) (x & AT91_PIT_MR_PIV_MASK)
#ifdef CONFIG_AT91_LEGACY
diff --git a/arch/arm/include/asm/arch-at91/at91_rtt.h b/arch/arm/include/asm/arch-at91/at91_rtt.h
new file mode 100644
index 0000000000..e0253ef821
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/at91_rtt.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.de
+ *
+ * Real-time Timer
+ * Based on AT91SAM9XE 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 AT91_RTT_H
+#define AT91_RTT_H
+
+#ifndef __ASSEMBLY__
+
+typedef struct at91_rtt {
+ u32 mr; /* Mode Register RW 0x00008000 */
+ u32 ar; /* Alarm Register RW 0xFFFFFFFF */
+ u32 vr; /* Value Register RO 0x00000000 */
+ u32 sr; /* Status Register RO 0x00000000 */
+} at91_rtt_t;
+
+#endif /* __ASSEMBLY__ */
+
+#define AT91_RTT_MR_RTPRES 0x0000ffff
+#define AT91_RTT_MR_ALMIEN 0x00010000
+#define AT91_RTT_RTTINCIEN 0x00020000
+#define AT91_RTT_RTTRST 0x00040000
+
+#define AT91_RTT_SR_ALMS 0x00000001
+#define AT91_RTT_SR_RTTINC 0x00000002
+
+#endif
diff --git a/arch/arm/include/asm/arch-at91/at91sam9260.h b/arch/arm/include/asm/arch-at91/at91sam9260.h
index ec04318036..cb34a94a3b 100644
--- a/arch/arm/include/asm/arch-at91/at91sam9260.h
+++ b/arch/arm/include/asm/arch-at91/at91sam9260.h
@@ -59,7 +59,15 @@
#define AT91_RTT_BASE 0xfffffd20
#define AT91_PIT_BASE 0xfffffd30
#define AT91_WDT_BASE 0xfffffd40
-#define AT91_GPR_BASE 0xfffffd50
+/*
+ * The AT91SAM9XE has the GPBRs at a different address than
+ * the AT91SAM9260/9G20.
+ */
+#ifdef CONFIG_AT91SAM9XE
+# define AT91_GPR_BASE 0xfffffd60
+#else
+# define AT91_GPR_BASE 0xfffffd50
+#endif
#ifdef CONFIG_AT91_LEGACY
@@ -140,10 +148,12 @@
/*
* Cpu Name
*/
-#if defined(CONFIG_AT91SAM9260)
-#define CONFIG_SYS_AT91_CPU_NAME "AT91SAM9260"
+#if defined(CONFIG_AT91SAM9XE)
+# define CONFIG_SYS_AT91_CPU_NAME "AT91SAM9XE"
+#elif defined(CONFIG_AT91SAM9260)
+# define CONFIG_SYS_AT91_CPU_NAME "AT91SAM9260"
#elif defined(CONFIG_AT91SAM9G20)
-#define CONFIG_SYS_AT91_CPU_NAME "AT91SAM9G20"
+# define CONFIG_SYS_AT91_CPU_NAME "AT91SAM9G20"
#endif
#endif
diff --git a/arch/arm/include/asm/arch-at91/clk.h b/arch/arm/include/asm/arch-at91/clk.h
index f642dd9958..457e6c9b2b 100644
--- a/arch/arm/include/asm/arch-at91/clk.h
+++ b/arch/arm/include/asm/arch-at91/clk.h
@@ -59,5 +59,10 @@ static inline unsigned long get_twi_clk_rate(unsigned int dev_id)
return get_mck_clk_rate();
}
+static inline unsigned long get_mci_clk_rate(void)
+{
+ return get_mck_clk_rate();
+}
+
int at91_clock_init(unsigned long main_clock);
#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 4ddb3155d7..9f732a738e 100644
--- a/arch/arm/include/asm/arch-at91/hardware.h
+++ b/arch/arm/include/asm/arch-at91/hardware.h
@@ -20,6 +20,7 @@
#include <asm/arch-at91/at91rm9200.h>
#elif defined(CONFIG_AT91SAM9260) || defined(CONFIG_AT91SAM9G20)
#include <asm/arch/at91sam9260.h>
+#define AT91_BASE_MCI AT91SAM9260_BASE_MCI
#define AT91_BASE_SPI AT91SAM9260_BASE_SPI0
#define AT91_ID_UHP AT91SAM9260_ID_UHP
#define AT91_PMC_UHP AT91SAM926x_PMC_UHP
diff --git a/board/esd/meesc/meesc.c b/board/esd/meesc/meesc.c
index 694bd74358..41fa3e1567 100644
--- a/board/esd/meesc/meesc.c
+++ b/board/esd/meesc/meesc.c
@@ -3,7 +3,7 @@
* Stelian Pop <stelian.pop@leadtechdesign.com>
* Lead Tech Design <www.leadtechdesign.com>
*
- * (C) Copyright 2009
+ * (C) Copyright 2009-2010
* Daniel Gorsulowski <daniel.gorsulowski@esd.eu>
* esd electronic system design gmbh <www.esd.eu>
*
@@ -28,13 +28,13 @@
#include <common.h>
#include <asm/arch/at91sam9263.h>
-#include <asm/arch/at91sam9_matrix.h>
#include <asm/arch/at91sam9_smc.h>
#include <asm/arch/at91_common.h>
#include <asm/arch/at91_pmc.h>
#include <asm/arch/at91_rstc.h>
+#include <asm/arch/at91_matrix.h>
+#include <asm/arch/at91_pio.h>
#include <asm/arch/clk.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/hardware.h>
#include <asm/arch/io.h>
#include <netdev.h>
@@ -52,10 +52,10 @@ int get_hw_rev(void)
if (hw_rev >= 0)
return hw_rev;
- hw_rev = at91_get_gpio_value(AT91_PIN_PB19);
- hw_rev |= at91_get_gpio_value(AT91_PIN_PB20) << 1;
- hw_rev |= at91_get_gpio_value(AT91_PIN_PB21) << 2;
- hw_rev |= at91_get_gpio_value(AT91_PIN_PB22) << 3;
+ hw_rev = at91_get_pio_value(AT91_PIO_PORTB, 19);
+ hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 20) << 1;
+ hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 21) << 2;
+ hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 22) << 3;
if (hw_rev == 15)
hw_rev = 0;
@@ -67,44 +67,44 @@ int get_hw_rev(void)
static void meesc_nand_hw_init(void)
{
unsigned long csa;
+ at91_smc_t *smc = (at91_smc_t *) AT91_SMC0_BASE;
+ at91_matrix_t *matrix = (at91_matrix_t *) AT91_MATRIX_BASE;
/* Enable CS3 */
- csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
- at91_sys_write(AT91_MATRIX_EBI0CSA,
- csa | AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA);
+ csa = readl(&matrix->csa[0]) | AT91_MATRIX_CSA_EBI_CS3A;
+ writel(csa, &matrix->csa[0]);
/* Configure SMC CS3 for NAND/SmartMedia */
- at91_sys_write(AT91_SMC_SETUP(3),
- AT91_SMC_NWESETUP_(1) | AT91_SMC_NCS_WRSETUP_(0) |
- AT91_SMC_NRDSETUP_(1) | AT91_SMC_NCS_RDSETUP_(0));
- at91_sys_write(AT91_SMC_PULSE(3),
- AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) |
- AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3));
- at91_sys_write(AT91_SMC_CYCLE(3),
- AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5));
- at91_sys_write(AT91_SMC_MODE(3),
- AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
- AT91_SMC_EXNWMODE_DISABLE |
-#ifdef CONFIG_SYS_NAND_DBW_16
- AT91_SMC_DBW_16 |
-#else /* CONFIG_SYS_NAND_DBW_8 */
- AT91_SMC_DBW_8 |
-#endif
- AT91_SMC_TDF_(2));
+ writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(0) |
+ AT91_SMC_SETUP_NRD(1) | AT91_SMC_SETUP_NCS_RD(0),
+ &smc->cs[3].setup);
+
+ writel(AT91_SMC_PULSE_NWE(3) | AT91_SMC_PULSE_NCS_WR(3) |
+ AT91_SMC_PULSE_NRD(3) | AT91_SMC_PULSE_NCS_RD(3),
+ &smc->cs[3].pulse);
+
+ writel(AT91_SMC_CYCLE_NWE(5) | AT91_SMC_CYCLE_NRD(5),
+ &smc->cs[3].cycle);
+ writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
+ AT91_SMC_MODE_EXNW_DISABLE |
+ AT91_SMC_MODE_DBW_8 |
+ AT91_SMC_MODE_TDF_CYCLE(2),
+ &smc->cs[3].mode);
/* Configure RDY/BSY */
- at91_set_gpio_input(CONFIG_SYS_NAND_READY_PIN, 1);
+ at91_set_pio_input(CONFIG_SYS_NAND_READY_PIN, 1);
/* Enable NandFlash */
- at91_set_gpio_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
+ at91_set_pio_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
}
#endif /* CONFIG_CMD_NAND */
#ifdef CONFIG_MACB
static void meesc_macb_hw_init(void)
{
+ at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
/* Enable clock */
- at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_EMAC);
+ writel(1 << AT91SAM9263_ID_EMAC, &pmc->pcer);
at91_macb_hw_init();
}
#endif
@@ -117,26 +117,27 @@ static void meesc_macb_hw_init(void)
*/
static void meesc_ethercat_hw_init(void)
{
+ at91_smc_t *smc1 = (at91_smc_t *) AT91_SMC1_BASE;
+
/* Configure SMC EBI1_CS0 for EtherCAT */
- at91_sys_write(AT91_SMC1_SETUP(0),
- AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) |
- AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
- at91_sys_write(AT91_SMC1_PULSE(0),
- AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(9) |
- AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(9));
- at91_sys_write(AT91_SMC1_CYCLE(0),
- AT91_SMC_NWECYCLE_(10) | AT91_SMC_NRDCYCLE_(5));
+ writel(AT91_SMC_SETUP_NWE(0) | AT91_SMC_SETUP_NCS_WR(0) |
+ AT91_SMC_SETUP_NRD(0) | AT91_SMC_SETUP_NCS_RD(0),
+ &smc1->cs[0].setup);
+ writel(AT91_SMC_PULSE_NWE(4) | AT91_SMC_PULSE_NCS_WR(9) |
+ AT91_SMC_PULSE_NRD(5) | AT91_SMC_PULSE_NCS_RD(9),
+ &smc1->cs[0].pulse);
+ writel(AT91_SMC_CYCLE_NWE(10) | AT91_SMC_CYCLE_NRD(6),
+ &smc1->cs[0].cycle);
/*
* Configure behavior at external wait signal, byte-select mode, 16 bit
* data bus width, none data float wait states and TDF optimization
*/
- at91_sys_write(AT91_SMC1_MODE(0),
- AT91_SMC_READMODE | AT91_SMC_EXNWMODE_READY |
- AT91_SMC_BAT_SELECT | AT91_SMC_DBW_16 | AT91_SMC_TDF_(0) |
- AT91_SMC_TDFMODE);
+ writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_EXNW_READY |
+ AT91_SMC_MODE_DBW_16 | AT91_SMC_MODE_TDF_CYCLE(0) |
+ AT91_SMC_MODE_TDF, &smc1->cs[0].mode);
/* Configure RDY/BSY */
- at91_set_B_periph(AT91_PIN_PE20, 0); /* EBI1_NWAIT */
+ at91_set_b_periph(AT91_PIO_PORTE, 20, 0); /* EBI1_NWAIT */
}
int dram_init(void)
@@ -150,7 +151,7 @@ int board_eth_init(bd_t *bis)
{
int rc = 0;
#ifdef CONFIG_MACB
- rc = macb_eth_initialize(0, (void *)AT91SAM9263_BASE_EMAC, 0x00);
+ rc = macb_eth_initialize(0, (void *)AT91_EMAC_BASE, 0x00);
#endif
return rc;
}
@@ -175,7 +176,7 @@ int checkboard(void)
gd->bd->bi_arch_number = MACH_TYPE_ETHERCAN2;
puts("Board: EtherCAN/2 Gateway");
/* switch on LED1D */
- at91_set_gpio_output(AT91_PIN_PB12, 1);
+ at91_set_pio_output(AT91_PIO_PORTB, 12, 1);
break;
default:
/* assume, no ET1100 present, arch number of EtherCAN/2-Board */
@@ -222,8 +223,9 @@ u32 get_board_rev(void)
#ifdef CONFIG_MISC_INIT_R
int misc_init_r(void)
{
- char *str;
- char buf[32];
+ char *str;
+ char buf[32];
+ at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
/*
* Normally the processor clock has a divisor of 2.
@@ -231,10 +233,9 @@ int misc_init_r(void)
* Check the user has set environment mdiv to 4 to change the divisor.
*/
if ((str = getenv("mdiv")) && (strcmp(str, "4") == 0)) {
- at91_sys_write(AT91_PMC_MCKR,
- (at91_sys_read(AT91_PMC_MCKR) & ~AT91_PMC_MDIV) |
- AT91SAM9_PMC_MDIV_4);
- at91_clock_init(0);
+ writel((readl(&pmc->mckr) & ~AT91_PMC_MDIV) |
+ AT91SAM9_PMC_MDIV_4, &pmc->mckr);
+ at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
serial_setbrg();
/* Notify the user that the clock is not default */
printf("Setting master clock to %s MHz\n",
@@ -247,10 +248,14 @@ int misc_init_r(void)
int board_init(void)
{
+ at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
+
/* Peripheral Clock Enable Register */
- at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_PIOA |
- 1 << AT91SAM9263_ID_PIOB |
- 1 << AT91SAM9263_ID_PIOCDE);
+ writel(1 << AT91SAM9263_ID_PIOA |
+ 1 << AT91SAM9263_ID_PIOB |
+ 1 << AT91SAM9263_ID_PIOCDE |
+ 1 << AT91SAM9263_ID_UHP,
+ &pmc->pcer);
/* initialize ET1100 Controller */
meesc_ethercat_hw_init();
@@ -271,5 +276,8 @@ int board_init(void)
#ifdef CONFIG_AT91_CAN
at91_can_hw_init();
#endif
+#ifdef CONFIG_USB_OHCI_NEW
+ at91_uhp_hw_init();
+#endif
return 0;
}
diff --git a/board/eukrea/cpuat91/cpuat91.c b/board/eukrea/cpuat91/cpuat91.c
index 0017962d42..cd4d42c6b7 100644
--- a/board/eukrea/cpuat91/cpuat91.c
+++ b/board/eukrea/cpuat91/cpuat91.c
@@ -1,5 +1,5 @@
/*
- * (C) Copyright 2006 Eukrea Electromatique <www.eukrea.com>
+ * (C) Copyright 2006-2010 Eukrea Electromatique <www.eukrea.com>
* Eric Benard <eric@eukrea.com>
* based on at91rm9200dk.c which is :
* (C) Copyright 2002
@@ -27,13 +27,11 @@
#include <common.h>
#include <netdev.h>
-#include <asm/arch/AT91RM9200.h>
-#include <asm/io.h>
-#if defined(CONFIG_DRIVER_ETHER)
-#include <at91rm9200_net.h>
-#include <ks8721.h>
-#endif
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/at91_pmc.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -61,31 +59,7 @@ int dram_init(void)
return 0;
}
-#if defined(CONFIG_DRIVER_ETHER)
-#if defined(CONFIG_CMD_NET)
-
-/*
- * Name:
- * at91rm9200_GetPhyInterface
- * Description:
- * Initialise the interface functions to the PHY
- * Arguments:
- * None
- * Return value:
- * None
- */
-void at91rm9200_GetPhyInterface(AT91PS_PhyOps p_phyops)
-{
- p_phyops->Init = ks8721_initphy;
- p_phyops->IsPhyConnected = ks8721_isphyconnected;
- p_phyops->GetLinkSpeed = ks8721_getlinkspeed;
- p_phyops->AutoNegotiate = ks8721_autonegotiate;
-}
-
-#endif /* CONFIG_CMD_NET */
-#endif /* CONFIG_DRIVER_ETHER */
#ifdef CONFIG_DRIVER_AT91EMAC
-
int board_eth_init(bd_t *bis)
{
int rc = 0;
@@ -93,3 +67,20 @@ int board_eth_init(bd_t *bis)
return rc;
}
#endif
+
+#ifdef CONFIG_SOFT_I2C
+void i2c_init_board(void)
+{
+ u32 pin;
+ at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
+ at91_pio_t *pio = (at91_pio_t *) AT91_PIO_BASE;
+
+ writel(1 << AT91_ID_PIOA, &pmc->pcer);
+ pin = AT91_PMX_AA_TWD | AT91_PMX_AA_TWCK;
+ writel(pin, &pio->pioa.idr);
+ writel(pin, &pio->pioa.pudr);
+ writel(pin, &pio->pioa.per);
+ writel(pin, &pio->pioa.oer);
+ writel(pin, &pio->pioa.sodr);
+}
+#endif
diff --git a/doc/README.atmel_mci b/doc/README.atmel_mci
new file mode 100644
index 0000000000..18b1bdf7e5
--- /dev/null
+++ b/doc/README.atmel_mci
@@ -0,0 +1,86 @@
+How to use SD/MMC cards with Atmel SoCs having MCI hardware
+-----------------------------------------------------------
+2010-08-16 Reinhard Meyer <reinhard.meyer@emk-elektronik.de>
+
+This is a new approach to use Atmel MCI hardware with the
+general MMC framework. Therefore it benefits from that
+framework's abilities to handle SDHC Cards and the ability
+to write blocks.
+
+- AT91SAM9XE512 (tested, will definitely work with XE128 and XE256)
+- AT91SAM9260 (not tested, but MCI is to AT91SAM9XE)
+- AT91SAM9G20 (not tested, should work)
+
+It should work with all other ATMEL devices that have MCI,
+including AVR32.
+
+The generic driver does NOT assign port pins to the MCI block
+nor does it start the MCI clock. This has to be handled in a
+board/SoC specific manner before the driver is initialized:
+
+example: this is added to at91sam9260_devices.c:
+
+#if defined(CONFIG_ATMEL_MCI) || defined(CONFIG_GENERIC_ATMEL_MCI)
+void at91_mci_hw_init(void)
+{
+ at91_set_a_periph(AT91_PIO_PORTA, 8, PUP); /* MCCK */
+#if defined(CONFIG_ATMEL_MCI_PORTB)
+ at91_set_b_periph(AT91_PIO_PORTA, 1, PUP); /* MCCDB */
+ at91_set_b_periph(AT91_PIO_PORTA, 0, PUP); /* MCDB0 */
+ at91_set_b_periph(AT91_PIO_PORTA, 5, PUP); /* MCDB1 */
+ at91_set_b_periph(AT91_PIO_PORTA, 4, PUP); /* MCDB2 */
+ at91_set_b_periph(AT91_PIO_PORTA, 3, PUP); /* MCDB3 */
+#else
+ at91_set_a_periph(AT91_PIO_PORTA, 7, PUP); /* MCCDA */
+ at91_set_a_periph(AT91_PIO_PORTA, 6, PUP); /* MCDA0 */
+ at91_set_a_periph(AT91_PIO_PORTA, 9, PUP); /* MCDA1 */
+ at91_set_a_periph(AT91_PIO_PORTA, 10, PUP); /* MCDA2 */
+ at91_set_a_periph(AT91_PIO_PORTA, 11, PUP); /* MCDA3 */
+#endif
+}
+#endif
+
+the board specific file need added:
+...
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+# include <mmc.h>
+#endif
+...
+#ifdef CONFIG_GENERIC_ATMEL_MCI
+/* this is a weak define that we are overriding */
+int board_mmc_init(bd_t *bd)
+{
+ /* Enable clock */
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_MCI);
+ at91_mci_hw_init();
+
+ /* This calls the atmel_mci_init in gen_atmel_mci.c */
+ return atmel_mci_init((void *)AT91_BASE_MCI);
+}
+
+/* this is a weak define that we are overriding */
+int board_mmc_getcd(u8 *cd, struct mmc *mmc)
+{
+ /*
+ * the only currently existing use of this function
+ * (fsl_esdhc.c) suggests this function must return
+ * *cs = TRUE if a card is NOT detected -> in most
+ * cases the value of the pin when the detect switch
+ * closes to GND
+ */
+ *cd = at91_get_gpio_value (CONFIG_SYS_MMC_CD_PIN) ? 1 : 0;
+ return 0;
+}
+
+#endif
+
+and the board definition files needs:
+
+/* SD/MMC card */
+#define CONFIG_MMC 1
+#define CONFIG_GENERIC_MMC 1
+#define CONFIG_GENERIC_ATMEL_MCI 1
+#define CONFIG_ATMEL_MCI_PORTB 1 /* Atmel XE-EK uses port B */
+#define CONFIG_SYS_MMC_CD_PIN AT91_PIN_PC9
+#define CONFIG_CMD_MMC 1
+
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 8dfd8a32ba..6603d74294 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -25,12 +25,13 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libmmc.a
-COBJS-$(CONFIG_GENERIC_MMC) += mmc.o
COBJS-$(CONFIG_ATMEL_MCI) += atmel_mci.o
COBJS-$(CONFIG_BFIN_SDH) += bfin_sdh.o
-COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o
COBJS-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
+COBJS-$(CONFIG_GENERIC_MMC) += mmc.o
+COBJS-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o
+COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o
COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o
COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o
diff --git a/drivers/mmc/atmel_mci.h b/drivers/mmc/atmel_mci.h
index 5b4f5c99b6..823a77d91b 100644
--- a/drivers/mmc/atmel_mci.h
+++ b/drivers/mmc/atmel_mci.h
@@ -22,7 +22,45 @@
#ifndef __CPU_AT32AP_ATMEL_MCI_H__
#define __CPU_AT32AP_ATMEL_MCI_H__
-/* Atmel MultiMedia Card Interface (MCI) registers */
+#ifndef __ASSEMBLY__
+
+/*
+ * Structure for struct SoC access.
+ * Names starting with '_' are fillers.
+ */
+typedef struct atmel_mci {
+ /* reg Offset */
+ u32 cr; /* 0x00 */
+ u32 mr; /* 0x04 */
+ u32 dtor; /* 0x08 */
+ u32 sdcr; /* 0x0c */
+ u32 argr; /* 0x10 */
+ u32 cmdr; /* 0x14 */
+ u32 _18; /* 0x18 */
+ u32 _1c; /* 0x1c */
+ u32 rspr; /* 0x20 */
+ u32 rspr1; /* 0x24 */
+ u32 rspr2; /* 0x28 */
+ u32 rspr3; /* 0x2c */
+ u32 rdr; /* 0x30 */
+ u32 tdr; /* 0x34 */
+ u32 _38; /* 0x38 */
+ u32 _3c; /* 0x3c */
+ u32 sr; /* 0x40 */
+ u32 ier; /* 0x44 */
+ u32 idr; /* 0x48 */
+ u32 imr; /* 0x4c */
+} atmel_mci_t;
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * NOTICE: Use of registers offsets is depreciated.
+ * These defines will be removed once the old driver
+ * is taken out of commision.
+ *
+ * Atmel MultiMedia Card Interface (MCI) registers
+ */
#define MMCI_CR 0x0000
#define MMCI_MR 0x0004
#define MMCI_DTOR 0x0008
@@ -192,7 +230,13 @@
<< MMCI_##name##_OFFSET)) \
| MMCI_BF(name,value))
-/* Register access macros */
+/*
+ * NOTICE: Use of registers offsets is depreciated.
+ * These defines will be removed once the old driver
+ * is taken out of commision.
+ *
+ * Register access macros
+ */
#define mmci_readl(reg) \
readl((void *)MMCI_BASE + MMCI_##reg)
#define mmci_writel(reg,value) \
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
new file mode 100644
index 0000000000..fa4df9943a
--- /dev/null
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2010
+ * Rob Emanuele <rob@emanuele.us>
+ * Reinhard Meyer, EMK Elektronik <reinhard.meyer@emk-elektronik.de>
+ *
+ * Original Driver:
+ * Copyright (C) 2004-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
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <part.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/byteorder.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/memory-map.h>
+#include "atmel_mci.h"
+
+#ifndef CONFIG_SYS_MMC_CLK_OD
+# define CONFIG_SYS_MMC_CLK_OD 150000
+#endif
+
+#define MMC_DEFAULT_BLKLEN 512
+
+#if defined(CONFIG_ATMEL_MCI_PORTB)
+# define MCI_BUS 1
+#else
+# define MCI_BUS 0
+#endif
+
+static int initialized = 0;
+
+/*
+ * Print command and status:
+ *
+ * - always when DEBUG is defined
+ * - on command errors
+ */
+static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
+{
+ printf("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n",
+ cmdr, cmdr&0x3F, arg, status, msg);
+}
+
+/* Setup for MCI Clock and Block Size */
+static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
+{
+ atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
+ u32 bus_hz = get_mci_clk_rate();
+ u32 clkdiv = 255;
+
+ debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n",
+ bus_hz, hz, blklen);
+ if (hz > 0) {
+ /* find lowest clkdiv yielding a rate <= than requested */
+ for (clkdiv=0; clkdiv<255; clkdiv++) {
+ if ((bus_hz / (clkdiv+1) / 2) <= hz)
+ break;
+ }
+ }
+ printf("mci: setting clock %u Hz, block size %u\n",
+ (bus_hz / (clkdiv+1)) / 2, blklen);
+
+ blklen &= 0xfffc;
+ /* On some platforms RDPROOF and WRPROOF are ignored */
+ writel((MMCI_BF(CLKDIV, clkdiv)
+ | MMCI_BF(BLKLEN, blklen)
+ | MMCI_BIT(RDPROOF)
+ | MMCI_BIT(WRPROOF)), &mci->mr);
+ initialized = 1;
+}
+
+/* Return the CMDR with flags for a given command and data packet */
+static u32 mci_encode_cmd(
+ struct mmc_cmd *cmd, struct mmc_data *data, u32* error_flags)
+{
+ u32 cmdr = 0;
+
+ /* Default Flags for Errors */
+ *error_flags |= (MMCI_BIT(DTOE) | MMCI_BIT(RDIRE) | MMCI_BIT(RENDE) |
+ MMCI_BIT(RINDE) | MMCI_BIT(RTOE));
+
+ /* Default Flags for the Command */
+ cmdr |= MMCI_BIT(MAXLAT);
+
+ if (data) {
+ cmdr |= MMCI_BF(TRCMD, 1);
+ if (data->blocks > 1)
+ cmdr |= MMCI_BF(TRTYP, 1);
+ if (data->flags & MMC_DATA_READ)
+ cmdr |= MMCI_BIT(TRDIR);
+ }
+
+ if (cmd->resp_type & MMC_RSP_CRC)
+ *error_flags |= MMCI_BIT(RCRCE);
+ if (cmd->resp_type & MMC_RSP_136)
+ cmdr |= MMCI_BF(RSPTYP, 2);
+ else if (cmd->resp_type & MMC_RSP_BUSY)
+ cmdr |= MMCI_BF(RSPTYP, 3);
+ else if (cmd->resp_type & MMC_RSP_PRESENT)
+ cmdr |= MMCI_BF(RSPTYP, 1);
+
+ return cmdr | MMCI_BF(CMDNB, cmd->cmdidx);
+}
+
+/* Entered into function pointer in mci_send_cmd */
+static u32 mci_data_read(atmel_mci_t *mci, u32* data, u32 error_flags)
+{
+ u32 status;
+
+ do {
+ status = readl(&mci->sr);
+ if (status & (error_flags | MMCI_BIT(OVRE)))
+ goto io_fail;
+ } while (!(status & MMCI_BIT(RXRDY)));
+
+ if (status & MMCI_BIT(RXRDY)) {
+ *data = readl(&mci->rdr);
+ status = 0;
+ }
+io_fail:
+ return status;
+}
+
+/* Entered into function pointer in mci_send_cmd */
+static u32 mci_data_write(atmel_mci_t *mci, u32* data, u32 error_flags)
+{
+ u32 status;
+
+ do {
+ status = readl(&mci->sr);
+ if (status & (error_flags | MMCI_BIT(UNRE)))
+ goto io_fail;
+ } while (!(status & MMCI_BIT(TXRDY)));
+
+ if (status & MMCI_BIT(TXRDY)) {
+ writel(*data, &mci->tdr);
+ status = 0;
+ }
+io_fail:
+ return status;
+}
+
+/*
+ * Entered into mmc structure during driver init
+ *
+ * Sends a command out on the bus and deals with the block data.
+ * Takes the mmc pointer, a command pointer, and an optional data pointer.
+ */
+static int
+mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+ atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
+ u32 cmdr;
+ u32 error_flags = 0;
+ u32 status;
+
+ if (!initialized) {
+ puts ("MCI not initialized!\n");
+ return COMM_ERR;
+ }
+
+ /* Figure out the transfer arguments */
+ cmdr = mci_encode_cmd(cmd, data, &error_flags);
+
+ /* Send the command */
+ writel(cmd->cmdarg, &mci->argr);
+ writel(cmdr, &mci->cmdr);
+
+#ifdef DEBUG
+ dump_cmd(cmdr, cmd->cmdarg, 0, "DEBUG");
+#endif
+
+ /* Wait for the command to complete */
+ while (!((status = readl(&mci->sr)) & MMCI_BIT(CMDRDY)));
+
+ if (status & error_flags) {
+ dump_cmd(cmdr, cmd->cmdarg, status, "Command Failed");
+ return COMM_ERR;
+ }
+
+ /* Copy the response to the response buffer */
+ if (cmd->resp_type & MMC_RSP_136) {
+ cmd->response[0] = readl(&mci->rspr);
+ cmd->response[1] = readl(&mci->rspr1);
+ cmd->response[2] = readl(&mci->rspr2);
+ cmd->response[3] = readl(&mci->rspr3);
+ } else
+ cmd->response[0] = readl(&mci->rspr);
+
+ /* transfer all of the blocks */
+ if (data) {
+ u32 word_count, block_count;
+ u32* ioptr;
+ u32 sys_blocksize, dummy, i;
+ u32 (*mci_data_op)
+ (atmel_mci_t *mci, u32* data, u32 error_flags);
+
+ if (data->flags & MMC_DATA_READ) {
+ mci_data_op = mci_data_read;
+ sys_blocksize = mmc->read_bl_len;
+ ioptr = (u32*)data->dest;
+ } else {
+ mci_data_op = mci_data_write;
+ sys_blocksize = mmc->write_bl_len;
+ ioptr = (u32*)data->src;
+ }
+
+ status = 0;
+ for (block_count = 0;
+ block_count < data->blocks && !status;
+ block_count++) {
+ word_count = 0;
+ do {
+ status = mci_data_op(mci, ioptr, error_flags);
+ word_count++;
+ ioptr++;
+ } while (!status && word_count < (data->blocksize/4));
+#ifdef DEBUG
+ if (data->flags & MMC_DATA_READ)
+ {
+ printf("Read Data:\n");
+ print_buffer(0, data->dest, 1,
+ word_count*4, 0);
+ }
+#endif
+#ifdef DEBUG
+ if (!status && word_count < (sys_blocksize / 4))
+ printf("filling rest of block...\n");
+#endif
+ /* fill the rest of a full block */
+ while (!status && word_count < (sys_blocksize / 4)) {
+ status = mci_data_op(mci, &dummy,
+ error_flags);
+ word_count++;
+ }
+ if (status) {
+ dump_cmd(cmdr, cmd->cmdarg, status,
+ "Data Transfer Failed");
+ return COMM_ERR;
+ }
+ }
+
+ /* Wait for Transfer End */
+ i = 0;
+ do {
+ status = readl(&mci->sr);
+
+ if (status & error_flags) {
+ dump_cmd(cmdr, cmd->cmdarg, status,
+ "DTIP Wait Failed");
+ return COMM_ERR;
+ }
+ i++;
+ } while ((status & MMCI_BIT(DTIP)) && i < 10000);
+ if (status & MMCI_BIT(DTIP)) {
+ dump_cmd(cmdr, cmd->cmdarg, status,
+ "XFER DTIP never unset, ignoring");
+ }
+ }
+
+ return 0;
+}
+
+/* Entered into mmc structure during driver init */
+static void mci_set_ios(struct mmc *mmc)
+{
+ atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
+ int busw = (mmc->bus_width == 4) ? 1 : 0;
+
+ /* Set the clock speed */
+ mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
+
+ /*
+ * set the bus width and select slot for this interface
+ * there is no capability for multiple slots on the same interface yet
+ * Bitfield SCDBUS needs to be expanded to 2 bits for 8-bit buses
+ */
+ writel(MMCI_BF(SCDBUS, busw) | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
+}
+
+/* Entered into mmc structure during driver init */
+static int mci_init(struct mmc *mmc)
+{
+ atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
+
+ /* Initialize controller */
+ writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */
+ writel(MMCI_BIT(PWSDIS), &mci->cr); /* disable power save */
+ writel(MMCI_BIT(MCIEN), &mci->cr); /* enable mci */
+
+ /* Initial Time-outs */
+ writel(0x5f, &mci->dtor);
+ /* Disable Interrupts */
+ writel(~0UL, &mci->idr);
+
+ /* Set default clocks and blocklen */
+ mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
+
+ return 0;
+}
+
+/*
+ * This is the only exported function
+ *
+ * Call it with the MCI register base address
+ */
+int atmel_mci_init(void *regs)
+{
+ struct mmc *mmc = malloc(sizeof(struct mmc));
+
+ if (!mmc)
+ return -1;
+ strcpy(mmc->name, "mci");
+ mmc->priv = regs;
+ mmc->send_cmd = mci_send_cmd;
+ mmc->set_ios = mci_set_ios;
+ mmc->init = mci_init;
+
+ /* need to be able to pass these in on a board by board basis */
+ mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+ mmc->host_caps = MMC_MODE_4BIT;
+ /*
+ * min and max frequencies determined by
+ * max and min of clock divider
+ */
+ mmc->f_min = get_mci_clk_rate() / (2*256);
+ mmc->f_max = get_mci_clk_rate() / (2*1);
+
+ mmc_register(mmc);
+
+ return 0;
+}
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 772a49a902..98734db77f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -27,6 +27,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)librtc.a
+COBJS-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o
COBJS-$(CONFIG_RTC_BFIN) += bfin_rtc.o
COBJS-y += date.o
COBJS-$(CONFIG_RTC_DS12887) += ds12887.o
diff --git a/drivers/rtc/at91sam9_rtt.c b/drivers/rtc/at91sam9_rtt.c
new file mode 100644
index 0000000000..de8e30d0d7
--- /dev/null
+++ b/drivers/rtc/at91sam9_rtt.c
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2010
+ * Reinhard Meyer, reinhard.meyer@emk-elektronik.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
+ */
+
+/*
+ * Date & Time support for the internal Real-time Timer
+ * of AT91SAM9260 and compatibles.
+ * Compatible with the LinuX rtc driver workaround:
+ * The RTT cannot be written to, but only reset.
+ * The actual time is the sum of RTT and one of
+ * the four GPBR registers.
+ *
+ * The at91sam9260 has 4 GPBR (0-3).
+ * For their typical use see at91_gpbr.h !
+ *
+ * make sure u-boot and kernel use the same GPBR !
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <asm/errno.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/io.h>
+#include <asm/arch/at91_rtt.h>
+#include <asm/arch/at91_gpbr.h>
+
+#if defined(CONFIG_CMD_DATE)
+
+int rtc_get (struct rtc_time *tmp)
+{
+ at91_rtt_t *rtt = (at91_rtt_t *) AT91_RTT_BASE;
+ at91_gpbr_t *gpbr = (at91_gpbr_t *) AT91_GPR_BASE;
+ ulong tim;
+ ulong tim2;
+ ulong off;
+
+ do {
+ tim = readl(&rtt->vr);
+ tim2 = readl(&rtt->vr);
+ } while (tim!=tim2);
+ off = readl(&gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]);
+ /* off==0 means time is invalid, but we ignore that */
+ to_tm (tim+off, tmp);
+ return 0;
+}
+
+int rtc_set (struct rtc_time *tmp)
+{
+ at91_rtt_t *rtt = (at91_rtt_t *) AT91_RTT_BASE;
+ at91_gpbr_t *gpbr = (at91_gpbr_t *) AT91_GPR_BASE;
+ ulong tim;
+
+ tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+ /* clear alarm, set prescaler to 32768, clear counter */
+ writel(32768+AT91_RTT_RTTRST, &rtt->mr);
+ writel(~0, &rtt->ar);
+ writel(tim, &gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]);
+ /* wait for counter clear to happen, takes less than a 1/32768th second */
+ while (readl(&rtt->vr) != 0)
+ ;
+ return 0;
+}
+
+void rtc_reset (void)
+{
+ at91_rtt_t *rtt = (at91_rtt_t *) AT91_RTT_BASE;
+ at91_gpbr_t *gpbr = (at91_gpbr_t *) AT91_GPR_BASE;
+
+ /* clear alarm, set prescaler to 32768, clear counter */
+ writel(32768+AT91_RTT_RTTRST, &rtt->mr);
+ writel(~0, &rtt->ar);
+ writel(0, &gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]);
+ /* wait for counter clear to happen, takes less than a 1/32768th second */
+ while (readl(&rtt->vr) != 0)
+ ;
+}
+
+#endif
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 317c0b41b6..d0de931968 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -43,7 +43,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
u32 csrx;
void *regs;
- if (cs > 3 || !spi_cs_is_valid(bus, cs))
+ if (!spi_cs_is_valid(bus, cs))
return NULL;
switch (bus) {
@@ -168,8 +168,17 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
* somewhat quirky, and it doesn't really buy us much anyway
* in the context of U-Boot.
*/
- if (flags & SPI_XFER_BEGIN)
+ if (flags & SPI_XFER_BEGIN) {
spi_cs_activate(slave);
+ /*
+ * sometimes the RDR is not empty when we get here,
+ * in theory that should not happen, but it DOES happen.
+ * Read it here to be on the safe side.
+ * That also clears the OVRES flag. Required if the
+ * following loop exits due to OVRES!
+ */
+ spi_readl(as, RDR);
+ }
for (len_tx = 0, len_rx = 0; len_rx < len; ) {
status = spi_readl(as, SR);
diff --git a/include/configs/cpuat91.h b/include/configs/cpuat91.h
index 049298cfa3..9ef4523de4 100644
--- a/include/configs/cpuat91.h
+++ b/include/configs/cpuat91.h
@@ -1,5 +1,5 @@
/*
- * CPUAT91 by (C) Copyright 2006 Eric Benard
+ * CPUAT91 by (C) Copyright 2006-2010 Eric Benard
* eric@eukrea.com
*
* Configuration settings for the CPUAT91 board.
@@ -23,15 +23,12 @@
* MA 02111-1307 USA
*/
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-#define CONFIG_AT91_LEGACY
+#ifndef _CONFIG_CPUAT91_H
+#define _CONFIG_CPUAT91_H
#ifdef CONFIG_CPUAT91_RAM
#define CONFIG_SKIP_LOWLEVEL_INIT 1
#define CONFIG_SKIP_RELOCATE_UBOOT 1
-#define CONFIG_CPUAT91 1
#else
#define CONFIG_BOOTDELAY 1
#endif
@@ -43,6 +40,7 @@
#define CONFIG_ARM920T 1
#define CONFIG_AT91RM9200 1
+#define CONFIG_CPUAT91 1
#undef CONFIG_USE_IRQ
#define USE_920T_MMU 1
@@ -89,16 +87,36 @@
#undef CONFIG_USART0
#undef CONFIG_USART1
-#define CONFIG_HARD_I2C 1
+#undef CONFIG_HARD_I2C
+#define CONFIG_SOFT_I2C 1
+#define AT91_PIN_SDA (1<<25)
+#define AT91_PIN_SCL (1<<26)
+
+#define CONFIG_SYS_I2C_INIT_BOARD 1
+#define CONFIG_SYS_I2C_SPEED 50000
+#define CONFIG_SYS_I2C_SLAVE 0
+
+#define I2C_INIT i2c_init_board();
+#define I2C_ACTIVE writel(AT91_PMX_AA_TWD, &pio->pioa.mddr);
+#define I2C_TRISTATE writel(AT91_PMX_AA_TWD, &pio->pioa.mder);
+#define I2C_READ ((readl(&pio->pioa.pdsr) & AT91_PMX_AA_TWD) != 0)
+#define I2C_SDA(bit) \
+ if (bit) \
+ writel(AT91_PMX_AA_TWD, &pio->pioa.sodr); \
+ else \
+ writel(AT91_PMX_AA_TWD, &pio->pioa.codr);
+#define I2C_SCL(bit) \
+ if (bit) \
+ writel(AT91_PMX_AA_TWCK, &pio->pioa.sodr); \
+ else \
+ writel(AT91_PMX_AA_TWCK, &pio->pioa.codr);
+
+#define I2C_DELAY udelay(2500000/CONFIG_SYS_I2C_SPEED)
-#if defined(CONFIG_HARD_I2C)
-#define CONFIG_SYS_I2C_SPEED 50000
-#define CONFIG_SYS_I2C_SLAVE 0
#define CONFIG_SYS_I2C_EEPROM_ADDR 0x54
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
#define CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW 1
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10
-#endif
#define CONFIG_BOOTP_BOOTFILESIZE 1
#define CONFIG_BOOTP_BOOTPATH 1
@@ -117,10 +135,8 @@
#undef CONFIG_CMD_LOADS
#undef CONFIG_CMD_NFS
-#if defined(CONFIG_HARD_I2C)
#define CONFIG_CMD_EEPROM 1
#define CONFIG_CMD_I2C 1
-#endif
#define CONFIG_NR_DRAM_BANKS 1
#define PHYS_SDRAM 0x20000000
@@ -148,6 +164,7 @@
#define PHYS_FLASH_1 0x10000000
#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
#define CONFIG_SYS_MAX_FLASH_SECT 128
+#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
#if defined(CONFIG_CMD_USB)
#define CONFIG_USB_OHCI_NEW 1
@@ -206,7 +223,7 @@
"mtdparts=physmap-flash.0:" \
"128k(u-boot)ro," \
"128k(u-boot-env)," \
- "1408k(kernel)," \
+ "1792k(kernel)," \
"-(rootfs)"
#define CONFIG_BOOTARGS \
@@ -221,13 +238,13 @@
"1001FFFF; erase 10000000 1001FFFF; cp.b 21000000 " \
"10000000 ${filesize}\0" \
"flui=tftp 21000000 cpuat91/uImage; protect off 10040000 " \
- "1019ffff; erase 10040000 1019ffff; cp.b 21000000 " \
+ "1019ffff; erase 10040000 101fffff; cp.b 21000000 " \
"10040000 ${filesize}\0" \
"flrfs=tftp 21000000 cpuat91/rootfs.jffs2; protect off " \
- "101a0000 10ffffff; erase 101a0000 10ffffff; cp.b " \
- "21000000 101A0000 ${filesize}\0" \
+ "10200000 10ffffff; erase 10200000 10ffffff; cp.b " \
+ "21000000 10200000 ${filesize}\0" \
"ramargs=setenv bootargs $(bootargs) $(mtdparts)\0" \
"flashboot=run ramargs;bootm 10040000\0" \
"netboot=run ramargs;tftpboot 21000000 cpuat91/uImage;" \
"bootm 21000000\0"
-#endif /* __CONFIG_H */
+#endif /* _CONFIG_CPUAT91_H */
diff --git a/include/configs/meesc.h b/include/configs/meesc.h
index e085f4a47c..dbb2531439 100644
--- a/include/configs/meesc.h
+++ b/include/configs/meesc.h
@@ -3,7 +3,7 @@
* Stelian Pop <stelian.pop@leadtechdesign.com>
* Lead Tech Design <www.leadtechdesign.com>
*
- * (C) Copyright 2009
+ * (C) Copyright 2009-2010
* Daniel Gorsulowski <daniel.gorsulowski@esd.eu>
* esd electronic system design gmbh <www.esd.eu>
*
@@ -31,13 +31,12 @@
#ifndef __CONFIG_H
#define __CONFIG_H
-#define CONFIG_AT91_LEGACY
-
/* Common stuff */
-#define CONFIG_SYS_HZ 1000 /* decrementer freq */
#define CONFIG_MEESC 1 /* Board is esd MEESC */
#define CONFIG_ARM926EJS 1 /* This is an ARM926EJS Core */
#define CONFIG_AT91SAM9263 1 /* It's an AT91SAM9263 SoC */
+#define CONFIG_SYS_AT91_MAIN_CLOCK 16000000/* 16.0 MHz crystal */
+#define CONFIG_SYS_HZ 1000 /* decrementer freq */
#define CONFIG_DISPLAY_BOARDINFO 1
#define CONFIG_DISPLAY_CPUINFO 1 /* display cpu info and speed */
#define CONFIG_PREBOOT /* enable preboot variable */
@@ -85,11 +84,11 @@
#undef CONFIG_CMD_FPGA
#undef CONFIG_CMD_LOADS
#undef CONFIG_CMD_IMLS
-#undef CONFIG_CMD_USB
#define CONFIG_CMD_PING 1
#define CONFIG_CMD_DHCP 1
#define CONFIG_CMD_NAND 1
+#define CONFIG_CMD_USB 1
/* LED */
#define CONFIG_AT91_LED 1
@@ -121,9 +120,9 @@
#define CONFIG_SYS_NAND_MASK_ALE (1 << 21)
/* our CLE is AD22 */
#define CONFIG_SYS_NAND_MASK_CLE (1 << 22)
-#define CONFIG_SYS_NAND_ENABLE_PIN AT91_PIN_PD15
-#define CONFIG_SYS_NAND_READY_PIN AT91_PIN_PA22
-
+#define CONFIG_SYS_NAND_ENABLE_PIN AT91_PIO_PORTD, 15
+#define CONFIG_SYS_NAND_READY_PIN AT91_PIO_PORTA, 22
+#define CONFIG_SYS_64BIT_VSPRINTF /* needed for nand_util.c */
#endif
/* Ethernet */
@@ -133,6 +132,17 @@
#define CONFIG_NET_RETRY_COUNT 20
#undef CONFIG_RESET_PHY_R
+/* USB */
+#define CONFIG_USB_ATMEL
+#define CONFIG_USB_OHCI_NEW 1
+#define CONFIG_DOS_PARTITION 1
+#define CONFIG_SYS_USB_OHCI_CPU_INIT 1
+#define CONFIG_SYS_USB_OHCI_REGS_BASE 0x00a00000
+#define CONFIG_SYS_USB_OHCI_SLOT_NAME "at91sam9263"
+#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2
+#define CONFIG_USB_STORAGE 1
+#define CONFIG_CMD_FAT 1
+
#define CONFIG_SYS_LOAD_ADDR 0x22000000 /* load address */
#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM
diff --git a/include/configs/otc570.h b/include/configs/otc570.h
index fb0f576f45..4a1cedec0f 100644
--- a/include/configs/otc570.h
+++ b/include/configs/otc570.h
@@ -35,6 +35,7 @@
#define CONFIG_OTC570 1 /* Board is esd OTC570 */
#define CONFIG_ARM926EJS 1 /* This is an ARM926EJS Core */
#define CONFIG_AT91SAM9263 1 /* It's an AT91SAM9263 SoC */
+#define CONFIG_SYS_AT91_MAIN_CLOCK 16000000/* 16.0 MHz crystal */
#define CONFIG_SYS_HZ 1000 /* decrementer freq */
#define CONFIG_DISPLAY_BOARDINFO 1
#define CONFIG_DISPLAY_CPUINFO 1 /* display cpu info and speed */
diff --git a/include/mmc.h b/include/mmc.h
index fcb237e81e..9f94f423fb 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -179,6 +179,16 @@ struct mmc_cid {
char pnm[7];
};
+/*
+ * WARNING!
+ *
+ * This structure is used by atmel_mci.c only.
+ * It works for the AVR32 architecture but NOT
+ * for ARM/AT91 architectures.
+ * Its use is highly depreciated.
+ * After the atmel_mci.c driver for AVR32 has
+ * been replaced this structure will be removed.
+ */
struct mmc_csd
{
u8 csd_structure:2,
@@ -275,7 +285,10 @@ int mmc_set_dev(int dev_num);
void print_mmc_devices(char separator);
int board_mmc_getcd(u8 *cd, struct mmc *mmc);
-#ifndef CONFIG_GENERIC_MMC
+#ifdef CONFIG_GENERIC_MMC
+int atmel_mci_init(void *regs);
+#else
int mmc_legacy_init(int verbose);
#endif
+
#endif /* _MMC_H_ */