diff options
author | Chris Brandt <chris.brandt@renesas.com> | 2017-10-27 11:37:56 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2017-10-27 15:39:29 -0400 |
commit | d982d66514192cdbe74eababa63d0a69be4b0ce1 (patch) | |
tree | bcc1f1d661623d1bee887df04ca3d19ce240fe7c | |
parent | 9b09342f5cfa5b4b3447de17de284111bfdeab26 (diff) |
i2c: riic: remove clock and frequency restrictions
Remove the restriction that the parent clock has to be a specific frequency
and also allow any speed to be supported.
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r-- | drivers/i2c/busses/i2c-riic.c | 115 |
1 files changed, 81 insertions, 34 deletions
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index c811af4c8d81..95c2f1ce3cad 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c | |||
@@ -84,12 +84,7 @@ | |||
84 | 84 | ||
85 | #define ICSR2_NACKF 0x10 | 85 | #define ICSR2_NACKF 0x10 |
86 | 86 | ||
87 | /* ICBRx (@ PCLK 33MHz) */ | ||
88 | #define ICBR_RESERVED 0xe0 /* Should be 1 on writes */ | 87 | #define ICBR_RESERVED 0xe0 /* Should be 1 on writes */ |
89 | #define ICBRL_SP100K (19 | ICBR_RESERVED) | ||
90 | #define ICBRH_SP100K (16 | ICBR_RESERVED) | ||
91 | #define ICBRL_SP400K (21 | ICBR_RESERVED) | ||
92 | #define ICBRH_SP400K (9 | ICBR_RESERVED) | ||
93 | 88 | ||
94 | #define RIIC_INIT_MSG -1 | 89 | #define RIIC_INIT_MSG -1 |
95 | 90 | ||
@@ -288,48 +283,99 @@ static const struct i2c_algorithm riic_algo = { | |||
288 | .functionality = riic_func, | 283 | .functionality = riic_func, |
289 | }; | 284 | }; |
290 | 285 | ||
291 | static int riic_init_hw(struct riic_dev *riic, u32 spd) | 286 | static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t) |
292 | { | 287 | { |
293 | int ret; | 288 | int ret; |
294 | unsigned long rate; | 289 | unsigned long rate; |
290 | int total_ticks, cks, brl, brh; | ||
295 | 291 | ||
296 | ret = clk_prepare_enable(riic->clk); | 292 | ret = clk_prepare_enable(riic->clk); |
297 | if (ret) | 293 | if (ret) |
298 | return ret; | 294 | return ret; |
299 | 295 | ||
296 | if (t->bus_freq_hz > 400000) { | ||
297 | dev_err(&riic->adapter.dev, | ||
298 | "unsupported bus speed (%dHz). 400000 max\n", | ||
299 | t->bus_freq_hz); | ||
300 | clk_disable_unprepare(riic->clk); | ||
301 | return -EINVAL; | ||
302 | } | ||
303 | |||
304 | rate = clk_get_rate(riic->clk); | ||
305 | |||
300 | /* | 306 | /* |
301 | * TODO: Implement formula to calculate the timing values depending on | 307 | * Assume the default register settings: |
302 | * variable parent clock rate and arbitrary bus speed | 308 | * FER.SCLE = 1 (SCL sync circuit enabled, adds 2 or 3 cycles) |
309 | * FER.NFE = 1 (noise circuit enabled) | ||
310 | * MR3.NF = 0 (1 cycle of noise filtered out) | ||
311 | * | ||
312 | * Freq (CKS=000) = (I2CCLK + tr + tf)/ (BRH + 3 + 1) + (BRL + 3 + 1) | ||
313 | * Freq (CKS!=000) = (I2CCLK + tr + tf)/ (BRH + 2 + 1) + (BRL + 2 + 1) | ||
303 | */ | 314 | */ |
304 | rate = clk_get_rate(riic->clk); | 315 | |
305 | if (rate != 33325000) { | 316 | /* |
306 | dev_err(&riic->adapter.dev, | 317 | * Determine reference clock rate. We must be able to get the desired |
307 | "invalid parent clk (%lu). Must be 33325000Hz\n", rate); | 318 | * frequency with only 62 clock ticks max (31 high, 31 low). |
319 | * Aim for a duty of 60% LOW, 40% HIGH. | ||
320 | */ | ||
321 | total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz); | ||
322 | |||
323 | for (cks = 0; cks < 7; cks++) { | ||
324 | /* | ||
325 | * 60% low time must be less than BRL + 2 + 1 | ||
326 | * BRL max register value is 0x1F. | ||
327 | */ | ||
328 | brl = ((total_ticks * 6) / 10); | ||
329 | if (brl <= (0x1F + 3)) | ||
330 | break; | ||
331 | |||
332 | total_ticks /= 2; | ||
333 | rate /= 2; | ||
334 | } | ||
335 | |||
336 | if (brl > (0x1F + 3)) { | ||
337 | dev_err(&riic->adapter.dev, "invalid speed (%lu). Too slow.\n", | ||
338 | (unsigned long)t->bus_freq_hz); | ||
308 | clk_disable_unprepare(riic->clk); | 339 | clk_disable_unprepare(riic->clk); |
309 | return -EINVAL; | 340 | return -EINVAL; |
310 | } | 341 | } |
311 | 342 | ||
343 | brh = total_ticks - brl; | ||
344 | |||
345 | /* Remove automatic clock ticks for sync circuit and NF */ | ||
346 | if (cks == 0) { | ||
347 | brl -= 4; | ||
348 | brh -= 4; | ||
349 | } else { | ||
350 | brl -= 3; | ||
351 | brh -= 3; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * Remove clock ticks for rise and fall times. Convert ns to clock | ||
356 | * ticks. | ||
357 | */ | ||
358 | brl -= t->scl_fall_ns / (1000000000 / rate); | ||
359 | brh -= t->scl_rise_ns / (1000000000 / rate); | ||
360 | |||
361 | /* Adjust for min register values for when SCLE=1 and NFE=1 */ | ||
362 | if (brl < 1) | ||
363 | brl = 1; | ||
364 | if (brh < 1) | ||
365 | brh = 1; | ||
366 | |||
367 | pr_debug("i2c-riic: freq=%lu, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n", | ||
368 | rate / total_ticks, ((brl + 3) * 100) / (brl + brh + 6), | ||
369 | t->scl_fall_ns / (1000000000 / rate), | ||
370 | t->scl_rise_ns / (1000000000 / rate), cks, brl, brh); | ||
371 | |||
312 | /* Changing the order of accessing IICRST and ICE may break things! */ | 372 | /* Changing the order of accessing IICRST and ICE may break things! */ |
313 | writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1); | 373 | writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1); |
314 | riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1); | 374 | riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1); |
315 | 375 | ||
316 | switch (spd) { | 376 | writeb(ICMR1_CKS(cks), riic->base + RIIC_ICMR1); |
317 | case 100000: | 377 | writeb(brh | ICBR_RESERVED, riic->base + RIIC_ICBRH); |
318 | writeb(ICMR1_CKS(3), riic->base + RIIC_ICMR1); | 378 | writeb(brl | ICBR_RESERVED, riic->base + RIIC_ICBRL); |
319 | writeb(ICBRH_SP100K, riic->base + RIIC_ICBRH); | ||
320 | writeb(ICBRL_SP100K, riic->base + RIIC_ICBRL); | ||
321 | break; | ||
322 | case 400000: | ||
323 | writeb(ICMR1_CKS(1), riic->base + RIIC_ICMR1); | ||
324 | writeb(ICBRH_SP400K, riic->base + RIIC_ICBRH); | ||
325 | writeb(ICBRL_SP400K, riic->base + RIIC_ICBRL); | ||
326 | break; | ||
327 | default: | ||
328 | dev_err(&riic->adapter.dev, | ||
329 | "unsupported bus speed (%dHz). Use 100000 or 400000\n", spd); | ||
330 | clk_disable_unprepare(riic->clk); | ||
331 | return -EINVAL; | ||
332 | } | ||
333 | 379 | ||
334 | writeb(0, riic->base + RIIC_ICSER); | 380 | writeb(0, riic->base + RIIC_ICSER); |
335 | writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3); | 381 | writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3); |
@@ -351,11 +397,10 @@ static struct riic_irq_desc riic_irqs[] = { | |||
351 | 397 | ||
352 | static int riic_i2c_probe(struct platform_device *pdev) | 398 | static int riic_i2c_probe(struct platform_device *pdev) |
353 | { | 399 | { |
354 | struct device_node *np = pdev->dev.of_node; | ||
355 | struct riic_dev *riic; | 400 | struct riic_dev *riic; |
356 | struct i2c_adapter *adap; | 401 | struct i2c_adapter *adap; |
357 | struct resource *res; | 402 | struct resource *res; |
358 | u32 bus_rate = 0; | 403 | struct i2c_timings i2c_t; |
359 | int i, ret; | 404 | int i, ret; |
360 | 405 | ||
361 | riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL); | 406 | riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL); |
@@ -396,8 +441,9 @@ static int riic_i2c_probe(struct platform_device *pdev) | |||
396 | 441 | ||
397 | init_completion(&riic->msg_done); | 442 | init_completion(&riic->msg_done); |
398 | 443 | ||
399 | of_property_read_u32(np, "clock-frequency", &bus_rate); | 444 | i2c_parse_fw_timings(&pdev->dev, &i2c_t, true); |
400 | ret = riic_init_hw(riic, bus_rate); | 445 | |
446 | ret = riic_init_hw(riic, &i2c_t); | ||
401 | if (ret) | 447 | if (ret) |
402 | return ret; | 448 | return ret; |
403 | 449 | ||
@@ -408,7 +454,8 @@ static int riic_i2c_probe(struct platform_device *pdev) | |||
408 | 454 | ||
409 | platform_set_drvdata(pdev, riic); | 455 | platform_set_drvdata(pdev, riic); |
410 | 456 | ||
411 | dev_info(&pdev->dev, "registered with %dHz bus speed\n", bus_rate); | 457 | dev_info(&pdev->dev, "registered with %dHz bus speed\n", |
458 | i2c_t.bus_freq_hz); | ||
412 | return 0; | 459 | return 0; |
413 | } | 460 | } |
414 | 461 | ||