无限可能!为MT7620添加N个SPI接口

前言

我的上一篇文章中谈到,如何使能mt7620的第二个spi接口.既然第二个spi接口已经开放成功,那么,可否接着添加第三个、第四个spi接口呢?熟悉mt7620硬件的朋友一定会第一时间站出来反对我:怎么可能!?mt7620总共才两个spi接口,怎么可能添加更多呢?除非在硬件上想办法.然而我总是善于将不可能变为可能^_^,今天我就要和大家分享一下,如何不改动任何硬件,通过修改驱动的方法,实现多个spi接口.注意,我这里实现的spi,并非用gpio口模拟的bitbang伪spi,而是基于硬件spi的真实接口.

背景知识

总所周知,mt7620有两个独立的硬件spi接口,且对应的片选cs为cs0与cs1.如果读者朋友对spi总线的通讯协议略懂的话,会发现:spi的通讯是按照message的方式来进行的,一次通讯过程是通过transfer_one_message的方法来实现.实际上是对spi硬件接口的分时复用.如果我们能够找到办法,扩充一下cs片选信号,且保留对spi硬件的分时复用,不就可以完美实现我们的目标了?那么问题来了:如何扩充cs片选?如何让spi硬件不产生冲突?具体如何实现?各位看官莫急,且听我慢慢道来.

实现过程

dts文件的奥秘

dts文件中有很多隐藏关卡(不要问我为神马知道这么多,因为我喜欢看驱动源码,嘿嘿^_^),通过简单的改动,就可以让spi凭空多出cs片选来.

        [email protected] {
            compatible = "ralink,rt5350-spi";
            status = "okay";
            cs-gpios = <0>, <0>, <&gpio3 0 1>;
            ...
            };

怎么样?就这么简(REN)单(XING),就能为spi总线添加一个用gpio口线实现的片选cs2(这个处理过程,实际上是在spi.c中完成的,读者朋友花点时间看看这个文件便能豁然开朗).在进行下面的讲解之前,让我再啰嗦几句,cs-gpio前面的<0>,<0>表示使用系统默认的cs0,与cs1,而cs2则绑定到gpio72.接下来,我们就要对驱动进行相应的修改,使之能够配合我们新指定的cs.

修改spi-rt2880.c

添加头文件

由于要用到gpio口,所以需要在文件开头

#include <linux/gpio.h>

修改宏定义

让mt7620的第二个spi成为分时复用的硬件接口,修改如下:

// manfeel, try to add more cs pins(>2)
#define M(cs) (cs ? 1 : cs)
#define RAMIPS_SPI_STAT(cs)     (0x00 + (M(cs) * RAMIPS_SPI_DEV_OFFSET))
#define RAMIPS_SPI_CFG(cs)      (0x10 + (M(cs) * RAMIPS_SPI_DEV_OFFSET))
#define RAMIPS_SPI_CTL(cs)      (0x14 + (M(cs) * RAMIPS_SPI_DEV_OFFSET))
#define RAMIPS_SPI_DATA(cs)     (0x20 + (M(cs) * RAMIPS_SPI_DEV_OFFSET))
#define RAMIPS_SPI_FIFO_STAT(cs)    (0x38 + (M(cs) * RAMIPS_SPI_DEV_OFFSET))

也就是说,当cs>=1的时候,第二个spi接口负责所有的通讯工作.

改动rt2880_spi_setup

static int rt2880_spi_setup(struct spi_device *spi)
{
    struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
    int status = 0;
    if ((spi->max_speed_hz == 0) ||
        (spi->max_speed_hz > (rs->sys_freq / 2)))
        spi->max_speed_hz = (rs->sys_freq / 2);

    if (spi->max_speed_hz < (rs->sys_freq / 128)) {
        dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n",
            spi->max_speed_hz);
        return -EINVAL;
    }

    // manfeel, set cs_gpio
    int cs = spi->cs_gpio;
    if (cs >= 0) {
        status = gpio_request(cs, dev_name(&spi->dev));
        dev_info(spi->master->dev.parent, "in %s, cs_gpio = %d, status = %d\n",__func__, cs, status);
        if (status)
            return status;
        status = gpio_direction_output(cs, !(spi->mode & SPI_CS_HIGH));
    }
    /*
     * baudrate & width will be set rt2880_spi_setup_transfer
     */
    return status;
}

注意spi->cs_gpio,与dts中的cs-gpios对应,其值分别为-2,-2,72.-2表示没有对应的gpio(由系统硬件实现片选).

修改rt2880_spi_set_cs

static void rt2880_spi_set_cs(struct spi_device *spi, int enable)
{
    struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
    int cs = spi->chip_select;
    // manfeel, deal cs_gpio first
    if (spi->cs_gpio >= 0) {
        /* SPI is normally active-low */
        gpio_set_value_cansleep(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? enable : !enable);
    } else {
        if (enable)
            rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_SPIENA);
        else
            rt2880_spi_setbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_SPIENA);
    }
}

总共添加不到20行代码,就实现了N个spi接口!

实验

将三个不同的spi flash同时连接到开发板上:

cs0连接w25q256

cs1连接s25sl032p

cs2(gpio72,亦即WLED_GPIO)连接en25p64

上电开机,观察TTL输出,能够看到如下内容:

[    0.570000] m25p80 spi32766.0: r=0, sreg3=0
[    0.570000] m25p80 spi32766.0: w25q256 (32768 Kbytes)
[    0.580000] 4 ofpart partitions found on MTD device spi32766.0
[    0.600000] Creating 4 MTD partitions on "spi32766.0":
[    0.600000] 0x000000000000-0x000000030000 : "u-boot"
[    0.620000] 0x000000030000-0x000000040000 : "u-boot-env"
[    0.620000] 0x000000040000-0x000000050000 : "factory"
[    0.640000] 0x000000050000-0x000002000000 : "firmware"
[    0.740000] 2 uimage-fw partitions found on MTD device firmware
[    0.760000] 0x000000050000-0x0000001de092 : "kernel"
[    0.760000] mtd: partition "kernel" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only
[    0.760000] 0x0000001de092-0x000002000000 : "rootfs"
[    0.760000] mtd: partition "rootfs" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only
[    0.760000] mtd: device 5 (rootfs) set to be root filesystem
[    0.760000] 1 squashfs-split partitions found on MTD device rootfs
[    0.760000] 0x000000470000-0x000002000000 : "rootfs_data"
[    0.760000] m25p80 spi32766.1: r=0, sreg3=0
[    0.760000] m25p80 spi32766.1: found s25sl032p, expected w25q256
[    0.760000] m25p80 spi32766.1: s25sl032p (4096 Kbytes)
[    0.760000] 1 ofpart partitions found on MTD device spi32766.1
[    0.760000] Creating 1 MTD partitions on "spi32766.1":
[    0.760000] 0x000000000000-0x000002000000 : "edisk1"
[    0.760000] mtd: partition "edisk1" extends beyond the end of device "spi32766.1" -- size truncated to 0x400000
[    0.760000] spi-rt2880 10000b00.spi: in rt2880_spi_setup, cs_gpio = 72, status = 0
[    0.760000] m25p80 spi32766.2: r=0, sreg3=0
[    0.760000] m25p80 spi32766.2: found en25p64, expected w25q256
[    0.760000] m25p80 spi32766.2: en25p64 (8192 Kbytes)
[    0.760000] 1 ofpart partitions found on MTD device spi32766.2
[    0.760000] Creating 1 MTD partitions on "spi32766.2":
[    0.760000] 0x000000000000-0x000002000000 : "edisk2"
[    0.760000] mtd: partition "edisk2" extends beyond the end of device "spi32766.2" -- size truncated to 0x800000

总结

通过添加cs-gpios的方式实现了N个spi接口,鉴于spi接口的简单高效与灵活,大大加强了mt7620芯片的战斗力.以后,可以在mt7620上添加spi接口的各种设备,而不需要有spi接口不够的顾虑了.

ps:本文用CSDN提供的mdeditor完成.

时间: 2024-08-25 19:26:36

无限可能!为MT7620添加N个SPI接口的相关文章

使能MT7620的第二个SPI接口(cs1)——兼谈pinmux与pinctrl驱动

前言 根据MT7620的数据手册,该芯片支持两个独立的spi接口,由于驱动不完善等种种原因,一直没能顺利的使用第二个spi接口.近日对mt7620的spi好好研究了一下,终于使能了第二个spi接口,将过程记录成文. 实现过程 spi驱动的诡异之处 mt7620的spi驱动位于:drivers/spi/spi-rt2880.c,里面有关spi cs1的代码非常诡异,因为7620与5350使用的是同一个spi控制芯片,而该驱动却区别对待,7620只有一个spi,5350有两个. 1: static 

STM32——SPI接口

STM32--SPI接口 宗旨:技术的学习是有限的,分享的精神的无限的. 一.SPI协议[SerialPeripheral Interface] 串行外围设备接口,是一种高速全双工的通信总线.在ADC/LCD等与MCU间通信. 1.SPI信号线 SPI 包含 4 条总线,SPI 总线包含 4 条总线,分别为SS .SCK.MOSI.MISO. (1)SS(SlaveSelect):片选信号线,当有多个 SPI 设备与 MCU 相连时,每个设备的这个片选信号线是与 MCU 单独的引脚相连的,而其他

自定义AXI总线形式SPI接口IP核,点亮OLED

一.前言 最近花费很多精力在算法仿真和实现上,外设接口的调试略有生疏.本文以FPGA控制OLED中的SPI接口为例,重新夯实下基础.重点内容为SPI时序的RTL设计以及AXI-Lite总线分析.当然做些项目时可以直接调用Xilinx提供的SPI IP核,这里仅出于练习的目的考虑. 二.接口时序分析 本项目用的OLED型号为UG-2832HSWEG04,核心控制器是SSD1306.该芯片支持并口.I2C以及SPI接口,这里采用4线SPI作为数据总线.4线SPI接口包括: SCLK:串行时钟,SSD

SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)

SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART(Universal Asynchronous Receiver Transmitter:通用异步收发器) 第二,区别在电气信号线上: SPI总线由三条信号线组成:串行时钟(SCLK).串行数据输出(SDO).串行数据输入(SDI).SPI总线可以实现多个SPI设备互相连接.提供SPI串行时钟的SPI

高通APQ8074 spi 接口配置

8074 平台含有两个BLSP(BAM Low-Speed Peripheral) , 每一个BLSP含有两个QUP, 每一个QUP可以被配置为I2C, SPI, UART, UIM接口, BLSP是高通对于低速接口的一种管理方式. 每个QUP是和特定的引脚相关的, 如下图所示,比如下面的引脚是属于BLSP8的, 也就是第二个BLSP的第二个QUP, 注意这些引脚只能被配置到第二个BLSP的第2个QUP上,可以通过继续查看高通相关资料 QUP的中断相关信息 得到这些信息后,如果只是要将SPI配置

tair中对get/get_range接口的理解及为get_range添加命令行测试接口

经过这段时间对淘宝开源K/V缓存系统tair基础接口put/get/get_range等源码的详细剖析后,按自己的理解简单总结下tair中我较关心的get和get_range这两个接口的基本实现流程.由于get_range接口是最新几个版本才加入的功能,因此以前的tair Java客户端及最新版本安装后的命令行测试中都没有加入get_range测试接口,这无疑给需要专门优化get_range接口的我带来了不便,因此本文最后给出了在tair中实现get_range命令行测试的方法和示例. 1 ta

如何从Cortex-m向STM32移植使用SPI接口协议

/***************************************************************************************************** * @brief: LDC1000应用程序 * _____________ _______________ * |PB4(SSI2CLK) ----> SCLK| * |PB5(SSI2FSS) ----> CSB | * |PB6(SSI2RX)    <----       SDO

[译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口)

原文:[译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口) 应用不只是包含textboxs和labels,还包含actions,如按钮和鼠标事件等.接下来我们加上一些像按钮这样的UI元素来看MVVM类怎么演变的.与之前的UI相比,这次我们加上一个"Cal Tax"按钮,当我们点击这个依赖于“sales amount”的按钮时,它会计算税费并显示在同窗口内. 为了完成所述的功能,我们先在Model类中添加一个

嵌入式物联网之SPI接口原理与配置

本实验采用W25Q64芯片 W25Q64是华邦公司推出的大容量SPI FLASH产品,其容量为64Mb.该25Q系列的器件在灵活性和性能方面远远超过普通的串行闪存器件.W25Q64将8M字节的容量分为128个块,每个块大小为64K字节,每个块又分为16个扇区,每个扇区4K个字节.W25Q64的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节.所以,这需要给W25Q64开辟一个至少4K的缓存区,这样必须要求芯片有4K以上的SRAM才能有很好的操作. W25Q64的擦写周期多达10W次,可将数据