bus-drivers-i2c-spi
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBus Drivers (I2C and SPI)
总线驱动(I2C和SPI)
Purpose
用途
Guide agents through Linux I2C and SPI client drivers: bus registration, / , regmap abstraction, DT on bus children, and probe patterns — complementing platform MMIO drivers in .
i2c_transferspi_synccompatibleskills/kernel/device-drivers指导Agent完成Linux I2C和SPI客户端驱动开发:总线注册、 / 、regmap抽象、总线子设备的DT 属性以及探测模式——作为中平台MMIO驱动的补充。
i2c_transferspi_synccompatibleskills/kernel/device-driversWhen to Use
使用场景
- Sensor or PMIC on I2C/SPI bus
- Converting bare-metal SPI register reads to kernel driver
- Using for multi-byte register access
regmap - Debugging or missing ACK
-EREMOTEIO
- I2C/SPI总线上的传感器或PMIC
- 将裸机SPI寄存器读取转换为内核驱动
- 使用进行多字节寄存器访问
regmap - 调试错误或缺失ACK响应
-EREMOTEIO
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 = ® },
{ .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 = ® },
{ .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/namebash
i2cdetect -y 1
i2cdump -y 1 0x48
cat /sys/bus/i2c/devices/i2c-1/1-0048/name6. 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 0x58Common Problems
常见问题
| Symptom | Cause | Fix |
|---|---|---|
| NACK — wrong address | |
| SPI mode wrong | CPOL/CPHA mismatch | Match datasheet + |
| Probe defer | Regulator/clock supplier | Return |
| regmap -EIO | 16-bit vs 8-bit reg | Set |
| DMA not used | Small | |
| 症状 | 原因 | 解决方法 |
|---|---|---|
| NACK响应——地址错误 | 使用 |
| SPI模式错误 | CPOL/CPHA不匹配 | 匹配数据手册设置 + 配置 |
| 探测延迟 | 调节器/时钟供应未就绪 | 返回 |
| regmap -EIO | 16位与8位寄存器不匹配 | 设置 |
| 未使用DMA | 小数据量 | 大数据量使用 |
Related Skills
相关技能
- — IRQ, DMA, PM runtime
skills/kernel/device-drivers - — bus child nodes
skills/kernel-dev/device-tree - — register-level protocol
skills/baremetal/spi-i2c-baremetal - — driver model parallels
skills/kernel-dev/platform-device-model - — expose sensor via char dev
skills/kernel-dev/writing-char-drivers
- —— IRQ、DMA、PM运行时管理
skills/kernel/device-drivers - —— 总线子节点
skills/kernel-dev/device-tree - —— 寄存器级协议
skills/baremetal/spi-i2c-baremetal - —— 驱动模型并行开发
skills/kernel-dev/platform-device-model - —— 通过字符设备暴露传感器
skills/kernel-dev/writing-char-drivers