Skip to content

Commit bd002ef

Browse files
jhnikulaAndi Shyti
authored andcommitted
i2c: designware: Move interrupt handling functions before i2c_dw_xfer()
Code is more logically arranged when i2c_dw_read_clear_intrbits() and i2c_dw_isr() are located before i2c_dw_xfer(). Real reason for this is to prepare for more shared code between interrupt and polling mode code. While at it, remove one extra space and refer to the i2c_dw_init_master() in two comment sections. Signed-off-by: Jarkko Nikula <[email protected]> Tested-by: Jiawen Wu <[email protected]> Signed-off-by: Andi Shyti <[email protected]>
1 parent 04c71da commit bd002ef

File tree

1 file changed

+113
-113
lines changed

1 file changed

+113
-113
lines changed

drivers/i2c/busses/i2c-designware-master.c

Lines changed: 113 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -633,119 +633,6 @@ i2c_dw_read(struct dw_i2c_dev *dev)
633633
}
634634
}
635635

636-
/*
637-
* Prepare controller for a transaction and call i2c_dw_xfer_msg.
638-
*/
639-
static int
640-
i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
641-
{
642-
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
643-
int ret;
644-
645-
dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
646-
647-
pm_runtime_get_sync(dev->dev);
648-
649-
/*
650-
* Initiate I2C message transfer when polling mode is enabled,
651-
* As it is polling based transfer mechanism, which does not support
652-
* interrupt based functionalities of existing DesignWare driver.
653-
*/
654-
switch (dev->flags & MODEL_MASK) {
655-
case MODEL_AMD_NAVI_GPU:
656-
ret = amd_i2c_dw_xfer_quirk(adap, msgs, num);
657-
goto done_nolock;
658-
case MODEL_WANGXUN_SP:
659-
ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num);
660-
goto done_nolock;
661-
default:
662-
break;
663-
}
664-
665-
reinit_completion(&dev->cmd_complete);
666-
dev->msgs = msgs;
667-
dev->msgs_num = num;
668-
dev->cmd_err = 0;
669-
dev->msg_write_idx = 0;
670-
dev->msg_read_idx = 0;
671-
dev->msg_err = 0;
672-
dev->status = 0;
673-
dev->abort_source = 0;
674-
dev->rx_outstanding = 0;
675-
676-
ret = i2c_dw_acquire_lock(dev);
677-
if (ret)
678-
goto done_nolock;
679-
680-
ret = i2c_dw_wait_bus_not_busy(dev);
681-
if (ret < 0)
682-
goto done;
683-
684-
/* Start the transfers */
685-
i2c_dw_xfer_init(dev);
686-
687-
/* Wait for tx to complete */
688-
if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) {
689-
dev_err(dev->dev, "controller timed out\n");
690-
/* i2c_dw_init implicitly disables the adapter */
691-
i2c_recover_bus(&dev->adapter);
692-
i2c_dw_init_master(dev);
693-
ret = -ETIMEDOUT;
694-
goto done;
695-
}
696-
697-
/*
698-
* We must disable the adapter before returning and signaling the end
699-
* of the current transfer. Otherwise the hardware might continue
700-
* generating interrupts which in turn causes a race condition with
701-
* the following transfer. Needs some more investigation if the
702-
* additional interrupts are a hardware bug or this driver doesn't
703-
* handle them correctly yet.
704-
*/
705-
__i2c_dw_disable_nowait(dev);
706-
707-
if (dev->msg_err) {
708-
ret = dev->msg_err;
709-
goto done;
710-
}
711-
712-
/* No error */
713-
if (likely(!dev->cmd_err && !dev->status)) {
714-
ret = num;
715-
goto done;
716-
}
717-
718-
/* We have an error */
719-
if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
720-
ret = i2c_dw_handle_tx_abort(dev);
721-
goto done;
722-
}
723-
724-
if (dev->status)
725-
dev_err(dev->dev,
726-
"transfer terminated early - interrupt latency too high?\n");
727-
728-
ret = -EIO;
729-
730-
done:
731-
i2c_dw_release_lock(dev);
732-
733-
done_nolock:
734-
pm_runtime_mark_last_busy(dev->dev);
735-
pm_runtime_put_autosuspend(dev->dev);
736-
737-
return ret;
738-
}
739-
740-
static const struct i2c_algorithm i2c_dw_algo = {
741-
.master_xfer = i2c_dw_xfer,
742-
.functionality = i2c_dw_func,
743-
};
744-
745-
static const struct i2c_adapter_quirks i2c_dw_quirks = {
746-
.flags = I2C_AQ_NO_ZERO_LEN,
747-
};
748-
749636
static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
750637
{
751638
unsigned int stat, dummy;
@@ -872,6 +759,119 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
872759
return IRQ_HANDLED;
873760
}
874761

762+
/*
763+
* Prepare controller for a transaction and call i2c_dw_xfer_msg.
764+
*/
765+
static int
766+
i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
767+
{
768+
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
769+
int ret;
770+
771+
dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
772+
773+
pm_runtime_get_sync(dev->dev);
774+
775+
/*
776+
* Initiate I2C message transfer when polling mode is enabled,
777+
* As it is polling based transfer mechanism, which does not support
778+
* interrupt based functionalities of existing DesignWare driver.
779+
*/
780+
switch (dev->flags & MODEL_MASK) {
781+
case MODEL_AMD_NAVI_GPU:
782+
ret = amd_i2c_dw_xfer_quirk(adap, msgs, num);
783+
goto done_nolock;
784+
case MODEL_WANGXUN_SP:
785+
ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num);
786+
goto done_nolock;
787+
default:
788+
break;
789+
}
790+
791+
reinit_completion(&dev->cmd_complete);
792+
dev->msgs = msgs;
793+
dev->msgs_num = num;
794+
dev->cmd_err = 0;
795+
dev->msg_write_idx = 0;
796+
dev->msg_read_idx = 0;
797+
dev->msg_err = 0;
798+
dev->status = 0;
799+
dev->abort_source = 0;
800+
dev->rx_outstanding = 0;
801+
802+
ret = i2c_dw_acquire_lock(dev);
803+
if (ret)
804+
goto done_nolock;
805+
806+
ret = i2c_dw_wait_bus_not_busy(dev);
807+
if (ret < 0)
808+
goto done;
809+
810+
/* Start the transfers */
811+
i2c_dw_xfer_init(dev);
812+
813+
/* Wait for tx to complete */
814+
if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) {
815+
dev_err(dev->dev, "controller timed out\n");
816+
/* i2c_dw_init_master() implicitly disables the adapter */
817+
i2c_recover_bus(&dev->adapter);
818+
i2c_dw_init_master(dev);
819+
ret = -ETIMEDOUT;
820+
goto done;
821+
}
822+
823+
/*
824+
* We must disable the adapter before returning and signaling the end
825+
* of the current transfer. Otherwise the hardware might continue
826+
* generating interrupts which in turn causes a race condition with
827+
* the following transfer. Needs some more investigation if the
828+
* additional interrupts are a hardware bug or this driver doesn't
829+
* handle them correctly yet.
830+
*/
831+
__i2c_dw_disable_nowait(dev);
832+
833+
if (dev->msg_err) {
834+
ret = dev->msg_err;
835+
goto done;
836+
}
837+
838+
/* No error */
839+
if (likely(!dev->cmd_err && !dev->status)) {
840+
ret = num;
841+
goto done;
842+
}
843+
844+
/* We have an error */
845+
if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
846+
ret = i2c_dw_handle_tx_abort(dev);
847+
goto done;
848+
}
849+
850+
if (dev->status)
851+
dev_err(dev->dev,
852+
"transfer terminated early - interrupt latency too high?\n");
853+
854+
ret = -EIO;
855+
856+
done:
857+
i2c_dw_release_lock(dev);
858+
859+
done_nolock:
860+
pm_runtime_mark_last_busy(dev->dev);
861+
pm_runtime_put_autosuspend(dev->dev);
862+
863+
return ret;
864+
}
865+
866+
static const struct i2c_algorithm i2c_dw_algo = {
867+
.master_xfer = i2c_dw_xfer,
868+
.functionality = i2c_dw_func,
869+
};
870+
871+
static const struct i2c_adapter_quirks i2c_dw_quirks = {
872+
.flags = I2C_AQ_NO_ZERO_LEN,
873+
};
874+
875875
void i2c_dw_configure_master(struct dw_i2c_dev *dev)
876876
{
877877
struct i2c_timings *t = &dev->timings;

0 commit comments

Comments
 (0)