Commit 9e605cb6 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Linus Walleij

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: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
Acked-by: default avatarTony Lindgren <tony@atomide.com>
[Removed a misplaced comment]
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 2830c368
...@@ -14,10 +14,12 @@ Optional properties: ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment