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

i2c: designware: Implement generic polling mode code for Wangxun 10Gb NIC

I got an idea the i2c-designware should not need duplicated state
machines for the interrupt and polling modes. The IP is practically the
same and state transitions happens in response to the events that can be
observed from the DW_IC_RAW_INTR_STAT register. Either by interrupts or
by polling.

Another reasons are the interrupt mode is the most tested, has handling
for special cases as well as transmit abort handling and those are
missing from two polling mode quirks.

Patch implements a generic polling mode by using existing code for
interrupt mode. This is done by moving event handling from the
i2c_dw_isr() into a new i2c_dw_process_transfer() that will be called
both from the i2c_dw_isr() and a polling loop.

Polling loop is implemented in a new i2c_dw_wait_transfer() that is
shared between both modes. In interrupt mode it waits for the completion
object as before. In polling mode both completion object and
DW_IC_RAW_INTR_STAT are polled to determine completed transfer and state
transitions.

Loop tries to save power by sleeping "stetson guessed" range between
3 and 25 µS which falls between 10 cycles of High-speed mode 3.4 Mb/s
and Fast mode 400 kHz. With it the CPU usage was reduced under heavy
Fast mode I2C transfer without much increase in total transfer time but
otherwise no more effort has been put to optimize this.

I decided to convert the txgbe_i2c_dw_xfer_quirk() straight to generic
polling mode code in this patch. It doesn't have HW dependent quirks
like the amd_i2c_dw_xfer_quirk() does have and without users this patch
is needless.

Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Tested-by: Jiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>

authored by

Jarkko Nikula and committed by
Andi Shyti
197ecada c94612a7

+75 -102
+5
drivers/i2c/busses/i2c-designware-core.h
··· 212 212 * @msg_err: error status of the current transfer 213 213 * @status: i2c master status, one of STATUS_* 214 214 * @abort_source: copy of the TX_ABRT_SOURCE register 215 + * @sw_mask: SW mask of DW_IC_INTR_MASK used in polling mode 215 216 * @irq: interrupt number for the i2c master 216 217 * @flags: platform specific flags like type of IO accessors or model 217 218 * @adapter: i2c subsystem adapter node ··· 271 270 int msg_err; 272 271 unsigned int status; 273 272 unsigned int abort_source; 273 + unsigned int sw_mask; 274 274 int irq; 275 275 u32 flags; 276 276 struct i2c_adapter adapter; ··· 360 358 unsigned int val = dev->flags & ACCESS_POLLING ? 0 : intr_mask; 361 359 362 360 regmap_write(dev->map, DW_IC_INTR_MASK, val); 361 + dev->sw_mask = intr_mask; 363 362 } 364 363 365 364 static inline void __i2c_dw_read_intr_mask(struct dw_i2c_dev *dev, ··· 368 365 { 369 366 if (!(dev->flags & ACCESS_POLLING)) 370 367 regmap_read(dev->map, DW_IC_INTR_MASK, intr_mask); 368 + else 369 + *intr_mask = dev->sw_mask; 371 370 } 372 371 373 372 void __i2c_dw_disable(struct dw_i2c_dev *dev);
+70 -102
drivers/i2c/busses/i2c-designware-master.c
··· 354 354 return 0; 355 355 } 356 356 357 - static int i2c_dw_poll_tx_empty(struct dw_i2c_dev *dev) 358 - { 359 - u32 val; 360 - 361 - return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val, 362 - val & DW_IC_INTR_TX_EMPTY, 363 - 100, 1000); 364 - } 365 - 366 - static int i2c_dw_poll_rx_full(struct dw_i2c_dev *dev) 367 - { 368 - u32 val; 369 - 370 - return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val, 371 - val & DW_IC_INTR_RX_FULL, 372 - 100, 1000); 373 - } 374 - 375 - static int txgbe_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, 376 - int num_msgs) 377 - { 378 - struct dw_i2c_dev *dev = i2c_get_adapdata(adap); 379 - int msg_idx, buf_len, data_idx, ret; 380 - unsigned int val, stop = 0; 381 - u8 *buf; 382 - 383 - dev->msgs = msgs; 384 - dev->msgs_num = num_msgs; 385 - i2c_dw_xfer_init(dev); 386 - 387 - for (msg_idx = 0; msg_idx < num_msgs; msg_idx++) { 388 - buf = msgs[msg_idx].buf; 389 - buf_len = msgs[msg_idx].len; 390 - 391 - for (data_idx = 0; data_idx < buf_len; data_idx++) { 392 - if (msg_idx == num_msgs - 1 && data_idx == buf_len - 1) 393 - stop |= BIT(9); 394 - 395 - if (msgs[msg_idx].flags & I2C_M_RD) { 396 - regmap_write(dev->map, DW_IC_DATA_CMD, 0x100 | stop); 397 - 398 - ret = i2c_dw_poll_rx_full(dev); 399 - if (ret) 400 - return ret; 401 - 402 - regmap_read(dev->map, DW_IC_DATA_CMD, &val); 403 - buf[data_idx] = val; 404 - } else { 405 - ret = i2c_dw_poll_tx_empty(dev); 406 - if (ret) 407 - return ret; 408 - 409 - regmap_write(dev->map, DW_IC_DATA_CMD, 410 - buf[data_idx] | stop); 411 - } 412 - } 413 - } 414 - 415 - return num_msgs; 416 - } 417 - 418 357 /* 419 358 * Initiate (and continue) low level master read/write transaction. 420 359 * This function is only called from i2c_dw_isr, and pumping i2c_msg ··· 588 649 * 589 650 * The raw version might be useful for debugging purposes. 590 651 */ 591 - regmap_read(dev->map, DW_IC_INTR_STAT, &stat); 652 + if (!(dev->flags & ACCESS_POLLING)) { 653 + regmap_read(dev->map, DW_IC_INTR_STAT, &stat); 654 + } else { 655 + regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat); 656 + stat &= dev->sw_mask; 657 + } 592 658 593 659 /* 594 660 * Do not use the IC_CLR_INTR register to clear interrupts, or ··· 633 689 return stat; 634 690 } 635 691 636 - /* 637 - * Interrupt service routine. This gets called whenever an I2C master interrupt 638 - * occurs. 639 - */ 640 - static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) 692 + static void i2c_dw_process_transfer(struct dw_i2c_dev *dev, unsigned int stat) 641 693 { 642 - struct dw_i2c_dev *dev = dev_id; 643 - unsigned int stat, enabled; 644 - 645 - regmap_read(dev->map, DW_IC_ENABLE, &enabled); 646 - regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat); 647 - if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY)) 648 - return IRQ_NONE; 649 - if (pm_runtime_suspended(dev->dev) || stat == GENMASK(31, 0)) 650 - return IRQ_NONE; 651 - dev_dbg(dev->dev, "enabled=%#x stat=%#x\n", enabled, stat); 652 - 653 - stat = i2c_dw_read_clear_intrbits(dev); 654 - 655 - if (!(dev->status & STATUS_ACTIVE)) { 656 - /* 657 - * Unexpected interrupt in driver point of view. State 658 - * variables are either unset or stale so acknowledge and 659 - * disable interrupts for suppressing further interrupts if 660 - * interrupt really came from this HW (E.g. firmware has left 661 - * the HW active). 662 - */ 663 - __i2c_dw_write_intr_mask(dev, 0); 664 - return IRQ_HANDLED; 665 - } 666 - 667 694 if (stat & DW_IC_INTR_TX_ABRT) { 668 695 dev->cmd_err |= DW_IC_ERR_TX_ABRT; 669 696 dev->status &= ~STATUS_MASK; ··· 670 755 __i2c_dw_write_intr_mask(dev, 0); 671 756 __i2c_dw_write_intr_mask(dev, stat); 672 757 } 758 + } 759 + 760 + /* 761 + * Interrupt service routine. This gets called whenever an I2C master interrupt 762 + * occurs. 763 + */ 764 + static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) 765 + { 766 + struct dw_i2c_dev *dev = dev_id; 767 + unsigned int stat, enabled; 768 + 769 + regmap_read(dev->map, DW_IC_ENABLE, &enabled); 770 + regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat); 771 + if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY)) 772 + return IRQ_NONE; 773 + if (pm_runtime_suspended(dev->dev) || stat == GENMASK(31, 0)) 774 + return IRQ_NONE; 775 + dev_dbg(dev->dev, "enabled=%#x stat=%#x\n", enabled, stat); 776 + 777 + stat = i2c_dw_read_clear_intrbits(dev); 778 + 779 + if (!(dev->status & STATUS_ACTIVE)) { 780 + /* 781 + * Unexpected interrupt in driver point of view. State 782 + * variables are either unset or stale so acknowledge and 783 + * disable interrupts for suppressing further interrupts if 784 + * interrupt really came from this HW (E.g. firmware has left 785 + * the HW active). 786 + */ 787 + __i2c_dw_write_intr_mask(dev, 0); 788 + return IRQ_HANDLED; 789 + } 790 + 791 + i2c_dw_process_transfer(dev, stat); 673 792 674 793 return IRQ_HANDLED; 794 + } 795 + 796 + static int i2c_dw_wait_transfer(struct dw_i2c_dev *dev) 797 + { 798 + unsigned long timeout = dev->adapter.timeout; 799 + unsigned int stat; 800 + int ret; 801 + 802 + if (!(dev->flags & ACCESS_POLLING)) { 803 + ret = wait_for_completion_timeout(&dev->cmd_complete, timeout); 804 + } else { 805 + timeout += jiffies; 806 + do { 807 + ret = try_wait_for_completion(&dev->cmd_complete); 808 + if (ret) 809 + break; 810 + 811 + stat = i2c_dw_read_clear_intrbits(dev); 812 + if (stat) 813 + i2c_dw_process_transfer(dev, stat); 814 + else 815 + /* Try save some power */ 816 + usleep_range(3, 25); 817 + } while (time_before(jiffies, timeout)); 818 + } 819 + 820 + return ret ? 0 : -ETIMEDOUT; 675 821 } 676 822 677 823 /* ··· 748 772 749 773 pm_runtime_get_sync(dev->dev); 750 774 751 - /* 752 - * Initiate I2C message transfer when polling mode is enabled, 753 - * As it is polling based transfer mechanism, which does not support 754 - * interrupt based functionalities of existing DesignWare driver. 755 - */ 756 775 switch (dev->flags & MODEL_MASK) { 757 776 case MODEL_AMD_NAVI_GPU: 758 777 ret = amd_i2c_dw_xfer_quirk(adap, msgs, num); 759 - goto done_nolock; 760 - case MODEL_WANGXUN_SP: 761 - ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num); 762 778 goto done_nolock; 763 779 default: 764 780 break; ··· 779 811 i2c_dw_xfer_init(dev); 780 812 781 813 /* Wait for tx to complete */ 782 - if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) { 814 + ret = i2c_dw_wait_transfer(dev); 815 + if (ret) { 783 816 dev_err(dev->dev, "controller timed out\n"); 784 817 /* i2c_dw_init_master() implicitly disables the adapter */ 785 818 i2c_recover_bus(&dev->adapter); 786 819 i2c_dw_init_master(dev); 787 - ret = -ETIMEDOUT; 788 820 goto done; 789 821 } 790 822