From nobody Tue Jan 25 15:16:30 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 72B7F1979117; Tue, 25 Jan 2022 15:16:30 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Jjr6Q2lpMz3DcF; Tue, 25 Jan 2022 15:16:30 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1643123790; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=uVINtIMr2iSJw0MX7/wduw0rr2ViO/nLHKjeTVomXx4=; b=tbBvPT/gbrsxobilfofATZDcTGu8Fha64xFzInalzB1TrxaWOG2KwrKjngH9OulSi00wfx Q70Fr7m+QUGQZJv9ors1cOOjgJUTPxPDc1ic37p80NyOs5M6KYSVi7SAiMOVmXOniMeL2O LDzHHd5RPStyQ91TT3B0cFnKg2q50jSpaikSmx7VKmr+7/uvizExOlBui3f8lz/rBezfps Ko/2xnZS8/bbm+l7rVJgApsuPqrHIGXgAXOfQnVEclzbNMhwWbQ+pUdtIVctqsNSObzPue u+OZ5THWf7wo8fgVSVxKgfJJSU3L7CpiCbnpiwai0bg6O47zrHCDwSCxzU/xMg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 3DD893DCB; Tue, 25 Jan 2022 15:16:30 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 20PFGUJo040906; Tue, 25 Jan 2022 15:16:30 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 20PFGU9P040905; Tue, 25 Jan 2022 15:16:30 GMT (envelope-from git) Date: Tue, 25 Jan 2022 15:16:30 GMT Message-Id: <202201251516.20PFGU9P040905@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Emmanuel Vadot Subject: git: 1961a14a4743 - main - linuxkpi: Add i2c support List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: manu X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 1961a14a47437595fb7fcdc20e327440e3eb51e2 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1643123790; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=uVINtIMr2iSJw0MX7/wduw0rr2ViO/nLHKjeTVomXx4=; b=l6plKvYwwF1vS1RVmTzu3gw8BCDDDQAYdR94nSAeH24Ze/cgdEX33BZXOs1+h0dIHKEa/0 HrJB2I2AVn5vGHNr9O2X4doB1NNllPANkvRePRbGanqDBrnTfOSg75wvjsEEko3BzFoEIL z/hKOUQwS13QAC5eTb3KlF+0+/7v77YRzYXdaFpzc1vjN5yCaE4IsHVjVUznnRHmHe7d8I rnT64ohqQCwe0JqX6EAUb/tSGoiu0jnur2kRlN0KXn8Krnir+fcK//tumtM5LCm4a4qVu7 vDFWvXiaAMGlnM0Mwhm7iq3y82WahXvaDUoVkqwPmOrWVxnLq7XqnKwiOJjpsg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1643123790; a=rsa-sha256; cv=none; b=S1nHlib9sTQpaPT/eEIxxZ3Omd7ymXBOXrb5OCrpIEx5KjiJS3sGhcPaMqJ5wAczqUGms3 kXInh/u77jpc2ayg7s6iKGQnb7ujOgHRvW6nKGHZWx9fdMjxDgzQgnNilOqSntp1/FMMFZ XnFWWASZ57g3E/6GyoxUQaqfswEYEVAppHqRoiA8P4Dqk0iHstHjQJzZoN3bM7j3IuhrX/ h2xerMY51f5/fVLkx80v6G1IUCORyTq30sQi4cyDZVll6or+cb3nfkolxFQy8witRPp1gk 4xZh8lICvVpAgmlLtbIXfaeo3NpNAP5F1QF+jCUaDrCVcb31QjIwz5GuvXuf7g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by manu: URL: https://cgit.FreeBSD.org/src/commit/?id=1961a14a47437595fb7fcdc20e327440e3eb51e2 commit 1961a14a47437595fb7fcdc20e327440e3eb51e2 Author: Emmanuel Vadot AuthorDate: 2021-11-04 09:42:37 +0000 Commit: Emmanuel Vadot CommitDate: 2022-01-25 15:15:39 +0000 linuxkpi: Add i2c support Add i2c support to linuxkpi. This is needed by drm-kmod. For every i2c_adapter added by i2c_add_adapter we add a child to the device named "lkpi_iic". This child handle the conversion between Linux i2c_msgs to FreeBSD iic_msgs. For every i2c_adapter added by i2c_bit_add_bus we add a child to the device named "lkpi_iicbb". This child handle the conversion between Linux i2c_msgs to FreeBSD iic_msgs. With the help of iic(4), this expose the i2c controller to userspace allowing a user to query DDC information from a monitor. e.g.: i2c -f /dev/iic0 -a 0x28 -c 128 -d r will query the standard EDID from the monitor if plugged. The bitbang part (lkpi_iicbb) isn't tested at all for now as I don't have compatible hardware (all my hardware have native i2c controller). Tested on: Intel (SandyBridge, Skylake, ApolloLake) Tested on: AMD (Picasso, Polaris (amd64 and arm64)) MFC after: 1 month Reviewed by: hselasky Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D33053 --- .../linuxkpi/common/include/linux/i2c-algo-bit.h | 49 ++++ sys/compat/linuxkpi/common/include/linux/i2c.h | 152 +++++++++++++ sys/compat/linuxkpi/common/src/linux_i2c.c | 217 ++++++++++++++++++ sys/compat/linuxkpi/common/src/linux_i2cbb.c | 252 +++++++++++++++++++++ sys/compat/linuxkpi/common/src/lkpi_iic_if.m | 37 +++ sys/conf/files | 19 +- sys/conf/kmod.mk | 4 + sys/modules/linuxkpi/Makefile | 2 + 8 files changed, 725 insertions(+), 7 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/i2c-algo-bit.h b/sys/compat/linuxkpi/common/include/linux/i2c-algo-bit.h new file mode 100644 index 000000000000..4e8f00f9bebc --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/i2c-algo-bit.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * + * 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. + * + */ + +#ifndef _LINUX_I2C_ALGO_BIT_H_ +#define _LINUX_I2C_ALGO_BIT_H_ + +#include + +struct i2c_algo_bit_data { + void *data; + void (*setsda) (void *data, int state); + void (*setscl) (void *data, int state); + int (*getsda) (void *data); + int (*getscl) (void *data); + int (*pre_xfer) (struct i2c_adapter *); + void (*post_xfer) (struct i2c_adapter *); + + int udelay; + int timeout; +}; + +int lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter); + +#define i2c_bit_add_bus(adapter) lkpi_i2c_bit_add_bus(adapter) + +#endif /*_LINUX_I2C_ALGO_BIT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/i2c.h b/sys/compat/linuxkpi/common/include/linux/i2c.h new file mode 100644 index 000000000000..0bb8b470edd7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/i2c.h @@ -0,0 +1,152 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * + * 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. + * + */ + +#ifndef _LINUX_I2C_H_ +#define _LINUX_I2C_H_ + +#include +#include +#include + +#include + +#define I2C_MAX_ADAPTER_NAME_LENGTH 32 + +#define I2C_M_RD 0x0001 +#define I2C_M_NOSTART 0x0002 +#define I2C_M_STOP 0x0004 + +/* No need for us */ +#define I2C_FUNC_I2C 0 +#define I2C_FUNC_SMBUS_EMUL 0 +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0 +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0 +#define I2C_FUNC_10BIT_ADDR 0 + +#define I2C_CLASS_DDC 0x8 +#define I2C_CLASS_SPD 0x80 + +struct i2c_adapter { + struct module *owner; + unsigned int class; + + char name[I2C_MAX_ADAPTER_NAME_LENGTH]; + struct device dev; + + const struct i2c_lock_operations *lock_ops; + const struct i2c_algorithm *algo; + void *algo_data; + + int retries; + void *data; +}; + +struct i2c_msg { + uint16_t addr; + uint16_t flags; + uint16_t len; + uint8_t *buf; +}; + +struct i2c_algorithm { + int (*master_xfer)(struct i2c_adapter *, struct i2c_msg *, int); + uint32_t (*functionality)(struct i2c_adapter *); +}; + +struct i2c_lock_operations { + void (*lock_bus)(struct i2c_adapter *, unsigned int); + int (*trylock_bus)(struct i2c_adapter *, unsigned int); + void (*unlock_bus)(struct i2c_adapter *, unsigned int); +}; + +int lkpi_i2c_add_adapter(struct i2c_adapter *adapter); +int lkpi_i2c_del_adapter(struct i2c_adapter *adapter); + +int lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs); + +#define i2c_add_adapter(adapter) lkpi_i2c_add_adapter(adapter) +#define i2c_del_adapter(adapter) lkpi_i2c_del_adapter(adapter) + +#define i2c_get_adapter(x) NULL +#define i2c_put_adapter(x) + +static inline int +do_i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) +{ + int ret, retries; + + retries = adapter->retries == 0 ? 1 : adapter->retries; + for (; retries != 0; retries--) { + if (adapter->algo->master_xfer != NULL) + ret = adapter->algo->master_xfer(adapter, msgs, nmsgs); + else + ret = lkpi_i2cbb_transfer(adapter, msgs, nmsgs); + if (ret != -EAGAIN) + break; + } + + return (ret); +} + +static inline int +i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) +{ + int ret; + + if (!adapter->algo) + return (-EOPNOTSUPP); + + if (adapter->lock_ops) + adapter->lock_ops->lock_bus(adapter, 0); + + ret = do_i2c_transfer(adapter, msgs, nmsgs); + + if (adapter->lock_ops) + adapter->lock_ops->unlock_bus(adapter, 0); + + return (ret); +} + +/* Unlocked version of i2c_transfer */ +static inline int +__i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) +{ + return (do_i2c_transfer(adapter, msgs, nmsgs)); +} + +static inline void +i2c_set_adapdata(struct i2c_adapter *adapter, void *data) +{ + adapter->data = data; +} + +static inline void * +i2c_get_adapdata(struct i2c_adapter *adapter) +{ + return (adapter->data); +} + +#endif /* _LINUX_I2C_H_ */ diff --git a/sys/compat/linuxkpi/common/src/linux_i2c.c b/sys/compat/linuxkpi/common/src/linux_i2c.c new file mode 100644 index 000000000000..cd002da49b19 --- /dev/null +++ b/sys/compat/linuxkpi/common/src/linux_i2c.c @@ -0,0 +1,217 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * + * 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. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "iicbus_if.h" +#include "iicbb_if.h" +#include "lkpi_iic_if.h" + +static int lkpi_i2c_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs); +static int lkpi_i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr); + +struct lkpi_iic_softc { + device_t iicbus; + struct i2c_adapter *adapter; +}; + +static int +lkpi_iic_probe(device_t dev) +{ + + device_set_desc(dev, "LinuxKPI I2C"); + return (BUS_PROBE_NOWILDCARD); +} + +static int +lkpi_iic_attach(device_t dev) +{ + struct lkpi_iic_softc *sc; + + sc = device_get_softc(dev); + sc->iicbus = device_add_child(dev, "iicbus", -1); + if (sc->iicbus == NULL) { + device_printf(dev, "Couldn't add iicbus child, aborting\n"); + return (ENXIO); + } + bus_generic_attach(dev); + return (0); +} + +static int +lkpi_iic_detach(device_t dev) +{ + struct lkpi_iic_softc *sc; + + sc = device_get_softc(dev); + if (sc->iicbus) + device_delete_child(dev, sc->iicbus); + return (0); +} + +static int +lkpi_iic_add_adapter(device_t dev, struct i2c_adapter *adapter) +{ + struct lkpi_iic_softc *sc; + + sc = device_get_softc(dev); + sc->adapter = adapter; + + return (0); +} + +static device_method_t lkpi_iic_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, lkpi_iic_probe), + DEVMETHOD(device_attach, lkpi_iic_attach), + DEVMETHOD(device_detach, lkpi_iic_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* iicbus interface */ + DEVMETHOD(iicbus_transfer, lkpi_i2c_transfer), + DEVMETHOD(iicbus_reset, lkpi_i2c_reset), + DEVMETHOD(iicbus_callback, iicbus_null_callback), + + /* lkpi_iic interface */ + DEVMETHOD(lkpi_iic_add_adapter, lkpi_iic_add_adapter), + + DEVMETHOD_END +}; + +devclass_t lkpi_iic_devclass; + +driver_t lkpi_iic_driver = { + "lkpi_iic", + lkpi_iic_methods, + sizeof(struct lkpi_iic_softc), +}; + +DRIVER_MODULE(lkpi_iic, drmn, lkpi_iic_driver, lkpi_iic_devclass, 0, 0); +DRIVER_MODULE(iicbus, lkpi_iic, iicbus_driver, iicbus_devclass, 0, 0); + +static int +lkpi_i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) +{ + + /* That doesn't seems to be supported in linux */ + return (0); +} + +static int +lkpi_i2c_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) +{ + struct lkpi_iic_softc *sc; + struct i2c_msg *linux_msgs; + int i, ret = 0; + + sc = device_get_softc(dev); + if (sc->adapter == NULL) + return (ENXIO); + linux_set_current(curthread); + + linux_msgs = malloc(sizeof(struct i2c_msg) * nmsgs, + M_DEVBUF, M_WAITOK | M_ZERO); + + for (i = 0; i < nmsgs; i++) { + linux_msgs[i].addr = msgs[i].slave; + linux_msgs[i].len = msgs[i].len; + linux_msgs[i].buf = msgs[i].buf; + if (msgs[i].flags & IIC_M_RD) { + linux_msgs[i].flags |= I2C_M_RD; + for (int j = 0; j < msgs[i].len; j++) + msgs[i].buf[j] = 0; + } + if (msgs[i].flags & IIC_M_NOSTART) + linux_msgs[i].flags |= I2C_M_NOSTART; + } + ret = i2c_transfer(sc->adapter, linux_msgs, nmsgs); + free(linux_msgs, M_DEVBUF); + + if (ret < 0) + return (-ret); + return (0); +} + +int +lkpi_i2c_add_adapter(struct i2c_adapter *adapter) +{ + device_t lkpi_iic; + int error; + + if (bootverbose) + device_printf(adapter->dev.parent->bsddev, + "Adding i2c adapter %s\n", adapter->name); + lkpi_iic = device_add_child(adapter->dev.parent->bsddev, "lkpi_iic", -1); + if (lkpi_iic == NULL) { + device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iic\n"); + return (ENXIO); + } + + error = bus_generic_attach(adapter->dev.parent->bsddev); + if (error) { + device_printf(adapter->dev.parent->bsddev, + "failed to attach child: error %d\n", error); + return (ENXIO); + } + LKPI_IIC_ADD_ADAPTER(lkpi_iic, adapter); + return (0); +} + +int +lkpi_i2c_del_adapter(struct i2c_adapter *adapter) +{ + device_t child; + + if (bootverbose) + device_printf(adapter->dev.parent->bsddev, + "Removing i2c adapter %s\n", adapter->name); + + child = device_find_child(adapter->dev.parent->bsddev, "lkpi_iic", -1); + if (child != NULL) + device_delete_child(adapter->dev.parent->bsddev, child); + + child = device_find_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1); + if (child != NULL) + device_delete_child(adapter->dev.parent->bsddev, child); + + return (0); +} diff --git a/sys/compat/linuxkpi/common/src/linux_i2cbb.c b/sys/compat/linuxkpi/common/src/linux_i2cbb.c new file mode 100644 index 000000000000..06d9ecd6a1fa --- /dev/null +++ b/sys/compat/linuxkpi/common/src/linux_i2cbb.c @@ -0,0 +1,252 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * + * 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. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "iicbb_if.h" +#include "lkpi_iic_if.h" + +static void lkpi_iicbb_setsda(device_t dev, int val); +static void lkpi_iicbb_setscl(device_t dev, int val); +static int lkpi_iicbb_getscl(device_t dev); +static int lkpi_iicbb_getsda(device_t dev); +static int lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr); + +struct lkpi_iicbb_softc { + device_t iicbb; + struct i2c_adapter *adapter; +}; + +static int +lkpi_iicbb_probe(device_t dev) +{ + + device_set_desc(dev, "LinuxKPI I2CBB"); + return (BUS_PROBE_NOWILDCARD); +} + +static int +lkpi_iicbb_attach(device_t dev) +{ + struct lkpi_iicbb_softc *sc; + + sc = device_get_softc(dev); + sc->iicbb = device_add_child(dev, "iicbb", -1); + if (sc->iicbb == NULL) { + device_printf(dev, "Couldn't add iicbb child, aborting\n"); + return (ENXIO); + } + bus_generic_attach(dev); + return (0); +} + +static int +lkpi_iicbb_detach(device_t dev) +{ + struct lkpi_iicbb_softc *sc; + + sc = device_get_softc(dev); + if (sc->iicbb) + device_delete_child(dev, sc->iicbb); + return (0); +} + +static int +lkpi_iicbb_add_adapter(device_t dev, struct i2c_adapter *adapter) +{ + struct lkpi_iicbb_softc *sc; + + sc = device_get_softc(dev); + sc->adapter = adapter; + + return (0); +} + +static device_method_t lkpi_iicbb_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, lkpi_iicbb_probe), + DEVMETHOD(device_attach, lkpi_iicbb_attach), + DEVMETHOD(device_detach, lkpi_iicbb_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* iicbb interface */ + DEVMETHOD(iicbb_setsda, lkpi_iicbb_setsda), + DEVMETHOD(iicbb_setscl, lkpi_iicbb_setscl), + DEVMETHOD(iicbb_getsda, lkpi_iicbb_getsda), + DEVMETHOD(iicbb_getscl, lkpi_iicbb_getscl), + DEVMETHOD(iicbb_reset, lkpi_iicbb_reset), + + /* lkpi_iicbb interface */ + DEVMETHOD(lkpi_iic_add_adapter, lkpi_iicbb_add_adapter), + + DEVMETHOD_END +}; + +static devclass_t lkpi_iicbb_devclass; + +driver_t lkpi_iicbb_driver = { + "lkpi_iicbb", + lkpi_iicbb_methods, + sizeof(struct lkpi_iicbb_softc), +}; + +DRIVER_MODULE(lkpi_iicbb, lkpi_iic, lkpi_iicbb_driver, lkpi_iicbb_devclass, 0, 0); +DRIVER_MODULE(iicbb, lkpi_iicbb, iicbb_driver, iicbb_devclass, 0, 0); +MODULE_DEPEND(lkpi_iicbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); + +static void +lkpi_iicbb_setsda(device_t dev, int val) +{ + struct lkpi_iicbb_softc *sc; + struct i2c_algo_bit_data *algo_data; + + sc = device_get_softc(dev); + algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; + algo_data->setsda(algo_data->data, val); + cpu_spinwait(); + DELAY(algo_data->udelay); +} + +static void +lkpi_iicbb_setscl(device_t dev, int val) +{ + struct lkpi_iicbb_softc *sc; + struct i2c_algo_bit_data *algo_data; + + sc = device_get_softc(dev); + + algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; + algo_data->setscl(algo_data->data, val); + cpu_spinwait(); + DELAY(algo_data->udelay); +} + +static int +lkpi_iicbb_getscl(device_t dev) +{ + struct lkpi_iicbb_softc *sc; + struct i2c_algo_bit_data *algo_data; + unsigned long orig_ticks; + int ret = 0; + + sc = device_get_softc(dev); + + algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; + + orig_ticks = ticks; + while (!ret) { + ret = algo_data->getscl(algo_data->data); + + if (ret) + break; + + if (ticks > orig_ticks + algo_data->timeout) + return (ETIMEDOUT); + + cpu_spinwait(); + DELAY(algo_data->udelay); + } + DELAY(algo_data->udelay); + return (ret); +} + +static int +lkpi_iicbb_getsda(device_t dev) +{ + struct lkpi_iicbb_softc *sc; + struct i2c_algo_bit_data *algo_data; + int ret = 0; + + sc = device_get_softc(dev); + algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data; + + cpu_spinwait(); + DELAY(algo_data->udelay); + ret = algo_data->getsda(algo_data->data); + cpu_spinwait(); + DELAY(algo_data->udelay); + return (ret); +} + +static int +lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) +{ + struct lkpi_iicbb_softc *sc; + + sc = device_get_softc(dev); + + return (0); +} + +int +lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) +{ + + /* TODO: convert from i2c_msg to iic_msg and call IICBUS_TRANFER */ + return (0); +} + +int +lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter) +{ + device_t lkpi_iicbb; + int error; + + if (bootverbose) + device_printf(adapter->dev.parent->bsddev, + "Adding i2c adapter %s\n", adapter->name); + lkpi_iicbb = device_add_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1); + if (lkpi_iicbb == NULL) { + device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iicbb\n"); + return (ENXIO); + } + + error = bus_generic_attach(adapter->dev.parent->bsddev); + if (error) { + device_printf(adapter->dev.parent->bsddev, + "failed to attach child: error %d\n", error); + return (ENXIO); + } + LKPI_IIC_ADD_ADAPTER(lkpi_iicbb, adapter); + return (0); +} + diff --git a/sys/compat/linuxkpi/common/src/lkpi_iic_if.m b/sys/compat/linuxkpi/common/src/lkpi_iic_if.m new file mode 100644 index 000000000000..2379182c409b --- /dev/null +++ b/sys/compat/linuxkpi/common/src/lkpi_iic_if.m @@ -0,0 +1,37 @@ +#- +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# +# Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG +# +# 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. +# + +INTERFACE lkpi_iic; + +HEADER { + struct i2c_adapter; +} + +METHOD int add_adapter { + device_t dev; + struct i2c_adapter *adapter; +}; diff --git a/sys/conf/files b/sys/conf/files index 5b33d66f3377..4ff4d1761a41 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1820,7 +1820,7 @@ dev/ichsmb/ichsmb_pci.c optional ichsmb pci dev/ida/ida.c optional ida dev/ida/ida_disk.c optional ida dev/ida/ida_pci.c optional ida pci -dev/iicbus/acpi_iicbus.c optional acpi iicbus +dev/iicbus/acpi_iicbus.c optional acpi iicbus | acpi compat_linuxkpi dev/iicbus/ad7418.c optional ad7418 dev/iicbus/ads111x.c optional ads111x dev/iicbus/ds1307.c optional ds1307 @@ -1831,13 +1831,13 @@ dev/iicbus/htu21.c optional htu21 dev/iicbus/icee.c optional icee dev/iicbus/if_ic.c optional ic dev/iicbus/iic.c optional iic -dev/iicbus/iic_recover_bus.c optional iicbus -dev/iicbus/iicbb.c optional iicbb -dev/iicbus/iicbb_if.m optional iicbb -dev/iicbus/iicbus.c optional iicbus -dev/iicbus/iicbus_if.m optional iicbus +dev/iicbus/iic_recover_bus.c optional iicbus | compat_linuxkpi +dev/iicbus/iicbb.c optional iicbb | compat_linuxkpi +dev/iicbus/iicbb_if.m optional iicbb | compat_linuxkpi +dev/iicbus/iicbus.c optional iicbus | compat_linuxkpi +dev/iicbus/iicbus_if.m optional iicbus | compat_linuxkpi dev/iicbus/iichid.c optional iichid acpi hid iicbus -dev/iicbus/iiconf.c optional iicbus +dev/iicbus/iiconf.c optional iicbus | compat_linuxkpi dev/iicbus/iicsmb.c optional iicsmb \ dependency "iicbus_if.h" dev/iicbus/iicoc.c optional iicoc @@ -4552,6 +4552,10 @@ compat/linuxkpi/common/src/linux_fpu.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_hrtimer.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" +compat/linuxkpi/common/src/linux_i2c.c optional compat_linuxkpi \ + compile-with "${LINUXKPI_C}" +compat/linuxkpi/common/src/linux_i2cbb.c optional compat_linuxkpi \ + compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_interrupt.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_kthread.c optional compat_linuxkpi \ @@ -4588,6 +4592,7 @@ compat/linuxkpi/common/src/linux_work.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_xarray.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" +compat/linuxkpi/common/src/lkpi_iic_if.m optional compat_linuxkpi compat/linuxkpi/common/src/linux_seq_file.c optional compat_linuxkpi | lindebugfs \ compile-with "${LINUXKPI_C}" diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index cf39de5e87cf..54d57b069435 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -96,6 +96,10 @@ LINUXKPI_GENSRCS+= \ backlight_if.h \ bus_if.h \ device_if.h \ + iicbus_if.h \ + iicbb_if.h \ + lkpi_iic_if.c \ + lkpi_iic_if.h \ pci_if.h \ pci_iov_if.h \ pcib_if.h \ diff --git a/sys/modules/linuxkpi/Makefile b/sys/modules/linuxkpi/Makefile index 4d15ac9fa962..6a256bf1f8e1 100644 --- a/sys/modules/linuxkpi/Makefile +++ b/sys/modules/linuxkpi/Makefile @@ -12,6 +12,8 @@ SRCS= linux_compat.c \ linux_hrtimer.c \ linux_idr.c \ linux_interrupt.c \ + linux_i2c.c \ + linux_i2cbb.c \ linux_kmod.c \ linux_kthread.c \ linux_lock.c \