Skip to content

Commit 9c80662

Browse files
jwrdegoedesre
authored andcommitted
power: supply: axp288_charger: Add special handling for HP Pavilion x2 10
Some HP Pavilion x2 10 models use an AXP288 for charging and fuel-gauge. We use a native power_supply / PMIC driver in this case, because on most models with an AXP288 the ACPI AC / Battery code is either completely missing or relies on custom / proprietary ACPI OpRegions which Linux does not implement. The native drivers mostly work fine, but there are 2 problems: 1. These model uses a Type-C connector for charging which the AXP288 does not support. As long as a Type-A charger (which uses the USB data pins for charger type detection) is used everything is fine. But if a Type-C charger is used (such as the charger shipped with the device) then the charger is not recognized. So we end up slowly discharging the device even though a charger is connected, because we are limiting the current from the charger to 500mA. To make things worse this happens with the device's official charger. Looking at the ACPI tables HP has "solved" the problem of the AXP288 not being able to recognize Type-C chargers by simply always programming the input-current-limit at 3000mA and relying on a Vhold setting of 4.7V (normally 4.4V) to limit the current intake if the charger cannot handle this. 2. If no charger is connected when the machine boots then it boots with the vbus-path disabled. On other devices this is done when a 5V boost converter is active to avoid the PMIC trying to charge from the 5V boost output. This is done when an OTG host cable is inserted and the ID pin on the micro-B receptacle is pulled low, the ID pin has an ACPI event handler associated with it which re-enables the vbus-path when the ID pin is pulled high when the OTG cable is removed. The Type-C connector has no ID pin, there is no ID pin handler and there appears to be no 5V boost converter, so we end up not charging because the vbus-path is disabled, until we unplug the charger which automatically clears the vbus-path disable bit and then on the second plug-in of the adapter we start charging. The HP Pavilion x2 10 models with an AXP288 do have mostly working ACPI AC / Battery code which does not rely on custom / proprietary ACPI OpRegions. So one possible solution would be to blacklist the AXP288 native power_supply drivers and add the HP Pavilion x2 10 with AXP288 DMI ids to the list of devices which should use the ACPI AC / Battery code even though they have an AXP288 PMIC. This would require changes to 4 files: drivers/acpi/ac.c, drivers/power/supply/axp288_charger.c, drivers/acpi/battery.c and drivers/power/supply/axp288_fuel_gauge.c. Beside needing adding the same DMI matches to 4 different files, this approach also triggers problem 2. from above, but then when suspended, during suspend the machine will not wakeup because the vbus path is disabled by the AML code when not charging, so the Vbus low-to-high IRQ is not triggered, the CPU never wakes up and the device does not charge even though the user likely things it is charging, esp. since the charge status LED is directly coupled to an adapter being plugged in and does not reflect actual charging. This could be worked by enabling vbus-path explicitly from say the axp288_charger driver's suspend handler. So neither situation is ideal, in both cased we need to explicitly enable the vbus-path to work around different variants of problem 2 above, this requires a quirk in the axp288_charger code. If we go the route of using the ACPI AC / Battery drivers then we need modifications to 3 other drivers; and we need to partially disable the axp288_charger code, while at the same time keeping it around to enable vbus-path on suspend. OTOH we can copy the hardcoding of 3A input-current-limit (we never touch Vhold, so that would stay at 4.7V) to the axp288_charger code, which needs changes regardless, then we concentrate all special handling of this interesting device model in the axp288_charger code. That is what this commit does. Cc: [email protected] BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1791098 Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Sebastian Reichel <[email protected]>
1 parent e42fe5b commit 9c80662

File tree

1 file changed

+56
-1
lines changed

1 file changed

+56
-1
lines changed

drivers/power/supply/axp288_charger.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/property.h>
2222
#include <linux/mfd/axp20x.h>
2323
#include <linux/extcon.h>
24+
#include <linux/dmi.h>
2425

2526
#define PS_STAT_VBUS_TRIGGER BIT(0)
2627
#define PS_STAT_BAT_CHRG_DIR BIT(2)
@@ -545,6 +546,49 @@ static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
545546
return IRQ_HANDLED;
546547
}
547548

549+
/*
550+
* The HP Pavilion x2 10 series comes in a number of variants:
551+
* Bay Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "815D"
552+
* Cherry Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "813E"
553+
* Cherry Trail SoC + TI PMIC, DMI_BOARD_NAME: "827C" or "82F4"
554+
*
555+
* The variants with the AXP288 PMIC are all kinds of special:
556+
*
557+
* 1. All variants use a Type-C connector which the AXP288 does not support, so
558+
* when using a Type-C charger it is not recognized. Unlike most AXP288 devices,
559+
* this model actually has mostly working ACPI AC / Battery code, the ACPI code
560+
* "solves" this by simply setting the input_current_limit to 3A.
561+
* There are still some issues with the ACPI code, so we use this native driver,
562+
* and to solve the charging not working (500mA is not enough) issue we hardcode
563+
* the 3A input_current_limit like the ACPI code does.
564+
*
565+
* 2. If no charger is connected the machine boots with the vbus-path disabled.
566+
* Normally this is done when a 5V boost converter is active to avoid the PMIC
567+
* trying to charge from the 5V boost converter's output. This is done when
568+
* an OTG host cable is inserted and the ID pin on the micro-B receptacle is
569+
* pulled low and the ID pin has an ACPI event handler associated with it
570+
* which re-enables the vbus-path when the ID pin is pulled high when the
571+
* OTG host cable is removed. The Type-C connector has no ID pin, there is
572+
* no ID pin handler and there appears to be no 5V boost converter, so we
573+
* end up not charging because the vbus-path is disabled, until we unplug
574+
* the charger which automatically clears the vbus-path disable bit and then
575+
* on the second plug-in of the adapter we start charging. To solve the not
576+
* charging on first charger plugin we unconditionally enable the vbus-path at
577+
* probe on this model, which is safe since there is no 5V boost converter.
578+
*/
579+
static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = {
580+
{
581+
/*
582+
* Bay Trail model has "Hewlett-Packard" as sys_vendor, Cherry
583+
* Trail model has "HP", so we only match on product_name.
584+
*/
585+
.matches = {
586+
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
587+
},
588+
},
589+
{} /* Terminating entry */
590+
};
591+
548592
static void axp288_charger_extcon_evt_worker(struct work_struct *work)
549593
{
550594
struct axp288_chrg_info *info =
@@ -568,7 +612,11 @@ static void axp288_charger_extcon_evt_worker(struct work_struct *work)
568612
}
569613

570614
/* Determine cable/charger type */
571-
if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
615+
if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
616+
/* See comment above axp288_hp_x2_dmi_ids declaration */
617+
dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n");
618+
current_limit = 3000000;
619+
} else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
572620
dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
573621
current_limit = 500000;
574622
} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
@@ -685,6 +733,13 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info)
685733
return ret;
686734
}
687735

736+
if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
737+
/* See comment above axp288_hp_x2_dmi_ids declaration */
738+
ret = axp288_charger_vbus_path_select(info, true);
739+
if (ret < 0)
740+
return ret;
741+
}
742+
688743
/* Read current charge voltage and current limit */
689744
ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
690745
if (ret < 0) {

0 commit comments

Comments
 (0)