svn commit: r362350 - in stable/12/sys: arm/allwinner dev/iicbus/twsi dts/arm64/overlays modules/dtb/allwinner

Emmanuel Vadot manu at FreeBSD.org
Thu Jun 18 23:21:14 UTC 2020


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 <gdotten at gmail.com>
  
  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 <arm/allwinner/allwinner_pinctrl.h>
 #include <dev/extres/clk/clk.h>
 #include <dev/extres/hwreset/hwreset.h>
+#include <dev/extres/regulator/regulator.h>
 
 #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: <gpio-phandle bank pin flags>. */
-	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 ***


More information about the svn-src-stable mailing list