mirror of https://github.com/hak5/openwrt-owl.git
unify gcc 3.4 fixes, move flash chip drivers to generic patches, move diag_led driver to separate patch, update docs
SVN-Revision: 1316owl
parent
328d6b8fa2
commit
697c74552a
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 <kaloz@dune.hu>
|
||||
+ *
|
||||
+ * 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 <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sysctl.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <typedefs.h>
|
||||
+#include <bcmdevs.h>
|
||||
+#include <sbutils.h>
|
||||
+
|
||||
+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);
|
|
@ -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. <info@crossnet.co.jp>
|
||||
+ *
|
||||
+ * 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 <linux/module.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <asm/byteorder.h>
|
||||
+
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/mtd/map.h>
|
||||
+#include <linux/mtd/cfi.h>
|
||||
+
|
||||
+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<<cfi->cfiq->WordWriteTimeoutTyp;
|
||||
+ cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
|
||||
+ cfi->chips[i].erase_time = 1<<cfi->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<<cfi->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; i<cfi->cfiq->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; j<cfi->numchips; 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; i<mtd->numeraseregions;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<<cfi->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 (i<mtd->numeraseregions && (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 && i<cfi->numchips; 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 && i<cfi->numchips; 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; i<cfi->numchips; 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);
|
|
@ -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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue