davinci sd卡驱动学习笔记(三)

简介:

接下来我们来看看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 modebus宽带都是这里实现的

  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  }

 



本文转自 曾永刚 51CTO博客,原文链接:http://blog.51cto.com/zyg0227/565383

相关文章
|
3月前
|
Linux 程序员
Linux系统中驱动之设备树的platform驱动实现
Linux系统中驱动之设备树的platform驱动实现
47 0
|
11月前
|
Linux Android开发 芯片
Linux驱动分析之Framebuffer驱动
前面我们了解了LCD的基本架构《Linux驱动分析之LCD驱动架构》,接下来我们拿个具体的实例来分析分析。这样可以了解其大概是如何使用和工作的。
|
存储 异构计算 内存技术
|
传感器 Linux SoC
嵌入式实践教程--设备树下的platform驱动
嵌入式实践教程--设备树下的platform驱动
嵌入式实践教程--设备树下的platform驱动
|
存储 Linux 芯片
如何编写linux下nand flash驱动-3
【读(read)操作过程详解】 以最简单的read操作为例,解释如何理解时序图,以及将时序图 中的要求,转化为代码。   解释时序图之前,让我们先要搞清楚,我们要做的事情:那就是,要从nand flash的某个页里面,读取我们要的数据。
1018 0
|
存储 Linux 芯片
如何编写linux下nand flash驱动-1
1.       硬件特性: 【Flash的硬件实现机制】 Flash全名叫做Flash Memory,属于非易失性存储设备(Non-volatile Memory Device),与此相对应的是易失性存储设备(Volatile Memory Device)。
938 0
|
存储 算法 Linux
如何编写linux下nand flash驱动-4
2.       软件方面 如果想要在Linux下编写Nand Flash驱动,那么就先要搞清楚Linux下,关于此部分的整个框架。弄明白,系统是如何管理你的nand flash的,以及,系统都帮你做了那些准备工作,而剩下的,驱动底层实现部分,你要去实现哪些功能,才能使得硬件正常工作起来。
918 0

热门文章

最新文章