mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 23:51:33 +00:00
Merge branch 'at91' of git://git.denx.de/u-boot-atmel
This commit is contained in:
commit
cf64fda38e
28 changed files with 1278 additions and 148 deletions
2
Makefile
2
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
271
arch/arm/cpu/arm926ejs/at91/eflash.c
Normal file
271
arch/arm/cpu/arm926ejs/at91/eflash.c
Normal file
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
;
|
||||
}
|
||||
|
|
|
@ -138,8 +138,5 @@ ulong get_timer(ulong base)
|
|||
*/
|
||||
ulong get_tbclk(void)
|
||||
{
|
||||
ulong tbclk;
|
||||
|
||||
tbclk = CONFIG_SYS_HZ;
|
||||
return tbclk;
|
||||
return timer_freq;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
41
arch/arm/include/asm/arch-at91/at91_dbu.h
Normal file
41
arch/arm/include/asm/arch-at91/at91_dbu.h
Normal file
|
@ -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
|
51
arch/arm/include/asm/arch-at91/at91_eefc.h
Normal file
51
arch/arm/include/asm/arch-at91/at91_eefc.h
Normal file
|
@ -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
|
45
arch/arm/include/asm/arch-at91/at91_gpbr.h
Normal file
45
arch/arm/include/asm/arch-at91/at91_gpbr.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
36
arch/arm/include/asm/arch-at91/at91_rtt.h
Normal file
36
arch/arm/include/asm/arch-at91/at91_rtt.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
@ -270,6 +275,9 @@ int board_init(void)
|
|||
#endif
|
||||
#ifdef CONFIG_AT91_CAN
|
||||
at91_can_hw_init();
|
||||
#endif
|
||||
#ifdef CONFIG_USB_OHCI_NEW
|
||||
at91_uhp_hw_init();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
86
doc/README.atmel_mci
Normal file
86
doc/README.atmel_mci
Normal file
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) \
|
||||
|
|
353
drivers/mmc/gen_atmel_mci.c
Normal file
353
drivers/mmc/gen_atmel_mci.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
100
drivers/rtc/at91sam9_rtt.c
Normal file
100
drivers/rtc/at91sam9_rtt.c
Normal file
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
Loading…
Reference in a new issue