devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Matti Vaittinen <mazziesaccount@gmail.com>
Cc: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>,
	Lars-Peter Clausen <lars@metafoo.de>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Shreeya Patel <shreeya.patel@collabora.com>,
	Zhigang Shi <Zhigang.Shi@liteon.com>,
	Paul Gazzillo <paul@pgazz.com>,
	Dmitry Osipenko <dmitry.osipenko@collabora.com>,
	linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4 4/5] iio: light: ROHM BU27008 color sensor
Date: Sun, 7 May 2023 15:54:34 +0100	[thread overview]
Message-ID: <20230507155434.3d05daa5@jic23-huawei> (raw)
In-Reply-To: <6d1e37f95dd039d9c96a992b1855fd193bdded40.1683105758.git.mazziesaccount@gmail.com>

On Wed, 3 May 2023 12:50:14 +0300
Matti Vaittinen <mazziesaccount@gmail.com> wrote:

> The ROHM BU27008 is a sensor with 5 photodiodes (red, green, blue, clear
> and IR) with four configurable channels. Red and green being always
> available and two out of the rest three (blue, clear, IR) can be
> selected to be simultaneously measured. Typical application is adjusting
> LCD backlight of TVs, mobile phones and tablet PCs.
> 
> Add initial support for the ROHM BU27008 color sensor.
>  - raw_read() of RGB and clear channels
>  - triggered buffer w/ DRDY interrtupt
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
> 
Mostly stuff that you asked about in response to earlier version but
which I hadn't replied to until today.

Upshot, don't need the manual irq handling in here.

Whilst you aren't setting IRQF_ONESHOT for the pollfunc side of the trigger
(the downstream IRQ / IRQ thread) the IIO utility functions are.

Jonathan


> diff --git a/drivers/iio/light/rohm-bu27008.c b/drivers/iio/light/rohm-bu27008.c
> new file mode 100644
> index 000000000000..c04d845062ba
> --- /dev/null
> +++ b/drivers/iio/light/rohm-bu27008.c
> @@ -0,0 +1,993 @@
...


> +
> +static int bu27008_read_raw(struct iio_dev *idev,
> +			   struct iio_chan_spec const *chan,
> +			   int *val, int *val2, long mask)
> +{
> +	struct bu27008_data *data = iio_priv(idev);
> +	int busy, ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +	{
> +		busy = iio_device_claim_direct_mode(idev);
> +		if (busy)
> +			return -EBUSY;
> +
> +		mutex_lock(&data->mutex);
> +		ret = bu27008_read_one(data, idev, chan, val, val2);
> +		mutex_unlock(&data->mutex);
> +
> +		iio_device_release_direct_mode(idev);
> +
> +		return ret;
> +	}
Why {}? 

I guess there was a local variable, but isn't any more?


> +	case IIO_CHAN_INFO_SCALE:
> +		ret = bu27008_get_scale(data, chan->scan_index == BU27008_IR,
> +					val, val2);
> +		if (ret)
> +			return ret;
> +
> +		return IIO_VAL_INT_PLUS_NANO;
> +
> +	case IIO_CHAN_INFO_INT_TIME:
> +		ret = bu27008_get_int_time_us(data);
> +		if (ret < 0)
> +			return ret;
> +
> +		*val = 0;
> +		*val2 = ret;
> +
> +		return IIO_VAL_INT_PLUS_MICRO;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +}


> +
> +static int bu27008_write_raw(struct iio_dev *idev,
> +			     struct iio_chan_spec const *chan,
> +			     int val, int val2, long mask)
> +{
> +	struct bu27008_data *data = iio_priv(idev);
> +	int ret;
> +
> +	/*
> +	 * Do not allow changing scale when measurement is ongoing as doing so
> +	 * could make values in the buffer inconsistent.
> +	 */
> +	ret = iio_device_claim_direct_mode(idev);
> +	if (ret)
> +		return ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_SCALE:
> +		ret = bu27008_set_scale(data, chan, val, val2);
> +		break;
> +	case IIO_CHAN_INFO_INT_TIME:
> +		if (val)
> +			ret = -EINVAL;
Slight preference for
		if (val) {
			ret = -EINVAL;
			break;
		}

		ret = bu27008....
		break;

so that the error path is out of line of the main flow.

Ever so slightly helps people follow this stuff if they are reading 'a lot'
of code (every little helps!). I have to look closer at anything other than
an obvious direct break / goto / return on error paths to make sure nothing
else snuck in that shouldn't be there.


> +		else
> +			ret = bu27008_try_set_int_time(data, val2);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +	iio_device_release_direct_mode(idev);
> +
> +	return ret;
> +}


> +static irqreturn_t bu27008_trigger_handler(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *idev = pf->indio_dev;
> +	struct bu27008_data *data = iio_priv(idev);
> +	struct {
> +		__le16 chan[BU27008_NUM_HW_CHANS];
> +		s64 ts __aligned(8);
> +	} raw;
> +	int ret, dummy;
> +
> +	memset(&raw, 0, sizeof(raw));
> +
> +	/*
> +	 * After some measurements, it seems reading the
> +	 * BU27008_REG_MODE_CONTROL3 debounces the IRQ line
> +	 */
> +	ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL3, &dummy);
> +	if (ret < 0)
> +		goto err_read;
> +
> +	ret = regmap_bulk_read(data->regmap, BU27008_REG_DATA0_LO, &raw.chan,
> +			       sizeof(raw.chan));
> +	if (ret < 0)
> +		goto err_read;
> +
> +	iio_push_to_buffers_with_timestamp(idev, &raw, pf->timestamp);
> +err_read:
> +	iio_trigger_notify_done(idev->trig);
> +
> +	enable_irq(data->irq);

As below. This shouldn't be needed (and if it was it should be in the
reenable path that is ultimately a result of that notify_done above and
some reference counting fun).

> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int bu27008_buffer_preenable(struct iio_dev *idev)
> +{
> +	struct bu27008_data *data = iio_priv(idev);
> +	int chan_sel, ret;
> +
> +	/* Configure channel selection */
> +	if (test_bit(BU27008_BLUE, idev->active_scan_mask)) {
> +		if (test_bit(BU27008_CLEAR, idev->active_scan_mask))
> +			chan_sel = BU27008_BLUE2_CLEAR3;
> +		else
> +			chan_sel = BU27008_BLUE2_IR3;
> +	} else {
> +		chan_sel = BU27008_CLEAR2_IR3;
> +	}
> +
> +	chan_sel = FIELD_PREP(BU27008_MASK_CHAN_SEL, chan_sel);
> +
> +	ret = regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
> +				 BU27008_MASK_CHAN_SEL, chan_sel);
> +	if (ret)
> +		return ret;

Hmm. I'd missed this before but. This is in the wrong place really
(though it probably doesn't make much difference), stuff related to
enabling particular channels should be in iio_info->update_scan_mode()

It's arguable that the actual measurement mode setting might come
in the postenable callback (after the update_scan_mode() call which
in turn follows the preenable callback).

All these callbacks have become a bit blurry over time as we end
up with devices that need to do nasty thing in one place.  In this
particular case it's pretty simple though, so nicer to move
the scan mask stuff to the callback that is given the active_scan
mask as a parameter.

> +
> +	return bu27008_meas_set(data, BU27008_MEAS_EN);
> +}
> +
> +static int bu27008_buffer_postdisable(struct iio_dev *idev)
> +{
> +	struct bu27008_data *data = iio_priv(idev);
> +
> +	return bu27008_meas_set(data, BU27008_MEAS_DIS);
> +}
> +
> +static const struct iio_buffer_setup_ops bu27008_buffer_ops = {
> +	.preenable = bu27008_buffer_preenable,
> +	.postdisable = bu27008_buffer_postdisable,
> +};
> +
> +static irqreturn_t bu27008_data_rdy_poll(int irq, void *private)
> +{
> +	/*
> +	 * The BU27008 keeps IRQ asserted until we read the VALID bit from
> +	 * a register. We need to keep the IRQ disabled until this
> +	 */
> +	disable_irq_nosync(irq);

As per my late reply to your question on this, shouldn't be needed
as IRQF_ONESHOT is ultimately set for the interrupts nested below this
so they'll get the resulting queuing on the threads which is fine.

Note if this were needed, you might want to provide the reenable callback
for the trigger to do the irq reenabling and to implement that correctly
against some race conditions, that might need to do another read of the
register.  That handles weird ordering conditions where another consumer
of the trigger is enabled before the device acting as a consumer has
it's own buffer enabled.

Anyhow, I don't think it's relevant here and you shouldn't need this unless
I've miss understood / remembered how all that interrupt logic is working.

Jonathan


> +	iio_trigger_poll(private);
> +
> +	return IRQ_HANDLED;
> +}



  parent reply	other threads:[~2023-05-07 14:38 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-03  9:44 [PATCH v4 0/5] Support ROHM BU27008 RGB sensor Matti Vaittinen
2023-05-03  9:48 ` [PATCH v4 1/5] dt-bindings: iio: light: ROHM BU27008 Matti Vaittinen
2023-05-03  9:48 ` [PATCH v4 2/5] iio: trigger: Add simple trigger_validation helper Matti Vaittinen
2023-05-07 14:34   ` Jonathan Cameron
2023-05-03  9:49 ` [PATCH v4 3/5] iio: kx022a: Use new iio_validate_own_trigger() Matti Vaittinen
2023-05-03  9:50 ` [PATCH v4 4/5] iio: light: ROHM BU27008 color sensor Matti Vaittinen
2023-05-04 14:33   ` Andy Shevchenko
2023-05-05  4:56     ` Vaittinen, Matti
2023-05-08 12:23       ` Andy Shevchenko
2023-05-08 12:40         ` Matti Vaittinen
2023-05-07 14:54   ` Jonathan Cameron [this message]
2023-05-08  6:32     ` Matti Vaittinen
2023-05-13 17:52       ` Jonathan Cameron
2023-05-15 12:31         ` Matti Vaittinen
2023-05-03  9:50 ` [PATCH v4 5/5] MAINTAINERS: Add ROHM BU27008 Matti Vaittinen

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=20230507155434.3d05daa5@jic23-huawei \
    --to=jic23@kernel.org \
    --cc=Zhigang.Shi@liteon.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dmitry.osipenko@collabora.com \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=matti.vaittinen@fi.rohmeurope.com \
    --cc=mazziesaccount@gmail.com \
    --cc=paul@pgazz.com \
    --cc=robh+dt@kernel.org \
    --cc=shreeya.patel@collabora.com \
    /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 NNTP newsgroup(s).