summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/pinctrl_stm32.c
diff options
context:
space:
mode:
authorVikas Manocha <vikas.manocha@st.com>2017-02-12 10:25:49 -0800
committerTom Rini <trini@konsulko.com>2017-03-17 14:15:14 -0400
commit94d53084120bd977249e78ae4738cc28e62d276d (patch)
treeae13da48f3e702bc1c82ad6faa1dfc50dfca2605 /drivers/pinctrl/pinctrl_stm32.c
parentb5be8f5ea8d9b0ffc46f818ce0cb38cd16f99e4d (diff)
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/pinctrl_stm32.c')
-rw-r--r--drivers/pinctrl/pinctrl_stm32.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
new file mode 100644
index 0000000000..aa2c440b14
--- /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,
+};