*\r
* \r
*/\r
-\r
+#include <linux/version.h>\r
#include <linux/module.h>\r
#include <linux/sched.h>\r
#include <linux/delay.h>\r
#include <linux/slab.h>\r
#include <linux/platform_device.h>\r
#include <linux/mtd/mtd.h>\r
+#include <linux/mtd/mtd.h>\r
#include <linux/mtd/partitions.h>\r
#include <linux/mutex.h>\r
#include <linux/kthread.h>\r
+#include <linux/dma-mapping.h>\r
+#include <asm/dma.h>\r
+#include <asm/cacheflush.h>\r
+#include <linux/irq.h>\r
+#include <linux/interrupt.h>\r
#include <linux/reboot.h>\r
#include <asm/io.h>\r
#include <asm/mach/flash.h>\r
//#include "api_flash.h"\r
#include "rknand_base.h"\r
+#include "../mtdcore.h"\r
#include <linux/clk.h>\r
#include <linux/cpufreq.h>\r
+#ifdef CONFIG_OF\r
+#include <linux/of.h>\r
+#endif\r
\r
#define DRIVER_NAME "rk29xxnand"\r
\r
#define SPARE_LEN (32*8*2/4) //УÑéÊý¾Ý³¤¶È\r
#define PAGE_LEN (DATA_LEN+SPARE_LEN) //ÿ¸öÊý¾Ýµ¥Î»µÄ³¤¶È\r
#define MAX_BUFFER_SIZE (long)(2048 * 8) //sector\r
-long grknand_buf[MAX_BUFFER_SIZE * 512/4] __attribute__((aligned(4096)));\r
-long grknand_dma_buf[PAGE_LEN*4*5] __attribute__((aligned(4096)));\r
-\r
+//long grknand_buf[MAX_BUFFER_SIZE * 512/4] __attribute__((aligned(4096)));\r
+//long grknand_dma_buf[PAGE_LEN*4*5] __attribute__((aligned(4096)));\r
static struct proc_dir_entry *my_proc_entry;\r
extern int rkNand_proc_ftlread(char *page);\r
extern int rkNand_proc_bufread(char *page);\r
return buf - page < count ? buf - page : count;\r
}\r
\r
+#if 0// (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))\r
static void rknand_create_procfs(void)\r
{\r
/* Install the proc_fs entry */\r
} \r
#endif\r
}\r
+#else\r
+static const struct file_operations my_proc_fops = {\r
+.owner = THIS_MODULE,\r
+.read = rkNand_proc_read,\r
+.write = NULL,\r
+};\r
\r
+static void rknand_create_procfs(void)\r
+{\r
+ /* Install the proc_fs entry */\r
+ my_proc_entry = proc_create("rknand",\r
+ S_IRUGO | S_IFREG,\r
+ NANDPROC_ROOT,&my_proc_fops);\r
+}\r
+#endif\r
void printk_write_log(long lba,int len, const u_char *pbuf)\r
{\r
char debug_buf[100];\r
#ifdef RKNAND_TRAC_EN\r
//trac_log(LBA,sector,0);\r
#endif\r
- //printk("R %d %d \n",(int)LBA,sector);\r
+ printk("R %d %d \n",(int)LBA,sector);\r
//if(rknand_debug)\r
// printk("rk28xxnand_read: from=%x,sector=%x,\n",(int)LBA,sector);\r
if(sector && gpNandInfo->ftl_read)\r
{\r
ret = gpNandInfo->ftl_read(LBA, sector, buf);\r
+ if(ret)\r
+ *retlen = 0;\r
}\r
- *retlen = len;\r
- return 0;//ret;\r
+ return ret;\r
}\r
\r
static int rknand_write(struct mtd_info *mtd, loff_t from, size_t len,\r
#ifdef RKNAND_TRAC_EN\r
trac_log(LBA,sector,1);\r
#endif\r
- //printk("W %d %d \n",(int)LBA,sector);\r
+ printk("W %d %d \n",(int)LBA,sector);\r
//return 0;\r
//printk("*");\r
//if(rknand_debug)\r
return 0;\r
}\r
\r
+static int rknand_diacard(struct mtd_info *mtd, loff_t from, size_t len)\r
+{\r
+ int ret = 0;\r
+ int sector = len>>9;\r
+ int LBA = (int)(from>>9);\r
+ //printk("rknand_diacard: from=%x,sector=%x,\n",(int)LBA,sector);\r
+ if(sector && gpNandInfo->ftl_discard)\r
+ {\r
+ ret = gpNandInfo->ftl_discard(LBA, sector);\r
+ }\r
+ return ret;\r
+}\r
+\r
static int rknand_erase(struct mtd_info *mtd, struct erase_info *instr)\r
{\r
int ret = 0;\r
return 0;\r
}\r
\r
-char GetSNSectorInfo(char * pbuf)\r
-{\r
- if(gpNandInfo->GetSNSectorInfo)\r
- return( gpNandInfo->GetSNSectorInfo( pbuf));\r
- return 0;\r
-}\r
-\r
-\r
char GetSNSectorInfoBeforeNandInit(char * pbuf)\r
{\r
char * sn_addr = ioremap(0x10501600,0x200);\r
memcpy(pbuf,sn_addr,0x200);\r
iounmap(sn_addr);\r
- //print_hex_dump(KERN_WARNING, "sn:", DUMP_PREFIX_NONE, 16,1, sn_addr, 0x200, 0);\r
+ //print_hex_dump(KERN_WARNING, "sn:", DUMP_PREFIX_NONE, 16,1, sn_addr, 16, 0);\r
return 0;\r
} \r
\r
+char GetSNSectorInfo(char * pbuf)\r
+{\r
+ if(gpNandInfo->GetSNSectorInfo)\r
+ return( gpNandInfo->GetSNSectorInfo( pbuf));\r
+ else\r
+ return GetSNSectorInfoBeforeNandInit(pbuf);\r
+ return 0;\r
+}\r
+\r
+\r
char GetVendor0InfoBeforeNandInit(char * pbuf)\r
{\r
char * sn_addr = ioremap(0x10501400,0x200);\r
memcpy(pbuf,sn_addr + 8,504);\r
iounmap(sn_addr);\r
- //print_hex_dump(KERN_WARNING, "sn:", DUMP_PREFIX_NONE, 16,1, sn_addr, 0x200, 0);\r
+ //print_hex_dump(KERN_WARNING, "sn:", DUMP_PREFIX_NONE, 16,1, sn_addr, 16, 0);\r
return 0;\r
} \r
\r
return ret?-1:(sector<<9);\r
}\r
\r
+void rknand_dev_cache_flush(void)\r
+{\r
+ if(gpNandInfo->rknand_dev_cache_flush)\r
+ gpNandInfo->rknand_dev_cache_flush();\r
+}\r
+\r
\r
static int rknand_block_isbad(struct mtd_info *mtd, loff_t ofs)\r
{\r
// Fill in remaining MTD driver data \r
mtd->type = MTD_NANDFLASH;\r
mtd->flags = (MTD_WRITEABLE|MTD_NO_ERASE);//\r
- mtd->erase = rknand_erase;\r
- mtd->point = NULL;\r
- mtd->unpoint = NULL;\r
- mtd->read = rknand_read;\r
- mtd->write = rknand_write;\r
- mtd->read_oob = NULL;\r
- mtd->write_oob = NULL;\r
- mtd->panic_write = rknand_panic_write;\r
-\r
- mtd->sync = rknand_sync;\r
- mtd->lock = NULL;\r
- mtd->unlock = NULL;\r
- mtd->suspend = NULL;\r
- mtd->resume = NULL;\r
- mtd->block_isbad = rknand_block_isbad;\r
- mtd->block_markbad = rknand_block_markbad;\r
+ mtd->_erase = rknand_erase;\r
+ mtd->_point = NULL;\r
+ mtd->_unpoint = NULL;\r
+ mtd->_read = rknand_read;\r
+ mtd->_write = rknand_write;\r
+ //mtd->discard = rknand_diacard;\r
+ mtd->_read_oob = NULL;\r
+ mtd->_write_oob = NULL;\r
+ mtd->_panic_write = rknand_panic_write;\r
+\r
+ mtd->_sync = rknand_sync;\r
+ mtd->_lock = NULL;\r
+ mtd->_unlock = NULL;\r
+ mtd->_suspend = NULL;\r
+ mtd->_resume = NULL;\r
+ mtd->_block_isbad = rknand_block_isbad;\r
+ mtd->_block_markbad = rknand_block_markbad;\r
mtd->owner = THIS_MODULE;\r
return 0;\r
}\r
// ´ÓÃüÁîÐнâÎö·ÖÇøµÄÐÅÏ¢\r
num_partitions = parse_mtd_partitions(&(rknand_mtd), part_probes, &rknand_parts, 0); \r
NAND_DEBUG(NAND_DEBUG_LEVEL0,"num_partitions = %d\n",num_partitions);\r
+ printk("num_partitions = %d\n",num_partitions);\r
if(num_partitions > 0) { \r
int i;\r
for (i = 0; i < num_partitions; i++) \r
rknand_parts[num_partitions - 1].size = rknand_mtd.size - rknand_parts[num_partitions - 1].offset;\r
\r
g_num_partitions = num_partitions;\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- return mtd_device_register(&rknand_mtd, rknand_parts, num_partitions);\r
-#else\r
+//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+// return mtd_device_register(&rknand_mtd, rknand_parts, num_partitions);\r
+//#else\r
return add_mtd_partitions(&(rknand_mtd), rknand_parts, num_partitions);\r
-#endif\r
+//#endif\r
} \r
#endif \r
g_num_partitions = 0;\r
struct mtd_partition *parts;\r
int i;\r
NAND_DEBUG(NAND_DEBUG_LEVEL0,"add_rknand_device: \n");\r
- \r
+ printk("gpNandInfo->nandCapacity = %lx\n",gpNandInfo->nandCapacity);\r
rknand_mtd.size = (uint64_t)gpNandInfo->nandCapacity*0x200;\r
\r
rknand_add_partitions(prknand_Info);\r
if(SysImageWriteEndAdd)\r
gpNandInfo->SysImageWriteEndAdd = SysImageWriteEndAdd;\r
\r
- nandc_clk = clk_get(NULL, "nandc");\r
- clk_enable(nandc_clk);\r
- rknand_nand_timing_cfg();\r
+ //nandc_clk = clk_get(NULL, "nandc");\r
+ //clk_enable(nandc_clk);\r
+ //rknand_nand_timing_cfg();\r
\r
return 0;\r
}\r
\r
EXPORT_SYMBOL(get_rknand_device);\r
\r
+int rknand_dma_map_single(unsigned long ptr,int size,int dir)\r
+{\r
+ return dma_map_single(NULL, ptr,size, dir?DMA_TO_DEVICE:DMA_FROM_DEVICE);\r
+}\r
+EXPORT_SYMBOL(rknand_dma_map_single);\r
+\r
+void rknand_dma_unmap_single(unsigned long ptr,int size,int dir)\r
+{\r
+ dma_unmap_single(NULL, ptr,size, dir?DMA_TO_DEVICE:DMA_FROM_DEVICE);\r
+}\r
+EXPORT_SYMBOL(rknand_dma_unmap_single);\r
+\r
+int rknand_flash_cs_init(void)\r
+{\r
+\r
+}\r
+EXPORT_SYMBOL(rknand_flash_cs_init);\r
+\r
+\r
+int rknand_get_reg_addr(int *pNandc,int *pSDMMC0,int *pSDMMC1,int *pSDMMC2)\r
+{\r
+ //*pNandc = ioremap(RK30_NANDC_PHYS,RK30_NANDC_SIZE);\r
+ //*pSDMMC0 = ioremap(SDMMC0_BASE_ADDR, 0x4000);\r
+ //*pSDMMC1 = ioremap(SDMMC1_BASE_ADDR, 0x4000);\r
+ //*pSDMMC2 = ioremap(EMMC_BASE_ADDR, 0x4000);\r
+ *pNandc = ioremap(0x10500000,0x4000);\r
+}\r
+EXPORT_SYMBOL(rknand_get_reg_addr);\r
+\r
+static int g_nandc_irq = 27;\r
+int rknand_nandc_irq_init(int mode,void * pfun)\r
+{\r
+ int ret = 0;\r
+ if(mode) //init\r
+ {\r
+ ret = request_irq(g_nandc_irq, pfun, 0, "nandc", NULL);\r
+ if(ret)\r
+ printk("request IRQ_NANDC irq , ret=%x.........\n", ret);\r
+ }\r
+ else //deinit\r
+ {\r
+ free_irq(g_nandc_irq, NULL);\r
+ }\r
+ return ret;\r
+}\r
+EXPORT_SYMBOL(rknand_nandc_irq_init);\r
static int rknand_probe(struct platform_device *pdev)\r
{\r
struct rknand_info *nand_info;\r
return -ENOMEM;\r
\r
nand_info = gpNandInfo;\r
+ printk("rknand_probe: \n");\r
\r
+ g_nandc_irq = platform_get_irq(pdev, 0);\r
+ if (g_nandc_irq < 0) {\r
+ dev_err(&pdev->dev, "no irq resource?\n");\r
+ return g_nandc_irq;\r
+ }\r
+ \r
memset(gpNandInfo,0,sizeof(struct rknand_info));\r
\r
gpNandInfo->bufSize = MAX_BUFFER_SIZE * 512;\r
- gpNandInfo->pbuf = (char *)grknand_buf;\r
- gpNandInfo->pdmaBuf = (char *)grknand_dma_buf;\r
+ gpNandInfo->pbuf = (char *)NULL;//grknand_buf;\r
+ gpNandInfo->pdmaBuf = (char *)NULL;//grknand_dma_buf;\r
//printk(" gpNandInfo->pdmaBuf=0x%x\n", gpNandInfo->pdmaBuf); \r
#ifdef CONFIG_MTD_EMMC_CLK_POWER_SAVE\r
gpNandInfo->emmc_clk_power_save_en = 1;\r
#endif\r
\r
- rknand_mtd.name = dev_name(&pdev->dev);\r
+ rknand_mtd.name = DRIVER_NAME;//dev_name(&pdev->dev);\r
rknand_mtd.priv = &nand_info->rknand;\r
rknand_mtd.owner = THIS_MODULE;\r
\r
gpNandInfo->rknand_buffer_shutdown(); \r
}\r
\r
+#ifdef CONFIG_OF\r
+static const struct of_device_id of_rk_nandc_match[] = {\r
+ { .compatible = "rockchip,rk-nandc" },\r
+ { /* Sentinel */ }\r
+};\r
+#endif\r
+\r
static struct platform_driver rknand_driver = {\r
.probe = rknand_probe,\r
.suspend = rknand_suspend,\r
.shutdown = rknand_shutdown,\r
.driver = {\r
.name = DRIVER_NAME,\r
+#ifdef CONFIG_OF\r
+ .of_match_table = of_rk_nandc_match,\r
+#endif\r
.owner = THIS_MODULE,\r
},\r
};\r