svn commit: r307822 - in head/sys/arm: allwinner conf
Emmanuel Vadot
manu at FreeBSD.org
Sun Oct 23 12:48:11 UTC 2016
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 <manu at 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 <manu at 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
More information about the svn-src-head
mailing list