summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorTrent Piepho <tpiepho@gmail.com>2020-09-09 00:19:05 -0700
committerSascha Hauer <s.hauer@pengutronix.de>2020-09-14 10:30:46 +0200
commitc6d2ab432d054976e233dc93734e362f0a1ab173 (patch)
tree445615b1e39c3b07f42ed949e0452a7273990378 /drivers/pinctrl
parent90566f5c77e06de1a031c2b30a7472362ff9a75e (diff)
downloadbarebox-c6d2ab432d054976e233dc93734e362f0a1ab173.tar.gz
barebox-c6d2ab432d054976e233dc93734e362f0a1ab173.tar.xz
pinctrl-single: Support 2 pinctrl-cells in ,pins mode
The 5.9rc-1 dts update pulled in a change that broke all TI AM33xx platforms. This fixes that. Previously, when using pinctrl-single,pins, the value of "#pinctrl-cells" was always 1, which indicates one data cell per pin, which contains the value to to program into the pinctrl register. In kernel v5.9-rc1, commit a13395418888 ("pinctrl: single: parse #pinctrl-cells = 2"), added support for 2 data cells per pin. The two cells get ORed together to produce one register value. Then commit 27c90e5e48d0 ("ARM: dts: am33xx-l4: change #pinctrl-cells from 1 to 2"), changed the dts files to use two cells for am33xx and changed the AM33XX_PADCONF() macro to produce two data cells instead of ORing the two values together. The pinctrl driver will now do the OR to produce the same value that was in one cell before. I don't see what this accomplishes, but there it is. The dts update pulled in the latter change, but not the former, leaving Barebox's pinctrl-single driver unable to correctly use the am33xx pinctrl data. This commit adds support for the 2 cell format. It would be easier to just change the dts files back, since this change doesn't appear actually accomplish anything, but then the dts source would be out of sync with the kernel. Signed-off-by: Trent Piepho <tpiepho@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinctrl-single.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 4ce66a84de..c31b7e0365 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -27,12 +27,13 @@ struct pinctrl_single {
unsigned (*read)(void __iomem *reg);
void (*write)(unsigned val, void __iomem *reg);
unsigned int width;
- unsigned int fmask;
+ unsigned int fmask;
unsigned int fshift;
unsigned int fmax;
bool bits_per_mux;
unsigned int bits_per_pin;
+ unsigned int args_count;
};
static unsigned __maybe_unused pcs_readb(void __iomem *reg)
@@ -96,7 +97,7 @@ static int pcs_set_state(struct pinctrl_device *pdev, struct device_node *np)
size /= sizeof(*mux); /* Number of elements in array */
- if (!mux || !size || (size & 1)) {
+ if (!mux || !size || (size % (pcs->args_count + 1))) {
dev_err(pcs->pinctrl.dev, "bad data for mux %s\n",
np->full_name);
return -EINVAL;
@@ -107,6 +108,14 @@ static int pcs_set_state(struct pinctrl_device *pdev, struct device_node *np)
offset = be32_to_cpup(mux + index++);
val = be32_to_cpup(mux + index++);
+ if (pcs->args_count > 1) {
+ /* If a 2nd data cell is present, it's ORed into
+ * the 1st. Additional cells are undefined,
+ * just skip them.
+ */
+ val |= be32_to_cpup(mux + index);
+ index += pcs->args_count - 1;
+ }
pcs->write(val, pcs->base + offset);
}
@@ -177,6 +186,13 @@ static int pcs_probe(struct device_d *dev)
if (pcs->bits_per_mux)
pcs->bits_per_pin = fls(pcs->fmask);
+ /* If no pinctrl-cells is present, default to old style of 2 cells with
+ * bits per mux and 1 cell otherwise.
+ */
+ ret = of_property_read_u32(np, "#pinctrl-cells", &pcs->args_count);
+ if (ret)
+ pcs->args_count = pcs->bits_per_mux ? 2 : 1;
+
ret = pinctrl_register(&pcs->pinctrl);
if (ret)
goto out;