您的位置:首页 > 运维架构 > Linux

S3C2440+Linux2.6mmc/sd驱动程序

2009-03-21 15:54 211 查看
S3C2440+Linux2.6mmc/sd驱动程序

这几天要做SD卡方面的事情了,看了看相关资料,从网上得到了 s3c2440 在2.6下的驱动,经过修改,目前可以工作了,
现拿出与大家分享.希望共同学习讨论.

1 /*
2 * linux/drivers/mmc/s3c2410mci.h - Samsung S3C2410 SDI Interface driver
3 *
4 * Copyright (C) 2004 Thomas Kleffel, 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 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19 #include
20 #include
21 #include
22 #include
23 #include
24 #include
25 #include
26
27 #include
28 #include
29 #include
30
31 #include
32 #include
33 #include
34
35 #include
36 #include
37 #include
38
39 //#define CONFIG_MMC_DEBUG
#ifdef CONFIG_MMC_DEBUG
42 #define DBG(x...) printk(KERN_INFO x)
43 #else
44 #define DBG(x...) do { } while (0)
45 #endif
46
47 #include "s3c2440mci.h"
48
49 #define DRIVER_NAME "mmci-s3c2410"
50 #define PFX DRIVER_NAME ": "
51
52 #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
53
54 static struct s3c2410_dma_client s3c2410sdi_dma_client = {
55 .name = "s3c2410-sdi",
56 };
static irqreturn_t s3c2410sdi_irq(int irq, void *dev_id, struct pt_regs *regs)
82 {
83 struct s3c2410sdi_host *host;
84 u32 sdi_csta, sdi_dsta, sdi_dcnt;
85 u32 sdi_cclear, sdi_dclear;
86 unsigned long iflags;
87
88 host = (struct s3c2410sdi_host *)dev_id;
89
90 /* Check for things not supposed to happen */
91 if(!host) return IRQ_HANDLED;
92
93 sdi_csta = readl(host->base + S3C2410_SDICMDSTAT);
94 sdi_dsta = readl(host->base + S3C2410_SDIDSTA);
95 sdi_dcnt = readl(host->base + S3C2410_SDIDCNT);
96
97 DBG(PFX "IRQ csta=0x%08x dsta=0x%08x dcnt:0x%08x/n", sdi_csta, sdi_dsta, sdi_dcnt);
98
99 spin_lock_irqsave( &host->complete_lock, iflags);
100
101 if( host->complete_what == COMPLETION_NONE ) {
102 goto clear_imask;
103 }
104
105 if(!host->mrq) {
106 goto clear_imask;
107 }
108
109 sdi_csta = readl(host->base + S3C2410_SDICMDSTAT);
110 sdi_dsta = readl(host->base + S3C2410_SDIDSTA);
111 sdi_dcnt = readl(host->base + S3C2410_SDIDCNT);
112 sdi_cclear = 0;
113 sdi_dclear = 0;
if(sdi_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
117 DBG(PFX "CMD TIMEOUT/n");
118 host->mrq->cmd->error = MMC_ERR_TIMEOUT;
119 goto transfer_closed;
120 }
121
122 if(sdi_csta & S3C2410_SDICMDSTAT_CMDSENT) {
123 if(host->complete_what == COMPLETION_CMDSENT) {
124 DBG(PFX "COMPLETION_CMDSENT/n");
125 host->mrq->cmd->error = MMC_ERR_NONE;
126 goto transfer_closed;
127 }
128
129 sdi_cclear |= S3C2410_SDICMDSTAT_CMDSENT;
130 }
131
132 if(sdi_csta & S3C2410_SDICMDSTAT_CRCFAIL) {
133
134 DBG(PFX "S3C2410_SDICMDSTAT_CRCFAIL/n");
135
136 if ((host->mrq->cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
137 DBG(PFX "s3c2410 fixup : ignore CRC fail with long rsp/n");
138 DBG(PFX "host->mrq->cmd->flags = %x/n", host->mrq->cmd->flags);
139 }
140 else {
141 if(host->mrq->cmd->flags & MMC_RSP_CRC) {
142 DBG(PFX "COMMAND CRC FAILED %x/n", sdi_csta);
143 host->mrq->cmd->error = MMC_ERR_BADCRC;
144 goto transfer_closed;
145 }
146 }
147 sdi_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
148 }
if(sdi_csta & S3C2410_SDICMDSTAT_RSPFIN) {
151
152 DBG(PFX "S3C2410_SDICMDSTAT_RSPFIN/n");
153 if(host->complete_what == COMPLETION_RSPFIN) {
154 host->mrq->cmd->error = MMC_ERR_NONE;
155 goto transfer_closed;
156 }
157
158 if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
159 host->mrq->cmd->error = MMC_ERR_NONE;
160 host->complete_what = COMPLETION_XFERFINISH;
161 }
162
163 sdi_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
164 }
165
166 if(sdi_dsta & S3C2410_SDIDSTA_FIFOFAIL) {
167 DBG(PFX "S3C2410_SDIDSTA_FIFOFAIL/n");
168 host->mrq->cmd->error = MMC_ERR_NONE;
169 host->mrq->data->error = MMC_ERR_FIFO;
170 goto transfer_closed;
171 }
172
173 if(sdi_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {
174 DBG(PFX "S3C2410_SDIDSTA_RXCRCFAIL/n");
175 host->mrq->cmd->error = MMC_ERR_NONE;
176 host->mrq->data->error = MMC_ERR_BADCRC;
177 goto transfer_closed;
178 }
179
180 if(sdi_dsta & S3C2410_SDIDSTA_CRCFAIL) {
181 DBG(PFX "DATA CRC FAILED %u/n", sdi_csta);
182 host->mrq->cmd->error = MMC_ERR_NONE;
183 host->mrq->data->error = MMC_ERR_BADCRC;
184 goto transfer_closed;
185 }

if(sdi_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {
188 DBG(PFX "S3C2410_SDIDSTA_DATATIMEOUT/n");
189 host->mrq->cmd->error = MMC_ERR_NONE;
190 host->mrq->data->error = MMC_ERR_TIMEOUT;
191 goto transfer_closed;
192 }
193
194 if(sdi_dsta & S3C2410_SDIDSTA_XFERFINISH) {
195 DBG(PFX "S3C2410_SDIDSTA_XFERFINISH/n");
196 if(host->complete_what == COMPLETION_XFERFINISH) {
197 DBG(PFX "COMPLETION_XFERFINISH/n");
198 host->mrq->cmd->error = MMC_ERR_NONE;
199 host->mrq->data->error = MMC_ERR_NONE;
200 goto transfer_closed;
201 }
202
203 if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
204 DBG(PFX "COMPLETION_XFERFINISH_RSPFIN/n");
205 host->mrq->data->error = MMC_ERR_NONE;
206 host->complete_what = COMPLETION_RSPFIN;
207 }
208
209 sdi_dclear |= S3C2410_SDIDSTA_XFERFINISH;
210 }
211
212 writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);
213 writel(sdi_dclear, host->base + S3C2410_SDIDSTA);
214
215 spin_unlock_irqrestore( &host->complete_lock, iflags);
216 DBG(PFX "IRQ still waiting./n");
217 return IRQ_HANDLED;

transfer_closed:
221 writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);
222 writel(sdi_dclear, host->base + S3C2410_SDIDSTA);
223 host->complete_what = COMPLETION_NONE;
224 complete(&host->complete_request);
225 writel(0, host->base + S3C2440_SDIIMSK);
226 spin_unlock_irqrestore( &host->complete_lock, iflags);
227 DBG(PFX "IRQ transfer closed./n");
228 return IRQ_HANDLED;
229
230 clear_imask:
231 writel(0, host->base + S3C2440_SDIIMSK);
232 spin_unlock_irqrestore( &host->complete_lock, iflags);
233 DBG(PFX "IRQ clear imask./n");
234 return IRQ_HANDLED;
235
236 }
237
238
239 /*
240 * ISR for the CardDetect Pin
241 */
242
243 static irqreturn_t s3c2410sdi_irq_cd(int irq, void *dev_id, struct pt_regs *regs)
244 {
245 struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)dev_id;
246
247 //DBG(" %s : %s :%s/n", __FUNCTION__, __FILE__, __LINE__);
248
249 mmc_detect_change(host->mmc, S3C2410SDI_CDLATENCY);
250
251 return IRQ_HANDLED;
252 }
253
void s3c2410sdi_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
257 int size, enum s3c2410_dma_buffresult result)
258 { unsigned long iflags;
259 u32 sdi_csta, sdi_dsta,sdi_dcnt;
260 struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)buf_id;
261
262 sdi_csta = readl(host->base + S3C2410_SDICMDSTAT);
263 sdi_dsta = readl(host->base + S3C2410_SDIDSTA);
264 sdi_dcnt = readl(host->base + S3C2410_SDIDCNT);
265
266 DBG(PFX "DMAD csta=0x%08x dsta=0x%08x dcnt:0x%08x result:0x%08x/n", sdi_csta, sdi_dsta, sdi_dcnt, result);
267
268 spin_lock_irqsave( &host->complete_lock, iflags);
269
270 if(!host->mrq) goto out;
271 if(!host->mrq->data) goto out;
272
273
274 sdi_csta = readl(host->base + S3C2410_SDICMDSTAT);
275 sdi_dsta = readl(host->base + S3C2410_SDIDSTA);
276 sdi_dcnt = readl(host->base + S3C2410_SDIDCNT);
277
278 if( result!=S3C2410_RES_OK ) {
279 goto fail_request;
280 }
281
282
283 if(host->mrq->data->flags & MMC_DATA_READ) {
284 if( sdi_dcnt>0 ) {
285 goto fail_request;
286 }
287 }
288
289 out:
290 complete(&host->complete_dma);
291 spin_unlock_irqrestore( &host->complete_lock, iflags);
292 return;
293
fail_request:
296 host->mrq->data->error = MMC_ERR_FAILED;
297 host->complete_what = COMPLETION_NONE;
298 complete(&host->complete_request);
299 writel(0, host->base + S3C2440_SDIIMSK);
300 goto out;
301
302 }
303
304
305 void s3c2410sdi_dma_setup(struct s3c2410sdi_host *host, enum s3c2410_dmasrc source) {
306
307 s3c2410_dma_devconfig(host->dma, source, 3, host->mem->start + S3C2440_SDIDATA);
308 s3c2410_dma_config(host->dma, 4, (1<<23) | (2<<24));
309 s3c2410_dma_set_buffdone_fn(host->dma, s3c2410sdi_dma_done_callback);
310 s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
311 }
312
313 static void s3c2410sdi_request(struct mmc_host *mmc, struct mmc_request *mrq) {
314 struct s3c2410sdi_host *host = mmc_priv(mmc);
315 struct device *dev = mmc_dev(host->mmc);
316 struct platform_device *pdev = to_platform_device(dev);
317 u32 sdi_carg, sdi_ccon, sdi_timer;
318 u32 sdi_bsize, sdi_dcon, sdi_imsk;
319 u32 sdi_fsta;
320
321 int dma_len = 0;
322
323 DBG(KERN_DEBUG PFX "request: [CMD] opcode:0x%02x arg:0x%08x flags:%x retries:%u/n",
324 mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags, mrq->cmd->retries);
325
326 DBG(PFX "request : %s mode/n",mmc->mode == MMC_MODE_MMC ? "mmc" : "sd");
328 sdi_ccon = mrq->cmd->opcode & S3C2410_SDICMDCON_INDEX;
329 sdi_ccon |= S3C2410_SDICMDCON_SENDERHOST;
330 sdi_ccon |= S3C2410_SDICMDCON_CMDSTART;
331
332 //sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
333 sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
334
335 sdi_carg = mrq->cmd->arg;
336
337 //sdi_timer= 0xF000;
338 sdi_timer= 0x7fffff;
339
340 sdi_bsize= 0;
341 sdi_dcon = 0;
342 sdi_imsk = 0;
343
344 /* enable interrupts for transmission errors */
345 sdi_imsk |= S3C2410_SDIIMSK_RESPONSEND;
346 sdi_imsk |= S3C2410_SDIIMSK_CRCSTATUS;
347
348 host->complete_what = COMPLETION_CMDSENT;
349
350 if ((mrq->cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) {
351 host->complete_what = COMPLETION_RSPFIN;
352
353 sdi_ccon |= S3C2410_SDICMDCON_WAITRSP;
354 sdi_imsk |= S3C2410_SDIIMSK_CMDTIMEOUT;
355
356 } else {
357 /* We need the CMDSENT-Interrupt only if we want are not waiting
358 * for a response
359 */
360 sdi_imsk |= S3C2410_SDIIMSK_CMDSENT;
361 }
362
363 //if(mrq->cmd->flags & MMC_RSP_LONG) {
364 if((mrq->cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
365 sdi_ccon |= S3C2410_SDICMDCON_LONGRSP;
366 }
367
368 if(mrq->cmd->flags & MMC_RSP_CRC) {
369 sdi_imsk |= S3C2410_SDIIMSK_RESPONSECRC;
370 }
371
372 if (mrq->data) {
373 host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
374
375 sdi_bsize = (1 << mrq->data->blksz_bits);
376 host->size = mrq->data->blocks << mrq->data->blksz_bits;
377
378 sdi_dcon = (mrq->data->blocks & S3C2410_SDIDCON_BLKNUM_MASK);
379 sdi_dcon |= S3C2410_SDIDCON_DMAEN;
380
381 sdi_dcon |= S3C2410_SDIDCON_DATA_WORD;
382 sdi_dcon |= S3C2410_SDIDCON_DTST;
383
384 sdi_imsk |= S3C2410_SDIIMSK_FIFOFAIL;
385 sdi_imsk |= S3C2410_SDIIMSK_DATACRC;
386 sdi_imsk |= S3C2410_SDIIMSK_DATATIMEOUT;
387 sdi_imsk |= S3C2410_SDIIMSK_DATAFINISH;
388 sdi_imsk |= 0xFFFFFFE0;
389
390 sdi_fsta |= S3C2440_SDIFSTA_FIFORESET;
391
392 DBG(PFX "request: [DAT] bsize:%u blocks:%u bytes:%u/n",
393 sdi_bsize, mrq->data->blocks, mrq->data->blocks * sdi_bsize);
394
395
396 if (host->bus_width == MMC_BUS_WIDTH_4) {
397 sdi_dcon |= S3C2410_SDIDCON_WIDEBUS;
398 }
399
400 if(!(mrq->data->flags & MMC_DATA_STREAM)) {
401 sdi_dcon |= S3C2410_SDIDCON_BLOCKMODE;
402 }
403
404 if(mrq->data->flags & MMC_DATA_WRITE) {
405 sdi_dcon |= S3C2410_SDIDCON_TXAFTERRESP;
406 sdi_dcon |= S3C2410_SDIDCON_XFER_TXSTART;
407 }
408
409 if(mrq->data->flags & MMC_DATA_READ) {
410 sdi_dcon |= S3C2410_SDIDCON_RXAFTERCMD;
411 sdi_dcon |= S3C2410_SDIDCON_XFER_RXSTART;
412 }
413
414 s3c2410sdi_dma_setup(host, mrq->data->flags & MMC_DATA_WRITE ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
415
416 /* see DMA-API.txt */
417 dma_len = dma_map_sg(&pdev->dev, mrq->data->sg, /
418 mrq->data->sg_len, /
419 mrq->data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
420
421 /* start DMA */
422 s3c2410_dma_enqueue(host->dma, (void *) host,
423 sg_dma_address(&mrq->data->sg[0]),
424 (mrq->data->blocks << mrq->data->blksz_bits) );
425 }
426
427 host->mrq = mrq;
428
429 init_completion(&host->complete_request);
430 init_completion(&host->complete_dma);
431
432 /* Clear command and data status registers */
433 writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
434 writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
435
436 writel(sdi_fsta, host->base + S3C2410_SDIFSTA);
437
438 /* Setup SDI controller */
439 writel(sdi_bsize, host->base + S3C2410_SDIBSIZE);
440 writel(sdi_timer, host->base + S3C2410_SDITIMER);
441 writel(sdi_imsk, host->base + S3C2440_SDIIMSK);
442
443 /* Setup SDI command argument and data control */
444 writel(sdi_carg, host->base + S3C2410_SDICMDARG);
445 writel(sdi_dcon, host->base + S3C2410_SDIDCON);
446
447 /* This initiates transfer */
448 writel(sdi_ccon, host->base + S3C2410_SDICMDCON);
449
450
451 /* Wait for transfer to complete */
452 wait_for_completion(&host->complete_request);
453
454 DBG(PFX "[CMD] request complete./n");
455
456 if(mrq->data) {
457 wait_for_completion(&host->complete_dma);
458 DBG(PFX "[DAT] DMA complete./n");
459 }
460
461 /* Cleanup controller */
462 writel(0, host->base + S3C2410_SDICMDARG);
463 writel(0, host->base + S3C2410_SDIDCON);
464 writel(0, host->base + S3C2410_SDICMDCON);
465 writel(0, host->base + S3C2440_SDIIMSK);
466
467 /* Read response */
468 mrq->cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
469 mrq->cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
470 mrq->cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
471 mrq->cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
472
473 host->mrq = NULL;
474
475 writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
476 writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
477
478 DBG(PFX "request done./n");
479
480 /* If we have no data transfer we are finished here */
481 if (!mrq->data) goto request_done;
482
483 dma_unmap_sg(&pdev->dev, mrq->data->sg, dma_len, /
484 mrq->data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
485
486 /* Calulate the amout of bytes transfer, but only if there was
487 * no error
488 */
489 if(mrq->data->error == MMC_ERR_NONE) {
490 mrq->data->bytes_xfered = (mrq->data->blocks << mrq->data->blksz_bits);
491 } else {
492 mrq->data->bytes_xfered = 0;
493 }
494
495 /* If we had an error while transfering data we flush the
496 * DMA channel to clear out any garbage
497 */
498 if(mrq->data->error != MMC_ERR_NONE) {
499 s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
500 DBG(PFX "flushing DMA./n");
501 }
502
503 if(mrq->data->stop) mmc_wait_for_cmd(mmc, mrq->data->stop, 3);
504
505 request_done:
506
507 mrq->done(mrq);
508 }
510 static void s3c2410sdi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) {
511 struct s3c2410sdi_host *host = mmc_priv(mmc);
512 u32 sdi_psc, sdi_con, sdi_fsta;
513
514 DBG(" %s: %s: line = %d/n", __FUNCTION__, __FILE__, __LINE__);
515
516 /* Set power */
517 sdi_con = readl(host->base + S3C2410_SDICON);
518 sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
519
520 switch(ios->power_mode) {
521 case MMC_POWER_ON:
522 case MMC_POWER_UP:
523 DBG(PFX "power on/n");
524 s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
525 s3c2410_gpio_pullup(S3C2410_GPE5, 0);
526 s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
527 s3c2410_gpio_pullup(S3C2410_GPE6, 0);
528 s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
529 s3c2410_gpio_pullup(S3C2410_GPE7, 0);
530 s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
531 s3c2410_gpio_pullup(S3C2410_GPE8, 0);
532 s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
533 s3c2410_gpio_pullup(S3C2410_GPE9, 0);
534 s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
535 s3c2410_gpio_pullup(S3C2410_GPE10, 0);
536
537 if (host->pdata->set_power)
538 (host->pdata->set_power)(1);
539
540 #ifdef CONFIG_CPU_S3C2440
541 sdi_fsta |= S3C2440_SDIFSTA_FIFORESET;
542 #else
543 sdi_con |= S3C2410_SDICON_FIFORESET;
544 #endif
545
546 //sdi_con |= S3C2410_SDICON_BYTEORDER;
547
548 break;
550 case MMC_POWER_OFF:
551 default:
552 if (host->pdata->set_power)
553 (host->pdata->set_power)(0);
554 break;
555 }
556
557 /* Set clock */
558 for(sdi_psc = 0; sdi_psc < 255; sdi_psc++) {
559 #ifdef CONFIG_CPU_S3C2440
560 if( (clk_get_rate(host->clk) / ((sdi_psc + 1))) <= ios->clock) break;
561 #else
562 if( (clk_get_rate(host->clk) / (2 * (sdi_psc + 1))) <= ios->clock) break;
563 #endif
564 }
565
566 DBG("/n ios->clock = %u /n", ios->clock);
567
568 if(sdi_psc > 255) sdi_psc = 255;
569
570 writel(sdi_psc, host->base + S3C2410_SDIPRE);
571
572 /* Set CLOCK_ENABLE */
573 #ifdef CONFIG_CPU_S3C2440
574 if(ios->clock) sdi_con |= S3C2440_SDICON_CLOCK_OUTE;
575 else sdi_con &= ~S3C2440_SDICON_CLOCK_OUTE;
576 #else
577 if(ios->clock) sdi_con |= S3C2410_SDICON_CLOCKTYPE;
578 else sdi_con &=~S3C2410_SDICON_CLOCKTYPE;
579 #endif
580
581 #ifdef CONFIG_CPU_S3C2440
582 writel(sdi_fsta, host->base + S3C2410_SDIFSTA);
583 #endif
584
585 writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
586 writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
587
588 //writel(0x0FFF, host->base + S3C2410_SDIDSTA);
589
590 writel(sdi_con, host->base + S3C2410_SDICON);
591
592 host->bus_width = ios->bus_width;
593
594 DBG("/n host->bus_width = %u /n", host->bus_width);
595
596 }
597
598 static struct mmc_host_ops s3c2410sdi_ops = {
599 .request = s3c2410sdi_request,
600 .set_ios = s3c2410sdi_set_ios,
601 };

611 static struct s3c24xx_mmc_platdata s3c2410_mmc_defplat = {
612 .gpio_detect = S3C2410_GPG10,
613 //.set_power = s3c2410_mmc_def_setpower,
614 .set_power = NULL,
615 .f_max = 3000000,
616 .ocr_avail = MMC_VDD_32_33,
617 };
618
619 static int s3c2410sdi_probe(struct device *dev)
620 {
621 struct platform_device *pdev = to_platform_device(dev);
622 struct mmc_host *mmc;
623 s3c24xx_mmc_pdata_t *pdata;
624 struct s3c2410sdi_host *host;
625
626 int ret;
627
628 mmc = mmc_alloc_host(sizeof(struct s3c2410sdi_host), dev);
629 if (!mmc) {
630 ret = -ENOMEM;
631 goto probe_out;
632 }
633
634 host = mmc_priv(mmc);
635
636 spin_lock_init( &host->complete_lock );
637 host->complete_what = COMPLETION_NONE;
638 host->mmc = mmc;
639 host->dma = S3C2410SDI_DMA;
640
641 pdata = dev->platform_data;
642 if (!pdata) {
643 dev->platform_data = &s3c2410_mmc_defplat;
644 pdata = &s3c2410_mmc_defplat;
645 }
646
647 host->pdata = pdata;

649 host->irq_cd = s3c2410_gpio_getirq(pdata->gpio_detect);
650 s3c2410_gpio_cfgpin(pdata->gpio_detect, S3C2410_GPIO_IRQ);
651
652 host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
653 if (!host->mem) {
654 printk(KERN_ERR PFX "failed to get io memory region resouce./n");
655 ret = -ENOENT;
656 goto probe_free_host;
657 }
658
659 host->mem = request_mem_region(host->mem->start,
660 RESSIZE(host->mem), pdev->name);
661
662 if (!host->mem) {
663 printk(KERN_ERR PFX "failed to request io memory region./n");
664 ret = -ENOENT;
665 goto probe_free_host;
666 }
667
668 host->base = ioremap(host->mem->start, RESSIZE(host->mem));
669 if (host->base == 0) {
670 printk(KERN_ERR PFX "failed to ioremap() io memory region./n");
671 ret = -EINVAL;
672 goto probe_free_mem_region;
673 }
674
675 host->irq = platform_get_irq(pdev, 0);
676 if (host->irq == 0) {
677 printk(KERN_ERR PFX "failed to get interrupt resouce./n");
678 ret = -EINVAL;
679 goto probe_iounmap;
680 }
681
682 if(request_irq(host->irq, s3c2410sdi_irq, 0, DRIVER_NAME, host)) {
683 printk(KERN_ERR PFX "failed to request sdi interrupt./n");
684 ret = -ENOENT;
685 goto probe_iounmap;
686 }

689 s3c2410_gpio_cfgpin(S3C2410_GPG10, S3C2410_GPG10_EINT18);
690
691 set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
692
693 if(request_irq(host->irq_cd, s3c2410sdi_irq_cd, 0, DRIVER_NAME, host)) {
694 printk(KERN_ERR PFX "failed to request card detect interrupt./n" );
695 ret = -ENOENT;
696 goto probe_free_irq;
697 }
698
699 if(s3c2410_dma_request(S3C2410SDI_DMA, &s3c2410sdi_dma_client, NULL)) {
700 printk(KERN_ERR PFX "unable to get DMA channel./n" );
701 ret = -EBUSY;
702 goto probe_free_irq_cd;
703 }
704
705 host->clk = clk_get(dev, "sdi");
706 if (IS_ERR(host->clk)) {
707 printk(KERN_ERR PFX "failed to find clock source./n");
708 ret = PTR_ERR(host->clk);
709 host->clk = NULL;
710 goto probe_free_host;
711 }
712
713 if((ret = clk_enable(host->clk))) {
714 printk(KERN_ERR PFX "failed to enable clock source./n");
715 goto clk_free;
716 }
717
718
719 mmc->ops = &s3c2410sdi_ops;
720 mmc->ocr_avail = MMC_VDD_32_33;
721
722 mmc->f_min = clk_get_rate(host->clk) / 512;
723 mmc->f_max = clk_get_rate(host->clk) / 2;
724
725 mmc->caps = MMC_CAP_4_BIT_DATA;
736 mmc->max_sectors = 64;
737
738 /*
739 * Set the maximum segment size. Since we aren't doing DMA
740 * (yet) we are only limited by the data length register.
741 */
742
743 mmc->max_seg_size = mmc->max_sectors << 9;
744
745 printk(KERN_INFO PFX "probe: mapped sdi_base=%p irq=%u irq_cd=%u /n", host->base, host->irq, host->irq_cd);
746
747 if((ret = mmc_add_host(mmc))) {
748 printk(KERN_ERR PFX "failed to add mmc host./n");
749 goto clk_disable;
750 }
751
752 dev_set_drvdata(dev, mmc);
753
754 printk(KERN_INFO PFX "initialisation done./n");
755 return 0;
756
757 clk_disable:
758 clk_disable(host->clk);
759
760 clk_free:
761 clk_put(host->clk);
762
763 probe_free_irq_cd:
764 free_irq(host->irq_cd, host);
765
766 probe_free_irq:
767 free_irq(host->irq, host);
768
769 probe_iounmap:
770 iounmap(host->base);
771
772 probe_free_mem_region:
773 release_mem_region(host->mem->start, RESSIZE(host->mem));

775 probe_free_host:
776 mmc_free_host(mmc);
777 probe_out:
778 return ret;
779 }
780
781 static int s3c2410sdi_remove(struct device *dev)
782 {
783 struct mmc_host *mmc = dev_get_drvdata(dev);
784 struct s3c2410sdi_host *host = mmc_priv(mmc);
785
786 mmc_remove_host(mmc);
787 clk_disable(host->clk);
788 clk_put(host->clk);
789 free_irq(host->irq_cd, host);
790 free_irq(host->irq, host);
791 iounmap(host->base);
792 release_mem_region(host->mem->start, RESSIZE(host->mem));
793 mmc_free_host(mmc);
794
795 return 0;
796 }
797
798 static struct device_driver s3c2410sdi_driver =
799 {
800 .name = "s3c2410-sdi",
801 .bus = &platform_bus_type,
802 .probe = s3c2410sdi_probe,
803 .remove = s3c2410sdi_remove,
804 };
static int __init s3c2410sdi_init(void)
807 {
808 return driver_register(&s3c2410sdi_driver);
809 }
810
811 static void __exit s3c2410sdi_exit(void)
812 {
813 driver_unregister(&s3c2410sdi_driver);
814 }
815
816 module_init(s3c2410sdi_init);
817 module_exit(s3c2410sdi_exit);
818
819 MODULE_DESCRIPTION("Samsung S3C2410 Multimedia Card Interface driver");
820 MODULE_LICENSE("GPL");
来自:http://www.embedwit.com/Html/NewsView.asp?ID=3&SortID=30
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: