【问题标题】:How linux driver can delegate functions to another driver (shared hardware)linux驱动程序如何将功能委托给另一个驱动程序(共享硬件)
【发布时间】:2019-07-12 02:05:17
【问题描述】:

我正在为嵌入式板上的 lirc 编写自定义红外发射器驱动程序。该板有一个 i2c-to-gpio 扩展器 (FXL6408)。

问题是我的驱动程序(因此是 LIRC)只需要一个 GPIO 引脚,而其他应用程序需要其他引脚。像这样的:

我读过 LWM、LDD3 和大量关于 i2c-slave、i2c 适配器、总线pinctrlgpio堆叠等的网站,但是不清楚如何做我想做的事:

my-driver 需要控制 GPIO 扩展器上的单个引脚,同时仍允许其他应用程序通过 /dev/i2c-0 控制其他 7 个引脚。

关注this SO suggestion 很有希望,但i2c_new_dummy 失败,返回NULL:

i2cAdaptor = i2c_get_adapter(ECP_I2CBUS); // 1 means i2c-1 bus
if (i2cAdaptor == NULL)
{
    printk("ecp_gpio: Could not acquire i2c adaptor\n");
    return -EBUSY;
}

i2cClient  = i2c_new_dummy(i2cAdaptor, ECP_I2CDEV); // 0x43 - slave address on i2c bus
if (i2cClient == NULL)
{
    printk("ecp_gpio: Could not acquire i2c client\n");
    return -EBUSY;
}

if ( (rc = i2c_smbus_write_byte(i2cClient, 0xF0)) < 0)
{
    printk("ecp_gpio: Error writing byte - error %d", rc);
    return -EIO;
}

连接管道以达到我想要的效果的正确方法是什么?

操作系统信息:

# uname -a
Linux ecp 4.4.127-1.el6.elrepo.i686 #1 SMP Sun Apr 8 09:44:43 EDT 2018 i686 i686 i386 GNU/Linux

【问题讨论】:

  • 在 Linux 内核中,一切都是通过框架委托的。在您的情况下,有一个用于 GPIO 扩展器的驱动程序,它通过 GPIO 库为系统提供资源。在另一个驱动程序中,您只需调用类似gpiod_get(dev, “pin_name”); 的名称,其中引脚的名称来自设备属性(它们可能收集在设备树、ACPI 或 GPIO 表或软件节点中)。
  • 是的。但是由于 GPIO 设备位于 i2c 总线的末端,我的驱动程序必须做的是通过 i2c 进行通信。任何现有的 gpio 驱动程序都不会知道 GPIO 设备,所以手头的任务是控制 i2c,因此使用 i2c 框架来控制 i2c,不是吗?
  • 没有。您需要调查香草内核是否有此扩展器的驱动程序(或您可以修改的非常相似的驱动程序),或者编写一个新的(大量示例)并使用我在第一条评论中提出的内容。
  • 以防万一此类芯片有一个通用库,在 drivers/gpio/gpio-mmio.c 中称为 bgpio
  • 谢谢,我去看看。不幸的是,我使用i2c_smbux_xfer 对(被否决的)解决方案进行了一些测试。它太慢了。硬件必须使用 100 kHz i2c 总线。所以回到另一种方法,“控制嵌入式板上的 USART RTS 引脚”。你也对这个问题发表了评论。那里有线索吗?我被困住了……

标签: driver linux-device-driver lirc


【解决方案1】:

在尝试了许多不同的事情之后,我找到了一个可行的。我不知道这是否是“正确的方法”,但它确实有效。

无需尝试创建虚拟客户端,只需直接调用 i2c_xx 函数即可。所以代码看起来像:

i2cAdaptor = i2c_get_adapter(ECP_I2CBUS); // 1 means i2c-1 bus etc
if (i2cAdaptor == NULL)
{
    printk("ecp_gpio: Could not acquire i2c adaptor\n");
    return -EBUSY;
}


union i2c_smbus_data data;

data.byte = 0xF0;

if ((rc = i2c_smbus_xfer(ecpHardware.i2cAdaptor, ECP_I2CDEV, 0, I2C_SMBUS_WRITE, 0x05, I2C_SMBUS_BYTE_DATA, &data)) < 0)
{
    printk("ecp_gpio: i2c_smbus_xfer failed: %d\n", rc);
    return -EIO;
}

data.byte = 0xE0;

if ((rc = i2c_smbus_xfer(ecpHardware.i2cAdaptor, ECP_I2CDEV, 0, I2C_SMBUS_WRITE, 0x05, I2C_SMBUS_BYTE_DATA, &data)) < 0)
{
    printk("ecp_gpio: i2c_smbus_xfer failed: %d\n", rc);
    return -EIO;
}

【讨论】:

  • 我做到了,这就是让我进入 i2c 框架的原因。请参阅我上面关于为什么 gpio 框架不适用于该用例的解释。 (我想如果我想将设备作为 GPIO 呈现给用户空间,那么我会注册一个 gpio 驱动程序。但是用户空间不应该对 i2c 或 gpio 有任何了解。所以“我的驱动程序”只需要控制i2c 做它需要做的事情。对吗?
猜你喜欢
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-25
  • 2021-07-30
  • 1970-01-01
相关资源
最近更新 更多