为MT7688 SPI添加N个SPI接口
要为SPI控制器中添加设备,以前的方法是在BSP文件中添加,这种方法过于麻烦,现在都使用设备树dts进行外设的描述.
要想让SPI控制器能够在加载驱动时添加你的设备,需要在dts中添加设备节点,如下:
MT7688的设备树在openwrt_widora-master/target/linux/ramips/dts/ 目录下面: Widora.dts
下面添加树节点到SPI驱动器节点下面:
palmbus@10000000 {68 spi@b00 {69 status = "okay";70 71 pinctrl-names = "default";72 73 74 pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>;75 76 m25p80@0 {77 #address-cells = <1>;78 #size-cells = <1>;79 compatible = "w25q128";80 reg = <0 0>;81 linux,modalias = "m25p80", "w25q128";82 spi-max-frequency = <40000000>;83 m25p,chunked-io = <31>;84 85 partition@0 {86 label = "u-boot";87 reg = <0x0 0x30000>;88 read-only;89 };90 91 partition@30000 {92 label = "u-boot-env";93 reg = <0x30000 0x10000>;94 };95 96 factory: partition@40000 {97 label = "factory";98 reg = <0x40000 0x10000>;99 read-only;
100 };
101
102 partition@50000 {
103 label = "firmware";
104 reg = <0x50000 0x0fb0000>;
105 };
106 };
107 /*
108 spidev@1 {
109 #address-cells = <1>;
110 #size-cells = <1>;
111 compatible = "spidev";
112 reg = <1 0>;
113 spi-max-frequency = <40000000>;
114 };
115 */
116 bpeer@1 {
117 #address-cells = <1>;
118 #size-cells = <1>;
119 compatible = "bpeer,tft0";
120 reg= <1 0>;spi-max-frequency = <60000000>;
122 spi-cpol = <1>;
123 spi-cpha = <1>;
124 };bpeer@2 { #address-cells = <1>; #size-cells = <1>; compatible = "bpeer,tft0";reg= <2 0>; spi-max-frequency = <60000000>; spi-cpha = <1>; spi-cpol = <1>;};
125 }
bpeer@1这个是我的设备节点, @前面名字可以根据自己的爱好随意命名,@后面的数字代表使用的是几号片选,我使用的是CS1,故为1,
.compatible.这里的属性必须与驱动中的结构体: struct of_device_id 中的成员.compatible保持一致,
reg:此处与bpeer@1保持一致,本例子设为:<1 0>
spi-max-frequency :此处设置spi使用的最高频率.
spi-cpol,spi-cpha:SPI 的工作模式在此设置,本例所用的SPI工作模式为SPI_MODE_3
我在这里加了两个设备节点因为我有两个类型相同的设备,所以公用的同一个驱动,不同之处在于它们的片选不同,一个是CS1,另一个是CS2,
这里估计就疑惑了吧,哪里来的CS2,别急,咱们这就加,
在这之前,要先了解一下设备树是如何被驱动使用的,众所周知,当控制器驱动注册到系统后,spi驱动会扫描控制器节点下面的子节点,也就是看有几个设备,
调用过程如下,首先在spi-mt7621.c的 static int mt7621_spi_probe(struct platform_device *pdev) 函数的结尾,注册了控制器驱动到系统,
472 spin_lock_irqsave(&rs->lock, flags);
473
474 device_reset(&pdev->dev);
475
476 mt7621_spi_reset(rs, 0);
477
478 return spi_register_master(master);
spi_register_master(master)函数会扫描有多少个设备
在spi/spi.c中有对此函数的定义,只关心咱们要分析的如下:
1675 list_for_each_entry(bi, &board_list, list)
1676 spi_match_master_to_boardinfo(master, &bi->board_info);
1677 mutex_unlock(&board_lock);
1678
1679 /* Register devices from the device tree and ACPI */
1680 of_register_spi_devices(master);
1681 acpi_register_spi_devices(master);
of_register_spi_devices(master);会注册所有的设备,它会根据设备树填充一个struct spi_device 结构体代表一个设备:
852 /* Device address */853 prop = of_get_property(nc, "reg", &len);854 if (!prop || len < sizeof(*prop)) {855 dev_err(&master->dev, "%s has no 'reg' property\n",856 nc->full_name);857 spi_dev_put(spi);858 continue;859 }860 spi->chip_select = be32_to_cpup(prop);861 862 /* Mode (clock phase/polarity/etc.) */863 if (of_find_property(nc, "spi-cpha", NULL))864 spi->mode |= SPI_CPHA;865 if (of_find_property(nc, "spi-cpol", NULL))866 spi->mode |= SPI_CPOL;867 if (of_find_property(nc, "spi-cs-high", NULL))868 spi->mode |= SPI_CS_HIGH;869 if (of_find_property(nc, "spi-3wire", NULL))870 spi->mode |= SPI_3WIRE;871 872 /* Device speed */873 prop = of_get_property(nc, "spi-max-frequency", &len);874 if (!prop || len < sizeof(*prop)) {875 dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n",876 nc->full_name);877 spi_dev_put(spi);878 continue;879 }880 spi->max_speed_hz = be32_to_cpup(prop);
设备树里面的它都会读到并且填充到struct spi_device 结构体中作为一个设备,注意第860行,它会读取reg属性字段,并填充到spi->chip_select中作为几号片选,这里就OK了
了解完这些后我们就利用一个GPIO来作为片选2来使用,
方法就是,在SPI控制器驱动的mt7621_spi_setup(struct spi_device *spi)中添加对GPIO的申请及配置,注意头文件中要包含#include<linux/gpio.h>,修改如下:
static int mt7621_spi_setup(struct spi_device *spi)
382 {
383 struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
384 int status = 0;
385 if ((spi->max_speed_hz == 0) ||
386 (spi->max_speed_hz > (rs->sys_freq / 2)))
387 spi->max_speed_hz = (rs->sys_freq / 2);
388
389 if (spi->max_speed_hz < (rs->sys_freq / 4097)) {
390 dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n",
391 spi->max_speed_hz);
392 return -EINVAL;
393 }
394 /**************************************************************
395 * Modefiy Liuchen on here
396 ***************************************************************/
397 // int cs = spi->cs_gpio;
398 int cs = spi->chip_select;
399 if( cs >= 2 )
400 {
401 status = gpio_request( 42, dev_name( &spi->dev ) );
402 dev_info( spi->master->dev.parent,"in %s,cs_gpio =%d, status =%d\n", __func__, cs, status );
403 if( status ) return status;
404 status = gpio_direction_output( 42, 1);
405 }
406 return status;
407 }
该函数会在static void of_register_spi_devices(struct spi_master *master)中被调用.
接下来添加GPIO作为CS来操作,修改另外一个函数 mt7621_spi_set_cs(struct spi_device *spi, int enable),此函数用来设置CS片选信号的拉低及拉高,修改如下:
102 static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
103 {
104 struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
105 int cs = spi->chip_select;
106 u32 polar = 0;
107
108 mt7621_spi_reset(rs, cs);
109 if(cs == 2)
110 {
111 //printk("enable = %d\n",enable);
112 //gpio_set_value_cansleep( 42, enable );
113 gpio_set_value_cansleep( 42, (spi->mode&SPI_CS_HIGH)?enable: !enable );
114 }else
115 {
116 if (enable)
117 polar = BIT(cs);
118 mt7621_spi_write(rs, MT7621_SPI_POLAR, polar);
119 }
120 }
至此已经添加完毕,重新编译内核就0K了.还有一种方式是在dts中直接添加,再此忽略了哦,没时间去搞了.........
为MT7688 SPI添加N个SPI接口相关推荐
- 基于MT7688 原厂SDK 使用SPI控制器驱动TFT屏幕ILI9225驱动器(spi接口)
以下是我的一个利用SPI控制器操作屏的一个操作实例 包含一个bpeer_tft.c 和一个bpeer_tft.h 这是我基于flash驱动剥离出来的spi控制器驱动 好的话,顶起来~~~~~~~~~~ ...
- SPI通信协议:单片机spi通信接口什么意思,spi接口干什么用的?
讲真,以前做开发的时候最怕就是调spi和iic. 因为公司没有逻辑分析仪,调起来全凭经验,一出问题找都找不到,只能仔细看代码盲调,看是不是哪个时序有问题. 说到这里,可能刚初学的小伙伴会问:单片机sp ...
- java spi_Java SPI(服务提供商接口)和ServiceLoader
java spi Java SPI (Service Provider Interface) is the mechanism to load services dynamically. We can ...
- 微雪树莓派PICO笔记——7. SPI(串行外设接口)
文章目录 SPI简介 硬件连接 通讯协议详解 RP2040 SPI 主要参数 RP2040 SPI 逻辑框图 machine.SPI类函数详解 例程地址 代码示例 代码实现 SPI简介 SPI全称为串 ...
- 为您的高速SPI添加强大和可靠的隔离交流
介绍 串行外设接口(SPI)是工业设备中常用于数字处理器核心和外围设备之间通信的一种协议.然而,为了安全使用,有必要对外围设备和核心进行电隔离.虽然隔离和SPI都是成熟的技术,但将两者接口并不像预期的 ...
- SPI协议概括、SPI总线工作的四种方式和SPI接口时序
SPI协议概括: SPI总线是一种4线总线,因其硬件功能很强,所以与SPI有关的软件就相当简单,使中央处理器(Central Processing Unit,CPU)有更多的时间处理其他事务.正是因为 ...
- linux spi屏驱动程序,65 linux spi设备驱动之spi LCD屏驱动
SPI的控制器驱动由平台设备与平台驱动来实现. 驱动后用spi_master对象来描述.在设备驱动中就可以通过函数spi_write, spi_read, spi_w8r16, spi_w8r8等函数 ...
- ginkgo spi 错误_开发SPI时不要犯这个错误
ginkgo spi 错误 您的大多数代码都是私有的,内部的,专有的,并且永远不会公开. 在这种情况下,您可以放轻松–您可以重构所有错误,包括那些可能导致API更改中断的错误. 但是,如果要维护公共A ...
- Arduino 与 SPI 结合使用 以及SPI 深层理解
本文主要讲解两部分内容,不做任何转发,仅个人学习记录: 一. Arduino 与 SPI 结合使用 : 二. SPI 深层理解 有价值的几个好的参考: 1. 中文版: https://blog.cs ...
最新文章
- SpringBoot入门(1)——创建springBoot项目
- hdu_4391,线段树
- 【暑假训练 7.10】 codevs 2492 上帝造题的七分钟2
- CentOS7下解决yum install mysql-server没有可用包的问题
- 比较=、==、===
- 详解Java动态代理机制
- 大神干货:冠军选手分享解题思路,助你轻松突围初赛
- ArrayList的add方法值被覆盖(android项目)
- Ubuntu18 mongodb 离线安装
- 《地球概论》(第3版)笔记 第二章 地球的宇宙环境
- 直线型一阶倒立摆3---控制器设计
- 超市进销存之openGauss数据库的应用与实践
- 001、【C语言编程题目】猴子吃桃问题
- 来钱快的3种副业,虽然不起眼,不过很赚钱
- ggplot 绘制热图
- CLICKHOUSE函数使用经验(arrayJoin与arrayMap函数应用场景)
- Excel大数据排查重复行内容方法,三步搞定!
- geotools 可视化,具有无状态渲染器
- 【离散数学期复习系列】二、一阶逻辑(谓词逻辑)
- 北京精雕电主轴用海德汉编码器AK ERM280/2480/TTRERM2404/vs sensorik编码器RGM2G-AE3-V3Z参数接线定义