From owner-svn-src-stable-12@freebsd.org Thu Jun 18 23:21:14 2020 Return-Path: Delivered-To: svn-src-stable-12@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 205323378BB; Thu, 18 Jun 2020 23:21:14 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49nycB0NHTz4DvQ; Thu, 18 Jun 2020 23:21:14 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 07EE9119C3; Thu, 18 Jun 2020 23:21:14 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 05INLEdw047225; Thu, 18 Jun 2020 23:21:14 GMT (envelope-from manu@FreeBSD.org) Received: (from manu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 05INLCCw047219; Thu, 18 Jun 2020 23:21:12 GMT (envelope-from manu@FreeBSD.org) Message-Id: <202006182321.05INLCCw047219@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: manu set sender to manu@FreeBSD.org using -f From: Emmanuel Vadot Date: Thu, 18 Jun 2020 23:21:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r362350 - in stable/12/sys: arm/allwinner dev/iicbus/twsi dts/arm64/overlays modules/dtb/allwinner X-SVN-Group: stable-12 X-SVN-Commit-Author: manu X-SVN-Commit-Paths: in stable/12/sys: arm/allwinner dev/iicbus/twsi dts/arm64/overlays modules/dtb/allwinner X-SVN-Commit-Revision: 362350 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-12@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for only the 12-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Jun 2020 23:21:14 -0000 Author: manu Date: Thu Jun 18 23:21:12 2020 New Revision: 362350 URL: https://svnweb.freebsd.org/changeset/base/362350 Log: MFC r356276, r356609-r356610, r356637, r356798-r356800, r356802 r356276: arm: allwinner: aw_spi: Call bus_generic_attach This is needed when the driver is compiled into the kernel. When compiled as a module this will be called from another code path as we also depend on ofw_spibus. r356609: twsi: Rework how we handle the i2c messages We use to handle each message separately in i2c_transfer but that cannot work with message with NOSTOP as it confuses the controller that we disable the interrupts and start a new message. Handle every message in the interrupt handler and fire a new start condition if the previous message have NOSTOP, the controller understand this as a repeated start. This fixes booting on Allwinner A10/A20 platform where before the i2c controller used to write 0 to the PMIC register that control the regulators as it though that this was the continuation of the write message. Tested on: A20 BananaPi, Cubieboard 1 (kevans) Reported by: kevans r356610: arm: allwinner: axp209: Add regnode_status method This allow consumers to check if the regulator is enable or not. r356637: arm64: allwinner: dtso: Add spi0 spigen DTSO This overlays can be used on A64 board to use spigen and spi(8) on the spi0 pins. Tested On: Pine64-LTS, A64-Olinuxino Submitted by: Gary Otten r356798: axp8xx: Add missing voltage regulators offset This lead to writing the desired voltage value to the wrong register. r356799: axp8xx: Add a regnode_init method This method will set the desired voltaged based on values in the DTS. It will not enable the regulator, this is the job of either a consumer or regnode_set_constraint SYSINIT if the regulator is boot_on or always_on. r356800: arm: allwinner: Add support for bank supply Each GPIO bank is powered by a different pin and so can be powered at different voltage from different regulators. Add a new config that now hold the pinmux data and the banks available on each SoCs. Since the aw_gpio driver being also the pinmux one it's attached before the PMIC so add a config_intrhook_oneshot function that will enable the needed regulators when the system is fully functional. r356802: arm: allwinner: ahci: target-supply is optional The target-supply regulator is optional so don't fail if it's not present. While here disable the clock on detach. X-MFC-With: 356600 Added: stable/12/sys/dts/arm64/overlays/sun50i-a64-spi0-spigen.dtso - copied unchanged from r356637, head/sys/dts/arm64/overlays/sun50i-a64-spi0-spigen.dtso Modified: stable/12/sys/arm/allwinner/a10_ahci.c stable/12/sys/arm/allwinner/aw_gpio.c stable/12/sys/arm/allwinner/aw_spi.c stable/12/sys/arm/allwinner/axp209.c stable/12/sys/arm/allwinner/axp81x.c stable/12/sys/dev/iicbus/twsi/twsi.c stable/12/sys/dev/iicbus/twsi/twsi.h stable/12/sys/modules/dtb/allwinner/Makefile Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/arm/allwinner/a10_ahci.c ============================================================================== --- stable/12/sys/arm/allwinner/a10_ahci.c Thu Jun 18 23:18:47 2020 (r362349) +++ stable/12/sys/arm/allwinner/a10_ahci.c Thu Jun 18 23:21:12 2020 (r362350) @@ -123,6 +123,8 @@ __FBSDID("$FreeBSD$"); struct ahci_a10_softc { struct ahci_controller ahci_ctlr; regulator_t ahci_reg; + clk_t clk_pll; + clk_t clk_gate; }; static void inline @@ -304,11 +306,9 @@ ahci_a10_attach(device_t dev) int error; struct ahci_a10_softc *sc; struct ahci_controller *ctlr; - clk_t clk_pll, clk_gate; sc = device_get_softc(dev); ctlr = &sc->ahci_ctlr; - clk_pll = clk_gate = NULL; ctlr->quirks = AHCI_Q_NOPMP; ctlr->vendorid = 0; @@ -320,41 +320,38 @@ ahci_a10_attach(device_t dev) &ctlr->r_rid, RF_ACTIVE))) return (ENXIO); - /* Enable the regulator */ - error = regulator_get_by_ofw_property(dev, 0, "target-supply", - &sc->ahci_reg); - if (error != 0) { - device_printf(dev, "Cannot get regulator\n"); - goto fail; + /* Enable the (optional) regulator */ + if (regulator_get_by_ofw_property(dev, 0, "target-supply", + &sc->ahci_reg) == 0) { + error = regulator_enable(sc->ahci_reg); + if (error != 0) { + device_printf(dev, "Could not enable regulator\n"); + goto fail; + } } - error = regulator_enable(sc->ahci_reg); - if (error != 0) { - device_printf(dev, "Could not enable regulator\n"); - goto fail; - } /* Enable clocks */ - error = clk_get_by_ofw_index(dev, 0, 0, &clk_gate); + error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_gate); if (error != 0) { device_printf(dev, "Cannot get gate clock\n"); goto fail; } - error = clk_get_by_ofw_index(dev, 0, 1, &clk_pll); + error = clk_get_by_ofw_index(dev, 0, 1, &sc->clk_pll); if (error != 0) { device_printf(dev, "Cannot get PLL clock\n"); goto fail; } - error = clk_set_freq(clk_pll, PLL_FREQ, CLK_SET_ROUND_DOWN); + error = clk_set_freq(sc->clk_pll, PLL_FREQ, CLK_SET_ROUND_DOWN); if (error != 0) { device_printf(dev, "Cannot set PLL frequency\n"); goto fail; } - error = clk_enable(clk_pll); + error = clk_enable(sc->clk_pll); if (error != 0) { device_printf(dev, "Cannot enable PLL\n"); goto fail; } - error = clk_enable(clk_gate); + error = clk_enable(sc->clk_gate); if (error != 0) { device_printf(dev, "Cannot enable clk gate\n"); goto fail; @@ -379,12 +376,12 @@ ahci_a10_attach(device_t dev) return (ahci_attach(dev)); fail: - if (sc->ahci_reg != 0) + if (sc->ahci_reg != NULL) regulator_disable(sc->ahci_reg); - if (clk_gate != NULL) - clk_release(clk_gate); - if (clk_pll != NULL) - clk_release(clk_pll); + if (sc->clk_gate != NULL) + clk_release(sc->clk_gate); + if (sc->clk_pll != NULL) + clk_release(sc->clk_pll); bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); return (error); } @@ -392,7 +389,19 @@ fail: static int ahci_a10_detach(device_t dev) { + struct ahci_a10_softc *sc; + struct ahci_controller *ctlr; + sc = device_get_softc(dev); + ctlr = &sc->ahci_ctlr; + + if (sc->ahci_reg != NULL) + regulator_disable(sc->ahci_reg); + if (sc->clk_gate != NULL) + clk_release(sc->clk_gate); + if (sc->clk_pll != NULL) + clk_release(sc->clk_pll); + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); return (ahci_detach(dev)); } Modified: stable/12/sys/arm/allwinner/aw_gpio.c ============================================================================== --- stable/12/sys/arm/allwinner/aw_gpio.c Thu Jun 18 23:18:47 2020 (r362349) +++ stable/12/sys/arm/allwinner/aw_gpio.c Thu Jun 18 23:21:12 2020 (r362350) @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #if defined(__aarch64__) #include "opt_soc.h" @@ -78,102 +79,167 @@ __FBSDID("$FreeBSD$"); #define AW_PINCTRL 1 #define AW_R_PINCTRL 2 +struct aw_gpio_conf { + struct allwinner_padconf *padconf; + const char *banks; +}; + /* Defined in aw_padconf.c */ #ifdef SOC_ALLWINNER_A10 -extern const struct allwinner_padconf a10_padconf; +extern struct allwinner_padconf a10_padconf; +struct aw_gpio_conf a10_gpio_conf = { + .padconf = &a10_padconf, + .banks = "abcdefghi", +}; #endif /* Defined in a13_padconf.c */ #ifdef SOC_ALLWINNER_A13 -extern const struct allwinner_padconf a13_padconf; +extern struct allwinner_padconf a13_padconf; +struct aw_gpio_conf a13_gpio_conf = { + .padconf = &a13_padconf, + .banks = "bcdefg", +}; #endif /* Defined in a20_padconf.c */ #ifdef SOC_ALLWINNER_A20 -extern const struct allwinner_padconf a20_padconf; +extern struct allwinner_padconf a20_padconf; +struct aw_gpio_conf a20_gpio_conf = { + .padconf = &a20_padconf, + .banks = "abcdefghi", +}; #endif /* Defined in a31_padconf.c */ #ifdef SOC_ALLWINNER_A31 -extern const struct allwinner_padconf a31_padconf; +extern struct allwinner_padconf a31_padconf; +struct aw_gpio_conf a31_gpio_conf = { + .padconf = &a31_padconf, + .banks = "abcdefgh", +}; #endif /* Defined in a31s_padconf.c */ #ifdef SOC_ALLWINNER_A31S -extern const struct allwinner_padconf a31s_padconf; +extern struct allwinner_padconf a31s_padconf; +struct aw_gpio_conf a31s_gpio_conf = { + .padconf = &a31s_padconf, + .banks = "abcdefgh", +}; #endif #if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S) -extern const struct allwinner_padconf a31_r_padconf; +extern struct allwinner_padconf a31_r_padconf; +struct aw_gpio_conf a31_r_gpio_conf = { + .padconf = &a31_r_padconf, + .banks = "lm", +}; #endif /* Defined in a33_padconf.c */ #ifdef SOC_ALLWINNER_A33 -extern const struct allwinner_padconf a33_padconf; +extern struct allwinner_padconf a33_padconf; +struct aw_gpio_conf a33_gpio_conf = { + .padconf = &a33_padconf, + .banks = "bcdefgh", +}; #endif /* Defined in h3_padconf.c */ #if defined(SOC_ALLWINNER_H3) || defined(SOC_ALLWINNER_H5) -extern const struct allwinner_padconf h3_padconf; -extern const struct allwinner_padconf h3_r_padconf; +extern struct allwinner_padconf h3_padconf; +extern struct allwinner_padconf h3_r_padconf; +struct aw_gpio_conf h3_gpio_conf = { + .padconf = &h3_padconf, + .banks = "acdefg", +}; +struct aw_gpio_conf h3_r_gpio_conf = { + .padconf = &h3_r_padconf, + .banks = "l", +}; #endif /* Defined in a83t_padconf.c */ #ifdef SOC_ALLWINNER_A83T -extern const struct allwinner_padconf a83t_padconf; -extern const struct allwinner_padconf a83t_r_padconf; +extern struct allwinner_padconf a83t_padconf; +extern struct allwinner_padconf a83t_r_padconf; +struct aw_gpio_conf a83t_gpio_conf = { + .padconf = &a83t_padconf, + .banks = "bcdefgh" +}; +struct aw_gpio_conf a83t_r_gpio_conf = { + .padconf = &a83t_r_padconf, + .banks = "l", +}; #endif /* Defined in a64_padconf.c */ #ifdef SOC_ALLWINNER_A64 -extern const struct allwinner_padconf a64_padconf; -extern const struct allwinner_padconf a64_r_padconf; +extern struct allwinner_padconf a64_padconf; +extern struct allwinner_padconf a64_r_padconf; +struct aw_gpio_conf a64_gpio_conf = { + .padconf = &a64_padconf, + .banks = "bcdefgh", +}; +struct aw_gpio_conf a64_r_gpio_conf = { + .padconf = &a64_r_padconf, + .banks = "l", +}; #endif /* Defined in h6_padconf.c */ #ifdef SOC_ALLWINNER_H6 -extern const struct allwinner_padconf h6_padconf; -extern const struct allwinner_padconf h6_r_padconf; +extern struct allwinner_padconf h6_padconf; +extern struct allwinner_padconf h6_r_padconf; +struct aw_gpio_conf h6_gpio_conf = { + .padconf = &h6_padconf, + .banks = "cdfgh", +}; +struct aw_gpio_conf h6_r_gpio_conf = { + .padconf = &h6_r_padconf, + .banks = "lm", +}; #endif static struct ofw_compat_data compat_data[] = { #ifdef SOC_ALLWINNER_A10 - {"allwinner,sun4i-a10-pinctrl", (uintptr_t)&a10_padconf}, + {"allwinner,sun4i-a10-pinctrl", (uintptr_t)&a10_gpio_conf}, #endif #ifdef SOC_ALLWINNER_A13 - {"allwinner,sun5i-a13-pinctrl", (uintptr_t)&a13_padconf}, + {"allwinner,sun5i-a13-pinctrl", (uintptr_t)&a13_gpio_conf}, #endif #ifdef SOC_ALLWINNER_A20 - {"allwinner,sun7i-a20-pinctrl", (uintptr_t)&a20_padconf}, + {"allwinner,sun7i-a20-pinctrl", (uintptr_t)&a20_gpio_conf}, #endif #ifdef SOC_ALLWINNER_A31 - {"allwinner,sun6i-a31-pinctrl", (uintptr_t)&a31_padconf}, + {"allwinner,sun6i-a31-pinctrl", (uintptr_t)&a31_gpio_conf}, #endif #ifdef SOC_ALLWINNER_A31S - {"allwinner,sun6i-a31s-pinctrl", (uintptr_t)&a31s_padconf}, + {"allwinner,sun6i-a31s-pinctrl", (uintptr_t)&a31s_gpio_conf}, #endif #if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S) - {"allwinner,sun6i-a31-r-pinctrl", (uintptr_t)&a31_r_padconf}, + {"allwinner,sun6i-a31-r-pinctrl", (uintptr_t)&a31_r_gpio_conf}, #endif #ifdef SOC_ALLWINNER_A33 - {"allwinner,sun6i-a33-pinctrl", (uintptr_t)&a33_padconf}, + {"allwinner,sun6i-a33-pinctrl", (uintptr_t)&a33_gpio_conf}, #endif #ifdef SOC_ALLWINNER_A83T - {"allwinner,sun8i-a83t-pinctrl", (uintptr_t)&a83t_padconf}, - {"allwinner,sun8i-a83t-r-pinctrl", (uintptr_t)&a83t_r_padconf}, + {"allwinner,sun8i-a83t-pinctrl", (uintptr_t)&a83t_gpio_conf}, + {"allwinner,sun8i-a83t-r-pinctrl", (uintptr_t)&a83t_r_gpio_conf}, #endif #if defined(SOC_ALLWINNER_H3) || defined(SOC_ALLWINNER_H5) - {"allwinner,sun8i-h3-pinctrl", (uintptr_t)&h3_padconf}, - {"allwinner,sun50i-h5-pinctrl", (uintptr_t)&h3_padconf}, - {"allwinner,sun8i-h3-r-pinctrl", (uintptr_t)&h3_r_padconf}, + {"allwinner,sun8i-h3-pinctrl", (uintptr_t)&h3_gpio_conf}, + {"allwinner,sun50i-h5-pinctrl", (uintptr_t)&h3_gpio_conf}, + {"allwinner,sun8i-h3-r-pinctrl", (uintptr_t)&h3_r_gpio_conf}, #endif #ifdef SOC_ALLWINNER_A64 - {"allwinner,sun50i-a64-pinctrl", (uintptr_t)&a64_padconf}, - {"allwinner,sun50i-a64-r-pinctrl", (uintptr_t)&a64_r_padconf}, + {"allwinner,sun50i-a64-pinctrl", (uintptr_t)&a64_gpio_conf}, + {"allwinner,sun50i-a64-r-pinctrl", (uintptr_t)&a64_r_gpio_conf}, #endif #ifdef SOC_ALLWINNER_H6 - {"allwinner,sun50i-h6-pinctrl", (uintptr_t)&h6_padconf}, - {"allwinner,sun50i-h6-r-pinctrl", (uintptr_t)&h6_r_padconf}, + {"allwinner,sun50i-h6-pinctrl", (uintptr_t)&h6_gpio_conf}, + {"allwinner,sun50i-h6-r-pinctrl", (uintptr_t)&h6_r_gpio_conf}, #endif {NULL, 0} }; @@ -192,7 +258,7 @@ struct aw_gpio_softc { bus_space_tag_t sc_bst; bus_space_handle_t sc_bsh; void * sc_intrhand; - const struct allwinner_padconf * padconf; + struct aw_gpio_conf *conf; TAILQ_HEAD(, clk_list) clk_list; }; @@ -237,10 +303,10 @@ aw_gpio_get_function(struct aw_gpio_softc *sc, uint32_ /* Must be called with lock held. */ AW_GPIO_LOCK_ASSERT(sc); - if (pin > sc->padconf->npins) + if (pin > sc->conf->padconf->npins) return (0); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; offset = ((pin & 0x07) << 2); func = AW_GPIO_READ(sc, AW_GPIO_GP_CFG(bank, pin >> 3)); @@ -254,14 +320,14 @@ aw_gpio_set_function(struct aw_gpio_softc *sc, uint32_ uint32_t bank, data, offset; /* Check if the function exists in the padconf data */ - if (sc->padconf->pins[pin].functions[f] == NULL) + if (sc->conf->padconf->pins[pin].functions[f] == NULL) return (EINVAL); /* Must be called with lock held. */ AW_GPIO_LOCK_ASSERT(sc); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; offset = ((pin & 0x07) << 2); data = AW_GPIO_READ(sc, AW_GPIO_GP_CFG(bank, pin >> 3)); @@ -280,8 +346,8 @@ aw_gpio_get_pud(struct aw_gpio_softc *sc, uint32_t pin /* Must be called with lock held. */ AW_GPIO_LOCK_ASSERT(sc); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; offset = ((pin & 0x0f) << 1); val = AW_GPIO_READ(sc, AW_GPIO_GP_PUL(bank, pin >> 4)); @@ -300,8 +366,8 @@ aw_gpio_set_pud(struct aw_gpio_softc *sc, uint32_t pin /* Must be called with lock held. */ AW_GPIO_LOCK_ASSERT(sc); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; offset = ((pin & 0x0f) << 1); val = AW_GPIO_READ(sc, AW_GPIO_GP_PUL(bank, pin >> 4)); @@ -318,8 +384,8 @@ aw_gpio_get_drv(struct aw_gpio_softc *sc, uint32_t pin /* Must be called with lock held. */ AW_GPIO_LOCK_ASSERT(sc); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; offset = ((pin & 0x0f) << 1); val = AW_GPIO_READ(sc, AW_GPIO_GP_DRV(bank, pin >> 4)); @@ -338,8 +404,8 @@ aw_gpio_set_drv(struct aw_gpio_softc *sc, uint32_t pin /* Must be called with lock held. */ AW_GPIO_LOCK_ASSERT(sc); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; offset = ((pin & 0x0f) << 1); val = AW_GPIO_READ(sc, AW_GPIO_GP_DRV(bank, pin >> 4)); @@ -357,7 +423,7 @@ aw_gpio_pin_configure(struct aw_gpio_softc *sc, uint32 /* Must be called with lock held. */ AW_GPIO_LOCK_ASSERT(sc); - if (pin > sc->padconf->npins) + if (pin > sc->conf->padconf->npins) return (EINVAL); /* Manage input/output. */ @@ -412,7 +478,7 @@ aw_gpio_pin_max(device_t dev, int *maxpin) sc = device_get_softc(dev); - *maxpin = sc->padconf->npins - 1; + *maxpin = sc->conf->padconf->npins - 1; return (0); } @@ -422,7 +488,7 @@ aw_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32 struct aw_gpio_softc *sc; sc = device_get_softc(dev); - if (pin >= sc->padconf->npins) + if (pin >= sc->conf->padconf->npins) return (EINVAL); *caps = AW_GPIO_DEFAULT_CAPS; @@ -438,7 +504,7 @@ aw_gpio_pin_getflags(device_t dev, uint32_t pin, uint3 uint32_t pud; sc = device_get_softc(dev); - if (pin >= sc->padconf->npins) + if (pin >= sc->conf->padconf->npins) return (EINVAL); AW_GPIO_LOCK(sc); @@ -478,11 +544,11 @@ aw_gpio_pin_getname(device_t dev, uint32_t pin, char * struct aw_gpio_softc *sc; sc = device_get_softc(dev); - if (pin >= sc->padconf->npins) + if (pin >= sc->conf->padconf->npins) return (EINVAL); snprintf(name, GPIOMAXNAME - 1, "%s", - sc->padconf->pins[pin].name); + sc->conf->padconf->pins[pin].name); name[GPIOMAXNAME - 1] = '\0'; return (0); @@ -495,7 +561,7 @@ aw_gpio_pin_setflags(device_t dev, uint32_t pin, uint3 int err; sc = device_get_softc(dev); - if (pin > sc->padconf->npins) + if (pin > sc->conf->padconf->npins) return (EINVAL); AW_GPIO_LOCK(sc); @@ -513,11 +579,11 @@ aw_gpio_pin_set_locked(struct aw_gpio_softc *sc, uint3 AW_GPIO_LOCK_ASSERT(sc); - if (pin > sc->padconf->npins) + if (pin > sc->conf->padconf->npins) return (EINVAL); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; data = AW_GPIO_READ(sc, AW_GPIO_GP_DAT(bank)); if (value) @@ -552,11 +618,11 @@ aw_gpio_pin_get_locked(struct aw_gpio_softc *sc,uint32 AW_GPIO_LOCK_ASSERT(sc); - if (pin > sc->padconf->npins) + if (pin > sc->conf->padconf->npins) return (EINVAL); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; reg_data = AW_GPIO_READ(sc, AW_GPIO_GP_DAT(bank)); *val = (reg_data & (1 << pin)) ? 1 : 0; @@ -655,11 +721,11 @@ aw_gpio_pin_toggle(device_t dev, uint32_t pin) uint32_t bank, data; sc = device_get_softc(dev); - if (pin > sc->padconf->npins) + if (pin > sc->conf->padconf->npins) return (EINVAL); - bank = sc->padconf->pins[pin].port; - pin = sc->padconf->pins[pin].pin; + bank = sc->conf->padconf->pins[pin].port; + pin = sc->conf->padconf->pins[pin].pin; AW_GPIO_LOCK(sc); data = AW_GPIO_READ(sc, AW_GPIO_GP_DAT(bank)); @@ -681,7 +747,7 @@ aw_gpio_pin_access_32(device_t dev, uint32_t first_pin uint32_t bank, data, pin; sc = device_get_softc(dev); - if (first_pin > sc->padconf->npins) + if (first_pin > sc->conf->padconf->npins) return (EINVAL); /* @@ -690,8 +756,8 @@ aw_gpio_pin_access_32(device_t dev, uint32_t first_pin * change simultaneously (required) with reasonably high performance * (desired); we need to do a read-modify-write on a single register. */ - bank = sc->padconf->pins[first_pin].port; - pin = sc->padconf->pins[first_pin].pin; + bank = sc->conf->padconf->pins[first_pin].port; + pin = sc->conf->padconf->pins[first_pin].pin; if (pin != 0) return (EINVAL); @@ -717,11 +783,11 @@ aw_gpio_pin_config_32(device_t dev, uint32_t first_pin int err; sc = device_get_softc(dev); - if (first_pin > sc->padconf->npins) + if (first_pin > sc->conf->padconf->npins) return (EINVAL); - bank = sc->padconf->pins[first_pin].port; - if (sc->padconf->pins[first_pin].pin != 0) + bank = sc->conf->padconf->pins[first_pin].port; + if (sc->conf->padconf->pins[first_pin].pin != 0) return (EINVAL); /* @@ -745,8 +811,8 @@ aw_find_pinnum_by_name(struct aw_gpio_softc *sc, const { int i; - for (i = 0; i < sc->padconf->npins; i++) - if (!strcmp(pinname, sc->padconf->pins[i].name)) + for (i = 0; i < sc->conf->padconf->npins; i++) + if (!strcmp(pinname, sc->conf->padconf->pins[i].name)) return i; return (-1); @@ -758,8 +824,8 @@ aw_find_pin_func(struct aw_gpio_softc *sc, int pin, co int i; for (i = 0; i < AW_MAX_FUNC_BY_PIN; i++) - if (sc->padconf->pins[pin].functions[i] && - !strcmp(func, sc->padconf->pins[pin].functions[i])) + if (sc->conf->padconf->pins[pin].functions[i] && + !strcmp(func, sc->conf->padconf->pins[pin].functions[i])) return (i); return (-1); @@ -828,6 +894,33 @@ aw_fdt_configure_pins(device_t dev, phandle_t cfgxref) return (ret); } +static void +aw_gpio_enable_bank_supply(void *arg) +{ + struct aw_gpio_softc *sc = arg; + regulator_t vcc_supply; + char bank_reg_name[16]; + int i, nbanks; + + nbanks = strlen(sc->conf->banks); + for (i = 0; i < nbanks; i++) { + snprintf(bank_reg_name, sizeof(bank_reg_name), "vcc-p%c-supply", + sc->conf->banks[i]); + + if (regulator_get_by_ofw_property(sc->sc_dev, 0, bank_reg_name, &vcc_supply) == 0) { + if (bootverbose) + device_printf(sc->sc_dev, + "Enabling regulator for gpio bank %c\n", + sc->conf->banks[i]); + if (regulator_enable(vcc_supply) != 0) { + device_printf(sc->sc_dev, + "Cannot enable regulator for bank %c\n", + sc->conf->banks[i]); + } + } + } +} + static int aw_gpio_probe(device_t dev) { @@ -884,7 +977,7 @@ aw_gpio_attach(device_t dev) goto fail; /* Use the right pin data for the current SoC */ - sc->padconf = (struct allwinner_padconf *)ofw_bus_search_compatible(dev, + sc->conf = (struct aw_gpio_conf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data; if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst) == 0) { @@ -928,6 +1021,8 @@ aw_gpio_attach(device_t dev) fdt_pinctrl_register(dev, "allwinner,pins"); fdt_pinctrl_configure_tree(dev); + config_intrhook_oneshot(aw_gpio_enable_bank_supply, sc); + return (0); fail: @@ -985,9 +1080,9 @@ aw_gpio_map_gpios(device_t bus, phandle_t dev, phandle sc = device_get_softc(bus); /* The GPIO pins are mapped as: . */ - for (i = 0; i < sc->padconf->npins; i++) - if (sc->padconf->pins[i].port == gpios[0] && - sc->padconf->pins[i].pin == gpios[1]) { + for (i = 0; i < sc->conf->padconf->npins; i++) + if (sc->conf->padconf->pins[i].port == gpios[0] && + sc->conf->padconf->pins[i].pin == gpios[1]) { *pin = i; break; } Modified: stable/12/sys/arm/allwinner/aw_spi.c ============================================================================== --- stable/12/sys/arm/allwinner/aw_spi.c Thu Jun 18 23:18:47 2020 (r362349) +++ stable/12/sys/arm/allwinner/aw_spi.c Thu Jun 18 23:21:12 2020 (r362350) @@ -240,7 +240,7 @@ aw_spi_attach(device_t dev) sc->spibus = device_add_child(dev, "spibus", -1); - return (0); + return (bus_generic_attach(dev)); fail: aw_spi_detach(dev); Modified: stable/12/sys/arm/allwinner/axp209.c ============================================================================== --- stable/12/sys/arm/allwinner/axp209.c Thu Jun 18 23:18:47 2020 (r362349) +++ stable/12/sys/arm/allwinner/axp209.c Thu Jun 18 23:21:12 2020 (r362350) @@ -709,6 +709,22 @@ axp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc } static int +axp2xx_regnode_status(struct regnode *regnode, int *status) +{ + struct axp2xx_reg_sc *sc; + uint8_t val; + + sc = regnode_get_softc(regnode); + + *status = 0; + axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1); + if (val & sc->def->enable_mask) + *status = REGULATOR_STATUS_ENABLED; + + return (0); +} + +static int axp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt, int *udelay) { @@ -751,6 +767,7 @@ static regnode_method_t axp2xx_regnode_methods[] = { /* Regulator interface */ REGNODEMETHOD(regnode_init, axp2xx_regnode_init), REGNODEMETHOD(regnode_enable, axp2xx_regnode_enable), + REGNODEMETHOD(regnode_status, axp2xx_regnode_status), REGNODEMETHOD(regnode_set_voltage, axp2xx_regnode_set_voltage), REGNODEMETHOD(regnode_get_voltage, axp2xx_regnode_get_voltage), REGNODEMETHOD(regnode_check_voltage, regnode_method_check_voltage), Modified: stable/12/sys/arm/allwinner/axp81x.c ============================================================================== --- stable/12/sys/arm/allwinner/axp81x.c Thu Jun 18 23:18:47 2020 (r362349) +++ stable/12/sys/arm/allwinner/axp81x.c Thu Jun 18 23:21:12 2020 (r362350) @@ -438,6 +438,7 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = .enable_reg = AXP_POWERCTL3, .enable_mask = (uint8_t) AXP_POWERCTL3_ALDO1, .enable_value = AXP_POWERCTL3_ALDO1, + .voltage_reg = AXP_VOLTCTL_ALDO1, .voltage_min = 700, .voltage_max = 3300, .voltage_step1 = 100, @@ -449,6 +450,7 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = .enable_reg = AXP_POWERCTL3, .enable_mask = (uint8_t) AXP_POWERCTL3_ALDO2, .enable_value = AXP_POWERCTL3_ALDO2, + .voltage_reg = AXP_VOLTCTL_ALDO2, .voltage_min = 700, .voltage_max = 3300, .voltage_step1 = 100, @@ -460,6 +462,7 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = .enable_reg = AXP_POWERCTL3, .enable_mask = (uint8_t) AXP_POWERCTL3_ALDO3, .enable_value = AXP_POWERCTL3_ALDO3, + .voltage_reg = AXP_VOLTCTL_ALDO3, .voltage_min = 700, .voltage_max = 3300, .voltage_step1 = 100, @@ -471,6 +474,7 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = .enable_reg = AXP_POWERCTL2, .enable_mask = (uint8_t) AXP_POWERCTL2_ELDO1, .enable_value = AXP_POWERCTL2_ELDO1, + .voltage_reg = AXP_VOLTCTL_ELDO1, .voltage_min = 700, .voltage_max = 1900, .voltage_step1 = 50, @@ -482,6 +486,7 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = .enable_reg = AXP_POWERCTL2, .enable_mask = (uint8_t) AXP_POWERCTL2_ELDO2, .enable_value = AXP_POWERCTL2_ELDO2, + .voltage_reg = AXP_VOLTCTL_ELDO2, .voltage_min = 700, .voltage_max = 1900, .voltage_step1 = 50, @@ -493,6 +498,7 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = .enable_reg = AXP_POWERCTL2, .enable_mask = (uint8_t) AXP_POWERCTL2_ELDO3, .enable_value = AXP_POWERCTL2_ELDO3, + .voltage_reg = AXP_VOLTCTL_ELDO3, .voltage_min = 700, .voltage_max = 1900, .voltage_step1 = 50, @@ -504,6 +510,7 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = .enable_reg = AXP_POWERCTL3, .enable_mask = (uint8_t) AXP_POWERCTL3_FLDO1, .enable_value = AXP_POWERCTL3_FLDO1, + .voltage_reg = AXP_VOLTCTL_FLDO1, .voltage_min = 700, .voltage_max = 1450, .voltage_step1 = 50, @@ -515,6 +522,7 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = .enable_reg = AXP_POWERCTL3, .enable_mask = (uint8_t) AXP_POWERCTL3_FLDO2, .enable_value = AXP_POWERCTL3_FLDO2, + .voltage_reg = AXP_VOLTCTL_FLDO2, .voltage_min = 700, .voltage_max = 1450, .voltage_step1 = 50, @@ -703,6 +711,8 @@ struct axp8xx_softc { #define AXP_LOCK(sc) mtx_lock(&(sc)->mtx) #define AXP_UNLOCK(sc) mtx_unlock(&(sc)->mtx) +static int axp8xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt, + int max_uvolt, int *udelay); static int axp8xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size) @@ -747,6 +757,31 @@ axp8xx_write(device_t dev, uint8_t reg, uint8_t val) } static int +axp8xx_regnode_init(struct regnode *regnode) +{ + struct axp8xx_reg_sc *sc; + struct regnode_std_param *param; + int rv, udelay; + + sc = regnode_get_softc(regnode); + param = regnode_get_stdparam(regnode); + if (param->min_uvolt == 0) + return (0); + + /* + * Set the regulator at the correct voltage + * Do not enable it, this is will be done either by a + * consumer or by regnode_set_constraint if boot_on is true + */ + rv = axp8xx_regnode_set_voltage(regnode, param->min_uvolt, + param->max_uvolt, &udelay); + if (rv != 0) + DELAY(udelay); + + return (rv); +} + +static int axp8xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay) { struct axp8xx_reg_sc *sc; @@ -863,6 +898,7 @@ axp8xx_regnode_get_voltage(struct regnode *regnode, in static regnode_method_t axp8xx_regnode_methods[] = { /* Regulator interface */ + REGNODEMETHOD(regnode_init, axp8xx_regnode_init), REGNODEMETHOD(regnode_enable, axp8xx_regnode_enable), REGNODEMETHOD(regnode_set_voltage, axp8xx_regnode_set_voltage), REGNODEMETHOD(regnode_get_voltage, axp8xx_regnode_get_voltage), Modified: stable/12/sys/dev/iicbus/twsi/twsi.c ============================================================================== --- stable/12/sys/dev/iicbus/twsi/twsi.c Thu Jun 18 23:18:47 2020 (r362349) +++ stable/12/sys/dev/iicbus/twsi/twsi.c Thu Jun 18 23:21:12 2020 (r362350) @@ -481,7 +481,6 @@ static int twsi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { struct twsi_softc *sc; - int i; sc = device_get_softc(dev); @@ -495,28 +494,25 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, uint TWSI_WRITE(sc, sc->reg_control, sc->control_val); debugf(dev, "transmitting %d messages\n", nmsgs); debugf(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status)); - for (i = 0; i < nmsgs && sc->error == 0; i++) { - sc->transfer = 1; - sc->msg = &msgs[i]; - debugf(dev, "msg[%d] flags: %x\n", i, msgs[i].flags); - debugf(dev, "msg[%d] len: %d\n", i, msgs[i].len); + sc->nmsgs = nmsgs; + sc->msgs = msgs; + sc->msg_idx = 0; + sc->transfer = 1; - /* Send start and re-enable interrupts */ - sc->control_val = TWSI_CONTROL_TWSIEN | - TWSI_CONTROL_INTEN | TWSI_CONTROL_ACK; - if (sc->msg->len == 1) - sc->control_val &= ~TWSI_CONTROL_ACK; - TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); - while (sc->error == 0 && sc->transfer != 0) { - pause_sbt("twsi", SBT_1MS * 30, SBT_1MS, 0); - } + /* Send start and re-enable interrupts */ + sc->control_val = TWSI_CONTROL_TWSIEN | + TWSI_CONTROL_INTEN | TWSI_CONTROL_ACK; + if (sc->msgs[0].len == 1) + sc->control_val &= ~TWSI_CONTROL_ACK; + TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); + while (sc->error == 0 && sc->transfer != 0) { + pause_sbt("twsi", SBT_1MS * 30, SBT_1MS, 0); + } + debugf(sc->dev, "pause finish\n"); - debugf(dev, "Done with msg[%d]\n", i); - if (sc->error) { - debugf(sc->dev, "Error, aborting (%d)\n", sc->error); - TWSI_WRITE(sc, sc->reg_control, 0); - goto out; - } + if (sc->error) { + debugf(sc->dev, "Error, aborting (%d)\n", sc->error); + TWSI_WRITE(sc, sc->reg_control, 0); } /* Disable module and interrupts */ @@ -524,7 +520,6 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, uint TWSI_WRITE(sc, sc->reg_control, 0); debugf(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status)); -out: return (sc->error); } @@ -537,122 +532,123 @@ twsi_intr(void *arg) sc = arg; - debugf(sc->dev, "Got interrupt\n"); + debugf(sc->dev, "Got interrupt Current msg=%x\n", sc->msg_idx); - while (TWSI_READ(sc, sc->reg_control) & TWSI_CONTROL_IFLG) { - status = TWSI_READ(sc, sc->reg_status); - debugf(sc->dev, "status=%x\n", status); + status = TWSI_READ(sc, sc->reg_status); + debugf(sc->dev, "initial status=%x\n", status); - switch (status) { - case TWSI_STATUS_START: - case TWSI_STATUS_RPTD_START: - /* Transmit the address */ - debugf(sc->dev, "Send the address\n"); + switch (status) { + case TWSI_STATUS_START: + case TWSI_STATUS_RPTD_START: + /* Transmit the address */ + debugf(sc->dev, "Send the address\n"); - if (sc->msg->flags & IIC_M_RD) - TWSI_WRITE(sc, sc->reg_data, - sc->msg->slave | LSB); - else - TWSI_WRITE(sc, sc->reg_data, - sc->msg->slave & ~LSB); + if (sc->msgs[sc->msg_idx].flags & IIC_M_RD) + TWSI_WRITE(sc, sc->reg_data, + sc->msgs[sc->msg_idx].slave | LSB); + else + TWSI_WRITE(sc, sc->reg_data, + sc->msgs[sc->msg_idx].slave & ~LSB); + TWSI_WRITE(sc, sc->reg_control, sc->control_val); + break; - TWSI_WRITE(sc, sc->reg_control, sc->control_val); - break; + case TWSI_STATUS_ADDR_W_ACK: + debugf(sc->dev, "Ack received after transmitting the address (write)\n"); + /* Directly send the first byte */ + sc->sent_bytes = 0; + debugf(sc->dev, "Sending byte 0 = %x\n", sc->msgs[sc->msg_idx].buf[0]); + TWSI_WRITE(sc, sc->reg_data, sc->msgs[sc->msg_idx].buf[0]); - case TWSI_STATUS_ADDR_W_ACK: - debugf(sc->dev, "Ack received after transmitting the address\n"); - /* Directly send the first byte */ - sc->sent_bytes = 0; - debugf(sc->dev, "Sending byte 0 = %x\n", sc->msg->buf[0]); - TWSI_WRITE(sc, sc->reg_data, sc->msg->buf[0]); + TWSI_WRITE(sc, sc->reg_control, sc->control_val); + break; - TWSI_WRITE(sc, sc->reg_control, sc->control_val); - break; + case TWSI_STATUS_ADDR_R_ACK: + debugf(sc->dev, "Ack received after transmitting the address (read)\n"); + sc->recv_bytes = 0; - case TWSI_STATUS_ADDR_R_ACK: - debugf(sc->dev, "Ack received after transmitting the address\n"); - sc->recv_bytes = 0; + TWSI_WRITE(sc, sc->reg_control, sc->control_val); + break; - TWSI_WRITE(sc, sc->reg_control, sc->control_val); - break; + case TWSI_STATUS_ADDR_W_NACK: + case TWSI_STATUS_ADDR_R_NACK: + debugf(sc->dev, "No ack received after transmitting the address\n"); + sc->transfer = 0; + sc->error = ETIMEDOUT; + sc->control_val = 0; + wakeup(sc); + break; - case TWSI_STATUS_ADDR_W_NACK: - case TWSI_STATUS_ADDR_R_NACK: - debugf(sc->dev, "No ack received after transmitting the address\n"); - sc->transfer = 0; - sc->error = ETIMEDOUT; - sc->control_val = 0; - wakeup(sc); - break; - - case TWSI_STATUS_DATA_WR_ACK: - debugf(sc->dev, "Ack received after transmitting data\n"); - if (sc->sent_bytes++ == (sc->msg->len - 1)) { - debugf(sc->dev, "Done sending all the bytes\n"); - /* Send stop, no interrupts on stop */ - if (!(sc->msg->flags & IIC_M_NOSTOP)) { - debugf(sc->dev, "Done TX data, send stop\n"); - TWSI_WRITE(sc, sc->reg_control, - sc->control_val | TWSI_CONTROL_STOP); - } else { - sc->control_val &= ~TWSI_CONTROL_INTEN; - TWSI_WRITE(sc, sc->reg_control, - sc->control_val); - } - transfer_done = 1; - } else { - debugf(sc->dev, "Sending byte %d = %x\n", - sc->sent_bytes, - sc->msg->buf[sc->sent_bytes]); - TWSI_WRITE(sc, sc->reg_data, - sc->msg->buf[sc->sent_bytes]); + case TWSI_STATUS_DATA_WR_ACK: + debugf(sc->dev, "Ack received after transmitting data\n"); + if (sc->sent_bytes++ == (sc->msgs[sc->msg_idx].len - 1)) { + debugf(sc->dev, "Done sending all the bytes for msg %d\n", sc->msg_idx); + /* Send stop, no interrupts on stop */ + if (!(sc->msgs[sc->msg_idx].flags & IIC_M_NOSTOP)) { + debugf(sc->dev, "Done TX data, send stop\n"); TWSI_WRITE(sc, sc->reg_control, - sc->control_val); + sc->control_val | TWSI_CONTROL_STOP); + } else { + debugf(sc->dev, "Done TX data with NO_STOP\n"); + TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); } + sc->msg_idx++; + if (sc->msg_idx == sc->nmsgs) { + debugf(sc->dev, "transfer_done=1\n"); + transfer_done = 1; + } + } else { + debugf(sc->dev, "Sending byte %d = %x\n", + sc->sent_bytes, + sc->msgs[sc->msg_idx].buf[sc->sent_bytes]); + TWSI_WRITE(sc, sc->reg_data, + sc->msgs[sc->msg_idx].buf[sc->sent_bytes]); + TWSI_WRITE(sc, sc->reg_control, + sc->control_val); + } + break; - break; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***