Commit 4404f73b authored by Stefan Tauner's avatar Stefan Tauner
Browse files

Cleanup ST M50 driver


There are two locking strategies used by this umbrella family, one uniform
and one that matches the sector layout of the chip. Refactor the functions
involved and rename the overly complicated file to just stm50.c and the
functions accordingly.

This fixes unlocking of some of the non-uniform chips and gets rid of the
abuse of page_size.

Corresponding to flashrom svn r1736.
Signed-off-by: default avatarStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: default avatarStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
parent 4c6d3a4b
......@@ -89,6 +89,7 @@ int probe_82802ab(struct flashctx *flash)
return 1;
}
/* FIXME: needs timeout */
uint8_t wait_82802ab(struct flashctx *flash)
{
uint8_t status;
......
......@@ -320,7 +320,7 @@ endif
###############################################################################
# Flash chip drivers and bus support infrastructure.
CHIP_OBJS = jedec.o stm50flw0x0x.o w39.o w29ee011.o \
CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
sst28sf040.o m29f400bt.o 82802ab.o pm49fl00x.o \
sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o spi25_statusreg.o \
opaque.o sfdp.o en29lv640b.o at45db.o
......
......@@ -193,9 +193,10 @@ int printlock_at49f(struct flashctx *flash);
/* w29ee011.c */
int probe_w29ee011(struct flashctx *flash);
/* stm50flw0x0x.c */
int erase_sector_stm50flw0x0x(struct flashctx *flash, unsigned int block, unsigned int blocksize);
int unlock_stm50flw0x0x(struct flashctx *flash);
/* stm50.c */
int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int blocksize);
int unlock_stm50_uniform(struct flashctx *flash);
int unlock_stm50_nonuniform(struct flashctx *flash);
/* en29lv640b.c */
int probe_en29lv640b(struct flashctx *flash);
......
......@@ -11008,7 +11008,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50FLW040A,
.total_size = 512,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_UNTESTED,
.probe = probe_82802ab,
......@@ -11028,8 +11028,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.write = write_82802ab,
.unlock = unlock_stm50_uniform,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
},
......@@ -11041,7 +11041,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50FLW040B,
.total_size = 512,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_UNTESTED,
.probe = probe_82802ab,
......@@ -11061,8 +11061,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.write = write_82802ab,
.unlock = unlock_stm50_uniform,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
},
......@@ -11074,7 +11074,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50FLW080A,
.total_size = 1024,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_OK_PRE,
.probe = probe_82802ab,
......@@ -11094,7 +11094,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.unlock = unlock_stm50_nonuniform,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11107,7 +11107,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50FLW080B,
.total_size = 1024,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_UNTESTED,
.probe = probe_82802ab,
......@@ -11127,7 +11127,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.unlock = unlock_stm50_nonuniform,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11140,7 +11140,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50FW002,
.total_size = 256,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_UNTESTED,
.probe = probe_82802ab,
......@@ -11157,7 +11157,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.unlock = unlock_stm50_nonuniform,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11170,7 +11170,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50FW016,
.total_size = 2048,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_UNTESTED,
.probe = probe_82802ab,
......@@ -11182,7 +11182,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.unlock = unlock_stm50_uniform,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11195,7 +11195,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50FW040,
.total_size = 512,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_OK_PR,
.probe = probe_82802ab,
......@@ -11207,7 +11207,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.unlock = unlock_stm50_uniform,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11220,7 +11220,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50FW080,
.total_size = 1024,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_OK_PREW,
.probe = probe_82802ab,
......@@ -11232,7 +11232,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.unlock = unlock_stm50_uniform,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11245,7 +11245,7 @@ const struct flashchip flashchips[] = {
.manufacture_id = ST_ID,
.model_id = ST_M50LPW116,
.total_size = 2048,
.page_size = 64 * 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_UNTESTED,
.probe = probe_82802ab,
......@@ -11263,7 +11263,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50flw0x0x,
.unlock = unlock_stm50_nonuniform,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......
......@@ -3,6 +3,7 @@
*
* Copyright (C) 2008 Claus Gindhart <claus.gindhart@kontron.com>
* Copyright (C) 2009 Sean Nelson <audiohacked@gmail.com>
* Copyright (C) 2013 Stefan Tauner
*
* 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
......@@ -20,84 +21,71 @@
*/
/*
* This module is designed for supporting the devices
* ST M50FLW040A (not yet tested)
* ST M50FLW040B (not yet tested)
* ST M50FLW080A
* ST M50FLW080B (not yet tested)
* All ST M50 chips are locked on startup. Most of them have a uniform 64 kB block layout, but some have
* a non-uniform block/sector segmentation which has to be handled with more care. Some of the non-uniform
* chips support erasing of the 4 kB sectors with another command.
*/
#include "flash.h"
#include "flashchips.h"
#include "chipdrivers.h"
/*
* claus.gindhart@kontron.com
* The ST M50FLW080B and STM50FLW080B chips have to be unlocked,
* before you can erase them or write to them.
*/
static int unlock_block_stm50flw0x0x(struct flashctx *flash, int offset)
static int stm50_unlock_address(struct flashctx *flash, int offset)
{
chipaddr wrprotect = flash->virtual_registers + 2;
static const uint8_t unlock_sector = 0x00;
int j;
/*
* These chips have to be unlocked before you can erase them or write
* to them. The size of the locking sectors depends on the type
* of chip.
*
* Sometimes, the BIOS does this for you; so you probably
* don't need to worry about that.
*/
msg_cdbg("unlocking at 0x%x\n", offset);
chip_writeb(flash, unlock_sector, wrprotect + offset);
if (chip_readb(flash, wrprotect + offset) != unlock_sector) {
msg_cerr("Cannot unlock address 0x%x\n", offset);
return -1;
}
return 0;
}
/* Check, if it's is a top/bottom-block with 4k-sectors. */
/* TODO: What about the other types? */
if ((offset == 0) ||
(offset == (flash->chip->model_id == ST_M50FLW080A ? 0xE0000 : 0x10000))
|| (offset == 0xF0000)) {
/* Chips known to use a non-uniform block and sector layout for locking (as well as for erasing):
* Name Size Address range of lock registers
* M50FLW080A 1MB FFB00002 - FFBFF002
* M50FLW080B 1MB FFB00002 - FFBFF002
* M50FW002 256k FFBC0002 - FFBFC002
* M50LPW116 2MB FFA00002 - FFBFC002
*/
int unlock_stm50_nonuniform(struct flashctx *flash)
{
int i;
struct eraseblock *eraseblocks = flash->chip->block_erasers[0].eraseblocks;
unsigned int done = 0;
for (i = 0; i < NUM_ERASEREGIONS && eraseblocks[i].count != 0; i++) {
unsigned int block_size = eraseblocks[i].size;
unsigned int block_count = eraseblocks[i].count;
// unlock each 4k-sector
for (j = 0; j < 0x10000; j += 0x1000) {
msg_cdbg("unlocking at 0x%x\n", offset + j);
chip_writeb(flash, unlock_sector,
wrprotect + offset + j);
if (chip_readb(flash, wrprotect + offset + j) !=
unlock_sector) {
msg_cerr("Cannot unlock sector @ 0x%x\n",
offset + j);
int j;
for (j = 0; j < block_count; j++) {
if (stm50_unlock_address(flash, done)) {
msg_cerr("UNLOCK FAILED!\n");
return -1;
}
}
} else {
msg_cdbg("unlocking at 0x%x\n", offset);
chip_writeb(flash, unlock_sector, wrprotect + offset);
if (chip_readb(flash, wrprotect + offset) != unlock_sector) {
msg_cerr("Cannot unlock sector @ 0x%x\n", offset);
return -1;
done += block_count * block_size;
}
}
return 0;
}
int unlock_stm50flw0x0x(struct flashctx *flash)
/* Unlocking for uniform 64 kB blocks starting at offset 2 of the feature registers. */
int unlock_stm50_uniform(struct flashctx *flash)
{
int i;
for (i = 0; i < flash->chip->total_size * 1024; i+= flash->chip->page_size) {
if(unlock_block_stm50flw0x0x(flash, i)) {
for (i = 0; i < flash->chip->total_size * 1024; i+= 64 * 1024) {
if (stm50_unlock_address(flash, i)) {
msg_cerr("UNLOCK FAILED!\n");
return -1;
}
}
return 0;
}
/* This function is unused. */
int erase_sector_stm50flw0x0x(struct flashctx *flash, unsigned int sector,
unsigned int sectorsize)
int erase_sector_stm50(struct flashctx *flash, unsigned int sector, unsigned int sectorsize)
{
chipaddr bios = flash->virtual_memory + sector;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment