On Sun, Jul 16, 2017 at 11:13:35PM +0200, Mark Kettenis wrote:
> > Date: Sun, 9 Jul 2017 20:34:29 +0300
> > From: Artturi Alm <artturi....@gmail.com>
> > 
> > Hi,
> > 
> > revived the diff below, i2c tested via pmic's shutdown(), for working
> > "shutdown -p now" operation.
> > there was only two i2c's w/"status: 'okay'" in the FDT, so not all of
> > them do attach.
> > 
> > related part of dmesg:
> > 
> > com0: console
> > sxitwi0 at simplebus0
> > iic0 at sxitwi0
> > axppmic0 at iic0 addr 0x34: AXP209, ACIN
> > sxitwi1 at simplebus0
> > iic1 at sxitwi1
> > dwge0 at simplebus0
> > 
> > Comments?
> > -Artturi
> 
> It's a pity that the PSCI "firmware" doesn't do an actual shutdown.
> But having i2c support is worth having in its own right.
> 

Yes, it would be plenty more ideal for us, if it did.
Yep, there's plenty more than just pmics we could have support for.

> A bit of a step backwards to add code under the old-style 4-clause BSD
> license, but I believe that is still acceptable.
> 

Yep, tbh., i haven't looked at freebsd, if they would have something
better w/regards that license currently, nor if netbsd has cleaned it,
but i doubt not.

> I don't think we'll ever support the Marvell Discovery hardware, so
> I'd just fold the gttwsi_core.c code into sxitwi.c and get rid of the
> GTTWSI_ALLWINNER hack.
> 

Will take a look at it, while it doesn't help w/the license.

> A few more comments inline below.
> 

reply to one of the comments below, for which i'd like to get some input
before going for the rest, but i will look at fixing everything in a single
new diff anyway, which might require a rainy day.
Thank you for your comments. :)

> On my (Allwinner A20) Banana Pi this seems to work, although the
> Ethernet link status LED turns back on shortly after the board powers
> down.  I guess it gets power from the link.  The power LED stays on as
> well, but that is just leakage from the serial console.  The green LED
> that is gpio controllable turns off when the board powers down.
> 

I have met these serial power leakages on most boards when using ftdi usb
uarts. will check if cubies do the same w/ethernet, atleast i don't remember
having noticed such.

> 
> > diff --git a/sys/arch/armv7/conf/GENERIC b/sys/arch/armv7/conf/GENERIC
> > index af71a6c4835..d8762ba394c 100644
> > --- a/sys/arch/armv7/conf/GENERIC
> > +++ b/sys/arch/armv7/conf/GENERIC
> > @@ -99,6 +99,8 @@ ehci*             at fdt?                 # EHCI (shim)
> >  usb*               at ehci?        #flags 0x1
> >  #ohci*             at sunxi?
> >  #usb*              at ohci?
> > +sxitwi*            at fdt?                 # Two-Wire Serial Interface
> > +iic*               at sxitwi?              # I2C bus
> >  
> >  # ARM Versatile Express
> >  sysreg*            at fdt?
> > @@ -148,6 +150,7 @@ mvxhci*         at fdt?
> >  usb*               at mvxhci?
> >  mvahci*            at fdt?
> >  
> > +axppmic*   at iic?                 # axp209 pmic
> >  crosec*            at iic?
> >  wskbd*             at crosec? mux 1
> >  pcfrtc*            at iic?
> > diff --git a/sys/arch/armv7/conf/RAMDISK b/sys/arch/armv7/conf/RAMDISK
> > index 56e64893df6..0c5f8aa4e1f 100644
> > --- a/sys/arch/armv7/conf/RAMDISK
> > +++ b/sys/arch/armv7/conf/RAMDISK
> > @@ -99,6 +99,8 @@ ehci*             at fdt?                 # EHCI (shim)
> >  usb*               at ehci?        #flags 0x1
> >  #ohci*             at sunxi?
> >  #usb*              at ohci?
> > +sxitwi*            at fdt?                 # Two-Wire Serial Interface
> > +iic*               at sxitwi?              # I2C bus
> >  
> >  # ARM Versatile Express
> >  sysreg*            at fdt?
> > @@ -145,6 +147,7 @@ mvxhci*         at fdt?
> >  usb*               at mvxhci?
> >  mvahci*            at fdt?
> >  
> > +axppmic*   at iic?                 # axp209 pmic
> >  crosec*            at iic?
> >  wskbd*             at crosec? mux 1
> >  pcfrtc*            at iic?
> > diff --git a/sys/dev/fdt/axp20x.c b/sys/dev/fdt/axp20x.c
> > new file mode 100644
> > index 00000000000..833038f0eff
> > --- /dev/null
> > +++ b/sys/dev/fdt/axp20x.c
> > @@ -0,0 +1,160 @@
> > +/*
> > + * Copyright (c) 2014,2016 Artturi Alm
> > + *
> > + * Permission to use, copy, modify, and distribute this software for any
> > + * purpose with or without fee is hereby granted, provided that the above
> > + * copyright notice and this permission notice appear in all copies.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > + */
> > +
> > +#include <sys/param.h>
> > +#include <sys/systm.h>
> > +#include <sys/device.h>
> > +#include <sys/sensors.h>
> > +
> > +#include <dev/i2c/i2cvar.h>
> > +
> > +#include <machine/bus.h>
> > +#include <machine/fdt.h>
> > +
> > +#include <dev/ofw/openfirm.h>
> > +#include <dev/ofw/fdt.h>
> > +
> > +#include <armv7/armv7/armv7_machdep.h>     /* needed for powerdownfn */
> > +
> > +/* Power Status Register / Input power status */
> > +#define    AXP209_PSR              0x00
> > +#define    AXP209_PSR_ACIN         (1 << 7)        /* ACIN Exists */
> > +#define    AXP209_PSR_VBUS         (1 << 5)        /* VBUS Exists */
> > +
> > +/* Shutdown settings, battery detection, and CHGLED Pin control */
> > +#define    AXP209_SDR              0x32
> > +#define    AXP209_SDR_SHUTDOWN     (1 << 7)        /* Shutdown Control */
> > +
> > +#define DNAME(sc)  ((sc)->sc_dev.dv_xname)
> 
> This macro is unused.
> 
> > +struct axp20x_softc {
> > +   struct device   sc_dev;
> > +   i2c_tag_t       sc_i2c;
> > +   i2c_addr_t      sc_addr;
> > +};
> > +
> > +int        axp20x_match(struct device *, void *, void *);
> > +void       axp20x_attach(struct device *, struct device *, void *);
> > +
> > +int        axp20x_readb(u_char, u_char *);
> > +int        axp20x_writeb(u_char, u_char);
> > +u_int      axp20x_get_acin(void);
> 
> This function is unused.

Ah, forgot about that, and this is something like i had in mind for it:

-Artturi


diff --git a/sys/arch/armv7/armv7/armv7_machdep.c 
b/sys/arch/armv7/armv7/armv7_machdep.c
index aa1c549b29b..cbe9daf47a2 100644
--- a/sys/arch/armv7/armv7/armv7_machdep.c
+++ b/sys/arch/armv7/armv7/armv7_machdep.c
@@ -203,6 +203,7 @@ int bootstrap_bs_map(void *, uint64_t, bus_size_t, int,
     bus_space_handle_t *);
 void   process_kernel_args(char *);
 void   consinit(void);
+static int     armv7_powerinput(void);
 
 bs_protos(bs_notimpl);
 
@@ -220,6 +221,13 @@ int stdout_node = 0;
 
 void (*cpuresetfn)(void);
 void (*powerdownfn)(void);
+int (*powerinputfn)(void) = armv7_powerinput;
+
+int
+armv7_powerinput(void)
+{
+       return _PMIC_POWERINPUT_UNK;    /* default input unknown */
+}
 
 /*
  * void boot(int howto, char *bootstr)
diff --git a/sys/arch/armv7/armv7/armv7_machdep.h 
b/sys/arch/armv7/armv7/armv7_machdep.h
index ff52b0c2744..c0dc99589e5 100644
--- a/sys/arch/armv7/armv7/armv7_machdep.h
+++ b/sys/arch/armv7/armv7/armv7_machdep.h
@@ -29,6 +29,13 @@ struct board_dev *platform_board_devs();
 void *fdt_find_cons(const char *);
 extern void (*cpuresetfn)(void);
 extern void (*powerdownfn)(void);
+extern int (*powerinputfn)(void);
+
+/* int *powerinputfn(void); return values */
+#define        _PMIC_POWERINPUT_BATT   0
+#define        _PMIC_POWERINPUT_UNK    1       /* default, allowing ie. 
ahci_attach */
+#define        _PMIC_POWERINPUT_USB    2
+#define        _PMIC_POWERINPUT_ACIN   3
 
 struct armv7_platform {
        struct board_dev *devs;
diff --git a/sys/arch/armv7/sunxi/sxiahci.c b/sys/arch/armv7/sunxi/sxiahci.c
index 455ff94754b..3c93b92a126 100644
--- a/sys/arch/armv7/sunxi/sxiahci.c
+++ b/sys/arch/armv7/sunxi/sxiahci.c
@@ -100,6 +100,11 @@ sxiahci_attach(struct device *parent, struct device *self, 
void *aux)
        uint32_t target_supply;
        uint32_t timo;
 
+       if ((*powerinputfn)() == _PMIC_POWERINPUT_BATT) {
+               printf(": unsupported configuration, power input battery.\n");
+               return;
+       }
+
        if (faa->fa_nreg < 1)
                return;
 
diff --git a/sys/dev/fdt/axp20x.c b/sys/dev/fdt/axp20x.c
index 833038f0eff..852b05d466a 100644
--- a/sys/dev/fdt/axp20x.c
+++ b/sys/dev/fdt/axp20x.c
@@ -51,7 +51,7 @@ void  axp20x_attach(struct device *, struct device *, void *);
 
 int    axp20x_readb(u_char, u_char *);
 int    axp20x_writeb(u_char, u_char);
-u_int  axp20x_get_acin(void);
+int    axp20x_get_powerinput(void);
 void   axp20x_shutdown(void);
 
 struct cfattach axppmic_ca = {
@@ -98,6 +98,7 @@ axp20x_attach(struct device *parent, struct device *self, 
void *args)
        printf("\n");
 
        powerdownfn = axp20x_shutdown;
+       powerinputfn = axp20x_get_powerinput;
 }
 
 int
@@ -138,15 +139,16 @@ axp20x_writeb(u_char reg, u_char data)
  * but as only user is the on-board ahci driver, this will likely be
  * enough to protect against trying to spin-up on battery atleast.
  */
-u_int
-axp20x_get_acin(void)
+int
+axp20x_get_powerinput(void)
 {
        u_char psr;
        if (axp20x_readb(AXP209_PSR, &psr))
-               psr = 0;
-       if (psr & AXP209_PSR_ACIN)
-               return 1;
-       return 0;
+               psr = 0;        if (psr & AXP209_PSR_ACIN)
+               return _PMIC_POWERINPUT_ACIN;
+       else if (psr & AXP209_PSR_VBUS)
+               return _PMIC_POWERINPUT_USB;
+       return _PMIC_POWERINPUT_BATT;
 }
 
 void


> 
> > +void       axp20x_shutdown(void);
> > +
> > +struct cfattach axppmic_ca = {
> > +   sizeof(struct axp20x_softc), axp20x_match, axp20x_attach
> > +};
> > +
> > +struct cfdriver axppmic_cd = {
> > +   NULL, "axppmic", DV_DULL
> > +};
> > +
> > +int
> > +axp20x_match(struct device *parent, void *cf, void *arg)
> > +{
> > +   struct i2c_attach_args *ia = arg;
> > +   int node = *(int *)ia->ia_cookie;
> > +
> > +   if (OF_is_compatible(node, "x-powers,axp209"))
> > +           return 1;
> > +   if (strcmp(ia->ia_name, "x-powers,axp209") == 0)
> > +           return 1;
> > +   return 0;
> > +}
> > +
> > +void
> > +axp20x_attach(struct device *parent, struct device *self, void *args)
> > +{
> > +   struct axp20x_softc *sc = (struct axp20x_softc *)self;
> > +   struct i2c_attach_args *ia = args;
> > +   uint8_t psr;
> > +
> > +   sc->sc_i2c = ia->ia_tag;
> > +   sc->sc_addr = ia->ia_addr;
> > +
> > +   axp20x_readb(AXP209_PSR, &psr);
> > +   printf(": AXP209,");
> > +   if (!(psr & (AXP209_PSR_ACIN | AXP209_PSR_VBUS)))
> > +           printf(" BAT");
> > +   else {
> > +           if (psr & AXP209_PSR_ACIN)
> > +                   printf(" ACIN");
> > +           if (psr & AXP209_PSR_VBUS)
> > +                   printf(" VBUS");
> > +   }
> > +   printf("\n");
> > +
> > +   powerdownfn = axp20x_shutdown;
> > +}
> > +
> > +int
> > +axp20x_readb(u_char reg, u_char *val)
> > +{
> > +   struct axp20x_softc *sc = axppmic_cd.cd_devs[0];
> > +   int flags = I2C_F_POLL;
> > +   int ret;
> > +
> > +   if (sc == NULL)
> > +           return 1;
> > +
> > +   iic_acquire_bus(sc->sc_i2c, flags);
> > +   ret = iic_smbus_read_byte(sc->sc_i2c, sc->sc_addr, reg, val, flags);
> > +   iic_release_bus(sc->sc_i2c, flags);
> > +   return ret;
> > +
> > +}
> > +
> > +int
> > +axp20x_writeb(u_char reg, u_char data)
> > +{
> > +   struct axp20x_softc *sc = axppmic_cd.cd_devs[0];
> > +   int flags = I2C_F_POLL;
> > +   int ret;
> > +
> > +   if (sc == NULL)
> > +           return 1;
> > +
> > +   iic_acquire_bus(sc->sc_i2c, flags);
> > +   ret = iic_smbus_write_byte(sc->sc_i2c, sc->sc_addr, reg, data, flags);
> > +   iic_release_bus(sc->sc_i2c, flags);
> > +   return ret;
> > +}
> > +
> > +/*
> > + * XXX this will detect power from usb-otg port as ACin on cubieboard,
> > + * but as only user is the on-board ahci driver, this will likely be
> > + * enough to protect against trying to spin-up on battery atleast.
> > + */
> > +u_int
> > +axp20x_get_acin(void)
> > +{
> > +   u_char psr;
> > +   if (axp20x_readb(AXP209_PSR, &psr))
> > +           psr = 0;
> > +   if (psr & AXP209_PSR_ACIN)
> > +           return 1;
> > +   return 0;
> > +}
> > +
> > +void
> > +axp20x_shutdown(void)
> > +{
> > +   /* XXX
> > +    * if (!i2c_initialized) sxitwi_init(); ?
> > +    * or bring back bitbanging gpio 'soft'i2c..
> > +    */
> 
> This comment makes no sense to me.
> 
> > +   axp20x_writeb(AXP209_SDR, AXP209_SDR_SHUTDOWN);
> > +}
> > diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt
> > index 9e2f64cbdaa..07e9b9025fd 100644
> > --- a/sys/dev/fdt/files.fdt
> > +++ b/sys/dev/fdt/files.fdt
> > @@ -23,6 +23,15 @@ device   sximmc: sdmmcbus
> >  attach     sximmc at fdt
> >  file       dev/fdt/sximmc.c                sximmc
> >  
> > +device     sxitwi: i2cbus
> > +attach     sxitwi at fdt
> > +file       dev/fdt/sxitwi.c                sxitwi
> > +file       dev/fdt/gttwsi_core.c           sxitwi
> > +
> > +device     axppmic
> > +attach     axppmic at i2c
> > +file       dev/fdt/axp20x.c                axppmic
> > +
> >  device     bcmdog
> >  attach     bcmdog at fdt
> >  file       dev/fdt/bcm2835_dog.c           bcmdog
> > diff --git a/sys/dev/fdt/gttwsi_core.c b/sys/dev/fdt/gttwsi_core.c
> > new file mode 100644
> > index 00000000000..2f6f09c3464
> > --- /dev/null
> > +++ b/sys/dev/fdt/gttwsi_core.c
> > @@ -0,0 +1,430 @@
> > +/* $NetBSD: gttwsi_core.c,v 1.2 2014/11/23 13:37:27 jmcneill Exp $ */
> > +/*
> > + * Copyright (c) 2008 Eiji Kawauchi.
> > + * All rights reserved.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + * 3. All advertising materials mentioning features or use of this software
> > + *    must display the following acknowledgement:
> > + *      This product includes software developed for the NetBSD Project by
> > + *      Eiji Kawauchi.
> > + * 4. The name of the author may not be used to endorse or promote products
> > + *    derived from this software without specific prior written permission
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
> > WARRANTIES
> > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 
> > USE,
> > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +/*
> > + * Copyright (c) 2005 Brocade Communcations, inc.
> > + * All rights reserved.
> > + *
> > + * Written by Matt Thomas for Brocade Communcations, Inc.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + * 3. The name of Brocade Communications, Inc. may not be used to endorse
> > + *    or promote products derived from this software without specific prior
> > + *    written permission.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY BROCADE COMMUNICATIONS, INC. ``AS IS'' AND
> > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
> > PURPOSE
> > + * ARE DISCLAIMED.  IN NO EVENT SHALL EITHER BROCADE COMMUNICATIONS, INC. 
> > BE
> > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
> > + * OF THE POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +
> > +/*
> > + * Marvell Two-Wire Serial Interface (aka I2C) master driver
> > + */
> > +
> > +#include <sys/param.h>
> > +#include <sys/systm.h>
> > +#include <sys/device.h>
> > +#include <sys/kernel.h>
> > +#include <sys/rwlock.h>
> > +
> > +#define    _I2C_PRIVATE
> > +#include <dev/i2c/i2cvar.h>
> > +
> > +#include <machine/bus.h>
> > +
> > +#include <dev/fdt/gttwsivar.h>
> > +
> > +#define    GTTWSI_SIZE             0x100
> > +
> > +#define    GTTWSI_ALLWINNER
> > +#if defined(GTTWSI_ALLWINNER)
> > +#define    TWSI_SLAVEADDR          0x00
> > +#define    TWSI_EXTEND_SLAVEADDR   0x04
> > +#define    TWSI_DATA               0x08
> > +#define    TWSI_CONTROL            0x0c
> > +#define    TWSI_STATUS             0x10
> > +#define    TWSI_BAUDRATE           0x14
> > +#define    TWSI_SOFTRESET          0x18
> > +#else
> > +#define    TWSI_SLAVEADDR          0x00
> > +#define    TWSI_EXTEND_SLAVEADDR   0x10
> > +#define    TWSI_DATA               0x04
> > +#define    TWSI_CONTROL            0x08
> > +#define    TWSI_STATUS             0x0c    /* for read */
> > +#define    TWSI_BAUDRATE           0x0c    /* for write */
> > +#define    TWSI_SOFTRESET          0x1c
> > +#endif
> > +
> > +#define    SLAVEADDR_GCE_MASK      0x01
> > +#define    SLAVEADDR_SADDR_MASK    0xfe
> > +
> > +#define    EXTEND_SLAVEADDR_MASK   0xff
> > +
> > +#define    DATA_MASK               0xff
> > +
> > +#define    CONTROL_ACK             (1 << 2)
> > +#define    CONTROL_IFLG            (1 << 3)
> > +#define    CONTROL_STOP            (1 << 4)
> > +#define    CONTROL_START           (1 << 5)
> > +#define    CONTROL_TWSIEN          (1 << 6)
> > +#define    CONTROL_INTEN           (1 << 7)
> > +
> > +#define    STAT_BE         0x00    /* Bus Error */
> > +#define    STAT_SCT        0x08    /* Start condition transmitted */
> > +#define    STAT_RSCT       0x10    /* Repeated start condition transmitted 
> > */
> > +#define    STAT_AWBT_AR    0x18    /* Address + write bit transd, ack 
> > recvd */
> > +#define    STAT_AWBT_ANR   0x20    /* Address + write bit transd, ack not 
> > recvd */
> > +#define    STAT_MTDB_AR    0x28    /* Master transd data byte, ack recvd */
> > +#define    STAT_MTDB_ANR   0x30    /* Master transd data byte, ack not 
> > recvd */
> > +#define    STAT_MLADADT    0x38    /* Master lost arbitr during addr or 
> > data tx */
> > +#define    STAT_ARBT_AR    0x40    /* Address + read bit transd, ack recvd 
> > */
> > +#define    STAT_ARBT_ANR   0x48    /* Address + read bit transd, ack not 
> > recvd */
> > +#define    STAT_MRRD_AT    0x50    /* Master received read data, ack 
> > transd */
> > +#define    STAT_MRRD_ANT   0x58    /* Master received read data, ack not 
> > transd */
> > +#define    STAT_SAWBT_AR   0xd0    /* Second addr + write bit transd, ack 
> > recvd */
> > +#define    STAT_SAWBT_ANR  0xd8    /* S addr + write bit transd, ack not 
> > recvd */
> > +#define    STAT_SARBT_AR   0xe0    /* Second addr + read bit transd, ack 
> > recvd */
> > +#define    STAT_SARBT_ANR  0xe8    /* S addr + read bit transd, ack not 
> > recvd */
> > +#define    STAT_NRS        0xf8    /* No relevant status */
> > +
> > +#define    SOFTRESET_VAL           0               /* reset value */
> > +
> > +#define    TWSI_RETRY_COUNT        1000            /* retry loop count */
> > +#define    TWSI_RETRY_DELAY        1               /* retry delay */
> > +#define    TWSI_STAT_DELAY         1               /* poll status delay */
> > +#define    TWSI_READ_DELAY         2               /* read delay */
> > +#define    TWSI_WRITE_DELAY        2               /* write delay */
> > +
> > +
> > +/*efine    TWSI_DEBUG
> 
> You messed that one up ;).
> 
> > +#ifdef TWSI_DEBUG
> > +/*
> > + * conditional debugging
> > + */
> > +#define    CD_INIT         0x00000001      /* init */
> > +#define    CD_ERR          0x00000002      /* errors */
> > +#define    CD_TIMO         0x00000004      /* timeout */
> > +#define    CD_INFO         0x00000004      /* timeout */
> > +#define    CD_DBG          0x00000010      /* just dbg */
> > +#define    CD_SPAM         0x00000020      /* verbose boot */
> > +#define    CD_ALL          0xffffffff
> > +
> > +int gttwsi_debug = 0 /*| CD_INIT | CD_DBG | CD_SPAM | CD_ALL*/;
> > +
> > +#define    DPRINTF(flg, stmt) \
> > +do { \
> > +   if (gttwsi_debug & (flg)) \
> > +           printf stmt; \
> > +} while (0)
> > +#else
> > +#define    DPRINTF(flg, stmt) do { } while (0)
> > +#endif     /* TWSI_DEBUG */
> > +
> > +#define DNAME(sc)  ((sc)->sc_dev.dv_xname)
> 
> We try to avoid elaborate debugging code like this.  I doubt it is
> very useful in this case.
> 
> > +
> > +int        gttwsi_acquire_bus(void *, int);
> > +void       gttwsi_release_bus(void *, int);
> > +int        gttwsi_send_start(void *v, int flags);
> > +int        gttwsi_send_stop(void *v, int flags);
> > +int        gttwsi_initiate_xfer(void *v, i2c_addr_t addr, int flags);
> > +int        gttwsi_read_byte(void *v, uint8_t *valp, int flags);
> > +int        gttwsi_write_byte(void *v, uint8_t val, int flags);
> > +
> > +int        gttwsi_wait(struct gttwsi_softc *, uint32_t, uint32_t, int);
> > +
> > +inline u_int
> > +gttwsi_read_4(struct gttwsi_softc *sc, u_int reg)
> > +{
> > +   u_int val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg);
> > +
> > +   DPRINTF(CD_SPAM, ("I2C:R:%02x:%02x\n", reg, val));
> > +#if !defined(TWSI_DEBUG)
> > +   delay(TWSI_READ_DELAY);
> > +#endif
> > +
> > +   return val;
> > +}
> > +
> > +inline void
> > +gttwsi_write_4(struct gttwsi_softc *sc, u_int reg, u_int val)
> > +{
> > +   bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, val);
> > +
> > +   DPRINTF(CD_SPAM, ("I2C:W:%02x:%02x\n", reg, val));
> > +#if !defined(TWSI_DEBUG)
> > +   delay(TWSI_WRITE_DELAY);
> > +#endif
> > +
> > +   return;
> > +}
> > +
> > +void
> > +gttwsi_attach_subr(struct device *self, bus_space_tag_t iot,
> > +    bus_space_handle_t ioh, int node)
> > +{
> > +   struct gttwsi_softc * const sc = (struct gttwsi_softc *)self;
> > +
> > +   sc->sc_iot = iot;
> > +   sc->sc_ioh = ioh;
> > +   sc->sc_node = node;
> > +
> > +   rw_init(&sc->sc_buslock, sc->sc_dev.dv_xname);
> > +
> > +   sc->sc_started = 0;
> > +   sc->sc_ic.ic_cookie = sc;
> > +   sc->sc_ic.ic_acquire_bus = gttwsi_acquire_bus;
> > +   sc->sc_ic.ic_release_bus = gttwsi_release_bus;
> > +   sc->sc_ic.ic_exec = NULL;
> > +   sc->sc_ic.ic_send_start = gttwsi_send_start;
> > +   sc->sc_ic.ic_send_stop = gttwsi_send_stop;
> > +   sc->sc_ic.ic_initiate_xfer = gttwsi_initiate_xfer;
> > +   sc->sc_ic.ic_read_byte = gttwsi_read_byte;
> > +   sc->sc_ic.ic_write_byte = gttwsi_write_byte;
> > +
> > +   /*
> > +    * Put the controller into Soft Reset.
> > +    */
> > +
> > +   gttwsi_write_4(sc, TWSI_SOFTRESET, SOFTRESET_VAL);
> > +
> > +   printf("\n");
> > +}
> > +
> > +void
> > +gttwsi_config_children(struct device *self)
> > +{
> > +   struct gttwsi_softc * const sc = (struct gttwsi_softc *)self;
> > +   struct i2cbus_attach_args iba;
> > +
> > +   memset(&iba, 0, sizeof(iba));
> > +   iba.iba_name = "iic";
> > +   iba.iba_tag = &sc->sc_ic;
> > +
> > +   (void)config_found(&sc->sc_dev, &iba, iicbus_print);
> > +}
> > +
> > +int
> > +gttwsi_intr(void *arg)
> > +{
> > +   struct gttwsi_softc *sc = arg;
> > +   u_int val;
> > +
> > +   val = gttwsi_read_4(sc, TWSI_CONTROL);
> > +   if (val & CONTROL_IFLG) {
> > +           gttwsi_write_4(sc, TWSI_CONTROL, val & ~CONTROL_INTEN);
> > +           wakeup(&sc->sc_dev);
> > +           return 1;
> > +   }
> > +   return 0;
> > +}
> > +
> > +int
> > +gttwsi_acquire_bus(void *arg, int flags)
> > +{
> > +   struct gttwsi_softc *sc = arg;
> > +
> > +   if (flags & I2C_F_POLL)
> > +           return 0;
> > +
> > +   return rw_enter(&sc->sc_buslock, RW_WRITE);
> > +}
> > +
> > +void
> > +gttwsi_release_bus(void *arg, int flags)
> > +{
> > +   struct gttwsi_softc *sc = arg;
> > +
> > +   if (flags & I2C_F_POLL)
> > +           return;
> > +
> > +   rw_exit(&sc->sc_buslock);
> > +}
> > +
> > +int
> > +gttwsi_send_start(void *v, int flags)
> > +{
> > +   struct gttwsi_softc *sc = v;
> > +   int expect;
> > +
> > +   if (sc->sc_started)
> > +           expect = STAT_RSCT;
> > +   else
> > +           expect = STAT_SCT;
> > +   sc->sc_started = 1;
> > +   return gttwsi_wait(sc, CONTROL_START, expect, flags);
> > +}
> > +
> > +int
> > +gttwsi_send_stop(void *v, int flags)
> > +{
> > +   struct gttwsi_softc *sc = v;
> > +   int retry = TWSI_RETRY_COUNT;
> > +   u_int control;
> > +
> > +   sc->sc_started = 0;
> > +
> > +   /* Interrupt is not generated for STAT_NRS. */
> > +   control = CONTROL_STOP | CONTROL_TWSIEN;
> > +   gttwsi_write_4(sc, TWSI_CONTROL, control);
> > +   while (--retry > 0) {
> > +           if (gttwsi_read_4(sc, TWSI_STATUS) == STAT_NRS)
> > +                   return 0;
> > +           delay(TWSI_STAT_DELAY);
> > +   }
> > +
> > +   DPRINTF(CD_ERR, ("%s: send STOP failed\n", DNAME(sc)));
> > +
> > +   return -1;
> > +}
> > +
> > +int
> > +gttwsi_initiate_xfer(void *v, i2c_addr_t addr, int flags)
> > +{
> > +   struct gttwsi_softc *sc = v;
> > +   u_int data, expect;
> > +   int error, read;
> > +
> > +   gttwsi_send_start(v, flags);
> > +
> > +   read = (flags & I2C_F_READ) != 0;
> > +   if (read)
> > +           expect = STAT_ARBT_AR;
> > +   else
> > +           expect = STAT_AWBT_AR;
> > +
> > +   /*
> > +    * First byte contains whether this xfer is a read or write.
> > +    */
> > +   data = read;
> > +   if (addr > 0x7f) {
> > +           /*
> > +            * If this is a 10bit request, the first address byte is
> > +            * 0b11110<b9><b8><r/w>.
> > +            */
> > +           data |= 0xf0 | ((addr & 0x300) >> 7);
> > +           gttwsi_write_4(sc, TWSI_DATA, data);
> > +           error = gttwsi_wait(sc, 0, expect, flags);
> > +           if (error)
> > +                   return error;
> > +           /*
> > +            * The first address byte has been sent, now to send
> > +            * the second one.
> > +            */
> > +           if (read)
> > +                   expect = STAT_SARBT_AR;
> > +           else
> > +                   expect = STAT_SAWBT_AR;
> > +           data = (uint8_t)addr;
> > +   } else
> > +           data |= (addr << 1);
> > +
> > +   gttwsi_write_4(sc, TWSI_DATA, data);
> > +   return gttwsi_wait(sc, 0, expect, flags);
> > +}
> > +
> > +int
> > +gttwsi_read_byte(void *v, uint8_t *valp, int flags)
> > +{
> > +   struct gttwsi_softc *sc = v;
> > +   int error;
> > +
> > +   if (flags & I2C_F_LAST)
> > +           error = gttwsi_wait(sc, 0, STAT_MRRD_ANT, flags);
> > +   else
> > +           error = gttwsi_wait(sc, CONTROL_ACK, STAT_MRRD_AT, flags);
> > +   if (!error)
> > +           *valp = gttwsi_read_4(sc, TWSI_DATA);
> > +   if ((flags & (I2C_F_LAST | I2C_F_STOP)) == (I2C_F_LAST | I2C_F_STOP))
> > +           error = gttwsi_send_stop(sc, flags);
> > +   return error;
> > +}
> > +
> > +int
> > +gttwsi_write_byte(void *v, uint8_t val, int flags)
> > +{
> > +   struct gttwsi_softc *sc = v;
> > +   int error;
> > +
> > +   gttwsi_write_4(sc, TWSI_DATA, val);
> > +   error = gttwsi_wait(sc, 0, STAT_MTDB_AR, flags);
> > +   if (flags & I2C_F_STOP)
> > +           gttwsi_send_stop(sc, flags);
> > +   return error;
> > +}
> > +
> > +int
> > +gttwsi_wait(struct gttwsi_softc *sc, u_int control, u_int expect, int 
> > flags)
> > +{
> > +   u_int status;
> > +   int timo, error = 0;
> > +
> > +   delay(5);
> > +   if (!(flags & I2C_F_POLL))
> > +           control |= CONTROL_INTEN;
> > +   gttwsi_write_4(sc, TWSI_CONTROL, control | CONTROL_TWSIEN);
> > +
> > +   timo = 0;
> > +   do {
> > +           control = gttwsi_read_4(sc, TWSI_CONTROL);
> > +           if (control & CONTROL_IFLG)
> > +                   break;
> > +           if (flags & I2C_F_POLL)
> > +                   delay(TWSI_RETRY_DELAY);
> > +           else {
> > +                   error = tsleep(&sc->sc_dev, PWAIT, "gttwsi", 100);
> > +                   if (error)
> > +                           return error;
> > +           }
> > +   } while (++timo < 1000000);
> > +
> > +   status = gttwsi_read_4(sc, TWSI_STATUS);
> > +   if (status != expect) {
> > +           DPRINTF(CD_ERR, ("%s: status %#x expected %#x\n",
> > +               DNAME(sc), status, expect));
> > +           return EIO;
> > +   }
> > +   return error;
> > +}
> > diff --git a/sys/dev/fdt/gttwsivar.h b/sys/dev/fdt/gttwsivar.h
> > new file mode 100644
> > index 00000000000..c5edf3a8548
> > --- /dev/null
> > +++ b/sys/dev/fdt/gttwsivar.h
> > @@ -0,0 +1,91 @@
> > +/* $NetBSD: gttwsivar.h,v 1.2 2014/11/23 13:37:27 jmcneill Exp $   */
> > +/*
> > + * Copyright (c) 2008 Eiji Kawauchi.
> > + * All rights reserved.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + * 3. All advertising materials mentioning features or use of this software
> > + *    must display the following acknowledgement:
> > + *      This product includes software developed for the NetBSD Project by
> > + *      Eiji Kawauchi.
> > + * 4. The name of the author may not be used to endorse or promote products
> > + *    derived from this software without specific prior written permission
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
> > WARRANTIES
> > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 
> > USE,
> > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +/*
> > + * Copyright (c) 2005 Brocade Communcations, inc.
> > + * All rights reserved.
> > + *
> > + * Written by Matt Thomas for Brocade Communcations, Inc.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + * 3. The name of Brocade Communications, Inc. may not be used to endorse
> > + *    or promote products derived from this software without specific prior
> > + *    written permission.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY BROCADE COMMUNICATIONS, INC. ``AS IS'' AND
> > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
> > PURPOSE
> > + * ARE DISCLAIMED.  IN NO EVENT SHALL EITHER BROCADE COMMUNICATIONS, INC. 
> > BE
> > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
> > + * OF THE POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +
> > +#ifndef _DEV_MARVELL_GTTWSIVAR_H_
> > +#define _DEV_MARVELL_GTTWSIVAR_H_
> > +
> > +/*
> > + * Marvell Two-Wire Serial Interface (aka I2C) master driver
> > + */
> > +#include <sys/device.h>
> > +#include <sys/rwlock.h>
> > +
> > +#include <dev/i2c/i2cvar.h>
> > +#include <machine/bus.h>
> > +
> > +struct gttwsi_softc {
> > +   struct device           sc_dev;
> > +   bus_space_tag_t         sc_iot;
> > +   bus_space_handle_t      sc_ioh;
> > +   int                     sc_node;
> > +   u_int                   sc_started;
> > +   struct i2c_controller   sc_ic;
> > +   struct rwlock           sc_buslock;
> > +};
> > +
> > +void       gttwsi_attach_subr(struct device *, bus_space_tag_t,
> > +       bus_space_handle_t, int);
> > +void       gttwsi_config_children(struct device *);
> 
> This function is unused.
> 
> > +
> > +int        gttwsi_intr(void *);
> > +
> > +#endif /* _DEV_MARVELL_GTTSWI_VAR_H_ */
> > diff --git a/sys/dev/fdt/sxitwi.c b/sys/dev/fdt/sxitwi.c
> > new file mode 100644
> > index 00000000000..665c7201045
> > --- /dev/null
> > +++ b/sys/dev/fdt/sxitwi.c
> > @@ -0,0 +1,170 @@
> > +/* $NetBSD: awin_twi.c,v 1.7 2015/12/26 16:54:41 macallan Exp $ */
> > +/*
> > + * Copyright (c) 2013 The NetBSD Foundation, Inc.
> > + * All rights reserved.
> > + *
> > + * This code is derived from software contributed to The NetBSD Foundation
> > + * by Matt Thomas of 3am Software Foundry.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 
> > CONTRIBUTORS
> > + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
> > LIMITED
> > + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
> > PARTICULAR
> > + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR 
> > CONTRIBUTORS
> > + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
> > THE
> > + * POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +
> > +#include <sys/param.h>
> > +#include <sys/device.h>
> > +#include <sys/systm.h>
> > +
> > +#define    _I2C_PRIVATE
> > +#include <dev/i2c/i2cvar.h>
> > +
> > +#include <machine/bus.h>
> > +#include <machine/fdt.h>
> > +
> > +#include <dev/fdt/gttwsivar.h>
> > +
> > +#include <dev/ofw/openfirm.h>
> > +#include <dev/ofw/ofw_clock.h>
> > +#include <dev/ofw/ofw_pinctrl.h>
> > +#include <dev/ofw/fdt.h>
> > +
> > +
> > +#define TWI_CCR_REG                0x14
> > +#define TWI_CCR_CLK_M              (0x0f << 3)
> > +#define TWI_CCR_CLK_N              (0x07 << 0)
> > +
> > +void       sxitwi_attach(struct device *, struct device *, void *);
> > +int        sxitwi_match(struct device *, void *, void *);
> > +void       sxitwi_bus_scan(struct device *, struct i2cbus_attach_args *, 
> > void *);
> > +
> > +struct sxitwi_softc {
> > +   struct gttwsi_softc      sc_sc;
> > +   void                    *sc_ih;
> > +};
> > +
> > +struct cfdriver sxitwi_cd = {
> > +   NULL, "sxitwi", DV_DULL
> > +};
> > +
> > +struct cfattach sxitwi_ca = {
> > +   sizeof(struct sxitwi_softc), sxitwi_match, sxitwi_attach
> > +};
> > +
> > +int
> > +sxitwi_match(struct device *parent, void *cf, void *arg)
> > +{
> > +   struct fdt_attach_args *faa = arg;
> > +
> > +   if (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-i2c"))
> > +           return 1;
> > +   if (OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-i2c"))
> > +           return 1;
> > +
> > +   return 0;
> > +}
> > +
> > +void
> > +sxitwi_attach(struct device *parent, struct device *self, void *arg)
> > +{
> > +   struct sxitwi_softc     *sc = (struct sxitwi_softc *)self;
> > +   struct fdt_attach_args  *faa = arg;
> > +   bus_space_tag_t          iot = faa->fa_iot;
> > +   bus_space_handle_t       ioh;
> > +
> > +   if (bus_space_map(iot, faa->fa_reg[0].addr,
> > +       faa->fa_reg[0].size, 0, &ioh))
> > +           panic("sxitwi_attach: bus_space_map failed!");
> > +
> > +   /*
> > +    * Acquire the PIO pins needed for the TWI port, and
> > +    * enable clock gating via CCMU
> > +    */
> > +   pinctrl_byname(faa->fa_node, "default");
> > +
> > +   /* enable clock */
> > +   clock_enable(faa->fa_node, NULL);
> > +
> > +   /*
> > +    * Set clock rate to 100kHz. From the datasheet:
> > +    *   For 100Khz standard speed 2Wire, CLK_N=2, CLK_M=11
> > +    *   F0=48M/2^2=12Mhz, F1=F0/(10*(11+1)) = 0.1Mhz
> > +    */
> > +   bus_space_write_4(iot, ioh, TWI_CCR_REG, (11 << 3) | (2 << 0));
> > +
> > +   /*
> > +    * Do the MI attach
> > +    */
> > +   gttwsi_attach_subr(self, iot, ioh, faa->fa_node);
> > +
> > +   /*
> > +    * Establish interrupt for it
> > +    */
> > +   sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO,
> > +       gttwsi_intr, sc, sc->sc_sc.sc_dev.dv_xname);
> > +   if (sc->sc_ih == NULL) {
> > +           printf(": can't to establish interrupt\n");
> > +           return;
> > +   }
> > +
> > +   /*
> > +    * Configure its children
> > +    */
> > +
> > +   struct i2cbus_attach_args iba;
> > +
> > +   memset(&iba, 0, sizeof(iba));
> > +   iba.iba_name = "iic";
> > +   iba.iba_tag = &sc->sc_sc.sc_ic;
> > +   iba.iba_bus_scan = sxitwi_bus_scan;
> > +   iba.iba_bus_scan_arg = &sc->sc_sc.sc_node;
> > +
> > +   (void)config_found(&sc->sc_sc.sc_dev, &iba, iicbus_print);
> > +
> > +}
> > +
> > +void
> > +sxitwi_bus_scan(struct device *self, struct i2cbus_attach_args *iba, void 
> > *arg)
> > +{
> > +   int iba_node = *(int *)arg;
> > +   struct i2c_attach_args ia;
> > +   char name[32];
> > +   uint32_t reg[1];
> > +   int node;
> > +
> > +   for (node = OF_child(iba_node); node; node = OF_peer(node)) {
> > +           memset(name, 0, sizeof(name));
> > +           memset(reg, 0, sizeof(reg));
> > +
> > +           if (OF_getprop(node, "compatible", name, sizeof(name)) == -1)
> > +                   continue;
> > +           if (name[0] == '\0')
> > +                   continue;
> > +
> > +           if (OF_getprop(node, "reg", &reg, sizeof(reg)) != sizeof(reg))
> > +                   continue;
> > +
> > +           memset(&ia, 0, sizeof(ia));
> > +           ia.ia_tag = iba->iba_tag;
> > +           ia.ia_addr = bemtoh32(&reg[0]);
> > +           ia.ia_name = name;
> > +           ia.ia_cookie = &node;
> > +           config_found(self, &ia, iic_print);
> > +   }
> > +}
> > 
> > 

Reply via email to