diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-single.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-single.c | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 4ce66a84de..0e706656b9 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * pinctrl-single - Generic device tree based pinctrl driver for one * register per pin type pinmux controllers * * Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <common.h> @@ -27,12 +18,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) @@ -72,7 +64,7 @@ static int pcs_set_state(struct pinctrl_device *pdev, struct device_node *np) unsigned int offset, val, rows, mask, reg, i; const __be32 *mux; - dev_dbg(pcs->pinctrl.dev, "set state: %s\n", np->full_name); + dev_dbg(pcs->pinctrl.dev, "set state: %pOF\n", np); if (pcs->bits_per_mux) { mux = of_get_property(np, "pinctrl-single,bits", &size); if (size % 3 != 0) @@ -96,9 +88,8 @@ 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)) { - dev_err(pcs->pinctrl.dev, "bad data for mux %s\n", - np->full_name); + if (!mux || !size || (size % (pcs->args_count + 1))) { + dev_err(pcs->pinctrl.dev, "bad data for mux %pOF\n", np); return -EINVAL; } @@ -107,6 +98,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); } @@ -119,11 +118,11 @@ static struct pinctrl_ops pcs_ops = { .set_state = pcs_set_state, }; -static int pcs_probe(struct device_d *dev) +int pinctrl_single_probe(struct device *dev) { struct resource *iores; struct pinctrl_single *pcs; - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; int ret = 0; pcs = xzalloc(sizeof(*pcs)); @@ -177,6 +176,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; @@ -196,15 +202,12 @@ static __maybe_unused struct of_device_id pcs_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, pcs_dt_ids); -static struct driver_d pcs_driver = { +static struct driver pcs_driver = { .name = "pinctrl-single", - .probe = pcs_probe, + .probe = pinctrl_single_probe, .of_compatible = DRV_OF_COMPAT(pcs_dt_ids), }; -static int pcs_init(void) -{ - return platform_driver_register(&pcs_driver); -} -core_initcall(pcs_init); +core_platform_driver(pcs_driver); |