From 45e9aa1fdbb2ebafec88c64bc53fe45cf8935b49 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 10 Aug 2022 18:14:22 +0200 Subject: ACPI: Rename acpi_bus_get/put_acpi_device() Because acpi_bus_get_acpi_device() is completely analogous to acpi_fetch_acpi_dev(), rename it to acpi_get_acpi_dev() and add a kerneldoc comment to it. Accordingly, rename acpi_bus_put_acpi_device() to acpi_put_acpi_dev() and update all of the users of these two functions. While at it, move the acpi_fetch_acpi_dev() header next to the acpi_get_acpi_dev() header in the header file holding them. Signed-off-by: Rafael J. Wysocki Acked-by: Guenter Roeck Reviewed-by: Punit Agrawal --- drivers/acpi/bus.c | 6 +++--- drivers/acpi/device_pm.c | 4 ++-- drivers/acpi/irq.c | 4 ++-- drivers/acpi/scan.c | 21 ++++++++++++++++----- drivers/hwmon/acpi_power_meter.c | 2 +- 5 files changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c0d20d997891..f43c6a4b0827 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -511,7 +511,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) break; } - adev = acpi_bus_get_acpi_device(handle); + adev = acpi_get_acpi_dev(handle); if (!adev) goto err; @@ -524,14 +524,14 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) } if (!hotplug_event) { - acpi_bus_put_acpi_device(adev); + acpi_put_acpi_dev(adev); return; } if (ACPI_SUCCESS(acpi_hotplug_schedule(adev, type))) return; - acpi_bus_put_acpi_device(adev); + acpi_put_acpi_dev(adev); err: acpi_evaluate_ost(handle, type, ost_code, NULL); diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 9dce1245689c..2b7e08d54c3f 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -497,7 +497,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) acpi_handle_debug(handle, "Wake notify\n"); - adev = acpi_bus_get_acpi_device(handle); + adev = acpi_get_acpi_dev(handle); if (!adev) return; @@ -515,7 +515,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) mutex_unlock(&acpi_pm_notifier_lock); - acpi_bus_put_acpi_device(adev); + acpi_put_acpi_dev(adev); } /** diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c index dabe45eba055..4db5bb587599 100644 --- a/drivers/acpi/irq.c +++ b/drivers/acpi/irq.c @@ -118,12 +118,12 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source, if (WARN_ON(ACPI_FAILURE(status))) return NULL; - device = acpi_bus_get_acpi_device(handle); + device = acpi_get_acpi_dev(handle); if (WARN_ON(!device)) return NULL; result = &device->fwnode; - acpi_bus_put_acpi_device(device); + acpi_put_acpi_dev(device); return result; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 42cec8120f18..b3ee0823f735 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -429,7 +429,7 @@ void acpi_device_hotplug(struct acpi_device *adev, u32 src) acpi_evaluate_ost(adev->handle, src, ost_code, NULL); out: - acpi_bus_put_acpi_device(adev); + acpi_put_acpi_dev(adev); mutex_unlock(&acpi_scan_lock); unlock_device_hotplug(); } @@ -599,11 +599,22 @@ static void get_acpi_device(void *dev) acpi_dev_get(dev); } -struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle) +/** + * acpi_get_acpi_dev - Retrieve ACPI device object and reference count it. + * @handle: ACPI handle associated with the requested ACPI device object. + * + * Return a pointer to the ACPI device object associated with @handle and bump + * up that object's reference counter (under the ACPI Namespace lock), if + * present, or return NULL otherwise. + * + * The ACPI device object reference acquired by this function needs to be + * dropped via acpi_dev_put(). + */ +struct acpi_device *acpi_get_acpi_dev(acpi_handle handle) { return handle_to_device(handle, get_acpi_device); } -EXPORT_SYMBOL_GPL(acpi_bus_get_acpi_device); +EXPORT_SYMBOL_GPL(acpi_get_acpi_dev); static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id) { @@ -2239,7 +2250,7 @@ static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *d { struct acpi_device *adev; - adev = acpi_bus_get_acpi_device(dep->consumer); + adev = acpi_get_acpi_dev(dep->consumer); if (adev) { *(struct acpi_device **)data = adev; return 1; @@ -2292,7 +2303,7 @@ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev) static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data) { - struct acpi_device *adev = acpi_bus_get_acpi_device(dep->consumer); + struct acpi_device *adev = acpi_get_acpi_dev(dep->consumer); if (adev) { adev->dep_unmet--; diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index d2545a1be9fc..44e04c75d0d3 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -598,7 +598,7 @@ static int read_domain_devices(struct acpi_power_meter_resource *resource) continue; /* Create a symlink to domain objects */ - obj = acpi_bus_get_acpi_device(element->reference.handle); + obj = acpi_get_acpi_dev(element->reference.handle); resource->domain_devices[i] = obj; if (!obj) continue; -- cgit v1.2.3 From f6f1e12f3add6e9d85d9fa1916bf4b2a39d8c194 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 10 Aug 2022 18:15:24 +0200 Subject: ACPI: scan: Rename acpi_bus_get_parent() and rearrange it The acpi_bus_get_parent() name doesn't really reflect the purpose of the function so change it to a more accurate acpi_find_parent_acpi_dev(). While at it, rearrange the code inside that function to make it easier to read. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Punit Agrawal --- drivers/acpi/scan.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b3ee0823f735..25a104d0b743 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -816,10 +816,9 @@ static const char * const acpi_honor_dep_ids[] = { NULL }; -static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) +static struct acpi_device *acpi_find_parent_acpi_dev(acpi_handle handle) { - struct acpi_device *device; - acpi_status status; + struct acpi_device *adev; /* * Fixed hardware devices do not appear in the namespace and do not @@ -830,13 +829,18 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) return acpi_root; do { + acpi_status status; + status = acpi_get_parent(handle, &handle); - if (ACPI_FAILURE(status)) - return status == AE_NULL_ENTRY ? NULL : acpi_root; + if (ACPI_FAILURE(status)) { + if (status != AE_NULL_ENTRY) + return acpi_root; - device = acpi_fetch_acpi_dev(handle); - } while (!device); - return device; + return NULL; + } + adev = acpi_fetch_acpi_dev(handle); + } while (!adev); + return adev; } acpi_status @@ -1778,7 +1782,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, INIT_LIST_HEAD(&device->pnp.ids); device->device_type = type; device->handle = handle; - device->parent = acpi_bus_get_parent(handle); + device->parent = acpi_find_parent_acpi_dev(handle); fwnode_init(&device->fwnode, &acpi_device_fwnode_ops); acpi_set_device_status(device, ACPI_STA_DEFAULT); acpi_device_get_busid(device); -- cgit v1.2.3 From 5c5e1237032aaa39107e2d0bb8e6cb84b3c41161 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 10 Aug 2022 18:16:33 +0200 Subject: ACPI: scan: Rearrange initialization of ACPI device objects The initialization of ACPI device objects is split between acpi_init_device_object() and __acpi_device_add() that initializes the dev field in struct acpi_device. The "release" function pointer is passed to __acpi_device_add() for this reason. However, that split is artificial and all of the initialization can be carried out by acpi_init_device_object(), so rearrange the code to that end. In particular, make acpi_init_device_object() take the "release" pointer as an argument, along with the "type" which is related to it, instead of __acpi_device_add(). No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Punit Agrawal --- drivers/acpi/internal.h | 5 ++--- drivers/acpi/power.c | 5 +++-- drivers/acpi/scan.c | 27 ++++++++++++++------------- 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 628bf8f18130..b799585eae2a 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -102,10 +102,9 @@ struct acpi_device_bus_id { struct list_head node; }; -int acpi_device_add(struct acpi_device *device, - void (*release)(struct device *)); void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, - int type); + int type, void (*release)(struct device *)); +int acpi_device_add(struct acpi_device *device); int acpi_device_setup_files(struct acpi_device *dev); void acpi_device_remove_files(struct acpi_device *dev); void acpi_device_add_finalize(struct acpi_device *device); diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 8c4a73a1351e..2ae48ab88396 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -944,7 +944,8 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) return NULL; device = &resource->device; - acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER); + acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER, + acpi_release_power_resource); mutex_init(&resource->resource_lock); INIT_LIST_HEAD(&resource->list_node); INIT_LIST_HEAD(&resource->dependents); @@ -968,7 +969,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); device->flags.match_driver = true; - result = acpi_device_add(device, acpi_release_power_resource); + result = acpi_device_add(device); if (result) goto err; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 25a104d0b743..75a32f2d0f33 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -673,8 +673,7 @@ static void acpi_store_pld_crc(struct acpi_device *adev) ACPI_FREE(pld); } -static int __acpi_device_add(struct acpi_device *device, - void (*release)(struct device *)) +static int __acpi_device_add(struct acpi_device *device) { struct acpi_device_bus_id *acpi_device_bus_id; int result; @@ -730,11 +729,6 @@ static int __acpi_device_add(struct acpi_device *device, mutex_unlock(&acpi_device_lock); - if (device->parent) - device->dev.parent = &device->parent->dev; - - device->dev.bus = &acpi_bus_type; - device->dev.release = release; result = device_add(&device->dev); if (result) { dev_err(&device->dev, "Error registering device\n"); @@ -761,7 +755,7 @@ err_unlock: return result; } -int acpi_device_add(struct acpi_device *adev, void (*release)(struct device *)) +int acpi_device_add(struct acpi_device *adev) { int ret; @@ -769,7 +763,7 @@ int acpi_device_add(struct acpi_device *adev, void (*release)(struct device *)) if (ret) return ret; - return __acpi_device_add(adev, release); + return __acpi_device_add(adev); } /* -------------------------------------------------------------------------- @@ -1777,12 +1771,19 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) } void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, - int type) + int type, void (*release)(struct device *)) { + struct acpi_device *parent = acpi_find_parent_acpi_dev(handle); + INIT_LIST_HEAD(&device->pnp.ids); device->device_type = type; device->handle = handle; - device->parent = acpi_find_parent_acpi_dev(handle); + if (parent) { + device->parent = parent; + device->dev.parent = &parent->dev; + } + device->dev.release = release; + device->dev.bus = &acpi_bus_type; fwnode_init(&device->fwnode, &acpi_device_fwnode_ops); acpi_set_device_status(device, ACPI_STA_DEFAULT); acpi_device_get_busid(device); @@ -1836,7 +1837,7 @@ static int acpi_add_single_object(struct acpi_device **child, if (!device) return -ENOMEM; - acpi_init_device_object(device, handle, type); + acpi_init_device_object(device, handle, type, acpi_device_release); /* * Getting the status is delayed till here so that we can call * acpi_bus_get_status() and use its quirk handling. Note that @@ -1866,7 +1867,7 @@ static int acpi_add_single_object(struct acpi_device **child, mutex_unlock(&acpi_dep_list_lock); if (!result) - result = __acpi_device_add(device, acpi_device_release); + result = __acpi_device_add(device); if (result) { acpi_device_release(&device->dev); -- cgit v1.2.3 From 6e1850b2f3747942d3813a2fde82f1e46aa593d1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 10 Aug 2022 18:17:23 +0200 Subject: ACPI: scan: Eliminate __acpi_device_add() Instead of having acpi_device_add() defined as a wrapper around __acpi_device_add(), export acpi_tie_acpi_dev() so it can be called directly by acpi_add_power_resource(), fold acpi_device_add() into the latter and rename __acpi_device_add() to acpi_device_add(). No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Punit Agrawal --- drivers/acpi/internal.h | 1 + drivers/acpi/power.c | 6 +++++- drivers/acpi/scan.c | 17 +++-------------- 3 files changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index b799585eae2a..219c02df9a08 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -104,6 +104,7 @@ struct acpi_device_bus_id { void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, int type, void (*release)(struct device *)); +int acpi_tie_acpi_dev(struct acpi_device *adev); int acpi_device_add(struct acpi_device *device); int acpi_device_setup_files(struct acpi_device *dev); void acpi_device_remove_files(struct acpi_device *dev); diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 2ae48ab88396..f2588aba8421 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -952,6 +952,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); device->power.state = ACPI_STATE_UNKNOWN; + device->flags.match_driver = true; /* Evaluate the object to get the system level and resource order. */ status = acpi_evaluate_object(handle, NULL, NULL, &buffer); @@ -968,7 +969,10 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); - device->flags.match_driver = true; + result = acpi_tie_acpi_dev(device); + if (result) + goto err; + result = acpi_device_add(device); if (result) goto err; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 75a32f2d0f33..0d9c350608bf 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -643,7 +643,7 @@ static int acpi_device_set_name(struct acpi_device *device, return 0; } -static int acpi_tie_acpi_dev(struct acpi_device *adev) +int acpi_tie_acpi_dev(struct acpi_device *adev) { acpi_handle handle = adev->handle; acpi_status status; @@ -673,7 +673,7 @@ static void acpi_store_pld_crc(struct acpi_device *adev) ACPI_FREE(pld); } -static int __acpi_device_add(struct acpi_device *device) +int acpi_device_add(struct acpi_device *device) { struct acpi_device_bus_id *acpi_device_bus_id; int result; @@ -755,17 +755,6 @@ err_unlock: return result; } -int acpi_device_add(struct acpi_device *adev) -{ - int ret; - - ret = acpi_tie_acpi_dev(adev); - if (ret) - return ret; - - return __acpi_device_add(adev); -} - /* -------------------------------------------------------------------------- Device Enumeration -------------------------------------------------------------------------- */ @@ -1867,7 +1856,7 @@ static int acpi_add_single_object(struct acpi_device **child, mutex_unlock(&acpi_dep_list_lock); if (!result) - result = __acpi_device_add(device); + result = acpi_device_add(device); if (result) { acpi_device_release(&device->dev); -- cgit v1.2.3 From 62fcb99bdf10fed34b4fe6e225489fe4be2d0536 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 24 Aug 2022 18:59:48 +0200 Subject: ACPI: Drop parent field from struct acpi_device The parent field in struct acpi_device is, in fact, redundant, because the dev.parent field in it effectively points to the same object and it is used by the driver core. Accordingly, the parent field can be dropped from struct acpi_device and for this purpose define acpi_dev_parent() to retrieve a parent struct acpi_device pointer from the dev.parent field in struct acpi_device. Next, update all of the users of the parent field in struct acpi_device to use acpi_dev_parent() instead of it and drop it. While at it, drop the ACPI_IS_ROOT_DEVICE() macro that is only used in one place in a confusing way. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Mark Brown Acked-by: Mika Westerberg Acked-by: Wei Liu Reviewed-by: Punit Agrawal --- drivers/acpi/acpi_amba.c | 5 +++-- drivers/acpi/acpi_platform.c | 6 +++--- drivers/acpi/acpi_video.c | 2 +- drivers/acpi/device_pm.c | 19 ++++++++++--------- drivers/acpi/property.c | 6 ++++-- drivers/acpi/sbs.c | 2 +- drivers/acpi/sbshc.c | 2 +- drivers/acpi/scan.c | 17 ++++++----------- drivers/hv/vmbus_drv.c | 3 ++- drivers/perf/arm_dsu_pmu.c | 4 ++-- drivers/perf/qcom_l3_pmu.c | 3 ++- drivers/spi/spi.c | 2 +- drivers/thunderbolt/acpi.c | 2 +- include/acpi/acpi_bus.h | 10 +++++++++- 14 files changed, 46 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_amba.c b/drivers/acpi/acpi_amba.c index ab8a4e0191b1..9d69546db2a4 100644 --- a/drivers/acpi/acpi_amba.c +++ b/drivers/acpi/acpi_amba.c @@ -48,6 +48,7 @@ static void amba_register_dummy_clk(void) static int amba_handler_attach(struct acpi_device *adev, const struct acpi_device_id *id) { + struct acpi_device *parent = acpi_dev_parent(adev); struct amba_device *dev; struct resource_entry *rentry; struct list_head resource_list; @@ -97,8 +98,8 @@ static int amba_handler_attach(struct acpi_device *adev, * attached to it, that physical device should be the parent of * the amba device we are about to create. */ - if (adev->parent) - dev->dev.parent = acpi_get_first_physical_node(adev->parent); + if (parent) + dev->dev.parent = acpi_get_first_physical_node(parent); ACPI_COMPANION_SET(&dev->dev, adev); diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index de3cbf152dee..1a1c78b23fba 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -78,7 +78,7 @@ static void acpi_platform_fill_resource(struct acpi_device *adev, * If the device has parent we need to take its resources into * account as well because this device might consume part of those. */ - parent = acpi_get_first_physical_node(adev->parent); + parent = acpi_get_first_physical_node(acpi_dev_parent(adev)); if (parent && dev_is_pci(parent)) dest->parent = pci_find_resource(to_pci_dev(parent), dest); } @@ -97,6 +97,7 @@ static void acpi_platform_fill_resource(struct acpi_device *adev, struct platform_device *acpi_create_platform_device(struct acpi_device *adev, const struct property_entry *properties) { + struct acpi_device *parent = acpi_dev_parent(adev); struct platform_device *pdev = NULL; struct platform_device_info pdevinfo; struct resource_entry *rentry; @@ -137,8 +138,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, * attached to it, that physical device should be the parent of the * platform device we are about to create. */ - pdevinfo.parent = adev->parent ? - acpi_get_first_physical_node(adev->parent) : NULL; + pdevinfo.parent = parent ? acpi_get_first_physical_node(parent) : NULL; pdevinfo.name = dev_name(&adev->dev); pdevinfo.id = -1; pdevinfo.res = resources; diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 5cbe2196176d..92a6c6f9a9a7 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -2030,7 +2030,7 @@ static int acpi_video_bus_add(struct acpi_device *device) acpi_status status; status = acpi_walk_namespace(ACPI_TYPE_DEVICE, - device->parent->handle, 1, + acpi_dev_parent(device)->handle, 1, acpi_video_bus_match, NULL, device, NULL); if (status == AE_ALREADY_EXISTS) { diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 2b7e08d54c3f..028d8d14cd44 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -74,6 +74,7 @@ static int acpi_dev_pm_explicit_get(struct acpi_device *device, int *state) */ int acpi_device_get_power(struct acpi_device *device, int *state) { + struct acpi_device *parent = acpi_dev_parent(device); int result = ACPI_STATE_UNKNOWN; int error; @@ -82,8 +83,7 @@ int acpi_device_get_power(struct acpi_device *device, int *state) if (!device->flags.power_manageable) { /* TBD: Non-recursive algorithm for walking up hierarchy. */ - *state = device->parent ? - device->parent->power.state : ACPI_STATE_D0; + *state = parent ? parent->power.state : ACPI_STATE_D0; goto out; } @@ -122,10 +122,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state) * point, the fact that the device is in D0 implies that the parent has * to be in D0 too, except if ignore_parent is set. */ - if (!device->power.flags.ignore_parent && device->parent - && device->parent->power.state == ACPI_STATE_UNKNOWN - && result == ACPI_STATE_D0) - device->parent->power.state = ACPI_STATE_D0; + if (!device->power.flags.ignore_parent && parent && + parent->power.state == ACPI_STATE_UNKNOWN && + result == ACPI_STATE_D0) + parent->power.state = ACPI_STATE_D0; *state = result; @@ -159,6 +159,7 @@ static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) */ int acpi_device_set_power(struct acpi_device *device, int state) { + struct acpi_device *parent = acpi_dev_parent(device); int target_state = state; int result = 0; @@ -191,12 +192,12 @@ int acpi_device_set_power(struct acpi_device *device, int state) return -ENODEV; } - if (!device->power.flags.ignore_parent && device->parent && - state < device->parent->power.state) { + if (!device->power.flags.ignore_parent && parent && + state < parent->power.state) { acpi_handle_debug(device->handle, "Cannot transition to %s for parent in %s\n", acpi_power_state_string(state), - acpi_power_state_string(device->parent->power.state)); + acpi_power_state_string(parent->power.state)); return -ENODEV; } diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 7b3ad8ed2f4e..3dab3ac9c4a1 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -304,8 +304,10 @@ static void acpi_init_of_compatible(struct acpi_device *adev) ret = acpi_dev_get_property(adev, "compatible", ACPI_TYPE_STRING, &of_compatible); if (ret) { - if (adev->parent - && adev->parent->flags.of_compatible_ok) + struct acpi_device *parent; + + parent = acpi_dev_parent(adev); + if (parent && parent->flags.of_compatible_ok) goto out; return; diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 4938010fcac7..e6a01a8df1b8 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -632,7 +632,7 @@ static int acpi_sbs_add(struct acpi_device *device) mutex_init(&sbs->lock); - sbs->hc = acpi_driver_data(device->parent); + sbs->hc = acpi_driver_data(acpi_dev_parent(device)); sbs->device = device; strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_SBS_CLASS); diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 7c62e149a7a1..340e0b61587e 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -266,7 +266,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device) mutex_init(&hc->lock); init_waitqueue_head(&hc->wait); - hc->ec = acpi_driver_data(device->parent); + hc->ec = acpi_driver_data(acpi_dev_parent(device)); hc->offset = (val >> 8) & 0xff; hc->query_bit = val & 0xff; device->driver_data = hc; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0d9c350608bf..f6b9ea937de1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -29,8 +29,6 @@ extern struct acpi_device *acpi_root; #define ACPI_BUS_HID "LNXSYBUS" #define ACPI_BUS_DEVICE_NAME "System Bus" -#define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) - #define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page) static const char *dummy_hid = "device"; @@ -1110,7 +1108,7 @@ static void acpi_device_get_busid(struct acpi_device *device) * The device's Bus ID is simply the object name. * TBD: Shouldn't this value be unique (within the ACPI namespace)? */ - if (ACPI_IS_ROOT_DEVICE(device)) { + if (!acpi_dev_parent(device)) { strcpy(device->pnp.bus_id, "ACPI"); return; } @@ -1646,7 +1644,7 @@ static void acpi_init_coherency(struct acpi_device *adev) { unsigned long long cca = 0; acpi_status status; - struct acpi_device *parent = adev->parent; + struct acpi_device *parent = acpi_dev_parent(adev); if (parent && parent->flags.cca_seen) { /* @@ -1690,7 +1688,7 @@ static int acpi_check_serial_bus_slave(struct acpi_resource *ares, void *data) static bool acpi_is_indirect_io_slave(struct acpi_device *device) { - struct acpi_device *parent = device->parent; + struct acpi_device *parent = acpi_dev_parent(device); static const struct acpi_device_id indirect_io_hosts[] = { {"HISI0191", 0}, {} @@ -1767,10 +1765,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, INIT_LIST_HEAD(&device->pnp.ids); device->device_type = type; device->handle = handle; - if (parent) { - device->parent = parent; - device->dev.parent = &parent->dev; - } + device->dev.parent = parent ? &parent->dev : NULL; device->dev.release = release; device->dev.bus = &acpi_bus_type; fwnode_init(&device->fwnode, &acpi_device_fwnode_ops); @@ -1867,8 +1862,8 @@ static int acpi_add_single_object(struct acpi_device **child, acpi_device_add_finalize(device); acpi_handle_debug(handle, "Added as %s, parent %s\n", - dev_name(&device->dev), device->parent ? - dev_name(&device->parent->dev) : "(null)"); + dev_name(&device->dev), device->dev.parent ? + dev_name(device->dev.parent) : "(null)"); *child = device; return 0; diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 23c680d1a0f5..c905d40964cb 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -2427,7 +2427,8 @@ static int vmbus_acpi_add(struct acpi_device *device) * Some ancestor of the vmbus acpi device (Gen1 or Gen2 * firmware) is the VMOD that has the mmio ranges. Get that. */ - for (ancestor = device->parent; ancestor; ancestor = ancestor->parent) { + for (ancestor = acpi_dev_parent(device); ancestor; + ancestor = acpi_dev_parent(ancestor)) { result = acpi_walk_resources(ancestor->handle, METHOD_NAME__CRS, vmbus_walk_resources, NULL); diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c index a36698a90d2f..4a15c86f45ef 100644 --- a/drivers/perf/arm_dsu_pmu.c +++ b/drivers/perf/arm_dsu_pmu.c @@ -639,6 +639,7 @@ static int dsu_pmu_dt_get_cpus(struct device *dev, cpumask_t *mask) static int dsu_pmu_acpi_get_cpus(struct device *dev, cpumask_t *mask) { #ifdef CONFIG_ACPI + struct acpi_device *parent_adev = acpi_dev_parent(ACPI_COMPANION(dev)); int cpu; /* @@ -653,8 +654,7 @@ static int dsu_pmu_acpi_get_cpus(struct device *dev, cpumask_t *mask) continue; acpi_dev = ACPI_COMPANION(cpu_dev); - if (acpi_dev && - acpi_dev->parent == ACPI_COMPANION(dev)->parent) + if (acpi_dev && acpi_dev_parent(acpi_dev) == parent_adev) cpumask_set_cpu(cpu, mask); } #endif diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c index 1ff2ff6582bf..346311a05460 100644 --- a/drivers/perf/qcom_l3_pmu.c +++ b/drivers/perf/qcom_l3_pmu.c @@ -742,7 +742,8 @@ static int qcom_l3_cache_pmu_probe(struct platform_device *pdev) l3pmu = devm_kzalloc(&pdev->dev, sizeof(*l3pmu), GFP_KERNEL); name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "l3cache_%s_%s", - acpi_dev->parent->pnp.unique_id, acpi_dev->pnp.unique_id); + acpi_dev_parent(acpi_dev)->pnp.unique_id, + acpi_dev->pnp.unique_id); if (!l3pmu || !name) return -ENOMEM; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 83da8862b8f2..58302259a5e3 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -4375,7 +4375,7 @@ static int acpi_spi_notify(struct notifier_block *nb, unsigned long value, switch (value) { case ACPI_RECONFIG_DEVICE_ADD: - ctlr = acpi_spi_find_controller_by_adev(adev->parent); + ctlr = acpi_spi_find_controller_by_adev(acpi_dev_parent(adev)); if (!ctlr) break; diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c index b1f0dc8df47c..7a8adf5ad5a0 100644 --- a/drivers/thunderbolt/acpi.c +++ b/drivers/thunderbolt/acpi.c @@ -42,7 +42,7 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, */ dev = acpi_get_first_physical_node(adev); while (!dev) { - adev = adev->parent; + adev = acpi_dev_parent(adev); if (!adev) break; dev = acpi_get_first_physical_node(adev); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7ff067a5a3bd..6289020fdab8 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -365,7 +365,6 @@ struct acpi_device { int device_type; acpi_handle handle; /* no handle for fixed hardware */ struct fwnode_handle fwnode; - struct acpi_device *parent; struct list_head wakeup_list; struct list_head del_list; struct acpi_device_status status; @@ -458,6 +457,14 @@ static inline void *acpi_driver_data(struct acpi_device *d) #define to_acpi_device(d) container_of(d, struct acpi_device, dev) #define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) +static inline struct acpi_device *acpi_dev_parent(struct acpi_device *adev) +{ + if (adev->dev.parent) + return to_acpi_device(adev->dev.parent); + + return NULL; +} + static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta) { *((u32 *)&adev->status) = sta; @@ -478,6 +485,7 @@ void acpi_initialize_hp_context(struct acpi_device *adev, /* acpi_device.dev.bus == &acpi_bus_type */ extern struct bus_type acpi_bus_type; +struct acpi_device *acpi_dev_parent(struct acpi_device *adev); int acpi_bus_for_each_dev(int (*fn)(struct device *, void *), void *data); int acpi_dev_for_each_child(struct acpi_device *adev, int (*fn)(struct acpi_device *, void *), void *data); -- cgit v1.2.3 From d5008ef5b5a21177d3042816542f1afd5ae36152 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 29 Aug 2022 17:21:43 +0200 Subject: ACPI: PM: Fix NULL argument handling in acpi_device_get/set_power() In principle, it should be valid to pass NULL as the ACPI device pointer to acpi_device_get_power() and acpi_device_set_power() and they both are expected to return -EINVAL in that case, but that has been broken recently by commit 62fcb99bdf10 ("ACPI: Drop parent field from struct acpi_device") which has caused the ACPI device pointer to be dereferenced in these functions before the NULL check. Fix that and while at it make acpi_device_set_power() only use the parent field if the target ACPI device object's ignore_parent flag in not set. Fixes: 62fcb99bdf10 ("ACPI: Drop parent field from struct acpi_device") Reported-by: Dan Carpenter Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 028d8d14cd44..3aca67cf9ce5 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -74,13 +74,15 @@ static int acpi_dev_pm_explicit_get(struct acpi_device *device, int *state) */ int acpi_device_get_power(struct acpi_device *device, int *state) { - struct acpi_device *parent = acpi_dev_parent(device); int result = ACPI_STATE_UNKNOWN; + struct acpi_device *parent; int error; if (!device || !state) return -EINVAL; + parent = acpi_dev_parent(device); + if (!device->flags.power_manageable) { /* TBD: Non-recursive algorithm for walking up hierarchy. */ *state = parent ? parent->power.state : ACPI_STATE_D0; @@ -159,7 +161,6 @@ static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) */ int acpi_device_set_power(struct acpi_device *device, int state) { - struct acpi_device *parent = acpi_dev_parent(device); int target_state = state; int result = 0; @@ -192,13 +193,17 @@ int acpi_device_set_power(struct acpi_device *device, int state) return -ENODEV; } - if (!device->power.flags.ignore_parent && parent && - state < parent->power.state) { - acpi_handle_debug(device->handle, - "Cannot transition to %s for parent in %s\n", - acpi_power_state_string(state), - acpi_power_state_string(parent->power.state)); - return -ENODEV; + if (!device->power.flags.ignore_parent) { + struct acpi_device *parent; + + parent = acpi_dev_parent(device); + if (parent && state < parent->power.state) { + acpi_handle_debug(device->handle, + "Cannot transition to %s for parent in %s\n", + acpi_power_state_string(state), + acpi_power_state_string(parent->power.state)); + return -ENODEV; + } } /* -- cgit v1.2.3 From 98378956a407392109817278c6edd464252c7a83 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 29 Aug 2022 18:12:33 +0200 Subject: ACPI: property: Use acpi_dev_parent() After introducing acpi_dev_parent() in commit 62fcb99bdf10 ("ACPI: Drop parent field from struct acpi_device"), it is better to use it instead of accessing the dev.parent field in struct acpi_device directly. Modify acpi_node_get_parent() accordingly. Suggested-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko --- drivers/acpi/property.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 3dab3ac9c4a1..f7c38481f42c 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -1270,10 +1270,11 @@ acpi_node_get_parent(const struct fwnode_handle *fwnode) return to_acpi_data_node(fwnode)->parent; } if (is_acpi_device_node(fwnode)) { - struct device *dev = to_acpi_device_node(fwnode)->dev.parent; + struct acpi_device *parent; - if (dev) - return acpi_fwnode_handle(to_acpi_device(dev)); + parent = acpi_dev_parent(to_acpi_device_node(fwnode)); + if (parent) + return acpi_fwnode_handle(parent); } return NULL; -- cgit v1.2.3 From cca8a7efea6402f463239a1bb337d01b0cad7b2e Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Thu, 22 Sep 2022 00:04:35 +0100 Subject: ACPI: scan: Add acpi_dev_get_next_consumer_dev() In commit b83e2b306736 ("ACPI: scan: Add function to fetch dependent of ACPI device") we added a means of fetching the first device to declare itself dependent on another ACPI device in the _DEP method. One assumption in that patch was that there would only be a single consuming device, but this has not held. Replace that function with a new function that fetches the next consumer of a supplier device. Where no "previous" consumer is passed in, it behaves identically to the original function. Reviewed-by: Hans de Goede Signed-off-by: Daniel Scally Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 40 +++++++++++++++++++++-------- drivers/platform/x86/intel/int3472/common.c | 2 +- include/acpi/acpi_bus.h | 4 ++- 3 files changed, 34 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f6b9ea937de1..d0277427e7ee 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2235,9 +2235,22 @@ ok: return 0; } -static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *data) +static int acpi_dev_get_next_consumer_dev_cb(struct acpi_dep_data *dep, void *data) { - struct acpi_device *adev; + struct acpi_device **adev_p = data; + struct acpi_device *adev = *adev_p; + + /* + * If we're passed a 'previous' consumer device then we need to skip + * any consumers until we meet the previous one, and then NULL @data + * so the next one can be returned. + */ + if (adev) { + if (dep->consumer == adev->handle) + *adev_p = NULL; + + return 0; + } adev = acpi_get_acpi_dev(dep->consumer); if (adev) { @@ -2368,25 +2381,32 @@ bool acpi_dev_ready_for_enumeration(const struct acpi_device *device) EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration); /** - * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier + * acpi_dev_get_next_consumer_dev - Return the next adev dependent on @supplier * @supplier: Pointer to the dependee device + * @start: Pointer to the current dependent device * - * Returns the first &struct acpi_device which declares itself dependent on + * Returns the next &struct acpi_device which declares itself dependent on * @supplier via the _DEP buffer, parsed from the acpi_dep_list. * - * The caller is responsible for putting the reference to adev when it is no - * longer needed. + * If the returned adev is not passed as @start to this function, the caller is + * responsible for putting the reference to adev when it is no longer needed. */ -struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier) +struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier, + struct acpi_device *start) { - struct acpi_device *adev = NULL; + struct acpi_device *adev = start; acpi_walk_dep_device_list(supplier->handle, - acpi_dev_get_first_consumer_dev_cb, &adev); + acpi_dev_get_next_consumer_dev_cb, &adev); + + acpi_dev_put(start); + + if (adev == start) + return NULL; return adev; } -EXPORT_SYMBOL_GPL(acpi_dev_get_first_consumer_dev); +EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev); /** * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. diff --git a/drivers/platform/x86/intel/int3472/common.c b/drivers/platform/x86/intel/int3472/common.c index 77cf058e4168..9db2bb0bbba4 100644 --- a/drivers/platform/x86/intel/int3472/common.c +++ b/drivers/platform/x86/intel/int3472/common.c @@ -62,7 +62,7 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev, struct acpi_device *sensor; int ret = 0; - sensor = acpi_dev_get_first_consumer_dev(adev); + sensor = acpi_dev_get_next_consumer_dev(adev, NULL); if (!sensor) { dev_err(dev, "INT3472 seems to have no dependents.\n"); return -ENODEV; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 42f76f2c2d49..c66d17c3298b 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -742,7 +742,9 @@ bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const ch void acpi_dev_clear_dependencies(struct acpi_device *supplier); bool acpi_dev_ready_for_enumeration(const struct acpi_device *device); -struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier); +struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier, + struct acpi_device *start); + struct acpi_device * acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv); struct acpi_device * -- cgit v1.2.3 From 43cf36974d760a3d1c705a83de89ac58059e5f0b Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Thu, 22 Sep 2022 00:04:37 +0100 Subject: platform/x86: int3472: Support multiple clock consumers At present, the tps68470.c only supports a single clock consumer when passing platform data to the clock driver. In some devices multiple sensors depend on the clock provided by a single TPS68470 and so all need to be able to acquire the clock. Support passing multiple consumers as platform data. Reviewed-by: Hans de Goede Signed-off-by: Daniel Scally Reviewed-by: Stephen Boyd Acked-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/clk/clk-tps68470.c | 13 ++++-- drivers/platform/x86/intel/int3472/tps68470.c | 59 +++++++++++++++++++++++---- include/linux/platform_data/tps68470.h | 7 +++- 3 files changed, 67 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-tps68470.c b/drivers/clk/clk-tps68470.c index e5fbefd6ac2d..38f44b5b9b1b 100644 --- a/drivers/clk/clk-tps68470.c +++ b/drivers/clk/clk-tps68470.c @@ -200,7 +200,9 @@ static int tps68470_clk_probe(struct platform_device *pdev) .flags = CLK_SET_RATE_GATE, }; struct tps68470_clkdata *tps68470_clkdata; + struct tps68470_clk_consumer *consumer; int ret; + int i; tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata), GFP_KERNEL); @@ -223,10 +225,13 @@ static int tps68470_clk_probe(struct platform_device *pdev) return ret; if (pdata) { - ret = devm_clk_hw_register_clkdev(&pdev->dev, - &tps68470_clkdata->clkout_hw, - pdata->consumer_con_id, - pdata->consumer_dev_name); + for (i = 0; i < pdata->n_consumers; i++) { + consumer = &pdata->consumers[i]; + ret = devm_clk_hw_register_clkdev(&pdev->dev, + &tps68470_clkdata->clkout_hw, + consumer->consumer_con_id, + consumer->consumer_dev_name); + } } return ret; diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c index 22f61b47f9e5..8a684030933d 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Author: Dan Scally */ +#include #include #include #include @@ -95,20 +96,64 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) return DESIGNED_FOR_WINDOWS; } +/* + * Return the size of the flexible array member, because we'll need that later + * on to pass .pdata_size to cells. + */ +static int +skl_int3472_fill_clk_pdata(struct device *dev, struct tps68470_clk_platform_data **clk_pdata) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + struct acpi_device *consumer; + unsigned int n_consumers = 0; + const char *sensor_name; + unsigned int i = 0; + + for_each_acpi_consumer_dev(adev, consumer) + n_consumers++; + + if (!n_consumers) { + dev_err(dev, "INT3472 seems to have no dependents\n"); + return -ENODEV; + } + + *clk_pdata = devm_kzalloc(dev, struct_size(*clk_pdata, consumers, n_consumers), + GFP_KERNEL); + if (!*clk_pdata) + return -ENOMEM; + + (*clk_pdata)->n_consumers = n_consumers; + i = 0; + + for_each_acpi_consumer_dev(adev, consumer) { + sensor_name = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT, + acpi_dev_name(consumer)); + if (!sensor_name) + return -ENOMEM; + + (*clk_pdata)->consumers[i].consumer_dev_name = sensor_name; + i++; + } + + acpi_dev_put(consumer); + + return n_consumers; +} + static int skl_int3472_tps68470_probe(struct i2c_client *client) { struct acpi_device *adev = ACPI_COMPANION(&client->dev); const struct int3472_tps68470_board_data *board_data; - struct tps68470_clk_platform_data clk_pdata = {}; + struct tps68470_clk_platform_data *clk_pdata; struct mfd_cell *cells; struct regmap *regmap; + int n_consumers; int device_type; int ret; - ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL, - &clk_pdata.consumer_dev_name); - if (ret) - return ret; + n_consumers = skl_int3472_fill_clk_pdata(&client->dev, &clk_pdata); + if (n_consumers < 0) + return n_consumers; regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config); if (IS_ERR(regmap)) { @@ -142,8 +187,8 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) * the clk + regulators must be ready when this happens. */ cells[0].name = "tps68470-clk"; - cells[0].platform_data = &clk_pdata; - cells[0].pdata_size = sizeof(clk_pdata); + cells[0].platform_data = clk_pdata; + cells[0].pdata_size = struct_size(clk_pdata, consumers, n_consumers); cells[1].name = "tps68470-regulator"; cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata; cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data); diff --git a/include/linux/platform_data/tps68470.h b/include/linux/platform_data/tps68470.h index 126d082c3f2e..e605a2cab07f 100644 --- a/include/linux/platform_data/tps68470.h +++ b/include/linux/platform_data/tps68470.h @@ -27,9 +27,14 @@ struct tps68470_regulator_platform_data { const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS]; }; -struct tps68470_clk_platform_data { +struct tps68470_clk_consumer { const char *consumer_dev_name; const char *consumer_con_id; }; +struct tps68470_clk_platform_data { + unsigned int n_consumers; + struct tps68470_clk_consumer consumers[]; +}; + #endif -- cgit v1.2.3 From 06a659d1f0a0ae3d104155655397e593296a65fa Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Thu, 22 Sep 2022 00:04:38 +0100 Subject: platform/x86: int3472: Support multiple gpio lookups in board data Currently, we only support passing a single gpiod_lookup_table as part of the board data for the tps68470 driver. This carries the implicit assumption that each TPS68470 device will only support a single sensor, which does not hold true. Extend the code to support the possibility of multiple sensors each having a gpiod_lookup_table, and opportunistically add the lookup table for the Surface Go line's IR camera. Reviewed-by: Hans de Goede Signed-off-by: Daniel Scally Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/intel/int3472/tps68470.c | 17 ++++++++++++----- drivers/platform/x86/intel/int3472/tps68470.h | 3 ++- .../x86/intel/int3472/tps68470_board_data.c | 21 ++++++++++++++++++--- 3 files changed, 32 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c index 8a684030933d..49fc379fe680 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -150,6 +150,7 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) int n_consumers; int device_type; int ret; + int i; n_consumers = skl_int3472_fill_clk_pdata(&client->dev, &clk_pdata); if (n_consumers < 0) @@ -194,15 +195,18 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data); cells[2].name = "tps68470-gpio"; - gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table); + for (i = 0; i < board_data->n_gpiod_lookups; i++) + gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_tables[i]); ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, cells, TPS68470_WIN_MFD_CELL_COUNT, NULL, 0, NULL); kfree(cells); - if (ret) - gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); + if (ret) { + for (i = 0; i < board_data->n_gpiod_lookups; i++) + gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]); + } break; case DESIGNED_FOR_CHROMEOS: @@ -226,10 +230,13 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) static int skl_int3472_tps68470_remove(struct i2c_client *client) { const struct int3472_tps68470_board_data *board_data; + int i; board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); - if (board_data) - gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); + if (board_data) { + for (i = 0; i < board_data->n_gpiod_lookups; i++) + gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]); + } return 0; } diff --git a/drivers/platform/x86/intel/int3472/tps68470.h b/drivers/platform/x86/intel/int3472/tps68470.h index cfd33eb62740..35915e701593 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.h +++ b/drivers/platform/x86/intel/int3472/tps68470.h @@ -16,8 +16,9 @@ struct tps68470_regulator_platform_data; struct int3472_tps68470_board_data { const char *dev_name; - struct gpiod_lookup_table *tps68470_gpio_lookup_table; const struct tps68470_regulator_platform_data *tps68470_regulator_pdata; + unsigned int n_gpiod_lookups; + struct gpiod_lookup_table *tps68470_gpio_lookup_tables[]; }; const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name); diff --git a/drivers/platform/x86/intel/int3472/tps68470_board_data.c b/drivers/platform/x86/intel/int3472/tps68470_board_data.c index 525f09a3b5ff..e6cc8f40f5af 100644 --- a/drivers/platform/x86/intel/int3472/tps68470_board_data.c +++ b/drivers/platform/x86/intel/int3472/tps68470_board_data.c @@ -96,7 +96,7 @@ static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = }, }; -static struct gpiod_lookup_table surface_go_tps68470_gpios = { +static struct gpiod_lookup_table surface_go_int347a_gpios = { .dev_id = "i2c-INT347A:00", .table = { GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW), @@ -105,16 +105,31 @@ static struct gpiod_lookup_table surface_go_tps68470_gpios = { } }; +static struct gpiod_lookup_table surface_go_int347e_gpios = { + .dev_id = "i2c-INT347E:00", + .table = { + GPIO_LOOKUP("tps68470-gpio", 5, "enable", GPIO_ACTIVE_HIGH), + { } + } +}; + static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = { .dev_name = "i2c-INT3472:05", - .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios, .tps68470_regulator_pdata = &surface_go_tps68470_pdata, + .n_gpiod_lookups = 2, + .tps68470_gpio_lookup_tables = { + &surface_go_int347a_gpios, + &surface_go_int347e_gpios, + }, }; static const struct int3472_tps68470_board_data surface_go3_tps68470_board_data = { .dev_name = "i2c-INT3472:01", - .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios, .tps68470_regulator_pdata = &surface_go_tps68470_pdata, + .n_gpiod_lookups = 1, + .tps68470_gpio_lookup_tables = { + &surface_go_int347a_gpios + }, }; static const struct dmi_system_id int3472_tps68470_board_data_table[] = { -- cgit v1.2.3 From 2a5a191c67ba4513f0a6ea459218129c23734ce2 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Thu, 22 Sep 2022 00:04:39 +0100 Subject: platform/x86: int3472: Add board data for Surface Go2 IR camera Add the board data describing the regulators for the Microsoft Surface Go line's IR camera. Reviewed-by: Hans de Goede Signed-off-by: Daniel Scally Signed-off-by: Rafael J. Wysocki --- .../x86/intel/int3472/tps68470_board_data.c | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/intel/int3472/tps68470_board_data.c b/drivers/platform/x86/intel/int3472/tps68470_board_data.c index e6cc8f40f5af..309eab9c0558 100644 --- a/drivers/platform/x86/intel/int3472/tps68470_board_data.c +++ b/drivers/platform/x86/intel/int3472/tps68470_board_data.c @@ -30,6 +30,15 @@ static struct regulator_consumer_supply int347a_vcm_consumer_supplies[] = { static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = { REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"), REGULATOR_SUPPLY("vsio", "i2c-INT347A:00-VCM"), + REGULATOR_SUPPLY("vddd", "i2c-INT347E:00"), +}; + +static struct regulator_consumer_supply int347a_aux1_consumer_supplies[] = { + REGULATOR_SUPPLY("vdda", "i2c-INT347E:00"), +}; + +static struct regulator_consumer_supply int347a_aux2_consumer_supplies[] = { + REGULATOR_SUPPLY("vdddo", "i2c-INT347E:00"), }; static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = { @@ -86,6 +95,28 @@ static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data = .consumer_supplies = int347a_vsio_consumer_supplies, }; +static const struct regulator_init_data surface_go_tps68470_aux1_reg_init_data = { + .constraints = { + .min_uV = 2815200, + .max_uV = 2815200, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_aux1_consumer_supplies), + .consumer_supplies = int347a_aux1_consumer_supplies, +}; + +static const struct regulator_init_data surface_go_tps68470_aux2_reg_init_data = { + .constraints = { + .min_uV = 1800600, + .max_uV = 1800600, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_aux2_consumer_supplies), + .consumer_supplies = int347a_aux2_consumer_supplies, +}; + static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = { .reg_init_data = { [TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data, @@ -93,6 +124,8 @@ static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = [TPS68470_VCM] = &surface_go_tps68470_vcm_reg_init_data, [TPS68470_VIO] = &surface_go_tps68470_vio_reg_init_data, [TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data, + [TPS68470_AUX1] = &surface_go_tps68470_aux1_reg_init_data, + [TPS68470_AUX2] = &surface_go_tps68470_aux2_reg_init_data, }, }; -- cgit v1.2.3