linux裝置驅動模型 - regmap
阿新 • • 發佈:2018-11-03
1. regmap介紹
regmap主要是為了方便操作暫存器而設計的,它將所有模組的暫存器(包括soc上模組的暫存器和外圍裝置的暫存器等)
抽象出來,用一套統一介面來操作暫存器
比如,如果要操作i2c裝置的暫存器,那麼就要呼叫i2c_transfer介面,要操作spi裝置的暫存器,就要呼叫spi_write/spi_read等介面,
如果把它們都抽象為regmap結構,那麼只要呼叫regmap_read/regmap_write就可以了
regmap的程式碼在目錄:drivers/base/regmap
目前regmap抽象的裝置主要分兩種型別,一種是cache型別的,這種裝置就是把暫存器值寫入到記憶體中,
另一種是實際的硬體裝置,暫存器的值要寫入實際的模組中
在核心版本4.14上,cache的型別有3中:
- flat:普通陣列型別
- rb-tree:紅黑樹型別
- lzo:壓縮型別
enum regcache_type {
REGCACHE_NONE,
REGCACHE_RBTREE,
REGCACHE_COMPRESSED,
REGCACHE_FLAT,
};
實際的硬體裝置實現regmap的有:I2C/SPI/spmi/mmio等,後面會舉例介紹一下mmio
2. regmap設計框架
regmap的整個框架如下:
2.1 regmap結構體
簡單介紹下regmap結構體
struct regmap { 。。。。。。 struct device *dev; /* Device we do I/O on */ void *work_buf; /* Scratch buffer used to format I/O */ struct regmap_format format; /* Buffer format */ const struct regmap_bus *bus;-------------regmap裝置匯流排 void *bus_context;------------------------匯流排私有資料 const char *name; unsigned int max_register; /×判斷是否可讀寫的函式×/ bool (*writeable_reg)(struct device *dev, unsigned int reg); bool (*readable_reg)(struct device *dev, unsigned int reg); bool (*volatile_reg)(struct device *dev, unsigned int reg); bool (*precious_reg)(struct device *dev, unsigned int reg); /×讀寫暫存器函式×/ int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); int (*reg_update_bits)(void *context, unsigned int reg, unsigned int mask, unsigned int val); /×讀寫掩碼×/ unsigned long read_flag_mask; unsigned long write_flag_mask; /* number of bits to (left) shift the reg value when formatting*/ int reg_shift;------------暫存器偏移 int reg_stride;-----------暫存器對齊位 int reg_stride_order; /×regcache相關的函式×/ /* regcache specific members */ const struct regcache_ops *cache_ops; enum regcache_type cache_type; /* number of bytes in reg_defaults_raw */ unsigned int cache_size_raw; /* number of bytes per word in reg_defaults_raw */ unsigned int cache_word_size; /* number of entries in reg_defaults */ unsigned int num_reg_defaults; /* number of entries in reg_defaults_raw */ unsigned int num_reg_defaults_raw; /* if set, only the cache is modified not the HW */ bool cache_only; /* if set, only the HW is modified not the cache */ bool cache_bypass; /* if set, remember to free reg_defaults_raw */ bool cache_free; /×多暫存器讀寫相關欄位×/ /* if set, converts bulk read to single read */ bool use_single_read; /* if set, converts bulk read to single read */ bool use_single_write; /* if set, the device supports multi write mode */ bool can_multi_write; /* if set, raw reads/writes are limited to this size */ size_t max_raw_read;---------能讀的暫存器範圍 size_t max_raw_write;--------能寫的暫存器範圍 。。。。。。 };
2.2 regmap_config結構體
我們要建立自己的regmap的時候,一般會先初始化regmap_config結構體,然後進行regmap的建立
struct regmap_config {
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 (*volatile_reg)(struct device *dev, unsigned int reg);
bool (*precious_reg)(struct device *dev, unsigned int reg);
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);---暫存器讀函式
int (*reg_write)(void *context, unsigned int reg, unsigned int val);---暫存器寫函式
unsigned int max_register;------------最大暫存器地址
enum regcache_type cache_type;--------regmap型別
unsigned long read_flag_mask;---------讀掩碼
unsigned long write_flag_mask;--------寫掩碼
enum regmap_endian reg_format_endian;-----暫存器地址大小端
enum regmap_endian val_format_endian;-----暫存器值大小端
};
2.3 regmap建立
2.3.1 __devm_regmap_init
呼叫devm介面方便驅動解除安裝的時候釋放資源
2.3.2 __regmap_init
init的過程如下:
- config的lock配置給regmap
- config的reg-bit/val-bit等配置給regmap
- 把regmap_bus給regmap
- 把config的讀寫判斷函式(writeable_reg/readable_reg)等相關配置給regmap
- 如果regmap_bus不為空,那麼把regmap_bus的讀寫函式給regmap,否則把config的配置給regmap
- 給regmap提供資料格式化format的相關函式
2.4 常用暫存器操作介面
使用regmap讀寫暫存器的介面有:
static inline int regmap_write(struct regmap *map, unsigned int reg,
unsigned int val)
static inline int regmap_read(struct regmap *map, unsigned int reg,
unsigned int *val)
static inline int regmap_bulk_read(struct regmap *map, unsigned int reg,
void *val, size_t val_count)
static inline int regmap_update_bits_base(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val,
bool *change, bool async, bool force)
3. regmap用例(regmap-mmio)
regmap-mmio是用來對映soc上的模組暫存器,方便驅動操作模組而設計的
3.1 regmap-mmio的建立
可以呼叫函式:
struct regmap *__regmap_init_mmio_clk(...)
struct regmap *__devm_regmap_init_mmio_clk(...)
建立過程:
1. 先初始化regmap-mmio的私有結構體:regmap_mmio_context
主要是分配讀寫函式和clock
2. 然後進行regmap的初始化,使用regmap_bus匯流排為regmap_mmio