summaryrefslogtreecommitdiff
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorVikas Manocha <vikas.manocha@st.com>2017-02-12 18:25:49 (GMT)
committerTom Rini <trini@konsulko.com>2017-03-17 18:15:14 (GMT)
commit94d53084120bd977249e78ae4738cc28e62d276d (patch)
treeae13da48f3e702bc1c82ad6faa1dfc50dfca2605 /drivers/pinctrl
parentb5be8f5ea8d9b0ffc46f818ce0cb38cd16f99e4d (diff)
downloadu-boot-fsl-qoriq-94d53084120bd977249e78ae4738cc28e62d276d.tar.xz
PINCTRL: stm32f7: add pin control driver
This driver uses the same pin control binding as that of linux, binding document of this patch is copied from linux. One addition done is for GPIO input and output mode configuration which was missing. Signed-off-by: Vikas Manocha <vikas.manocha@st.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/Kconfig9
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/pinctrl_stm32.c117
3 files changed, 127 insertions, 0 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 0c832e1..d011dad 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -185,6 +185,15 @@ config PINCTRL_STI
the GPIO definitions and pin control functions for each available multiplex
function.
+config PINCTRL_STM32
+ bool "ST STM32 pin control driver"
+ depends on DM
+ help
+ Supports pin multiplexing control on stm32 SoCs. The driver is
+ controlled by a device tree node which contains both the GPIO
+ definitions and pin control functions for each available multiplex
+ function.
+
endif
source "drivers/pinctrl/meson/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index a2f8101..b04ca86 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/
obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/
obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
+obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
new file mode 100644
index 0000000..aa2c440
--- /dev/null
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -0,0 +1,117 @@
+#include <common.h>
+#include <asm/arch/gpio.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin)
+{
+ gpio_dsc->port = (port_pin & 0xF000) >> 12;
+ gpio_dsc->pin = (port_pin & 0x0F00) >> 8;
+ debug("%s: GPIO:port= %d, pin= %d\n", __func__, gpio_dsc->port,
+ gpio_dsc->pin);
+
+ return 0;
+}
+
+static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node)
+{
+ gpio_fn &= 0x00FF;
+
+ switch (gpio_fn) {
+ case 0:
+ gpio_ctl->mode = STM32_GPIO_MODE_IN;
+ break;
+ case 1 ... 16:
+ gpio_ctl->mode = STM32_GPIO_MODE_AF;
+ gpio_ctl->af = gpio_fn - 1;
+ break;
+ case 17:
+ gpio_ctl->mode = STM32_GPIO_MODE_AN;
+ break;
+ default:
+ gpio_ctl->mode = STM32_GPIO_MODE_OUT;
+ break;
+ }
+
+ gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0);
+
+ if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain"))
+ gpio_ctl->otype = STM32_GPIO_OTYPE_OD;
+ else
+ gpio_ctl->otype = STM32_GPIO_OTYPE_PP;
+
+ if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up"))
+ gpio_ctl->pupd = STM32_GPIO_PUPD_UP;
+ else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down"))
+ gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN;
+ else
+ gpio_ctl->pupd = STM32_GPIO_PUPD_NO;
+
+ debug("%s: gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is = %x\n",
+ __func__, gpio_fn, gpio_ctl->speed, gpio_ctl->otype,
+ gpio_ctl->pupd);
+
+ return 0;
+}
+
+static int stm32_pinctrl_set_state_simple(struct udevice *dev,
+ struct udevice *periph)
+{
+ u32 pin_mux[50];
+ struct fdtdec_phandle_args args;
+ int rv, len;
+
+ /* Get node pinctrl-0 */
+ rv = fdtdec_parse_phandle_with_args(gd->fdt_blob, periph->of_offset,
+ "pinctrl-0", 0, 0, 0, &args);
+ if (rv)
+ return rv;
+ /*
+ * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for
+ * usart1) of pin controller phandle "pinctrl-0"
+ * */
+ fdt_for_each_subnode(args.node, gd->fdt_blob, args.node) {
+ struct stm32_gpio_dsc gpio_dsc;
+ struct stm32_gpio_ctl gpio_ctl;
+ int i;
+
+ len = fdtdec_get_int_array_count(gd->fdt_blob, args.node,
+ "pinmux", pin_mux,
+ ARRAY_SIZE(pin_mux));
+ debug("%s: periph->name = %s, no of pinmux entries= %d\n",
+ __func__, periph->name, len);
+ if (len < 0)
+ return -EINVAL;
+ for (i = 0; i < len; i++) {
+ debug("%s: pinmux = %x\n", __func__, *(pin_mux + i));
+ prep_gpio_dsc(&gpio_dsc, *(pin_mux + i));
+ prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), args.node);
+
+ rv = stm32_gpio_config(&gpio_dsc, &gpio_ctl);
+ debug("%s: rv = %d\n\n", __func__, rv);
+ if (rv)
+ return rv;
+ }
+ }
+
+ return 0;
+}
+
+static struct pinctrl_ops stm32_pinctrl_ops = {
+ .set_state_simple = stm32_pinctrl_set_state_simple,
+};
+
+static const struct udevice_id stm32_pinctrl_ids[] = {
+ { .compatible = "st,stm32f746-pinctrl" },
+ { }
+};
+
+U_BOOT_DRIVER(pinctrl_stm32) = {
+ .name = "pinctrl_stm32",
+ .id = UCLASS_PINCTRL,
+ .of_match = stm32_pinctrl_ids,
+ .ops = &stm32_pinctrl_ops,
+ .bind = dm_scan_fdt_dev,
+};