diff options
author | Michal Meloun <mmel@FreeBSD.org> | 2020-04-25 09:17:49 +0000 |
---|---|---|
committer | Michal Meloun <mmel@FreeBSD.org> | 2020-04-25 09:17:49 +0000 |
commit | a3fc40936ab57a63f212ea2f1376752dc87b82fa (patch) | |
tree | 4a14bc4ad6f13fb7d2a5e1cf8e3679c669c771ac /sys/arm64 | |
parent | 983066f05bacda3e18aae456e56feb00f70c0b55 (diff) | |
download | src-a3fc40936ab57a63f212ea2f1376752dc87b82fa.tar.gz src-a3fc40936ab57a63f212ea2f1376752dc87b82fa.zip |
Reorder initialization steps for given pin.
If pin is switched from fixed function to GPIO, it should have prepared
direction, pull-up/down and default value before function gets switched.
Otherwise we may produce unwanted glitch on output pin.
Right order of drive strength settings is questionable, but I think that
is slightly safer to do it also before function switch.
This fixes serial port corruption observed after DT 5.6 import.
MFC after: 1 week
Notes
Notes:
svn path=/head/; revision=360293
Diffstat (limited to 'sys/arm64')
-rw-r--r-- | sys/arm64/rockchip/rk_pinctrl.c | 45 |
1 files changed, 22 insertions, 23 deletions
diff --git a/sys/arm64/rockchip/rk_pinctrl.c b/sys/arm64/rockchip/rk_pinctrl.c index 143f8592c8af..a3707b0d28cc 100644 --- a/sys/arm64/rockchip/rk_pinctrl.c +++ b/sys/arm64/rockchip/rk_pinctrl.c @@ -932,7 +932,28 @@ rk_pinctrl_configure_pin(struct rk_pinctrl_softc *sc, uint32_t *pindata) /* Find syscon */ syscon = sc->conf->get_syscon(sc, bank); - /* Parse pin function */ + /* Setup GPIO properties first */ + rv = rk_pinctrl_handle_io(sc, pin_conf, bank, pin); + + /* Then pin pull-up/down */ + bias = sc->conf->parse_bias(pin_conf, bank); + if (bias >= 0) { + reg = sc->conf->get_pd_offset(sc, bank); + reg += bank * 0x10 + ((pin / 8) * 0x4); + bit = (pin % 8) * 2; + mask = (0x3 << bit); + SYSCON_MODIFY_4(syscon, reg, mask, bias << bit | (mask << 16)); + } + + /* Then drive strength */ + rv = rk_pinctrl_parse_drive(sc, pin_conf, bank, subbank, &drive, ®); + if (rv == 0) { + bit = (pin % 8) * 2; + mask = (0x3 << bit); + SYSCON_MODIFY_4(syscon, reg, mask, drive << bit | (mask << 16)); + } + + /* Finally set the pin function */ reg = sc->conf->iomux_conf[i].offset; switch (sc->conf->iomux_conf[i].nbits) { case 4: @@ -966,28 +987,6 @@ rk_pinctrl_configure_pin(struct rk_pinctrl_softc *sc, uint32_t *pindata) * without hi-word write mask. */ SYSCON_MODIFY_4(syscon, reg, mask, function << bit | (mask << 16)); - - /* Pull-Up/Down */ - bias = sc->conf->parse_bias(pin_conf, bank); - if (bias >= 0) { - reg = sc->conf->get_pd_offset(sc, bank); - - reg += bank * 0x10 + ((pin / 8) * 0x4); - bit = (pin % 8) * 2; - mask = (0x3 << bit); - SYSCON_MODIFY_4(syscon, reg, mask, bias << bit | (mask << 16)); - } - - /* Drive Strength */ - rv = rk_pinctrl_parse_drive(sc, pin_conf, bank, subbank, &drive, ®); - if (rv == 0) { - bit = (pin % 8) * 2; - mask = (0x3 << bit); - SYSCON_MODIFY_4(syscon, reg, mask, drive << bit | (mask << 16)); - } - - /* Input/Outpot + default level */ - rv = rk_pinctrl_handle_io(sc, pin_conf, bank, pin); } static int |