]> Git Repo - linux.git/commitdiff
Merge tag 'i2c-for-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <[email protected]>
Wed, 5 Oct 2022 01:54:33 +0000 (18:54 -0700)
committerLinus Torvalds <[email protected]>
Wed, 5 Oct 2022 01:54:33 +0000 (18:54 -0700)
Pull i2c updates from Wolfram Sang:

 - 'remove' callback converted to return void. Big change with trivial
   fixes all over the tree. Other subsystems depending on this change
   have been asked to pull an immutable topic branch for this.

 - new driver for Microchip PCI1xxxx switch

 - heavy refactoring of the Mellanox BlueField driver

 - we prefer async probe in the i801 driver now

 - the rest is usual driver updates (support for more SoCs, some
   refactoring, some feature additions)

* tag 'i2c-for-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (37 commits)
  i2c: pci1xxxx: prevent signed integer overflow
  i2c: acpi: Replace zero-length array with DECLARE_FLEX_ARRAY() helper
  i2c: i801: Prefer async probe
  i2c: designware-pci: Use standard pattern for memory allocation
  i2c: designware-pci: Group AMD NAVI quirk parts together
  i2c: microchip: pci1xxxx: Add driver for I2C host controller in multifunction endpoint of pci1xxxx switch
  docs: i2c: slave-interface: return errno when handle I2C_SLAVE_WRITE_REQUESTED
  i2c: mlxbf: remove device tree support
  i2c: mlxbf: support BlueField-3 SoC
  i2c: cadence: Add standard bus recovery support
  i2c: mlxbf: add multi slave functionality
  i2c: mlxbf: support lock mechanism
  macintosh/ams: Adapt declaration of ams_i2c_remove() to earlier change
  i2c: riic: Use devm_platform_ioremap_resource()
  i2c: mlxbf: remove IRQF_ONESHOT
  dt-bindings: i2c: rockchip: add rockchip,rk3128-i2c
  dt-bindings: i2c: renesas,rcar-i2c: Add r8a779g0 support
  i2c: tegra: Add GPCDMA support
  i2c: scmi: Convert to be a platform driver
  i2c: rk3x: Add rv1126 support
  ...

1  2 
MAINTAINERS
drivers/gpu/drm/bridge/lontium-lt8912b.c
drivers/i2c/busses/i2c-mlxbf.c
drivers/net/dsa/lan9303_i2c.c
drivers/net/dsa/microchip/ksz9477_i2c.c
drivers/net/dsa/xrs700x/xrs700x_i2c.c
drivers/net/ethernet/mellanox/mlxsw/i2c.c
drivers/platform/x86/intel/int3472/tps68470.c

diff --combined MAINTAINERS
index 9ca84cb5ab4a95496065e55abfa8b9bc08c27144,d71adf29f8bb78f08805f00b5aae19d5b228614e..a8e68844b34b4fc9b44a7ac91d4b183acf384e88
@@@ -348,6 -348,7 +348,6 @@@ M: "Rafael J. Wysocki" <[email protected]
  R:    Len Brown <[email protected]>
  L:    [email protected]
  S:    Supported
 -W:    https://01.org/linux-acpi
  Q:    https://patchwork.kernel.org/project/linux-acpi/list/
  B:    https://bugzilla.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
@@@ -426,6 -427,7 +426,6 @@@ M: Rafael J. Wysocki <[email protected]
  R:    Zhang Rui <[email protected]>
  L:    [email protected]
  S:    Supported
 -W:    https://01.org/linux-acpi
  B:    https://bugzilla.kernel.org
  F:    drivers/acpi/*thermal*
  
@@@ -877,13 -879,6 +877,13 @@@ L:       [email protected]
  S:    Maintained
  F:    drivers/net/ethernet/altera/
  
 +ALTERA TSE PCS
 +M:    Maxime Chevallier <[email protected]>
 +L:    [email protected]
 +S:    Supported
 +F:    drivers/net/pcs/pcs-altera-tse.c
 +F:    include/linux/pcs-altera-tse.h
 +
  ALTERA UART/JTAG UART SERIAL DRIVERS
  M:    Tobias Klauser <[email protected]>
  L:    [email protected]
@@@ -2399,7 -2394,6 +2399,7 @@@ N:      atme
  ARM/Microchip Sparx5 SoC support
  M:    Lars Povlsen <[email protected]>
  M:    Steen Hegelund <[email protected]>
 +M:    Daniel Machon <[email protected]>
  M:    [email protected]
  L:    [email protected] (moderated for non-subscribers)
  S:    Supported
@@@ -2585,7 -2579,7 +2585,7 @@@ W:      http://www.armlinux.org.uk
  
  ARM/QUALCOMM SUPPORT
  M:    Andy Gross <[email protected]>
 -M:    Bjorn Andersson <bjorn.andersson@linaro.org>
 +M:    Bjorn Andersson <andersson@kernel.org>
  R:    Konrad Dybcio <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -2676,6 -2670,7 +2676,6 @@@ M:      Russell King <[email protected]
  L:    [email protected] (moderated for non-subscribers)
  S:    Maintained
  W:    http://www.armlinux.org.uk/
 -F:    arch/arm/include/asm/hardware/entry-macro-iomd.S
  F:    arch/arm/include/asm/hardware/ioc.h
  F:    arch/arm/include/asm/hardware/iomd.h
  F:    arch/arm/include/asm/hardware/memc.h
@@@ -3830,7 -3825,6 +3830,7 @@@ F:      kernel/bpf/dispatcher.
  F:    kernel/bpf/trampoline.c
  F:    include/linux/bpf*
  F:    include/linux/filter.h
 +F:    include/linux/tnum.h
  
  BPF [BTF]
  M:    Martin KaFai Lau <[email protected]>
@@@ -5729,6 -5723,13 +5729,6 @@@ F:     include/linux/tfrc.
  F:    include/uapi/linux/dccp.h
  F:    net/dccp/
  
 -DECnet NETWORK LAYER
 -L:    [email protected]
 -S:    Orphan
 -W:    http://linux-decnet.sourceforge.net
 -F:    Documentation/networking/decnet.rst
 -F:    net/decnet/
 -
  DECSTATION PLATFORM SUPPORT
  M:    "Maciej W. Rozycki" <[email protected]>
  L:    [email protected]
@@@ -7687,6 -7688,7 +7687,6 @@@ R:      Kees Cook <[email protected]
  L:    [email protected]
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/execve
 -F:    arch/alpha/kernel/binfmt_loader.c
  F:    fs/*binfmt_*.c
  F:    fs/exec.c
  F:    include/linux/binfmts.h
@@@ -8003,7 -8005,6 +8003,7 @@@ L:      [email protected]
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
  F:    include/linux/fortify-string.h
 +F:    lib/fortify_kunit.c
  F:    lib/test_fortify/*
  F:    scripts/test_fortify.sh
  K:    \b__NO_FORTIFY\b
@@@ -8943,7 -8944,7 +8943,7 @@@ F:      include/linux/hw_random.
  
  HARDWARE SPINLOCK CORE
  M:    Ohad Ben-Cohen <[email protected]>
 -M:    Bjorn Andersson <bjorn.andersson@linaro.org>
 +M:    Bjorn Andersson <andersson@kernel.org>
  R:    Baolin Wang <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -10378,6 -10379,7 +10378,6 @@@ INTEL MENLOW THERMAL DRIVE
  M:    Sujith Thomas <[email protected]>
  L:    [email protected]
  S:    Supported
 -W:    https://01.org/linux-acpi
  F:    drivers/thermal/intel/intel_menlow.c
  
  INTEL P-Unit IPC DRIVER
@@@ -12982,9 -12984,9 +12982,9 @@@ F:   drivers/input/touchscreen/melfas_mip
  
  MELLANOX BLUEFIELD I2C DRIVER
  M:    Khalil Blaiech <[email protected]>
+ M:    Asmaa Mnebhi <[email protected]>
  L:    [email protected]
  S:    Supported
- F:    Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml
  F:    drivers/i2c/busses/i2c-mlxbf.c
  
  MELLANOX ETHERNET DRIVER (mlx4_en)
@@@ -13433,6 -13435,14 +13433,14 @@@ F: Documentation/devicetree/bindings/nv
  F:    drivers/nvmem/microchip-otpc.c
  F:    include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
  
+ MICROCHIP PCI1XXXX I2C DRIVER
+ M:    Tharun Kumar P <[email protected]>
+ M:    Kumaravel Thiagarajan <[email protected]>
+ M:    Microchip Linux Driver Support <[email protected]>
+ L:    [email protected]
+ S:    Maintained
+ F:    drivers/i2c/busses/i2c-mchp-pci1xxxx.c
  MICROCHIP PWM DRIVER
  M:    Claudiu Beznea <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
@@@ -14448,7 -14458,6 +14456,7 @@@ M:   Willy Tarreau <[email protected]
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git
  F:    tools/include/nolibc/
 +F:    tools/testing/selftests/nolibc/
  
  NSDEPS
  M:    Matthias Maennich <[email protected]>
@@@ -14746,13 -14755,6 +14754,13 @@@ F: net/dsa/tag_ocelot.
  F:    net/dsa/tag_ocelot_8021q.c
  F:    tools/testing/selftests/drivers/net/ocelot/*
  
 +OCELOT EXTERNAL SWITCH CONTROL
 +M:    Colin Foster <[email protected]>
 +S:    Supported
 +F:    Documentation/devicetree/bindings/mfd/mscc,ocelot.yaml
 +F:    drivers/mfd/ocelot*
 +F:    include/linux/mfd/ocelot.h
 +
  OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
  M:    Frederic Barrat <[email protected]>
  M:    Andrew Donnellan <[email protected]>
@@@ -16132,7 -16134,7 +16140,7 @@@ F:   drivers/gpio/gpio-sama5d2-piobu.
  F:    drivers/pinctrl/pinctrl-at91*
  
  PIN CONTROLLER - QUALCOMM
 -M:    Bjorn Andersson <bjorn.andersson@linaro.org>
 +M:    Bjorn Andersson <andersson@kernel.org>
  L:    [email protected]
  S:    Maintained
  F:    Documentation/devicetree/bindings/pinctrl/qcom,*.txt
@@@ -16825,7 -16827,7 +16833,7 @@@ F:   Documentation/devicetree/bindings/me
  F:    drivers/media/platform/qcom/camss/
  
  QUALCOMM CLOCK DRIVERS
 -M:    Bjorn Andersson <bjorn.andersson@linaro.org>
 +M:    Bjorn Andersson <andersson@kernel.org>
  L:    [email protected]
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
@@@ -17315,7 -17317,7 +17323,7 @@@ S:   Supporte
  F:    fs/reiserfs/
  
  REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
 -M:    Bjorn Andersson <bjorn.andersson@linaro.org>
 +M:    Bjorn Andersson <andersson@kernel.org>
  M:    Mathieu Poirier <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -17328,7 -17330,7 +17336,7 @@@ F:   include/linux/remoteproc.
  F:    include/linux/remoteproc/
  
  REMOTE PROCESSOR MESSAGING (RPMSG) SUBSYSTEM
 -M:    Bjorn Andersson <bjorn.andersson@linaro.org>
 +M:    Bjorn Andersson <andersson@kernel.org>
  M:    Mathieu Poirier <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -17764,24 -17766,6 +17772,24 @@@ F: include/rv
  F:    kernel/trace/rv/
  F:    tools/verification/
  
 +RUST
 +M:    Miguel Ojeda <[email protected]>
 +M:    Alex Gaynor <[email protected]>
 +M:    Wedson Almeida Filho <[email protected]>
 +R:    Boqun Feng <[email protected]>
 +R:    Gary Guo <[email protected]>
 +R:    Björn Roy Baron <[email protected]>
 +L:    [email protected]
 +S:    Supported
 +W:    https://github.com/Rust-for-Linux/linux
 +B:    https://github.com/Rust-for-Linux/linux/issues
 +T:    git https://github.com/Rust-for-Linux/linux.git rust-next
 +F:    Documentation/rust/
 +F:    rust/
 +F:    samples/rust/
 +F:    scripts/*rust*
 +K:    \b(?i:rust)\b
 +
  RXRPC SOCKETS (AF_RXRPC)
  M:    David Howells <[email protected]>
  M:    Marc Dionne <[email protected]>
  S:    Maintained
  F:    drivers/net/ethernet/dlink/sundance.c
  
 +SUN HAPPY MEAL ETHERNET DRIVER
 +M:    Sean Anderson <[email protected]>
 +S:    Maintained
 +F:    drivers/net/ethernet/sun/sunhme.*
 +
  SUNPLUS ETHERNET DRIVER
  M:    Wells Lu <[email protected]>
  L:    [email protected]
@@@ -19990,7 -19969,7 +19998,7 @@@ S:   Supporte
  F:    drivers/net/team/
  F:    include/linux/if_team.h
  F:    include/uapi/linux/if_team.h
 -F:    tools/testing/selftests/net/team/
 +F:    tools/testing/selftests/drivers/net/team/
  
  TECHNOLOGIC SYSTEMS TS-5500 PLATFORM SUPPORT
  M:    "Savoir-faire Linux Inc." <[email protected]>
@@@ -21903,11 -21882,9 +21911,11 @@@ F: drivers/input/tablet/wacom_serial4.
  
  WANGXUN ETHERNET DRIVER
  M:    Jiawen Wu <[email protected]>
 +M:    Mengyuan Lou <[email protected]>
 +W:    https://www.net-swift.com
  L:    [email protected]
  S:    Maintained
 -F:    Documentation/networking/device_drivers/ethernet/wangxun/txgbe.rst
 +F:    Documentation/networking/device_drivers/ethernet/wangxun/*
  F:    drivers/net/ethernet/wangxun/
  
  WATCHDOG DEVICE DRIVERS
index 5968f4af190bae69cc99550c4aa6c492dd3ffd7b,374db575f97cf841e3e936f6b3d35f45d1ae4801..be533d2945e747ef5657c590e9b825be956918a8
@@@ -188,7 -188,7 +188,7 @@@ static int lt8912_write_lvds_config(str
                {0x03, 0xff},
        };
  
 -      return regmap_multi_reg_write(lt->regmap[I2C_CEC_DSI], seq, ARRAY_SIZE(seq));
 +      return regmap_multi_reg_write(lt->regmap[I2C_MAIN], seq, ARRAY_SIZE(seq));
  };
  
  static inline struct lt8912 *bridge_to_lt8912(struct drm_bridge *b)
@@@ -268,7 -268,7 +268,7 @@@ static int lt8912_video_setup(struct lt
        u32 hactive, h_total, hpw, hfp, hbp;
        u32 vactive, v_total, vpw, vfp, vbp;
        u8 settle = 0x08;
 -      int ret;
 +      int ret, hsync_activehigh, vsync_activehigh;
  
        if (!lt)
                return -EINVAL;
        hpw = lt->mode.hsync_len;
        hbp = lt->mode.hback_porch;
        h_total = hactive + hfp + hpw + hbp;
 +      hsync_activehigh = lt->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH;
  
        vactive = lt->mode.vactive;
        vfp = lt->mode.vfront_porch;
        vpw = lt->mode.vsync_len;
        vbp = lt->mode.vback_porch;
        v_total = vactive + vfp + vpw + vbp;
 +      vsync_activehigh = lt->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH;
  
        if (vactive <= 600)
                settle = 0x04;
        ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3e, hfp & 0xff);
        ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3f, hfp >> 8);
  
 +      ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(0),
 +                                vsync_activehigh ? BIT(0) : 0);
 +      ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(1),
 +                                hsync_activehigh ? BIT(1) : 0);
 +      ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xb2, BIT(0),
 +                                lt->connector.display_info.is_hdmi ? BIT(0) : 0);
 +
        return ret;
  }
  
@@@ -723,7 -714,7 +723,7 @@@ err_dt_parse
        return ret;
  }
  
- static int lt8912_remove(struct i2c_client *client)
+ static void lt8912_remove(struct i2c_client *client)
  {
        struct lt8912 *lt = i2c_get_clientdata(client);
  
        drm_bridge_remove(&lt->bridge);
        lt8912_free_i2c(lt);
        lt8912_put_dt(lt);
-       return 0;
  }
  
  static const struct of_device_id lt8912_dt_match[] = {
index 60908c5737f1b57ec305a77cf94ea9601203465c,cb91a38cfebfd1ec73ebb14f349af33fa5a51a72..e68e775f187e68662722fb007c7e608c230aa7ef
@@@ -32,8 -32,6 +32,6 @@@
        (MLXBF_I2C_FUNC_SMBUS_DEFAULT | MLXBF_I2C_FUNC_SMBUS_BLOCK | \
         I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SLAVE)
  
- #define MLXBF_I2C_SMBUS_MAX        3
  /* Shared resources info in BlueField platforms. */
  
  #define MLXBF_I2C_COALESCE_TYU_ADDR    0x02801300
@@@ -48,6 -46,9 +46,9 @@@
  #define MLXBF_I2C_COREPLL_YU_ADDR      0x02800c30
  #define MLXBF_I2C_COREPLL_YU_SIZE      0x00c
  
+ #define MLXBF_I2C_COREPLL_RSH_YU_ADDR  0x13409824
+ #define MLXBF_I2C_COREPLL_RSH_YU_SIZE  0x00c
  #define MLXBF_I2C_SHARED_RES_MAX       3
  
  /*
  /* Slave busy bit reset. */
  #define MLXBF_I2C_CAUSE_S_GW_BUSY_FALL        BIT(18)
  
- #define MLXBF_I2C_CAUSE_SLAVE_ARBITER_BITS_MASK     GENMASK(20, 0)
  /* Cause coalesce registers. */
  #define MLXBF_I2C_CAUSE_COALESCE_0        0x00
- #define MLXBF_I2C_CAUSE_COALESCE_1        0x04
- #define MLXBF_I2C_CAUSE_COALESCE_2        0x08
  
- #define MLXBF_I2C_CAUSE_TYU_SLAVE_BIT   MLXBF_I2C_SMBUS_MAX
+ #define MLXBF_I2C_CAUSE_TYU_SLAVE_BIT   3
  #define MLXBF_I2C_CAUSE_YU_SLAVE_BIT    1
  
  /* Functional enable register. */
  #define MLXBF_I2C_GPIO_SMBUS_GW_ASSERT_PINS(num, val) \
        ((val) | (0x3 << MLXBF_I2C_GPIO_SMBUS_GW_PINS(num)))
  
- /* SMBus timing parameters. */
- #define MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH    0x00
- #define MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE     0x04
- #define MLXBF_I2C_SMBUS_TIMER_THOLD               0x08
- #define MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP   0x0c
- #define MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA         0x10
- #define MLXBF_I2C_SMBUS_THIGH_MAX_TBUF            0x14
- #define MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT           0x18
  /*
   * Defines SMBus operating frequency and core clock frequency.
   * According to ADB files, default values are compliant to 100KHz SMBus
  #define MLXBF_I2C_COREPLL_CORE_OD_YU_MASK   GENMASK(3, 0)
  #define MLXBF_I2C_COREPLL_CORE_R_YU_MASK    GENMASK(31, 26)
  
+ /* SMBus timing parameters. */
+ #define MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH    0x00
+ #define MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE     0x04
+ #define MLXBF_I2C_SMBUS_TIMER_THOLD               0x08
+ #define MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP   0x0c
+ #define MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA         0x10
+ #define MLXBF_I2C_SMBUS_THIGH_MAX_TBUF            0x14
+ #define MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT           0x18
  
- /* Core PLL frequency. */
- static u64 mlxbf_i2c_corepll_frequency;
+ #define MLXBF_I2C_SHIFT_0   0
+ #define MLXBF_I2C_SHIFT_8   8
+ #define MLXBF_I2C_SHIFT_16  16
+ #define MLXBF_I2C_SHIFT_24  24
+ #define MLXBF_I2C_MASK_8    GENMASK(7, 0)
+ #define MLXBF_I2C_MASK_16   GENMASK(15, 0)
+ #define MLXBF_I2C_MST_ADDR_OFFSET         0x200
  
  /* SMBus Master GW. */
- #define MLXBF_I2C_SMBUS_MASTER_GW     0x200
+ #define MLXBF_I2C_SMBUS_MASTER_GW         0x0
  /* Number of bytes received and sent. */
- #define MLXBF_I2C_SMBUS_RS_BYTES      0x300
+ #define MLXBF_I2C_YU_SMBUS_RS_BYTES       0x100
+ #define MLXBF_I2C_RSH_YU_SMBUS_RS_BYTES   0x10c
  /* Packet error check (PEC) value. */
- #define MLXBF_I2C_SMBUS_MASTER_PEC    0x304
+ #define MLXBF_I2C_SMBUS_MASTER_PEC        0x104
  /* Status bits (ACK/NACK/FW Timeout). */
- #define MLXBF_I2C_SMBUS_MASTER_STATUS 0x308
+ #define MLXBF_I2C_SMBUS_MASTER_STATUS     0x108
  /* SMbus Master Finite State Machine. */
- #define MLXBF_I2C_SMBUS_MASTER_FSM    0x310
- /*
-  * When enabled, the master will issue a stop condition in case of
-  * timeout while waiting for FW response.
-  */
- #define MLXBF_I2C_SMBUS_EN_FW_TIMEOUT 0x31c
+ #define MLXBF_I2C_YU_SMBUS_MASTER_FSM     0x110
+ #define MLXBF_I2C_RSH_YU_SMBUS_MASTER_FSM 0x100
  
  /* SMBus master GW control bits offset in MLXBF_I2C_SMBUS_MASTER_GW[31:3]. */
  #define MLXBF_I2C_MASTER_LOCK_BIT         BIT(31) /* Lock bit. */
  #define MLXBF_I2C_MASTER_ENABLE_READ \
        (MLXBF_I2C_MASTER_ENABLE | MLXBF_I2C_MASTER_CTL_READ_BIT)
  
- #define MLXBF_I2C_MASTER_SLV_ADDR_SHIFT   12 /* Slave address shift. */
- #define MLXBF_I2C_MASTER_WRITE_SHIFT      21 /* Control write bytes shift. */
- #define MLXBF_I2C_MASTER_SEND_PEC_SHIFT   20 /* Send PEC byte shift. */
- #define MLXBF_I2C_MASTER_PARSE_EXP_SHIFT  11 /* Parse expected bytes shift. */
- #define MLXBF_I2C_MASTER_READ_SHIFT       4  /* Control read bytes shift. */
+ #define MLXBF_I2C_MASTER_WRITE_SHIFT      21 /* Control write bytes */
+ #define MLXBF_I2C_MASTER_SEND_PEC_SHIFT   20 /* Send PEC byte when set to 1 */
+ #define MLXBF_I2C_MASTER_PARSE_EXP_SHIFT  11 /* Control parse expected bytes */
+ #define MLXBF_I2C_MASTER_SLV_ADDR_SHIFT   12 /* Slave address */
+ #define MLXBF_I2C_MASTER_READ_SHIFT       4  /* Control read bytes */
  
  /* SMBus master GW Data descriptor. */
- #define MLXBF_I2C_MASTER_DATA_DESC_ADDR   0x280
+ #define MLXBF_I2C_MASTER_DATA_DESC_ADDR   0x80
  #define MLXBF_I2C_MASTER_DATA_DESC_SIZE   0x80 /* Size in bytes. */
  
  /* Maximum bytes to read/write per SMBus transaction. */
  #define MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK      BIT(31)
  #define MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK  BIT(15)
  
+ #define MLXBF_I2C_SLV_ADDR_OFFSET             0x400
  /* SMBus slave GW. */
- #define MLXBF_I2C_SMBUS_SLAVE_GW              0x400
+ #define MLXBF_I2C_SMBUS_SLAVE_GW              0x0
  /* Number of bytes received and sent from/to master. */
- #define MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES 0x500
+ #define MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES 0x100
  /* Packet error check (PEC) value. */
- #define MLXBF_I2C_SMBUS_SLAVE_PEC             0x504
+ #define MLXBF_I2C_SMBUS_SLAVE_PEC             0x104
  /* SMBus slave Finite State Machine (FSM). */
- #define MLXBF_I2C_SMBUS_SLAVE_FSM             0x510
+ #define MLXBF_I2C_SMBUS_SLAVE_FSM             0x110
  /*
   * Should be set when all raised causes handled, and cleared by HW on
   * every new cause.
   */
- #define MLXBF_I2C_SMBUS_SLAVE_READY           0x52c
+ #define MLXBF_I2C_SMBUS_SLAVE_READY           0x12c
  
  /* SMBus slave GW control bits offset in MLXBF_I2C_SMBUS_SLAVE_GW[31:19]. */
  #define MLXBF_I2C_SLAVE_BUSY_BIT         BIT(30) /* Busy bit. */
  #define MLXBF_I2C_SLAVE_SEND_PEC_SHIFT    21 /* Send PEC byte shift. */
  
  /* SMBus slave GW Data descriptor. */
- #define MLXBF_I2C_SLAVE_DATA_DESC_ADDR   0x480
+ #define MLXBF_I2C_SLAVE_DATA_DESC_ADDR   0x80
  #define MLXBF_I2C_SLAVE_DATA_DESC_SIZE   0x80 /* Size in bytes. */
  
  /* SMbus slave configuration registers. */
- #define MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG        0x514
+ #define MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG        0x114
  #define MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT        16
- #define MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT     7
+ #define MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT     BIT(7)
  #define MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK       GENMASK(6, 0)
  
- #define MLXBF_I2C_SLAVE_ADDR_ENABLED(addr) \
-       ((addr) & (1 << MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT))
  /*
   * Timeout is given in microsends. Note also that timeout handling is not
   * exact.
   */
  #define MLXBF_I2C_SMBUS_TIMEOUT   (300 * 1000) /* 300ms */
+ #define MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT (300 * 1000) /* 300ms */
+ /* Polling frequency in microseconds. */
+ #define MLXBF_I2C_POLL_FREQ_IN_USEC        200
+ #define MLXBF_I2C_SMBUS_OP_CNT_1   1
+ #define MLXBF_I2C_SMBUS_OP_CNT_2   2
+ #define MLXBF_I2C_SMBUS_OP_CNT_3   3
+ #define MLXBF_I2C_SMBUS_MAX_OP_CNT MLXBF_I2C_SMBUS_OP_CNT_3
+ /* Helper macro to define an I2C resource parameters. */
+ #define MLXBF_I2C_RES_PARAMS(addr, size, str) \
+       { \
+               .start = (addr), \
+               .end = (addr) + (size) - 1, \
+               .name = (str) \
+       }
+ enum {
+       MLXBF_I2C_TIMING_100KHZ = 100000,
+       MLXBF_I2C_TIMING_400KHZ = 400000,
+       MLXBF_I2C_TIMING_1000KHZ = 1000000,
+ };
+ enum {
+       MLXBF_I2C_F_READ = BIT(0),
+       MLXBF_I2C_F_WRITE = BIT(1),
+       MLXBF_I2C_F_NORESTART = BIT(3),
+       MLXBF_I2C_F_SMBUS_OPERATION = BIT(4),
+       MLXBF_I2C_F_SMBUS_BLOCK = BIT(5),
+       MLXBF_I2C_F_SMBUS_PEC = BIT(6),
+       MLXBF_I2C_F_SMBUS_PROCESS_CALL = BIT(7),
+ };
+ /* Mellanox BlueField chip type. */
+ enum mlxbf_i2c_chip_type {
+       MLXBF_I2C_CHIP_TYPE_1, /* Mellanox BlueField-1 chip. */
+       MLXBF_I2C_CHIP_TYPE_2, /* Mellanox BlueField-2 chip. */
+       MLXBF_I2C_CHIP_TYPE_3 /* Mellanox BlueField-3 chip. */
+ };
+ /* List of chip resources that are being accessed by the driver. */
+ enum {
+       MLXBF_I2C_SMBUS_RES,
+       MLXBF_I2C_MST_CAUSE_RES,
+       MLXBF_I2C_SLV_CAUSE_RES,
+       MLXBF_I2C_COALESCE_RES,
+       MLXBF_I2C_SMBUS_TIMER_RES,
+       MLXBF_I2C_SMBUS_MST_RES,
+       MLXBF_I2C_SMBUS_SLV_RES,
+       MLXBF_I2C_COREPLL_RES,
+       MLXBF_I2C_GPIO_RES,
+       MLXBF_I2C_END_RES
+ };
  
  /* Encapsulates timing parameters. */
  struct mlxbf_i2c_timings {
        u32 timeout;            /* Detect clock low timeout. */
  };
  
- enum {
-       MLXBF_I2C_F_READ = BIT(0),
-       MLXBF_I2C_F_WRITE = BIT(1),
-       MLXBF_I2C_F_NORESTART = BIT(3),
-       MLXBF_I2C_F_SMBUS_OPERATION = BIT(4),
-       MLXBF_I2C_F_SMBUS_BLOCK = BIT(5),
-       MLXBF_I2C_F_SMBUS_PEC = BIT(6),
-       MLXBF_I2C_F_SMBUS_PROCESS_CALL = BIT(7),
- };
  struct mlxbf_i2c_smbus_operation {
        u32 flags;
        u32 length; /* Buffer length in bytes. */
        u8 *buffer;
  };
  
- #define MLXBF_I2C_SMBUS_OP_CNT_1      1
- #define MLXBF_I2C_SMBUS_OP_CNT_2      2
- #define MLXBF_I2C_SMBUS_OP_CNT_3      3
- #define MLXBF_I2C_SMBUS_MAX_OP_CNT    MLXBF_I2C_SMBUS_OP_CNT_3
  struct mlxbf_i2c_smbus_request {
        u8 slave;
        u8 operation_cnt;
@@@ -360,24 -397,38 +397,38 @@@ struct mlxbf_i2c_resource 
        u8 type;
  };
  
- /* List of chip resources that are being accessed by the driver. */
- enum {
-       MLXBF_I2C_SMBUS_RES,
-       MLXBF_I2C_MST_CAUSE_RES,
-       MLXBF_I2C_SLV_CAUSE_RES,
-       MLXBF_I2C_COALESCE_RES,
-       MLXBF_I2C_COREPLL_RES,
-       MLXBF_I2C_GPIO_RES,
-       MLXBF_I2C_END_RES,
+ struct mlxbf_i2c_chip_info {
+       enum mlxbf_i2c_chip_type type;
+       /* Chip shared resources that are being used by the I2C controller. */
+       struct mlxbf_i2c_resource *shared_res[MLXBF_I2C_SHARED_RES_MAX];
+       /* Callback to calculate the core PLL frequency. */
+       u64 (*calculate_freq)(struct mlxbf_i2c_resource *corepll_res);
+       /* Registers' address offset */
+       u32 smbus_master_rs_bytes_off;
+       u32 smbus_master_fsm_off;
  };
  
- /* Helper macro to define an I2C resource parameters. */
- #define MLXBF_I2C_RES_PARAMS(addr, size, str) \
-       { \
-               .start = (addr), \
-               .end = (addr) + (size) - 1, \
-               .name = (str) \
-       }
+ struct mlxbf_i2c_priv {
+       const struct mlxbf_i2c_chip_info *chip;
+       struct i2c_adapter adap;
+       struct mlxbf_i2c_resource *smbus;
+       struct mlxbf_i2c_resource *timer;
+       struct mlxbf_i2c_resource *mst;
+       struct mlxbf_i2c_resource *slv;
+       struct mlxbf_i2c_resource *mst_cause;
+       struct mlxbf_i2c_resource *slv_cause;
+       struct mlxbf_i2c_resource *coalesce;
+       u64 frequency; /* Core frequency in Hz. */
+       int bus; /* Physical bus identifier. */
+       int irq;
+       struct i2c_client *slave[MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT];
+       u32 resource_version;
+ };
+ /* Core PLL frequency. */
+ static u64 mlxbf_i2c_corepll_frequency;
  
  static struct resource mlxbf_i2c_coalesce_tyu_params =
                MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COALESCE_TYU_ADDR,
@@@ -391,6 -442,10 +442,10 @@@ static struct resource mlxbf_i2c_corepl
                MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COREPLL_YU_ADDR,
                                     MLXBF_I2C_COREPLL_YU_SIZE,
                                     "COREPLL_MEM");
+ static struct resource mlxbf_i2c_corepll_rsh_yu_params =
+               MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COREPLL_RSH_YU_ADDR,
+                                    MLXBF_I2C_COREPLL_RSH_YU_SIZE,
+                                    "COREPLL_MEM");
  static struct resource mlxbf_i2c_gpio_tyu_params =
                MLXBF_I2C_RES_PARAMS(MLXBF_I2C_GPIO_TYU_ADDR,
                                     MLXBF_I2C_GPIO_TYU_SIZE,
@@@ -400,34 -455,6 +455,6 @@@ static struct mutex mlxbf_i2c_coalesce_
  static struct mutex mlxbf_i2c_corepll_lock;
  static struct mutex mlxbf_i2c_gpio_lock;
  
- /* Mellanox BlueField chip type. */
- enum mlxbf_i2c_chip_type {
-       MLXBF_I2C_CHIP_TYPE_1, /* Mellanox BlueField-1 chip. */
-       MLXBF_I2C_CHIP_TYPE_2, /* Mallanox BlueField-2 chip. */
- };
- struct mlxbf_i2c_chip_info {
-       enum mlxbf_i2c_chip_type type;
-       /* Chip shared resources that are being used by the I2C controller. */
-       struct mlxbf_i2c_resource *shared_res[MLXBF_I2C_SHARED_RES_MAX];
-       /* Callback to calculate the core PLL frequency. */
-       u64 (*calculate_freq)(struct mlxbf_i2c_resource *corepll_res);
- };
- struct mlxbf_i2c_priv {
-       const struct mlxbf_i2c_chip_info *chip;
-       struct i2c_adapter adap;
-       struct mlxbf_i2c_resource *smbus;
-       struct mlxbf_i2c_resource *mst_cause;
-       struct mlxbf_i2c_resource *slv_cause;
-       struct mlxbf_i2c_resource *coalesce;
-       u64 frequency; /* Core frequency in Hz. */
-       int bus; /* Physical bus identifier. */
-       int irq;
-       struct i2c_client *slave;
- };
  static struct mlxbf_i2c_resource mlxbf_i2c_coalesce_res[] = {
        [MLXBF_I2C_CHIP_TYPE_1] = {
                .params = &mlxbf_i2c_coalesce_tyu_params,
@@@ -447,6 -474,11 +474,11 @@@ static struct mlxbf_i2c_resource mlxbf_
                .params = &mlxbf_i2c_corepll_yu_params,
                .lock = &mlxbf_i2c_corepll_lock,
                .type = MLXBF_I2C_COREPLL_RES,
+       },
+       [MLXBF_I2C_CHIP_TYPE_3] = {
+               .params = &mlxbf_i2c_corepll_rsh_yu_params,
+               .lock = &mlxbf_i2c_corepll_lock,
+               .type = MLXBF_I2C_COREPLL_RES,
        }
  };
  
@@@ -463,24 -495,13 +495,13 @@@ static u8 mlxbf_i2c_bus_count
  
  static struct mutex mlxbf_i2c_bus_lock;
  
- /* Polling frequency in microseconds. */
- #define MLXBF_I2C_POLL_FREQ_IN_USEC        200
- #define MLXBF_I2C_SHIFT_0   0
- #define MLXBF_I2C_SHIFT_8   8
- #define MLXBF_I2C_SHIFT_16  16
- #define MLXBF_I2C_SHIFT_24  24
- #define MLXBF_I2C_MASK_8    GENMASK(7, 0)
- #define MLXBF_I2C_MASK_16   GENMASK(15, 0)
  /*
   * Function to poll a set of bits at a specific address; it checks whether
   * the bits are equal to zero when eq_zero is set to 'true', and not equal
   * to zero when eq_zero is set to 'false'.
   * Note that the timeout is given in microseconds.
   */
- static u32 mlxbf_smbus_poll(void __iomem *io, u32 addr, u32 mask,
+ static u32 mlxbf_i2c_poll(void __iomem *io, u32 addr, u32 mask,
                            bool eq_zero, u32  timeout)
  {
        u32 bits;
   * a transaction. Accordingly, this function polls the Master FSM stop
   * bit; it returns false when the bit is asserted, true if not.
   */
- static bool mlxbf_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv)
+ static bool mlxbf_i2c_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv)
  {
        u32 mask = MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK;
-       u32 addr = MLXBF_I2C_SMBUS_MASTER_FSM;
+       u32 addr = priv->chip->smbus_master_fsm_off;
        u32 timeout = MLXBF_I2C_SMBUS_TIMEOUT;
  
-       if (mlxbf_smbus_poll(priv->smbus->io, addr, mask, true, timeout))
+       if (mlxbf_i2c_poll(priv->mst->io, addr, mask, true, timeout))
+               return true;
+       return false;
+ }
+ /*
+  * wait for the lock to be released before acquiring it.
+  */
+ static bool mlxbf_i2c_smbus_master_lock(struct mlxbf_i2c_priv *priv)
+ {
+       if (mlxbf_i2c_poll(priv->mst->io, MLXBF_I2C_SMBUS_MASTER_GW,
+                          MLXBF_I2C_MASTER_LOCK_BIT, true,
+                          MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT))
                return true;
  
        return false;
  }
  
+ static void mlxbf_i2c_smbus_master_unlock(struct mlxbf_i2c_priv *priv)
+ {
+       /* Clear the gw to clear the lock */
+       writel(0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW);
+ }
  static bool mlxbf_i2c_smbus_transaction_success(u32 master_status,
                                                u32 cause_status)
  {
@@@ -551,7 -591,7 +591,7 @@@ static int mlxbf_i2c_smbus_check_status
         * then read the cause and master status bits to determine if
         * errors occurred during the transaction.
         */
-       mlxbf_smbus_poll(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_GW,
+       mlxbf_i2c_poll(priv->mst->io, MLXBF_I2C_SMBUS_MASTER_GW,
                         MLXBF_I2C_MASTER_BUSY_BIT, true,
                         MLXBF_I2C_SMBUS_TIMEOUT);
  
         * Parse both Cause and Master GW bits, then return transaction status.
         */
  
-       master_status_bits = readl(priv->smbus->io +
+       master_status_bits = readl(priv->mst->io +
                                        MLXBF_I2C_SMBUS_MASTER_STATUS);
        master_status_bits &= MLXBF_I2C_SMBUS_MASTER_STATUS_MASK;
  
  }
  
  static void mlxbf_i2c_smbus_write_data(struct mlxbf_i2c_priv *priv,
-                                      const u8 *data, u8 length, u32 addr)
+                                      const u8 *data, u8 length, u32 addr,
+                                      bool is_master)
  {
        u8 offset, aligned_length;
        u32 data32;
         */
        for (offset = 0; offset < aligned_length; offset += sizeof(u32)) {
                data32 = *((u32 *)(data + offset));
-               iowrite32be(data32, priv->smbus->io + addr + offset);
+               if (is_master)
+                       iowrite32be(data32, priv->mst->io + addr + offset);
+               else
+                       iowrite32be(data32, priv->slv->io + addr + offset);
        }
  }
  
  static void mlxbf_i2c_smbus_read_data(struct mlxbf_i2c_priv *priv,
-                                     u8 *data, u8 length, u32 addr)
+                                     u8 *data, u8 length, u32 addr,
+                                     bool is_master)
  {
        u32 data32, mask;
        u8 byte, offset;
         */
  
        for (offset = 0; offset < (length & ~mask); offset += sizeof(u32)) {
-               data32 = ioread32be(priv->smbus->io + addr + offset);
+               if (is_master)
+                       data32 = ioread32be(priv->mst->io + addr + offset);
+               else
+                       data32 = ioread32be(priv->slv->io + addr + offset);
                *((u32 *)(data + offset)) = data32;
        }
  
        if (!(length & mask))
                return;
  
-       data32 = ioread32be(priv->smbus->io + addr + offset);
+       if (is_master)
+               data32 = ioread32be(priv->mst->io + addr + offset);
+       else
+               data32 = ioread32be(priv->slv->io + addr + offset);
  
        for (byte = 0; byte < (length & mask); byte++) {
                data[offset + byte] = data32 & GENMASK(7, 0);
@@@ -660,16 -711,16 +711,16 @@@ static int mlxbf_i2c_smbus_enable(struc
        command |= rol32(pec_en, MLXBF_I2C_MASTER_SEND_PEC_SHIFT);
  
        /* Clear status bits. */
-       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_STATUS);
+       writel(0x0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_STATUS);
        /* Set the cause data. */
        writel(~0x0, priv->mst_cause->io + MLXBF_I2C_CAUSE_OR_CLEAR);
        /* Zero PEC byte. */
-       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_PEC);
+       writel(0x0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_PEC);
        /* Zero byte count. */
-       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_RS_BYTES);
+       writel(0x0, priv->mst->io + priv->chip->smbus_master_rs_bytes_off);
  
        /* GW activation. */
-       writel(command, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_GW);
+       writel(command, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW);
  
        /*
         * Poll master status and check status bits. An ACK is sent when
@@@ -705,10 -756,19 +756,19 @@@ mlxbf_i2c_smbus_start_transaction(struc
        slave = request->slave & GENMASK(6, 0);
        addr = slave << 1;
  
-       /* First of all, check whether the HW is idle. */
-       if (WARN_ON(!mlxbf_smbus_master_wait_for_idle(priv)))
+       /*
+        * Try to acquire the smbus gw lock before any reads of the GW register since
+        * a read sets the lock.
+        */
+       if (WARN_ON(!mlxbf_i2c_smbus_master_lock(priv)))
                return -EBUSY;
  
+       /* Check whether the HW is idle */
+       if (WARN_ON(!mlxbf_i2c_smbus_master_wait_for_idle(priv))) {
+               ret = -EBUSY;
+               goto out_unlock;
+       }
        /* Set first byte. */
        data_desc[data_idx++] = addr;
  
                        write_en = 1;
                        write_len += operation->length;
                        if (data_idx + operation->length >
-                                       MLXBF_I2C_MASTER_DATA_DESC_SIZE)
-                               return -ENOBUFS;
+                                       MLXBF_I2C_MASTER_DATA_DESC_SIZE) {
+                               ret = -ENOBUFS;
+                               goto out_unlock;
+                       }
                        memcpy(data_desc + data_idx,
                               operation->buffer, operation->length);
                        data_idx += operation->length;
         * must be written to the data registers.
         */
        mlxbf_i2c_smbus_write_data(priv, (const u8 *)data_desc, data_len,
-                                  MLXBF_I2C_MASTER_DATA_DESC_ADDR);
+                                  MLXBF_I2C_MASTER_DATA_DESC_ADDR, true);
  
        if (write_en) {
                ret = mlxbf_i2c_smbus_enable(priv, slave, write_len, block_en,
                                         pec_en, 0);
                if (ret)
-                       return ret;
+                       goto out_unlock;
        }
  
        if (read_en) {
                /* Write slave address to Master GW data descriptor. */
                mlxbf_i2c_smbus_write_data(priv, (const u8 *)&addr, 1,
-                                          MLXBF_I2C_MASTER_DATA_DESC_ADDR);
+                                          MLXBF_I2C_MASTER_DATA_DESC_ADDR, true);
                ret = mlxbf_i2c_smbus_enable(priv, slave, read_len, block_en,
                                         pec_en, 1);
                if (!ret) {
                        /* Get Master GW data descriptor. */
                        mlxbf_i2c_smbus_read_data(priv, data_desc, read_len + 1,
-                                            MLXBF_I2C_MASTER_DATA_DESC_ADDR);
+                                            MLXBF_I2C_MASTER_DATA_DESC_ADDR, true);
  
                        /* Get data from Master GW data descriptor. */
                        memcpy(read_buf, data_desc, read_len + 1);
                 * next tag integration.
                 */
                writel(MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK,
-                       priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_FSM);
+                       priv->mst->io + priv->chip->smbus_master_fsm_off);
        }
  
+ out_unlock:
+       mlxbf_i2c_smbus_master_unlock(priv);
        return ret;
  }
  
@@@ -1078,7 -1143,7 +1143,7 @@@ static void mlxbf_i2c_set_timings(struc
        timer |= mlxbf_i2c_set_timer(priv, timings->scl_low,
                                     false, MLXBF_I2C_MASK_16,
                                     MLXBF_I2C_SHIFT_16);
-       writel(timer, priv->smbus->io +
+       writel(timer, priv->timer->io +
                MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH);
  
        timer = mlxbf_i2c_set_timer(priv, timings->sda_rise, false,
                                     MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_16);
        timer |= mlxbf_i2c_set_timer(priv, timings->scl_fall, false,
                                     MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_24);
-       writel(timer, priv->smbus->io +
+       writel(timer, priv->timer->io +
                MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE);
  
        timer = mlxbf_i2c_set_timer(priv, timings->hold_start, true,
                                    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
        timer |= mlxbf_i2c_set_timer(priv, timings->hold_data, true,
                                     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
-       writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_TIMER_THOLD);
+       writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_TIMER_THOLD);
  
        timer = mlxbf_i2c_set_timer(priv, timings->setup_start, true,
                                    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
        timer |= mlxbf_i2c_set_timer(priv, timings->setup_stop, true,
                                     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
-       writel(timer, priv->smbus->io +
+       writel(timer, priv->timer->io +
                MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP);
  
        timer = mlxbf_i2c_set_timer(priv, timings->setup_data, true,
                                    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
-       writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA);
+       writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA);
  
        timer = mlxbf_i2c_set_timer(priv, timings->buf, false,
                                    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
        timer |= mlxbf_i2c_set_timer(priv, timings->thigh_max, false,
                                     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
-       writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_THIGH_MAX_TBUF);
+       writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_THIGH_MAX_TBUF);
  
        timer = timings->timeout;
-       writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT);
+       writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT);
  }
  
  enum mlxbf_i2c_timings_config {
@@@ -1509,28 -1574,26 +1574,26 @@@ static int mlxbf_i2c_calculate_corepll_
        return 0;
  }
  
- static int mlxbf_slave_enable(struct mlxbf_i2c_priv *priv, u8 addr)
+ static int mlxbf_i2c_slave_enable(struct mlxbf_i2c_priv *priv,
+                             struct i2c_client *slave)
  {
-       u32 slave_reg, slave_reg_tmp, slave_reg_avail, slave_addr_mask;
-       u8 reg, reg_cnt, byte, addr_tmp, reg_avail, byte_avail;
-       bool avail, disabled;
-       disabled = false;
-       avail = false;
+       u8 reg, reg_cnt, byte, addr_tmp;
+       u32 slave_reg, slave_reg_tmp;
  
        if (!priv)
                return -EPERM;
  
        reg_cnt = MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT >> 2;
-       slave_addr_mask = MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK;
  
        /*
         * Read the slave registers. There are 4 * 32-bit slave registers.
-        * Each slave register can hold up to 4 * 8-bit slave configuration
-        * (7-bit address, 1 status bit (1 if enabled, 0 if not)).
+        * Each slave register can hold up to 4 * 8-bit slave configuration:
+        * 1) A 7-bit address
+        * 2) And a status bit (1 if enabled, 0 if not).
+        * Look for the next available slave register slot.
         */
        for (reg = 0; reg < reg_cnt; reg++) {
-               slave_reg = readl(priv->smbus->io +
+               slave_reg = readl(priv->slv->io +
                                MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4);
                /*
                 * Each register holds 4 slave addresses. So, we have to keep
                        addr_tmp = slave_reg_tmp & GENMASK(7, 0);
  
                        /*
-                        * Mark the first available slave address slot, i.e. its
-                        * enabled bit should be unset. This slot might be used
-                        * later on to register our slave.
+                        * If an enable bit is not set in the
+                        * MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG register, then the
+                        * slave address slot associated with that bit is
+                        * free. So set the enable bit and write the
+                        * slave address bits.
                         */
-                       if (!avail && !MLXBF_I2C_SLAVE_ADDR_ENABLED(addr_tmp)) {
-                               avail = true;
-                               reg_avail = reg;
-                               byte_avail = byte;
-                               slave_reg_avail = slave_reg;
-                       }
-                       /*
-                        * Parse slave address bytes and check whether the
-                        * slave address already exists and it's enabled,
-                        * i.e. most significant bit is set.
-                        */
-                       if ((addr_tmp & slave_addr_mask) == addr) {
-                               if (MLXBF_I2C_SLAVE_ADDR_ENABLED(addr_tmp))
-                                       return 0;
-                               disabled = true;
-                               break;
+                       if (!(addr_tmp & MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT)) {
+                               slave_reg &= ~(MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK << (byte * 8));
+                               slave_reg |= (slave->addr << (byte * 8));
+                               slave_reg |= MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT << (byte * 8);
+                               writel(slave_reg, priv->slv->io +
+                                       MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG +
+                                       (reg * 0x4));
+                               /*
+                                * Set the slave at the corresponding index.
+                                */
+                               priv->slave[(reg * 4) + byte] = slave;
+                               return 0;
                        }
  
                        /* Parse next byte. */
                        slave_reg_tmp >>= 8;
                }
-               /* Exit the loop if the slave address is found. */
-               if (disabled)
-                       break;
-       }
-       if (!avail && !disabled)
-               return -EINVAL; /* No room for a new slave address. */
-       if (avail && !disabled) {
-               reg = reg_avail;
-               byte = byte_avail;
-               /* Set the slave address. */
-               slave_reg_avail &= ~(slave_addr_mask << (byte * 8));
-               slave_reg_avail |= addr << (byte * 8);
-               slave_reg = slave_reg_avail;
        }
  
-       /* Enable the slave address and update the register. */
-       slave_reg |= (1 << MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT) << (byte * 8);
-       writel(slave_reg, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG +
-               reg * 0x4);
-       return 0;
+       return -EBUSY;
  }
  
- static int mlxbf_slave_disable(struct mlxbf_i2c_priv *priv)
+ static int mlxbf_i2c_slave_disable(struct mlxbf_i2c_priv *priv, u8 addr)
  {
-       u32 slave_reg, slave_reg_tmp, slave_addr_mask;
-       u8 addr, addr_tmp, reg, reg_cnt, slave_byte;
-       struct i2c_client *client = priv->slave;
-       bool exist;
-       exist = false;
+       u8 addr_tmp, reg, reg_cnt, byte;
+       u32 slave_reg, slave_reg_tmp;
  
-       addr = client->addr;
        reg_cnt = MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT >> 2;
-       slave_addr_mask = MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK;
  
        /*
         * Read the slave registers. There are 4 * 32-bit slave registers.
-        * Each slave register can hold up to 4 * 8-bit slave configuration
-        * (7-bit address, 1 status bit (1 if enabled, 0 if not)).
+        * Each slave register can hold up to 4 * 8-bit slave configuration:
+        * 1) A 7-bit address
+        * 2) And a status bit (1 if enabled, 0 if not).
+        * Check if addr is present in the registers.
         */
        for (reg = 0; reg < reg_cnt; reg++) {
-               slave_reg = readl(priv->smbus->io +
+               slave_reg = readl(priv->slv->io +
                                MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4);
  
                /* Check whether the address slots are empty. */
-               if (slave_reg == 0)
+               if (!slave_reg)
                        continue;
  
                /*
-                * Each register holds 4 slave addresses. So, we have to keep
-                * the byte order consistent with the value read in order to
-                * update the register correctly, if needed.
+                * Check if addr matches any of the 4 slave addresses
+                * in the register.
                 */
                slave_reg_tmp = slave_reg;
-               slave_byte = 0;
-               while (slave_reg_tmp != 0) {
-                       addr_tmp = slave_reg_tmp & slave_addr_mask;
+               for (byte = 0; byte < 4; byte++) {
+                       addr_tmp = slave_reg_tmp & MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK;
                        /*
                         * Parse slave address bytes and check whether the
                         * slave address already exists.
                         */
                        if (addr_tmp == addr) {
-                               exist = true;
-                               break;
+                               /* Clear the slave address slot. */
+                               slave_reg &= ~(GENMASK(7, 0) << (byte * 8));
+                               writel(slave_reg, priv->slv->io +
+                                       MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG +
+                                       (reg * 0x4));
+                               /* Free slave at the corresponding index */
+                               priv->slave[(reg * 4) + byte] = NULL;
+                               return 0;
                        }
  
                        /* Parse next byte. */
                        slave_reg_tmp >>= 8;
-                       slave_byte += 1;
                }
-               /* Exit the loop if the slave address is found. */
-               if (exist)
-                       break;
        }
  
-       if (!exist)
-               return 0; /* Slave is not registered, nothing to do. */
-       /* Cleanup the slave address slot. */
-       slave_reg &= ~(GENMASK(7, 0) << (slave_byte * 8));
-       writel(slave_reg, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG +
-               reg * 0x4);
-       return 0;
+       return -ENXIO;
  }
  
  static int mlxbf_i2c_init_coalesce(struct platform_device *pdev,
@@@ -1746,7 -1775,7 +1775,7 @@@ static int mlxbf_i2c_init_slave(struct 
        int ret;
  
        /* Reset FSM. */
-       writel(0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_FSM);
+       writel(0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_FSM);
  
        /*
         * Enable slave cause interrupt bits. Drive
        writel(int_reg, priv->slv_cause->io + MLXBF_I2C_CAUSE_OR_EVTEN0);
  
        /* Finally, set the 'ready' bit to start handling transactions. */
-       writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);
+       writel(0x1, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_READY);
  
        /* Initialize the cause coalesce resource. */
        ret = mlxbf_i2c_init_coalesce(pdev, priv);
@@@ -1806,84 -1835,93 +1835,93 @@@ static bool mlxbf_i2c_has_coalesce(stru
        return true;
  }
  
- static bool mlxbf_smbus_slave_wait_for_idle(struct mlxbf_i2c_priv *priv,
+ static bool mlxbf_i2c_slave_wait_for_idle(struct mlxbf_i2c_priv *priv,
                                            u32 timeout)
  {
        u32 mask = MLXBF_I2C_CAUSE_S_GW_BUSY_FALL;
        u32 addr = MLXBF_I2C_CAUSE_ARBITER;
  
-       if (mlxbf_smbus_poll(priv->slv_cause->io, addr, mask, false, timeout))
+       if (mlxbf_i2c_poll(priv->slv_cause->io, addr, mask, false, timeout))
                return true;
  
        return false;
  }
  
- /* Send byte to 'external' smbus master. */
static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
+ static struct i2c_client *mlxbf_i2c_get_slave_from_addr(
                      struct mlxbf_i2c_priv *priv, u8 addr)
  {
-       u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 };
-       u8 write_size, pec_en, addr, byte, value, byte_cnt, desc_size;
-       struct i2c_client *slave = priv->slave;
-       u32 control32, data32;
-       int ret;
+       int i;
  
-       if (!slave)
-               return -EINVAL;
+       for (i = 0; i < MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT; i++) {
+               if (!priv->slave[i])
+                       continue;
  
-       addr = 0;
-       byte = 0;
-       desc_size = MLXBF_I2C_SLAVE_DATA_DESC_SIZE;
+               if (priv->slave[i]->addr == addr)
+                       return priv->slave[i];
+       }
+       return NULL;
+ }
+ /*
+  * Send byte to 'external' smbus master. This function is executed when
+  * an external smbus master wants to read data from the BlueField.
+  */
+ static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
+ {
+       u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 };
+       u8 write_size, pec_en, addr, value, byte_cnt;
+       struct i2c_client *slave;
+       u32 control32, data32;
+       int ret = 0;
  
        /*
-        * Read bytes received from the external master. These bytes should
-        * be located in the first data descriptor register of the slave GW.
-        * These bytes are the slave address byte and the internal register
-        * address, if supplied.
+        * Read the first byte received from the external master to
+        * determine the slave address. This byte is located in the
+        * first data descriptor register of the slave GW.
         */
-       if (recv_bytes > 0) {
-               data32 = ioread32be(priv->smbus->io +
-                                       MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
-               /* Parse the received bytes. */
-               switch (recv_bytes) {
-               case 2:
-                       byte = (data32 >> 8) & GENMASK(7, 0);
-                       fallthrough;
-               case 1:
-                       addr = (data32 & GENMASK(7, 0)) >> 1;
-               }
+       data32 = ioread32be(priv->slv->io +
+                               MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
+       addr = (data32 & GENMASK(7, 0)) >> 1;
  
-               /* Check whether it's our slave address. */
-               if (slave->addr != addr)
-                       return -EINVAL;
+       /*
+        * Check if the slave address received in the data descriptor register
+        * matches any of the slave addresses registered. If there is a match,
+        * set the slave.
+        */
+       slave = mlxbf_i2c_get_slave_from_addr(priv, addr);
+       if (!slave) {
+               ret = -ENXIO;
+               goto clear_csr;
        }
  
        /*
-        * I2C read transactions may start by a WRITE followed by a READ.
-        * Indeed, most slave devices would expect the internal address
-        * following the slave address byte. So, write that byte first,
-        * and then, send the requested data bytes to the master.
+        * An I2C read can consist of a WRITE bit transaction followed by
+        * a READ bit transaction. Indeed, slave devices often expect
+        * the slave address to be followed by the internal address.
+        * So, write the internal address byte first, and then, send the
+        * requested data to the master.
         */
        if (recv_bytes > 1) {
                i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
-               value = byte;
+               value = (data32 >> 8) & GENMASK(7, 0);
                ret = i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED,
                                      &value);
                i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
  
                if (ret < 0)
-                       return ret;
+                       goto clear_csr;
        }
  
        /*
-        * Now, send data to the master; currently, the driver supports
-        * READ_BYTE, READ_WORD and BLOCK READ protocols. Note that the
-        * hardware can send up to 128 bytes per transfer. That is the
-        * size of its data registers.
+        * Send data to the master. Currently, the driver supports
+        * READ_BYTE, READ_WORD and BLOCK READ protocols. The
+        * hardware can send up to 128 bytes per transfer which is
+        * the total size of the data registers.
         */
        i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
  
-       for (byte_cnt = 0; byte_cnt < desc_size; byte_cnt++) {
+       for (byte_cnt = 0; byte_cnt < MLXBF_I2C_SLAVE_DATA_DESC_SIZE; byte_cnt++) {
                data_desc[byte_cnt] = value;
                i2c_slave_event(slave, I2C_SLAVE_READ_PROCESSED, &value);
        }
        /* Send a stop condition to the backend. */
        i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
  
-       /* Handle the actual transfer. */
        /* Set the number of bytes to write to master. */
        write_size = (byte_cnt - 1) & 0x7f;
  
        /* Write data to Slave GW data descriptor. */
        mlxbf_i2c_smbus_write_data(priv, data_desc, byte_cnt,
-                                  MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
+                                  MLXBF_I2C_SLAVE_DATA_DESC_ADDR, false);
  
        pec_en = 0; /* Disable PEC since it is not supported. */
  
        control32 |= rol32(write_size, MLXBF_I2C_SLAVE_WRITE_BYTES_SHIFT);
        control32 |= rol32(pec_en, MLXBF_I2C_SLAVE_SEND_PEC_SHIFT);
  
-       writel(control32, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_GW);
+       writel(control32, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_GW);
  
        /*
         * Wait until the transfer is completed; the driver will wait
         * until the GW is idle, a cause will rise on fall of GW busy.
         */
-       mlxbf_smbus_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT);
+       mlxbf_i2c_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT);
  
+ clear_csr:
        /* Release the Slave GW. */
-       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
-       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC);
-       writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);
+       writel(0x0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
+       writel(0x0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_PEC);
+       writel(0x1, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_READY);
  
-       return 0;
+       return ret;
  }
  
- /* Receive bytes from 'external' smbus master. */
- static int mlxbf_smbus_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
+ /*
+  * Receive bytes from 'external' smbus master. This function is executed when
+  * an external smbus master wants to write data to the BlueField.
+  */
+ static int mlxbf_i2c_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
  {
        u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 };
-       struct i2c_client *slave = priv->slave;
+       struct i2c_client *slave;
        u8 value, byte, addr;
        int ret = 0;
  
-       if (!slave)
-               return -EINVAL;
        /* Read data from Slave GW data descriptor. */
        mlxbf_i2c_smbus_read_data(priv, data_desc, recv_bytes,
-                                 MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
-       /* Check whether its our slave address. */
+                                 MLXBF_I2C_SLAVE_DATA_DESC_ADDR, false);
        addr = data_desc[0] >> 1;
-       if (slave->addr != addr)
-               return -EINVAL;
  
        /*
-        * Notify the slave backend; another I2C master wants to write data
-        * to us. This event is sent once the slave address and the write bit
-        * is detected.
+        * Check if the slave address received in the data descriptor register
+        * matches any of the slave addresses registered.
+        */
+       slave = mlxbf_i2c_get_slave_from_addr(priv, addr);
+       if (!slave) {
+               ret = -EINVAL;
+               goto clear_csr;
+       }
+       /*
+        * Notify the slave backend that an smbus master wants to write data
+        * to the BlueField.
         */
        i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
  
                        break;
        }
  
-       /* Send a stop condition to the backend. */
+       /*
+        * Send a stop event to the slave backend, to signal
+        * the end of the write transactions.
+        */
        i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
  
+ clear_csr:
        /* Release the Slave GW. */
-       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
-       writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC);
-       writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);
+       writel(0x0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
+       writel(0x0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_PEC);
+       writel(0x1, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_READY);
  
        return ret;
  }
  
- static irqreturn_t mlxbf_smbus_irq(int irq, void *ptr)
+ static irqreturn_t mlxbf_i2c_irq(int irq, void *ptr)
  {
        struct mlxbf_i2c_priv *priv = ptr;
        bool read, write, irq_is_set;
         * slave, if the higher 8 bits are sent then the slave expect N bytes
         * from the master.
         */
-       rw_bytes_reg = readl(priv->smbus->io +
+       rw_bytes_reg = readl(priv->slv->io +
                                MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
        recv_bytes = (rw_bytes_reg >> 8) & GENMASK(7, 0);
  
                MLXBF_I2C_SLAVE_DATA_DESC_SIZE : recv_bytes;
  
        if (read)
-               mlxbf_smbus_irq_send(priv, recv_bytes);
+               mlxbf_i2c_irq_send(priv, recv_bytes);
        else
-               mlxbf_smbus_irq_recv(priv, recv_bytes);
+               mlxbf_i2c_irq_recv(priv, recv_bytes);
  
        return IRQ_HANDLED;
  }
@@@ -2115,23 -2161,21 +2161,21 @@@ static s32 mlxbf_i2c_smbus_xfer(struct 
  static int mlxbf_i2c_reg_slave(struct i2c_client *slave)
  {
        struct mlxbf_i2c_priv *priv = i2c_get_adapdata(slave->adapter);
+       struct device *dev = &slave->dev;
        int ret;
  
-       if (priv->slave)
-               return -EBUSY;
        /*
         * Do not support ten bit chip address and do not use Packet Error
         * Checking (PEC).
         */
-       if (slave->flags & (I2C_CLIENT_TEN | I2C_CLIENT_PEC))
+       if (slave->flags & (I2C_CLIENT_TEN | I2C_CLIENT_PEC)) {
+               dev_err(dev, "SMBus PEC and 10 bit address not supported\n");
                return -EAFNOSUPPORT;
+       }
  
-       ret = mlxbf_slave_enable(priv, slave->addr);
-       if (ret < 0)
-               return ret;
-       priv->slave = slave;
+       ret = mlxbf_i2c_slave_enable(priv, slave);
+       if (ret)
+               dev_err(dev, "Surpassed max number of registered slaves allowed\n");
  
        return 0;
  }
  static int mlxbf_i2c_unreg_slave(struct i2c_client *slave)
  {
        struct mlxbf_i2c_priv *priv = i2c_get_adapdata(slave->adapter);
+       struct device *dev = &slave->dev;
        int ret;
  
-       WARN_ON(!priv->slave);
-       /* Unregister slave, i.e. disable the slave address in hardware. */
-       ret = mlxbf_slave_disable(priv);
-       if (ret < 0)
-               return ret;
-       priv->slave = NULL;
+       /*
+        * Unregister slave by:
+        * 1) Disabling the slave address in hardware
+        * 2) Freeing priv->slave at the corresponding index
+        */
+       ret = mlxbf_i2c_slave_disable(priv, slave->addr);
+       if (ret)
+               dev_err(dev, "Unable to find slave 0x%x\n", slave->addr);
  
-       return 0;
+       return ret;
  }
  
  static u32 mlxbf_i2c_functionality(struct i2c_adapter *adap)
@@@ -2166,14 -2211,27 +2211,27 @@@ static struct mlxbf_i2c_chip_info mlxbf
                        [1] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_1],
                        [2] = &mlxbf_i2c_gpio_res[MLXBF_I2C_CHIP_TYPE_1]
                },
-               .calculate_freq = mlxbf_i2c_calculate_freq_from_tyu
+               .calculate_freq = mlxbf_i2c_calculate_freq_from_tyu,
+               .smbus_master_rs_bytes_off = MLXBF_I2C_YU_SMBUS_RS_BYTES,
+               .smbus_master_fsm_off = MLXBF_I2C_YU_SMBUS_MASTER_FSM
        },
        [MLXBF_I2C_CHIP_TYPE_2] = {
                .type = MLXBF_I2C_CHIP_TYPE_2,
                .shared_res = {
                        [0] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_2]
                },
-               .calculate_freq = mlxbf_i2c_calculate_freq_from_yu
+               .calculate_freq = mlxbf_i2c_calculate_freq_from_yu,
+               .smbus_master_rs_bytes_off = MLXBF_I2C_YU_SMBUS_RS_BYTES,
+               .smbus_master_fsm_off = MLXBF_I2C_YU_SMBUS_MASTER_FSM
+       },
+       [MLXBF_I2C_CHIP_TYPE_3] = {
+               .type = MLXBF_I2C_CHIP_TYPE_3,
+               .shared_res = {
+                       [0] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_3]
+               },
+               .calculate_freq = mlxbf_i2c_calculate_freq_from_yu,
+               .smbus_master_rs_bytes_off = MLXBF_I2C_RSH_YU_SMBUS_RS_BYTES,
+               .smbus_master_fsm_off = MLXBF_I2C_RSH_YU_SMBUS_MASTER_FSM
        }
  };
  
@@@ -2189,24 -2247,11 +2247,11 @@@ static struct i2c_adapter_quirks mlxbf_
        .max_write_len = MLXBF_I2C_MASTER_DATA_W_LENGTH,
  };
  
- static const struct of_device_id mlxbf_i2c_dt_ids[] = {
-       {
-               .compatible = "mellanox,i2c-mlxbf1",
-               .data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1]
-       },
-       {
-               .compatible = "mellanox,i2c-mlxbf2",
-               .data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2]
-       },
-       {},
- };
- MODULE_DEVICE_TABLE(of, mlxbf_i2c_dt_ids);
  #ifdef CONFIG_ACPI
  static const struct acpi_device_id mlxbf_i2c_acpi_ids[] = {
        { "MLNXBF03", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1] },
        { "MLNXBF23", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2] },
+       { "MLNXBF31", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_3] },
        {},
  };
  
@@@ -2215,27 -2260,35 +2260,27 @@@ MODULE_DEVICE_TABLE(acpi, mlxbf_i2c_acp
  static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
  {
        const struct acpi_device_id *aid;
 -      struct acpi_device *adev;
 -      unsigned long bus_id = 0;
 -      const char *uid;
 +      u64 bus_id;
        int ret;
  
        if (acpi_disabled)
                return -ENOENT;
  
 -      adev = ACPI_COMPANION(dev);
 -      if (!adev)
 -              return -ENXIO;
 -
        aid = acpi_match_device(mlxbf_i2c_acpi_ids, dev);
        if (!aid)
                return -ENODEV;
  
        priv->chip = (struct mlxbf_i2c_chip_info *)aid->driver_data;
  
 -      uid = acpi_device_uid(adev);
 -      if (!uid || !(*uid)) {
 +      ret = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &bus_id);
 +      if (ret) {
                dev_err(dev, "Cannot retrieve UID\n");
 -              return -ENODEV;
 +              return ret;
        }
  
 -      ret = kstrtoul(uid, 0, &bus_id);
 -      if (!ret)
 -              priv->bus = bus_id;
 +      priv->bus = bus_id;
  
 -      return ret;
 +      return 0;
  }
  #else
  static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
  }
  #endif /* CONFIG_ACPI */
  
- static int mlxbf_i2c_of_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
- {
-       const struct of_device_id *oid;
-       int bus_id = -1;
-       if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
-               oid = of_match_node(mlxbf_i2c_dt_ids, dev->of_node);
-               if (!oid)
-                       return -ENODEV;
-               priv->chip = oid->data;
-               bus_id = of_alias_get_id(dev->of_node, "i2c");
-               if (bus_id >= 0)
-                       priv->bus = bus_id;
-       }
-       if (bus_id < 0) {
-               dev_err(dev, "Cannot get bus id");
-               return bus_id;
-       }
-       return 0;
- }
  static int mlxbf_i2c_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct mlxbf_i2c_priv *priv;
        struct i2c_adapter *adap;
+       u32 resource_version;
        int irq, ret;
  
        priv = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_priv), GFP_KERNEL);
                return -ENOMEM;
  
        ret = mlxbf_i2c_acpi_probe(dev, priv);
-       if (ret < 0 && ret != -ENOENT && ret != -ENXIO)
-               ret = mlxbf_i2c_of_probe(dev, priv);
        if (ret < 0)
                return ret;
  
-       ret = mlxbf_i2c_init_resource(pdev, &priv->smbus,
-                                     MLXBF_I2C_SMBUS_RES);
-       if (ret < 0) {
-               dev_err(dev, "Cannot fetch smbus resource info");
-               return ret;
+       /* This property allows the driver to stay backward compatible with older
+        * ACPI tables.
+        * Starting BlueField-3 SoC, the "smbus" resource was broken down into 3
+        * separate resources "timer", "master" and "slave".
+        */
+       if (device_property_read_u32(dev, "resource_version", &resource_version))
+               resource_version = 0;
+       priv->resource_version = resource_version;
+       if (priv->chip->type < MLXBF_I2C_CHIP_TYPE_3 && resource_version == 0) {
+               priv->timer = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_resource), GFP_KERNEL);
+               if (!priv->timer)
+                       return -ENOMEM;
+               priv->mst = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_resource), GFP_KERNEL);
+               if (!priv->mst)
+                       return -ENOMEM;
+               priv->slv = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_resource), GFP_KERNEL);
+               if (!priv->slv)
+                       return -ENOMEM;
+               ret = mlxbf_i2c_init_resource(pdev, &priv->smbus,
+                                             MLXBF_I2C_SMBUS_RES);
+               if (ret < 0) {
+                       dev_err(dev, "Cannot fetch smbus resource info");
+                       return ret;
+               }
+               priv->timer->io = priv->smbus->io;
+               priv->mst->io = priv->smbus->io + MLXBF_I2C_MST_ADDR_OFFSET;
+               priv->slv->io = priv->smbus->io + MLXBF_I2C_SLV_ADDR_OFFSET;
+       } else {
+               ret = mlxbf_i2c_init_resource(pdev, &priv->timer,
+                                             MLXBF_I2C_SMBUS_TIMER_RES);
+               if (ret < 0) {
+                       dev_err(dev, "Cannot fetch timer resource info");
+                       return ret;
+               }
+               ret = mlxbf_i2c_init_resource(pdev, &priv->mst,
+                                             MLXBF_I2C_SMBUS_MST_RES);
+               if (ret < 0) {
+                       dev_err(dev, "Cannot fetch master resource info");
+                       return ret;
+               }
+               ret = mlxbf_i2c_init_resource(pdev, &priv->slv,
+                                             MLXBF_I2C_SMBUS_SLV_RES);
+               if (ret < 0) {
+                       dev_err(dev, "Cannot fetch slave resource info");
+                       return ret;
+               }
        }
  
        ret = mlxbf_i2c_init_resource(pdev, &priv->mst_cause,
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
                return irq;
-       ret = devm_request_irq(dev, irq, mlxbf_smbus_irq,
-                              IRQF_ONESHOT | IRQF_SHARED | IRQF_PROBE_SHARED,
+       ret = devm_request_irq(dev, irq, mlxbf_i2c_irq,
+                              IRQF_SHARED | IRQF_PROBE_SHARED,
                               dev_name(dev), priv);
        if (ret < 0) {
                dev_err(dev, "Cannot get irq %d\n", irq);
@@@ -2379,8 -2454,19 +2446,19 @@@ static int mlxbf_i2c_remove(struct plat
        struct device *dev = &pdev->dev;
        struct resource *params;
  
-       params = priv->smbus->params;
-       devm_release_mem_region(dev, params->start, resource_size(params));
+       if (priv->chip->type < MLXBF_I2C_CHIP_TYPE_3 && priv->resource_version == 0) {
+               params = priv->smbus->params;
+               devm_release_mem_region(dev, params->start, resource_size(params));
+       } else {
+               params = priv->timer->params;
+               devm_release_mem_region(dev, params->start, resource_size(params));
+               params = priv->mst->params;
+               devm_release_mem_region(dev, params->start, resource_size(params));
+               params = priv->slv->params;
+               devm_release_mem_region(dev, params->start, resource_size(params));
+       }
  
        params = priv->mst_cause->params;
        devm_release_mem_region(dev, params->start, resource_size(params));
@@@ -2412,7 -2498,6 +2490,6 @@@ static struct platform_driver mlxbf_i2c
        .remove = mlxbf_i2c_remove,
        .driver = {
                .name = "i2c-mlxbf",
-               .of_match_table = mlxbf_i2c_dt_ids,
  #ifdef CONFIG_ACPI
                .acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids),
  #endif /* CONFIG_ACPI  */
@@@ -2445,4 -2530,5 +2522,5 @@@ module_exit(mlxbf_i2c_exit)
  
  MODULE_DESCRIPTION("Mellanox BlueField I2C bus driver");
  MODULE_AUTHOR("Khalil Blaiech <[email protected]>");
+ MODULE_AUTHOR("Asmaa Mnebhi <[email protected]>");
  MODULE_LICENSE("GPL v2");
index 79be5fc044bd48a7690b4753fba904544cd554c1,b25e91b26d99170007caa5cebc58b0e1a911d23a..7d746cd9ca1bc6b72b253792c8878d97e48ecd9b
@@@ -65,16 -65,16 +65,14 @@@ static int lan9303_i2c_probe(struct i2c
        return 0;
  }
  
- static int lan9303_i2c_remove(struct i2c_client *client)
+ static void lan9303_i2c_remove(struct i2c_client *client)
  {
        struct lan9303_i2c *sw_dev = i2c_get_clientdata(client);
  
        if (!sw_dev)
-               return 0;
+               return;
  
        lan9303_remove(&sw_dev->chip);
--
-       return 0;
 -      i2c_set_clientdata(client, NULL);
  }
  
  static void lan9303_i2c_shutdown(struct i2c_client *client)
index e111756f6473543e670c1ffe84f3f5d5f49cd409,4a719ab8aa89cdb715427dfb945cc6094c915050..3763930dc6fc4765d08e7c3e6cf1ebe4acc3b24a
@@@ -52,14 -52,14 +52,12 @@@ static int ksz9477_i2c_probe(struct i2c
        return 0;
  }
  
- static int ksz9477_i2c_remove(struct i2c_client *i2c)
+ static void ksz9477_i2c_remove(struct i2c_client *i2c)
  {
        struct ksz_device *dev = i2c_get_clientdata(i2c);
  
        if (dev)
                ksz_switch_remove(dev);
--
-       return 0;
 -      i2c_set_clientdata(i2c, NULL);
  }
  
  static void ksz9477_i2c_shutdown(struct i2c_client *i2c)
@@@ -89,10 -89,6 +87,10 @@@ static const struct of_device_id ksz947
                .compatible = "microchip,ksz9477",
                .data = &ksz_switch_chips[KSZ9477]
        },
 +      {
 +              .compatible = "microchip,ksz9896",
 +              .data = &ksz_switch_chips[KSZ9896]
 +      },
        {
                .compatible = "microchip,ksz9897",
                .data = &ksz_switch_chips[KSZ9897]
index cd533b9e17eca444bbca4e3017f5fa1eacb9355c,bbaf5a3fbf000d7b69e49bc9de99bfae9fed6dd3..54065cdedd3572b1040acd9e450ae20523855d43
@@@ -105,16 -105,16 +105,14 @@@ static int xrs700x_i2c_probe(struct i2c
        return 0;
  }
  
- static int xrs700x_i2c_remove(struct i2c_client *i2c)
+ static void xrs700x_i2c_remove(struct i2c_client *i2c)
  {
        struct xrs700x *priv = i2c_get_clientdata(i2c);
  
        if (!priv)
-               return 0;
+               return;
  
        xrs700x_switch_remove(priv);
--
-       return 0;
 -      i2c_set_clientdata(i2c, NULL);
  }
  
  static void xrs700x_i2c_shutdown(struct i2c_client *i2c)
index 716c73e4fd594bd8358242274157c03d76b664fb,50b7121a5e3cd54e758ab8ab7718528e5aceb036..f5f5f8dc3d190c5298ce8b3c9272a8155062d4b3
@@@ -9,7 -9,6 +9,7 @@@
  #include <linux/mutex.h>
  #include <linux/module.h>
  #include <linux/mod_devicetable.h>
 +#include <linux/platform_data/mlxreg.h>
  #include <linux/slab.h>
  
  #include "cmd.h"
  #define MLXSW_I2C_TIMEOUT_MSECS               5000
  #define MLXSW_I2C_MAX_DATA_SIZE               256
  
 +/* Driver can be initialized by kernel platform driver or from the user
 + * space. In the first case IRQ line number is passed through the platform
 + * data, otherwise default IRQ line is to be used. Default IRQ is relevant
 + * only for specific I2C slave address, allowing 3.4 MHz I2C path to the chip
 + * (special hardware feature for I2C acceleration).
 + */
 +#define MLXSW_I2C_DEFAULT_IRQ         17
 +#define MLXSW_FAST_I2C_SLAVE          0x37
 +
  /**
   * struct mlxsw_i2c - device private data:
   * @cmd: command attributes;
@@@ -73,9 -63,6 +73,9 @@@
   * @core: switch core pointer;
   * @bus_info: bus info block;
   * @block_size: maximum block size allowed to pass to under layer;
 + * @pdata: device platform data;
 + * @irq_work: interrupts work item;
 + * @irq: IRQ line number;
   */
  struct mlxsw_i2c {
        struct {
@@@ -89,9 -76,6 +89,9 @@@
        struct mlxsw_core *core;
        struct mlxsw_bus_info bus_info;
        u16 block_size;
 +      struct mlxreg_core_hotplug_platform_data *pdata;
 +      struct work_struct irq_work;
 +      int irq;
  };
  
  #define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) {  \
@@@ -562,67 -546,6 +562,67 @@@ static void mlxsw_i2c_fini(void *bus_pr
        mlxsw_i2c->core = NULL;
  }
  
 +static void mlxsw_i2c_work_handler(struct work_struct *work)
 +{
 +      struct mlxsw_i2c *mlxsw_i2c;
 +
 +      mlxsw_i2c = container_of(work, struct mlxsw_i2c, irq_work);
 +      mlxsw_core_irq_event_handlers_call(mlxsw_i2c->core);
 +}
 +
 +static irqreturn_t mlxsw_i2c_irq_handler(int irq, void *dev)
 +{
 +      struct mlxsw_i2c *mlxsw_i2c = dev;
 +
 +      mlxsw_core_schedule_work(&mlxsw_i2c->irq_work);
 +
 +      /* Interrupt handler shares IRQ line with 'main' interrupt handler.
 +       * Return here IRQ_NONE, while main handler will return IRQ_HANDLED.
 +       */
 +      return IRQ_NONE;
 +}
 +
 +static int mlxsw_i2c_irq_init(struct mlxsw_i2c *mlxsw_i2c, u8 addr)
 +{
 +      int err;
 +
 +      /* Initialize interrupt handler if system hotplug driver is reachable,
 +       * otherwise interrupt line is not enabled and interrupts will not be
 +       * raised to CPU. Also request_irq() call will be not valid.
 +       */
 +      if (!IS_REACHABLE(CONFIG_MLXREG_HOTPLUG))
 +              return 0;
 +
 +      /* Set default interrupt line. */
 +      if (mlxsw_i2c->pdata && mlxsw_i2c->pdata->irq)
 +              mlxsw_i2c->irq = mlxsw_i2c->pdata->irq;
 +      else if (addr == MLXSW_FAST_I2C_SLAVE)
 +              mlxsw_i2c->irq = MLXSW_I2C_DEFAULT_IRQ;
 +
 +      if (!mlxsw_i2c->irq)
 +              return 0;
 +
 +      INIT_WORK(&mlxsw_i2c->irq_work, mlxsw_i2c_work_handler);
 +      err = request_irq(mlxsw_i2c->irq, mlxsw_i2c_irq_handler,
 +                        IRQF_TRIGGER_FALLING | IRQF_SHARED, "mlxsw-i2c",
 +                        mlxsw_i2c);
 +      if (err) {
 +              dev_err(mlxsw_i2c->bus_info.dev, "Failed to request irq: %d\n",
 +                      err);
 +              return err;
 +      }
 +
 +      return 0;
 +}
 +
 +static void mlxsw_i2c_irq_fini(struct mlxsw_i2c *mlxsw_i2c)
 +{
 +      if (!IS_REACHABLE(CONFIG_MLXREG_HOTPLUG) || !mlxsw_i2c->irq)
 +              return;
 +      cancel_work_sync(&mlxsw_i2c->irq_work);
 +      free_irq(mlxsw_i2c->irq, mlxsw_i2c);
 +}
 +
  static const struct mlxsw_bus mlxsw_i2c_bus = {
        .kind                   = "i2c",
        .init                   = mlxsw_i2c_init,
@@@ -715,24 -638,17 +715,24 @@@ static int mlxsw_i2c_probe(struct i2c_c
        mlxsw_i2c->bus_info.dev = &client->dev;
        mlxsw_i2c->bus_info.low_frequency = true;
        mlxsw_i2c->dev = &client->dev;
 +      mlxsw_i2c->pdata = client->dev.platform_data;
 +
 +      err = mlxsw_i2c_irq_init(mlxsw_i2c, client->addr);
 +      if (err)
 +              goto errout;
  
        err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info,
                                             &mlxsw_i2c_bus, mlxsw_i2c, false,
                                             NULL, NULL);
        if (err) {
                dev_err(&client->dev, "Fail to register core bus\n");
 -              return err;
 +              goto err_bus_device_register;
        }
  
        return 0;
  
 +err_bus_device_register:
 +      mlxsw_i2c_irq_fini(mlxsw_i2c);
  errout:
        mutex_destroy(&mlxsw_i2c->cmd.lock);
        i2c_set_clientdata(client, NULL);
        return err;
  }
  
- static int mlxsw_i2c_remove(struct i2c_client *client)
+ static void mlxsw_i2c_remove(struct i2c_client *client)
  {
        struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
  
        mlxsw_core_bus_device_unregister(mlxsw_i2c->core, false);
 +      mlxsw_i2c_irq_fini(mlxsw_i2c);
        mutex_destroy(&mlxsw_i2c->cmd.lock);
-       return 0;
  }
  
  int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver)
index 49fc379fe680abbac986f384759bb0004610fd9b,5dd81bb05255babe407f406eb05427856ffef3a8..f83e9c393f31b3a356f9465803975b0bc293a09f
@@@ -1,7 -1,6 +1,7 @@@
  // SPDX-License-Identifier: GPL-2.0
  /* Author: Dan Scally <[email protected]> */
  
 +#include <linux/acpi.h>
  #include <linux/i2c.h>
  #include <linux/kernel.h>
  #include <linux/mfd/core.h>
@@@ -96,65 -95,20 +96,65 @@@ static int skl_int3472_tps68470_calc_ty
        return DESIGNED_FOR_WINDOWS;
  }
  
 +/*
 + * Return the size of the flexible array member, because we'll need that later
 + * on to pass .pdata_size to cells.
 + */
 +static int
 +skl_int3472_fill_clk_pdata(struct device *dev, struct tps68470_clk_platform_data **clk_pdata)
 +{
 +      struct acpi_device *adev = ACPI_COMPANION(dev);
 +      struct acpi_device *consumer;
 +      unsigned int n_consumers = 0;
 +      const char *sensor_name;
 +      unsigned int i = 0;
 +
 +      for_each_acpi_consumer_dev(adev, consumer)
 +              n_consumers++;
 +
 +      if (!n_consumers) {
 +              dev_err(dev, "INT3472 seems to have no dependents\n");
 +              return -ENODEV;
 +      }
 +
 +      *clk_pdata = devm_kzalloc(dev, struct_size(*clk_pdata, consumers, n_consumers),
 +                                GFP_KERNEL);
 +      if (!*clk_pdata)
 +              return -ENOMEM;
 +
 +      (*clk_pdata)->n_consumers = n_consumers;
 +      i = 0;
 +
 +      for_each_acpi_consumer_dev(adev, consumer) {
 +              sensor_name = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
 +                                           acpi_dev_name(consumer));
 +              if (!sensor_name)
 +                      return -ENOMEM;
 +
 +              (*clk_pdata)->consumers[i].consumer_dev_name = sensor_name;
 +              i++;
 +      }
 +
 +      acpi_dev_put(consumer);
 +
 +      return n_consumers;
 +}
 +
  static int skl_int3472_tps68470_probe(struct i2c_client *client)
  {
        struct acpi_device *adev = ACPI_COMPANION(&client->dev);
        const struct int3472_tps68470_board_data *board_data;
 -      struct tps68470_clk_platform_data clk_pdata = {};
 +      struct tps68470_clk_platform_data *clk_pdata;
        struct mfd_cell *cells;
        struct regmap *regmap;
 +      int n_consumers;
        int device_type;
        int ret;
 +      int i;
  
 -      ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL,
 -                                                 &clk_pdata.consumer_dev_name);
 -      if (ret)
 -              return ret;
 +      n_consumers = skl_int3472_fill_clk_pdata(&client->dev, &clk_pdata);
 +      if (n_consumers < 0)
 +              return n_consumers;
  
        regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
        if (IS_ERR(regmap)) {
                 * the clk + regulators must be ready when this happens.
                 */
                cells[0].name = "tps68470-clk";
 -              cells[0].platform_data = &clk_pdata;
 -              cells[0].pdata_size = sizeof(clk_pdata);
 +              cells[0].platform_data = clk_pdata;
 +              cells[0].pdata_size = struct_size(clk_pdata, consumers, n_consumers);
                cells[1].name = "tps68470-regulator";
                cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata;
                cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data);
                cells[2].name = "tps68470-gpio";
  
 -              gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table);
 +              for (i = 0; i < board_data->n_gpiod_lookups; i++)
 +                      gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
  
                ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
                                           cells, TPS68470_WIN_MFD_CELL_COUNT,
                                           NULL, 0, NULL);
                kfree(cells);
  
 -              if (ret)
 -                      gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
 +              if (ret) {
 +                      for (i = 0; i < board_data->n_gpiod_lookups; i++)
 +                              gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
 +              }
  
                break;
        case DESIGNED_FOR_CHROMEOS:
        return ret;
  }
  
- static int skl_int3472_tps68470_remove(struct i2c_client *client)
+ static void skl_int3472_tps68470_remove(struct i2c_client *client)
  {
        const struct int3472_tps68470_board_data *board_data;
 +      int i;
  
        board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
 -      if (board_data)
 -              gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
 +      if (board_data) {
 +              for (i = 0; i < board_data->n_gpiod_lookups; i++)
 +                      gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
 +      }
-       return 0;
  }
  
  static const struct acpi_device_id int3472_device_id[] = {
This page took 0.294027 seconds and 4 git commands to generate.