Commit 52e70c8a authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-power', 'acpi-blacklist', 'acpi-video' and 'acpi-doc'

* acpi-power:
  power: supply: axp288_charger: Only wait for INT3496 device if present
  ACPI / AC: Add a blacklist with PMIC ACPI HIDs with a native charger driver
  ACPI / battery: Add a blacklist with PMIC ACPI HIDs with a native battery driver
  ACPI / battery: Fix acpi_battery_exit on acpi_battery_init_async errors
  ACPI / utils: Add new acpi_dev_present helper

* acpi-blacklist:
  ACPI / blacklist: add _REV quirk for Dell Inspiron 7537

* acpi-video:
  ACPI / video: add comments about subtle cases
  ACPI / video: get rid of magic numbers and use enum instead

* acpi-doc:
  ACPI / doc: linuxized-acpica.txt: fix typos
......@@ -24,7 +24,7 @@ upstream.
The homepage of ACPICA project is: www.acpica.org, it is maintained and
supported by Intel Corporation.
The following figure depicts the Linux ACPI subystem where the ACPICA
The following figure depicts the Linux ACPI subsystem where the ACPICA
adaptation is included:
+---------------------------------------------------------+
......@@ -110,7 +110,7 @@ upstream.
Linux patches. The patches generated by this process are referred to as
"linuxized ACPICA patches". The release process is carried out on a local
copy the ACPICA git repository. Each commit in the monthly release is
converted into a linuxized ACPICA patch. Together, they form the montly
converted into a linuxized ACPICA patch. Together, they form the monthly
ACPICA release patchset for the Linux ACPI community. This process is
illustrated in the following figure:
......@@ -165,7 +165,7 @@ upstream.
<http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git>.
Before the linuxized ACPICA patches are sent to the Linux ACPI community
for review, there is a quality ensurance build test process to reduce
for review, there is a quality assurance build test process to reduce
porting issues. Currently this build process only takes care of the
following kernel configuration options:
CONFIG_ACPI/CONFIG_ACPI_DEBUG/CONFIG_ACPI_DEBUGGER
......@@ -195,12 +195,12 @@ upstream.
release utilities (please refer to Section 4 below for the details).
3. Linux specific features - Sometimes it's impossible to use the
current ACPICA APIs to implement features required by the Linux kernel,
so Linux developers occasionaly have to change ACPICA code directly.
so Linux developers occasionally have to change ACPICA code directly.
Those changes may not be acceptable by ACPICA upstream and in such cases
they are left as committed ACPICA divergences unless the ACPICA side can
implement new mechanisms as replacements for them.
4. ACPICA release fixups - ACPICA only tests commits using a set of the
user space simulation utilies, thus the linuxized ACPICA patches may
user space simulation utilities, thus the linuxized ACPICA patches may
break the Linux kernel, leaving us build/boot failures. In order to
avoid breaking Linux bisection, fixes are applied directly to the
linuxized ACPICA patches during the release process. When the release
......
......@@ -57,12 +57,23 @@ static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device);
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[] = {
{"ACPI0003", 0},
{"", 0},
};
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
static int acpi_ac_resume(struct device *dev);
#endif
......@@ -424,11 +435,20 @@ static int acpi_ac_remove(struct acpi_device *device)
static int __init acpi_ac_init(void)
{
unsigned int i;
int result;
if (acpi_disabled)
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
acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir)
......
This diff is collapsed.
......@@ -67,6 +67,7 @@ MODULE_DESCRIPTION("ACPI Battery Driver");
MODULE_LICENSE("GPL");
static async_cookie_t async_cookie;
static bool battery_driver_registered;
static int battery_bix_broken_package;
static int battery_notification_delay_ms;
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);
/* 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 {
ACPI_BATTERY_ALARM_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)
{
unsigned int i;
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);
#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)
acpi_unlock_battery_dir(acpi_battery_dir);
#endif
battery_driver_registered = (result == 0);
}
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)
{
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
acpi_unlock_battery_dir(acpi_battery_dir);
if (acpi_battery_dir)
acpi_unlock_battery_dir(acpi_battery_dir);
#endif
}
......
......@@ -188,6 +188,14 @@ static struct dmi_system_id acpi_rev_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"),
},
},
{
.callback = dmi_enable_rev_override,
.ident = "DELL Inspiron 7537",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
},
},
#endif
{}
};
......
......@@ -736,6 +736,72 @@ bool acpi_dev_found(const char *hid)
}
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
* because __setup cannot be used in modules.
......
......@@ -14,6 +14,7 @@
* GNU General Public License for more details.
*/
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/regmap.h>
......@@ -113,7 +114,8 @@
#define ILIM_3000MA 3000 /* 3000mA */
#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[] =
{ 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;
}
info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_DEV_NAME);
if (info->otg.cable == NULL) {
dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n");
return -EPROBE_DEFER;
if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
if (info->otg.cable == NULL) {
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);
......@@ -849,13 +855,15 @@ static int axp288_charger_probe(struct platform_device *pdev)
/* Register for OTG notification */
INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
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);
if (ret) {
dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n");
return ret;
if (ret) {
dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n");
return ret;
}
schedule_work(&info->otg.work);
}
schedule_work(&info->otg.work);
/* Register charger interrupts */
for (i = 0; i < CHRG_INTR_END; i++) {
......
......@@ -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_present(const char *hid, const char *uid, s64 hrv);
#ifdef CONFIG_ACPI
......
......@@ -607,6 +607,11 @@ static inline bool acpi_dev_found(const char *hid)
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)
{
return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment