Date: Tue, 21 Jun 2022 15:23:09 GMT From: Emmanuel Vadot <manu@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 7f14bc44022d - stable/13 - linuxkpi: Add i2c support Message-ID: <202206211523.25LFN9GL062829@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by manu: URL: https://cgit.FreeBSD.org/src/commit/?id=7f14bc44022da73cfdb0dd6d73a4ade239c7e857 commit 7f14bc44022da73cfdb0dd6d73a4ade239c7e857 Author: Emmanuel Vadot <manu@FreeBSD.org> AuthorDate: 2021-11-04 09:42:37 +0000 Commit: Emmanuel Vadot <manu@FreeBSD.org> 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 <linux/i2c.h> + +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 <sys/types.h> +#include <sys/errno.h> +#include <sys/systm.h> + +#include <linux/device.h> + +#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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/malloc.h> + +#include <dev/iicbus/iicbus.h> +#include <dev/iicbus/iiconf.h> + +#include <linux/device.h> +#include <linux/i2c.h> +#include <linux/i2c-algo-bit.h> +#include <linux/list.h> +#include <linux/pci.h> + +#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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/malloc.h> + +#include <dev/iicbus/iicbus.h> +#include <dev/iicbus/iiconf.h> + +#include <linux/device.h> +#include <linux/i2c.h> +#include <linux/i2c-algo-bit.h> +#include <linux/list.h> +#include <linux/pci.h> + +#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 \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202206211523.25LFN9GL062829>