[CIFS] Missing flags2 for DFS
[pandora-kernel.git] / arch / mips / basler / excite / excite_flashtest.c
1 /*
2 *  Copyright (C) 2005 by Basler Vision Technologies AG
3 *  Author: Thies Moeller <thies.moeller@baslerweb.com>
4 *
5 *  This program is free software; you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation; either version 2 of the License, or
8 *  (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/init.h>
23 #include <linux/kernel.h>
24 #include <linux/string.h>
25 #include <linux/ioport.h>
26 #include <linux/device.h>
27 #include <linux/delay.h>
28 #include <linux/err.h>
29 #include <linux/kernel.h>
30
31 #include <excite.h>
32
33 #include <asm/io.h>
34
35 #include <linux/mtd/mtd.h>
36 #include <linux/mtd/nand.h>
37 #include <linux/mtd/nand_ecc.h>
38 #include <linux/mtd/partitions.h>
39 #include <asm/rm9k-ocd.h> // for ocd_write
40 #include <linux/workqueue.h> // for queue
41
42 #include "excite_nandflash.h"
43 #include "nandflash.h"
44
45 #define PFX "excite flashtest: "
46 typedef void __iomem *io_reg_t;
47
48 #define io_readb(__a__)         __raw_readb((__a__))
49 #define io_writeb(__v__, __a__) __raw_writeb((__v__), (__a__))
50
51
52
53 static inline const struct resource *excite_nandflash_get_resource(
54         struct platform_device *d, unsigned long flags, const char *basename)
55 {
56         const char fmt[] = "%s_%u";
57         char buf[80];
58
59         if (unlikely(snprintf(buf, sizeof buf, fmt, basename, d->id) >= sizeof buf))
60                 return NULL;
61
62         return platform_get_resource_byname(d, flags, buf);
63 }
64
65 static inline io_reg_t
66 excite_nandflash_map_regs(struct platform_device *d, const char *basename)
67 {
68         void *result = NULL;
69         const struct resource *const r =
70             excite_nandflash_get_resource(d, IORESOURCE_MEM, basename);
71         if (r)
72            result = ioremap_nocache(r->start, r->end + 1 - r->start);
73         return result;
74 }
75
76 /* controller and mtd information */
77
78 struct excite_nandflash_drvdata {
79         struct mtd_info board_mtd;
80         struct nand_chip board_chip;
81         io_reg_t regs;
82 };
83
84
85 /* command and control functions */
86 static void excite_nandflash_hwcontrol(struct mtd_info *mtd, int cmd)
87 {
88         struct nand_chip *this = mtd->priv;
89         io_reg_t regs = container_of(mtd,struct excite_nandflash_drvdata,board_mtd)->regs;
90
91         switch (cmd) {
92         /* Select the command latch */
93         case NAND_CTL_SETCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_CMD;
94                 break;
95         /* Deselect the command latch */
96         case NAND_CTL_CLRCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA;
97                 break;
98         /* Select the address latch */
99         case NAND_CTL_SETALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_ADDR;
100                 break;
101         /* Deselect the address latch */
102         case NAND_CTL_CLRALE: this->IO_ADDR_W = regs  + EXCITE_NANDFLASH_DATA;
103                 break;
104         /* Select the chip  -- not used */
105         case NAND_CTL_SETNCE:
106                 break;
107         /* Deselect the chip -- not used */
108         case NAND_CTL_CLRNCE:
109                 break;
110         }
111
112         this->IO_ADDR_R = this->IO_ADDR_W;
113 }
114
115 /* excite_nandflash_devready()
116  *
117  * returns 0 if the nand is busy, 1 if it is ready
118  */
119 static int excite_nandflash_devready(struct mtd_info *mtd)
120 {
121         struct excite_nandflash_drvdata *drvdata =
122             container_of(mtd, struct excite_nandflash_drvdata, board_mtd);
123
124         return io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
125 }
126
127 /* device management functions */
128
129 /* excite_nandflash_remove
130  *
131  * called by device layer to remove the driver
132  * the binding to the mtd and all allocated
133  * resources are released
134  */
135 static int excite_nandflash_remove(struct device *dev)
136 {
137         struct excite_nandflash_drvdata *this = dev_get_drvdata(dev);
138
139         pr_info(PFX "remove");
140
141         dev_set_drvdata(dev, NULL);
142
143         if (this == NULL) {
144                 pr_debug(PFX "call remove without private data!!");
145                 return 0;
146         }
147
148
149         /* free the common resources */
150         if (this->regs != NULL) {
151                 iounmap(this->regs);
152                 this->regs = NULL;
153         }
154
155         kfree(this);
156
157         return 0;
158 }
159
160 static int elapsed;
161
162 void my_workqueue_handler(void *arg)
163 {
164         elapsed = 1;
165 }
166
167 DECLARE_WORK(sigElapsed, my_workqueue_handler, 0);
168
169
170 /* excite_nandflash_probe
171  *
172  * called by device layer when it finds a device matching
173  * one our driver can handled. This code checks to see if
174  * it can allocate all necessary resources then calls the
175  * nand layer to look for devices
176 */
177 static int excite_nandflash_probe(struct device *dev)
178 {
179         struct platform_device *pdev = to_platform_device(dev);
180
181         struct excite_nandflash_drvdata *drvdata;           /* private driver data     */
182         struct nand_chip              *board_chip;  /* private flash chip data */
183         struct mtd_info               *board_mtd;   /* mtd info for this board */
184
185         int err      = 0;
186         int count    = 0;
187         struct timeval tv,endtv;
188         unsigned int dt;
189
190         pr_info(PFX "probe dev: (%p)\n", dev);
191
192         pr_info(PFX "adjust LB timing\n");
193         ocd_writel(0x00000330, LDP2);
194
195         drvdata = kmalloc(sizeof(*drvdata), GFP_KERNEL);
196         if (unlikely(!drvdata)) {
197                 printk(KERN_ERR PFX "no memory for drvdata\n");
198                 err = -ENOMEM;
199                 goto mem_error;
200         }
201
202         /* Initialize structures */
203         memset(drvdata, 0, sizeof(*drvdata));
204
205         /* bind private data into driver */
206         dev_set_drvdata(dev, drvdata);
207
208         /* allocate and map the resource */
209         drvdata->regs =
210             excite_nandflash_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
211
212         if (unlikely(!drvdata->regs)) {
213                 printk(KERN_ERR PFX "cannot reserve register region\n");
214                 err = -ENXIO;
215                 goto io_error;
216         }
217
218         /* initialise our chip */
219         board_chip = &drvdata->board_chip;
220
221         board_chip->IO_ADDR_R = drvdata->regs + EXCITE_NANDFLASH_DATA;
222         board_chip->IO_ADDR_W = drvdata->regs + EXCITE_NANDFLASH_DATA;
223
224         board_chip->hwcontrol = excite_nandflash_hwcontrol;
225         board_chip->dev_ready = excite_nandflash_devready;
226
227         board_chip->chip_delay = 25;
228         #if 0
229         /* TODO: speedup the initial scan */
230         board_chip->options = NAND_USE_FLASH_BBT;
231         #endif
232         board_chip->eccmode = NAND_ECC_SOFT;
233
234         /* link chip to mtd */
235         board_mtd = &drvdata->board_mtd;
236         board_mtd->priv = board_chip;
237
238
239         pr_info(PFX "FlashTest\n");
240         elapsed = 0;
241 /*      schedule_delayed_work(&sigElapsed, 1*HZ);
242         while (!elapsed) {
243                 io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
244                 count++;
245         }
246         pr_info(PFX "reads in 1 sec --> %d\n",count);
247 */
248         do_gettimeofday(&tv);
249         for (count = 0 ; count < 1000000; count ++) {
250                 io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
251         }
252         do_gettimeofday(&endtv);
253         dt = (endtv.tv_sec - tv.tv_sec) * 1000000 + endtv.tv_usec  - tv.tv_usec;
254         pr_info(PFX "%8d us timeval\n",dt);
255         pr_info(PFX "EndFlashTest\n");
256
257 /*      return with error to unload everything
258 */
259 io_error:
260         iounmap(drvdata->regs);
261
262 mem_error:
263         kfree(drvdata);
264
265         if (err == 0)
266                 err = -EINVAL;
267         return err;
268 }
269
270 static struct device_driver excite_nandflash_driver = {
271         .name = "excite_nand",
272         .bus = &platform_bus_type,
273         .probe = excite_nandflash_probe,
274         .remove = excite_nandflash_remove,
275 };
276
277 static int __init excite_nandflash_init(void)
278 {
279         pr_info(PFX "register Driver (Rev: $Revision:$)\n");
280         return driver_register(&excite_nandflash_driver);
281 }
282
283 static void __exit excite_nandflash_exit(void)
284 {
285         driver_unregister(&excite_nandflash_driver);
286         pr_info(PFX "Driver unregistered");
287 }
288
289 module_init(excite_nandflash_init);
290 module_exit(excite_nandflash_exit);
291
292 MODULE_AUTHOR("Thies Moeller <thies.moeller@baslerweb.com>");
293 MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
294 MODULE_LICENSE("GPL");