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-all mailing list