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