[PATCH 3/5] Add rtems i2c adaptation layer

Christian Mauderer list at c-mauderer.de
Wed Jun 5 18:53:21 UTC 2019


On 01/06/2019 21:20, Vijay Kumar Banerjee wrote:
> ---
>  libbsd.py                |   1 +
>  rtemsbsd/i2c/rtems-i2c.c | 218 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 219 insertions(+)
>  create mode 100644 rtemsbsd/i2c/rtems-i2c.c

I think the file would be better located at
    rtemsbsd/sys/dev/iicbus/rtems-i2c.c

The directory structure for drivers should be similar to the one in FreeBSD.

> 
> diff --git a/libbsd.py b/libbsd.py
> index a25d3a8a..6e8ff987 100644
> --- a/libbsd.py
> +++ b/libbsd.py
> @@ -771,6 +771,7 @@ class iic(builder.Module):
>          self.addRTEMSSourceFiles(
>              [
>                  'local/iicbus_if.c',
> +                'i2c/rtems-i2c.c',
>              ],
>              mm.generator['source']()
>          )
> diff --git a/rtemsbsd/i2c/rtems-i2c.c b/rtemsbsd/i2c/rtems-i2c.c
> new file mode 100644
> index 00000000..5189e5fe
> --- /dev/null
> +++ b/rtemsbsd/i2c/rtems-i2c.c
> @@ -0,0 +1,218 @@
> +/*
> + * Copyright (c) 2019 Vijay Kumar Banerjee <vijaykumar9597 at gmail.com>.
> + * 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.
> + */
> +
> +#include <machine/rtems-bsd-kernel-space.h>
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <fcntl.h>
> +
> +#include <sys/module.h>
> +#include <sys/param.h>
> +#include <sys/kernel.h>
> +#include <sys/errno.h>
> +#include <sys/bus.h>
> +
> +#include <dev/iicbus/iicbus.h>
> +#include <dev/iicbus/iic.h>
> +#include <dev/iicbus/iiconf.h>
> +#include <dev/ofw/ofw_bus.h>
> +#include <dev/ofw/ofw_bus_subr.h>
> +#include <dev/ofw/openfirm.h>
> +
> +#include <rtems/bsd/local/iicbus_if.h>
> +
> +#include <linux/i2c.h>
> +#include <linux/i2c-dev.h>
> +
> +typedef struct i2c_msg i2c_msg;
> +
> +struct i2c_softc {
> +	device_t dev;
> +	device_t sc_iicbus;
> +	char *path;
> +	int fd;
> +	int mem_rid;
> +	int irq_rid;

mem_rid and irq_rid seem to be unused.

> +};
> +
> +static int
> +rtems_i2c_probe(device_t dev)
> +{
> +	if (!ofw_bus_status_okay(dev)) {
> +		return (ENXIO);
> +	}
> +	if (!ofw_bus_is_compatible(dev, "rtems,bsp-i2c")){
> +		return (ENXIO);
> +	}
> +
> +	device_set_desc(dev, "RTEMS libbsd I2C");
> +	return (BUS_PROBE_SPECIFIC);
> +}
> +
> +static int
> +rtems_i2c_attach(device_t dev)
> +{
> +	phandle_t node;
> +	ssize_t compatlen;
> +	char *compat;
> +	char *curstr;
> +	struct i2c_softc *sc;
> +	int len;
> +
> +	sc = device_get_softc(dev);
> +	sc->dev = dev;
> +	node = ofw_bus_get_node(sc->dev);
> +
> +	len = OF_getprop_alloc(node, "rtems,i2c-path", &sc->path);
> +	if (len == -1){
> +		device_printf(sc->dev, "Path not found in Device Tree");
> +		OF_prop_free(sc->path);
> +		return (ENXIO);
> +	}
> +	else{

You don't really need the else here. If your error case hits, you return
anyway. So you can save one level of indentation for the next block.

> +		if ((sc->sc_iicbus = device_add_child(sc->dev, "iicbus", -1)) == NULL) {
> +			device_printf(sc->dev, "could not allocate iicbus instance\n");
> +			OF_prop_free(sc->path);
> +			return (ENXIO);
> +		}
> +		config_intrhook_oneshot((ich_func_t)bus_generic_attach, sc->dev);
> +	}
> +	return (0);
> +}
> +
> +static int
> +rtems_i2c_detach(device_t dev)
> +{
> +	struct i2c_softc *sc;
> +	int error;
> +
> +	sc = device_get_softc(dev);
> +
> +	OF_prop_free(sc->path);
> +
> +	if (sc->sc_iicbus && (error = device_delete_child(dev, sc->sc_iicbus)) != 0)
> +		return (error);
> +
> +	if ((error = bus_generic_detach(sc->dev)) != 0) {
> +		device_printf(sc->dev, "cannot detach child devices\n");
> +		return (error);
> +	}

Maybe we misunderstood each other there in our chat: The detach should
have roughly a reverse order of the attach. The last action in your
attach is the bus_generic_attach so the first one in detach should be
the bus_generic_detach.

> +
> +
> +	return (0);
> +}
> +
> +static int
> +rtems_i2c_transfer(device_t dev, struct iic_msg *msgs, u_int num)
> +{
> +	i2c_msg *messages;
> +	int err;
> +	char *addr;
> +	struct i2c_softc *sc;
> +	struct i2c_rdwr_ioctl_data ioctl_data;
> +
> +	sc = device_get_softc(dev);
> +
> +	/* Open /dev/iic0 */
> +	sc->fd = open(sc->path, O_RDWR);

Why save the fd in the softc if you only use it in this function? You
can use a local variable here.

> +	if (sc->fd < 0) {
> +		device_printf(sc->dev, "%s\n", strerror(errno));
> +		return errno;
> +	}
> +
> +	/* cast iic_msg to i2c_msg */
> +	messages = (i2c_msg *) msgs;
> +	ioctl_data.msgs = messages;
> +	ioctl_data.nmsgs = num;
> +
> +	/* IOCTL call to write */
> +	err = ioctl(sc->fd, I2C_RDWR, &ioctl_data);
> +	if (err < 0){
> +		device_printf(sc->dev, "%s\n", strerror(errno));
> +		close(sc->fd);
> +		return errno;
> +	}
> +
> +	/* Close the device */
> +	close(sc->fd);
> +
> +	return (0);
> +}
> +
> +static int
> +rtems_i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
> +{
> +	return (0);
> +}
> +
> +static phandle_t
> +rtems_i2c_get_node(device_t bus, device_t dev)
> +{
> +
> +	/* Share controller node with iibus device. */
> +	return (ofw_bus_get_node(bus));
> +}
> +
> +static device_method_t rtems_i2c_methods[] = {
> +	/* Device Interface */
> +	DEVMETHOD(device_probe,		rtems_i2c_probe),
> +	DEVMETHOD(device_attach,	rtems_i2c_attach),
> +	DEVMETHOD(device_detach,	rtems_i2c_detach),
> +
> +	/* Bus interface */
> +	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
> +	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
> +	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
> +	DEVMETHOD(bus_release_resource, bus_generic_release_resource),
> +	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
> +	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
> +	DEVMETHOD(bus_adjust_resource,	bus_generic_adjust_resource),
> +	DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
> +	DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
> +
> +	/* OFW methods */
> +	DEVMETHOD(ofw_bus_get_node, rtems_i2c_get_node),
> +
> +	/* iicbus interface */
> +	DEVMETHOD(iicbus_callback,	iicbus_null_callback),
> +	DEVMETHOD(iicbus_reset,		rtems_i2c_reset),
> +	DEVMETHOD(iicbus_transfer,	rtems_i2c_transfer),
> +
> +	DEVMETHOD_END
> +};
> +
> +static driver_t rtems_i2c_driver = {
> +	"rtems_i2c",
> +	rtems_i2c_methods,
> +	sizeof(struct i2c_softc),
> +};
> +
> +static devclass_t rtems_i2c_devclass;
> +DRIVER_MODULE(rtems_i2c, simplebus, rtems_i2c_driver, rtems_i2c_devclass, 0, 0);
> +DRIVER_MODULE(iicbus, rtems_i2c, iicbus_driver, iicbus_devclass, 0, 0);
> +DRIVER_MODULE(ofw_iicbus, rtems_i2c, ofw_iicbus_driver, ofw_iicbus_devclass, 0, 0);
> 




More information about the devel mailing list