diff options
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c | 45 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.h | 1 |
2 files changed, 35 insertions, 11 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 2bf4f60a9ac2..e1f1b7519771 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c | |||
@@ -460,27 +460,29 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) | |||
460 | static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) | 460 | static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) |
461 | { | 461 | { |
462 | struct i2c_msg *msgs = dev->msgs; | 462 | struct i2c_msg *msgs = dev->msgs; |
463 | u32 ic_con, ic_tar = 0; | 463 | u32 ic_tar = 0; |
464 | 464 | ||
465 | /* Disable the adapter */ | 465 | /* Disable the adapter */ |
466 | __i2c_dw_enable_and_wait(dev, false); | 466 | __i2c_dw_enable_and_wait(dev, false); |
467 | 467 | ||
468 | /* if the slave address is ten bit address, enable 10BITADDR */ | 468 | /* if the slave address is ten bit address, enable 10BITADDR */ |
469 | ic_con = dw_readl(dev, DW_IC_CON); | 469 | if (dev->dynamic_tar_update_enabled) { |
470 | if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { | ||
471 | ic_con |= DW_IC_CON_10BITADDR_MASTER; | ||
472 | /* | 470 | /* |
473 | * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing | 471 | * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing |
474 | * mode has to be enabled via bit 12 of IC_TAR register. | 472 | * mode has to be enabled via bit 12 of IC_TAR register, |
475 | * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be | 473 | * otherwise bit 4 of IC_CON is used. |
476 | * detected from registers. | ||
477 | */ | 474 | */ |
478 | ic_tar = DW_IC_TAR_10BITADDR_MASTER; | 475 | if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) |
476 | ic_tar = DW_IC_TAR_10BITADDR_MASTER; | ||
479 | } else { | 477 | } else { |
480 | ic_con &= ~DW_IC_CON_10BITADDR_MASTER; | 478 | u32 ic_con = dw_readl(dev, DW_IC_CON); |
481 | } | ||
482 | 479 | ||
483 | dw_writel(dev, ic_con, DW_IC_CON); | 480 | if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) |
481 | ic_con |= DW_IC_CON_10BITADDR_MASTER; | ||
482 | else | ||
483 | ic_con &= ~DW_IC_CON_10BITADDR_MASTER; | ||
484 | dw_writel(dev, ic_con, DW_IC_CON); | ||
485 | } | ||
484 | 486 | ||
485 | /* | 487 | /* |
486 | * Set the slave (target) address and enable 10-bit addressing mode | 488 | * Set the slave (target) address and enable 10-bit addressing mode |
@@ -901,6 +903,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) | |||
901 | { | 903 | { |
902 | struct i2c_adapter *adap = &dev->adapter; | 904 | struct i2c_adapter *adap = &dev->adapter; |
903 | int r; | 905 | int r; |
906 | u32 reg; | ||
904 | 907 | ||
905 | init_completion(&dev->cmd_complete); | 908 | init_completion(&dev->cmd_complete); |
906 | 909 | ||
@@ -908,6 +911,26 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) | |||
908 | if (r) | 911 | if (r) |
909 | return r; | 912 | return r; |
910 | 913 | ||
914 | r = i2c_dw_acquire_lock(dev); | ||
915 | if (r) | ||
916 | return r; | ||
917 | |||
918 | /* | ||
919 | * Test if dynamic TAR update is enabled in this controller by writing | ||
920 | * to IC_10BITADDR_MASTER field in IC_CON: when it is enabled this | ||
921 | * field is read-only so it should not succeed | ||
922 | */ | ||
923 | reg = dw_readl(dev, DW_IC_CON); | ||
924 | dw_writel(dev, reg ^ DW_IC_CON_10BITADDR_MASTER, DW_IC_CON); | ||
925 | |||
926 | if ((dw_readl(dev, DW_IC_CON) & DW_IC_CON_10BITADDR_MASTER) == | ||
927 | (reg & DW_IC_CON_10BITADDR_MASTER)) { | ||
928 | dev->dynamic_tar_update_enabled = true; | ||
929 | dev_dbg(dev->dev, "Dynamic TAR update enabled"); | ||
930 | } | ||
931 | |||
932 | i2c_dw_release_lock(dev); | ||
933 | |||
911 | snprintf(adap->name, sizeof(adap->name), | 934 | snprintf(adap->name, sizeof(adap->name), |
912 | "Synopsys DesignWare I2C adapter"); | 935 | "Synopsys DesignWare I2C adapter"); |
913 | adap->retries = 3; | 936 | adap->retries = 3; |
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 22bfbe147870..0d44d2ae7d4c 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h | |||
@@ -117,6 +117,7 @@ struct dw_i2c_dev { | |||
117 | int (*acquire_lock)(struct dw_i2c_dev *dev); | 117 | int (*acquire_lock)(struct dw_i2c_dev *dev); |
118 | void (*release_lock)(struct dw_i2c_dev *dev); | 118 | void (*release_lock)(struct dw_i2c_dev *dev); |
119 | bool pm_runtime_disabled; | 119 | bool pm_runtime_disabled; |
120 | bool dynamic_tar_update_enabled; | ||
120 | }; | 121 | }; |
121 | 122 | ||
122 | #define ACCESS_SWAP 0x00000001 | 123 | #define ACCESS_SWAP 0x00000001 |