This allows to set the TWI bite rate based on a programmable clock source. The lan966x supports this feature. Signed-off-by: Horatiu Vultur <horatiu.vultur@xxxxxxxxxxxxx> --- drivers/i2c/busses/i2c-at91-core.c | 16 ++++++++++++++++ drivers/i2c/busses/i2c-at91-master.c | 23 +++++++++++++++++++++-- drivers/i2c/busses/i2c-at91.h | 1 + 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c index 2df9df585131..d98b437e5775 100644 --- a/drivers/i2c/busses/i2c-at91-core.c +++ b/drivers/i2c/busses/i2c-at91-core.c @@ -146,6 +146,19 @@ static struct at91_twi_pdata sam9x60_config = { .has_clear_cmd = true, }; +static struct at91_twi_pdata lan966x_config = { + .clk_max_div = 7, + .clk_offset = 0, + .clk_brsrcclk = true, + .has_unre_flag = true, + .has_alt_cmd = true, + .has_hold_field = true, + .has_dig_filtr = true, + .has_adv_dig_filtr = true, + .has_ana_filtr = true, + .has_clear_cmd = true, +}; + static const struct of_device_id atmel_twi_dt_ids[] = { { .compatible = "atmel,at91rm9200-i2c", @@ -174,6 +187,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = { }, { .compatible = "microchip,sam9x60-i2c", .data = &sam9x60_config, + }, { + .compatible = "microchip,lan966x-i2c", + .data = &lan966x_config, }, { /* sentinel */ } diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c index b0eae94909f4..f504af30adbe 100644 --- a/drivers/i2c/busses/i2c-at91-master.c +++ b/drivers/i2c/busses/i2c-at91-master.c @@ -120,8 +120,27 @@ static void at91_calc_twi_clock(struct at91_twi_dev *dev) } } - dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv - | AT91_TWI_CWGR_HOLD(hold); + if (pdata->clk_brsrcclk) { + u8 chdiv, cldiv, gck_pr; + + gck_pr = 1000000000 / clk_get_rate(dev->clk); + + /* thigh = bus_freq_hz in ns * 0.4 + * tlow = bus_freq_hz in ns * 0.6 + * chdiv = (thigh / GCK_PR)/2 ^ CKDIV + * cldiv = (tlow / GCK_PR)/2 ^ CKDIV + * where ckdiv = 0; + */ + cldiv = (1000000000 / t->bus_freq_hz * 6 / 10) / gck_pr; + chdiv = (1000000000 / t->bus_freq_hz * 4 / 10) / gck_pr; + + dev->twi_cwgr_reg = (chdiv << 8) | cldiv + | AT91_TWI_CWGR_HOLD(hold) + | pdata->clk_brsrcclk << 20; + } else { + dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv + | AT91_TWI_CWGR_HOLD(hold); + } dev->filter_width = filter_width; diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h index 942e9c3973bb..f7328fbe8eb8 100644 --- a/drivers/i2c/busses/i2c-at91.h +++ b/drivers/i2c/busses/i2c-at91.h @@ -115,6 +115,7 @@ struct at91_twi_pdata { unsigned clk_max_div; unsigned clk_offset; + bool clk_brsrcclk; bool has_unre_flag; bool has_alt_cmd; bool has_hold_field; -- 2.33.0