MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / mmc / host / moxasd.c.johnson
blobc496e1e027de9b034cd8038457a5f02c15937781
1 /*
2  *  linux/drivers/mmc/moxasd.c - Moxa CPU SD/MMC driver
3  *
4  *  Copyright (C) 2005 Moxa Tech., All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  */
11 #if 1   // add by Victor Yu. 02-09-2007
12 #include <linux/version.h>
13 #endif
14 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) // add by Victor Yu. 02-09-2007
15 #include <linux/config.h>
16 #endif
17 #include <asm/arch/cpe/cpe.h>
18 #include <asm/arch/cpe_int.h>
19 #include <linux/module.h>
20 #include <linux/init.h>
21 #include <linux/ioport.h>
22 #include <linux/device.h>
23 #include <linux/delay.h>
24 #include <linux/interrupt.h>
25 #include <linux/blkdev.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/mmc/host.h>
28 #include <linux/sched.h>
29 #include <linux/delay.h>
30 #include <linux/mmc/sd.h>
31 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)  // add by Victor Yu. 03-07-2007
32 #include <linux/platform_device.h>
33 #else
34 #include <linux/device.h>
35 #endif  // LINUX_VERSION_CODE
37 #include <asm/dma.h>
38 #include <asm/io.h>
39 #include <asm/irq.h>
40 #include <asm/sizes.h>
41 #include <asm/arch/gpio.h>
43 #include "moxasd.h"
45 //#define MSD_SUPPORT_GET_CLOCK 1
47 #define MSD_RETRY_COUNT         1000
49 //#define CONFIG_MMC_DEBUG
50 #ifdef CONFIG_MMC_DEBUG
51 #define DBG(x...)       printk(x)
52 #else
53 #define DBG(x...)
54 #endif
56 struct moxasd_host {
57         struct mmc_host         *mmc;
58         spinlock_t              lock;
59         moxasd_reg              *reg;
60         apb_dma_priv            *dma;
61 #ifdef MSD_SUPPORT_GET_CLOCK
62         unsigned int            sysclk;
63 #endif
64         struct mmc_request      *mrq;
65         struct mmc_data         *data;
67         struct scatterlist      *cur_sg;        /* Current SG entry */
68         unsigned int            num_sg;         /* Number of entries left */
69         void                    *mapped_sg;     /* vaddr of mapped sg */
70         unsigned int            offset;         /* Offset into current entry */
71         unsigned int            remain;         /* Data left in curren entry */
72         int                     size;           /* Total size of transfer */
74         struct tasklet_struct   card_change_tasklet;
75         struct tasklet_struct   fifo_run_tasklet;
76 //johnson
77         struct tasklet_struct   data_end_tasklet;
78         struct tasklet_struct   data_crc_tasklet;
79         struct tasklet_struct   data_timeout_tasklet;
80 //johnson
83 static inline void moxasd_init_sg(struct moxasd_host* host, struct mmc_data* data)
85         /*
86          * Get info. about SG list from data structure.
87          */
89         host->cur_sg = data->sg;
90         host->num_sg = data->sg_len;
92         host->offset = 0;
93         host->remain = host->cur_sg->length;
94 #if 1   // add by Victor Yu. 07-04-2007
95         if ( host->remain > host->size )
96                 host->remain = host->size;
97         host->mapped_sg = NULL;
98 #endif
99         data->error = MMC_ERR_NONE;
102 static inline int moxasd_next_sg(struct moxasd_host* host)
104         /*
105          * Skip to next SG entry.
106          */
108         host->cur_sg++;
109         host->num_sg--;
111         /*
112          * Any entries left?
113          */
114         if (host->num_sg > 0) {
115                 host->offset = 0;
116                 host->remain = host->cur_sg->length;
117         }
119         return host->num_sg;
122 static inline char *moxasd_kmap_sg(struct moxasd_host* host)
124         host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ) +
125                 host->cur_sg->offset;
126         return host->mapped_sg;
129 static inline void moxasd_check_data_crc(struct moxasd_host *host, struct mmc_data *data)
131         unsigned int    status;
132         
133         status = readl(&host->reg->status);
134         
135         if ( status & MSD_DATA_CRC_OK ) {
136                 writel(MSD_CLR_DATA_CRC_OK, &host->reg->clear);
137                 host->mrq->cmd->data->error=MMC_ERR_NONE;
138         }
139         else if ( status & MSD_DATA_CRC_FAIL ) {
140                 writel(MSD_CLR_DATA_CRC_FAIL, &host->reg->clear);
141                 //data->error = MMC_ERR_TIMEOUT;
142                 host->mrq->cmd->data->error=MMC_ERR_BADCRC;
143         }else host->mrq->cmd->data->error=MMC_ERR_TIMEOUT;
144         /*if ( status & MSD_DATA_END ) {
145                 writel(MSD_CLR_DATA_END, &host->reg->clear);
146                 
147         }
148         if ( status & MSD_DATA_TIMEOUT ) {
149                 writel(MSD_DATA_TIMEOUT, &host->reg->clear);
150                 host->mrq->cmd->data->error=MMC_ERR_TIMEOUT;
151         }*/
154 static inline int moxasd_check_fifo_ready(struct moxasd_host *host)
156         unsigned int    status;
158         status = readl(&host->reg->status);
159         if ( status & MSD_CARD_DETECT ) {       // card is removed
160                 return 0;
161         }
162         if ( status & (MSD_FIFO_URUN|MSD_FIFO_ORUN) ) {
163                 writel(status&(MSD_FIFO_URUN|MSD_FIFO_ORUN), &host->reg->clear);
164         }
165         if ( status & MSD_DATA_TIMEOUT ) {
166                 writel(MSD_CLR_DATA_TIMEOUT, &host->reg->clear);
167                 return 0;
168         }
169         return 1;
172 static void     moxasd_do_fifo(struct moxasd_host *host, struct mmc_data *data)
174         char    *buffer;
175         int     wcnt, i;
177         if ( host->size == data->bytes_xfered ) {
178                 return;
179         }
180         //buffer = moxasd_kmap_sg(host) + host->offset;
181         buffer = moxasd_kmap_sg(host);
182         if ( host->size > MSD_FIFO_LENB && host->dma ) {
183                 apb_dma_conf_param      param;
184                 param.size = host->remain;
185                 param.burst_mode = APB_DMAB_BURST_MODE;
186                 param.data_width = APB_DMAB_DATA_WIDTH_4;
187                 if ( data->flags & MMC_DATA_WRITE ) {
188                         param.source_addr = (unsigned int)buffer;
189                         param.dest_addr = (unsigned int)&host->reg->data_window;
190                         param.dest_inc = APB_DMAB_DEST_INC_0;
191                         param.source_inc = APB_DMAB_DEST_INC_4_16;
192                         param.dest_sel = APB_DMAB_DEST_APB;
193                         param.source_sel = APB_DMAB_SOURCE_AHB;
194                 } else {
195                         param.dest_addr = (unsigned int)buffer;
196                         param.source_addr = (unsigned int)&host->reg->data_window;
197                         param.source_inc = APB_DMAB_DEST_INC_0;
198                         param.dest_inc = APB_DMAB_DEST_INC_4_16;
199                         param.source_sel = APB_DMAB_DEST_APB;
200                         param.dest_sel = APB_DMAB_SOURCE_AHB;
201                 }
202                 data->bytes_xfered += host->remain;
203 #if 0   // don't need to do this
204                 host->offset = host->remain;
205                 host->remain = 0;
206 #endif
207                 apb_dma_conf(host->dma, &param);
208                 kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
209                 moxasd_next_sg(host);
210                 apb_dma_enable(host->dma);
211         }else{
212 #if 0
213                 if ( host->remain >= MSD_FIFO_LENB )
214                         wcnt = MSD_FIFO_LENW;
215                 else
216 #endif                  
217                         wcnt = host->remain >> 2;
218                 if ( data->flags & MMC_DATA_WRITE ) {
219                         for ( i=0; i<wcnt; i++, buffer+=4 )
220                                 writel(*(unsigned int *)buffer, &host->reg->data_window);
221                 } else {
222                         for ( i=0; i<wcnt; i++, buffer+=4 )
223                                 *(unsigned int *)buffer = readl(&host->reg->data_window);
224                 }
225                 wcnt <<= 2;
226                 host->offset += wcnt;
227                 host->remain -= wcnt;
228                 data->bytes_xfered += wcnt;
229                 kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
231                 /* because this will be just one time
232                 if ( host->remain <= 0 )
233                         moxasd_next_sg(host);
234                 */
235         }
238 static void moxasd_request_done(struct moxasd_host *host)
240         struct mmc_request      *mrq=host->mrq;
242         if ( mrq == NULL ) {
243                 return;
244         }
245         host->mrq = NULL;
246         host->data = NULL;
247         mmc_request_done(host->mmc, mrq);
250 static void moxasd_prepare_data(struct moxasd_host *host, struct mmc_data *data)
252         unsigned int    timeout, datactrl;
253         unsigned int blksz_bit=ffs(data->blksz) - 1;
254         
255         host->data = data;
256         moxasd_init_sg(host, data);
258         // initialize the timeout value
259         timeout = (host->mmc->f_max/1000000) * (data->timeout_ns/1000);
260         timeout += data->timeout_clks;
261         writel(timeout, &host->reg->data_timer);
262         
263         // initialize the data size
264         //host->remain=host->size = data->blocks << data->blksz;//johnson
265         host->remain=host->size = data->blocks << blksz_bit;//johnson
266         writel(host->size, &host->reg->data_length);
268         // initialize the data control
269         //datactrl = (data->blksz & MSD_BLK_SIZE_MASK) | MSD_DATA_EN;
270         datactrl = (blksz_bit & MSD_BLK_SIZE_MASK) | MSD_DATA_EN;
271         
272         if ( data->flags & MMC_DATA_WRITE ) {
273                 datactrl |= MSD_DATA_WRITE;
274         }
275         if ( host->size > MSD_FIFO_LENB && host->dma ) {
276                 datactrl |= MSD_DMA_EN;
277         }
278         writel(datactrl, &host->reg->data_control);
279         writel(4, &host->reg->argument);
280         //printk("DCR:%x data_length:%x data->blocks:%x host->remain:%x\n",host->reg->data_control,host->reg->data_length,data->blocks, host->remain);//johnson
282 #if 1
283         //if ( host->size > MSD_FIFO_LENB && (data->flags & MMC_DATA_READ) ) {
284         if ( host->size > MSD_FIFO_LENB ) {
285                 // disable the overrun & underrun interrupt
286                 unsigned long flags;
287                 local_save_flags/*save_flags*/(flags);
288                 local_irq_disable/*cli*/();
289                 writel(MSD_INT_CARD_CHANGE|/*MSD_INT_DATA_CRC_OK|MSD_INT_DATA_CRC_FAIL*/MSD_INT_DATA_END|MSD_INT_DATA_TIMEOUT, &host->reg->interrupt_mask);
290                 local_irq_restore/*restore_flags*/(flags);
291                 moxasd_do_fifo(host, data);
292         }else{
293                 // enable the overrun & underrun interrupt
294                 unsigned long flags;
295                 local_save_flags/*save_flags*/(flags);
296                 local_irq_disable/*cli*/();
297                 writel(MSD_INT_FIFO_URUN|MSD_INT_FIFO_ORUN|MSD_INT_CARD_CHANGE, &host->reg->interrupt_mask);
298                 local_irq_restore/*restore_flags*/(flags);
299         }
300 #endif
303 static void moxasd_send_command(struct moxasd_host *host, struct mmc_command *cmd)
305         unsigned int    status, cmdctrl;
306         int             retry=0;
308         // first clear status
309         writel(MSD_CLR_RSP_TIMEOUT|MSD_CLR_RSP_CRC_OK|MSD_CLR_RSP_CRC_FAIL|MSD_CLR_CMD_SENT, &host->reg->clear);
311         // write argument
312         writel(cmd->arg, &host->reg->argument);
314         // write command
315         cmdctrl = cmd->opcode & MSD_CMD_IDX_MASK;
316         if ( cmdctrl == SD_APP_SET_BUS_WIDTH ||
317              cmdctrl == SD_APP_OP_COND ||
318              cmdctrl == SD_APP_SEND_SCR )       // this is SD application specific command
319                 cmdctrl |= MSD_APP_CMD;
321         if ( cmd->flags & /*MMC_RSP_LONG*/MMC_RSP_136 )
322                 cmdctrl |= (MSD_LONG_RSP|MSD_NEED_RSP);
323         else if ( cmd->flags & /*MMC_RSP_SHORT*/MMC_RSP_PRESENT )
324                 cmdctrl |= MSD_NEED_RSP;
325         
326         //writel(cmd->flags, &host->reg->argument);     
327         writel(cmdctrl|MSD_CMD_EN, &host->reg->command);
328         
329         // wait response
330         while ( retry++ < MSD_RETRY_COUNT ) {
331                 status = readl(&host->reg->status);
332                 if ( status & MSD_CARD_DETECT ) {       // card is removed
333                         cmd->error = MMC_ERR_TIMEOUT;
334                         return;
335                 }
336                 if ( cmdctrl & MSD_NEED_RSP ) {
337                         if ( status & MSD_RSP_TIMEOUT ) {
338                                 writel(MSD_CLR_RSP_TIMEOUT, &host->reg->clear);
339                                 cmd->error = MMC_ERR_TIMEOUT;
340                                 return;
341                         }
342 #if 0
343                         if ( status & MSD_RSP_CRC_FAIL ) {
344 #else
345                         if ( (cmd->flags&MMC_RSP_CRC) && (status&MSD_RSP_CRC_FAIL) ) {
346 #endif
347                                 writel(MSD_CLR_RSP_CRC_FAIL, &host->reg->clear);
348                                 cmd->error = MMC_ERR_BADCRC;
349                                 return;
350                         }
351                         if ( status & MSD_RSP_CRC_OK ) {
352                                 writel(MSD_CLR_RSP_CRC_OK, &host->reg->clear);
353                                 // read response
354                                 cmd->resp[0] = readl(&host->reg->response0);
355                                 cmd->resp[1] = readl(&host->reg->response1);
356                                 cmd->resp[2] = readl(&host->reg->response2);
357                                 cmd->resp[3] = readl(&host->reg->response3);
358                                 cmd->error = MMC_ERR_NONE;
359                                 return;
360                         }
361                 } else {
362                         if ( status & MSD_CMD_SENT ) {
363                                 writel(MSD_CLR_CMD_SENT, &host->reg->clear);
364                                 cmd->error = MMC_ERR_NONE;
365                                 return;
366                         }
367                 }
368         }
369 //      cmd->error = MMC_ERR_TIMEOUT;
370         cmd->error = MMC_ERR_NONE;
373 //static int moxasd_inited=0;
374 //static void moxasd_dma_irq(void *);
375 static irqreturn_t moxasd_irq(int irq, void *devid/*, struct pt_regs *regs*/)
377         struct moxasd_host      *host=devid;
378         unsigned int            status;
380         // get the interrupt status
382         status = readl(&host->reg->status);
383         
384         // acknowledge the interurpt
385         if ( status & MSD_CARD_CHANGE ) {       // has card inserted or removed
386                 //writel(MSD_CLR_CARD_CHANGE, &host->reg->clear);
387                 tasklet_schedule(&host->card_change_tasklet);
388         }
389         
390         if ( status & (MSD_FIFO_ORUN|MSD_FIFO_URUN) ) {
391                 writel(status&(MSD_FIFO_ORUN|MSD_FIFO_URUN), &host->reg->clear);
392                 tasklet_schedule(&host->fifo_run_tasklet);
393         }
395         if(status & MSD_DATA_CRC_OK){//printk("MSD_DATA_CRC_OK\n");
396                 writel(status&MSD_DATA_CRC_OK, &host->reg->clear);
397                 tasklet_schedule(&host->data_end_tasklet);
398         }else
401         /*if(status & (MSD_DATA_CRC_FAIL)){printk("MSD_DATA_CRC_FAIL\n");
402                 writel(status&(MSD_DATA_CRC_FAIL|MSD_DATA_END), &host->reg->clear);
403                 tasklet_schedule(&host->data_crc_tasklet);      
404         }else*/
407         if(status & MSD_DATA_END){//printk("MSD_DATA_END\n");
408                 writel(status&(MSD_DATA_CRC_FAIL|MSD_DATA_END), &host->reg->clear);
409                 tasklet_schedule(&host->data_end_tasklet);
410         }
412         if(status & MSD_DATA_TIMEOUT){printk("MSD_DATA_TIMEOUT\n");
413                 writel(status&MSD_DATA_TIMEOUT, &host->reg->clear);
414                 tasklet_schedule(&host->data_timeout_tasklet);
415         }
416 //johnson
417         return IRQ_HANDLED;
420 static void moxasd_fifo_run(unsigned long param)
422         struct moxasd_host      *host=(struct moxasd_host *)param;
423         struct mmc_data         *data;
425         /*
426         if ( !moxasd_check_fifo_ready(host) && host->data ) {
427                 host->size = host->data->bytes_xfered;
428                 host->data->error = MMC_ERR_TIMEOUT;
429                 if ( host->dma && host->size > MSD_FIFO_LENB ) {
430                         apb_dma_disable(host->dma);
431                 }
432         }
433         writel(readl(&host->reg->status)&(MSD_FIFO_URUN|MSD_FIFO_ORUN), &host->reg->clear);
434         */
435         
436 spin_lock(&host->lock);
437         if ( host->mrq == NULL ) {
438                 spin_unlock(&host->lock);
439                 return;
440         }
441 #if 0   // never happened
442         if ( host->data == NULL ) {
443                 goto moxasd_fifo_run_done;
444         }
445 #endif
446         data = host->data;
447         moxasd_do_fifo(host, data);
449         if ( host->size == data->bytes_xfered )
450                 if ( !data->stop ){
451                         moxasd_request_done(host);
452                         //tasklet_schedule(&host->data_end_tasklet);
453                 }
455         if ( host->size == data->bytes_xfered ){
456                 if(!(data->flags & MMC_DATA_WRITE) ){
457                         //printk("fifo_run:moxasd_request_done\n");
458                         moxasd_request_done(host);
459                 }       
460         }
461 #if 0
462         if ( host->size == data->bytes_xfered ) {
463 #if 0
464                 // maybe need to check the data is OK or fail
465                 if ( data->error == MMC_ERR_NONE ) {
466                         moxasd_check_data_crc(host, data);
467                 }
468 #endif
469                 
470                 if ( data->stop ) {
471                         moxasd_send_command(host, data->stop);
472                 }
474         } else {
475                 spin_unlock(&host->lock);
476                 //tasklet_schedule(&host->fifo_run_tasklet);
477                 return;
478         }
479 //moxasd_fifo_run_done:
480         moxasd_request_done(host);
481 #endif  
482         spin_unlock(&host->lock);
485 static inline struct mmc_data *moxasd_get_data(struct moxasd_host *host)
487         if (!host->mrq)
488                 return NULL;
489         if (!host->mrq->cmd)
490                 return NULL;
491         if (!host->mrq->cmd->data)
492                 return NULL;
493         return host->mrq->cmd->data;
496 static void moxasd_data_end(unsigned long param)
498         struct moxasd_host      *host=(struct moxasd_host *)param;
499         struct mmc_data         *data;
500         
501         spin_lock(&host->lock);
503         data=moxasd_get_data(host);
504         
505         if(data==NULL){
506                 //goto moxasd_request_done;
507                 spin_unlock(&host->lock);
508                 return;
509         }
511         if ( data->stop ) {
512                 moxasd_send_command(host, data->stop);
513         }
515         //if ( host->size == data->bytes_xfered ){
516                 if(!(host->data->flags & MMC_DATA_WRITE)){
517                         spin_unlock(&host->lock);
518                         return;
519                 }       
520         //}
521         
522 //moxasd_request_done:
523         //printk("data_end:moxasd_request_done\n");
524         moxasd_request_done(host);
525         spin_unlock(&host->lock);
528 static void moxasd_data_crc(unsigned long param)
530         struct moxasd_host *host = (struct moxasd_host *)param;
531         struct mmc_data *data;
533         spin_lock(&host->lock);
535         if (!host->mrq)
536                 goto end;
538         data = moxasd_get_data(host);
539         if (!data)
540                 goto end;
542         data->error = MMC_ERR_BADCRC;
544         tasklet_schedule(&host->data_end_tasklet);
546 end:
547         spin_unlock(&host->lock);
550 static void moxasd_data_timeout(unsigned long param)
552         struct moxasd_host *host = (struct moxasd_host *)param;
553         struct mmc_data *data;
555         spin_lock(&host->lock);
557         if (!host->mrq)
558                 goto end;
560         data = moxasd_get_data(host);
561         if (!data)
562                 goto end;
563         data->error = MMC_ERR_TIMEOUT;
564         tasklet_schedule(&host->data_end_tasklet);
566 end:
567         spin_unlock(&host->lock);
570 static void moxasd_card_change(unsigned long param)
572         struct moxasd_host      *host=(struct moxasd_host *)param;
573         unsigned int            status;
574         int                     delay;
576         spin_lock(&host->lock);
577         udelay(3000);   // to wait the hardware stably for card inserted or removed
578         status = readl(&host->reg->status);
579         if ( status & MSD_CARD_DETECT ) {       // card removed
580                 printk("Moxa CPU SD/MMC card is removed.\n");
581                 delay = 0;
582                 if ( host->data ) {
583                         if ( host->dma && host->size > MSD_FIFO_LENB )
584                                 apb_dma_disable(host->dma);
585                         host->size = host->data->bytes_xfered;
586                         spin_unlock(&host->lock);
587                         moxasd_fifo_run(*(unsigned long *)host);
588                         spin_lock(&host->lock);
589                 }
590         } else {        // card inserted
591                 printk("Moxa CPU SD/MMC card is inserted.\n");
592                 if ( readl(&host->reg->clock_control) & MSD_CLK_SD ) {  // SD
593                         host->mmc->f_max = 25000000;
594                         host->mmc->mode = MMC_MODE_SD;
595                 } else {
596                         host->mmc->f_max = 20000000;
597                         host->mmc->mode = MMC_MODE_MMC;
598                 }
599                 delay = 500;
600         }
601         writel(MSD_CLR_CARD_CHANGE, &host->reg->clear);
602         spin_unlock(&host->lock);
603         mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
606 static void moxasd_dma_irq(void *param)
608         struct moxasd_host      *host=(struct moxasd_host *)param;
610         if ( host->data ) {//printk("moxasd_dma_irq\n");
611                 struct mmc_data *data=host->data;
612                 if ( host->dma->error_flag ) {
613                         host->size = data->bytes_xfered;
614                         data->error = MMC_ERR_TIMEOUT;
615                 }
616 #if 1
617                 tasklet_schedule(&host->fifo_run_tasklet);
618 #endif
619         }
622 static void moxasd_request(struct mmc_host *mmc, struct mmc_request *mrq)
624         struct moxasd_host      *host=mmc_priv(mmc);
625         struct mmc_command      *cmd;
627         spin_lock(&host->lock);
628         host->mrq = mrq;
629         cmd = mrq->cmd;
631         // if no card inserted, return timeout error
632         if ( readl(&host->reg->status) & MSD_CARD_DETECT ) {    // card is removed
633                 cmd->error = MMC_ERR_TIMEOUT;
634                 goto request_done;
635         }
637         // request include data or not
638         if ( cmd->data ) {
639                 moxasd_prepare_data(host, cmd->data);
640         }
642         // do request command
643         moxasd_send_command(host, cmd);
645         if ( cmd->data && cmd->error == MMC_ERR_NONE ) {
646                 spin_unlock(&host->lock);
647                 return;
648         }
651 request_done:
652         moxasd_request_done(host);
653         spin_unlock(&host->lock);
656 #define MIN_POWER       (/*MMC_VDD_360*/23 - MSD_SD_POWER_MASK)
657 static void moxasd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
659         struct moxasd_host      *host=mmc_priv(mmc);
661         spin_lock(&host->lock);
662         if (ios->clock) {
663                 int     div;
664 #ifdef MSD_SUPPORT_GET_CLOCK
665                 div = (host->sysclk / (host->mmc->f_max * 2)) - 1;
666 #else
667                 div = (APB_CLK / (host->mmc->f_max * 2)) - 1;
668 #endif
669                 if ( div > MSD_CLK_DIV_MASK )
670                         div = MSD_CLK_DIV_MASK;
671                 else if ( div < 0 )
672                         div = 0;
673                 if ( host->mmc->mode == MMC_MODE_SD )
674                         div |= MSD_CLK_SD;
675                 writel(div, &host->reg->clock_control);
676         } else if ( !(readl(&host->reg->clock_control) & MSD_CLK_DIS) ) {
677                 /*
678                  * Ensure that the clock is off.
679                  */
680                 writel(readl(&host->reg->clock_control)|MSD_CLK_DIS, &host->reg->clock_control);
681         }
683         if ( ios->power_mode == MMC_POWER_OFF ) {
684                 writel(readl(&host->reg->power_control)&~MSD_SD_POWER_ON, &host->reg->power_control);
685         } else {
686                 unsigned short  power;
687                 if ( ios->vdd < MIN_POWER )
688                         power = 0;
689                 else
690                         power = ios->vdd - MIN_POWER;
691                 writel(MSD_SD_POWER_ON|(unsigned int)power, &host->reg->power_control);
692         }
694 #if 1
695         if ( ios->bus_width == MMC_BUS_WIDTH_1 ) {
696                 writel(MSD_SINGLE_BUS, &host->reg->bus_width);
697         } else {
698                 writel(MSD_WIDE_BUS, &host->reg->bus_width);
699         }
700 #endif
701         spin_unlock(&host->lock);
704 /* 
705  * To check write protect or not. Return 0 for none, 1 for write protect.
706  */
707 static int      moxasd_get_ro(struct mmc_host *mmc)
709         struct moxasd_host      *host=mmc_priv(mmc);
711         if ( readl(&host->reg->status) & MSD_WRITE_PROT )
712                 return 1;
713         else
714                 return 0;
717 static struct mmc_host_ops moxasd_ops = {
718         .request        = moxasd_request,
719         .set_ios        = moxasd_set_ios,
720         .get_ro         = moxasd_get_ro,
723 //static int moxasd_probe(struct device *dev)
724 static int moxasd_probe(struct platform_device *pdev)
726         struct device *dev = &pdev->dev;
727         struct mmc_host         *mmc;
728         struct moxasd_host      *host=NULL;
729         int                     ret;
731         mmc = mmc_alloc_host(sizeof(struct moxasd_host), dev);
732         if (!mmc) {
733                 ret = -ENOMEM;
734                 goto out;
735         }
737         mmc->ops = &moxasd_ops;
738         mmc->f_min = 400000;
739         mmc->f_max = 25000000;
741         mmc->mode = MMC_MODE_SD;
742 #if 1
743         mmc->ocr_avail = 0xffff00;      // support 2.0v - 3.6v power
744 #else
745         mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
746         mmc->caps = MMC_CAP_4_BIT_DATA;
747         mmc->max_hw_segs = 128;
748         mmc->max_phys_segs = 128;
749         mmc->max_sectors = 128;
750         mmc->max_seg_size = mmc->max_sectors * 512;
751 #endif
752         host = mmc_priv(mmc);
753         host->mmc = mmc;
754         spin_lock_init(&host->lock);
755         tasklet_init(&host->card_change_tasklet, moxasd_card_change, (unsigned long)host);
756         tasklet_init(&host->fifo_run_tasklet, moxasd_fifo_run, (unsigned long)host);
757 //johnson
758         tasklet_init(&host->data_end_tasklet, moxasd_data_end, (unsigned long)host);
759         tasklet_init(&host->data_crc_tasklet, moxasd_data_crc, (unsigned long)host);
760         tasklet_init(&host->data_timeout_tasklet, moxasd_data_timeout, (unsigned long)host);
761 //johnson
762         host->reg = (moxasd_reg *)CPE_SD_VA_BASE;
763         host->dma = apb_dma_alloc(APB_DMA_SD_REQ_NO);
765         if ( host->dma ) {
766                 apb_dma_set_irq(host->dma, moxasd_dma_irq, host);
767         }
769 #ifdef MSD_SUPPORT_GET_CLOCK
770         // get system clock
771         {
772         unsigned int    mul, val, div;
773         mul = (*(volatile unsigned int *)(CPE_PMU_VA_BASE+0x30) >> 3) & 0x1ff;
774         val = (*(volatile unsigned int *)(CPE_PMU_VA_BASE+0x0c) >> 4) & 0x7;
775         switch ( val ) {
776         case 0 :        div = 2;        break;
777         case 1 :        div = 3;        break;
778         case 2 :        div = 4;        break;
779         case 3 :        div = 6;        break;
780         case 4 :        div = 8;        break;
781         default :       div = 2;        break;
782         }
783         host->sysclk = (38684*mul + 10000) / (div * 10000);
784         host->sysclk = (host->sysclk * 1000000) / 2;
785         }
786 #endif
788         // change I/O multiplexing to SD, so the GPIO 17-10 will be fail
789 #if 0   // mask by Victor Yu. 03-06-2006
790         *(volatile unsigned int *)(CPE_PMU_VA_BASE+0x100) &= (~(0xff<<10));
791 #else   // add by Victor Yu. 03-06-2006
792         mcpu_gpio_mp_clear(0xff<<10);
793 #endif
795         /*
796          * Ensure that the host controller is shut down, and setup
797          * with our defaults.
798          */
799         writel(0, &host->reg->interrupt_mask);  // disable all interrupt
800         writel(MSD_SDC_RST, &host->reg->command);       // reset chip
801         while ( readl(&host->reg->command) & MSD_SDC_RST);      // wait for reset finished
802         writel(0, &host->reg->interrupt_mask);  // disable all interrupt
804         // to check any card inserted or not
805 #if 1
806         if ( !(readl(&host->reg->status) & MSD_CARD_DETECT) ) { // is inserted
807                 if ( readl(&host->reg->clock_control) & MSD_CLK_SD ) {  // is SD card
808                         mmc->f_max = 25000000;
809                         mmc->mode = MMC_MODE_SD;
810                 } else {        // is MMC card
811                         mmc->f_max = 20000000;
812                         mmc->mode = MMC_MODE_MMC;
813                 }
814         }
815 #endif
817         mmc->caps = MMC_CAP_4_BIT_DATA;
818         writel(MSD_WIDE_BUS, &host->reg->bus_width);
820         cpe_int_set_irq(IRQ_SD, EDGE, H_ACTIVE);
821         ret = request_irq(IRQ_SD, moxasd_irq, /*IRQF_SHARED*/SA_INTERRUPT, "moxart-sd"/*"MOXASD"*/, host);
822         if (ret)
823                 goto out;
825         //writel(MSD_INT_CARD_CHANGE|MSD_INT_FIFO_ORUN|MSD_INT_FIFO_URUN, &host->reg->interrupt_mask);
826         writel(MSD_INT_CARD_CHANGE, &host->reg->interrupt_mask);
827         dev_set_drvdata(dev, mmc);
828         mmc_add_host(mmc);
830         return 0;
832  out:
833         if (mmc)
834                 mmc_free_host(mmc);
836         return ret;
839 static int moxasd_remove(struct platform_device *pdev)
841         struct device *dev = &pdev->dev;
842         struct mmc_host *mmc=dev_get_drvdata(dev);
843         
844         dev_set_drvdata(dev, NULL);
846         if (mmc) {
847                 struct moxasd_host      *host=mmc_priv(mmc);
849                 mmc_remove_host(mmc);
851                 // stop SD/MMC
852                 if ( host->dma ) {
853                         apb_dma_disable(host->dma);
854                         apb_dma_release_irq(host->dma);
855                         apb_dma_release(host->dma);
856                 }
857                 writel(0, &host->reg->interrupt_mask);
858                 writel(0, &host->reg->power_control);
859                 writel(readl(&host->reg->clock_control)|MSD_CLK_DIS, &host->reg->clock_control);
861                 free_irq(IRQ_SD, host);
862                 tasklet_kill(&host->card_change_tasklet);
863                 tasklet_kill(&host->fifo_run_tasklet);
864                 //johnson
865                 tasklet_kill(&host->data_end_tasklet);
866                 tasklet_kill(&host->data_crc_tasklet);
867                 tasklet_kill(&host->data_timeout_tasklet);
868                 //johnson
869                 mmc_free_host(mmc);
870         }
871         return 0;
874 static struct platform_device moxasd_device = {
875         .name   = "moxart-sd",
876         .id     = -1,
879 static struct device_driver moxasd_driver = {
880         .name           = "moxart-sd",
881         .bus            = &platform_bus_type,
882         .probe          = moxasd_probe,
883         .remove         = moxasd_remove,
886 static int __init moxasd_init(void)
888         int     ret;
890         printk("Moxa CPU SD/MMC Device Driver V1.0 initialize ");
891         platform_device_register(&moxasd_device);
892         ret = driver_register(&moxasd_driver);
893         if ( ret ) {
894                 printk("fail !\n");
895                 platform_device_unregister(&moxasd_device);
896         } else {
897                 printk("OK.\n");
898         }
899         return ret;
902 static void __exit moxasd_exit(void)
904         platform_device_unregister(&moxasd_device);
905         driver_unregister(&moxasd_driver);
908 module_init(moxasd_init);
909 module_exit(moxasd_exit);
911 MODULE_DESCRIPTION("Moxa CPU SD/Multimedia Card Interface Driver");
912 MODULE_LICENSE("GPL");