From 697c74552a2cd97b639ef6551575e1d6cbc30c27 Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Sat, 2 Jul 2005 11:08:39 +0000 Subject: [PATCH] unify gcc 3.4 fixes, move flash chip drivers to generic patches, move diag_led driver to separate patch, update docs SVN-Revision: 1316 --- openwrt/target/linux/linux-2.4/README | 67 +- .../linux-2.4/patches/brcm/001-bcm47xx.patch | 1185 ----------------- .../linux-2.4/patches/brcm/004-diag_led.patch | 265 ++++ .../patches/generic/005-mtd_flashtypes.patch | 925 +++++++++++++ .../generic/205-gcc_3.4_ldscript.patch | 10 - .../patches/generic/206-gcc_3.4_fixes.patch | 53 +- 6 files changed, 1267 insertions(+), 1238 deletions(-) create mode 100644 openwrt/target/linux/linux-2.4/patches/brcm/004-diag_led.patch create mode 100644 openwrt/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch delete mode 100644 openwrt/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch diff --git a/openwrt/target/linux/linux-2.4/README b/openwrt/target/linux/linux-2.4/README index 3f7cad23e2..d5e2d6392e 100644 --- a/openwrt/target/linux/linux-2.4/README +++ b/openwrt/target/linux/linux-2.4/README @@ -1,32 +1,29 @@ -Description of kernel patches in patches: +Description of kernel patches: + + +generic/ + Generic patches for vanilla Linux kernel 000-linux_mips.patch This is the diff between vanilla linux-2.4.30 and linux-mips.org kernel (CVS tag 2_4_30 used). The kernel source from linux-mips.org CVS repository has newer drivers and code then vanilla linux-2.4.30 especially for the mips architecture. -001-bcm47xx.patch - This is the broadcom specific code from asus (1941) GPL source tarball. - There are many small patches included, so it works with linux 2.4.30 kernel. - The original code is based on Linux 2.4.20. - -002-wl_fix.patch - The driver for the wireless lan chip on brcm47xx based routers is binary only. - This means it depends on older data structures in the kernel. We backported some - of the changes or changed some of the data structures to work with the binary modul. - This is a really bad hack, but without source code, there is no better chance to get - the driver working with newer kernels. - -003-squashfs.patch +001-squashfs.patch Support for the squashfs filesystem. It has better compression ratio then cramfs. -004-squashfs_lzma.patch +002-squashfs_lzma.patch LZMA Addon patch from Oleg I. Vdovikin for the squashfs filesystem. Even better compression ratio. -005-jffs2_compression.patch +003-jffs2_compression.patch Compression for jffs2 filesystem. - + +004-exec_pagesize.patch + +005-mtd_flashtypes.patch + Additional mtd drivers for flash chips + 100-ebtables.patch Filtering packets on ethernet layer. See http://ebtables.sf.net @@ -57,9 +54,6 @@ Description of kernel patches in patches: 110-netdev_random_core.patch Support for gathering entropy from network devices for /dev/random -111-netdev_random_et.patch - Patch agains the Broadcom et driver to gather entropy for /dev/random - 200-i4l.patch 201-hfc_usb_backport.patch @@ -71,8 +65,37 @@ Description of kernel patches in patches: 204-net_b44.patch Support for the BCM47xx chipset in the b44 driver -205-gcc_3.4_ldscript.patch - 206-gcc_3.4_fixes.patch + mips specific gcc 3.4 fixes 207-gcc_4.0_fixes.patch + gcc 4.0 fixes + + +brcm/ + Broadcom specific patches + +001-bcm47xx.patch + This is the broadcom specific code from asus (1941) GPL source tarball. + There are many small patches included, so it works with linux 2.4.30 kernel. + The original code is based on Linux 2.4.20. + +002-wl_fix.patch + The driver for the wireless lan chip on brcm47xx based routers is binary only. + This means it depends on older data structures in the kernel. We backported some + of the changes or changed some of the data structures to work with the binary modul. + This is a really bad hack, but without source code, there is no better chance to get + the driver working with newer kernels. + +003-bcm47xx_cache_fixes.patch + +004-diag_led.patch + OpenWrt diag (led and reset button) driver + + +ar7/ + TI AR7 specific patches + +000-ar7_support.patch + +001-flash_map.patch diff --git a/openwrt/target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch b/openwrt/target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch index 5e3fc34fe6..80145c9493 100644 --- a/openwrt/target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch +++ b/openwrt/target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch @@ -12831,926 +12831,6 @@ diff -Nur linux-2.4.30/drivers/char/serial.c linux-2.4.30-brcm/drivers/char/seri if (doflow) state->flags |= ASYNC_CONS_FLOW; info = &async_sercons; -diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c linux-2.4.30-brcm/drivers/mtd/chips/cfi_cmdset_0701.c ---- linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.30-brcm/drivers/mtd/chips/cfi_cmdset_0701.c 2005-05-22 22:55:52.000000000 +0200 -@@ -0,0 +1,855 @@ -+/* -+ * Common Flash Interface support: -+ * SST Standard Vendor Command Set (ID 0x0701) -+ * -+ * Copyright (C) 2000 Crossnet Co. -+ * -+ * 2_by_8 routines added by Simon Munton -+ * -+ * This code is GPL -+ * -+ * $Id: cfi_cmdset_0701.c,v 1.1 2005/03/16 13:50:00 wbx Exp $ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int cfi_sststd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -+static int cfi_sststd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -+static int cfi_sststd_erase_onesize(struct mtd_info *, struct erase_info *); -+static int cfi_sststd_erase_varsize(struct mtd_info *, struct erase_info *); -+static void cfi_sststd_sync (struct mtd_info *); -+static int cfi_sststd_suspend (struct mtd_info *); -+static void cfi_sststd_resume (struct mtd_info *); -+ -+static void cfi_sststd_destroy(struct mtd_info *); -+ -+struct mtd_info *cfi_cmdset_0701(struct map_info *, int); -+static struct mtd_info *cfi_sststd_setup (struct map_info *); -+ -+ -+static struct mtd_chip_driver cfi_sststd_chipdrv = { -+ probe: NULL, /* Not usable directly */ -+ destroy: cfi_sststd_destroy, -+ name: "cfi_cmdset_0701", -+ module: THIS_MODULE -+}; -+ -+struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ int ofs_factor = cfi->interleave * cfi->device_type; -+ int i; -+ __u8 major, minor; -+ __u32 base = cfi->chips[0].start; -+ -+ if (cfi->cfi_mode==1){ -+ __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; -+ -+ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ -+ major = cfi_read_query(map, base + (adr+3)*ofs_factor); -+ minor = cfi_read_query(map, base + (adr+4)*ofs_factor); -+ -+ printk(" SST Query Table v%c.%c at 0x%4.4X\n", -+ major, minor, adr); -+ cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ -+ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ cfi->mfr = cfi_read_query(map, base); -+ cfi->id = cfi_read_query(map, base + ofs_factor); -+ -+ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ -+ switch (cfi->device_type) { -+ case CFI_DEVICETYPE_X16: -+ cfi->addr_unlock1 = 0x5555; -+ cfi->addr_unlock2 = 0x2AAA; -+ break; -+ default: -+ printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0701 device type %d\n", cfi->device_type); -+ return NULL; -+ } -+ } /* CFI mode */ -+ -+ for (i=0; i< cfi->numchips; i++) { -+ cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; -+ cfi->chips[i].buffer_write_time = 1<cfiq->BufWriteTimeoutTyp; -+ cfi->chips[i].erase_time = 1<cfiq->BlockEraseTimeoutTyp; -+ } -+ -+ map->fldrv = &cfi_sststd_chipdrv; -+ MOD_INC_USE_COUNT; -+ -+ cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ return cfi_sststd_setup(map); -+} -+ -+static struct mtd_info *cfi_sststd_setup(struct map_info *map) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct mtd_info *mtd; -+ unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; -+ -+ mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); -+ printk("number of %s chips: %d\n", (cfi->cfi_mode)?"JEDEC":"CFI",cfi->numchips); -+ -+ if (!mtd) { -+ printk("Failed to allocate memory for MTD device\n"); -+ kfree(cfi->cmdset_priv); -+ return NULL; -+ } -+ -+ memset(mtd, 0, sizeof(*mtd)); -+ mtd->priv = map; -+ mtd->type = MTD_NORFLASH; -+ /* Also select the correct geometry setup too */ -+ mtd->size = devsize * cfi->numchips; -+ -+ if (cfi->cfiq->NumEraseRegions == 1) { -+ /* No need to muck about with multiple erase sizes */ -+ mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave; -+ } else { -+ unsigned long offset = 0; -+ int i,j; -+ -+ mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; -+ mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); -+ if (!mtd->eraseregions) { -+ printk("Failed to allocate memory for MTD erase region info\n"); -+ kfree(cfi->cmdset_priv); -+ return NULL; -+ } -+ -+ for (i=0; icfiq->NumEraseRegions; i++) { -+ unsigned long ernum, ersize; -+ ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave; -+ ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1; -+ -+ if (mtd->erasesize < ersize) { -+ mtd->erasesize = ersize; -+ } -+ for (j=0; jnumchips; j++) { -+ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset; -+ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize; -+ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum; -+ } -+ offset += (ersize * ernum); -+ } -+ -+ // debug -+ for (i=0; inumeraseregions;i++){ -+ printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", -+ i,mtd->eraseregions[i].offset, -+ mtd->eraseregions[i].erasesize, -+ mtd->eraseregions[i].numblocks); -+ } -+ } -+ -+ switch (CFIDEV_BUSWIDTH) -+ { -+ case 1: -+ case 2: -+ case 4: -+ if (mtd->numeraseregions > 1) -+ mtd->erase = cfi_sststd_erase_varsize; -+ else -+ mtd->erase = cfi_sststd_erase_onesize; -+ mtd->read = cfi_sststd_read; -+ mtd->write = cfi_sststd_write; -+ break; -+ -+ default: -+ printk("Unsupported buswidth\n"); -+ kfree(mtd); -+ kfree(cfi->cmdset_priv); -+ return NULL; -+ break; -+ } -+ mtd->sync = cfi_sststd_sync; -+ mtd->suspend = cfi_sststd_suspend; -+ mtd->resume = cfi_sststd_resume; -+ mtd->flags = MTD_CAP_NORFLASH; -+ map->fldrv = &cfi_sststd_chipdrv; -+ mtd->name = map->name; -+ MOD_INC_USE_COUNT; -+ return mtd; -+} -+ -+static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long timeo = jiffies + HZ; -+ -+ retry: -+ cfi_spin_lock(chip->mutex); -+ -+ if (chip->state != FL_READY){ -+ printk("Waiting for chip to read, status = %d\n", chip->state); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ -+ cfi_spin_unlock(chip->mutex); -+ -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ timeo = jiffies + HZ; -+ -+ goto retry; -+ } -+ -+ adr += chip->start; -+ -+ chip->state = FL_READY; -+ -+ map->copy_from(map, buf, adr, len); -+ -+ wake_up(&chip->wq); -+ cfi_spin_unlock(chip->mutex); -+ -+ return 0; -+} -+ -+static int cfi_sststd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ unsigned long ofs; -+ int chipnum; -+ int ret = 0; -+ -+ /* ofs: offset within the first chip that the first read should start */ -+ -+ chipnum = (from >> cfi->chipshift); -+ ofs = from - (chipnum << cfi->chipshift); -+ -+ -+ *retlen = 0; -+ -+ while (len) { -+ unsigned long thislen; -+ -+ if (chipnum >= cfi->numchips) -+ break; -+ -+ if ((len + ofs -1) >> cfi->chipshift) -+ thislen = (1<chipshift) - ofs; -+ else -+ thislen = len; -+ -+ ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); -+ if (ret) -+ break; -+ -+ *retlen += thislen; -+ len -= thislen; -+ buf += thislen; -+ -+ ofs = 0; -+ chipnum++; -+ } -+ return ret; -+} -+ -+static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast) -+{ -+ unsigned long timeo = jiffies + HZ; -+ unsigned int Last[4]; -+ unsigned long Count = 0; -+ struct cfi_private *cfi = map->fldrv_priv; -+ DECLARE_WAITQUEUE(wait, current); -+ int ret = 0; -+ -+ retry: -+ cfi_spin_lock(chip->mutex); -+ -+ if (chip->state != FL_READY){ -+ printk("Waiting for chip to write, status = %d\n", chip->state); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ -+ cfi_spin_unlock(chip->mutex); -+ -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ printk("Wake up to write:\n"); -+ timeo = jiffies + HZ; -+ -+ goto retry; -+ } -+ -+ chip->state = FL_WRITING; -+ -+ adr += chip->start; -+ ENABLE_VPP(map); -+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); -+ cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); -+ -+ cfi_write(map, datum, adr); -+ -+ cfi_spin_unlock(chip->mutex); -+ cfi_udelay(chip->word_write_time); -+ cfi_spin_lock(chip->mutex); -+ -+ Last[0] = cfi_read(map, adr); -+ // printk("Last[0] is %x\n", Last[0]); -+ Last[1] = cfi_read(map, adr); -+ // printk("Last[1] is %x\n", Last[1]); -+ Last[2] = cfi_read(map, adr); -+ // printk("Last[2] is %x\n", Last[2]); -+ -+ for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){ -+ cfi_spin_unlock(chip->mutex); -+ cfi_udelay(10); -+ cfi_spin_lock(chip->mutex); -+ -+ Last[Count % 4] = cfi_read(map, adr); -+ // printk("Last[%d%%4] is %x\n", Count, Last[Count%4]); -+ } -+ -+ if (Last[(Count - 1) % 4] != datum){ -+ printk("Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum); -+ cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL); -+ DISABLE_VPP(map); -+ ret = -EIO; -+ } -+ DISABLE_VPP(map); -+ chip->state = FL_READY; -+ wake_up(&chip->wq); -+ cfi_spin_unlock(chip->mutex); -+ -+ return ret; -+} -+ -+static int cfi_sststd_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 cfi_private *cfi = map->fldrv_priv; -+ int ret = 0; -+ int chipnum; -+ unsigned long ofs, chipstart; -+ -+ *retlen = 0; -+ if (!len) -+ return 0; -+ -+ chipnum = to >> cfi->chipshift; -+ ofs = to - (chipnum << cfi->chipshift); -+ chipstart = cfi->chips[chipnum].start; -+ -+ /* If it's not bus-aligned, do the first byte write */ -+ if (ofs & (CFIDEV_BUSWIDTH-1)) { -+ unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1); -+ int i = ofs - bus_ofs; -+ int n = 0; -+ u_char tmp_buf[4]; -+ __u32 datum; -+ -+ map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); -+ while (len && i < CFIDEV_BUSWIDTH) -+ tmp_buf[i++] = buf[n++], len--; -+ -+ if (cfi_buswidth_is_2()) { -+ datum = *(__u16*)tmp_buf; -+ } else if (cfi_buswidth_is_4()) { -+ datum = *(__u32*)tmp_buf; -+ } else { -+ return -EINVAL; /* should never happen, but be safe */ -+ } -+ -+ ret = do_write_oneword(map, &cfi->chips[chipnum], -+ bus_ofs, datum, 0); -+ if (ret) -+ return ret; -+ -+ ofs += n; -+ buf += n; -+ (*retlen) += n; -+ -+ if (ofs >> cfi->chipshift) { -+ chipnum ++; -+ ofs = 0; -+ if (chipnum == cfi->numchips) -+ return 0; -+ } -+ } -+ -+ /* We are now aligned, write as much as possible */ -+ while(len >= CFIDEV_BUSWIDTH) { -+ __u32 datum; -+ -+ if (cfi_buswidth_is_1()) { -+ datum = *(__u8*)buf; -+ } else if (cfi_buswidth_is_2()) { -+ datum = *(__u16*)buf; -+ } else if (cfi_buswidth_is_4()) { -+ datum = *(__u32*)buf; -+ } else { -+ return -EINVAL; -+ } -+ ret = do_write_oneword(map, &cfi->chips[chipnum], -+ ofs, datum, cfi->fast_prog); -+ if (ret) { -+ return ret; -+ } -+ -+ ofs += CFIDEV_BUSWIDTH; -+ buf += CFIDEV_BUSWIDTH; -+ (*retlen) += CFIDEV_BUSWIDTH; -+ len -= CFIDEV_BUSWIDTH; -+ -+ if (ofs >> cfi->chipshift) { -+ chipnum ++; -+ ofs = 0; -+ if (chipnum == cfi->numchips) -+ return 0; -+ chipstart = cfi->chips[chipnum].start; -+ } -+ } -+ -+ if (len & (CFIDEV_BUSWIDTH-1)) { -+ int i = 0, n = 0; -+ u_char tmp_buf[4]; -+ __u32 datum; -+ -+ map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); -+ while (len--) -+ tmp_buf[i++] = buf[n++]; -+ -+ if (cfi_buswidth_is_2()) { -+ datum = *(__u16*)tmp_buf; -+ } else if (cfi_buswidth_is_4()) { -+ datum = *(__u32*)tmp_buf; -+ } else { -+ return -EINVAL; /* should never happen, but be safe */ -+ } -+ -+ ret = do_write_oneword(map, &cfi->chips[chipnum], -+ ofs, datum, 0); -+ if (ret) -+ return ret; -+ -+ (*retlen) += n; -+ } -+ -+ return 0; -+} -+ -+static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) -+{ -+ unsigned int status; -+ unsigned long timeo = jiffies + HZ; -+ struct cfi_private *cfi = map->fldrv_priv; -+ unsigned int rdy_mask; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ retry: -+ cfi_spin_lock(chip->mutex); -+ -+ if (chip->state != FL_READY){ -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ -+ cfi_spin_unlock(chip->mutex); -+ -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ timeo = jiffies + HZ; -+ -+ goto retry; -+ } -+ -+ chip->state = FL_ERASING; -+ -+ adr += chip->start; -+ ENABLE_VPP(map); -+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); -+ cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); -+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); -+ cfi_write(map, CMD(0x30), adr); -+ -+ timeo = jiffies + (HZ*20); -+ -+ cfi_spin_unlock(chip->mutex); -+ schedule_timeout(HZ); -+ cfi_spin_lock(chip->mutex); -+ -+ rdy_mask = CMD(0x80); -+ -+ /* Once the state machine's known to be working I'll do that */ -+ -+ while ( ( (status = cfi_read(map,adr)) & rdy_mask ) != rdy_mask ) { -+ static int z=0; -+ -+ if (chip->state != FL_ERASING) { -+ /* Someone's suspended the erase. Sleep */ -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ -+ cfi_spin_unlock(chip->mutex); -+ printk("erase suspended. Sleeping\n"); -+ -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ timeo = jiffies + (HZ*2); -+ cfi_spin_lock(chip->mutex); -+ continue; -+ } -+ -+ /* OK Still waiting */ -+ if (time_after(jiffies, timeo)) { -+ chip->state = FL_READY; -+ cfi_spin_unlock(chip->mutex); -+ printk("waiting for erase to complete timed out."); -+ DISABLE_VPP(map); -+ return -EIO; -+ } -+ -+ /* Latency issues. Drop the lock, wait a while and retry */ -+ cfi_spin_unlock(chip->mutex); -+ -+ z++; -+ if ( 0 && !(z % 100 )) -+ printk("chip not ready yet after erase. looping\n"); -+ -+ cfi_udelay(1); -+ -+ cfi_spin_lock(chip->mutex); -+ continue; -+ } -+ -+ /* Done and happy. */ -+ DISABLE_VPP(map); -+ chip->state = FL_READY; -+ wake_up(&chip->wq); -+ cfi_spin_unlock(chip->mutex); -+ return 0; -+} -+ -+static int cfi_sststd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ unsigned long adr, len; -+ int chipnum, ret = 0; -+ int i, first; -+ struct mtd_erase_region_info *regions = mtd->eraseregions; -+ -+ if (instr->addr > mtd->size) -+ return -EINVAL; -+ -+ if ((instr->len + instr->addr) > mtd->size) -+ return -EINVAL; -+ -+ /* Check that both start and end of the requested erase are -+ * aligned with the erasesize at the appropriate addresses. -+ */ -+ -+ i = 0; -+ -+ /* Skip all erase regions which are ended before the start of -+ the requested erase. Actually, to save on the calculations, -+ we skip to the first erase region which starts after the -+ start of the requested erase, and then go back one. -+ */ -+ -+ while (i < mtd->numeraseregions && instr->addr >= regions[i].offset) -+ i++; -+ i--; -+ -+ /* OK, now i is pointing at the erase region in which this -+ erase request starts. Check the start of the requested -+ erase range is aligned with the erase size which is in -+ effect here. -+ */ -+ -+ if (instr->addr & (regions[i].erasesize-1)) -+ return -EINVAL; -+ -+ /* Remember the erase region we start on */ -+ first = i; -+ -+ /* Next, check that the end of the requested erase is aligned -+ * with the erase region at that address. -+ */ -+ -+ while (inumeraseregions && (instr->addr + instr->len) >= regions[i].offset) -+ i++; -+ -+ /* As before, drop back one to point at the region in which -+ the address actually falls -+ */ -+ i--; -+ -+ if ((instr->addr + instr->len) & (regions[i].erasesize-1)) -+ return -EINVAL; -+ -+ chipnum = instr->addr >> cfi->chipshift; -+ adr = instr->addr - (chipnum << cfi->chipshift); -+ len = instr->len; -+ -+ i=first; -+ -+ while(len) { -+ ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); -+ -+ if (ret) -+ return ret; -+ -+ adr += regions[i].erasesize; -+ len -= regions[i].erasesize; -+ -+ if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) -+ i++; -+ -+ if (adr >> cfi->chipshift) { -+ adr = 0; -+ chipnum++; -+ -+ if (chipnum >= cfi->numchips) -+ break; -+ } -+ } -+ -+ instr->state = MTD_ERASE_DONE; -+ if (instr->callback) -+ instr->callback(instr); -+ -+ return 0; -+} -+ -+static int cfi_sststd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = 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 >> cfi->chipshift; -+ adr = instr->addr - (chipnum << cfi->chipshift); -+ len = instr->len; -+ -+ while(len) { -+ ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); -+ -+ if (ret) -+ return ret; -+ -+ adr += mtd->erasesize; -+ len -= mtd->erasesize; -+ -+ if (adr >> cfi->chipshift) { -+ adr = 0; -+ chipnum++; -+ -+ if (chipnum >= cfi->numchips) -+ break; -+ } -+ } -+ -+ instr->state = MTD_ERASE_DONE; -+ if (instr->callback) -+ instr->callback(instr); -+ -+ return 0; -+} -+ -+static void cfi_sststd_sync (struct mtd_info *mtd) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int i; -+ struct flchip *chip; -+ int ret = 0; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ for (i=0; !ret && inumchips; i++) { -+ chip = &cfi->chips[i]; -+ -+ retry: -+ cfi_spin_lock(chip->mutex); -+ -+ switch(chip->state) { -+ case FL_READY: -+ case FL_STATUS: -+ case FL_CFI_QUERY: -+ case FL_JEDEC_QUERY: -+ chip->oldstate = chip->state; -+ chip->state = FL_SYNCING; -+ /* No need to wake_up() on this state change - -+ * as the whole point is that nobody can do anything -+ * with the chip now anyway. -+ */ -+ case FL_SYNCING: -+ cfi_spin_unlock(chip->mutex); -+ break; -+ -+ default: -+ /* Not an idle state */ -+ add_wait_queue(&chip->wq, &wait); -+ -+ cfi_spin_unlock(chip->mutex); -+ -+ schedule(); -+ -+ remove_wait_queue(&chip->wq, &wait); -+ -+ goto retry; -+ } -+ } -+ -+ /* Unlock the chips again */ -+ -+ for (i--; i >=0; i--) { -+ chip = &cfi->chips[i]; -+ -+ cfi_spin_lock(chip->mutex); -+ -+ if (chip->state == FL_SYNCING) { -+ chip->state = chip->oldstate; -+ wake_up(&chip->wq); -+ } -+ cfi_spin_unlock(chip->mutex); -+ } -+} -+ -+ -+static int cfi_sststd_suspend(struct mtd_info *mtd) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int i; -+ struct flchip *chip; -+ int ret = 0; -+//printk("suspend\n"); -+ -+ for (i=0; !ret && inumchips; i++) { -+ chip = &cfi->chips[i]; -+ -+ cfi_spin_lock(chip->mutex); -+ -+ switch(chip->state) { -+ case FL_READY: -+ case FL_STATUS: -+ case FL_CFI_QUERY: -+ case FL_JEDEC_QUERY: -+ chip->oldstate = chip->state; -+ chip->state = FL_PM_SUSPENDED; -+ /* No need to wake_up() on this state change - -+ * as the whole point is that nobody can do anything -+ * with the chip now anyway. -+ */ -+ case FL_PM_SUSPENDED: -+ break; -+ -+ default: -+ ret = -EAGAIN; -+ break; -+ } -+ cfi_spin_unlock(chip->mutex); -+ } -+ -+ /* Unlock the chips again */ -+ -+ if (ret) { -+ for (i--; i >=0; i--) { -+ chip = &cfi->chips[i]; -+ -+ cfi_spin_lock(chip->mutex); -+ -+ if (chip->state == FL_PM_SUSPENDED) { -+ chip->state = chip->oldstate; -+ wake_up(&chip->wq); -+ } -+ cfi_spin_unlock(chip->mutex); -+ } -+ } -+ -+ return ret; -+} -+ -+static void cfi_sststd_resume(struct mtd_info *mtd) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int i; -+ struct flchip *chip; -+//printk("resume\n"); -+ -+ for (i=0; inumchips; i++) { -+ -+ chip = &cfi->chips[i]; -+ -+ cfi_spin_lock(chip->mutex); -+ -+ if (chip->state == FL_PM_SUSPENDED) { -+ chip->state = FL_READY; -+ cfi_write(map, CMD(0xF0), chip->start); -+ wake_up(&chip->wq); -+ } -+ else -+ printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n"); -+ -+ cfi_spin_unlock(chip->mutex); -+ } -+} -+ -+static void cfi_sststd_destroy(struct mtd_info *mtd) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ kfree(cfi->cmdset_priv); -+ kfree(cfi); -+} -+ -+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -+#define cfi_sststd_init init_module -+#define cfi_sststd_exit cleanup_module -+#endif -+ -+static char im_name[]="cfi_cmdset_0701"; -+ -+mod_init_t cfi_sststd_init(void) -+{ -+ inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0701); -+ return 0; -+} -+ -+mod_exit_t cfi_sststd_exit(void) -+{ -+ inter_module_unregister(im_name); -+} -+ -+module_init(cfi_sststd_init); -+module_exit(cfi_sststd_exit); -+ -diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_probe.c linux-2.4.30-brcm/drivers/mtd/chips/cfi_probe.c ---- linux-2.4.30/drivers/mtd/chips/cfi_probe.c 2003-06-13 16:51:34.000000000 +0200 -+++ linux-2.4.30-brcm/drivers/mtd/chips/cfi_probe.c 2005-05-22 22:55:52.000000000 +0200 -@@ -67,8 +67,15 @@ - cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); - -- if (!qry_present(map,base,cfi)) -- return 0; -+ if (!qry_present(map,base,cfi)) { -+ /* rather broken SST cfi probe (requires SST unlock) */ -+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); -+ if (!qry_present(map,base,cfi)) -+ return 0; -+ } - - if (!cfi->numchips) { - /* This is the first time we're called. Set up the CFI -diff -Nur linux-2.4.30/drivers/mtd/chips/Config.in linux-2.4.30-brcm/drivers/mtd/chips/Config.in ---- linux-2.4.30/drivers/mtd/chips/Config.in 2003-06-13 16:51:34.000000000 +0200 -+++ linux-2.4.30-brcm/drivers/mtd/chips/Config.in 2005-05-22 22:55:52.000000000 +0200 -@@ -45,6 +45,7 @@ - dep_tristate ' Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE - dep_tristate ' Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE - dep_tristate ' Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE -+dep_tristate ' Support for SST flash chips' CONFIG_MTD_CFI_SSTSTD $CONFIG_MTD_GEN_PROBE - - dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD - dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD -diff -Nur linux-2.4.30/drivers/mtd/chips/gen_probe.c linux-2.4.30-brcm/drivers/mtd/chips/gen_probe.c ---- linux-2.4.30/drivers/mtd/chips/gen_probe.c 2003-08-25 13:44:42.000000000 +0200 -+++ linux-2.4.30-brcm/drivers/mtd/chips/gen_probe.c 2005-05-22 22:55:52.000000000 +0200 -@@ -332,9 +332,13 @@ - return cfi_cmdset_0002(map, primary); - #endif - #ifdef CONFIG_MTD_CFI_STAA -- case 0x0020: -+ case 0x0020: - return cfi_cmdset_0020(map, primary); - #endif -+#ifdef CONFIG_MTD_CFI_SSTSTD -+ case 0x0701: -+ return cfi_cmdset_0701(map, primary); -+#endif - } - - return cfi_cmdset_unknown(map, primary); -diff -Nur linux-2.4.30/drivers/mtd/chips/Makefile linux-2.4.30-brcm/drivers/mtd/chips/Makefile ---- linux-2.4.30/drivers/mtd/chips/Makefile 2003-06-13 16:51:34.000000000 +0200 -+++ linux-2.4.30-brcm/drivers/mtd/chips/Makefile 2005-05-22 22:55:52.000000000 +0200 -@@ -18,6 +18,7 @@ - obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o - obj-$(CONFIG_MTD_CFI) += cfi_probe.o - obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o -+obj-$(CONFIG_MTD_CFI_SSTSTD) += cfi_cmdset_0701.o - obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o - obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o - obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o diff -Nur linux-2.4.30/drivers/mtd/maps/bcm947xx-flash.c linux-2.4.30-brcm/drivers/mtd/maps/bcm947xx-flash.c --- linux-2.4.30/drivers/mtd/maps/bcm947xx-flash.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.30-brcm/drivers/mtd/maps/bcm947xx-flash.c 2005-05-22 22:55:52.000000000 +0200 @@ -14042,271 +13122,6 @@ diff -Nur linux-2.4.30/drivers/net/Config.in linux-2.4.30-brcm/drivers/net/Confi dep_tristate ' CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA dep_tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then -diff -Nur linux-2.4.30/drivers/net/diag/diag_led.c linux-2.4.30-brcm/drivers/net/diag/diag_led.c ---- linux-2.4.30/drivers/net/diag/diag_led.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.30-brcm/drivers/net/diag/diag_led.c 2005-05-25 20:41:19.000000000 +0200 -@@ -0,0 +1,244 @@ -+/* -+ * diag_led.c - replacement diag module -+ * -+ * Copyright (C) 2004 Mike Baker, -+ * Imre Kaloz -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * $Id: diag_led.c,v 1.5 2005/04/18 09:05:24 mbm Exp $ -+ */ -+ -+/* -+ * ChangeLog: -+ * 2004/03/28 initial release -+ * 2004/08/26 asus & buffalo support added -+ * 2005/03/14 asus wl-500g deluxe and buffalo v2 support added -+ * 2005/04/13 added licensing informations -+ * 2005/04/18 base reset polarity off initial readings -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern char * nvram_get(const char *name); -+static void *sbh; -+ -+// v2.x - - - - - -+#define DIAG_GPIO (1<<1) -+#define DMZ_GPIO (1<<7) -+ -+static void set_gpio(uint32 mask, uint32 value) { -+ sb_gpiocontrol(sbh,mask,0); -+ sb_gpioouten(sbh,mask,mask); -+ sb_gpioout(sbh,mask,value); -+} -+ -+static void v2_set_diag(u8 state) { -+ set_gpio(DIAG_GPIO,state); -+} -+static void v2_set_dmz(u8 state) { -+ set_gpio(DMZ_GPIO,state); -+} -+ -+// v1.x - - - - - -+#define LED_DIAG 0x13 -+#define LED_DMZ 0x12 -+ -+static void v1_set_diag(u8 state) { -+ if (!state) { -+ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF; -+ } else { -+ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG); -+ } -+} -+static void v1_set_dmz(u8 state) { -+ if (!state) { -+ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF; -+ } else { -+ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ); -+ } -+} -+ -+// - - - - - -+static void ignore(u8 ignored) {}; -+ -+// - - - - - -+#define BIT_DMZ 0x01 -+#define BIT_DIAG 0x04 -+ -+void (*set_diag)(u8 state); -+void (*set_dmz)(u8 state); -+ -+static unsigned int diag = 0; -+ -+static void diag_change() -+{ -+ set_diag(0xFF); // off -+ set_dmz(0xFF); // off -+ -+ if(diag & BIT_DIAG) -+ set_diag(0x00); // on -+ if(diag & BIT_DMZ) -+ set_dmz(0x00); // on -+} -+ -+static int proc_diag(ctl_table *table, int write, struct file *filp, -+ void *buffer, size_t *lenp) -+{ -+ int r; -+ r = proc_dointvec(table, write, filp, buffer, lenp); -+ if (write && !r) { -+ diag_change(); -+ } -+ return r; -+} -+ -+// - - - - - -+static unsigned char reset_gpio = 0; -+static unsigned char reset_polarity = 0; -+static unsigned int reset = 0; -+ -+static int proc_reset(ctl_table *table, int write, struct file *filp, -+ void *buffer, size_t *lenp) -+{ -+ -+ if (reset_gpio) { -+ sb_gpiocontrol(sbh,reset_gpio,reset_gpio); -+ sb_gpioouten(sbh,reset_gpio,0); -+ reset=!(sb_gpioin(sbh)&reset_gpio); -+ -+ if (reset_polarity) reset=!reset; -+ } else { -+ reset=0; -+ } -+ -+ return proc_dointvec(table, write, filp, buffer, lenp); -+} -+ -+// - - - - - -+static struct ctl_table_header *diag_sysctl_header; -+ -+static ctl_table sys_diag[] = { -+ { -+ ctl_name: 2000, -+ procname: "diag", -+ data: &diag, -+ maxlen: sizeof(diag), -+ mode: 0644, -+ proc_handler: proc_diag -+ }, -+ { -+ ctl_name: 2001, -+ procname: "reset", -+ data: &reset, -+ maxlen: sizeof(reset), -+ mode: 0444, -+ proc_handler: proc_reset -+ }, -+ { 0 } -+}; -+ -+static int __init diag_init() -+{ -+ char *buf; -+ u32 board_type; -+ sbh = sb_kattach(); -+ sb_gpiosetcore(sbh); -+ -+ board_type = sb_boardtype(sbh); -+ printk(KERN_INFO "diag boardtype: %08x\n",board_type); -+ -+ set_diag=ignore; -+ set_dmz=ignore; -+ -+ if ((board_type & 0xf00) == 0x400) { -+ buf=nvram_get("boardtype")?:""; -+ if (!strcmp(buf,"bcm94710dev")) { -+ buf=nvram_get("boardnum")?:""; -+ if (!strcmp(buf,"42")) { -+ // wrt54g v1.x -+ set_diag=v1_set_diag; -+ set_dmz=v1_set_dmz; -+ reset_gpio=(1<<6); -+ } -+ if (!strcmp(buf,"asusX")) { -+ //asus wl-500g -+ reset_gpio=(1<<6); -+ } -+ } -+ if (!strcmp(buf,"bcm94710ap")) { -+ buf=nvram_get("boardnum")?:""; -+ if (!strcmp(buf,"42")) { -+ // buffalo -+ set_dmz=v2_set_dmz; -+ reset_gpio=(1<<4); -+ } -+ if (!strcmp(buf,"44")) { -+ //dell truemobile -+ set_dmz=v2_set_dmz; -+ reset_gpio=(1<<0); -+ } -+ } -+ } else { -+ buf=nvram_get("boardnum")?:""; -+ if (!strcmp(buf,"42")) { -+ //linksys -+ set_diag=v2_set_diag; -+ set_dmz=v2_set_dmz; -+ reset_gpio=(1<<6); -+ } -+ if (!strcmp(buf,"44")) { -+ //motorola -+ reset_gpio=(1<<5); -+ } -+ if (!strcmp(buf,"00")) { -+ //buffalo -+ reset_gpio=(1<<7); -+ } -+ if (!strcmp(buf,"45")) { -+ //wl-500g deluxe -+ reset_gpio=(1<<6); -+ } -+ } -+ -+ -+ sb_gpiocontrol(sbh,reset_gpio,reset_gpio); -+ sb_gpioouten(sbh,reset_gpio,0); -+ reset_polarity=!(sb_gpioin(sbh)&reset_gpio); -+ -+ diag_sysctl_header = register_sysctl_table(sys_diag, 0); -+ diag_change(); -+ -+ return 0; -+} -+ -+static void __exit diag_exit() -+{ -+ unregister_sysctl_table(diag_sysctl_header); -+} -+ -+EXPORT_NO_SYMBOLS; -+MODULE_AUTHOR("openwrt.org"); -+MODULE_LICENSE("GPL"); -+ -+module_init(diag_init); -+module_exit(diag_exit); -diff -Nur linux-2.4.30/drivers/net/diag/Makefile linux-2.4.30-brcm/drivers/net/diag/Makefile ---- linux-2.4.30/drivers/net/diag/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.30-brcm/drivers/net/diag/Makefile 2005-05-26 17:13:16.000000000 +0200 -@@ -0,0 +1,13 @@ -+#$Id$ -+ -+EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER -+ -+O_TARGET := diag.o -+ -+MAC_OBJS := diag_led.o -+ -+export-objs := -+obj-y := $(MAC_OBJS) -+obj-m := $(O_TARGET) -+ -+include $(TOPDIR)/Rules.make diff -Nur linux-2.4.30/drivers/net/et/Makefile linux-2.4.30-brcm/drivers/net/et/Makefile --- linux-2.4.30/drivers/net/et/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.30-brcm/drivers/net/et/Makefile 2005-05-26 02:37:05.000000000 +0200 diff --git a/openwrt/target/linux/linux-2.4/patches/brcm/004-diag_led.patch b/openwrt/target/linux/linux-2.4/patches/brcm/004-diag_led.patch new file mode 100644 index 0000000000..77fb289797 --- /dev/null +++ b/openwrt/target/linux/linux-2.4/patches/brcm/004-diag_led.patch @@ -0,0 +1,265 @@ +diff -Nur linux-2.4.30/drivers/net/diag/Makefile linux-2.4.30.openwrt/drivers/net/diag/Makefile +--- linux-2.4.30/drivers/net/diag/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.4.30.openwrt/drivers/net/diag/Makefile 2005-06-28 11:35:26.000000000 +0200 +@@ -0,0 +1,13 @@ ++#$Id$ ++ ++EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER ++ ++O_TARGET := diag.o ++ ++MAC_OBJS := diag_led.o ++ ++export-objs := ++obj-y := $(MAC_OBJS) ++obj-m := $(O_TARGET) ++ ++include $(TOPDIR)/Rules.make +diff -Nur linux-2.4.30/drivers/net/diag/diag_led.c linux-2.4.30.openwrt/drivers/net/diag/diag_led.c +--- linux-2.4.30/drivers/net/diag/diag_led.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.4.30.openwrt/drivers/net/diag/diag_led.c 2005-06-28 11:35:26.000000000 +0200 +@@ -0,0 +1,244 @@ ++/* ++ * diag_led.c - replacement diag module ++ * ++ * Copyright (C) 2004 Mike Baker, ++ * Imre Kaloz ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * $Id: diag_led.c,v 1.5 2005/04/18 09:05:24 mbm Exp $ ++ */ ++ ++/* ++ * ChangeLog: ++ * 2004/03/28 initial release ++ * 2004/08/26 asus & buffalo support added ++ * 2005/03/14 asus wl-500g deluxe and buffalo v2 support added ++ * 2005/04/13 added licensing informations ++ * 2005/04/18 base reset polarity off initial readings ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern char * nvram_get(const char *name); ++static void *sbh; ++ ++// v2.x - - - - - ++#define DIAG_GPIO (1<<1) ++#define DMZ_GPIO (1<<7) ++ ++static void set_gpio(uint32 mask, uint32 value) { ++ sb_gpiocontrol(sbh,mask,0); ++ sb_gpioouten(sbh,mask,mask); ++ sb_gpioout(sbh,mask,value); ++} ++ ++static void v2_set_diag(u8 state) { ++ set_gpio(DIAG_GPIO,state); ++} ++static void v2_set_dmz(u8 state) { ++ set_gpio(DMZ_GPIO,state); ++} ++ ++// v1.x - - - - - ++#define LED_DIAG 0x13 ++#define LED_DMZ 0x12 ++ ++static void v1_set_diag(u8 state) { ++ if (!state) { ++ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF; ++ } else { ++ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG); ++ } ++} ++static void v1_set_dmz(u8 state) { ++ if (!state) { ++ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF; ++ } else { ++ *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ); ++ } ++} ++ ++// - - - - - ++static void ignore(u8 ignored) {}; ++ ++// - - - - - ++#define BIT_DMZ 0x01 ++#define BIT_DIAG 0x04 ++ ++void (*set_diag)(u8 state); ++void (*set_dmz)(u8 state); ++ ++static unsigned int diag = 0; ++ ++static void diag_change() ++{ ++ set_diag(0xFF); // off ++ set_dmz(0xFF); // off ++ ++ if(diag & BIT_DIAG) ++ set_diag(0x00); // on ++ if(diag & BIT_DMZ) ++ set_dmz(0x00); // on ++} ++ ++static int proc_diag(ctl_table *table, int write, struct file *filp, ++ void *buffer, size_t *lenp) ++{ ++ int r; ++ r = proc_dointvec(table, write, filp, buffer, lenp); ++ if (write && !r) { ++ diag_change(); ++ } ++ return r; ++} ++ ++// - - - - - ++static unsigned char reset_gpio = 0; ++static unsigned char reset_polarity = 0; ++static unsigned int reset = 0; ++ ++static int proc_reset(ctl_table *table, int write, struct file *filp, ++ void *buffer, size_t *lenp) ++{ ++ ++ if (reset_gpio) { ++ sb_gpiocontrol(sbh,reset_gpio,reset_gpio); ++ sb_gpioouten(sbh,reset_gpio,0); ++ reset=!(sb_gpioin(sbh)&reset_gpio); ++ ++ if (reset_polarity) reset=!reset; ++ } else { ++ reset=0; ++ } ++ ++ return proc_dointvec(table, write, filp, buffer, lenp); ++} ++ ++// - - - - - ++static struct ctl_table_header *diag_sysctl_header; ++ ++static ctl_table sys_diag[] = { ++ { ++ ctl_name: 2000, ++ procname: "diag", ++ data: &diag, ++ maxlen: sizeof(diag), ++ mode: 0644, ++ proc_handler: proc_diag ++ }, ++ { ++ ctl_name: 2001, ++ procname: "reset", ++ data: &reset, ++ maxlen: sizeof(reset), ++ mode: 0444, ++ proc_handler: proc_reset ++ }, ++ { 0 } ++}; ++ ++static int __init diag_init() ++{ ++ char *buf; ++ u32 board_type; ++ sbh = sb_kattach(); ++ sb_gpiosetcore(sbh); ++ ++ board_type = sb_boardtype(sbh); ++ printk(KERN_INFO "diag boardtype: %08x\n",board_type); ++ ++ set_diag=ignore; ++ set_dmz=ignore; ++ ++ if ((board_type & 0xf00) == 0x400) { ++ buf=nvram_get("boardtype")?:""; ++ if (!strcmp(buf,"bcm94710dev")) { ++ buf=nvram_get("boardnum")?:""; ++ if (!strcmp(buf,"42")) { ++ // wrt54g v1.x ++ set_diag=v1_set_diag; ++ set_dmz=v1_set_dmz; ++ reset_gpio=(1<<6); ++ } ++ if (!strcmp(buf,"asusX")) { ++ //asus wl-500g ++ reset_gpio=(1<<6); ++ } ++ } ++ if (!strcmp(buf,"bcm94710ap")) { ++ buf=nvram_get("boardnum")?:""; ++ if (!strcmp(buf,"42")) { ++ // buffalo ++ set_dmz=v2_set_dmz; ++ reset_gpio=(1<<4); ++ } ++ if (!strcmp(buf,"44")) { ++ //dell truemobile ++ set_dmz=v2_set_dmz; ++ reset_gpio=(1<<0); ++ } ++ } ++ } else { ++ buf=nvram_get("boardnum")?:""; ++ if (!strcmp(buf,"42")) { ++ //linksys ++ set_diag=v2_set_diag; ++ set_dmz=v2_set_dmz; ++ reset_gpio=(1<<6); ++ } ++ if (!strcmp(buf,"44")) { ++ //motorola ++ reset_gpio=(1<<5); ++ } ++ if (!strcmp(buf,"00")) { ++ //buffalo ++ reset_gpio=(1<<7); ++ } ++ if (!strcmp(buf,"45")) { ++ //wl-500g deluxe ++ reset_gpio=(1<<6); ++ } ++ } ++ ++ ++ sb_gpiocontrol(sbh,reset_gpio,reset_gpio); ++ sb_gpioouten(sbh,reset_gpio,0); ++ reset_polarity=!(sb_gpioin(sbh)&reset_gpio); ++ ++ diag_sysctl_header = register_sysctl_table(sys_diag, 0); ++ diag_change(); ++ ++ return 0; ++} ++ ++static void __exit diag_exit() ++{ ++ unregister_sysctl_table(diag_sysctl_header); ++} ++ ++EXPORT_NO_SYMBOLS; ++MODULE_AUTHOR("openwrt.org"); ++MODULE_LICENSE("GPL"); ++ ++module_init(diag_init); ++module_exit(diag_exit); diff --git a/openwrt/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch b/openwrt/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch new file mode 100644 index 0000000000..9115b9f611 --- /dev/null +++ b/openwrt/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch @@ -0,0 +1,925 @@ +diff -Nur linux-2.4.30/drivers/mtd/chips/Config.in linux-2.4.30.openwrt/drivers/mtd/chips/Config.in +--- linux-2.4.30/drivers/mtd/chips/Config.in 2003-06-13 16:51:34.000000000 +0200 ++++ linux-2.4.30.openwrt/drivers/mtd/chips/Config.in 2005-06-28 11:26:26.000000000 +0200 +@@ -45,6 +45,7 @@ + dep_tristate ' Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE + dep_tristate ' Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE + dep_tristate ' Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE ++dep_tristate ' Support for SST flash chips' CONFIG_MTD_CFI_SSTSTD $CONFIG_MTD_GEN_PROBE + + dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD + dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD +diff -Nur linux-2.4.30/drivers/mtd/chips/Makefile linux-2.4.30.openwrt/drivers/mtd/chips/Makefile +--- linux-2.4.30/drivers/mtd/chips/Makefile 2003-06-13 16:51:34.000000000 +0200 ++++ linux-2.4.30.openwrt/drivers/mtd/chips/Makefile 2005-06-28 11:26:26.000000000 +0200 +@@ -18,6 +18,7 @@ + obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o + obj-$(CONFIG_MTD_CFI) += cfi_probe.o + obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o ++obj-$(CONFIG_MTD_CFI_SSTSTD) += cfi_cmdset_0701.o + obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o + obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o + obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o +diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c linux-2.4.30.openwrt/drivers/mtd/chips/cfi_cmdset_0701.c +--- linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.4.30.openwrt/drivers/mtd/chips/cfi_cmdset_0701.c 2005-06-28 11:26:26.000000000 +0200 +@@ -0,0 +1,855 @@ ++/* ++ * Common Flash Interface support: ++ * SST Standard Vendor Command Set (ID 0x0701) ++ * ++ * Copyright (C) 2000 Crossnet Co. ++ * ++ * 2_by_8 routines added by Simon Munton ++ * ++ * This code is GPL ++ * ++ * $Id: cfi_cmdset_0701.c,v 1.1 2005/03/16 13:50:00 wbx Exp $ ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int cfi_sststd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); ++static int cfi_sststd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); ++static int cfi_sststd_erase_onesize(struct mtd_info *, struct erase_info *); ++static int cfi_sststd_erase_varsize(struct mtd_info *, struct erase_info *); ++static void cfi_sststd_sync (struct mtd_info *); ++static int cfi_sststd_suspend (struct mtd_info *); ++static void cfi_sststd_resume (struct mtd_info *); ++ ++static void cfi_sststd_destroy(struct mtd_info *); ++ ++struct mtd_info *cfi_cmdset_0701(struct map_info *, int); ++static struct mtd_info *cfi_sststd_setup (struct map_info *); ++ ++ ++static struct mtd_chip_driver cfi_sststd_chipdrv = { ++ probe: NULL, /* Not usable directly */ ++ destroy: cfi_sststd_destroy, ++ name: "cfi_cmdset_0701", ++ module: THIS_MODULE ++}; ++ ++struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary) ++{ ++ struct cfi_private *cfi = map->fldrv_priv; ++ int ofs_factor = cfi->interleave * cfi->device_type; ++ int i; ++ __u8 major, minor; ++ __u32 base = cfi->chips[0].start; ++ ++ if (cfi->cfi_mode==1){ ++ __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; ++ ++ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ ++ major = cfi_read_query(map, base + (adr+3)*ofs_factor); ++ minor = cfi_read_query(map, base + (adr+4)*ofs_factor); ++ ++ printk(" SST Query Table v%c.%c at 0x%4.4X\n", ++ major, minor, adr); ++ cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ ++ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ cfi->mfr = cfi_read_query(map, base); ++ cfi->id = cfi_read_query(map, base + ofs_factor); ++ ++ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ ++ switch (cfi->device_type) { ++ case CFI_DEVICETYPE_X16: ++ cfi->addr_unlock1 = 0x5555; ++ cfi->addr_unlock2 = 0x2AAA; ++ break; ++ default: ++ printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0701 device type %d\n", cfi->device_type); ++ return NULL; ++ } ++ } /* CFI mode */ ++ ++ for (i=0; i< cfi->numchips; i++) { ++ cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; ++ cfi->chips[i].buffer_write_time = 1<cfiq->BufWriteTimeoutTyp; ++ cfi->chips[i].erase_time = 1<cfiq->BlockEraseTimeoutTyp; ++ } ++ ++ map->fldrv = &cfi_sststd_chipdrv; ++ MOD_INC_USE_COUNT; ++ ++ cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ return cfi_sststd_setup(map); ++} ++ ++static struct mtd_info *cfi_sststd_setup(struct map_info *map) ++{ ++ struct cfi_private *cfi = map->fldrv_priv; ++ struct mtd_info *mtd; ++ unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; ++ ++ mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); ++ printk("number of %s chips: %d\n", (cfi->cfi_mode)?"JEDEC":"CFI",cfi->numchips); ++ ++ if (!mtd) { ++ printk("Failed to allocate memory for MTD device\n"); ++ kfree(cfi->cmdset_priv); ++ return NULL; ++ } ++ ++ memset(mtd, 0, sizeof(*mtd)); ++ mtd->priv = map; ++ mtd->type = MTD_NORFLASH; ++ /* Also select the correct geometry setup too */ ++ mtd->size = devsize * cfi->numchips; ++ ++ if (cfi->cfiq->NumEraseRegions == 1) { ++ /* No need to muck about with multiple erase sizes */ ++ mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave; ++ } else { ++ unsigned long offset = 0; ++ int i,j; ++ ++ mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; ++ mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); ++ if (!mtd->eraseregions) { ++ printk("Failed to allocate memory for MTD erase region info\n"); ++ kfree(cfi->cmdset_priv); ++ return NULL; ++ } ++ ++ for (i=0; icfiq->NumEraseRegions; i++) { ++ unsigned long ernum, ersize; ++ ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave; ++ ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1; ++ ++ if (mtd->erasesize < ersize) { ++ mtd->erasesize = ersize; ++ } ++ for (j=0; jnumchips; j++) { ++ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset; ++ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize; ++ mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum; ++ } ++ offset += (ersize * ernum); ++ } ++ ++ // debug ++ for (i=0; inumeraseregions;i++){ ++ printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", ++ i,mtd->eraseregions[i].offset, ++ mtd->eraseregions[i].erasesize, ++ mtd->eraseregions[i].numblocks); ++ } ++ } ++ ++ switch (CFIDEV_BUSWIDTH) ++ { ++ case 1: ++ case 2: ++ case 4: ++ if (mtd->numeraseregions > 1) ++ mtd->erase = cfi_sststd_erase_varsize; ++ else ++ mtd->erase = cfi_sststd_erase_onesize; ++ mtd->read = cfi_sststd_read; ++ mtd->write = cfi_sststd_write; ++ break; ++ ++ default: ++ printk("Unsupported buswidth\n"); ++ kfree(mtd); ++ kfree(cfi->cmdset_priv); ++ return NULL; ++ break; ++ } ++ mtd->sync = cfi_sststd_sync; ++ mtd->suspend = cfi_sststd_suspend; ++ mtd->resume = cfi_sststd_resume; ++ mtd->flags = MTD_CAP_NORFLASH; ++ map->fldrv = &cfi_sststd_chipdrv; ++ mtd->name = map->name; ++ MOD_INC_USE_COUNT; ++ return mtd; ++} ++ ++static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) ++{ ++ DECLARE_WAITQUEUE(wait, current); ++ unsigned long timeo = jiffies + HZ; ++ ++ retry: ++ cfi_spin_lock(chip->mutex); ++ ++ if (chip->state != FL_READY){ ++ printk("Waiting for chip to read, status = %d\n", chip->state); ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ add_wait_queue(&chip->wq, &wait); ++ ++ cfi_spin_unlock(chip->mutex); ++ ++ schedule(); ++ remove_wait_queue(&chip->wq, &wait); ++ timeo = jiffies + HZ; ++ ++ goto retry; ++ } ++ ++ adr += chip->start; ++ ++ chip->state = FL_READY; ++ ++ map->copy_from(map, buf, adr, len); ++ ++ wake_up(&chip->wq); ++ cfi_spin_unlock(chip->mutex); ++ ++ return 0; ++} ++ ++static int cfi_sststd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = map->fldrv_priv; ++ unsigned long ofs; ++ int chipnum; ++ int ret = 0; ++ ++ /* ofs: offset within the first chip that the first read should start */ ++ ++ chipnum = (from >> cfi->chipshift); ++ ofs = from - (chipnum << cfi->chipshift); ++ ++ ++ *retlen = 0; ++ ++ while (len) { ++ unsigned long thislen; ++ ++ if (chipnum >= cfi->numchips) ++ break; ++ ++ if ((len + ofs -1) >> cfi->chipshift) ++ thislen = (1<chipshift) - ofs; ++ else ++ thislen = len; ++ ++ ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); ++ if (ret) ++ break; ++ ++ *retlen += thislen; ++ len -= thislen; ++ buf += thislen; ++ ++ ofs = 0; ++ chipnum++; ++ } ++ return ret; ++} ++ ++static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast) ++{ ++ unsigned long timeo = jiffies + HZ; ++ unsigned int Last[4]; ++ unsigned long Count = 0; ++ struct cfi_private *cfi = map->fldrv_priv; ++ DECLARE_WAITQUEUE(wait, current); ++ int ret = 0; ++ ++ retry: ++ cfi_spin_lock(chip->mutex); ++ ++ if (chip->state != FL_READY){ ++ printk("Waiting for chip to write, status = %d\n", chip->state); ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ add_wait_queue(&chip->wq, &wait); ++ ++ cfi_spin_unlock(chip->mutex); ++ ++ schedule(); ++ remove_wait_queue(&chip->wq, &wait); ++ printk("Wake up to write:\n"); ++ timeo = jiffies + HZ; ++ ++ goto retry; ++ } ++ ++ chip->state = FL_WRITING; ++ ++ adr += chip->start; ++ ENABLE_VPP(map); ++ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); ++ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); ++ cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); ++ ++ cfi_write(map, datum, adr); ++ ++ cfi_spin_unlock(chip->mutex); ++ cfi_udelay(chip->word_write_time); ++ cfi_spin_lock(chip->mutex); ++ ++ Last[0] = cfi_read(map, adr); ++ // printk("Last[0] is %x\n", Last[0]); ++ Last[1] = cfi_read(map, adr); ++ // printk("Last[1] is %x\n", Last[1]); ++ Last[2] = cfi_read(map, adr); ++ // printk("Last[2] is %x\n", Last[2]); ++ ++ for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){ ++ cfi_spin_unlock(chip->mutex); ++ cfi_udelay(10); ++ cfi_spin_lock(chip->mutex); ++ ++ Last[Count % 4] = cfi_read(map, adr); ++ // printk("Last[%d%%4] is %x\n", Count, Last[Count%4]); ++ } ++ ++ if (Last[(Count - 1) % 4] != datum){ ++ printk("Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum); ++ cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL); ++ DISABLE_VPP(map); ++ ret = -EIO; ++ } ++ DISABLE_VPP(map); ++ chip->state = FL_READY; ++ wake_up(&chip->wq); ++ cfi_spin_unlock(chip->mutex); ++ ++ return ret; ++} ++ ++static int cfi_sststd_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 cfi_private *cfi = map->fldrv_priv; ++ int ret = 0; ++ int chipnum; ++ unsigned long ofs, chipstart; ++ ++ *retlen = 0; ++ if (!len) ++ return 0; ++ ++ chipnum = to >> cfi->chipshift; ++ ofs = to - (chipnum << cfi->chipshift); ++ chipstart = cfi->chips[chipnum].start; ++ ++ /* If it's not bus-aligned, do the first byte write */ ++ if (ofs & (CFIDEV_BUSWIDTH-1)) { ++ unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1); ++ int i = ofs - bus_ofs; ++ int n = 0; ++ u_char tmp_buf[4]; ++ __u32 datum; ++ ++ map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); ++ while (len && i < CFIDEV_BUSWIDTH) ++ tmp_buf[i++] = buf[n++], len--; ++ ++ if (cfi_buswidth_is_2()) { ++ datum = *(__u16*)tmp_buf; ++ } else if (cfi_buswidth_is_4()) { ++ datum = *(__u32*)tmp_buf; ++ } else { ++ return -EINVAL; /* should never happen, but be safe */ ++ } ++ ++ ret = do_write_oneword(map, &cfi->chips[chipnum], ++ bus_ofs, datum, 0); ++ if (ret) ++ return ret; ++ ++ ofs += n; ++ buf += n; ++ (*retlen) += n; ++ ++ if (ofs >> cfi->chipshift) { ++ chipnum ++; ++ ofs = 0; ++ if (chipnum == cfi->numchips) ++ return 0; ++ } ++ } ++ ++ /* We are now aligned, write as much as possible */ ++ while(len >= CFIDEV_BUSWIDTH) { ++ __u32 datum; ++ ++ if (cfi_buswidth_is_1()) { ++ datum = *(__u8*)buf; ++ } else if (cfi_buswidth_is_2()) { ++ datum = *(__u16*)buf; ++ } else if (cfi_buswidth_is_4()) { ++ datum = *(__u32*)buf; ++ } else { ++ return -EINVAL; ++ } ++ ret = do_write_oneword(map, &cfi->chips[chipnum], ++ ofs, datum, cfi->fast_prog); ++ if (ret) { ++ return ret; ++ } ++ ++ ofs += CFIDEV_BUSWIDTH; ++ buf += CFIDEV_BUSWIDTH; ++ (*retlen) += CFIDEV_BUSWIDTH; ++ len -= CFIDEV_BUSWIDTH; ++ ++ if (ofs >> cfi->chipshift) { ++ chipnum ++; ++ ofs = 0; ++ if (chipnum == cfi->numchips) ++ return 0; ++ chipstart = cfi->chips[chipnum].start; ++ } ++ } ++ ++ if (len & (CFIDEV_BUSWIDTH-1)) { ++ int i = 0, n = 0; ++ u_char tmp_buf[4]; ++ __u32 datum; ++ ++ map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); ++ while (len--) ++ tmp_buf[i++] = buf[n++]; ++ ++ if (cfi_buswidth_is_2()) { ++ datum = *(__u16*)tmp_buf; ++ } else if (cfi_buswidth_is_4()) { ++ datum = *(__u32*)tmp_buf; ++ } else { ++ return -EINVAL; /* should never happen, but be safe */ ++ } ++ ++ ret = do_write_oneword(map, &cfi->chips[chipnum], ++ ofs, datum, 0); ++ if (ret) ++ return ret; ++ ++ (*retlen) += n; ++ } ++ ++ return 0; ++} ++ ++static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) ++{ ++ unsigned int status; ++ unsigned long timeo = jiffies + HZ; ++ struct cfi_private *cfi = map->fldrv_priv; ++ unsigned int rdy_mask; ++ DECLARE_WAITQUEUE(wait, current); ++ ++ retry: ++ cfi_spin_lock(chip->mutex); ++ ++ if (chip->state != FL_READY){ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ add_wait_queue(&chip->wq, &wait); ++ ++ cfi_spin_unlock(chip->mutex); ++ ++ schedule(); ++ remove_wait_queue(&chip->wq, &wait); ++ timeo = jiffies + HZ; ++ ++ goto retry; ++ } ++ ++ chip->state = FL_ERASING; ++ ++ adr += chip->start; ++ ENABLE_VPP(map); ++ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); ++ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); ++ cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); ++ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); ++ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); ++ cfi_write(map, CMD(0x30), adr); ++ ++ timeo = jiffies + (HZ*20); ++ ++ cfi_spin_unlock(chip->mutex); ++ schedule_timeout(HZ); ++ cfi_spin_lock(chip->mutex); ++ ++ rdy_mask = CMD(0x80); ++ ++ /* Once the state machine's known to be working I'll do that */ ++ ++ while ( ( (status = cfi_read(map,adr)) & rdy_mask ) != rdy_mask ) { ++ static int z=0; ++ ++ if (chip->state != FL_ERASING) { ++ /* Someone's suspended the erase. Sleep */ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ add_wait_queue(&chip->wq, &wait); ++ ++ cfi_spin_unlock(chip->mutex); ++ printk("erase suspended. Sleeping\n"); ++ ++ schedule(); ++ remove_wait_queue(&chip->wq, &wait); ++ timeo = jiffies + (HZ*2); ++ cfi_spin_lock(chip->mutex); ++ continue; ++ } ++ ++ /* OK Still waiting */ ++ if (time_after(jiffies, timeo)) { ++ chip->state = FL_READY; ++ cfi_spin_unlock(chip->mutex); ++ printk("waiting for erase to complete timed out."); ++ DISABLE_VPP(map); ++ return -EIO; ++ } ++ ++ /* Latency issues. Drop the lock, wait a while and retry */ ++ cfi_spin_unlock(chip->mutex); ++ ++ z++; ++ if ( 0 && !(z % 100 )) ++ printk("chip not ready yet after erase. looping\n"); ++ ++ cfi_udelay(1); ++ ++ cfi_spin_lock(chip->mutex); ++ continue; ++ } ++ ++ /* Done and happy. */ ++ DISABLE_VPP(map); ++ chip->state = FL_READY; ++ wake_up(&chip->wq); ++ cfi_spin_unlock(chip->mutex); ++ return 0; ++} ++ ++static int cfi_sststd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = map->fldrv_priv; ++ unsigned long adr, len; ++ int chipnum, ret = 0; ++ int i, first; ++ struct mtd_erase_region_info *regions = mtd->eraseregions; ++ ++ if (instr->addr > mtd->size) ++ return -EINVAL; ++ ++ if ((instr->len + instr->addr) > mtd->size) ++ return -EINVAL; ++ ++ /* Check that both start and end of the requested erase are ++ * aligned with the erasesize at the appropriate addresses. ++ */ ++ ++ i = 0; ++ ++ /* Skip all erase regions which are ended before the start of ++ the requested erase. Actually, to save on the calculations, ++ we skip to the first erase region which starts after the ++ start of the requested erase, and then go back one. ++ */ ++ ++ while (i < mtd->numeraseregions && instr->addr >= regions[i].offset) ++ i++; ++ i--; ++ ++ /* OK, now i is pointing at the erase region in which this ++ erase request starts. Check the start of the requested ++ erase range is aligned with the erase size which is in ++ effect here. ++ */ ++ ++ if (instr->addr & (regions[i].erasesize-1)) ++ return -EINVAL; ++ ++ /* Remember the erase region we start on */ ++ first = i; ++ ++ /* Next, check that the end of the requested erase is aligned ++ * with the erase region at that address. ++ */ ++ ++ while (inumeraseregions && (instr->addr + instr->len) >= regions[i].offset) ++ i++; ++ ++ /* As before, drop back one to point at the region in which ++ the address actually falls ++ */ ++ i--; ++ ++ if ((instr->addr + instr->len) & (regions[i].erasesize-1)) ++ return -EINVAL; ++ ++ chipnum = instr->addr >> cfi->chipshift; ++ adr = instr->addr - (chipnum << cfi->chipshift); ++ len = instr->len; ++ ++ i=first; ++ ++ while(len) { ++ ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); ++ ++ if (ret) ++ return ret; ++ ++ adr += regions[i].erasesize; ++ len -= regions[i].erasesize; ++ ++ if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) ++ i++; ++ ++ if (adr >> cfi->chipshift) { ++ adr = 0; ++ chipnum++; ++ ++ if (chipnum >= cfi->numchips) ++ break; ++ } ++ } ++ ++ instr->state = MTD_ERASE_DONE; ++ if (instr->callback) ++ instr->callback(instr); ++ ++ return 0; ++} ++ ++static int cfi_sststd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = 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 >> cfi->chipshift; ++ adr = instr->addr - (chipnum << cfi->chipshift); ++ len = instr->len; ++ ++ while(len) { ++ ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); ++ ++ if (ret) ++ return ret; ++ ++ adr += mtd->erasesize; ++ len -= mtd->erasesize; ++ ++ if (adr >> cfi->chipshift) { ++ adr = 0; ++ chipnum++; ++ ++ if (chipnum >= cfi->numchips) ++ break; ++ } ++ } ++ ++ instr->state = MTD_ERASE_DONE; ++ if (instr->callback) ++ instr->callback(instr); ++ ++ return 0; ++} ++ ++static void cfi_sststd_sync (struct mtd_info *mtd) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = map->fldrv_priv; ++ int i; ++ struct flchip *chip; ++ int ret = 0; ++ DECLARE_WAITQUEUE(wait, current); ++ ++ for (i=0; !ret && inumchips; i++) { ++ chip = &cfi->chips[i]; ++ ++ retry: ++ cfi_spin_lock(chip->mutex); ++ ++ switch(chip->state) { ++ case FL_READY: ++ case FL_STATUS: ++ case FL_CFI_QUERY: ++ case FL_JEDEC_QUERY: ++ chip->oldstate = chip->state; ++ chip->state = FL_SYNCING; ++ /* No need to wake_up() on this state change - ++ * as the whole point is that nobody can do anything ++ * with the chip now anyway. ++ */ ++ case FL_SYNCING: ++ cfi_spin_unlock(chip->mutex); ++ break; ++ ++ default: ++ /* Not an idle state */ ++ add_wait_queue(&chip->wq, &wait); ++ ++ cfi_spin_unlock(chip->mutex); ++ ++ schedule(); ++ ++ remove_wait_queue(&chip->wq, &wait); ++ ++ goto retry; ++ } ++ } ++ ++ /* Unlock the chips again */ ++ ++ for (i--; i >=0; i--) { ++ chip = &cfi->chips[i]; ++ ++ cfi_spin_lock(chip->mutex); ++ ++ if (chip->state == FL_SYNCING) { ++ chip->state = chip->oldstate; ++ wake_up(&chip->wq); ++ } ++ cfi_spin_unlock(chip->mutex); ++ } ++} ++ ++ ++static int cfi_sststd_suspend(struct mtd_info *mtd) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = map->fldrv_priv; ++ int i; ++ struct flchip *chip; ++ int ret = 0; ++//printk("suspend\n"); ++ ++ for (i=0; !ret && inumchips; i++) { ++ chip = &cfi->chips[i]; ++ ++ cfi_spin_lock(chip->mutex); ++ ++ switch(chip->state) { ++ case FL_READY: ++ case FL_STATUS: ++ case FL_CFI_QUERY: ++ case FL_JEDEC_QUERY: ++ chip->oldstate = chip->state; ++ chip->state = FL_PM_SUSPENDED; ++ /* No need to wake_up() on this state change - ++ * as the whole point is that nobody can do anything ++ * with the chip now anyway. ++ */ ++ case FL_PM_SUSPENDED: ++ break; ++ ++ default: ++ ret = -EAGAIN; ++ break; ++ } ++ cfi_spin_unlock(chip->mutex); ++ } ++ ++ /* Unlock the chips again */ ++ ++ if (ret) { ++ for (i--; i >=0; i--) { ++ chip = &cfi->chips[i]; ++ ++ cfi_spin_lock(chip->mutex); ++ ++ if (chip->state == FL_PM_SUSPENDED) { ++ chip->state = chip->oldstate; ++ wake_up(&chip->wq); ++ } ++ cfi_spin_unlock(chip->mutex); ++ } ++ } ++ ++ return ret; ++} ++ ++static void cfi_sststd_resume(struct mtd_info *mtd) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = map->fldrv_priv; ++ int i; ++ struct flchip *chip; ++//printk("resume\n"); ++ ++ for (i=0; inumchips; i++) { ++ ++ chip = &cfi->chips[i]; ++ ++ cfi_spin_lock(chip->mutex); ++ ++ if (chip->state == FL_PM_SUSPENDED) { ++ chip->state = FL_READY; ++ cfi_write(map, CMD(0xF0), chip->start); ++ wake_up(&chip->wq); ++ } ++ else ++ printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n"); ++ ++ cfi_spin_unlock(chip->mutex); ++ } ++} ++ ++static void cfi_sststd_destroy(struct mtd_info *mtd) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = map->fldrv_priv; ++ kfree(cfi->cmdset_priv); ++ kfree(cfi); ++} ++ ++#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) ++#define cfi_sststd_init init_module ++#define cfi_sststd_exit cleanup_module ++#endif ++ ++static char im_name[]="cfi_cmdset_0701"; ++ ++mod_init_t cfi_sststd_init(void) ++{ ++ inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0701); ++ return 0; ++} ++ ++mod_exit_t cfi_sststd_exit(void) ++{ ++ inter_module_unregister(im_name); ++} ++ ++module_init(cfi_sststd_init); ++module_exit(cfi_sststd_exit); ++ +diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_probe.c linux-2.4.30.openwrt/drivers/mtd/chips/cfi_probe.c +--- linux-2.4.30/drivers/mtd/chips/cfi_probe.c 2003-06-13 16:51:34.000000000 +0200 ++++ linux-2.4.30.openwrt/drivers/mtd/chips/cfi_probe.c 2005-06-28 11:26:26.000000000 +0200 +@@ -67,8 +67,15 @@ + cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); + +- if (!qry_present(map,base,cfi)) +- return 0; ++ if (!qry_present(map,base,cfi)) { ++ /* rather broken SST cfi probe (requires SST unlock) */ ++ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); ++ cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); ++ if (!qry_present(map,base,cfi)) ++ return 0; ++ } + + if (!cfi->numchips) { + /* This is the first time we're called. Set up the CFI +diff -Nur linux-2.4.30/drivers/mtd/chips/gen_probe.c linux-2.4.30.openwrt/drivers/mtd/chips/gen_probe.c +--- linux-2.4.30/drivers/mtd/chips/gen_probe.c 2003-08-25 13:44:42.000000000 +0200 ++++ linux-2.4.30.openwrt/drivers/mtd/chips/gen_probe.c 2005-06-28 11:29:23.000000000 +0200 +@@ -328,13 +328,18 @@ + return cfi_cmdset_0001(map, primary); + #endif + #ifdef CONFIG_MTD_CFI_AMDSTD ++ case 0x0006: + case 0x0002: + return cfi_cmdset_0002(map, primary); + #endif + #ifdef CONFIG_MTD_CFI_STAA +- case 0x0020: ++ case 0x0020: + return cfi_cmdset_0020(map, primary); + #endif ++#ifdef CONFIG_MTD_CFI_SSTSTD ++ case 0x0701: ++ return cfi_cmdset_0701(map, primary); ++#endif + } + + return cfi_cmdset_unknown(map, primary); diff --git a/openwrt/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch b/openwrt/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch deleted file mode 100644 index 782a9ce6fa..0000000000 --- a/openwrt/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- linux-2.4.30.old/arch/mips/ld.script.in 2005-04-28 23:22:23.513764016 +0400 -+++ linux-2.4.30/arch/mips/ld.script.in 2005-04-28 23:22:36.329673152 +0400 -@@ -9,6 +9,7 @@ - { - _ftext = . ; - *(.text) -+ *(.fixup) - *(.rodata) - *(.rodata.*) - *(.rodata1) diff --git a/openwrt/target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch b/openwrt/target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch index 27adbf163e..9cf055346a 100644 --- a/openwrt/target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch +++ b/openwrt/target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch @@ -1,6 +1,6 @@ -diff -Nur linux-2.4.29/arch/mips/kernel/signal.c linux-2.4.29-gcc3.4/arch/mips/kernel/signal.c ---- linux-2.4.29/arch/mips/kernel/signal.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.29-gcc3.4/arch/mips/kernel/signal.c 2005-03-27 23:09:57.000000000 +0200 +diff -Nur linux-2.4.30/arch/mips/kernel/signal.c linux-2.4.30.openwrt/arch/mips/kernel/signal.c +--- linux-2.4.30/arch/mips/kernel/signal.c 2005-07-02 13:00:13.000000000 +0200 ++++ linux-2.4.30.openwrt/arch/mips/kernel/signal.c 2005-07-02 13:00:49.000000000 +0200 @@ -6,8 +6,10 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994 - 1999 Ralf Baechle @@ -34,9 +34,9 @@ diff -Nur linux-2.4.29/arch/mips/kernel/signal.c linux-2.4.29-gcc3.4/arch/mips/k { sigset_t *unewset, saveset, newset; size_t sigsetsize; -diff -Nur linux-2.4.29/arch/mips/kernel/syscall.c linux-2.4.29-gcc3.4/arch/mips/kernel/syscall.c ---- linux-2.4.29/arch/mips/kernel/syscall.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.29-gcc3.4/arch/mips/kernel/syscall.c 2005-03-27 23:09:57.000000000 +0200 +diff -Nur linux-2.4.30/arch/mips/kernel/syscall.c linux-2.4.30.openwrt/arch/mips/kernel/syscall.c +--- linux-2.4.30/arch/mips/kernel/syscall.c 2005-07-02 13:00:13.000000000 +0200 ++++ linux-2.4.30.openwrt/arch/mips/kernel/syscall.c 2005-07-02 13:00:49.000000000 +0200 @@ -5,6 +5,7 @@ * * Copyright (C) 1995 - 2000 by Ralf Baechle @@ -67,9 +67,20 @@ diff -Nur linux-2.4.29/arch/mips/kernel/syscall.c linux-2.4.29-gcc3.4/arch/mips/ { unsigned long clone_flags; unsigned long newsp; -diff -Nur linux-2.4.29/arch/mips64/kernel/signal.c linux-2.4.29-gcc3.4/arch/mips64/kernel/signal.c ---- linux-2.4.29/arch/mips64/kernel/signal.c 2005-01-19 15:09:32.000000000 +0100 -+++ linux-2.4.29-gcc3.4/arch/mips64/kernel/signal.c 2005-03-27 23:09:57.000000000 +0200 +diff -Nur linux-2.4.30/arch/mips/ld.script.in linux-2.4.30.openwrt/arch/mips/ld.script.in +--- linux-2.4.30/arch/mips/ld.script.in 2005-07-02 13:00:22.000000000 +0200 ++++ linux-2.4.30.openwrt/arch/mips/ld.script.in 2005-07-02 13:00:42.000000000 +0200 +@@ -9,6 +9,7 @@ + { + _ftext = . ; + *(.text) ++ *(.fixup) + *(.rodata) + *(.rodata.*) + *(.rodata1) +diff -Nur linux-2.4.30/arch/mips64/kernel/signal.c linux-2.4.30.openwrt/arch/mips64/kernel/signal.c +--- linux-2.4.30/arch/mips64/kernel/signal.c 2005-07-02 13:00:13.000000000 +0200 ++++ linux-2.4.30.openwrt/arch/mips64/kernel/signal.c 2005-07-02 13:00:49.000000000 +0200 @@ -6,8 +6,10 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994 - 2000 Ralf Baechle @@ -92,9 +103,9 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/signal.c linux-2.4.29-gcc3.4/arch/mips { sigset_t *unewset, saveset, newset; size_t sigsetsize; -diff -Nur linux-2.4.29/arch/mips64/kernel/signal32.c linux-2.4.29-gcc3.4/arch/mips64/kernel/signal32.c ---- linux-2.4.29/arch/mips64/kernel/signal32.c 2005-01-19 15:09:33.000000000 +0100 -+++ linux-2.4.29-gcc3.4/arch/mips64/kernel/signal32.c 2005-03-27 23:09:57.000000000 +0200 +diff -Nur linux-2.4.30/arch/mips64/kernel/signal32.c linux-2.4.30.openwrt/arch/mips64/kernel/signal32.c +--- linux-2.4.30/arch/mips64/kernel/signal32.c 2005-07-02 13:00:13.000000000 +0200 ++++ linux-2.4.30.openwrt/arch/mips64/kernel/signal32.c 2005-07-02 13:00:49.000000000 +0200 @@ -6,7 +6,9 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994 - 2000 Ralf Baechle @@ -127,9 +138,9 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/signal32.c linux-2.4.29-gcc3.4/arch/mi { sigset32_t *uset; sigset_t newset, saveset; -diff -Nur linux-2.4.29/arch/mips64/kernel/syscall.c linux-2.4.29-gcc3.4/arch/mips64/kernel/syscall.c ---- linux-2.4.29/arch/mips64/kernel/syscall.c 2005-01-19 15:09:33.000000000 +0100 -+++ linux-2.4.29-gcc3.4/arch/mips64/kernel/syscall.c 2005-03-27 23:09:57.000000000 +0200 +diff -Nur linux-2.4.30/arch/mips64/kernel/syscall.c linux-2.4.30.openwrt/arch/mips64/kernel/syscall.c +--- linux-2.4.30/arch/mips64/kernel/syscall.c 2005-07-02 13:00:13.000000000 +0200 ++++ linux-2.4.30.openwrt/arch/mips64/kernel/syscall.c 2005-07-02 13:00:49.000000000 +0200 @@ -6,7 +6,9 @@ * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. @@ -162,9 +173,9 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/syscall.c linux-2.4.29-gcc3.4/arch/mip { unsigned long clone_flags; unsigned long newsp; -diff -Nur linux-2.4.29/include/asm-mips/ptrace.h linux-2.4.29-gcc3.4/include/asm-mips/ptrace.h ---- linux-2.4.29/include/asm-mips/ptrace.h 2004-02-18 14:36:32.000000000 +0100 -+++ linux-2.4.29-gcc3.4/include/asm-mips/ptrace.h 2005-03-27 23:09:57.000000000 +0200 +diff -Nur linux-2.4.30/include/asm-mips/ptrace.h linux-2.4.30.openwrt/include/asm-mips/ptrace.h +--- linux-2.4.30/include/asm-mips/ptrace.h 2005-07-02 13:00:13.000000000 +0200 ++++ linux-2.4.30.openwrt/include/asm-mips/ptrace.h 2005-07-02 13:00:49.000000000 +0200 @@ -4,6 +4,7 @@ * for more details. * @@ -187,9 +198,9 @@ diff -Nur linux-2.4.29/include/asm-mips/ptrace.h linux-2.4.29-gcc3.4/include/asm #endif /* !__ASSEMBLY__ */ /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ -diff -Nur linux-2.4.29/include/asm-mips64/ptrace.h linux-2.4.29-gcc3.4/include/asm-mips64/ptrace.h ---- linux-2.4.29/include/asm-mips64/ptrace.h 2004-02-18 14:36:32.000000000 +0100 -+++ linux-2.4.29-gcc3.4/include/asm-mips64/ptrace.h 2005-03-27 23:09:57.000000000 +0200 +diff -Nur linux-2.4.30/include/asm-mips64/ptrace.h linux-2.4.30.openwrt/include/asm-mips64/ptrace.h +--- linux-2.4.30/include/asm-mips64/ptrace.h 2005-07-02 13:00:13.000000000 +0200 ++++ linux-2.4.30.openwrt/include/asm-mips64/ptrace.h 2005-07-02 13:00:49.000000000 +0200 @@ -5,6 +5,7 @@ * * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle