Merge branch 'acpi-dev'

Merge changes regarding the management of ACPI device objects for
6.1-rc1:

 - Rename ACPI device object reference counting functions (Rafael
   Wysocki).

 - Rearrange ACPI device object initialization code (Rafael Wysocki).

 - Drop parent field from struct acpi_device (Rafael Wysocki).

 - Extend the the int3472-tps68470 driver to support multiple consumers
   of a single TPS68470 along with the requisite framework-level
   support (Daniel Scally).

* acpi-dev:
  platform/x86: int3472: Add board data for Surface Go2 IR camera
  platform/x86: int3472: Support multiple gpio lookups in board data
  platform/x86: int3472: Support multiple clock consumers
  ACPI: bus: Add iterator for dependent devices
  ACPI: scan: Add acpi_dev_get_next_consumer_dev()
  ACPI: property: Use acpi_dev_parent()
  ACPI: Drop redundant acpi_dev_parent() header
  ACPI: PM: Fix NULL argument handling in acpi_device_get/set_power()
  ACPI: Drop parent field from struct acpi_device
  ACPI: scan: Eliminate __acpi_device_add()
  ACPI: scan: Rearrange initialization of ACPI device objects
  ACPI: scan: Rename acpi_bus_get_parent() and rearrange it
  ACPI: Rename acpi_bus_get/put_acpi_device()
This commit is contained in:
Rafael J. Wysocki 2022-09-30 20:05:16 +02:00
commit 80487a37de
25 changed files with 295 additions and 127 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -75,15 +75,17 @@ static int acpi_dev_pm_explicit_get(struct acpi_device *device, int *state)
int acpi_device_get_power(struct acpi_device *device, int *state)
{
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 = device->parent ?
device->parent->power.state : ACPI_STATE_D0;
*state = parent ? parent->power.state : ACPI_STATE_D0;
goto out;
}
@ -122,10 +124,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;
@ -191,13 +193,17 @@ 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) {
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));
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;
}
}
/*
@ -497,7 +503,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 +521,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);
}
/**

View File

@ -102,10 +102,10 @@ 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_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);
void acpi_device_add_finalize(struct acpi_device *device);

View File

@ -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;
}

View File

@ -944,13 +944,15 @@ 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);
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);
@ -967,8 +969,11 @@ 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_tie_acpi_dev(device);
if (result)
goto err;
result = acpi_device_add(device);
if (result)
goto err;

View File

@ -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;
@ -1267,10 +1269,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;

View File

@ -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);

View File

@ -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;

View File

@ -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";
@ -429,7 +427,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 +597,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)
{
@ -632,7 +641,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;
@ -662,8 +671,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 *))
int acpi_device_add(struct acpi_device *device)
{
struct acpi_device_bus_id *acpi_device_bus_id;
int result;
@ -719,11 +727,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");
@ -750,17 +753,6 @@ err_unlock:
return result;
}
int acpi_device_add(struct acpi_device *adev, void (*release)(struct device *))
{
int ret;
ret = acpi_tie_acpi_dev(adev);
if (ret)
return ret;
return __acpi_device_add(adev, release);
}
/* --------------------------------------------------------------------------
Device Enumeration
-------------------------------------------------------------------------- */
@ -805,10 +797,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
@ -819,13 +810,18 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
return acpi_root;
do {
status = acpi_get_parent(handle, &handle);
if (ACPI_FAILURE(status))
return status == AE_NULL_ENTRY ? NULL : acpi_root;
acpi_status status;
device = acpi_fetch_acpi_dev(handle);
} while (!device);
return device;
status = acpi_get_parent(handle, &handle);
if (ACPI_FAILURE(status)) {
if (status != AE_NULL_ENTRY)
return acpi_root;
return NULL;
}
adev = acpi_fetch_acpi_dev(handle);
} while (!adev);
return adev;
}
acpi_status
@ -1112,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;
}
@ -1648,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) {
/*
@ -1692,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},
{}
@ -1762,12 +1758,16 @@ 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_bus_get_parent(handle);
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);
acpi_set_device_status(device, ACPI_STA_DEFAULT);
acpi_device_get_busid(device);
@ -1821,7 +1821,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
@ -1851,7 +1851,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);
@ -1862,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;
@ -2235,11 +2235,24 @@ 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;
adev = acpi_bus_get_acpi_device(dep->consumer);
/*
* 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) {
*(struct acpi_device **)data = adev;
return 1;
@ -2292,7 +2305,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--;
@ -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.

View File

@ -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;

View File

@ -2453,7 +2453,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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Author: Dan Scally <djrscally@gmail.com> */
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
@ -95,20 +96,65 @@ 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;
int i;
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,22 +188,25 @@ 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);
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:
@ -181,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;
}

View File

@ -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);

View File

@ -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,10 +124,12 @@ 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,
},
};
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 +138,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[] = {

View File

@ -4374,7 +4374,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;

View File

@ -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);

View File

@ -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;
@ -512,7 +519,6 @@ extern int unregister_acpi_notifier(struct notifier_block *);
* External Functions
*/
struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle);
acpi_status acpi_bus_get_status_handle(acpi_handle handle,
unsigned long long *sta);
int acpi_bus_get_status(struct acpi_device *device);
@ -736,7 +742,20 @@ 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);
/**
* for_each_acpi_consumer_dev - iterate over the consumer ACPI devices for a
* given supplier
* @supplier: Pointer to the supplier's ACPI device
* @consumer: Pointer to &struct acpi_device to hold the consumer, initially NULL
*/
#define for_each_acpi_consumer_dev(supplier, consumer) \
for (consumer = acpi_dev_get_next_consumer_dev(supplier, NULL); \
consumer; \
consumer = acpi_dev_get_next_consumer_dev(supplier, consumer))
struct acpi_device *
acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);
struct acpi_device *
@ -767,9 +786,10 @@ static inline void acpi_dev_put(struct acpi_device *adev)
put_device(&adev->dev);
}
struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle);
struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle);
struct acpi_device *acpi_get_acpi_dev(acpi_handle handle);
static inline void acpi_bus_put_acpi_device(struct acpi_device *adev)
static inline void acpi_put_acpi_dev(struct acpi_device *adev)
{
acpi_dev_put(adev);
}

View File

@ -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