On Mon, Nov 25, 2019 at 2:05 PM Heiko Schocher <h...@denx.de> wrote: > > Hello Vladimir, > > Am 22.11.2019 um 22:20 schrieb Vladimir Olovyannikov: > > From: Arjun Jyothi <arjun.jyo...@broadcom.com> > > > > Add I2C driver support for Broadcom iproc-based socs. > > > > Signed-off-by: Arjun Jyothi <arjun.jyo...@broadcom.com> > > Signed-off-by: Rayagonda Kokatanur <rayagonda.kokata...@broadcom.com> > > Signed-off-by: Sheetal Tigadoli <sheetal.tigad...@broadcom.com> > > Signed-off-by: Vladimir Olovyannikov <vladimir.olovyanni...@broadcom.com> > > --- > > drivers/i2c/Kconfig | 623 ++++++++++++++++---------------- > > drivers/i2c/Makefile | 2 +- > > drivers/i2c/iproc_i2c.c | 765 ++++++++++++++++++++++++++++++++++++++++ > > drivers/i2c/iproc_i2c.h | 356 +++++++++++++++++++ > > 4 files changed, 1437 insertions(+), 309 deletions(-) > > create mode 100644 drivers/i2c/iproc_i2c.c > > create mode 100644 drivers/i2c/iproc_i2c.h > > > > diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig > > index 03d2fed341..7a80971b12 100644 > > --- a/drivers/i2c/Kconfig > > +++ b/drivers/i2c/Kconfig > > @@ -5,454 +5,461 @@ > > menu "I2C support" > > > > config DM_I2C > > - bool "Enable Driver Model for I2C drivers" > > - depends on DM > > - help > > - Enable driver model for I2C. The I2C uclass interface: probe, read, > > - write and speed, is implemented with the bus drivers operations, > > - which provide methods for bus setting and data transfer. Each chip > > - device (bus child) info is kept as parent platdata. The interface > > - is defined in include/i2c.h. > > + bool "Enable Driver Model for I2C drivers" > > + depends on DM > > + help > > + Enable driver model for I2C. The I2C uclass interface: probe, read, > > + write and speed, is implemented with the bus drivers operations, > > + which provide methods for bus setting and data transfer. Each chip > > + device (bus child) info is kept as parent platdata. The interface > > + is defined in include/i2c.h. > > This (and a lot of following) change removes tabs with spaces, NACK. > > Please do not remove the tabs! > > > config I2C_CROS_EC_TUNNEL > > - tristate "Chrome OS EC tunnel I2C bus" > > - depends on CROS_EC > > - help > > - This provides an I2C bus that will tunnel i2c commands through to > > - the other side of the Chrome OS EC to the I2C bus connected there. > > - This will work whatever the interface used to talk to the EC (SPI, > > - I2C or LPC). Some Chromebooks use this when the hardware design > > - does not allow direct access to the main PMIC from the AP. > > + tristate "Chrome OS EC tunnel I2C bus" > > + depends on CROS_EC > > + help > > + This provides an I2C bus that will tunnel i2c commands through to > > + the other side of the Chrome OS EC to the I2C bus connected there. > > + This will work whatever the interface used to talk to the EC (SPI, > > + I2C or LPC). Some Chromebooks use this when the hardware design > > + does not allow direct access to the main PMIC from the AP. > > > > config I2C_CROS_EC_LDO > > - bool "Provide access to LDOs on the Chrome OS EC" > > - depends on CROS_EC > > - ---help--- > > - On many Chromebooks the main PMIC is inaccessible to the AP. This is > > - often dealt with by using an I2C pass-through interface provided by > > - the EC. On some unfortunate models (e.g. Spring) the pass-through > > - is not available, and an LDO message is available instead. This > > - option enables a driver which provides very basic access to those > > - regulators, via the EC. We implement this as an I2C bus which > > - emulates just the TPS65090 messages we know about. This is done to > > - avoid duplicating the logic in the TPS65090 regulator driver for > > - enabling/disabling an LDO. > > + bool "Provide access to LDOs on the Chrome OS EC" > > + depends on CROS_EC > > + ---help--- > > + On many Chromebooks the main PMIC is inaccessible to the AP. This is > > + often dealt with by using an I2C pass-through interface provided by > > + the EC. On some unfortunate models (e.g. Spring) the pass-through > > + is not available, and an LDO message is available instead. This > > + option enables a driver which provides very basic access to those > > + regulators, via the EC. We implement this as an I2C bus which > > + emulates just the TPS65090 messages we know about. This is done to > > + avoid duplicating the logic in the TPS65090 regulator driver for > > + enabling/disabling an LDO. > > > > config I2C_SET_DEFAULT_BUS_NUM > > - bool "Set default I2C bus number" > > - depends on DM_I2C > > - help > > - Set default number of I2C bus to be accessed. This option provides > > - behaviour similar to old (i.e. pre DM) I2C bus driver. > > + bool "Set default I2C bus number" > > + depends on DM_I2C > > + help > > + Set default number of I2C bus to be accessed. This option provides > > + behaviour similar to old (i.e. pre DM) I2C bus driver. > > > > config I2C_DEFAULT_BUS_NUMBER > > - hex "I2C default bus number" > > - depends on I2C_SET_DEFAULT_BUS_NUM > > - default 0x0 > > - help > > - Number of default I2C bus to use > > + hex "I2C default bus number" > > + depends on I2C_SET_DEFAULT_BUS_NUM > > + default 0x0 > > + help > > + Number of default I2C bus to use > > > > config DM_I2C_GPIO > > - bool "Enable Driver Model for software emulated I2C bus driver" > > - depends on DM_I2C && DM_GPIO > > - help > > - Enable the i2c bus driver emulation by using the GPIOs. The bus GPIO > > - configuration is given by the device tree. Kernel-style device tree > > - bindings are supported. > > - Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt > > + bool "Enable Driver Model for software emulated I2C bus driver" > > + depends on DM_I2C && DM_GPIO > > + help > > + Enable the i2c bus driver emulation by using the GPIOs. The bus GPIO > > + configuration is given by the device tree. Kernel-style device tree > > + bindings are supported. > > + Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt > > > > config SYS_I2C_AT91 > > - bool "Atmel I2C driver" > > - depends on DM_I2C && ARCH_AT91 > > - help > > - Add support for the Atmel I2C driver. A serious problem is that > > there > > - is no documented way to issue repeated START conditions for more > > than > > - two messages, as needed to support combined I2C messages. Use the > > - i2c-gpio driver unless your system can cope with this limitation. > > - Binding info: doc/device-tree-bindings/i2c/i2c-at91.txt > > + bool "Atmel I2C driver" > > + depends on DM_I2C && ARCH_AT91 > > + help > > + Add support for the Atmel I2C driver. A serious problem is that there > > + is no documented way to issue repeated START conditions for more than > > + two messages, as needed to support combined I2C messages. Use the > > + i2c-gpio driver unless your system can cope with this limitation. > > + Binding info: doc/device-tree-bindings/i2c/i2c-at91.txt > > + > > +config IPROC_I2C > > + bool "Broadcom iProc I2C driver" > > + depends on DM_I2C > > + help > > + Add support for Broadcom iProc I2C driver. > > + The driver is used in iProc SoCs. > > > > config SYS_I2C_FSL > > bool "Freescale I2C bus driver" > > depends on DM_I2C > > help > > - Add support for Freescale I2C busses as used on MPC8240, MPC8245, > > and > > - MPC85xx processors. > > + Add support for Freescale I2C busses as used on MPC8240, MPC8245, and > > + MPC85xx processors. > > > > config SYS_I2C_CADENCE > > - tristate "Cadence I2C Controller" > > - depends on DM_I2C && (ARCH_ZYNQ || ARM64) > > - help > > - Say yes here to select Cadence I2C Host Controller. This controller > > is > > - e.g. used by Xilinx Zynq. > > + tristate "Cadence I2C Controller" > > + depends on DM_I2C && (ARCH_ZYNQ || ARM64) > > + help > > + Say yes here to select Cadence I2C Host Controller. This controller > > is > > + e.g. used by Xilinx Zynq. > > > > config SYS_I2C_DAVINCI > > - bool "Davinci I2C Controller" > > - depends on (ARCH_KEYSTONE || ARCH_DAVINCI) > > - help > > - Say yes here to add support for Davinci and Keystone I2C controller > > + bool "Davinci I2C Controller" > > + depends on (ARCH_KEYSTONE || ARCH_DAVINCI) > > + help > > + Say yes here to add support for Davinci and Keystone I2C controller > > > > config SYS_I2C_DW > > - bool "Designware I2C Controller" > > - default n > > - help > > - Say yes here to select the Designware I2C Host Controller. This > > - controller is used in various SoCs, e.g. the ST SPEAr, Altera > > - SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs. > > + bool "Designware I2C Controller" > > + default n > > + help > > + Say yes here to select the Designware I2C Host Controller. This > > + controller is used in various SoCs, e.g. the ST SPEAr, Altera > > + SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs. > > > > config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED > > - bool "DW I2C Enable Status Register not supported" > > - depends on SYS_I2C_DW && (TARGET_SPEAR300 || TARGET_SPEAR310 || \ > > - TARGET_SPEAR320 || TARGET_SPEAR600 || TARGET_X600) > > - default y > > - help > > - Some versions of the Designware I2C controller do not support the > > - enable status register. This config option can be enabled in such > > - cases. > > + bool "DW I2C Enable Status Register not supported" > > + depends on SYS_I2C_DW && (TARGET_SPEAR300 || TARGET_SPEAR310 || \ > > + TARGET_SPEAR320 || TARGET_SPEAR600 || TARGET_X600) > > + default y > > + help > > + Some versions of the Designware I2C controller do not support the > > + enable status register. This config option can be enabled in such > > + cases. > > > > config SYS_I2C_ASPEED > > - bool "Aspeed I2C Controller" > > - depends on DM_I2C && ARCH_ASPEED > > - help > > - Say yes here to select Aspeed I2C Host Controller. The driver > > - supports AST2500 and AST2400 controllers, but is very limited. > > - Only single master mode is supported and only byte-by-byte > > - synchronous reads and writes are supported, no Pool Buffers or DMA. > > + bool "Aspeed I2C Controller" > > + depends on DM_I2C && ARCH_ASPEED > > + help > > + Say yes here to select Aspeed I2C Host Controller. The driver > > + supports AST2500 and AST2400 controllers, but is very limited. > > + Only single master mode is supported and only byte-by-byte > > + synchronous reads and writes are supported, no Pool Buffers or DMA. > > > > config SYS_I2C_INTEL > > - bool "Intel I2C/SMBUS driver" > > - depends on DM_I2C > > - help > > - Add support for the Intel SMBUS driver. So far this driver is just > > - a stub which perhaps some basic init. There is no implementation of > > - the I2C API meaning that any I2C operations will immediately fail > > - for now. > > + bool "Intel I2C/SMBUS driver" > > + depends on DM_I2C > > + help > > + Add support for the Intel SMBUS driver. So far this driver is just > > + a stub which perhaps some basic init. There is no implementation of > > + the I2C API meaning that any I2C operations will immediately fail > > + for now. > > > > config SYS_I2C_IMX_LPI2C > > - bool "NXP i.MX LPI2C driver" > > - help > > - Add support for the NXP i.MX LPI2C driver. > > + bool "NXP i.MX LPI2C driver" > > + help > > + Add support for the NXP i.MX LPI2C driver. > > > > config SYS_I2C_MESON > > - bool "Amlogic Meson I2C driver" > > - depends on DM_I2C && ARCH_MESON > > - help > > - Add support for the I2C controller available in Amlogic Meson > > - SoCs. The controller supports programmable bus speed including > > - standard (100kbits/s) and fast (400kbit/s) speed and allows the > > - software to define a flexible format of the bit streams. It has an > > - internal buffer holding up to 8 bytes for transfers and supports > > - both 7-bit and 10-bit addresses. > > + bool "Amlogic Meson I2C driver" > > + depends on DM_I2C && ARCH_MESON > > + help > > + Add support for the I2C controller available in Amlogic Meson > > + SoCs. The controller supports programmable bus speed including > > + standard (100kbits/s) and fast (400kbit/s) speed and allows the > > + software to define a flexible format of the bit streams. It has an > > + internal buffer holding up to 8 bytes for transfers and supports > > + both 7-bit and 10-bit addresses. > > > > config SYS_I2C_MXC > > - bool "NXP MXC I2C driver" > > - help > > - Add support for the NXP I2C driver. This supports up to four bus > > - channels and operating on standard mode up to 100 kbits/s and fast > > - mode up to 400 kbits/s. > > + bool "NXP MXC I2C driver" > > + help > > + Add support for the NXP I2C driver. This supports up to four bus > > + channels and operating on standard mode up to 100 kbits/s and fast > > + mode up to 400 kbits/s. > > > > # These settings are not used with DM_I2C, however SPL doesn't use > > # DM_I2C even if DM_I2C is enabled, and so might use these settings even > > # when main u-boot does not! > > if SYS_I2C_MXC && (!DM_I2C || SPL) > > config SYS_I2C_MXC_I2C1 > > - bool "NXP MXC I2C1" > > - help > > - Add support for NXP MXC I2C Controller 1. > > - Required for SoCs which have I2C MXC controller 1 eg LS1088A, LS2080A > > + bool "NXP MXC I2C1" > > + help > > + Add support for NXP MXC I2C Controller 1. > > + Required for SoCs which have I2C MXC controller 1 eg LS1088A, LS2080A > > > > config SYS_I2C_MXC_I2C2 > > - bool "NXP MXC I2C2" > > - help > > - Add support for NXP MXC I2C Controller 2. > > - Required for SoCs which have I2C MXC controller 2 eg LS1088A, LS2080A > > + bool "NXP MXC I2C2" > > + help > > + Add support for NXP MXC I2C Controller 2. > > + Required for SoCs which have I2C MXC controller 2 eg LS1088A, LS2080A > > > > config SYS_I2C_MXC_I2C3 > > - bool "NXP MXC I2C3" > > - help > > - Add support for NXP MXC I2C Controller 3. > > - Required for SoCs which have I2C MXC controller 3 eg LS1088A, LS2080A > > + bool "NXP MXC I2C3" > > + help > > + Add support for NXP MXC I2C Controller 3. > > + Required for SoCs which have I2C MXC controller 3 eg LS1088A, LS2080A > > > > config SYS_I2C_MXC_I2C4 > > - bool "NXP MXC I2C4" > > - help > > - Add support for NXP MXC I2C Controller 4. > > - Required for SoCs which have I2C MXC controller 4 eg LS1088A, LS2080A > > + bool "NXP MXC I2C4" > > + help > > + Add support for NXP MXC I2C Controller 4. > > + Required for SoCs which have I2C MXC controller 4 eg LS1088A, LS2080A > > > > config SYS_I2C_MXC_I2C5 > > - bool "NXP MXC I2C5" > > - help > > - Add support for NXP MXC I2C Controller 5. > > - Required for SoCs which have I2C MXC controller 5 eg LX2160A > > + bool "NXP MXC I2C5" > > + help > > + Add support for NXP MXC I2C Controller 5. > > + Required for SoCs which have I2C MXC controller 5 eg LX2160A > > > > config SYS_I2C_MXC_I2C6 > > - bool "NXP MXC I2C6" > > - help > > - Add support for NXP MXC I2C Controller 6. > > - Required for SoCs which have I2C MXC controller 6 eg LX2160A > > + bool "NXP MXC I2C6" > > + help > > + Add support for NXP MXC I2C Controller 6. > > + Required for SoCs which have I2C MXC controller 6 eg LX2160A > > > > config SYS_I2C_MXC_I2C7 > > - bool "NXP MXC I2C7" > > - help > > - Add support for NXP MXC I2C Controller 7. > > - Required for SoCs which have I2C MXC controller 7 eg LX2160A > > + bool "NXP MXC I2C7" > > + help > > + Add support for NXP MXC I2C Controller 7. > > + Required for SoCs which have I2C MXC controller 7 eg LX2160A > > > > config SYS_I2C_MXC_I2C8 > > - bool "NXP MXC I2C8" > > - help > > - Add support for NXP MXC I2C Controller 8. > > - Required for SoCs which have I2C MXC controller 8 eg LX2160A > > + bool "NXP MXC I2C8" > > + help > > + Add support for NXP MXC I2C Controller 8. > > + Required for SoCs which have I2C MXC controller 8 eg LX2160A > > endif > > > > if SYS_I2C_MXC_I2C1 > > config SYS_MXC_I2C1_SPEED > > - int "I2C Channel 1 speed" > > - default 40000000 if TARGET_LS2080A_SIMU || TARGET_LS2080A_EMU > > - default 100000 > > - help > > - MXC I2C Channel 1 speed > > + int "I2C Channel 1 speed" > > + default 40000000 if TARGET_LS2080A_SIMU || TARGET_LS2080A_EMU > > + default 100000 > > + help > > + MXC I2C Channel 1 speed > > > > config SYS_MXC_I2C1_SLAVE > > - int "I2C1 Slave" > > - default 0 > > - help > > - MXC I2C1 Slave > > + int "I2C1 Slave" > > + default 0 > > + help > > + MXC I2C1 Slave > > endif > > > > if SYS_I2C_MXC_I2C2 > > config SYS_MXC_I2C2_SPEED > > - int "I2C Channel 2 speed" > > - default 40000000 if TARGET_LS2080A_SIMU || TARGET_LS2080A_EMU > > - default 100000 > > - help > > - MXC I2C Channel 2 speed > > + int "I2C Channel 2 speed" > > + default 40000000 if TARGET_LS2080A_SIMU || TARGET_LS2080A_EMU > > + default 100000 > > + help > > + MXC I2C Channel 2 speed > > > > config SYS_MXC_I2C2_SLAVE > > - int "I2C2 Slave" > > - default 0 > > - help > > - MXC I2C2 Slave > > + int "I2C2 Slave" > > + default 0 > > + help > > + MXC I2C2 Slave > > endif > > > > if SYS_I2C_MXC_I2C3 > > config SYS_MXC_I2C3_SPEED > > - int "I2C Channel 3 speed" > > - default 100000 > > - help > > - MXC I2C Channel 3 speed > > + int "I2C Channel 3 speed" > > + default 100000 > > + help > > + MXC I2C Channel 3 speed > > > > config SYS_MXC_I2C3_SLAVE > > - int "I2C3 Slave" > > - default 0 > > - help > > - MXC I2C3 Slave > > + int "I2C3 Slave" > > + default 0 > > + help > > + MXC I2C3 Slave > > endif > > > > if SYS_I2C_MXC_I2C4 > > config SYS_MXC_I2C4_SPEED > > - int "I2C Channel 4 speed" > > - default 100000 > > - help > > - MXC I2C Channel 4 speed > > + int "I2C Channel 4 speed" > > + default 100000 > > + help > > + MXC I2C Channel 4 speed > > > > config SYS_MXC_I2C4_SLAVE > > - int "I2C4 Slave" > > - default 0 > > - help > > - MXC I2C4 Slave > > + int "I2C4 Slave" > > + default 0 > > + help > > + MXC I2C4 Slave > > endif > > > > if SYS_I2C_MXC_I2C5 > > config SYS_MXC_I2C5_SPEED > > - int "I2C Channel 5 speed" > > - default 100000 > > - help > > - MXC I2C Channel 5 speed > > + int "I2C Channel 5 speed" > > + default 100000 > > + help > > + MXC I2C Channel 5 speed > > > > config SYS_MXC_I2C5_SLAVE > > - int "I2C5 Slave" > > - default 0 > > - help > > - MXC I2C5 Slave > > + int "I2C5 Slave" > > + default 0 > > + help > > + MXC I2C5 Slave > > endif > > > > if SYS_I2C_MXC_I2C6 > > config SYS_MXC_I2C6_SPEED > > - int "I2C Channel 6 speed" > > - default 100000 > > - help > > - MXC I2C Channel 6 speed > > + int "I2C Channel 6 speed" > > + default 100000 > > + help > > + MXC I2C Channel 6 speed > > > > config SYS_MXC_I2C6_SLAVE > > - int "I2C6 Slave" > > - default 0 > > - help > > - MXC I2C6 Slave > > + int "I2C6 Slave" > > + default 0 > > + help > > + MXC I2C6 Slave > > endif > > > > if SYS_I2C_MXC_I2C7 > > config SYS_MXC_I2C7_SPEED > > - int "I2C Channel 7 speed" > > - default 100000 > > - help > > - MXC I2C Channel 7 speed > > + int "I2C Channel 7 speed" > > + default 100000 > > + help > > + MXC I2C Channel 7 speed > > > > config SYS_MXC_I2C7_SLAVE > > - int "I2C7 Slave" > > - default 0 > > - help > > - MXC I2C7 Slave > > + int "I2C7 Slave" > > + default 0 > > + help > > + MXC I2C7 Slave > > endif > > > > if SYS_I2C_MXC_I2C8 > > config SYS_MXC_I2C8_SPEED > > - int "I2C Channel 8 speed" > > - default 100000 > > - help > > - MXC I2C Channel 8 speed > > + int "I2C Channel 8 speed" > > + default 100000 > > + help > > + MXC I2C Channel 8 speed > > > > config SYS_MXC_I2C8_SLAVE > > - int "I2C8 Slave" > > - default 0 > > - help > > - MXC I2C8 Slave > > + int "I2C8 Slave" > > + default 0 > > + help > > + MXC I2C8 Slave > > endif > > > > config SYS_I2C_OMAP24XX > > - bool "TI OMAP2+ I2C driver" > > - depends on ARCH_OMAP2PLUS || ARCH_K3 > > - help > > - Add support for the OMAP2+ I2C driver. > > + bool "TI OMAP2+ I2C driver" > > + depends on ARCH_OMAP2PLUS || ARCH_K3 > > + help > > + Add support for the OMAP2+ I2C driver. > > > > if SYS_I2C_OMAP24XX > > config SYS_OMAP24_I2C_SLAVE > > - int "I2C Slave addr channel 0" > > - default 1 > > - help > > - OMAP24xx I2C Slave address channel 0 > > + int "I2C Slave addr channel 0" > > + default 1 > > + help > > + OMAP24xx I2C Slave address channel 0 > > > > config SYS_OMAP24_I2C_SPEED > > - int "I2C Slave channel 0 speed" > > - default 100000 > > - help > > - OMAP24xx Slave speed channel 0 > > + int "I2C Slave channel 0 speed" > > + default 100000 > > + help > > + OMAP24xx Slave speed channel 0 > > endif > > > > config SYS_I2C_RCAR_I2C > > - bool "Renesas RCar I2C driver" > > - depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C > > - help > > - Support for Renesas RCar I2C controller. > > + bool "Renesas RCar I2C driver" > > + depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C > > + help > > + Support for Renesas RCar I2C controller. > > > > config SYS_I2C_RCAR_IIC > > - bool "Renesas RCar Gen3 IIC driver" > > - depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C > > - help > > - Support for Renesas RCar Gen3 IIC controller. > > + bool "Renesas RCar Gen3 IIC driver" > > + depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C > > + help > > + Support for Renesas RCar Gen3 IIC controller. > > > > config SYS_I2C_ROCKCHIP > > - bool "Rockchip I2C driver" > > - depends on DM_I2C > > - help > > - Add support for the Rockchip I2C driver. This is used with various > > - Rockchip parts such as RK3126, RK3128, RK3036 and RK3288. All chips > > - have several I2C ports and all are provided, controlled by the > > - device tree. > > + bool "Rockchip I2C driver" > > + depends on DM_I2C > > + help > > + Add support for the Rockchip I2C driver. This is used with various > > + Rockchip parts such as RK3126, RK3128, RK3036 and RK3288. All chips > > + have several I2C ports and all are provided, controlled by the > > + device tree. > > > > config SYS_I2C_SANDBOX > > - bool "Sandbox I2C driver" > > - depends on SANDBOX && DM_I2C > > - help > > - Enable I2C support for sandbox. This is an emulation of a real I2C > > - bus. Devices can be attached to the bus using the device tree > > - which specifies the driver to use. See sandbox.dts as an example. > > + bool "Sandbox I2C driver" > > + depends on SANDBOX && DM_I2C > > + help > > + Enable I2C support for sandbox. This is an emulation of a real I2C > > + bus. Devices can be attached to the bus using the device tree > > + which specifies the driver to use. See sandbox.dts as an example. > > > > config SYS_I2C_S3C24X0 > > - bool "Samsung I2C driver" > > - depends on ARCH_EXYNOS4 && DM_I2C > > - help > > - Support for Samsung I2C controller as Samsung SoCs. > > + bool "Samsung I2C driver" > > + depends on ARCH_EXYNOS4 && DM_I2C > > + help > > + Support for Samsung I2C controller as Samsung SoCs. > > > > config SYS_I2C_STM32F7 > > - bool "STMicroelectronics STM32F7 I2C support" > > - depends on (STM32F7 || STM32H7 || ARCH_STM32MP) && DM_I2C > > - help > > - Enable this option to add support for STM32 I2C controller > > - introduced with STM32F7/H7 SoCs. This I2C controller supports : > > - _ Slave and master modes > > - _ Multimaster capability > > - _ Standard-mode (up to 100 kHz) > > - _ Fast-mode (up to 400 kHz) > > - _ Fast-mode Plus (up to 1 MHz) > > - _ 7-bit and 10-bit addressing mode > > - _ Multiple 7-bit slave addresses (2 addresses, 1 with configurable > > mask) > > - _ All 7-bit addresses acknowledge mode > > - _ General call > > - _ Programmable setup and hold times > > - _ Easy to use event management > > - _ Optional clock stretching > > - _ Software reset > > + bool "STMicroelectronics STM32F7 I2C support" > > + depends on (STM32F7 || STM32H7 || ARCH_STM32MP) && DM_I2C > > + help > > + Enable this option to add support for STM32 I2C controller > > + introduced with STM32F7/H7 SoCs. This I2C controller supports : > > + _ Slave and master modes > > + _ Multimaster capability > > + _ Standard-mode (up to 100 kHz) > > + _ Fast-mode (up to 400 kHz) > > + _ Fast-mode Plus (up to 1 MHz) > > + _ 7-bit and 10-bit addressing mode > > + _ Multiple 7-bit slave addresses (2 addresses, 1 with configurable > > mask) > > + _ All 7-bit addresses acknowledge mode > > + _ General call > > + _ Programmable setup and hold times > > + _ Easy to use event management > > + _ Optional clock stretching > > + _ Software reset > > > > config SYS_I2C_TEGRA > > - bool "NVIDIA Tegra internal I2C controller" > > - depends on TEGRA > > - help > > - Support for NVIDIA I2C controller available in Tegra SoCs. > > + bool "NVIDIA Tegra internal I2C controller" > > + depends on TEGRA > > + help > > + Support for NVIDIA I2C controller available in Tegra SoCs. > > > > config SYS_I2C_UNIPHIER > > - bool "UniPhier I2C driver" > > - depends on ARCH_UNIPHIER && DM_I2C > > - default y > > - help > > - Support for UniPhier I2C controller driver. This I2C controller > > - is used on PH1-LD4, PH1-sLD8 or older UniPhier SoCs. > > + bool "UniPhier I2C driver" > > + depends on ARCH_UNIPHIER && DM_I2C > > + default y > > + help > > + Support for UniPhier I2C controller driver. This I2C controller > > + is used on PH1-LD4, PH1-sLD8 or older UniPhier SoCs. > > > > config SYS_I2C_UNIPHIER_F > > - bool "UniPhier FIFO-builtin I2C driver" > > - depends on ARCH_UNIPHIER && DM_I2C > > - default y > > - help > > - Support for UniPhier FIFO-builtin I2C controller driver. > > - This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs. > > + bool "UniPhier FIFO-builtin I2C driver" > > + depends on ARCH_UNIPHIER && DM_I2C > > + default y > > + help > > + Support for UniPhier FIFO-builtin I2C controller driver. > > + This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs. > > > > config SYS_I2C_VERSATILE > > - bool "Arm Ltd Versatile I2C bus driver" > > - depends on DM_I2C && (TARGET_VEXPRESS_CA15_TC2 || > > TARGET_VEXPRESS64_JUNO) > > - help > > - Add support for the Arm Ltd Versatile Express I2C driver. The I2C > > host > > - controller is present in the development boards manufactured by Arm > > Ltd. > > + bool "Arm Ltd Versatile I2C bus driver" > > + depends on DM_I2C && (TARGET_VEXPRESS_CA15_TC2 || > > TARGET_VEXPRESS64_JUNO) > > + help > > + Add support for the Arm Ltd Versatile Express I2C driver. The I2C > > host > > + controller is present in the development boards manufactured by Arm > > Ltd. > > > > config SYS_I2C_MVTWSI > > - bool "Marvell I2C driver" > > - depends on DM_I2C > > - help > > - Support for Marvell I2C controllers as used on the orion5x and > > - kirkwood SoC families. > > + bool "Marvell I2C driver" > > + depends on DM_I2C > > + help > > + Support for Marvell I2C controllers as used on the orion5x and > > + kirkwood SoC families. > > > > config TEGRA186_BPMP_I2C > > - bool "Enable Tegra186 BPMP-based I2C driver" > > - depends on TEGRA186_BPMP > > - help > > - Support for Tegra I2C controllers managed by the BPMP (Boot and > > - Power Management Processor). On Tegra186, some I2C controllers are > > - directly controlled by the main CPU, whereas others are controlled > > - by the BPMP, and can only be accessed by the main CPU via IPC > > - requests to the BPMP. This driver covers the latter case. > > + bool "Enable Tegra186 BPMP-based I2C driver" > > + depends on TEGRA186_BPMP > > + help > > + Support for Tegra I2C controllers managed by the BPMP (Boot and > > + Power Management Processor). On Tegra186, some I2C controllers are > > + directly controlled by the main CPU, whereas others are controlled > > + by the BPMP, and can only be accessed by the main CPU via IPC > > + requests to the BPMP. This driver covers the latter case. > > > > config SYS_I2C_BUS_MAX > > - int "Max I2C busses" > > - depends on ARCH_KEYSTONE || ARCH_OMAP2PLUS || ARCH_SOCFPGA > > - default 2 if TI816X > > - default 3 if OMAP34XX || AM33XX || AM43XX || ARCH_KEYSTONE > > - default 4 if ARCH_SOCFPGA || OMAP44XX || TI814X > > - default 5 if OMAP54XX > > - help > > - Define the maximum number of available I2C buses. > > + int "Max I2C busses" > > + depends on ARCH_KEYSTONE || ARCH_OMAP2PLUS || ARCH_SOCFPGA > > + default 2 if TI816X > > + default 3 if OMAP34XX || AM33XX || AM43XX || ARCH_KEYSTONE > > + default 4 if ARCH_SOCFPGA || OMAP44XX || TI814X > > + default 5 if OMAP54XX > > + help > > + Define the maximum number of available I2C buses. > > > > config SYS_I2C_XILINX_XIIC > > - bool "Xilinx AXI I2C driver" > > - depends on DM_I2C > > - help > > - Support for Xilinx AXI I2C controller. > > + bool "Xilinx AXI I2C driver" > > + depends on DM_I2C > > + help > > + Support for Xilinx AXI I2C controller. > > > > config SYS_I2C_IHS > > bool "gdsys IHS I2C driver" > > diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile > > index c2f75d8755..7cfe68e088 100644 > > --- a/drivers/i2c/Makefile > > +++ b/drivers/i2c/Makefile > > @@ -38,5 +38,5 @@ obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o > > obj-$(CONFIG_SYS_I2C_VERSATILE) += i2c-versatile.o > > obj-$(CONFIG_SYS_I2C_XILINX_XIIC) += xilinx_xiic.o > > obj-$(CONFIG_TEGRA186_BPMP_I2C) += tegra186_bpmp_i2c.o > > - > > +obj-$(CONFIG_IPROC_I2C) += iproc_i2c.o > > please keep lists sorted! > (Same applies to your "drivers: pcie: Add Broadcom IPROC PCIe driver" patch) > > > obj-$(CONFIG_I2C_MUX) += muxes/ > > diff --git a/drivers/i2c/iproc_i2c.c b/drivers/i2c/iproc_i2c.c > > new file mode 100644 > > index 0000000000..692035666c > > --- /dev/null > > +++ b/drivers/i2c/iproc_i2c.c > > @@ -0,0 +1,765 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (C)) 2018 Broadcom > > + */ > > + > > +#include <common.h> > > +#include <config.h> > > +#include <dm.h> > > +#include <i2c.h> > > +#include <asm/io.h> > > +#include "errno.h" > > +#include "iproc_i2c.h" > > + > > +DECLARE_GLOBAL_DATA_PTR; > > + > > +static int i2c_init_done; > > + > > +struct iproc_i2c_regs { > > + u32 cfg_reg; > > + u32 timg_cfg; > > + u32 addr_reg; > > + u32 mstr_fifo_ctrl; > > + u32 slv_fifo_ctrl; > > + u32 bitbng_ctrl; > > + u32 blnks[6]; /* Not to be used */ > > + u32 mstr_cmd; > > + u32 slv_cmd; > > + u32 evt_en; > > + u32 evt_sts; > > + u32 mstr_datawr; > > + u32 mstr_datard; > > + u32 slv_datawr; > > + u32 slv_datard; > > +}; > > + > > +struct iproc_i2c { > > + struct iproc_i2c_regs __iomem *base; /* register base */ > > + int bus_speed; > > +}; > > + > > +/* Function to read a value from specified register. */ > > +static unsigned int iproc_i2c_reg_read(u32 *reg_addr) > > +{ > > + unsigned int val; > > + > > + val = readl((void *)(reg_addr)); > > + return cpu_to_le32(val); > > +} > > + > > +/* Function to write a value ('val') in to a specified register. */ > > +static int iproc_i2c_reg_write(u32 *reg_addr, unsigned int val) > > +{ > > + val = cpu_to_le32(val); > > + writel(val, (void *)(reg_addr)); > > + return 0; > > +} > > + > > +#ifdef IPROC_I2C_DBG > > Can you add this define at least through Kconfig ? > > Do we need this define? debug() should be dropped if DEBUG is > not defined... and you can do here > > #if defined(DEBUG) > static int iproc_dump_i2c_regs(struct iproc_i2c *bus_prvdata) > [...] > #else > static int iproc_dump_i2c_regs(struct iproc_i2c *bus_prvdata){ > return 0; > } > #endif > > and drop all later "ifdef IPROC_I2C_DBG" stuff... > > > +static int iproc_dump_i2c_regs(struct iproc_i2c *bus_prvdata) > > +{ > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + unsigned int regval; > > + > > + debug("\n----------------------------------------------\n"); > > + debug("%s: Dumping SMBus registers...\n", __func__); > > + > > + regval = iproc_i2c_reg_read(&base->cfg_reg); > > + debug("CCB_SMB_CFG_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->timg_cfg); > > + debug("CCB_SMB_TIMGCFG_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->addr_reg); > > + debug("CCB_SMB_ADDR_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->mstr_fifo_ctrl); > > + debug("CCB_SMB_MSTRFIFOCTL_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->slv_fifo_ctrl); > > + debug("CCB_SMB_SLVFIFOCTL_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->bitbng_ctrl); > > + debug("CCB_SMB_BITBANGCTL_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + debug("CCB_SMB_MSTRCMD_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->slv_cmd); > > + debug("CCB_SMB_SLVCMD_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->evt_en); > > + debug("CCB_SMB_EVTEN_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->evt_sts); > > + debug("CCB_SMB_EVTSTS_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->mstr_datawr); > > + debug("CCB_SMB_MSTRDATAWR_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->mstr_datard); > > + debug("CCB_SMB_MSTRDATARD_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->slv_datawr); > > + debug("CCB_SMB_SLVDATAWR_REG=0x%08X\n", regval); > > + > > + regval = iproc_i2c_reg_read(&base->slv_datard); > > + debug("CCB_SMB_SLVDATARD_REG=0x%08X\n", regval); > > + > > + debug("----------------------------------------------\n\n"); > > + return 0; > > +} > > +#endif > > + > > +/* > > + * Function to ensure that the previous transaction was completed before > > + * initiating a new transaction. It can also be used in polling mode to > > + * check status of completion of a command > > + */ > > +static int iproc_i2c_startbusy_wait(struct iproc_i2c *bus_prvdata) > > +{ > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + unsigned int regval; > > + > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + > > + /* Check if an operation is in progress. During probe it won't be. > > + * But when shutdown/remove was called we want to make sure that > > + * the transaction in progress completed > > + */ > > + if (regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) { > > + unsigned int i = 0; > > + > > + do { > > + mdelay(10); /* Wait for 10 msec */ > > Please remove this comment. > > > + i++; > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + > > + /* If start-busy bit cleared, exit the loop */ > > + } while ((regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) && > > + (i < IPROC_SMB_MAX_RETRIES)); > > + > > + if (i >= IPROC_SMB_MAX_RETRIES) { > > + pr_err("%s: START_BUSY bit didn't clear, exiting\n", > > + __func__); > > + > > + return -ETIMEDOUT; > > + } > > + } > > + return 0; > > +} > > + > > +/* > > + * This function set clock frequency for SMBus block. As per hardware > > + * engineering, the clock frequency can be changed dynamically. > > + */ > > +static int iproc_i2c_set_clk_freq(struct iproc_i2c *bus_prvdata) > > +{ > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + unsigned int regval; > > + > > + regval = iproc_i2c_reg_read(&base->timg_cfg); > > + > > + switch (bus_prvdata->bus_speed) { > > + case I2C_SPEED_100KHZ: > > + SETREGFLDVAL(regval, SMBUS_BLOCK_MODE_100, > > + CCB_SMB_TIMGCFG_MODE400_MASK, > > + CCB_SMB_TIMGCFG_MODE400_SHIFT); > > + break; > > + > > + case I2C_SPEED_400KHZ: > > + SETREGFLDVAL(regval, SMBUS_BLOCK_MODE_400, > > + CCB_SMB_TIMGCFG_MODE400_MASK, > > + CCB_SMB_TIMGCFG_MODE400_SHIFT); > > + break; > > + > > + default: > > + return -EINVAL; > > + } > > + > > + iproc_i2c_reg_write(&base->timg_cfg, regval); > > + return 0; > > +} > > + > > +static int iproc_i2c_init(struct iproc_i2c *bus_prvdata) > > +{ > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + unsigned int regval; > > + > > +#ifdef IPROC_I2C_DBG > > + debug("\n%s: Entering", __func__); > > +#endif /* IPROC_I2C_DBG */ > > + > > + /* Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0. > > + * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts > > + */ > > + regval = CCB_SMB_MSTRRXFIFOFLSH_MASK | CCB_SMB_MSTRTXFIFOFLSH_MASK; > > + iproc_i2c_reg_write(&base->mstr_fifo_ctrl, regval); > > + > > + /* Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero > > + * since there will be only one master > > + */ > > + > > + regval = iproc_i2c_reg_read(&base->cfg_reg); > > + regval |= CCB_SMB_CFG_SMBEN_MASK; > > + iproc_i2c_reg_write(&base->cfg_reg, regval); > > +#if defined(CONFIG_CYGNUS) || defined(CONFIG_TARGET_BCMOMEGA) > > What are this defines? Wbere come they from ? They are not in current mainline > code: > > pollux:u-boot hs [work] $ grep -lr CONFIG_CYGNUS . > ./mbox > pollux:u-boot hs [work] $ grep -lr BCMOMEGA . > ./mbox > pollux:u-boot hs [work] $ > > please remove this code. Also this seems board specific code. We should > prevent this in common driver code! > > > + regval = iproc_i2c_reg_read(&base->cfg_reg); > > + regval |= CCB_SMB_CFG_RST_MASK; > > + iproc_i2c_reg_write(&base->cfg_reg, regval); > > + regval &= ~CCB_SMB_CFG_RST_MASK; > > + iproc_i2c_reg_write(&base->cfg_reg, regval); > > +#endif > > + /* Wait a minimum of 50 Usec, as per SMB hw doc */ > > + udelay(50); > > linux driver waits here for 100usec ... with the comment "per spec" ... > and flushes the FIFO after ... but I have no insight into this hardware, > so cannot say, what the better procedure... > > > + > > + /* Set default clock frequency */ > > + iproc_i2c_set_clk_freq(bus_prvdata); > > + > > + /* Disable intrs */ > > + iproc_i2c_reg_write(&base->evt_en, 0); > > + > > + /* Clear intrs (W1TC) */ > > + regval = iproc_i2c_reg_read(&base->evt_sts); > > + iproc_i2c_reg_write(&base->evt_sts, regval); > > + > > + i2c_init_done = 1; > > Why you need this global variable ? Please store this variable > in "iproc_i2c" > > > + > > +#ifdef IPROC_I2C_DBG > > + iproc_dump_i2c_regs(bus_prvdata); > > + > > + debug("%s: Init successful\n", __func__); > > +#endif /* IPROC_I2C_DBG */ > > + > > + return 0; > > +} > > + > > +/* > > + * This function copies data to SMBus's Tx FIFO. Valid for write > > transactions > > + * only > > + * > > + * base_addr: Mapped address of this SMBus instance > > + * dev_addr: SMBus (I2C) device address. We are assuming 7-bit addresses > > + * initially > > + * info: Data to copy in to Tx FIFO. For read commands, the size should > > be > > + * set to zero by the caller > > + * > > + */ > > +static void iproc_i2c_write_trans_data(struct iproc_i2c *bus_prvdata, > > + unsigned short dev_addr, > > + struct iproc_xact_info *info) > > +{ > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + unsigned int regval; > > + unsigned int i; > > + unsigned int num_data_bytes = 0; > > + > > +#ifdef IPROC_I2C_DBG > > + debug("%s: dev_addr=0x%X cmd_valid=%d cmd=0x%02x size=%u proto=%d\n" > > + "buf[] %x\n", > > + __func__, > > + dev_addr, > > + info->cmd_valid, > > + info->command, > > + info->size, > > + info->smb_proto, > > + info->data[0]); > > +#endif /* IPROC_I2C_DBG */ > > + > > + /* Write SMBus device address first */ > > + /* Note, we are assuming 7-bit addresses for now. For 10-bit > > addresses, > > + * we may have one more write to send the upper 3 bits of 10-bit addr > > + */ > > + iproc_i2c_reg_write(&base->mstr_datawr, dev_addr); > > + > > + /* If the protocol needs command code, copy it */ > > + if (info->cmd_valid) > > + iproc_i2c_reg_write(&base->mstr_datawr, info->command); > > + > > + /* Depending on the SMBus protocol, we need to write additional > > + * transaction data in to Tx FIFO. Refer to section 5.5 of SMBus > > + * spec for sequence for a transaction > > + */ > > + switch (info->smb_proto) { > > + case SMBUS_PROT_RECV_BYTE: > > + /* No additional data to be written */ > > + num_data_bytes = 0; > > + break; > > + > > + case SMBUS_PROT_SEND_BYTE: > > + num_data_bytes = info->size; > > + break; > > + > > + case SMBUS_PROT_RD_BYTE: > > + case SMBUS_PROT_RD_WORD: > > + case SMBUS_PROT_BLK_RD: > > + /* Write slave address with R/W~ set (bit #0) */ > > + iproc_i2c_reg_write(&base->mstr_datawr, > > + dev_addr | 0x1); > > + num_data_bytes = 0; > > + break; > > +#if defined(CONFIG_CYGNUS) || defined(CONFIG_TARGET_BCMOMEGA) > > + case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL: > > + iproc_i2c_reg_write(&base->mstr_datawr, > > + dev_addr | 0x1 | > > + CCB_SMB_MSTRWRSTS_MASK); > > + num_data_bytes = 0; > > + break; > > +#endif > > + case SMBUS_PROT_WR_BYTE: > > + case SMBUS_PROT_WR_WORD: > > + /* No additional bytes to be written. > > + * Data portion is written in the > > + * 'for' loop below > > + */ > > + num_data_bytes = info->size; > > + break; > > + > > + case SMBUS_PROT_BLK_WR: > > + /* 3rd byte is byte count */ > > + iproc_i2c_reg_write(&base->mstr_datawr, info->size); > > + num_data_bytes = info->size; > > + break; > > + > > + default: > > + break; > > + } > > + > > + /* Copy actual data from caller, next. In general, for reads, no data > > is > > + * copied > > + */ > > + for (i = 0; num_data_bytes; --num_data_bytes, i++) { > > + /* For the last byte, set MASTER_WR_STATUS bit */ > > + regval = (num_data_bytes == 1) ? > > + info->data[i] | CCB_SMB_MSTRWRSTS_MASK : > > + info->data[i]; > > + > > + iproc_i2c_reg_write(&base->mstr_datawr, regval); > > + } > > +} > > + > > +static int iproc_i2c_data_send(struct iproc_i2c *bus_prvdata, > > + unsigned short addr, > > + struct iproc_xact_info *info) > > +{ > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + int rc, retry = 3; unsigned int regval; > > + > > + /* Make sure the previous transaction completed */ > > + rc = iproc_i2c_startbusy_wait(bus_prvdata); > > + > > + if (rc < 0) { > > + pr_err("%s: Send: bus is busy, exiting\n", __func__); > > + return rc; > > + } > > + > > + /* Write transaction bytes to Tx FIFO */ > > + iproc_i2c_write_trans_data(bus_prvdata, addr, info); > > + > > + /* Program master command register (0x30) with protocol type and set > > + * start_busy_command bit to initiate the write transaction > > + */ > > + regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | > > + CCB_SMB_MSTRSTARTBUSYCMD_MASK; > > + > > + iproc_i2c_reg_write(&base->mstr_cmd, regval); > > + > > + /* Check for Master status */ > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + while (regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) { > > + mdelay(10); > > + if (retry-- <= 0) > > + break; > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + } > > + > > + /* If start_busy bit cleared, check if there are any errors */ > > + if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { > > + /* start_busy bit cleared, check master_status field now */ > > + regval &= CCB_SMB_MSTRSTS_MASK; > > + regval >>= CCB_SMB_MSTRSTS_SHIFT; > > + > > + if (regval != MSTR_STS_XACT_SUCCESS) { > > + /* Error We can flush Tx FIFO here */ > > + pr_err("%s: ERROR: Error in transaction %u, > > exiting\n", > > + __func__, regval); > > + return -EREMOTEIO; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int iproc_i2c_data_recv(struct iproc_i2c *bus_prvdata, > > + unsigned short addr, > > + struct iproc_xact_info *info, > > + unsigned int *num_bytes_read) > > +{ > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + int rc, retry = 3; > > + unsigned int regval; > > + > > + /* Make sure the previous transaction completed */ > > + rc = iproc_i2c_startbusy_wait(bus_prvdata); > > + > > + if (rc < 0) { > > + pr_err("%s: Receive: Bus is busy, exiting\n", __func__); > > + return rc; > > + } > > + > > + /* Program all transaction bytes into master Tx FIFO */ > > + iproc_i2c_write_trans_data(bus_prvdata, addr, info); > > + > > + /* Program master command register (0x30) with protocol type and set > > + * start_busy_command bit to initiate the write transaction > > + */ > > + regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | > > + CCB_SMB_MSTRSTARTBUSYCMD_MASK | info->size; > > + > > + iproc_i2c_reg_write(&base->mstr_cmd, regval); > > + > > + /* Check for Master status */ > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + while (regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) { > > + udelay(1000); > > + if (retry-- <= 0) > > + break; > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + } > > + > > + /* If start_busy bit cleared, check if there are any errors */ > > + if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { > > + /* start_busy bit cleared, check master_status field now */ > > + regval &= CCB_SMB_MSTRSTS_MASK; > > + regval >>= CCB_SMB_MSTRSTS_SHIFT; > > + > > + if (regval != MSTR_STS_XACT_SUCCESS) { > > + /* We can flush Tx FIFO here */ > > + pr_err("%s: Error in transaction %d, exiting\n", > > + __func__, regval); > > + return -EREMOTEIO; > > + } > > + } > > + > > + /* Read received byte(s), after TX out address etc */ > > + regval = iproc_i2c_reg_read(&base->mstr_datard); > > + > > + /* For block read, protocol (hw) returns byte count, > > + * as the first byte > > + */ > > + if (info->smb_proto == SMBUS_PROT_BLK_RD) { > > + int i; > > + > > + *num_bytes_read = regval & CCB_SMB_MSTRRDDATA_MASK; > > + > > + /* Limit to reading a max of 32 bytes only; just a safeguard. > > + * If # bytes read is a number > 32, check transaction set up, > > + * and contact hw engg. Assumption: PEC is disabled > > + */ > > + for (i = 0; > > + (i < *num_bytes_read) && (i < I2C_SMBUS_BLOCK_MAX); > > + i++) { > > + /* Read Rx FIFO for data bytes */ > > + regval = iproc_i2c_reg_read(&base->mstr_datard); > > + info->data[i] = regval & CCB_SMB_MSTRRDDATA_MASK; > > + } > > + } else { > > + /* 1 Byte data */ > > + *info->data = regval & CCB_SMB_MSTRRDDATA_MASK; > > + *num_bytes_read = 1; > > + } > > + > > + return 0; > > +} > > + > > +static int i2c_write_byte(struct iproc_i2c *bus_prvdata, > > + u8 devaddr, > > + u8 regoffset, > > + u8 value) > > +{ > > + int rc; > > + struct iproc_xact_info info; > > + > > + devaddr <<= 1; > > + > > + info.cmd_valid = 1; > > + info.command = (unsigned char)regoffset; > > + info.data = &value; > > + info.size = 1; > > + info.flags = 0; > > +#if defined(CONFIG_CYGNUS) || defined(CONFIG_TARGET_BCMOMEGA) > > unknown defines ... > > > + info.smb_proto = SMBUS_PROT_WR_WORD;/*SMBUS_PROT_WR_BYTE;*/ > > +#else > > + info.smb_proto = SMBUS_PROT_WR_BYTE; > > +#endif > > + /* Refer to i2c_smbus_write_byte params passed. */ > > + rc = iproc_i2c_data_send(bus_prvdata, devaddr, &info); > > + > > + if (rc < 0) { > > + pr_err("%s: %s error accessing device 0x%X\n", > > + __func__, "Write", devaddr); > > + return -EREMOTEIO; > > + } > > + > > + return 0; > > +} > > + > > +int i2c_write(struct iproc_i2c *bus_prvdata, > > + uchar chip, > > + uint regaddr, > > + int alen, > > + uchar *buffer, > > + int len) > > +{ > > + int i, data_len; > > + u8 *data; > > + > > + if (alen > 1) { > > + pr_err("I2C write: addr len %d not supported\n", alen); > > + return 1; > > + } > > + > > + if (regaddr + len > 256) { > > + pr_err("I2C write: address out of range\n"); > > + return 1; > > + } > > + > > + if (len < 1) { > > + pr_err("I2C write: Need offset addr and value\n"); > > + return 1; > > + } > > + > > + /* buffer contains offset addr followed by value to be written */ > > + regaddr = buffer[0]; > > + data = &buffer[1]; > > + data_len = len - 1; > > + > > + for (i = 0; i < data_len; i++) { > > + if (i2c_write_byte(bus_prvdata, chip, regaddr + i, data[i])) { > > + pr_err("I2C write (%d): I/O error\n", i); > > + iproc_i2c_init(bus_prvdata); > > + return 1; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int i2c_read_byte(struct iproc_i2c *bus_prvdata, > > + u8 devaddr, > > + u8 regoffset, > > + u8 *value) > > +{ > > + int rc; > > + struct iproc_xact_info info; > > + unsigned int num_bytes_read = 0; > > + > > + devaddr <<= 1; > > + > > + info.cmd_valid = 1; > > + info.command = (unsigned char)regoffset; > > + info.data = value; > > + info.size = 1; > > + info.flags = 0; > > +#if defined(CONFIG_CYGNUS) || defined(CONFIG_TARGET_BCMOMEGA) > > + info.smb_proto = SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL; > > +#else > > + info.smb_proto = SMBUS_PROT_RD_BYTE; > > +#endif > > + /* Refer to i2c_smbus_read_byte for params passed. */ > > + rc = iproc_i2c_data_recv(bus_prvdata, devaddr, &info, > > &num_bytes_read); > > + > > + if (rc < 0) { > > + pr_err("%s: %s error accessing device 0x%X\n", > > + __func__, "Read", devaddr); > > + return -EREMOTEIO; > > + } > > + > > + return 0; > > +} > > + > > +int i2c_read(struct iproc_i2c *bus_prvdata, > > + uchar chip, > > + uint addr, > > + int alen, > > + uchar *buffer, > > + int len) > > +{ > > + int i; > > + > > + if (alen > 1) { > > + pr_err("I2C read: addr len %d not supported\n", alen); > > + return 1; > > + } > > + > > + if (addr + len > 256) { > > + pr_err("I2C read: address out of range\n"); > > + return 1; > > + } > > You always pass addr = 0 and alen = 0 ... so this checks are useless (beside > len check) > same for i2c_write ... > > > + > > + for (i = 0; i < len; i++) { > > + if (i2c_read_byte(bus_prvdata, chip, addr + i, &buffer[i])) { > > + pr_err("I2C read: I/O error\n"); > > + iproc_i2c_init(bus_prvdata); > > + return 1; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int iproc_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int > > nmsgs) > > +{ > > + struct iproc_i2c *bus_prvdata = dev_get_priv(bus); > > + int ret = 0; > > + > > +#ifdef IPROC_I2C_DBG > > + debug("%s: %d messages\n", __func__, nmsgs); > > +#endif > > + > > + for (; nmsgs > 0; nmsgs--, msg++) { > > + if (msg->flags & I2C_M_RD) > > + ret = i2c_read(bus_prvdata, > > + msg->addr, > > + 0, > > + 0, > > + msg->buf, > > + msg->len); > > + else > > + ret = i2c_write(bus_prvdata, > > + msg->addr, > > + 0, > > + 0, > > + msg->buf, > > + msg->len); > > + } > > + > > + return ret; > > +} > > + > > +static int iproc_i2c_probe_chip(struct udevice *bus, uint chip_addr, > > + uint chip_flags) > > +{ > > + struct iproc_i2c *bus_prvdata = dev_get_priv(bus); > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + u32 regval; > > + > > +#ifdef IPROC_I2C_DBG > > + debug("\n%s: Entering chip probe\n", __func__); > > +#endif /* IPROC_I2C_DBG */ > > + > > + /* Init internal regs, disable intrs (and then clear intrs), set fifo > > + * thresholds, etc. > > + */ > > + if (!i2c_init_done) > > + iproc_i2c_init(bus_prvdata); > > Couldn;t you store this "i2c_init_done" in bus_prvdata ? > > > + > > + regval = (chip_addr << 1); > > + iproc_i2c_reg_write(&base->mstr_datawr, regval); > > + regval = ((SMBUS_PROT_QUICK_CMD << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | > > + (1 << CCB_SMB_MSTRSTARTBUSYCMD_SHIFT)); > > + iproc_i2c_reg_write(&base->mstr_cmd, regval); > > + > > + do { > > + udelay(100); > > Is this delay somewhere described in a spec? > > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + regval &= CCB_SMB_MSTRSTARTBUSYCMD_MASK; > > + } while (regval); > > + > > + regval = iproc_i2c_reg_read(&base->mstr_cmd); > > + > > + if ((regval & CCB_SMB_MSTRSTS_MASK) != 0) > > + return -1; > > + > > +#ifdef IPROC_I2C_DBG > > + iproc_dump_i2c_regs(bus_prvdata); > > + > > + debug("%s: chip probe successful\n", __func__); > > +#endif /* IPROC_I2C_DBG */ > > + > > + return 0; > > +} > > + > > +static int iproc_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) > > +{ > > + struct iproc_i2c *bus_prvdata = dev_get_priv(bus); > > + > > + bus_prvdata->bus_speed = speed; > > + if (iproc_i2c_set_clk_freq(bus_prvdata)) > > + return -EINVAL; > > couldn; t you return simply the return value from iproc_i2c_set_clk_freq()? > > > + > > + return 0; > > +} > > + > > +/** > > + * i2c_get_bus_speed - get i2c bus speed > > + * > > + * This function returns the speed of operation in Hz > > + */ > > +int iproc_i2c_get_bus_speed(struct udevice *bus) > > +{ > > + struct iproc_i2c *bus_prvdata = dev_get_priv(bus); > > + struct iproc_i2c_regs *base = bus_prvdata->base; > > + unsigned int regval; > > + unsigned int val; > > + > > + regval = iproc_i2c_reg_read(&base->timg_cfg); > > + val = GETREGFLDVAL(regval, CCB_SMB_TIMGCFG_MODE400_MASK, > > + CCB_SMB_TIMGCFG_MODE400_SHIFT); > > + switch (val) { > > + case 0: > > + return I2C_SPEED_100KHZ; > > + case 1: > > + return I2C_SPEED_400KHZ; > > + default: > > + return -EINVAL; > > + } > > + return -EINVAL; > > +} > > + > > +static int iproc_i2c_probe(struct udevice *bus) > > +{ > > + struct iproc_i2c *bus_prvdata = dev_get_priv(bus); > > + > > + return iproc_i2c_init(bus_prvdata); > > +} > > + > > +static int iproc_i2c_ofdata_to_platdata(struct udevice *bus) > > +{ > > + struct iproc_i2c *bus_prvdata = dev_get_priv(bus); > > + int node = dev_of_offset(bus); > > + const void *blob = gd->fdt_blob; > > + > > + bus_prvdata->base = map_physmem(devfdt_get_addr(bus), > > + sizeof(void *), > > + MAP_NOCACHE); > > + > > + /* default 100KHz freq */ > > + bus_prvdata->bus_speed = fdtdec_get_int(blob, node, "bus-frequency", > > + I2C_SPEED_100KHZ); > > + > > + return 0; > > +} > > + > > +static const struct dm_i2c_ops iproc_i2c_ops = { > > + .xfer = iproc_i2c_xfer, > > + .probe_chip = iproc_i2c_probe_chip, > > + .set_bus_speed = iproc_i2c_set_bus_speed, > > + .get_bus_speed = iproc_i2c_get_bus_speed, > > +}; > > + > > +static const struct udevice_id iproc_i2c_ids[] = { > > + { .compatible = "brcm,iproc-i2c" }, > > + { } > > +}; > > + > > +U_BOOT_DRIVER(iproc_i2c) = { > > + .name = "iproc_i2c", > > + .id = UCLASS_I2C, > > + .of_match = iproc_i2c_ids, > > + .ofdata_to_platdata = iproc_i2c_ofdata_to_platdata, > > + .probe = iproc_i2c_probe, > > + .priv_auto_alloc_size = sizeof(struct iproc_i2c), > > + .ops = &iproc_i2c_ops, > > + .flags = DM_FLAG_PRE_RELOC, > > +}; > > diff --git a/drivers/i2c/iproc_i2c.h b/drivers/i2c/iproc_i2c.h > > new file mode 100644 > > index 0000000000..4f8d6ba2b2 > > --- /dev/null > > +++ b/drivers/i2c/iproc_i2c.h > > @@ -0,0 +1,356 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > +/* Copyright (C) 2018 Broadcom */ > > + > > +#ifndef __IPROC_I2C_H__ > > +#define __IPROC_I2C_H__ > > + > > +#if (defined(CONFIG_NS_PLUS) || defined(CONFIG_HELIX4)) > > again defines not in mainline! Please remove! > > > +#define SHADOW_CPY_BUFFER_ADDR1 0x70000000 > > +#define SHADOW_CPY_BUFFER_ADDR2 0x70100000 > > +#define IPROC_SMBUS_BASE_ADDR1 0x18038000 > > +#define IPROC_SMBUS_BASE_ADDR2 0x1803B000 > > +#elif (defined(CONFIG_CYGNUS)) > > +#define SHADOW_CPY_BUFFER_ADDR1 0x70000000 > > +#define SHADOW_CPY_BUFFER_ADDR2 0x70100000 > > +#define IPROC_SMBUS_BASE_ADDR1 0x18008000 > > +#define IPROC_SMBUS_BASE_ADDR2 0x1800B000 > > +#endif > > Hmm... couldn;t come this values through DTS ? > > SHADOW_CPY_BUFFER_ADDR1, SHADOW_CPY_BUFFER_ADDR2, IPROC_SMBUS_BASE_ADDR1 > and IPROC_SMBUS_BASE_ADDR2 not used in this patch in other places! > > So please remove this defines complete. > > > + > > +/* Registers */ > > +#define CCB_SMB_CFG_REG 0x0 > > + > > +#define CCB_SMB_CFG_RST_MASK 0x80000000 > > +#define CCB_SMB_CFG_RST_SHIFT 31 > > + > > +#define CCB_SMB_CFG_SMBEN_MASK 0x40000000 > > +#define CCB_SMB_CFG_SMBEN_SHIFT 30 > > + > > +#define CCB_SMB_CFG_BITBANGEN_MASK 0x20000000 > > +#define CCB_SMB_CFG_BITBANGEN_SHIFT 29 > > + > > +#define CCB_SMB_CFG_EN_NIC_SMBADDR0_MASK 0x10000000 > > +#define CCB_SMB_CFG_EN_NIC_SMBADDR0_SHIFT 28 > > + > > +#define CCB_SMB_CFG_PROMISCMODE_MASK 0x08000000 > > +#define CCB_SMB_CFG_PROMISCMODE_SHIFT 27 > > + > > +#define CCB_SMB_CFG_TSTMPCNTEN_MASK 0x04000000 > > +#define CCB_SMB_CFG_TSTMPCNTEN_SHIFT 26 > > + > > +#define CCB_SMB_CFG_MSTRRTRYCNT_MASK 0x000F0000 > > +#define CCB_SMB_CFG_MSTRRTRYCNT_SHIFT 16 > > + > > +#define CCB_SMB_TIMGCFG_REG 0x4 > > + > > +#define CCB_SMB_TIMGCFG_MODE400_MASK 0x80000000 > > +#define CCB_SMB_TIMGCFG_MODE400_SHIFT 31 > > + > > +#define CCB_SMB_TIMGCFG_RNDSLVSTR_MASK 0x7F000000 > > +#define CCB_SMB_TIMGCFG_RNDSLVSTR_SHIFT 24 > > + > > +#define CCB_SMB_TIMGCFG_PERSLVSTR_MASK 0x00FF0000 > > +#define CCB_SMB_TIMGCFG_PERSLVSTR_SHIFT 16 > > + > > +#define CCB_SMB_TIMGCFG_IDLTIME_MASK 0x0000FF00 > > +#define CCB_SMB_TIMGCFG_IDLTIME_SHIFT 8 > > + > > +#define CCB_SMB_ADDR_REG 0x8 > > + > > +#define CCB_SMB_EN_NIC_SMBADDR3_MASK 0x80000000 > > +#define CCB_SMB_EN_NIC_SMBADDR3_SHIFT 31 > > + > > +#define CCB_SMB_NIC_SMBADDR3_MASK 0x7F000000 > > +#define CCB_SMB_NIC_SMBADDR3_SHIFT 24 > > + > > +#define CCB_SMB_EN_NIC_SMBADDR2_MASK 0x00800000 > > +#define CCB_SMB_EN_NIC_SMBADDR2_SHIFT 23 > > + > > +#define CCB_SMB_NIC_SMBADDR2_MASK 0x007F0000 > > +#define CCB_SMB_NIC_SMBADDR2_SHIFT 16 > > + > > +#define CCB_SMB_EN_NIC_SMBADDR1_MASK 0x00008000 > > +#define CCB_SMB_EN_NIC_SMBADDR1_SHIFT 15 > > + > > +#define CCB_SMB_NIC_SMBADDR1_MASK 0x00007F00 > > +#define CCB_SMB_NIC_SMBADDR1_SHIFT 8 > > + > > +#define CCB_SMB_EN_NIC_SMBADDR0_MASK 0x00000080 > > +#define CCB_SMB_EN_NIC_SMBADDR0_SHIFT 7 > > + > > +#define CCB_SMB_NIC_SMBADDR0_MASK 0x0000007F > > +#define CCB_SMB_NIC_SMBADDR0_SHIFT 0 > > + > > +#define CCB_SMB_MSTRFIFOCTL_REG 0xC > > + > > +#define CCB_SMB_MSTRRXFIFOFLSH_MASK 0x80000000 > > +#define CCB_SMB_MSTRRXFIFOFLSH_SHIFT 31 > > + > > +#define CCB_SMB_MSTRTXFIFOFLSH_MASK 0x40000000 > > +#define CCB_SMB_MSTRTXFIFOFLSH_SHIFT 30 > > + > > +#define CCB_SMB_MSTRRXPKTCNT_MASK 0x007F0000 > > +#define CCB_SMB_MSTRRXPKTCNT_SHIFT 16 > > + > > +#define CCB_SMB_MSTRRXFIFOTHR_MASK 0x00003F00 > > +#define CCB_SMB_MSTRRXFIFOTHR_SHIFT 8 > > + > > +#define CCB_SMB_SLVFIFOCTL_REG 0x10 > > + > > +#define CCB_SMB_SLVRXFIFOFLSH_MASK 0x80000000 > > +#define CCB_SMB_SLVRXFIFOFLSH_SHIFT 31 > > + > > +#define CCB_SMB_SLVTXFIFOFLSH_MASK 0x40000000 > > +#define CCB_SMB_SLVTXFIFOFLSH_SHIFT 30 > > + > > +#define CCB_SMB_SLVRXPKTCNT_MASK 0x007F0000 > > +#define CCB_SMB_SLVRXPKTCNT_SHIFT 16 > > + > > +#define CCB_SMB_SLVRXFIFOTHR_MASK 0x00003F00 > > +#define CCB_SMB_SLVRXFIFOTHR_SHIFT 8 > > + > > +#define CCB_SMB_BITBANGCTL_REG 0x14 > > + > > +#define CCB_SMB_SMBCLKIN_MASK 0x80000000 > > +#define CCB_SMB_SMBCLKIN_SHIFT 31 > > + > > +#define CCB_SMB_SMBCLKOUTEN_MASK 0x40000000 > > +#define CCB_SMB_SMBCLKOUTEN_SHIFT 30 > > + > > +#define CCB_SMB_SMBDATAIN_MASK 0x20000000 > > +#define CCB_SMB_SMBDATAIN_SHIFT 29 > > + > > +#define CCB_SMB_SMBDATAOUTEN_MASK 0x10000000 > > +#define CCB_SMB_SMBDATAOUTEN_SHIFT 28 > > + > > +#define CCB_SMB_MSTRCMD_REG 0x30 > > + > > +#define CCB_SMB_MSTRSTARTBUSYCMD_MASK 0x80000000 > > +#define CCB_SMB_MSTRSTARTBUSYCMD_SHIFT 31 > > + > > +#define CCB_SMB_MSTRABORT_MASK 0x40000000 > > +#define CCB_SMB_MSTRABORT_SHIFT 30 > > + > > +#define CCB_SMB_MSTRSTS_MASK 0x0E000000 > > +#define CCB_SMB_MSTRSTS_SHIFT 25 > > + > > +#define CCB_SMB_MSTRSMBUSPROTO_MASK 0x00001E00 > > +#define CCB_SMB_MSTRSMBUSPROTO_SHIFT 9 > > + > > +#define CCB_SMB_MSTRPEC_MASK 0x00000100 > > +#define CCB_SMB_MSTRPEC_SHIFT 8 > > + > > +#define CCB_SMB_MSTRRDBYTECNT_MASK 0x000000FF > > +#define CCB_SMB_MSTRRDBYTECNT_SHIFT 0 > > + > > +#define CCB_SMB_SLVCMD_REG 0x34 > > + > > +#define CCB_SMB_SLVSTARTBUSYCMD_MASK 0x80000000 > > +#define CCB_SMB_SLVSTARTBUSYCMD_SHIFT 31 > > + > > +#define CCB_SMB_SLVABORT_MASK 0x40000000 > > +#define CCB_SMB_SLVABORT_SHIFT 30 > > + > > +#define CCB_SMB_SLVSTS_MASK 0x03800000 > > +#define CCB_SMB_SLVSTS_SHIFT 23 > > + > > +#define CCB_SMB_SLVPEC_MASK 0x00000100 > > +#define CCB_SMB_SLVPEC_SHIFT 8 > > + > > +#define CCB_SMB_EVTEN_REG 0x38 > > + > > +#define CCB_SMB_MSTRRXFIFOFULLEN_MASK 0x80000000 > > +#define CCB_SMB_MSTRRXFIFOFULLEN_SHIFT 31 > > + > > +#define CCB_SMB_MSTRRXFIFOTHRHITEN_MASK 0x40000000 > > +#define CCB_SMB_MSTRRXFIFOTHRHITEN_SHIFT 30 > > + > > +#define CCB_SMB_MSTRRXEVTEN_MASK 0x20000000 > > +#define CCB_SMB_MSTRRXEVTEN_SHIFT 29 > > + > > +#define CCB_SMB_MSTRSTARTBUSYEN_MASK 0x10000000 > > +#define CCB_SMB_MSTRSTARTBUSYEN_SHIFT 28 > > + > > +#define CCB_SMB_MSTRTXUNDEN_MASK 0x08000000 > > +#define CCB_SMB_MSTRTXUNDEN_SHIFT 27 > > + > > +#define CCB_SMB_SLVRXFIFOFULLEN_MASK 0x04000000 > > +#define CCB_SMB_SLVRXFIFOFULLEN_SHIFT 26 > > + > > +#define CCB_SMB_SLVRXFIFOTHRHITEN_MASK 0x02000000 > > +#define CCB_SMB_SLVRXFIFOTHRHITEN_SHIFT 25 > > + > > +#define CCB_SMB_SLVRXEVTEN_MASK 0x01000000 > > +#define CCB_SMB_SLVRXEVTEN_SHIFT 24 > > + > > +#define CCB_SMB_SLVSTARTBUSYEN_MASK 0x00800000 > > +#define CCB_SMB_SLVSTARTBUSYEN_SHIFT 23 > > + > > +#define CCB_SMB_SLVTXUNDEN_MASK 0x00400000 > > +#define CCB_SMB_SLVTXUNDEN_SHIFT 22 > > + > > +#define CCB_SMB_SLVRDEVTEN_MASK 0x00200000 > > +#define CCB_SMB_SLVRDEVTEN_SHIFT 21 > > + > > +#define CCB_SMB_EVTSTS_REG 0x3C > > + > > +#define CCB_SMB_MSTRRXFIFOFULLSTS_MASK 0x80000000 > > +#define CCB_SMB_MSTRRXFIFOFULLSTS_SHIFT 31 > > + > > +#define CCB_SMB_MSTRRXFIFOTHRHITSTS_MASK 0x40000000 > > +#define CCB_SMB_MSTRRXFIFOTHRHITSTS_SHIFT 30 > > + > > +#define CCB_SMB_MSTRRXEVTSTS_MASK 0x20000000 > > +#define CCB_SMB_MSTRRXEVTSTS_SHIFT 29 > > + > > +#define CCB_SMB_MSTRSTARTBUSYSTS_MASK 0x10000000 > > +#define CCB_SMB_MSTRSTARTBUSYSTS_SHIFT 28 > > + > > +#define CCB_SMB_MSTRTXUNDSTS_MASK 0x08000000 > > +#define CCB_SMB_MSTRTXUNDSTS_SHIFT 27 > > + > > +#define CCB_SMB_SLVRXFIFOFULLSTS_MASK 0x04000000 > > +#define CCB_SMB_SLVRXFIFOFULLSTS_SHIFT 26 > > + > > +#define CCB_SMB_SLVRXFIFOTHRHITSTS_MASK 0x02000000 > > +#define CCB_SMB_SLVRXFIFOTHRHITSTS_SHIFT 25 > > + > > +#define CCB_SMB_SLVRXEVTSTS_MASK 0x01000000 > > +#define CCB_SMB_SLVRXEVTSTS_SHIFT 24 > > + > > +#define CCB_SMB_SLVSTARTBUSYSTS_MASK 0x00800000 > > +#define CCB_SMB_SLVSTARTBUSYSTS_SHIFT 23 > > + > > +#define CCB_SMB_SLVTXUNDSTS_MASK 0x00400000 > > +#define CCB_SMB_SLVTXUNDSTS_SHIFT 22 > > + > > +#define CCB_SMB_SLVRDEVTSTS_MASK 0x00200000 > > +#define CCB_SMB_SLVRDEVTSTS_SHIFT 21 > > + > > +#define CCB_SMB_MSTRDATAWR_REG 0x40 > > + > > +#define CCB_SMB_MSTRWRSTS_MASK 0x80000000 > > +#define CCB_SMB_MSTRWRSTS_SHIFT 31 > > + > > +#define CCB_SMB_MSTRWRDATA_MASK 0x000000FF > > +#define CCB_SMB_MSTRWRDATA_SHIFT 0 > > + > > +#define CCB_SMB_MSTRDATARD_REG 0x44 > > + > > +#define CCB_SMB_MSTRRDSTS_MASK 0xC0000000 > > +#define CCB_SMB_MSTRRDSTS_SHIFT 30 > > + > > +#define CCB_SMB_MSTRRDPECERR_MASK 0x20000000 > > +#define CCB_SMB_MSTRRDPECERR_SHIFT 29 > > + > > +#define CCB_SMB_MSTRRDDATA_MASK 0x000000FF > > +#define CCB_SMB_MSTRRDDATA_SHIFT 0 > > + > > +#define CCB_SMB_SLVDATAWR_REG 0x48 > > + > > +#define CCB_SMB_SLVWRSTS_MASK 0x80000000 > > +#define CCB_SMB_SLVWRSTS_SHIFT 31 > > + > > +#define CCB_SMB_SLVWRDATA_MASK 0x000000FF > > +#define CCB_SMB_SLVWRDATA_SHIFT 0 > > + > > +#define CCB_SMB_SLVDATARD_REG 0x4C > > + > > +#define CCB_SMB_SLVRDSTS_MASK 0xC0000000 > > +#define CCB_SMB_SLVRDSTS_SHIFT 30 > > + > > +#define CCB_SMB_SLVRDERRSTS_MASK 0x30000000 > > +#define CCB_SMB_SLVRDERRSTS_SHIFT 28 > > + > > +#define CCB_SMB_SLVRDDATA_MASK 0x000000FF > > +#define CCB_SMB_SLVRDDATA_SHIFT 0 > > + > > +/* --Registers-- */ > > + > > +/* Transaction error codes defined in Master command register (0x30) */ > > +#define MSTR_STS_XACT_SUCCESS 0 > > +#define MSTR_STS_LOST_ARB 1 > > +#define MSTR_STS_NACK_FIRST_BYTE 2 > > + > > +/* NACK on a byte other than > > + * the first byte > > + */ > > +#define MSTR_STS_NACK_NON_FIRST_BYTE 3 > > + > > +#define MSTR_STS_TTIMEOUT_EXCEEDED 4 > > +#define MSTR_STS_TX_TLOW_MEXT_EXCEEDED 5 > > +#define MSTR_STS_RX_TLOW_MEXT_EXCEEDED 6 > > + > > +/* SMBUS protocol values defined in register 0x30 */ > > +#define SMBUS_PROT_QUICK_CMD 0 > > +#define SMBUS_PROT_SEND_BYTE 1 > > +#define SMBUS_PROT_RECV_BYTE 2 > > +#define SMBUS_PROT_WR_BYTE 3 > > +#define SMBUS_PROT_RD_BYTE 4 > > +#define SMBUS_PROT_WR_WORD 5 > > +#define SMBUS_PROT_RD_WORD 6 > > +#define SMBUS_PROT_BLK_WR 7 > > +#define SMBUS_PROT_BLK_RD 8 > > +#define SMBUS_PROT_PROC_CALL 9 > > +#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10 > > + > > +/* SMBUS Block speed mode */ > > +#define SMBUS_BLOCK_MODE_100 0 > > +#define SMBUS_BLOCK_MODE_400 1 > > + > > +#define BUS_BUSY_COUNT 100000 /* Number can be changed later */ > > +#define IPROC_I2C_INVALID_ADDR 0xFF > > +#define IPROC_SMB_MAX_RETRIES 35 > > +#define I2C_SMBUS_BLOCK_MAX 32 > > +#define GETREGFLDVAL(regval, mask, startbit) \ > > + (((regval) & (mask)) >> (startbit)) > > +#define SETREGFLDVAL(regval, fldval, mask, startbit) (regval) = \ > > + ((regval) & ~(mask)) | \ > > + ((fldval) << (startbit)) > > checkpatch complains with a warning: > > CHECK: Macro argument reuse 'regval' - possible side-effects? > #1981: FILE: drivers/i2c/iproc_i2c.h:306: > +#define SETREGFLDVAL(regval, fldval, mask, startbit) (regval) = \ > > + ((regval) & ~(mask)) | \ > > + ((fldval) << (startbit)) > > > > > > + > > +/* Enum to specify clock speed. The user will provide it during > > initialization > > + * If needed, it can be changed dynamically > > + */ > > +enum iproc_smb_clk_freq { > > + I2C_SPEED_100KHZ = 100000, > > + I2C_SPEED_400KHZ = 400000, > > + I2C_SPEED_INVALID = 255 > > +}; > > + > > +/* This enum will be used to notify the user of status of a data transfer > > + * request > > + */ > > +enum iproc_smb_error_code { > > + I2C_NO_ERR = 0, > > + I2C_TIMEOUT_ERR = 1, > > + > > + /* Invalid parameter(s) passed to the driver */ > > + I2C_INVALID_PARAM_ERR = 2, > > + > > + /* The driver API was called before the present > > + * transfer was completed > > + */ > > + I2C_OPER_IN_PROGRESS = 3, > > + > > + /* Transfer aborted unexpectedly, for example a NACK > > + * received, before last byte was read/written > > + */ > > + I2C_OPER_ABORT_ERR = 4, > > + > > + /* Feature or function not supported > > + * (e.g., 10-bit addresses, or clock speeds > > + * other than 100KHz, 400KHz) > > + */ > > + I2C_FUNC_NOT_SUPPORTED = 5, > > +}; > > + > > +/* Structure used to pass information to read/write functions. */ > > +struct iproc_xact_info { > > + unsigned char command; > > + unsigned char *data; > > + unsigned int size; > > + unsigned short flags; /* used for specifying PEC, 10-bit addresses */ > > + unsigned char smb_proto; /* SMBus protocol */ > > + unsigned int cmd_valid; /* true if command is valid else false */ > > +}; > > + > > +#endif /* __IPROC_I2C_H__ */ > >
Hi Heiko, Thank you for detailed review. I will work on all your review points and send v2. > > -- > DENX Software Engineering GmbH, Managing Director: Wolfgang Denk > HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany > Phone: +49-8142-66989-52 Fax: +49-8142-66989-80 Email: h...@denx.de