Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 14 additions & 42 deletions arch/arm/boot/dts/rp1.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,8 @@
compatible = "snps,designware-i2c";
interrupts = <RP1_INT_I2C0 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rp1_clocks RP1_CLK_SYS>;
snps,ss_hcnt = <978>;
snps,ss_lcnt = <990>;
snps,fs_hcnt = <200>;
snps,fs_lcnt = <268>;
snps,fp_hcnt = <60>;
snps,fp_lcnt = <107>;
i2c-scl-rising-time-ns = <65>;
i2c-scl-falling-time-ns = <100>;
status = "disabled";
};

Expand All @@ -319,12 +315,8 @@
compatible = "snps,designware-i2c";
interrupts = <RP1_INT_I2C1 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rp1_clocks RP1_CLK_SYS>;
snps,ss_hcnt = <978>;
snps,ss_lcnt = <990>;
snps,fs_hcnt = <200>;
snps,fs_lcnt = <268>;
snps,fp_hcnt = <60>;
snps,fp_lcnt = <107>;
i2c-scl-rising-time-ns = <65>;
i2c-scl-falling-time-ns = <100>;
status = "disabled";
};

Expand All @@ -333,12 +325,8 @@
compatible = "snps,designware-i2c";
interrupts = <RP1_INT_I2C2 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rp1_clocks RP1_CLK_SYS>;
snps,ss_hcnt = <978>;
snps,ss_lcnt = <990>;
snps,fs_hcnt = <200>;
snps,fs_lcnt = <268>;
snps,fp_hcnt = <60>;
snps,fp_lcnt = <107>;
i2c-scl-rising-time-ns = <65>;
i2c-scl-falling-time-ns = <100>;
status = "disabled";
};

Expand All @@ -347,12 +335,8 @@
compatible = "snps,designware-i2c";
interrupts = <RP1_INT_I2C3 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rp1_clocks RP1_CLK_SYS>;
snps,ss_hcnt = <978>;
snps,ss_lcnt = <990>;
snps,fs_hcnt = <200>;
snps,fs_lcnt = <268>;
snps,fp_hcnt = <60>;
snps,fp_lcnt = <107>;
i2c-scl-rising-time-ns = <65>;
i2c-scl-falling-time-ns = <100>;
status = "disabled";
};

Expand All @@ -361,12 +345,8 @@
compatible = "snps,designware-i2c";
interrupts = <RP1_INT_I2C4 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rp1_clocks RP1_CLK_SYS>;
snps,ss_hcnt = <978>;
snps,ss_lcnt = <990>;
snps,fs_hcnt = <200>;
snps,fs_lcnt = <268>;
snps,fp_hcnt = <60>;
snps,fp_lcnt = <107>;
i2c-scl-rising-time-ns = <65>;
i2c-scl-falling-time-ns = <100>;
status = "disabled";
};

Expand All @@ -375,12 +355,8 @@
compatible = "snps,designware-i2c";
interrupts = <RP1_INT_I2C5 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rp1_clocks RP1_CLK_SYS>;
snps,ss_hcnt = <978>;
snps,ss_lcnt = <990>;
snps,fs_hcnt = <200>;
snps,fs_lcnt = <268>;
snps,fp_hcnt = <60>;
snps,fp_lcnt = <107>;
i2c-scl-rising-time-ns = <65>;
i2c-scl-falling-time-ns = <100>;
status = "disabled";
};

Expand All @@ -389,12 +365,8 @@
compatible = "snps,designware-i2c";
interrupts = <RP1_INT_I2C6 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rp1_clocks RP1_CLK_SYS>;
snps,ss_hcnt = <978>;
snps,ss_lcnt = <990>;
snps,fs_hcnt = <200>;
snps,fs_lcnt = <268>;
snps,fp_hcnt = <60>;
snps,fp_lcnt = <107>;
i2c-scl-rising-time-ns = <65>;
i2c-scl-falling-time-ns = <100>;
status = "disabled";
};

Expand Down
27 changes: 27 additions & 0 deletions drivers/i2c/busses/i2c-designware-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev)
{
u32 acpi_speed = i2c_dw_acpi_round_bus_speed(dev->dev);
struct i2c_timings *t = &dev->timings;
u32 wanted_speed;
u32 legal_speed = 0;
int i;

/*
* Find bus speed from the "clock-frequency" device property, ACPI
Expand All @@ -329,6 +332,30 @@ void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev)
t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed);
else
t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ;

wanted_speed = t->bus_freq_hz;

/* For unsupported speeds, scale down the lowest speed which is faster. */
for (i = 0; i < ARRAY_SIZE(supported_speeds); i++) {
/* supported speeds is in decreasing order */
if (wanted_speed == supported_speeds[i]) {
legal_speed = 0;
break;
}
if (wanted_speed > supported_speeds[i])
break;

legal_speed = supported_speeds[i];
}

if (legal_speed) {
/*
* Pretend this was the requested speed, but preserve the preferred
* speed so the clock counts can be scaled.
*/
t->bus_freq_hz = legal_speed;
dev->wanted_bus_speed = wanted_speed;
}
}
EXPORT_SYMBOL_GPL(i2c_dw_adjust_bus_speed);

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 @@ -287,6 +287,7 @@ struct dw_i2c_dev {
u16 fp_lcnt;
u16 hs_hcnt;
u16 hs_lcnt;
u32 wanted_bus_speed;
int (*acquire_lock)(void);
void (*release_lock)(void);
int semaphore_idx;
Expand Down
26 changes: 26 additions & 0 deletions drivers/i2c/busses/i2c-designware-master.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,30 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
regmap_write(dev->map, DW_IC_CON, dev->master_cfg);
}

static u16 clock_calc(struct dw_i2c_dev *dev, bool want_high)
{
struct i2c_timings *t = &dev->timings;
u32 wanted_speed = dev->wanted_bus_speed ?: t->bus_freq_hz;
u32 clk_khz = i2c_dw_clk_rate(dev);
u32 extra_ns = want_high ? t->scl_fall_ns : t->scl_rise_ns;
u32 extra_cycles = (u32)((u64)clk_khz * extra_ns / 1000000);
u32 period = ((u64)clk_khz * 1000 + wanted_speed - 1) / wanted_speed;
u32 cycles = (period + want_high)/2 - extra_cycles;

if (cycles > 0xffff)
cycles = 0xffff;

return (u16)cycles;
}

static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
{
u32 comp_param1;
u32 sda_falling_time, scl_falling_time;
struct i2c_timings *t = &dev->timings;
const char *fp_str = "";
u32 ic_clk;
u32 hcnt, lcnt;
int ret;

ret = i2c_dw_acquire_lock(dev);
Expand All @@ -59,6 +76,9 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
sda_falling_time = t->sda_fall_ns ?: 300; /* ns */
scl_falling_time = t->scl_fall_ns ?: 300; /* ns */

hcnt = clock_calc(dev, true);
lcnt = clock_calc(dev, false);

/* Calculate SCL timing parameters for standard mode if not set */
if (!dev->ss_hcnt || !dev->ss_lcnt) {
ic_clk = i2c_dw_clk_rate(dev);
Expand All @@ -74,6 +94,8 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
scl_falling_time,
0); /* No offset */
}
dev->ss_hcnt = hcnt;
dev->ss_lcnt = lcnt;
dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n",
dev->ss_hcnt, dev->ss_lcnt);

Expand Down Expand Up @@ -124,6 +146,8 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
scl_falling_time,
0); /* No offset */
}
dev->fs_hcnt = hcnt;
dev->fs_lcnt = lcnt;
dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n",
fp_str, dev->fs_hcnt, dev->fs_lcnt);

Expand Down Expand Up @@ -152,6 +176,8 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
scl_falling_time,
0); /* No offset */
}
dev->hs_hcnt = hcnt;
dev->hs_lcnt = lcnt;
dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n",
dev->hs_hcnt, dev->hs_lcnt);
}
Expand Down
18 changes: 0 additions & 18 deletions drivers/i2c/busses/i2c-designware-platdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,18 +132,9 @@ static int mscc_twi_set_sda_hold_time(struct dw_i2c_dev *dev)
return 0;
}

static void dw_i2c_read_of_cnt(struct device_node *np, const char *name, u16 *pval)
{
u32 val;

if (!of_property_read_u32(np, name, &val))
*pval = (u16)val;
}

static int dw_i2c_of_configure(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
struct device_node *np = pdev->dev.of_node;

switch (dev->flags & MODEL_MASK) {
case MODEL_MSCC_OCELOT:
Expand All @@ -155,15 +146,6 @@ static int dw_i2c_of_configure(struct platform_device *pdev)
break;
}

dw_i2c_read_of_cnt(np, "snps,ss_hcnt", &dev->ss_hcnt);
dw_i2c_read_of_cnt(np, "snps,ss_lcnt", &dev->ss_lcnt);
dw_i2c_read_of_cnt(np, "snps,fs_hcnt", &dev->fs_hcnt);
dw_i2c_read_of_cnt(np, "snps,fs_lcnt", &dev->fs_lcnt);
dw_i2c_read_of_cnt(np, "snps,fp_hcnt", &dev->fp_hcnt);
dw_i2c_read_of_cnt(np, "snps,fp_lcnt", &dev->fp_lcnt);
dw_i2c_read_of_cnt(np, "snps,hs_hcnt", &dev->hs_hcnt);
dw_i2c_read_of_cnt(np, "snps,hs_lcnt", &dev->hs_lcnt);

return 0;
}

Expand Down