svn commit: r308104 - in head: . share/man/man4 sys/conf sys/dev/chromebook_platform sys/dev/cyapa sys/dev/ichiic sys/dev/iicbus sys/dev/isl sys/modules sys/modules/chromebook_platform sys/modules/...

Andriy Gapon avg at FreeBSD.org
Sun Oct 30 12:15:35 UTC 2016


Author: avg
Date: Sun Oct 30 12:15:33 2016
New Revision: 308104
URL: https://svnweb.freebsd.org/changeset/base/308104

Log:
  add iic interface to ig4 driver, move isl and cyapa to iicbus
  
  Summary:
  The hardware does not expose a classic SMBus interface.
  Instead it has a lower level interface that can express a far richer
  I2C protocol than what smbus offers.  However, the interface does not
  provide a way to explicitly generate the I2C stop and start conditions.
  It's only possible to request that the stop condition is generated
  after transferring the next byte in either direction.  So, at least
  one data byte must always be transferred.
  Thus, some I2C sequences are impossible to generate, e.g., an equivalent
  of smbus quick command (<start>-<slave addr>-<r/w bit>-<stop>).
  
  At the same time isl(4) and cyapa(4) are moved to iicbus and now they use
  iicbus_transfer for communication.  Previously they used smbus_trans()
  interface that is not defined by the SMBus protocol and was implemented
  only by ig4(4).  In fact, that interface was impossible to implement
  for the typical SMBus controllers like intpm(4) or ichsmb(4) where
  a type of the SMBus command must be programmed.
  
  The plan is to remove smbus_trans() and all its uses.
  As an aside, the smbus_trans() method deviates from the standard,
  but perhaps backwards, FreeBSD convention of using 8-bit slave
  addresses (shifted by 1 bit to the left).  The method expects
  7-bit addresses.
  
  There is a user facing consequence of this change.
  A user must now provide device hints for isl and cyapa that specify an iicbus to use
  and a slave address on it.
  On Chromebook hardware where isl and cyapa devices are commonly found
  it is also possible to use a new chromebook_platform(4) driver that
  automatically configures isl and cyapa devices.  There is no need to
  provide the device hints in that case,
  
  Right now smbus(4) driver tries to discover all slaves on the bus.
  That is very dangerous.  Fortunately, the probing code uses smbus_trans()
  to do its job, so it is really enabled for ig4 only.
  The plan is to remove that auto-probing code and smbus_trans().
  
  Tested by:	grembo, Matthias Apitz <guru at unixarea.de> (w/o
  		chromebook_platform)
  Discussed with:	grembo, imp
  Reviewed by:	wblock (docs)
  MFC after:	1 month
  Relnotes:	yes
  Differential Revision: https://reviews.freebsd.org/D8172

Added:
  head/share/man/man4/chromebook_platform.4   (contents, props changed)
  head/sys/dev/chromebook_platform/
  head/sys/dev/chromebook_platform/chromebook_platform.c   (contents, props changed)
  head/sys/modules/chromebook_platform/
  head/sys/modules/chromebook_platform/Makefile   (contents, props changed)
Modified:
  head/UPDATING
  head/share/man/man4/cyapa.4
  head/share/man/man4/ig4.4
  head/share/man/man4/isl.4
  head/sys/conf/files
  head/sys/dev/cyapa/cyapa.c
  head/sys/dev/ichiic/ig4_iic.c
  head/sys/dev/ichiic/ig4_pci.c
  head/sys/dev/ichiic/ig4_var.h
  head/sys/dev/iicbus/iicbus.c
  head/sys/dev/isl/isl.c
  head/sys/modules/Makefile
  head/sys/modules/i2c/controllers/ichiic/Makefile
  head/sys/modules/i2c/cyapa/Makefile
  head/sys/modules/i2c/isl/Makefile

Modified: head/UPDATING
==============================================================================
--- head/UPDATING	Sun Oct 30 11:45:01 2016	(r308103)
+++ head/UPDATING	Sun Oct 30 12:15:33 2016	(r308104)
@@ -51,6 +51,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12
 
 ****************************** SPECIAL WARNING: ******************************
 
+20161030:
+	isl(4) and cyapa(4) drivers now require a new driver,
+	chromebook_platform(4), to work properly on Chromebook-class hardware.
+	On other types of hardware the drivers may need to be configured using
+	device hints.  Please see the corresponding manual pages for details.
+
 20161017:
 	The urtwn(4) driver was merged into rtwn(4) and now consists of
 	rtwn(4) main module + rtwn_usb(4) and rtwn_pci(4) bus-specific

Added: head/share/man/man4/chromebook_platform.4
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man4/chromebook_platform.4	Sun Oct 30 12:15:33 2016	(r308104)
@@ -0,0 +1,68 @@
+.\" Copyright (c) 2016 Andriy Gapon <avg 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 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 AUTHOR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 13, 2016
+.Dt CHROMEBOOK_PLATFORM 4
+.Os
+.Sh NAME
+.Nm chromebook_platform
+.Nd support driver for hardware on various Chromebook models
+.Sh SYNOPSIS
+To compile this driver into the kernel, place the following lines into
+the kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device chromebook_platform"
+.Ed
+.Pp
+Alternatively, to load the driver as a module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+chromebook_platform_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides automatic configuration for devices that cannot be enumerated
+or safely probed.
+In particular, I2C peripherals are different from model to model.
+.Nm
+has a model-specific information about the I2C peripherals, their drivers,
+their bus attachments and slave addresses.
+.Pp
+Note that
+.Nm
+does not load driver modules for the peripherals.
+Those have to be compiled into the kernel or loaded separately.
+.Sh SEE ALSO
+.Xr cyapa 4 ,
+.Xr iicbus 4 ,
+.Xr isl 4 ,
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver and this manual page were written by
+.An Andriy Gapon Aq Mt avg at FreeBSD.org .

Modified: head/share/man/man4/cyapa.4
==============================================================================
--- head/share/man/man4/cyapa.4	Sun Oct 30 11:45:01 2016	(r308103)
+++ head/share/man/man4/cyapa.4	Sun Oct 30 12:15:33 2016	(r308104)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 25, 2015
+.Dd October 03, 2016
 .Dt CYAPA 4
 .Os
 .Sh NAME
@@ -36,7 +36,7 @@ the kernel configuration file:
 .Bd -ragged -offset indent
 .Cd "device cyapa"
 .Cd "device ig4"
-.Cd "device smbus"
+.Cd "device iicbus"
 .Ed
 .Pp
 Alternatively, to load the driver as a module at boot time, place the following line in
@@ -45,6 +45,13 @@ Alternatively, to load the driver as a m
 cyapa_load="YES"
 ig4_load="YES"
 .Ed
+.Pp
+In
+.Pa /boot/device.hints :
+.Cd hint.cyapa.0.at="iicbus0"
+.Cd hint.cyapa.0.addr="0xCE"
+.Cd hint.cyapa.1.at="iicbus1"
+.Cd hint.cyapa.1.addr="0xCE"
 .Sh DESCRIPTION
 The
 .Nm
@@ -86,6 +93,20 @@ The upper right corner issues a MIDDLE b
 The lower right corner issues a RIGHT button.
 Optionally, tap to click can be enabled (see below).
 .El
+.Pp
+On a system using
+.Xr device.hints 5 ,
+these values are configurable for
+.Nm :
+.Bl -tag -width "hint.cyapa.%d.addr"
+.It Va hint.cyapa.%d.at
+target
+.Xr iicbus 4 .
+.It Va hint.cyapa.%d.addr
+.Nm
+i2c address on the
+.Xr iicbus 4 .
+.El
 .Sh SYSCTL VARIABLES
 These
 .Xr sysctl 8
@@ -175,7 +196,7 @@ file:
 .Dl debug.cyapa_enable_tapclick=2
 .Sh SEE ALSO
 .Xr ig4 4 ,
-.Xr smbus 4 ,
+.Xr iicbus 4 ,
 .Xr sysmouse 4 ,
 .Xr moused 8
 .Sh AUTHORS
@@ -195,6 +216,6 @@ This manual page was written by
 .Sh BUGS
 The
 .Nm
-driver detects the device based on its I2C address (0x67).
+driver detects the device from the I2C address.
 This might have unforeseen consequences if the initialization sequence
 is sent to an unknown device at that address.

Modified: head/share/man/man4/ig4.4
==============================================================================
--- head/share/man/man4/ig4.4	Sun Oct 30 11:45:01 2016	(r308103)
+++ head/share/man/man4/ig4.4	Sun Oct 30 12:15:33 2016	(r308104)
@@ -24,18 +24,18 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 30, 2015
+.Dd October 03, 2016
 .Dt IG4 4
 .Os
 .Sh NAME
 .Nm ig4
-.Nd Intel(R) fourth generation mobile CPU integrated I2C SMBus driver
+.Nd Intel(R) fourth generation mobile CPU integrated I2C driver
 .Sh SYNOPSIS
 To compile this driver into the kernel, place the following lines into
 the kernel configuration file:
 .Bd -ragged -offset indent
 .Cd "device ig4"
-.Cd "device smbus"
+.Cd "device iicbus"
 .Ed
 .Pp
 Alternatively, to load the driver as a module at boot time, place the following line in
@@ -46,9 +46,10 @@ ig4_load="YES"
 .Sh DESCRIPTION
 The
 .Nm
-driver provides access to peripherals attached to an I2C SMB controller.
+driver provides access to peripherals attached to an I2C controller.
+.Sh HARDWARE
 .Nm
-supports the SMBus controller found in fourth generation Intel(R) Core(TM)
+supports the I2C controllers found in fourth generation Intel(R) Core(TM)
 processors based on the mobile U-processor line for intelligent systems.
 This includes the i7-4650U, i5-4300U, i3-4010U, and 2980U.
 .Sh SYSCTL VARIABLES
@@ -57,13 +58,15 @@ These
 variables are available:
 .Bl -tag -width "debug.ig4_dump"
 .It Va debug.ig4_dump
-Setting this to a non-zero value dumps controller registers to console and
-syslog once.
-The sysctl resets to zero immediately.
+This sysctl is a zero-based bit mask.
+When any of the bits are set, a register dump is printed for
+every I2C transfer on an
+.Nm
+device with the same unit number.
 .El
 .Sh SEE ALSO
-.Xr smb 4 ,
-.Xr smbus 4
+.Xr iic 4 ,
+.Xr iicbus 4
 .Sh AUTHORS
 .An -nosplit
 The

Modified: head/share/man/man4/isl.4
==============================================================================
--- head/share/man/man4/isl.4	Sun Oct 30 11:45:01 2016	(r308103)
+++ head/share/man/man4/isl.4	Sun Oct 30 12:15:33 2016	(r308104)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 25, 2015
+.Dd October 03, 2016
 .Dt ISL 4
 .Os
 .Sh NAME
@@ -36,7 +36,7 @@ the kernel configuration file:
 .Bd -ragged -offset indent
 .Cd "device isl"
 .Cd "device ig4"
-.Cd "device smbus"
+.Cd "device iicbus"
 .Ed
 .Pp
 Alternatively, to load the driver as a module at boot time, place the following line in
@@ -45,6 +45,13 @@ Alternatively, to load the driver as a m
 isl_load="YES"
 ig4_load="YES"
 .Ed
+.Pp
+In
+.Pa /boot/device.hints :
+.Cd hint.isl.0.at="iicbus0"
+.Cd hint.isl.0.addr="0x88"
+.Cd hint.isl.1.at="iicbus1"
+.Cd hint.isl.1.addr="0x88"
 .Sh DESCRIPTION
 The
 .Nm
@@ -54,6 +61,20 @@ Function.
 Functionality is basic and provided through the
 .Xr sysctl 8
 interface.
+.Pp
+On a system using
+.Xr device.hints 5 ,
+these values are configurable for
+.Nm :
+.Bl -tag -width "hint.isl.%d.addr"
+.It Va hint.isl.%d.at
+target
+.Xr iicbus 4 .
+.It Va hint.isl.%d.addr
+.Nm
+i2c address on the
+.Xr iicbus 4 .
+.El
 .Sh SYSCTL VARIABLES
 The following
 .Xr sysctl 8
@@ -86,7 +107,7 @@ $ sh /usr/local/share/examples/intel-bac
 .Ed
 .Sh SEE ALSO
 .Xr ig4 4 ,
-.Xr smbus 4
+.Xr iicbus 4
 .Sh AUTHORS
 .An -nosplit
 The
@@ -99,6 +120,6 @@ This manual page was written by
 .Sh BUGS
 The
 .Nm
-driver detects the device based on its I2C address (0x44).
+driver detects the device based from the I2C address.
 This might have unforeseen consequences if the initialization sequence
 is sent to an unknown device at that address.

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sun Oct 30 11:45:01 2016	(r308103)
+++ head/sys/conf/files	Sun Oct 30 12:15:33 2016	(r308104)
@@ -1273,6 +1273,7 @@ dev/cfi/cfi_bus_nexus.c		optional cfi
 dev/cfi/cfi_core.c		optional cfi
 dev/cfi/cfi_dev.c		optional cfi
 dev/cfi/cfi_disk.c		optional cfid
+dev/chromebook_platform/chromebook_platform.c	optional chromebook_platform
 dev/ciss/ciss.c			optional ciss
 dev/cm/smc90cx6.c		optional cm
 dev/cmx/cmx.c			optional cmx
@@ -1389,7 +1390,7 @@ t5fw.fw			optional cxgbe					\
 dev/cy/cy.c			optional cy
 dev/cy/cy_isa.c			optional cy isa
 dev/cy/cy_pci.c			optional cy pci
-dev/cyapa/cyapa.c		optional cyapa smbus
+dev/cyapa/cyapa.c		optional cyapa iicbus
 dev/dc/if_dc.c			optional dc pci
 dev/dc/dcphy.c			optional dc pci
 dev/dc/pnphy.c			optional dc pci
@@ -1631,8 +1632,8 @@ dev/hptiop/hptiop.c		optional hptiop scb
 dev/hwpmc/hwpmc_logging.c	optional hwpmc
 dev/hwpmc/hwpmc_mod.c		optional hwpmc
 dev/hwpmc/hwpmc_soft.c		optional hwpmc
-dev/ichiic/ig4_iic.c		optional ig4 smbus
-dev/ichiic/ig4_pci.c		optional ig4 pci smbus
+dev/ichiic/ig4_iic.c		optional ig4 iicbus
+dev/ichiic/ig4_pci.c		optional ig4 pci iicbus
 dev/ichsmb/ichsmb.c		optional ichsmb
 dev/ichsmb/ichsmb_pci.c		optional ichsmb pci
 dev/ida/ida.c			optional ida
@@ -1726,7 +1727,7 @@ dev/iscsi_initiator/isc_soc.c	optional i
 dev/iscsi_initiator/isc_sm.c	optional iscsi_initiator scbus
 dev/iscsi_initiator/isc_subr.c	optional iscsi_initiator scbus
 dev/ismt/ismt.c			optional ismt
-dev/isl/isl.c			optional isl smbus
+dev/isl/isl.c			optional isl iicbus
 dev/isp/isp.c			optional isp
 dev/isp/isp_freebsd.c		optional isp
 dev/isp/isp_library.c		optional isp

Added: head/sys/dev/chromebook_platform/chromebook_platform.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/chromebook_platform/chromebook_platform.c	Sun Oct 30 12:15:33 2016	(r308104)
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Project.
+ * 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/errno.h>
+#include <sys/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+/*
+ * Driver that attaches I2C devices.
+ */
+static struct {
+	uint32_t	pci_id;
+	const char	*name;
+	uint8_t		addr;
+} slaves[] = {
+	{ 0x9c628086,	"isl",		0x88 },
+	{ 0x9c618086,	"cyapa",	0xce },
+};
+
+static void
+chromebook_i2c_identify(driver_t *driver, device_t bus)
+{
+	device_t controller;
+	device_t child;
+	int i;
+
+	/*
+	 * A stopgap approach to preserve the status quo.
+	 * A more intelligent approach is required to correctly
+	 * identify a machine model and hardware available on it.
+	 * For instance, DMI could be used.
+	 * See http://lxr.free-electrons.com/source/drivers/platform/chrome/chromeos_laptop.c
+	 */
+	controller = device_get_parent(bus);
+	if (strcmp(device_get_name(controller), "ig4iic") != 0)
+		return;
+
+	for (i = 0; i < nitems(slaves); i++) {
+		if (device_find_child(bus, slaves[i].name, -1) != NULL)
+			continue;
+		if (slaves[i].pci_id != pci_get_devid(controller))
+			continue;
+		child = BUS_ADD_CHILD(bus, 0, slaves[i].name, -1);
+		if (child != NULL)
+			iicbus_set_addr(child, slaves[i].addr);
+	}
+}
+
+static device_method_t chromebook_i2c_methods[] = {
+	DEVMETHOD(device_identify,	chromebook_i2c_identify),
+	{ 0, 0 }
+};
+
+static driver_t chromebook_i2c_driver = {
+	"chromebook_i2c",
+	chromebook_i2c_methods,
+	0	/* no softc */
+};
+
+static devclass_t chromebook_i2c_devclass;
+
+DRIVER_MODULE(chromebook_i2c, iicbus, chromebook_i2c_driver,
+    chromebook_i2c_devclass, 0, 0);
+MODULE_VERSION(chromebook_i2c, 1);
+

Modified: head/sys/dev/cyapa/cyapa.c
==============================================================================
--- head/sys/dev/cyapa/cyapa.c	Sun Oct 30 11:45:01 2016	(r308103)
+++ head/sys/dev/cyapa/cyapa.c	Sun Oct 30 12:15:33 2016	(r308104)
@@ -122,11 +122,11 @@ __FBSDID("$FreeBSD$");
 #include <sys/uio.h>
 #include <sys/vnode.h>
 
-#include <dev/smbus/smbconf.h>
-#include <dev/smbus/smbus.h>
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
 #include <dev/cyapa/cyapa.h>
 
-#include "smbus_if.h"
+#include "iicbus_if.h"
 #include "bus_if.h"
 #include "device_if.h"
 
@@ -149,7 +149,6 @@ struct cyapa_fifo {
 struct cyapa_softc {
 	device_t dev;
 	int	count;			/* >0 if device opened */
-	int	addr;
 	struct cdev *devnode;
 	struct selinfo selinfo;
 	struct mtx mutex;
@@ -273,6 +272,30 @@ static int cyapa_reset = 0;
 SYSCTL_INT(_debug, OID_AUTO, cyapa_reset, CTLFLAG_RW,
 	    &cyapa_reset, 0, "Reset track pad");
 
+static int
+cyapa_read_bytes(device_t dev, uint8_t reg, uint8_t *val, int cnt)
+{
+	uint16_t addr = iicbus_get_addr(dev);
+	struct iic_msg msgs[] = {
+	     { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
+	     { addr, IIC_M_RD, cnt, val },
+	};
+
+	return (iicbus_transfer(dev, msgs, nitems(msgs)));
+}
+
+static int
+cyapa_write_bytes(device_t dev, uint8_t reg, const uint8_t *val, int cnt)
+{
+	uint16_t addr = iicbus_get_addr(dev);
+	struct iic_msg msgs[] = {
+	     { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
+	     { addr, IIC_M_WR | IIC_M_NOSTART, cnt, __DECONST(uint8_t *, val) },
+	};
+
+	return (iicbus_transfer(dev, msgs, nitems(msgs)));
+}
+
 static void
 cyapa_lock(struct cyapa_softc *sc)
 {
@@ -318,7 +341,7 @@ cyapa_notify(struct cyapa_softc *sc)
  * Initialize the device
  */
 static int
-init_device(device_t dev, struct cyapa_cap *cap, int addr, int probe)
+init_device(device_t dev, struct cyapa_cap *cap, int probe)
 {
 	static char bl_exit[] = {
 		0x00, 0xff, 0xa5, 0x00, 0x01,
@@ -326,17 +349,13 @@ init_device(device_t dev, struct cyapa_c
 	static char bl_deactivate[] = {
 		0x00, 0xff, 0x3b, 0x00, 0x01,
 		0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
-	device_t bus;
 	struct cyapa_boot_regs boot;
 	int error;
 	int retries;
 
-	bus = device_get_parent(dev);	/* smbus */
-
 	/* Get status */
-	error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
-	    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-	    NULL, 0, (void *)&boot, sizeof(boot), NULL);
+	error = cyapa_read_bytes(dev, CMD_BOOT_STATUS,
+	    (void *)&boot, sizeof(boot));
 	if (error)
 		goto done;
 
@@ -350,25 +369,21 @@ init_device(device_t dev, struct cyapa_c
 			/* Busy, wait loop. */
 		} else if (boot.error & CYAPA_ERROR_BOOTLOADER) {
 			/* Magic */
-			error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
-			    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-			    bl_deactivate, sizeof(bl_deactivate),
-			    NULL, 0, NULL);
+			error = cyapa_write_bytes(dev, CMD_BOOT_STATUS,
+			    bl_deactivate, sizeof(bl_deactivate));
 			if (error)
 				goto done;
 		} else {
 			/* Magic */
-			error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
-			    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-			    bl_exit, sizeof(bl_exit), NULL, 0, NULL);
+			error = cyapa_write_bytes(dev, CMD_BOOT_STATUS,
+			    bl_exit, sizeof(bl_exit));
 			if (error)
 				goto done;
 		}
 		pause("cyapab1", (hz * 2) / 10);
 		--retries;
-		error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
-		    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-		    NULL, 0, (void *)&boot, sizeof(boot), NULL);
+		error = cyapa_read_bytes(dev, CMD_BOOT_STATUS,
+		    (void *)&boot, sizeof(boot));
 		if (error)
 			goto done;
 	}
@@ -381,9 +396,8 @@ init_device(device_t dev, struct cyapa_c
 
 	/* Check identity */
 	if (cap) {
-		error = smbus_trans(bus, addr, CMD_QUERY_CAPABILITIES,
-		    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-		    NULL, 0, (void *)cap, sizeof(*cap), NULL);
+		error = cyapa_read_bytes(dev, CMD_QUERY_CAPABILITIES,
+		    (void *)cap, sizeof(*cap));
 
 		if (strncmp(cap->prod_ida, "CYTRA", 5) != 0) {
 			device_printf(dev, "Product ID \"%5.5s\" mismatch\n",
@@ -391,9 +405,8 @@ init_device(device_t dev, struct cyapa_c
 			error = ENXIO;
 		}
 	}
-	error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
-	    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-	    NULL, 0, (void *)&boot, sizeof(boot), NULL);
+	error = cyapa_read_bytes(dev, CMD_BOOT_STATUS,
+	    (void *)&boot, sizeof(boot));
 
 	if (probe == 0)		/* official init */
 		device_printf(dev, "cyapa init status %02x\n", boot.stat);
@@ -452,16 +465,16 @@ cyapa_probe(device_t dev)
 	int addr;
 	int error;
 
-	addr = smbus_get_addr(dev);
+	addr = iicbus_get_addr(dev);
 
 	/*
 	 * 0x67 - cypress trackpad on the acer c720
 	 * (other devices might use other ids).
 	 */
-	if (addr != 0x67)
+	if (addr != 0xce)
 		return (ENXIO);
 
-	error = init_device(dev, &cap, addr, 1);
+	error = init_device(dev, &cap, 1);
 	if (error != 0)
 		return (ENXIO);
 
@@ -482,15 +495,14 @@ cyapa_attach(device_t dev)
 	sc->reporting_mode = 1;
 
 	unit = device_get_unit(dev);
-	addr = smbus_get_addr(dev);
+	addr = iicbus_get_addr(dev);
 
-	if (init_device(dev, &cap, addr, 0))
+	if (init_device(dev, &cap, 0))
 		return (ENXIO);
 
 	mtx_init(&sc->mutex, "cyapa", NULL, MTX_DEF);
 
 	sc->dev = dev;
-	sc->addr = addr;
 
 	knlist_init_mtx(&sc->selinfo.si_note, &sc->mutex);
 
@@ -1159,7 +1171,7 @@ cyapa_poll_thread(void *arg)
 {
 	struct cyapa_softc *sc;
 	struct cyapa_regs regs;
-	device_t bus;		/* smbus */
+	device_t bus;		/* iicbus */
 	int error;
 	int freq;
 	int isidle;
@@ -1180,12 +1192,10 @@ cyapa_poll_thread(void *arg)
 
 	while (!sc->detaching) {
 		cyapa_unlock(sc);
-		error = smbus_request_bus(bus, sc->dev, SMB_WAIT);
+		error = iicbus_request_bus(bus, sc->dev, IIC_WAIT);
 		if (error == 0) {
-			error = smbus_trans(bus, sc->addr, CMD_DEV_STATUS,
-			    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-			    NULL, 0,
-			    (void *)&regs, sizeof(regs), NULL);
+			error = cyapa_read_bytes(sc->dev, CMD_DEV_STATUS,
+			    (void *)&regs, sizeof(regs));
 			if (error == 0) {
 				isidle = cyapa_raw_input(sc, &regs, freq);
 			}
@@ -1200,9 +1210,9 @@ cyapa_poll_thread(void *arg)
 			     (unsigned)(ticks - last_reset) > TIME_TO_RESET)) {
 				cyapa_reset = 0;
 				last_reset = ticks;
-				init_device(sc->dev, NULL, sc->addr, 2);
+				init_device(sc->dev, NULL, 2);
 			}
-			smbus_release_bus(bus, sc->dev);
+			iicbus_release_bus(bus, sc->dev);
 		}
 		pause("cyapw", hz / freq);
 		++sc->poll_ticks;
@@ -1531,18 +1541,16 @@ cyapa_set_power_mode(struct cyapa_softc 
 	int error;
 
 	bus = device_get_parent(sc->dev);
-	error = smbus_request_bus(bus, sc->dev, SMB_WAIT);
+	error = iicbus_request_bus(bus, sc->dev, IIC_WAIT);
 	if (error == 0) {
-		error = smbus_trans(bus, sc->addr, CMD_POWER_MODE,
-		    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-		    NULL, 0, (void *)&data, 1, NULL);
+		error = cyapa_read_bytes(sc->dev, CMD_POWER_MODE,
+		    &data, 1);
 		data = (data & ~0xFC) | mode;
 		if (error == 0) {
-			error = smbus_trans(bus, sc->addr, CMD_POWER_MODE,
-			    SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
-			    (void *)&data, 1, NULL, 0, NULL);
+			error = cyapa_write_bytes(sc->dev, CMD_POWER_MODE,
+			    &data, 1);
 		}
-		smbus_release_bus(bus, sc->dev);
+		iicbus_release_bus(bus, sc->dev);
 	}
 }
 
@@ -1697,6 +1705,6 @@ cyapa_fuzz(int delta, int *fuzzp)
 	return (delta);
 }
 
-DRIVER_MODULE(cyapa, smbus, cyapa_driver, cyapa_devclass, NULL, NULL);
-MODULE_DEPEND(cyapa, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+DRIVER_MODULE(cyapa, iicbus, cyapa_driver, cyapa_devclass, NULL, NULL);
+MODULE_DEPEND(cyapa, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
 MODULE_VERSION(cyapa, 1);

Modified: head/sys/dev/ichiic/ig4_iic.c
==============================================================================
--- head/sys/dev/ichiic/ig4_iic.c	Sun Oct 30 11:45:01 2016	(r308103)
+++ head/sys/dev/ichiic/ig4_iic.c	Sun Oct 30 12:15:33 2016	(r308104)
@@ -61,6 +61,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
 #include <dev/smbus/smbconf.h>
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
 
 #include <dev/ichiic/ig4_reg.h>
 #include <dev/ichiic/ig4_var.h>
@@ -120,7 +122,7 @@ set_controller(ig4iic_softc_t *sc, uint3
 		reg_write(sc, IG4_REG_INTR_MASK, 0);
 
 	reg_write(sc, IG4_REG_I2C_EN, ctl);
-	error = SMB_ETIMEOUT;
+	error = IIC_ETIMEOUT;
 
 	for (retry = 100; retry > 0; --retry) {
 		v = reg_read(sc, IG4_REG_ENABLE_STATUS);
@@ -148,7 +150,7 @@ wait_status(ig4iic_softc_t *sc, uint32_t
 	u_int count_us = 0;
 	u_int limit_us = 25000; /* 25ms */
 
-	error = SMB_ETIMEOUT;
+	error = IIC_ETIMEOUT;
 
 	for (;;) {
 		/*
@@ -484,6 +486,236 @@ done:
 }
 
 /*
+ *				IICBUS API FUNCTIONS
+ */
+static int
+ig4iic_xfer_start(ig4iic_softc_t *sc, uint16_t slave)
+{
+	/* XXX 10-bit address support? */
+	set_slave_addr(sc, slave >> 1, 0);
+	return (0);
+}
+
+static int
+ig4iic_read(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
+    bool repeated_start, bool stop)
+{
+	uint32_t cmd;
+	uint16_t i;
+	int error;
+
+	if (len == 0)
+		return (0);
+
+	cmd = IG4_DATA_COMMAND_RD;
+	cmd |= repeated_start ? IG4_DATA_RESTART : 0;
+	cmd |= stop && len == 1 ? IG4_DATA_STOP : 0;
+
+	/* Issue request for the first byte (could be last as well). */
+	reg_write(sc, IG4_REG_DATA_CMD, cmd);
+
+	for (i = 0; i < len; i++) {
+		/*
+		 * Maintain a pipeline by queueing the allowance for the next
+		 * read before waiting for the current read.
+		 */
+		cmd = IG4_DATA_COMMAND_RD;
+		if (i < len - 1) {
+			cmd = IG4_DATA_COMMAND_RD;
+			cmd |= stop && i == len - 2 ? IG4_DATA_STOP : 0;
+			reg_write(sc, IG4_REG_DATA_CMD, cmd);
+		}
+		error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY);
+		if (error)
+			break;
+		buf[i] = data_read(sc);
+	}
+
+	(void)reg_read(sc, IG4_REG_TX_ABRT_SOURCE);
+	return (error);
+}
+
+static int
+ig4iic_write(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
+    bool repeated_start, bool stop)
+{
+	uint32_t cmd;
+	uint16_t i;
+	int error;
+
+	if (len == 0)
+		return (0);
+
+	cmd = repeated_start ? IG4_DATA_RESTART : 0;
+	for (i = 0; i < len; i++) {
+		error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
+		if (error)
+			break;
+		cmd |= buf[i];
+		cmd |= stop && i == len - 1 ? IG4_DATA_STOP : 0;
+		reg_write(sc, IG4_REG_DATA_CMD, cmd);
+		cmd = 0;
+	}
+
+	(void)reg_read(sc, IG4_REG_TX_ABRT_SOURCE);
+	return (error);
+}
+
+int
+ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+	ig4iic_softc_t *sc = device_get_softc(dev);
+	const char *reason = NULL;
+	uint32_t i;
+	int error;
+	int unit;
+	bool rpstart;
+	bool stop;
+
+	/*
+	 * The hardware interface imposes limits on allowed I2C messages.
+	 * It is not possible to explicitly send a start or stop.
+	 * They are automatically sent (or not sent, depending on the
+	 * configuration) when a data byte is transferred.
+	 * For this reason it's impossible to send a message with no data
+	 * at all (like an SMBus quick message).
+	 * The start condition is automatically generated after the stop
+	 * condition, so it's impossible to not have a start after a stop.
+	 * The repeated start condition is automatically sent if a change
+	 * of the transfer direction happens, so it's impossible to have
+	 * a change of direction without a (repeated) start.
+	 * The repeated start can be forced even without the change of
+	 * direction.
+	 * Changing the target slave address requires resetting the hardware
+	 * state, so it's impossible to do that without the stop followed
+	 * by the start.
+	 */
+	for (i = 0; i < nmsgs; i++) {
+#if 0
+		if (i == 0 && (msgs[i].flags & IIC_M_NOSTART) != 0) {
+			reason = "first message without start";
+			break;
+		}
+		if (i == nmsgs - 1 && (msgs[i].flags & IIC_M_NOSTOP) != 0) {
+			reason = "last message without stop";
+			break;
+		}
+#endif
+		if (msgs[i].len == 0) {
+			reason = "message with no data";
+			break;
+		}
+		if (i > 0) {
+			if ((msgs[i].flags & IIC_M_NOSTART) != 0 &&
+			    (msgs[i - 1].flags & IIC_M_NOSTOP) == 0) {
+				reason = "stop not followed by start";
+				break;
+			}
+			if ((msgs[i - 1].flags & IIC_M_NOSTOP) != 0 &&
+			    msgs[i].slave != msgs[i - 1].slave) {
+				reason = "change of slave without stop";
+				break;
+			}
+			if ((msgs[i].flags & IIC_M_NOSTART) != 0 &&
+			    (msgs[i].flags & IIC_M_RD) !=
+			    (msgs[i - 1].flags & IIC_M_RD)) {
+				reason = "change of direction without repeated"
+				    " start";
+				break;
+			}
+		}
+	}
+	if (reason != NULL) {
+		if (bootverbose)
+			device_printf(dev, "%s\n", reason);
+		return (IIC_ENOTSUPP);
+	}
+
+	sx_xlock(&sc->call_lock);
+	mtx_lock(&sc->io_lock);
+
+	/* Debugging - dump registers. */
+	if (ig4_dump) {
+		unit = device_get_unit(dev);
+		if (ig4_dump & (1 << unit)) {
+			ig4_dump &= ~(1 << unit);
+			ig4iic_dump(sc);
+		}
+	}
+
+	/*
+	 * Clear any previous abort condition that may have been holding
+	 * the txfifo in reset.
+	 */
+	reg_read(sc, IG4_REG_CLR_TX_ABORT);
+
+	/*
+	 * Clean out any previously received data.
+	 */
+	if (sc->rpos != sc->rnext && bootverbose) {
+		device_printf(sc->dev, "discarding %d bytes of spurious data\n",
+		    sc->rnext - sc->rpos);
+	}
+	sc->rpos = 0;
+	sc->rnext = 0;
+
+	rpstart = false;
+	error = 0;
+	for (i = 0; i < nmsgs; i++) {
+		if ((msgs[i].flags & IIC_M_NOSTART) == 0) {
+			error = ig4iic_xfer_start(sc, msgs[i].slave);
+		} else {
+			if (!sc->slave_valid ||
+			    (msgs[i].slave >> 1) != sc->last_slave) {
+				device_printf(dev, "start condition suppressed"
+				    "but slave address is not set up");
+				error = EINVAL;
+				break;
+			}
+			rpstart = false;
+		}
+		if (error != 0)
+			break;
+
+		stop = (msgs[i].flags & IIC_M_NOSTOP) == 0;
+		if (msgs[i].flags & IIC_M_RD)
+			error = ig4iic_read(sc, msgs[i].buf, msgs[i].len,
+			    rpstart, stop);
+		else
+			error = ig4iic_write(sc, msgs[i].buf, msgs[i].len,
+			    rpstart, stop);
+		if (error != 0)
+			break;
+
+		rpstart = !stop;
+	}
+
+	mtx_unlock(&sc->io_lock);
+	sx_unlock(&sc->call_lock);
+	return (error);
+}
+
+int
+ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+	ig4iic_softc_t *sc = device_get_softc(dev);
+
+	sx_xlock(&sc->call_lock);
+	mtx_lock(&sc->io_lock);
+
+	/* TODO handle speed configuration? */
+	if (oldaddr != NULL)
+		*oldaddr = sc->last_slave << 1;
+	set_slave_addr(sc, addr >> 1, 0);
+	if (addr == IIC_UNKNOWN)
+		sc->slave_valid = false;
+
+	mtx_unlock(&sc->io_lock);
+	sx_unlock(&sc->call_lock);
+	return (0);
+}
+
+/*
  *				SMBUS API FUNCTIONS
  *
  * Called from ig4iic_pci_attach/detach()
@@ -549,9 +781,9 @@ ig4iic_attach(ig4iic_softc_t *sc)
 		  IG4_CTL_RESTARTEN |
 		  IG4_CTL_SPEED_STD);
 
-	sc->smb = device_add_child(sc->dev, "smbus", -1);
-	if (sc->smb == NULL) {
-		device_printf(sc->dev, "smbus driver not found\n");
+	sc->iicbus = device_add_child(sc->dev, "iicbus", -1);
+	if (sc->iicbus == NULL) {
+		device_printf(sc->dev, "iicbus driver not found\n");
 		error = ENXIO;
 		goto done;
 	}
@@ -624,15 +856,15 @@ ig4iic_detach(ig4iic_softc_t *sc)
 		if (error)
 			return (error);
 	}
-	if (sc->smb)
-		device_delete_child(sc->dev, sc->smb);
+	if (sc->iicbus)
+		device_delete_child(sc->dev, sc->iicbus);
 	if (sc->intr_handle)
 		bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle);
 
 	sx_xlock(&sc->call_lock);
 	mtx_lock(&sc->io_lock);
 
-	sc->smb = NULL;
+	sc->iicbus = NULL;
 	sc->intr_handle = NULL;
 	reg_write(sc, IG4_REG_INTR_MASK, 0);
 	set_controller(sc, 0);
@@ -976,4 +1208,4 @@ ig4iic_dump(ig4iic_softc_t *sc)
 }
 #undef REGDUMP
 
-DRIVER_MODULE(smbus, ig4iic, smbus_driver, smbus_devclass, NULL, NULL);
+DRIVER_MODULE(iicbus, ig4iic, iicbus_driver, iicbus_devclass, NULL, NULL);

Modified: head/sys/dev/ichiic/ig4_pci.c
==============================================================================
--- head/sys/dev/ichiic/ig4_pci.c	Sun Oct 30 11:45:01 2016	(r308103)
+++ head/sys/dev/ichiic/ig4_pci.c	Sun Oct 30 12:15:33 2016	(r308104)
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
 #include <dev/smbus/smbconf.h>
+#include <dev/iicbus/iiconf.h>
 
 #include "smbus_if.h"
 
@@ -180,6 +181,10 @@ static device_method_t ig4iic_pci_method
 	DEVMETHOD(smbus_bread, ig4iic_smb_bread),
 	DEVMETHOD(smbus_trans, ig4iic_smb_trans),
 

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list