From mboxrd@z Thu Jan 1 00:00:00 1970 From: Xiang W Date: Sat, 25 Sep 2021 12:39:59 +0800 Subject: [PATCH 2/4] lib: utils/gpio: Add simple FDT based I2C framework In-Reply-To: <20210924113347.3576-3-nikita.shubin@maquefel.me> References: <20210924113347.3576-1-nikita.shubin@maquefel.me> <20210924113347.3576-3-nikita.shubin@maquefel.me> Message-ID: <8f2fa486cd3d4fa1546d6b7d678dd7e223e23575.camel@126.com> List-Id: To: opensbi@lists.infradead.org MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit ? 2021-09-24???? 14:33 +0300?Nikita Shubin??? > From: Nikita Shubin > > FDT based I2C framework on the top of I2C library. > > The drivers are probed on demand by fdt_i2c_adapter_get > function. > > Signed-off-by: Nikita Shubin > --- > ?include/sbi_utils/i2c/fdt_i2c.h |? 26 ++++++++ > ?lib/utils/i2c/fdt_i2c.c???????? | 107 > ++++++++++++++++++++++++++++++++ > ?lib/utils/i2c/objects.mk??????? |?? 1 + > ?3 files changed, 134 insertions(+) > ?create mode 100644 include/sbi_utils/i2c/fdt_i2c.h > ?create mode 100644 lib/utils/i2c/fdt_i2c.c > > diff --git a/include/sbi_utils/i2c/fdt_i2c.h > b/include/sbi_utils/i2c/fdt_i2c.h > new file mode 100644 > index 0000000..1f41a0f > --- /dev/null > +++ b/include/sbi_utils/i2c/fdt_i2c.h > @@ -0,0 +1,26 @@ > +/* > + * SPDX-License-Identifier: BSD-2-Clause > + * > + * Copyright (c) 2021 YADRO > + * > + * Authors: > + *?? Nikita Shubin > + */ > + > +#ifndef __FDT_I2C_H__ > +#define __FDT_I2C_H__ > + > +#include > + > +/** FDT based I2C adapter driver */ > +struct fdt_i2c_adapter { > +???????const struct fdt_match *match_table; > +???????int (*init)(void *fdt, int nodeoff, > +?????????????????? const struct fdt_match *match); > +}; > + > +/** Get I2C adapter identified by nodeoff */ > +int fdt_i2c_adapter_get(void *fdt, int nodeoff, > +???????????????????????struct i2c_adapter **out_adapter); > + > +#endif > diff --git a/lib/utils/i2c/fdt_i2c.c b/lib/utils/i2c/fdt_i2c.c > new file mode 100644 > index 0000000..27e28a4 > --- /dev/null > +++ b/lib/utils/i2c/fdt_i2c.c > @@ -0,0 +1,107 @@ > +/* > + * SPDX-License-Identifier: BSD-2-Clause > + * > + * Copyright (c) 2021 YADRO > + * > + * Authors: > + *?? Nikita Shubin > + * > + * derivate: lib/utils/gpio/fdt_gpio.c > + * Authors: > + *?? Anup Patel > + */ > + > +#include > +#include > +#include > +#include > + > +#include > + > +static struct fdt_i2c_adapter *i2c_adapter_drivers[] = { > +}; > + > +static struct fdt_i2c_adapter *fdt_i2c_adapter_driver(struct > i2c_adapter *adapter) > +{ > +???????int pos; > + > +???????if (!adapter) > +???????????????return NULL; > + > +???????for (pos = 0; pos < array_size(i2c_adapter_drivers); pos++) { > +???????????????if (adapter->driver == i2c_adapter_drivers[pos]) > +???????????????????????return i2c_adapter_drivers[pos]; > +???????} > + > +???????return NULL; > +} > + > +static int fdt_i2c_adapter_init(void *fdt, int nodeoff) > +{ > +???????int pos, rc; > +???????struct fdt_i2c_adapter *drv; > +???????const struct fdt_match *match; > + > +???????/* Try all I2C drivers one-by-one */ > +???????for (pos = 0; pos < array_size(i2c_adapter_drivers); pos++) { > +???????????????drv = i2c_adapter_drivers[pos]; > +???????????????match = fdt_match_node(fdt, nodeoff, drv- > >match_table); > +???????????????if (match && drv->init) { > +???????????????????????rc = drv->init(fdt, nodeoff, match); > +???????????????????????if (rc == SBI_ENODEV) > +???????????????????????????????continue; > +???????????????????????if (rc) > +???????????????????????????????return rc; > +???????????????????????return 0; > +???????????????} > +???????} > + > +???????return SBI_ENOSYS; > +} > + > +static int fdt_i2c_adapter_find(void *fdt, int nodeoff, > +???????????????????????????????struct i2c_adapter **out_adapter) > +{ > +???????int rc; > +???????struct i2c_adapter *adapter = i2c_adapter_find(nodeoff); > + > +???????if (!adapter) { > +???????????????/* I2C adapter not found so initialize matching > driver */ Reinitializing the I2C adapter may affect other adapters that have already been initialized. So I suggest to add a static variable, through this control the initial operation is executed once. Regards, Xiang W > +???????????????rc = fdt_i2c_adapter_init(fdt, nodeoff); > +???????????????if (rc) > +???????????????????????return rc; > + > +???????????????/* Try to find I2C adapter again */ > +???????????????adapter = i2c_adapter_find(nodeoff); > +???????????????if (!adapter) > +???????????????????????return SBI_ENOSYS; > +???????} > + > +???????if (out_adapter) > +???????????????*out_adapter = adapter; > + > +???????return 0; > +} > + > +int fdt_i2c_adapter_get(void *fdt, int nodeoff, > +???????????????????????struct i2c_adapter **out_adapter) > +{ > +???????int rc; > +???????struct i2c_adapter *adapter; > +???????struct fdt_i2c_adapter *drv; > + > +???????if (!fdt || (nodeoff < 0) || !out_adapter) > +???????????????return SBI_EINVAL; > + > +???????rc = fdt_i2c_adapter_find(fdt, nodeoff, &adapter); > +???????if (rc) > +???????????????return rc; > + > +???????drv = fdt_i2c_adapter_driver(adapter); > +???????if (!drv) > +???????????????return SBI_ENOSYS; > + > +???????*out_adapter = adapter; > + > +???????return 0; > +} > diff --git a/lib/utils/i2c/objects.mk b/lib/utils/i2c/objects.mk > index 16a70da..06baa65 100644 > --- a/lib/utils/i2c/objects.mk > +++ b/lib/utils/i2c/objects.mk > @@ -8,3 +8,4 @@ > ?# > ? > ?libsbiutils-objs-y += i2c/i2c.o > +libsbiutils-objs-y += i2c/fdt_i2c.o > -- > 2.31.1 > >