-/* $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>
*
#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 {
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
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;
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);
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];
}
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];
}
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];
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);
+}