Merge branch 'develop-3.10' of ssh://10.10.10.29/rk/kernel into develop-3.10
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / rknandbase.c
1 \r
2 #include <linux/module.h>\r
3 #include <linux/kernel.h>\r
4 #include <linux/slab.h>\r
5 #include <linux/dma-mapping.h>\r
6 #include <linux/irq.h>\r
7 #include <linux/interrupt.h>\r
8 #include <linux/bootmem.h>\r
9 #include <asm/io.h>\r
10 #include <linux/platform_device.h>\r
11 #include <linux/semaphore.h>\r
12 \r
13 \r
14 #ifdef CONFIG_OF\r
15 #include <linux/of.h>\r
16 #endif\r
17 \r
18 struct rknand_info {\r
19     int tag;\r
20     int enable;\r
21     int reserved0[6];\r
22     \r
23     void (*rknand_suspend)(void);\r
24     void (*rknand_resume)(void);\r
25     void (*rknand_buffer_shutdown)(void);\r
26     int (*rknand_exit)(void);\r
27     \r
28     int (*ftl_read) (int lun,int Index, int nSec, void *buf);  \r
29     int (*ftl_write) (int lun,int Index, int nSec, void *buf);\r
30     void (*nand_timing_config)(unsigned long AHBnKHz);\r
31     void (*rknand_dev_cache_flush)(void);\r
32     \r
33     int reserved1[16];\r
34 };\r
35 \r
36 struct rknand_info * gpNandInfo = NULL;\r
37 static char *cmdline=NULL;\r
38 int rknand_get_part_info(char **s)\r
39 {\r
40         *s = cmdline;\r
41     return 0;\r
42 }\r
43 EXPORT_SYMBOL(rknand_get_part_info); \r
44 \r
45 static char sn_data[512];\r
46 static char vendor0[512];\r
47 \r
48 char GetSNSectorInfo(char * pbuf)\r
49 {\r
50     memcpy(pbuf,sn_data,0x200);\r
51     return 0;\r
52 }\r
53 \r
54 char GetSNSectorInfoBeforeNandInit(char * pbuf)\r
55 {\r
56     memcpy(pbuf,sn_data,0x200);\r
57     return 0;\r
58\r
59 \r
60 char GetVendor0InfoBeforeNandInit(char * pbuf)\r
61 {\r
62     memcpy(pbuf,vendor0 + 8,504);\r
63     return 0;\r
64 }\r
65 \r
66 int  GetParamterInfo(char * pbuf , int len)\r
67 {\r
68     int ret = -1;\r
69         return ret;\r
70 }\r
71 \r
72 void rknand_spin_lock_init(spinlock_t * p_lock)\r
73 {\r
74     spin_lock_init(p_lock);\r
75 }\r
76 EXPORT_SYMBOL(rknand_spin_lock_init);\r
77 \r
78 void rknand_spin_lock(spinlock_t * p_lock)\r
79 {\r
80     spin_lock_irq(p_lock);\r
81 }\r
82 EXPORT_SYMBOL(rknand_spin_lock);\r
83 \r
84 void rknand_spin_unlock(spinlock_t * p_lock)\r
85 {\r
86     spin_unlock_irq(p_lock);\r
87 }\r
88 EXPORT_SYMBOL(rknand_spin_unlock);\r
89 \r
90 \r
91 struct semaphore  g_rk_nand_ops_mutex;\r
92 void rknand_device_lock_init(void)\r
93 {\r
94         sema_init(&g_rk_nand_ops_mutex, 1);\r
95 }\r
96 EXPORT_SYMBOL(rknand_device_lock_init);\r
97 void rknand_device_lock (void)\r
98 {\r
99      down(&g_rk_nand_ops_mutex);\r
100 }\r
101 EXPORT_SYMBOL(rknand_device_lock);\r
102 \r
103 int rknand_device_trylock (void)\r
104 {\r
105     return down_trylock(&g_rk_nand_ops_mutex);\r
106 }\r
107 EXPORT_SYMBOL(rknand_device_trylock);\r
108 \r
109 void rknand_device_unlock (void)\r
110 {\r
111     up(&g_rk_nand_ops_mutex);\r
112 }\r
113 EXPORT_SYMBOL(rknand_device_unlock);\r
114 \r
115 \r
116 int rknand_get_device(struct rknand_info ** prknand_Info)\r
117 {\r
118     *prknand_Info = gpNandInfo;\r
119     return 0;    \r
120 }\r
121 EXPORT_SYMBOL(rknand_get_device);\r
122 \r
123 int rknand_dma_map_single(unsigned long ptr,int size,int dir)\r
124 {\r
125     return dma_map_single(NULL, ptr,size, dir?DMA_TO_DEVICE:DMA_FROM_DEVICE);\r
126 }\r
127 EXPORT_SYMBOL(rknand_dma_map_single);\r
128 \r
129 void rknand_dma_unmap_single(unsigned long ptr,int size,int dir)\r
130 {\r
131     dma_unmap_single(NULL, ptr,size, dir?DMA_TO_DEVICE:DMA_FROM_DEVICE);\r
132 }\r
133 EXPORT_SYMBOL(rknand_dma_unmap_single);\r
134 \r
135 int rknand_flash_cs_init(void)\r
136 {\r
137 \r
138 }\r
139 EXPORT_SYMBOL(rknand_flash_cs_init);\r
140 \r
141 int rknand_get_reg_addr(int *pNandc0,int *pNandc1,int *pSDMMC0,int *pSDMMC1,int *pSDMMC2)\r
142 {\r
143     //*pNandc = ioremap(RK30_NANDC_PHYS,RK30_NANDC_SIZE);\r
144     //*pSDMMC0 = ioremap(SDMMC0_BASE_ADDR, 0x4000);\r
145     //*pSDMMC1 = ioremap(SDMMC1_BASE_ADDR, 0x4000);\r
146     //*pSDMMC2 = ioremap(EMMC_BASE_ADDR,   0x4000);\r
147         *pNandc0 = ioremap(0x10500000,0x4000);\r
148         //*pNandc1 = NULL;\r
149 }\r
150 \r
151 EXPORT_SYMBOL(rknand_get_reg_addr);\r
152 \r
153 static int g_nandc_irq = 59;\r
154 int rknand_nandc_irq_init(int mode,void * pfun)\r
155 {\r
156     int ret = 0;\r
157     if(mode) //init\r
158     {\r
159         ret = request_irq(g_nandc_irq, pfun, 0, "nandc", NULL);\r
160         if(ret)\r
161             printk("request IRQ_NANDC irq , ret=%x.........\n", ret);\r
162     }\r
163     else //deinit\r
164     {\r
165         free_irq(g_nandc_irq,  NULL);\r
166     }\r
167     return ret;\r
168 }\r
169 EXPORT_SYMBOL(rknand_nandc_irq_init);\r
170 static int rknand_probe(struct platform_device *pdev)\r
171 {\r
172         g_nandc_irq = platform_get_irq(pdev, 0);\r
173         printk("g_nandc_irq: %d\n",g_nandc_irq);\r
174         if (g_nandc_irq < 0) {\r
175                 dev_err(&pdev->dev, "no irq resource?\n");\r
176                 return g_nandc_irq;\r
177         }\r
178         return 0;\r
179 }\r
180 \r
181 static int rknand_suspend(struct platform_device *pdev, pm_message_t state)\r
182 {\r
183     if(gpNandInfo->rknand_suspend)\r
184         gpNandInfo->rknand_suspend();  \r
185         return 0;\r
186 }\r
187 \r
188 static int rknand_resume(struct platform_device *pdev)\r
189 {\r
190     if(gpNandInfo->rknand_resume)\r
191        gpNandInfo->rknand_resume();  \r
192         return 0;\r
193 }\r
194 \r
195 static void rknand_shutdown(struct platform_device *pdev)\r
196 {\r
197     if(gpNandInfo->rknand_buffer_shutdown)\r
198         gpNandInfo->rknand_buffer_shutdown();    \r
199 }\r
200 \r
201 void rknand_dev_cache_flush(void)\r
202 {\r
203     if(gpNandInfo->rknand_dev_cache_flush)\r
204         gpNandInfo->rknand_dev_cache_flush();\r
205 }\r
206 \r
207 #ifdef CONFIG_OF\r
208 static const struct of_device_id of_rk_nandc_match[] = {\r
209         { .compatible = "rockchip,rk-nandc" },\r
210         { /* Sentinel */ }\r
211 };\r
212 #endif\r
213 \r
214 static struct platform_driver rknand_driver = {\r
215         .probe          = rknand_probe,\r
216         .suspend        = rknand_suspend,\r
217         .resume         = rknand_resume,\r
218         .shutdown   = rknand_shutdown,\r
219         .driver         = {\r
220             .name       = "rknand",\r
221 #ifdef CONFIG_OF\r
222         .of_match_table = of_rk_nandc_match,\r
223 #endif\r
224                 .owner  = THIS_MODULE,\r
225         },\r
226 };\r
227 \r
228 static void __exit rknand_part_exit(void)\r
229 {\r
230         printk("rknand_part_exit: \n");\r
231     platform_driver_unregister(&rknand_driver);\r
232     if(gpNandInfo->rknand_exit)\r
233         gpNandInfo->rknand_exit();    \r
234         if (gpNandInfo)\r
235             kfree(gpNandInfo);\r
236 }\r
237 \r
238 MODULE_ALIAS(DRIVER_NAME);\r
239 static int __init rknand_part_init(void)\r
240 {\r
241         int ret = 0;\r
242     char * pbuf = ioremap(0x10501400,0x400);\r
243     memcpy(vendor0,pbuf,0x200);\r
244     memcpy(sn_data,pbuf+0x200,0x200);\r
245     iounmap(pbuf);\r
246         cmdline = strstr(saved_command_line, "mtdparts=") + 9;\r
247         gpNandInfo = kzalloc(sizeof(struct rknand_info), GFP_KERNEL);\r
248         if (!gpNandInfo)\r
249                 return -ENOMEM;\r
250     memset(gpNandInfo,0,sizeof(struct rknand_info));\r
251         ret = platform_driver_register(&rknand_driver);\r
252         printk("rknand_driver:ret = %x \n",ret);\r
253         return ret;\r
254 }\r
255 \r
256 module_init(rknand_part_init);\r
257 module_exit(rknand_part_exit);\r