Rockchip SPI 功能特点

SPI (serial peripheral interface),以下是 linux 4.4 spi 驱动支持的一些特性︰

  • 默认采用摩托罗拉 SPI 协议
  • 支持 8 位和 16 位
  • 软件可编程时钟频率和传输速率高达 50MHz
  • 支持 SPI 4 种传输模式配置
  • 每个 SPI 控制器支持一个到两个片选
    除以上支持,linux 4.19 新增以下特性:
  • 框架支持 slave 和 master 两种模式

代码路径

内核配置

DTS 节点配置

spi1: spi@fe620000 {compatible = "rockchip,rk3066-spi";reg = <0x0 0xfe620000 0x0 0x1000>;interrupts = <0 104 4>;#address-cells = <1>;#size-cells = <0>;clocks = <&cru 340>, <&cru 339>;clock-names = "spiclk", "apb_pclk";dmas = <&dmac0 22>, <&dmac0 23>;dma-names = "tx", "rx";pinctrl-names = "default", "high_speed";pinctrl-0 = <&spi1m0_cs0 &spi1m0_cs1 &spi1m0_pins>;pinctrl-1 = <&spi1m0_cs0 &spi1m0_cs1 &spi1m0_pins_hs>;status = "disabled";
};

&spi1 : 引用spi 控制器节点
clocks:指定 SPI sclk,可以通过查看 dtsi 中命名为 spiclk 的时钟
dmas 、dma-names : 使能DMA模式,一般通讯字节少于32字节的不建议用,dtsi 中默认设定,可通过置空赋值去掉使能;

spi 读写操作

对 spi 读写操作请参考 include/linux/spi/spi.h,以下简单列出几个:

spi_write

/*** spi_write - SPI synchronous write* @spi: device to which data will be written* @buf: data buffer* @len: data buffer size* Context: can sleep** This function writes the buffer @buf.* Callable only from contexts that can sleep.** Return: zero on success, else a negative error code.*/
static inline int
spi_write(struct spi_device *spi, const void *buf, size_t len)
{struct spi_transfer    t = {.tx_buf       = buf,.len     = len,};return spi_sync_transfer(spi, &t, 1);
}

spi_read

/*** spi_read - SPI synchronous read* @spi: device from which data will be read* @buf: data buffer* @len: data buffer size* Context: can sleep** This function reads the buffer @buf.* Callable only from contexts that can sleep.** Return: zero on success, else a negative error code.*/
static inline int
spi_read(struct spi_device *spi, void *buf, size_t len)
{struct spi_transfer    t = {.rx_buf       = buf,.len     = len,};return spi_sync_transfer(spi, &t, 1);
}

spi_sync_transfer

/*** spi_sync_transfer - synchronous SPI data transfer* @spi: device with which data will be exchanged* @xfers: An array of spi_transfers* @num_xfers: Number of items in the xfer array* Context: can sleep** Does a synchronous SPI data transfer of the given spi_transfer array.** For more specific semantics see spi_sync().** Return: Return: zero on success, else a negative error code.*/
static inline int
spi_sync_transfer(struct spi_device *spi, struct spi_transfer *xfers,unsigned int num_xfers)
{struct spi_message msg;spi_message_init_with_transfers(&msg, xfers, num_xfers);return spi_sync(spi, &msg);
}

当然也可以自己封装,以下也简单列出几个

spidev_sync_write

static inline ssize_t
spidev_sync_write(struct spidev_data *spidev, size_t len)
{int status;char cmd[1] = {PAGE_PROGRAM};unsigned char addr[3];struct spi_transfer c[] = {{.tx_buf = cmd,.len = ARRAY_SIZE(cmd),},{.tx_buf = addr,.len = ARRAY_SIZE(addr),},};struct spi_transfer t = {.tx_buf       = spidev->tx_buffer,.len        = len,.speed_hz    = spidev->speed_hz,};struct spi_message m;addr[0] = (unsigned char)((spidev->cur_addr & 0xff0000) >> 16);addr[1] = (unsigned char)((spidev->cur_addr & 0xff00) >> 8);addr[2] = (unsigned char)(spidev->cur_addr & 0xff);rs_spi_w25x_write_enable(spidev->spi);spi_message_init(&m);spi_message_add_tail(&c[0], &m);spi_message_add_tail(&c[1], &m);spi_message_add_tail(&t, &m);status = spidev_sync(spidev, &m);rs_spi_w25x_wait_ready(spidev->spi);return status;
}

spidev_sync_read

static inline ssize_t
spidev_sync_read(struct spidev_data *spidev, size_t len)
{int status;char cmd[] = {READ_DATA};unsigned char addr[3];struct spi_transfer t[] = {{.tx_buf = cmd,.len = ARRAY_SIZE(cmd),.speed_hz = spidev->speed_hz,},{.tx_buf = addr,.len = ARRAY_SIZE(addr),},{.rx_buf     = spidev->rx_buffer,.len        = len,.speed_hz    = spidev->speed_hz,}};struct spi_message    m;addr[0] = (unsigned char)((spidev->cur_addr & 0xff0000) >> 16);addr[1] = (unsigned char)((spidev->cur_addr & 0xff00) >> 8);addr[2] = (unsigned char)(spidev->cur_addr & 0xff);spi_message_init(&m);spi_message_add_tail(&t[0], &m);spi_message_add_tail(&t[1], &m);spi_message_add_tail(&t[2], &m);status = spidev_sync(spidev, &m);rs_spi_w25x_wait_ready(spidev->spi);return status;
}

例子

&spi1 {status = "okay" ;spi_test@00 {status = "okay";compatible = "rockchip,test";reg = <0x00>;spi-max-frequency = <24000000>; /*spi clk输出的时钟频率,不超过
50M */spi-lsb-first;  /* IO 先传输 lsb8*/spi-cpha;       /*SPI mode: CPHA = 1,不配置则为 0*/spi-cpol;       /*SPI mode: CPOL = 1,不配置则为 0*/
};

spiclk assigned-clock-rates 和 spi-max-frequency 的配置说明:

  • spi-max-frequency 是 SPI 的输出时钟,由 SPI 工作时钟 spiclk assigned-clock-rates 内部分频后输出,由于内部至少 2 分频,所以关系是 spiclk assigned-clock-rates >= 2*spi-max-frequency;
  • 假定需要 50MHz 的 SPI IO 速率,可以考虑配置(记住内部分频为偶数分频)spi_clk assigned-clockrates = <100000000>,spi-max-frequency = <50000000>,即工作时钟 100 MHz(PLL 分频到一个不大于 100MHz 但最接近的值),然后内部二分频最终 IO 接近 50 MHz;
  • spiclk assigned-clock-rates 不要低于 24M,否则可能有问题;
  • 如果需要配置 spi-cpha 的话, 要求 spiclk assigned-clock-rates <= 6M, 1M <= spi-max-frequency >=3M

cs-gpios 支持

可以通过 spi-bus 的 cs-gpios 属性来实现 gpio 模拟 cs 以扩展 SPI 片选信号

Optional properties (master mode only):
- cs-gpios    - gpios chip select.
- num-cs      - total number of chipselects.If cs-gpios is used the number of chip selects will be increased automatically
with max(cs-gpios > hw cs).So if for example the controller has 2 CS lines, and the cs-gpios
property looks like this:cs-gpios = <&gpio1 0 0>, <0>, <&gpio1 1 0>, <&gpio1 2 0>;Then it should be configured so that num_chipselect = 4 with the
following mapping:cs0 : &gpio1 0 0
cs1 : native
cs2 : &gpio1 1 0
cs3 : &gpio1 2 0

设备驱动注册

static int spi_test_probe(struct spi_device *spi)
{int ret;int id = 0;if(!spi)return -ENOMEM;spi->bits_per_word= 8;ret= spi_setup(spi);if(ret < 0) {dev_err(&spi->dev,"ERR: fail to setup spi\n");return-1;} return ret;
} static int spi_test_remove(struct spi_device *spi)
{printk("%s\n",__func__);return 0;
}static const struct of_device_id spi_test_dt_match[]= {{.compatible = "rockchip,test",}.{},
};
MODULE_DEVICE_TABLE(of,spi_test_dt_match);static struct spi_driver spi_test_driver = {.driver = {.name = "spi_test",.owner = THIS_MODULE,.of_match_table = of_match_ptr(spi_test_dt_match),},.probe = spi_test_probe,.remove = spi_test_remove,
};static int __init spi_test_init(void)
{int ret = 0;ret = spi_register_driver(&spi_test_driver);return ret;
}
device_initcall(spi_test_init);static void __exit spi_test_exit(void)
{return spi_unregister_driver(&spi_test_driver);
}
module_exit(spi_test_exit);

具体的使用可以参考:https://blog.csdn.net/qq_29890089/article/details/121230149

RK356X SPI 使用相关推荐

  1. stc15w404as引脚图_STC15F2K6S2与stc15w404AS的spi通讯

    #include/*********************************位定义***********************************/ #define uchar unsi ...

  2. I2C和SPI总线优缺点对比

    IIC vs SPI现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影 ...

  3. Java中的ClassLoader和SPI机制

    深入探讨 Java 类加载器 成富是著名的Java专家,在IBM技术网站发表很多Java好文,也有著作. 线程上下文类加载器 线程上下文类加载器(context class loader)是从 JDK ...

  4. Java的SPI机制

    Dubbo等框架使用到必须掌握. java.sql.Driver 是 Spi,com.mysql.jdbc.Driver 是 Spi 实现,其它的都是 Api. package org.hadoop. ...

  5. linux spi双机通信,【转】STM32 SPI双机通信(主从全双工)

    欢迎大家测试 u8 SPI1_ReadByte(u8 TxData) { u8 retry=0; // while((SPI1->SR&1<<1)==0)//等待发送区空 / ...

  6. JDK/Dubbo/Spring 三种 SPI 机制,谁更好?

    点击关注公众号,Java干货及时送达 来源:juejin.cn/post/6950266942875779108 SPI 全称为 Service Provider Interface,是一种服务发现机 ...

  7. 通讯波形记录——I2S、I2C、Uart、SPI

    SPI波形 设置: UART I2S 扩展: I2S有3个主要信号: 1.  SCLK:串行时钟,也叫位时钟(BCLK),即对应数字音频的每一位数据,SCLK都有1个脉冲.SCLK的频率=2×采样频率 ...

  8. SPI flash配置

    配置表中预先配好了一些,我们用到什么SPI就需要添加相应的spi配置参数 spi flash name jedec_id ext_id block_size chip_size clk chip se ...

  9. spi nor flash使用汇总

    Overview SPI flash, 分为spi flash, DUAL spi flash, QUAD spi flash, 3-wire spi, 4-wire spi, 6-wire spi. ...

  10. c语言spi发送12位数据,【51单片机】普通I/O口模拟SPI口C语言程序

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 89C51系列单片机都不带SPI口,所在在这种情况下,我们可以模拟SPI口来现实我们要的功能,程序如下: //---------------------- ...

最新文章

  1. 用python实现水仙花数
  2. 大型网站架构模式之一
  3. Serverless Kubernetes:理想,现实与未来
  4. git学习笔记04-将本地仓库添加到GitHub远程仓库-git比svn先进的地方
  5. iOS9适配(包括APNs)的改变
  6. 洪学海(1967-),男,博士,中国科学院计算技术研究所研究员,信息技术战略研究中心常务副主任。...
  7. 设计素材|美丽的几何和多边形背景纹理
  8. ELF文件加载与动态链接(一)
  9. android canvas_Android实现自定义阴影效果
  10. 驱动人生服务器正在维护,驱动人生驱动更新失败或者设备出现异常的解决方法...
  11. 移动网络怎么修改服务器地址,移动宽带怎么修改wifi密码?
  12. chm文件无法打开,chm电子书显示“此程序无法显示网页”的解决办法
  13. 猜数字(Bulls and Cows)游戏
  14. 国产麒麟系统PXE安装-传统bios(legacy)引导
  15. 02—JAVA(基础)—(数据类型转换,运算符,方法)
  16. etcd之日志和快照管理
  17. windows程序设计(一)
  18. 元宇宙临近,区块链成为新世代的底层技术的脉络越发清晰
  19. 1~n中与n互质数的个数(欧拉函数)
  20. Oracle11G的数据库数据导入导出(由11g上导出导入10g数据库等)

热门文章

  1. 2020年11月总结
  2. Docker Windows Containers
  3. H264解码器源码(Android 1.6 版)
  4. 【历史上的今天】9 月 28 日:“超级计算机之父”诞生;三星推出移动支付;LibreOffice 发布
  5. 2021年焊工(初级)报名考试及焊工(初级)新版试题
  6. ajax dojo deferred,Dojo学习-14:Ajax with dojo/request
  7. ITSM基础框架开发维护指南
  8. 德州达拉斯大学计算机录取要求,德克萨斯大学达拉斯分校申请条件(德克萨斯大...
  9. 想要降低gradle版本时遇到“Minimum supported Gradle version is XXX. Current version is XXX.”
  10. 全息眼镜HoloLens可快速捕捉真人3D图像