From nobody Tue Jun 21 15:23:09 2022 X-Original-To: dev-commits-src-branches@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 7A15E869D66; Tue, 21 Jun 2022 15:23:09 +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 4LS9JF2z4kz4g7m; Tue, 21 Jun 2022 15:23:09 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1655824989; 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=YSCh9Tw/i3a0ZfE3yifQSW+VOz9YV6KV0zCEL1c+XdA=; b=qLP66Aw8vgRxFzdsYR3iNGd7T11P3h6oX/0zPrYHU82GsFAwamG19yZA34eD7oLkpcg7CJ 5UfSrNxOs/zYK67flbSMvwrg0aLO8P8k9URIx/QN7yDs6Lj5XiDbqF5jZ2DtSqYwqGvPON RG8X/Y/V/eq5UFNd7WvNJDN5k91db4NapUDeQoOsmuD4Os6niWzhME3AxRHqC/nnm3xZp7 RwEyBJB1U/YtweAkI0xpIJ4OY60vVleK8MsOoq7mSXXEEKHK8jizINx3A26Ka77KZQi/W+ 1feA08nSio+t9aRbLNVjO7j6JCK0E30Wx/w6ydx1fO+8WBLqDy3zDD4ZOficqA== 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 4650D14643; Tue, 21 Jun 2022 15:23:09 +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 25LFN9jK062830; Tue, 21 Jun 2022 15:23:09 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 25LFN9GL062829; Tue, 21 Jun 2022 15:23:09 GMT (envelope-from git) Date: Tue, 21 Jun 2022 15:23:09 GMT Message-Id: <202206211523.25LFN9GL062829@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Emmanuel Vadot Subject: git: 7f14bc44022d - stable/13 - linuxkpi: Add i2c support List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@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/stable/13 X-Git-Reftype: branch X-Git-Commit: 7f14bc44022da73cfdb0dd6d73a4ade239c7e857 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1655824989; 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=YSCh9Tw/i3a0ZfE3yifQSW+VOz9YV6KV0zCEL1c+XdA=; b=U2Vmd0X7V+RxAQ0ih4c6dwuK8JyVg7+6rIMCr7tCcqd7tqqLJ2Mn5zKvvvT/ZCIYUnywUc UDsauh6xc7makKqOG9vkNhiJppmRfYy0XhlvR0y2tWfRMGUkuOsvYXTRF9BFwzyxYDxnca cw3Cr/xrDo5yxUfTAYfw1HEwZcXaIMLPWgaaEv9+XC9b1SkjiWwHUxchwlg3cvcXHD0AIT YULGgluTDiX6QqhW2aLrdAkbiHc2dsg631IMDFAiOjGRK8s1YGPVLW97lvbs097y5Qk9NC SG8WsxiEgudI7Q8vWV3AIrtr3lTgZzg02BKTTXkoFjjOG5mGCQLf9AouxXdtcQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1655824989; a=rsa-sha256; cv=none; b=LqexDDpnlq0sStSqGE1HYcNASSj1BICo4ij6NTFPFadDo01wbTDINpSxg1ansEeklb6X4n pVhGYne8OiyAoB6lePqauew84DbUWe6qljDk3ve7dbmJNrTAwHff2ADkJiRDdAA1sPRnTT Gd/fBHWXEv2UkN038P530ueYML3zrgImghEpuVkUQ+kRmSQ8yz7AqRmFZSIorTNfXpTwVA MMfx3z9ISWnQdhA8i1+SE091SOKYNdZ5jujpU+1mBsqQNNRUbdhFwK++FSY8bOBRnYuugC /k5VFQ+xYgMsJSx/4CmANwQow/L8MCAWhbJHlKPPkrYaoT64jwV3Wq3VgDFVTA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by manu: URL: https://cgit.FreeBSD.org/src/commit/?id=7f14bc44022da73cfdb0dd6d73a4ade239c7e857 commit 7f14bc44022da73cfdb0dd6d73a4ade239c7e857 Author: Emmanuel Vadot AuthorDate: 2021-11-04 09:42:37 +0000 Commit: Emmanuel Vadot CommitDate: 2022-06-21 15:13:57 +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 (cherry picked from commit 1961a14a47437595fb7fcdc20e327440e3eb51e2) --- .../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 7fc99a929947..81781ab0bc66 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1850,7 +1850,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 @@ -1861,13 +1861,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 @@ -4597,6 +4597,10 @@ compat/linuxkpi/common/src/linux_firmware.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 \ @@ -4633,6 +4637,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 629b7554f005..cc5d394bb186 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -94,6 +94,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 f478ebbe0baf..e34bd1e954d7 100644 --- a/sys/modules/linuxkpi/Makefile +++ b/sys/modules/linuxkpi/Makefile @@ -11,6 +11,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 \