I2C multi-master mode no longer supported in Jetpack 3.1?

With Jetpack 3.1, new flag, “has_multi_master_support”, was introduced in the I2C driver (drivers/i2c/busses/i2c-tegra.c) and it’s set to false for all the defined hw platforms, e.g.

static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
        .has_continue_xfer_support = true,
        .has_per_pkt_xfer_complete_irq = true,
        .has_single_clk_source = true,
        .clk_divisor_hs_mode = 2,
        .clk_multiplier_hs_mode = 13,
        .clk_divisor_std_fast_mode = 0x19,
        .clk_divisor_fast_plus_mode = 0x10,
        .has_config_load_reg = true,
        .has_multi_master_mode = true,
        .has_slcg_override_reg = true,
        .has_sw_reset_reg = true,
        .has_hw_arb_support = true,
        .has_reg_write_buffering = false,
        .has_slcg_support = true,
        .has_hs_mode_support = false,
        .has_multi_master_support = false,
};

If you define “multi-master” in the DT node as in L4T v27, you will get error message saying “multi-master mode not supported”. What was the reason for the multi-master support being turned off in L4T v28?

@rong1129

Due to HW bugs with I2C HS mode and multi-master mode features, these features are de-featured, remove this support from SW.

If we don’t use HS mode on one particular I2C interface, can we enable the multi-master support in driver? Looks like there are some other code changes we need to make to enable the multi-master support, right?

Could you help to verify it? Below it the change to de-featured it.

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 049c860..6af0f9f 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -233,6 +233,7 @@ struct tegra_i2c_hw_feature {
        bool has_reg_write_buffering;
        bool has_slcg_support;
        bool has_hs_mode_support;
+       bool has_multi_master_support;
 };

 /**
@@ -2041,6 +2042,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
        .has_reg_write_buffering = true,
        .has_slcg_support = false,
        .has_hs_mode_support = false,
+       .has_multi_master_support = false,
 };

 static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -2059,6 +2061,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
        .has_reg_write_buffering = true,
        .has_slcg_support = false,
        .has_hs_mode_support = false,
+       .has_multi_master_support = false,
 };

 static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -2077,6 +2080,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
        .has_reg_write_buffering = true,
        .has_slcg_support = false,
        .has_hs_mode_support = false,
+       .has_multi_master_support = false,
 };

 static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -2095,6 +2099,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
        .has_reg_write_buffering = true,
        .has_slcg_support = false,
        .has_hs_mode_support = false,
+       .has_multi_master_support = false,
 };

 static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -2113,6 +2118,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
        .has_reg_write_buffering = true,
        .has_slcg_support = false,
        .has_hs_mode_support = false,
+       .has_multi_master_support = false,
 };

 static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
@@ -2131,6 +2137,7 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
        .has_reg_write_buffering = false,
        .has_slcg_support = true,
        .has_hs_mode_support = false,
+       .has_multi_master_support = false,
 };

 /* Match table for of_platform binding */
@@ -2235,6 +2242,13 @@ static int tegra_i2c_probe(struct platform_device *pdev)
                dev_info(i2c_dev->dev, "HS mode not supported\n");
                i2c_dev->bus_clk_rate = 100000; /* default clock rate */
        }
+
+       if (i2c_dev->is_multimaster_mode &&
+                       !i2c_dev->hw->has_multi_master_support) {
+               dev_info(i2c_dev->dev, "multi-master mode not supported\n");
+               i2c_dev->is_multimaster_mode = false;
+       }
+
        init_completion(&i2c_dev->msg_complete);
        init_completion(&i2c_dev->tx_dma_complete);
        init_completion(&i2c_dev->rx_dma_complete);

Would you be able to share the nature of the h/w bug wrt. the I2C multi-master mode, what the symptom is like and what problems it may cause? We use the I2C interface to communicate with smart battery, therefore safety and reliability is critical here.

@roung1129
I just looks carefully both HS and multi master mode have HW issue.