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.
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>
9 This work is redistributed under the terms of the GNU General Public License.
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>
24 #define REQUEST_MEM_REGION 0
30 #define DEBUGP(format, args...)
33 #define SECS 1000000 /* unit for wait_not_busy() is 1us */
38 unsigned cf_sectors
= 0;
39 static unsigned cf_block_size
= 1;
40 static void *baddr
= 0;
42 #define DBUF32 ((volatile u32 *)((unsigned long)dev->baddr | ATA_DBUF_OFFSET))
45 static void cf_do_tasklet(unsigned long dev_l
);
48 static inline void wareg(u8 val
, unsigned reg
, struct cf_mips_dev
* dev
)
50 writeb(val
, dev
->baddr
+ ATA_REG_OFFSET
+ reg
);
53 static inline u8
rareg(unsigned reg
, struct cf_mips_dev
* dev
)
55 return readb(dev
->baddr
+ ATA_REG_OFFSET
+ reg
);
58 static inline int get_gpio_bit(gpio_func ofs
, struct cf_mips_dev
*dev
)
60 return (gpio_get(ofs
) >> dev
->pin
) & 1;
63 static inline void set_gpio_bit(int bit
, gpio_func ofs
, struct cf_mips_dev
*dev
)
65 gpio_set(ofs
, (1 << dev
->pin
), ((bit
& 1) << dev
->pin
));
68 static inline int cfrdy(struct cf_mips_dev
*dev
)
70 return get_gpio_bit(DATA
, dev
);
73 static inline void prepare_cf_irq(struct cf_mips_dev
*dev
)
75 set_gpio_bit(1, ILEVEL
, dev
); /* interrupt on cf ready (not busy) */
76 set_gpio_bit(0, ISTAT
, dev
); /* clear interrupt status */
79 static inline int cf_present(struct cf_mips_dev
* dev
)
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
87 /* setup CFRDY GPIO as input */
88 set_gpio_bit(0, FUNC
, dev
);
89 set_gpio_bit(0, CFG
, dev
);
91 for (i
= 0; i
< 0x10; ++i
) {
92 if (rareg(i
,dev
) != 0xff)
98 static inline int is_busy(struct cf_mips_dev
*dev
)
103 static int wait_not_busy(int to_us
, int wait_for_busy
,struct cf_mips_dev
*dev
)
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
116 udelay(1); /* never reached in async mode */
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
));
124 if (us_passed
== 1 * SECS
) {
125 printk(KERN_WARNING
"cf-mips: wait not busy %dus..\n", to_us
);
127 if (dev
->async_mode
) {
128 dev
->to_timer
.expires
= jiffies
+ (to_us
* HZ
/ SECS
);
129 dev
->irq_enable_time
= jiffies
;
132 add_timer(&dev
->to_timer
);
133 enable_irq(dev
->irq
);
134 return CF_TRANS_IN_PROGRESS
;
139 } while (us_passed
< to_us
);
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
;
147 static irqreturn_t
cf_irq_handler(int irq
, void *dev_id
)
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.
153 struct cf_mips_dev
*dev
=dev_id
;
155 set_gpio_bit(0, ILEVEL
, dev
);
156 set_gpio_bit(0, ISTAT
, dev
);
158 del_timer(&dev
->to_timer
);
159 tasklet_schedule(&dev
->tasklet
);
163 static int do_reset(struct cf_mips_dev
*dev
)
165 printk(KERN_INFO
"cf-mips: resetting..\n");
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
);
171 return wait_not_busy(30 * SECS
, 1,dev
);
174 static int set_multiple(struct cf_mips_dev
*dev
)
176 if (dev
->block_size
<= 1)
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
);
183 return wait_not_busy(10 * SECS
, 1,dev
);
186 static int set_cmd(struct cf_mips_dev
*dev
)
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
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
);
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
);
205 static int do_trans(struct cf_mips_dev
*dev
)
211 //printk("do_trans: %d sectors left\n",dev->tsectors_left);
212 while (dev
->tsectors_left
) {
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
);
223 return CF_TRANS_FAILED
;
225 do { /* Fill/read the buffer one block */
227 qbuf
= (u32
*)dev
->tbuf
;
228 qend
= qbuf
+ CF_SECT_SIZE
/ sizeof(u32
);
231 put_unaligned(*DBUF32
,qbuf
++);
232 //*(qbuf++) = *DBUF32;
236 *DBUF32
= get_unaligned(qbuf
++);
239 dev
->tsectors_left
--;
240 dev
->tbuf
+= CF_SECT_SIZE
;
241 dev
->tbuf_size
-= CF_SECT_SIZE
;
243 } while (transfered
!= dev
->block_size
&& dev
->tsectors_left
> 0);
245 res
= wait_not_busy(10 * SECS
, 1,dev
);
246 if (res
!= CF_TRANS_OK
)
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
);
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
);
262 return CF_TRANS_FAILED
;
267 static int cf_do_state(struct cf_mips_dev
*dev
)
270 switch (dev
->tstate
) { /* fall through everywhere */
272 dev
->tstate
= TS_READY
;
274 dev
->tstate
= TS_AFTER_RESET
;
276 if (res
!= CF_TRANS_OK
)
280 if (dev
->tstate
== TS_AFTER_RESET
) {
281 dev
->tstate
= TS_READY
;
282 res
= set_multiple(dev
);
283 if (res
!= CF_TRANS_OK
)
287 dev
->tstate
= TS_CMD
;
289 if (res
!= CF_TRANS_OK
)
292 dev
->tstate
= TS_TRANS
;
297 printk(KERN_ERR
"cf-mips: BUG: unknown tstate %d\n", dev
->tstate
);
298 return CF_TRANS_FAILED
;
300 if (res
!= CF_TRANS_IN_PROGRESS
)
301 dev
->tstate
= TS_IDLE
;
305 static void cf_do_tasklet(unsigned long dev_l
)
307 struct cf_mips_dev
* dev
=(struct cf_mips_dev
*) dev_l
;
310 disable_irq(dev
->irq
);
312 if (dev
->tstate
== TS_IDLE
)
313 return; /* can happen when irq is first registered */
316 DEBUGP(KERN_WARNING
"cf-mips: not busy ok (tasklet) status 0x%02x\n",
317 (unsigned) rareg(ATA_REG_ST
,dev
));
320 res
= cf_do_state(dev
);
321 if (res
== CF_TRANS_IN_PROGRESS
)
323 cf_async_trans_done(dev
,res
);
326 static void cf_async_timeout(unsigned long dev_l
)
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
);
338 int cf_do_transfer(struct cf_mips_dev
* dev
,sector_t sector
, unsigned long nsect
,
339 char* buffer
, int is_write
)
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
;
346 if (sector
+ nsect
> dev
->sectors
) {
347 printk(KERN_WARNING
"cf-mips: sector %lu out of range\n",sector
);
348 return CF_TRANS_FAILED
;
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;
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
));
361 return cf_do_state(dev
);
364 static int do_identify(struct cf_mips_dev
*dev
)
366 u16 sbuf
[CF_SECT_SIZE
>> 1];
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;
376 dev
->tcmd
= ATA_CMD_IDENTIFY_DRIVE
;
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
;
384 if (res
!= CF_TRANS_OK
)
390 dev
->sectors
= ((unsigned long) sbuf
[7] << 16) | sbuf
[8];
392 memcpy(tstr
,&sbuf
[12],16);
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
);
400 static void init_multiple(struct cf_mips_dev
* dev
)
403 DEBUGP(KERN_INFO
"cf-mips: detecting block size\n");
405 dev
->block_size
= 128; /* max block size = 128 sectors (64KB) */
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
);
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");
417 if ((rareg(ATA_REG_ST
,dev
) & ATA_REG_ST_ERR
) == 0)
419 dev
->block_size
/= 2;
420 } while (dev
->block_size
> 1);
422 printk(KERN_INFO
"cf-mips: multiple sectors = %d\n", dev
->block_size
);
425 int cf_init(struct cf_mips_dev
*dev
)
427 tasklet_init(&dev
->tasklet
,cf_do_tasklet
,(unsigned long)dev
);
428 dev
->baddr
= ioremap_nocache((unsigned long)dev
->base
, CFDEV_BUF_SIZE
);
430 printk(KERN_ERR
"cf-mips: cf_init: ioremap for (%lx,%x) failed\n",
431 (unsigned long) dev
->base
, CFDEV_BUF_SIZE
);
435 if (!cf_present(dev
)) {
436 printk(KERN_WARNING
"cf-mips: cf card not present\n");
441 if (do_reset(dev
) != CF_TRANS_OK
) {
442 printk(KERN_ERR
"cf-mips: cf reset failed\n");
447 if (!do_identify(dev
)) {
448 printk(KERN_ERR
"cf-mips: cf identify failed\n");
453 /* set_apm_level(ATA_APM_WITH_STANDBY); */
456 init_timer(&dev
->to_timer
);
457 dev
->to_timer
.function
= cf_async_timeout
;
458 dev
->to_timer
.data
= (unsigned long)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");
466 /* Disable below would be odd, because request will enable, and the tasklet
467 will disable it itself */
468 //disable_irq(dev->irq);
475 void cf_cleanup(struct cf_mips_dev
*dev
)
478 free_irq(dev
->irq
, NULL
);
479 #if REQUEST_MEM_REGION
480 release_mem_region((unsigned long)dev
->base
, CFDEV_BUF_SIZE
);
This page took 0.068828 seconds and 5 git commands to generate.