在Linu 3.1开始,Linux引入了regmap来同意管理内核的I2C, SPI等总线,将I2C, SPI驱动做了一次重构,把I/O读写的重复逻辑在regmap中实现。
用一个I2C设备为例,在3.1之前的I2C设备驱动,需要各自调用i2c_transfer来实现读写,比如:
static int raydium_i2c_pda2_write(struct i2c_client *client,
unsigned char addr, unsigned char *w_data, unsigned short length)
{
int retval = -1;
unsigned char retry;
unsigned char buf[MAX_WRITE_PACKET_SIZE + 1];
struct raydium_ts_data *data = i2c_get_clientdata(client);
struct i2c_msg msg[] = {
{
.addr = RAYDIUM_I2C_NID,
.flags = RAYDIUM_I2C_WRITE,
.len = length + 1,
.buf = buf,
},
};
if (length > MAX_WRITE_PACKET_SIZE)
{
return -EINVAL;
}
u8_i2c_mode = PDA2_MODE;
buf[0] = addr;
memcpy(&buf[1], w_data, length);
for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++)
{
if (i2c_transfer(client->adapter, msg, 1) == 1)
{
retval = length;
break;
}
msleep(20);
}
if (retry == SYN_I2C_RETRY_TIMES)
{
dev_err(&data->client->dev,"[touch]%s: I2C write over retry limit.addr[0x%x]\n",__func__, addr);
retval = -EIO;
}
return retval;
}
需要自行构建i2c_msg,然后使用i2c_transfer传输数据。
但是使用regmap机制,就会变的更为简单。只需要如下几步:
// 1.构建regmap_config结构
static const struct regmap_config mlx90632_regmap = {
.reg_bits = 16,
.val_bits = 16,
.volatile_table = &mlx90632_volatile_regs_tbl,
.rd_table = &mlx90632_readable_regs_tbl,
.wr_table = &mlx90632_writeable_regs_tbl,
.use_single_rw = true,
.reg_format_endian = REGMAP_ENDIAN_BIG,
.val_format_endian = REGMAP_ENDIAN_BIG,
.cache_type = REGCACHE_RBTREE,
};
// 2. 初始化regmap
regmap = regmap_init_i2c(client, &mlx90632_regmap);
//3.读写操作
ret = regmap_read(mlx90632->regmap, MLX90632_EE_VERSION, &read);
我们分析三步操作:
1.regmap_config结构
在regmap_config,定义了寄存器的各种信息,比如寄存器地址长度,寄存器值的长度,读写寄存器的地址范围的信息,寄存器地址和值的大小端已经缓冲方式。
struct regmap_config {
const char *name; // 可选,寄存器名字
int reg_bits; // 寄存器地址位宽,必须填