SPI在linux3.14.78 FS_S5PC100(Cortex A8)和S3C2440上驱动移植(deep dive)

发布者:MysticJourney最新更新时间:2024-08-09 来源: cnblogs关键字:SPI  linux  Cortex  S3C2440  驱动移植 手机看文章 扫描二维码
随时随地手机看文章

                s3c_gpio_setpull(S5PC1XX_GPB(4), S3C_GPIO_PULL_UP);

                s3c_gpio_setpull(S5PC1XX_GPB(5), S3C_GPIO_PULL_UP);

                s3c_gpio_setpull(S5PC1XX_GPB(6), S3C_GPIO_PULL_UP);

                break;

case 2:

                s3c_gpio_cfgpin(S5PC1XX_GPG3(0), S5PC1XX_GPG3_0_SPI_CLK2);

                s3c_gpio_cfgpin(S5PC1XX_GPG3(2), S5PC1XX_GPG3_2_SPI_MISO2);

                s3c_gpio_cfgpin(S5PC1XX_GPG3(3), S5PC1XX_GPG3_3_SPI_MOSI2);

                s3c_gpio_setpull(S5PC1XX_GPG3(0), S3C_GPIO_PULL_UP);

                s3c_gpio_setpull(S5PC1XX_GPG3(2), S3C_GPIO_PULL_UP);

                s3c_gpio_setpull(S5PC1XX_GPG3(3), S3C_GPIO_PULL_UP);

                break;

default:

                dev_err(&pdev->dev, 'Invalid SPI Controller number!');

                return -EINVAL;

        }

//platform_driver,参看drivers/spi/spi_s3c64xx.c文件

static struct platform_driver s3c64xx_spi_driver = {

                .driver = {

                        .name = 's3c64xx-spi', //名称,和platform_device对应

                        .owner = THIS_MODULE,

                },

                .remove = s3c64xx_spi_remove,

                .suspend = s3c64xx_spi_suspend,

                .resume = s3c64xx_spi_resume,

        };

platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);//注册s3c64xx_spi_driver

//和平台中注册的platform_device匹配后,调用s3c64xx_spi_probe。然后根据传入的platform_device参数,构建一个用于描述SPI控制器的结构体spi_master,并注册。spi_register_master(master)。后续注册的spi_device需要选定自己的spi_master,并利用spi_master提供的传输功能传输spi数据。和I2C类似,SPI也有一个描述控制器的对象叫spi_master,其主要成员是主机控制器的序号(系统中可能存在多个SPI主机控制器)、片选数量、SPI模式和时钟设置用到的函数、数据传输用到的函数等;

struct spi_master {

                struct device    dev;

                s16  bus_num;     //表示是SPI主机控制器的编号。由平台代码决定

                u16  num_chipselect;    //控制器支持的片选数量,即能支持多少个spi设备

                int  (*setup)(struct spi_device *spi);    //针对设备设置SPI的工作时钟及数据传输模式等。在spi_add_device函数中调用。

                int  (*transfer)(struct spi_device *spi,

                struct spi_message *mesg);    //实现数据的双向传输,可能会睡眠

                void       (*cleanup)(struct spi_device *spi);    //注销时调用

        };


static int s3c24xx_spi_probe(struct platform_device *pdev)

{

    struct s3c2410_spi_info *pdata;

    struct s3c24xx_spi *hw;

    struct spi_master *master;

    struct resource *res;

    int err = 0;

    master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));//分配SPI控制器结构及驱动私有数据

    if (master == NULL) {

        dev_err(&pdev->dev, 'No memory for spi_mastern');

        return -ENOMEM;

    }

    hw = spi_master_get_devdata(master);

    memset(hw, 0, sizeof(struct s3c24xx_spi));

    hw->master = master;

    hw->pdata = pdata = dev_get_platdata(&pdev->dev);

    hw->dev = &pdev->dev;

    if (pdata == NULL) {

        dev_err(&pdev->dev, 'No platform data suppliedn');

        err = -ENOENT;

        goto err_no_pdata;

    }

    platform_set_drvdata(pdev, hw);//将SPI控制器私有数据作为平台设备驱动数据,便于通过相应接口获得

    init_completion(&hw->done);//初始化完成接口

    /* initialise fiq handler */

    s3c24xx_spi_initfiq(hw);

    /* setup the master state. */

    /* the spi->mode bits understood by this driver: */

    master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

    master->num_chipselect = hw->pdata->num_cs;//设置控制器片选总数和总线编号

    master->bus_num = pdata->bus_num;

    /* setup the state for the bitbang driver 初始化bitbang驱动的相关成员*/

    hw->bitbang.master         = hw->master;

    hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;

    hw->bitbang.chipselect     = s3c24xx_spi_chipsel;

    hw->bitbang.txrx_bufs      = s3c24xx_spi_txrx;

    hw->master->setup  = s3c24xx_spi_setup;

    hw->master->cleanup = s3c24xx_spi_cleanup;

    dev_dbg(hw->dev, 'bitbang at %pn', &hw->bitbang);

    /* find and map our resources 这是平台驱动中最常规的工作,找到并映射资源*/

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

    hw->regs = devm_ioremap_resource(&pdev->dev, res);

    if (IS_ERR(hw->regs)) {

        err = PTR_ERR(hw->regs);

        goto err_no_pdata;

    }

    hw->irq = platform_get_irq(pdev, 0);

    if (hw->irq < 0) {

        dev_err(&pdev->dev, 'No IRQ specifiedn');

        err = -ENOENT;

        goto err_no_pdata;

    }

    err = devm_request_irq(&pdev->dev, hw->irq, s3c24xx_spi_irq, 0,

                pdev->name, hw);

    if (err) {

        dev_err(&pdev->dev, 'Cannot claim IRQn');

        goto err_no_pdata;

    }

    hw->clk = devm_clk_get(&pdev->dev, 'spi');//获取SPI的时钟资源

    if (IS_ERR(hw->clk)) {

        dev_err(&pdev->dev, 'No clock for devicen');

        err = PTR_ERR(hw->clk);

        goto err_no_pdata;

    }

    /* setup any gpio we can 设置片选方法并配置片选引脚 */

    if (!pdata->set_cs) {

        if (pdata->pin_cs < 0) {

            dev_err(&pdev->dev, 'No chipselect pinn');

            err = -EINVAL;

            goto err_register;

        }

        err = devm_gpio_request(&pdev->dev, pdata->pin_cs,

                    dev_name(&pdev->dev));

        if (err) {

            dev_err(&pdev->dev, 'Failed to get gpio for csn');

            goto err_register;

        }

        hw->set_cs = s3c24xx_spi_gpiocs;

        gpio_direction_output(pdata->pin_cs, 1);

    } else

        hw->set_cs = pdata->set_cs;

    s3c24xx_spi_initialsetup(hw);//使能SPI时钟,初始化2440 SPI控制器寄存器及片选引脚等

    /* register our spi controller 注册SPI控制器,进而完成对控制器对象的分配初始化和注册,注册控制器会扫描

    board_list链表,从中取出spi_board_info创建spi_device设备,因此在执行probe方法时,只要board_list链表

    上有控制器对应的spi_board_info,就能创建出控制器的设备对象,并与控制器设备驱动匹配,进而创建出用于访问该控制器的设备文件

  */

    err = spi_bitbang_start(&hw->bitbang);

    if (err) {

        dev_err(&pdev->dev, 'Failed to register SPI mastern');

        goto err_register;

    }

    return 0;

 err_register:

    clk_disable(hw->clk);

 err_no_pdata:

    spi_master_put(hw->master);

    return err;

}


Step3,分析实现SPI总线通信方法


SPI控制器通常由spi_bitbang来完成实际数据的数据传输,spi_bitbang的定义如下:


struct spi_bitbang {

    spinlock_t        lock;   /*操作工作队列时使用的自旋锁*/

    u8            busy;

    u8            use_dma;

    u8            flags;        /* extra spi->mode support */

    struct spi_master    *master;

    /* setup_transfer() changes clock and/or wordsize to match settings

     * for this transfer; zeroes restore defaults from spi_device.为特定的传输设置时钟、字宽等属性的方法

     */

    int    (*setup_transfer)(struct spi_device *spi,

            struct spi_transfer *t);

    void    (*chipselect)(struct spi_device *spi, int is_on);

#define    BITBANG_CS_ACTIVE    1    /* normally nCS, active low */

#define    BITBANG_CS_INACTIVE    0

    /* txrx_bufs()为实际的传输方法 may handle dma mapping for transfers that don't

     * already have one (transfer.{tx,rx}_dma is zero), or use PIO

     */

    int    (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);

    /* txrx_word[SPI_MODE_*]()按字传输的方法 just looks like a shift register */

    u32    (*txrx_word[4])(struct spi_device *spi,

            unsigned nsecs,

[1] [2] [3] [4] [5]
关键字:SPI  linux  Cortex  S3C2440  驱动移植 引用地址:SPI在linux3.14.78 FS_S5PC100(Cortex A8)和S3C2440上驱动移植(deep dive)

上一篇:S3C2440的中断体系结构
下一篇:LCD驱动移植在在mini2440(linux2.6.29)和FS4412(linux3.14.78)上实现对比(deep dive)

推荐阅读最新更新时间:2026-02-27 16:37

基于S3C2440linux-3.6.6移植——LED驱动
目前的linux版本的许多驱动都是基于设备模型,LED也不例外。 简单地说,设备模型就是系统认为所有的设备都是挂接在总线上的,而要使设备工作,就需要相应的驱动。设备模型会产生一个虚拟的文件系统——sysfs,它给用户提供了一个从用户空间去访问内核设备的方法,它在linux里的路径是/sys。如果要写程序访问sysfs,可以像读写普通文件一样来操作/sys目录下的文件。 对于基于s3c2440的开发板来说,linux-3.6.6自动的LED驱动只需改变连接LED的IO端口,及高、低电平响应即可。我的开发板的四个LED连接在了B口的5到8引脚上,当输出低电平时被点亮,与linux自带的LED驱动一致,因此无需做任何改动。
[单片机]
S3C2440 Linux驱动移植——SD卡驱动
开发板:TQ2440 内核:Linux 2.6.32 PC OS:Ubuntu 11.04 本文将对SD卡驱动的移植做简要介绍。 1. 添加板级信息 打开arch/arm/mach-s3c2440/mach-smdk2440.c。 添加如下结构体: /* Added by Yan Jun for SD/MMC driver */ /*********************************************/ #include plat/mci.h static struct s3c24xx_mci_pdata s3c_mci_data = { .no_detect =
[单片机]
<font color='red'>S3C2440</font> <font color='red'>Linux</font><font color='red'>驱动</font><font color='red'>移植</font>——SD卡<font color='red'>驱动</font>
LinuxSPI子系统图解和mini2440下的SPI驱动移植
1.SPI子系统框图详解: SPI总线上有两类设备:一类是主控端,通常作为SOC系统的一个子模块出现,比如很多嵌入式MPU中都常常包含SPI模块。一类是受控端,例如一些SPI接口的Flash、传感器等等。主控端是SPI总线的控制者,通过使用SPI协议主动发起SPI总线上的会话。而受控端则被动接受SPI主控端的指令,并作出响应的响应。 如图1所示,linux下的spi子系统主要涉及3个部分:spi核心、spiprotocol驱动和spi主控制器驱动。如图1.1,spi核心负责抽象出所有控制器都具备的功能代码,同时向上为spiprotocol驱动提供接口比如spi_message、spi_transfer,spi_async等,具
[单片机]
<font color='red'>Linux</font>中<font color='red'>SPI</font>子系统图解和mini2440下的<font color='red'>SPI</font><font color='red'>驱动</font><font color='red'>移植</font>
S3C2440 音频解码芯片WM8976声卡驱动移植、madplay测试
1. WM9876接口和工作原理 本节使用了JZ2440开发板移植WM9876驱动,其结构如下图所示,最后利用madplay工具测试音频文件。 IIS和控制接口; WM9876声卡是负责录音、播音、调节音量和声音合成等的一种多媒体板卡。包括两种接口:IIS接口(提供音频接收和发送)、控制接口(控制音量大小,使能各个输出通道等) 1)当我们播放声音时,将数字信号传入I2SDO脚,声卡便通过解码,产生模拟信号到喇叭/耳机; 2)当我们录音时,声卡便获取麦克风的模拟信号,编码出数字信号到I2SDI引脚上。 ----------- 接口说明 ---------------- ----------- 接口说明
[单片机]
ARM处理器的Cache之cortex a8
Cache 是位于 CPU与主存储器DRAM(Dynamic RAM,动态存储器)之间的少量超高速静态存储器 SRAM(static RAM),其是为了解决 CPU 与 主存之间速度匹配问题而设置的,不能由用户直接寻址访问。 具有 Cache 的计算机,当 CPU 需要进行存储器存取时,首先检查所需数据是否在 Cache中。如果存在,则可以直接存取其中的数据而不必插入任何等待状态,这是最佳状态,称为高速命中;当 CPU 所需信息不在 Cache 中时,则需切换存取主存储器,由于速度较慢,需要插入等待,这种情况称为 高速未命中;在CPU存取主存储器的时候,按照最优化原则将存储信息同时写入到 Cache 中以保证下次可能的
[单片机]
ARM处理器的Cache之<font color='red'>cortex</font> <font color='red'>a8</font>
基于ARM v7 Cortex A8的开发平台
一、ARM Cortex处理器概述 随着嵌入式技术应用领域的不断扩展,对嵌入式系统的要求越来越高,而作为嵌入式系统核心的微处理器也面临日益严竣的挑战。ARM公司从成立以来,一直以知识产权(IP,Intelligence Property)提供者的身份出售知识产权,在32位RISC CPU开发领域中不断取得突破,其设计的微处理器结构已经从v3发展到现在的v7。ARMv7架构是在ARMv6架构的基础上诞生的。该架构采用了Thumb-2技术,它是在ARM的Thumb代码压缩技术的基础上发展起来的,并且保持了对现存ARM解决方案的完整的代码兼容性。Thumb-2技术比纯32位代码少使用31%的内存,减小了系统开销,同时能够提供比已有的基于
[单片机]
基于ARM v7 <font color='red'>Cortex</font> <font color='red'>A8</font>的开发平台
研华推出新一代采用ARM Cortex™-A8的工业级单板电脑
新一代PCM-C3500单板电脑系列产品带有内置TI OMAP3500 SoC,旨在满足小尺寸、低功耗的应用需求,如工业控制、HMI、车载电脑等 2011年8月26日, 作为全球领先的提供嵌入式平台解决方案的嵌入式计算机供应商,研华 (TWSE: 2395.TW) 在推出了一款全新的、采用最新Texas Instruments OMAP35系列处理器的基于RISC的单板电脑。 PCM-C3500采用了集成移动DDR的基于Cortex™A8的TI OMAP35 600 MHz高性能/应用处理器,支持OpenGL ES 1.1 & 2.0、OpenVG 1.0和Direct 3D;此外,而PCM-C3500还支持D1视频分辨率。研
[工业控制]
Linux移植Linux驱动交叉编译环境搭建
需要工具: 1.Linux内核源码包,可在http://www.kernel.org/pub/linux/kernel/中去下载自己需要的版本,我们这里我们使用的内核为 linux-3.0.8.tar。 2.需要挂载的芯片源码,这里使用三星的S5PV210为例,代码包为rootfs_fs210.tgz的一个压缩包 3.交叉工具链,toolchain-4.5.1-farsight.tar.bz2。 1.我们要移植配置Linux-3.0.8系统,这里我是直接在用户目录下使用Samba直接建立个共享文件夹的,在Windows中直接把想要需要的文件放在其中,然后在linux中操作文件。正如下图所示,将.bz2文件放在s5PV2
[单片机]
<font color='red'>Linux</font>的<font color='red'>移植</font>与<font color='red'>Linux</font><font color='red'>驱动</font>交叉编译环境搭建
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved