The code responsible for setting proper values in the MUX registers (in the mxs_pinctrl_set_state()) has been ported from Barebox project (branch: master, SHA1: eb3b0f7414cd8102844dd16b1c789e445e8947f8, file: drivers/pinctrl/pinctrl-mxs.c).
As the pinctrl node in the imx28.dtsi file has gpio pins nodes as subnodes, it was necessary to use 'dm_scan_fdt_dev()' (as a .bind method) to also make them 'visible' by the DM's "gpio_mxs" driver. Signed-off-by: Lukasz Majewski <lu...@denx.de> --- Changes in v2: None drivers/pinctrl/nxp/Kconfig | 10 +++ drivers/pinctrl/nxp/Makefile | 1 + drivers/pinctrl/nxp/pinctrl-mxs.c | 164 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 drivers/pinctrl/nxp/pinctrl-mxs.c diff --git a/drivers/pinctrl/nxp/Kconfig b/drivers/pinctrl/nxp/Kconfig index 61f93be42d..f2e67ca231 100644 --- a/drivers/pinctrl/nxp/Kconfig +++ b/drivers/pinctrl/nxp/Kconfig @@ -89,6 +89,16 @@ config PINCTRL_IMX8M only parses the 'fsl,pins' property and configure related registers. +config PINCTRL_MXS + bool "NXP MXS pinctrl driver" + depends on ARCH_MX28 && PINCTRL_FULL + help + Say Y here to enable the i.MX mxs pinctrl driver + + This option provides a simple pinctrl driver for i.MX mxs SoC + familiy, e.g. i.MX28. This feature depends on device tree + configuration. + config PINCTRL_VYBRID bool "Vybrid (vf610) pinctrl driver" depends on ARCH_VF610 && PINCTRL_FULL diff --git a/drivers/pinctrl/nxp/Makefile b/drivers/pinctrl/nxp/Makefile index b340d9448a..b86448aac9 100644 --- a/drivers/pinctrl/nxp/Makefile +++ b/drivers/pinctrl/nxp/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_PINCTRL_IMX7ULP) += pinctrl-imx7ulp.o obj-$(CONFIG_PINCTRL_IMX_SCU) += pinctrl-scu.o obj-$(CONFIG_PINCTRL_IMX8) += pinctrl-imx8.o obj-$(CONFIG_PINCTRL_IMX8M) += pinctrl-imx8m.o +obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o obj-$(CONFIG_PINCTRL_VYBRID) += pinctrl-vf610.o diff --git a/drivers/pinctrl/nxp/pinctrl-mxs.c b/drivers/pinctrl/nxp/pinctrl-mxs.c new file mode 100644 index 0000000000..42b1b7998b --- /dev/null +++ b/drivers/pinctrl/nxp/pinctrl-mxs.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 DENX Software Engineering + * Lukasz Majewski, DENX Software Engineering, lu...@denx.de + * + * This work is based on drivers/pinctrl/pinctrl-mxs.c + * SHA1: eb3b0f7414cd8102844dd16b1c789e445e8947f8 + * from Barebox project. + * + * Author of original Barebox pinctrl-mxs.c: + * Copyright (c) 2015 Sascha Hauer <s.ha...@pengutronix.de> + */ + +#include <common.h> +#include <linux/io.h> +#include <linux/err.h> +#include <dm.h> +#include <dm/pinctrl.h> +#include <dm/read.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define PINID(bank, pin) ((bank) * 32 + (pin)) +#define MUXID_TO_PINID(m) PINID((m) >> 12 & 0xf, (m) >> 4 & 0xff) +#define MUXID_TO_MUXSEL(m) ((m) & 0xf) +#define PINID_TO_BANK(p) ((p) >> 5) +#define PINID_TO_PIN(p) ((p) % 32) + +#define STMP_OFFSET_REG_SET 0x4 +#define STMP_OFFSET_REG_CLR 0x8 +#define STMP_OFFSET_REG_TOG 0xc + +struct mxs_pinctrl_priv { + void __iomem *base; +}; + +static int mxs_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + int ma_present = 0, vol_present = 0, pull_present = 0; + struct mxs_pinctrl_priv *iomux = dev_get_priv(dev); + u32 *pin_data, val, ma, vol, pull; + int npins, size, i, ret; + + debug("\n%s: set state: %s\n", __func__, config->name); + + size = dev_read_size(config, "fsl,pinmux-ids"); + if (size < 0) + return size; + + if (!size || size % 4) { + dev_err(dev, "Invalid fsl,pinmux-ids property in %s\n", + config->name); + return -EINVAL; + } + + npins = size / 4; + + pin_data = devm_kzalloc(dev, size, 0); + if (!pin_data) + return -ENOMEM; + + ret = dev_read_u32_array(config, "fsl,pinmux-ids", pin_data, npins); + if (ret) { + dev_err(dev, "Error reading pin data.\n"); + devm_kfree(dev, pin_data); + return -EINVAL; + } + + ret = dev_read_u32(config, "fsl,drive-strength", &ma); + if (!ret) + ma_present = 1; + + ret = dev_read_u32(config, "fsl,voltage", &vol); + if (!ret) + vol_present = 1; + + ret = dev_read_u32(config, "fsl,pull-up", &pull); + if (!ret) + pull_present = 1; + + for (i = 0; i < npins; i++) { + int muxsel, pinid, bank, pin, shift; + void __iomem *reg; + + val = *pin_data++; + + muxsel = MUXID_TO_MUXSEL(val); + pinid = MUXID_TO_PINID(val); + + bank = PINID_TO_BANK(pinid); + pin = PINID_TO_PIN(pinid); + reg = iomux->base + 0x100; + reg += bank * 0x20 + pin / 16 * 0x10; + shift = pin % 16 * 2; + + writel(0x3 << shift, reg + STMP_OFFSET_REG_CLR); + writel(muxsel << shift, reg + STMP_OFFSET_REG_SET); + + debug("(val: 0x%x) pin %d, mux %d, ma: %d, vol: %d, pull: %d\n", + val, pinid, muxsel, ma, vol, pull); + + /* drive */ + reg = iomux->base + 0x300; + reg += bank * 0x40 + pin / 8 * 0x10; + + /* mA */ + if (ma_present) { + shift = pin % 8 * 4; + writel(0x3 << shift, reg + STMP_OFFSET_REG_CLR); + writel(ma << shift, reg + STMP_OFFSET_REG_SET); + } + + /* vol */ + if (vol_present) { + shift = pin % 8 * 4 + 2; + if (vol) + writel(1 << shift, reg + STMP_OFFSET_REG_SET); + else + writel(1 << shift, reg + STMP_OFFSET_REG_CLR); + } + + /* pull */ + if (pull_present) { + reg = iomux->base + 0x600; + reg += bank * 0x10; + shift = pin; + if (pull) + writel(1 << shift, reg + STMP_OFFSET_REG_SET); + else + writel(1 << shift, reg + STMP_OFFSET_REG_CLR); + } + } + + return 0; +} + +static struct pinctrl_ops mxs_pinctrl_ops = { + .set_state = mxs_pinctrl_set_state, +}; + +static int mxs_pinctrl_probe(struct udevice *dev) +{ + struct mxs_pinctrl_priv *iomux = dev_get_priv(dev); + iomux->base = dev_read_addr_ptr(dev); + + return 0; +} + +static const struct udevice_id mxs_pinctrl_match[] = { + { .compatible = "fsl,imx28-pinctrl" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(mxs_pinctrl) = { + .name = "mxs-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = of_match_ptr(mxs_pinctrl_match), + .probe = mxs_pinctrl_probe, +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + .bind = dm_scan_fdt_dev, +#endif + .priv_auto_alloc_size = sizeof(struct mxs_pinctrl_priv), + .ops = &mxs_pinctrl_ops, +}; -- 2.11.0 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot