Message ID | m1k5bohs61.fsf@frodo.ebiederm.org |
---|---|
State | Superseded |
Headers | show |
On Fri, 2008-10-31 at 23:33 -0700, Eric W. Biederman wrote: > Forget my last I see now how we can try a 16bit device on an 8 bit > bus. I had missed the type <<=1 in gen_probe_new_chip. Ooops. > > With that said I think we need to fix cfi_send_gen_cmd as this problem > applies to all uses of it. > > Unless I've missed something the patch below completely fixes the > problem. Yeah, that looks better. I had looked at the possibility of continuing to use 'word' addresses and fixing up cfi_build_cmd_addr(), but for some reason I hadn't noticed that it was used _only_ for the unlock addresses (or zero). I thought I was going to need to put a special case in for when it was being used with unlock addresses, and it all got a bit complex. So I switched to using byte addresses in the variables instead. I prefer your approach, although I think the patch isn't quite correct. You have to make sure we properly handle the case of a 16-bit device in 16-bit mode. We mustn't set the byte address to 0x555 there; it has to remain 0x554. We need to do the 'addr |= ....' bit _only_ if the device is in compatibility mode (i.e. interleave * type > map_bankwidth(map)).
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index a972cc6..9e7a236 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -362,19 +362,6 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) /* Set the default CFI lock/unlock addresses */ cfi->addr_unlock1 = 0x555; cfi->addr_unlock2 = 0x2aa; - /* Modify the unlock address if we are in compatibility mode */ - if ( /* x16 in x8 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X8) && - (cfi->cfiq->InterfaceDesc == - CFI_INTERFACE_X8_BY_X16_ASYNC)) || - /* x32 in x16 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X16) && - (cfi->cfiq->InterfaceDesc == - CFI_INTERFACE_X16_BY_X32_ASYNC))) - { - cfi->addr_unlock1 = 0xaaa; - cfi->addr_unlock2 = 0x555; - } } /* CFI mode */ else if (cfi->cfi_mode == CFI_MODE_JEDEC) { diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index d6fb115..0b62217 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -283,7 +283,14 @@ struct cfi_private { */ static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type) { - return (cmd_ofs * type) * interleave; + uint32_t addr = cmd_ofs * type; + /* Modify the unlock address if we are in compatiblity mode. + * For 16bit devices on 8 bit busses + * and 32bit devices on 16 bit busses + * set the low bit of the alternating bit sequence of the address. + */ + addr |= ((cmd_ofs & 2) * type) >> 2; + return addr * interleave; } /*