如何在 Linux 设备树下将可选的 GPIO 映射到 IIO 驱动程序

问题描述 投票:0回答:1

我在运行嵌入式 Linux (Yocto) 的 Xilinx Zynq-7020 SoC 上通过 SPI 与 Analog Devices AD9850 DDS IC 连接。 SPI 接口是通过 AXI SPI IP 核实现的——每个事务最多只支持 32 位,而 AD9850 需要 40 位,所以我只使用 SPI 外设来生成时钟和数据线,我想使用一条 GPIO 线,用于单独手动控制 CS 线。

我已经将一个 IIO 驱动程序放在一起来控制 SPI 外设和(可选)GPIO 线。目前,数据和时钟(来自 SPI 外围设备)工作正常(在逻辑分析仪上查看),但是 CS 线(来自 GPIO 外围设备)没有按照我的预期进行。

我认为这很可能是由于 GPIO 外设没有通过 Linux 设备树正确映射到 IIO 驱动程序,因为其他 GPIO 外设在独立驱动程序下工作正常。有人可以建议我应该如何在 DDS 条目下映射“fq_update”GPIO 外围设备吗?

这是我的设备树的摘录:

&amba_pl {
    gpio-dds-cs {
        compatible = "adi,fq_update";
        
        dds_cs {
            label = "dds_cs";
            gpios = <&dds_chip_select_gpio 0 1>;
            default-state = "off";
        };
    };
};

&dds_spi {
    num-cs = <1>;
    status = "okay";
                       
    dds: ad9850@0 {
        label = "dds";
        compatible = "ad9850";
        reg = <0x0>;
        spi-max-frequency = <1000000>;
    };
};

这是我的 IIO 驱动程序的摘录:

struct ad9850_state {
    struct spi_device *spi;
    struct gpio_desc *fq_update;
    uint32_t cache[AD9850_NUM_CHANNELS];
    struct mutex lock;
    
    /* DMA (thus cache coherency maintenance) may require the transfer buffers to live in their own cache lines. */
    u8 data[AD9850_DATA_SIZE_BYTES] ____cacheline_aligned;
};

static int ad9850_channel_write(struct ad9850_state *priv, int channel, u32 val) {
    int ret;
    
    priv->cache[channel] = val;
    memset(priv->data, 0, AD9850_DATA_SIZE_BYTES);
    memcpy(priv->data, (u8 *)&priv->cache[channel], sizeof(priv->cache[channel]));
    
    gpiod_set_value(priv->fq_update, 1);
    gpiod_set_value(priv->fq_update, 0);
    ret = spi_write(priv->spi, &priv->data, AD9850_DATA_SIZE_BYTES);
    gpiod_set_value(priv->fq_update, 1);
    gpiod_set_value(priv->fq_update, 0);
    if (ret < 0) {
        return ret;
    }

    return 0;
}

static int ad9850_probe(struct spi_device *spi) {
*************
    /* The FQ_UPDATE pin can be controlled by the driver or externally. */
    priv->fq_update = devm_gpiod_get_optional(&spi->dev, "adi,fq_update", GPIOD_OUT_LOW);
    if (IS_ERR(priv->fq_update)) {
        return PTR_ERR(priv->fq_update);
    }
*************
}
linux-device-driver gpio spi iio
1个回答
0
投票

我似乎已经设法解决了这个问题,如下所示。

我删除了“&amba_pl”下的“gpio-dds-cs”条目,而是直接从 DDS 条目引用 GPIO。

&dds_spi {
    num-cs = <1>;
    status = "okay";
                       
    dds: ad9850@0 {
        label = "dds";
        compatible = "ad9850";
        reg = <0x0>;
        spi-max-frequency = <1000000>;
        fq_update-gpios = <&dds_chip_select_gpio 0 1>;
    };
};

这意味着更新 IIO 驱动程序中的 GPIO 名称——我也将其从“可选”更改为它,因为它是设备操作所必需的。

#define AD9850_GPIO_NAME                "fq_update"    

priv->fq_update = devm_gpiod_get(&spi->dev, AD9850_GPIO_NAME, GPIOD_OUT_LOW);
    if (IS_ERR(priv->fq_update)) {
    #if (PRINT_TO_KERNEL_LOG == true)
        printk(KERN_INFO "GPIO setup for IIO device %s failed!\n", AD9850_DRV_NAME);
    #endif
        return PTR_ERR(priv->fq_update);
    }
© www.soinside.com 2019 - 2024. All rights reserved.