2005-11-09 22:18:14

by Pavel Machek

[permalink] [raw]
Subject: latest mtd changes broke collie


Latest mtd changes break collie...it now oopses during boot. This
reverts the bad patch.

Signed-off-by: Pavel Machek <[email protected]>

diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
--- a/drivers/mtd/chips/sharp.c
+++ b/drivers/mtd/chips/sharp.c
@@ -4,7 +4,7 @@
* Copyright 2000,2001 David A. Schleef <[email protected]>
* 2000,2001 Lineo, Inc.
*
- * $Id: sharp.c,v 1.16 2005/11/07 11:14:23 gleixner Exp $
+ * $Id: sharp.c,v 1.14 2004/08/09 13:19:43 dwmw2 Exp $
*
* Devices supported:
* LH28F016SCT Symmetrical block flash memory, 2Mx8
@@ -32,7 +32,6 @@
#include <linux/mtd/cfi.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/slab.h>

#define CMD_RESET 0xffffffff
#define CMD_READ_ID 0x90909090
@@ -234,7 +233,7 @@ static int sharp_probe_map(struct map_in
/* This function returns with the chip->mutex lock held. */
static int sharp_wait(struct map_info *map, struct flchip *chip)
{
- int status, i;
+ __u32 status;
unsigned long timeo = jiffies + HZ;
DECLARE_WAITQUEUE(wait, current);
int adr = 0;
@@ -247,11 +246,13 @@ retry:
map_write32(map, CMD_READ_STATUS, adr);
chip->state = FL_STATUS;
case FL_STATUS:
- for(i=0;i<100;i++){
- status = map_read32(map,adr);
- if((status & SR_READY)==SR_READY)
- break;
- udelay(1);
+ status = map_read32(map,adr);
+ if ((status & SR_READY) == SR_READY)
+ break;
+ spin_unlock_bh(chip->mutex);
+ if (time_after(jiffies, timeo)) {
+ printk("Waiting for chip to be ready timed out in erase\n");
+ return -EIO;
}
sharp_udelay(1);
goto retry;
@@ -491,11 +492,7 @@ static inline int sharp_do_wait_for_read
spin_lock_bh(chip->mutex);

remove_wait_queue(&chip->wq, &wait);
-
- if (signal_pending(current)){
- ret = -EINTR;
- goto out;
- }
+ set_current_state(TASK_RUNNING);
}
ret = -ETIME;
out:



--
Thanks, Sharp!


2005-11-10 00:19:04

by Josh Boyer

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

On 11/9/05, Pavel Machek <[email protected]> wrote:
>
> Latest mtd changes break collie...it now oopses during boot. This
> reverts the bad patch.
>
> Signed-off-by: Pavel Machek <[email protected]>
>
<snip>
> - for(i=0;i<100;i++){
> - status = map_read32(map,adr);
> - if((status & SR_READY)==SR_READY)
> - break;
> - udelay(1);
> + status = map_read32(map,adr);

I was just discussing with someone today how map_read32 no longer
exists in the kernel... does this even compile for you?

Somehow I think I'm missing something...

josh

2005-11-10 02:59:12

by Todd Poynor

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Pavel Machek wrote:
> Latest mtd changes break collie...it now oopses during boot. This
> reverts the bad patch.

What tree was this generated against? It doesn't seem to match recent
linux-mtd or kernel.org trees. It looks like the tree used had
different version of a couple fixes recently added to linux-mtd (removal
of bogus udelays and 32-bit status datatype).

I'm guessing the important part is to add a missing spin_unlock_bh(),
which is definitely a bug in the mtd code, but this code is so different
than linux-mtd CVS that it seems more resyncing is needed. As it stands
now, force-fitting this patch would still leave an unbalanced
spin_lock_bh() without other changes. And it does look like this driver
hasn't been converted to modern mtd apis.

>
> Signed-off-by: Pavel Machek <[email protected]>
>
> diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
> --- a/drivers/mtd/chips/sharp.c
> +++ b/drivers/mtd/chips/sharp.c
> @@ -4,7 +4,7 @@
> * Copyright 2000,2001 David A. Schleef <[email protected]>
> * 2000,2001 Lineo, Inc.
> *
> - * $Id: sharp.c,v 1.16 2005/11/07 11:14:23 gleixner Exp $
> + * $Id: sharp.c,v 1.14 2004/08/09 13:19:43 dwmw2 Exp $
> *
> * Devices supported:
> * LH28F016SCT Symmetrical block flash memory, 2Mx8
> @@ -32,7 +32,6 @@
> #include <linux/mtd/cfi.h>
> #include <linux/delay.h>
> #include <linux/init.h>
> -#include <linux/slab.h>
>
> #define CMD_RESET 0xffffffff
> #define CMD_READ_ID 0x90909090
> @@ -234,7 +233,7 @@ static int sharp_probe_map(struct map_in
> /* This function returns with the chip->mutex lock held. */
> static int sharp_wait(struct map_info *map, struct flchip *chip)
> {
> - int status, i;
> + __u32 status;
> unsigned long timeo = jiffies + HZ;
> DECLARE_WAITQUEUE(wait, current);
> int adr = 0;
> @@ -247,11 +246,13 @@ retry:
> map_write32(map, CMD_READ_STATUS, adr);
> chip->state = FL_STATUS;
> case FL_STATUS:
> - for(i=0;i<100;i++){
> - status = map_read32(map,adr);
> - if((status & SR_READY)==SR_READY)
> - break;
> - udelay(1);
> + status = map_read32(map,adr);
> + if ((status & SR_READY) == SR_READY)
> + break;
> + spin_unlock_bh(chip->mutex);
> + if (time_after(jiffies, timeo)) {
> + printk("Waiting for chip to be ready timed out in erase\n");
> + return -EIO;
> }
> sharp_udelay(1);
> goto retry;
> @@ -491,11 +492,7 @@ static inline int sharp_do_wait_for_read
> spin_lock_bh(chip->mutex);
>
> remove_wait_queue(&chip->wq, &wait);
> -
> - if (signal_pending(current)){
> - ret = -EINTR;
> - goto out;
> - }
> + set_current_state(TASK_RUNNING);
> }
> ret = -ETIME;
> out:
>
>
>


--
Todd

2005-11-10 09:50:18

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > Latest mtd changes break collie...it now oopses during boot. This
> > reverts the bad patch.
> >
> > Signed-off-by: Pavel Machek <[email protected]>
> >
> <snip>
> > - for(i=0;i<100;i++){
> > - status = map_read32(map,adr);
> > - if((status & SR_READY)==SR_READY)
> > - break;
> > - udelay(1);
> > + status = map_read32(map,adr);
>
> I was just discussing with someone today how map_read32 no longer
> exists in the kernel... does this even compile for you?
>
> Somehow I think I'm missing something...

I had other changes in my tree. Only old_mtd+my_changes worked, but
new_mtd+my_changes broke, so I figured out diff between old_mtd and
new_mtd must be bad. Given that neither old_mtd compiled nor new_mtd
compiled...

Fixes to map_read32 are being prepared.

Pavel
--
Thanks, Sharp!

2005-11-10 09:52:35

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> >Latest mtd changes break collie...it now oopses during boot. This
> >reverts the bad patch.
>
> What tree was this generated against? It doesn't seem to match recent
> linux-mtd or kernel.org trees. It looks like the tree used had
> different version of a couple fixes recently added to linux-mtd (removal
> of bogus udelays and 32-bit status datatype).
>
> I'm guessing the important part is to add a missing spin_unlock_bh(),
> which is definitely a bug in the mtd code, but this code is so different
> than linux-mtd CVS that it seems more resyncing is needed. As it stands
> now, force-fitting this patch would still leave an unbalanced
> spin_lock_bh() without other changes. And it does look like this driver
> hasn't been converted to modern mtd apis.

Is there easy way to get at linux-mtd CVS? Attached is my current
version of sharp.c; map_read32/map_write32 was deleted thanks to
Richard Purdue.

Pavel
/*
* MTD chip driver for pre-CFI Sharp flash chips
*
* Copyright 2000,2001 David A. Schleef <[email protected]>
* 2000,2001 Lineo, Inc.
*
* $Id: sharp.c,v 1.14 2004/08/09 13:19:43 dwmw2 Exp $
*
* Devices supported:
* LH28F016SCT Symmetrical block flash memory, 2Mx8
* LH28F008SCT Symmetrical block flash memory, 1Mx8
*
* Documentation:
* http://www.sharpmeg.com/datasheets/memic/flashcmp/
* http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
* 016sctl9.pdf
*
* Limitations:
* This driver only supports 4x1 arrangement of chips.
* Not tested on anything but PowerPC.
*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/cfi.h>
#include <linux/delay.h>
#include <linux/init.h>

#define CMD_RESET 0xffffffff
#define CMD_READ_ID 0x90909090
#define CMD_READ_STATUS 0x70707070
#define CMD_CLEAR_STATUS 0x50505050
#define CMD_BLOCK_ERASE_1 0x20202020
#define CMD_BLOCK_ERASE_2 0xd0d0d0d0
#define CMD_BYTE_WRITE 0x40404040
#define CMD_SUSPEND 0xb0b0b0b0
#define CMD_RESUME 0xd0d0d0d0
#define CMD_SET_BLOCK_LOCK_1 0x60606060
#define CMD_SET_BLOCK_LOCK_2 0x01010101
#define CMD_SET_MASTER_LOCK_1 0x60606060
#define CMD_SET_MASTER_LOCK_2 0xf1f1f1f1
#define CMD_CLEAR_BLOCK_LOCKS_1 0x60606060
#define CMD_CLEAR_BLOCK_LOCKS_2 0xd0d0d0d0

#define SR_READY 0x80808080 // 1 = ready
#define SR_ERASE_SUSPEND 0x40404040 // 1 = block erase suspended
#define SR_ERROR_ERASE 0x20202020 // 1 = error in block erase or clear lock bits
#define SR_ERROR_WRITE 0x10101010 // 1 = error in byte write or set lock bit
#define SR_VPP 0x08080808 // 1 = Vpp is low
#define SR_WRITE_SUSPEND 0x04040404 // 1 = byte write suspended
#define SR_PROTECT 0x02020202 // 1 = lock bit set
#define SR_RESERVED 0x01010101

#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)

#define BLOCK_MASK 0xfffe0000

/* Configuration options */

#define AUTOUNLOCK /* automatically unlocks blocks before erasing */

struct mtd_info *sharp_probe(struct map_info *);

static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);

static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, const u_char *buf);
static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
static void sharp_sync(struct mtd_info *mtd);
static int sharp_suspend(struct mtd_info *mtd);
static void sharp_resume(struct mtd_info *mtd);
static void sharp_destroy(struct mtd_info *mtd);

static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
unsigned long adr, __u32 datum);
static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr);
#ifdef AUTOUNLOCK
static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr);
#endif


struct sharp_info{
struct flchip *chip;
int bogus;
int chipshift;
int numchips;
struct flchip chips[1];
};

struct mtd_info *sharp_probe(struct map_info *map);
static void sharp_destroy(struct mtd_info *mtd);

static struct mtd_chip_driver sharp_chipdrv = {
.probe = sharp_probe,
.destroy = sharp_destroy,
.name = "sharp",
.module = THIS_MODULE
};

static void sharp_udelay(unsigned long i) {
if (in_interrupt()) {
udelay(i);
} else {
schedule();
}
}

struct mtd_info *sharp_probe(struct map_info *map)
{
struct mtd_info *mtd = NULL;
struct sharp_info *sharp = NULL;
int width;

mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
if(!mtd)
return NULL;

sharp = kmalloc(sizeof(*sharp), GFP_KERNEL);
if(!sharp) {
kfree(mtd);
return NULL;
}

memset(mtd, 0, sizeof(*mtd));

width = sharp_probe_map(map,mtd);
if(!width){
kfree(mtd);
kfree(sharp);
return NULL;
}

mtd->priv = map;
mtd->type = MTD_NORFLASH;
mtd->erase = sharp_erase;
mtd->read = sharp_read;
mtd->write = sharp_write;
mtd->sync = sharp_sync;
mtd->suspend = sharp_suspend;
mtd->resume = sharp_resume;
mtd->flags = MTD_CAP_NORFLASH;
mtd->name = map->name;

memset(sharp, 0, sizeof(*sharp));
sharp->chipshift = 24;
sharp->numchips = 1;
sharp->chips[0].start = 0;
sharp->chips[0].state = FL_READY;
sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
sharp->chips[0].word_write_time = 0;
init_waitqueue_head(&sharp->chips[0].wq);
spin_lock_init(&sharp->chips[0]._spinlock);

map->fldrv = &sharp_chipdrv;
map->fldrv_priv = sharp;

__module_get(THIS_MODULE);
return mtd;
}

static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr)
{
map_word map_cmd;
map_cmd.x[0] = cmd;
map_write(map, map_cmd, adr);
}

static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
{
map_word tmp, read0, read4;
unsigned long base = 0;
int width = 4;

tmp = map_read(map, base+0);

sharp_send_cmd(map, CMD_READ_ID, base+0);

read0 = map_read(map, base+0);
read4 = map_read(map, base+4);
if (read0.x[0] == 0x00b000b0) {
switch(read4.x[0]){
case 0xaaaaaaaa:
case 0xa0a0a0a0:
/* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
/* a0 - LH28F016SCT-Z4 2Mx8, 32 64k blocks*/
mtd->erasesize = 0x10000 * width;
mtd->size = 0x200000 * width;
return width;
case 0xa6a6a6a6:
/* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
/* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
mtd->erasesize = 0x10000 * width;
mtd->size = 0x100000 * width;
return width;
case 0x00b000b0:
/* a6 - LH28F640BFHE 8 64k * 2 chip blocks*/
mtd->erasesize = 0x10000 * width / 2;
mtd->size = 0x800000 * width / 2;
return width;
default:
printk("Sort-of looks like sharp flash.\n");
}
} else if ((map_read(map, base+0).x[0] == CMD_READ_ID)){
/* RAM, probably */
printk("Looks like RAM\n");
map_write(map, tmp, base+0);
} else {
printk("Doesn't look like sharp flash.\n");
}

return 0;
}

/* This function returns with the chip->mutex lock held. */
static int sharp_wait(struct map_info *map, struct flchip *chip)
{
map_word status;
unsigned long timeo = jiffies + HZ;
DECLARE_WAITQUEUE(wait, current);
int adr = 0;

retry:
spin_lock_bh(chip->mutex);

switch (chip->state) {
case FL_READY:
sharp_send_cmd(map, CMD_READ_STATUS, adr);
chip->state = FL_STATUS;
case FL_STATUS:
status = map_read(map, adr);
if ((status.x[0] & SR_READY) == SR_READY)
break;
spin_unlock_bh(chip->mutex);
if (time_after(jiffies, timeo)) {
printk("Waiting for chip to be ready timed out in erase\n");
return -EIO;
}
sharp_udelay(1);
goto retry;
default:
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);

spin_unlock_bh(chip->mutex);

sharp_udelay(1);

set_current_state(TASK_RUNNING);
remove_wait_queue(&chip->wq, &wait);

if(signal_pending(current))
return -EINTR;

timeo = jiffies + HZ;

goto retry;
}

sharp_send_cmd(map, CMD_RESET, adr);

chip->state = FL_READY;

return 0;
}

static void sharp_release(struct flchip *chip)
{
wake_up(&chip->wq);
spin_unlock_bh(chip->mutex);
}

static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;
int chipnum;
int ret = 0;
int ofs = 0;

chipnum = (from >> sharp->chipshift);
ofs = from & ((1 << sharp->chipshift)-1);

*retlen = 0;

while(len){
unsigned long thislen;

if(chipnum>=sharp->numchips)
break;

thislen = len;
if(ofs+thislen >= (1<<sharp->chipshift))
thislen = (1<<sharp->chipshift) - ofs;

ret = sharp_wait(map,&sharp->chips[chipnum]);
if(ret<0)
break;

map_copy_from(map,buf,ofs,thislen);

sharp_release(&sharp->chips[chipnum]);

*retlen += thislen;
len -= thislen;
buf += thislen;

ofs = 0;
chipnum++;
}
return ret;
}

static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;
int ret = 0;
int i,j;
int chipnum;
unsigned long ofs;
union { u32 l; unsigned char uc[4]; } tbuf;

*retlen = 0;

while(len){
tbuf.l = 0xffffffff;
chipnum = to >> sharp->chipshift;
ofs = to & ((1<<sharp->chipshift)-1);

j=0;
for(i=ofs&3;i<4 && len;i++){
tbuf.uc[i] = *buf;
buf++;
to++;
len--;
j++;
}
sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
if(ret<0)
return ret;
(*retlen)+=j;
}

return 0;
}

static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
unsigned long adr, __u32 datum)
{
int ret;
int try;
int i;
map_word status, data;

status.x[0] = 0;
ret = sharp_wait(map,chip);
if (ret < 0)
return ret;

for(try=0;try<10;try++){
sharp_send_cmd(map, CMD_BYTE_WRITE, adr);
/* cpu_to_le32 -> hack to fix the writel be->le conversion */
data.x[0] = cpu_to_le32(datum);
map_write(map, data, adr);

chip->state = FL_WRITING;

sharp_send_cmd(map, CMD_READ_STATUS, adr);
for(i=0;i<100;i++){
status = map_read(map, adr);
if((status.x[0] & SR_READY)==SR_READY)
break;
}
#ifdef AUTOUNLOCK
if (status.x[0] & SR_PROTECT) { /* lock block */
sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
sharp_unlock_oneblock(map,chip,adr);
sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
sharp_send_cmd(map, CMD_RESET, adr);
continue;
}
#endif
if(i==100){
printk("sharp: timed out writing\n");
}

if (!(status.x[0] & SR_ERRORS))
break;

printk("sharp: error writing byte at addr=%08lx status=%08x\n",adr,status.x[0]);

sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
}
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;

sharp_release(chip);

return 0;
}

static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;
unsigned long adr,len;
int chipnum, ret=0;

//printk("sharp_erase()\n");
if(instr->addr & (mtd->erasesize - 1))
return -EINVAL;
if(instr->len & (mtd->erasesize - 1))
return -EINVAL;
if(instr->len + instr->addr > mtd->size)
return -EINVAL;

chipnum = instr->addr >> sharp->chipshift;
adr = instr->addr & ((1<<sharp->chipshift)-1);
len = instr->len;

while(len){
ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
if(ret)return ret;

if (adr >= 0xfe0000) {
adr += mtd->erasesize / 8;
len -= mtd->erasesize / 8;
} else {
adr += mtd->erasesize;
len -= mtd->erasesize;
}
if(adr >> sharp->chipshift){
adr = 0;
chipnum++;
if(chipnum>=sharp->numchips)
break;
}
}

instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);

return 0;
}

static inline int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
int ret;
unsigned long timeo;
map_word status;
DECLARE_WAITQUEUE(wait, current);

sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);

timeo = jiffies + HZ * 10;

while (time_before(jiffies, timeo)){
sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);
if ((status.x[0] & SR_READY)==SR_READY) {
ret = 0;
goto out;
}
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);

spin_unlock_bh(chip->mutex);

schedule_timeout(1);
schedule();

spin_lock_bh(chip->mutex);

remove_wait_queue(&chip->wq, &wait);
set_current_state(TASK_RUNNING);
}
ret = -ETIME;
out:
return ret;
}

static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
int ret;
map_word status;

ret = sharp_wait(map,chip);
if (ret < 0)
return ret;

#ifdef AUTOUNLOCK
/* This seems like a good place to do an unlock */
sharp_unlock_oneblock(map,chip,adr);
#endif

sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr);
sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr);

chip->state = FL_ERASING;

ret = sharp_do_wait_for_ready(map,chip,adr);
if(ret<0) {
spin_unlock_bh(chip->mutex);
return ret;
}

sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map,adr);

if (!(status.x[0] & SR_ERRORS)) {
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;
spin_unlock_bh(chip->mutex);
return 0;
}

printk("sharp: error erasing block at addr=%08lx status=%08x\n", adr, status.x[0]);
sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);

sharp_release(chip);

return -EIO;
}

#ifdef AUTOUNLOCK
static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
map_word status;

sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr & BLOCK_MASK);
sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr & BLOCK_MASK);

sharp_do_wait_for_ready(map,chip,adr);

status = map_read(map, adr);

if (!(status.x[0] & SR_ERRORS)) {
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;
return;
}

printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]);
sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
}
#endif

static void sharp_sync(struct mtd_info *mtd)
{
}

static int sharp_suspend(struct mtd_info *mtd)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;
int i;
struct flchip *chip;
int ret = 0;

for (i = 0; !ret && i < sharp->numchips; i++) {
chip = &sharp->chips[i];
ret = sharp_wait(map,chip);

if (ret) {
ret = -EAGAIN;
} else {
chip->state = FL_PM_SUSPENDED;
spin_unlock_bh(chip->mutex);
}
}
return ret;
}

static void sharp_resume(struct mtd_info *mtd)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;
int i;
struct flchip *chip;

for (i = 0; i < sharp->numchips; i++) {
chip = &sharp->chips[i];

spin_lock_bh(chip->mutex);

if (chip->state == FL_PM_SUSPENDED) {
/* We need to force it back to a known state */
sharp_send_cmd(map, CMD_RESET, chip->start);
chip->state = FL_READY;
wake_up(&chip->wq);
}

spin_unlock_bh(chip->mutex);
}
}

static void sharp_destroy(struct mtd_info *mtd)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;

kfree(sharp);
}

int __init sharp_probe_init(void)
{
printk("MTD Sharp chip driver <[email protected]>\n");

register_mtd_chip_driver(&sharp_chipdrv);

return 0;
}

static void __exit sharp_probe_exit(void)
{
unregister_mtd_chip_driver(&sharp_chipdrv);
}

module_init(sharp_probe_init);
module_exit(sharp_probe_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Schleef <[email protected]>");
MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");


--
Thanks, Sharp!

2005-11-10 10:02:43

by David Woodhouse

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

On Thu, 2005-11-10 at 10:50 +0100, Pavel Machek wrote:
> Is there easy way to get at linux-mtd CVS? Attached is my current
> version of sharp.c; map_read32/map_write32 was deleted thanks to
> Richard Purdue.

http://www.linux-mtd.infradead.org/source.html has a reference to
anoncvs.

I'd really prefer not to see sharp.c revived -- it's supposed to be
dying, in favour of the CFI chipset drivers and jedec_probe code.
Can we try to work out what's wrong with those, instead?

--
dwmw2


2005-11-10 10:39:21

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > Is there easy way to get at linux-mtd CVS? Attached is my current
> > version of sharp.c; map_read32/map_write32 was deleted thanks to
> > Richard Purdue.
>
> http://www.linux-mtd.infradead.org/source.html has a reference to
> anoncvs.
>
> I'd really prefer not to see sharp.c revived -- it's supposed to be
> dying, in favour of the CFI chipset drivers and jedec_probe code.
> Can we try to work out what's wrong with those, instead?

This is quite hard to debug -- I do not even have serial console for
collie, and I know nothing about mtd.

Another issue is that collie is in pretty poor state -- it never
worked in mainline. Getting it working in mainline, even with
deprecated sharp.c driver, would bea big plus as I should get
users/testers at that point.

That said... I can certainly do few experiments. Switching map_name
from "sharp" to "cfi" should be theoretically enough to get new code
up?
Pavel
--
Thanks, Sharp!

2005-11-10 10:51:49

by David Woodhouse

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

On Thu, 2005-11-10 at 11:38 +0100, Pavel Machek wrote:
> That said... I can certainly do few experiments. Switching map_name
> from "sharp" to "cfi" should be theoretically enough to get new code
> up?

That's if the chips are actually compliant with the Common Flash
Interface. Otherwise, use the 'jedec_probe' method to identify them,
which will still end up using the same actual back-end driver.

--
dwmw2


2005-11-10 11:01:11

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > That said... I can certainly do few experiments. Switching map_name
> > from "sharp" to "cfi" should be theoretically enough to get new code
> > up?
>
> That's if the chips are actually compliant with the Common Flash
> Interface. Otherwise, use the 'jedec_probe' method to identify them,
> which will still end up using the same actual back-end driver.

Well, how do I found out? I tried switching to CFI, and it will not
boot (unable to mount root...). No mtd-related messages as far as I
can see. There's quite a lot of mtd-related config options, I set them
like this:

#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set

#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set

#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_AMDSTD_RETRY=0
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
CONFIG_MTD_OBSOLETE_CHIPS=y
# CONFIG_MTD_AMDSTD is not set
# CONFIG_MTD_SHARP is not set
# CONFIG_MTD_JEDEC is not set
# CONFIG_MTD_XIP is not set

#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
CONFIG_MTD_SA1100=y
# CONFIG_MTD_IMPA7 is not set
# CONFIG_MTD_PLATRAM is not set

#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set

There's this kind of strange code in sharp.c; is it the thing I need
to rewrite into cfi_probe?

static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
{
map_word tmp, read0, read4;
unsigned long base = 0;
int width = 4;

tmp = map_read(map, base+0);

sharp_send_cmd(map, CMD_READ_ID, base+0);

read0 = map_read(map, base+0);
read4 = map_read(map, base+4);
if (read0.x[0] == 0x00b000b0) {
switch(read4.x[0]){
case 0xaaaaaaaa:
case 0xa0a0a0a0:
/* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
/* a0 - LH28F016SCT-Z4 2Mx8, 32 64k blocks*/
mtd->erasesize = 0x10000 * width;
mtd->size = 0x200000 * width;
return width;
case 0xa6a6a6a6:
/* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
/* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
mtd->erasesize = 0x10000 * width;
mtd->size = 0x100000 * width;
return width;
case 0x00b000b0:
/* a6 - LH28F640BFHE 8 64k * 2 chip blocks*/
mtd->erasesize = 0x10000 * width / 2;
mtd->size = 0x800000 * width / 2;
return width;
default:
printk("Sort-of looks like sharp flash.\n");
}

?
Pavel
--
Thanks, Sharp!

2005-11-10 11:11:38

by David Woodhouse

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

On Thu, 2005-11-10 at 11:59 +0100, Pavel Machek wrote:
> Well, how do I found out? I tried switching to CFI, and it will not
> boot (unable to mount root...). No mtd-related messages as far as I
> can see. There's quite a lot of mtd-related config options, I set them
> like this:

If the old sharp driver had even a _chance_ of working, then you
presumably have four 8-bit flash chips laid out on a 32-bit bus, and
those chips are compatible with the Intel command set.

You can CONFIG_MTD_JEDECPROBE, and you want CONFIG_MTD_MAP_BANK_WIDTH=4,
CONFIG_MTD_CFI_I4, CONFIG_MTD_CFI_INTELEXT.

Check that your chips are listed in the table in jedec_probe.c and turn
on all the debugging in jedec_probe.c

--
dwmw2


2005-11-10 11:45:47

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > Well, how do I found out? I tried switching to CFI, and it will not
> > boot (unable to mount root...). No mtd-related messages as far as I
> > can see. There's quite a lot of mtd-related config options, I set them
> > like this:
>
> If the old sharp driver had even a _chance_ of working, then you
> presumably have four 8-bit flash chips laid out on a 32-bit bus, and
> those chips are compatible with the Intel command set.
>
> You can CONFIG_MTD_JEDECPROBE, and you want CONFIG_MTD_MAP_BANK_WIDTH=4,
> CONFIG_MTD_CFI_I4, CONFIG_MTD_CFI_INTELEXT.
>
> Check that your chips are listed in the table in jedec_probe.c and turn
> on all the debugging in jedec_probe.c

As far as I can see, they are not listed :-(.

static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
{
map_word tmp, read0, read4;
int width = 4;

tmp = map_read(map, base+0);
sharp_send_cmd(map, CMD_READ_ID, base+0);

read0 = map_read(map, base+0);
read4 = map_read(map, base+4);
if (read0.x[0] == 0x00b000b0) {
switch(read4.x[0]){
case 0x00b000b0:
/* a6 - LH28F640BFHE 8 64k * 2 chip blocks*/
mtd->erasesize = 0x10000 * width / 2;
mtd->size = 0x800000 * width / 2;
return width;

...I've removed unneccessary code, this path is actually taken. Does
it mean that mfr == id == 0x00b0? [Notice that comment is wrong there,
probably belongs to another chip :-(]
Pavel

--
Thanks, Sharp!

2005-11-10 12:08:03

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > Well, how do I found out? I tried switching to CFI, and it will not
> > boot (unable to mount root...). No mtd-related messages as far as I
> > can see. There's quite a lot of mtd-related config options, I set them
> > like this:
>
> If the old sharp driver had even a _chance_ of working, then you
> presumably have four 8-bit flash chips laid out on a 32-bit bus, and
> those chips are compatible with the Intel command set.
>
> You can CONFIG_MTD_JEDECPROBE, and you want CONFIG_MTD_MAP_BANK_WIDTH=4,
> CONFIG_MTD_CFI_I4, CONFIG_MTD_CFI_INTELEXT.
>
> Check that your chips are listed in the table in jedec_probe.c and turn
> on all the debugging in jedec_probe.c

Ok, I got a little bit more forward.

I created entry like this:
{
.mfr_id = 0x00b0,
.dev_id = 0x00b0,
.name = "Collie hack",
.uaddr = {
[0] = MTD_UADDR_UNNECESSARY, /* x8 */
},
.DevSize = SIZE_4MiB,
.CmdSet = P_ID_INTEL_EXT,
.NumEraseRegions= 1,
.regions = {
ERASEINFO(0x10000,8),
}
}

(Which is probably wrong, I just made up the data), and set name in
collie.c to "jedec_probe". That made jedec_probe.c go alive, and it
prints...

Found: Collie hack
sa1100-0: Found 4 x8 devices at 0x0 in 32-bit bank
Sum of regions (200000) != total size of set of interleaved chips (1000000)
gen_probe: No Supported Vendor Command set found

sharp.c sets

width = 4;
mtd->erasesize = 0x10000 * width / 2;
mtd->size = 0x800000 * width / 2;

...that is
width = 4;
erazesize = 0x20000;
size = 0x1000000;

Does it mean ERASEINFO(0x20000,7) should do the trick?

Pavel
--
Thanks, Sharp!

2005-11-10 13:02:34

by David Vrabel

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Pavel Machek wrote:
>
> Ok, I got a little bit more forward.
>
> I created entry like this:
> {
> .mfr_id = 0x00b0,
> .dev_id = 0x00b0,
> .name = "Collie hack",
> .uaddr = {
> [0] = MTD_UADDR_UNNECESSARY, /* x8 */
> },
> .DevSize = SIZE_4MiB,
> .CmdSet = P_ID_INTEL_EXT,
> .NumEraseRegions= 1,
> .regions = {
> ERASEINFO(0x10000,8),
> }
> }
>
> (Which is probably wrong, I just made up the data)

Shouldn't you get hold of the datasheet for the flash chips and fill in
this information correctly?

David Vrabel

2005-11-10 13:10:23

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > Ok, I got a little bit more forward.
> >
> > I created entry like this:
> > {
> > .mfr_id = 0x00b0,
> > .dev_id = 0x00b0,
> > .name = "Collie hack",
> > .uaddr = {
> > [0] = MTD_UADDR_UNNECESSARY, /* x8 */
> > },
> > .DevSize = SIZE_4MiB,
> > .CmdSet = P_ID_INTEL_EXT,
> > .NumEraseRegions= 1,
> > .regions = {
> > ERASEINFO(0x10000,8),
> > }
> > }
> >
> > (Which is probably wrong, I just made up the data)
>
> Shouldn't you get hold of the datasheet for the flash chips and fill in
> this information correctly?

I already have working sharp.c driver... And I do not even know
manufacturer of the chip, just its ids.
Pavel

--
Thanks, Sharp!

2005-11-10 17:41:37

by Richard Purdie

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

On Thu, 2005-11-10 at 14:09 +0100, Pavel Machek wrote:
> > Shouldn't you get hold of the datasheet for the flash chips and fill in
> > this information correctly?
>
> I already have working sharp.c driver... And I do not even know
> manufacturer of the chip, just its ids.

The chip number is LF28F640BX which is a 64MBit device so perhaps Intel
StrataFlash 28F640? That seems to be a fairly common chip...

Richard

2005-11-10 18:10:19

by Richard Purdie

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

On Thu, 2005-11-10 at 17:41 +0000, Richard Purdie wrote:
> On Thu, 2005-11-10 at 14:09 +0100, Pavel Machek wrote:
> > > Shouldn't you get hold of the datasheet for the flash chips and fill in
> > > this information correctly?
> >
> > I already have working sharp.c driver... And I do not even know
> > manufacturer of the chip, just its ids.
>
> The chip number is LF28F640BX which is a 64MBit device so perhaps Intel
> StrataFlash 28F640? That seems to be a fairly common chip...

Some further research suggests it should perhaps be LH28F640BX which is
a 48 pin Sharp flash chip (much more likely). The nearest datasheet I
can find is:

http://www.datasheetarchive.com/semiconductors/download.php?Datasheet=1120647

Richard

2005-11-10 22:07:38

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > > > Shouldn't you get hold of the datasheet for the flash chips and fill in
> > > > this information correctly?
> > >
> > > I already have working sharp.c driver... And I do not even know
> > > manufacturer of the chip, just its ids.
> >
> > The chip number is LF28F640BX which is a 64MBit device so perhaps Intel
> > StrataFlash 28F640? That seems to be a fairly common chip...
>
> Some further research suggests it should perhaps be LH28F640BX which is
> a 48 pin Sharp flash chip (much more likely). The nearest datasheet I
> can find is:
>
> http://www.datasheetarchive.com/semiconductors/download.php?Datasheet=1120647

That's strange; first the datasheet is pretty much useless; it does
not even give you product ID ("refer to documentation"). Then it
claims this device supports CFI. I guess it is easier to get the
values from sharp.c than from this datasheet :-(.

[It seems like the chip has many "options", and it is up to user how
it uses the chip.]
Pavel
--
Thanks, Sharp!

2005-11-10 22:43:00

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > Well, how do I found out? I tried switching to CFI, and it will not
> > boot (unable to mount root...). No mtd-related messages as far as I
> > can see. There's quite a lot of mtd-related config options, I set them
> > like this:
>
> If the old sharp driver had even a _chance_ of working, then you
> presumably have four 8-bit flash chips laid out on a 32-bit bus, and
> those chips are compatible with the Intel command set.
>
> You can CONFIG_MTD_JEDECPROBE, and you want CONFIG_MTD_MAP_BANK_WIDTH=4,
> CONFIG_MTD_CFI_I4, CONFIG_MTD_CFI_INTELEXT.
>
> Check that your chips are listed in the table in jedec_probe.c and turn
> on all the debugging in jedec_probe.c

With these hacks, I'm able to mount flash at least read-only. On
attempt to remount read-write, I get

"Write error in obliterating obsoleted node at 0x00bc0000: -30
...
Erase at 0x00c00000 failed immediately: -EROFS. Is the sector locked?"

Is it good news?
Pavel

diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -208,7 +208,7 @@ static void collie_set_vpp(int vpp)
}

static struct flash_platform_data collie_flash_data = {
- .map_name = "sharp",
+ .map_name = "jedec_probe",
.set_vpp = collie_set_vpp,
.parts = collie_partitions,
.nr_parts = ARRAY_SIZE(collie_partitions),
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -25,6 +25,8 @@
#include <linux/mtd/cfi.h>
#include <linux/mtd/gen_probe.h>

+#define DEBUG(a, b...) printk(b)
+
/* Manufacturers */
#define MANUFACTURER_AMD 0x0001
#define MANUFACTURER_ATMEL 0x001f
@@ -271,6 +273,19 @@ struct amd_flash_info {
*/
static const struct amd_flash_info jedec_table[] = {
{
+ .mfr_id = 0x00b0,
+ .dev_id = 0x00b0,
+ .name = "Collie hack",
+ .uaddr = {
+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */
+ },
+ .DevSize = SIZE_4MiB,
+ .CmdSet = P_ID_INTEL_EXT,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x10000,64),
+ }
+ }, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29F032B,
.name = "AMD AM29F032B",


--
Thanks, Sharp!

2005-11-10 23:58:04

by Todd Poynor

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Pavel Machek wrote:
>
> With these hacks, I'm able to mount flash at least read-only. On
> attempt to remount read-write, I get
>
> "Write error in obliterating obsoleted node at 0x00bc0000: -30
> ...
> Erase at 0x00c00000 failed immediately: -EROFS. Is the sector locked?"
>
> Is it good news?

I see the old sharp driver has a normally-not-defined AUTOUNLOCK symbol
that would enable some code to unlock blocks before writing/erasing
(which isn't recommended since the code doesn't know the policy on
whether the block is supposed to be locked). The tree previously in use
may have had something similar setup. It seems these flashes have all
blocks locked by default at power up.

Try flash_unlock /dev/mtdX before remounting. More automatic means of
handling this are still under debate, I need to try another stab at
resolving that soon.

Looks like you're close to obsoleting the pre-CFI Sharp flash driver,
it's good news...

--
Todd

2005-11-11 00:17:17

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> >With these hacks, I'm able to mount flash at least read-only. On
> >attempt to remount read-write, I get
> >
> >"Write error in obliterating obsoleted node at 0x00bc0000: -30
> >...
> >Erase at 0x00c00000 failed immediately: -EROFS. Is the sector locked?"
> >
> >Is it good news?
>
> I see the old sharp driver has a normally-not-defined AUTOUNLOCK symbol
> that would enable some code to unlock blocks before writing/erasing
> (which isn't recommended since the code doesn't know the policy on
> whether the block is supposed to be locked). The tree previously in use
> may have had something similar setup. It seems these flashes have all
> blocks locked by default at power up.

Is there some quick hack I can do in kernel to unlock it? Is it
possible to accidentally unlock "BIOS" area and brick the device?

> Try flash_unlock /dev/mtdX before remounting. More automatic means of
> handling this are still under debate, I need to try another stab at
> resolving that soon.

Good news is that I do have /dev/mtdX. Bad news is I do not have
flash_unlock. Does anyone have binary suitable for arm, preferably
statically linked?

> Looks like you're close to obsoleting the pre-CFI Sharp flash driver,
> it's good news...

Ok, good. Read-only access is certainly better than nothing, and might
even be enough. Sharp shipped it with flash read-only originally.

Pavel
--
Thanks, Sharp!

2005-11-11 07:02:08

by Ian Campbell

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

On Fri, 2005-11-11 at 01:16 +0100, Pavel Machek wrote:
> Hi!
>
> > >With these hacks, I'm able to mount flash at least read-only. On
> > >attempt to remount read-write, I get
> > >
> > >"Write error in obliterating obsoleted node at 0x00bc0000: -30
> > >...
> > >Erase at 0x00c00000 failed immediately: -EROFS. Is the sector locked?"
> > >
> > >Is it good news?
> >
> > I see the old sharp driver has a normally-not-defined AUTOUNLOCK symbol
> > that would enable some code to unlock blocks before writing/erasing
> > (which isn't recommended since the code doesn't know the policy on
> > whether the block is supposed to be locked). The tree previously in use
> > may have had something similar setup. It seems these flashes have all
> > blocks locked by default at power up.
>
> Is there some quick hack I can do in kernel to unlock it?

I use the following on my device:

mtd = do_map_probe(...);

if (!mtd) { ...err... }

mtd->owner = THIS_MODULE;

mtd->unlock(mtd,0,mtd->size);

> Is it possible to accidentally unlock "BIOS" area and brick the device?

Yep, but you could modify the parameters to unlock to no do so.
Depending on you partitioning scheme you might be able to use that to
figure out what to unlock...

Ian.

--
Ian Campbell

The most exciting phrase to hear in science, the one that heralds new
discoveries, is not "Eureka!" (I found it!) but "That's funny ..."
-- Isaac Asimov


Attachments:
signature.asc (189.00 B)
This is a digitally signed message part

2005-11-12 23:48:23

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > > I see the old sharp driver has a normally-not-defined AUTOUNLOCK symbol
> > > that would enable some code to unlock blocks before writing/erasing
> > > (which isn't recommended since the code doesn't know the policy on
> > > whether the block is supposed to be locked). The tree previously in use
> > > may have had something similar setup. It seems these flashes have all
> > > blocks locked by default at power up.
> >
> > Is there some quick hack I can do in kernel to unlock it?
>
> I use the following on my device:
>
> mtd = do_map_probe(...);
>
> if (!mtd) { ...err... }
>
> mtd->owner = THIS_MODULE;
>
> mtd->unlock(mtd,0,mtd->size);
>
> > Is it possible to accidentally unlock "BIOS" area and brick the device?
>
> Yep, but you could modify the parameters to unlock to no do so.
> Depending on you partitioning scheme you might be able to use that to
> figure out what to unlock...

I tried this one. Size 0xc0000 is reported as a "bootloader" during
boot.

[Plus I get a warning from jffs2 that flashsize is not aligned to
erasesize. Then I get lot of messages that empty flash at XXX ends at
XXX.]

Any more ideas?
Pavel

diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -208,8 +208,8 @@ static void collie_set_vpp(int vpp)
}

static struct flash_platform_data collie_flash_data = {
-// .map_name = "jedec_probe",
- .map_name = "sharp",
+ .map_name = "jedec_probe",
+// .map_name = "sharp",
.set_vpp = collie_set_vpp,
.parts = collie_partitions,
.nr_parts = ARRAY_SIZE(collie_partitions),
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -211,6 +211,7 @@ static int sa1100_probe_subdev(struct sa
goto err;
}
subdev->mtd->owner = THIS_MODULE;
+ subdev->mtd->unlock(subdev->mtd, 0xc0000, subdev->mtd->size);

printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
"%d-bit\n", phys, subdev->mtd->size >> 20,




--
Thanks, Sharp!

2005-11-13 10:35:26

by Ian Campbell

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

On Sat, 2005-11-12 at 22:33 +0100, Pavel Machek wrote:
> I tried this one. Size 0xc0000 is reported as a "bootloader" during
> boot.
>
> [Plus I get a warning from jffs2 that flashsize is not aligned to
> erasesize. Then I get lot of messages that empty flash at XXX ends at
> XXX.]

What erase size did you end up using? Is 0xc0000 a multiple of it?

> + subdev->mtd->unlock(subdev->mtd, 0xc0000, subdev->mtd->size);

Probably unrelated to the actual problems, but shouldn't that be
subdev->mtd->size - 0xc0000 at the end?

Ian.
--
Ian Campbell


Attachments:
signature.asc (189.00 B)
This is a digitally signed message part

2005-11-13 19:39:59

by Todd Poynor

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Pavel Machek wrote:

> [Plus I get a warning from jffs2 that flashsize is not aligned to
> erasesize. Then I get lot of messages that empty flash at XXX ends at
> XXX.]

The datasheet ref'ed earlier says the chips have a 64KB erase block
size, and the sharp driver multiplies that value by an interleave of 4
chips to set the erase size. What erase size is set under the new
setup? cat /proc/mtd or set loglevel for KERN_DEBUG at chip probe time.
The new code is setting it based on what was read from the CFI query
info reported by the chip times the interleave factor (which apparently
should be set as 4 after detecting 4 chips if CONFIG_MTD_CFI_I4=y).


--
Todd

2005-11-14 15:33:47

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> >[Plus I get a warning from jffs2 that flashsize is not aligned to
> >erasesize. Then I get lot of messages that empty flash at XXX ends at
> >XXX.]
>
> The datasheet ref'ed earlier says the chips have a 64KB erase block
> size, and the sharp driver multiplies that value by an interleave of 4
> chips to set the erase size. What erase size is set under the new

I'm currently using:

{
.mfr_id = 0x00b0,
.dev_id = 0x00b0,
.name = "Collie hack",
.uaddr = {
[0] = MTD_UADDR_UNNECESSARY, /* x8 */
},
.DevSize = SIZE_4MiB,
.CmdSet = P_ID_INTEL_STD,
.NumEraseRegions= 1,
.regions = {
ERASEINFO(0x10000,64),
}
},

...so I should use ERASEINFO(0x40000,16)?

> setup? cat /proc/mtd or set loglevel for KERN_DEBUG at chip probe time.
> The new code is setting it based on what was read from the CFI query
> info reported by the chip times the interleave factor (which apparently
> should be set as 4 after detecting 4 chips if CONFIG_MTD_CFI_I4=y).

I do not have collie with me right now.
Pavel
--
Thanks, Sharp!

2005-11-14 15:33:44

by Pavel Machek

[permalink] [raw]
Subject: Re: latest mtd changes broke collie

Hi!

> > I tried this one. Size 0xc0000 is reported as a "bootloader" during
> > boot.
> >
> > [Plus I get a warning from jffs2 that flashsize is not aligned to
> > erasesize. Then I get lot of messages that empty flash at XXX ends at
> > XXX.]
>
> What erase size did you end up using? Is 0xc0000 a multiple of it?

I ended up using ERASEINFO(0x10000,64), but I should probably be using
ERASEINFO(0x40000,16).

> > + subdev->mtd->unlock(subdev->mtd, 0xc0000, subdev->mtd->size);
>
> Probably unrelated to the actual problems, but shouldn't that be
> subdev->mtd->size - 0xc0000 at the end?

Fixed, thanks.
Pavel
--
Thanks, Sharp!