diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-12-06 08:23:27 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-12-06 08:23:27 +0100 |
commit | ed039cd72bfe7cf897fc195dd9cfec0bfa359222 (patch) | |
tree | ff64b841e6245817d987be35c488fbf747560d95 /drivers/pinctrl | |
parent | 6d7fae1e97d67b635a972b0f1f5c6a140c596e95 (diff) | |
parent | 03d601d58f4d6228bcb67e6035d4ede7b1d99ae3 (diff) | |
download | barebox-ed039cd72bfe7cf897fc195dd9cfec0bfa359222.tar.gz barebox-ed039cd72bfe7cf897fc195dd9cfec0bfa359222.tar.xz |
Merge branch 'for-next/omap-drivers'
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/Kconfig | 3 | ||||
-rw-r--r-- | drivers/pinctrl/Makefile | 1 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-single.c | 166 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl.c | 24 |
4 files changed, 188 insertions, 6 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 58397a0ac8..8257586929 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -23,6 +23,9 @@ config PINCTRL_IMX_IOMUX_V3 help This iomux controller is found on i.MX25,35,51,53,6. +config PINCTRL_SINGLE + bool "pinctrl single" + config PINCTRL_TEGRA20 select PINCTRL bool diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 169ed184c7..b3b0fa9c58 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -2,4 +2,5 @@ obj-$(CONFIG_PINCTRL) += pinctrl.o obj-$(CONFIG_PINCTRL_IMX_IOMUX_V1) += imx-iomux-v1.o obj-$(CONFIG_PINCTRL_IMX_IOMUX_V2) += imx-iomux-v2.o obj-$(CONFIG_PINCTRL_IMX_IOMUX_V3) += imx-iomux-v3.o +obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c new file mode 100644 index 0000000000..5c60c70b17 --- /dev/null +++ b/drivers/pinctrl/pinctrl-single.c @@ -0,0 +1,166 @@ +/* + * 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> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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> +#include <init.h> +#include <io.h> +#include <pinctrl.h> +#include <malloc.h> + +struct pinctrl_single { + void __iomem *base; + struct pinctrl_device pinctrl; + unsigned (*read)(void __iomem *reg); + void (*write)(unsigned val, void __iomem *reg); + unsigned width; +}; + +static unsigned __maybe_unused pcs_readb(void __iomem *reg) +{ + return readb(reg); +} + +static unsigned __maybe_unused pcs_readw(void __iomem *reg) +{ + return readw(reg); +} + +static unsigned __maybe_unused pcs_readl(void __iomem *reg) +{ + return readl(reg); +} + +static void __maybe_unused pcs_writeb(unsigned val, void __iomem *reg) +{ + writeb(val, reg); +} + +static void __maybe_unused pcs_writew(unsigned val, void __iomem *reg) +{ + writew(val, reg); +} + +static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg) +{ + writel(val, reg); +} + +static int pcs_set_state(struct pinctrl_device *pdev, struct device_node *np) +{ + struct pinctrl_single *pcs = container_of(pdev, struct pinctrl_single, pinctrl); + unsigned size = 0, index = 0; + const __be32 *mux; + + dev_dbg(pcs->pinctrl.dev, "set state: %s\n", np->full_name); + + mux = of_get_property(np, "pinctrl-single,pins", &size); + + 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); + return -EINVAL; + } + + while (index < size) { + unsigned offset, val; + + offset = be32_to_cpup(mux + index++); + val = be32_to_cpup(mux + index++); + + pcs->write(val, pcs->base + offset); + } + + return 0; +} + +static struct pinctrl_ops pcs_ops = { + .set_state = pcs_set_state, +}; + +static int pcs_probe(struct device_d *dev) +{ + struct pinctrl_single *pcs; + struct device_node *np = dev->device_node; + int ret = 0; + + pcs = xzalloc(sizeof(*pcs)); + pcs->base = dev_request_mem_region(dev, 0); + pcs->pinctrl.dev = dev; + pcs->pinctrl.ops = &pcs_ops; + + ret = of_property_read_u32(np, "pinctrl-single,register-width", + &pcs->width); + if (ret) { + dev_dbg(dev, "no pinctrl-single,register-width property\n"); + goto out; + } + + switch (pcs->width) { + case 8: + pcs->read = pcs_readb; + pcs->write = pcs_writeb; + break; + case 16: + pcs->read = pcs_readw; + pcs->write = pcs_writew; + break; + case 32: + pcs->read = pcs_readl; + pcs->write = pcs_writel; + break; + default: + ret = -EINVAL; + dev_dbg(dev, "invalid register width: %d\n", pcs->width); + goto out; + } + + ret = pinctrl_register(&pcs->pinctrl); + if (ret) + goto out; + + return 0; + +out: + free(pcs); + + return ret; +} + +static __maybe_unused struct of_device_id pcs_dt_ids[] = { + { + .compatible = "pinctrl-single", + }, { + /* sentinel */ + } +}; + +static struct driver_d pcs_driver = { + .name = "pinctrl-single", + .probe = pcs_probe, + .of_compatible = DRV_OF_COMPAT(pcs_dt_ids), +}; + +static int pcs_init(void) +{ + return platform_driver_register(&pcs_driver); +} +postcore_initcall(pcs_init); diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c index 7f76d5a681..8963ac75c0 100644 --- a/drivers/pinctrl/pinctrl.c +++ b/drivers/pinctrl/pinctrl.c @@ -51,7 +51,7 @@ static int pinctrl_config_one(struct device_node *np) return pdev->ops->set_state(pdev, np); } -int pinctrl_select_state(struct device_d *dev, const char *name) +int of_pinctrl_select_state(struct device_node *np, const char *name) { int state, ret; char *propname; @@ -59,13 +59,9 @@ int pinctrl_select_state(struct device_d *dev, const char *name) const __be32 *list; int size, config; phandle phandle; - struct device_node *np_config, *np; + struct device_node *np_config; const char *statename; - np = dev->device_node; - if (!np) - return 0; - if (!of_find_property(np, "pinctrl-0", NULL)) return 0; @@ -127,6 +123,22 @@ err: return ret; } +int of_pinctrl_select_state_default(struct device_node *np) +{ + return of_pinctrl_select_state(np, "default"); +} + +int pinctrl_select_state(struct device_d *dev, const char *name) +{ + struct device_node *np; + + np = dev->device_node; + if (!np) + return 0; + + return of_pinctrl_select_state(np, name); +} + int pinctrl_select_state_default(struct device_d *dev) { return pinctrl_select_state(dev, "default"); |