dect
/
linux-2.6
Archived
13
0
Fork 0

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:
Peter Ujfalusi 2012-09-11 11:54:24 +03:00 committed by Linus Walleij
parent 2830c3686b
commit 9e605cb68a
2 changed files with 74 additions and 13 deletions

View File

@ -14,10 +14,12 @@ Optional properties:
- pinctrl-single,function-off : function off mode for disabled state if
available and same for all registers; if not specified, disabling of
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,
and uses the common pinctrl bindings as specified in the pinctrl-bindings.txt
document in this directory.
This driver assumes that there is only one register for each pin (unless the
pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as
specified in the pinctrl-bindings.txt document in this directory.
The pin configuration nodes for pinctrl-single are specified as pinctrl
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
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:
/* SoC common file */
@ -55,6 +66,15 @@ pmx_wkup: pinmux@4a31e040 {
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 */
@ -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 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;

View File

@ -26,7 +26,8 @@
#include "core.h"
#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_OFF_DISABLED ~0U
@ -54,6 +55,7 @@ struct pcs_pingroup {
struct pcs_func_vals {
void __iomem *reg;
unsigned val;
unsigned mask;
};
/**
@ -139,6 +141,7 @@ struct pcs_device {
unsigned fshift;
unsigned foff;
unsigned fmax;
bool bits_per_mux;
struct pcs_name *names;
struct pcs_data pins;
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++) {
struct pcs_func_vals *vals;
unsigned val;
unsigned val, mask;
vals = &func->vals[i];
val = pcs->read(vals->reg);
val &= ~pcs->fmask;
val |= (vals->val & pcs->fmask);
if (!vals->mask)
mask = pcs->fmask;
else
mask = pcs->fmask & vals->mask;
val &= ~mask;
val |= (vals->val & mask);
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;
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;
mux = of_get_property(np, PCS_MUX_NAME, &size);
if ((!mux) || (size < sizeof(*mux) * 2)) {
dev_err(pcs->dev, "bad data for mux %s\n",
np->name);
if (pcs->bits_per_mux) {
params = 3;
mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
} 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;
}
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);
if (!vals)
@ -686,6 +705,10 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
val = be32_to_cpup(mux + index++);
vals[found].reg = pcs->base + offset;
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);
if (pin < 0) {
@ -883,6 +906,9 @@ static int __devinit pcs_probe(struct platform_device *pdev)
if (ret)
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);
if (!res) {
dev_err(pcs->dev, "could not get resource\n");