接下来我们来看看davinci_mmc.c文件,这个是我们真正需要修改或者移植的文件,对应的是davinci_mmc.ko模块;
davinci_mmcsd_init-> platform_driver_register-> davinci_mmc_probe
相关代码如下:
static struct platform_driver davinci_mmcsd_driver = {
.probe = davinci_mmc_probe,
.remove = davinci_mmcsd_remove,
.suspend = davinci_mmcsd_suspend,
.resume = davinci_mmcsd_resume,
.driver = {
.name = DRIVER_NAME,
},
};
static int davinci_mmcsd_init(void)
{
return platform_driver_register(&davinci_mmcsd_driver);
}
/**
* platform_driver_register
* @drv: platform driver structure
*/
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;
if (drv->suspend)
drv->driver.suspend = platform_drv_suspend;
if (drv->resume)
drv->driver.resume = platform_drv_resume;
return driver_register(&drv->driver);
}
调用了driver_register函数,是要把驱动注册到总线上去;
下面我们来看下davinci_mmc_probe函数:
在这个函数总主要创建并初始化了两个结构体
struct mmc_host *mmc;//用于DMA方式传输
struct mmc_davinci_host *host = NULL;//irq 中断
函数原型:
1410 static int davinci_mmc_probe(struct platform_device *pdev)
1411 {
1412 struct davinci_mmc_platform_data *minfo = pdev->dev.platform_data;
1413 struct mmc_host *mmc;//DMA
1414 struct mmc_davinci_host *host = NULL;//irq
1415 struct resource *res;
1416 resource_size_t dma_rx_chan, dma_tx_chan, dma_eventq;
1417 int ret = 0;
1418 int irq;
1419
1420 if (minfo == NULL) {
1421 dev_err(&pdev->dev, "platform data missing\n");
1422 return -ENODEV;
1423 }
1424 //获取内存资源
1425 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
//获取中断号
1426 irq = platform_get_irq(pdev, 0);
1427 if (res == NULL || irq < 0)
1428 return -ENODEV;
1429 //分配从start开始,n长度的内存
1430 res = request_mem_region(res->start, res->end - res->start + 1,
1431 pdev->name);
1432 if (res == NULL)
1433 return -EBUSY;
1434 //分配sizeof(struct mmc_host)+extra这么大的空间,并做以下初始化
1435 mmc = mmc_alloc_host(sizeof(struct mmc_davinci_host), &pdev->dev);
1436 if (mmc == NULL) {
1437 ret = -ENOMEM;
1438 goto err_free_mem_region;
1439 }
1440
1441 host = mmc_priv(mmc); //将mmc转化为host
1442 host->mmc = mmc;
1443
//*******************以下都在初始化host结构体****************************
1444 spin_lock_init(&host->mmc_lock);
1445
1446 host->mem_res = res; //MEM INFO
1447 host->irq = irq; //IRQ
1448
1449 host->phys_base = host->mem_res->start; //MEM INFO START ADDR
1450 host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base); //STARTADDR TO VIRTUAL ADDR
1451
1452 host->use_dma = 0; //不使能DMA
1453 我们是需要使用DMA来传输的,下面是获取DMA相关的资源
1454 #ifdef CONFIG_MMC_DAVINCI_DMA
1455 dma_rx_chan = mmc_get_dma_resource(pdev, IORESOURCE_DMA_RX_CHAN);
1456 if (dma_rx_chan >= 0) {
1457 host->dma_rx_event = dma_rx_chan;//dma recv start address
1458 dma_tx_chan = mmc_get_dma_resource(pdev,
1459 IORESOURCE_DMA_TX_CHAN);
1460 if (dma_tx_chan >= 0) {
1461 host->dma_tx_event = dma_tx_chan; //dma snd start address
1462 dma_eventq = mmc_get_dma_resource(pdev,
1463 IORESOURCE_DMA_EVENT_Q);
1464 if (dma_eventq >= 0) {
1465 host->queue_no = dma_eventq; //dma event quene start address
如果获取前面的DMA资源都成功,那么使能DMA传输功能
1466 host->use_dma = 1; //enable dma
1467 } else {
1468 host->dma_tx_event = 0;
1469 host->dma_rx_event = 0;
1470 }
1471 } else
1472 host->dma_rx_event = 0;
1473 }
1474 #endif
1475 //获取host所需要的时钟
1476 host->clk = clk_get(&pdev->dev, minfo->mmc_clk);
1477 if (IS_ERR(host->clk)) {
1478 ret = -ENODEV;
1479 goto err_free_mmc_host;
1480 }
1481
1482 ret = clk_enable(host->clk);//使能时钟
1483 if (ret)
1484 goto err_put_clk;
1485
1486 init_mmcsd_host(host); //write clock reg
1487
1488 if (minfo->use_8bit_mode) {
1489 dev_info(mmc->dev, "Supporting 8-bit mode\n");
1490 mmc->caps |= MMC_CAP_8_BIT_DATA;
1491 }
1492
1493 if (minfo->use_4bit_mode) {
1494 dev_info(mmc->dev, "Supporting 4-bit mode\n");
1495 mmc->caps |= MMC_CAP_4_BIT_DATA;
1496 }
1497
1498 if (!minfo->use_8bit_mode && !minfo->use_4bit_mode)
1499 dev_info(mmc->dev, "Supporting 1-bit mode\n");
1500
1501 host->get_ro = minfo->get_ro;
1502
1503 host->pio_set_dmatrig = minfo->pio_set_dmatrig;
1504
1505 host->rw_threshold = minfo->rw_threshold;
1506
1507 mmc->ops = &mmc_davinci_ops;//对应sd卡的操作请求,设置时钟,bus mode,bus宽带都是这里实现的
1508 mmc->f_min = 312500;
1509 if (minfo->max_frq)
1510 mmc->f_max = minfo->max_frq;
1511 else
1512 mmc->f_max = 25000000;
1513 mmc->ocr_avail = MMC_VDD_32_33;
1514
1518 mmc->max_phys_segs = EDMA_MAX_LOGICAL_CHA_ALLOWED + 1;
1519 mmc->max_hw_segs = EDMA_MAX_LOGICAL_CHA_ALLOWED + 1;
1520
1521 mmc->max_sectors = 256;
1522
1523 /* Restrict the max size of seg we can handle */
1524 mmc->max_seg_size = mmc->max_sectors * 512; //128kB
1525
1526 dev_dbg(mmc->dev, "max_phys_segs=%d\n", mmc->max_phys_segs);
1527 dev_dbg(mmc->dev, "max_hw_segs=%d\n", mmc->max_hw_segs);
1528 dev_dbg(mmc->dev, "max_sect=%d\n", mmc->max_sectors);
1529 dev_dbg(mmc->dev, "max_seg_size=%d\n", mmc->max_seg_size);
1530
1531 if (host->use_dma) {
1532 dev_info(mmc->dev, "Using DMA mode\n");
1533 ret = davinci_acquire_dma_channels(host);
1534 if (ret)
1535 {
1536 printk("MMC: Acquire dma channels fail!!!!!!!!!!\n");
1537 goto err_release_clk;
1538 }
1539 } else {
1540 dev_info(mmc->dev, "Not Using DMA mode\n");
1541 }
1542 //这里启用了中断请求函数;mmc_davinci_irq
1543 host->sd_support = 1;
1544 ret = request_irq(host->irq, mmc_davinci_irq, 0, DRIVER_NAME, host);
1545 if (ret)
1546 {
1547 printk("MMC: IRQ register fail!!!!!!!!!!\n");
1548 goto err_release_dma;
1549 }
1550
1551 host->dev = &pdev->dev;
1552 platform_set_drvdata(pdev, host);//保存私有数据
1553 mmc_add_host(mmc);
1554 //初始化一个定时器,1HZ调用一次davinci_mmc_check_status函数去检查sd卡的状态
1555 init_timer(&host->timer);
1556 host->timer.data = (unsigned long)host;
1557 host->timer.function = davinci_mmc_check_status;
1558 host->timer.expires = jiffies + MULTIPLIER_TO_HZ * HZ;
1559 add_timer(&host->timer);
1560
1561 return 0;
1562
1563 err_release_dma:
1564 davinci_release_dma_channels(host);
1565 err_release_clk:
1566 clk_disable(host->clk);
1567 err_put_clk:
1568 clk_put(host->clk);
1569 err_free_mmc_host:
1570 mmc_free_host(mmc);
1571 err_free_mem_region:
1572 release_mem_region(res->start, res->end - res->start + 1);
1573
1574 return ret;
1575 }