svn commit: r358653 - in stable/12: share/man/man9 sys/arm/allwinner sys/arm/broadcom/bcm2835 sys/arm64/rockchip sys/dev/fdt

Emmanuel Vadot manu at FreeBSD.org
Wed Mar 4 21:53:56 UTC 2020


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;


More information about the svn-src-all mailing list