summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/drivers/mtd/chips/rtl819x
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2012-09-13 00:40:35 +0300
committerRoman Yeryomin <roman@advem.lv>2012-12-03 00:13:21 +0200
commit5deb3317cb51ac52de922bb55f8492624018906d (patch)
treec2fbe6346699d9bb0f2100490c3029519bb8fde8 /target/linux/realtek/files/drivers/mtd/chips/rtl819x
parent0239d37124f9184b478a42de8a7fa1bc85a6a6fe (diff)
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/mtd/chips/rtl819x')
-rw-r--r--target/linux/realtek/files/drivers/mtd/chips/rtl819x/Makefile12
-rw-r--r--target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_cmd.c172
-rw-r--r--target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_common.c1208
-rw-r--r--target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_common.h203
-rw-r--r--target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.c146
-rw-r--r--target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.h29
-rw-r--r--target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_probe.c209
7 files changed, 1979 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/mtd/chips/rtl819x/Makefile b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/Makefile
new file mode 100644
index 000000000..0e878a3b3
--- /dev/null
+++ b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/Makefile
@@ -0,0 +1,12 @@
+#
+# linux/drivers/mtd/devices/rtd2885/Makefile
+#
+# $Id: Makefile,v 1.1.1.1 2005/01/12 03:23:03 cyhuang Exp $
+
+EXTRA_CFLAGS += -DSPI_KERNEL
+
+obj-y += spi_probe.o spi_cmd.o spi_common.o spi_flash.o
+CFLAGS_spi_probe.o += -O0
+CFLAGS_spi_cmd.o += -O0
+CFLAGS_spi_common.o += -O0
+CFLAGS_spi_flash.o += -O0
diff --git a/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_cmd.c b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_cmd.c
new file mode 100644
index 000000000..4e37c64e3
--- /dev/null
+++ b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_cmd.c
@@ -0,0 +1,172 @@
+/**
+ * SPI Flash common control code.
+ * (C) 2006 Atmark Techno, Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+//#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/gen_probe.h>
+
+#include "spi_flash.h"
+
+//#define MTD_SPI_DEBUG
+
+#if defined(MTD_SPI_DEBUG)
+#define KDEBUG(args...) printk(args)
+#else
+#define KDEBUG(args...)
+#endif
+
+// eric modified
+#if 1
+#else
+extern int mtd_spi_erase(struct mtd_info *mtd, struct erase_info *instr);
+extern int mtd_spi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+extern int mtd_spi_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+extern void mtd_spi_sync(struct mtd_info *mtd);
+extern int mtd_spi_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
+extern int mtd_spi_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
+extern int mtd_spi_suspend(struct mtd_info *mtd);
+extern void mtd_spi_resume(struct mtd_info *mtd);
+#endif
+
+int mtd_spi_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct map_info *map = mtd->priv;
+ struct spi_chip_info *chip_info = (struct spi_chip_info *)map->fldrv_priv;
+ unsigned long adr, len;
+ int ret = 0;
+
+ if (!chip_info->erase)
+ return -EOPNOTSUPP;
+#if 0
+ // skip 1st block erase
+ if (instr->addr < (mtd->erasesize ))
+ {
+ instr->state = MTD_ERASE_DONE;
+ return 0;
+ }
+#endif
+ 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;
+
+ adr = instr->addr;
+ len = instr->len;
+
+ KDEBUG("mtd_spi_erase():: adr: 0x%08lx, len: 0x%08lx\n", adr, len);
+
+
+ if (len & (mtd->erasesize-1))
+ {
+ len = len - (len & (mtd->erasesize-1)) + mtd->erasesize;
+ }
+
+ if (len < mtd->erasesize)
+ len = mtd->erasesize;
+
+ while (len) {
+ ret = chip_info->erase(adr,chip_info->chip_select);
+ if (ret)
+ return ret;
+ adr += mtd->erasesize;
+ len -= mtd->erasesize;
+ }
+
+ instr->state = MTD_ERASE_DONE;
+ if (instr->callback)
+ instr->callback(instr);
+
+ return 0;
+}
+
+int mtd_spi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ struct map_info *map = mtd->priv;
+ struct spi_chip_info *chip_info = (struct spi_chip_info *)map->fldrv_priv;
+ int ret = 0;
+
+ if (!chip_info->read)
+ return -EOPNOTSUPP;
+
+ KDEBUG("mtd_spi_read():: adr: 0x%08x, len: %08x, cs=%d\n", (u32)from, len, chip_info->chip_select);
+
+ ret = chip_info->read(from, (u32)buf, len, chip_info->chip_select);
+ if (ret)
+ return ret;
+
+ if(retlen)
+ (*retlen) = len;
+
+ return 0;
+}
+
+int mtd_spi_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 spi_chip_info *chip_info = (struct spi_chip_info *)map->fldrv_priv;
+ int ret = 0;
+
+ if (!chip_info->write)
+ return -EOPNOTSUPP;
+
+ KDEBUG(" mtd_spi_write():: adr: 0x%08x, len: 0x%08x, cs=%d\n", (u32)to, len, chip_info->chip_select);
+
+ ret = chip_info->write((u32)buf, to, len, chip_info->chip_select);
+ if (ret)
+ return ret;
+
+ if (retlen)
+ (*retlen) = len;
+
+ return 0;
+}
+
+void mtd_spi_sync(struct mtd_info *mtd)
+{
+ /* Operation not supported on transport endpoint */
+}
+
+int mtd_spi_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ /* Operation not supported on transport endpoint */
+ return -EOPNOTSUPP;
+}
+
+int mtd_spi_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ /* Operation not supported on transport endpoint */
+ return -EOPNOTSUPP;
+}
+
+int mtd_spi_suspend(struct mtd_info *mtd)
+{
+ /* Operation not supported on transport endpoint */
+ return -EOPNOTSUPP;
+}
+
+void mtd_spi_resume(struct mtd_info *mtd)
+{
+ /* Operation not supported on transport endpoint */
+}
+
+EXPORT_SYMBOL(mtd_spi_erase);
+EXPORT_SYMBOL(mtd_spi_read);
+EXPORT_SYMBOL(mtd_spi_write);
+EXPORT_SYMBOL(mtd_spi_sync);
+EXPORT_SYMBOL(mtd_spi_lock);
+EXPORT_SYMBOL(mtd_spi_unlock);
+EXPORT_SYMBOL(mtd_spi_suspend);
+EXPORT_SYMBOL(mtd_spi_resume);
diff --git a/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_common.c b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_common.c
new file mode 100644
index 000000000..89c49edfb
--- /dev/null
+++ b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_common.c
@@ -0,0 +1,1208 @@
+/* SPI Flash driver
+ *
+ * Written by sam (sam@realtek.com)
+ * 2010-05-01
+ *
+ */
+
+#define MTD_SPI_DEBUG 2
+#define MTD_SPI_TEST_CHIP 0
+#include "spi_common.h"
+
+#ifndef SPI_KERNEL
+// ****** spi flash driver in bootcode
+
+#include <asm/rtl8196x.h>
+#include <rtl_types.h>
+#if (MTD_SPI_DEBUG == 0)
+//0
+#define NDEBUG(args...) printf(args)
+#define KDEBUG(args...) printf(args)
+#define LDEBUG(args...) printf(args)
+#endif
+//1
+#if (MTD_SPI_DEBUG == 1)
+#define NDEBUG(args...) printf(args)
+#define KDEBUG(args...) printf(args)
+#define LDEBUG(args...)
+#endif
+//2
+#if (MTD_SPI_DEBUG == 2)
+#define NDEBUG(args...) printf(args)
+#define KDEBUG(args...)
+#define LDEBUG(args...)
+#endif
+//3
+#if (MTD_SPI_DEBUG == 3)
+#define NDEBUG(args...)
+#define KDEBUG(args...)
+#define LDEBUG(args...)
+#endif
+
+#else
+// ****** spi flash driver in kernel
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#define malloc vmalloc
+#define free vfree
+//0
+#if (MTD_SPI_DEBUG == 0)
+#define NDEBUG(args...) printk(args)
+#define KDEBUG(args...) printk(args)
+#define LDEBUG(args...) printk(args)
+#endif
+//1
+#if (MTD_SPI_DEBUG == 1)
+#define NDEBUG(args...) printk(args)
+#define KDEBUG(args...) printk(args)
+#define LDEBUG(args...)
+#endif
+//2
+#if (MTD_SPI_DEBUG == 2)
+#define NDEBUG(args...) printk(args)
+#define KDEBUG(args...)
+#define LDEBUG(args...)
+#endif
+//3
+#if (MTD_SPI_DEBUG == 3)
+#define NDEBUG(args...)
+#define KDEBUG(args...)
+#define LDEBUG(args...)
+#endif
+
+#endif
+
+/* SPI Flash Configuration Register(SFCR) (0xb800-1200) */
+#define SFCR 0xb8001200 /*SPI Flash Configuration Register*/
+#define SFCR_SPI_CLK_DIV(val) ((val) << 29)
+#define SFCR_RBO(val) ((val) << 28)
+#define SFCR_WBO(val) ((val) << 27)
+#define SFCR_SPI_TCS(val) ((val) << 23) /*4 bit, 1111 */
+
+/* SPI Flash Configuration Register(SFCR2) (0xb800-1204) */
+#define SFCR2 0xb8001204
+#define SFCR2_SFCMD(val) ((val) << 24) /*8 bit, 1111_1111 */
+#define SFCR2_SFSIZE(val) ((val) << 21) /*3 bit, 111 */
+#define SFCR2_RD_OPT(val) ((val) << 20)
+#define SFCR2_CMD_IO(val) ((val) << 18) /*2 bit, 11 */
+#define SFCR2_ADDR_IO(val) ((val) << 16) /*2 bit, 11 */
+#define SFCR2_DUMMY_CYCLE(val) ((val) << 13) /*3 bit, 111 */
+#define SFCR2_DATA_IO(val) ((val) << 11) /*2 bit, 11 */
+#define SFCR2_HOLD_TILL_SFDR2(val) ((val) << 10)
+
+/* SPI Flash Control and Status Register(SFCSR)(0xb800-1208) */
+#define SFCSR 0xb8001208
+#define SFCSR_SPI_CSB0(val) ((val) << 31)
+#define SFCSR_SPI_CSB1(val) ((val) << 30)
+#define SFCSR_LEN(val) ((val) << 28) /*2 bits*/
+#define SFCSR_SPI_RDY(val) ((val) << 27)
+#define SFCSR_IO_WIDTH(val) ((val) << 25) /*2 bits*/
+#define SFCSR_CHIP_SEL(val) ((val) << 24)
+#define SFCSR_CMD_BYTE(val) ((val) << 16) /*8 bit, 1111_1111 */
+
+#define SFCSR_SPI_CSB(val) ((val) << 30)
+
+/* SPI Flash Data Register(SFDR)(0xb800-120c) */
+#define SFDR 0xb800120c
+
+/* SPI Flash Data Register(SFDR2)(0xb8001210) */
+#define SFDR2 0xb8001210
+
+#define SPI_BLOCK_SIZE 0x10000 /* 64KB */
+#define SPI_SECTOR_SIZE 0x1000 /* 4KB */
+#define SPI_PAGE_SIZE 0x100 /* 256B */
+
+#define SPICMD_WREN (0x06 << 24) /* 06 xx xx xx xx sets the (WEL) write enable latch bit */
+#define SPICMD_WRDI (0x04 << 24) /* 04 xx xx xx xx resets the (WEL) write enable latch bit*/
+#define SPICMD_RDID (0x9f << 24) /* 9f xx xx xx xx outputs JEDEC ID: 1 byte manufacturer ID & 2 byte device ID */
+#define SPICMD_RDSR (0x05 << 24) /* 05 xx xx xx xx to read out the values of the status register */
+#define SPICMD_WRSR (0x01 << 24) /* 01 xx xx xx xx to write new values to the status register */
+#define SPICMD_READ (0x03 << 24) /* 03 a1 a2 a3 xx n bytes read out until CS# goes high */
+#define SPICMD_FASTREAD (0x0b << 24) /* 0b a1 a2 a3 dd n bytes read out until CS# goes high */
+#define SPICMD_2READ (0xbb << 24) /* bb 12 3d xx xx n bytes read out by 2 I/O until CS# goes high */
+#define SPICMD_4READ (0xeb << 24) /* eb 3a 3d xx xx n bytes read out by 4 x I/O until CS# goes high */
+#define SPICMD_SE (0x20 << 24) /* 20 a1 a2 a3 xx to erase the selected sector */
+#define SPICMD_BE (0xd8 << 24) /* d8 a1 a2 a3 xx to erase the selected block */
+#define SPICMD_CE (0x60 << 24) /* 60 xx xx xx xx to erase whole chip (cmd or 0xc7) */
+#define SPICMD_PP (0x02 << 24) /* 02 a1 a2 a3 xx to program the selected page */
+#define SPICMD_4PP (0x38 << 24) /* 38 3a 3d xx xx quad input to program the selected page */
+#define SPICMD_CP (0xad << 24) /* ad a1 a2 a3 xx continously program whole chip, the address is automaticlly increase */
+#define SPICMD_DP (0xb9 << 24) /* b9 xx xx xx xx enters deep power down mode */
+#define SPICMD_RDP (0xab << 24) /* ab xx xx xx xx release from deep power down mode */
+#define SPICMD_RES (0xab << 24) /* ab ?? ?? ?? xx to read out 1 byte device ID */
+#define SPICMD_REMS_90 (0x90 << 24) /* 90 ?? ?? ?? xx output the manufacter ID & device ID */
+#define SPICMD_REMS_EF (0xef << 24) /* ef ?? ?? ?? xx output the manufacter ID & device ID */
+#define SPICMD_REMS_DF (0xdf << 24) /* df ?? ?? ?? ?? output the manufacture ID & device ID */
+#define SPICMD_ENSO (0xb1 << 24) /* b1 xx xx xx xx to enter the 512 bit secured OTP mode */
+#define SPICMD_EXSO (0xc1 << 24) /* c1 xx xx xx xx to exit the 512 bit secured OTP mode */
+#define SPICMD_RDSCUR (0x2b << 24) /* 2b xx xx xx xx to read value of secured register */
+#define SPICMD_WRSCUR (0x2f << 24) /* 2f xx xx xx xx to set the lock down bit as "1" (once lock down, can not be updated) */
+#define SPICMD_ESRY (0x70 << 24) /* 70 xx xx xx xx to enable SO to output RY/BY# during CP mode */
+#define SPICMD_DSRY (0x80 << 24) /* 80 xx xx xx xx to disable SO to output RY/BY# during CP mode */
+
+#define SPI_STATUS_REG_SRWD 0x07 /* status register write protect */
+#define SPI_STATUS_CP 0x06 /* continously program mode */
+#define SPI_STATUS_QE 0x06 /* quad enable */
+#define SPI_STATUS_BP3 0x05 /* level of protected block */
+#define SPI_STATUS_BP2 0x04 /* level of protected block */
+#define SPI_STATUS_BP1 0x03 /* level of protected block */
+#define SPI_STATUS_BP0 0x02 /* level of protected block */
+#define SPI_STATUS_WEL 0x01 /* write enable latch */
+#define SPI_STATUS_WIP 0x00 /* write in process bit */
+
+/****** EON ******/
+
+/****** SPANSION ******/
+#define SPICMD_SPAN_QOR (0x6b << 24) /* 3 0 1 (1 to ∞) Quad Ou// write sector use malloc buffer */
+#define SPICMD_SPAN_QPP (0x32 << 24) /* Quad Page Programming */
+#define SPAN_CONF_QUAD 0x01
+
+/****** WINBOND ******/
+#define WB_STATUS_QE 0x09 /* QUAD ENABLE (non-volatile) */
+#define SPICMD_WB_QPP (0x32 << 24) /* Quad Page Program */
+
+/****** SST ******/
+
+/****** GigaDevice ******/
+#define GD_STATUS_QE 0x09 /* 9 When the QE bit is set to 0 (Default) the WP# pin and HOLD# pin are enable */
+#define SPICMD_GD_HPM (0xA3 << 24) /* High Performance Mode A3H dummy dummy dummy */
+#define SPICMD_GD_QPP 0x32
+
+/****** ATMEL ******/
+// Clock Address Dummy Data
+//Command Opcode Frequency Bytes Bytes Bytes
+#define SPICMD_AT_READ2 (0x3b << 24) //Dual-Output Read Array 3Bh 0011 1011 Up to 85 MHz 3 1 1+
+#define SPICMD_AT_PP2 (0xa2 << 24) //Dual-Input Byte/Page Program A2h 1010 0010 Up to 100 MHz 3 0 1+
+
+/* Spanson Flash */
+#define S25FL004A 0x00010212
+#define S25FL016A 0x00010214
+#define S25FL032A 0x00010215
+#define S25FL064A 0x00010216 /*supposed support*/
+#define S25FL128P 0x00012018 /*only S25FL128P0XMFI001, Uniform 64KB secotr*/
+ /*not support S25FL128P0XMFI011, Uniform 256KB secotr*/
+ /*because #define SPI_BLOCK_SIZE 65536 */
+#define S25FL032P 0x00010215
+
+/* MICRONIX Flash */
+#define MX25L4005 0x00C22013
+#define MX25L1605D 0x00C22015
+#define MX25L1605E 0x00C22015
+#define MX25L3205D 0x00C22016 /*supposed support*/
+#define MX25L3205E 0x00C22016 /*supposed support*/
+#define MX25L6405D 0x00C22017
+#define MX25L6405E 0x00C22017
+#define MX25L6445E 0x00C22017
+#define MX25L12805D 0x00C22018
+#define MX25L12845E 0x00C22018
+
+#define MX25L1635D 0x00C22415
+#define MX25L1635E 0x00C22515
+#define MX25L1636E 0x00C22515
+#define MX25L3235D 0x00C25E16
+
+/* SST Flash */
+#define SST25VF032B 0x00BF254A //4MB
+#define SST26VF016 0x00BF2601
+#define SST26VF032 0x00BF2602
+
+/* WinBond Flash */
+#define W25Q80 0x00EF4014
+#define W25Q16 0x00EF4015
+#define W25Q32 0x00EF4016
+
+/* Eon Flash */
+#define EN25F32 0x001c3116
+#define EN25F16 0x001c3115
+#define EN25Q32 0x001c3016
+#define EN25Q16 0x001c3015
+
+/* GigaDevice Flash */
+#define GD25Q16 0x00c84015
+#define GD25Q32 0x00c84016
+#define GD25Q64 0x00c84017
+
+/* Atmel Flash */
+#define AT25DF161 0x001f4602
+
+#define SIZE2N_128K 0x11
+#define SIZE2N_256K 0x12
+#define SIZE2N_512K 0x13
+#define SIZE2N_01MB 0x14
+#define SIZE2N_02MB 0x15
+#define SIZE2N_04MB 0x16
+#define SIZE2N_08MB 0x17
+#define SIZE2N_16MB 0x18
+#define SIZE2N_32MB 0x19
+#define SIZE2N_64MB 0x20
+#define SIZE2N_128M 0x21
+
+#define SIZE_256B 0x100
+#define SIZE_004K 0x1000
+#define SIZE_064K 0x10000
+
+#define SPI_REG_READ(reg) *((volatile unsigned int *)(reg))
+#define SPI_REG_LOAD(reg,val) while((*((volatile unsigned int *)SFCSR) & (SFCSR_SPI_RDY(1))) == 0); *((volatile unsigned int *)(reg)) = (val)
+
+#define IOWIDTH_SINGLE 0x00
+#define IOWIDTH_DUAL 0x01
+#define IOWIDTH_QUAD 0x02
+#define DATA_LENTH1 0x00
+#define DATA_LENTH2 0x01
+#define DATA_LENTH4 0x02
+#define ISFAST_NO 0x00
+#define ISFAST_YES 0x01
+#define ISFAST_ALL 0x02
+#define DUMMYCOUNT_0 0x00
+#define DUMMYCOUNT_1 0x01
+#define DUMMYCOUNT_2 0x02
+#define DUMMYCOUNT_3 0x03
+#define DUMMYCOUNT_4 0x04
+#define DUMMYCOUNT_5 0x05
+#define DUMMYCOUNT_6 0x06
+#define DUMMYCOUNT_7 0x07
+#define DUMMYCOUNT_8 0x08
+#define DUMMYCOUNT_9 0x09
+
+struct spi_flash_type spi_flash_info[2];
+//unsigned char ucDispCount = 0;
+unsigned char ucSFCR2 = 154;
+#if (MTD_SPI_TEST_CHIP == 1)
+unsigned int test_spi_flash(unsigned char ucChip);
+#endif
+
+struct spi_flash_known spi_flash_registed[] = {
+/****************************************** Micronix Flash ******************************************/
+//#define MX25L1605D 0x00C22015
+{0x00C22015, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "MX25L1605D/E"
+#if (SPI_DRIVER_MODE == 1)
+, 86, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 86, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define MX25L3205D 0x00C22016
+{0x00C22016, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "MX25L3205D/E"
+#if (SPI_DRIVER_MODE == 1)
+, 86, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 86, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define MX25L6405D 0x00C22017
+//#define MX25L6405E 0x00C22017
+//#define MX25L6445E 0x00C22017
+{0x00C22017, 0x00, SIZE2N_08MB, SIZE_064K, SIZE_004K, SIZE_256B, "MX6405D/05E/45E"
+#if (SPI_DRIVER_MODE == 1)
+, 86, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 86, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#defien MX25L12805D 0x00C22018
+//#define MX25L12845E 0x00C22018
+{0x00C22018, 0x00, SIZE2N_16MB, SIZE_064K, SIZE_004K, SIZE_256B, "MX25L12805D/45E"
+#if (SPI_DRIVER_MODE == 1)
+, 86, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 86, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define MX25L1635D 0x00C22415
+{0x00C22415, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "MX25L1635D"
+#if (SPI_DRIVER_MODE == 1)
+, 75, ComSrlCmd_SE, SpiRead_1443EB, mxic_spi_setQEBit, PageWrite_144038
+#else
+, 75, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define MX25L1635E 0x00C22515 (clock 108 down to 54)
+{0x00C22515, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "MX25L1635E/36E"
+#if (SPI_DRIVER_MODE == 1)
+, 108, ComSrlCmd_SE, SpiRead_1443EB, mxic_spi_setQEBit, PageWrite_144038
+#else
+, 108, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define MX25L3235D 0x00C25E16
+{0x00C25E16, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "MX25L3235D"
+#if (SPI_DRIVER_MODE == 1)
+, 75, ComSrlCmd_SE, SpiRead_1443EB, mxic_spi_setQEBit, PageWrite_144038
+#else
+, 104, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+/****************************************** Spanson Flash ******************************************/
+//#define S25FL016A 0x00010214
+{0x00010214, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_064K, SIZE_256B, "S25FL016A"
+#if (SPI_DRIVER_MODE == 1)
+, 50, ComSrlCmd_BE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 50, ComSrlCmd_BE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define S25FL032A 0x00010215
+{0x00010215, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_064K, SIZE_256B, "S25FL032A"
+#if (SPI_DRIVER_MODE == 1)
+, 50, ComSrlCmd_BE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 50, ComSrlCmd_BE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define S25FL064A 0x00010216
+{0x00010216, 0x00, SIZE2N_08MB, SIZE_064K, SIZE_064K, SIZE_256B, "S25FL064P"
+#if (SPI_DRIVER_MODE == 1)
+, 80, ComSrlCmd_BE, SpiRead_1443EB, span_spi_setQEBit, PageWrite_114032
+#else
+, 104, ComSrlCmd_BE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+/****************************************** Eon Flash ******************************************/
+//#define EN25F16 0x001c3115
+{0x001c3115, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "EN25F16"
+#if (SPI_DRIVER_MODE == 1)
+, 100, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 100, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define EN25F32 0x001c3116
+{0x001c3116, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "EN25F32-100"
+#if (SPI_DRIVER_MODE == 1)
+, 100, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 100, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define EN25Q16 0x001c3015
+{0x001c3015, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "EN25Q16A"
+#if (SPI_DRIVER_MODE == 1)
+, 80, ComSrlCmd_SE, SpiRead_1443EB, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 80, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define EN25Q32 0x001c3016
+{0x001c3016, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "EN25Q32A"
+#if (SPI_DRIVER_MODE == 1)
+, 80, ComSrlCmd_SE, SpiRead_1443EB, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 80, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+/****************************************** SST Flash ******************************************/
+//#define SST25VF032B 0x00BF254A (clock 80 down to 40)
+{0x00BF254A, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "SST25VF032B"
+#if (SPI_DRIVER_MODE == 1)
+, 40, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, sst_PageWrite_s1
+#else
+, 40, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, sst_PageWrite_s1
+#endif
+},
+/****************************************** GigaDevice Flash ******************************************/
+//#define GD25Q16 0x00c84015
+{0x00c84015, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "GD25Q16"
+#if (SPI_DRIVER_MODE == 1)
+, 90, ComSrlCmd_SE, SpiRead_1443EB, gd_spi_setQEBit, PageWrite_111002
+#else
+, 120, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define GD25Q32 0x00c84016
+{0x00c84016, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "GD25Q32"
+#if (SPI_DRIVER_MODE == 1)
+, 80, ComSrlCmd_SE, SpiRead_1443EB, gd_spi_setQEBit, PageWrite_114032
+#else
+, 100, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define GD25Q64 0x00c84017
+{0x00c84017, 0x00, SIZE2N_08MB, SIZE_064K, SIZE_004K, SIZE_256B, "GD25Q64"
+#if (SPI_DRIVER_MODE == 1)
+, 80, ComSrlCmd_SE, SpiRead_1443EB, gd_spi_setQEBit, PageWrite_114032
+#else
+, 100, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+/****************************************** WinBond Flash ******************************************/
+//#define W25Q16 0x00EF4015
+{0x00EF4015, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "W25Q16"
+#if (SPI_DRIVER_MODE == 1)
+, 104, ComSrlCmd_SE, SpiRead_1443EB, wb_spi_setQEBit, PageWrite_114032
+#else
+, 104, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define W25Q32 0x00EF4016
+{0x00EF4016, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "W25Q32"
+#if (SPI_DRIVER_MODE == 1)
+, 104, ComSrlCmd_SE, SpiRead_1443EB, wb_spi_setQEBit, PageWrite_114032
+#else
+, 104, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define W25X16 0x00EF3015
+{0x00EF3015, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "W25X16"
+#if (SPI_DRIVER_MODE == 1)
+, 104, ComSrlCmd_SE, SpiRead_11213B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 104, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define W25X32 0x00EF3016
+{0x00EF3016, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "W25X32"
+#if (SPI_DRIVER_MODE == 1)
+, 104, ComSrlCmd_SE, SpiRead_11213B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 104, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+//#define W25X64 0x00EF3017
+{0x00EF3016, 0x00, SIZE2N_08MB, SIZE_064K, SIZE_004K, SIZE_256B, "W25X64"
+#if (SPI_DRIVER_MODE == 1)
+, 104, ComSrlCmd_SE, SpiRead_11213B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 104, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+/****************************************** ATMEL Flash ******************************************/
+//#define AT25DF161 0x001f4602
+{0x001f4602, 0x00, SIZE2N_02MB, SIZE_064K, SIZE_004K, SIZE_256B, "AT25DF161"
+#if (SPI_DRIVER_MODE == 1)
+, 85, ComSrlCmd_SE, SpiRead_11213B, ComSrlCmd_NoneQeBit, PageWrite_1120A2
+#else
+, 85, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+/****************************************** Qingistek ******************************************/
+//#define PM25LQ032 0x007f9d46
+{0x007f9d46, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "PM25LQ032"
+#if (SPI_DRIVER_MODE == 1)
+, 85, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 85, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+},
+/****************************************** ESMT ******************************************/
+//#define PM25LQ032 0x007f9d46
+{0x008c2016, 0x00, SIZE2N_04MB, SIZE_064K, SIZE_004K, SIZE_256B, "F25L32PA-100"
+#if (SPI_DRIVER_MODE == 1)
+, 100, ComSrlCmd_SE, SpiRead_1221BB, ComSrlCmd_NoneQeBit, PageWrite_111002
+#else
+, 50, ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002
+#endif
+}
+};
+
+// spi flash probe
+void spi_regist(unsigned char ucChip)
+{
+ unsigned int ui, i, uiCount, uiRems;
+ unsigned char pucBuffer[4];
+
+ ui = ComSrlCmd_RDID(ucChip, 4);
+ ui = ComSrlCmd_RDID(ucChip, 4);
+ ui = ui >> 8;
+
+ uiCount = sizeof(spi_flash_registed) / sizeof(struct spi_flash_known);
+
+ for (i = 0; i < uiCount; i++)
+ {
+ if(spi_flash_registed[i].uiChipId == ui)
+ {
+ break;
+ }
+ }
+ if(i == uiCount)
+ {
+ // default setting
+ i = ui & 0xff;
+ if((i < SIZE2N_128K) || (i > SIZE2N_128M))
+ {
+ i = SIZE2N_04MB;
+ }
+ setFSCR(ucChip, 40, 1, 1, 15);
+ set_flash_info(ucChip, ui, i, SIZE_064K, SIZE_004K, SIZE_256B, "UNKNOWN", ComSrlCmd_SE, SpiRead_11110B, ComSrlCmd_NoneQeBit, PageWrite_111002, 40);
+ }
+ else
+ {
+ // have registed
+ setFSCR(ucChip, spi_flash_registed[i].chipClock, 1, 1, 15);
+ set_flash_info(ucChip, ui, spi_flash_registed[i].uiCapacityId, spi_flash_registed[i].uiBlockSize, spi_flash_registed[i].uiSectorSize, spi_flash_registed[i].uiPageSize, spi_flash_registed[i].pcChipName, spi_flash_registed[i].pfErase, spi_flash_registed[i].pfRead, spi_flash_registed[i].pfQeBit, spi_flash_registed[i].pfPageWrite, spi_flash_registed[i].chipClock);
+ }
+ spi_flash_info[ucChip].pfQeBit(ucChip);
+ prnFlashInfo(ucChip, spi_flash_info[ucChip]);
+ ui = spi_flash_info[ucChip].pfRead(ucChip, 0x00, 4, pucBuffer);
+#if (MTD_SPI_TEST_CHIP == 1)
+ ui = test_spi_flash(ucChip);
+#endif
+ LDEBUG("spi_regist: ucChip=%x; i=%x; uiCount=%x\n", ucChip, i, uiCount);
+}
+// set spi_flash_info struction content
+void set_flash_info(unsigned char ucChip, unsigned int chip_id, unsigned int device_cap, unsigned int block_size, unsigned int sector_size, unsigned int page_size, char* chip_name, FUNC_ERASE pfErase, FUNC_READ pfRead, FUNC_SETQEBIT pfQeBit, FUNC_PAGEWRITE pfPageWrite, unsigned int chipClock)
+{
+ unsigned int ui = 1 << device_cap;
+ spi_flash_info[ucChip].chip_id = chip_id;
+ spi_flash_info[ucChip].mfr_id = (chip_id >> 16) & 0xff;
+ spi_flash_info[ucChip].dev_id = (chip_id >> 8) & 0xff;
+ spi_flash_info[ucChip].capacity_id = (chip_id) & 0xff;
+ spi_flash_info[ucChip].size_shift = calShift(spi_flash_info[ucChip].capacity_id, device_cap);
+ spi_flash_info[ucChip].device_size = device_cap; // 2 ^ N (bytes)
+ spi_flash_info[ucChip].chip_size = ui;
+ spi_flash_info[ucChip].block_size = block_size;
+ spi_flash_info[ucChip].block_cnt = ui / block_size;
+ spi_flash_info[ucChip].sector_size = sector_size;
+ spi_flash_info[ucChip].sector_cnt = ui / sector_size;
+ spi_flash_info[ucChip].page_size = page_size;
+ spi_flash_info[ucChip].page_cnt = sector_size / page_size;
+ spi_flash_info[ucChip].chip_name = chip_name;
+ spi_flash_info[ucChip].pfErase = pfErase;
+ spi_flash_info[ucChip].pfWrite = ComSrlCmd_ComWriteData;
+ spi_flash_info[ucChip].pfRead = pfRead;
+ spi_flash_info[ucChip].pfQeBit = pfQeBit;
+ spi_flash_info[ucChip].pfPageWrite = pfPageWrite;
+ spi_flash_info[ucChip].chipClock = chipClock;
+ //SPI_REG_LOAD(SFCR2, 0x0bb08000);
+ LDEBUG("set_flash_info: ucChip=%x; chip_id=%x; device_cap=%x; block_size=%x; sector_size=%x; page_size=%x; chip_name=%s\n", ucChip, chip_id, device_cap, block_size, sector_size, page_size, chip_name);
+}
+
+/****************************** Common function ******************************/
+// get Dram Frequence
+unsigned int CheckDramFreq(void) //JSW:For 8196C
+{
+ unsigned short usFreqBit;
+#ifdef CONFIG_RTL8198
+ unsigned short usFreqVal[] = {65, 181, 150, 125, 156, 168, 237, 193};
+#else
+ unsigned short usFreqVal[] = {65, 78, 125, 150, 156, 168, 193, 193};
+#endif
+ usFreqBit = (0x00001C00 & (*(unsigned int*)0xb8000008)) >> 10 ;
+ LDEBUG("CheckDramFreq:usFreqVal=%dMHZ; usFreqBit=%x; B8000008=%x;\n", usFreqVal[usFreqBit], usFreqBit, (*(unsigned int*)0xb8000008));
+ NDEBUG("SDRAM CLOCK:%dMHZ\n", usFreqVal[usFreqBit]);
+ return usFreqVal[usFreqBit];
+}
+// Set FSCR register, disable this function in kernel
+void setFSCR(unsigned char ucChip, unsigned int uiClkMhz, unsigned int uiRBO, unsigned int uiWBO, unsigned int uiTCS)
+{
+#ifndef SPI_KERNEL
+ unsigned int ui, uiClk;
+ uiClk = CheckDramFreq();
+#ifdef CONFIG_AUTO_PROBE_LIMITED_SPI_CLK_UNDER_40MHZ
+ uiClkMhz = 40;
+#endif
+ ui = uiClk / uiClkMhz;
+ if((uiClk % uiClkMhz) > 0)
+ {
+ ui = ui + 1;
+ }
+ if((ui % 2) > 0)
+ {
+ ui = ui + 1;
+ }
+ spi_flash_info[ucChip].chip_clk = uiClk / ui;
+ SPI_REG_LOAD(SFCR, SFCR_SPI_CLK_DIV((ui-2)/2) | SFCR_RBO(uiRBO) | SFCR_WBO(uiWBO) | SFCR_SPI_TCS(uiTCS));
+ LDEBUG("setFSCR:uiClkMhz=%d, uiRBO=%d, uiWBO=%d, uiTCS=%d, resMhz=%d, vale=%8x\n", uiClkMhz, uiRBO, uiWBO, uiTCS, spi_flash_info[ucChip].chip_clk, SPI_REG_READ(SFCR));
+#endif
+}
+// Calculate write address group
+void calAddr(unsigned int uiStart, unsigned int uiLenth, unsigned int uiSectorSize, unsigned int* uiStartAddr, unsigned int* uiStartLen, unsigned int* uiSectorAddr, unsigned int* uiSectorCount, unsigned int* uiEndAddr, unsigned int* uiEndLen)
+{
+ unsigned int ui;
+ // only one sector
+ if ((uiStart + uiLenth) < ((uiStart / uiSectorSize + 1) * uiSectorSize))
+ { // start
+ *uiStartAddr = uiStart;
+ *uiStartLen = uiLenth;
+ //middle
+ *uiSectorAddr = 0x00;
+ *uiSectorCount = 0x00;
+ // end
+ *uiEndAddr = 0x00;
+ *uiEndLen = 0x00;
+ }
+ //more then one sector
+ else
+ {
+ // start
+ *uiStartAddr = uiStart;
+ *uiStartLen = uiSectorSize - (uiStart % uiSectorSize);
+ if(*uiStartLen == uiSectorSize)
+ {
+ *uiStartLen = 0x00;
+ }
+ // middle
+ ui = uiLenth - *uiStartLen;
+ *uiSectorAddr = *uiStartAddr + *uiStartLen;
+ *uiSectorCount = ui / uiSectorSize;
+ //end
+ *uiEndAddr = *uiSectorAddr + (*uiSectorCount * uiSectorSize);
+ *uiEndLen = ui % uiSectorSize;
+ }
+ LDEBUG("calAddr:uiStart=%x; uiSectorSize=%x; uiLenth=%x;-> uiStartAddr=%x; uiStartLen=%x; uiSectorAddr=%x; uiSectorCount=%x; uiEndAddr=%x; uiEndLen=%x;\n",uiStart, uiSectorSize, uiLenth, *uiStartAddr, *uiStartLen, *uiSectorAddr, *uiSectorCount, *uiEndAddr, *uiEndLen);
+}
+// Calculate chip capacity shift bit
+unsigned char calShift(unsigned char ucCapacityId, unsigned char ucChipSize)
+{
+ unsigned int ui;
+ if(ucChipSize > ucCapacityId)
+ {
+ ui = ucChipSize - ucCapacityId;
+ }
+ else
+ {
+ ui = ucChipSize + 0x100 -ucCapacityId;
+ }
+ LDEBUG("calShift: ucCapacityId=%x; ucChipSize=%x; ucReturnVal=%x\n", ucCapacityId, ucChipSize, ui);
+ return (unsigned char)ui;
+}
+// Print spi_flash_type
+void prnFlashInfo(unsigned char ucChip, struct spi_flash_type sftInfo)
+{
+#if (SPI_DRIVER_MODE == 1)
+ NDEBUG(" ========================= Registed SPI Flash Model ========================= \n");
+ NDEBUG("|No chipID Sft chipSize blkSize secSize pageSize sdCk opCk chipName |\n");
+ NDEBUG("|%2d %6xh %2xh %7xh %6xh %6xh %7xh %4d %4d %17s|\n", ucChip, sftInfo.chip_id, sftInfo.size_shift, sftInfo.chip_size, sftInfo.block_size, sftInfo.sector_size, sftInfo.page_size, sftInfo.chipClock, sftInfo.chip_clk, sftInfo.chip_name);
+ ////////1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa
+ NDEBUG(" ============================================================================ \n");
+#else
+ NDEBUG(" ------------------------- Force into Single IO Mode ------------------------ \n");
+ NDEBUG("|No chipID Sft chipSize blkSize secSize pageSize sdCk opCk chipName |\n");
+ NDEBUG("|%2d %6xh %2xh %7xh %6xh %6xh %7xh %4d %4d %17s|\n", ucChip, sftInfo.chip_id, sftInfo.size_shift, sftInfo.chip_size, sftInfo.block_size, sftInfo.sector_size, sftInfo.page_size, sftInfo.chipClock, sftInfo.chip_clk, sftInfo.chip_name);
+ ////////1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa
+ NDEBUG(" ---------------------------------------------------------------------------- \n");
+#endif
+}
+
+// Check WIP bit
+unsigned int spiFlashReady(unsigned char ucChip)
+{
+ unsigned int uiCount, ui;
+ uiCount = 0;
+ while (1)
+ {
+ uiCount++;
+ ui = SeqCmd_Read(ucChip, IOWIDTH_SINGLE, SPICMD_RDSR, 1);
+ if ((ui & (1 << SPI_STATUS_WIP)) == 0)
+ {
+ break;
+ }
+ }
+ KDEBUG("spiFlashReady: uiCount=%x\n", uiCount);
+ return uiCount;
+}
+//toggle CS
+void rstSPIFlash(unsigned char ucChip)
+{
+ SFCSR_CS_L(ucChip, 0, IOWIDTH_SINGLE);
+ SFCSR_CS_H(ucChip, 0, IOWIDTH_SINGLE);
+ SFCSR_CS_L(ucChip, 0, IOWIDTH_SINGLE);
+ SFCSR_CS_H(ucChip, 0, IOWIDTH_SINGLE);
+ LDEBUG("rstFPIFlash: ucChip=%x;\n", ucChip);
+}
+
+/****************************** Layer 1 ******************************/
+// set cs high
+void SFCSR_CS_L(unsigned char ucChip, unsigned char ucLen, unsigned char ucIOWidth)
+{
+ LDEBUG("SFCSR_CS_L: ucChip=%x; uiLen=%x; ucIOWidth=%x;\n", ucChip, ucLen, ucIOWidth);
+ while((*((volatile unsigned int *)SFCSR) & (SFCSR_SPI_RDY(1))) == 0);
+ //*((volatile unsigned int *)(SFCSR)) = SFCSR_SPI_CSB(1 + (ucChip)) | SFCSR_LEN(uiLen) | SFCSR_SPI_RDY(1) | SFCSR_IO_WIDTH(ucIOWidth) | SFCSR_CHIP_SEL(0) | SFCSR_CMD_BYTE(0);
+ *((volatile unsigned int *)(SFCSR)) = SFCSR_SPI_CSB(1 + (ucChip)) | SFCSR_LEN(ucLen) | SFCSR_SPI_RDY(1) | SFCSR_IO_WIDTH(ucIOWidth);
+}
+// set cs low
+void SFCSR_CS_H(unsigned char ucChip, unsigned char ucLen, unsigned char ucIOWidth)
+{
+ LDEBUG("SFCSR_CS_H: ucChip=%x; uiLen=%x; ucIOWidth=%x;\n", ucChip, ucLen, ucIOWidth);
+ while((*((volatile unsigned int *)SFCSR) & (SFCSR_SPI_RDY(1))) == 0);
+ //*((volatile unsigned int *)(SFCSR)) = SFCSR_SPI_CSB(3) | SFCSR_LEN(uiLen) | SFCSR_SPI_RDY(1) | SFCSR_IO_WIDTH(ucIOWidth) | SFCSR_CHIP_SEL(0) | SFCSR_CMD_BYTE(0);
+ *((volatile unsigned int *)(SFCSR)) = SFCSR_SPI_CSB(3) | SFCSR_LEN(ucLen) | SFCSR_SPI_RDY(1) | SFCSR_IO_WIDTH(ucIOWidth);
+}
+// Read Identification (RDID) Sequence (Command 9F)
+unsigned int ComSrlCmd_RDID(unsigned char ucChip, unsigned int uiLen)
+{
+ unsigned int ui;
+ SPI_REG_LOAD(SFCR, (SFCR_SPI_CLK_DIV(7) | SFCR_RBO(1) | SFCR_WBO(1) | SFCR_SPI_TCS(15))); //SFCR default setting
+ rstSPIFlash(ucChip);
+ SFCSR_CS_L(ucChip, 0, IOWIDTH_SINGLE);
+ SPI_REG_LOAD(SFDR, SPICMD_RDID);
+ SFCSR_CS_L(ucChip, (uiLen - 1), IOWIDTH_SINGLE);
+ ui = SPI_REG_READ(SFDR);
+ SFCSR_CS_H(ucChip, 0, IOWIDTH_SINGLE);
+ LDEBUG("ComSrlCmd_RDID: ucChip=%x; uiLen=%x; returnValue=%x; SPICMD_RDID=%x;\n", ucChip, uiLen, ui, SPICMD_RDID);
+ return ui;
+}
+// One byte Command
+void SeqCmd_Order(unsigned char ucChip, unsigned char ucIOWidth, unsigned int uiCmd)
+{
+ LDEBUG("SeqCmd_Type1: ucChip=%x; ucIOWidth=%x; SPICMD=%x;\n", ucChip, ucIOWidth, uiCmd);
+ SFCSR_CS_L(ucChip, ucIOWidth, IOWIDTH_SINGLE);
+ SPI_REG_LOAD(SFDR, uiCmd);
+ SFCSR_CS_H(ucChip, ucIOWidth, IOWIDTH_SINGLE);
+}
+// One byte Command Write
+void SeqCmd_Write(unsigned char ucChip, unsigned char ucIOWidth, unsigned int uiCmd, unsigned int uiValue, unsigned char ucValueLen)
+{
+ SFCSR_CS_L(ucChip, DATA_LENTH1, ucIOWidth);
+ SPI_REG_LOAD(SFDR, uiCmd);
+ SFCSR_CS_L(ucChip, ucValueLen - 1, ucIOWidth);
+ SPI_REG_LOAD(SFDR, (uiValue << ((4 - ucValueLen) * 8)));
+ SFCSR_CS_H(ucChip, DATA_LENTH1, IOWIDTH_SINGLE);
+ LDEBUG("SeqCmd_Write: ucChip=%x; ucIOWidth=%x; uiCmd=%x; uiValue=%x; ucValueLen=%x;\n", ucChip, ucIOWidth, uiCmd, uiValue, ucValueLen);
+}
+// One byte Command Read
+unsigned int SeqCmd_Read(unsigned char ucChip, unsigned char ucIOWidth, unsigned int uiCmd, unsigned char ucRDLen)
+{
+ unsigned int ui;
+ SFCSR_CS_L(ucChip, DATA_LENTH1, ucIOWidth);
+ SPI_REG_LOAD(SFDR, uiCmd);
+ SFCSR_CS_L(ucChip, ucRDLen-1, ucIOWidth);
+ ui = SPI_REG_READ(SFDR);
+ SFCSR_CS_H(ucChip, DATA_LENTH1, ucIOWidth);
+ ui = ui >> ((4 - ucRDLen) * 8);
+ LDEBUG("SeqCmd_Read: ucChip=%x; ucIOWidth=%x; uiCmd=%x; ucRDLen=%x; RetVal=%x\n", ucChip, ucIOWidth, uiCmd, ucRDLen, ui);
+ return ui;
+}
+
+/****************************** Layer 2 ******************************/
+// Sector Erase (SE) Sequence (Command 20)
+unsigned int ComSrlCmd_SE(unsigned char ucChip, unsigned int uiAddr)
+{
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+ SeqCmd_Write(ucChip, IOWIDTH_SINGLE, SPICMD_SE, uiAddr, 3);
+ KDEBUG("ComSrlCmd_SE: ucChip=%x; uiSector=%x; uiSectorSize=%x; SPICMD_SE=%x\n", ucChip, uiAddr, spi_flash_info[ucChip].sector_size, SPICMD_SE);
+ return spiFlashReady(ucChip);
+}
+// Block Erase (BE) Sequence (Command D8)
+unsigned int ComSrlCmd_BE(unsigned char ucChip, unsigned int uiAddr)
+{
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+ SeqCmd_Write(ucChip, IOWIDTH_SINGLE, SPICMD_BE, uiAddr, 3);
+ KDEBUG("ComSrlCmd_BE: ucChip=%x; uiBlock=%x; uiBlockSize=%x; SPICMD_BE=%x\n", ucChip, uiAddr, spi_flash_info[ucChip].block_size, SPICMD_BE);
+ return spiFlashReady(ucChip);
+}
+// Chip Erase (CE) Sequence (Command 60 or C7)
+unsigned int ComSrlCmd_CE(unsigned char ucChip)
+{
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_CE);
+ KDEBUG("ComSrlCmd_CE: ucChip=%x; SPICMD_CE=%x\n", ucChip, SPICMD_CE);
+ return spiFlashReady(ucChip);
+}
+// without QE bit
+unsigned int ComSrlCmd_NoneQeBit(unsigned char ucChip)
+{
+ KDEBUG("ComSrlCmd_NoneQeBit: ucChip=%x;\n", ucChip);
+ return 0;
+}
+// ucIsFast: = 0 cmd, address, dummy single IO ; =1 cmd single IO, address and dummy multi IO; =2 cmd, address and dummy multi IO;
+void ComSrlCmd_InputCommand(unsigned char ucChip, unsigned int uiAddr, unsigned int uiCmd, unsigned char ucIsFast, unsigned char ucIOWidth, unsigned char ucDummyCount)
+{
+ int i;
+ LDEBUG("ComSrlCmd_InputCommand: ucChip=%x; uiAddr=%x; uiCmd=%x; uiIsfast=%x; ucIOWidth=%x; ucDummyCount=%x\n", ucChip, uiAddr, uiCmd, ucIsFast, ucIOWidth, ucDummyCount);
+
+ // input command
+ if(ucIsFast == ISFAST_ALL)
+ {
+ SFCSR_CS_L(ucChip, 0, ucIOWidth);
+ }
+ else
+ {
+ SFCSR_CS_L(ucChip, 0, IOWIDTH_SINGLE);
+ }
+ SPI_REG_LOAD(SFDR, uiCmd); // Read Command
+
+ // input 3 bytes address
+ if(ucIsFast == ISFAST_NO)
+ {
+ SFCSR_CS_L(ucChip, 0, IOWIDTH_SINGLE);
+ }
+ else
+ {
+ SFCSR_CS_L(ucChip, 0, ucIOWidth);
+ }
+ SPI_REG_LOAD(SFDR,(uiAddr << 8));
+ SPI_REG_LOAD(SFDR,(uiAddr << 16));
+ SPI_REG_LOAD(SFDR,(uiAddr << 24));
+
+ //input dummy cycle
+ for (i = 0; i < ucDummyCount; i++)
+ {
+ SPI_REG_LOAD(SFDR, 0);
+ }
+
+ SFCSR_CS_L(ucChip, 3, ucIOWidth);
+}
+
+// Set SFCR2 for memery map read
+unsigned int SetSFCR2(unsigned int uiCmd, unsigned char ucIsFast, unsigned char ucIOWidth, unsigned char ucDummyCount)
+{
+ unsigned int ui, uiDy;
+ ucSFCR2 = 0;
+ ui = SFCR2_SFCMD(uiCmd) | SFCR2_SFSIZE(spi_flash_info[0].device_size - 17) | SFCR2_RD_OPT(0) | SFCR2_HOLD_TILL_SFDR2(0);
+ switch (ucIsFast)
+ {
+ case ISFAST_NO:
+ {
+ ui = ui | SFCR2_CMD_IO(IOWIDTH_SINGLE) | SFCR2_ADDR_IO(IOWIDTH_SINGLE) | SFCR2_DATA_IO(ucIOWidth);
+ uiDy = 1;
+ break;
+ }
+ case ISFAST_YES:
+ {
+ ui = ui | SFCR2_CMD_IO(IOWIDTH_SINGLE) | SFCR2_ADDR_IO(ucIOWidth) | SFCR2_DATA_IO(ucIOWidth);
+ uiDy = ucIOWidth * 2;
+ break;
+ }
+ case ISFAST_ALL:
+ {
+ ui = ui | SFCR2_CMD_IO(ucIOWidth) | SFCR2_ADDR_IO(ucIOWidth) | SFCR2_DATA_IO(ucIOWidth);
+ uiDy = ucIOWidth * 2;
+ break;
+ }
+ default:
+ {
+ ui = ui | SFCR2_CMD_IO(IOWIDTH_SINGLE) | SFCR2_ADDR_IO(IOWIDTH_SINGLE) | SFCR2_DATA_IO(ucIOWidth);
+ uiDy = 1;
+ break;
+ }
+ }
+ if (uiDy == 0)
+ {
+ uiDy = 1;
+ }
+ ui = ui | SFCR2_DUMMY_CYCLE((ucDummyCount * 4 / uiDy)); // ucDummyCount is Byte Count ucDummyCount*8 / (uiDy*2)
+ SPI_REG_LOAD(SFCR2, ui);
+ LDEBUG("SetSFCR2: uiCmd=%x; ucIsFast=%; ucIOWidth=%x; ucDummyCount=%x; ucSFCR2=%x; SFCR2=%x\n;", uiCmd, ucIsFast, ucIOWidth, ucDummyCount, ucSFCR2, ui);
+ return ui;
+}
+
+// read template
+unsigned int ComSrlCmd_ComRead(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer,unsigned int uiCmd, unsigned char ucIsFast, unsigned char ucIOWidth, unsigned char ucDummyCount)
+{
+
+ unsigned int ui, uiCount, i;
+ unsigned char* puc = pucBuffer;
+ LDEBUG("ComSrlCmd_ComRead: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; uiCmd=%x; uiIsfast=%x; ucIOWidth=%x; ucDummyCount=%x\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, uiCmd, ucIsFast, ucIOWidth, ucDummyCount);
+ ComSrlCmd_InputCommand(ucChip, uiAddr, uiCmd, ucIsFast, ucIOWidth, ucDummyCount);
+ if(ucSFCR2 != 0) // set SFCR2
+ {
+ ui = SetSFCR2((uiCmd >> 24), ucIsFast, ucIOWidth, ucDummyCount);
+ }
+
+ uiCount = uiLen / 4;
+ for( i = 0; i< uiCount; i++) // Read 4 bytes every time.
+ {
+ ui = SPI_REG_READ(SFDR);
+ memcpy(puc, &ui, 4);
+ puc += 4;
+ }
+
+ i = uiLen % 4;
+ if(i > 0)
+ {
+ ui = SPI_REG_READ(SFDR); // another bytes.
+ memcpy(puc, &ui, i);
+ puc += i;
+ }
+ SFCSR_CS_H(ucChip, 0, IOWIDTH_SINGLE);
+ return uiLen;
+
+}
+
+// write template
+unsigned int ComSrlCmd_ComWrite(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer, unsigned int uiCmd, unsigned char ucIsFast, unsigned char ucIOWidth, unsigned char ucDummyCount)
+{
+ unsigned int ui, uiCount, i;
+ unsigned char* puc = pucBuffer;
+ LDEBUG("ComSrlCmd_ComWrite: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; uiCmd=%x; uiIsfast=%x; ucIOWidth=%x; ucDummyCount=%x\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, uiCmd, ucIsFast, ucIOWidth, ucDummyCount);
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+
+ ComSrlCmd_InputCommand(ucChip, uiAddr, uiCmd, ucIsFast, ucIOWidth, ucDummyCount);
+
+ uiCount = uiLen / 4;
+ for (i = 0; i < uiCount; i++)
+ {
+ memcpy(&ui, puc, 4);
+ puc += 4;
+ SPI_REG_LOAD(SFDR, ui);
+ }
+
+ i = uiLen % 4;
+ if(i > 0)
+ {
+ memcpy(&ui, puc, i);
+ puc += i;
+ SFCSR_CS_L(ucChip, i-1, ucIOWidth);
+ SPI_REG_LOAD(SFDR, ui);
+ }
+ SFCSR_CS_H(ucChip, 0, IOWIDTH_SINGLE);
+ ui = spiFlashReady(ucChip);
+ return uiLen;
+}
+
+// write a whole sector once
+unsigned int ComSrlCmd_ComWriteSector(unsigned char ucChip, unsigned int uiAddr, unsigned char* pucBuffer)
+{
+ unsigned int i, ui;
+ unsigned char* puc = pucBuffer;
+ LDEBUG("ComSrlCmd_ComWriteSector: ucChip=%x; uiAddr=%x; pucBuffer=%x; returnValue=%x;\n", ucChip, uiAddr, (unsigned int)pucBuffer, spi_flash_info[ucChip].sector_size);
+ //prnDispAddr(uiAddr);
+ NDEBUG(".");
+ ui = spi_flash_info[ucChip].pfErase(ucChip, uiAddr);
+ for (i = 0; i < spi_flash_info[ucChip].page_cnt; i++)
+ {
+ ui = spi_flash_info[ucChip].pfPageWrite(ucChip, uiAddr, spi_flash_info[ucChip].page_size, puc);
+ uiAddr += spi_flash_info[ucChip].page_size;
+ puc += spi_flash_info[ucChip].page_size;
+ }
+ return spi_flash_info[ucChip].sector_size;
+}
+
+// write sector use malloc buffer
+unsigned int ComSrlCmd_BufWriteSector(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ unsigned char pucSector[spi_flash_info[ucChip].sector_size];
+ unsigned int ui, uiStartAddr, uiOffset;
+ LDEBUG("ComSrlCmd_BufWriteSector:ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x;\n", ucChip, uiAddr, uiLen, pucBuffer);
+ uiOffset = uiAddr % spi_flash_info[ucChip].sector_size;
+ uiStartAddr = uiAddr - uiOffset;
+ // get
+ ui = spi_flash_info[ucChip].pfRead(ucChip, uiStartAddr, spi_flash_info[ucChip].sector_size, pucSector);
+ // modify
+ memcpy(pucSector + uiOffset, pucBuffer, uiLen);
+ //write back
+ ui = ComSrlCmd_ComWriteSector(ucChip, uiStartAddr, pucSector);
+ return ui;
+}
+
+// write data, any address any lenth
+unsigned int ComSrlCmd_ComWriteData(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ unsigned int uiStartAddr, uiStartLen, uiSectorAddr, uiSectorCount, uiEndAddr, uiEndLen, i;
+ unsigned char* puc = pucBuffer;
+ LDEBUG("ComSrlCmd_ComWriteData:ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer);
+ calAddr(uiAddr, uiLen, spi_flash_info[ucChip].sector_size, &uiStartAddr, &uiStartLen, &uiSectorAddr, &uiSectorCount, &uiEndAddr, &uiEndLen);
+ if((uiSectorCount == 0x00) && (uiEndLen == 0x00)) // all data in the same sector
+ {
+ ComSrlCmd_BufWriteSector(ucChip, uiStartAddr, uiStartLen, puc);
+ }
+ else
+ {
+ if(uiStartLen > 0)
+ {
+ ComSrlCmd_BufWriteSector(ucChip, uiStartAddr, uiStartLen, puc);
+ puc += uiStartLen;
+ }
+ for(i = 0; i < uiSectorCount; i++)
+ {
+ ComSrlCmd_ComWriteSector(ucChip, uiSectorAddr, puc);
+ puc += spi_flash_info[ucChip].sector_size;
+ uiSectorAddr += spi_flash_info[ucChip].sector_size;
+ }
+ if(uiEndLen > 0)
+ {
+ ComSrlCmd_BufWriteSector(ucChip, uiEndAddr, uiEndLen, puc);
+ }
+ }
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WRDI);
+ return uiLen;
+}
+
+/****************************** Macronix ******************************/
+// MX25L1605 MX25L3205 Read at High Speed (FAST_READ) Sequence (Command 0B)
+unsigned int SpiRead_11110B(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ KDEBUG(" SpiRead_11110B: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; SPICMD_FASTREAD=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, SPICMD_FASTREAD);
+ return ComSrlCmd_ComRead(ucChip, uiAddr, uiLen, pucBuffer, SPICMD_FASTREAD, ISFAST_NO, IOWIDTH_SINGLE, DUMMYCOUNT_1);
+}
+// Page Program (PP) Sequence (Command 02)
+unsigned int PageWrite_111002(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ KDEBUG(" PageWrite_111002: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; SPICMD_PP=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, SPICMD_PP);
+ return ComSrlCmd_ComWrite(ucChip, uiAddr, uiLen, pucBuffer, SPICMD_PP, ISFAST_NO, IOWIDTH_SINGLE, DUMMYCOUNT_0);
+}
+#if (SPI_DRIVER_MODE == 1)
+// Set quad enable bit
+unsigned int mxic_spi_setQEBit(unsigned char ucChip)
+{
+ unsigned int ui;
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+ ui = 1 << SPI_STATUS_QE;
+ SeqCmd_Write(ucChip, IOWIDTH_SINGLE, SPICMD_WRSR, ui, 1);
+ KDEBUG("MxicSetQEBit: ucChip=%d; statusRegister=%x; returnValue=%x\n", ucChip, SeqCmd_Read(ucChip, IOWIDTH_SINGLE, SPICMD_RDSR, 1), ui);
+ return ui;
+}
+// MX25L1605 MX25L3205 Read at Dual IO Mode Sequence (Command BB)
+unsigned int SpiRead_1221BB(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ KDEBUG(" SpiRead_1221BB: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; SPICMD_2READ=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, SPICMD_2READ);
+ return ComSrlCmd_ComRead(ucChip, uiAddr, uiLen, pucBuffer, SPICMD_2READ, ISFAST_YES, IOWIDTH_DUAL, DUMMYCOUNT_1);
+}
+// MX25L1635 MX25L3235 4 x I/O Read Mode Sequence (Command EB)
+unsigned int SpiRead_1443EB(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ KDEBUG(" SpiRead_1443EB: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; SPICMD_4READ=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, SPICMD_4READ);
+ return ComSrlCmd_ComRead(ucChip, uiAddr, uiLen, pucBuffer, SPICMD_4READ, ISFAST_YES, IOWIDTH_QUAD, DUMMYCOUNT_3);
+}
+// 4 x I/O Page Program (4PP) Sequence (Command 38)
+unsigned int PageWrite_144038(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ KDEBUG(" PageWrite_144038: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; SPICMD_4PP=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, SPICMD_4PP);
+ return ComSrlCmd_ComWrite(ucChip, uiAddr, uiLen, pucBuffer, SPICMD_4PP, ISFAST_YES, IOWIDTH_QUAD, DUMMYCOUNT_0);
+}
+#endif
+
+/****************************** SST ******************************/
+// Layer1 SST Byte-Program
+void SstComSrlCmd_BP(unsigned char ucChip, unsigned int uiAddr, unsigned char ucValue)
+{
+ unsigned int ui;
+ ui = SPICMD_PP | (uiAddr & 0x00ffffff);
+ SFCSR_CS_L(ucChip, 3, 0);
+ SPI_REG_LOAD(SFDR, ui);
+ SFCSR_CS_L(ucChip, 0, IOWIDTH_SINGLE);
+ SPI_REG_LOAD(SFDR, (ucValue<< 24));
+ SFCSR_CS_H(ucChip, 0, IOWIDTH_SINGLE);
+ LDEBUG("SstComSrlCmd_BP: ucChip=%x; uiAddr=%x; ucValue=%x; SPICMD_SST_BP=%x;\n", ucChip, uiAddr, ucValue, SPICMD_PP);
+}
+// Layer2 Sector Write Use BP Mode
+unsigned int sst_PageWrite_s1(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ unsigned int i, ui;
+ unsigned char* puc = pucBuffer;
+ KDEBUG("sst_cmd_write_s1: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; returnValue=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, uiLen);
+ for (i = 0; i < uiLen; i++)
+ {
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+ SstComSrlCmd_BP(ucChip, uiAddr, *puc);
+ ui = spiFlashReady(ucChip);
+ puc += 1;
+ uiAddr = uiAddr + 1;
+ }
+ return uiLen;
+}
+
+/****************************** Spansion ******************************/
+// Layer2 Spansion Set QE bit
+#if (SPI_DRIVER_MODE == 1)
+unsigned int span_spi_setQEBit(unsigned char ucChip)
+{
+ unsigned int ui;
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+ ui = 1 << SPAN_CONF_QUAD;
+ SeqCmd_Write(ucChip, IOWIDTH_SINGLE, SPICMD_WRSR, ui, 2);
+ KDEBUG("SpanSetQEBit: ucChip=%d; statusRegister=%x; returnValue=%x\n", ucChip, SeqCmd_Read(ucChip, IOWIDTH_SINGLE, SPICMD_RDSR, 2), ui);
+ return spiFlashReady(ucChip);
+}
+#endif
+
+/****************************** Winbond ******************************/
+// Layer3 Winbond Set QE Bit
+#if (SPI_DRIVER_MODE == 1)
+unsigned int wb_spi_setQEBit(unsigned char ucChip)
+{
+ unsigned int ui;
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+ ui = 1 << (WB_STATUS_QE - 8);
+ SeqCmd_Write(ucChip, IOWIDTH_SINGLE, SPICMD_WRSR, ui, 2);
+ KDEBUG("WBSetQEBit: ucChip=%d; statusRegister=%x; returnValue=%x\n", ucChip, SeqCmd_Read(ucChip, IOWIDTH_SINGLE, SPICMD_RDSR, 1), ui);
+ return spiFlashReady(ucChip);
+}
+// Quad Program Page Program (Command 32)
+unsigned int PageWrite_114032(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ KDEBUG("PageWrite_114032: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; SPICMD_WB_QPP=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, SPICMD_WB_QPP);
+ return ComSrlCmd_ComWrite(ucChip, uiAddr, uiLen, pucBuffer, SPICMD_WB_QPP, ISFAST_NO, IOWIDTH_QUAD, DUMMYCOUNT_0);
+}
+#endif
+
+/****************************** Giga Device ******************************/
+// Set quad enable bit
+#if (SPI_DRIVER_MODE == 1)
+unsigned int gd_spi_setQEBit(unsigned char ucChip)
+{
+ unsigned int ui;
+ SeqCmd_Order(ucChip, IOWIDTH_SINGLE, SPICMD_WREN);
+ ui = 1 << (GD_STATUS_QE - 8);
+ SeqCmd_Write(ucChip, IOWIDTH_SINGLE, SPICMD_WRSR, ui, 2); // set Giga Devcie QE bit
+ KDEBUG("gd_spi_setQEBit: ucChip=%d; statusRegister=%x; returnValue=%x\n", ucChip, SeqCmd_Read(ucChip, IOWIDTH_SINGLE, SPICMD_RDSR, 2));
+ GdCmdSrl_HPM(ucChip);
+ return ui;
+}
+// High Performance Mode (HPM) (A3H)
+unsigned int GdCmdSrl_HPM(unsigned char ucChip)
+{
+ SeqCmd_Write(ucChip, IOWIDTH_SINGLE, SPICMD_GD_HPM, 0x00, 3); // command add 3 dummy
+ KDEBUG("GdCmdSrl_HPM: ucChip=%d; SPICMD_GD_HPM=%x; \n", ucChip, SPICMD_GD_HPM);
+ return spiFlashReady(ucChip);
+}
+#endif
+
+/****************************** ATMEL ******************************/
+// AT25DF161 Dual-Output Read Array(Command 3B)
+#if (SPI_DRIVER_MODE == 1)
+unsigned int SpiRead_11213B(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ KDEBUG("SpiRead_11213B: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; SPICMD_AT_READ2=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, SPICMD_AT_READ2);
+ return ComSrlCmd_ComRead(ucChip, uiAddr, uiLen, pucBuffer, SPICMD_AT_READ2, ISFAST_NO, IOWIDTH_DUAL, DUMMYCOUNT_1);
+}
+// AT25DF161 Dual-Input Byte/Page Program(Command A2)
+unsigned int PageWrite_1120A2(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer)
+{
+ KDEBUG("PageWrite_1120A2: ucChip=%x; uiAddr=%x; uiLen=%x; pucBuffer=%x; SPICMD_AT_PP2=%x;\n", ucChip, uiAddr, uiLen, (unsigned int)pucBuffer, SPICMD_AT_PP2);
+ return ComSrlCmd_ComWrite(ucChip, uiAddr, uiLen, pucBuffer, SPICMD_AT_PP2, ISFAST_NO, IOWIDTH_DUAL, DUMMYCOUNT_0);
+}
+#endif
+
+#if (MTD_SPI_TEST_CHIP == 1)
+unsigned int test_spi_flash(unsigned char ucChip)
+{
+ unsigned char pucSrc[0x100] = {0};
+ unsigned char pucDst[0x100] = {0};
+ unsigned int uiOffset = 0x10000;
+ unsigned int uiAddr = 0x10000;
+ unsigned int uiCount = spi_flash_info[ucChip].sector_cnt - (uiOffset) / spi_flash_info[ucChip].sector_size;
+ unsigned int uiRet = 0;
+ unsigned int uiLine = 0;
+ unsigned int uiStep = 0;
+ int i = 0, j = 0;
+ if(uiCount > 0x1f0)
+ {
+ uiStep = uiCount / 0x1f0;
+ }
+ else
+ {
+ uiStep = 1;
+ }
+ for (i = 0; i< 0x100; i++) pucSrc[i] = i;
+ NDEBUG("\nTest SPI flash: offset->0x%x, step->0x%x\n", (uiOffset - 0x80), (spi_flash_info[ucChip].sector_size * uiStep));
+ uiCount = 1; // Delete
+ for (j = 0; j < uiCount; j += uiStep)
+ {
+ uiAddr = uiOffset + j * spi_flash_info[ucChip].sector_size - 0x80;
+ spi_flash_info[ucChip].pfWrite(ucChip, uiAddr, 0x100, pucSrc);
+ memset(pucDst, 0, 0x100);
+ spi_flash_info[ucChip].pfRead(ucChip, uiAddr, 0x100, pucDst);
+ for( i = 0; i < 0x100; i++)
+ {
+ if(pucDst[i] != pucSrc[i])
+ {
+ NDEBUG("%07x-ER", uiAddr);
+ uiRet += 1;
+ break;
+ }
+ }
+ if(i == 0x100) NDEBUG("%07x-OK", uiAddr);
+ uiLine++;
+ if(uiLine == 6)
+ {
+ NDEBUG("\n");
+ uiLine = 0;
+ }
+ }
+ NDEBUG("\nTotal Count = 0x%x; OK Count = 0x%x; Error Count = 0x%x\n", uiCount, (uiCount - uiRet), uiRet);
+ return uiRet;
+}
+#endif
diff --git a/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_common.h b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_common.h
new file mode 100644
index 000000000..c1fa7df66
--- /dev/null
+++ b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_common.h
@@ -0,0 +1,203 @@
+/* SPI Flash driver
+ *
+ * Written by sam (sam@realtek.com)
+ * 2010-05-01
+ *
+ */
+
+#include "../../../../include/linux/autoconf.h"
+
+#if defined(CONFIG_RTL_8198)
+ #define CONFIG_RTL8198 1
+#endif
+
+//#define CONFIG_SPI_STD_MODE 1
+//#define SPI_KERNEL 1
+#ifdef SPI_KERNEL
+ #ifdef CONFIG_RTL8198
+ #define SPI_DRIVER_MODE 0
+ #elif defined(CONFIG_RTL_8196CS)
+ #define SPI_DRIVER_MODE 0
+ #else
+ #define SPI_DRIVER_MODE 1
+ #endif
+#else
+ #ifdef CONFIG_RTL8198
+ #define SPI_DRIVER_MODE 0
+ #else
+ #ifdef CONFIG_SPI_STD_MODE
+ #define SPI_DRIVER_MODE 0
+ #else
+ #define SPI_DRIVER_MODE 1
+ #endif
+ #endif
+#endif
+
+typedef unsigned int (*FUNC_ERASE)(unsigned char ucChip, unsigned int uiAddr);
+typedef unsigned int (*FUNC_READ)(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+typedef unsigned int (*FUNC_WRITE)(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+typedef unsigned int (*FUNC_SETQEBIT)(unsigned char ucChip);
+typedef unsigned int (*FUNC_PAGEWRITE)(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+
+struct spi_flash_type
+{
+ unsigned int chip_id;
+ unsigned char mfr_id;
+ unsigned char dev_id;
+
+ unsigned char capacity_id;
+ unsigned char size_shift;
+
+ unsigned char device_size; // 2 ^ N (bytes)
+ unsigned int chip_size;
+
+ unsigned int block_size;
+ unsigned int block_cnt;
+
+ unsigned int sector_size;
+ unsigned int sector_cnt;
+
+ unsigned int page_size;
+ unsigned int page_cnt;
+ unsigned int chip_clk;
+ char* chip_name;
+
+ unsigned int chipClock;
+ FUNC_ERASE pfErase;
+ FUNC_WRITE pfWrite;
+ FUNC_READ pfRead;
+ FUNC_SETQEBIT pfQeBit;
+ FUNC_PAGEWRITE pfPageWrite;
+};
+
+struct spi_flash_known
+{
+ unsigned int uiChipId;
+ unsigned int uiDistinguish;
+ unsigned int uiCapacityId;
+ unsigned int uiBlockSize;
+ unsigned int uiSectorSize;
+ unsigned int uiPageSize;
+ char* pcChipName;
+ unsigned int chipClock;
+
+ FUNC_ERASE pfErase;
+ FUNC_READ pfRead;
+ FUNC_SETQEBIT pfQeBit;
+ FUNC_PAGEWRITE pfPageWrite;
+};
+
+
+/****************************** Common0 ******************************/
+void spi_regist(unsigned char ucChip);
+void set_flash_info(unsigned char ucChip, unsigned int chip_id, unsigned int device_cap, unsigned int block_size, unsigned int sector_size, unsigned int page_size, char* chip_name, FUNC_ERASE pfErase, FUNC_READ pfRead, FUNC_SETQEBIT pfQeBit, FUNC_PAGEWRITE pfPageWrite, unsigned int chipClock);
+
+/****************************** Common ******************************/
+// get Dram Frequence
+unsigned int CheckDramFreq(void); //JSW:For 8196C
+// Set FSCR register
+void setFSCR(unsigned char ucChip, unsigned int uiClkMhz, unsigned int uiRBO, unsigned int uiWBO, unsigned int uiTCS);
+// Calculate write address group
+void calAddr(unsigned int uiStart, unsigned int uiLenth, unsigned int uiSectorSize, unsigned int* uiStartAddr, unsigned int* uiStartLen, unsigned int* uiSectorAddr, unsigned int* uiSectorCount, unsigned int* uiEndAddr, unsigned int* uiEndLen);
+// Calculate chip capacity shift bit
+unsigned char calShift(unsigned char ucCapacityId, unsigned char ucChipSize);
+// Print spi_flash_type
+void prnFlashInfo(unsigned char ucChip, struct spi_flash_type sftInfo);
+// Check WIP bit
+unsigned int spiFlashReady(unsigned char ucChip);
+//toggle CS
+void rstSPIFlash(unsigned char ucChip);
+
+/****************************** Layer 1 ******************************/
+//set cs low
+void SFCSR_CS_L(unsigned char ucChip, unsigned char ucLen, unsigned char ucIOWidth);
+// set cs high
+void SFCSR_CS_H(unsigned char ucChip, unsigned char ucLen, unsigned char ucIOWidth);
+// Read Identification (RDID) Sequence (Command 9F)
+unsigned int ComSrlCmd_RDID(unsigned char ucChip, unsigned int uiLen);
+// One byte Command
+void SeqCmd_Order(unsigned char ucChip, unsigned char ucIOWidth, unsigned int uiCmd);
+// One byte Command Write
+void SeqCmd_Write(unsigned char ucChip, unsigned char ucIOWidth, unsigned int uiCmd, unsigned int uiValue, unsigned char ucValueLen);
+// One byte Command Read
+unsigned int SeqCmd_Read(unsigned char ucChip, unsigned char ucIOWidth, unsigned int uiCmd, unsigned char ucRDLen);
+
+/****************************** Layer 2 ******************************/
+// Sector Erase (SE) Sequence (Command 20)
+unsigned int ComSrlCmd_SE(unsigned char ucChip, unsigned int uiAddr);
+// Block Erase (BE) Sequence (Command D8)
+unsigned int ComSrlCmd_BE(unsigned char ucChip, unsigned int uiAddr);
+// Chip Erase (CE) Sequence (Command 60 or C7)
+unsigned int ComSrlCmd_CE(unsigned char ucChip);
+// without QE bit
+unsigned int ComSrlCmd_NoneQeBit(unsigned char ucChip);
+// uiIsFast: = 0 cmd, address, dummy single IO ; =1 cmd single IO, address and dummy multi IO; =2 cmd, address and dummy multi IO;
+void ComSrlCmd_InputCommand(unsigned char ucChip, unsigned int uiAddr, unsigned int uiCmd, unsigned char ucIsFast, unsigned char ucIOWidth, unsigned char ucDummyCount);
+// Set SFCR2 for memery map read
+unsigned int SetSFCR2(unsigned int uiCmd, unsigned char ucIsFast, unsigned char ucIOWidth, unsigned char ucDummyCount);
+// read function template
+unsigned int ComSrlCmd_ComRead(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer,unsigned int uiCmd, unsigned char ucIsFast, unsigned char ucIOWidth, unsigned char ucDummyCount);
+// write template
+unsigned int ComSrlCmd_ComWrite(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer, unsigned int uiCmd, unsigned char ucIsFast, unsigned char ucIOWidth, unsigned char ucDummyCount);
+// write a sector once
+unsigned int ComSrlCmd_ComWriteSector(unsigned char ucChip, unsigned int uiAddr, unsigned char* pucBuffer);
+// write sector use malloc buffer
+unsigned int ComSrlCmd_BufWriteSector(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+// write function
+unsigned int ComSrlCmd_ComWriteData(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+
+/****************************** Macronix ******************************/
+// MX25L1605 MX25L3205 Read at High Speed (FAST_READ) Sequence (Command 0B)
+unsigned int SpiRead_11110B(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+// Page Program (PP) Sequence (Command 02)
+unsigned int PageWrite_111002(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+
+#if (SPI_DRIVER_MODE == 1)
+// Set quad enable bit
+unsigned int mxic_spi_setQEBit(unsigned char ucChip);
+// MX25L1605 MX25L3205 Read at Dual IO Mode Sequence (Command BB)
+unsigned int SpiRead_1221BB(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+// MX25L1635 MX25L3235 4 x I/O Read Mode Sequence (Command EB)
+unsigned int SpiRead_1443EB(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+// 4 x I/O Page Program (4PP) Sequence (Command 38)
+unsigned int PageWrite_144038(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+#endif
+
+/****************************** SST ******************************/
+// Layer1 SST Byte-Program
+void SstComSrlCmd_BP(unsigned char ucChip, unsigned int uiAddr, unsigned char ucValue);
+// Layer2 Sector Write Use BP Mode
+unsigned int sst_PageWrite_s1(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+
+/****************************** Spansion ******************************/
+#if (SPI_DRIVER_MODE == 1)
+// Layer2 Spansion Set QE bit
+unsigned int span_spi_setQEBit(unsigned char ucChip);
+// Quad Page Programming (Command 32)
+unsigned int PageWrite_114032(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+#endif
+
+/****************************** Winbond ******************************/
+#if (SPI_DRIVER_MODE == 1)
+// Layer3 Winbond Set QE Bit
+unsigned int wb_spi_setQEBit(unsigned char ucChip);
+#endif
+
+/****************************** Eon ******************************/
+
+
+/****************************** Giga Device ******************************/
+#if (SPI_DRIVER_MODE == 1)
+// Set quad enable bit
+unsigned int gd_spi_setQEBit(unsigned char ucChip);
+// High Performance Mode (HPM) (A3H)
+unsigned int GdCmdSrl_HPM(unsigned char ucChip);
+#endif
+
+/****************************** ATMEL ******************************/
+#if (SPI_DRIVER_MODE == 1)
+// AT25DF161 Dual-Output Read Array(Command 3B)
+unsigned int SpiRead_11213B(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+// AT25DF161 Dual-Input Byte/Page Program(Command A2)
+unsigned int PageWrite_1120A2(unsigned char ucChip, unsigned int uiAddr, unsigned int uiLen, unsigned char* pucBuffer);
+#endif
diff --git a/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.c b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.c
new file mode 100644
index 000000000..6f21f791c
--- /dev/null
+++ b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.c
@@ -0,0 +1,146 @@
+#include <linux/config.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/gen_probe.h>
+#include <linux/spinlock.h>
+
+#include "spi_flash.h"
+#include "spi_common.h"
+
+#define MTD_SPI_DEBUG 0
+#if (MTD_SPI_DEBUG)
+#define KDEBUG(args...) printk(args)
+#else
+#define KDEBUG(args...)
+#endif
+
+struct spi_chip_mtd spi_probe_mtd;
+extern struct spi_flash_type spi_flash_info[2];
+
+// uiAddr = from; pucBuffer = to; uiLen = size
+static unsigned int do_spi_read(unsigned int from, unsigned int to, unsigned int size, unsigned int uiChip)
+{
+ unsigned int uiRet;
+ uiRet = spi_flash_info[uiChip].pfRead(uiChip, from, size, (unsigned char*)to);
+ KDEBUG("do_spi_read: from=%x; to=%x; size=%x; uiRet=%x\n", from, to, size, uiRet);
+ return 0;
+}
+/*
+// uiAddr = to; pucBuffer = from; uiLen = size
+static unsigned int do_spi_write(unsigned int from, unsigned int to, unsigned int size)
+{
+ unsigned int uiRet;
+ uiRet = spi_flash_info[0].pfWrite(0, to, size, (unsigned char*)from);
+ KDEBUG("do_spi_write: from=%x; to=%x; size=%x; uiRet=%x\n", from, to, size, uiRet);
+ return 0;
+}
+*/
+// uiAddr = to; pucBuffer = from; uiLen = size (stupid!!!)
+static unsigned int do_spi_write(unsigned int from, unsigned int to, unsigned int size, unsigned int uiChip)
+{
+ unsigned int uiStartAddr, uiStartLen, uiPageAddr, uiPageCount, uiEndAddr, uiEndLen, i, uiRet;
+ unsigned char* puc = (unsigned char*)from;
+ KDEBUG("do_spi_write:from=%x; to=%x; size=%x;\n", from, to, size);
+ calAddr(to, size, spi_flash_info[uiChip].page_size, &uiStartAddr, &uiStartLen, &uiPageAddr, &uiPageCount, &uiEndAddr, &uiEndLen);
+ if((uiPageCount == 0x00) && (uiEndLen == 0x00)) // all data in the same page
+ {
+ uiRet = spi_flash_info[uiChip].pfPageWrite(uiChip, uiStartAddr, uiStartLen, puc);
+ }
+ else
+ {
+ if(uiStartLen > 0)
+ {
+ uiRet = spi_flash_info[uiChip].pfPageWrite(uiChip, uiStartAddr, uiStartLen, puc);
+ puc += uiStartLen;
+ }
+ for(i = 0; i < uiPageCount; i++)
+ {
+ uiRet = spi_flash_info[uiChip].pfPageWrite(uiChip, uiPageAddr, spi_flash_info[uiChip].page_size, puc);
+ puc += spi_flash_info[uiChip].page_size;
+ uiPageAddr += spi_flash_info[uiChip].page_size;
+ }
+ if(uiEndLen > 0)
+ {
+ uiRet = spi_flash_info[uiChip].pfPageWrite(uiChip, uiEndAddr, uiEndLen, puc);
+ }
+ }
+ //ComSrlCmd_WRDI(0);
+ return 0;
+}
+// uiAddr = addr
+static int do_spi_erase(unsigned int addr, unsigned int uiChip)
+{
+ unsigned int uiRet;
+ uiRet = spi_flash_info[uiChip].pfErase(uiChip, addr);
+ KDEBUG("do_spi_erase: addr=%x;\n", addr);
+ return 0;
+}
+// SPI flash destroy
+static void spi_suzaku_destroy(struct spi_chip_info *chip_info)
+{
+ KDEBUG("spi_suzaku_destroy:\n");
+ return;
+}
+
+// SPI flash probe
+int spi_cp_probe(unsigned int uiChip)
+{
+ spi_regist(uiChip);
+
+ spi_probe_mtd.chip_id = spi_flash_info[uiChip].chip_id;
+ spi_probe_mtd.extra_id = spi_flash_info[uiChip].dev_id;
+ spi_probe_mtd.sectorSize = spi_flash_info[uiChip].sector_size;
+ spi_probe_mtd.deviceSize = spi_flash_info[uiChip].chip_size;
+ spi_probe_mtd.uiClkMhz = 0;
+ spi_probe_mtd.name = spi_flash_info[uiChip].chip_name;
+
+ KDEBUG("spi_cp_probe:uiChip=%x\n", uiChip);
+ return 0;
+}
+
+// malloc mtd
+static struct spi_chip_info *spi_suzaku_setup(struct map_info *map)
+{
+ struct spi_chip_info *chip_info;
+ chip_info = kmalloc(sizeof(*chip_info), GFP_KERNEL);
+ if (!chip_info)
+ {
+ printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
+ return NULL;
+ }
+ memset(chip_info, 0, sizeof(struct spi_chip_info));
+ KDEBUG("spi_suzaku_setup\n");
+ return chip_info;
+}
+
+
+struct spi_chip_info *spi_probe_flash_chip(struct map_info *map, struct chip_probe *cp)
+{
+ struct spi_chip_info *chip_info = NULL;
+ unsigned int chip_select=0; // 0 or 1
+
+ if (!strcmp(cp->name,"SPI2"))
+ chip_select=1;
+
+ spi_cp_probe(chip_select);
+ chip_info = spi_suzaku_setup(map);
+ KDEBUG("spi_probe_flash_chip\n");
+ if (chip_info)
+ {
+ chip_info->name = cp->name;
+ chip_info->chip_select = chip_select;
+ chip_info->flash = &spi_probe_mtd;
+ chip_info->destroy = spi_suzaku_destroy;
+ chip_info->read = do_spi_read;
+ chip_info->write = do_spi_write;
+ chip_info->erase = do_spi_erase;
+ return chip_info;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+EXPORT_SYMBOL(spi_probe_flash_chip);
+
+
diff --git a/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.h b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.h
new file mode 100644
index 000000000..3681a6531
--- /dev/null
+++ b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.h
@@ -0,0 +1,29 @@
+#ifndef _MTD_SPI_PROBE_H_
+#define _MTD_SPI_PROBE_H_
+
+struct spi_chip_mtd
+{
+ unsigned int chip_id;
+ unsigned int extra_id;
+ unsigned int sectorSize;
+ unsigned int deviceSize;
+ unsigned int uiClkMhz;
+ char* name;
+};
+
+struct spi_chip_info
+{
+ char* name;
+ unsigned int chip_select;
+ struct spi_chip_mtd *flash;
+
+ void (*destroy)(struct spi_chip_info *chip_info);
+
+ unsigned int (*read)(unsigned int from, unsigned int to, unsigned int size, unsigned int uiChip);
+ unsigned int (*write)(unsigned int from, unsigned int to, unsigned int size, unsigned int uiChip);
+ int (*erase)(unsigned int addr, unsigned int uiChip);
+};
+
+#endif /* _MTD_SPI_PROBE_H_ */
+
+
diff --git a/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_probe.c b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_probe.c
new file mode 100644
index 000000000..857a44138
--- /dev/null
+++ b/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_probe.c
@@ -0,0 +1,209 @@
+/**
+ * SPI Flash probe code.
+ * (C) 2006 Atmark Techno, Inc.
+ */
+
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+//#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <linux/mtd/map.h>
+#include <linux/mtd/gen_probe.h>
+#include "spi_flash.h"
+#include <linux/autoconf.h>
+//#include "spi_common.h"
+
+#include <linux/mtd/mtd.h>
+//#define MTD_SPI_DEBUG
+#define REG32(reg) (*(volatile unsigned int *)((unsigned int)reg))
+
+#if defined(MTD_SPI_DEBUG)
+#define KDEBUG(args...) printk(args)
+#else
+#define KDEBUG(args...)
+#endif
+
+typedef struct spi_chip_info *(spi_probe_func)(struct map_info *, struct chip_probe *);
+
+//extern spi_probe_func spi_probe_suzaku;
+struct spi_chip_info *spi_probe_flash_chip(struct map_info *map, struct chip_probe *cp);
+static spi_probe_func *probe_func[] = {
+//#if defined(CONFIG_MTD_SPI_SUZAKU) || defined(CONFIG_MTD_SPI_SUZAKU_MODULE)
+ spi_probe_flash_chip,
+//#endif
+ NULL
+};
+
+extern int mtd_spi_erase(struct mtd_info *mtd, struct erase_info *instr);
+extern int mtd_spi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+extern int mtd_spi_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+extern void mtd_spi_sync(struct mtd_info *mtd);
+extern int mtd_spi_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
+extern int mtd_spi_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
+extern int mtd_spi_suspend(struct mtd_info *mtd);
+extern void mtd_spi_resume(struct mtd_info *mtd);
+
+static struct mtd_info *spi_chip_setup(struct map_info *map, struct spi_chip_info *chip_info);
+static struct mtd_info *spi_probe_chip(struct map_info *map, struct chip_probe *cp);
+
+struct mtd_info *spi_probe1(struct map_info *map);
+static void spi_destroy1(struct mtd_info *mtd);
+#ifdef CONFIG_RTL_TWO_SPI_FLASH_ENABLE
+struct mtd_info *spi_probe2(struct map_info *map);
+static void spi_destroy2(struct mtd_info *mtd);
+#endif
+
+
+
+
+static struct mtd_chip_driver spi_chipdrv1 = {
+ probe: spi_probe1,
+ destroy: spi_destroy1,
+ name: "flash_bank_1",
+ module: THIS_MODULE,
+};
+#ifdef CONFIG_RTL_TWO_SPI_FLASH_ENABLE
+static struct mtd_chip_driver spi_chipdrv2 = {
+ probe: spi_probe2,
+ destroy: spi_destroy2,
+ name: "flash_bank_2",
+ module: THIS_MODULE,
+};
+#endif
+static struct mtd_info *spi_chip_setup(struct map_info *map, struct spi_chip_info *chip_info)
+{
+ struct mtd_info *mtd;
+
+ mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ if (!mtd) {
+ printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
+ return NULL;
+ }
+
+ memset(mtd, 0, sizeof(struct mtd_info));
+
+ mtd->type = MTD_NORFLASH;//MTD_OTHER;
+ mtd->flags = MTD_CAP_NORFLASH;
+
+ mtd->name = map->name;
+
+ mtd->size = chip_info->flash->deviceSize;
+ mtd->erasesize = chip_info->flash->sectorSize;
+
+ mtd->erase = mtd_spi_erase;
+ mtd->read = mtd_spi_read;
+ mtd->write = mtd_spi_write;
+ mtd->sync = mtd_spi_sync;
+ mtd->lock = mtd_spi_lock;
+ mtd->unlock = mtd_spi_unlock;
+ mtd->suspend = mtd_spi_suspend;
+ mtd->resume = mtd_spi_resume;
+
+ mtd->priv = (void *)map;
+#ifdef CONFIG_RTL_TWO_SPI_FLASH_ENABLE
+ if (0 == chip_info->chip_select) map->fldrv = &spi_chipdrv1;
+ else map->fldrv = &spi_chipdrv2;
+#else
+ map->fldrv = &spi_chipdrv1;
+#endif
+
+ map->fldrv_priv = chip_info;
+ mtd->writesize = 1;
+
+ printk(KERN_INFO "SPI flash(%s) was found at CS%d, size 0x%x\n",
+ chip_info->flash->name, chip_info->chip_select, chip_info->flash->deviceSize );
+
+ return mtd;
+}
+
+static struct mtd_info *spi_probe_chip(struct map_info *map, struct chip_probe *cp)
+{
+ struct mtd_info *mtd = NULL;
+ struct spi_chip_info *chip_info = NULL;
+ int i;
+
+ for (i = 0; probe_func[i]; i++) {
+ chip_info = probe_func[i](map, cp);
+ if (!chip_info) continue;
+
+ mtd = spi_chip_setup(map, chip_info);
+
+ if (!mtd) {
+ kfree(chip_info);
+ continue;
+ }
+
+ return mtd;
+ }
+ return NULL;
+}
+
+static struct chip_probe spi_chip_probe1 = {
+ name: "SPI1",
+};
+#ifdef CONFIG_RTL_TWO_SPI_FLASH_ENABLE
+static struct chip_probe spi_chip_probe2 = {
+ name: "SPI2",
+};
+#endif
+struct mtd_info *spi_probe1(struct map_info *map)
+{
+ KDEBUG("SPI flash 1\n");
+ return spi_probe_chip(map, &spi_chip_probe1);
+}
+#ifdef CONFIG_RTL_TWO_SPI_FLASH_ENABLE
+struct mtd_info *spi_probe2(struct map_info *map)
+{
+ KDEBUG("SPI flash 2\n");
+ return spi_probe_chip(map, &spi_chip_probe2);
+}
+#endif
+static void spi_destroy1(struct mtd_info *mtd)
+{
+ KDEBUG("SPI flash 1\n");
+ struct map_info *map = (struct map_info *)mtd->priv;
+ struct spi_chip_info *chip_info = (struct spi_chip_info *)map->fldrv_priv;
+
+ if (chip_info->destroy) {
+ chip_info->destroy(chip_info);
+ }
+}
+#ifdef CONFIG_RTL_TWO_SPI_FLASH_ENABLE
+static void spi_destroy2(struct mtd_info *mtd)
+{
+ KDEBUG("SPI flash 2\n");
+ struct map_info *map = (struct map_info *)mtd->priv;
+ struct spi_chip_info *chip_info = (struct spi_chip_info *)map->fldrv_priv;
+
+ if (chip_info->destroy) {
+ chip_info->destroy(chip_info);
+ }
+}
+#endif
+int __init spi_probe_init(void)
+{
+ printk("SPI INIT\n");
+ register_mtd_chip_driver(&spi_chipdrv1);
+#ifdef CONFIG_RTL_TWO_SPI_FLASH_ENABLE
+ register_mtd_chip_driver(&spi_chipdrv2);
+#endif
+ return 0;
+}
+
+void __exit spi_probe_exit(void)
+{
+ unregister_mtd_chip_driver(&spi_chipdrv1);
+#ifdef CONFIG_RTL_TWO_SPI_FLASH_ENABLE
+ unregister_mtd_chip_driver(&spi_chipdrv2);
+#endif
+}
+
+module_init(spi_probe_init);
+module_exit(spi_probe_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Masahiro Nakai <nakai@atmark-techno.com> et al.");
+MODULE_DESCRIPTION("Probe code for SPI flash chips");