Hi Neil Armstrong,

moved to separate commit in v2 patch set, please refer: [PATCH v2 5/7] i2c: geni: Add chip probing support - Gurumoorthy Santhakumar

<https://lore.kernel.org/u-boot/20261021125003.2948090-6-gurumoorthy.santhaku...@oss.qualcomm.com/>Regards,
Gurumoorthy

On 10/20/2026 2:33 PM, [email protected] wrote:
On 10/7/26 19:41, Gurumoorthy Santhakumar wrote:
Add support for 32MHz GENI SE clocks through dedicated timing tables
selected via the qcom,geni-se-clk-32mhz DT property. Also add chip
probing support.

Depends on:
misc: qcom_geni: Add minicore support
Link: https://lore.kernel.org/u-boot/[email protected]/

Signed-off-by: Gurumoorthy Santhakumar <[email protected]>
---
  drivers/i2c/geni_i2c.c | 76 ++++++++++++++++++++++++++++++++++++------
  1 file changed, 66 insertions(+), 10 deletions(-)

diff --git a/drivers/i2c/geni_i2c.c b/drivers/i2c/geni_i2c.c
index 7498cbcb41a..9edba3dd551 100644
--- a/drivers/i2c/geni_i2c.c
+++ b/drivers/i2c/geni_i2c.c
@@ -96,18 +96,35 @@ struct geni_i2c_priv {
   * clk_freq_out = t / t_cycle
   * source_clock = 19.2 MHz
   */
-static const struct geni_i2c_clk_fld geni_i2c_clk_map[] = {
-    {I2C_SPEED_STANDARD_RATE, 7, 10, 11, 26},
-    {I2C_SPEED_FAST_RATE, 2,  5, 12, 24},
-    {I2C_SPEED_FAST_PLUS_RATE, 1, 3,  9, 18},
+static const struct geni_i2c_clk_fld geni_i2c_clk_map_19p2mhz[] = {
+    {I2C_SPEED_STANDARD_RATE, 7, 10, 12, 26},
+    {I2C_SPEED_FAST_RATE, 2,  5, 11, 22},
+    {I2C_SPEED_FAST_PLUS_RATE, 1, 2,  8, 18},
  };
  -static int geni_i2c_clk_map_idx(struct geni_i2c_priv *geni, unsigned int clk_freq)
+/* source_clock = 32 MHz */
+static const struct geni_i2c_clk_fld geni_i2c_clk_map_32mhz[] = {
+    {I2C_SPEED_STANDARD_RATE, 12, 9, 10, 26},
+    {I2C_SPEED_FAST_RATE, 4,  3, 9, 19},
+    {I2C_SPEED_FAST_PLUS_RATE, 2, 3, 5, 15},
+};
+
+static int geni_i2c_clk_map_idx(struct geni_i2c_priv *geni,
+                unsigned int clk_freq, bool use_32mhz)
  {
-    const struct geni_i2c_clk_fld *itr = geni_i2c_clk_map;
+    const struct geni_i2c_clk_fld *itr;
+    int array_size;
      int i;
  -    for (i = 0; i < ARRAY_SIZE(geni_i2c_clk_map); i++, itr++) {
+    if (use_32mhz) {
+        itr = geni_i2c_clk_map_32mhz;
+        array_size = ARRAY_SIZE(geni_i2c_clk_map_32mhz);
+    } else {
+        itr = geni_i2c_clk_map_19p2mhz;
+        array_size = ARRAY_SIZE(geni_i2c_clk_map_19p2mhz);
+    }
+
+    for (i = 0; i < array_size; i++, itr++) {
          if (itr->clk_freq_out == clk_freq) {
              geni->clk_fld = itr;
              return 0;
@@ -262,6 +279,38 @@ static int geni_i2c_xfer_rx(struct geni_i2c_priv *geni, struct i2c_msg *msg, u32
      return geni_i2c_fifo_rx_drain(geni, msg);
  }
  +/* Probe to see if a chip is present. */
+static int geni_i2c_probe_chip(struct udevice *dev, uint chip_addr,
+                   uint chip_flags)
+{
+    struct geni_i2c_priv *geni = dev_get_priv(dev);
+    u32 m_param = (chip_addr << SLV_ADDR_SHFT) & SLV_ADDR_MSK;
+    u32 status;
+    ulong start;
+
+    (void)chip_flags;
+
+    /* Add delay before chip detect to prevent the bus going undefined. */
+    mdelay(1);
+
+    qcom_geni_i2c_conf(geni);
+    writel(0, geni->base + SE_I2C_TX_TRANS_LEN);
+    geni_i2c_setup_m_cmd(geni, I2C_ADDR_ONLY, m_param);
+    writel(1, geni->base + SE_GENI_TX_WATERMARK_REG);
+
+    start = get_timer(0);
+    while (get_timer(start) < I2C_TIMEOUT_MS) {
+        status = readl(geni->base + SE_GENI_M_IRQ_STATUS);
+        if (status & M_CMD_DONE_EN) {
+            writel(status, geni->base + SE_GENI_M_IRQ_CLEAR);
+            return (status & SE_I2C_ERR) ? -ENODEV : 0;
+        }
+        udelay(10);
+    }
+
+    return -ETIMEDOUT;
+}

This probe_chip callback is unrelated to this change, move it to a separate commit.

Neil

+
  static int geni_i2c_xfer(struct udevice *bus, struct i2c_msg msgs[], int num)
  {
      struct geni_i2c_priv *geni = dev_get_priv(bus);
@@ -468,6 +517,8 @@ static int geni_i2c_probe(struct udevice *dev)
      ofnode parent_node = ofnode_get_parent(dev_ofnode(dev));
      struct geni_i2c_priv *geni = dev_get_priv(dev);
      u32 proto, tx_depth, fifo_disable;
+    u32 clk_freq;
+    bool use_32mhz;
      int ret;
        geni->is_master_hub = dev_get_driver_data(dev) & GENI_I2C_IS_MASTER_HUB;
@@ -538,19 +589,24 @@ static int geni_i2c_probe(struct udevice *dev)
      geni_i2c_config_packing(geni, BITS_PER_BYTE,
                  PACKING_BYTES_PW, true, true, true);
  -    /* Setup for standard rate */
-    return geni_i2c_clk_map_idx(geni, I2C_SPEED_STANDARD_RATE);
+    clk_freq = dev_read_u32_default(dev, "clock-frequency",
+                    I2C_SPEED_STANDARD_RATE);
+    use_32mhz = dev_read_bool(dev, "qcom,geni-se-clk-32mhz");
+
+    return geni_i2c_clk_map_idx(geni, clk_freq, use_32mhz);
  }
    static int geni_i2c_set_bus_speed(struct udevice *dev, unsigned int clk_freq)
  {
      struct geni_i2c_priv *geni = dev_get_priv(dev);
+    bool use_32mhz = dev_read_bool(dev, "qcom,geni-se-clk-32mhz");
  -    return geni_i2c_clk_map_idx(geni, clk_freq);
+    return geni_i2c_clk_map_idx(geni, clk_freq, use_32mhz);
  }
    static const struct dm_i2c_ops geni_i2c_ops = {
      .xfer        = geni_i2c_xfer,
+    .probe_chip    = geni_i2c_probe_chip,
      .set_bus_speed    = geni_i2c_set_bus_speed,
  };

Reply via email to