Author: manu
Date: Sun Oct 23 12:48:09 2016
New Revision: 307822
URL: https://svnweb.freebsd.org/changeset/base/307822

Log:
  allwinner: Add support for P2WI bus
  
  P2WI (Push-Pull Two Wire Interface) is an I2C-like bus used in sun6i SoC
  for talking to power management unit IC.

Added:
  head/sys/arm/allwinner/aw_p2wi.c   (contents, props changed)
  head/sys/arm/allwinner/aw_p2wi.h   (contents, props changed)
Modified:
  head/sys/arm/allwinner/files.allwinner
  head/sys/arm/conf/GENERIC

Added: head/sys/arm/allwinner/aw_p2wi.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/arm/allwinner/aw_p2wi.c    Sun Oct 23 12:48:09 2016        
(r307822)
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 2016 Emmanuel Vadot <m...@freebsd.org>
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Allwinner P2WI (Push-Pull Two Wire Interface)
+ * P2WI is a iic-like interface used on sun6i hardware
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+
+#include <arm/allwinner/aw_p2wi.h>
+
+#include "iicbus_if.h"
+
+static struct ofw_compat_data compat_data[] = {
+       { "allwinner,sun6i-a31-p2wi",           1 },
+       { NULL,                                 0 }
+};
+
+static struct resource_spec p2wi_spec[] = {
+       { SYS_RES_MEMORY,       0,      RF_ACTIVE },
+       { -1, 0 }
+};
+
+struct p2wi_softc {
+       struct resource *res;
+       struct mtx      mtx;
+       clk_t           clk;
+       hwreset_t       rst;
+       device_t        iicbus;
+};
+
+#define        P2WI_LOCK(sc)                   mtx_lock(&(sc)->mtx)
+#define        P2WI_UNLOCK(sc)                 mtx_unlock(&(sc)->mtx)
+#define        P2WI_READ(sc, reg)              bus_read_4((sc)->res, (reg))
+#define        P2WI_WRITE(sc, reg, val)        bus_write_4((sc)->res, (reg), 
(val))
+
+#define        P2WI_RETRY      1000
+
+static phandle_t
+p2wi_get_node(device_t bus, device_t dev)
+{
+       return (ofw_bus_get_node(bus));
+}
+
+static int
+p2wi_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+       struct p2wi_softc *sc;
+       int retry;
+
+       sc = device_get_softc(dev);
+
+       P2WI_LOCK(sc);
+
+       P2WI_WRITE(sc, P2WI_CTRL, P2WI_CTRL_SOFT_RESET);
+       for (retry = P2WI_RETRY; retry > 0; retry--)
+               if ((P2WI_READ(sc, P2WI_CTRL) & P2WI_CTRL_SOFT_RESET) == 0)
+                       break;
+
+       P2WI_UNLOCK(sc);
+
+       if (retry == 0) {
+               device_printf(dev, "soft reset timeout\n");
+               return (ETIMEDOUT);
+       }
+
+       return (IIC_ENOADDR);
+}
+
+static int
+p2wi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+       struct p2wi_softc *sc;
+       int retry, error;
+       uint8_t data_len;
+
+       sc = device_get_softc(dev);
+
+       /*
+        * Since P2WI is only used for AXP22x PMIC we only support
+        * two messages of one byte length
+        */
+       if (nmsgs != 2 || (msgs[0].flags & IIC_M_RD) == IIC_M_RD ||
+           msgs[0].len != 1 || msgs[1].len != 1)
+               return (EINVAL);
+
+       P2WI_LOCK(sc);
+
+       /* Write address */
+       P2WI_WRITE(sc, P2WI_DADDR0, msgs[0].buf[0]);
+
+       /* Write Data length/Direction */
+       data_len = P2WI_DLEN_LEN(msgs[1].len);
+       if ((msgs[1].flags & IIC_M_RD) == 0)
+               P2WI_WRITE(sc, P2WI_DATA0, msgs[1].buf[0]);
+       else
+               data_len |= P2WI_DLEN_READ;
+       P2WI_WRITE(sc, P2WI_DLEN, data_len);
+
+       /* Start transfer */
+       P2WI_WRITE(sc, P2WI_CTRL, P2WI_CTRL_START_TRANS);
+
+       /* Wait for transfer to complete */
+       for (retry = P2WI_RETRY; retry > 0; retry--)
+               if ((P2WI_READ(sc, P2WI_CTRL) & P2WI_CTRL_START_TRANS) == 0)
+                       break;
+
+       if (retry == 0) {
+               error = ETIMEDOUT;
+               goto done;
+       }
+
+       /* Read data if needed */
+       if ((msgs[1].flags & IIC_M_RD) == IIC_M_RD) {
+               msgs[1].buf[0] = P2WI_READ(sc, P2WI_DATA0) & 0xff;
+               msgs[1].len = 1;
+       }
+
+       error = 0;
+
+done:
+       P2WI_UNLOCK(sc);
+
+       return (error);
+}
+
+static int
+p2wi_probe(device_t dev)
+{
+       if (!ofw_bus_status_okay(dev))
+               return (ENXIO);
+
+       if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+               return (ENXIO);
+
+       device_set_desc(dev, "Allwinner P2WI");
+       return (BUS_PROBE_DEFAULT);
+}
+
+static int
+p2wi_attach(device_t dev)
+{
+       struct p2wi_softc *sc;
+       int error;
+
+       sc = device_get_softc(dev);
+       mtx_init(&sc->mtx, device_get_nameunit(dev), "p2wi", MTX_DEF);
+
+       if (clk_get_by_ofw_index(dev, 0, 0, &sc->clk) == 0) {
+               error = clk_enable(sc->clk);
+               if (error != 0) {
+                       device_printf(dev, "cannot enable clock\n");
+                       goto fail;
+               }
+       }
+       if (hwreset_get_by_ofw_idx(dev, 0, 0, &sc->rst) == 0) {
+               error = hwreset_deassert(sc->rst);
+               if (error != 0) {
+                       device_printf(dev, "cannot de-assert reset\n");
+                       goto fail;
+               }
+       }
+
+       if (bus_alloc_resources(dev, p2wi_spec, &sc->res) != 0) {
+               device_printf(dev, "cannot allocate resources for device\n");
+               error = ENXIO;
+               goto fail;
+       }
+
+       sc->iicbus = device_add_child(dev, "iicbus", -1);
+       if (sc->iicbus == NULL) {
+               device_printf(dev, "cannot add iicbus child device\n");
+               error = ENXIO;
+               goto fail;
+       }
+
+       /* Disable interrupts */
+       P2WI_WRITE(sc, P2WI_INTE, 0x0);
+
+       bus_generic_attach(dev);
+
+       return (0);
+
+fail:
+       bus_release_resources(dev, p2wi_spec, &sc->res);
+       if (sc->rst != NULL)
+               hwreset_release(sc->rst);
+       if (sc->clk != NULL)
+               clk_release(sc->clk);
+       mtx_destroy(&sc->mtx);
+       return (error);
+}
+
+static device_method_t p2wi_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         p2wi_probe),
+       DEVMETHOD(device_attach,        p2wi_attach),
+
+       /* Bus interface */
+       DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
+       DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
+       DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
+       DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+       DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+       DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+       DEVMETHOD(bus_adjust_resource,  bus_generic_adjust_resource),
+       DEVMETHOD(bus_set_resource,     bus_generic_rl_set_resource),
+       DEVMETHOD(bus_get_resource,     bus_generic_rl_get_resource),
+
+       /* OFW methods */
+       DEVMETHOD(ofw_bus_get_node,     p2wi_get_node),
+
+       /* iicbus interface */
+       DEVMETHOD(iicbus_callback,      iicbus_null_callback),
+       DEVMETHOD(iicbus_reset,         p2wi_reset),
+       DEVMETHOD(iicbus_transfer,      p2wi_transfer),
+
+       DEVMETHOD_END
+};
+
+static driver_t p2wi_driver = {
+       "iichb",
+       p2wi_methods,
+       sizeof(struct p2wi_softc),
+};
+
+static devclass_t p2wi_devclass;
+
+EARLY_DRIVER_MODULE(iicbus, p2wi, iicbus_driver, iicbus_devclass, 0, 0,
+    BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(p2wi, simplebus, p2wi_driver, p2wi_devclass, 0, 0,
+    BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(p2wi, 1);

Added: head/sys/arm/allwinner/aw_p2wi.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/arm/allwinner/aw_p2wi.h    Sun Oct 23 12:48:09 2016        
(r307822)
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2016 Emmanuel Vadot <m...@freebsd.org>
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __AW_P2WI_H__
+#define        __AW_P2WI_H__
+
+#define        P2WI_CTRL                       0x00
+#define         P2WI_CTRL_SOFT_RESET           (1 << 0)
+#define         P2WI_CTRL_GLOBAL_INT_ENB       (1 << 1)
+#define         P2WI_CTRL_ABORT_TRANS          (1 << 6)
+#define         P2WI_CTRL_START_TRANS          (1 << 7)
+
+#define        P2WI_CCR                        0x04
+#define         P2WI_CCR_CLK_DIV_SHIFT         0
+#define         P2WI_CCR_CLK_DIV_MASK          0xFF
+#define         P2WI_CCR_SDA_ODLY_SHIFT        7
+#define         P2WI_CCR_SDA_ODLY_MASK         0x700
+
+#define        P2WI_INTE       0x08
+#define         P2WI_INTE_TRANS_OVER_ENB
+#define         P2WI_INTE_TRANS_ERR_ENB
+#define         P2WI_INTE_LOAD_BSY_ENB
+
+#define        P2WI_STAT                       0x0C
+#define         P2WI_STAT_TRANS_OVER           (1 << 0)
+#define         P2WI_STAT_TRANS_ERR            (1 << 1)
+#define         P2WI_STAT_LOAD_BSY             (1 << 2)
+#define         P2WI_STAT_TRANS_ERR_ID_SHIFT   7
+#define         P2WI_STAT_TRANS_ERR_ID_MASK    0xFF00
+
+#define        P2WI_DADDR0     0x10
+
+#define        P2WI_DADDR1     0x14
+
+#define        P2WI_DLEN               0x18
+#define         P2WI_DLEN_LEN(x)       ((x - 1) & 0x7)
+#define         P2WI_DLEN_READ         (1 << 4)
+
+#define        P2WI_DATA0      0x1C
+
+#define        P2WI_DATA1      0x20
+
+#define        P2WI_LCR                0x24
+#define         P2WI_LCR_SDA_CTL_EN    (1 << 0)
+#define         P2WI_LCR_SDA_CTL       (1 << 1)
+#define         P2WI_LCR_SCL_CTL_EN    (1 << 2)
+#define         P2WI_LCR_SCL_CTL       (1 << 3)
+#define         P2WI_LCR_SDA_STATE     (1 << 4)
+#define         P2WI_LCR_SCL_STATE     (1 << 5)
+
+
+#define        P2WI_PMCR       0x28
+
+#endif /* __AW_P2WI_H__ */

Modified: head/sys/arm/allwinner/files.allwinner
==============================================================================
--- head/sys/arm/allwinner/files.allwinner      Sun Oct 23 11:23:17 2016        
(r307821)
+++ head/sys/arm/allwinner/files.allwinner      Sun Oct 23 12:48:09 2016        
(r307822)
@@ -12,6 +12,7 @@ arm/allwinner/a10_mmc.c                       optional        
mmc
 arm/allwinner/a10_sramc.c              standard
 arm/allwinner/aw_nmi.c                 optional        intrng
 arm/allwinner/aw_if_dwc.c              optional        dwc
+arm/allwinner/aw_p2wi.c                        optional        p2wi
 arm/allwinner/aw_rsb.c                 optional        rsb
 arm/allwinner/aw_rtc.c                 standard
 arm/allwinner/aw_ts.c                  standard

Modified: head/sys/arm/conf/GENERIC
==============================================================================
--- head/sys/arm/conf/GENERIC   Sun Oct 23 11:23:17 2016        (r307821)
+++ head/sys/arm/conf/GENERIC   Sun Oct 23 12:48:09 2016        (r307822)
@@ -104,6 +104,7 @@ device              iicbus
 device         iic
 device         twsi
 device         rsb
+device         p2wi                    # Allwinner Push-Pull Two Wire interface
 device         axp209                  # AXP209 Power Management Unit
 device         axp81x                  # AXP813/818 Power Management Unit
 device         bcm2835_bsc
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to