mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
Merge remote-tracking branch 'regmap/topic/field' into regmap-next
This commit is contained in:
commit
7bc8c4c37a
7 changed files with 1689 additions and 0 deletions
110
Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
Normal file
110
Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
Normal file
|
@ -0,0 +1,110 @@
|
|||
*ST pin controller.
|
||||
|
||||
Each multi-function pin is controlled, driven and routed through the
|
||||
PIO multiplexing block. Each pin supports GPIO functionality (ALT0)
|
||||
and multiple alternate functions(ALT1 - ALTx) that directly connect
|
||||
the pin to different hardware blocks.
|
||||
|
||||
When a pin is in GPIO mode, Output Enable (OE), Open Drain(OD), and
|
||||
Pull Up (PU) are driven by the related PIO block.
|
||||
|
||||
ST pinctrl driver controls PIO multiplexing block and also interacts with
|
||||
gpio driver to configure a pin.
|
||||
|
||||
Required properties: (PIO multiplexing block)
|
||||
- compatible : should be "st,<SOC>-<pio-block>-pinctrl"
|
||||
like st,stih415-sbc-pinctrl, st,stih415-front-pinctrl and so on.
|
||||
- gpio-controller : Indicates this device is a GPIO controller
|
||||
- #gpio-cells : Should be one. The first cell is the pin number.
|
||||
- st,retime-pin-mask : Should be mask to specify which pins can be retimed.
|
||||
If the property is not present, it is assumed that all the pins in the
|
||||
bank are capable of retiming. Retiming is mainly used to improve the
|
||||
IO timing margins of external synchronous interfaces.
|
||||
- st,bank-name : Should be a name string for this bank as
|
||||
specified in datasheet.
|
||||
- st,syscfg : Should be a phandle of the syscfg node.
|
||||
|
||||
Example:
|
||||
pin-controller-sbc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "st,stih415-sbc-pinctrl";
|
||||
st,syscfg = <&syscfg_sbc>;
|
||||
ranges = <0 0xfe610000 0x5000>;
|
||||
PIO0: gpio@fe610000 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
reg = <0 0x100>;
|
||||
st,bank-name = "PIO0";
|
||||
};
|
||||
...
|
||||
pin-functions nodes follow...
|
||||
};
|
||||
|
||||
|
||||
Contents of function subnode node:
|
||||
----------------------
|
||||
Required properties for pin configuration node:
|
||||
- st,pins : Child node with list of pins with configuration.
|
||||
|
||||
Below is the format of how each pin conf should look like.
|
||||
|
||||
<bank offset mux mode rt_type rt_delay rt_clk>
|
||||
|
||||
Every PIO is represented with 4-7 parameters depending on retime configuration.
|
||||
Each parameter is explained as below.
|
||||
|
||||
-bank : Should be bank phandle to which this PIO belongs.
|
||||
-offset : Offset in the PIO bank.
|
||||
-mux : Should be alternate function number associated this pin.
|
||||
Use same numbers from datasheet.
|
||||
-mode :pin configuration is selected from one of the below values.
|
||||
IN
|
||||
IN_PU
|
||||
OUT
|
||||
BIDIR
|
||||
BIDIR_PU
|
||||
|
||||
-rt_type Retiming Configuration for the pin.
|
||||
Possible retime configuration are:
|
||||
|
||||
------- -------------
|
||||
value args
|
||||
------- -------------
|
||||
NICLK <delay> <clk>
|
||||
ICLK_IO <delay> <clk>
|
||||
BYPASS <delay>
|
||||
DE_IO <delay> <clk>
|
||||
SE_ICLK_IO <delay> <clk>
|
||||
SE_NICLK_IO <delay> <clk>
|
||||
|
||||
- delay is retime delay in pico seconds as mentioned in data sheet.
|
||||
|
||||
- rt_clk :clk to be use for retime.
|
||||
Possible values are:
|
||||
CLK_A
|
||||
CLK_B
|
||||
CLK_C
|
||||
CLK_D
|
||||
|
||||
Example of mmcclk pin which is a bi-direction pull pu with retime config
|
||||
as non inverted clock retimed with CLK_B and delay of 0 pico seconds:
|
||||
|
||||
pin-controller {
|
||||
...
|
||||
mmc0 {
|
||||
pinctrl_mmc: mmc {
|
||||
st,pins {
|
||||
mmcclk = <&PIO13 4 ALT4 BIDIR_PU NICLK 0 CLK_B>;
|
||||
...
|
||||
};
|
||||
};
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
sdhci0:sdhci@fe810000{
|
||||
...
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_mmc>;
|
||||
};
|
|
@ -176,6 +176,14 @@ struct regmap_range_node {
|
|||
unsigned int window_len;
|
||||
};
|
||||
|
||||
struct regmap_field {
|
||||
struct regmap *regmap;
|
||||
unsigned int mask;
|
||||
/* lsb */
|
||||
unsigned int shift;
|
||||
unsigned int reg;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern void regmap_debugfs_initcall(void);
|
||||
extern void regmap_debugfs_init(struct regmap *map, const char *name);
|
||||
|
|
|
@ -807,6 +807,95 @@ struct regmap *devm_regmap_init(struct device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(devm_regmap_init);
|
||||
|
||||
static void regmap_field_init(struct regmap_field *rm_field,
|
||||
struct regmap *regmap, struct reg_field reg_field)
|
||||
{
|
||||
int field_bits = reg_field.msb - reg_field.lsb + 1;
|
||||
rm_field->regmap = regmap;
|
||||
rm_field->reg = reg_field.reg;
|
||||
rm_field->shift = reg_field.lsb;
|
||||
rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_regmap_field_alloc(): Allocate and initialise a register field
|
||||
* in a register map.
|
||||
*
|
||||
* @dev: Device that will be interacted with
|
||||
* @regmap: regmap bank in which this register field is located.
|
||||
* @reg_field: Register field with in the bank.
|
||||
*
|
||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||
* to a struct regmap_field. The regmap_field will be automatically freed
|
||||
* by the device management code.
|
||||
*/
|
||||
struct regmap_field *devm_regmap_field_alloc(struct device *dev,
|
||||
struct regmap *regmap, struct reg_field reg_field)
|
||||
{
|
||||
struct regmap_field *rm_field = devm_kzalloc(dev,
|
||||
sizeof(*rm_field), GFP_KERNEL);
|
||||
if (!rm_field)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
regmap_field_init(rm_field, regmap, reg_field);
|
||||
|
||||
return rm_field;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
|
||||
|
||||
/**
|
||||
* devm_regmap_field_free(): Free register field allocated using
|
||||
* devm_regmap_field_alloc. Usally drivers need not call this function,
|
||||
* as the memory allocated via devm will be freed as per device-driver
|
||||
* life-cyle.
|
||||
*
|
||||
* @dev: Device that will be interacted with
|
||||
* @field: regmap field which should be freed.
|
||||
*/
|
||||
void devm_regmap_field_free(struct device *dev,
|
||||
struct regmap_field *field)
|
||||
{
|
||||
devm_kfree(dev, field);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_regmap_field_free);
|
||||
|
||||
/**
|
||||
* regmap_field_alloc(): Allocate and initialise a register field
|
||||
* in a register map.
|
||||
*
|
||||
* @regmap: regmap bank in which this register field is located.
|
||||
* @reg_field: Register field with in the bank.
|
||||
*
|
||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||
* to a struct regmap_field. The regmap_field should be freed by the
|
||||
* user once its finished working with it using regmap_field_free().
|
||||
*/
|
||||
struct regmap_field *regmap_field_alloc(struct regmap *regmap,
|
||||
struct reg_field reg_field)
|
||||
{
|
||||
struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
|
||||
|
||||
if (!rm_field)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
regmap_field_init(rm_field, regmap, reg_field);
|
||||
|
||||
return rm_field;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_alloc);
|
||||
|
||||
/**
|
||||
* regmap_field_free(): Free register field allocated using regmap_field_alloc
|
||||
*
|
||||
* @field: regmap field which should be freed.
|
||||
*/
|
||||
void regmap_field_free(struct regmap_field *field)
|
||||
{
|
||||
kfree(field);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_free);
|
||||
|
||||
/**
|
||||
* regmap_reinit_cache(): Reinitialise the current register cache
|
||||
*
|
||||
|
@ -1255,6 +1344,22 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_raw_write);
|
||||
|
||||
/**
|
||||
* regmap_field_write(): Write a value to a single register field
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @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_write(struct regmap_field *field, unsigned int val)
|
||||
{
|
||||
return regmap_update_bits(field->regmap, field->reg,
|
||||
field->mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_write);
|
||||
|
||||
/*
|
||||
* regmap_bulk_write(): Write multiple registers to the device
|
||||
*
|
||||
|
@ -1537,6 +1642,31 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_raw_read);
|
||||
|
||||
/**
|
||||
* regmap_field_read(): Read a value to a single register field
|
||||
*
|
||||
* @field: Register field to read from
|
||||
* @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_field_read(struct regmap_field *field, unsigned int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int reg_val;
|
||||
ret = regmap_read(field->regmap, field->reg, ®_val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
reg_val &= field->mask;
|
||||
reg_val >>= field->shift;
|
||||
*val = reg_val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_read);
|
||||
|
||||
/**
|
||||
* regmap_bulk_read(): Read multiple registers from the device
|
||||
*
|
||||
|
|
|
@ -169,6 +169,12 @@ config PINCTRL_SUNXI
|
|||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
|
||||
config PINCTRL_ST
|
||||
bool
|
||||
depends on OF
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
|
||||
config PINCTRL_TEGRA
|
||||
bool
|
||||
select PINMUX
|
||||
|
|
|
@ -45,6 +45,7 @@ obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o
|
|||
obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
|
||||
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
|
||||
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
|
||||
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
|
||||
|
||||
obj-$(CONFIG_PLAT_ORION) += mvebu/
|
||||
obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
|
||||
|
|
1403
drivers/pinctrl/pinctrl-st.c
Normal file
1403
drivers/pinctrl/pinctrl-st.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -23,6 +23,7 @@ struct irq_domain;
|
|||
struct spi_device;
|
||||
struct regmap;
|
||||
struct regmap_range_cfg;
|
||||
struct regmap_field;
|
||||
|
||||
/* An enum of all the supported cache types */
|
||||
enum regcache_type {
|
||||
|
@ -416,6 +417,36 @@ bool regmap_reg_in_ranges(unsigned int reg,
|
|||
const struct regmap_range *ranges,
|
||||
unsigned int nranges);
|
||||
|
||||
/**
|
||||
* Description of an register field
|
||||
*
|
||||
* @reg: Offset of the register within the regmap bank
|
||||
* @lsb: lsb of the register field.
|
||||
* @reg: msb of the register field.
|
||||
*/
|
||||
struct reg_field {
|
||||
unsigned int reg;
|
||||
unsigned int lsb;
|
||||
unsigned int msb;
|
||||
};
|
||||
|
||||
#define REG_FIELD(_reg, _lsb, _msb) { \
|
||||
.reg = _reg, \
|
||||
.lsb = _lsb, \
|
||||
.msb = _msb, \
|
||||
}
|
||||
|
||||
struct regmap_field *regmap_field_alloc(struct regmap *regmap,
|
||||
struct reg_field reg_field);
|
||||
void regmap_field_free(struct regmap_field *field);
|
||||
|
||||
struct regmap_field *devm_regmap_field_alloc(struct device *dev,
|
||||
struct regmap *regmap, struct reg_field reg_field);
|
||||
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);
|
||||
|
||||
/**
|
||||
* Description of an IRQ for the generic regmap irq_chip.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue