Skip to content

Commit

Permalink
i2c: designware: Enable high speed mode
Browse files Browse the repository at this point in the history
This patch enabled high speed mode. High speed mode can be turn on by
setting the clk_freq to 3400000. High speed HCNT and LCNT are needed
as there is no default value provided.

Signed-off-by: Weifeng Voon <weifeng.voon@intel.com>
Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
  • Loading branch information
Weifeng Voon authored and Wolfram Sang committed Aug 25, 2016
1 parent 548e669 commit b6e6714
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
26 changes: 25 additions & 1 deletion drivers/i2c/busses/i2c-designware-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
#define DW_IC_SS_SCL_LCNT 0x18
#define DW_IC_FS_SCL_HCNT 0x1c
#define DW_IC_FS_SCL_LCNT 0x20
#define DW_IC_HS_SCL_HCNT 0x24
#define DW_IC_HS_SCL_LCNT 0x28
#define DW_IC_INTR_STAT 0x2c
#define DW_IC_INTR_MASK 0x30
#define DW_IC_RAW_INTR_STAT 0x34
Expand Down Expand Up @@ -95,6 +97,9 @@

#define DW_IC_TAR_10BITADDR_MASTER BIT(12)

#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3))
#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2)

/*
* status codes
*/
Expand Down Expand Up @@ -293,7 +298,7 @@ static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
int i2c_dw_init(struct dw_i2c_dev *dev)
{
u32 hcnt, lcnt;
u32 reg;
u32 reg, comp_param1;
u32 sda_falling_time, scl_falling_time;
int ret;

Expand All @@ -320,6 +325,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
return -ENODEV;
}

comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);

/* Disable the adapter */
__i2c_dw_enable(dev, false);

Expand Down Expand Up @@ -369,6 +376,23 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);

if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
DW_IC_CON_SPEED_HIGH) {
if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
!= DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) {
dev_err(dev->dev, "High Speed not supported!\n");
dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
dev->master_cfg |= DW_IC_CON_SPEED_FAST;
} else if (dev->hs_hcnt && dev->hs_lcnt) {
hcnt = dev->hs_hcnt;
lcnt = dev->hs_lcnt;
dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
hcnt, lcnt);
}
}

/* Configure SDA Hold Time if required */
if (dev->sda_hold_time) {
reg = dw_readl(dev, DW_IC_COMP_VERSION);
Expand Down
1 change: 1 addition & 0 deletions drivers/i2c/busses/i2c-designware-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#define DW_IC_CON_MASTER 0x1
#define DW_IC_CON_SPEED_STD 0x2
#define DW_IC_CON_SPEED_FAST 0x4
#define DW_IC_CON_SPEED_HIGH 0x6
#define DW_IC_CON_SPEED_MASK 0x6
#define DW_IC_CON_10BITADDR_MASTER 0x10
#define DW_IC_CON_RESTART_EN 0x20
Expand Down
16 changes: 11 additions & 5 deletions drivers/i2c/busses/i2c-designware-platdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,12 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)

/*
* Only standard mode at 100kHz, fast mode at 400kHz,
* and fast mode plus at 1MHz are supported.
* fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
*/
if (dev->clk_freq != 100000 && dev->clk_freq != 400000
&& dev->clk_freq != 1000000) {
&& dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
dev_err(&pdev->dev,
"Only 100kHz, 400kHz and 1MHz are supported");
"Only 100kHz, 400kHz, 1MHz and 3.4MHz supported");
return -EINVAL;
}

Expand All @@ -221,10 +221,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
DW_IC_CON_RESTART_EN;

if (dev->clk_freq == 100000)
switch (dev->clk_freq) {
case 100000:
dev->master_cfg |= DW_IC_CON_SPEED_STD;
else
break;
case 3400000:
dev->master_cfg |= DW_IC_CON_SPEED_HIGH;
break;
default:
dev->master_cfg |= DW_IC_CON_SPEED_FAST;
}

dev->clk = devm_clk_get(&pdev->dev, NULL);
if (!i2c_dw_plat_prepare_clk(dev, true)) {
Expand Down

0 comments on commit b6e6714

Please sign in to comment.