Re: [PATCHv2] w1: omap-hdq: Simplify driver with PM runtime autosuspend

From: Adam Ford
Date: Mon Dec 16 2019 - 14:03:37 EST


On Mon, Dec 16, 2019 at 10:43 AM Tony Lindgren <tony@xxxxxxxxxxx> wrote:
>
> * Tony Lindgren <tony@xxxxxxxxxxx> [191216 14:54]:
> > Vignesh, any comments on the ti,mode = "1w" and removal of the call to
> > hdq_disable_interrupt()? Is there some specific section where we need
> > to have interrupts disabled and then re-enabled?
>
> OK I got "1w" mode working too now. We need to clear the irqstatus before
> calling wait_event_timeout() on it, and we're now missing it in the
> hdq_read_byte().
>
> Looks like we should not tinker with the actual irstatus register though,
> that's up to the hdq_isr() to manage.
>
> So the following helper is probably what we want to do additionally.
> I'll be posting v3 of the $subject patch.

I manually attempted to apply the patches. I 'think' I did it right.

For testing, I ran:
watch cat /sys/devices/w1_bus_master1/01-000000000000/power_supply/bq27000-battery/voltage_now

I inserted and removed the power cable several times and observed the
voltage readings with the battery connected.
The numbers looked reasonable.

I then put the board to suspend, waited a few seconds and woke the
board from sleep. I resumed my 'watch' function from above and it
worked just fine.
If there is nothing else you want me to test, go ahead and add:

Tested-by: Adam Ford <aford173@xxxxxxxxx> #logicpd-torpedo-37xx-devkit

adam
>
> Regards,
>
> Tony
>
> 8< ----------------------
> diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
> --- a/drivers/w1/masters/omap_hdq.c
> +++ b/drivers/w1/masters/omap_hdq.c
> @@ -119,22 +119,24 @@ static int hdq_wait_for_flag(struct hdq_data *hdq_data, u32 offset,
> return ret;
> }
>
> +/* Clear saved irqstatus after using an interrupt */
> +static void hdq_reset_irqstatus(struct hdq_data *hdq_data)
> +{
> + unsigned long irqflags;
> +
> + spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
> + hdq_data->hdq_irqstatus = 0;
> + spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
> +}
> +
> /* write out a byte and fill *status with HDQ_INT_STATUS */
> static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)
> {
> int ret;
> u8 tmp_status;
> - unsigned long irqflags;
>
> *status = 0;
>
> - spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
> - /* clear interrupt flags via a dummy read */
> - hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
> - /* ISR loads it with new INT_STATUS */
> - hdq_data->hdq_irqstatus = 0;
> - spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
> -
> hdq_reg_out(hdq_data, OMAP_HDQ_TX_DATA, val);
>
> /* set the GO bit */
> @@ -168,6 +170,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)
> }
>
> out:
> + hdq_reset_irqstatus(hdq_data);
> return ret;
> }
>
> @@ -219,7 +222,6 @@ static int omap_hdq_break(struct hdq_data *hdq_data)
> {
> int ret = 0;
> u8 tmp_status;
> - unsigned long irqflags;
>
> ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
> if (ret < 0) {
> @@ -228,13 +230,6 @@ static int omap_hdq_break(struct hdq_data *hdq_data)
> goto rtn;
> }
>
> - spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
> - /* clear interrupt flags via a dummy read */
> - hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
> - /* ISR loads it with new INT_STATUS */
> - hdq_data->hdq_irqstatus = 0;
> - spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
> -
> /* set the INIT and GO bit */
> hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS,
> OMAP_HDQ_CTRL_STATUS_INITIALIZATION | OMAP_HDQ_CTRL_STATUS_GO,
> @@ -283,6 +278,7 @@ static int omap_hdq_break(struct hdq_data *hdq_data)
> " return to zero, %x", tmp_status);
>
> out:
> + hdq_reset_irqstatus(hdq_data);
> mutex_unlock(&hdq_data->hdq_mutex);
> rtn:
> return ret;
> @@ -330,6 +326,7 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)
> /* the data is ready. Read it in! */
> *val = hdq_reg_in(hdq_data, OMAP_HDQ_RX_DATA);
> out:
> + hdq_reset_irqstatus(hdq_data);
> mutex_unlock(&hdq_data->hdq_mutex);
> rtn:
> return ret;
> @@ -363,7 +360,6 @@ static u8 omap_w1_triplet(void *_hdq, u8 bdir)
> goto rtn;
> }
>
> - hdq_data->hdq_irqstatus = 0;
> /* read id_bit */
> hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS,
> ctrl | OMAP_HDQ_CTRL_STATUS_DIR, mask);
> @@ -377,7 +373,9 @@ static u8 omap_w1_triplet(void *_hdq, u8 bdir)
> }
> id_bit = (hdq_reg_in(_hdq, OMAP_HDQ_RX_DATA) & 0x01);
>
> - hdq_data->hdq_irqstatus = 0;
> + /* Must clear irqstatus for another RXCOMPLETE interrupt */
> + hdq_reset_irqstatus(hdq_data);
> +
> /* read comp_bit */
> hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS,
> ctrl | OMAP_HDQ_CTRL_STATUS_DIR, mask);
> @@ -420,6 +418,7 @@ static u8 omap_w1_triplet(void *_hdq, u8 bdir)
> OMAP_HDQ_CTRL_STATUS_SINGLE);
>
> out:
> + hdq_reset_irqstatus(hdq_data);
> mutex_unlock(&hdq_data->hdq_mutex);
> rtn:
> pm_runtime_mark_last_busy(hdq_data->dev);
> @@ -460,7 +459,7 @@ static u8 omap_w1_read_byte(void *_hdq)
> if (ret < 0) {
> pm_runtime_put_noidle(hdq_data->dev);
>
> - return ret;
> + return -1;
> }
>
> ret = hdq_read_byte(hdq_data, &val);
> --
> 2.24.1