This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
Re: at91sam7s patch for PIT EFC PMC all in one...
- From: Andrew Lunn <andrew at lunn dot ch>
- To: "oliver munz @ s p e a g" <munz at speag dot ch>
- Cc: ecos-patches at sourceware dot org
- Date: Sat, 13 Jun 2009 17:13:07 +0200
- Subject: Re: at91sam7s patch for PIT EFC PMC all in one...
- References: <4A27893B.8070303@speag.ch>
On Thu, Jun 04, 2009 at 10:43:39AM +0200, oliver munz @ s p e a g wrote:
> Hier comes the announced patch:
>
> 1. It allows the use of the second flash in the 512k devices.
> 2. It solves a possible problem with a late PIT-initalisation.
> 3. It improves the startup-time and prevents changes in the holly
> system-clock when booting from a boot-monitor.
> 4. It removes a spaces at the end of the line.
>
Hi Oliver
I committed your hal changes.
The flash changes i reworked a little. I simplified the conditional
compilation of the code. Since many of the functions in the driver are
inlined, the compiler should be able to throw away a lot of unneeded
code itself when there is only one Flash controller. This makes the
code more readable.
However, i could not test this. So please can you test the attached
patch.
Thanks
Andrew
Index: devs/flash/arm/at91/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/arm/at91/current/ChangeLog,v
retrieving revision 1.11
diff -u -r1.11 ChangeLog
--- devs/flash/arm/at91/current/ChangeLog 29 Jan 2009 17:48:19 -0000 1.11
+++ devs/flash/arm/at91/current/ChangeLog 13 Jun 2009 15:12:55 -0000
@@ -1,3 +1,8 @@
+2009-06-13 Andrew Lunn <andrew@lunn.ch>
+2009-06-03 Oliver Munz <munz@speag.ch>
+
+ * src/at91_flash.c: Add support for 512kByte-devices.
+
2008-11-17 Jonathan Larmour <jifl@eCosCentric.com>
* src/at91_flash.c: Explicitly include <cyg/io/flash_dev.h> rather
Index: devs/flash/arm/at91/current/src/at91_flash.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/arm/at91/current/src/at91_flash.c,v
retrieving revision 1.11
diff -u -r1.11 at91_flash.c
--- devs/flash/arm/at91/current/src/at91_flash.c 29 Jan 2009 17:48:19 -0000 1.11
+++ devs/flash/arm/at91/current/src/at91_flash.c 13 Jun 2009 15:12:56 -0000
@@ -2,14 +2,15 @@
//
// at91_flash.c
//
-// Flash programming for the at91 devices which have the
+// Flash programming for the at91 devices which have the
// Embedded Flash Controller.
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006 Free Software Foundation, Inc.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006 Free Software
+// Foundation, Inc.
//
// eCos 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
@@ -41,11 +42,11 @@
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
-// Contributors: gthomas, dmoseley, Andrew Lunn, Oliver Munz
-// Date: 2000-07-26
-// Purpose:
-// Description:
-//
+// Contributors: gthomas, dmoseley, Andrew Lunn, Oliver Munz, Kasim Malla
+// Date: 2009-06-03
+// Purpose:
+// Description:
+//
//####DESCRIPTIONEND####
//
//==========================================================================
@@ -53,7 +54,7 @@
#include <pkgconf/hal.h>
#include <pkgconf/devs_flash_at91.h>
-#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_io.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/infra/cyg_ass.h>
@@ -62,7 +63,10 @@
#include <string.h>
-#define FLASH_TIMEOUT 100000
+/* Stupid timeout depends of the CPU clock speed */
+#define FLASH_TIMEOUT 100000
+#define AT91_FLASH_FMCN_VALUE \
+ (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED * 15 / 10000000 + 1)
#ifdef CYGBLD_DEV_FLASH_AT91_LOCKING
static cyg_uint32 sector_size;
@@ -70,53 +74,71 @@
// Disable the flash controller from erasing the page before
// programming it
-static void
+
+#ifdef AT91_MC_FMR1
+ #define PAGE_AT_WHICH_WE_USE_THE_EFC1 1024
+ #define SECTOR_AT_WHICH_WE_USE_THE_EFC1 16
+#endif
+
+
+static void
flash_erase_before_write_disable (void)
{
cyg_uint32 fmr;
-
+
HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, fmr);
fmr = fmr | AT91_MC_FMR_NEBP;
HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, fmr);
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+ HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR1, fmr);
+#endif
}
// Enable the flash controller to erase the page before programming
// it
-static void
-flash_erase_before_write_enable (void)
+static void
+flash_erase_before_write_enable (void)
{
-
+
cyg_uint32 fmr;
HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, fmr);
fmr = fmr & ~((cyg_uint32) AT91_MC_FMR_NEBP);
HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, fmr);
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+ HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR1, fmr);
+#endif
}
// Is the flash controller ready to accept the next command?
-static __inline__ cyg_bool
-flash_controller_is_ready(void)
+static __inline__ cyg_bool
+flash_controller_is_ready(cyg_uint32 page)
CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
-static __inline__ cyg_bool
-flash_controller_is_ready(void)
+static __inline__ cyg_bool
+flash_controller_is_ready(cyg_uint32 page)
{
cyg_uint32 fsr;
+#ifdef AT91_MC_FMR1
+ if (page >= PAGE_AT_WHICH_WE_USE_THE_EFC1){
+ HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
+ } else
+#endif
+ HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
- HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
return (fsr & AT91_MC_FSR_FRDY ? true : false);
}
// Busy loop waiting for the controller to finish the command.
// Wait a maximum of timeout loops and then return an error.
-static __inline__ int
-flash_wait_for_controller (cyg_uint32 timeout)
+static __inline__ int
+flash_wait_for_controller (cyg_uint32 page, cyg_uint32 timeout)
CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
-static __inline__ int
-flash_wait_for_controller (cyg_uint32 timeout)
+static __inline__ int
+flash_wait_for_controller (cyg_uint32 page, cyg_uint32 timeout)
{
- while (!flash_controller_is_ready()){
+ while (!flash_controller_is_ready(page)){
timeout--;
if (!timeout) {
return FLASH_ERR_DRV_TIMEOUT;
@@ -128,40 +150,53 @@
// Execute one command on the flash controller. This code should
// probably not be in flash
-static int
-flash_run_command(cyg_uint32 address,
- cyg_uint32 command,
- cyg_uint32 timeout)
+static int
+flash_run_command(cyg_uint32 address,
+ cyg_uint32 command,
+ cyg_uint32 timeout)
CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
-static int
-flash_run_command(cyg_uint32 address,
- cyg_uint32 command,
- cyg_uint32 timeout)
+static int
+flash_run_command(cyg_uint32 address,
+ cyg_uint32 command,
+ cyg_uint32 timeout)
{
cyg_uint32 retcode;
cyg_uint32 fsr;
cyg_uint32 mask;
cyg_uint32 page;
+ cyg_uint32 page_in_flash;
+ cyg_uint32 fcr_addr = AT91_MC+AT91_MC_FCR;
+ cyg_uint32 fsr_addr= AT91_MC+AT91_MC_FSR;
- page = ((cyg_uint32) address - (cyg_uint32) flash_info.start) /
+ page = ((cyg_uint32) address - (cyg_uint32) flash_info.start) /
flash_info.block_size;
+ page_in_flash = page;
+
+#ifdef AT91_MC_FMR1
+ if (page >= PAGE_AT_WHICH_WE_USE_THE_EFC1){
+ fcr_addr = AT91_MC+AT91_MC_FCR1;
+ fsr_addr = AT91_MC+AT91_MC_FSR1;
+ page_in_flash = page - PAGE_AT_WHICH_WE_USE_THE_EFC1;
+ }
+#endif
// Wait for the last command to finish
- retcode = flash_wait_for_controller(timeout);
+ retcode = flash_wait_for_controller(page, timeout);
if (retcode != FLASH_ERR_OK){
return retcode;
}
-
- HAL_DISABLE_INTERRUPTS(mask);
-
- HAL_WRITE_UINT32(AT91_MC+AT91_MC_FCR,
- command |
- ((page & AT91_MC_FCR_PAGE_MASK) << AT91_MC_FCR_PAGE_SHIFT) |
- AT91_MC_FCR_KEY);
- retcode = flash_wait_for_controller(timeout);
+ HAL_DISABLE_INTERRUPTS(mask);
+ HAL_WRITE_UINT32(fcr_addr,
+ command |
+ ((page_in_flash & AT91_MC_FCR_PAGE_MASK)
+ << AT91_MC_FCR_PAGE_SHIFT) |
+ AT91_MC_FCR_KEY);
+
+ retcode = flash_wait_for_controller(page, timeout);
+
HAL_RESTORE_INTERRUPTS(mask);
if (retcode != FLASH_ERR_OK){
@@ -169,7 +204,7 @@
}
// Check for an error
- HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
+ HAL_READ_UINT32(fsr_addr, fsr);
if ((fsr & AT91_MC_FSR_LOCKE) == AT91_MC_FSR_LOCKE)
return FLASH_ERR_PROTECT;
@@ -182,12 +217,12 @@
// The flash is embedded in the CPU package. So return the chip
// ID. This allows us to determine if the chip is one we support and
// the size of the flash
-int flash_query(void *data)
+int flash_query(void *data)
{
cyg_uint32 chipID1r;
-
+
HAL_READ_UINT32(AT91_DBG+AT91_DBG_C1R, chipID1r);
-
+
memcpy(data, &chipID1r, sizeof(chipID1r));
return FLASH_ERR_OK;
}
@@ -197,14 +232,13 @@
// the number of blocks. The query function returns the chip ID 1
// register which tells us about the CPU we are running on, the flash
// size etc. Use this information to determine we have a valid setup.
-int
+int
flash_hwr_init(void){
cyg_uint32 chipID1r;
cyg_uint32 flash_mode;
- cyg_uint8 fmcn;
cyg_uint32 lock_bits;
-
+
flash_query (&chipID1r);
if ((chipID1r & AT91_DBG_C1R_CPU_MASK) != AT91_DBG_C1R_ARM7TDMI)
@@ -215,103 +249,103 @@
((chipID1r & AT91_DBG_C1R_ARCH_MASK) != AT91_DBG_C1R_ARCH_AT91SAM7XC) &&
((chipID1r & AT91_DBG_C1R_ARCH_MASK) != AT91_DBG_C1R_ARCH_AT91SAM7SExx))
goto out;
-
+
if ((chipID1r & AT91_DBG_C1R_FLASH_MASK) == AT91_DBG_C1R_FLASH_0K)
goto out;
-
- if ((chipID1r & AT91_DBG_C1R_NVPTYP_MASK) != AT91_DBG_C1R_NVPTYP_ROMFLASH)
- {
- switch (chipID1r & AT91_DBG_C1R_FLASH_MASK) {
- case AT91_DBG_C1R_FLASH_32K:
- flash_info.block_size = 128;
- flash_info.blocks = 256;
- lock_bits = 8;
- break;
- case AT91_DBG_C1R_FLASH_64K:
- flash_info.block_size = 128;
- flash_info.blocks = 512;
- lock_bits = 16;
- break;
- case AT91_DBG_C1R_FLASH_128K:
- flash_info.block_size = 256;
- flash_info.blocks = 512;
- lock_bits = 8;
- break;
- case AT91_DBG_C1R_FLASH_256K:
- flash_info.block_size = 256;
- flash_info.blocks = 1024;
- lock_bits = 16;
- break;
+
+ if ((chipID1r & AT91_DBG_C1R_NVPTYP_MASK) != AT91_DBG_C1R_NVPTYP_ROMFLASH) {
+ switch (chipID1r & AT91_DBG_C1R_FLASH_MASK) {
+ case AT91_DBG_C1R_FLASH_32K:
+ flash_info.block_size = 128;
+ flash_info.blocks = 256;
+ lock_bits = 8;
+ break;
+ case AT91_DBG_C1R_FLASH_64K:
+ flash_info.block_size = 128;
+ flash_info.blocks = 512;
+ lock_bits = 16;
+ break;
+ case AT91_DBG_C1R_FLASH_128K:
+ flash_info.block_size = 256;
+ flash_info.blocks = 512;
+ lock_bits = 8;
+ break;
+ case AT91_DBG_C1R_FLASH_256K:
+ flash_info.block_size = 256;
+ flash_info.blocks = 1024;
+ lock_bits = 16;
+ break;
+ case AT91_DBG_C1R_FLASH_512K:
+ flash_info.block_size = 256;
#ifdef AT91_MC_FMR1
- case AT91_DBG_C1R_FLASH_512K:
- flash_info.block_size = 256;
- flash_info.blocks = 1024;
- lock_bits = 16;
- (*flash_info.pf)("at91_flash: Only EFC0 is supported for writes and locks");
- //flash_info.blocks = 2048;
- //lock_bits = 32;
- break;
-#endif
- default:
- goto out;
- }
+ flash_info.blocks = 2048;
+ lock_bits = 32;
+#else
+ flash_info.blocks = 1024;
+ lock_bits = 16;
+ (*flash_info.pf)
+ ("at91_flash: Only EFC0 is supported for writes and locks");
+#endif
+ break;
+ default:
+ goto out;
+ }
} else {
- // if there is both flash & ROM then: ROM=AT91_DBG_C1R_FLASH, flash=AT91_DBG_C1R_FLASH2
- switch (chipID1r & AT91_DBG_C1R_FLASH2_MASK) {
- case AT91_DBG_C1R_FLASH2_32K:
- flash_info.block_size = 128;
- flash_info.blocks = 256;
- lock_bits = 8;
- break;
- case AT91_DBG_C1R_FLASH2_64K:
- flash_info.block_size = 128;
- flash_info.blocks = 512;
- lock_bits = 16;
- break;
- case AT91_DBG_C1R_FLASH2_128K:
- flash_info.block_size = 256;
- flash_info.blocks = 512;
- lock_bits = 8;
- break;
- case AT91_DBG_C1R_FLASH2_256K:
- flash_info.block_size = 256;
- flash_info.blocks = 1024;
- lock_bits = 16;
- break;
+ // if there is both flash & ROM then:
+ // ROM=AT91_DBG_C1R_FLASH, flash=AT91_DBG_C1R_FLASH2
+ switch (chipID1r & AT91_DBG_C1R_FLASH2_MASK) {
+ case AT91_DBG_C1R_FLASH2_32K:
+ flash_info.block_size = 128;
+ flash_info.blocks = 256;
+ lock_bits = 8;
+ break;
+ case AT91_DBG_C1R_FLASH2_64K:
+ flash_info.block_size = 128;
+ flash_info.blocks = 512;
+ lock_bits = 16;
+ break;
+ case AT91_DBG_C1R_FLASH2_128K:
+ flash_info.block_size = 256;
+ flash_info.blocks = 512;
+ lock_bits = 8;
+ break;
+ case AT91_DBG_C1R_FLASH2_256K:
+ flash_info.block_size = 256;
+ flash_info.blocks = 1024;
+ lock_bits = 16;
+ break;
+ case AT91_DBG_C1R_FLASH2_512K:
+ flash_info.block_size = 256;
#ifdef AT91_MC_FMR1
- case AT91_DBG_C1R_FLASH2_512K:
- flash_info.block_size = 256;
- flash_info.blocks = 1024;
- lock_bits = 16;
- (*flash_info.pf)("at91_flash: Only EFC0 is supported for writes and locks");
- //flash_info.blocks = 2048;
- //lock_bits = 32;
- break;
+ flash_info.blocks = 2048;
+ lock_bits = 32;
+#else
+ flash_info.blocks = 1024;
+ lock_bits = 16;
+ (*flash_info.pf)
+ ("at91_flash: Only EFC0 is supported for writes and locks");
#endif
- default:
- goto out;
- }
+ break;
+ default:
+ goto out;
+ }
}
flash_info.buffer_size = 0;
flash_info.start = (void *) 0x00100000;
- flash_info.end = (void *)(((cyg_uint32) flash_info.start) +
+ flash_info.end = (void *)(((cyg_uint32) flash_info.start) +
flash_info.block_size * flash_info.blocks);
#ifdef CYGBLD_DEV_FLASH_AT91_LOCKING
sector_size = flash_info.block_size * flash_info.blocks / lock_bits;
#endif
// Set the FLASH clock to 1.5 microseconds based on the MCLK. This
// assumes the CPU is still running from the PLL clock as defined in
- // the HAL CDL and the HAL startup code.
- fmcn = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED * 1.5 / 1000000 + 0.999999; // We must round up!
+ // the HAL CDL and the HAL startup code.
HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, flash_mode);
flash_mode = flash_mode & ~AT91_MC_FMR_FMCN_MASK;
- flash_mode = flash_mode | (fmcn << AT91_MC_FMR_FMCN_SHIFT);
+ flash_mode = flash_mode | (AT91_FLASH_FMCN_VALUE << AT91_MC_FMR_FMCN_SHIFT);
HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, flash_mode);
#ifdef AT91_MC_FMR1
- HAL_READ_UINT32(AT91_MC+AT91_MC_FMR1, flash_mode);
- flash_mode = flash_mode & ~AT91_MC_FMR_FMCN_MASK;
- flash_mode = flash_mode | (fmcn << AT91_MC_FMR_FMCN_SHIFT);
HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR1, flash_mode);
#endif
@@ -326,26 +360,26 @@
// Erase a block. The flash controller does not have a command to
// erase a block. So instead we setup the controller to do a program
// writing all 0xff with an erase operation first.
-int
-flash_erase_block (volatile unsigned long block)
+int
+flash_erase_block (volatile unsigned long block)
{
cyg_uint32 retcode;
cyg_uint32 *buffer;
cyg_uint32 *end;
-
+
buffer = (cyg_uint32 *) block;
end = (cyg_uint32 *) (block + flash_info.block_size);
-
- while (buffer < end){
+
+ while (buffer < end){
*buffer = (cyg_uint32) 0xffffffff;
buffer++;
}
-
+
flash_erase_before_write_enable();
- retcode = flash_run_command(block,
- AT91_MC_FCR_START_PROG,
+ retcode = flash_run_command(block,
+ AT91_MC_FCR_START_PROG,
FLASH_TIMEOUT);
-
+
return retcode;
}
@@ -354,29 +388,29 @@
// checks that these conditions are upheld. It would be possible to
// perform extra reads and masking operation to support writing to
// none word assigned addresses or not multiple or a word length.
-int
+int
flash_program_buf (volatile unsigned long addr, unsigned long *data, int len)
{
cyg_uint32 retcode;
volatile unsigned long *target;
-
+
CYG_ASSERT(len % 4 == 0, "Only word writes allowed by current code");
CYG_ASSERT(addr % 4 == 0, "Address must be word aligned for current code");
-
+
target = (volatile unsigned long *)addr;
-
+
while (len > 0) {
*target = *data;
data++;
target++;
len = len - sizeof(unsigned long);
}
-
+
flash_erase_before_write_disable();
- retcode = flash_run_command(addr,
- AT91_MC_FCR_START_PROG,
+ retcode = flash_run_command(addr,
+ AT91_MC_FCR_START_PROG,
FLASH_TIMEOUT);
-
+
return retcode;
}
@@ -390,17 +424,24 @@
cyg_uint32 sector;
cyg_uint32 retcode;
cyg_uint32 status;
+ cyg_uint32 fsr_addr = AT91_MC + AT91_MC_FSR;
- sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) /
+ sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) /
sector_size;
-
- HAL_READ_UINT32(AT91_MC + AT91_MC_FSR, status);
+
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+ if (sector >= SECTOR_AT_WHICH_WE_USE_THE_EFC1){
+ fsr_addr = AT91_MC + AT91_MC_FSR1;
+ sector -= SECTOR_AT_WHICH_WE_USE_THE_EFC1;
+ }
+#endif
+ HAL_READ_UINT32(fsr_addr, status);
if (status & (1 << (sector + 16))){
- retcode = flash_run_command(block,
- AT91_MC_FCR_UNLOCK,
- FLASH_TIMEOUT);
- return retcode;
+ retcode = flash_run_command(block,
+ AT91_MC_FCR_UNLOCK,
+ FLASH_TIMEOUT);
+ return retcode;
} else {
return FLASH_ERR_OK;
}
@@ -415,24 +456,31 @@
cyg_uint32 sector;
cyg_uint32 retcode;
cyg_uint32 status;
+ cyg_uint32 fsr_addr = AT91_MC + AT91_MC_FSR;
- sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) /
+ sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) /
sector_size;
-
- HAL_READ_UINT32(AT91_MC + AT91_MC_FSR, status);
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+ if (sector >= SECTOR_AT_WHICH_WE_USE_THE_EFC1){
+ fsr_addr = AT91_MC + AT91_MC_FSR1;
+ sector -= SECTOR_AT_WHICH_WE_USE_THE_EFC1;
+ }
+#endif
+ HAL_READ_UINT32(fsr_addr, status);
+
if (!(status & (1 << (sector + 16)))){
- retcode = flash_run_command(block,
- AT91_MC_FCR_LOCK,
- FLASH_TIMEOUT);
-
- return retcode;
+ retcode = flash_run_command(block,
+ AT91_MC_FCR_LOCK,
+ FLASH_TIMEOUT);
+
+ return retcode;
} else {
return FLASH_ERR_OK;
}
}
-#endif
-
+#endif /*CYGBLD_DEV_FLASH_AT91_LOCKING */
+
// Map a hardware status to a package error. NOP since the errors are
// already mapped.
int flash_hwr_map_error(int err){