Author: manu
Date: Wed Mar  4 21:53:54 2020
New Revision: 358653
URL: https://svnweb.freebsd.org/changeset/base/358653

Log:
  MFC r348885, r351543, r356806-r356807
  
  r348885 by bz:
  A bit of code hygiene (no functional changes).
  
  Hide unused code under #ifdef notyet (in one case the only caller is under
  that same ifdef), or if it is arm (not arm64) specific code under the
  __arm__ ifdef to not yield -Wunused-function warnings during the arm64
  kernel compile.
  
  r351543 by mmel:
  Add support for RK3288 into existing RockChip drivers.
  This patch ensures only minimal level of compatibility necessary to boot
  on RK3288 based boards. GPIO and pinctrl interaction, missing in current
  implementation, will be improved by own patch in the near future.
  
  MFC with:     r351452
  
  r356806:
  fdt_pinctrl: Add new methods for gpios
  
  Most of the gpio controller cannot configure or get the configuration
  of the pin muxing as it's usually handled in the pinctrl driver.
  But they can know what is the pinmuxing driver either because they are
  child of it or via the gpio-range property.
  Add some new methods to fdt_pinctrl that a pin controller can implement.
  Some methods are :
  fdt_pinctrl_is_gpio: Use to know if the pin in the gpio mode
  fdt_pinctrl_set_flags: Set the flags of the pin (pullup/pulldown etc ...)
  fdt_pinctrl_get_flags: Get the flags of the pin (pullup/pulldown etc ...)
  
  The defaults method returns EOPNOTSUPP.
  
  Reviewed by:  ian, bcr (manpages)
  Differential Revision:        https://reviews.freebsd.org/D23093
  
  r356807:
  arm64: rockchip: Add new interface for rk_pinctrl
  
  The gpio controller in rockchips SoC in a child of the pinctrl driver
  and cannot control pullups and pulldowns.
  Use the new fdt_pinctrl interface for accessing pin capabilities and
  setting them.
  We can now report that every pins is capable of being IN or OUT function
  and PULLUP PULLDOWN.
  If the pin isn't in gpio mode no changes will be allowed.
  
  Reviewed by:  ganbold (previous version)
  Differential Revision:        https://reviews.freebsd.org/D22849

Modified:
  stable/12/share/man/man9/fdt_pinctrl.9
  stable/12/sys/arm/allwinner/a10_timer.c
  stable/12/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c
  stable/12/sys/arm64/rockchip/if_dwc_rk.c
  stable/12/sys/arm64/rockchip/rk_gpio.c
  stable/12/sys/arm64/rockchip/rk_grf.c
  stable/12/sys/arm64/rockchip/rk_pinctrl.c
  stable/12/sys/dev/fdt/fdt_pinctrl_if.m
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/share/man/man9/fdt_pinctrl.9
==============================================================================
--- stable/12/share/man/man9/fdt_pinctrl.9      Wed Mar  4 21:45:12 2020        
(r358652)
+++ stable/12/share/man/man9/fdt_pinctrl.9      Wed Mar  4 21:53:54 2020        
(r358653)
@@ -125,6 +125,36 @@ foo_configure_pins(device_t dev, phandle_t cfgxref)
 }
 
 static int
+foo_is_gpio(device_t dev, device_t gpiodev, bool *is_gpio)
+{
+       return (foo_is_pin_func_gpio(is_gpio));
+}
+
+static int
+foo_set_flags(device_t dev, device_t gpiodev, uint32_t pin, uint32_t flags)
+{
+       int rv;
+
+       rv = foo_is_pin_func_gpio(is_gpio);
+       if (rv != 0)
+               return (rv);
+       foo_set_flags(pin, flags);
+       return (0);
+}
+
+static int
+foo_get_flags(device_t dev, device_t gpiodev, uint32_t pin, uint32_t *flags)
+{
+       int rv;
+
+       rv = foo_is_pin_func_gpio(is_gpio);
+       if (rv != 0)
+               return (rv);
+       foo_get_flags(pin, flags);
+       return (0);
+}
+
+static int
 foo_attach(device_t dev)
 {
        ...
@@ -144,6 +174,9 @@ static device_method_t foo_methods[] = {
 
        /* fdt_pinctrl interface */
        DEVMETHOD(fdt_pinctrl_configure, foo_configure_pins),
+       DEVMETHOD(fdt_pinctrl_is_gpio, foo_is_gpio),
+       DEVMETHOD(fdt_pinctrl_set_flags, foo_set_flags),
+       DEVMETHOD(fdt_pinctrl_get_flags, foo_get_flags),
 
        /* Terminate method list */
        DEVMETHOD_END

Modified: stable/12/sys/arm/allwinner/a10_timer.c
==============================================================================
--- stable/12/sys/arm/allwinner/a10_timer.c     Wed Mar  4 21:45:12 2020        
(r358652)
+++ stable/12/sys/arm/allwinner/a10_timer.c     Wed Mar  4 21:53:54 2020        
(r358653)
@@ -108,12 +108,16 @@ struct a10_timer_softc {
        bus_write_4(sc->res[A10_TIMER_MEMRES], reg, val)
 
 static u_int   a10_timer_get_timecount(struct timecounter *);
+#if defined(__arm__)
 static int     a10_timer_timer_start(struct eventtimer *,
     sbintime_t first, sbintime_t period);
 static int     a10_timer_timer_stop(struct eventtimer *);
+#endif
 
 static uint64_t timer_read_counter64(struct a10_timer_softc *sc);
+#if defined(__arm__)
 static void a10_timer_eventtimer_setup(struct a10_timer_softc *sc);
+#endif
 
 static void a23_timer_timecounter_setup(struct a10_timer_softc *sc);
 static u_int a23_timer_get_timecount(struct timecounter *tc);
@@ -279,6 +283,7 @@ a10_timer_irq(void *arg)
  * Event timer function for A10 and A13
  */
 
+#if defined(__arm__)
 static void
 a10_timer_eventtimer_setup(struct a10_timer_softc *sc)
 {
@@ -363,6 +368,7 @@ a10_timer_timer_stop(struct eventtimer *et)
 
        return (0);
 }
+#endif
 
 /*
  * Timecounter functions for A23 and above

Modified: stable/12/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c
==============================================================================
--- stable/12/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c Wed Mar  4 21:45:12 
2020        (r358652)
+++ stable/12/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c Wed Mar  4 21:53:54 
2020        (r358653)
@@ -251,6 +251,7 @@ WR4(struct bcm_sdhost_softc *sc, bus_size_t off, uint3
        bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
 }
 
+#ifdef notyet
 static inline uint16_t
 RD2(struct bcm_sdhost_softc *sc, bus_size_t off)
 {
@@ -260,6 +261,7 @@ RD2(struct bcm_sdhost_softc *sc, bus_size_t off)
 
        return ((val >> (off & 3)*8) & 0xffff);
 }
+#endif
 
 static inline uint8_t
 RD1(struct bcm_sdhost_softc *sc, bus_size_t off)

Modified: stable/12/sys/arm64/rockchip/if_dwc_rk.c
==============================================================================
--- stable/12/sys/arm64/rockchip/if_dwc_rk.c    Wed Mar  4 21:45:12 2020        
(r358652)
+++ stable/12/sys/arm64/rockchip/if_dwc_rk.c    Wed Mar  4 21:53:54 2020        
(r358653)
@@ -65,6 +65,14 @@ __FBSDID("$FreeBSD$");
 #define        RK3328_GRF_MACPHY_CON3          0x0B0C
 #define        RK3328_GRF_MACPHY_STATUS        0x0B10
 
+static struct ofw_compat_data compat_data[] = {
+       {"rockchip,rk3288-gmac", 1},
+       {"rockchip,rk3328-gmac", 1},
+       {"rockchip,rk3399-gmac", 1},
+       {NULL,                   0}
+};
+
+#ifdef notyet
 static void
 rk3328_set_delays(struct syscon *grf, phandle_t node)
 {
@@ -82,6 +90,7 @@ rk3328_set_delays(struct syscon *grf, phandle_t node)
 
        SYSCON_WRITE_4(grf, RK3328_GRF_MAC_CON0, tx | rx | 0xFFFF0000);
 }
+#endif
 
 #define        RK3399_GRF_SOC_CON6             0xc218
 #define         RK3399_GRF_SOC_CON6_TX_MASK    0x7F
@@ -89,6 +98,7 @@ rk3328_set_delays(struct syscon *grf, phandle_t node)
 #define         RK3399_GRF_SOC_CON6_RX_MASK    0x7F
 #define         RK3399_GRF_SOC_CON6_RX_SHIFT   8
 
+#ifdef notyet
 static void
 rk3399_set_delays(struct syscon *grf, phandle_t node)
 {
@@ -106,6 +116,7 @@ rk3399_set_delays(struct syscon *grf, phandle_t node)
 
        SYSCON_WRITE_4(grf, RK3399_GRF_SOC_CON6, tx | rx | 0xFFFF0000);
 }
+#endif
 
 static int
 if_dwc_rk_probe(device_t dev)
@@ -113,8 +124,7 @@ if_dwc_rk_probe(device_t dev)
 
        if (!ofw_bus_status_okay(dev))
                return (ENXIO);
-       if (!(ofw_bus_is_compatible(dev, "rockchip,rk3328-gmac") ||
-             ofw_bus_is_compatible(dev, "rockchip,rk3399-gmac")))
+       if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
                return (ENXIO);
        device_set_desc(dev, "Rockchip Gigabit Ethernet Controller");
 

Modified: stable/12/sys/arm64/rockchip/rk_gpio.c
==============================================================================
--- stable/12/sys/arm64/rockchip/rk_gpio.c      Wed Mar  4 21:45:12 2020        
(r358652)
+++ stable/12/sys/arm64/rockchip/rk_gpio.c      Wed Mar  4 21:53:54 2020        
(r358653)
@@ -50,10 +50,10 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus_subr.h>
 #include <dev/extres/clk/clk.h>
 
-#include "opt_soc.h"
-
 #include "gpio_if.h"
 
+#include "fdt_pinctrl_if.h"
+
 #define        RK_GPIO_SWPORTA_DR      0x00    /* Data register */
 #define        RK_GPIO_SWPORTA_DDR     0x04    /* Data direction register */
 
@@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
 
 #define        RK_GPIO_LS_SYNC         0x60    /* Level sensitive 
syncronization enable register */
 
+#define        RK_GPIO_DEFAULT_CAPS    (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |     
\
+    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
+
 struct rk_gpio_softc {
        device_t                sc_dev;
        device_t                sc_busdev;
@@ -79,6 +82,7 @@ struct rk_gpio_softc {
        bus_space_tag_t         sc_bst;
        bus_space_handle_t      sc_bsh;
        clk_t                   clk;
+       device_t                pinctrl;
 };
 
 static struct ofw_compat_data compat_data[] = {
@@ -126,6 +130,7 @@ rk_gpio_attach(device_t dev)
 
        sc = device_get_softc(dev);
        sc->sc_dev = dev;
+       sc->pinctrl = device_get_parent(dev);
 
        node = ofw_bus_get_node(sc->sc_dev);
        if (!OF_hasprop(node, "gpio-controller"))
@@ -196,6 +201,7 @@ rk_gpio_pin_max(device_t dev, int *maxpin)
 {
 
        /* Each bank have always 32 pins */
+       /* XXX not true*/
        *maxpin = 31;
        return (0);
 }
@@ -222,17 +228,30 @@ rk_gpio_pin_getflags(device_t dev, uint32_t pin, uint3
 {
        struct rk_gpio_softc *sc;
        uint32_t reg;
+       int rv;
+       bool is_gpio;
 
        sc = device_get_softc(dev);
 
+       rv = FDT_PINCTRL_IS_GPIO(sc->pinctrl, dev, pin, &is_gpio);
+       if (rv != 0)
+               return (rv);
+       if (!is_gpio)
+               return (EINVAL);
+
+       *flags = 0;
+       rv = FDT_PINCTRL_GET_FLAGS(sc->pinctrl, dev, pin, flags);
+       if (rv != 0)
+               return (rv);
+
        RK_GPIO_LOCK(sc);
        reg = RK_GPIO_READ(sc, RK_GPIO_SWPORTA_DDR);
        RK_GPIO_UNLOCK(sc);
 
        if (reg & (1 << pin))
-               *flags = GPIO_PIN_OUTPUT;
+               *flags |= GPIO_PIN_OUTPUT;
        else
-               *flags = GPIO_PIN_INPUT;
+               *flags |= GPIO_PIN_INPUT;
 
        return (0);
 }
@@ -241,8 +260,7 @@ static int
 rk_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 {
 
-       /* Caps are managed by the pinctrl device */
-       *caps = 0;
+       *caps = RK_GPIO_DEFAULT_CAPS;
        return (0);
 }
 
@@ -251,9 +269,21 @@ rk_gpio_pin_setflags(device_t dev, uint32_t pin, uint3
 {
        struct rk_gpio_softc *sc;
        uint32_t reg;
+       int rv;
+       bool is_gpio;
 
        sc = device_get_softc(dev);
 
+       rv = FDT_PINCTRL_IS_GPIO(sc->pinctrl, dev, pin, &is_gpio);
+       if (rv != 0)
+               return (rv);
+       if (!is_gpio)
+               return (EINVAL);
+
+       rv = FDT_PINCTRL_SET_FLAGS(sc->pinctrl, dev, pin, flags);
+       if (rv != 0)
+               return (rv);
+
        RK_GPIO_LOCK(sc);
 
        reg = RK_GPIO_READ(sc, RK_GPIO_SWPORTA_DDR);
@@ -394,6 +424,14 @@ rk_gpio_map_gpios(device_t bus, phandle_t dev, phandle
        return (0);
 }
 
+static phandle_t
+rk_gpio_get_node(device_t bus, device_t dev)
+{
+
+       /* We only have one child, the GPIO bus, which needs our own node. */
+       return (ofw_bus_get_node(bus));
+}
+
 static device_method_t rk_gpio_methods[] = {
        /* Device interface */
        DEVMETHOD(device_probe,         rk_gpio_probe),
@@ -414,6 +452,9 @@ static device_method_t rk_gpio_methods[] = {
        DEVMETHOD(gpio_pin_config_32,   rk_gpio_pin_config_32),
        DEVMETHOD(gpio_map_gpios,       rk_gpio_map_gpios),
 
+       /* ofw_bus interface */
+       DEVMETHOD(ofw_bus_get_node,     rk_gpio_get_node),
+
        DEVMETHOD_END
 };
 
@@ -425,5 +466,10 @@ static driver_t rk_gpio_driver = {
 
 static devclass_t rk_gpio_devclass;
 
+/*
+ * GPIO driver is always a child of rk_pinctrl driver and should be probed
+ * and attached within rk_pinctrl_attach function. Due to this, bus pass order
+ * must be same as bus pass order of rk_pinctrl driver.
+ */
 EARLY_DRIVER_MODULE(rk_gpio, simplebus, rk_gpio_driver,
-    rk_gpio_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
+    rk_gpio_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);

Modified: stable/12/sys/arm64/rockchip/rk_grf.c
==============================================================================
--- stable/12/sys/arm64/rockchip/rk_grf.c       Wed Mar  4 21:45:12 2020        
(r358652)
+++ stable/12/sys/arm64/rockchip/rk_grf.c       Wed Mar  4 21:53:54 2020        
(r358653)
@@ -44,16 +44,11 @@ __FBSDID("$FreeBSD$");
 #include <dev/extres/syscon/syscon.h>
 #include <dev/fdt/simple_mfd.h>
 
-#include "opt_soc.h"
-
 static struct ofw_compat_data compat_data[] = {
-#ifdef SOC_ROCKCHIP_RK3328
+       {"rockchip,rk3288-grf", 1},
        {"rockchip,rk3328-grf", 1},
-#endif
-#ifdef SOC_ROCKCHIP_RK3399
        {"rockchip,rk3399-grf", 1},
        {"rockchip,rk3399-pmugrf", 1},
-#endif
        {NULL,             0}
 };
 

Modified: stable/12/sys/arm64/rockchip/rk_pinctrl.c
==============================================================================
--- stable/12/sys/arm64/rockchip/rk_pinctrl.c   Wed Mar  4 21:45:12 2020        
(r358652)
+++ stable/12/sys/arm64/rockchip/rk_pinctrl.c   Wed Mar  4 21:53:54 2020        
(r358653)
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
 
 #include "gpio_if.h"
 #include "syscon_if.h"
+#include "fdt_pinctrl_if.h"
 
 struct rk_pinctrl_pin_drive {
        uint32_t        bank;
@@ -102,6 +103,8 @@ struct rk_pinctrl_conf {
        uint32_t        (*get_pd_offset)(struct rk_pinctrl_softc *, uint32_t);
        struct syscon   *(*get_syscon)(struct rk_pinctrl_softc *, uint32_t);
        int             (*parse_bias)(phandle_t, int);
+       int             (*resolv_bias_value)(int, int);
+       int             (*get_bias_value)(int, int);
 };
 
 struct rk_pinctrl_softc {
@@ -110,8 +113,13 @@ struct rk_pinctrl_softc {
        struct syscon           *grf;
        struct syscon           *pmu;
        struct rk_pinctrl_conf  *conf;
+       struct mtx              mtx;
 };
 
+#define        RK_PINCTRL_LOCK(_sc)            mtx_lock_spin(&(_sc)->mtx)
+#define        RK_PINCTRL_UNLOCK(_sc)          mtx_unlock_spin(&(_sc)->mtx)
+#define        RK_PINCTRL_LOCK_ASSERT(_sc)     mtx_assert(&(_sc)->mtx, 
MA_OWNED)
+
 #define        RK_IOMUX(_bank, _subbank, _offset, _nbits)                      
\
 {                                                                      \
        .bank = _bank,                                                  \
@@ -385,6 +393,32 @@ rk3288_parse_bias(phandle_t node, int bank)
        return (-1);
 }
 
+static int
+rk3288_resolv_bias_value(int bank, int bias)
+{
+       int rv = 0;
+
+       if (bias == 1)
+               rv = GPIO_PIN_PULLUP;
+       else if (bias == 2)
+               rv = GPIO_PIN_PULLDOWN;
+
+       return (rv);
+}
+
+static int
+rk3288_get_bias_value(int bank, int bias)
+{
+       int rv = 0;
+
+       if (bias & GPIO_PIN_PULLUP)
+               rv = 1;
+       else if (bias & GPIO_PIN_PULLDOWN)
+               rv = 2;
+
+       return (rv);
+}
+
 struct rk_pinctrl_conf rk3288_conf = {
        .iomux_conf = rk3288_iomux_bank,
        .iomux_nbanks = nitems(rk3288_iomux_bank),
@@ -397,6 +431,8 @@ struct rk_pinctrl_conf rk3288_conf = {
        .get_pd_offset = rk3288_get_pd_offset,
        .get_syscon = rk3288_get_syscon,
        .parse_bias = rk3288_parse_bias,
+       .resolv_bias_value = rk3288_resolv_bias_value,
+       .get_bias_value = rk3288_get_bias_value,
 };
 
 static struct rk_pinctrl_gpio rk3328_gpio_bank[] = {
@@ -541,6 +577,8 @@ struct rk_pinctrl_conf rk3328_conf = {
        .get_pd_offset = rk3328_get_pd_offset,
        .get_syscon = rk3328_get_syscon,
        .parse_bias = rk3288_parse_bias,
+       .resolv_bias_value = rk3288_resolv_bias_value,
+       .get_bias_value = rk3288_get_bias_value,
 };
 
 static struct rk_pinctrl_gpio rk3399_gpio_bank[] = {
@@ -664,6 +702,58 @@ rk3399_parse_bias(phandle_t node, int bank)
        return (-1);
 }
 
+static int
+rk3399_resolv_bias_value(int bank, int bias)
+{
+       int rv = 0;
+
+       switch (bank) {
+       case 0:
+       case 2:
+               if (bias == 3)
+                       rv = GPIO_PIN_PULLUP;
+               else if (bias == 1)
+                       rv = GPIO_PIN_PULLDOWN;
+               break;
+       case 1:
+       case 3:
+       case 4:
+               if (bias == 1)
+                       rv = GPIO_PIN_PULLUP;
+               else if (bias == 2)
+                       rv = GPIO_PIN_PULLDOWN;
+               break;
+       }
+
+       return (rv);
+}
+
+static int
+rk3399_get_bias_value(int bank, int bias)
+{
+       int rv = 0;
+
+       switch (bank) {
+       case 0:
+       case 2:
+               if (bias & GPIO_PIN_PULLUP)
+                       rv = 3;
+               else if (bias & GPIO_PIN_PULLDOWN)
+                       rv = 1;
+               break;
+       case 1:
+       case 3:
+       case 4:
+               if (bias & GPIO_PIN_PULLUP)
+                       rv = 1;
+               else if (bias & GPIO_PIN_PULLDOWN)
+                       rv = 2;
+               break;
+       }
+
+       return (rv);
+}
+
 struct rk_pinctrl_conf rk3399_conf = {
        .iomux_conf = rk3399_iomux_bank,
        .iomux_nbanks = nitems(rk3399_iomux_bank),
@@ -676,6 +766,8 @@ struct rk_pinctrl_conf rk3399_conf = {
        .get_pd_offset = rk3399_get_pd_offset,
        .get_syscon = rk3399_get_syscon,
        .parse_bias = rk3399_parse_bias,
+       .resolv_bias_value = rk3399_resolv_bias_value,
+       .get_bias_value = rk3399_get_bias_value,
 };
 
 static struct ofw_compat_data compat_data[] = {
@@ -921,8 +1013,189 @@ rk_pinctrl_configure_pins(device_t dev, phandle_t cfgx
        return (0);
 }
 
+static int
+rk_pinctrl_is_gpio_locked(struct rk_pinctrl_softc *sc, struct syscon *syscon,
+  int bank, uint32_t pin, bool *is_gpio)
+{
+       uint32_t subbank, bit, mask, reg;
+       uint32_t pinfunc;
+       int i;
 
+       RK_PINCTRL_LOCK_ASSERT(sc);
+
+       subbank = pin / 8;
+       *is_gpio = false;
+
+       for (i = 0; i < sc->conf->iomux_nbanks; i++)
+               if (sc->conf->iomux_conf[i].bank == bank &&
+                   sc->conf->iomux_conf[i].subbank == subbank)
+                       break;
+
+       if (i == sc->conf->iomux_nbanks) {
+               device_printf(sc->dev, "Unknown pin %d in bank %d\n", pin,
+                   bank);
+               return (EINVAL);
+       }
+
+       syscon = sc->conf->get_syscon(sc, bank);
+
+       /* Parse pin function */
+       reg = sc->conf->iomux_conf[i].offset;
+       switch (sc->conf->iomux_conf[i].nbits) {
+       case 4:
+               if ((pin % 8) >= 4)
+                       reg += 0x4;
+               bit = (pin % 4) * 4;
+               mask = (0xF << bit);
+               break;
+       case 3:
+               if ((pin % 8) >= 5)
+                       reg += 4;
+               bit = (pin % 8 % 5) * 3;
+               mask = (0x7 << bit);
+               break;
+       case 2:
+               bit = (pin % 8) * 2;
+               mask = (0x3 << bit);
+               break;
+       default:
+               device_printf(sc->dev,
+                   "Unknown pin stride width %d in bank %d\n",
+                   sc->conf->iomux_conf[i].nbits, bank);
+               return (EINVAL);
+       }
+       rk_pinctrl_get_fixup(sc, bank, pin, &reg, &mask, &bit);
+
+       reg = SYSCON_READ_4(syscon, reg);
+       pinfunc = (reg & mask) >> bit;
+
+       /* Test if the pin is in gpio mode */
+       if (pinfunc == 0)
+               *is_gpio = true;
+
+       return (0);
+}
+
 static int
+rk_pinctrl_get_bank(struct rk_pinctrl_softc *sc, device_t gpio, int *bank)
+{
+       int i;
+
+       for (i = 0; i < sc->conf->ngpio_bank; i++) {
+               if (sc->conf->gpio_bank[i].gpio_dev == gpio)
+                       break;
+       }
+       if (i == sc->conf->ngpio_bank)
+               return (EINVAL);
+
+       *bank = i;
+       return (0);
+}
+
+static int
+rk_pinctrl_is_gpio(device_t pinctrl, device_t gpio, uint32_t pin, bool 
*is_gpio)
+{
+       struct rk_pinctrl_softc *sc;
+       struct syscon *syscon;
+       int bank;
+       int rv;
+
+       sc = device_get_softc(pinctrl);
+       RK_PINCTRL_LOCK(sc);
+
+       rv = rk_pinctrl_get_bank(sc, gpio, &bank);
+       if (rv != 0)
+               goto done;
+       syscon = sc->conf->get_syscon(sc, bank);
+       rv = rk_pinctrl_is_gpio_locked(sc, syscon, bank, pin, is_gpio);
+
+done:
+       RK_PINCTRL_UNLOCK(sc);
+
+       return (rv);
+}
+
+static int
+rk_pinctrl_get_flags(device_t pinctrl, device_t gpio, uint32_t pin,
+    uint32_t *flags)
+{
+       struct rk_pinctrl_softc *sc;
+       struct syscon *syscon;
+       uint32_t reg, mask, bit;
+       uint32_t bias;
+       int bank;
+       int rv = 0;
+       bool is_gpio;
+
+       sc = device_get_softc(pinctrl);
+       RK_PINCTRL_LOCK(sc);
+
+       rv = rk_pinctrl_get_bank(sc, gpio, &bank);
+       if (rv != 0)
+               goto done;
+       syscon = sc->conf->get_syscon(sc, bank);
+       rv = rk_pinctrl_is_gpio_locked(sc, syscon, bank, pin, &is_gpio);
+       if (rv != 0)
+               goto done;
+       if (!is_gpio) {
+               rv = EINVAL;
+               goto done;
+       }
+       /* Get the pullup/pulldown configuration */
+       reg = sc->conf->get_pd_offset(sc, bank);
+       reg += bank * 0x10 + ((pin / 8) * 0x4);
+       bit = (pin % 8) * 2;
+       mask = (0x3 << bit) << 16;
+       reg = SYSCON_READ_4(syscon, reg);
+       reg = (reg >> bit) & 0x3;
+       bias = sc->conf->resolv_bias_value(bank, reg);
+       *flags = bias;
+
+done:
+       RK_PINCTRL_UNLOCK(sc);
+       return (rv);
+}
+
+static int
+rk_pinctrl_set_flags(device_t pinctrl, device_t gpio, uint32_t pin,
+    uint32_t flags)
+{
+       struct rk_pinctrl_softc *sc;
+       struct syscon *syscon;
+       uint32_t bit, mask, reg;
+       uint32_t bias;
+       int bank;
+       int rv = 0;
+       bool is_gpio;
+
+       sc = device_get_softc(pinctrl);
+       RK_PINCTRL_LOCK(sc);
+
+       rv = rk_pinctrl_get_bank(sc, gpio, &bank);
+       if (rv != 0)
+               goto done;
+       syscon = sc->conf->get_syscon(sc, bank);
+       rv = rk_pinctrl_is_gpio_locked(sc, syscon, bank, pin, &is_gpio);
+       if (rv != 0)
+               goto done;
+       if (!is_gpio) {
+               rv = EINVAL;
+               goto done;
+       }
+       /* Get the pullup/pulldown configuration */
+       reg = sc->conf->get_pd_offset(sc, bank);
+       reg += bank * 0x10 + ((pin / 8) * 0x4);
+       bit = (pin % 8) * 2;
+       mask = (0x3 << bit);
+       bias = sc->conf->get_bias_value(bank, flags);
+       SYSCON_MODIFY_4(syscon, reg, mask, bias << bit | (mask << 16));
+
+done:
+       RK_PINCTRL_UNLOCK(sc);
+       return (rv);
+}
+
+static int
 rk_pinctrl_register_gpio(struct rk_pinctrl_softc *sc, char *gpio_name,
     device_t gpio_dev)
 {
@@ -983,6 +1256,8 @@ rk_pinctrl_attach(device_t dev)
                }
        }
 
+       mtx_init(&sc->mtx, "rk pinctrl", "pinctrl", MTX_SPIN);
+
        sc->conf = (struct rk_pinctrl_conf *)ofw_bus_search_compatible(dev,
            compat_data)->ocd_data;
 
@@ -1060,6 +1335,9 @@ static device_method_t rk_pinctrl_methods[] = {
 
         /* fdt_pinctrl interface */
        DEVMETHOD(fdt_pinctrl_configure,        rk_pinctrl_configure_pins),
+       DEVMETHOD(fdt_pinctrl_is_gpio,          rk_pinctrl_is_gpio),
+       DEVMETHOD(fdt_pinctrl_get_flags,        rk_pinctrl_get_flags),
+       DEVMETHOD(fdt_pinctrl_set_flags,        rk_pinctrl_set_flags),
 
        DEVMETHOD_END
 };

Modified: stable/12/sys/dev/fdt/fdt_pinctrl_if.m
==============================================================================
--- stable/12/sys/dev/fdt/fdt_pinctrl_if.m      Wed Mar  4 21:45:12 2020        
(r358652)
+++ stable/12/sys/dev/fdt/fdt_pinctrl_if.m      Wed Mar  4 21:53:54 2020        
(r358653)
@@ -36,6 +36,31 @@
 
 INTERFACE fdt_pinctrl;
 
+CODE {
+       static int
+       fdt_pinctrl_default_is_gpio(device_t pinctrl, device_t gpio, bool 
*is_gpio)
+       {
+
+               return (EOPNOTSUPP);
+       }
+
+       static int
+       fdt_pinctrl_default_set_flags(device_t pinctrl, device_t gpio, uint32_t 
pin,
+           uint32_t flags)
+       {
+
+               return (EOPNOTSUPP);
+       }
+
+       static int
+       fdt_pinctrl_default_get_flags(device_t pinctrl, device_t gpio, uint32_t 
pin,
+           uint32_t *flags)
+       {
+
+               return (EOPNOTSUPP);
+       }
+};
+
 # Needed for timestamping device probe/attach calls
 HEADER {
        #include <sys/tslog.h>
@@ -57,3 +82,36 @@ METHOD int configure {
        phandle_t       cfgxref;
 };
 
+
+#
+# Test if the pin is in gpio mode
+# Called from a gpio device
+#
+METHOD int is_gpio {
+       device_t pinctrl;
+       device_t gpio;
+       uint32_t pin;
+       bool *is_gpio;
+} DEFAULT fdt_pinctrl_default_is_gpio;
+
+#
+# Set the flags of a pin
+# Called from a gpio device
+#
+METHOD int set_flags {
+       device_t pinctrl;
+       device_t gpio;
+       uint32_t pin;
+       uint32_t flags;
+} DEFAULT fdt_pinctrl_default_set_flags;
+
+#
+# Get the flags of a pin
+# Called from a gpio device
+#
+METHOD int get_flags {
+       device_t pinctrl;
+       device_t gpio;
+       uint32_t pin;
+       uint32_t *flags;
+} DEFAULT fdt_pinctrl_default_get_flags;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to