반응형
regmap의 특정 비트를 업데이트하기 위해서 regmap_update_bits 함수를 사용한다.
static inline int regmap_update_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val)
{
return regmap_update_bits_base(map, reg, mask, val, NULL, false, false);
}
regmap_update_bits 함수를 살펴보면, 파라미터로 받는 reg 변수의 mask에 해당하는 영역에 val 변수값을 업데이트한다.
val 변수값은 FIELD_PREP 매크로를 통해서 비트 영역에 맞는 값을 할당할 수 있다.
/**
* FIELD_PREP() - prepare a bitfield element
* @_mask: shifted mask defining the field's length and position
* @_val: value to put in the field
*
* FIELD_PREP() masks and shifts up the value. The result should
* be combined with other fields of the bitfield using logical OR.
*/
#define FIELD_PREP(_mask, _val) \
({ \
__BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \
((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
})
예를 들어 값이 3인데 4~5번 비트에 할당되는 값이면, 다음과 같은 형식을 통해서 val 변수에 값을 할당할 수 있다.
이렇게 하면 regmap_update_bits 함수에 값을 더 쉽게 입력할 수 있다.
val = FIELD_PREP( GENMASK(4,5), 3 );
FIELD_PREP 매크로를 통해서 할당한 값을 regmap_update_bits 함수에 설정하면 된다.
regmap_update_bits 함수를 좀더 상세히 살펴보자.
/**
* regmap_update_bits_base() - Perform a read/modify/write cycle on a register
*
* @map: Register map to update
* @reg: Register to update
* @mask: Bitmask to change
* @val: New value for bitmask
* @change: Boolean indicating if a write was done
* @async: Boolean indicating asynchronously
* @force: Boolean indicating use force update
*
* Perform a read/modify/write cycle on a register map with change, async, force
* options.
*
* If async is true:
*
* With most buses the read must be done synchronously so this is most useful
* for devices with a cache which do not need to interact with the hardware to
* determine the current register value.
*
* Returns zero for success, a negative number on error.
*/
int regmap_update_bits_base(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val,
bool *change, bool async, bool force)
{
int ret;
map->lock(map->lock_arg);
map->async = async;
ret = _regmap_update_bits(map, reg, mask, val, change, force);
map->async = false;
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_update_bits_base);
함수는 regmap_read로 값을 읽은 후, 값을 OR 연산하고 regmap_write로 다시 쓴다. 이때 뮤텍스 처리를 해서 값이 서로 충돌하는 것을 막는다.
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val,
bool *change, bool force_write)
{
int ret;
unsigned int tmp, orig;
if (change)
*change = false;
if (regmap_volatile(map, reg) && map->reg_update_bits) {
ret = map->reg_update_bits(map->bus_context, reg, mask, val);
if (ret == 0 && change)
*change = true;
} else {
ret = _regmap_read(map, reg, &orig);
if (ret != 0)
return ret;
tmp = orig & ~mask;
tmp |= val & mask;
if (force_write || (tmp != orig)) {
ret = _regmap_write(map, reg, tmp);
if (ret == 0 && change)
*change = true;
}
}
return ret;
}
regmap의 특정 비트를 업데이트 할때 regmap_update_bits 함수를 사용해 보자.
반응형
'임베디드' 카테고리의 다른 글
JTAG과 SWD의 차이와 장단점 (0) | 2023.10.18 |
---|---|
가속도계(Accelerometer)와 방향 계산 (0) | 2023.09.08 |
Linux CAN Network - CAN드라이버와 SocketCAN (0) | 2022.11.05 |
디바이스트리 pinctrl -bindings.txt (0) | 2022.11.04 |
댓글