Patchwork [v6,3/4] ACPI / PMIC: Add generic intel_soc_pmic_exec_mipi_pmic_seq_element handling

login
register
mail settings
Submitter Hans de Goede
Date Jan. 7, 2019, 11:15 a.m.
Message ID <20190107111556.4510-4-hdegoede@redhat.com>
Download mbox | patch
Permalink /patch/693761/
State New
Headers show

Comments

Hans de Goede - Jan. 7, 2019, 11:15 a.m.
Most PMIC-s use only a single i2c-address, so after verifying the
i2c-address matches, we can simply pass the call to regmap_update_bits.

This commit adds support for this and hooks this up for the xpower AXP288
PMIC by setting the new pmic_i2c_address field.

This fixes the following errors on display on / off on a Jumper Ezpad
mini 3 and an Onda V80 plus tablet, both of which use the AXP288:

intel_soc_pmic_exec_mipi_pmic_seq_element: Not implemented
intel_soc_pmic_exec_mipi_pmic_seq_element: i2c-addr: 0x34 reg-addr ...
[drm:mipi_exec_pmic [i915]] *ERROR* mipi_exec_pmic failed, error: -95

Instead of these errors on both devices we now correctly turn on / off
DLDO3 (through direct register manipulation). On the Onda V80 plus this
fixes an issue with the backlight being brighter around the borders after
an off / on cycle. This should also help to save some power when the
display is off.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v6:
-This is a new patch in v6 of this patch-set
---
 drivers/acpi/pmic/intel_pmic.c        | 9 +++++++++
 drivers/acpi/pmic/intel_pmic.h        | 2 ++
 drivers/acpi/pmic/intel_pmic_xpower.c | 1 +
 3 files changed, 12 insertions(+)
Ville Syrjälä - Jan. 7, 2019, 3:31 p.m.
On Mon, Jan 07, 2019 at 12:15:55PM +0100, Hans de Goede wrote:
> Most PMIC-s use only a single i2c-address, so after verifying the
> i2c-address matches, we can simply pass the call to regmap_update_bits.
> 
> This commit adds support for this and hooks this up for the xpower AXP288
> PMIC by setting the new pmic_i2c_address field.
> 
> This fixes the following errors on display on / off on a Jumper Ezpad
> mini 3 and an Onda V80 plus tablet, both of which use the AXP288:
> 
> intel_soc_pmic_exec_mipi_pmic_seq_element: Not implemented
> intel_soc_pmic_exec_mipi_pmic_seq_element: i2c-addr: 0x34 reg-addr ...
> [drm:mipi_exec_pmic [i915]] *ERROR* mipi_exec_pmic failed, error: -95
> 
> Instead of these errors on both devices we now correctly turn on / off
> DLDO3 (through direct register manipulation). On the Onda V80 plus this
> fixes an issue with the backlight being brighter around the borders after
> an off / on cycle. This should also help to save some power when the
> display is off.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
> Changes in v6:
> -This is a new patch in v6 of this patch-set
> ---
>  drivers/acpi/pmic/intel_pmic.c        | 9 +++++++++
>  drivers/acpi/pmic/intel_pmic.h        | 2 ++
>  drivers/acpi/pmic/intel_pmic_xpower.c | 1 +
>  3 files changed, 12 insertions(+)
> 
> diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c
> index 471afeea87c2..c14cfaea92e2 100644
> --- a/drivers/acpi/pmic/intel_pmic.c
> +++ b/drivers/acpi/pmic/intel_pmic.c
> @@ -359,6 +359,15 @@ int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
>  		ret = d->exec_mipi_pmic_seq_element(intel_pmic_opregion->regmap,
>  						    i2c_address, reg_address,
>  						    value, mask);
> +	} else if (d->pmic_i2c_address) {
> +		if (i2c_address == d->pmic_i2c_address) {
> +			ret = regmap_update_bits(intel_pmic_opregion->regmap,
> +						 reg_address, mask, value);
> +		} else {
> +			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
> +			       __func__, i2c_address, reg_address, value, mask);
> +			ret = -ENXIO;
> +		}
>  	} else {
>  		pr_warn("%s: Not implemented\n", __func__);
>  		pr_warn("%s: i2c-addr: 0x%x reg-addr 0x%x value 0x%x mask 0x%x\n",
> diff --git a/drivers/acpi/pmic/intel_pmic.h b/drivers/acpi/pmic/intel_pmic.h
> index 5cd195fabca8..89379476a1df 100644
> --- a/drivers/acpi/pmic/intel_pmic.h
> +++ b/drivers/acpi/pmic/intel_pmic.h
> @@ -21,6 +21,8 @@ struct intel_pmic_opregion_data {
>  	int power_table_count;
>  	struct pmic_table *thermal_table;
>  	int thermal_table_count;
> +	/* For generic exec_mipi_pmic_seq_element handling */
> +	int pmic_i2c_address;
>  };
>  
>  int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, struct regmap *regmap, struct intel_pmic_opregion_data *d);
> diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c
> index e7c0006e6602..a091d5a8392c 100644
> --- a/drivers/acpi/pmic/intel_pmic_xpower.c
> +++ b/drivers/acpi/pmic/intel_pmic_xpower.c
> @@ -265,6 +265,7 @@ static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = {
>  	.power_table_count = ARRAY_SIZE(power_table),
>  	.thermal_table = thermal_table,
>  	.thermal_table_count = ARRAY_SIZE(thermal_table),
> +	.pmic_i2c_address = 0x34,

Seems to match the axp288 datasheet.

FWIW
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

>  };
>  
>  static acpi_status intel_xpower_pmic_gpio_handler(u32 function,
> -- 
> 2.20.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Andy Shevchenko - Jan. 7, 2019, 3:46 p.m.
On Mon, Jan 07, 2019 at 12:15:55PM +0100, Hans de Goede wrote:
> Most PMIC-s use only a single i2c-address, so after verifying the
> i2c-address matches, we can simply pass the call to regmap_update_bits.
> 
> This commit adds support for this and hooks this up for the xpower AXP288
> PMIC by setting the new pmic_i2c_address field.
> 
> This fixes the following errors on display on / off on a Jumper Ezpad
> mini 3 and an Onda V80 plus tablet, both of which use the AXP288:
> 
> intel_soc_pmic_exec_mipi_pmic_seq_element: Not implemented
> intel_soc_pmic_exec_mipi_pmic_seq_element: i2c-addr: 0x34 reg-addr ...
> [drm:mipi_exec_pmic [i915]] *ERROR* mipi_exec_pmic failed, error: -95
> 
> Instead of these errors on both devices we now correctly turn on / off
> DLDO3 (through direct register manipulation). On the Onda V80 plus this
> fixes an issue with the backlight being brighter around the borders after
> an off / on cycle. This should also help to save some power when the
> display is off.

> +	} else if (d->pmic_i2c_address) {
> +		if (i2c_address == d->pmic_i2c_address) {
> +			ret = regmap_update_bits(intel_pmic_opregion->regmap,
> +						 reg_address, mask, value);
> +		} else {
> +			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
> +			       __func__, i2c_address, reg_address, value, mask);
> +			ret = -ENXIO;
> +		}

> --- a/drivers/acpi/pmic/intel_pmic_xpower.c
> +++ b/drivers/acpi/pmic/intel_pmic_xpower.c
> +	.pmic_i2c_address = 0x34,

Can we just have a hook here instead of exposing PMIC I2C address?
Am I missing something in case it's not possible?
Hans de Goede - Jan. 8, 2019, 1:45 p.m.
Hi,

On 07-01-19 16:46, Andy Shevchenko wrote:
> On Mon, Jan 07, 2019 at 12:15:55PM +0100, Hans de Goede wrote:
>> Most PMIC-s use only a single i2c-address, so after verifying the
>> i2c-address matches, we can simply pass the call to regmap_update_bits.
>>
>> This commit adds support for this and hooks this up for the xpower AXP288
>> PMIC by setting the new pmic_i2c_address field.
>>
>> This fixes the following errors on display on / off on a Jumper Ezpad
>> mini 3 and an Onda V80 plus tablet, both of which use the AXP288:
>>
>> intel_soc_pmic_exec_mipi_pmic_seq_element: Not implemented
>> intel_soc_pmic_exec_mipi_pmic_seq_element: i2c-addr: 0x34 reg-addr ...
>> [drm:mipi_exec_pmic [i915]] *ERROR* mipi_exec_pmic failed, error: -95
>>
>> Instead of these errors on both devices we now correctly turn on / off
>> DLDO3 (through direct register manipulation). On the Onda V80 plus this
>> fixes an issue with the backlight being brighter around the borders after
>> an off / on cycle. This should also help to save some power when the
>> display is off.
> 
>> +	} else if (d->pmic_i2c_address) {
>> +		if (i2c_address == d->pmic_i2c_address) {
>> +			ret = regmap_update_bits(intel_pmic_opregion->regmap,
>> +						 reg_address, mask, value);
>> +		} else {
>> +			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
>> +			       __func__, i2c_address, reg_address, value, mask);
>> +			ret = -ENXIO;
>> +		}
> 
>> --- a/drivers/acpi/pmic/intel_pmic_xpower.c
>> +++ b/drivers/acpi/pmic/intel_pmic_xpower.c
>> +	.pmic_i2c_address = 0x34,
> 
> Can we just have a hook here instead of exposing PMIC I2C address?
> Am I missing something in case it's not possible?

We already have a hook, but it isn't really necessary to implement
that for each model PMIC. The MFD device which is the PMIC's parent
in most cases will give us a regmap to access the PMIC registers and
that allows us to do a generic implementation.

But the MIPI PMIC sequence includes an i2c-address as some PMICs
span multiple i2c-addresses. For the simple single i2c-address case
the regmap gives us access to the registers behind that single address
and we can use a generic solution. In this case we should verify the
i2c-addr is what we expect, which is where the pmic_i2c_address comes in.

Regards,

Hans
Andy Shevchenko - Jan. 8, 2019, 2:51 p.m.
On Tue, Jan 08, 2019 at 02:45:39PM +0100, Hans de Goede wrote:
> On 07-01-19 16:46, Andy Shevchenko wrote:
> > On Mon, Jan 07, 2019 at 12:15:55PM +0100, Hans de Goede wrote:

> > > +	} else if (d->pmic_i2c_address) {
> > > +		if (i2c_address == d->pmic_i2c_address) {
> > > +			ret = regmap_update_bits(intel_pmic_opregion->regmap,
> > > +						 reg_address, mask, value);
> > > +		} else {
> > > +			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
> > > +			       __func__, i2c_address, reg_address, value, mask);
> > > +			ret = -ENXIO;
> > > +		}
> > 
> > > --- a/drivers/acpi/pmic/intel_pmic_xpower.c
> > > +++ b/drivers/acpi/pmic/intel_pmic_xpower.c
> > > +	.pmic_i2c_address = 0x34,
> > 
> > Can we just have a hook here instead of exposing PMIC I2C address?
> > Am I missing something in case it's not possible?
> 
> We already have a hook, but it isn't really necessary to implement
> that for each model PMIC. The MFD device which is the PMIC's parent
> in most cases will give us a regmap to access the PMIC registers and
> that allows us to do a generic implementation.
> 
> But the MIPI PMIC sequence includes an i2c-address as some PMICs
> span multiple i2c-addresses. For the simple single i2c-address case
> the regmap gives us access to the registers behind that single address
> and we can use a generic solution. In this case we should verify the
> i2c-addr is what we expect, which is where the pmic_i2c_address comes in.

But we also can have a generic hook in intel_pmic.c and assign it whenever
it's the case?
Hans de Goede - Jan. 8, 2019, 3:35 p.m.
Hi,

On 08-01-19 15:51, Andy Shevchenko wrote:
> On Tue, Jan 08, 2019 at 02:45:39PM +0100, Hans de Goede wrote:
>> On 07-01-19 16:46, Andy Shevchenko wrote:
>>> On Mon, Jan 07, 2019 at 12:15:55PM +0100, Hans de Goede wrote:
> 
>>>> +	} else if (d->pmic_i2c_address) {
>>>> +		if (i2c_address == d->pmic_i2c_address) {
>>>> +			ret = regmap_update_bits(intel_pmic_opregion->regmap,
>>>> +						 reg_address, mask, value);
>>>> +		} else {
>>>> +			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
>>>> +			       __func__, i2c_address, reg_address, value, mask);
>>>> +			ret = -ENXIO;
>>>> +		}
>>>
>>>> --- a/drivers/acpi/pmic/intel_pmic_xpower.c
>>>> +++ b/drivers/acpi/pmic/intel_pmic_xpower.c
>>>> +	.pmic_i2c_address = 0x34,
>>>
>>> Can we just have a hook here instead of exposing PMIC I2C address?
>>> Am I missing something in case it's not possible?
>>
>> We already have a hook, but it isn't really necessary to implement
>> that for each model PMIC. The MFD device which is the PMIC's parent
>> in most cases will give us a regmap to access the PMIC registers and
>> that allows us to do a generic implementation.
>>
>> But the MIPI PMIC sequence includes an i2c-address as some PMICs
>> span multiple i2c-addresses. For the simple single i2c-address case
>> the regmap gives us access to the registers behind that single address
>> and we can use a generic solution. In this case we should verify the
>> i2c-addr is what we expect, which is where the pmic_i2c_address comes in.
> 
> But we also can have a generic hook in intel_pmic.c and assign it whenever
> it's the case?

We could, but then we still need the pmic_i2c_address member and now the
hook would need to passed both the regmap and the intel_pmic_opregion_data
pointer so that it can verify the i2c address so handling the generic case
directly inside intel_soc_pmic_exec_mipi_pmic_seq_element is easier.

Regards,

Hans
Andy Shevchenko - Jan. 8, 2019, 5:33 p.m.
On Tue, Jan 08, 2019 at 04:35:45PM +0100, Hans de Goede wrote:
> Hi,
> 
> On 08-01-19 15:51, Andy Shevchenko wrote:
> > On Tue, Jan 08, 2019 at 02:45:39PM +0100, Hans de Goede wrote:
> > > On 07-01-19 16:46, Andy Shevchenko wrote:
> > > > On Mon, Jan 07, 2019 at 12:15:55PM +0100, Hans de Goede wrote:
> > 
> > > > > +	} else if (d->pmic_i2c_address) {
> > > > > +		if (i2c_address == d->pmic_i2c_address) {
> > > > > +			ret = regmap_update_bits(intel_pmic_opregion->regmap,
> > > > > +						 reg_address, mask, value);
> > > > > +		} else {
> > > > > +			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
> > > > > +			       __func__, i2c_address, reg_address, value, mask);
> > > > > +			ret = -ENXIO;
> > > > > +		}
> > > > 
> > > > > --- a/drivers/acpi/pmic/intel_pmic_xpower.c
> > > > > +++ b/drivers/acpi/pmic/intel_pmic_xpower.c
> > > > > +	.pmic_i2c_address = 0x34,
> > > > 
> > > > Can we just have a hook here instead of exposing PMIC I2C address?
> > > > Am I missing something in case it's not possible?
> > > 
> > > We already have a hook, but it isn't really necessary to implement
> > > that for each model PMIC. The MFD device which is the PMIC's parent
> > > in most cases will give us a regmap to access the PMIC registers and
> > > that allows us to do a generic implementation.
> > > 
> > > But the MIPI PMIC sequence includes an i2c-address as some PMICs
> > > span multiple i2c-addresses. For the simple single i2c-address case
> > > the regmap gives us access to the registers behind that single address
> > > and we can use a generic solution. In this case we should verify the
> > > i2c-addr is what we expect, which is where the pmic_i2c_address comes in.
> > 
> > But we also can have a generic hook in intel_pmic.c and assign it whenever
> > it's the case?
> 
> We could, but then we still need the pmic_i2c_address member and now the
> hook would need to passed both the regmap and the intel_pmic_opregion_data
> pointer so that it can verify the i2c address so handling the generic case
> directly inside intel_soc_pmic_exec_mipi_pmic_seq_element is easier.

I see.

One more question, can we unify somehow error messages and do something like

if (...) {
	...
} else if (pmic_i2c_address && i2c_address == pmic_i2c_address) {
	ret = regmap_update_bits(...);
} else {
	...
}

?
Hans de Goede - Jan. 9, 2019, 9:26 a.m.
Hi,

On 08-01-19 18:33, Andy Shevchenko wrote:
> On Tue, Jan 08, 2019 at 04:35:45PM +0100, Hans de Goede wrote:
>> Hi,
>>
>> On 08-01-19 15:51, Andy Shevchenko wrote:
>>> On Tue, Jan 08, 2019 at 02:45:39PM +0100, Hans de Goede wrote:
>>>> On 07-01-19 16:46, Andy Shevchenko wrote:
>>>>> On Mon, Jan 07, 2019 at 12:15:55PM +0100, Hans de Goede wrote:
>>>
>>>>>> +	} else if (d->pmic_i2c_address) {
>>>>>> +		if (i2c_address == d->pmic_i2c_address) {
>>>>>> +			ret = regmap_update_bits(intel_pmic_opregion->regmap,
>>>>>> +						 reg_address, mask, value);
>>>>>> +		} else {
>>>>>> +			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
>>>>>> +			       __func__, i2c_address, reg_address, value, mask);
>>>>>> +			ret = -ENXIO;
>>>>>> +		}
>>>>>
>>>>>> --- a/drivers/acpi/pmic/intel_pmic_xpower.c
>>>>>> +++ b/drivers/acpi/pmic/intel_pmic_xpower.c
>>>>>> +	.pmic_i2c_address = 0x34,
>>>>>
>>>>> Can we just have a hook here instead of exposing PMIC I2C address?
>>>>> Am I missing something in case it's not possible?
>>>>
>>>> We already have a hook, but it isn't really necessary to implement
>>>> that for each model PMIC. The MFD device which is the PMIC's parent
>>>> in most cases will give us a regmap to access the PMIC registers and
>>>> that allows us to do a generic implementation.
>>>>
>>>> But the MIPI PMIC sequence includes an i2c-address as some PMICs
>>>> span multiple i2c-addresses. For the simple single i2c-address case
>>>> the regmap gives us access to the registers behind that single address
>>>> and we can use a generic solution. In this case we should verify the
>>>> i2c-addr is what we expect, which is where the pmic_i2c_address comes in.
>>>
>>> But we also can have a generic hook in intel_pmic.c and assign it whenever
>>> it's the case?
>>
>> We could, but then we still need the pmic_i2c_address member and now the
>> hook would need to passed both the regmap and the intel_pmic_opregion_data
>> pointer so that it can verify the i2c address so handling the generic case
>> directly inside intel_soc_pmic_exec_mipi_pmic_seq_element is easier.
> 
> I see.
> 
> One more question, can we unify somehow error messages and do something like
> 
> if (...) {
> 	...
> } else if (pmic_i2c_address && i2c_address == pmic_i2c_address) {
> 	ret = regmap_update_bits(...);
> } else {
> 	...
> }

I can understand where you are coming from with this request but I would
prefer to keep the messages separate, merging them doing something like this:

if (...) {
  	...
} else if (pmic_i2c_address && i2c_address == pmic_i2c_address) {
  	ret = regmap_update_bits(...);
} else {
  	...
}

if (ret)
	pr_err()

Would mean that the messages become less clear and the user would need to
go by the error code to figure out what is going on. Also currently one
of the 2 messages this would merge is a pr_err, while the other is a pr_warn.

I hope that the clear error messages lead to clear bug reports (or help
the user over the threshold to report a bug at all when they are hit).

Regards,

Hans

Patch

diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c
index 471afeea87c2..c14cfaea92e2 100644
--- a/drivers/acpi/pmic/intel_pmic.c
+++ b/drivers/acpi/pmic/intel_pmic.c
@@ -359,6 +359,15 @@  int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
 		ret = d->exec_mipi_pmic_seq_element(intel_pmic_opregion->regmap,
 						    i2c_address, reg_address,
 						    value, mask);
+	} else if (d->pmic_i2c_address) {
+		if (i2c_address == d->pmic_i2c_address) {
+			ret = regmap_update_bits(intel_pmic_opregion->regmap,
+						 reg_address, mask, value);
+		} else {
+			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
+			       __func__, i2c_address, reg_address, value, mask);
+			ret = -ENXIO;
+		}
 	} else {
 		pr_warn("%s: Not implemented\n", __func__);
 		pr_warn("%s: i2c-addr: 0x%x reg-addr 0x%x value 0x%x mask 0x%x\n",
diff --git a/drivers/acpi/pmic/intel_pmic.h b/drivers/acpi/pmic/intel_pmic.h
index 5cd195fabca8..89379476a1df 100644
--- a/drivers/acpi/pmic/intel_pmic.h
+++ b/drivers/acpi/pmic/intel_pmic.h
@@ -21,6 +21,8 @@  struct intel_pmic_opregion_data {
 	int power_table_count;
 	struct pmic_table *thermal_table;
 	int thermal_table_count;
+	/* For generic exec_mipi_pmic_seq_element handling */
+	int pmic_i2c_address;
 };
 
 int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, struct regmap *regmap, struct intel_pmic_opregion_data *d);
diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c
index e7c0006e6602..a091d5a8392c 100644
--- a/drivers/acpi/pmic/intel_pmic_xpower.c
+++ b/drivers/acpi/pmic/intel_pmic_xpower.c
@@ -265,6 +265,7 @@  static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = {
 	.power_table_count = ARRAY_SIZE(power_table),
 	.thermal_table = thermal_table,
 	.thermal_table_count = ARRAY_SIZE(thermal_table),
+	.pmic_i2c_address = 0x34,
 };
 
 static acpi_status intel_xpower_pmic_gpio_handler(u32 function,