bus-drivers-i2c-spi

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Bus Drivers (I2C and SPI)

总线驱动(I2C和SPI)

Purpose

用途

Guide agents through Linux I2C and SPI client drivers: bus registration,
i2c_transfer
/
spi_sync
, regmap abstraction, DT
compatible
on bus children, and probe patterns — complementing platform MMIO drivers in
skills/kernel/device-drivers
.
指导Agent完成Linux I2C和SPI客户端驱动开发:总线注册、
i2c_transfer
/
spi_sync
、regmap抽象、总线子设备的DT
compatible
属性以及探测模式——作为
skills/kernel/device-drivers
中平台MMIO驱动的补充。

When to Use

使用场景

  • Sensor or PMIC on I2C/SPI bus
  • Converting bare-metal SPI register reads to kernel driver
  • Using
    regmap
    for multi-byte register access
  • Debugging
    -EREMOTEIO
    or missing ACK
  • I2C/SPI总线上的传感器或PMIC
  • 将裸机SPI寄存器读取转换为内核驱动
  • 使用
    regmap
    进行多字节寄存器访问
  • 调试
    -EREMOTEIO
    错误或缺失ACK响应

Workflow

工作流程

1. I2C client driver

1. I2C客户端驱动

c
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>

static int my_probe(struct i2c_client *client)
{
    struct regmap *map;

    map = devm_regmap_init_i2c(client, &my_regmap_config);
    if (IS_ERR(map))
        return PTR_ERR(map);

    dev_info(&client->dev, "probed at 0x%02x\n", client->addr);
    return 0;
}

static const struct of_device_id my_of_id[] = {
    { .compatible = "vendor,sensor" },
    { }
};
MODULE_DEVICE_TABLE(of, my_of_id);

static const struct i2c_device_id my_id[] = {
    { "mysensor", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, my_id);

static struct i2c_driver my_driver = {
    .probe    = my_probe,
    .remove   = my_remove,
    .driver   = { .name = "mysensor", .of_match_table = my_of_id },
    .id_table = my_id,
};
module_i2c_driver(my_driver);
DT child:
dts
i2c1 {
    sensor@48 {
        compatible = "vendor,sensor";
        reg = <0x48>;
    };
};
c
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>

static int my_probe(struct i2c_client *client)
{
    struct regmap *map;

    map = devm_regmap_init_i2c(client, &my_regmap_config);
    if (IS_ERR(map))
        return PTR_ERR(map);

    dev_info(&client->dev, "probed at 0x%02x\n", client->addr);
    return 0;
}

static const struct of_device_id my_of_id[] = {
    { .compatible = "vendor,sensor" },
    { }
};
MODULE_DEVICE_TABLE(of, my_of_id);

static const struct i2c_device_id my_id[] = {
    { "mysensor", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, my_id);

static struct i2c_driver my_driver = {
    .probe    = my_probe,
    .remove   = my_remove,
    .driver   = { .name = "mysensor", .of_match_table = my_of_id },
    .id_table = my_id,
};
module_i2c_driver(my_driver);
DT子节点:
dts
i2c1 {
    sensor@48 {
        compatible = "vendor,sensor";
        reg = <0x48>;
    };
};

2. Raw I2C transfer

2. 原生I2C传输

c
u8 reg = 0x0F, val;
struct i2c_msg msgs[] = {
    { .addr = client->addr, .flags = 0,       .len = 1, .buf = &reg },
    { .addr = client->addr, .flags = I2C_M_RD, .len = 1, .buf = &val },
};
ret = i2c_transfer(client->adapter, msgs, 2);
c
u8 reg = 0x0F, val;
struct i2c_msg msgs[] = {
    { .addr = client->addr, .flags = 0,       .len = 1, .buf = &reg },
    { .addr = client->addr, .flags = I2C_M_RD, .len = 1, .buf = &val },
};
ret = i2c_transfer(client->adapter, msgs, 2);

3. SPI driver

3. SPI驱动

c
static int spi_probe(struct spi_device *spi)
{
    spi->mode = SPI_MODE_0;
    spi->bits_per_word = 8;
    spi_setup(spi);

    struct spi_transfer t = {
        .tx_buf = tx,
        .rx_buf = rx,
        .len    = len,
    };
    struct spi_message m;
    spi_message_init(&m);
    spi_message_add_tail(&t, &m);
    return spi_sync(spi, &m);
}

static struct spi_driver spi_drv = {
    .probe  = spi_probe,
    .driver = { .name = "my-spi", .of_match_table = my_of_match },
};
module_spi_driver(spi_drv);
c
static int spi_probe(struct spi_device *spi)
{
    spi->mode = SPI_MODE_0;
    spi->bits_per_word = 8;
    spi_setup(spi);

    struct spi_transfer t = {
        .tx_buf = tx,
        .rx_buf = rx,
        .len    = len,
    };
    struct spi_message m;
    spi_message_init(&m);
    spi_message_add_tail(&t, &m);
    return spi_sync(spi, &m);
}

static struct spi_driver spi_drv = {
    .probe  = spi_probe,
    .driver = { .name = "my-spi", .of_match_table = my_of_match },
};
module_spi_driver(spi_drv);

4. regmap (preferred for register maps)

4. regmap(寄存器映射的首选方案)

c
static const struct regmap_config my_regmap_config = {
    .reg_bits   = 8,
    .val_bits   = 8,
    .max_register = 0x7F,
};

regmap_read(map, REG_STATUS, &val);
regmap_write(map, REG_CTRL, CTRL_ENABLE);
regmap_update_bits(map, REG_CTRL, MASK, ENABLE);
c
static const struct regmap_config my_regmap_config = {
    .reg_bits   = 8,
    .val_bits   = 8,
    .max_register = 0x7F,
};

regmap_read(map, REG_STATUS, &val);
regmap_write(map, REG_CTRL, CTRL_ENABLE);
regmap_update_bits(map, REG_CTRL, MASK, ENABLE);

5. Debug

5. 调试

bash
i2cdetect -y 1
i2cdump -y 1 0x48
cat /sys/bus/i2c/devices/i2c-1/1-0048/name
bash
i2cdetect -y 1
i2cdump -y 1 0x48
cat /sys/bus/i2c/devices/i2c-1/1-0048/name

6. Agent usage

6. Agent使用方式

/bus-drivers-i2c-spi Write regmap-based driver for I2C PMIC at 0x58
/bus-drivers-i2c-spi Write regmap-based driver for I2C PMIC at 0x58

Common Problems

常见问题

SymptomCauseFix
-EREMOTEIO
NACK — wrong address
i2cdetect
; check
reg
in DT
SPI mode wrongCPOL/CPHA mismatchMatch datasheet +
spi->mode
Probe deferRegulator/clock supplierReturn
-EPROBE_DEFER
regmap -EIO16-bit vs 8-bit regSet
reg_bits
,
val_bits
DMA not usedSmall
spi_sync
OK
spi_sync_transfer
for bulk
症状原因解决方法
-EREMOTEIO
NACK响应——地址错误使用
i2cdetect
检查;确认DT中的
reg
属性
SPI模式错误CPOL/CPHA不匹配匹配数据手册设置 + 配置
spi->mode
探测延迟调节器/时钟供应未就绪返回
-EPROBE_DEFER
regmap -EIO16位与8位寄存器不匹配设置
reg_bits
val_bits
未使用DMA小数据量
spi_sync
可行
大数据量使用
spi_sync_transfer

Related Skills

相关技能

  • skills/kernel/device-drivers
    — IRQ, DMA, PM runtime
  • skills/kernel-dev/device-tree
    — bus child nodes
  • skills/baremetal/spi-i2c-baremetal
    — register-level protocol
  • skills/kernel-dev/platform-device-model
    — driver model parallels
  • skills/kernel-dev/writing-char-drivers
    — expose sensor via char dev
  • skills/kernel/device-drivers
    —— IRQ、DMA、PM运行时管理
  • skills/kernel-dev/device-tree
    —— 总线子节点
  • skills/baremetal/spi-i2c-baremetal
    —— 寄存器级协议
  • skills/kernel-dev/platform-device-model
    —— 驱动模型并行开发
  • skills/kernel-dev/writing-char-drivers
    —— 通过字符设备暴露传感器