erasesize
Frederic Giasson
fgiasson at mediatrix.com
Tue Jun 5 13:40:38 EDT 2001
fgiasson at mediatrix.com said:
> Therefore, this is why I think that the length of the block to erase
> whould be passed by the user. At least, this is what the code suggest.
That's correct. The user should pass the length of the region to erase.
For example, if you have a chip which has 8 * 8K regions, then 15 * 64K,
the user may request that you erase 72K starting at offset 56K. That would
require the magic incantation to be issued once at offset 56K to erase that
8K block, and once at offset 64K to erase that 64K block.
--
dwmw2
We agree on that. Now I am questionning on the portabilty of the piece of
code below
( which belongs to cfi_amdstd_erase_varsize() ) between different CFI ( and
maybe even non-cfi ) flashes.
There is the reasons of my concern:
if( instr->addr > mtd->size )
{
printk( "cfi_amdstd_erase_varsize: Requested erase region begining
out of range!\n" );
printk( "instr->addr: %X, mtd->size: %d\n", instr->addr, mtd->size
);
return -EINVAL;
}
if( ( instr->len + instr->addr ) > mtd->size )
{
printk( "cfi_amdstd_erase_varsize: Requested erase region end out of
range!\n" );
printk( "instr->len: %X instr->addr: %X, mtd->size: %d\n",
instr->len, instr->addr, mtd->size );
return -EINVAL;
}
/* Check that both start and end of the requested erase are
* aligned with the erasesize at the appropriate addresses.
*/
/* Skip all erase regions which are ended before the start of
the requested erase. Actually, to save on the calculations,
we skip to the first erase region which starts after the
start of the requested erase, and then go back one.
*/
i = 0;
while( ( i < mtd->numeraseregions ) && ( instr->addr >=
regions[i].offset ) )
{
i++;
}
i--;
/* OK, now i is pointing at the erase region in which this
erase request starts. Check the start of the requested
erase range is aligned with the erase size which is in
effect here.
*/
if( instr->addr & ( regions[i].erasesize - 1 ) )
{
printk( "cfi_amdstd_erase_varsize: Erase region begin address as to
be aligned with physical sector.\n" );
return -EINVAL;
}
/* Remember the erase region we start on */
first = i;
/* Next, check that the end of the requested erase is aligned
* with the erase region at that address.
*/
while( ( i < mtd->numeraseregions ) && ( (instr->addr + instr->len)
>= regions[i].offset ) )
{
i++;
}
/* As before, drop back one to point at the region in which
the address actually falls
*/
i--;
if( (instr->addr + instr->len) & (regions[i].erasesize-1) )
{
printk( "cfi_amdstd_erase_varsize: End address is not aligned with
the region requested to be erased.\n" );
return -EINVAL;
}
Those 2 instructions ( from the code above)
if( instr->addr & ( regions[i].erasesize - 1 ) )
{
[return error]
}
and
if( (instr->addr + instr->len) & (regions[i].erasesize-1) )
{
[return error]
}
, which job are to ensure respectively that the start address of the block
to be erased is aligned
with the start of a physical sector, and that the instr->len is in a way so
that the block ends at
the very end of a physical sector, not a byte more or less.
With my flash ( Atmel, which is not CFI ) and probably most of the
existing flash memories on the market,
it does the job. However, it assumes 2 things:
- sectors must have power-2 sizes
- sectors must be aligned on a multiple of their own size.
For example, a 32KB sector beggining at address 24KB wouldn't be OK.
I never seen a flash physically mapped in
such a way, but maybe it is not always the case ( someone has the answer??
).
Whatever that answer would be, it would be safer to do as the code below
does:
// Searching for a sector that begins at the starting address of the
block
// requested to be erased
while( ( i < mtd->numeraseregions ) && ( instr->addr !=
regions[i].offset ) )
{
i++;
}
/* Remember the erase region we start on */
first = i;
// Searching for a sector that ends exactly at the last address of the
block
// requested to be erased
while(
( i < mtd->numeraseregions ) &&
(
( instr->addr + instr->len ) !=
( regions[i].offset + regions[i].erasesize )
)
)
{
i++;
}
This would be safer, without taking longer to execute.
Anyone disagree?
Frédéric Giasson
More information about the linux-mtd
mailing list