i2c: cdns: Read address from DT in ofdata_to_platdata
PATCH 1/4 i2c: cdns: Read address from DT in ofdata_to_platdata
Extract reading IP base address in function which is designed for it. Also enable option to read more information from DT in this function.
---
drivers/i2c/i2c-cdns.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/i2c/i2c-cdns.c +12 -4
@@ -125,10 +125,6 @@ static int cdns_i2c_probe(struct udevice *dev) {struct i2c_cdns_bus *bus =dev_get_priv (dev); - bus->regs = (struct cdns_i2c_regs *)dev_get_addr (dev); -if (!bus->regs) -return -ENOMEM ; -/* TODO: Calculate dividers based on CPU_CLK_1X */ /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ writel((16 << CDNS_I2C_CONTROL_DIV_B_SHIFT) |
@@ -313,6 +309,17 @@ static int cdns_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,return 0 ; } +static int cdns_i2c_ofdata_to_platdata (struct udevice *dev) +{ +struct i2c_cdns_bus *i2c_bus =dev_get_priv (dev); + + i2c_bus->regs = (struct cdns_i2c_regs *)dev_get_addr (dev); +if (!i2c_bus->regs) +return -ENOMEM ; + +return 0 ; +} +static const struct dm_i2c_ops cdns_i2c_ops = { .xfer = cdns_i2c_xfer, .probe_chip = cdns_i2c_probe_chip,
@@ -330,6 +337,7 @@ U_BOOT_DRIVER(cdns_i2c) = { .of_match = cdns_i2c_of_match, .probe = cdns_i2c_probe, .remove = cdns_i2c_remove, + .ofdata_to_platdata = cdns_i2c_ofdata_to_platdata, .priv_auto_alloc_size = sizeof(struct i2c_cdns_bus), .ops = &cdns_i2c_ops, };
Signature · 1 line
1.9.1
PATCH 2/4 i2c: cdns: Moving speed setup from probe to set_bus_speed function
set_bus_speed is the right function where bus speed should be setup. This move enable option to remove probe and remove functions which are empty.
---
drivers/i2c/i2c-cdns.c | 48 +++++++++++------------------------------------- 1 file changed, 11 insertions(+), 37 deletions(-)
drivers/i2c/i2c-cdns.c +11 -37
@@ -115,41 +115,6 @@ struct i2c_cdns_bus {struct cdns_i2c_regs __iomem *regs;/* register base */ }; - -/** cdns_i2c_probe() - Probe method -* @dev: udevice pointer -* -* DM callback called when device is probed -*/ -static int cdns_i2c_probe (struct udevice *dev) -{ -struct i2c_cdns_bus *bus =dev_get_priv (dev); - -/* TODO: Calculate dividers based on CPU_CLK_1X */ -/* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ -writel ((16 <<CDNS_I2C_CONTROL_DIV_B_SHIFT ) | - (2 <<CDNS_I2C_CONTROL_DIV_A_SHIFT ), &bus->regs->control); - -/* Enable master mode, ack, and 7-bit addressing */ -setbits_le32 (&bus->regs->control,CDNS_I2C_CONTROL_MS | -CDNS_I2C_CONTROL_ACKEN |CDNS_I2C_CONTROL_NEA ); - -debug ("%s bus %d at %p\n" , __func__, dev->seq, bus->regs); - -return 0 ; -} - -static int cdns_i2c_remove (struct udevice *dev) -{ -struct i2c_cdns_bus *bus =dev_get_priv (dev); - -debug ("%s bus %d at %p\n" , __func__, dev->seq, bus->regs); - -unmap_sysmem (bus->regs); - -return 0 ; -} -/* Wait for an interrupt */ static u32 cdns_i2c_wait (struct cdns_i2c_regs *cdns_i2c,u32 mask) {
@@ -170,12 +135,23 @@ static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask)static int cdns_i2c_set_bus_speed (struct udevice *dev,unsigned int speed) { +struct i2c_cdns_bus *bus =dev_get_priv (dev); +if (speed !=100000 ) {printf ("%s, failed to set clock speed to %u\n" , __func__, speed);return -EINVAL ; } +/* TODO: Calculate dividers based on CPU_CLK_1X */ +/* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ +writel ((16 <<CDNS_I2C_CONTROL_DIV_B_SHIFT ) | + (2 <<CDNS_I2C_CONTROL_DIV_A_SHIFT ), &bus->regs->control); + +/* Enable master mode, ack, and 7-bit addressing */ +setbits_le32 (&bus->regs->control,CDNS_I2C_CONTROL_MS | +CDNS_I2C_CONTROL_ACKEN |CDNS_I2C_CONTROL_NEA ); +return 0 ; }
@@ -335,8 +311,6 @@ U_BOOT_DRIVER(cdns_i2c) = { .name = "i2c-cdns", .id = UCLASS_I2C, .of_match = cdns_i2c_of_match, - .probe = cdns_i2c_probe, - .remove = cdns_i2c_remove, .ofdata_to_platdata = cdns_i2c_ofdata_to_platdata, .priv_auto_alloc_size = sizeof(struct i2c_cdns_bus), .ops = &cdns_i2c_ops,
Signature · 1 line
1.9.1
PATCH 2/4 i2c: cdns: Moving speed setup from probe to set_bus_speed function
Hello Michal,
Am 14.04.2016 um 14:15 schrieb Michal Simek:
Quoted 9 lines
set_bus_speedis the right function where bus speed should be setup. This move enable option to remove probe and remove functions which are empty.Signed-off-by Michal Simek <[email protected]>---
drivers/i2c/i2c-cdns.c | 48 +++++++++++------------------------------------- 1 file changed, 11 insertions(+), 37 deletions(-)
bye,
Heiko
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH 3/4 i2c: cdns: Support different bus speeds
In reply to Michal Simek400kHz is maximum freq which can be used on Xilinx ZynqMP. Support it with standard divider calculator.
Input freq is hardcoded to 100MHz input freq till we have clock driver which can provide this information for exact configuration.
---
drivers/i2c/i2c-cdns.c | 76 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-)
drivers/i2c/i2c-cdns.c +69 -7
@@ -112,6 +112,7 @@ static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c)struct i2c_cdns_bus {int id; +unsigned int input_freq;struct cdns_i2c_regs __iomem *regs;/* register base */ };
@@ -133,20 +134,79 @@ static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask)return int_status & mask; } +#define CDNS_I2C_DIVA_MAX 4 +#define CDNS_I2C_DIVB_MAX 64 + +static int cdns_i2c_calc_divs (unsigned long *f,unsigned long input_clk, +unsigned int *a,unsigned int *b) +{ +unsigned long fscl = *f, best_fscl = *f, actual_fscl, temp; +unsigned int div_a, div_b, calc_div_a =0 , calc_div_b =0 ; +unsigned int last_error, current_error; + +/* calculate (divisor_a+1) x (divisor_b+1) */ + temp = input_clk / (22 * fscl); + +/* +* If the calculated value is negative or 0CDNS_I2C_DIVA_MAX, +* the fscl input is out of range. Return error. +*/ +if (!temp || (temp > (CDNS_I2C_DIVA_MAX *CDNS_I2C_DIVB_MAX ))) +return -EINVAL ; + + last_error =-1 ; +for (div_a =0 ; div_a <CDNS_I2C_DIVA_MAX ; div_a++) { + div_b =DIV_ROUND_UP (input_clk,22 * fscl * (div_a +1 )); + +if ((div_b <1 ) || (div_b >CDNS_I2C_DIVB_MAX )) +continue ; + div_b--; + + actual_fscl = input_clk / (22 * (div_a +1 ) * (div_b +1 )); + +if (actual_fscl > fscl) +continue ; + + current_error = ((actual_fscl > fscl) ? (actual_fscl - fscl) : + (fscl - actual_fscl)); + +if (last_error > current_error) { + calc_div_a = div_a; + calc_div_b = div_b; + best_fscl = actual_fscl; + last_error = current_error; + } + } + + *a = calc_div_a; + *b = calc_div_b; + *f = best_fscl; + +return 0 ; +} +static int cdns_i2c_set_bus_speed (struct udevice *dev,unsigned int speed) {struct i2c_cdns_bus *bus =dev_get_priv (dev); +u32 div_a =0 , div_b =0 ; +unsigned long speed_p = speed; +int ret =0 ; -if (speed !=100000 ) { -printf ("%s, failed to set clock speed to %u\n" , __func__, - speed); +if (speed >400000 ) { +debug ("%s, failed to set clock speed to %u\n" , __func__, + speed);return -EINVAL ; } -/* TODO: Calculate dividers based on CPU_CLK_1X */ -/* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ -writel ((16 <<CDNS_I2C_CONTROL_DIV_B_SHIFT ) | - (2 <<CDNS_I2C_CONTROL_DIV_A_SHIFT ), &bus->regs->control); + ret =cdns_i2c_calc_divs (&speed_p, bus->input_freq, &div_a, &div_b); +if (ret) +return ret; + +debug ("%s: div_a: %d, div_b: %d, input freq: %d, speed: %d/%ld\n" , + __func__, div_a, div_b, bus->input_freq, speed, speed_p); + +writel ((div_b <<CDNS_I2C_CONTROL_DIV_B_SHIFT ) | + (div_a <<CDNS_I2C_CONTROL_DIV_A_SHIFT ), &bus->regs->control);/* Enable master mode, ack, and 7-bit addressing */ setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS |
@@ -293,6 +353,8 @@ static int cdns_i2c_ofdata_to_platdata(struct udevice *dev)if (!i2c_bus->regs)return -ENOMEM ; + i2c_bus->input_freq =100000000 ;/* TODO hardcode input freq for now */ +return 0 ; }
Signature · 1 line
1.9.1
PATCH 3/4 i2c: cdns: Support different bus speeds
Hello Michal,
Am 14.04.2016 um 14:15 schrieb Michal Simek:
Quoted 10 lines
400kHz is maximum freq which can be used on Xilinx ZynqMP. Support it with standard divider calculator.
Input freq is hardcoded to 100MHz input freq till we have clock driver which can provide this information for exact configuration.Signed-off-by Michal Simek <[email protected]>---
drivers/i2c/i2c-cdns.c | 76 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-)
just some nitpick, beside of this:
Quoted 17 lines
drivers/i2c/i2c-cdns.c +2
-0@@ -112,6 +112,7 @@ static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c)struct i2c_cdns_bus {int id; +unsigned int input_freq;struct cdns_i2c_regs __iomem *regs;/* register base */ };@@ -133,20 +134,79 @@ static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask)return int_status & mask; } +#define CDNS_I2C_DIVA_MAX 4
drivers/i2c/i2c-cdns.c static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask) · line 147
Quoted 10 lines
drivers/i2c/i2c-cdns.c +10
-0+#define CDNS_I2C_DIVB_MAX 64 + +static int cdns_i2c_calc_divs (unsigned long *f,unsigned long input_clk, +unsigned int *a,unsigned int *b) +{ +unsigned long fscl = *f, best_fscl = *f, actual_fscl, temp; +unsigned int div_a, div_b, calc_div_a =0 , calc_div_b =0 ; +unsigned int last_error, current_error; + +/* calculate (divisor_a+1) x (divisor_b+1) */
please add a space before and after the "+"
Quoted 74 lines
drivers/i2c/i2c-cdns.c +55
-7+ temp = input_clk / (22 * fscl); + +/* +* If the calculated value is negative or 0CDNS_I2C_DIVA_MAX, +* the fscl input is out of range. Return error. +*/ +if (!temp || (temp > (CDNS_I2C_DIVA_MAX *CDNS_I2C_DIVB_MAX ))) +return -EINVAL ; + + last_error =-1 ; +for (div_a =0 ; div_a <CDNS_I2C_DIVA_MAX ; div_a++) { + div_b =DIV_ROUND_UP (input_clk,22 * fscl * (div_a +1 )); + +if ((div_b <1 ) || (div_b >CDNS_I2C_DIVB_MAX )) +continue ; + div_b--; + + actual_fscl = input_clk / (22 * (div_a +1 ) * (div_b +1 )); + +if (actual_fscl > fscl) +continue ; + + current_error = ((actual_fscl > fscl) ? (actual_fscl - fscl) : + (fscl - actual_fscl)); + +if (last_error > current_error) { + calc_div_a = div_a; + calc_div_b = div_b; + best_fscl = actual_fscl; + last_error = current_error; + } + } + + *a = calc_div_a; + *b = calc_div_b; + *f = best_fscl; + +return 0 ; +} +static int cdns_i2c_set_bus_speed (struct udevice *dev,unsigned int speed) {struct i2c_cdns_bus *bus =dev_get_priv (dev); +u32 div_a =0 , div_b =0 ; +unsigned long speed_p = speed; +int ret =0 ; -if (speed !=100000 ) { -printf ("%s, failed to set clock speed to %u\n" , __func__, - speed); +if (speed >400000 ) { +debug ("%s, failed to set clock speed to %u\n" , __func__, + speed);return -EINVAL ; } -/* TODO: Calculate dividers based on CPU_CLK_1X */ -/* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ -writel ((16 <<CDNS_I2C_CONTROL_DIV_B_SHIFT ) | - (2 <<CDNS_I2C_CONTROL_DIV_A_SHIFT ), &bus->regs->control); + ret =cdns_i2c_calc_divs (&speed_p, bus->input_freq, &div_a, &div_b); +if (ret) +return ret; + +debug ("%s: div_a: %d, div_b: %d, input freq: %d, speed: %d/%ld\n" , + __func__, div_a, div_b, bus->input_freq, speed, speed_p); + +writel ((div_b <<CDNS_I2C_CONTROL_DIV_B_SHIFT ) | + (div_a <<CDNS_I2C_CONTROL_DIV_A_SHIFT ), &bus->regs->control);/* Enable master mode, ack, and 7-bit addressing */ setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS |
drivers/i2c/i2c-cdns.c static int cdns_i2c_ofdata_to_platdata(struct udevice *dev) · line 360
Quoted 8 lines
drivers/i2c/i2c-cdns.c +2
-0@@ -293,6 +353,8 @@ static int cdns_i2c_ofdata_to_platdata(struct udevice *dev)if (!i2c_bus->regs)return -ENOMEM ; + i2c_bus->input_freq =100000000 ;/* TODO hardcode input freq for now */ +return 0 ; }
bye,
Heiko
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH 3/4 i2c: cdns: Support different bus speeds
Quoted 37 lines · Heiko Schocher
Hello Michal,
Am 14.04.2016 um 14:15 schrieb Michal Simek:
Quoted 11 lines
400kHz is maximum freq which can be used on Xilinx ZynqMP. Support it with standard divider calculator.
Input freq is hardcoded to 100MHz input freq till we have clock driver which can provide this information for exact configuration.Signed-off-by Michal Simek <[email protected]>---
drivers/i2c/i2c-cdns.c | 76 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-)just some nitpick, beside of this:
Reviewed-by Heiko Schocher <[email protected]>Quoted 18 lines
drivers/i2c/i2c-cdns.c +1
-0@@ -112,6 +112,7 @@ static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c)struct i2c_cdns_bus {int id; +unsigned int input_freq;struct cdns_i2c_regs __iomem *regs;/* register base */ };@@ -133,20 +134,79 @@ static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask)return int_status & mask; }
Quoted 13 lines
drivers/i2c/i2c-cdns.c static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask) · line 147
Quoted 11 lines
drivers/i2c/i2c-cdns.c +11
-0+#define CDNS_I2C_DIVA_MAX 4 +#define CDNS_I2C_DIVB_MAX 64 + +static int cdns_i2c_calc_divs (unsigned long *f,unsigned long input_clk, +unsigned int *a,unsigned int *b) +{ +unsigned long fscl = *f, best_fscl = *f, actual_fscl, temp; +unsigned int div_a, div_b, calc_div_a =0 , calc_div_b =0 ; +unsigned int last_error, current_error; + +/* calculate (divisor_a+1) x (divisor_b+1) */ please add a space before and after the "+"
I have fixed this.
Thanks,
Michal
PATCH 4/4 i2c: muxes: Add support for TI PCA954X mux
In reply to Michal SimekAdd 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.
---
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
drivers/i2c/muxes/Kconfig +7 -0
@@ -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.
drivers/i2c/muxes/Makefile +1 -0
@@ -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
drivers/i2c/muxes/pca954x.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH 4/4 i2c: muxes: Add support for TI PCA954X mux
Hello Michal,
Am 14.04.2016 um 14:15 schrieb Michal Simek:
Quoted 7 lines
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.
Quoted 8 lines
Signed-off-by Michal Simek <[email protected]>---
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:
bye,
Heiko
Quoted 110 lines
drivers/i2c/muxes/Kconfig +7
-0@@ -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.drivers/i2c/muxes/Makefile +1
-0@@ -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.odrivers/i2c/muxes/pca954x.c new file +79
-0@@ -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 ), +};
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH 4/4 i2c: muxes: Add support for TI PCA954X mux
In reply to Michal SimekHi Michal,
Quoted 7 lines · 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.
Quoted 8 lines
Signed-off-by Michal Simek <[email protected]>---
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:
Quoted 6 lines
drivers/i2c/muxes/Kconfig +0
-0
drivers/i2c/muxes/Kconfig config I2C_ARB_GPIO_CHALLENGE · line 33
Quoted 10 lines
drivers/i2c/muxes/Kconfig +7
-0@@ -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?
Quoted 22 lines
drivers/i2c/muxes/Makefile +1
-0@@ -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.odrivers/i2c/muxes/pca954x.c new file +7
-0@@ -0,0 +1,79 @@ +/* +* Copyright (C) 2015 - 2016 Xilinx, Inc. +* Written by Michal Simek +* +* SPDX-License-Identifier: GPL-2.0+ +*/ +
drivers/i2c/muxes/pca954x.c line 17
Quoted 10 lines
drivers/i2c/muxes/pca954x.c new file +10
-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?
drivers/i2c/muxes/pca954x.c line 18
Quoted 1 line
drivers/i2c/muxes/pca954x.c new file +1
-0+u32 width;
Comments?
Quoted 29 lines
drivers/i2c/muxes/pca954x.c new file +29
-0+}; + +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 }, + { }
drivers/i2c/muxes/pca954x.c line 57
Quoted 10 lines
drivers/i2c/muxes/pca954x.c new file +10
-0+}; + +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
drivers/i2c/muxes/pca954x.c line 63
Quoted 6 lines
drivers/i2c/muxes/pca954x.c new file +6
-0+ } + priv->width =dev_get_driver_data (dev); + +if (!priv->width) { +debug ("No I2C MUX width specified\n" ); +return -ENOSYS ;
-EINVAL
Quoted 17 lines
drivers/i2c/muxes/pca954x.c new file +16
-1+ } + +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 ), +}; --
Quoted 2 lines
1.9.1
Regards,
Simon
PATCH 4/4 i2c: muxes: Add support for TI PCA954X mux
Quoted 33 lines · Simon Glass
Hi Michal,
Quoted 7 lines · 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.Quoted 8 lines
Signed-off-by Michal Simek <[email protected]>---
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.cnits below, but otherwise:
Reviewed-by Simon Glass <[email protected]>Quoted 10 lines
drivers/i2c/muxes/Kconfig +1
-0@@ -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. +
Quoted 8 lines
drivers/i2c/muxes/Kconfig config I2C_ARB_GPIO_CHALLENGE · line 33
Quoted 6 lines
drivers/i2c/muxes/Kconfig +6
-0+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.
Quoted 27 lines
Quoted 27 lines
drivers/i2c/muxes/Makefile +1
-0@@ -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.odrivers/i2c/muxes/pca954x.c new file +11
-0@@ -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>
Quoted 8 lines
drivers/i2c/muxes/pca954x.c line 17
Quoted 6 lines
drivers/i2c/muxes/pca954x.c new file +6
-0+#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.
Quoted 4 lines
drivers/i2c/muxes/pca954x.c line 18
Quoted 2 lines
drivers/i2c/muxes/pca954x.c new file +1
-0+u32 width;Comments?
Added.
Quoted 34 lines
Quoted 34 lines
drivers/i2c/muxes/pca954x.c new file +33
-0+}; + +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) +{
Quoted 8 lines
drivers/i2c/muxes/pca954x.c line 57
Quoted 6 lines
drivers/i2c/muxes/pca954x.c new file +6
-0+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.
Quoted 9 lines
drivers/i2c/muxes/pca954x.c line 63
Quoted 7 lines
drivers/i2c/muxes/pca954x.c new file +6
-0+ } + priv->width =dev_get_driver_data (dev); + +if (!priv->width) { +debug ("No I2C MUX width specified\n" ); +return -ENOSYS ;
-EINVAL
fixed.
Quoted 15 lines
Quoted 15 lines
drivers/i2c/muxes/pca954x.c new file +14
-0+ } + +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,
Quoted 9 lines
Quoted 5 lines
drivers/i2c/muxes/pca954x.c new file +2
-1+ .priv_auto_alloc_size = sizeof(struct pca95xx_priv), +}; --1.9.1
Regards,
Simon
Thanks,
Michal
PATCH 1/4 i2c: cdns: Read address from DT in ofdata_to_platdata
In reply to Michal SimekHello Michal,
Am 14.04.2016 um 14:15 schrieb Michal Simek:
Quoted 8 lines
Extract reading IP base address in function which is designed for it. Also enable option to read more information from DT in this function.
Signed-off-by Michal Simek <[email protected]>---
drivers/i2c/i2c-cdns.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
bye,
Heiko
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany