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.ujfal...@ti.com>
---
 .../devicetree/bindings/pinctrl/pinctrl-single.txt |  9 +++++
 drivers/pinctrl/pinctrl-single.c                   | 42 ++++++++++++++++------
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt 
b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 5187f0d..287801d 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -31,6 +31,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 can 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 */
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 3508631..aec338e 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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;
 };
 
 /**
@@ -332,12 +334,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 +664,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);
+       mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
+       if (mux) {
+               params = 2;
+       } else {
+               mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
+               if (!mux) {
+                       dev_err(pcs->dev, "no valid property for %s\n",
+                               np->name);
+                       return -EINVAL;
+               }
+               params = 3;
+       }
+
+       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;   /* Each row is a key value pair */
 
        vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
        if (!vals)
@@ -686,6 +704,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) {
-- 
1.7.12

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to