#include <asm/io.h>\r
#include <linux/platform_device.h>\r
#include <linux/semaphore.h>\r
+#include <linux/clk.h>\r
\r
+#define RKNAND_VERSION_AND_DATE "rknandbase v1.0 2014-03-31"\r
\r
#ifdef CONFIG_OF\r
#include <linux/of.h>\r
struct rknand_info {\r
int tag;\r
int enable;\r
- int reserved0[6];\r
+ int clk_rate[2];\r
+ int reserved0[8];\r
\r
void (*rknand_suspend)(void);\r
void (*rknand_resume)(void);\r
int reserved1[16];\r
};\r
\r
+struct rk_nandc_info \r
+{\r
+ int id;\r
+ void __iomem * reg_base ;\r
+ int irq;\r
+ int clk_rate;\r
+ struct clk *clk; // flash clk\r
+ struct clk *hclk; // nandc clk\r
+ struct clk *gclk; // flash clk gate\r
+};\r
+\r
struct rknand_info * gpNandInfo = NULL;\r
+static struct rk_nandc_info g_nandc_info[2];\r
+\r
static char *cmdline=NULL;\r
int rknand_get_part_info(char **s)\r
{\r
EXPORT_SYMBOL(rknand_device_unlock);\r
\r
\r
-int rknand_get_device(struct rknand_info ** prknand_Info)\r
+int rk_nand_get_device(struct rknand_info ** prknand_Info)\r
{\r
*prknand_Info = gpNandInfo;\r
- return 0; \r
+ return 0; \r
}\r
-EXPORT_SYMBOL(rknand_get_device);\r
+EXPORT_SYMBOL(rk_nand_get_device);\r
\r
int rknand_dma_map_single(unsigned long ptr,int size,int dir)\r
{\r
}\r
EXPORT_SYMBOL(rknand_dma_unmap_single);\r
\r
-int rknand_flash_cs_init(void)\r
+int rknand_flash_cs_init(int id)\r
{\r
\r
}\r
\r
int rknand_get_reg_addr(int *pNandc0,int *pNandc1,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
- *pNandc0 = ioremap(0x10500000,0x4000);\r
- //*pNandc1 = NULL;\r
+ *pNandc0 = g_nandc_info[0].reg_base;\r
+ *pNandc1 = g_nandc_info[1].reg_base;\r
}\r
-\r
EXPORT_SYMBOL(rknand_get_reg_addr);\r
\r
-static int g_nandc_irq = 59;\r
-int rknand_nandc_irq_init(int mode,void * pfun)\r
+int rknand_nandc_irq_init(int id,int mode,void * pfun)\r
{\r
int ret = 0;\r
+ int irq= g_nandc_info[id].irq;\r
+\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
+ ret = request_irq(irq, pfun, 0, "nandc", g_nandc_info[id].reg_base);\r
+ //if(ret)\r
+ printk("request IRQ_NANDC %x irq %x, ret=%x.........\n",id,irq, ret);\r
}\r
else //deinit\r
{\r
- free_irq(g_nandc_irq, NULL);\r
+ free_irq(irq, NULL);\r
}\r
return ret;\r
}\r
EXPORT_SYMBOL(rknand_nandc_irq_init);\r
+\r
static int rknand_probe(struct platform_device *pdev)\r
{\r
- g_nandc_irq = platform_get_irq(pdev, 0);\r
- printk("g_nandc_irq: %d\n",g_nandc_irq);\r
- if (g_nandc_irq < 0) {\r
+ unsigned int id = 0;\r
+ int irq ;\r
+ struct resource *mem;\r
+ void __iomem *membase;\r
+ \r
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+ membase = devm_request_and_ioremap(&pdev->dev, mem);\r
+\r
+ irq = platform_get_irq(pdev, 0);\r
+ printk("nand irq: %d\n",irq);\r
+ if (irq < 0) {\r
dev_err(&pdev->dev, "no irq resource?\n");\r
- return g_nandc_irq;\r
+ return irq;\r
+ }\r
+\r
+#ifdef CONFIG_OF\r
+ if(0==of_property_read_u32(pdev->dev.of_node, "nandc_id", &id))\r
+ {\r
+ ;\r
+ }\r
+ pdev->id = id;\r
+#endif\r
+ printk("rknand_probe %d %x\n", pdev->id,mem);\r
+ \r
+ if(id == 0)\r
+ {\r
+ memcpy(vendor0,membase+0x1400,0x200);\r
+ memcpy(sn_data,membase+0x1600,0x200);\r
+ }\r
+\r
+ g_nandc_info[id].id = id;\r
+ g_nandc_info[id].irq = irq;\r
+ g_nandc_info[id].reg_base = membase;\r
+\r
+ g_nandc_info[id].hclk = devm_clk_get(&pdev->dev, "hclk_nandc");\r
+ g_nandc_info[id].clk = devm_clk_get(&pdev->dev, "clk_nandc");\r
+ g_nandc_info[id].gclk = devm_clk_get(&pdev->dev, "g_clk_nandc");\r
+\r
+ if (unlikely(IS_ERR(g_nandc_info[id].clk)) || unlikely(IS_ERR(g_nandc_info[id].hclk))\r
+ || unlikely(IS_ERR(g_nandc_info[id].gclk))) {\r
+ printk("rknand_probe get clk error\n");\r
+ return -1;\r
}\r
+\r
+ clk_set_rate(g_nandc_info[id].clk,150*1000*1000);\r
+ g_nandc_info[id].clk_rate = clk_get_rate(g_nandc_info[id].clk );\r
+ printk("rknand_probe clk rate = %d\n",g_nandc_info[id].clk_rate);\r
+ gpNandInfo->clk_rate[id] = g_nandc_info[id].clk_rate;\r
+ \r
+ clk_prepare_enable( g_nandc_info[id].clk );\r
+ clk_prepare_enable( g_nandc_info[id].hclk);\r
+ clk_prepare_enable( g_nandc_info[id].gclk);\r
+\r
return 0;\r
}\r
\r
static int __init rknand_part_init(void)\r
{\r
int ret = 0;\r
- char * pbuf = ioremap(0x10501400,0x400);\r
- memcpy(vendor0,pbuf,0x200);\r
- memcpy(sn_data,pbuf+0x200,0x200);\r
- iounmap(pbuf);\r
+ printk("%s\n", RKNAND_VERSION_AND_DATE);\r
+\r
cmdline = strstr(saved_command_line, "mtdparts=") + 9;\r
+\r
gpNandInfo = kzalloc(sizeof(struct rknand_info), GFP_KERNEL);\r
if (!gpNandInfo)\r
return -ENOMEM;\r
- memset(gpNandInfo,0,sizeof(struct rknand_info));\r
+ //memset(gpNandInfo,0,sizeof(struct rknand_info));// no need\r
+ \r
ret = platform_driver_register(&rknand_driver);\r
printk("rknand_driver:ret = %x \n",ret);\r
return ret;\r