linux-kexecboot: use hacked sharp-flash driver
authorThomas Kunze <thommycheck@gmx.de>
Sat, 18 Oct 2008 00:04:35 +0000 (02:04 +0200)
committerThomas Kunze <thommycheck@gmx.de>
Sat, 18 Oct 2008 00:06:07 +0000 (02:06 +0200)
packages/kexecboot/linux-kexecboot-2.6.26/collie.patch
packages/kexecboot/linux-kexecboot-2.6.26/collie/defconfig
packages/kexecboot/linux-kexecboot_2.6.26.bb

index 6dad002..750be8e 100644 (file)
@@ -1,8 +1,8 @@
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index c7ad324..daa2e0a 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -998,7 +998,7 @@ config CPU_FREQ_SA1100
+Index: linux-2.6.26/arch/arm/Kconfig
+===================================================================
+--- linux-2.6.26.orig/arch/arm/Kconfig 2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/arch/arm/Kconfig      2008-10-17 18:15:31.391792839 +0200
+@@ -967,7 +967,7 @@
  
  config CPU_FREQ_SA1110
        bool
@@ -11,11 +11,24 @@ index c7ad324..daa2e0a 100644
        default y
  
  config CPU_FREQ_INTEGRATOR
-diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c
-index e508028..36f726c 100644
---- a/arch/arm/mach-sa1100/dma.c
-+++ b/arch/arm/mach-sa1100/dma.c
-@@ -39,7 +39,7 @@ typedef struct {
+Index: linux-2.6.26/arch/arm/mach-sa1100/collie.c
+===================================================================
+--- linux-2.6.26.orig/arch/arm/mach-sa1100/collie.c    2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/arch/arm/mach-sa1100/collie.c 2008-10-17 18:15:31.391792839 +0200
+@@ -206,7 +206,7 @@
+ }
+ static struct flash_platform_data collie_flash_data = {
+-      .map_name       = "cfi_probe",
++      .map_name       = "sharp",
+       .set_vpp        = collie_set_vpp,
+       .parts          = collie_partitions,
+       .nr_parts       = ARRAY_SIZE(collie_partitions),
+Index: linux-2.6.26/arch/arm/mach-sa1100/dma.c
+===================================================================
+--- linux-2.6.26.orig/arch/arm/mach-sa1100/dma.c       2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/arch/arm/mach-sa1100/dma.c    2008-10-17 18:15:31.399789199 +0200
+@@ -39,7 +39,7 @@
  
  static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
  
@@ -24,11 +37,11 @@ index e508028..36f726c 100644
  
  
  static irqreturn_t dma_irq_handler(int irq, void *dev_id)
-diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
-index 9caed30..79e19bf 100644
---- a/drivers/input/keyboard/locomokbd.c
-+++ b/drivers/input/keyboard/locomokbd.c
-@@ -265,6 +265,7 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev)
+Index: linux-2.6.26/drivers/input/keyboard/locomokbd.c
+===================================================================
+--- linux-2.6.26.orig/drivers/input/keyboard/locomokbd.c       2008-10-17 18:13:16.000000000 +0200
++++ linux-2.6.26/drivers/input/keyboard/locomokbd.c    2008-10-17 18:15:31.403791239 +0200
+@@ -272,6 +272,7 @@
        for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
                set_bit(locomokbd->keycode[i], input_dev->keybit);
        clear_bit(0, input_dev->keybit);
@@ -36,11 +49,11 @@ index 9caed30..79e19bf 100644
  
        /* attempt to get the interrupt */
        err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
-diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
-index 9f93c29..33fc5d6 100644
---- a/drivers/mfd/Kconfig
-+++ b/drivers/mfd/Kconfig
-@@ -72,4 +72,10 @@ config MCP_UCB1200_TS
+Index: linux-2.6.26/drivers/mfd/Kconfig
+===================================================================
+--- linux-2.6.26.orig/drivers/mfd/Kconfig      2008-10-17 18:13:21.000000000 +0200
++++ linux-2.6.26/drivers/mfd/Kconfig   2008-10-17 18:15:31.403791239 +0200
+@@ -77,4 +77,10 @@
        tristate "Touchscreen interface support"
        depends on MCP_UCB1200 && INPUT
  
@@ -51,11 +64,11 @@ index 9f93c29..33fc5d6 100644
 +        Driver for touchscreen on collie - sharp sl-5500.
 +
  endmenu
-diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
-index 33daa2f..0885ccd 100644
---- a/drivers/mfd/Makefile
-+++ b/drivers/mfd/Makefile
-@@ -16,7 +16,7 @@ obj-$(CONFIG_MCP)            += mcp-core.o
+Index: linux-2.6.26/drivers/mfd/Makefile
+===================================================================
+--- linux-2.6.26.orig/drivers/mfd/Makefile     2008-10-17 18:13:21.000000000 +0200
++++ linux-2.6.26/drivers/mfd/Makefile  2008-10-17 18:15:31.407791679 +0200
+@@ -14,7 +14,7 @@
  obj-$(CONFIG_MCP_SA11X0)      += mcp-sa11x0.o
  obj-$(CONFIG_MCP_UCB1200)     += ucb1x00-core.o
  obj-$(CONFIG_MCP_UCB1200_TS)  += ucb1x00-ts.o
@@ -64,11 +77,10 @@ index 33daa2f..0885ccd 100644
  ifeq ($(CONFIG_SA1100_ASSABET),y)
  obj-$(CONFIG_MCP_UCB1200)     += ucb1x00-assabet.o
  endif
-diff --git a/drivers/mfd/collie-ts.c b/drivers/mfd/collie-ts.c
-new file mode 100644
-index 0000000..ddde5fc
---- /dev/null
-+++ b/drivers/mfd/collie-ts.c
+Index: linux-2.6.26/drivers/mfd/collie-ts.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.26/drivers/mfd/collie-ts.c       2008-10-17 18:15:31.415790559 +0200
 @@ -0,0 +1,449 @@
 +/*
 + *  Touchscreen driver for UCB1x00-based touchscreens
@@ -103,9 +115,9 @@ index 0000000..ddde5fc
 +#include <linux/freezer.h>
 +#include <linux/slab.h>
 +#include <linux/kthread.h>
++#include <linux/semaphore.h>
 +
 +#include <asm/dma.h>
-+#include <asm/semaphore.h>
 +#include <asm/arch/collie.h>
 +#include <asm/mach-types.h>
 +
@@ -519,10 +531,10 @@ index 0000000..ddde5fc
 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 +MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
 +MODULE_LICENSE("GPL");
-diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h
-index a8ad8a0..137b043 100644
---- a/drivers/mfd/ucb1x00.h
-+++ b/drivers/mfd/ucb1x00.h
+Index: linux-2.6.26/drivers/mfd/ucb1x00.h
+===================================================================
+--- linux-2.6.26.orig/drivers/mfd/ucb1x00.h    2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/mfd/ucb1x00.h 2008-10-17 18:15:31.415790559 +0200
 @@ -34,7 +34,10 @@
  #define UCB_IE_TCLIP          (1 << 14)
  #define UCB_IE_ACLIP          (1 << 15)
@@ -534,28 +546,719 @@ index a8ad8a0..137b043 100644
  
  #define UCB_TC_A      0x05
  #define UCB_TC_A_LOOP         (1 << 7)        /* UCB1200 */
-diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
-index c7d5a52..215bec2 100644
---- a/drivers/mtd/maps/sa1100-flash.c
-+++ b/drivers/mtd/maps/sa1100-flash.c
-@@ -210,6 +210,12 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
+Index: linux-2.6.26/drivers/mtd/chips/Kconfig
+===================================================================
+--- linux-2.6.26.orig/drivers/mtd/chips/Kconfig        2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/mtd/chips/Kconfig     2008-10-17 18:15:31.419791479 +0200
+@@ -239,5 +239,13 @@
+         used for XIP purposes.  If you're not sure what this is all about
+         then say N.
++config MTD_SHARP
++        tristate "pre-CFI Sharp chip support"
++        depends on MTD
++        help
++          This option enables support for flash chips using Sharp-compatible
++          commands, including some which are not CFI-compatible and hence
++          cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
++
+ endmenu
+Index: linux-2.6.26/drivers/mtd/chips/Makefile
+===================================================================
+--- linux-2.6.26.orig/drivers/mtd/chips/Makefile       2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/mtd/chips/Makefile    2008-10-17 18:15:31.419791479 +0200
+@@ -12,4 +12,5 @@
+ obj-$(CONFIG_MTD_JEDECPROBE)  += jedec_probe.o
+ obj-$(CONFIG_MTD_RAM)         += map_ram.o
+ obj-$(CONFIG_MTD_ROM)         += map_rom.o
++obj-$(CONFIG_MTD_SHARP)         += sharp.o
+ obj-$(CONFIG_MTD_ABSENT)      += map_absent.o
+Index: linux-2.6.26/drivers/mtd/chips/sharp.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.26/drivers/mtd/chips/sharp.c     2008-10-17 18:15:31.423790399 +0200
+@@ -0,0 +1,645 @@
++/*
++ * MTD chip driver for pre-CFI Sharp flash chips
++ *
++ * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
++ *           2000,2001 Lineo, Inc.
++ *
++ * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner 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 */
++
++static 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];
++};
++
++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();
++      }
++}
++
++static struct mtd_info *sharp_probe(struct map_info *map)
++{
++      struct mtd_info *mtd = NULL;
++      struct sharp_info *sharp = NULL;
++      int width;
++
++      mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
++      if(!mtd)
++              return NULL;
++
++      sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
++      if(!sharp) {
++              kfree(mtd);
++              return NULL;
++      }
++
++      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->writesize = 1;
++      mtd->name = map->name;
++
++      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) {
++              printk("Sharp chip, %lx, %lx, width = %d\n", read0.x[0], read4.x[0], width);
++              /* Prints b000b0, b000b0, width = 4 on collie */
++              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, 0x%08lx 0x%08lx\n",
++                              read0.x[0], read4.x[0]);
++              }
++      } 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, 0x%08lx 0x%08lx\n",
++                      read0.x[0], read4.x[0]);
++      }
++
++      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 data, status;
++
++      status.x[0] = 0;
++      ret = sharp_wait(map,chip);
++      if (ret < 0)
++              return ret;
++
++      for (try=0; try<10; try++) {
++              long timeo;
++
++              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;
++              timeo = jiffies + (HZ/2);
++
++              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=%08lx\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;
++
++      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=%08lx\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);
++}
++
++static int __init sharp_probe_init(void)
++{
++      printk("MTD Sharp chip driver <ds@lineo.com>\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 <ds@schleef.org>");
++MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");
+Index: linux-2.6.26/drivers/mtd/maps/Kconfig
+===================================================================
+--- linux-2.6.26.orig/drivers/mtd/maps/Kconfig 2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/mtd/maps/Kconfig      2008-10-17 18:15:31.431789839 +0200
+@@ -392,7 +392,7 @@
+ config MTD_SA1100
+       tristate "CFI Flash device mapped on StrongARM SA11x0"
+-      depends on MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS
++      depends on (MTD_CFI || MTD_SHARP) && ARCH_SA1100 && MTD_PARTITIONS
+       help
+         This enables access to the flash chips on most platforms based on
+         the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
+Index: linux-2.6.26/drivers/mtd/maps/sa1100-flash.c
+===================================================================
+--- linux-2.6.26.orig/drivers/mtd/maps/sa1100-flash.c  2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/mtd/maps/sa1100-flash.c       2008-10-17 18:15:31.431789839 +0200
+@@ -210,6 +210,12 @@
                goto err;
        }
        subdev->mtd->owner = THIS_MODULE;
 +      
 +#ifdef CONFIG_SA1100_COLLIE
 +      /* collie flash starts locked */
-+       if (subdev->mtd->unlock)
-+               subdev->mtd->unlock(subdev->mtd, 0xc0000, subdev->mtd->size - 0xc0000);
++//     if (subdev->mtd->unlock)
++//             subdev->mtd->unlock(subdev->mtd, 0xc0000, subdev->mtd->size - 0xc0000);
 +#endif
  
        printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
                "%d-bit\n", phys, subdev->mtd->size >> 20,
-diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
-index 3b4e55c..0ae741d 100644
---- a/drivers/net/wireless/hostap/hostap_cs.c
-+++ b/drivers/net/wireless/hostap/hostap_cs.c
-@@ -35,7 +35,7 @@ static int ignore_cis_vcc;
+Index: linux-2.6.26/drivers/net/wireless/hostap/hostap_cs.c
+===================================================================
+--- linux-2.6.26.orig/drivers/net/wireless/hostap/hostap_cs.c  2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/net/wireless/hostap/hostap_cs.c       2008-10-17 18:15:31.435790279 +0200
+@@ -35,7 +35,7 @@
  module_param(ignore_cis_vcc, int, 0444);
  MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
  
@@ -564,7 +1267,7 @@ index 3b4e55c..0ae741d 100644
  /* struct local_info::hw_priv */
  struct hostap_cs_priv {
        dev_node_t node;
-@@ -499,11 +499,13 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev)
+@@ -499,11 +499,13 @@
  
        PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
        p_dev->conf.IntType = INT_MEMORY_AND_IO;
@@ -579,10 +1282,10 @@ index 3b4e55c..0ae741d 100644
  
        return ret;
  }
-diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
-index 13d5882..6f24d66 100644
---- a/drivers/net/wireless/hostap/hostap_hw.c
-+++ b/drivers/net/wireless/hostap/hostap_hw.c
+Index: linux-2.6.26/drivers/net/wireless/hostap/hostap_hw.c
+===================================================================
+--- linux-2.6.26.orig/drivers/net/wireless/hostap/hostap_hw.c  2008-10-17 18:13:21.000000000 +0200
++++ linux-2.6.26/drivers/net/wireless/hostap/hostap_hw.c       2008-10-17 18:15:31.443789719 +0200
 @@ -54,6 +54,7 @@
  #include "hostap.h"
  #include "hostap_ap.h"
@@ -591,7 +1294,7 @@ index 13d5882..6f24d66 100644
  
  /* #define final_version */
  
-@@ -1497,6 +1498,8 @@ static int prism2_hw_config(struct net_device *dev, int initial)
+@@ -1534,6 +1535,8 @@
        if (local->hw_downloading)
                return 1;
  
@@ -600,7 +1303,7 @@ index 13d5882..6f24d66 100644
        if (prism2_hw_init(dev, initial)) {
                return local->no_pri ? 0 : 1;
        }
-@@ -2628,8 +2631,15 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
+@@ -2665,8 +2668,15 @@
        int events = 0;
        u16 ev;
  
@@ -616,12 +1319,12 @@ index 13d5882..6f24d66 100644
 +      iface = netdev_priv(dev);
 +      local = iface->local;
  
-       prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
-diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
-index 3a874fc..df58aa3 100644
---- a/drivers/net/wireless/hostap/hostap_pci.c
-+++ b/drivers/net/wireless/hostap/hostap_pci.c
+       if(dev->base_addr == 0)
+       {
+Index: linux-2.6.26/drivers/net/wireless/hostap/hostap_pci.c
+===================================================================
+--- linux-2.6.26.orig/drivers/net/wireless/hostap/hostap_pci.c 2008-10-17 18:13:18.000000000 +0200
++++ linux-2.6.26/drivers/net/wireless/hostap/hostap_pci.c      2008-10-17 18:15:31.447790279 +0200
 @@ -19,6 +19,7 @@
  
  #include "hostap_wlan.h"
@@ -630,10 +1333,10 @@ index 3a874fc..df58aa3 100644
  
  static char *dev_info = "hostap_pci";
  
-diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
-index cbf15d7..4475174 100644
---- a/drivers/net/wireless/hostap/hostap_plx.c
-+++ b/drivers/net/wireless/hostap/hostap_plx.c
+Index: linux-2.6.26/drivers/net/wireless/hostap/hostap_plx.c
+===================================================================
+--- linux-2.6.26.orig/drivers/net/wireless/hostap/hostap_plx.c 2008-10-17 18:13:18.000000000 +0200
++++ linux-2.6.26/drivers/net/wireless/hostap/hostap_plx.c      2008-10-17 18:15:31.451790719 +0200
 @@ -21,7 +21,7 @@
  #include <asm/io.h>
  
@@ -643,11 +1346,11 @@ index cbf15d7..4475174 100644
  
  static char *dev_info = "hostap_plx";
  
-diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
-index c5b2a44..eecbe8c 100644
---- a/drivers/pcmcia/sa1100_generic.c
-+++ b/drivers/pcmcia/sa1100_generic.c
-@@ -81,13 +81,14 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev)
+Index: linux-2.6.26/drivers/pcmcia/sa1100_generic.c
+===================================================================
+--- linux-2.6.26.orig/drivers/pcmcia/sa1100_generic.c  2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/pcmcia/sa1100_generic.c       2008-10-17 18:15:31.459789719 +0200
+@@ -81,13 +81,14 @@
        return ret;
  }
  
@@ -669,7 +1372,7 @@ index c5b2a44..eecbe8c 100644
  };
  
  /* sa11x0_pcmcia_init()
-@@ -100,7 +101,7 @@ static struct device_driver sa11x0_pcmcia_driver = {
+@@ -100,7 +101,7 @@
   */
  static int __init sa11x0_pcmcia_init(void)
  {
@@ -678,7 +1381,7 @@ index c5b2a44..eecbe8c 100644
  }
  
  /* sa11x0_pcmcia_exit()
-@@ -110,7 +111,7 @@ static int __init sa11x0_pcmcia_init(void)
+@@ -110,7 +111,7 @@
   */
  static void __exit sa11x0_pcmcia_exit(void)
  {
@@ -687,11 +1390,11 @@ index c5b2a44..eecbe8c 100644
  }
  
  MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
-diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
-index 66ec5d8..aba38d7 100644
---- a/drivers/spi/Kconfig
-+++ b/drivers/spi/Kconfig
-@@ -123,6 +123,10 @@ config SPI_MPC52xx_PSC
+Index: linux-2.6.26/drivers/spi/Kconfig
+===================================================================
+--- linux-2.6.26.orig/drivers/spi/Kconfig      2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/spi/Kconfig   2008-10-17 18:15:31.463790519 +0200
+@@ -123,6 +123,10 @@
          This enables using the Freescale MPC52xx Programmable Serial
          Controller in master SPI mode.
  
@@ -702,11 +1405,11 @@ index 66ec5d8..aba38d7 100644
  config SPI_MPC83xx
        tristate "Freescale MPC83xx/QUICC Engine SPI controller"
        depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
-diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
-index 7fca043..b89992b 100644
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -28,6 +28,7 @@ obj-$(CONFIG_SPI_S3C24XX)            += spi_s3c24xx.o
+Index: linux-2.6.26/drivers/spi/Makefile
+===================================================================
+--- linux-2.6.26.orig/drivers/spi/Makefile     2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/spi/Makefile  2008-10-17 18:15:31.463790519 +0200
+@@ -28,6 +28,7 @@
  obj-$(CONFIG_SPI_TXX9)                        += spi_txx9.o
  obj-$(CONFIG_SPI_XILINX)              += xilinx_spi.o
  obj-$(CONFIG_SPI_SH_SCI)              += spi_sh_sci.o
@@ -714,11 +1417,10 @@ index 7fca043..b89992b 100644
  #     ... add above this line ...
  
  # SPI protocol drivers (device/link on bus)
-diff --git a/drivers/spi/locomo_spi.c b/drivers/spi/locomo_spi.c
-new file mode 100644
-index 0000000..d3a4bd9
---- /dev/null
-+++ b/drivers/spi/locomo_spi.c
+Index: linux-2.6.26/drivers/spi/locomo_spi.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.26/drivers/spi/locomo_spi.c      2008-10-17 18:15:31.471790439 +0200
 @@ -0,0 +1,1097 @@
 +#include <asm/io.h>
 +#include <asm/irq.h>
@@ -1817,11 +2519,10 @@ index 0000000..d3a4bd9
 +MODULE_AUTHOR("Thomas Kunze thommy@tabao.de");
 +MODULE_DESCRIPTION("Collie mmc driver");
 +MODULE_LICENSE("GPL");
-diff --git a/drivers/spi/locomo_spi.h b/drivers/spi/locomo_spi.h
-new file mode 100644
-index 0000000..7e1c0ce
---- /dev/null
-+++ b/drivers/spi/locomo_spi.h
+Index: linux-2.6.26/drivers/spi/locomo_spi.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.26/drivers/spi/locomo_spi.h      2008-10-17 18:15:31.471790439 +0200
 @@ -0,0 +1,75 @@
 +#include <asm/hardware/locomo.h>
 +#ifndef __LOCOMO_SPI_H__
index a65552f..4434962 100644 (file)
@@ -327,13 +327,8 @@ CONFIG_MTD_BLOCK=y
 #
 # RAM/ROM/Flash chip drivers
 #
-CONFIG_MTD_CFI=y
+# CONFIG_MTD_CFI is not set
 # CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-# CONFIG_MTD_CFI_NOSWAP is not set
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
 CONFIG_MTD_MAP_BANK_WIDTH_1=y
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
 CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -344,14 +339,10 @@ 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 is not set
-# CONFIG_MTD_CFI_STAA is not set
-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_XIP is not set
+CONFING_MTD_SHARP=y
 
 #
 # Mapping drivers for chip access
index 6dec914..7d000ff 100644 (file)
@@ -1,6 +1,6 @@
 require linux-kexecboot.inc
 
-FILE_PR = "r4"
+FILE_PR = "r5"
 DEFAULT_PREFERENCE = "-1"
 DEFAULT_PREFERENCE_qemuarm = "-1"
 DEFAULT_PREFERENCE_qemux86 = "-1"