SPI子系统
一、SPI子系统模型

三个组成部分:
SPI核心:连通了SPI客户驱动、SPI主控制器驱动
SPI控制器驱动:驱动芯片中的SPI控制器
SPI的FLASH(客户驱动)
二、SPI控制器驱动分析
- static int __init 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));
- if (master == NULL) {
- dev_err(&pdev->dev, "No memory for spi_master\n");
- err = -ENOMEM;
- goto err_nomem;
- }
- hw = spi_master_get_devdata(master);
- memset(hw, 0, sizeof(struct s3c24xx_spi));
- hw->master = spi_master_get(master);
- hw->pdata = pdata = pdev->dev.platform_data;
- hw->dev = &pdev->dev;
- if (pdata == NULL) {
- dev_err(&pdev->dev, "No platform data supplied\n");
- err = -ENOENT;
- goto err_no_pdata;
- }
- platform_set_drvdata(pdev, hw);
- init_completion(&hw->done);
- /* setup the master state. */
- master->num_chipselect = hw->pdata->num_cs;
- master->bus_num = pdata->bus_num;
- /* setup the state for the bitbang driver */
- 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->bitbang.master->setup = s3c24xx_spi_setup;
- dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
- /* find and map our resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
- err = -ENOENT;
- goto err_no_iores;
- }
- hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1,
- pdev->name); //设置硬件资源
- if (hw->ioarea == NULL) {
- dev_err(&pdev->dev, "Cannot reserve region\n");
- err = -ENXIO;
- goto err_no_iores;
- }
- hw->regs = ioremap(res->start, (res->end - res->start)+1); //获取映射地址
- if (hw->regs == NULL) {
- dev_err(&pdev->dev, "Cannot map IO\n");
- err = -ENXIO;
- goto err_no_iomap;
- }
- hw->irq = platform_get_irq(pdev, 0); //获取中断号
- if (hw->irq < 0) {
- dev_err(&pdev->dev, "No IRQ specified\n");
- err = -ENOENT;
- goto err_no_irq;
- }
- err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw); //注册中断
- if (err) {
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
- goto err_no_irq;
- }
- hw->clk = clk_get(&pdev->dev, "spi");
- if (IS_ERR(hw->clk)) {
- dev_err(&pdev->dev, "No clock for device\n");
- err = PTR_ERR(hw->clk);
- goto err_no_clk;
- }
- /* setup any gpio we can */
- if (!pdata->set_cs) {
- if (pdata->pin_cs < 0) {
- dev_err(&pdev->dev, "No chipselect pin\n");
- goto err_register;
- }
- err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
- if (err) {
- dev_err(&pdev->dev, "Failed to get gpio for cs\n");
- 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); //初始化部分
- /* register our spi controller */
- err = spi_bitbang_start(&hw->bitbang); //完成注册
- if (err) {
- dev_err(&pdev->dev, "Failed to register SPI master\n");
- goto err_register;
- }
- return 0;
- err_register:
- if (hw->set_cs == s3c24xx_spi_gpiocs)
- gpio_free(pdata->pin_cs);
- clk_disable(hw->clk);
- clk_put(hw->clk);
- err_no_clk:
- free_irq(hw->irq, hw);
- err_no_irq:
- iounmap(hw->regs);
- err_no_iomap:
- release_resource(hw->ioarea);
- kfree(hw->ioarea);
- err_no_iores:
- err_no_pdata:
- spi_master_put(hw->master);;
- err_nomem:
- return err;
- }
s3c24xx_spi_initialsetup:
- static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
- {
- /* for the moment, permanently enable the clock */
- clk_enable(hw->clk);
- /* program defaults into the registers */
- writeb(0xff, hw->regs + S3C2410_SPPRE);
- writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
- writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); //设置成中断触发方式
- if (hw->pdata) {
- if (hw->set_cs == s3c24xx_spi_gpiocs)
- gpio_direction_output(hw->pdata->pin_cs, 1);
- if (hw->pdata->gpio_setup)
- hw->pdata->gpio_setup(hw->pdata, 1);
- }
- }
中断函数s3c24xx_spi_irq:
- static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
- {
- struct s3c24xx_spi *hw = dev;
- unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
- unsigned int count = hw->count;
- if (spsta & S3C2410_SPSTA_DCOL) {
- dev_dbg(hw->dev, "data-collision\n");
- complete(&hw->done);
- goto irq_done;
- }
- if (!(spsta & S3C2410_SPSTA_READY)) {
- dev_dbg(hw->dev, "spi not ready for tx?\n");
- complete(&hw->done);
- goto irq_done;
- }
- hw->count++;
- if (hw->rx)
- hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
- count++;
- if (count < hw->len) //判断长度来收发?
- writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
- else
- complete(&hw->done);
- irq_done:
- return IRQ_HANDLED;
- }
SPI子系统的更多相关文章
- spi子系统之驱动SSD1306 OLED
spi子系统之驱动SSD1306 OLED 接触Linux之前,曾以为读源码可以更快的学习软件,于是前几个博客都是一边读源码一边添加注释,甚至精读到每一行代码,实际上效果并不理想,看过之后就忘记了.主 ...
- [国嵌攻略][159][SPI子系统]
SPI 子系统架构 1.SPI core核心:用于连接SPI客户驱动和SPI主控制器驱动,并且提供了对应的注册和注销的接口. 2.SPI controller driver主控制器驱动:用来驱动SPI ...
- SPI子系统分析之二:数据结构【转】
转自:http://www.cnblogs.com/jason-lu/articles/3164901.html 内核版本:3.9.5 spi_master struct spi_master用来描述 ...
- SPI子系统分析之四:驱动模块
内核版本:3.9.5 SPI控制器层(平台相关) 上一节讲了SPI核心层的注册和匹配函数,它是平台无关的.正是在核心层抽象了SPI控制器层的相同部分然后提供了统一的API给SPI设备层来使用.我们这一 ...
- SPI子系统分析之三:驱动模块
内核版本:3.9.5 SPI核心层(平台无关) SPI子系统初始化的第一步就是将SPI总线注册进内核,并且在/sys下创建一个spi_master的类,以后注册的从设备都将挂接在该总线下. 下列函数位 ...
- SPI子系统分析之二:数据结构
内核版本:3.9.5 spi_master struct spi_master用来描述一个SPI主控制器,我们一般不需要自己编写spi控制器驱动. /*结构体master代表一个SPI接口,或者叫一个 ...
- SPI子系统分析之一:框架
内核版本:3.9.5 SPI子系统概述: 一个SPI主控制器对应一条SPI总线,当然在系统中有唯一的总线编号. SPI总线上有两类设备: 其一是主控端,通常作为SOC系统的一个子模块出现,很多嵌入式M ...
- spi 子系统
http://blog.csdn.net/ropenyuan/article/details/42269641 http://blog.chinaunix.net/uid-27406766-id-33 ...
- Linux内核中SPI/I2c子系统剖析
Linux内核中,SPI和I2C两个子系统的软件架构是一致的,且Linux内核的驱动模型都以bus,driver,device三种抽象对象为基本元素构建起来.下文的分析将主要用这三种抽象对象的创建过程 ...
随机推荐
- 企业打开云HBase的正确方式,来自阿里云云数据库团队的解读
一.HBase的历史由来 HBase是一个开源的非关系型分布式数据库(NoSQL),基于谷歌的BigTable建模,是一个高可靠性.高性能.高伸缩的分布式存储系统,使用HBase技术可在廉价PC Se ...
- BottomNavigationBar 自定义 底部导航条
在flutter中,BottomNavigationBar 是底部导航条,可以让我们定义底部 Tab 切换,bottomNavigationBar是 Scaffold 组件的参数. BottomNav ...
- AcWing 257. 关押罪犯 (并查集)打卡
题目:https://www.acwing.com/problem/content/description/259/ 题意:有两个监狱,监狱里面有很多犯人,现在有很多对冲突,还有个冲突值,现在问我们怎 ...
- 如何理解c++迭代器(上)
1.如何理解迭代器?迭代器不是指针,也似乎不是string这种类型 参考:迭代器与指针的区别是? C++map迭代器的++操作是如何实现的?讨论.iterator提供了遍历STL容器里元素的方式,no ...
- hdu3518 Boring counting(后缀数组)
Boring counting 题目传送门 解题思路 后缀数组.枚举每种长度,对于每个字符串,记录其最大起始位置和最小起始位置,比较是否重合. 代码如下 #include <bits/stdc+ ...
- 手机网页制作的认识(有关meta标签)(转)
仅用来记录学习: 链接地址:https://blog.csdn.net/ye1992/article/details/22714621
- 在虚拟机的Linux系统下安装wineqq
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 本文参考教程:http://www.ubuntukylin.com/ukylin/forum.php?mod=viewthread& ...
- 推荐系统之隐语义模型LFM
LFM(latent factor model)隐语义模型,这也是在推荐系统中应用相当普遍的一种模型.那这种模型跟ItemCF或UserCF的不同在于: 对于UserCF,我们可以先计算和目标用户兴趣 ...
- unique(去重函数)
去重排序(unique函数的使用) 2013年05月30日 11:05:45 阅读数:9689更多 个人分类: 字符串处理 出处:http://www.cnblogs.com/QQbai/archi ...
- VUE $SET源码