You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DTS中正确描述SPI总线及双电能计量芯片配置?

ARM Linux SPI双电能计量芯片驱动实现方案

一、DTS总线与双设备配置

由于两颗芯片共享SPI总线、使用独立GPIO片选,需在设备树中明确描述SPI控制器及两个计量设备节点:

// 假设使用SPI1控制器,根据实际硬件调整节点名
&spi1 {
    pinctrl-names = "default";
    // 绑定SPI控制器的pinctrl配置(包含mosi/miso/sck引脚复用)
    pinctrl-0 = <&spi1_pins>;
    status = "okay";
    // 全局声明可用片选GPIO,每个设备可单独指定
    cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>, <&gpio1 11 GPIO_ACTIVE_LOW>;

    // 第一颗电能计量芯片
    energy_meter@0 {
        // 与驱动的compatible字段匹配
        compatible = "your-vendor,energy-meter-chip";
        // reg值对应chip_select编号,从0开始
        reg = <0>;
        spi-max-frequency = <1000000>; // 芯片支持的最高SPI时钟
        // 单独指定该设备的片选GPIO(必须与硬件一致,不可修改)
        cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
    };

    // 第二颗电能计量芯片
    energy_meter@1 {
        compatible = "your-vendor,energy-meter-chip";
        reg = <1>;
        spi-max-frequency = <1000000>;
        cs-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
    };
};
  • SPI控制器的pinctrl-0关联的引脚配置节点(如spi1_pins)需在板级DTS中定义,指定mosi/miso/sck引脚的复用功能与电气参数,这部分由SOC厂商的DTSI或板级配置完成,驱动无需修改。
  • 每个设备节点的cs-gpios必须严格匹配硬件连接的GPIO,内核会自动将该值填充到struct spi_device的cs_gpio字段。

二、struct spi_board_info字段说明

若使用设备树枚举设备(当前主流方式),无需手动初始化struct spi_board_info,内核会自动从DTS解析生成struct spi_device实例。

若需兼容无DTS的老内核场景:

  • bus_num:对应SPI控制器的编号(如SPI1对应1,需与内核中SPI控制器的注册编号一致)。
  • chip_select:对应设备的片选编号,与DTS中reg值一致(第一颗为0,第二颗为1)。

三、单驱动管控双设备实现

驱动只需注册一个struct spi_driver,内核会为每个DTS中匹配的spi_device调用一次probe函数,通过私有数据区分不同设备:

#include <linux/spi/spi.h>
#include <linux/device.h>

// 私有数据结构,存储每个设备的独立状态与数据
struct energy_meter_data {
    struct spi_device *spi;
    int dev_id; // 区分两颗芯片(0或1)
    // 计量数据缓存
    u32 voltage;
    u32 current;
};

// sysfs电压属性读取函数
static ssize_t voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct energy_meter_data *data = spi_get_drvdata(to_spi_device(dev));
    // 此处添加从对应芯片读取电压的逻辑
    return sprintf(buf, "%u\n", data->voltage);
}
static DEVICE_ATTR_RO(voltage);

// sysfs电流属性读取函数
static ssize_t current_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct energy_meter_data *data = spi_get_drvdata(to_spi_device(dev));
    // 此处添加从对应芯片读取电流的逻辑
    return sprintf(buf, "%u\n", data->current);
}
static DEVICE_ATTR_RO(current);

static struct attribute *energy_meter_attrs[] = {
    &dev_attr_voltage.attr,
    &dev_attr_current.attr,
    NULL,
};
ATTRIBUTE_GROUPS(energy_meter);

static int energy_meter_probe(struct spi_device *spi)
{
    struct energy_meter_data *data;
    int ret;

    // 分配并初始化私有数据
    data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
    if (!data)
        return -ENOMEM;

    data->spi = spi;
    data->dev_id = spi->chip_select; // 从spi_device获取设备编号

    // 绑定私有数据到spi_device
    spi_set_drvdata(spi, data);

    // 注册sysfs属性组
    ret = sysfs_create_group(&spi->dev.kobj, &energy_meter_group);
    if (ret)
        return ret;

    // 此处添加芯片初始化逻辑(如复位、配置寄存器)
    return 0;
}

static void energy_meter_remove(struct spi_device *spi)
{
    sysfs_remove_group(&spi->dev.kobj, &energy_meter_group);
}

static const struct of_device_id energy_meter_of_match[] = {
    { .compatible = "your-vendor,energy-meter-chip" },
    { /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, energy_meter_of_match);

static struct spi_driver energy_meter_driver = {
    .driver = {
        .name = "energy-meter-driver",
        .of_match_table = energy_meter_of_match,
    },
    .probe = energy_meter_probe,
    .remove = energy_meter_remove,
};
module_spi_driver(energy_meter_driver);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Dual Energy Meter SPI Driver");
  • 每个设备的sysfs属性会生成在各自的设备目录下(如/sys/bus/spi/devices/spi1.0/voltage和/sys/bus/spi/devices/spi1.1/voltage),天然实现数据隔离。
  • 芯片初始化、数据读取逻辑需根据芯片手册实现,读取时通过spi_device的cs_gpio自动切换片选,无需手动控制GPIO。

四、SPI线路GPIO的指定说明

SPI的mosi/miso/sck引脚由pinctrl子系统管控,无需在驱动中指定:

  1. 在板级DTS中定义spi1_pins节点,配置引脚复用为SPI功能、设置上下拉、速率等参数。
  2. SPI控制器节点通过pinctrl-0引用该引脚配置节点,内核启动时会自动配置这些引脚。

内容的提问来源于stack exchange,提问作者Michael_Y

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:01:09