Merge back power-related ACPI material for v4.12.

This commit is contained in:
Rafael J. Wysocki 2017-04-21 21:12:57 +02:00
commit 8494206dc5
6 changed files with 130 additions and 12 deletions

View File

@ -57,12 +57,23 @@ static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device); static int acpi_ac_remove(struct acpi_device *device);
static void acpi_ac_notify(struct acpi_device *device, u32 event); static void acpi_ac_notify(struct acpi_device *device, u32 event);
struct acpi_ac_bl {
const char *hid;
int hrv;
};
static const struct acpi_device_id ac_device_ids[] = { static const struct acpi_device_id ac_device_ids[] = {
{"ACPI0003", 0}, {"ACPI0003", 0},
{"", 0}, {"", 0},
}; };
MODULE_DEVICE_TABLE(acpi, ac_device_ids); MODULE_DEVICE_TABLE(acpi, ac_device_ids);
/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
static const struct acpi_ac_bl acpi_ac_blacklist[] = {
{ "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
{ "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
};
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int acpi_ac_resume(struct device *dev); static int acpi_ac_resume(struct device *dev);
#endif #endif
@ -424,11 +435,20 @@ static int acpi_ac_remove(struct acpi_device *device)
static int __init acpi_ac_init(void) static int __init acpi_ac_init(void)
{ {
unsigned int i;
int result; int result;
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
acpi_ac_blacklist[i].hrv)) {
pr_info(PREFIX "AC: found native %s PMIC, not loading\n",
acpi_ac_blacklist[i].hid);
return -ENODEV;
}
#ifdef CONFIG_ACPI_PROCFS_POWER #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_dir = acpi_lock_ac_dir(); acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir) if (!acpi_ac_dir)

View File

@ -67,6 +67,7 @@ MODULE_DESCRIPTION("ACPI Battery Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static async_cookie_t async_cookie; static async_cookie_t async_cookie;
static bool battery_driver_registered;
static int battery_bix_broken_package; static int battery_bix_broken_package;
static int battery_notification_delay_ms; static int battery_notification_delay_ms;
static unsigned int cache_time = 1000; static unsigned int cache_time = 1000;
@ -93,6 +94,11 @@ static const struct acpi_device_id battery_device_ids[] = {
MODULE_DEVICE_TABLE(acpi, battery_device_ids); MODULE_DEVICE_TABLE(acpi, battery_device_ids);
/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
static const char * const acpi_battery_blacklist[] = {
"INT33F4", /* X-Powers AXP288 PMIC */
};
enum { enum {
ACPI_BATTERY_ALARM_PRESENT, ACPI_BATTERY_ALARM_PRESENT,
ACPI_BATTERY_XINFO_PRESENT, ACPI_BATTERY_XINFO_PRESENT,
@ -1315,8 +1321,17 @@ static struct acpi_driver acpi_battery_driver = {
static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
{ {
unsigned int i;
int result; int result;
for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
": found native %s PMIC, not loading\n",
acpi_battery_blacklist[i]);
return;
}
dmi_check_system(bat_dmi_table); dmi_check_system(bat_dmi_table);
#ifdef CONFIG_ACPI_PROCFS_POWER #ifdef CONFIG_ACPI_PROCFS_POWER
@ -1329,6 +1344,7 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
if (result < 0) if (result < 0)
acpi_unlock_battery_dir(acpi_battery_dir); acpi_unlock_battery_dir(acpi_battery_dir);
#endif #endif
battery_driver_registered = (result == 0);
} }
static int __init acpi_battery_init(void) static int __init acpi_battery_init(void)
@ -1343,9 +1359,11 @@ static int __init acpi_battery_init(void)
static void __exit acpi_battery_exit(void) static void __exit acpi_battery_exit(void)
{ {
async_synchronize_cookie(async_cookie + 1); async_synchronize_cookie(async_cookie + 1);
acpi_bus_unregister_driver(&acpi_battery_driver); if (battery_driver_registered)
acpi_bus_unregister_driver(&acpi_battery_driver);
#ifdef CONFIG_ACPI_PROCFS_POWER #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_battery_dir(acpi_battery_dir); if (acpi_battery_dir)
acpi_unlock_battery_dir(acpi_battery_dir);
#endif #endif
} }

View File

@ -736,6 +736,72 @@ bool acpi_dev_found(const char *hid)
} }
EXPORT_SYMBOL(acpi_dev_found); EXPORT_SYMBOL(acpi_dev_found);
struct acpi_dev_present_info {
struct acpi_device_id hid[2];
const char *uid;
s64 hrv;
};
static int acpi_dev_present_cb(struct device *dev, void *data)
{
struct acpi_device *adev = to_acpi_device(dev);
struct acpi_dev_present_info *match = data;
unsigned long long hrv;
acpi_status status;
if (acpi_match_device_ids(adev, match->hid))
return 0;
if (match->uid && (!adev->pnp.unique_id ||
strcmp(adev->pnp.unique_id, match->uid)))
return 0;
if (match->hrv == -1)
return 1;
status = acpi_evaluate_integer(adev->handle, "_HRV", NULL, &hrv);
if (ACPI_FAILURE(status))
return 0;
return hrv == match->hrv;
}
/**
* acpi_dev_present - Detect that a given ACPI device is present
* @hid: Hardware ID of the device.
* @uid: Unique ID of the device, pass NULL to not check _UID
* @hrv: Hardware Revision of the device, pass -1 to not check _HRV
*
* Return %true if a matching device was present at the moment of invocation.
* Note that if the device is pluggable, it may since have disappeared.
*
* Note that unlike acpi_dev_found() this function checks the status
* of the device. So for devices which are present in the dsdt, but
* which are disabled (their _STA callback returns 0) this function
* will return false.
*
* For this function to work, acpi_bus_scan() must have been executed
* which happens in the subsys_initcall() subsection. Hence, do not
* call from a subsys_initcall() or earlier (use acpi_get_devices()
* instead). Calling from module_init() is fine (which is synonymous
* with device_initcall()).
*/
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
{
struct acpi_dev_present_info match = {};
struct device *dev;
strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
match.uid = uid;
match.hrv = hrv;
dev = bus_find_device(&acpi_bus_type, NULL, &match,
acpi_dev_present_cb);
return !!dev;
}
EXPORT_SYMBOL(acpi_dev_present);
/* /*
* acpi_backlight= handling, this is done here rather then in video_detect.c * acpi_backlight= handling, this is done here rather then in video_detect.c
* because __setup cannot be used in modules. * because __setup cannot be used in modules.

View File

@ -14,6 +14,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/acpi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
@ -113,7 +114,8 @@
#define ILIM_3000MA 3000 /* 3000mA */ #define ILIM_3000MA 3000 /* 3000mA */
#define AXP288_EXTCON_DEV_NAME "axp288_extcon" #define AXP288_EXTCON_DEV_NAME "axp288_extcon"
#define USB_HOST_EXTCON_DEV_NAME "INT3496:00" #define USB_HOST_EXTCON_HID "INT3496"
#define USB_HOST_EXTCON_NAME "INT3496:00"
static const unsigned int cable_ids[] = static const unsigned int cable_ids[] =
{ EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_CDP, EXTCON_CHG_USB_DCP }; { EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_CDP, EXTCON_CHG_USB_DCP };
@ -807,10 +809,14 @@ static int axp288_charger_probe(struct platform_device *pdev)
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_DEV_NAME); if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
if (info->otg.cable == NULL) { info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n"); if (info->otg.cable == NULL) {
return -EPROBE_DEFER; dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n");
return -EPROBE_DEFER;
}
dev_info(&pdev->dev,
"Using " USB_HOST_EXTCON_HID " extcon for usb-id\n");
} }
platform_set_drvdata(pdev, info); platform_set_drvdata(pdev, info);
@ -849,13 +855,15 @@ static int axp288_charger_probe(struct platform_device *pdev)
/* Register for OTG notification */ /* Register for OTG notification */
INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker); INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt; info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
ret = devm_extcon_register_notifier(&pdev->dev, info->otg.cable, if (info->otg.cable) {
ret = devm_extcon_register_notifier(&pdev->dev, info->otg.cable,
EXTCON_USB_HOST, &info->otg.id_nb); EXTCON_USB_HOST, &info->otg.id_nb);
if (ret) { if (ret) {
dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n"); dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n");
return ret; return ret;
}
schedule_work(&info->otg.work);
} }
schedule_work(&info->otg.work);
/* Register charger interrupts */ /* Register charger interrupts */
for (i = 0; i < CHRG_INTR_END; i++) { for (i = 0; i < CHRG_INTR_END; i++) {

View File

@ -88,6 +88,7 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, u64 rev, u64 func,
} }
bool acpi_dev_found(const char *hid); bool acpi_dev_found(const char *hid);
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI

View File

@ -611,6 +611,11 @@ static inline bool acpi_dev_found(const char *hid)
return false; return false;
} }
static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
{
return false;
}
static inline bool is_acpi_node(struct fwnode_handle *fwnode) static inline bool is_acpi_node(struct fwnode_handle *fwnode)
{ {
return false; return false;