Implement support for the GPIOs on the JH7110. Makes it possible to reboot
authorkettenis <kettenis@openbsd.org>
Wed, 5 Jul 2023 11:07:36 +0000 (11:07 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 5 Jul 2023 11:07:36 +0000 (11:07 +0000)
the VisionFive 2 from OpenBSD.

ok jsing@

sys/arch/riscv64/dev/stfclock.c
sys/arch/riscv64/dev/stfpinctrl.c

index 5b47454..6edce16 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: stfclock.c,v 1.5 2023/07/04 10:34:03 kettenis Exp $   */
+/*     $OpenBSD: stfclock.c,v 1.6 2023/07/05 11:07:36 kettenis Exp $   */
 /*
  * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
  * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
 #define JH7110_SYSCLK_GMAC0_GTXCLK     108
 #define JH7110_SYSCLK_GMAC0_PTP                109
 #define JH7110_SYSCLK_GMAC0_GTXC       111
+#define JH7110_SYSCLK_IOMUX_APB                112
 #define JH7110_SYSCLK_TEMP_APB         129
 #define JH7110_SYSCLK_TEMP_CORE                130
 #define JH7110_SYSCLK_UART0_CORE       146
@@ -764,6 +765,7 @@ stfclock_enable_jh7110_sys(void *cookie, uint32_t *cells, int on)
        case JH7110_SYSCLK_GMAC0_GTXCLK:
        case JH7110_SYSCLK_GMAC0_PTP:
        case JH7110_SYSCLK_GMAC0_GTXC:
+       case JH7110_SYSCLK_IOMUX_APB:
        case JH7110_SYSCLK_TEMP_APB:
        case JH7110_SYSCLK_TEMP_CORE:
        case JH7110_SYSCLK_UART0_CORE:
index ae26777..c89cce4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: stfpinctrl.c,v 1.2 2022/09/04 06:49:11 jsg Exp $      */
+/*     $OpenBSD: stfpinctrl.c,v 1.3 2023/07/05 11:07:37 kettenis Exp $ */
 /*
  * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -26,6 +26,7 @@
 #include <machine/fdt.h>
 
 #include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
 #include <dev/ofw/ofw_gpio.h>
 #include <dev/ofw/fdt.h>
 
 #define PAD_FUNC_SHARE(pin)            (0x0080 + (((pin) / 2) * 4))
 #define IO_PADSHARE_SEL                        0x01a0
 
+#define JH7110_DOEN(pin)               (0x0000 + (((pin) / 4) * 4))
+#define  JH7110_DOEN_SHIFT(pin)                (((pin) % 4) * 8)
+#define  JH7110_DOEN_MASK              0x3f
+#define  JH7110_DOEN_ENABLE            0
+#define  JH7110_DOEN_DISABLE           1
+#define JH7110_DOUT(pin)               (0x0040 + (((pin) / 4) * 4))
+#define  JH7110_DOUT_SHIFT(pin)                (((pin) % 4) * 8)
+#define  JH7110_DOUT_MASK              0x7f
+#define JH7110_GPIOIN(pin)             (0x0118 + (((pin) / 32) * 4))
+#define JH7110_PADCFG(pin)             (0x0120 + ((pin) * 4))
+#define  JH7110_PADCFG_IE              (1 << 0)
+#define  JH7110_PADCFG_PU              (1 << 3)
+#define  JH7110_PADCFG_PD              (1 << 4)
+#define  JH7110_PADCFG_SMT             (1 << 6)
+
 #define GPIO_NUM_PINS          64
 
 struct stfpinctrl_softc {
@@ -68,16 +84,21 @@ struct cfdriver stfpinctrl_cd = {
        NULL, "stfpinctrl", DV_DULL
 };
 
-void   stfpinctrl_config_pin(void *, uint32_t *, int);
-int    stfpinctrl_get_pin(void *, uint32_t *);
-void   stfpinctrl_set_pin(void *, uint32_t *, int);
+void   stfpinctrl_jh7100_config_pin(void *, uint32_t *, int);
+int    stfpinctrl_jh7100_get_pin(void *, uint32_t *);
+void   stfpinctrl_jh7100_set_pin(void *, uint32_t *, int);
+
+void   stfpinctrl_jh7110_config_pin(void *, uint32_t *, int);
+int    stfpinctrl_jh7110_get_pin(void *, uint32_t *);
+void   stfpinctrl_jh7110_set_pin(void *, uint32_t *, int);
 
 int
 stfpinctrl_match(struct device *parent, void *match, void *aux)
 {
        struct fdt_attach_args *faa = aux;
 
-       return OF_is_compatible(faa->fa_node, "starfive,jh7100-pinctrl");
+       return OF_is_compatible(faa->fa_node, "starfive,jh7100-pinctrl") ||
+           OF_is_compatible(faa->fa_node, "starfive,jh7110-sys-pinctrl");
 }
 
 void
@@ -92,6 +113,12 @@ stfpinctrl_attach(struct device *parent, struct device *self, void *aux)
                return;
        }
 
+       if (OF_is_compatible(faa->fa_node, "starfive,jh7100-pinctrl") &&
+           faa->fa_nreg < 2) {
+               printf(": no padctl registers\n");
+               return;
+       }
+
        sc->sc_node = faa->fa_node;
        sc->sc_iot = faa->fa_iot;
 
@@ -100,7 +127,9 @@ stfpinctrl_attach(struct device *parent, struct device *self, void *aux)
                printf(": can't map registers\n");
                return;
        }
-       if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr,
+
+       if (OF_is_compatible(faa->fa_node, "starfive,jh7100-pinctrl") &&
+           bus_space_map(sc->sc_iot, faa->fa_reg[1].addr,
            faa->fa_reg[1].size, 0, &sc->sc_padctl_ioh)) {
                bus_space_unmap(sc->sc_iot, sc->sc_gpio_ioh,
                    faa->fa_reg[0].size);
@@ -110,38 +139,52 @@ stfpinctrl_attach(struct device *parent, struct device *self, void *aux)
 
        printf("\n");
 
-       sel = bus_space_read_4(sc->sc_iot, sc->sc_padctl_ioh, IO_PADSHARE_SEL);
-       switch (sel) {
-       case 0:
-       default:
-               /* No GPIOs available. */
-               return;
-       case 1:
-               sc->sc_padctl_gpio = PAD_GPIO(0);
-               break;
-       case 2:
-               sc->sc_padctl_gpio = PAD_FUNC_SHARE(72);
-               break;
-       case 3:
-               sc->sc_padctl_gpio = PAD_FUNC_SHARE(70);
-               break;
-       case 4:
-       case 5:
-       case 6:
-               sc->sc_padctl_gpio = PAD_FUNC_SHARE(0);
-               break;
+       if (OF_is_compatible(faa->fa_node, "starfive,jh7100-pinctrl")) {
+               sel = bus_space_read_4(sc->sc_iot, sc->sc_padctl_ioh,
+                   IO_PADSHARE_SEL);
+               switch (sel) {
+               case 0:
+               default:
+                       /* No GPIOs available. */
+                       return;
+               case 1:
+                       sc->sc_padctl_gpio = PAD_GPIO(0);
+                       break;
+               case 2:
+                       sc->sc_padctl_gpio = PAD_FUNC_SHARE(72);
+                       break;
+               case 3:
+                       sc->sc_padctl_gpio = PAD_FUNC_SHARE(70);
+                       break;
+               case 4:
+               case 5:
+               case 6:
+                       sc->sc_padctl_gpio = PAD_FUNC_SHARE(0);
+                       break;
+               }
+       } else {
+               reset_deassert(faa->fa_node, NULL);
+               clock_enable(faa->fa_node, NULL);
        }
 
        sc->sc_gc.gc_node = faa->fa_node;
        sc->sc_gc.gc_cookie = sc;
-       sc->sc_gc.gc_config_pin = stfpinctrl_config_pin;
-       sc->sc_gc.gc_get_pin = stfpinctrl_get_pin;
-       sc->sc_gc.gc_set_pin = stfpinctrl_set_pin;
+       if (OF_is_compatible(faa->fa_node, "starfive,jh7100-pinctrl")) {
+               sc->sc_gc.gc_config_pin = stfpinctrl_jh7100_config_pin;
+               sc->sc_gc.gc_get_pin = stfpinctrl_jh7100_get_pin;
+               sc->sc_gc.gc_set_pin = stfpinctrl_jh7100_set_pin;
+       } else {
+               sc->sc_gc.gc_config_pin = stfpinctrl_jh7110_config_pin;
+               sc->sc_gc.gc_get_pin = stfpinctrl_jh7110_get_pin;
+               sc->sc_gc.gc_set_pin = stfpinctrl_jh7110_set_pin;
+       }
        gpio_controller_register(&sc->sc_gc);
 }
 
+/* JH7100 */
+
 void
-stfpinctrl_config_pin(void *cookie, uint32_t *cells, int config)
+stfpinctrl_jh7100_config_pin(void *cookie, uint32_t *cells, int config)
 {
        struct stfpinctrl_softc *sc = cookie;
        uint32_t pin = cells[0];
@@ -166,7 +209,7 @@ stfpinctrl_config_pin(void *cookie, uint32_t *cells, int config)
 }
 
 int
-stfpinctrl_get_pin(void *cookie, uint32_t *cells)
+stfpinctrl_jh7100_get_pin(void *cookie, uint32_t *cells)
 {
        struct stfpinctrl_softc *sc = cookie;
        uint32_t pin = cells[0];
@@ -185,7 +228,7 @@ stfpinctrl_get_pin(void *cookie, uint32_t *cells)
 }
 
 void
-stfpinctrl_set_pin(void *cookie, uint32_t *cells, int val)
+stfpinctrl_jh7100_set_pin(void *cookie, uint32_t *cells, int val)
 {
        struct stfpinctrl_softc *sc = cookie;
        uint32_t pin = cells[0];
@@ -199,3 +242,79 @@ stfpinctrl_set_pin(void *cookie, uint32_t *cells, int val)
        bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh,
            GPIO_DOUT_CFG(pin), val);
 }
+
+/* JH7110 */
+
+void
+stfpinctrl_jh7110_config_pin(void *cookie, uint32_t *cells, int config)
+{
+       struct stfpinctrl_softc *sc = cookie;
+       uint32_t pin = cells[0];
+       uint32_t doen, padcfg;
+
+       if (pin >= GPIO_NUM_PINS)
+               return;
+
+       doen = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, JH7110_DOEN(pin));
+       padcfg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh,
+           JH7110_PADCFG(pin));
+       doen &= ~(JH7110_DOEN_MASK << JH7110_DOEN_SHIFT(pin));
+       if (config & GPIO_CONFIG_OUTPUT) {
+               doen |= (JH7110_DOEN_ENABLE << JH7110_DOEN_SHIFT(pin));
+               bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh,
+                   JH7110_DOEN(pin), doen);
+               /* Disable input, Schmitt trigger and bias. */
+               padcfg &= ~(JH7110_PADCFG_IE | JH7110_PADCFG_SMT);
+               padcfg &= ~(JH7110_PADCFG_PU | JH7110_PADCFG_PD);
+               bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh,
+                   JH7110_PADCFG(pin), padcfg);
+       } else {
+               /* Enable input and Schmitt trigger. */
+               padcfg |= JH7110_PADCFG_IE | JH7110_PADCFG_SMT;
+               bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh,
+                   JH7110_PADCFG(pin), padcfg);
+               doen |= (JH7110_DOEN_DISABLE << JH7110_DOEN_SHIFT(pin));
+               bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh,
+                   JH7110_DOEN(pin), doen);
+       }
+}
+
+int
+stfpinctrl_jh7110_get_pin(void *cookie, uint32_t *cells)
+{
+       struct stfpinctrl_softc *sc = cookie;
+       uint32_t pin = cells[0];
+       uint32_t flags = cells[1];
+       uint32_t reg;
+       int val;
+
+       if (pin >= GPIO_NUM_PINS)
+               return 0;
+
+       reg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh,
+           JH7110_GPIOIN(pin));
+       val = (reg >> (pin % 32)) & 1;
+       if (flags & GPIO_ACTIVE_LOW)
+               val = !val;
+       return val;
+}
+
+void
+stfpinctrl_jh7110_set_pin(void *cookie, uint32_t *cells, int val)
+{
+       struct stfpinctrl_softc *sc = cookie;
+       uint32_t pin = cells[0];
+       uint32_t flags = cells[1];
+       uint32_t reg;
+
+       if (pin >= GPIO_NUM_PINS)
+               return;
+
+       if (flags & GPIO_ACTIVE_LOW)
+               val = !val;
+
+       reg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, JH7110_DOUT(pin));
+       reg &= ~(JH7110_DOUT_MASK << JH7110_DOUT_SHIFT(pin));
+       reg |= (val << JH7110_DOUT_SHIFT(pin));
+       bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh, JH7110_DOUT(pin), reg);
+}