Message ID | 78605bb6b60148dc1fe68567708769fdcda71eb0.1460636146.git.michal.simek@xilinx.com |
---|---|
State | Superseded |
Delegated to: | Heiko Schocher |
Headers | show |
Hello Michal, Am 14.04.2016 um 14:15 schrieb Michal Simek: > Add support for common TI i2c mux which is available on ZynqMP zcu102 > board. > DM i2c mux core code is selecting/deselecting bus before/after > every command is performed that's why only one channel is active at a > time. That's also the reason why deselect is just disable all available > channels. > > Signed-off-by: Michal Simek <michal.simek@xilinx.com> > --- > > drivers/i2c/muxes/Kconfig | 7 ++++ > drivers/i2c/muxes/Makefile | 1 + > drivers/i2c/muxes/pca954x.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 87 insertions(+) > create mode 100644 drivers/i2c/muxes/pca954x.c Thanks for your work! I added Simon to CC, as he is the DM expert ;-) from my side, your patch looks fine, so: Reviewed-by: Heiko Schocher <hs@denx.de> bye, Heiko > diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig > index f959d9de9e8b..e16b902f9611 100644 > --- a/drivers/i2c/muxes/Kconfig > +++ b/drivers/i2c/muxes/Kconfig > @@ -24,3 +24,10 @@ config I2C_ARB_GPIO_CHALLENGE > I2C multimaster arbitration scheme using GPIOs and a challenge & > response mechanism where masters have to claim the bus by asserting > a GPIO. > + > +config I2C_MUX_PCA954X > + tristate "TI PCA954x I2C Mux/switches" > + depends on I2C_MUX > + help > + If you say yes here you get support for the TI PCA954x > + I2C mux/switch devices. > diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile > index 47c1240d7e9e..fb2d67ec9a97 100644 > --- a/drivers/i2c/muxes/Makefile > +++ b/drivers/i2c/muxes/Makefile > @@ -5,3 +5,4 @@ > # > obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE) += i2c-arb-gpio-challenge.o > obj-$(CONFIG_$(SPL_)I2C_MUX) += i2c-mux-uclass.o > +obj-$(CONFIG_I2C_MUX_PCA954X) += pca954x.o > diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c > new file mode 100644 > index 000000000000..206581d3d908 > --- /dev/null > +++ b/drivers/i2c/muxes/pca954x.c > @@ -0,0 +1,79 @@ > +/* > + * Copyright (C) 2015 - 2016 Xilinx, Inc. > + * Written by Michal Simek > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <errno.h> > +#include <i2c.h> > +#include <asm/gpio.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +struct pca95xx_priv { > + u32 addr; > + u32 width; > +}; > + > +static int pca95xx_deselect(struct udevice *mux, struct udevice *bus, > + uint channel) > +{ > + struct pca95xx_priv *priv = dev_get_priv(mux); > + uchar byte = 0; > + > + return dm_i2c_write(mux, priv->addr, &byte, 1); > +} > + > +static int pca95xx_select(struct udevice *mux, struct udevice *bus, > + uint channel) > +{ > + struct pca95xx_priv *priv = dev_get_priv(mux); > + uchar byte = 1 << channel; > + > + return dm_i2c_write(mux, priv->addr, &byte, 1); > +} > + > +static const struct i2c_mux_ops pca95xx_ops = { > + .select = pca95xx_select, > + .deselect = pca95xx_deselect, > +}; > + > +static const struct udevice_id pca95xx_ids[] = { > + { .compatible = "nxp,pca9548", .data = (ulong)8 }, > + { .compatible = "nxp,pca9544", .data = (ulong)4 }, > + { } > +}; > + > +static int pca95xx_ofdata_to_platdata(struct udevice *dev) > +{ > + struct pca95xx_priv *priv = dev_get_priv(dev); > + > + priv->addr = dev_get_addr(dev); > + if (!priv->addr) { > + debug("MUX not found\n"); > + return -ENOSYS; > + } > + priv->width = dev_get_driver_data(dev); > + > + if (!priv->width) { > + debug("No I2C MUX width specified\n"); > + return -ENOSYS; > + } > + > + debug("Device %s at 0x%x with width %d\n", > + dev->name, priv->addr, priv->width); > + > + return 0; > +} > + > +U_BOOT_DRIVER(pca95xx) = { > + .name = "pca95xx", > + .id = UCLASS_I2C_MUX, > + .of_match = pca95xx_ids, > + .ops = &pca95xx_ops, > + .ofdata_to_platdata = pca95xx_ofdata_to_platdata, > + .priv_auto_alloc_size = sizeof(struct pca95xx_priv), > +}; >
Hi Michal, On 14 April 2016 at 06:15, Michal Simek <michal.simek@xilinx.com> wrote: > Add support for common TI i2c mux which is available on ZynqMP zcu102 > board. > DM i2c mux core code is selecting/deselecting bus before/after > every command is performed that's why only one channel is active at a > time. That's also the reason why deselect is just disable all available > channels. > > Signed-off-by: Michal Simek <michal.simek@xilinx.com> > --- > > drivers/i2c/muxes/Kconfig | 7 ++++ > drivers/i2c/muxes/Makefile | 1 + > drivers/i2c/muxes/pca954x.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 87 insertions(+) > create mode 100644 drivers/i2c/muxes/pca954x.c nits below, but otherwise: Reviewed-by: Simon Glass <sjg@chromium.org> > > diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig > index f959d9de9e8b..e16b902f9611 100644 > --- a/drivers/i2c/muxes/Kconfig > +++ b/drivers/i2c/muxes/Kconfig > @@ -24,3 +24,10 @@ config I2C_ARB_GPIO_CHALLENGE > I2C multimaster arbitration scheme using GPIOs and a challenge & > response mechanism where masters have to claim the bus by asserting > a GPIO. > + > +config I2C_MUX_PCA954X > + tristate "TI PCA954x I2C Mux/switches" > + depends on I2C_MUX > + help > + If you say yes here you get support for the TI PCA954x > + I2C mux/switch devices. Can you add a few lines about what this device is? What does it allow? > diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile > index 47c1240d7e9e..fb2d67ec9a97 100644 > --- a/drivers/i2c/muxes/Makefile > +++ b/drivers/i2c/muxes/Makefile > @@ -5,3 +5,4 @@ > # > obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE) += i2c-arb-gpio-challenge.o > obj-$(CONFIG_$(SPL_)I2C_MUX) += i2c-mux-uclass.o > +obj-$(CONFIG_I2C_MUX_PCA954X) += pca954x.o > diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c > new file mode 100644 > index 000000000000..206581d3d908 > --- /dev/null > +++ b/drivers/i2c/muxes/pca954x.c > @@ -0,0 +1,79 @@ > +/* > + * Copyright (C) 2015 - 2016 Xilinx, Inc. > + * Written by Michal Simek > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <errno.h> > +#include <i2c.h> > +#include <asm/gpio.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +struct pca95xx_priv { > + u32 addr; ulong? > + u32 width; Comments? > +}; > + > +static int pca95xx_deselect(struct udevice *mux, struct udevice *bus, > + uint channel) > +{ > + struct pca95xx_priv *priv = dev_get_priv(mux); > + uchar byte = 0; > + > + return dm_i2c_write(mux, priv->addr, &byte, 1); > +} > + > +static int pca95xx_select(struct udevice *mux, struct udevice *bus, > + uint channel) > +{ > + struct pca95xx_priv *priv = dev_get_priv(mux); > + uchar byte = 1 << channel; > + > + return dm_i2c_write(mux, priv->addr, &byte, 1); > +} > + > +static const struct i2c_mux_ops pca95xx_ops = { > + .select = pca95xx_select, > + .deselect = pca95xx_deselect, > +}; > + > +static const struct udevice_id pca95xx_ids[] = { > + { .compatible = "nxp,pca9548", .data = (ulong)8 }, > + { .compatible = "nxp,pca9544", .data = (ulong)4 }, > + { } > +}; > + > +static int pca95xx_ofdata_to_platdata(struct udevice *dev) > +{ > + struct pca95xx_priv *priv = dev_get_priv(dev); > + > + priv->addr = dev_get_addr(dev); > + if (!priv->addr) { > + debug("MUX not found\n"); > + return -ENOSYS; -EINVAL > + } > + priv->width = dev_get_driver_data(dev); > + > + if (!priv->width) { > + debug("No I2C MUX width specified\n"); > + return -ENOSYS; -EINVAL > + } > + > + debug("Device %s at 0x%x with width %d\n", > + dev->name, priv->addr, priv->width); > + > + return 0; > +} > + > +U_BOOT_DRIVER(pca95xx) = { > + .name = "pca95xx", > + .id = UCLASS_I2C_MUX, > + .of_match = pca95xx_ids, > + .ops = &pca95xx_ops, > + .ofdata_to_platdata = pca95xx_ofdata_to_platdata, > + .priv_auto_alloc_size = sizeof(struct pca95xx_priv), > +}; > -- > 1.9.1 > Regards, Simon
On 20.4.2016 16:41, Simon Glass wrote: > Hi Michal, > > On 14 April 2016 at 06:15, Michal Simek <michal.simek@xilinx.com> wrote: >> Add support for common TI i2c mux which is available on ZynqMP zcu102 >> board. >> DM i2c mux core code is selecting/deselecting bus before/after >> every command is performed that's why only one channel is active at a >> time. That's also the reason why deselect is just disable all available >> channels. >> >> Signed-off-by: Michal Simek <michal.simek@xilinx.com> >> --- >> >> drivers/i2c/muxes/Kconfig | 7 ++++ >> drivers/i2c/muxes/Makefile | 1 + >> drivers/i2c/muxes/pca954x.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 87 insertions(+) >> create mode 100644 drivers/i2c/muxes/pca954x.c > > nits below, but otherwise: > > > Reviewed-by: Simon Glass <sjg@chromium.org> >> >> diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig >> index f959d9de9e8b..e16b902f9611 100644 >> --- a/drivers/i2c/muxes/Kconfig >> +++ b/drivers/i2c/muxes/Kconfig >> @@ -24,3 +24,10 @@ config I2C_ARB_GPIO_CHALLENGE >> I2C multimaster arbitration scheme using GPIOs and a challenge & >> response mechanism where masters have to claim the bus by asserting >> a GPIO. >> + >> +config I2C_MUX_PCA954X >> + tristate "TI PCA954x I2C Mux/switches" >> + depends on I2C_MUX >> + help >> + If you say yes here you get support for the TI PCA954x >> + I2C mux/switch devices. > > Can you add a few lines about what this device is? What does it allow? done. > >> diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile >> index 47c1240d7e9e..fb2d67ec9a97 100644 >> --- a/drivers/i2c/muxes/Makefile >> +++ b/drivers/i2c/muxes/Makefile >> @@ -5,3 +5,4 @@ >> # >> obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE) += i2c-arb-gpio-challenge.o >> obj-$(CONFIG_$(SPL_)I2C_MUX) += i2c-mux-uclass.o >> +obj-$(CONFIG_I2C_MUX_PCA954X) += pca954x.o >> diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c >> new file mode 100644 >> index 000000000000..206581d3d908 >> --- /dev/null >> +++ b/drivers/i2c/muxes/pca954x.c >> @@ -0,0 +1,79 @@ >> +/* >> + * Copyright (C) 2015 - 2016 Xilinx, Inc. >> + * Written by Michal Simek >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> + >> +#include <common.h> >> +#include <dm.h> >> +#include <errno.h> >> +#include <i2c.h> >> +#include <asm/gpio.h> >> + >> +DECLARE_GLOBAL_DATA_PTR; >> + >> +struct pca95xx_priv { >> + u32 addr; > > ulong? it is i2c address that's why 32bit address should be enough. > >> + u32 width; > > Comments? Added. > >> +}; >> + >> +static int pca95xx_deselect(struct udevice *mux, struct udevice *bus, >> + uint channel) >> +{ >> + struct pca95xx_priv *priv = dev_get_priv(mux); >> + uchar byte = 0; >> + >> + return dm_i2c_write(mux, priv->addr, &byte, 1); >> +} >> + >> +static int pca95xx_select(struct udevice *mux, struct udevice *bus, >> + uint channel) >> +{ >> + struct pca95xx_priv *priv = dev_get_priv(mux); >> + uchar byte = 1 << channel; >> + >> + return dm_i2c_write(mux, priv->addr, &byte, 1); >> +} >> + >> +static const struct i2c_mux_ops pca95xx_ops = { >> + .select = pca95xx_select, >> + .deselect = pca95xx_deselect, >> +}; >> + >> +static const struct udevice_id pca95xx_ids[] = { >> + { .compatible = "nxp,pca9548", .data = (ulong)8 }, >> + { .compatible = "nxp,pca9544", .data = (ulong)4 }, >> + { } >> +}; >> + >> +static int pca95xx_ofdata_to_platdata(struct udevice *dev) >> +{ >> + struct pca95xx_priv *priv = dev_get_priv(dev); >> + >> + priv->addr = dev_get_addr(dev); >> + if (!priv->addr) { >> + debug("MUX not found\n"); >> + return -ENOSYS; > > -EINVAL fixed. > >> + } >> + priv->width = dev_get_driver_data(dev); >> + >> + if (!priv->width) { >> + debug("No I2C MUX width specified\n"); >> + return -ENOSYS; > > -EINVAL fixed. > >> + } >> + >> + debug("Device %s at 0x%x with width %d\n", >> + dev->name, priv->addr, priv->width); >> + >> + return 0; >> +} >> + >> +U_BOOT_DRIVER(pca95xx) = { >> + .name = "pca95xx", >> + .id = UCLASS_I2C_MUX, >> + .of_match = pca95xx_ids, >> + .ops = &pca95xx_ops, >> + .ofdata_to_platdata = pca95xx_ofdata_to_platdata, >> + .priv_auto_alloc_size = sizeof(struct pca95xx_priv), >> +}; >> -- >> 1.9.1 >> > > Regards, > Simon > Thanks, Michal
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index f959d9de9e8b..e16b902f9611 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -24,3 +24,10 @@ config I2C_ARB_GPIO_CHALLENGE I2C multimaster arbitration scheme using GPIOs and a challenge & response mechanism where masters have to claim the bus by asserting a GPIO. + +config I2C_MUX_PCA954X + tristate "TI PCA954x I2C Mux/switches" + depends on I2C_MUX + help + If you say yes here you get support for the TI PCA954x + I2C mux/switch devices. diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile index 47c1240d7e9e..fb2d67ec9a97 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -5,3 +5,4 @@ # obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE) += i2c-arb-gpio-challenge.o obj-$(CONFIG_$(SPL_)I2C_MUX) += i2c-mux-uclass.o +obj-$(CONFIG_I2C_MUX_PCA954X) += pca954x.o diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c new file mode 100644 index 000000000000..206581d3d908 --- /dev/null +++ b/drivers/i2c/muxes/pca954x.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 - 2016 Xilinx, Inc. + * Written by Michal Simek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <i2c.h> +#include <asm/gpio.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct pca95xx_priv { + u32 addr; + u32 width; +}; + +static int pca95xx_deselect(struct udevice *mux, struct udevice *bus, + uint channel) +{ + struct pca95xx_priv *priv = dev_get_priv(mux); + uchar byte = 0; + + return dm_i2c_write(mux, priv->addr, &byte, 1); +} + +static int pca95xx_select(struct udevice *mux, struct udevice *bus, + uint channel) +{ + struct pca95xx_priv *priv = dev_get_priv(mux); + uchar byte = 1 << channel; + + return dm_i2c_write(mux, priv->addr, &byte, 1); +} + +static const struct i2c_mux_ops pca95xx_ops = { + .select = pca95xx_select, + .deselect = pca95xx_deselect, +}; + +static const struct udevice_id pca95xx_ids[] = { + { .compatible = "nxp,pca9548", .data = (ulong)8 }, + { .compatible = "nxp,pca9544", .data = (ulong)4 }, + { } +}; + +static int pca95xx_ofdata_to_platdata(struct udevice *dev) +{ + struct pca95xx_priv *priv = dev_get_priv(dev); + + priv->addr = dev_get_addr(dev); + if (!priv->addr) { + debug("MUX not found\n"); + return -ENOSYS; + } + priv->width = dev_get_driver_data(dev); + + if (!priv->width) { + debug("No I2C MUX width specified\n"); + return -ENOSYS; + } + + debug("Device %s at 0x%x with width %d\n", + dev->name, priv->addr, priv->width); + + return 0; +} + +U_BOOT_DRIVER(pca95xx) = { + .name = "pca95xx", + .id = UCLASS_I2C_MUX, + .of_match = pca95xx_ids, + .ops = &pca95xx_ops, + .ofdata_to_platdata = pca95xx_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct pca95xx_priv), +};
Add support for common TI i2c mux which is available on ZynqMP zcu102 board. DM i2c mux core code is selecting/deselecting bus before/after every command is performed that's why only one channel is active at a time. That's also the reason why deselect is just disable all available channels. Signed-off-by: Michal Simek <michal.simek@xilinx.com> --- drivers/i2c/muxes/Kconfig | 7 ++++ drivers/i2c/muxes/Makefile | 1 + drivers/i2c/muxes/pca954x.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 drivers/i2c/muxes/pca954x.c