Devicetree
 help / color / mirror / Atom feed
* RE: [PATCH v7 3/4] firmware: arm_scmi: Add SCMI v3.2 pincontrol protocol basic support
From: Peng Fan @ 2024-04-02 14:04 UTC (permalink / raw)
  To: Cristian Marussi, Peng Fan (OSS)
  Cc: Sudeep Holla, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Linus Walleij, Dan Carpenter,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linux-gpio@vger.kernel.org, Oleksii Moisieiev
In-Reply-To: <Zgvd7npz1jdJSu-b@pluto>

> Subject: Re: [PATCH v7 3/4] firmware: arm_scmi: Add SCMI v3.2 pincontrol
> protocol basic support
> 
> On Tue, Apr 02, 2024 at 10:22:23AM +0800, Peng Fan (OSS) wrote:
> > From: Peng Fan <peng.fan@nxp.com>
> >
> > Add basic implementation of the SCMI v3.2 pincontrol protocol.
> >
> 
> Hi,
> 
> 
> > Co-developed-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> > Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > ---
> 
> [snip]
> 
> 
> > +struct scmi_settings_get_ipriv {
> > +	u32 selector;
> > +	enum scmi_pinctrl_selector_type type;
> > +	bool get_all;
> > +	enum scmi_pinctrl_conf_type *config_types;
> > +	u32 *config_values;
> > +};
> > +
> > +static void
> > +iter_pinctrl_settings_get_prepare_message(void *message, u32 desc_index,
> > +					  const void *priv)
> > +{
> > +	struct scmi_msg_settings_get *msg = message;
> > +	const struct scmi_settings_get_ipriv *p = priv;
> > +	u32 attributes;
> > +
> > +	attributes = FIELD_PREP(SELECTOR_MASK, p->type);
> > +
> > +	if (p->get_all) {
> > +		attributes |= FIELD_PREP(CONFIG_FLAG_MASK, 1) |
> > +			FIELD_PREP(SKIP_CONFIGS_MASK, desc_index);
> > +	} else {
> > +		attributes |= FIELD_PREP(CONFIG_TYPE_MASK, p-
> >config_types[0]);
> > +	}
> > +
> > +	msg->attributes = cpu_to_le32(attributes);
> > +	msg->identifier = cpu_to_le32(p->selector); }
> > +
> > +static int
> > +iter_pinctrl_settings_get_update_state(struct scmi_iterator_state *st,
> > +				       const void *response, void *priv) {
> > +	const struct scmi_resp_settings_get *r = response;
> > +	struct scmi_settings_get_ipriv *p = priv;
> > +
> > +	if (p->get_all) {
> > +		st->num_returned = le32_get_bits(r->num_configs,
> GENMASK(7, 0));
> > +		st->num_remaining = le32_get_bits(r->num_configs,
> GENMASK(31, 24));
> > +	} else {
> > +		st->num_returned = 1;
> > +		st->num_remaining = 0;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +iter_pinctrl_settings_get_process_response(const struct
> scmi_protocol_handle *ph,
> > +					   const void *response,
> > +					   struct scmi_iterator_state *st,
> > +					   void *priv)
> > +{
> > +	const struct scmi_resp_settings_get *r = response;
> > +	struct scmi_settings_get_ipriv *p = priv;
> > +	u32 type = le32_get_bits(r->configs[st->loop_idx * 2], GENMASK(7,
> 0));
> > +	u32 val = le32_to_cpu(r->configs[st->loop_idx * 2 + 1]);
> > +
> > +	if (p->get_all) {
> > +		p->config_types[st->desc_index + st->loop_idx] = type;
> > +	} else {
> > +		if (p->config_types[0] != type)
> > +			return -EINVAL;
> > +	}
> > +
> > +	p->config_values[st->desc_index + st->loop_idx] = val;
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +scmi_pinctrl_settings_get(const struct scmi_protocol_handle *ph, u32
> selector,
> > +			  enum scmi_pinctrl_selector_type type,
> > +			  enum scmi_pinctrl_conf_type config_type,
> > +			  u32 *config_value, bool get_all) {
> > +	int ret;
> > +	void *iter;
> > +	struct scmi_iterator_ops ops = {
> > +		.prepare_message =
> iter_pinctrl_settings_get_prepare_message,
> > +		.update_state = iter_pinctrl_settings_get_update_state,
> > +		.process_response =
> iter_pinctrl_settings_get_process_response,
> > +	};
> > +	struct scmi_settings_get_ipriv ipriv = {
> > +		.selector = selector,
> > +		.type = type,
> > +		.get_all = get_all,
> > +		.config_types = &config_type,
> > +		.config_values = config_value,
> > +	};
> > +
> > +	if (!config_value || type == FUNCTION_TYPE)
> > +		return -EINVAL;
> > +
> > +	ret = scmi_pinctrl_validate_id(ph, selector, type);
> > +	if (ret)
> > +		return ret;
> > +
> > +	iter = ph->hops->iter_response_init(ph, &ops, SCMI_PIN_OEM_END,
> > +					    PINCTRL_SETTINGS_GET,
> > +					    sizeof(struct
> scmi_msg_settings_get),
> > +					    &ipriv);
> > +	if (IS_ERR(iter))
> > +		return PTR_ERR(iter);
> > +
> > +	return ph->hops->iter_response_run(iter);
> > +}
> > +
> > +static int scmi_pinctrl_settings_get_one(const struct scmi_protocol_handle
> *ph,
> > +					 u32 selector,
> > +					 enum scmi_pinctrl_selector_type
> type,
> > +					 enum scmi_pinctrl_conf_type
> config_type,
> > +					 u32 *config_value)
> > +{
> > +	return scmi_pinctrl_settings_get(ph, selector, type, config_type,
> > +					 config_value, false);
> > +}
> > +
> > +static int scmi_pinctrl_settings_get_all(const struct scmi_protocol_handle
> *ph,
> > +					 u32 selector,
> > +					 enum scmi_pinctrl_selector_type
> type,
> > +					 enum scmi_pinctrl_conf_type
> config_type,
> > +					 u32 *config_value)
> > +{
> > +	return scmi_pinctrl_settings_get(ph, selector, type, config_type,
> > +					 config_value, true);
> > +}
> > +
> 
> If you generalize the scmi_pinctrl_settings_get() and reintroduce a
> .settings_get_all() ops (even though unused by pinctrl driver, I am fine with
> this..), you should take care to pass as an input parameter NOT only the array
> of config_values BUT also an array of config_types since you could get back
> up to 256 OEM types: for this reason you will need also to pass to
> scmi_pinctrl_settings_get() an input param that specifies the sizes of the
> 2 array input params (in order to avoid oveflows) AND use that same inout
> param also as an output param to report at the end how many OEM types
> were effectively found and returned....
> 
> IOW, I did this on top of your V7 to make the settings_get_all work:
> 
> ---8<---
> diff --git a/drivers/firmware/arm_scmi/pinctrl.c
> b/drivers/firmware/arm_scmi/pinctrl.c
> index b75af1dd75fa..f4937af66c4d 100644
> --- a/drivers/firmware/arm_scmi/pinctrl.c
> +++ b/drivers/firmware/arm_scmi/pinctrl.c
> @@ -317,6 +317,7 @@ struct scmi_settings_get_ipriv {
>  	u32 selector;
>  	enum scmi_pinctrl_selector_type type;
>  	bool get_all;
> +	unsigned int *nr_configs;
>  	enum scmi_pinctrl_conf_type *config_types;
>  	u32 *config_values;
>  };
> @@ -379,6 +380,7 @@ iter_pinctrl_settings_get_process_response(const
> struct scmi_protocol_handle *ph
>  	}
> 
>  	p->config_values[st->desc_index + st->loop_idx] = val;
> +	++*p->nr_configs;
> 
>  	return 0;
>  }
> @@ -386,11 +388,13 @@ iter_pinctrl_settings_get_process_response(const
> struct scmi_protocol_handle *ph  static int  scmi_pinctrl_settings_get(const
> struct scmi_protocol_handle *ph, u32 selector,
>  			  enum scmi_pinctrl_selector_type type,
> -			  enum scmi_pinctrl_conf_type config_type,
> -			  u32 *config_value, bool get_all)
> +			  unsigned int *nr_configs,
> +			  enum scmi_pinctrl_conf_type *config_types,
> +			  u32 *config_values)
>  {
>  	int ret;
>  	void *iter;
> +	unsigned int max_configs = *nr_configs;
>  	struct scmi_iterator_ops ops = {
>  		.prepare_message =
> iter_pinctrl_settings_get_prepare_message,
>  		.update_state = iter_pinctrl_settings_get_update_state,
> @@ -399,19 +403,22 @@ scmi_pinctrl_settings_get(const struct
> scmi_protocol_handle *ph, u32 selector,
>  	struct scmi_settings_get_ipriv ipriv = {
>  		.selector = selector,
>  		.type = type,
> -		.get_all = get_all,
> -		.config_types = &config_type,
> -		.config_values = config_value,
> +		.get_all = (max_configs > 1),
> +		.nr_configs = nr_configs,
> +		.config_types = config_types,
> +		.config_values = config_values,
>  	};
> 
> -	if (!config_value || type == FUNCTION_TYPE)
> +	if (!config_types || !config_values || type == FUNCTION_TYPE)
>  		return -EINVAL;
> 
>  	ret = scmi_pinctrl_validate_id(ph, selector, type);
>  	if (ret)
>  		return ret;
> 
> -	iter = ph->hops->iter_response_init(ph, &ops, SCMI_PIN_OEM_END,
> +	/* Prepare to count returned configs */
> +	*nr_configs = 0;
> +	iter = ph->hops->iter_response_init(ph, &ops, max_configs,
>  					    PINCTRL_SETTINGS_GET,
>  					    sizeof(struct
> scmi_msg_settings_get),
>  					    &ipriv);
> @@ -427,18 +434,24 @@ static int scmi_pinctrl_settings_get_one(const
> struct scmi_protocol_handle *ph,
>  					 enum scmi_pinctrl_conf_type
> config_type,
>  					 u32 *config_value)
>  {
> -	return scmi_pinctrl_settings_get(ph, selector, type, config_type,
> -					 config_value, false);
> +	unsigned int nr_configs = 1;
> +
> +	return scmi_pinctrl_settings_get(ph, selector, type, &nr_configs,
> +					 &config_type, config_value);
>  }
> 
>  static int scmi_pinctrl_settings_get_all(const struct scmi_protocol_handle
> *ph,
>  					 u32 selector,
>  					 enum scmi_pinctrl_selector_type
> type,
> -					 enum scmi_pinctrl_conf_type
> config_type,
> -					 u32 *config_value)
> +					 unsigned int *nr_configs,
> +					 enum scmi_pinctrl_conf_type
> *config_types,
> +					 u32 *config_values)
>  {
> -	return scmi_pinctrl_settings_get(ph, selector, type, config_type,
> -					 config_value, true);
> +	if (!nr_configs || *nr_configs == 0)
> +		return -EINVAL;
> +
> +	return scmi_pinctrl_settings_get(ph, selector, type, nr_configs,
> +					 config_types, config_values);
>  }
> 
>  static int
> diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
> index abaf6122ea37..7915792efd81 100644
> --- a/include/linux/scmi_protocol.h
> +++ b/include/linux/scmi_protocol.h
> @@ -882,8 +882,9 @@ struct scmi_pinctrl_proto_ops {
>  	int (*settings_get_all)(const struct scmi_protocol_handle *ph,
>  				u32 selector,
>  				enum scmi_pinctrl_selector_type type,
> -				enum scmi_pinctrl_conf_type config_type,
> -				u32 *config_value);
> +				unsigned int *nr_configs,
> +				enum scmi_pinctrl_conf_type *config_types,
> +				u32 *config_values);
>  	int (*settings_conf)(const struct scmi_protocol_handle *ph,
>  			     u32 selector, enum scmi_pinctrl_selector_type
> type,
>  			     unsigned int nr_configs,
> --->8-----
> 
> Please check if this addition sounds good to you and integrate into v8
> eventually...

Thanks for helping on this, I will included your changes, and your
Co-developed-by tag if you not mind.

Thanks,
Peng.

> 
> Thanks,
> Cristian

^ permalink raw reply

* RE: [PATCH v6 3/4] firmware: arm_scmi: Add SCMI v3.2 pincontrol protocol basic support
From: Peng Fan @ 2024-04-02 14:01 UTC (permalink / raw)
  To: Andy Shevchenko, Cristian Marussi
  Cc: Peng Fan (OSS), Sudeep Holla, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Linus Walleij, Dan Carpenter,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linux-gpio@vger.kernel.org, Oleksii Moisieiev
In-Reply-To: <CAHp75VdAaTeQ_Ag3gd0s9UfT=kAT2hwibeJ9-YFXJx4z=R3e+g@mail.gmail.com>

> Subject: Re: [PATCH v6 3/4] firmware: arm_scmi: Add SCMI v3.2 pincontrol
> protocol basic support
> 
> On Tue, Apr 2, 2024 at 10:48 AM Cristian Marussi
> <cristian.marussi@arm.com> wrote:
> > On Sun, Mar 31, 2024 at 01:44:28PM +0000, Peng Fan wrote:
> > > > Sat, Mar 23, 2024 at 08:15:16PM +0800, Peng Fan (OSS) kirjoitti:
> 
> ...
> 
> > > > > +#include <linux/module.h>
> > > > > +#include <linux/scmi_protocol.h> #include <linux/slab.h>
> > > >
> > > > This is semi-random list of headers. Please, follow IWYU principle
> > > > (include what you use). There are a lot of inclusions I see
> > > > missing (just in the context of this page I see bits.h, types.h, and
> asm/byteorder.h).
> > >
> > > Is there any documentation about this requirement?
> > > Some headers are already included by others.
> 
> The documentation here is called "a common sense".
> The C language is built like this and we expect that nobody will invest into the
> dependency hell that we have already, that's why IWYU principle, please
> follow it.
> 
> > Andy made (mostly) the same remarks on this same patch ~1-year ago on
> > this same patch while it was posted by Oleksii.
> >
> > And I told that time that most of the remarks around devm_ usage were
> > wrong due to how the SCMI core handles protocol initialization (using
> > a devres group transparently).
> >
> > This is what I answered that time.
> >
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore
> > .kernel.org%2Flinux-arm-kernel%2FZJ78hBcjAhiU%2BZBO%40e120937-
> lin%2F%2
> >
> 3t&data=05%7C02%7Cpeng.fan%40nxp.com%7C3f8c12062db048608e2a08d
> c5315bed
> >
> 0%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6384766000583
> 40430%7CUn
> >
> known%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6I
> k1haW
> >
> wiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=Whn3ehZjXy%2BcKG4irlWjQ6
> K3HF%2FofD
> > Yu7j0Lrm8dN5k%3D&reserved=0
> >
> > I wont repeat myself, but, in a nutshell the memory allocation like it
> > is now is fine: a bit happens via devm_ at protocol initialization,
> > the other is doe via explicit kmalloc at runtime and freed via kfree
> > at remove time (if needed...i.e. checking the present flag of some
> > structs)
> 
> This sounds like a mess. devm_ is expected to be used only for the
> ->probe() stage, otherwise you may consider cleanup.h (__free() macro)
> to have automatic free at the paths where memory is not needed.
> 
> And the function naming doesn't suggest that you have a probe-remove pair.
> Moreover, if the init-deinit part is called in the probe-remove, the devm_
> must not be mixed with non-devm ones, as it breaks the order and leads to
> subtle mistakes.

I am new to __free() honestly. I'll let Cristian and Sudeep to comment on
what should I do for v8.

Thanks,
Peng.

> 
> > I'll made further remarks on v7 that you just posted.
> 
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply

* Re: [PATCH RFT 01/10] arm64: dts: microchip: sparx5: fix mdio reg
From: Steen Hegelund @ 2024-04-02 14:00 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Nicolas Ferre, Claudiu Beznea, Rob Herring, Krzysztof Kozlowski,
	Lars Povlsen, Daniel Machon, UNGLinuxDriver, David S. Miller,
	Bjarni Jonasson, linux-arm-kernel, devicetree, linux-kernel,
	Conor Dooley
In-Reply-To: <20240401153740.123978-1-krzk@kernel.org>

Hi Krzysztof,


On Mon, 2024-04-01 at 17:37 +0200, Krzysztof Kozlowski wrote:
> [Some people who received this message don't often get email from
> krzk@kernel.org. Learn why this is important at
> https://aka.ms/LearnAboutSenderIdentification ]
> 
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
> 
> Correct the reg address of mdio node to match unit address.  Assume
> the
> reg is not correct and unit address was correct, because there is
> alerady node using the existing reg 0x110102d4.
> 
>   sparx5.dtsi:443.25-451.5: Warning (simple_bus_reg):
> /axi@600000000/mdio@6110102f8: simple-bus unit address format error,
> expected "6110102d4"
> 
> Fixes: d0f482bb06f9 ("arm64: dts: sparx5: Add the Sparx5 switch
> node")
> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
> 
> ---
> 
> Not tested on hardware
> ---
>  arch/arm64/boot/dts/microchip/sparx5.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi
> b/arch/arm64/boot/dts/microchip/sparx5.dtsi
> index 24075cd91420..5d820da8c69d 100644
> --- a/arch/arm64/boot/dts/microchip/sparx5.dtsi
> +++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi
> @@ -447,7 +447,7 @@ mdio2: mdio@6110102f8 {
>                         pinctrl-names = "default";
>                         #address-cells = <1>;
>                         #size-cells = <0>;
> -                       reg = <0x6 0x110102d4 0x24>;
> +                       reg = <0x6 0x110102f8 0x24>;
>                 };
> 
>                 mdio3: mdio@61101031c {
> --
> 2.34.1
> 

I did a check of our current Sparx5 EVBs and none of them uses
controller 2 in any revision, so this is probably why it has not come
up before, so as it stands we have no platform to test this change on
currently.

Besides that the change looks good to me.

Best Regards
Steen

Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>



^ permalink raw reply

* Re: [PATCH 6/6] iio: adc: ad7173: Add support for AD411x devices
From: David Lechner @ 2024-04-02 14:00 UTC (permalink / raw)
  To: dumitru.ceclan
  Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-iio,
	devicetree, linux-kernel, Dumitru Ceclan
In-Reply-To: <CAMknhBFdtv84E_S4wa4UW0pO2yiUEk9=jn=_i4F=b8VHdR6v+w@mail.gmail.com>

On Mon, Apr 1, 2024 at 2:45 PM David Lechner <dlechner@baylibre.com> wrote:
>
> On Mon, Apr 1, 2024 at 10:10 AM Dumitru Ceclan via B4 Relay
> <devnull+dumitru.ceclan.analog.com@kernel.org> wrote:
> >
> > From: Dumitru Ceclan <dumitru.ceclan@analog.com>
> >
> > Add support for AD4111/AD4112/AD4114/AD4115/AD4116.
> >

...

> > @@ -1028,15 +1204,22 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
> >                 *chan = ad7173_channel_template;
> >                 chan->address = chan_index;
> >                 chan->scan_index = chan_index;
> > -               chan->channel = ain[0];
> > -               chan->channel2 = ain[1];
> > -               chan->differential = true;
> >
> > -               chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]);
> > +               if (reg >= AD4111_CURRENT_CHAN_CUTOFF) {
> > +                       chan->type = IIO_CURRENT;
> > +                       chan->channel = ain[0];
> > +                       chan_st_priv->ain = ad4111_current_channel_config[ain[0]];
> > +               } else {
> > +                       chan->channel = ain[0];
> > +                       chan->channel2 = ain[1];
> > +                       chan->differential = true;
>
> Expecting chan->differential = false when ADCIN15 is configured for
> pseudo-differential inputs.
>
> Also, perhaps missed in previous reviews, I would expect
> chan->differential = false when channels are used as single-ended.
>

After sleeping on it, I came to the concision that these parts are
probably too complex to try to worry about differential vs.
pseudo-differential/single-ended (what the datasheet calls
single-ended is really pseudo-differential).

So I take back my comments about expecting differential = false in those cases.

^ permalink raw reply

* RE: [PATCH v7 4/4] pinctrl: Implementation of the generic scmi-pinctrl driver
From: Peng Fan @ 2024-04-02 13:59 UTC (permalink / raw)
  To: Andy Shevchenko, Peng Fan (OSS)
  Cc: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Linus Walleij, Dan Carpenter,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linux-gpio@vger.kernel.org, Oleksii Moisieiev
In-Reply-To: <ZgwGpZ6S13vjk8jh@smile.fi.intel.com>

> Subject: Re: [PATCH v7 4/4] pinctrl: Implementation of the generic scmi-
> pinctrl driver
> 
> On Tue, Apr 02, 2024 at 10:22:24AM +0800, Peng Fan (OSS) wrote:
> > From: Peng Fan <peng.fan@nxp.com>
> >
> > scmi-pinctrl driver implements pinctrl driver interface and using SCMI
> > protocol to redirect messages from pinctrl subsystem SDK to SCMI
> > platform firmware, which does the changes in HW.
> 
> ...
> 
> > +#include <linux/device.h>
> > +#include <linux/err.h>
> > +#include <linux/module.h>
> > +#include <linux/seq_file.h>
> > +#include <linux/scmi_protocol.h>
> > +#include <linux/slab.h>
> 
> Missing headers.

Not sure there is an easy way to filter out what is missed.

> 
> ...
> 
> > +	*p_groups = (const char * const *)func->groups;
> 
> Is this casting needed?

This is no needed.

> 
> ...
> 
> > +static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
> > +				    unsigned int _pin, unsigned long *config)
> 
> Why underscored parameter name?

Underscore could be dropped.

> 
> ...
> 
> > +static int pinctrl_scmi_get_pins(struct scmi_pinctrl *pmx,
> > +				 struct pinctrl_desc *desc)
> > +{
> > +	struct pinctrl_pin_desc *pins;
> > +	unsigned int npins;
> > +	int ret, i;
> > +
> > +	npins = pinctrl_ops->count_get(pmx->ph, PIN_TYPE);
> > +	/*
> > +	 * npins will never be zero, the scmi pinctrl driver has bailed out
> > +	 * if npins is zero.
> > +	 */
> 
> This is fragile, but at least it is documented.
> 
> > +	pins = devm_kmalloc_array(pmx->dev, npins, sizeof(*pins),
> GFP_KERNEL);
> > +	if (!pins)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0; i < npins; i++) {
> > +		pins[i].number = i;
> > +		ret = pinctrl_ops->name_get(pmx->ph, i, PIN_TYPE,
> &pins[i].name);
> > +		if (ret)
> 
> How does the cleanup work for the previously assigned pin names? Is it
> needed?

No need. The "name" memory region is allocated in firmware pinctrl
Protocol init phase.

> Maybe a comment?

ok.  As below.
/*
 * The region for name is handled by the scmi firmware driver, 
 * no need free here
*/

> 
> > +			return dev_err_probe(pmx->dev, ret,
> > +					     "Can't get name for pin %d", i);
> > +	}
> > +
> > +	desc->npins = npins;
> > +	desc->pins = pins;
> > +	dev_dbg(pmx->dev, "got pins %u", npins);
> > +
> > +	return 0;
> > +}
> 
> ...
> 
> > +static const struct scmi_device_id scmi_id_table[] = {
> > +	{ SCMI_PROTOCOL_PINCTRL, "pinctrl" },
> > +	{ }
> > +};
> > +MODULE_DEVICE_TABLE(scmi, scmi_id_table);
> 
> Move this closer to the user.

ok. Fix in v8.

Thanks,
Peng.
> 
> --
> With Best Regards,
> Andy Shevchenko
> 


^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: leds: add LED_FUNCTION_FNLOCK
From: Krzysztof Kozlowski @ 2024-04-02 13:55 UTC (permalink / raw)
  To: Gergo Koteles, Ike Panhc, Hans de Goede, Ilpo Järvinen,
	Pavel Machek, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: platform-driver-x86, linux-kernel, linux-leds, devicetree
In-Reply-To: <8ac95e85a53dc0b8cce1e27fc1cab6d19221543b.1712063200.git.soyer@irl.hu>

On 02/04/2024 15:21, Gergo Koteles wrote:
> Newer laptops have FnLock LED.
> 
> Add a define for this very common function.
> 
> Signed-off-by: Gergo Koteles <soyer@irl.hu>
> ---
>  include/dt-bindings/leds/common.h | 1 +

Do we really need to define all these possible LED functions? Please
link to DTS user for this.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH net-next 2/3] net: stmmac: add support for RZ/N1 GMAC
From: Russell King (Oracle) @ 2024-04-02 13:49 UTC (permalink / raw)
  To: Romain Gantois
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Magnus Damm, Alexandre Torgue, Jose Abreu,
	Maxime Coquelin, Clément Léger, Thomas Petazzoni,
	netdev, devicetree, linux-kernel, linux-renesas-soc, linux-stm32,
	linux-arm-kernel
In-Reply-To: <20240402-rzn1-gmac1-v1-2-5be2b2894d8c@bootlin.com>

On Tue, Apr 02, 2024 at 02:37:01PM +0200, Romain Gantois wrote:
> +	ret = stmmac_dvr_probe(dev, plat_dat, &stmmac_res);
> +	if (ret)
> +		return ret;
> +
> +	ndev = platform_get_drvdata(pdev);
> +	priv = netdev_priv(ndev);
> +
> +	pcs_node = of_parse_phandle(np, "pcs-handle", 0);
> +	if (pcs_node) {
> +		pcs = miic_create(dev, pcs_node);
> +		of_node_put(pcs_node);
> +		if (IS_ERR(pcs))
> +			return PTR_ERR(pcs);
> +
> +		priv->hw->phylink_pcs = pcs;
> +	}

I'm afraid that this fails at one of the most basic principles of kernel
multi-threaded programming. stmmac_dvr_probe() as part of its work calls
register_netdev() which publishes to userspace the network device.

Everything that is required must be setup _prior_ to publication to
userspace to avoid races, because as soon as the network device is
published, userspace can decide to bring that interface up. If one
hasn't finished the initialisation, the interface can be brought up
before that initialisation is complete.

I don't see anything obvious in the stmmac data structures that would
allow you to hook in at an appropriate point before the
register_netdev() but after the netdev has been created. The
priv->hw data structure is created by stmmac_hwif_init()

I see that drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c is also
guilty of this as well, and should be fixed. It's even worse because it
does a truck load of stuff after stmmac_dvr_probe() which it most
definitely should not be doing.

I definitely get the feeling that the structure of the stmmac driver
is really getting out of hand, and is making stuff harder for people,
and it's not improving over time - in fact, it's getting worse. It
needs a *lot* of work to bring it back to a sane model.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: arm: ti: Add BeagleY-AI
From: Rob Herring @ 2024-04-02 13:43 UTC (permalink / raw)
  To: Robert Nelson
  Cc: Jason Kridner, linux-arm-kernel, Nishanth Menon, linux-kernel,
	Jared McArthur, devicetree, Deepak Khatri
In-Reply-To: <20240328191205.82295-1-robertcnelson@gmail.com>


On Thu, 28 Mar 2024 14:12:04 -0500, Robert Nelson wrote:
> This board is based on ti,j722s
> 
> https://beagley-ai.org/
> https://openbeagle.org/beagley-ai/beagley-ai
> 
> Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
> CC: Rob Herring <robh@kernel.org>
> CC: Nishanth Menon <nm@ti.com>
> CC: Jared McArthur <j-mcarthur@ti.com>
> CC: Jason Kridner <jkridner@beagleboard.org>
> CC: Deepak Khatri <lorforlinux@beagleboard.org>
> ---
>  Documentation/devicetree/bindings/arm/ti/k3.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring <robh@kernel.org>


^ permalink raw reply

* Re: [PATCH net-next 1/3] dt-bindings: net: renesas,rzn1-gmac: Document RZ/N1 GMAC support
From: Geert Uytterhoeven @ 2024-04-02 13:43 UTC (permalink / raw)
  To: Romain Gantois
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Magnus Damm, Alexandre Torgue, Jose Abreu,
	Maxime Coquelin, Russell King, Clément Léger,
	Thomas Petazzoni, netdev, devicetree, linux-kernel,
	linux-renesas-soc, linux-stm32, linux-arm-kernel
In-Reply-To: <20240402-rzn1-gmac1-v1-1-5be2b2894d8c@bootlin.com>

Hi Romain,

On Tue, Apr 2, 2024 at 2:36 PM Romain Gantois
<romain.gantois@bootlin.com> wrote:
> From: Clément Léger <clement.leger@bootlin.com>
>
> The RZ/N1 series of MPUs feature up to two Gigabit Ethernet controllers.
> These controllers are based on Synopsys IPs. They can be connected to
> RZ/N1 RGMII/RMII converters.
>
> Add a binding that describes these GMAC devices.
>
> Signed-off-by: "Clément Léger" <clement.leger@bootlin.com>
> [rgantois: commit log]
> Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>

Thanks for your patch!

> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/renesas,rzn1-gmac.yaml

> +examples:
> +  - |
> +    #include <dt-bindings/clock/r9a06g032-sysctrl.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    ethernet@44000000 {
> +      compatible = "renesas,r9a06g032-gmac", "renesas,rzn1-gmac", "snps,dwmac";
> +      reg = <0x44000000 0x2000>;
> +      interrupt-parent = <&gic>;

There is no need to use interrupt-parent in examples.

> +      interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
> +                   <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
> +                   <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
> +      interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
> +      clock-names = "stmmaceth";
> +      clocks = <&sysctrl R9A06G032_HCLK_GMAC0>;

If you want this to be a real example, you should add power-domains.

> +      snps,multicast-filter-bins = <256>;
> +      snps,perfect-filter-entries = <128>;
> +      tx-fifo-depth = <2048>;
> +      rx-fifo-depth = <4096>;
> +      pcs-handle = <&mii_conv1>;
> +      phy-mode = "mii";
> +    };

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH net-next v6 14/17] dt-bindings: net: pse-pd: Add bindings for PD692x0 PSE controller
From: Rob Herring @ 2024-04-02 13:28 UTC (permalink / raw)
  To: Kory Maincent
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Jonathan Corbet, Luis Chamberlain, Russ Weight,
	Greg Kroah-Hartman, Rafael J. Wysocki, Krzysztof Kozlowski,
	Conor Dooley, Oleksij Rempel, Mark Brown, Frank Rowand,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Petazzoni,
	netdev, linux-kernel, linux-doc, devicetree, Dent Project
In-Reply-To: <20240326-feature_poe-v6-14-c1011b6ea1cb@bootlin.com>

On Tue, Mar 26, 2024 at 03:04:51PM +0100, Kory Maincent wrote:
> From: Kory Maincent (Dent Project) <kory.maincent@bootlin.com>
> 
> Add the PD692x0 I2C Power Sourcing Equipment controller device tree
> bindings documentation.
> 
> Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
> ---
> 
> Changes in v2:
> - Enhance ports-matrix description.
> - Replace additionalProperties by unevaluatedProperties.
> - Drop i2c suffix.
> 
> Changes in v3:
> - Remove ports-matrix parameter.
> - Add description of all physical ports and managers.
> - Add pse_pis subnode moving to the API of pse-controller binding.
> - Remove the MAINTAINERS section for this driver as I will be maintaining
>   all pse-pd subsystem.
> 
> Changes in v5:
> - Remove defs used only once.
> - Replace underscore by dash.
> - Add description.
> ---
>  .../bindings/net/pse-pd/microchip,pd692x0.yaml     | 158 +++++++++++++++++++++
>  1 file changed, 158 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/net/pse-pd/microchip,pd692x0.yaml b/Documentation/devicetree/bindings/net/pse-pd/microchip,pd692x0.yaml
> new file mode 100644
> index 000000000000..62ea4363cba3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/pse-pd/microchip,pd692x0.yaml
> @@ -0,0 +1,158 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/pse-pd/microchip,pd692x0.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip PD692x0 Power Sourcing Equipment controller
> +
> +maintainers:
> +  - Kory Maincent <kory.maincent@bootlin.com>
> +
> +allOf:
> +  - $ref: pse-controller.yaml#
> +
> +properties:
> +  compatible:
> +    enum:
> +      - microchip,pd69200
> +      - microchip,pd69210
> +      - microchip,pd69220
> +
> +  reg:
> +    maxItems: 1
> +
> +  managers:
> +    type: object
> +    description:
> +      List of the PD69208T4/PD69204T4/PD69208M PSE managers. Each manager
> +      have 4 or 8 physical ports according to the chip version. No need to
> +      specify the SPI chip select as it is automatically detected by the
> +      PD692x0 PSE controller. The PSE managers have to be described from
> +      the lowest chip select to the greatest one, which is the detection
> +      behavior of the PD692x0 PSE controller. The PD692x0 support up to
> +      12 PSE managers which can expose up to 96 physical ports. All
> +      physical ports available on a manager have to be described in the
> +      incremental order even if they are not used.
> +
> +    properties:
> +      "#address-cells":
> +        const: 1
> +
> +      "#size-cells":
> +        const: 0
> +
> +    required:
> +      - "#address-cells"
> +      - "#size-cells"
> +
> +    patternProperties:
> +      "^manager@0[0-9]|1[0-2]$":

Unit-addresses are typically in hex.

Is 'manager' something specific to this device or should be common?

> +        $ref: /schemas/graph.yaml#/properties/ports

This is not using the graph binding. Furthermore, I don't want to see 
new cases of 'port' node names which are not graph nodes. We have it 
already with ethernet switches, but 'ethernet-port' is preferred over 
'port'.

Why is this one 'managers' and the other device binding 'channels'?

> +        description:
> +          PD69208T4/PD69204T4/PD69208M PSE manager exposing 4 or 8 physical
> +          ports.
> +
> +        properties:
> +          reg:
> +            description:
> +              Incremental index of the PSE manager starting from 0, ranging
> +              from lowest to highest chip select, up to 12.
> +            maxItems: 1
> +
> +        patternProperties:
> +          '^port@[0-7]$':
> +            type: object
> +            required:
> +              - reg

Any property you want is allowed in this node. You are missing 
'additionalProperties'.

> +
> +        required:
> +          - reg
> +
> +required:
> +  - compatible
> +  - reg
> +  - pse-pis
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    i2c {
> +      #address-cells = <1>;
> +      #size-cells = <0>;
> +
> +      ethernet-pse@3c {
> +        compatible = "microchip,pd69200";
> +        reg = <0x3c>;
> +
> +        managers {
> +          #address-cells = <1>;
> +          #size-cells = <0>;
> +
> +          manager@0 {
> +            reg = <0>;
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +
> +            phys0: port@0 {
> +              reg = <0>;
> +            };
> +
> +            phys1: port@1 {
> +              reg = <1>;
> +            };
> +
> +            phys2: port@2 {
> +              reg = <2>;
> +            };
> +
> +            phys3: port@3 {
> +              reg = <3>;
> +            };
> +          };
> +
> +          manager@1 {
> +            reg = <1>;
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +
> +            phys4: port@0 {
> +              reg = <0>;
> +            };
> +
> +            phys5: port@1 {
> +              reg = <1>;
> +            };
> +
> +            phys6: port@2 {
> +              reg = <2>;
> +            };
> +
> +            phys7: port@3 {
> +              reg = <3>;
> +            };
> +          };
> +        };
> +
> +        pse-pis {
> +          #address-cells = <1>;
> +          #size-cells = <0>;
> +
> +          pse_pi0: pse-pi@0 {
> +            reg = <0>;
> +            #pse-cells = <0>;
> +            pairset-names = "alternative-a", "alternative-b";
> +            pairsets = <&phys0>, <&phys1>;

It is very strange that you are describing the connections within a 
device.


> +            polarity-supported = "MDI", "S";
> +          };
> +          pse_pi1: pse-pi@1 {
> +            reg = <1>;
> +            #pse-cells = <0>;
> +            pairset-names = "alternative-a";
> +            pairsets = <&phys2>;
> +            polarity-supported = "MDI";
> +          };
> +        };
> +      };
> +    };
> 
> -- 
> 2.25.1
> 

^ permalink raw reply

* RE: [PATCH v7 3/4] firmware: arm_scmi: Add SCMI v3.2 pincontrol protocol basic support
From: Peng Fan @ 2024-04-02 13:27 UTC (permalink / raw)
  To: Andy Shevchenko, Peng Fan (OSS)
  Cc: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Linus Walleij, Dan Carpenter,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linux-gpio@vger.kernel.org, Oleksii Moisieiev
In-Reply-To: <ZgwEtxj-qi6uy_m2@smile.fi.intel.com>

Hi Andy

> Subject: Re: [PATCH v7 3/4] firmware: arm_scmi: Add SCMI v3.2 pincontrol
> protocol basic support
> 
> On Tue, Apr 02, 2024 at 10:22:23AM +0800, Peng Fan (OSS) wrote:
> 
> ...
> 
> > +#include <linux/module.h>
> > +#include <linux/scmi_protocol.h>
> > +#include <linux/slab.h>
> 
> Please, follow IWYU principle, a lot of headers are missed.

ok. I will try to figure out. BTW, is there an easy way to filter
out what is missed?

> 
> > +#include "common.h"
> > +#include "protocols.h"
> 
> ...
> 
> > +		ret = scmi_pinctrl_get_pin_info(ph, selector,
> > +						&pi->pins[selector]);
> 
> It's netter as a single line.

I try to follow 80 max chars per SCMI coding style. If Sudeep and Cristian
is ok, I could use a single line.

> 
> > +		if (ret)
> > +			return ret;
> > +	}
> 
> ...
> 
> > +static int scmi_pinctrl_protocol_init(const struct
> > +scmi_protocol_handle *ph) {
> > +	int ret;
> > +	u32 version;
> > +	struct scmi_pinctrl_info *pinfo;
> > +
> > +	ret = ph->xops->version_get(ph, &version);
> > +	if (ret)
> > +		return ret;
> > +
> > +	dev_dbg(ph->dev, "Pinctrl Version %d.%d\n",
> > +		PROTOCOL_REV_MAJOR(version),
> PROTOCOL_REV_MINOR(version));
> > +
> > +	pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
> > +	if (!pinfo)
> > +		return -ENOMEM;
> > +
> > +	ret = scmi_pinctrl_attributes_get(ph, pinfo);
> > +	if (ret)
> > +		return ret;
> > +
> > +	pinfo->pins = devm_kcalloc(ph->dev, pinfo->nr_pins,
> > +				   sizeof(*pinfo->pins), GFP_KERNEL);
> > +	if (!pinfo->pins)
> > +		return -ENOMEM;
> > +
> > +	pinfo->groups = devm_kcalloc(ph->dev, pinfo->nr_groups,
> > +				     sizeof(*pinfo->groups), GFP_KERNEL);
> > +	if (!pinfo->groups)
> > +		return -ENOMEM;
> > +
> > +	pinfo->functions = devm_kcalloc(ph->dev, pinfo->nr_functions,
> > +					sizeof(*pinfo->functions),
> GFP_KERNEL);
> > +	if (!pinfo->functions)
> > +		return -ENOMEM;
> > +
> > +	pinfo->version = version;
> > +
> > +	return ph->set_priv(ph, pinfo, version);
> 
> Same comments as per previous version. devm_ here is simply wrong.
> It breaks the order of freeing resources.
> 
> I.o.w. I see *no guarantee* that these init-deinit functions will be properly
> called from the respective probe-remove. Moreover the latter one may also
> have its own devm allocations (which are rightfully placed) and you get
> completely out of control the resource management.

I see an old thread.
https://lore.kernel.org/linux-arm-kernel/ZJ78hBcjAhiU+ZBO@e120937-lin/#t

The free in deinit is not to free the ones alloced in init, it is to free the ones
alloced such as in scmi_pinctrl_get_function_info

Thanks,
Peng.

> 
> > +}
> 
> --
> With Best Regards,
> Andy Shevchenko
> 


^ permalink raw reply

* [Patch v2 2/2] memory: tegra: make sid and broadcast regions optional
From: Sumit Gupta @ 2024-04-02 13:26 UTC (permalink / raw)
  To: krzysztof.kozlowski, robh, conor+dt, maz, mark.rutland, treding,
	jonathanh
  Cc: devicetree, linux-kernel, linux-tegra, amhetre, bbasu, sumitg
In-Reply-To: <20240402132626.24693-1-sumitg@nvidia.com>

MC SID and Broadbast channel register access is restricted for Guest VM.
In Tegra MC driver, consider both the regions as optional and skip
access to restricted registers from Guest if a region is not present
in Guest DT.

Signed-off-by: Sumit Gupta <sumitg@nvidia.com>
---
 drivers/memory/tegra/mc.c       |  9 ++++++++-
 drivers/memory/tegra/mc.h       | 18 +++++++++---------
 drivers/memory/tegra/tegra186.c | 22 ++++++++++++----------
 3 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index 224b488794e5..d819dab1b223 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -899,6 +899,7 @@ static void tegra_mc_num_channel_enabled(struct tegra_mc *mc)
 
 static int tegra_mc_probe(struct platform_device *pdev)
 {
+	struct resource *res;
 	struct tegra_mc *mc;
 	u64 mask;
 	int err;
@@ -923,7 +924,13 @@ static int tegra_mc_probe(struct platform_device *pdev)
 	/* length of MC tick in nanoseconds */
 	mc->tick = 30;
 
-	mc->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (mc->soc->num_channels) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sid");
+		if (res)
+			mc->regs = devm_ioremap_resource(&pdev->dev, res);
+	} else {
+		mc->regs = devm_platform_ioremap_resource(pdev, 0);
+	}
 	if (IS_ERR(mc->regs))
 		return PTR_ERR(mc->regs);
 
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index c3f6655bec60..5cdb9451f364 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -112,11 +112,11 @@ icc_provider_to_tegra_mc(struct icc_provider *provider)
 static inline u32 mc_ch_readl(const struct tegra_mc *mc, int ch,
 			      unsigned long offset)
 {
-	if (!mc->bcast_ch_regs)
-		return 0;
-
-	if (ch == MC_BROADCAST_CHANNEL)
+	if (ch == MC_BROADCAST_CHANNEL) {
+		if (!mc->bcast_ch_regs)
+			return 0;
 		return readl_relaxed(mc->bcast_ch_regs + offset);
+	}
 
 	return readl_relaxed(mc->ch_regs[ch] + offset);
 }
@@ -124,13 +124,13 @@ static inline u32 mc_ch_readl(const struct tegra_mc *mc, int ch,
 static inline void mc_ch_writel(const struct tegra_mc *mc, int ch,
 				u32 value, unsigned long offset)
 {
-	if (!mc->bcast_ch_regs)
-		return;
-
-	if (ch == MC_BROADCAST_CHANNEL)
+	if (ch == MC_BROADCAST_CHANNEL) {
+		if (!mc->bcast_ch_regs)
+			return;
 		writel_relaxed(value, mc->bcast_ch_regs + offset);
-	else
+	} else {
 		writel_relaxed(value, mc->ch_regs[ch] + offset);
+	}
 }
 
 static inline u32 mc_readl(const struct tegra_mc *mc, unsigned long offset)
diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
index 1b3183951bfe..7b5e9bd13ffd 100644
--- a/drivers/memory/tegra/tegra186.c
+++ b/drivers/memory/tegra/tegra186.c
@@ -26,20 +26,16 @@
 static int tegra186_mc_probe(struct tegra_mc *mc)
 {
 	struct platform_device *pdev = to_platform_device(mc->dev);
+	struct resource *res;
 	unsigned int i;
 	char name[8];
 	int err;
 
-	mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "broadcast");
-	if (IS_ERR(mc->bcast_ch_regs)) {
-		if (PTR_ERR(mc->bcast_ch_regs) == -EINVAL) {
-			dev_warn(&pdev->dev,
-				 "Broadcast channel is missing, please update your device-tree\n");
-			mc->bcast_ch_regs = NULL;
-			goto populate;
-		}
-
-		return PTR_ERR(mc->bcast_ch_regs);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "broadcast");
+	if (res) {
+		mc->bcast_ch_regs = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(mc->bcast_ch_regs))
+			return PTR_ERR(mc->bcast_ch_regs);
 	}
 
 	mc->ch_regs = devm_kcalloc(mc->dev, mc->soc->num_channels, sizeof(*mc->ch_regs),
@@ -121,6 +117,9 @@ static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
 	if (!tegra_dev_iommu_get_stream_id(dev, &sid))
 		return 0;
 
+	if (!mc->regs)
+		return 0;
+
 	while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells",
 					   index, &args)) {
 		if (args.np == mc->dev->of_node && args.args_count != 0) {
@@ -146,6 +145,9 @@ static int tegra186_mc_resume(struct tegra_mc *mc)
 #if IS_ENABLED(CONFIG_IOMMU_API)
 	unsigned int i;
 
+	if (!mc->regs)
+		return 0;
+
 	for (i = 0; i < mc->soc->num_clients; i++) {
 		const struct tegra_mc_client *client = &mc->soc->clients[i];
 
-- 
2.17.1


^ permalink raw reply related

* [Patch v2 1/2] dt-bindings: make sid and broadcast reg optional
From: Sumit Gupta @ 2024-04-02 13:26 UTC (permalink / raw)
  To: krzysztof.kozlowski, robh, conor+dt, maz, mark.rutland, treding,
	jonathanh
  Cc: devicetree, linux-kernel, linux-tegra, amhetre, bbasu, sumitg
In-Reply-To: <20240402132626.24693-1-sumitg@nvidia.com>

MC SID and Broadbast channel register access is restricted for Guest VM.
Make both the regions as optional for SoC's from Tegra186 onwards.
Tegra MC driver will skip access to the restricted registers from Guest
if the respective regions are not present in the memory-controller node
of Guest DT.

Signed-off-by: Sumit Gupta <sumitg@nvidia.com>
---
 .../memory-controllers/nvidia,tegra186-mc.yaml | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
index 935d63d181d9..c52c259f7ec5 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
@@ -146,17 +146,17 @@ allOf:
     then:
       properties:
         reg:
-          maxItems: 6
+          maxItems: 4
           description: 5 memory controller channels and 1 for stream-id registers
 
         reg-names:
           items:
-            - const: sid
-            - const: broadcast
             - const: ch0
             - const: ch1
             - const: ch2
             - const: ch3
+            - const: sid
+            - const: broadcast
 
   - if:
       properties:
@@ -165,13 +165,11 @@ allOf:
     then:
       properties:
         reg:
-          minItems: 18
+          minItems: 16
           description: 17 memory controller channels and 1 for stream-id registers
 
         reg-names:
           items:
-            - const: sid
-            - const: broadcast
             - const: ch0
             - const: ch1
             - const: ch2
@@ -188,6 +186,8 @@ allOf:
             - const: ch13
             - const: ch14
             - const: ch15
+            - const: sid
+            - const: broadcast
 
   - if:
       properties:
@@ -196,13 +196,11 @@ allOf:
     then:
       properties:
         reg:
-          minItems: 18
+          minItems: 16
           description: 17 memory controller channels and 1 for stream-id registers
 
         reg-names:
           items:
-            - const: sid
-            - const: broadcast
             - const: ch0
             - const: ch1
             - const: ch2
@@ -219,6 +217,8 @@ allOf:
             - const: ch13
             - const: ch14
             - const: ch15
+            - const: sid
+            - const: broadcast
 
 additionalProperties: false
 
-- 
2.17.1


^ permalink raw reply related

* [Patch v2 0/2] memory: tegra: Skip restricted register access from Guest
From: Sumit Gupta @ 2024-04-02 13:26 UTC (permalink / raw)
  To: krzysztof.kozlowski, robh, conor+dt, maz, mark.rutland, treding,
	jonathanh
  Cc: devicetree, linux-kernel, linux-tegra, amhetre, bbasu, sumitg

MC SID and Broadbast channel register access is restricted for Guest VM.
But the Tegra MC driver is considering both these regions as mandatory
and causes error on access. Change that to consider both the regions as
optional in SoC's from Tegra186 onwards. Then skip access to the
restricted registers from Guest if its region is not present in Guest DT
and hence not mapped.
Previously, the solution in [1] was not accepted. Now, handled the
problem with this alternate solution.

---
v1[1] -> v2:
- consider broadcast channel registers also as restricted along with sid.
- make sid and broadcast regions optional and access if present in dt.
- update the yaml file.

Sumit Gupta (2):
  dt-bindings: make sid and broadcast reg optional
  memory: tegra: make sid and broadcast regions optional

 .../nvidia,tegra186-mc.yaml                   | 18 +++++++--------
 drivers/memory/tegra/mc.c                     |  9 +++++++-
 drivers/memory/tegra/mc.h                     | 18 +++++++--------
 drivers/memory/tegra/tegra186.c               | 22 ++++++++++---------
 4 files changed, 38 insertions(+), 29 deletions(-)

[1] https://lore.kernel.org/lkml/20240206114852.8472-1-sumitg@nvidia.com/

-- 
2.17.1


^ permalink raw reply

* Re: [PATCH net-next v6 11/17] dt-bindings: net: pse-pd: Add another way of describing several PSE PIs
From: Rob Herring @ 2024-04-02 13:26 UTC (permalink / raw)
  To: Kory Maincent
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Jonathan Corbet, Luis Chamberlain, Russ Weight,
	Greg Kroah-Hartman, Rafael J. Wysocki, Krzysztof Kozlowski,
	Conor Dooley, Oleksij Rempel, Mark Brown, Frank Rowand,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Petazzoni,
	netdev, linux-kernel, linux-doc, devicetree, Dent Project
In-Reply-To: <20240326-feature_poe-v6-11-c1011b6ea1cb@bootlin.com>

On Tue, Mar 26, 2024 at 03:04:48PM +0100, Kory Maincent wrote:
> From: Kory Maincent (Dent Project) <kory.maincent@bootlin.com>
> 
> PSE PI setup may encompass multiple PSE controllers or auxiliary circuits
> that collectively manage power delivery to one Ethernet port.
> Such configurations might support a range of PoE standards and require
> the capability to dynamically configure power delivery based on the
> operational mode (e.g., PoE2 versus PoE4) or specific requirements of
> connected devices. In these instances, a dedicated PSE PI node becomes
> essential for accurately documenting the system architecture. This node
> would serve to detail the interactions between different PSE controllers,
> the support for various PoE modes, and any additional logic required to
> coordinate power delivery across the network infrastructure.
> 
> The old usage of "#pse-cells" is unsuficient as it carries only the PSE PI
> index information.
> 
> Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
> ---
> 
> Changes in v3:
> - New patch
> 
> Changes in v4:
> - Remove $def
> - Fix pairset-names item list
> - Upgrade few properties description
> - Update the commit message
> 
> Changes in v5:
> - Fix yamllint error.
> - Replace underscore by dash in properties names.
> - Add polarity-supported property.
> 
> Changes in v6:
> - Reorder the pairset pinout table documentation to shrink the lines size.
> - Remove pairset and polarity as required fields.
> - Add vpwr-supply regulator supply.
> ---
>  .../bindings/net/pse-pd/pse-controller.yaml        | 102 ++++++++++++++++++++-
>  1 file changed, 99 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml b/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml
> index 2d382faca0e6..03f7f215c162 100644
> --- a/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml
> +++ b/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml
> @@ -13,6 +13,7 @@ description: Binding for the Power Sourcing Equipment (PSE) as defined in the
>  
>  maintainers:
>    - Oleksij Rempel <o.rempel@pengutronix.de>
> +  - Kory Maincent <kory.maincent@bootlin.com>
>  
>  properties:
>    $nodename:
> @@ -22,11 +23,106 @@ properties:
>      description:
>        Used to uniquely identify a PSE instance within an IC. Will be
>        0 on PSE nodes with only a single output and at least 1 on nodes
> -      controlling several outputs.
> +      controlling several outputs which are not described in the pse-pis
> +      subnode. This property is deprecated, please use pse-pis instead.
>      enum: [0, 1]
>  
> -required:
> -  - "#pse-cells"
> +  pse-pis:
> +    type: object
> +    description:
> +      Overview of the PSE PIs provided by the controller.
> +
> +    properties:
> +      "#address-cells":
> +        const: 1
> +
> +      "#size-cells":
> +        const: 0
> +
> +    required:
> +      - "#address-cells"
> +      - "#size-cells"
> +
> +    patternProperties:
> +      "^pse-pi@[0-9a-f]+$":
> +        type: object
> +        description:
> +          PSE PI for power delivery via pairsets, compliant with IEEE
> +          802.3-2022, Section 145.2.4. Each pairset comprises a positive and
> +          a negative VPSE pair, adhering to the pinout configurations
> +          detailed in the standard.
> +          See Documentation/networking/pse-pd/pse-pi.rst for details.
> +
> +        properties:
> +          reg:
> +            description:
> +              Address describing the PSE PI index.
> +            maxItems: 1
> +
> +          "#pse-cells":
> +            const: 0
> +
> +          pairset-names:
> +            $ref: /schemas/types.yaml#/definitions/string-array
> +            description:
> +              Names of the pairsets as per IEEE 802.3-2022, Section 145.2.4.
> +              Valid values are "alternative-a" and "alternative-b". Each name

Don't state constraints in prose which are defined as schema 
constraints.

> +              should correspond to a phandle in the 'pairset' property
> +              pointing to the power supply for that pairset.
> +            minItems: 1
> +            maxItems: 2
> +            items:
> +              enum:
> +                - alternative-a
> +                - alternative-b
> +
> +          pairsets:
> +            $ref: /schemas/types.yaml#/definitions/phandle-array
> +            description:
> +              List of phandles, each pointing to the power supply for the
> +              corresponding pairset named in 'pairset-names'. This property
> +              aligns with IEEE 802.3-2022, Section 33.2.3 and 145.2.4.
> +              PSE Pinout Alternatives (as per IEEE 802.3-2022 Table 145\u20133)
> +              |-----------|---------------|---------------|---------------|---------------|
> +              | Conductor | Alternative A | Alternative A | Alternative B | Alternative B |
> +              |           |    (MDI-X)    |     (MDI)     |      (X)      |      (S)      |
> +              |-----------|---------------|---------------|---------------|---------------|
> +              | 1         | Negative VPSE | Positive VPSE | \u2014             | \u2014             |
> +              | 2         | Negative VPSE | Positive VPSE | \u2014             | \u2014             |
> +              | 3         | Positive VPSE | Negative VPSE | \u2014             | \u2014             |
> +              | 4         | \u2014             | \u2014             | Negative VPSE | Positive VPSE |
> +              | 5         | \u2014             | \u2014             | Negative VPSE | Positive VPSE |
> +              | 6         | Positive VPSE | Negative VPSE | \u2014             | \u2014             |
> +              | 7         | \u2014             | \u2014             | Positive VPSE | Negative VPSE |
> +              | 8         | \u2014             | \u2014             | Positive VPSE | Negative VPSE |
> +            minItems: 1
> +            maxItems: 2

"pairsets" does not follow the normal design pattern of foos, foo-names, 
and #foo-cells. You could add #foo-cells I suppose, but what would cells 
convey? I don't think it's a good fit for what you need.

The other oddity is the number of entries and the names are fixed. That 
is usually defined per consumer. 

As each entry is just a power rail, why can't the regulator binding be 
used here?

> +
> +          polarity-supported:
> +            $ref: /schemas/types.yaml#/definitions/string-array
> +            description:
> +              Polarity configuration supported by the PSE PI pairsets.
> +            minItems: 1
> +            maxItems: 4
> +            items:
> +              enum:
> +                - MDI-X
> +                - MDI
> +                - X
> +                - S
> +
> +          vpwr-supply:
> +            description: Regulator power supply for the PSE PI.

I don't see this being used anywhere.

> +
> +        required:
> +          - reg
> +          - "#pse-cells"
> +
> +oneOf:
> +  - required:
> +      - "#pse-cells"
> +  - required:
> +      - pse-pis
>  
>  additionalProperties: true
>  
> 
> -- 
> 2.25.1
> 

^ permalink raw reply

* Re: [PATCH v7 4/4] pinctrl: Implementation of the generic scmi-pinctrl driver
From: Andy Shevchenko @ 2024-04-02 13:22 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Linus Walleij, Dan Carpenter, linux-arm-kernel,
	linux-kernel, devicetree, linux-gpio, Peng Fan, Oleksii Moisieiev
In-Reply-To: <20240402-pinctrl-scmi-v7-4-3ea519d12cf7@nxp.com>

On Tue, Apr 02, 2024 at 10:22:24AM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> scmi-pinctrl driver implements pinctrl driver interface and using
> SCMI protocol to redirect messages from pinctrl subsystem SDK to
> SCMI platform firmware, which does the changes in HW.

...

> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/module.h>
> +#include <linux/seq_file.h>
> +#include <linux/scmi_protocol.h>
> +#include <linux/slab.h>

Missing headers.

...

> +	*p_groups = (const char * const *)func->groups;

Is this casting needed?

...

> +static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
> +				    unsigned int _pin, unsigned long *config)

Why underscored parameter name?

...

> +static int pinctrl_scmi_get_pins(struct scmi_pinctrl *pmx,
> +				 struct pinctrl_desc *desc)
> +{
> +	struct pinctrl_pin_desc *pins;
> +	unsigned int npins;
> +	int ret, i;
> +
> +	npins = pinctrl_ops->count_get(pmx->ph, PIN_TYPE);
> +	/*
> +	 * npins will never be zero, the scmi pinctrl driver has bailed out
> +	 * if npins is zero.
> +	 */

This is fragile, but at least it is documented.

> +	pins = devm_kmalloc_array(pmx->dev, npins, sizeof(*pins), GFP_KERNEL);
> +	if (!pins)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < npins; i++) {
> +		pins[i].number = i;
> +		ret = pinctrl_ops->name_get(pmx->ph, i, PIN_TYPE, &pins[i].name);
> +		if (ret)

How does the cleanup work for the previously assigned pin names? Is it needed?
Maybe a comment?

> +			return dev_err_probe(pmx->dev, ret,
> +					     "Can't get name for pin %d", i);
> +	}
> +
> +	desc->npins = npins;
> +	desc->pins = pins;
> +	dev_dbg(pmx->dev, "got pins %u", npins);
> +
> +	return 0;
> +}

...

> +static const struct scmi_device_id scmi_id_table[] = {
> +	{ SCMI_PROTOCOL_PINCTRL, "pinctrl" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(scmi, scmi_id_table);

Move this closer to the user.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* [PATCH 3/3] platform/x86: ideapad-laptop: add FnLock LED class device
From: Gergo Koteles @ 2024-04-02 13:21 UTC (permalink / raw)
  To: Ike Panhc, Hans de Goede, Ilpo Järvinen, Pavel Machek,
	Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: platform-driver-x86, linux-kernel, linux-leds, devicetree,
	Gergo Koteles
In-Reply-To: <cover.1712063200.git.soyer@irl.hu>

Some Ideapad/Yoga Laptops have an FnLock LED in the Esc key.

Expose Fnlock as an LED class device for easier OSD support.

Signed-off-by: Gergo Koteles <soyer@irl.hu>
---
 drivers/platform/x86/ideapad-laptop.c | 97 ++++++++++++++++++++++++++-
 1 file changed, 96 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 529df08af548..8a5bef4eedfe 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -152,6 +152,11 @@ struct ideapad_private {
 		struct led_classdev led;
 		unsigned int last_brightness;
 	} kbd_bl;
+	struct {
+		bool initialized;
+		struct led_classdev led;
+		unsigned int last_brightness;
+	} fn_lock;
 };
 
 static bool no_bt_rfkill;
@@ -531,6 +536,19 @@ static int ideapad_fn_lock_set(struct ideapad_private *priv, bool state)
 		state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
 }
 
+static void ideapad_fn_lock_led_notify(struct ideapad_private *priv, int brightness)
+{
+	if (!priv->fn_lock.initialized)
+		return;
+
+	if (brightness == priv->fn_lock.last_brightness)
+		return;
+
+	priv->fn_lock.last_brightness = brightness;
+
+	led_classdev_notify_brightness_hw_changed(&priv->fn_lock.led, brightness);
+}
+
 static ssize_t fn_lock_show(struct device *dev,
 			    struct device_attribute *attr,
 			    char *buf)
@@ -561,6 +579,8 @@ static ssize_t fn_lock_store(struct device *dev,
 	if (err)
 		return err;
 
+	ideapad_fn_lock_led_notify(priv, state);
+
 	return count;
 }
 
@@ -1479,6 +1499,65 @@ static void ideapad_kbd_bl_exit(struct ideapad_private *priv)
 	led_classdev_unregister(&priv->kbd_bl.led);
 }
 
+/*
+ * FnLock LED
+ */
+static enum led_brightness ideapad_fn_lock_led_cdev_get(struct led_classdev *led_cdev)
+{
+	struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, fn_lock.led);
+
+	return ideapad_fn_lock_get(priv);
+}
+
+static int ideapad_fn_lock_led_cdev_set(struct led_classdev *led_cdev,
+	enum led_brightness brightness)
+{
+	struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, fn_lock.led);
+
+	return ideapad_fn_lock_set(priv, brightness);
+}
+
+static int ideapad_fn_lock_led_init(struct ideapad_private *priv)
+{
+	int brightness, err;
+
+	if (!priv->features.fn_lock)
+		return -ENODEV;
+
+	if (WARN_ON(priv->fn_lock.initialized))
+		return -EEXIST;
+
+	priv->fn_lock.led.max_brightness = 1;
+
+	brightness = ideapad_fn_lock_get(priv);
+	if (brightness < 0)
+		return brightness;
+
+	priv->fn_lock.last_brightness = brightness;
+	priv->fn_lock.led.name                    = "platform::" LED_FUNCTION_FNLOCK;
+	priv->fn_lock.led.brightness_get          = ideapad_fn_lock_led_cdev_get;
+	priv->fn_lock.led.brightness_set_blocking = ideapad_fn_lock_led_cdev_set;
+	priv->fn_lock.led.flags                   = LED_BRIGHT_HW_CHANGED;
+
+	err = led_classdev_register(&priv->platform_device->dev, &priv->fn_lock.led);
+	if (err)
+		return err;
+
+	priv->fn_lock.initialized = true;
+
+	return 0;
+}
+
+static void ideapad_fn_lock_led_exit(struct ideapad_private *priv)
+{
+	if (!priv->fn_lock.initialized)
+		return;
+
+	priv->fn_lock.initialized = false;
+
+	led_classdev_unregister(&priv->fn_lock.led);
+}
+
 /*
  * module init/exit
  */
@@ -1741,8 +1820,10 @@ static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data)
 		if (priv->features.set_fn_lock_led) {
 			int brightness = ideapad_fn_lock_get(priv);
 
-			if (brightness >= 0)
+			if (brightness >= 0) {
 				ideapad_fn_lock_set(priv, brightness);
+				ideapad_fn_lock_led_notify(priv, brightness);
+			}
 		}
 
 		if (data->type != ACPI_TYPE_INTEGER) {
@@ -1754,6 +1835,10 @@ static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data)
 		dev_dbg(&wdev->dev, "WMI fn-key event: 0x%llx\n",
 			data->integer.value);
 
+		/* 0x02 FnLock, 0x03 Esc */
+		if (data->integer.value == 0x02 || data->integer.value == 0x03)
+			ideapad_fn_lock_led_notify(priv, data->integer.value == 0x02);
+
 		ideapad_input_report(priv,
 				     data->integer.value | IDEAPAD_WMI_KEY);
 
@@ -1847,6 +1932,14 @@ static int ideapad_acpi_add(struct platform_device *pdev)
 			dev_info(&pdev->dev, "Keyboard backlight control not available\n");
 	}
 
+	err = ideapad_fn_lock_led_init(priv);
+	if (err) {
+		if (err != -ENODEV)
+			dev_warn(&pdev->dev, "Could not set up FnLock LED: %d\n", err);
+		else
+			dev_info(&pdev->dev, "FnLock control not available\n");
+	}
+
 	/*
 	 * On some models without a hw-switch (the yoga 2 13 at least)
 	 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
@@ -1903,6 +1996,7 @@ static int ideapad_acpi_add(struct platform_device *pdev)
 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
 		ideapad_unregister_rfkill(priv, i);
 
+	ideapad_fn_lock_led_exit(priv);
 	ideapad_kbd_bl_exit(priv);
 	ideapad_input_exit(priv);
 
@@ -1930,6 +2024,7 @@ static void ideapad_acpi_remove(struct platform_device *pdev)
 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
 		ideapad_unregister_rfkill(priv, i);
 
+	ideapad_fn_lock_led_exit(priv);
 	ideapad_kbd_bl_exit(priv);
 	ideapad_input_exit(priv);
 	ideapad_debugfs_exit(priv);
-- 
2.44.0


^ permalink raw reply related

* [PATCH 2/3] platform/x86: ideapad-laptop: add fn_lock_get/set functions
From: Gergo Koteles @ 2024-04-02 13:21 UTC (permalink / raw)
  To: Ike Panhc, Hans de Goede, Ilpo Järvinen, Pavel Machek,
	Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: platform-driver-x86, linux-kernel, linux-leds, devicetree,
	Gergo Koteles
In-Reply-To: <cover.1712063200.git.soyer@irl.hu>

The FnLock is retrieved and set in several places in the code.

Move details into ideapad_fn_lock_get and ideapad_fn_lock_set functions.

Signed-off-by: Gergo Koteles <soyer@irl.hu>
---
 drivers/platform/x86/ideapad-laptop.c | 38 +++++++++++++++++++--------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 901849810ce2..529df08af548 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -513,11 +513,8 @@ static ssize_t fan_mode_store(struct device *dev,
 
 static DEVICE_ATTR_RW(fan_mode);
 
-static ssize_t fn_lock_show(struct device *dev,
-			    struct device_attribute *attr,
-			    char *buf)
+static int ideapad_fn_lock_get(struct ideapad_private *priv)
 {
-	struct ideapad_private *priv = dev_get_drvdata(dev);
 	unsigned long hals;
 	int err;
 
@@ -525,7 +522,27 @@ static ssize_t fn_lock_show(struct device *dev,
 	if (err)
 		return err;
 
-	return sysfs_emit(buf, "%d\n", !!test_bit(HALS_FNLOCK_STATE_BIT, &hals));
+	return !!test_bit(HALS_FNLOCK_STATE_BIT, &hals);
+}
+
+static int ideapad_fn_lock_set(struct ideapad_private *priv, bool state)
+{
+	return exec_sals(priv->adev->handle,
+		state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
+}
+
+static ssize_t fn_lock_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct ideapad_private *priv = dev_get_drvdata(dev);
+	int brightness;
+
+	brightness = ideapad_fn_lock_get(priv);
+	if (brightness < 0)
+		return brightness;
+
+	return sysfs_emit(buf, "%d\n", brightness);
 }
 
 static ssize_t fn_lock_store(struct device *dev,
@@ -540,7 +557,7 @@ static ssize_t fn_lock_store(struct device *dev,
 	if (err)
 		return err;
 
-	err = exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
+	err = ideapad_fn_lock_set(priv, state);
 	if (err)
 		return err;
 
@@ -1709,7 +1726,6 @@ static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data)
 {
 	struct ideapad_wmi_private *wpriv = dev_get_drvdata(&wdev->dev);
 	struct ideapad_private *priv;
-	unsigned long result;
 
 	mutex_lock(&ideapad_shared_mutex);
 
@@ -1722,11 +1738,11 @@ static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data)
 		ideapad_input_report(priv, 128);
 		break;
 	case IDEAPAD_WMI_EVENT_FN_KEYS:
-		if (priv->features.set_fn_lock_led &&
-		    !eval_hals(priv->adev->handle, &result)) {
-			bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result);
+		if (priv->features.set_fn_lock_led) {
+			int brightness = ideapad_fn_lock_get(priv);
 
-			exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
+			if (brightness >= 0)
+				ideapad_fn_lock_set(priv, brightness);
 		}
 
 		if (data->type != ACPI_TYPE_INTEGER) {
-- 
2.44.0


^ permalink raw reply related

* [PATCH 1/3] dt-bindings: leds: add LED_FUNCTION_FNLOCK
From: Gergo Koteles @ 2024-04-02 13:21 UTC (permalink / raw)
  To: Ike Panhc, Hans de Goede, Ilpo Järvinen, Pavel Machek,
	Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: platform-driver-x86, linux-kernel, linux-leds, devicetree,
	Gergo Koteles
In-Reply-To: <cover.1712063200.git.soyer@irl.hu>

Newer laptops have FnLock LED.

Add a define for this very common function.

Signed-off-by: Gergo Koteles <soyer@irl.hu>
---
 include/dt-bindings/leds/common.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h
index ecea167930d9..d7c980bdf383 100644
--- a/include/dt-bindings/leds/common.h
+++ b/include/dt-bindings/leds/common.h
@@ -46,6 +46,7 @@
 #define LED_FUNCTION_CAPSLOCK "capslock"
 #define LED_FUNCTION_SCROLLLOCK "scrolllock"
 #define LED_FUNCTION_NUMLOCK "numlock"
+#define LED_FUNCTION_FNLOCK "fnlock"
 /*   Obsolete equivalents: "tpacpi::thinklight" (IBM/Lenovo Thinkpads),
      "lp5523:kb{1,2,3,4,5,6}" (Nokia N900) */
 #define LED_FUNCTION_KBD_BACKLIGHT "kbd_backlight"
-- 
2.44.0


^ permalink raw reply related

* [PATCH 0/3] add FnLock LED class device to ideapad laptops
From: Gergo Koteles @ 2024-04-02 13:20 UTC (permalink / raw)
  To: Ike Panhc, Hans de Goede, Ilpo Järvinen, Pavel Machek,
	Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: platform-driver-x86, linux-kernel, linux-leds, devicetree,
	Gergo Koteles

Hi All,

This patch series adds a new LED_FUNCTION_FNLOCK define as "fnlock" and 
adds a new FnLock LED class device into the ideapad-laptop driver.

This helps to display FnLock LED status in OSD or other places.

Best regards,
Gergo

Gergo Koteles (3):
  dt-bindings: leds: add LED_FUNCTION_FNLOCK
  platform/x86: ideapad-laptop: add fn_lock_get/set functions
  platform/x86: ideapad-laptop: add FnLock LED class device

 drivers/platform/x86/ideapad-laptop.c | 133 +++++++++++++++++++++++---
 include/dt-bindings/leds/common.h     |   1 +
 2 files changed, 123 insertions(+), 11 deletions(-)


base-commit: 39cd87c4eb2b893354f3b850f916353f2658ae6f
-- 
2.44.0


^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: mfd: Add ROHM BD71828 system-power-controller property
From: Matti Vaittinen @ 2024-04-02 13:15 UTC (permalink / raw)
  To: Andreas Kemnade, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	devicetree, linux-kernel
  Cc: Krzysztof Kozlowski
In-Reply-To: <20240402111700.494004-2-andreas@kemnade.info>

On 4/2/24 14:16, Andreas Kemnade wrote:
> As the PMIC can power off the system, add the corresponding property.
> 
> Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

FWIW
Acked-by: Matti Vaittinen <mazziesaccount@gmail.com>

> ---
>   Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
> index 11089aa89ec6..0b62f854bf6b 100644
> --- a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
> +++ b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
> @@ -73,6 +73,8 @@ properties:
>         used to mark the pins which should not be configured for GPIO. Please see
>         the ../gpio/gpio.txt for more information.
>   
> +  system-power-controller: true
> +
>   required:
>     - compatible
>     - reg

-- 
Matti Vaittinen
Linux kernel developer at ROHM Semiconductors
Oulu Finland

~~ When things go utterly wrong vim users can always type :help! ~~


^ permalink raw reply

* Re: [PATCH v7 3/4] firmware: arm_scmi: Add SCMI v3.2 pincontrol protocol basic support
From: Andy Shevchenko @ 2024-04-02 13:14 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Linus Walleij, Dan Carpenter, linux-arm-kernel,
	linux-kernel, devicetree, linux-gpio, Peng Fan, Oleksii Moisieiev
In-Reply-To: <20240402-pinctrl-scmi-v7-3-3ea519d12cf7@nxp.com>

On Tue, Apr 02, 2024 at 10:22:23AM +0800, Peng Fan (OSS) wrote:

...

> +#include <linux/module.h>
> +#include <linux/scmi_protocol.h>
> +#include <linux/slab.h>

Please, follow IWYU principle, a lot of headers are missed.

> +#include "common.h"
> +#include "protocols.h"

...

> +		ret = scmi_pinctrl_get_pin_info(ph, selector,
> +						&pi->pins[selector]);

It's netter as a single line.

> +		if (ret)
> +			return ret;
> +	}

...

> +static int scmi_pinctrl_protocol_init(const struct scmi_protocol_handle *ph)
> +{
> +	int ret;
> +	u32 version;
> +	struct scmi_pinctrl_info *pinfo;
> +
> +	ret = ph->xops->version_get(ph, &version);
> +	if (ret)
> +		return ret;
> +
> +	dev_dbg(ph->dev, "Pinctrl Version %d.%d\n",
> +		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
> +
> +	pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
> +	if (!pinfo)
> +		return -ENOMEM;
> +
> +	ret = scmi_pinctrl_attributes_get(ph, pinfo);
> +	if (ret)
> +		return ret;
> +
> +	pinfo->pins = devm_kcalloc(ph->dev, pinfo->nr_pins,
> +				   sizeof(*pinfo->pins), GFP_KERNEL);
> +	if (!pinfo->pins)
> +		return -ENOMEM;
> +
> +	pinfo->groups = devm_kcalloc(ph->dev, pinfo->nr_groups,
> +				     sizeof(*pinfo->groups), GFP_KERNEL);
> +	if (!pinfo->groups)
> +		return -ENOMEM;
> +
> +	pinfo->functions = devm_kcalloc(ph->dev, pinfo->nr_functions,
> +					sizeof(*pinfo->functions), GFP_KERNEL);
> +	if (!pinfo->functions)
> +		return -ENOMEM;
> +
> +	pinfo->version = version;
> +
> +	return ph->set_priv(ph, pinfo, version);

Same comments as per previous version. devm_ here is simply wrong.
It breaks the order of freeing resources.

I.o.w. I see *no guarantee* that these init-deinit functions will be properly
called from the respective probe-remove. Moreover the latter one may also have
its own devm allocations (which are rightfully placed) and you get completely
out of control the resource management.

> +}

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [RFC PATCH 1/2] spi: dt-bindings: add Siflower Quad SPI controller
From: Krzysztof Kozlowski @ 2024-04-02 13:12 UTC (permalink / raw)
  To: Mark Brown
  Cc: Qingfang Deng, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Qingfang Deng, linux-spi, devicetree, linux-kernel
In-Reply-To: <c4df0a94-be48-464f-892a-7157cb30f034@sirena.org.uk>

On 02/04/2024 14:22, Mark Brown wrote:
> On Sat, Mar 30, 2024 at 06:42:11PM +0100, Krzysztof Kozlowski wrote:
>> On 29/03/2024 02:51, Qingfang Deng wrote:
> 
>>> Add YAML devicetree bindings for Siflower Quad SPI controller.
> 
>> Describe the hardware. What is this Siflower?
> 
> That seems like a perfectly adequate description - ${VENDOR} ${FUNCTION}
> is normal enough and Quad SPI is a well known standard.  We don't need a
> marketing spiel for whatever IP version is currently supported.

What we are missing here is the final product, so for example the SoC.
Is the company making exactly one and only one Quad SPI? I provided more
explanation what is missing further in the quoted email and in follow up
email/discussion.

Best regards,
Krzysztof


^ permalink raw reply

* [RFC PATCH 6/6] MAINTAINERS: Add ROHM BD96801 'scalable PMIC' entries
From: Matti Vaittinen @ 2024-04-02 13:12 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Wim Van Sebroeck,
	Guenter Roeck, devicetree, linux-kernel, linux-watchdog
In-Reply-To: <cover.1712058690.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1470 bytes --]

Add maintainer entries for ROHM BD96801 a.k.a 'scalable PMIC'

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 MAINTAINERS | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index aa3b947fb080..da68144d51ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19111,17 +19111,21 @@ F:	drivers/gpio/gpio-bd71828.c
 F:	drivers/mfd/rohm-bd71828.c
 F:	drivers/mfd/rohm-bd718x7.c
 F:	drivers/mfd/rohm-bd9576.c
+F:	drivers/mfd/rohm-bd96801.c
 F:	drivers/regulator/bd71815-regulator.c
 F:	drivers/regulator/bd71828-regulator.c
 F:	drivers/regulator/bd718x7-regulator.c
 F:	drivers/regulator/bd9576-regulator.c
+F:	drivers/regulator/bd96801-regulator.c
 F:	drivers/regulator/rohm-regulator.c
 F:	drivers/rtc/rtc-bd70528.c
 F:	drivers/watchdog/bd9576_wdt.c
+F:	drivers/watchdog/bd96801_wdt.c
 F:	include/linux/mfd/rohm-bd71815.h
 F:	include/linux/mfd/rohm-bd71828.h
 F:	include/linux/mfd/rohm-bd718x7.h
 F:	include/linux/mfd/rohm-bd957x.h
+F:	include/linux/mfd/rohm-bd96801.h
 F:	include/linux/mfd/rohm-generic.h
 F:	include/linux/mfd/rohm-shared.h
 
-- 
2.43.2


-- 
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =] 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* [RFC PATCH 5/6] watchdog: ROHM BD96801 PMIC WDG driver
From: Matti Vaittinen @ 2024-04-02 13:11 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Matti Vaittinen, Wim Van Sebroeck, Guenter Roeck,
	devicetree, linux-kernel, linux-watchdog
In-Reply-To: <cover.1712058690.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 12479 bytes --]

Introduce driver for WDG block on ROHM BD96801 scalable PMIC.

This driver only supports watchdog with I2C feeding and delayed
response detection. Whether the watchdog toggles PRSTB pin or
just causes an interrupt can be configured via device-tree.

The BD96801 PMIC HW supports also window watchdog (too early
feeding detection) and Q&A mode. These are not supported by
this driver.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 drivers/watchdog/Kconfig       |  13 ++
 drivers/watchdog/Makefile      |   1 +
 drivers/watchdog/bd96801_wdt.c | 375 +++++++++++++++++++++++++++++++++
 3 files changed, 389 insertions(+)
 create mode 100644 drivers/watchdog/bd96801_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 6bee137cfbe0..d97e735e1faa 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -181,6 +181,19 @@ config BD957XMUF_WATCHDOG
 	  watchdog. Alternatively say M to compile the driver as a module,
 	  which will be called bd9576_wdt.
 
+config BD96801_WATCHDOG
+	tristate "ROHM BD96801 PMIC Watchdog"
+	depends on MFD_ROHM_BD96801
+	select WATCHDOG_CORE
+	help
+	  Support for the watchdog in the ROHM BD96801 PMIC. Watchdog can be
+	  configured to only generate IRQ or to trigger system reset via reset
+	  pin.
+
+	  Say Y here to include support for the ROHM BD96801 watchdog.
+	  Alternatively say M to compile the driver as a module,
+	  which will be called bd96801_wdt.
+
 config CROS_EC_WATCHDOG
 	tristate "ChromeOS EC-based watchdog"
 	select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 3710c218f05e..31bc94436c81 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -217,6 +217,7 @@ obj-$(CONFIG_XEN_WDT) += xen_wdt.o
 
 # Architecture Independent
 obj-$(CONFIG_BD957XMUF_WATCHDOG) += bd9576_wdt.o
+obj-$(CONFIG_BD96801_WATCHDOG) += bd96801_wdt.o
 obj-$(CONFIG_CROS_EC_WATCHDOG) += cros_ec_wdt.o
 obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o
 obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o
diff --git a/drivers/watchdog/bd96801_wdt.c b/drivers/watchdog/bd96801_wdt.c
new file mode 100644
index 000000000000..cb2b526ecc21
--- /dev/null
+++ b/drivers/watchdog/bd96801_wdt.c
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 ROHM Semiconductors
+ *
+ * ROHM BD96801 watchdog driver
+ */
+
+#include <linux/kernel.h>
+#include <linux/mfd/rohm-bd96801.h>
+#include <linux/mfd/rohm-generic.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/watchdog.h>
+
+static bool nowayout;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+		"Watchdog cannot be stopped once started (default=\"false\")");
+
+#define BD96801_WD_TMO_SHORT_MASK	0x70
+#define BD96801_WD_RATIO_MASK		0x3
+#define BD96801_WD_TYPE_MASK		0x4
+#define BD96801_WD_TYPE_SLOW		0x4
+#define BD96801_WD_TYPE_WIN		0x0
+
+#define BD96801_WD_EN_MASK		0x3
+#define BD96801_WD_IF_EN		0x1
+#define BD96801_WD_QA_EN		0x2
+#define BD96801_WD_DISABLE		0x0
+
+#define BD96801_WD_ASSERT_MASK		0x8
+#define BD96801_WD_ASSERT_RST		0x8
+#define BD96801_WD_ASSERT_IRQ		0x0
+
+#define BD96801_WD_FEED_MASK		0x1
+#define BD96801_WD_FEED			0x1
+
+/* units in uS */
+#define FASTNG_MIN			3370
+#define BD96801_WDT_DEFAULT_MARGIN	6905120
+/* Unit is seconds */
+#define DEFAULT_TIMEOUT 30
+
+/*
+ * BD96801 WDG supports window mode so the TMO consists of SHORT and LONG
+ * timeout values. SHORT time is meaningfull only in window mode where feeding
+ * period shorter than SHORT would be an error. LONG time is used to detect if
+ * feeding is not occurring within given time limit (SoC SW hangs). The LONG
+ * timeout time is a multiple of (2, 4, 8 0r 16 times) the SHORT timeout.
+ */
+
+struct wdtbd96801 {
+	struct device		*dev;
+	struct regmap		*regmap;
+	bool			always_running;
+	struct watchdog_device	wdt;
+};
+
+static int bd96801_wdt_ping(struct watchdog_device *wdt)
+{
+	struct wdtbd96801 *w = watchdog_get_drvdata(wdt);
+
+	return regmap_update_bits(w->regmap, BD96801_REG_WD_FEED,
+				 BD96801_WD_FEED_MASK, BD96801_WD_FEED);
+}
+
+static int bd96801_wdt_start(struct watchdog_device *wdt)
+{
+	struct wdtbd96801 *w = watchdog_get_drvdata(wdt);
+	int ret;
+
+	ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF,
+				 BD96801_WD_EN_MASK, BD96801_WD_IF_EN);
+
+	return ret;
+}
+
+static int bd96801_wdt_stop(struct watchdog_device *wdt)
+{
+	struct wdtbd96801 *w = watchdog_get_drvdata(wdt);
+
+	if (!w->always_running)
+		return regmap_update_bits(w->regmap, BD96801_REG_WD_CONF,
+				 BD96801_WD_EN_MASK, BD96801_WD_DISABLE);
+	set_bit(WDOG_HW_RUNNING, &wdt->status);
+
+	return 0;
+}
+
+static const struct watchdog_info bd96801_wdt_info = {
+	.options	= WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING |
+			  WDIOF_SETTIMEOUT,
+	.identity	= "BD96801 Watchdog",
+};
+
+static const struct watchdog_ops bd96801_wdt_ops = {
+	.start		= bd96801_wdt_start,
+	.stop		= bd96801_wdt_stop,
+	.ping		= bd96801_wdt_ping,
+};
+
+static int find_closest_fast(int target, int *sel, int *val)
+{
+	int i;
+	int window = FASTNG_MIN;
+
+	for (i = 0; i < 8 && window < target; i++)
+		window <<= 1;
+
+	*val = window;
+	*sel = i;
+
+	if (i == 8)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int find_closest_slow_by_fast(int fast_val, int *target, int *slowsel)
+{
+	int sel;
+	static const int multipliers[] = {2, 4, 8, 16};
+
+	for (sel = 0; sel < ARRAY_SIZE(multipliers) &&
+	     multipliers[sel] * fast_val < *target; sel++)
+		;
+
+	if (sel == ARRAY_SIZE(multipliers))
+		return -EINVAL;
+
+	*slowsel = sel;
+	*target = multipliers[sel] * fast_val;
+
+	return 0;
+}
+
+static int find_closest_slow(int *target, int *slow_sel, int *fast_sel)
+{
+	static const int multipliers[] = {2, 4, 8, 16};
+	int i, j;
+	int val = 0;
+	int window = FASTNG_MIN;
+
+	for (i = 0; i < 8; i++) {
+		for (j = 0; j < ARRAY_SIZE(multipliers); j++) {
+			int slow;
+
+			slow = window * multipliers[j];
+			if (slow >= *target && (!val || slow < val)) {
+				val = slow;
+				*fast_sel = i;
+				*slow_sel = j;
+			}
+		}
+		window <<= 1;
+	}
+	if (!val)
+		return -EINVAL;
+
+	*target = val;
+
+	return 0;
+}
+
+static int bd96801_set_wdt_mode(struct wdtbd96801 *w, int hw_margin,
+			       int hw_margin_min)
+{
+	int ret, fastng, slowng, type, reg, mask;
+	struct device *dev = w->dev;
+
+	/* convert to uS */
+	hw_margin *= 1000;
+	hw_margin_min *= 1000;
+	if (hw_margin_min) {
+		int min;
+
+		type = BD96801_WD_TYPE_WIN;
+		dev_dbg(dev, "Setting type WINDOW 0x%x\n", type);
+		ret = find_closest_fast(hw_margin_min, &fastng, &min);
+		if (ret) {
+			dev_err(dev, "bad WDT window for fast timeout\n");
+			return ret;
+		}
+
+		ret = find_closest_slow_by_fast(min, &hw_margin, &slowng);
+		if (ret) {
+			dev_err(dev, "bad WDT window\n");
+			return ret;
+		}
+		w->wdt.min_hw_heartbeat_ms = min / 1000;
+	} else {
+		type = BD96801_WD_TYPE_SLOW;
+		dev_dbg(dev, "Setting type SLOW 0x%x\n", type);
+		ret = find_closest_slow(&hw_margin, &slowng, &fastng);
+		if (ret) {
+			dev_err(dev, "bad WDT window\n");
+			return ret;
+		}
+	}
+
+	w->wdt.max_hw_heartbeat_ms = hw_margin / 1000;
+
+	fastng <<= ffs(BD96801_WD_TMO_SHORT_MASK) - 1;
+
+	reg = slowng | fastng;
+	mask = BD96801_WD_RATIO_MASK | BD96801_WD_TMO_SHORT_MASK;
+	ret = regmap_update_bits(w->regmap, BD96801_REG_WD_TMO,
+				 mask, reg);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF,
+				 BD96801_WD_TYPE_MASK, type);
+
+	return ret;
+}
+
+static int bd96801_set_heartbeat_from_hw(struct wdtbd96801 *w,
+					 unsigned int conf_reg)
+{
+	int ret;
+	unsigned int val, sel, fast;
+
+	/*
+	 * The BD96801 supports a somewhat peculiar QA-mode, which we do not
+	 * support in this driver. If the QA-mode is enabled then we just
+	 * warn and bail-out.
+	 */
+	if ((conf_reg & BD96801_WD_EN_MASK) != BD96801_WD_IF_EN) {
+		dev_warn(w->dev, "watchdog set to Q&A mode - exiting\n");
+		return -EINVAL;
+	}
+
+	ret = regmap_read(w->regmap, BD96801_REG_WD_TMO, &val);
+	if (ret)
+		return ret;
+
+	sel = val & BD96801_WD_TMO_SHORT_MASK;
+	sel >>= ffs(BD96801_WD_TMO_SHORT_MASK) - 1;
+	fast = FASTNG_MIN << sel;
+
+	sel = (val & BD96801_WD_RATIO_MASK) + 1;
+	w->wdt.max_hw_heartbeat_ms = (fast << sel) / USEC_PER_MSEC;
+
+	if ((conf_reg & BD96801_WD_TYPE_MASK) == BD96801_WD_TYPE_WIN)
+		w->wdt.min_hw_heartbeat_ms = fast / USEC_PER_MSEC;
+
+	return 0;
+}
+
+static int init_wdg_hw(struct wdtbd96801 *w)
+{
+	u32 hw_margin[2];
+	int count, ret;
+	u32 hw_margin_max = BD96801_WDT_DEFAULT_MARGIN, hw_margin_min = 0;
+
+	count = device_property_count_u32(w->dev->parent, "rohm,hw-timeout-ms");
+	if (count < 0 && count != -EINVAL)
+		return count;
+
+	if (count > 0) {
+		if (count > ARRAY_SIZE(hw_margin))
+			return -EINVAL;
+
+		ret = device_property_read_u32_array(w->dev->parent,
+						     "rohm,hw-timeout-ms",
+						     &hw_margin[0], count);
+		if (ret < 0)
+			return ret;
+
+		if (count == 1)
+			hw_margin_max = hw_margin[0];
+
+		if (count == 2) {
+			hw_margin_max = hw_margin[1];
+			hw_margin_min = hw_margin[0];
+		}
+	}
+
+	ret = bd96801_set_wdt_mode(w, hw_margin_max, hw_margin_min);
+	if (ret)
+		return ret;
+
+	ret = device_property_match_string(w->dev->parent, "rohm,wdg-action",
+					   "prstb");
+	if (ret >= 0) {
+		ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF,
+				 BD96801_WD_ASSERT_MASK,
+				 BD96801_WD_ASSERT_RST);
+		return ret;
+	}
+
+	ret = device_property_match_string(w->dev->parent, "rohm,wdg-action",
+					   "intb-only");
+	if (ret >= 0) {
+		ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF,
+				 BD96801_WD_ASSERT_MASK,
+				 BD96801_WD_ASSERT_IRQ);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int bd96801_wdt_probe(struct platform_device *pdev)
+{
+	struct wdtbd96801 *w;
+	int ret;
+	unsigned int val;
+
+	w = devm_kzalloc(&pdev->dev, sizeof(*w), GFP_KERNEL);
+	if (!w)
+		return -ENOMEM;
+
+	w->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	w->dev = &pdev->dev;
+
+	w->wdt.info = &bd96801_wdt_info;
+	w->wdt.ops =  &bd96801_wdt_ops;
+	w->wdt.parent = pdev->dev.parent;
+	w->wdt.timeout = DEFAULT_TIMEOUT;
+	watchdog_set_drvdata(&w->wdt, w);
+
+	w->always_running = device_property_read_bool(pdev->dev.parent,
+						      "always-running");
+
+	ret = regmap_read(w->regmap, BD96801_REG_WD_CONF, &val);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "Failed to get the watchdog state\n");
+
+	/*
+	 * If the WDG is already enabled we assume it is configured by boot.
+	 * In this case we just update the hw-timeout based on values set to
+	 * the timeout / mode registers and leave the hardware configs
+	 * untouched.
+	 */
+	if ((val & BD96801_WD_EN_MASK) != BD96801_WD_DISABLE) {
+		dev_dbg(&pdev->dev, "watchdog was running during probe\n");
+		ret = bd96801_set_heartbeat_from_hw(w, val);
+		if (ret)
+			return ret;
+
+		set_bit(WDOG_HW_RUNNING, &w->wdt.status);
+	} else {
+		/* If WDG is not running so we will initializate it */
+		ret = init_wdg_hw(w);
+		if (ret)
+			return ret;
+	}
+
+	watchdog_init_timeout(&w->wdt, 0, pdev->dev.parent);
+	watchdog_set_nowayout(&w->wdt, nowayout);
+	watchdog_stop_on_reboot(&w->wdt);
+
+	if (w->always_running)
+		bd96801_wdt_start(&w->wdt);
+
+	return devm_watchdog_register_device(&pdev->dev, &w->wdt);
+}
+
+static struct platform_driver bd96801_wdt = {
+	.driver = {
+		.name = "bd96801-wdt"
+	},
+	.probe = bd96801_wdt_probe,
+};
+module_platform_driver(bd96801_wdt);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("BD96801 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bd96801-wdt");
-- 
2.43.2


-- 
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =] 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox