===================================================================
@@ -21,7 +21,10 @@
#include "flash.h"
-static int printlock_w39_fwh_block(struct flashchip *flash, int offset)
+#define RWLOCK ((1 << 2) | (1 << 0))
+#define LOCKDOWN (1 << 1)
+
+static int printlock_regspace2_block(struct flashchip *flash, int offset)
{
chipaddr wrprotect = flash->virtual_registers + offset + 2;
uint8_t locking;
@@ -56,30 +59,67 @@
}
/* Read or write lock present? */
- return (locking & ((1 << 2) | (1 << 0))) ? -1 : 0;
+ return (locking & RWLOCK) ? -1 : 0;
}
-static int unlock_w39_fwh_block(struct flashchip *flash, int offset)
+int changelock_regspace2_block(struct flashchip *flash, int offset, uint8_t bits)
{
chipaddr wrprotect = flash->virtual_registers + offset + 2;
uint8_t locking;
+ if (bits & 0xf8) {
+ msg_cerr("Invalid locking change 0x%02x requested at 0x%08x! "
+ "Please report a bug at flashrom@flashrom.org\n",
+ bits, offset);
+ return -1;
+ }
locking = chip_readb(wrprotect);
- /* Read or write lock present? */
- if (locking & ((1 << 2) | (1 << 0))) {
+ /* Did we request a change of read/write/lockdown? */
+ if (((locking ^ bits) & (RWLOCK | LOCKDOWN)) == 0) {
+ msg_cdbg2("Locking status at 0x%08x not changed\n", offset);
+ return 0;
+ }
+ /* Change read or write lock? */
+ if ((locking ^ bits) & RWLOCK) {
/* Lockdown active? */
- if (locking & (1 << 1)) {
- msg_cerr("Can't unlock block at 0x%08x!\n", offset);
+ if (locking & LOCKDOWN) {
+ msg_cerr("Can't change locking status at 0x%08x due to "
+ "lockdown!\n", offset);
return -1;
} else {
- msg_cdbg("Unlocking block at 0x%08x\n", offset);
- chip_writeb(0, wrprotect);
+ /* Do not lockdown yet. */
+ msg_cdbg("Changing locking status at 0x%08x\n", offset);
+ chip_writeb(bits & RWLOCK, wrprotect);
+ if (chip_readb(wrprotect) != (bits & RWLOCK)) {
+ msg_cerr("Locking status change FAILED at "
+ "0x%08x!\n", offset);
+ return -1;
+ }
}
}
+ if ((locking & LOCKDOWN) && !(bits & LOCKDOWN)) {
+ msg_cerr("Lockdown can't be removed at 0x%08x!\n", offset);
+ /* FIXME: Is this really an error? */
+ return -1;
+ }
+ if (!(locking & LOCKDOWN) && (bits & LOCKDOWN)) {
+ msg_cdbg("Enabling lockdown at 0x%08x\n", offset);
+ chip_writeb(bits, wrprotect);
+ if (chip_readb(wrprotect) != (bits)) {
+ msg_cerr("Lockdown status change FAILED at "
+ "0x%08x!\n", offset);
+ return -1;
+ }
+ }
return 0;
}
+static int unlock_w39_fwh_block(struct flashchip *flash, int offset)
+{
+ return changelock_regspace2_block(flash, offset, 0x00);
+}
+
static uint8_t w39_idmode_readb(struct flashchip *flash, int offset)
{
chipaddr bios = flash->virtual_memory;
@@ -143,7 +183,7 @@
/* Print lock status of the complete chip */
for (i = 0; i < total_size; i += flash->page_size)
- ret |= printlock_w39_fwh_block(flash, i);
+ ret |= printlock_regspace2_block(flash, i);
return ret;
}
===================================================================
@@ -23,15 +23,6 @@
#include "flash.h"
#include "chipdrivers.h"
-static int write_lockbits_block_49lfxxxc(struct flashchip *flash, unsigned long address, unsigned char bits)
-{
- unsigned long lock = flash->virtual_registers + address + 2;
- msg_cdbg("lockbits at address=0x%08lx is 0x%01x\n", lock, chip_readb(lock));
- chip_writeb(bits, lock);
-
- return 0;
-}
-
static int write_lockbits_49lfxxxc(struct flashchip *flash, unsigned char bits)
{
chipaddr registers = flash->virtual_registers;
@@ -40,16 +31,16 @@
msg_cdbg("\nbios=0x%08lx\n", registers);
for (i = 0; left > 65536; i++, left -= 65536) {
- write_lockbits_block_49lfxxxc(flash, i * 65536, bits);
+ changelock_regspace2_block(flash, i * 65536, bits);
}
address = i * 65536;
- write_lockbits_block_49lfxxxc(flash, address, bits);
+ changelock_regspace2_block(flash, address, bits);
address += 32768;
- write_lockbits_block_49lfxxxc(flash, address, bits);
+ changelock_regspace2_block(flash, address, bits);
address += 8192;
- write_lockbits_block_49lfxxxc(flash, address, bits);
+ changelock_regspace2_block(flash, address, bits);
address += 8192;
- write_lockbits_block_49lfxxxc(flash, address, bits);
+ changelock_regspace2_block(flash, address, bits);
return 0;
}
===================================================================
@@ -110,10 +110,10 @@
int unlock_82802ab(struct flashchip *flash)
{
int i;
- //chipaddr wrprotect = flash->virtual_registers + page + 2;
for (i = 0; i < flash->total_size * 1024; i+= flash->page_size)
- chip_writeb(0, flash->virtual_registers + i + 2);
+ if (changelock_regspace2_block(flash, i, 0x00))
+ return -1;
return 0;
}
===================================================================
@@ -21,29 +21,30 @@
*/
#include "flash.h"
+#include "chipdrivers.h"
-static void write_lockbits_49fl00x(chipaddr bios, int size,
- unsigned char bits, int block_size)
+static int write_lockbits_49fl00x(struct flashchip *flash, uint8_t bits,
+ int block_size)
{
- int i, left = size;
+ int i, left = flash->total_size * 1024;
for (i = 0; left >= block_size; i++, left -= block_size) {
/* pm49fl002 */
if (block_size == 16384 && i % 2)
continue;
- chip_writeb(bits, bios + (i * block_size) + 2);
+ if (changelock_regspace2_block(flash, i * block_size, bits))
+ return -1;
}
+ return 0;
}
int unlock_49fl00x(struct flashchip *flash)
{
- write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 0, flash->page_size);
- return 0;
+ return write_lockbits_49fl00x(flash, 0, flash->page_size);
}
int lock_49fl00x(struct flashchip *flash)
{
- write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 1, flash->page_size);
- return 0;
+ return write_lockbits_49fl00x(flash, 1, flash->page_size);
}
===================================================================
@@ -7523,9 +7523,9 @@
.total_size = 256,
.page_size = 64 * 1024,
.feature_bits = FEATURE_REGISTERMAP,
- .tested = TEST_UNTESTED,
+ .tested = TEST_OK_PREW,
.probe = probe_82802ab,
- .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst49lfxxxc.c) */
+ .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (82802ab.c) */
.block_erasers =
{
{
@@ -7536,9 +7536,12 @@
{16 * 1024, 1},
},
.block_erase = erase_block_82802ab,
+ }, {
+ .eraseblocks = { {256 * 1024, 1}, },
+ .block_erase = NULL, /* Only in A/A mux mode */
}
},
- .unlock = unlock_stm50flw0x0x,
+ .unlock = unlock_stm50fw002,
.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) 2011 Carl-Daniel Hailfinger
*
* 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
@@ -38,8 +39,6 @@
*/
static int unlock_block_stm50flw0x0x(struct flashchip *flash, int offset)
{
- chipaddr wrprotect = flash->virtual_registers + 2;
- static const uint8_t unlock_sector = 0x00;
int j;
/*
@@ -58,23 +57,11 @@
|| (offset == 0xF0000)) {
// unlock each 4k-sector
- for (j = 0; j < 0x10000; j += 0x1000) {
- msg_cdbg("unlocking at 0x%x\n", offset + j);
- chip_writeb(unlock_sector, wrprotect + offset + j);
- if (chip_readb(wrprotect + offset + j) != unlock_sector) {
- msg_cerr("Cannot unlock sector @ 0x%x\n",
- offset + j);
+ for (j = 0; j < 0x10000; j += 0x1000)
+ if (changelock_regspace2_block(flash, offset + j, 0x00))
return -1;
- }
- }
- } else {
- msg_cdbg("unlocking at 0x%x\n", offset);
- chip_writeb(unlock_sector, wrprotect + offset);
- if (chip_readb(wrprotect + offset) != unlock_sector) {
- msg_cerr("Cannot unlock sector @ 0x%x\n", offset);
+ } else if (changelock_regspace2_block(flash, offset, 0x00))
return -1;
- }
- }
return 0;
}
@@ -84,7 +71,7 @@
int i;
for (i = 0; i < flash->total_size * 1024; i+= flash->page_size) {
- if(unlock_block_stm50flw0x0x(flash, i)) {
+ if (unlock_block_stm50flw0x0x(flash, i)) {
msg_cerr("UNLOCK FAILED!\n");
return -1;
}
@@ -93,6 +80,27 @@
return 0;
}
+/* FIXME: Should this be moved to a generic walk_unlockregions()? */
+int unlock_stm50fw002(struct flashchip *flash)
+{
+ static const struct eraseblock unlockregions[4] = {
+ {64 * 1024, 3},
+ {32 * 1024, 1},
+ {8 * 1024, 2},
+ {16 * 1024, 1}};
+ int i, j;
+ int addr = 0;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < unlockregions[i].count; j++) {
+ if (changelock_regspace2_block(flash, addr, 0x00))
+ return 1;
+ addr += unlockregions[i].size;
+ }
+ }
+ return 0;
+}
+
/* This function is unused. */
int erase_sector_stm50flw0x0x(struct flashchip *flash, unsigned int sector, unsigned int sectorsize)
{
===================================================================
@@ -139,6 +139,8 @@
int printlock_w39v080fa_dual(struct flashchip *flash);
int unlock_w39v040fb(struct flashchip *flash);
int unlock_w39v080fa(struct flashchip *flash);
+int printlock_regspace2_block(struct flashchip *flash, int offset);
+int changelock_regspace2_block(struct flashchip *flash, int offset, uint8_t bits);
/* w29ee011.c */
int probe_w29ee011(struct flashchip *flash);
@@ -146,5 +148,6 @@
/* stm50flw0x0x.c */
int erase_sector_stm50flw0x0x(struct flashchip *flash, unsigned int block, unsigned int blocksize);
int unlock_stm50flw0x0x(struct flashchip *flash);
+int unlock_stm50fw002(struct flashchip *flash);
#endif /* !__CHIPDRIVERS_H__ */