linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Daniel Scally <djrscally@gmail.com>
Cc: linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org,
	platform-driver-x86@vger.kernel.org, devel@acpica.org,
	rjw@rjwysocki.net, lenb@kernel.org, andy@kernel.org,
	mika.westerberg@linux.intel.com, linus.walleij@linaro.org,
	bgolaszewski@baylibre.com, wsa@kernel.org, lee.jones@linaro.org,
	hdegoede@redhat.com, mgross@linux.intel.com,
	robert.moore@intel.com, erik.kaneda@intel.com,
	sakari.ailus@linux.intel.com, andriy.shevchenko@linux.intel.com,
	kieran.bingham@ideasonboard.com
Subject: Re: [PATCH v2 6/7] platform: x86: Add intel_skl_int3472 driver
Date: Tue, 19 Jan 2021 18:33:16 +0200	[thread overview]
Message-ID: <YAcJzHQkDHK6K2iV@pendragon.ideasonboard.com> (raw)
In-Reply-To: <c76be8f9-1e58-8ea2-4a2e-61ac9865d326@gmail.com>

Hi Daniel,

On Tue, Jan 19, 2021 at 08:43:43AM +0000, Daniel Scally wrote:
> On 19/01/2021 06:19, Laurent Pinchart wrote:
> > On Mon, Jan 18, 2021 at 08:46:34PM +0000, Daniel Scally wrote:
> >> Hi Laurent, thanks for the comments - really appreciate the detail.
> >>
> >> Some specific responses below but assume a general "will do" to
> >> everything you mentioned otherwise...
> >>
> >> On 18/01/2021 09:15, Laurent Pinchart wrote:
> >>>> +	  PMIC) and one designed for Chrome OS.
> >>> How about expanding this a bit to explain what the INT3472 stands for ?
> >>>
> >>> 	  The INT3472 is an Intel camera power controller, a logical device
> >>> 	  found on some Skylake-based systems that can map to different
> >>> 	  hardware devices depending on the platform. On machines
> >>> 	  designed for Chrome OS, it maps to a TPS68470 camera PMIC. On
> >>> 	  machines designed for Windows, it maps to either a TP68470
> >>> 	  camera PMIC, a uP6641Q sensor PMIC, or a set of discrete GPIOs
> >>> 	  and power gates.
> >> Yeah sure ok
> >>
> >>>> This driver handles all three
> >>>> +	  situations by discovering information it needs to discern them at
> >>>> +	  runtime.
> >>>> +
> >>>> +	  If your device was designed for Chrome OS, this driver will provide
> >>>> +	  an ACPI operation region, which must be available before any of the
> >>>> +	  devices using this are probed. For this reason, you should select Y
> >>>> +	  if your device was designed for ChromeOS. This option also configures
> >>>> +	  the designware-i2c driver to be built-in, for the same reason.
> >>> Is the last sentence a leftover ?
> >> Oops - it is, but it was supposed to remind me to double check that that
> >> was still necessary. I'll take a look, thanks.
> >>
> >>>> +
> >>>> +#include "intel_skl_int3472_common.h"
> >>>> +
> >>>> +int skl_int3472_get_cldb_buffer(struct acpi_device *adev,
> >>>> +				struct int3472_cldb *cldb)
> >>>> +{
> >>>> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> >>>> +	acpi_handle handle = adev->handle;
> >>>> +	union acpi_object *obj;
> >>>> +	acpi_status status;
> >>>> +	int ret = 0;
> >>>> +
> >>>> +	status = acpi_evaluate_object(handle, "CLDB", NULL, &buffer);
> >>>> +	if (ACPI_FAILURE(status))
> >>>> +		return -ENODEV;
> >>>> +
> >>>> +	obj = buffer.pointer;
> >>>> +	if (!obj) {
> >>>> +		dev_err(&adev->dev, "ACPI device has no CLDB object\n");
> >>> Is this the code path that is taken on Chrome OS ? If so an error
> >>> message isn't appropriate. I'd drop this message, and instead add an
> >>> error message in the discrete PMIC code.
> >> Ah yes of course, thanks, I'll move the error message.
> >>
> >>>> +
> >>>> +	unsigned int n_gpios; /* how many GPIOs have we seen */
> >>>> +
> >>>> +	struct int3472_gpio_regulator regulator;
> >>>> +	struct int3472_gpio_clock clock;
> >>> You don't necessarily need to define separate structures for this, you
> >>> could also write
> >>>
> >>> 	struct {
> >>> 		char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
> >>> 		char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
> >>> 		struct gpio_desc *gpio;
> >>> 		struct regulator_dev *rdev;
> >>> 		struct regulator_desc rdesc;
> >>> 	} regulator;
> >>>
> >>> 	struct {
> >>> 		struct clk *clk;
> >>> 		struct clk_hw clk_hw;
> >>> 		struct clk_lookup *cl;
> >>> 		struct gpio_desc *gpio;
> >>> 	} clock;
> >>>
> >>> It's entirely up to you.
> >> Ooh yeah I like that more, thanks very much.
> >>
> >>>> +/* 79234640-9e10-4fea-a5c1-b5aa8b19756f */
> >>>> +static const guid_t int3472_gpio_guid =
> >>>> +	GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> >>>> +		  0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
> >>>> +
> >>>> +/* 822ace8f-2814-4174-a56b-5f029fe079ee */
> >>>> +static const guid_t cio2_sensor_module_guid =
> >>>> +	GUID_INIT(0x822ace8f, 0x2814, 0x4174,
> >>>> +		  0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
> >>> A comment that explains what those DSM functions do would be useful for
> >>> reference. It has taken lots of time to figure it out, let's spare the
> >>> pain to the next person who tries to understand this :-)
> >> Hah - good point, well made. I'll explain what they're for then.
> >>
> >>>> +static int skl_int3472_clk_enable(struct clk_hw *hw)
> >>>> +{
> >>>> +	struct int3472_gpio_clock *clk = to_int3472_clk(hw);
> >>>> +
> >>>> +	gpiod_set_value(clk->gpio, 1);
> >>> The clock enable() and disable() methods are not supposed to sleep,
> >>> while setting a GPIO value may sleep in the general case. Should this be
> >>> moved to skl_int3472_clk_prepare() ? Same for skl_int3472_clk_disable()
> >>> and skl_int3472_clk_unprepare().
> >> I was under the assumption the difference between gpiod_set_value() and
> >> gpiod_set_value_cansleep() was that gpiod_set_value() _can't_ sleep, but
> >> actually reading the function's comments it seems it will just complain
> >> if it turns out it can sleep:
> >>
> >> * This function can be called from contexts where we cannot sleep, and will
> >> * complain if the GPIO chip functions potentially sleep. It doesn't
> >> complain, on either of my devices, but I guess that can't be guaranteed
> >> for _every_ device, so these calls probably are safer in (un)prepare() yes.
> > If we could guarantee that the GPIOs are connected to the SoC, we could
> > keep using the code above, as there should be no need to sleep. The
> > question is whether this can be guaranteed or not. It's true that I
> > would be surprised if the GPIOs were connected, for instance, to an I2C
> > GPIO expander..
>
> Is that the deciding factor? I'd say that's unlikely, but what do I
> know? Then again, is there actually any downside to calling
> gpiod_set_value() in the prepare() function instead? If not, may as well
> be safe.

The downside is that prepare() is meant to be called earlier than
enable() when the consumer needs to call enable() in a context that
can't sleep. This can sometimes cause the clock to be enabled for longer
than necessary. In this case I don't think it's an issue, sensor drivers
will use clk_prepare_enable() anyway.

> >>>> +			}
> >>>> +
> >>>> +			i++;
> >>>> +		}
> >>>> +	}
> >>>> +
> >>>> +	if (!func)
> >>>> +		return 0;
> >>> I initially thought this wasn't right, as if no entry was found in the
> >>> mapping table, func would still have its non-NULL value as passed to
> >>> this function. I then realized that you're checking if the match that
> >>> was found is NULL. A comment to explain this would be useful.
> >> Yep ok - I actually had one and decided it was superfluous and removed
> >> it - my bad.
> >>
> >>>> +
> >>>> +	status = acpi_get_handle(NULL, path, &handle);
> >>>> +	if (ACPI_FAILURE(status))
> >>>> +		return -EINVAL;
> >>>> +
> >>>> +	ret = acpi_bus_get_device(handle, &adev);
> >>>> +	if (ret)
> >>>> +		return -ENODEV;
> >>>> +
> >>>> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> >>>> +							   ares->data.gpio.pin_table[0],
> >>>> +							   func, 0, polarity);
> >>> I wonder if
> >>>
> >>> 	table_entry.key = acpi_dev_name(adev);
> >>> 	table_entry.chip_hwnum = ares->data.gpio.pin_table[0];
> >>> 	table_entry.con_id = func;
> >>> 	table_entry.idx = 0;
> >>> 	table_entry.flags = polarity;
> >>>
> >>> (with struct gpiod_lookup table_entry = { }; above) would be more
> >>> readable. Up to you.
> >>>
> >>>> +
> >>>> +	memcpy(&int3472->gpios.table[int3472->n_sensor_gpios], &table_entry,
> >>>> +	       sizeof(table_entry));
> >>> Ah, or maybe
> >>>
> >>> 	struct gpio_lookup *table_entry;
> >>>
> >>> 	table_entry = &int3472->gpios.table[int3472->n_sensor_gpios];
> >>> 	table_entry->key = acpi_dev_name(adev);
> >>> 	table_entry->chip_hwnum = ares->data.gpio.pin_table[0];
> >>> 	table_entry->con_id = func;
> >>> 	table_entry->idx = 0;
> >>> 	table_entry->flags = polarity;
> >>>
> >>> (no need to memset() to 0 first as the whole structure has been
> >>> allocated with kzalloc()).
> >> Yeah you're right, this looks much nicer - thanks.
> >>
> >>>> +	int ret = 0;
> >>>> +
> >>>> +	init.name = kasprintf(GFP_KERNEL, "%s-clk",
> >>>> +			      acpi_dev_name(int3472->adev));
> >>> You need to check for NULL and return -ENOMEM.
> >> Oops, of course, thanks
> >>
> >>>> +		goto err_unregister_clk;
> >>> If this fails, you will end up calling clk_unregister() and
> >>> clkdev_drop() in skl_int3472_discrete_remove(). You should replace the
> >>> check in the remove function with
> >>>
> >>> 	if (!int3472->clock.cl) {
> >> You're right, good spot, thank you.
> >>
> >>>> +		dev_err(&int3472->pdev->dev, "No sensor module config\n");
> >>>> +		return PTR_ERR(sensor_config);
> >>>> +	}
> >>> Would it make sense to call this in skl_int3472_discrete_probe() or
> >>> skl_int3472_parse_crs() and cache the config pointer ?
> >> Yes, probably actually, and then the GPIO mapping function can just
> >> check for its presence.
> >>
> >>>> +	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
> >>>> +	init_data.num_consumer_supplies = 1;
> >>>> +	init_data.consumer_supplies = &sensor_config->supply_map;
> >>>> +
> >>>> +	snprintf(int3472->regulator.regulator_name,
> >>>> +		 GPIO_REGULATOR_NAME_LENGTH, "int3472-discrete-regulator");
> >>> s/GPIO_REGULATOR_NAME_LENGTH/sizeof(int3472->regulator.regulator_name)/
> >>>
> >>> Do regulator names need to be unique ? If so you may have a problem if a
> >>> platform has two discrete INT3472.
> >> Unlike clocks, the regulator framework doesn't shout at you when you do
> >> this, but I agree it's suboptimal at the very least, I'll set it to
> >> ..."%s-regulator", acpi_dev_name(int3472->adev)... as with the clock.
> >>
> >>>> +	case INT3472_GPIO_TYPE_PRIVACY_LED:
> >>>> +		ret = skl_int3472_map_gpio_to_sensor(int3472, ares,
> >>>> +						     "indicator-led",
> >>>> +						     GPIO_ACTIVE_HIGH);
> >>> Mapping the indicator LED to the sensor isn't great, as all sensor
> >>> drivers would then need to handle it. Could it be handled in the
> >>> regulator instead, so that it would be turned on automatically when the
> >>> sensor is powered up ? Another option, more complicated, would be to
> >>> handle it in the CIO2 driver (but I'm not sure how we would map it).
> >> Not with the regulator, because it turns out only the 0x0b pin is one of
> >> those and those appear on very few devices in scope, so it wouldn't be
> >> called on a Surface Book 2 for example. Perhaps as part of clock
> >> prepare/enable? I don't much like the idea of it running in the CIO2
> >> driver to be honest, feels a bit out of place.
> > The clock is another option, but could there be platforms where the
> > clock GPIO isn't present ?
> 
> I haven't ever seen a DSDT that didn't include a 0x0c pin to enable the
> clock, though that doesn't necessarily mean they're always there. Plenty
> of driver datasheets say they're happy for the external clock to be free
> running, so it could just be always active I suppose.

Maybe we can handle this later if such a platform is found. You should
then print a warning message if no clock is present.

> > Another option would be to let userspace handle that GPIO, but we then
> > need to convey it to userspace.
> 
> Can you point me to an example of that to look at perhaps?

I don't think there's any :-) We'd have to design the mechanism.

> >>>> +
> >>>> +	if (int3472->gpios_mapped)
> >>>> +		gpiod_remove_lookup_table(&int3472->gpios);
> >>> You could avoid the need for the gpios_mapped field by checking for
> >>>
> >>> 	if (int3472->gpios.list.next)
> >>>
> >>> Up to you.
> >> Thank you! I was scratching my head trying to figure out a better way of
> >> doing that.

-- 
Regards,

Laurent Pinchart

  reply	other threads:[~2021-01-19 18:27 UTC|newest]

Thread overview: 98+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-18  0:34 [PATCH v2 0/7] Introduce intel_skl_int3472 driver Daniel Scally
2021-01-18  0:34 ` [PATCH v2 1/7] acpi: utils: move acpi_lpss_dep() to utils Daniel Scally
2021-01-18  7:24   ` Laurent Pinchart
2021-01-18  8:31     ` Daniel Scally
2021-01-18 12:29     ` Andy Shevchenko
2021-01-18 12:35       ` Daniel Scally
2021-01-18 12:28   ` Andy Shevchenko
2021-01-18 16:06     ` Rafael J. Wysocki
2021-01-18 16:42       ` Andy Shevchenko
2021-01-18  0:34 ` [PATCH v2 2/7] acpi: utils: Add function to fetch dependent acpi_devices Daniel Scally
2021-01-18  7:34   ` Laurent Pinchart
2021-01-18  8:37     ` Daniel Scally
2021-01-18 12:33   ` Andy Shevchenko
2021-01-18 13:37     ` Daniel Scally
2021-01-18 16:14   ` Rafael J. Wysocki
2021-01-18 20:51     ` Daniel Scally
2021-01-19 13:15       ` Rafael J. Wysocki
2021-01-19 13:28         ` Daniel Scally
2021-01-21  9:47         ` Daniel Scally
2021-01-21 11:58           ` Rafael J. Wysocki
2021-01-21 12:04             ` Daniel Scally
2021-01-21 14:39               ` Rafael J. Wysocki
2021-01-21 16:34                 ` Daniel Scally
2021-01-21 18:08                   ` Rafael J. Wysocki
2021-01-21 21:06                     ` Daniel Scally
2021-02-02  9:58                       ` Daniel Scally
2021-02-02 11:27                         ` Andy Shevchenko
2021-02-02 14:02                         ` Rafael J. Wysocki
2021-01-18  0:34 ` [PATCH v2 3/7] i2c: i2c-core-base: Use format macro in i2c_dev_set_name() Daniel Scally
2021-01-18  7:28   ` Laurent Pinchart
2021-01-18 12:41     ` Andy Shevchenko
2021-01-18  9:41   ` Sakari Ailus
2021-01-18  9:42     ` Sakari Ailus
2021-01-18  9:48     ` Wolfram Sang
2021-01-18 12:39   ` Andy Shevchenko
2021-01-18  0:34 ` [PATCH v2 4/7] i2c: i2c-core-acpi: Add i2c_acpi_dev_name() Daniel Scally
2021-01-18  9:18   ` Laurent Pinchart
2021-01-18 13:41     ` Andy Shevchenko
2021-01-19 13:19     ` Rafael J. Wysocki
2021-01-28  9:00       ` Wolfram Sang
2021-01-28  9:15         ` Daniel Scally
2021-01-28  9:17           ` Wolfram Sang
2021-01-28  9:22             ` Daniel Scally
2021-01-18 13:39   ` Andy Shevchenko
2021-01-18 18:43     ` Joe Perches
2021-01-18 18:56       ` Andy Shevchenko
2021-01-18 19:00         ` Joe Perches
2021-01-18 19:01         ` Andy Shevchenko
2021-01-18  0:34 ` [PATCH v2 5/7] gpio: gpiolib-acpi: Export acpi_get_gpiod() Daniel Scally
2021-01-18  7:37   ` Laurent Pinchart
2021-01-18 13:45   ` Andy Shevchenko
2021-01-18 13:46     ` Andy Shevchenko
2021-01-18 21:32     ` Daniel Scally
2021-01-18  0:34 ` [PATCH v2 6/7] platform: x86: Add intel_skl_int3472 driver Daniel Scally
2021-01-18  9:15   ` Laurent Pinchart
2021-01-18 14:46     ` Andy Shevchenko
2021-01-18 21:19       ` Daniel Scally
2021-01-19  0:11         ` Daniel Scally
2021-01-19  6:21           ` Laurent Pinchart
2021-01-19  9:35             ` Andy Shevchenko
2021-01-19 16:49               ` Laurent Pinchart
2021-01-19  9:33           ` Andy Shevchenko
2021-01-19  9:34             ` Daniel Scally
2021-01-19 16:36             ` Laurent Pinchart
2021-01-19 17:43               ` Andy Shevchenko
2021-01-20  4:18                 ` Laurent Pinchart
2021-01-20 11:44                   ` Andy Shevchenko
2021-01-21 21:08                     ` Daniel Scally
2021-01-19  9:24         ` Andy Shevchenko
2021-01-19 10:40           ` Daniel Scally
2021-01-19 11:08             ` Andy Shevchenko
2021-01-19 16:48               ` Laurent Pinchart
2021-01-19 17:51                 ` Andy Shevchenko
2021-01-20  4:21                   ` Laurent Pinchart
2021-01-20 12:57                     ` Andy Shevchenko
2021-01-21  0:18                       ` Daniel Scally
2021-02-07 11:00                         ` Daniel Scally
2021-02-07 11:56                           ` Andy Shevchenko
2021-01-18 20:46     ` Daniel Scally
2021-01-19  6:19       ` Laurent Pinchart
2021-01-19  8:43         ` Daniel Scally
2021-01-19 16:33           ` Laurent Pinchart [this message]
2021-01-18 11:12   ` Barnabás Pőcze
2021-01-18 13:51     ` andriy.shevchenko
2021-01-18 14:51       ` Barnabás Pőcze
2021-01-18 15:23         ` andriy.shevchenko
2021-01-18 15:32           ` Hans de Goede
2021-01-18 15:48             ` andriy.shevchenko
2021-01-18 16:00               ` Daniel Scally
2021-01-18 16:03                 ` Hans de Goede
2021-01-18 17:05             ` Laurent Pinchart
2021-01-19 10:56   ` Kieran Bingham
2021-01-19 11:11     ` Andy Shevchenko
2021-01-19 11:12       ` Daniel Scally
2021-01-18  0:34 ` [PATCH v2 7/7] mfd: Remove tps68470 MFD driver Daniel Scally
2021-01-18  7:42   ` Laurent Pinchart
2021-01-18 13:53   ` Andy Shevchenko
2021-01-18 20:07     ` Joe Perches

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=YAcJzHQkDHK6K2iV@pendragon.ideasonboard.com \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=andy@kernel.org \
    --cc=bgolaszewski@baylibre.com \
    --cc=devel@acpica.org \
    --cc=djrscally@gmail.com \
    --cc=erik.kaneda@intel.com \
    --cc=hdegoede@redhat.com \
    --cc=kieran.bingham@ideasonboard.com \
    --cc=lee.jones@linaro.org \
    --cc=lenb@kernel.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mgross@linux.intel.com \
    --cc=mika.westerberg@linux.intel.com \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=rjw@rjwysocki.net \
    --cc=robert.moore@intel.com \
    --cc=sakari.ailus@linux.intel.com \
    --cc=wsa@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 NNTP newsgroup(s).