Linux-i2c Archive mirror
 help / color / mirror / Atom feed
From: Sam Edwards <sam@turingpi.com>
To: Gregory CLEMENT <gregory.clement@bootlin.com>,
	Andi Shyti <andi.shyti@kernel.org>
Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [RESEND RFC PATCH 4/5] i2c: mv64xxx: Allow continuing after read
Date: Tue, 19 Mar 2024 22:20:39 -0600	[thread overview]
Message-ID: <CAF8uH3vzy3GmxxrQ4Vnj=i-_p+rGZ7ip2r6fR4mm7+_FCY+R2w@mail.gmail.com> (raw)

The current FSM does not check the `send_stop` flag when completing a
read message; it just assumes any read message is always the end of the
transfer. This means subsequent messages go unprocessed, with no error
code to indicate otherwise.

Fixing this requires that the FSM check the `send_stop` flag and issue
the `SEND_RESTART` action instead of stop, but there are only two RCV_*
variants, one for receive-and-continue and one for receive-and-stop. We
could add another variant, however, the new FSM from the previous patch
makes it pretty clear that the RCV_* variants aren't really full actions
in their own respect, since they both implement the same observable
functionality as another action, just with an added read from the data
register first.

Therefore, convert the receive actions to a flag that can be set,
allowing any action to have an "...and also read" variant. The FSM can
then just use the plain SEND_RESTART action, but OR-in the flag, to
represent "read a byte, finish this message, go to the next message."

Signed-off-by: Sam Edwards <sam@turingpi.com>
---
 drivers/i2c/busses/i2c-mv64xxx.c | 47 +++++++++++---------------------
 1 file changed, 16 insertions(+), 31 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 3ae74160001d..6a205cca603a 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -116,9 +116,9 @@ enum mv64xxx_i2c_action {
        MV64XXX_I2C_ACTION_SEND_ADDR_1,
        MV64XXX_I2C_ACTION_SEND_ADDR_2,
        MV64XXX_I2C_ACTION_SEND_DATA,
-       MV64XXX_I2C_ACTION_RCV_DATA,
-       MV64XXX_I2C_ACTION_RCV_DATA_STOP,
        MV64XXX_I2C_ACTION_SEND_STOP,
+
+       MV64XXX_I2C_ACTION_RECEIVE = 0x80,
 };

 struct mv64xxx_i2c_regs {
@@ -395,16 +395,15 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data
*drv_data, u32 status)

        case MV64XXX_I2C_STATE_READ:
                if (drv_data->bytes_left == 0) {
-                       if (prev_state == MV64XXX_I2C_STATE_READ)
-                               drv_data->action =
MV64XXX_I2C_ACTION_RCV_DATA_STOP;
-                       else
+                       if (drv_data->send_stop || drv_data->aborting) {
                                drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
-                       drv_data->state = MV64XXX_I2C_STATE_IDLE;
+                               drv_data->state = MV64XXX_I2C_STATE_IDLE;
+                       } else {
+                               drv_data->action =
MV64XXX_I2C_ACTION_SEND_RESTART;
+                               drv_data->state = MV64XXX_I2C_STATE_RESTART;
+                       }
                } else {
-                       if (prev_state == MV64XXX_I2C_STATE_READ)
-                               drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA;
-                       else
-                               drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;
+                       drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;

                        /*
                         * bytes_left counts the remaining read actions to send
@@ -419,6 +418,8 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data,
u32 status)
                        if (drv_data->bytes_left == 0)
                                drv_data->cntl_bits &=
~MV64XXX_I2C_REG_CONTROL_ACK;
                }
+               if (prev_state == MV64XXX_I2C_STATE_READ)
+                       drv_data->action |= MV64XXX_I2C_ACTION_RECEIVE;
                break;

        case MV64XXX_I2C_STATE_WRITE:
@@ -457,6 +458,11 @@ static void mv64xxx_i2c_send_start(struct
mv64xxx_i2c_data *drv_data)
 static void
 mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
 {
+       if (drv_data->action & MV64XXX_I2C_ACTION_RECEIVE)
+               drv_data->msg->buf[drv_data->byte_posn++] =
+                       readl(drv_data->reg_base + drv_data->reg_offsets.data);
+       drv_data->action &= ~MV64XXX_I2C_ACTION_RECEIVE;
+
        switch(drv_data->action) {
        case MV64XXX_I2C_ACTION_SEND_RESTART:
                /* We should only get here if we have further messages */
@@ -503,27 +509,6 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
                        drv_data->reg_base + drv_data->reg_offsets.control);
                break;

-       case MV64XXX_I2C_ACTION_RCV_DATA:
-               drv_data->msg->buf[drv_data->byte_posn++] =
-                       readl(drv_data->reg_base + drv_data->reg_offsets.data);
-               writel(drv_data->cntl_bits,
-                       drv_data->reg_base + drv_data->reg_offsets.control);
-               break;
-
-       case MV64XXX_I2C_ACTION_RCV_DATA_STOP:
-               drv_data->msg->buf[drv_data->byte_posn++] =
-                       readl(drv_data->reg_base + drv_data->reg_offsets.data);
-               if (!drv_data->atomic)
-                       drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
-               writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
-                       drv_data->reg_base + drv_data->reg_offsets.control);
-               drv_data->block = 0;
-               if (drv_data->errata_delay)
-                       udelay(5);
-
-               wake_up(&drv_data->waitq);
-               break;
-
        case MV64XXX_I2C_ACTION_INVALID:
        default:
                dev_err(&drv_data->adapter.dev,
--
2.43.2

                 reply	other threads:[~2024-03-20  4:20 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAF8uH3vzy3GmxxrQ4Vnj=i-_p+rGZ7ip2r6fR4mm7+_FCY+R2w@mail.gmail.com' \
    --to=sam@turingpi.com \
    --cc=andi.shyti@kernel.org \
    --cc=gregory.clement@bootlin.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).