From 6052ac8386725056629357c197d13909ff0658eb Mon Sep 17 00:00:00 2001 From: Matthias Weisser Date: Mon, 9 Aug 2010 13:31:49 +0200 Subject: ARM: Add support for MB86R0x SoCs Signed-off-by: Matthias Weisser --- arch/arm/cpu/arm926ejs/mb86r0x/Makefile | 47 +++++++++++ arch/arm/cpu/arm926ejs/mb86r0x/clock.c | 43 ++++++++++ arch/arm/cpu/arm926ejs/mb86r0x/reset.c | 40 +++++++++ arch/arm/cpu/arm926ejs/mb86r0x/timer.c | 142 ++++++++++++++++++++++++++++++++ 4 files changed, 272 insertions(+) create mode 100644 arch/arm/cpu/arm926ejs/mb86r0x/Makefile create mode 100644 arch/arm/cpu/arm926ejs/mb86r0x/clock.c create mode 100644 arch/arm/cpu/arm926ejs/mb86r0x/reset.c create mode 100644 arch/arm/cpu/arm926ejs/mb86r0x/timer.c (limited to 'arch/arm/cpu/arm926ejs') diff --git a/arch/arm/cpu/arm926ejs/mb86r0x/Makefile b/arch/arm/cpu/arm926ejs/mb86r0x/Makefile new file mode 100644 index 0000000000..ce3e5a5a5a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mb86r0x/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = clock.o reset.o timer.o +SOBJS = + +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/arm926ejs/mb86r0x/clock.c b/arch/arm/cpu/arm926ejs/mb86r0x/clock.c new file mode 100644 index 0000000000..70c8c8b04a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mb86r0x/clock.c @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2010 + * Matthias Weisser + * + * 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 +#include +#include + +/* + * Get the peripheral bus frequency depending on pll pin settings + */ +ulong get_bus_freq(ulong dummy) +{ + struct mb86r0x_crg * crg = (struct mb86r0x_crg *) + MB86R0x_CRG_BASE; + uint32_t pllmode; + + pllmode = readl(&crg->crpr) & MB86R0x_CRG_CRPR_PLLMODE; + + if (pllmode == MB86R0x_CRG_CRPR_PLLMODE_X20) + return 40000000; + + return 41164767; +} diff --git a/arch/arm/cpu/arm926ejs/mb86r0x/reset.c b/arch/arm/cpu/arm926ejs/mb86r0x/reset.c new file mode 100644 index 0000000000..e7f0f6788b --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mb86r0x/reset.c @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2010 + * Matthias Weisser + * + * 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 +#include +#include + +/* + * Reset the cpu by setting software reset request bit + */ +void reset_cpu(ulong ignored) +{ + struct mb86r0x_crg * crg = (struct mb86r0x_crg *) + MB86R0x_CRG_BASE; + + writel(MB86R0x_CRSR_SWRSTREQ, &crg->crsr); + while (1) + /* NOP */; + /* Never reached */ +} diff --git a/arch/arm/cpu/arm926ejs/mb86r0x/timer.c b/arch/arm/cpu/arm926ejs/mb86r0x/timer.c new file mode 100644 index 0000000000..9175b71d16 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mb86r0x/timer.c @@ -0,0 +1,142 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop + * Lead Tech Design + * + * (C) Copyright 2010 + * Matthias Weisser, Graf-Syteco + * + * 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 +#include +#include +#include + +#define TIMER_LOAD_VAL 0xffffffff +#define TIMER_FREQ (CONFIG_MB86R0x_IOCLK / 256) + +static unsigned long long timestamp; +static ulong lastdec; + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, TIMER_FREQ); + + return tick; +} + +static inline unsigned long long usec_to_tick(unsigned long long usec) +{ + usec *= TIMER_FREQ; + do_div(usec, 1000000); + + return usec; +} + +/* nothing really to do with interrupts, just starts up a counter. */ +int timer_init(void) +{ + struct mb86r0x_timer * timer = (struct mb86r0x_timer *) + MB86R0x_TIMER_BASE; + ulong ctrl = readl(&timer->control); + + writel(TIMER_LOAD_VAL, &timer->load); + + ctrl |= MB86R0x_TIMER_ENABLE | MB86R0x_TIMER_PRS_8S | + MB86R0x_TIMER_SIZE_32; + + writel(ctrl, &timer->control); + + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ +unsigned long long get_ticks(void) +{ + struct mb86r0x_timer * timer = (struct mb86r0x_timer *) + MB86R0x_TIMER_BASE; + ulong now = readl(&timer->value); + + if (now <= lastdec) { + /* normal mode (non roll) */ + /* move stamp forward with absolut diff ticks */ + timestamp += lastdec - now; + } else { + /* we have rollover of incrementer */ + timestamp += lastdec + TIMER_LOAD_VAL - now; + } + lastdec = now; + return timestamp; +} + +void reset_timer_masked(void) +{ + struct mb86r0x_timer * timer = (struct mb86r0x_timer *) + MB86R0x_TIMER_BASE; + + /* capture current value time */ + lastdec = readl(&timer->value); + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked(void) +{ + return tick_to_time(get_ticks()); +} + +void __udelay(unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + tmo = usec_to_tick(usec); + tmp = get_ticks(); /* get current timestamp */ + + while ((get_ticks() - tmp) < tmo) /* loop till event */ + /*NOP*/; +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + ulong tbclk; + + tbclk = TIMER_FREQ; + return tbclk; +} -- cgit v1.2.3 From 4e4479a8922833025a8aac4f33fff9fa1e294ac9 Mon Sep 17 00:00:00 2001 From: Albert Aribaud <[albert.aribaud@free.fr]> Date: Thu, 26 Aug 2010 14:05:19 +0530 Subject: Orion5x: bugfix: window size (mis)calculation Fix orion5x_winctrl_calcsize() off-by-1 bug which caused mapping windows to be cut by half. This afected all windows including NOR flash (causing half the flash to be unaccessible) but DRAM was and still is fine as its size is determined otherwise. Signed-off-by: Albert Aribaud --- arch/arm/cpu/arm926ejs/orion5x/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu/arm926ejs') diff --git a/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/arch/arm/cpu/arm926ejs/orion5x/cpu.c index 3740e33e9d..260f88b46e 100644 --- a/arch/arm/cpu/arm926ejs/orion5x/cpu.c +++ b/arch/arm/cpu/arm926ejs/orion5x/cpu.c @@ -61,7 +61,7 @@ unsigned int orion5x_winctrl_calcsize(unsigned int sizeval) unsigned int j = 0; u32 val = sizeval >> 1; - for (i = 0; val > 0x10000; i++) { + for (i = 0; val >= 0x10000; i++) { j |= (1 << i); val = val >> 1; } -- cgit v1.2.3 From f106056095049c2c748c2a2797e5353295240e04 Mon Sep 17 00:00:00 2001 From: Prafulla Wadaskar Date: Thu, 26 Aug 2010 14:43:55 +0530 Subject: Kirkwood: bugfix: window size (mis)calculation Fixed kw_winctrl_calcsize() off-by-1 bug which caused mapping windows size to be cut by half. This corrected all windows address configuration Signed-off-by: Prafulla Wadaskar --- arch/arm/cpu/arm926ejs/kirkwood/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu/arm926ejs') diff --git a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c index c63e8641f2..82c978bd93 100644 --- a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c +++ b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c @@ -81,7 +81,7 @@ unsigned int kw_winctrl_calcsize(unsigned int sizeval) unsigned int j = 0; u32 val = sizeval >> 1; - for (i = 0; val > 0x10000; i++) { + for (i = 0; val >= 0x10000; i++) { j |= (1 << i); val = val >> 1; } -- cgit v1.2.3 From c982d866eaee5e8469af9e22eb8f51c63adcfafa Mon Sep 17 00:00:00 2001 From: Jens Scharsig Date: Sat, 7 Aug 2010 19:49:42 +0200 Subject: AT91 Fix: return value of get_tbclk * Fix: return value of get_tbclk * this fixes issue with prematurely restart/retry, if BOOT_RETRY_TIMEOUT is used Signed-off-by: Jens Scharsig --- arch/arm/cpu/arm926ejs/at91/timer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/arm/cpu/arm926ejs') 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; } -- cgit v1.2.3 From 1592ef8596fffd937a30462eb15f1d64e237ae49 Mon Sep 17 00:00:00 2001 From: Reinhard Meyer Date: Fri, 13 Aug 2010 10:31:06 +0200 Subject: AT91: MCI: add SD/MMC driver using mmc framework Signed-off-by: Reinhard Meyer --- arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'arch/arm/cpu/arm926ejs') diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c index 77d49ab1c7..2d8848152a 100644 --- a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c +++ b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c @@ -194,3 +194,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 + -- cgit v1.2.3 From d88bebe16d8141e85adcc894a10165a6dfd44805 Mon Sep 17 00:00:00 2001 From: Reinhard Meyer Date: Tue, 27 Jul 2010 15:18:38 +0200 Subject: AT91SAM9XE: add embedded flash support Signed-off-by: Reinhard Meyer --- arch/arm/cpu/arm926ejs/at91/Makefile | 1 + arch/arm/cpu/arm926ejs/at91/eflash.c | 271 +++++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 arch/arm/cpu/arm926ejs/at91/eflash.c (limited to 'arch/arm/cpu/arm926ejs') 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/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 +#include +#include +#include +#include +#include + +/* 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; ifrr); /* 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; ifrr); /* 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; ifrr); + 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; isector_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; isector_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; +} + -- cgit v1.2.3 From e0cd44c3c1209c281d67b18372e584b143885303 Mon Sep 17 00:00:00 2001 From: Reinhard Meyer Date: Mon, 9 Aug 2010 13:25:37 +0200 Subject: AT91: reset.c: fix comments, add option Signed-off-by: Reinhard Meyer --- arch/arm/cpu/arm926ejs/at91/reset.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'arch/arm/cpu/arm926ejs') 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 #include -/* - * 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) + ; } -- cgit v1.2.3 From 7588ad12bafe596c273e13cd80bb3bfbac0e08c7 Mon Sep 17 00:00:00 2001 From: Reinhard Meyer Date: Wed, 25 Aug 2010 12:32:53 +0200 Subject: AT91: add option to enable pullups in at91sam9260_devices.c Signed-off-by: Reinhard Meyer --- arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c | 35 ++++++++++++++++------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'arch/arm/cpu/arm926ejs') diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c b/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c index 2d8848152a..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 #include +/* + * 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); -- cgit v1.2.3