X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fmtd%2Fmaps%2Fixp4xx.c;h=7a828e3e6446d7f9254f083d3b02bb2e9e02e9e0;hb=ea3c4b126ad63bd782c7bb5266bb4fd88e203169;hp=c510c736ed97233af0606ec5a073ce424b89015e;hpb=9090ed0b82f817bde471bdbb2e73278ab75f5fd3;p=linux-2.6-omap-h63xx.git diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index c510c736ed9..7a828e3e644 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -1,5 +1,5 @@ /* - * $Id: ixp4xx.c,v 1.11 2005/11/06 11:15:51 gleixner Exp $ + * $Id: ixp4xx.c,v 1.13 2005/11/16 16:23:21 dvrabel Exp $ * * drivers/mtd/maps/ixp4xx.c * @@ -34,10 +34,55 @@ #include +/* + * Read/write a 16 bit word from flash address 'addr'. + * + * When the cpu is in little-endian mode it swizzles the address lines + * ('address coherency') so we need to undo the swizzling to ensure commands + * and the like end up on the correct flash address. + * + * To further complicate matters, due to the way the expansion bus controller + * handles 32 bit reads, the byte stream ABCD is stored on the flash as: + * D15 D0 + * +---+---+ + * | A | B | 0 + * +---+---+ + * | C | D | 2 + * +---+---+ + * This means that on LE systems each 16 bit word must be swapped. Note that + * this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI + * data and other flash commands which are always in D7-D0. + */ #ifndef __ARMEB__ +#ifndef CONFIG_MTD_CFI_BE_BYTE_SWAP +# error CONFIG_MTD_CFI_BE_BYTE_SWAP required +#endif + +static inline u16 flash_read16(void __iomem *addr) +{ + return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2))); +} + +static inline void flash_write16(u16 d, void __iomem *addr) +{ + __raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2)); +} + #define BYTE0(h) ((h) & 0xFF) #define BYTE1(h) (((h) >> 8) & 0xFF) + #else + +static inline u16 flash_read16(const void __iomem *addr) +{ + return __raw_readw(addr); +} + +static inline void flash_write16(u16 d, void __iomem *addr) +{ + __raw_writew(d, addr); +} + #define BYTE0(h) (((h) >> 8) & 0xFF) #define BYTE1(h) ((h) & 0xFF) #endif @@ -45,7 +90,7 @@ static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs) { map_word val; - val.x[0] = le16_to_cpu(readw(map->virt + ofs)); + val.x[0] = flash_read16(map->virt + ofs); return val; } @@ -57,37 +102,46 @@ static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs) static void ixp4xx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { - int i; u8 *dest = (u8 *) to; void __iomem *src = map->virt + from; - u16 data; - for (i = 0; i < (len / 2); i++) { - data = le16_to_cpu(readw(src + 2*i)); - dest[i * 2] = BYTE0(data); - dest[i * 2 + 1] = BYTE1(data); + if (len <= 0) + return; + + if (from & 1) { + *dest++ = BYTE1(flash_read16(src)); + src++; + --len; } - if (len & 1) - dest[len - 1] = BYTE0(le16_to_cpu(readw(src + 2*i))); + while (len >= 2) { + u16 data = flash_read16(src); + *dest++ = BYTE0(data); + *dest++ = BYTE1(data); + src += 2; + len -= 2; + } + + if (len > 0) + *dest++ = BYTE0(flash_read16(src)); } -/* +/* * Unaligned writes are ignored, causing the 8-bit * probe to fail and proceed to the 16-bit probe (which succeeds). */ static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr) { if (!(adr & 1)) - writew(cpu_to_le16(d.x[0]), map->virt + adr); + flash_write16(d.x[0], map->virt + adr); } -/* +/* * Fast write16 function without the probing check above */ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) { - writew(cpu_to_le16(d.x[0]), map->virt + adr); + flash_write16(d.x[0], map->virt + adr); } struct ixp4xx_flash_info { @@ -99,13 +153,12 @@ struct ixp4xx_flash_info { static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -static int ixp4xx_flash_remove(struct device *_dev) +static int ixp4xx_flash_remove(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(_dev); struct flash_platform_data *plat = dev->dev.platform_data; - struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev); + struct ixp4xx_flash_info *info = platform_get_drvdata(dev); - dev_set_drvdata(&dev->dev, NULL); + platform_set_drvdata(dev, NULL); if(!info) return 0; @@ -117,8 +170,7 @@ static int ixp4xx_flash_remove(struct device *_dev) if (info->map.virt) iounmap(info->map.virt); - if (info->partitions) - kfree(info->partitions); + kfree(info->partitions); if (info->res) { release_resource(info->res); @@ -131,9 +183,8 @@ static int ixp4xx_flash_remove(struct device *_dev) return 0; } -static int ixp4xx_flash_probe(struct device *_dev) +static int ixp4xx_flash_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(_dev); struct flash_platform_data *plat = dev->dev.platform_data; struct ixp4xx_flash_info *info; int err = -1; @@ -151,10 +202,10 @@ static int ixp4xx_flash_probe(struct device *_dev) if(!info) { err = -ENOMEM; goto Error; - } + } memzero(info, sizeof(struct ixp4xx_flash_info)); - dev_set_drvdata(&dev->dev, info); + platform_set_drvdata(dev, info); /* * Tell the MTD layer we're not 1:1 mapped so that it does @@ -174,8 +225,8 @@ static int ixp4xx_flash_probe(struct device *_dev) info->map.write = ixp4xx_probe_write16, info->map.copy_from = ixp4xx_copy_from, - info->res = request_mem_region(dev->resource->start, - dev->resource->end - dev->resource->start + 1, + info->res = request_mem_region(dev->resource->start, + dev->resource->end - dev->resource->start + 1, "IXP4XXFlash"); if (!info->res) { printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n"); @@ -198,11 +249,11 @@ static int ixp4xx_flash_probe(struct device *_dev) goto Error; } info->mtd->owner = THIS_MODULE; - + /* Use the fast version */ info->map.write = ixp4xx_write16, - err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); + err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start); if (err > 0) { err = add_mtd_partitions(info->mtd, info->partitions, err); if(err) @@ -215,25 +266,26 @@ static int ixp4xx_flash_probe(struct device *_dev) return 0; Error: - ixp4xx_flash_remove(_dev); + ixp4xx_flash_remove(dev); return err; } -static struct device_driver ixp4xx_flash_driver = { - .name = "IXP4XX-Flash", - .bus = &platform_bus_type, +static struct platform_driver ixp4xx_flash_driver = { .probe = ixp4xx_flash_probe, .remove = ixp4xx_flash_remove, + .driver = { + .name = "IXP4XX-Flash", + }, }; static int __init ixp4xx_flash_init(void) { - return driver_register(&ixp4xx_flash_driver); + return platform_driver_register(&ixp4xx_flash_driver); } static void __exit ixp4xx_flash_exit(void) { - driver_unregister(&ixp4xx_flash_driver); + platform_driver_unregister(&ixp4xx_flash_driver); }