regmap API——寄存器映射
引入regmap API的原因:为了分解和统一内核开发人员访问SPI/I2C设备的方式
struct regmap_config {
const char *name;
int reg_bits; //寄存器地址位数,必填
int reg_stride;
int pad_bits;
int val_bits; //存储寄存器值的位数,必填
bool (*writeable_reg)(struct device *dev,unsigned int reg);
bool (*readable_reg)(struct device *dev,unsigned int reg);
bool (*voltileable_reg)(struct device *dev,unsigned int reg);
bool (*preciousable_reg)(struct device *dev,unsigned int reg);
regmap_lock lock;
regmap_unlock lock;
void *lock_arg;
int (*reg_read)(void *context,unsigned int reg,unsigned int *val);
int (*reg_write)(void *context,unsigned int reg,unsigned int *val);
bool fast_io;
unsigned int max_register; //最大的有效寄存器地址
const struct regmap_access_table *wr_table;
const struct regmap_access_table *rd_table;
const struct regmap_access_table *volatile_table;
const struct regmap_access_table *precious_table;
const struct reg_default *reg_defaults;
unsigned int num_reg_defaults;
enum regcache_type cache_type;
const void *reg_defaults_raw;
unsigned int num_reg_defaults_raw;
u8 read_flag_mask;
u8 write_flag_mask;
bool use_single_raw;
bool can_multi_write;
enum regmap_endian reg_format_endian;
enum regmap_endian val_format_endian;
const struct regmap_range_cfg *ranges;
unsigned int num_ranges;
};
- voltileable_reg:如果寄存器为易失性的,该函数返回true,然后对寄存器执行直接读写;如果寄存器为非易失性的,返回false,缓存用于读取操作,在写入时写入缓存
- writeable_reg:可选回调函数,如果使用,在写入寄存器之前,自动调用该函数检查寄存器是否可以写入
- wr_table:不使用writeable_reg函数时,可以使用regmap_access_table,该函数包含yes_range(可写入)和no_range(不可写入)字段,两者都指向struct regmap_range
regmap_config初始化
static const struct regmap_config regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = LM3553_REG_MAX,
.readable_reg = lm3553_readable_register,
.volatile_reg = lm3553_volatile_register,
.precious_reg = lm3553_precious_register,
};
regmap 初始化
- SPI初始化
设置regmap,
struct regmap * regmap_init_spi(struct spi_device *spi, const struct regmap_config);
- 输入参数:struct spi_device表示与之交互的设备,
const strcut regmap_config表示regmap配置 - 返回值:成功时返回指向分配的struct regmap 指针,出错时返回ERR_PTR()
- I2C初始化
struct regmap * regmap_init_i2c(struct i2c_client *i2c, const struct regmap_config);
- 输入参数:struct i2c_client表示交互的I2C设备,
const struct regmap_config表示regmap配置 - 返回值:成功时返回指向分配的struct regmap 指针,出错时返回ERR_PTR()
设备访问函数
- int regmap_write(struct regmap *map, unsigned int reg, unsigned int *val);
将数据写入设备
- 若寄存器地址小于等于max_register,则写操作会执行
- 否则将返回无效I/O错误(-EIO),此时调用writeable_reg,该函数执行前必须返回true,如果返回false,则返回EIO,写操作停止
- 如果配置了wr_table,结果如下:
如果在no_range内,返回-EIO;
如果在yes_range内,执行下一步
如果不在yes_range和no_range内,返回-EIO,操作中断
如果cache_type != REGCACHE_NONE,则启动缓存。此时首先更新缓存项,之后执行到硬件的写操作,否则不执行缓存操作
如果有reg_write,则用它执行写入操作
-
int regmap_write(struct remap *map, unsigned int reg, unsigned int *val);
-
int regmap_update_bits(struct regmap *map, unsigned int reg, unsigned int *mask, unsigned int val);
需要更新的位必须在掩码中设置为1,相应的位应该设置为val中的值
eg:将第一位和第三位置1,掩码为0b00000101,值为0bxxxxx1x1
要清除第七位,掩码为0b01000000,值为0bx0xxxxxx -
int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs, int num_regs);
向设备写入多个寄存器 -
regmap_bulk_read()和regmap_bulk_write()用于从设备读取多个寄存器和向设备写入多个寄存器,可被用于处理大块数据。
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, size_t val_count);
int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, size_t val_count);