zoukankan      html  css  js  c++  java
  • SPI子系统

    一、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 ");
    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 ");
    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 ", &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 ");
    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 ");
    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 ");
    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 ");
    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 ");
    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 ");
    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 ");
    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 ");
    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 ");
    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 ");
    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? ");
    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. }

    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    (原创)神舟笔记本bios设置——神船战神ZX7-CP7S2 <一>
    Kali笔记<三> 安装中文输入法
    (原创)Kali笔记<二>root权限的使用和启用
    (原创)Kali笔记<一>虚拟机安装Kali
    加快vmware虚拟机运行速度的方法(大牛勿笑)
    PR/AE/PS 素材模板网站
    批量查杀该死的VBscript “svchost.exe” 脚本挂马
    echarts统计图Y轴(或X轴)文字过长问题解决
    正则实例
    Angular.js的自定义功能
  • 原文地址:https://www.cnblogs.com/ch122633/p/7363291.html
Copyright © 2011-2022 走看看