Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

I2C: JZ4780: Add support for the X1000.

Add support for probing i2c driver on the X1000 Soc from Ingenic.
call the corresponding fifo parameter according to the device
model obtained from the devicetree.

Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Acked-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

authored by

周琰杰 (Zhou Yanjie) and committed by
Wolfram Sang
21575a7a f4b5af78

+116 -40
+116 -40
drivers/i2c/busses/i2c-jz4780.c
··· 4 4 * 5 5 * Copyright (C) 2006 - 2009 Ingenic Semiconductor Inc. 6 6 * Copyright (C) 2015 Imagination Technologies 7 + * Copyright (C) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com> 7 8 */ 8 9 9 10 #include <linux/bitops.h> ··· 18 17 #include <linux/io.h> 19 18 #include <linux/kernel.h> 20 19 #include <linux/module.h> 20 + #include <linux/of_device.h> 21 21 #include <linux/platform_device.h> 22 22 #include <linux/sched.h> 23 23 #include <linux/slab.h> ··· 57 55 #define JZ4780_I2C_ACKGC 0x98 58 56 #define JZ4780_I2C_ENSTA 0x9C 59 57 #define JZ4780_I2C_SDAHD 0xD0 58 + #define X1000_I2C_SDAHD 0x7C 60 59 61 60 #define JZ4780_I2C_CTRL_STPHLD BIT(7) 62 61 #define JZ4780_I2C_CTRL_SLVDIS BIT(6) ··· 75 72 #define JZ4780_I2C_STA_TFE BIT(2) 76 73 #define JZ4780_I2C_STA_TFNF BIT(1) 77 74 #define JZ4780_I2C_STA_ACT BIT(0) 75 + 76 + #define X1000_I2C_DC_STOP BIT(9) 78 77 79 78 static const char * const jz4780_i2c_abrt_src[] = { 80 79 "ABRT_7B_ADDR_NOACK", ··· 135 130 #define JZ4780_I2CFLCNT_ADJUST(n) (((n) - 1) < 8 ? 8 : ((n) - 1)) 136 131 137 132 #define JZ4780_I2C_FIFO_LEN 16 138 - #define TX_LEVEL 3 139 - #define RX_LEVEL (JZ4780_I2C_FIFO_LEN - TX_LEVEL - 1) 133 + 134 + #define X1000_I2C_FIFO_LEN 64 140 135 141 136 #define JZ4780_I2C_TIMEOUT 300 142 137 143 138 #define BUFSIZE 200 139 + 140 + enum ingenic_i2c_version { 141 + ID_JZ4780, 142 + ID_X1000, 143 + }; 144 + 145 + /* ingenic_i2c_config: SoC specific config data. */ 146 + struct ingenic_i2c_config { 147 + enum ingenic_i2c_version version; 148 + 149 + int fifosize; 150 + int tx_level; 151 + int rx_level; 152 + }; 144 153 145 154 struct jz4780_i2c { 146 155 void __iomem *iomem; 147 156 int irq; 148 157 struct clk *clk; 149 158 struct i2c_adapter adap; 159 + const struct ingenic_i2c_config *cdata; 150 160 151 161 /* lock to protect rbuf and wbuf between xfer_rd/wr and irq handler */ 152 162 spinlock_t lock; ··· 360 340 361 341 if (hold_time >= 0) { 362 342 /*i2c hold time enable */ 363 - hold_time |= JZ4780_I2C_SDAHD_HDENB; 364 - jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, hold_time); 343 + if (i2c->cdata->version >= ID_X1000) { 344 + jz4780_i2c_writew(i2c, X1000_I2C_SDAHD, hold_time); 345 + } else { 346 + hold_time |= JZ4780_I2C_SDAHD_HDENB; 347 + jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, hold_time); 348 + } 365 349 } else { 366 350 /* disable hold time */ 367 - jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, 0); 351 + if (i2c->cdata->version >= ID_X1000) 352 + jz4780_i2c_writew(i2c, X1000_I2C_SDAHD, 0); 353 + else 354 + jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, 0); 368 355 } 369 356 370 357 return 0; ··· 386 359 spin_lock_irqsave(&i2c->lock, flags); 387 360 388 361 /* can send stop now if need */ 389 - tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 390 - tmp &= ~JZ4780_I2C_CTRL_STPHLD; 391 - jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 362 + if (i2c->cdata->version < ID_X1000) { 363 + tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 364 + tmp &= ~JZ4780_I2C_CTRL_STPHLD; 365 + jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 366 + } 392 367 393 368 /* disable all interrupts first */ 394 369 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0); ··· 428 399 return jz4780_i2c_enable(i2c); 429 400 } 430 401 431 - static void jz4780_i2c_send_rcmd(struct jz4780_i2c *i2c, int cmd_count) 402 + static void jz4780_i2c_send_rcmd(struct jz4780_i2c *i2c, 403 + int cmd_count, 404 + int cmd_left) 432 405 { 433 406 int i; 434 407 435 - for (i = 0; i < cmd_count; i++) 408 + for (i = 0; i < cmd_count - 1; i++) 409 + jz4780_i2c_writew(i2c, JZ4780_I2C_DC, JZ4780_I2C_DC_READ); 410 + 411 + if ((cmd_left == 0) && (i2c->cdata->version >= ID_X1000)) 412 + jz4780_i2c_writew(i2c, JZ4780_I2C_DC, 413 + JZ4780_I2C_DC_READ | X1000_I2C_DC_STOP); 414 + else 436 415 jz4780_i2c_writew(i2c, JZ4780_I2C_DC, JZ4780_I2C_DC_READ); 437 416 } 438 417 ··· 495 458 496 459 rd_left = i2c->rd_total_len - i2c->rd_data_xfered; 497 460 498 - if (rd_left <= JZ4780_I2C_FIFO_LEN) 461 + if (rd_left <= i2c->cdata->fifosize) 499 462 jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, rd_left - 1); 500 463 } 501 464 502 465 if (intst & JZ4780_I2C_INTST_TXEMP) { 503 466 if (i2c->is_write == 0) { 504 467 int cmd_left = i2c->rd_total_len - i2c->rd_cmd_xfered; 505 - int max_send = (JZ4780_I2C_FIFO_LEN - 1) 468 + int max_send = (i2c->cdata->fifosize - 1) 506 469 - (i2c->rd_cmd_xfered 507 470 - i2c->rd_data_xfered); 508 471 int cmd_to_send = min(cmd_left, max_send); 509 472 510 473 if (i2c->rd_cmd_xfered != 0) 511 474 cmd_to_send = min(cmd_to_send, 512 - JZ4780_I2C_FIFO_LEN 513 - - TX_LEVEL - 1); 475 + i2c->cdata->fifosize 476 + - i2c->cdata->tx_level - 1); 514 477 515 478 if (cmd_to_send) { 516 - jz4780_i2c_send_rcmd(i2c, cmd_to_send); 517 479 i2c->rd_cmd_xfered += cmd_to_send; 480 + cmd_left = i2c->rd_total_len - 481 + i2c->rd_cmd_xfered; 482 + jz4780_i2c_send_rcmd(i2c, 483 + cmd_to_send, cmd_left); 484 + 518 485 } 519 486 520 - cmd_left = i2c->rd_total_len - i2c->rd_cmd_xfered; 521 487 if (cmd_left == 0) { 522 488 intmsk = jz4780_i2c_readw(i2c, JZ4780_I2C_INTM); 523 489 intmsk &= ~JZ4780_I2C_INTM_MTXEMP; 524 490 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, intmsk); 525 491 526 - tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 527 - tmp &= ~JZ4780_I2C_CTRL_STPHLD; 528 - jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 492 + if (i2c->cdata->version < ID_X1000) { 493 + tmp = jz4780_i2c_readw(i2c, 494 + JZ4780_I2C_CTRL); 495 + tmp &= ~JZ4780_I2C_CTRL_STPHLD; 496 + jz4780_i2c_writew(i2c, 497 + JZ4780_I2C_CTRL, tmp); 498 + } 529 499 } 530 500 } else { 531 501 unsigned short data; ··· 541 497 i2c_sta = jz4780_i2c_readw(i2c, JZ4780_I2C_STA); 542 498 543 499 while ((i2c_sta & JZ4780_I2C_STA_TFNF) && 544 - (i2c->wt_len > 0)) { 500 + (i2c->wt_len > 0)) { 545 501 i2c_sta = jz4780_i2c_readw(i2c, JZ4780_I2C_STA); 546 502 data = *i2c->wbuf; 547 503 data &= ~JZ4780_I2C_DC_READ; 548 - jz4780_i2c_writew(i2c, JZ4780_I2C_DC, 549 - data); 504 + if ((!i2c->stop_hold) && (i2c->cdata->version >= 505 + ID_X1000)) 506 + data |= X1000_I2C_DC_STOP; 507 + jz4780_i2c_writew(i2c, JZ4780_I2C_DC, data); 550 508 i2c->wbuf++; 551 509 i2c->wt_len--; 552 510 } 553 511 554 512 if (i2c->wt_len == 0) { 555 - if (!i2c->stop_hold) { 513 + if ((!i2c->stop_hold) && (i2c->cdata->version < 514 + ID_X1000)) { 556 515 tmp = jz4780_i2c_readw(i2c, 557 - JZ4780_I2C_CTRL); 516 + JZ4780_I2C_CTRL); 558 517 tmp &= ~JZ4780_I2C_CTRL_STPHLD; 559 - jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, 560 - tmp); 518 + jz4780_i2c_writew(i2c, 519 + JZ4780_I2C_CTRL, tmp); 561 520 } 562 521 563 522 jz4780_i2c_trans_done(i2c); ··· 614 567 i2c->rd_data_xfered = 0; 615 568 i2c->rd_cmd_xfered = 0; 616 569 617 - if (len <= JZ4780_I2C_FIFO_LEN) 570 + if (len <= i2c->cdata->fifosize) 618 571 jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, len - 1); 619 572 else 620 - jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, RX_LEVEL); 573 + jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, i2c->cdata->rx_level); 621 574 622 - jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, TX_LEVEL); 575 + jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, i2c->cdata->tx_level); 623 576 624 577 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 625 578 JZ4780_I2C_INTM_MRXFL | JZ4780_I2C_INTM_MTXEMP 626 579 | JZ4780_I2C_INTM_MTXABT | JZ4780_I2C_INTM_MRXOF); 627 580 628 - tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 629 - tmp |= JZ4780_I2C_CTRL_STPHLD; 630 - jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 581 + if (i2c->cdata->version < ID_X1000) { 582 + tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 583 + tmp |= JZ4780_I2C_CTRL_STPHLD; 584 + jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 585 + } 631 586 632 587 spin_unlock_irqrestore(&i2c->lock, flags); 633 588 ··· 675 626 i2c->wbuf = buf; 676 627 i2c->wt_len = len; 677 628 678 - jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, TX_LEVEL); 629 + jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, i2c->cdata->tx_level); 679 630 680 631 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, JZ4780_I2C_INTM_MTXEMP 681 632 | JZ4780_I2C_INTM_MTXABT); 682 633 683 - tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 684 - tmp |= JZ4780_I2C_CTRL_STPHLD; 685 - jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 634 + if (i2c->cdata->version < ID_X1000) { 635 + tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 636 + tmp |= JZ4780_I2C_CTRL_STPHLD; 637 + jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 638 + } 686 639 687 640 spin_unlock_irqrestore(&i2c->lock, flags); 688 641 ··· 767 716 .functionality = jz4780_i2c_functionality, 768 717 }; 769 718 719 + static const struct ingenic_i2c_config jz4780_i2c_config = { 720 + .version = ID_JZ4780, 721 + 722 + .fifosize = JZ4780_I2C_FIFO_LEN, 723 + .tx_level = JZ4780_I2C_FIFO_LEN / 2, 724 + .rx_level = JZ4780_I2C_FIFO_LEN / 2 - 1, 725 + }; 726 + 727 + static const struct ingenic_i2c_config x1000_i2c_config = { 728 + .version = ID_X1000, 729 + 730 + .fifosize = X1000_I2C_FIFO_LEN, 731 + .tx_level = X1000_I2C_FIFO_LEN / 2, 732 + .rx_level = X1000_I2C_FIFO_LEN / 2 - 1, 733 + }; 734 + 770 735 static const struct of_device_id jz4780_i2c_of_matches[] = { 771 - { .compatible = "ingenic,jz4780-i2c", }, 736 + { .compatible = "ingenic,jz4780-i2c", .data = &jz4780_i2c_config }, 737 + { .compatible = "ingenic,x1000-i2c", .data = &x1000_i2c_config }, 772 738 { /* sentinel */ } 773 739 }; 774 740 MODULE_DEVICE_TABLE(of, jz4780_i2c_of_matches); ··· 801 733 i2c = devm_kzalloc(&pdev->dev, sizeof(struct jz4780_i2c), GFP_KERNEL); 802 734 if (!i2c) 803 735 return -ENOMEM; 736 + 737 + i2c->cdata = device_get_match_data(&pdev->dev); 738 + if (!i2c->cdata) { 739 + dev_err(&pdev->dev, "Error: No device match found\n"); 740 + return -ENODEV; 741 + } 804 742 805 743 i2c->adap.owner = THIS_MODULE; 806 744 i2c->adap.algo = &jz4780_i2c_algorithm; ··· 851 777 852 778 dev_info(&pdev->dev, "Bus frequency is %d KHz\n", i2c->speed); 853 779 854 - tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 855 - tmp &= ~JZ4780_I2C_CTRL_STPHLD; 856 - jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 780 + if (i2c->cdata->version < ID_X1000) { 781 + tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL); 782 + tmp &= ~JZ4780_I2C_CTRL_STPHLD; 783 + jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp); 784 + } 857 785 858 786 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0x0); 859 787