Add support for handling pinctrl device tree bindings to imxiomuxc(4).
authorkettenis <kettenis@openbsd.org>
Sun, 10 Jul 2016 11:46:28 +0000 (11:46 +0000)
committerkettenis <kettenis@openbsd.org>
Sun, 10 Jul 2016 11:46:28 +0000 (11:46 +0000)
These are used to do board-specific setup of mux settings and pad
configuration.

ok jsg@, patrick@

sys/arch/armv7/imx/if_fec.c
sys/arch/armv7/imx/imxehci.c
sys/arch/armv7/imx/imxesdhc.c
sys/arch/armv7/imx/imxiic.c
sys/arch/armv7/imx/imxiomuxc.c
sys/arch/armv7/imx/imxiomuxcvar.h
sys/arch/armv7/imx/imxuart.c

index f35f727..33ee28d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_fec.c,v 1.4 2016/07/09 12:39:28 kettenis Exp $ */
+/* $OpenBSD: if_fec.c,v 1.5 2016/07/10 11:46:28 kettenis Exp $ */
 /*
  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
  *
@@ -47,7 +47,7 @@
 #include <armv7/armv7/armv7var.h>
 #include <armv7/imx/imxccmvar.h>
 #include <armv7/imx/imxgpiovar.h>
-#include <armv7/imx/imxocotpvar.h>
+#include <armv7/imx/imxiomuxcvar.h>
 
 #include <dev/ofw/openfirm.h>
 
@@ -309,6 +309,8 @@ fec_attach(struct device *parent, struct device *self, void *aux)
 
        sc->sc_dma_tag = faa->fa_dmat;
 
+       imxiomuxc_pinctrlbyname(faa->fa_node, "default");
+
        /* power it up */
        imxccm_enable_enet();
 
index cc216cf..f83a692 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: imxehci.c,v 1.10 2016/07/09 12:32:50 kettenis Exp $ */
+/*     $OpenBSD: imxehci.c,v 1.11 2016/07/10 11:46:28 kettenis Exp $ */
 /*
  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
  *
@@ -34,6 +34,7 @@
 #include <armv7/armv7/armv7var.h>
 #include <armv7/imx/imxccmvar.h>
 #include <armv7/imx/imxgpiovar.h>
+#include <armv7/imx/imxiomuxcvar.h>
 
 #include <dev/ofw/openfirm.h>
 
@@ -170,6 +171,8 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
 
        printf("\n");
 
+       imxiomuxc_pinctrlbyname(faa->fa_node, "default");
+
        imxccm_enable_usboh3();
        delay(1000);
 
index 7142072..dfc1f6d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: imxesdhc.c,v 1.23 2016/06/14 14:41:03 kettenis Exp $  */
+/*     $OpenBSD: imxesdhc.c,v 1.24 2016/07/10 11:46:28 kettenis Exp $  */
 /*
  * Copyright (c) 2009 Dale Rahn <drahn@openbsd.org>
  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -35,6 +35,7 @@
 #include <armv7/armv7/armv7var.h>
 #include <armv7/imx/imxccmvar.h>
 #include <armv7/imx/imxgpiovar.h>
+#include <armv7/imx/imxiomuxcvar.h>
 
 #include <dev/ofw/openfirm.h>
 
@@ -306,6 +307,8 @@ imxesdhc_attach(struct device *parent, struct device *self, void *aux)
 
        printf("\n");
 
+       imxiomuxc_pinctrlbyname(faa->fa_node, "default");
+
        sc->sc_ih = arm_intr_establish(faa->fa_intr[1], IPL_SDMMC,
           imxesdhc_intr, sc, sc->sc_dev.dv_xname);
 
index 95875fb..b966e0d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: imxiic.c,v 1.7 2016/06/09 12:35:46 kettenis Exp $ */
+/* $OpenBSD: imxiic.c,v 1.8 2016/07/10 11:46:28 kettenis Exp $ */
 /*
  * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se>
  *
@@ -134,7 +134,7 @@ imxiic_attach(struct device *parent, struct device *self, void *aux)
        printf("\n");
 
        /* set iomux pins */
-       imxiomuxc_enable_i2c(sc->unit);
+       imxiomuxc_pinctrlbyname(faa->fa_node, "default");
 
        /* set speed to 100kHz */
        imxiic_setspeed(sc, 100);
index d58e8b8..3709981 100644 (file)
@@ -1,6 +1,7 @@
-/* $OpenBSD: imxiomuxc.c,v 1.2 2013/11/06 19:03:07 syl Exp $ */
+/* $OpenBSD: imxiomuxc.c,v 1.3 2016/07/10 11:46:28 kettenis Exp $ */
 /*
  * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se>
+ * Copyright (c) 2016 Mark Kettenus <kettenis@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include <sys/evcount.h>
 #include <sys/socket.h>
 #include <sys/timeout.h>
+
 #include <machine/intr.h>
 #include <machine/bus.h>
+
 #include <armv7/armv7/armv7var.h>
+#include <armv7/imx/imxiomuxcvar.h>
+
+#include <dev/ofw/openfirm.h>
 
 /* registers */
 #define IOMUXC_GPR1                    0x004
 #define IOMUXC_GPR12                   0x030
 #define IOMUXC_GPR13                   0x034
 
-#define IOMUXC_MUX_CTL_PAD_EIM_EB2     0x08C
-#define IOMUXC_MUX_CTL_PAD_EIM_DATA16  0x090
-#define IOMUXC_MUX_CTL_PAD_EIM_DATA17  0x094
-#define IOMUXC_MUX_CTL_PAD_EIM_DATA18  0x098
-#define IOMUXC_MUX_CTL_PAD_EIM_DATA21  0x0A4
-#define IOMUXC_MUX_CTL_PAD_EIM_DATA28  0x0C4
-
-#define IOMUXC_PAD_CTL_PAD_EIM_EB2     0x3A0
-#define IOMUXC_PAD_CTL_PAD_EIM_DATA16  0x3A4
-#define IOMUXC_PAD_CTL_PAD_EIM_DATA17  0x3A8
-#define IOMUXC_PAD_CTL_PAD_EIM_DATA18  0x3AC
-#define IOMUXC_PAD_CTL_PAD_EIM_DATA21  0x3B8
-#define IOMUXC_PAD_CTL_PAD_EIM_DATA28  0x3D8
-
-#define IOMUXC_I2C1_SCL_IN_SELECT_INPUT        0x898
-#define IOMUXC_I2C1_SDA_IN_SELECT_INPUT        0x89C
-#define IOMUXC_I2C2_SCL_IN_SELECT_INPUT        0x8A0
-#define IOMUXC_I2C2_SDA_IN_SELECT_INPUT        0x8A4
-#define IOMUXC_I2C3_SCL_IN_SELECT_INPUT        0x8A8
-#define IOMUXC_I2C3_SDA_IN_SELECT_INPUT        0x8AC
-
 /* bits and bytes */
 #define IOMUXC_GPR1_REF_SSP_EN                                 (1 << 16)
 #define IOMUXC_GPR1_TEST_POWERDOWN                             (1 << 18)
 
 #define IOMUX_CONFIG_SION              (1 << 4)
 
+#define IMX_PINCTRL_NO_PAD_CTL         (1 << 31)
+#define IMX_PINCTRL_SION               (1 << 30)
+
 struct imxiomuxc_softc {
        struct device           sc_dev;
        bus_space_tag_t         sc_iot;
@@ -128,11 +116,7 @@ struct imxiomuxc_softc {
 struct imxiomuxc_softc *imxiomuxc_sc;
 
 void imxiomuxc_attach(struct device *parent, struct device *self, void *args);
-void imxiomuxc_enable_sata(void);
-void imxiomuxc_enable_i2c(int);
-void imxiomuxc_enable_pcie(void);
-void imxiomuxc_pcie_refclk(int);
-void imxiomuxc_pcie_test_powerdown(int);
+int imxiomuxc_pinctrl(uint32_t);
 
 struct cfattach imxiomuxc_ca = {
        sizeof (struct imxiomuxc_softc), NULL, imxiomuxc_attach
@@ -157,6 +141,123 @@ imxiomuxc_attach(struct device *parent, struct device *self, void *args)
        imxiomuxc_sc = sc;
 }
 
+int
+imxiomuxc_pinctrlbyid(int node, int id)
+{
+       char pinctrl[32];
+       uint32_t *phandles;
+       int len, i;
+
+       snprintf(pinctrl, sizeof(pinctrl), "pinctrl-%d", id);
+       len = OF_getproplen(node, pinctrl);
+       if (len <= 0)
+               return -1;
+
+       phandles = malloc(len, M_TEMP, M_WAITOK);
+       OF_getpropintarray(node, pinctrl, phandles, len);
+       for (i = 0; i < len / sizeof(uint32_t); i++)
+               imxiomuxc_pinctrl(phandles[i]);
+       free(phandles, M_TEMP, len);
+       return 0;
+}
+
+int
+imxiomuxc_pinctrlbyname(int node, const char *config)
+{
+       char *names;
+       char *name;
+       char *end;
+       int id = 0;
+       int len;
+
+       len = OF_getproplen(node, "pinctrl-names");
+       if (len <= 0)
+               printf("no pinctrl-names\n");
+
+       names = malloc(len, M_TEMP, M_WAITOK);
+       OF_getprop(node, "pinctrl-names", names, len);
+       end = names + len;
+       name = names;
+       while (name < end) {
+               if (strcmp(name, config) == 0) {
+                       free(names, M_TEMP, len);
+                       return imxiomuxc_pinctrlbyid(node, id);
+               }
+               name += strlen(name) + 1;
+               id++;
+       }
+       free(names, M_TEMP, len);
+       return -1;
+}
+
+int
+imxiomuxc_pinctrl(uint32_t phandle)
+{
+       struct imxiomuxc_softc *sc = imxiomuxc_sc;
+       uint32_t *pins;
+       int npins;
+       int node;
+       int len;
+       int i;
+
+       node = OF_getnodebyphandle(phandle);
+       if (node == 0)
+               return -1;
+
+       len = OF_getproplen(node, "fsl,pins");
+       if (len <= 0)
+               return -1;
+
+       pins = malloc(len, M_TEMP, M_WAITOK);
+       OF_getpropintarray(node, "fsl,pins", pins, len);
+       npins = len / (6 * sizeof(uint32_t));
+
+       for (i = 0; i < npins; i++) {
+               uint32_t mux_reg = pins[6 * i + 0];
+               uint32_t conf_reg = pins[6 * i + 1];
+               uint32_t input_reg = pins[6 * i + 2];
+               uint32_t mux_val = pins[6 * i + 3];
+               uint32_t conf_val = pins[6 * i + 5];
+               uint32_t input_val = pins[6 * i + 4];
+               uint32_t val;
+
+               /* Set MUX mode. */
+               if (conf_val & IMX_PINCTRL_SION)
+                       mux_val |= IOMUX_CONFIG_SION;
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh, mux_reg, mux_val);
+
+               /* Set PAD config. */
+               if ((conf_val & IMX_PINCTRL_NO_PAD_CTL) == 0)
+                       bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+                           conf_reg, conf_val);
+
+               /* Set input select. */
+               if ((input_val >> 24) == 0xff) {
+                       /*
+                        * Magic value used to clear or set specific
+                        * bits in the general purpose registers.
+                        */
+                       uint8_t shift = (input_val >> 16) & 0xff;
+                       uint8_t width = (input_val >> 8) & 0xff;
+                       uint32_t clr = ((1 << width) - 1) << shift;
+                       uint32_t set = (input_val & 0xff) << shift;
+
+                       val = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+                           input_reg);
+                       val &= ~clr;
+                       val |= set;
+                       bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+                           input_reg, val);
+               } else if (input_reg != 0) {
+                       bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+                           input_reg, input_val);
+               }
+       }
+
+       free(pins, M_TEMP, len);
+       return 0;
+}
+
 void
 imxiomuxc_enable_sata(void)
 {
@@ -220,43 +321,3 @@ imxiomuxc_pcie_test_powerdown(int enable)
                bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_GPR1,
                    bus_space_read_4(sc->sc_iot, sc->sc_ioh, IOMUXC_GPR1) | IOMUXC_GPR1_TEST_POWERDOWN);
 }
-
-void
-imxiomuxc_enable_i2c(int x)
-{
-       struct imxiomuxc_softc *sc = imxiomuxc_sc;
-
-       /* let's just use EIM for those */
-       switch (x) {
-               case 0:
-                       /* scl in select */
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_MUX_CTL_PAD_EIM_DATA21, IOMUX_CONFIG_SION | 6);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_I2C1_SCL_IN_SELECT_INPUT, 0);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_PAD_CTL_PAD_EIM_DATA21, IOMUXC_IMX6Q_I2C_PAD_CTRL);
-                       /* sda in select */
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_MUX_CTL_PAD_EIM_DATA28, IOMUX_CONFIG_SION | 1);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_I2C1_SDA_IN_SELECT_INPUT, 0);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_PAD_CTL_PAD_EIM_DATA28, IOMUXC_IMX6Q_I2C_PAD_CTRL);
-                       break;
-               case 1:
-                       /* scl in select */
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_MUX_CTL_PAD_EIM_EB2, IOMUX_CONFIG_SION | 6);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_I2C2_SCL_IN_SELECT_INPUT, 0);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_PAD_CTL_PAD_EIM_EB2, IOMUXC_IMX6Q_I2C_PAD_CTRL);
-                       /* sda in select */
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_MUX_CTL_PAD_EIM_DATA16, IOMUX_CONFIG_SION | 6);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_I2C2_SDA_IN_SELECT_INPUT, 0);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_PAD_CTL_PAD_EIM_DATA16, IOMUXC_IMX6Q_I2C_PAD_CTRL);
-                       break;
-               case 2:
-                       /* scl in select */
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_MUX_CTL_PAD_EIM_DATA17, IOMUX_CONFIG_SION | 6);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_I2C3_SCL_IN_SELECT_INPUT, 0);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_PAD_CTL_PAD_EIM_DATA17, IOMUXC_IMX6Q_I2C_PAD_CTRL);
-                       /* sda in select */
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_MUX_CTL_PAD_EIM_DATA18, IOMUX_CONFIG_SION | 6);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_I2C3_SDA_IN_SELECT_INPUT, 0);
-                       bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOMUXC_PAD_CTL_PAD_EIM_DATA18, IOMUXC_IMX6Q_I2C_PAD_CTRL);
-                       break;
-       }
-}
index 682711e..ba12f0a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: imxiomuxcvar.h,v 1.1 2013/09/06 20:45:54 patrick Exp $ */
+/* $OpenBSD: imxiomuxcvar.h,v 1.2 2016/07/10 11:46:28 kettenis Exp $ */
 /*
  * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se>
  *
 #ifndef IMXIOMUXCVAR_H
 #define IMXIOMUXCVAR_H
 
+int imxiomuxc_pinctrlbyid(int node, int id);
+int imxiomuxc_pinctrlbyname(int node, const char *);
+
 void imxiomuxc_enable_sata(void);
-void imxiomuxc_enable_i2c(int);
 void imxiomuxc_enable_pcie(void);
 void imxiomuxc_pcie_refclk(int);
 void imxiomuxc_pcie_test_powerdown(int);
index 9f13590..be43d47 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: imxuart.c,v 1.6 2016/06/11 14:26:18 jsg Exp $ */
+/* $OpenBSD: imxuart.c,v 1.7 2016/07/10 11:46:28 kettenis Exp $ */
 /*
  * Copyright (c) 2005 Dale Rahn <drahn@motorola.com>
  *
@@ -44,6 +44,7 @@
 #include <armv7/armv7/armv7var.h>
 #include <armv7/armv7/armv7_machdep.h>
 #include <armv7/imx/imxccmvar.h>
+#include <armv7/imx/imxiomuxcvar.h>
 
 #include <dev/ofw/fdt.h>
 #include <dev/ofw/openfirm.h>
@@ -165,6 +166,8 @@ imxuart_attach(struct device *parent, struct device *self, void *aux)
        if (faa->fa_nreg < 2 || faa->fa_nintr < 3)
                return;
 
+       imxiomuxc_pinctrlbyname(faa->fa_node, "default");
+
        sc->sc_irq = arm_intr_establish(faa->fa_intr[1], IPL_TTY,
            imxuart_intr, sc, sc->sc_dev.dv_xname);