一、SPI子系统模型





三个组成部分:

SPI核心:连通了SPI客户驱动、SPI主控制器驱动

SPI控制器驱动:驱动芯片中的SPI控制器

SPI的FLASH(客户驱动)



二、SPI控制器驱动分析

  1. static int __init s3c24xx_spi_probe(struct platform_device *pdev)
  2. {
  3. struct s3c2410_spi_info *pdata;
  4. struct s3c24xx_spi *hw;
  5. struct spi_master *master;
  6. struct resource *res;
  7. int err = 0;
  8. master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
  9. if (master == NULL) {
  10. dev_err(&pdev->dev, "No memory for spi_master\n");
  11. err = -ENOMEM;
  12. goto err_nomem;
  13. }
  14. hw = spi_master_get_devdata(master);
  15. memset(hw, 0, sizeof(struct s3c24xx_spi));
  16. hw->master = spi_master_get(master);
  17. hw->pdata = pdata = pdev->dev.platform_data;
  18. hw->dev = &pdev->dev;
  19. if (pdata == NULL) {
  20. dev_err(&pdev->dev, "No platform data supplied\n");
  21. err = -ENOENT;
  22. goto err_no_pdata;
  23. }
  24. platform_set_drvdata(pdev, hw);
  25. init_completion(&hw->done);
  26. /* setup the master state. */
  27. master->num_chipselect = hw->pdata->num_cs;
  28. master->bus_num = pdata->bus_num;
  29. /* setup the state for the bitbang driver */
  30. hw->bitbang.master = hw->master;
  31. hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
  32. hw->bitbang.chipselect = s3c24xx_spi_chipsel;
  33. hw->bitbang.txrx_bufs = s3c24xx_spi_txrx;
  34. hw->bitbang.master->setup = s3c24xx_spi_setup;
  35. dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
  36. /* find and map our resources */
  37. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  38. if (res == NULL) {
  39. dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
  40. err = -ENOENT;
  41. goto err_no_iores;
  42. }
  43. hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1,
  44. pdev->name);                                                                    //设置硬件资源
  45. if (hw->ioarea == NULL) {
  46. dev_err(&pdev->dev, "Cannot reserve region\n");
  47. err = -ENXIO;
  48. goto err_no_iores;
  49. }
  50. hw->regs = ioremap(res->start, (res->end - res->start)+1);                                      //获取映射地址
  51. if (hw->regs == NULL) {
  52. dev_err(&pdev->dev, "Cannot map IO\n");
  53. err = -ENXIO;
  54. goto err_no_iomap;
  55. }
  56. hw->irq = platform_get_irq(pdev, 0);                                                            //获取中断号
  57. if (hw->irq < 0) {
  58. dev_err(&pdev->dev, "No IRQ specified\n");
  59. err = -ENOENT;
  60. goto err_no_irq;
  61. }
  62. err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);                                 //注册中断
  63. if (err) {
  64. dev_err(&pdev->dev, "Cannot claim IRQ\n");
  65. goto err_no_irq;
  66. }
  67. hw->clk = clk_get(&pdev->dev, "spi");
  68. if (IS_ERR(hw->clk)) {
  69. dev_err(&pdev->dev, "No clock for device\n");
  70. err = PTR_ERR(hw->clk);
  71. goto err_no_clk;
  72. }
  73. /* setup any gpio we can */
  74. if (!pdata->set_cs) {
  75. if (pdata->pin_cs < 0) {
  76. dev_err(&pdev->dev, "No chipselect pin\n");
  77. goto err_register;
  78. }
  79. err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
  80. if (err) {
  81. dev_err(&pdev->dev, "Failed to get gpio for cs\n");
  82. goto err_register;
  83. }
  84. hw->set_cs = s3c24xx_spi_gpiocs;
  85. gpio_direction_output(pdata->pin_cs, 1);
  86. } else
  87. hw->set_cs = pdata->set_cs;
  88. s3c24xx_spi_initialsetup(hw);                                                                    //初始化部分
  89. /* register our spi controller */
  90. err = spi_bitbang_start(&hw->bitbang);                                                           //完成注册
  91. if (err) {
  92. dev_err(&pdev->dev, "Failed to register SPI master\n");
  93. goto err_register;
  94. }
  95. return 0;
  96. err_register:
  97. if (hw->set_cs == s3c24xx_spi_gpiocs)
  98. gpio_free(pdata->pin_cs);
  99. clk_disable(hw->clk);
  100. clk_put(hw->clk);
  101. err_no_clk:
  102. free_irq(hw->irq, hw);
  103. err_no_irq:
  104. iounmap(hw->regs);
  105. err_no_iomap:
  106. release_resource(hw->ioarea);
  107. kfree(hw->ioarea);
  108. err_no_iores:
  109. err_no_pdata:
  110. spi_master_put(hw->master);;
  111. err_nomem:
  112. return err;
  113. }

s3c24xx_spi_initialsetup:

  1. static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
  2. {
  3. /* for the moment, permanently enable the clock */
  4. clk_enable(hw->clk);
  5. /* program defaults into the registers */
  6. writeb(0xff, hw->regs + S3C2410_SPPRE);
  7. writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
  8. writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);                                       //设置成中断触发方式
  9. if (hw->pdata) {
  10. if (hw->set_cs == s3c24xx_spi_gpiocs)
  11. gpio_direction_output(hw->pdata->pin_cs, 1);
  12. if (hw->pdata->gpio_setup)
  13. hw->pdata->gpio_setup(hw->pdata, 1);
  14. }
  15. }

中断函数s3c24xx_spi_irq:

  1. static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
  2. {
  3. struct s3c24xx_spi *hw = dev;
  4. unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
  5. unsigned int count = hw->count;
  6. if (spsta & S3C2410_SPSTA_DCOL) {
  7. dev_dbg(hw->dev, "data-collision\n");
  8. complete(&hw->done);
  9. goto irq_done;
  10. }
  11. if (!(spsta & S3C2410_SPSTA_READY)) {
  12. dev_dbg(hw->dev, "spi not ready for tx?\n");
  13. complete(&hw->done);
  14. goto irq_done;
  15. }
  16. hw->count++;
  17. if (hw->rx)
  18. hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
  19. count++;
  20. if (count < hw->len)                                                                            //判断长度来收发?
  21. writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
  22. else
  23. complete(&hw->done);
  24. irq_done:
  25. return IRQ_HANDLED;
  26. }

SPI子系统的更多相关文章

  1. spi子系统之驱动SSD1306 OLED

    spi子系统之驱动SSD1306 OLED 接触Linux之前,曾以为读源码可以更快的学习软件,于是前几个博客都是一边读源码一边添加注释,甚至精读到每一行代码,实际上效果并不理想,看过之后就忘记了.主 ...

  2. [国嵌攻略][159][SPI子系统]

    SPI 子系统架构 1.SPI core核心:用于连接SPI客户驱动和SPI主控制器驱动,并且提供了对应的注册和注销的接口. 2.SPI controller driver主控制器驱动:用来驱动SPI ...

  3. SPI子系统分析之二:数据结构【转】

    转自:http://www.cnblogs.com/jason-lu/articles/3164901.html 内核版本:3.9.5 spi_master struct spi_master用来描述 ...

  4. SPI子系统分析之四:驱动模块

    内核版本:3.9.5 SPI控制器层(平台相关) 上一节讲了SPI核心层的注册和匹配函数,它是平台无关的.正是在核心层抽象了SPI控制器层的相同部分然后提供了统一的API给SPI设备层来使用.我们这一 ...

  5. SPI子系统分析之三:驱动模块

    内核版本:3.9.5 SPI核心层(平台无关) SPI子系统初始化的第一步就是将SPI总线注册进内核,并且在/sys下创建一个spi_master的类,以后注册的从设备都将挂接在该总线下. 下列函数位 ...

  6. SPI子系统分析之二:数据结构

    内核版本:3.9.5 spi_master struct spi_master用来描述一个SPI主控制器,我们一般不需要自己编写spi控制器驱动. /*结构体master代表一个SPI接口,或者叫一个 ...

  7. SPI子系统分析之一:框架

    内核版本:3.9.5 SPI子系统概述: 一个SPI主控制器对应一条SPI总线,当然在系统中有唯一的总线编号. SPI总线上有两类设备: 其一是主控端,通常作为SOC系统的一个子模块出现,很多嵌入式M ...

  8. spi 子系统

    http://blog.csdn.net/ropenyuan/article/details/42269641 http://blog.chinaunix.net/uid-27406766-id-33 ...

  9. Linux内核中SPI/I2c子系统剖析

    Linux内核中,SPI和I2C两个子系统的软件架构是一致的,且Linux内核的驱动模型都以bus,driver,device三种抽象对象为基本元素构建起来.下文的分析将主要用这三种抽象对象的创建过程 ...

随机推荐

  1. 【Http2.0】Http2.0

    序言 目前HTTP/2.0(简称h2)已经在广泛使用(截止2018年8月根据Alexa流行度排名的头部1千万网站中,h2占比约29%,https://w3techs.com/technologies/ ...

  2. LDD3 第13章 USB驱动程序

    通用串行总线(USB)是主机和外围设备之间的一种连接.最新USB规范修订增加了理论上高达480Mbps的高速连接. 从拓扑上看,USB子系统并不是以总线的方式来布置的,它是一颗由几个点对点的连接构建而 ...

  3. Vue响应式原理的实现-面试必问

    Vue2的数据响应式原理 1.什么是defineProperty? defineProperty是设置对象属性,利用属性里的set和get实现了响应式双向绑定: 语法:Object.definePro ...

  4. delphi 创建桌面快捷方式

    unit UShorCut; interface uses Windows, Classes, SysUtils,Dialogs, ShlObj, ComObj, ActiveX, Registry; ...

  5. python中冒泡 排序法练习题

    # 第四题:写出冒泡排序函数,可以排序任意类型的元素,可以逆序 # 1.实现冒泡排序算法 # 2.可以排序任意类型的元素 # 3.能够通过参数设置进行逆序,默认升序 def my_sort(lt,ke ...

  6. 8051 r0-r7 是什么

    R0~R7表示当前选中的寄存器组的寄存器0~7,5I机有p0,p1,p2,p3口,每组有八个寄存器(R0-R7),比如MOV A Rn (n=0~7),表示把寄存器Rn 的内容送给累加器A,其中源操作 ...

  7. Checking out pull requests locally

    https://help.github.com/en/articles/checking-out-pull-requests-locally https://github.com/betaflight ...

  8. Design:设计(活动)百科

    ylbtech-Design:设计(活动)百科 设计是把一种设想通过合理的规划.周密的计划.通过各种感觉形式传达出来的过程.人类通过劳动改造世界,创造文明,创造物质财富和精神财富,而最基础.最主要的创 ...

  9. 原生js事件绑定

    一.JS事件 (一)JS事件分类 1.鼠标事件: click/dbclick/mouseover/mouseout 2.HTML事件: onload/onunload/onsubmit/onresiz ...

  10. 如何取消bootstrap浮动时的padding值

    在bootstrap框架中使用浮动时,可以对元素添加pull-left 或 pull-right 类来达到目的.但是框架会默认给该元素添加一个15px的左右padding. <div class ...