forked from Minki/linux
regmap: Add support for repeated blocks of fields
Save duplication for devices using the regmap field APIs by allowing repeated blocks to be described once and referred to with an index. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJSOFCPAAoJELSic+t+oim9mqQP/jfy0yh8+67Jel+SAM5I1BJS uzYNVDT0dV1H1UcRNr+brQCsqh/8gugDvMbwJXLVQtEhiUl98PCCEZd5lELbNniq Nw1ZdTm/+/3Oh4lR4G+9ZnBKFzvexNs8fUuKDDpD7QAOxHTI1C4NreB8mwlPVpSe YoUMXe6a0/FRGJCcgLHI3S2EJ8RwDEiHbhcVXGJhNPTZpi5NNYcTIPf2ynAZvlfD ZKt6RWT6riNOd1z/21qHVzGkWFvKHiRtwYI57sh7rTsiwNoW5dhqFx0L3SFPgfxJ Oa5FviHDQjI+WDEaWivXpx4MhbvLwGQWv2FPzKDftzQYwjdnOyEQSsFrJFfm18CD 1VCMnRFyb5xtNUXWQ1vGQp2G0nGV/dlbcn1pRCfYrcNgB2NrFWlLXiR9FRXZFljM lBW8TyqHDFxQzW+pbRAZcsQ6kZm0yTJrgDUhV5svWF26TyObraH4tlOrsPFhGF25 ZoC/mU7lBIBJoCZ/z5Ldg+tGiYzgM4zmN5X5k7PZUSUfJukKoSFAsSNJ6GzbscFj PhiPmk2K1EDkMyV1xDlJK1RTBTeFJZwIKyXHd3UjnNVXUuz2NsgvW1xm7GjJzlvH uWIJphKHYMHmIbdIiZCm2k13E90P/dBCo9suBcCIVOxp+8Kf4yOxsWHN+pVcI9M1 diW5hrPQU2iyNAOayXYO =Y3LA -----END PGP SIGNATURE----- Merge tag 'regmap-fields' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap into asoc-rcar regmap: Add support for repeated blocks of fields Save duplication for devices using the regmap field APIs by allowing repeated blocks to be described once and referred to with an index.
This commit is contained in:
commit
ef85b64246
@ -179,6 +179,9 @@ struct regmap_field {
|
||||
/* lsb */
|
||||
unsigned int shift;
|
||||
unsigned int reg;
|
||||
|
||||
unsigned int id_size;
|
||||
unsigned int id_offset;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
@ -821,6 +821,8 @@ static void regmap_field_init(struct regmap_field *rm_field,
|
||||
rm_field->reg = reg_field.reg;
|
||||
rm_field->shift = reg_field.lsb;
|
||||
rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
|
||||
rm_field->id_size = reg_field.id_size;
|
||||
rm_field->id_offset = reg_field.id_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1369,6 +1371,74 @@ int regmap_field_write(struct regmap_field *field, unsigned int val)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_write);
|
||||
|
||||
/**
|
||||
* regmap_field_update_bits(): Perform a read/modify/write cycle
|
||||
* on the register field
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @mask: Bitmask to change
|
||||
* @val: Value to be written
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val)
|
||||
{
|
||||
mask = (mask << field->shift) & field->mask;
|
||||
|
||||
return regmap_update_bits(field->regmap, field->reg,
|
||||
mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_update_bits);
|
||||
|
||||
/**
|
||||
* regmap_fields_write(): Write a value to a single register field with port ID
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @id: port ID
|
||||
* @val: Value to be written
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_fields_write(struct regmap_field *field, unsigned int id,
|
||||
unsigned int val)
|
||||
{
|
||||
if (id >= field->id_size)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_update_bits(field->regmap,
|
||||
field->reg + (field->id_offset * id),
|
||||
field->mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_write);
|
||||
|
||||
/**
|
||||
* regmap_fields_update_bits(): Perform a read/modify/write cycle
|
||||
* on the register field
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @id: port ID
|
||||
* @mask: Bitmask to change
|
||||
* @val: Value to be written
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
if (id >= field->id_size)
|
||||
return -EINVAL;
|
||||
|
||||
mask = (mask << field->shift) & field->mask;
|
||||
|
||||
return regmap_update_bits(field->regmap,
|
||||
field->reg + (field->id_offset * id),
|
||||
mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_update_bits);
|
||||
|
||||
/*
|
||||
* regmap_bulk_write(): Write multiple registers to the device
|
||||
*
|
||||
@ -1676,6 +1746,39 @@ int regmap_field_read(struct regmap_field *field, unsigned int *val)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_read);
|
||||
|
||||
/**
|
||||
* regmap_fields_read(): Read a value to a single register field with port ID
|
||||
*
|
||||
* @field: Register field to read from
|
||||
* @id: port ID
|
||||
* @val: Pointer to store read value
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_fields_read(struct regmap_field *field, unsigned int id,
|
||||
unsigned int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int reg_val;
|
||||
|
||||
if (id >= field->id_size)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_read(field->regmap,
|
||||
field->reg + (field->id_offset * id),
|
||||
®_val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
reg_val &= field->mask;
|
||||
reg_val >>= field->shift;
|
||||
*val = reg_val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_read);
|
||||
|
||||
/**
|
||||
* regmap_bulk_read(): Read multiple registers from the device
|
||||
*
|
||||
|
@ -425,11 +425,15 @@ bool regmap_reg_in_ranges(unsigned int reg,
|
||||
* @reg: Offset of the register within the regmap bank
|
||||
* @lsb: lsb of the register field.
|
||||
* @reg: msb of the register field.
|
||||
* @id_size: port size if it has some ports
|
||||
* @id_offset: address offset for each ports
|
||||
*/
|
||||
struct reg_field {
|
||||
unsigned int reg;
|
||||
unsigned int lsb;
|
||||
unsigned int msb;
|
||||
unsigned int id_size;
|
||||
unsigned int id_offset;
|
||||
};
|
||||
|
||||
#define REG_FIELD(_reg, _lsb, _msb) { \
|
||||
@ -448,6 +452,15 @@ void devm_regmap_field_free(struct device *dev, struct regmap_field *field);
|
||||
|
||||
int regmap_field_read(struct regmap_field *field, unsigned int *val);
|
||||
int regmap_field_write(struct regmap_field *field, unsigned int val);
|
||||
int regmap_field_update_bits(struct regmap_field *field,
|
||||
unsigned int mask, unsigned int val);
|
||||
|
||||
int regmap_fields_write(struct regmap_field *field, unsigned int id,
|
||||
unsigned int val);
|
||||
int regmap_fields_read(struct regmap_field *field, unsigned int id,
|
||||
unsigned int *val);
|
||||
int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
|
||||
unsigned int mask, unsigned int val);
|
||||
|
||||
/**
|
||||
* Description of an IRQ for the generic regmap irq_chip.
|
||||
|
Loading…
Reference in New Issue
Block a user