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