GPIO code updates, make the cf-mips driver compile against this gpio version
[librecmc/librecmc.git] / target / linux / rb532 / files / drivers / block / rb500 / ata.c
1 /* CF-mips driver
2    This is a block driver for the direct (mmaped) interface to the CF-slot,
3    found in Routerboard.com's RB532 board
4    See SDK provided from routerboard.com.
5    
6    Module adapted By P.Christeas <p_christeas@yahoo.com>, 2005-6.
7    Cleaned up and adapted to platform_device by Felix Fietkau <nbd@openwrt.org>
8
9    This work is redistributed under the terms of the GNU General Public License.
10 */
11
12 #include <linux/kernel.h>       /* printk() */
13 #include <linux/module.h>       /* module to be loadable */
14 #include <linux/delay.h>
15 #include <linux/sched.h>
16 #include <linux/pci.h>
17 #include <linux/ioport.h>       /* request_mem_region() */
18
19 #include <asm/gpio.h>
20 #include <asm/unaligned.h>              /* ioremap() */
21 #include <asm/io.h>             /* ioremap() */
22 #include <asm/rc32434/rb.h>
23
24 #include "ata.h"
25
26 #define REQUEST_MEM_REGION 0
27 #define DEBUG 1
28
29 #if DEBUG
30 #define DEBUGP printk
31 #else
32 #define DEBUGP(format, args...)
33 #endif
34
35 #define SECS    1000000         /* unit for wait_not_busy() is 1us */
36
37 unsigned cf_head = 0;
38 unsigned cf_cyl = 0;
39 unsigned cf_spt = 0;
40 unsigned cf_sectors = 0;
41 static unsigned cf_block_size = 1;
42 static void *baddr = 0;
43
44 #define DBUF32 ((volatile u32 *)((unsigned long)dev->baddr | ATA_DBUF_OFFSET))
45
46
47 static void cf_do_tasklet(unsigned long dev_l);
48
49
50 static inline void wareg(u8 val, unsigned reg, struct cf_mips_dev* dev)
51 {
52         writeb(val, dev->baddr + ATA_REG_OFFSET + reg);
53 }
54
55 static inline u8 rareg(unsigned reg, struct cf_mips_dev* dev)
56 {
57         return readb(dev->baddr + ATA_REG_OFFSET + reg);
58 }
59
60 static inline int cfrdy(struct cf_mips_dev *dev)
61 {
62         return gpio_get_value(dev->pin);
63 }
64
65 static inline void prepare_cf_irq(struct cf_mips_dev *dev)
66 {
67         rb500_gpio_set_int_level(1, dev->pin);  /* interrupt on cf ready (not busy) */
68         rb500_gpio_set_int_status(0, dev->pin);         /* clear interrupt status */
69 }
70
71 static inline int cf_present(struct cf_mips_dev* dev)
72 {
73         /* TODO: read and configure CIS into memory mapped mode
74          * TODO:   parse CISTPL_CONFIG on CF+ cards to get base address (0x200)
75          * TODO:   maybe adjust power saving setting for Hitachi Microdrive
76          */
77         int i;
78
79         /* setup CFRDY GPIO as input */
80         rb500_gpio_set_func(dev->pin, 0);
81         gpio_direction_input(dev->pin);
82
83         for (i = 0; i < 0x10; ++i) {
84                 if (rareg(i,dev) != 0xff)
85                         return 1;
86         }
87         return 0;
88 }
89
90 static inline int is_busy(struct cf_mips_dev *dev)
91 {
92         return !cfrdy(dev);
93 }
94
95 static int wait_not_busy(int to_us, int wait_for_busy,struct cf_mips_dev *dev)
96 {
97         int us_passed = 0;
98         if (wait_for_busy && !is_busy(dev)) {
99                 /* busy must appear within 400ns,
100                  * but it may dissapear before we see it
101                  *  => must not wait for busy in a loop
102                  */
103                 ndelay(400);
104         }
105
106         do {
107                 if (us_passed)
108                         udelay(1);      /* never reached in async mode */
109                 if (!is_busy(dev)) {
110                         if (us_passed > 1 * SECS) {
111                                 printk(KERN_WARNING "cf-mips:   not busy ok (after %dus)"
112                                        ", status 0x%02x\n", us_passed, (unsigned) rareg(ATA_REG_ST,dev));
113                         }
114                         return CF_TRANS_OK;
115                 }
116                 if (us_passed == 1 * SECS) {
117                         printk(KERN_WARNING "cf-mips: wait not busy %dus..\n", to_us);
118                 }
119                 if (dev->async_mode) {
120                         dev->to_timer.expires = jiffies + (to_us * HZ / SECS);
121                         dev->irq_enable_time = jiffies;
122                         prepare_cf_irq(dev);
123                         if (is_busy(dev)) {
124                                 add_timer(&dev->to_timer);
125                                 enable_irq(dev->irq);
126                                 return CF_TRANS_IN_PROGRESS;
127                         }
128                         continue;
129                 }
130                 ++us_passed;
131         } while (us_passed < to_us);
132
133         printk(KERN_ERR "cf-mips:  wait not busy timeout (%dus)"
134                ", status 0x%02x, state %d\n",
135                to_us, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
136         return CF_TRANS_FAILED;
137 }
138
139 static irqreturn_t cf_irq_handler(int irq, void *dev_id)
140 {
141         /* While tasklet has not disabled irq, irq will be retried all the time
142          * because of ILEVEL matching GPIO pin status => deadlock.
143          * To avoid this, we change ILEVEL to 0.
144          */
145         struct cf_mips_dev *dev=dev_id;
146
147         rb500_gpio_set_int_level(0, dev->pin);
148         rb500_gpio_set_int_status(0, dev->pin);
149         
150         del_timer(&dev->to_timer);
151         tasklet_schedule(&dev->tasklet);
152         return IRQ_HANDLED;
153 }
154
155 static int do_reset(struct cf_mips_dev *dev)
156 {
157         printk(KERN_INFO "cf-mips: resetting..\n");
158
159         wareg(ATA_REG_DC_SRST, ATA_REG_DC,dev);
160         udelay(1);              /* FIXME: how long should we wait here? */
161         wareg(0, ATA_REG_DC,dev);
162
163         return wait_not_busy(30 * SECS, 1,dev);
164 }
165
166 static int set_multiple(struct cf_mips_dev *dev)
167 {
168         if (dev->block_size <= 1)
169                 return CF_TRANS_OK;
170
171         wareg(dev->block_size, ATA_REG_SC,dev);
172         wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
173         wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
174
175         return wait_not_busy(10 * SECS, 1,dev);
176 }
177
178 static int set_cmd(struct cf_mips_dev *dev)
179 {
180         //DEBUGP(KERN_INFO "cf-mips: ata cmd 0x%02x\n", dev->tcmd);
181         // sector_count should be <=24 bits..
182         BUG_ON(dev->tsect_start>=0x10000000);
183         // This way, it addresses 2^24 * 512 = 128G
184
185         if (dev->tsector_count) {
186                 wareg(dev->tsector_count & 0xff, ATA_REG_SC,dev);
187                 wareg(dev->tsect_start & 0xff, ATA_REG_SN,dev);
188                 wareg((dev->tsect_start >> 8) & 0xff, ATA_REG_CL,dev);
189                 wareg((dev->tsect_start >> 16) & 0xff, ATA_REG_CH,dev);
190         }
191         wareg(((dev->tsect_start >> 24) & 0x0f) | ATA_REG_DH_BASE | ATA_REG_DH_LBA,
192               ATA_REG_DH,dev);  /* select drive on all commands */
193         wareg(dev->tcmd, ATA_REG_CMD,dev);
194         return wait_not_busy(10 * SECS, 1,dev);
195 }
196
197 static int do_trans(struct cf_mips_dev *dev)
198 {
199         int res;
200         unsigned st;
201         int transfered;
202         
203         //printk("do_trans: %d sectors left\n",dev->tsectors_left);
204         while (dev->tsectors_left) {
205                 transfered = 0;
206
207                 st = rareg(ATA_REG_ST,dev);
208                 if (!(st & ATA_REG_ST_DRQ)) {
209                         printk(KERN_ERR "cf-mips: do_trans without DRQ (status 0x%x)!\n", st);
210                         if (st & ATA_REG_ST_ERR) {
211                                 int errId = rareg(ATA_REG_ERR,dev);
212                                 printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
213                                        (dev->tread ? "read" : "write"), st, errId);
214                         }
215                         return CF_TRANS_FAILED;
216                 }
217                 do { /* Fill/read the buffer one block */
218                         u32 *qbuf, *qend;
219                         qbuf = (u32 *)dev->tbuf;
220                         qend = qbuf + CF_SECT_SIZE / sizeof(u32);
221                         if (dev->tread) {
222                             while (qbuf!=qend)
223                                 put_unaligned(*DBUF32,qbuf++);
224                                 //*(qbuf++) = *DBUF32;
225                         }
226                         else {
227                             while(qbuf!=qend)
228                                 *DBUF32 = get_unaligned(qbuf++);
229                         }
230
231                         dev->tsectors_left--;
232                         dev->tbuf += CF_SECT_SIZE;
233                         dev->tbuf_size -= CF_SECT_SIZE;
234                         transfered++;
235                 } while (transfered != dev->block_size && dev->tsectors_left > 0);
236
237                 res = wait_not_busy(10 * SECS, 1,dev);
238                 if (res != CF_TRANS_OK)
239                         return res;
240         };
241
242         st = rareg(ATA_REG_ST,dev);
243         if (st & (ATA_REG_ST_DRQ | ATA_REG_ST_DWF | ATA_REG_ST_ERR)) {
244                 if (st & ATA_REG_ST_DRQ) {
245                         printk(KERN_ERR "cf-mips: DRQ after all %d sectors are %s"
246                                ", status 0x%x\n", dev->tsector_count, (dev->tread ? "read" : "written"), st);
247                 } else if (st & ATA_REG_ST_DWF) {
248                         printk(KERN_ERR "cf-mips: write fault, status 0x%x\n", st);
249                 } else {
250                         int errId = rareg(ATA_REG_ERR,dev);
251                         printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
252                                (dev->tread ? "read" : "write"), st, errId);
253                 }
254                 return CF_TRANS_FAILED;
255         }
256         return CF_TRANS_OK;
257 }
258
259 static int cf_do_state(struct cf_mips_dev *dev)
260 {
261         int res;
262         switch (dev->tstate) {  /* fall through everywhere */
263         case TS_IDLE:
264                 dev->tstate = TS_READY;
265                 if (is_busy(dev)) {
266                         dev->tstate = TS_AFTER_RESET;
267                         res = do_reset(dev);
268                         if (res != CF_TRANS_OK)
269                                 break;
270                 }
271         case TS_AFTER_RESET:
272                 if (dev->tstate == TS_AFTER_RESET) {
273                         dev->tstate = TS_READY;
274                         res = set_multiple(dev);
275                         if (res != CF_TRANS_OK)
276                                 break;
277                 }
278         case TS_READY:
279                 dev->tstate = TS_CMD;
280                 res = set_cmd(dev);
281                 if (res != CF_TRANS_OK)
282                         break;;
283         case TS_CMD:
284                 dev->tstate = TS_TRANS;
285         case TS_TRANS:
286                 res = do_trans(dev);
287                 break;
288         default:
289                 printk(KERN_ERR "cf-mips: BUG: unknown tstate %d\n", dev->tstate);
290                 return CF_TRANS_FAILED;
291         }
292         if (res != CF_TRANS_IN_PROGRESS)
293                 dev->tstate = TS_IDLE;
294         return res;
295 }
296
297 static void cf_do_tasklet(unsigned long dev_l)
298 {
299         struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
300         int res;
301
302         disable_irq(dev->irq);
303
304         if (dev->tstate == TS_IDLE)
305                 return;         /* can happen when irq is first registered */
306
307 #if 0
308         DEBUGP(KERN_WARNING "cf-mips:   not busy ok (tasklet)  status 0x%02x\n",
309                (unsigned) rareg(ATA_REG_ST,dev));
310 #endif
311
312         res = cf_do_state(dev);
313         if (res == CF_TRANS_IN_PROGRESS)
314                 return;
315         cf_async_trans_done(dev,res);
316 }
317
318 static void cf_async_timeout(unsigned long dev_l)
319 {
320         struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
321         disable_irq(dev->irq);
322         /* Perhaps send abort to the device? */
323         printk(KERN_ERR "cf-mips:  wait not busy timeout (%lus)"
324                ", status 0x%02x, state %d\n",
325                jiffies - dev->irq_enable_time, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
326         dev->tstate = TS_IDLE;
327         cf_async_trans_done(dev,CF_TRANS_FAILED);
328 }
329
330 int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect, 
331         char* buffer, int is_write)
332 {
333         BUG_ON(dev->tstate!=TS_IDLE);
334         if (nsect > ATA_MAX_SECT_PER_CMD) {
335                 printk(KERN_WARNING "cf-mips: sector count %lu out of range\n",nsect);
336                 return CF_TRANS_FAILED;
337         }
338         if (sector + nsect > dev->sectors) {
339                 printk(KERN_WARNING "cf-mips: sector %lu out of range\n",sector);
340                 return CF_TRANS_FAILED;
341         }
342         dev->tbuf = buffer;
343         dev->tbuf_size = nsect*512;
344         dev->tsect_start = sector;
345         dev->tsector_count = nsect;
346         dev->tsectors_left = dev->tsector_count;
347         dev->tread = (is_write)?0:1;
348         
349         dev->tcmd = (dev->block_size == 1 ?
350                 (is_write ? ATA_CMD_WRITE_SECTORS : ATA_CMD_READ_SECTORS) :
351                 (is_write ? ATA_CMD_WRITE_MULTIPLE : ATA_CMD_READ_MULTIPLE));
352
353         return cf_do_state(dev);
354 }
355
356 static int do_identify(struct cf_mips_dev *dev)
357 {
358         u16 sbuf[CF_SECT_SIZE >> 1];
359         int res;
360         char tstr[17]; //serial
361         BUG_ON(dev->tstate!=TS_IDLE);
362         dev->tbuf = (char *) sbuf;
363         dev->tbuf_size = CF_SECT_SIZE;
364         dev->tsect_start = 0;
365         dev->tsector_count = 0;
366         dev->tsectors_left = 1;
367         dev->tread = 1;
368         dev->tcmd = ATA_CMD_IDENTIFY_DRIVE;
369
370         DEBUGP(KERN_INFO "cf-mips: identify drive..\n");
371         res = cf_do_state(dev);
372         if (res == CF_TRANS_IN_PROGRESS) {
373                 printk(KERN_ERR "cf-mips: BUG: async identify cmd\n");
374                 return CF_TRANS_FAILED;
375         }
376         if (res != CF_TRANS_OK)
377                 return 0;
378
379         dev->head = sbuf[3];
380         dev->cyl = sbuf[1];
381         dev->spt = sbuf[6];
382         dev->sectors = ((unsigned long) sbuf[7] << 16) | sbuf[8];
383         dev->dtype=sbuf[0];
384         memcpy(tstr,&sbuf[12],16);
385         tstr[16]=0;
386         printk(KERN_INFO "cf-mips: %s detected, C/H/S=%d/%d/%d sectors=%u (%uMB) Serial=%s\n",
387                (sbuf[0] == 0x848A ? "CF card" : "ATA drive"), dev->cyl, dev->head,
388                dev->spt, dev->sectors, dev->sectors >> 11, tstr);
389         return 1;
390 }
391
392 static void init_multiple(struct cf_mips_dev * dev)
393 {
394         int res;
395         DEBUGP(KERN_INFO "cf-mips: detecting block size\n");
396
397         dev->block_size = 128;  /* max block size = 128 sectors (64KB) */
398         do {
399                 wareg(dev->block_size, ATA_REG_SC,dev);
400                 wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
401                 wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
402
403                 res = wait_not_busy(10 * SECS, 1,dev);
404                 if (res != CF_TRANS_OK) {
405                         printk(KERN_ERR "cf-mips: failed to detect block size: busy!\n");
406                         dev->block_size = 1;
407                         return;
408                 }
409                 if ((rareg(ATA_REG_ST,dev) & ATA_REG_ST_ERR) == 0)
410                         break;
411                 dev->block_size /= 2;
412         } while (dev->block_size > 1);
413
414         printk(KERN_INFO "cf-mips: multiple sectors = %d\n", dev->block_size);
415 }
416
417 int cf_init(struct cf_mips_dev *dev)
418 {
419         tasklet_init(&dev->tasklet,cf_do_tasklet,(unsigned long)dev);
420         dev->baddr = ioremap_nocache((unsigned long)dev->base, CFDEV_BUF_SIZE);
421         if (!dev->baddr) {
422                 printk(KERN_ERR "cf-mips: cf_init: ioremap for (%lx,%x) failed\n",
423                        (unsigned long) dev->base, CFDEV_BUF_SIZE);
424                 return -EBUSY;
425         }
426
427         if (!cf_present(dev)) {
428                 printk(KERN_WARNING "cf-mips: cf card not present\n");
429                 iounmap(dev->baddr);
430                 return -ENODEV;
431         }
432
433         if (do_reset(dev) != CF_TRANS_OK) {
434                 printk(KERN_ERR "cf-mips: cf reset failed\n");
435                 iounmap(dev->baddr);
436                 return -EBUSY;
437         }
438
439         if (!do_identify(dev)) {
440                 printk(KERN_ERR "cf-mips: cf identify failed\n");
441                 iounmap(dev->baddr);
442                 return -EBUSY;
443         }
444
445 /*      set_apm_level(ATA_APM_WITH_STANDBY); */
446         init_multiple(dev);
447
448         init_timer(&dev->to_timer);
449         dev->to_timer.function = cf_async_timeout;
450         dev->to_timer.data = (unsigned long)dev;
451
452         prepare_cf_irq(dev);
453         if (request_irq(dev->irq, cf_irq_handler, 0, "CF Mips", dev)) {
454                 printk(KERN_ERR "cf-mips: failed to get irq\n");
455                 iounmap(dev->baddr);
456                 return -EBUSY;
457         }
458         /* Disable below would be odd, because request will enable, and the tasklet
459           will disable it itself */
460         //disable_irq(dev->irq);
461         
462         dev->async_mode = 1;
463
464         return 0;
465 }
466
467 void cf_cleanup(struct cf_mips_dev *dev)
468 {
469         iounmap(dev->baddr);
470         free_irq(dev->irq, NULL);
471 #if REQUEST_MEM_REGION
472         release_mem_region((unsigned long)dev->base, CFDEV_BUF_SIZE);
473 #endif
474 }
475
476
477 /*eof*/