pinctrl: pinctrl-single: Add pinctrl-single,bits type of mux
With pinctrl-single,bits it is possible to update just part of the register within the pinctrl-single,function-mask area. This is useful when one register configures mmore than one pin's mux. pinctrl-single,bits takes three parameters: <reg offset, value, sub-mask> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> [Removed a misplaced comment] Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
2830c3686b
commit
9e605cb68a
|
@ -14,10 +14,12 @@ Optional properties:
|
||||||
- pinctrl-single,function-off : function off mode for disabled state if
|
- pinctrl-single,function-off : function off mode for disabled state if
|
||||||
available and same for all registers; if not specified, disabling of
|
available and same for all registers; if not specified, disabling of
|
||||||
pin functions is ignored
|
pin functions is ignored
|
||||||
|
- pinctrl-single,bit-per-mux : boolean to indicate that one register controls
|
||||||
|
more than one pin
|
||||||
|
|
||||||
This driver assumes that there is only one register for each pin,
|
This driver assumes that there is only one register for each pin (unless the
|
||||||
and uses the common pinctrl bindings as specified in the pinctrl-bindings.txt
|
pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as
|
||||||
document in this directory.
|
specified in the pinctrl-bindings.txt document in this directory.
|
||||||
|
|
||||||
The pin configuration nodes for pinctrl-single are specified as pinctrl
|
The pin configuration nodes for pinctrl-single are specified as pinctrl
|
||||||
register offset and value pairs using pinctrl-single,pins. Only the bits
|
register offset and value pairs using pinctrl-single,pins. Only the bits
|
||||||
|
@ -31,6 +33,15 @@ device pinctrl register, and 0x118 contains the desired value of the
|
||||||
pinctrl register. See the device example and static board pins example
|
pinctrl register. See the device example and static board pins example
|
||||||
below for more information.
|
below for more information.
|
||||||
|
|
||||||
|
In case when one register changes more than one pin's mux the
|
||||||
|
pinctrl-single,bits need to be used which takes three parameters:
|
||||||
|
|
||||||
|
pinctrl-single,bits = <0xdc 0x18, 0xff>;
|
||||||
|
|
||||||
|
Where 0xdc is the offset from the pinctrl register base address for the
|
||||||
|
device pinctrl register, 0x18 is the desired value, and 0xff is the sub mask to
|
||||||
|
be used when applying this change to the register.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
/* SoC common file */
|
/* SoC common file */
|
||||||
|
@ -55,6 +66,15 @@ pmx_wkup: pinmux@4a31e040 {
|
||||||
pinctrl-single,function-mask = <0xffff>;
|
pinctrl-single,function-mask = <0xffff>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
control_devconf0: pinmux@48002274 {
|
||||||
|
compatible = "pinctrl-single";
|
||||||
|
reg = <0x48002274 4>; /* Single register */
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
pinctrl-single,bit-per-mux;
|
||||||
|
pinctrl-single,register-width = <32>;
|
||||||
|
pinctrl-single,function-mask = <0x5F>;
|
||||||
|
};
|
||||||
|
|
||||||
/* board specific .dts file */
|
/* board specific .dts file */
|
||||||
|
|
||||||
|
@ -87,6 +107,21 @@ pmx_wkup: pinmux@4a31e040 {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&control_devconf0 {
|
||||||
|
mcbsp1_pins: pinmux_mcbsp1_pins {
|
||||||
|
pinctrl-single,bits = <
|
||||||
|
0x00 0x18 0x18 /* FSR/CLKR signal from FSX/CLKX pin */
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
mcbsp2_clks_pins: pinmux_mcbsp2_clks_pins {
|
||||||
|
pinctrl-single,bits = <
|
||||||
|
0x00 0x40 0x40 /* McBSP2 CLKS from McBSP_CLKS pin */
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
&uart2 {
|
&uart2 {
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&uart2_pins>;
|
pinctrl-0 = <&uart2_pins>;
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
|
||||||
#define DRIVER_NAME "pinctrl-single"
|
#define DRIVER_NAME "pinctrl-single"
|
||||||
#define PCS_MUX_NAME "pinctrl-single,pins"
|
#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
|
||||||
|
#define PCS_MUX_BITS_NAME "pinctrl-single,bits"
|
||||||
#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1)
|
#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1)
|
||||||
#define PCS_OFF_DISABLED ~0U
|
#define PCS_OFF_DISABLED ~0U
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ struct pcs_pingroup {
|
||||||
struct pcs_func_vals {
|
struct pcs_func_vals {
|
||||||
void __iomem *reg;
|
void __iomem *reg;
|
||||||
unsigned val;
|
unsigned val;
|
||||||
|
unsigned mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,6 +141,7 @@ struct pcs_device {
|
||||||
unsigned fshift;
|
unsigned fshift;
|
||||||
unsigned foff;
|
unsigned foff;
|
||||||
unsigned fmax;
|
unsigned fmax;
|
||||||
|
bool bits_per_mux;
|
||||||
struct pcs_name *names;
|
struct pcs_name *names;
|
||||||
struct pcs_data pins;
|
struct pcs_data pins;
|
||||||
struct radix_tree_root pgtree;
|
struct radix_tree_root pgtree;
|
||||||
|
@ -332,12 +335,17 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
|
||||||
|
|
||||||
for (i = 0; i < func->nvals; i++) {
|
for (i = 0; i < func->nvals; i++) {
|
||||||
struct pcs_func_vals *vals;
|
struct pcs_func_vals *vals;
|
||||||
unsigned val;
|
unsigned val, mask;
|
||||||
|
|
||||||
vals = &func->vals[i];
|
vals = &func->vals[i];
|
||||||
val = pcs->read(vals->reg);
|
val = pcs->read(vals->reg);
|
||||||
val &= ~pcs->fmask;
|
if (!vals->mask)
|
||||||
val |= (vals->val & pcs->fmask);
|
mask = pcs->fmask;
|
||||||
|
else
|
||||||
|
mask = pcs->fmask & vals->mask;
|
||||||
|
|
||||||
|
val &= ~mask;
|
||||||
|
val |= (vals->val & mask);
|
||||||
pcs->write(val, vals->reg);
|
pcs->write(val, vals->reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,18 +665,29 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
||||||
{
|
{
|
||||||
struct pcs_func_vals *vals;
|
struct pcs_func_vals *vals;
|
||||||
const __be32 *mux;
|
const __be32 *mux;
|
||||||
int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
|
int size, params, rows, *pins, index = 0, found = 0, res = -ENOMEM;
|
||||||
struct pcs_function *function;
|
struct pcs_function *function;
|
||||||
|
|
||||||
mux = of_get_property(np, PCS_MUX_NAME, &size);
|
if (pcs->bits_per_mux) {
|
||||||
if ((!mux) || (size < sizeof(*mux) * 2)) {
|
params = 3;
|
||||||
dev_err(pcs->dev, "bad data for mux %s\n",
|
mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
|
||||||
np->name);
|
} else {
|
||||||
|
params = 2;
|
||||||
|
mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mux) {
|
||||||
|
dev_err(pcs->dev, "no valid property for %s\n", np->name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < (sizeof(*mux) * params)) {
|
||||||
|
dev_err(pcs->dev, "bad data for %s\n", np->name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size /= sizeof(*mux); /* Number of elements in array */
|
size /= sizeof(*mux); /* Number of elements in array */
|
||||||
rows = size / 2; /* Each row is a key value pair */
|
rows = size / params;
|
||||||
|
|
||||||
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
|
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
|
||||||
if (!vals)
|
if (!vals)
|
||||||
|
@ -686,6 +705,10 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
||||||
val = be32_to_cpup(mux + index++);
|
val = be32_to_cpup(mux + index++);
|
||||||
vals[found].reg = pcs->base + offset;
|
vals[found].reg = pcs->base + offset;
|
||||||
vals[found].val = val;
|
vals[found].val = val;
|
||||||
|
if (params == 3) {
|
||||||
|
val = be32_to_cpup(mux + index++);
|
||||||
|
vals[found].mask = val;
|
||||||
|
}
|
||||||
|
|
||||||
pin = pcs_get_pin_by_offset(pcs, offset);
|
pin = pcs_get_pin_by_offset(pcs, offset);
|
||||||
if (pin < 0) {
|
if (pin < 0) {
|
||||||
|
@ -883,6 +906,9 @@ static int __devinit pcs_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
pcs->foff = PCS_OFF_DISABLED;
|
pcs->foff = PCS_OFF_DISABLED;
|
||||||
|
|
||||||
|
pcs->bits_per_mux = of_property_read_bool(np,
|
||||||
|
"pinctrl-single,bit-per-mux");
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
dev_err(pcs->dev, "could not get resource\n");
|
dev_err(pcs->dev, "could not get resource\n");
|
||||||
|
|
Loading…
Reference in New Issue