^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * ACPI device specific properties support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Darren Hart <dvhart@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static int acpi_data_get_property_array(const struct acpi_device_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) acpi_object_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) const union acpi_object **obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * The GUIDs here are made equivalent to each other in order to avoid extra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * complexity in the properties handling code, with the caveat that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * kernel will accept certain combinations of GUID and properties that are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * not defined without a warning. For instance if any of the properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * from different GUID appear in a property list of another, it will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * accepted by the kernel. Firmware validation tools should catch these.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static const guid_t prp_guids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) 0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) 0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Thunderbolt GUID for IMR_VALID: c44d002f-69f9-4e7d-a904-a7baabdf43f7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) GUID_INIT(0xc44d002f, 0x69f9, 0x4e7d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) 0xa9, 0x04, 0xa7, 0xba, 0xab, 0xdf, 0x43, 0xf7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Thunderbolt GUID for WAKE_SUPPORTED: 6c501103-c189-4296-ba72-9bf5a26ebe5d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) GUID_INIT(0x6c501103, 0xc189, 0x4296,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 0xba, 0x72, 0x9b, 0xf5, 0xa2, 0x6e, 0xbe, 0x5d),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* Storage device needs D3 GUID: 5025030f-842f-4ab4-a561-99a5189762d0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) GUID_INIT(0x5025030f, 0x842f, 0x4ab4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 0xa5, 0x61, 0x99, 0xa5, 0x18, 0x97, 0x62, 0xd0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const guid_t ads_guid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const union acpi_object *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct acpi_device_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct fwnode_handle *parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static bool acpi_extract_properties(const union acpi_object *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct acpi_device_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) acpi_handle handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) const union acpi_object *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct list_head *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct fwnode_handle *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct acpi_data_node *dn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) bool result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dn = kzalloc(sizeof(*dn), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!dn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) dn->name = link->package.elements[0].string.pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) fwnode_init(&dn->fwnode, &acpi_data_fwnode_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dn->parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) INIT_LIST_HEAD(&dn->data.properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) INIT_LIST_HEAD(&dn->data.subnodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) result = acpi_extract_properties(desc, &dn->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (handle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) acpi_handle scope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * The scope for the subnode object lookup is the one of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * namespace node (device) containing the object that has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * returned the package. That is, it's the scope of that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * object's parent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) status = acpi_get_parent(handle, &scope);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (ACPI_SUCCESS(status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) &dn->fwnode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) result = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) } else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) &dn->fwnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) result = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dn->handle = handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dn->data.pointer = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) list_add_tail(&dn->sibling, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) kfree(dn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const union acpi_object *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct list_head *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct fwnode_handle *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ACPI_TYPE_PACKAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (ACPI_FAILURE(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ACPI_FREE(buf.pointer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static bool acpi_nondev_subnode_ok(acpi_handle scope,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) const union acpi_object *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct list_head *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct fwnode_handle *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) acpi_handle handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (!scope)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) &handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (ACPI_FAILURE(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return acpi_nondev_subnode_data_ok(handle, link, list, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int acpi_add_nondev_subnodes(acpi_handle scope,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) const union acpi_object *links,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct list_head *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct fwnode_handle *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) bool ret = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) for (i = 0; i < links->package.count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) const union acpi_object *link, *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) acpi_handle handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) bool result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) link = &links->package.elements[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* Only two elements allowed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (link->package.count != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* The first one must be a string. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (link->package.elements[0].type != ACPI_TYPE_STRING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* The second one may be a string, a reference or a package. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) switch (link->package.elements[1].type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) case ACPI_TYPE_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) result = acpi_nondev_subnode_ok(scope, link, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) case ACPI_TYPE_LOCAL_REFERENCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) handle = link->package.elements[1].reference.handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) result = acpi_nondev_subnode_data_ok(handle, link, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) case ACPI_TYPE_PACKAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) desc = &link->package.elements[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) result = acpi_nondev_subnode_extract(desc, NULL, link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) list, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) result = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ret = ret || result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) const union acpi_object *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct acpi_device_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct fwnode_handle *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Look for the ACPI data subnodes GUID. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) for (i = 0; i < desc->package.count; i += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) const union acpi_object *guid, *links;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) guid = &desc->package.elements[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) links = &desc->package.elements[i + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * The first element must be a GUID and the second one must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * a package.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (guid->type != ACPI_TYPE_BUFFER ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) guid->buffer.length != 16 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) links->type != ACPI_TYPE_PACKAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static bool acpi_property_value_ok(const union acpi_object *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * The value must be an integer, a string, a reference, or a package
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * whose every element must be an integer, a string, or a reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) switch (value->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case ACPI_TYPE_INTEGER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case ACPI_TYPE_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) case ACPI_TYPE_LOCAL_REFERENCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) case ACPI_TYPE_PACKAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) for (j = 0; j < value->package.count; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) switch (value->package.elements[j].type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case ACPI_TYPE_INTEGER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case ACPI_TYPE_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case ACPI_TYPE_LOCAL_REFERENCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static bool acpi_properties_format_valid(const union acpi_object *properties)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) for (i = 0; i < properties->package.count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) const union acpi_object *property;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) property = &properties->package.elements[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * Only two elements allowed, the first one must be a string and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * the second one has to satisfy certain conditions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (property->package.count != 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) || property->package.elements[0].type != ACPI_TYPE_STRING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) || !acpi_property_value_ok(&property->package.elements[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static void acpi_init_of_compatible(struct acpi_device *adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) const union acpi_object *of_compatible;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ret = acpi_data_get_property_array(&adev->data, "compatible",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ACPI_TYPE_STRING, &of_compatible);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ret = acpi_dev_get_property(adev, "compatible",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ACPI_TYPE_STRING, &of_compatible);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (adev->parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) && adev->parent->flags.of_compatible_ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) adev->data.of_compatible = of_compatible;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) adev->flags.of_compatible_ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static bool acpi_is_property_guid(const guid_t *guid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) for (i = 0; i < ARRAY_SIZE(prp_guids); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (guid_equal(guid, &prp_guids[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct acpi_device_properties *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) const union acpi_object *properties)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct acpi_device_properties *props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) props = kzalloc(sizeof(*props), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (props) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) INIT_LIST_HEAD(&props->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) props->guid = guid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) props->properties = properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) list_add_tail(&props->list, &data->properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static bool acpi_extract_properties(const union acpi_object *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct acpi_device_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (desc->package.count % 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* Look for the device properties GUID. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) for (i = 0; i < desc->package.count; i += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) const union acpi_object *guid, *properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) guid = &desc->package.elements[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) properties = &desc->package.elements[i + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * The first element must be a GUID and the second one must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * a package.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (guid->type != ACPI_TYPE_BUFFER ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) guid->buffer.length != 16 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) properties->type != ACPI_TYPE_PACKAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * We found the matching GUID. Now validate the format of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * package immediately following it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!acpi_properties_format_valid(properties))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return !list_empty(&data->properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) void acpi_init_properties(struct acpi_device *adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct acpi_hardware_id *hwid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) bool acpi_of = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) INIT_LIST_HEAD(&adev->data.properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) INIT_LIST_HEAD(&adev->data.subnodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (!adev->handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * Device Tree compatible properties for this device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) list_for_each_entry(hwid, &adev->pnp.ids, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) acpi_of = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ACPI_TYPE_PACKAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (ACPI_FAILURE(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (acpi_extract_properties(buf.pointer, &adev->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) adev->data.pointer = buf.pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (acpi_of)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) acpi_init_of_compatible(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) &adev->data, acpi_fwnode_handle(adev)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) adev->data.pointer = buf.pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!adev->data.pointer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) ACPI_FREE(buf.pointer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (acpi_of && !adev->flags.of_compatible_ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) acpi_handle_info(adev->handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (!adev->data.pointer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) acpi_extract_apple_properties(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static void acpi_destroy_nondev_subnodes(struct list_head *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) struct acpi_data_node *dn, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (list_empty(list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) list_for_each_entry_safe_reverse(dn, next, list, sibling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) acpi_destroy_nondev_subnodes(&dn->data.subnodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) wait_for_completion(&dn->kobj_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) list_del(&dn->sibling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ACPI_FREE((void *)dn->data.pointer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) kfree(dn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) void acpi_free_properties(struct acpi_device *adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct acpi_device_properties *props, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) acpi_destroy_nondev_subnodes(&adev->data.subnodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) ACPI_FREE((void *)adev->data.pointer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) adev->data.of_compatible = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) adev->data.pointer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) list_for_each_entry_safe(props, tmp, &adev->data.properties, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) list_del(&props->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) kfree(props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * acpi_data_get_property - return an ACPI property with given name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * @data: ACPI device deta object to get the property from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * @name: Name of the property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * @type: Expected property type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * @obj: Location to store the property value (if not %NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * Look up a property with @name and store a pointer to the resulting ACPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * object at the location pointed to by @obj if found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * Callers must not attempt to free the returned objects. These objects will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * freed by the ACPI core automatically during the removal of @data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * Return: %0 if property with @name has been found (success),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * %-EINVAL if the arguments are invalid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * %-EINVAL if the property doesn't exist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * %-EPROTO if the property value type doesn't match @type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static int acpi_data_get_property(const struct acpi_device_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) const char *name, acpi_object_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) const union acpi_object **obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) const struct acpi_device_properties *props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!data || !name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (!data->pointer || list_empty(&data->properties))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) list_for_each_entry(props, &data->properties, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) const union acpi_object *properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) properties = props->properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) for (i = 0; i < properties->package.count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) const union acpi_object *propname, *propvalue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) const union acpi_object *property;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) property = &properties->package.elements[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) propname = &property->package.elements[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) propvalue = &property->package.elements[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (!strcmp(name, propname->string.pointer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (type != ACPI_TYPE_ANY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) propvalue->type != type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *obj = propvalue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * acpi_dev_get_property - return an ACPI property with given name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * @adev: ACPI device to get the property from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * @name: Name of the property.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * @type: Expected property type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * @obj: Location to store the property value (if not %NULL).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) acpi_object_type type, const union acpi_object **obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) EXPORT_SYMBOL_GPL(acpi_dev_get_property);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static const struct acpi_device_data *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) acpi_device_data_of_node(const struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (is_acpi_device_node(fwnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) const struct acpi_device *adev = to_acpi_device_node(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return &adev->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) } else if (is_acpi_data_node(fwnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return &dn->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * acpi_node_prop_get - return an ACPI property with given name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * @fwnode: Firmware node to get the property from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * @propname: Name of the property.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * @valptr: Location to store a pointer to the property value (if not %NULL).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int acpi_node_prop_get(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) const char *propname, void **valptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return acpi_data_get_property(acpi_device_data_of_node(fwnode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) propname, ACPI_TYPE_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) (const union acpi_object **)valptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * acpi_data_get_property_array - return an ACPI array property with given name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * @adev: ACPI data object to get the property from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * @name: Name of the property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * @type: Expected type of array elements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * @obj: Location to store a pointer to the property value (if not NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * Look up an array property with @name and store a pointer to the resulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * ACPI object at the location pointed to by @obj if found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * Callers must not attempt to free the returned objects. Those objects will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * freed by the ACPI core automatically during the removal of @data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * Return: %0 if array property (package) with @name has been found (success),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * %-EINVAL if the arguments are invalid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * %-EINVAL if the property doesn't exist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * %-EPROTO if the property is not a package or the type of its elements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * doesn't match @type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static int acpi_data_get_property_array(const struct acpi_device_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) acpi_object_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) const union acpi_object **obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) const union acpi_object *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (type != ACPI_TYPE_ANY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* Check that all elements are of correct type. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) for (i = 0; i < prop->package.count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (prop->package.elements[i].type != type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) *obj = prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static struct fwnode_handle *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) const char *childname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct fwnode_handle *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) fwnode_for_each_child_node(fwnode, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (is_acpi_data_node(child)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (acpi_data_node_match(child, childname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (!strncmp(acpi_device_bid(to_acpi_device_node(child)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) childname, ACPI_NAMESEG_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * __acpi_node_get_property_reference - returns handle to the referenced object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * @fwnode: Firmware node to get the property from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * @propname: Name of the property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * @index: Index of the reference to return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * @num_args: Maximum number of arguments after each reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * @args: Location to store the returned reference with optional arguments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * Find property with @name, verifify that it is a package containing at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * one object reference and if so, store the ACPI device object pointer to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * target object in @args->adev. If the reference includes arguments, store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * them in the @args->args[] array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * If there's more than one reference in the property value package, @index is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * used to select the one to return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * It is possible to leave holes in the property value set like in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * example below:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * Package () {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * "cs-gpios",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * Package () {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * ^GPIO, 19, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * ^GPIO, 20, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * ^GPIO, 21, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * Calling this function with index %2 or index %3 return %-ENOENT. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * property does not contain any more values %-ENOENT is returned. The NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * entry must be single integer and preferably contain value %0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * Return: %0 on success, negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) const char *propname, size_t index, size_t num_args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct fwnode_reference_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) const union acpi_object *element, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) const union acpi_object *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) const struct acpi_device_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct acpi_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) int ret, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) data = acpi_device_data_of_node(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return ret == -EINVAL ? -ENOENT : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * The simplest case is when the value is a single reference. Just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * return that reference then.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ret = acpi_bus_get_device(obj->reference.handle, &device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return ret == -ENODEV ? -EINVAL : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) args->fwnode = acpi_fwnode_handle(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) args->nargs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * If it is not a single reference, then it is a package of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * references followed by number of ints as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * Package () { REF, INT, REF, INT, INT }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * The index argument is then used to determine which reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * the caller wants (along with the arguments).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (obj->type != ACPI_TYPE_PACKAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (index >= obj->package.count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) element = obj->package.elements;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) end = element + obj->package.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) while (element < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) u32 nargs, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) struct fwnode_handle *ref_fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ret = acpi_bus_get_device(element->reference.handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) &device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) nargs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) element++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * Find the referred data extension node under the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * referred device node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) for (ref_fwnode = acpi_fwnode_handle(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) element < end && element->type == ACPI_TYPE_STRING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) element++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) ref_fwnode = acpi_fwnode_get_named_child_node(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) ref_fwnode, element->string.pointer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (!ref_fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* assume following integer elements are all args */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) for (i = 0; element + i < end && i < num_args; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) int type = element[i].type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (type == ACPI_TYPE_INTEGER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) nargs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) else if (type == ACPI_TYPE_LOCAL_REFERENCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (nargs > NR_FWNODE_REFERENCE_ARGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (idx == index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) args->fwnode = ref_fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) args->nargs = nargs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) for (i = 0; i < nargs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) args->args[i] = element[i].integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) element += nargs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) } else if (element->type == ACPI_TYPE_INTEGER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (idx == index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) element++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static int acpi_data_prop_read_single(const struct acpi_device_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) const char *propname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) enum dev_prop_type proptype, void *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) const union acpi_object *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) switch (proptype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) case DEV_PROP_U8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (obj->integer.value > U8_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) *(u8 *)val = obj->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) case DEV_PROP_U16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (obj->integer.value > U16_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) *(u16 *)val = obj->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) case DEV_PROP_U32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (obj->integer.value > U32_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) *(u32 *)val = obj->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) *(u64 *)val = obj->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) } else if (proptype == DEV_PROP_STRING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) *(char **)val = obj->string.pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) enum dev_prop_type proptype, void *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (!adev || !val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (ret < 0 || proptype != ACPI_TYPE_STRING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) for (i = 0; i < nval; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (items[i].type != ACPI_TYPE_INTEGER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (items[i].integer.value > U8_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) val[i] = items[i].integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) static int acpi_copy_property_array_u16(const union acpi_object *items,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) u16 *val, size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) for (i = 0; i < nval; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (items[i].type != ACPI_TYPE_INTEGER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (items[i].integer.value > U16_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) val[i] = items[i].integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static int acpi_copy_property_array_u32(const union acpi_object *items,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) u32 *val, size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) for (i = 0; i < nval; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (items[i].type != ACPI_TYPE_INTEGER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (items[i].integer.value > U32_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) val[i] = items[i].integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static int acpi_copy_property_array_u64(const union acpi_object *items,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) u64 *val, size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) for (i = 0; i < nval; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (items[i].type != ACPI_TYPE_INTEGER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) val[i] = items[i].integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static int acpi_copy_property_array_string(const union acpi_object *items,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) char **val, size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) for (i = 0; i < nval; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (items[i].type != ACPI_TYPE_STRING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) val[i] = items[i].string.pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return nval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static int acpi_data_prop_read(const struct acpi_device_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) const char *propname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) enum dev_prop_type proptype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) void *val, size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) const union acpi_object *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) const union acpi_object *items;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (nval == 1 || !val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ret = acpi_data_prop_read_single(data, propname, proptype, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * The overflow error means that the property is there and it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * single-value, but its type does not match, so return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (ret >= 0 || ret == -EOVERFLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) * Reading this property as a single-value one failed, but its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * value may still be represented as one-element array, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) return obj->package.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (proptype != DEV_PROP_STRING && nval > obj->package.count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) else if (nval <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) items = obj->package.elements;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) switch (proptype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) case DEV_PROP_U8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) case DEV_PROP_U16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) case DEV_PROP_U32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case DEV_PROP_U64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) case DEV_PROP_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) ret = acpi_copy_property_array_string(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) items, (char **)val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) min_t(u32, nval, obj->package.count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) int acpi_dev_prop_read(const struct acpi_device *adev, const char *propname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) enum dev_prop_type proptype, void *val, size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * @fwnode: Firmware node to get the property from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * @propname: Name of the property.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * @proptype: Expected property type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * @val: Location to store the property value (if not %NULL).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * @nval: Size of the array pointed to by @val.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * If @val is %NULL, return the number of array elements comprising the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * of the property. Otherwise, read at most @nval values to the array at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * location pointed to by @val.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) int acpi_node_prop_read(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) const char *propname, enum dev_prop_type proptype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) void *val, size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) propname, proptype, val, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * acpi_get_next_subnode - Return the next child node handle for a fwnode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) * @fwnode: Firmware node to find the next child node for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) * @child: Handle to one of the device's child nodes or a null handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) struct fwnode_handle *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) const struct acpi_device *adev = to_acpi_device_node(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) const struct list_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) struct list_head *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (!child || is_acpi_device_node(child)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) struct acpi_device *child_adev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) head = &adev->children;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) goto nondev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (list_empty(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) goto nondev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) adev = to_acpi_device_node(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) next = adev->node.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (next == head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) goto nondev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) child_adev = list_entry(next, struct acpi_device, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) child_adev = list_first_entry(head, struct acpi_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return acpi_fwnode_handle(child_adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) nondev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (!child || is_acpi_data_node(child)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) const struct acpi_data_node *data = to_acpi_data_node(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) struct acpi_data_node *dn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * We can have a combination of device and data nodes, e.g. with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * hierarchical _DSD properties. Make sure the adev pointer is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) * restored before going through data nodes, otherwise we will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) * be looking for data_nodes below the last device found instead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) * of the common fwnode shared by device_nodes and data_nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) adev = to_acpi_device_node(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) head = &adev->data.subnodes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) else if (data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) head = &data->data.subnodes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (list_empty(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) dn = to_acpi_data_node(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) next = dn->sibling.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (next == head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) dn = list_entry(next, struct acpi_data_node, sibling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) dn = list_first_entry(head, struct acpi_data_node, sibling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return &dn->fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) * acpi_node_get_parent - Return parent fwnode of this fwnode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * @fwnode: Firmware node whose parent to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * Returns parent node of an ACPI device or data firmware node or %NULL if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) * not available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (is_acpi_data_node(fwnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /* All data nodes have parent pointer so just return that */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) return to_acpi_data_node(fwnode)->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) } else if (is_acpi_device_node(fwnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return acpi_fwnode_handle(to_acpi_device(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * Return true if the node is an ACPI graph node. Called on either ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * or endpoints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) unsigned int len = strlen(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (!len || !is_acpi_data_node(fwnode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) name = to_acpi_data_node(fwnode)->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return (fwnode_property_present(fwnode, "reg") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) !strncmp(name, str, len) && name[len] == '@') ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) fwnode_property_present(fwnode, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * acpi_graph_get_next_endpoint - Get next endpoint ACPI firmware node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) * @fwnode: Pointer to the parent firmware node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * @prev: Previous endpoint node or %NULL to get the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * Looks up next endpoint ACPI firmware node below a given @fwnode. Returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) * %NULL if there is no next endpoint or in case of error. In case of success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * the next endpoint is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) static struct fwnode_handle *acpi_graph_get_next_endpoint(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) struct fwnode_handle *port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) struct fwnode_handle *endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (!prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) port = fwnode_get_next_child_node(fwnode, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) * The names of the port nodes begin with "port@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * followed by the number of the port node and they also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * have a "reg" property that also has the number of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * port node. For compatibility reasons a node is also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * recognised as a port node from the "port" property.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (is_acpi_graph_node(port, "port"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) } while (port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) port = fwnode_get_parent(prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (!port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) endpoint = fwnode_get_next_child_node(port, prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) while (!endpoint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) port = fwnode_get_next_child_node(fwnode, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (!port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (is_acpi_graph_node(port, "port"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) endpoint = fwnode_get_next_child_node(port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * The names of the endpoint nodes begin with "endpoint@" followed by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * the number of the endpoint node and they also have a "reg" property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) * that also has the number of the endpoint node. For compatibility
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) * reasons a node is also recognised as an endpoint node from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) * "endpoint" property.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (!is_acpi_graph_node(endpoint, "endpoint"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) * acpi_graph_get_child_prop_value - Return a child with a given property value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) * @fwnode: device fwnode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) * @prop_name: The name of the property to look for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) * @val: the desired property value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) * Return the port node corresponding to a given port number. Returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * the child node on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) static struct fwnode_handle *acpi_graph_get_child_prop_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) const struct fwnode_handle *fwnode, const char *prop_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) struct fwnode_handle *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) fwnode_for_each_child_node(fwnode, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) u32 nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (fwnode_property_read_u32(child, prop_name, &nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (val == nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) * acpi_graph_get_remote_endpoint - Parses and returns remote end of an endpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) * @fwnode: Endpoint firmware node pointing to a remote device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * @endpoint: Firmware node of remote endpoint is filled here if not %NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * Returns the remote endpoint corresponding to @__fwnode. NULL on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) static struct fwnode_handle *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) struct fwnode_handle *fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) unsigned int port_nr, endpoint_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) struct fwnode_reference_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) memset(&args, 0, sizeof(args));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) /* Direct endpoint reference? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (!is_acpi_device_node(args.fwnode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return args.nargs ? NULL : args.fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * Always require two arguments with the reference: port and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * endpoint indices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (args.nargs != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) fwnode = args.fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) port_nr = args.args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) endpoint_nr = args.args[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (!is_acpi_device_node(fwnode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return acpi_device_is_present(to_acpi_device_node(fwnode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) const char *propname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) return !acpi_node_prop_get(fwnode, propname, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) const char *propname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) unsigned int elem_size, void *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) enum dev_prop_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) switch (elem_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) case sizeof(u8):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) type = DEV_PROP_U8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) case sizeof(u16):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) type = DEV_PROP_U16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) case sizeof(u32):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) type = DEV_PROP_U32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) case sizeof(u64):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) type = DEV_PROP_U64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return acpi_node_prop_read(fwnode, propname, type, val, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) const char *propname, const char **val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) size_t nval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) val, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) const char *prop, const char *nargs_prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) unsigned int args_count, unsigned int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) struct fwnode_reference_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return __acpi_node_get_property_reference(fwnode, prop, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) args_count, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) static const char *acpi_fwnode_get_name(const struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) const struct acpi_device *adev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) struct fwnode_handle *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) /* Is this the root node? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) parent = fwnode_get_parent(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return "\\";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) fwnode_handle_put(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (is_acpi_data_node(fwnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) return dn->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) adev = to_acpi_device_node(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (WARN_ON(!adev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return acpi_device_bid(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) static const char *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) acpi_fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) struct fwnode_handle *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) /* Is this the root node? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) parent = fwnode_get_parent(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) /* Is this 2nd node from the root? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) parent = fwnode_get_next_parent(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) return "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) fwnode_handle_put(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) /* ACPI device or data node. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) return ".";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) static struct fwnode_handle *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) return acpi_node_get_parent(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) struct fwnode_endpoint *endpoint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) endpoint->local_fwnode = fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) static const void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) const struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) return acpi_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) #define DECLARE_ACPI_FWNODE_OPS(ops) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) const struct fwnode_operations ops = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) .device_is_available = acpi_fwnode_device_is_available, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) .device_get_match_data = acpi_fwnode_device_get_match_data, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) .property_present = acpi_fwnode_property_present, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) .property_read_int_array = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) acpi_fwnode_property_read_int_array, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) .property_read_string_array = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) acpi_fwnode_property_read_string_array, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) .get_parent = acpi_node_get_parent, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) .get_next_child_node = acpi_get_next_subnode, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) .get_named_child_node = acpi_fwnode_get_named_child_node, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) .get_name = acpi_fwnode_get_name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) .get_name_prefix = acpi_fwnode_get_name_prefix, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) .get_reference_args = acpi_fwnode_get_reference_args, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) .graph_get_next_endpoint = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) acpi_graph_get_next_endpoint, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) .graph_get_remote_endpoint = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) acpi_graph_get_remote_endpoint, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) .graph_get_port_parent = acpi_fwnode_get_parent, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) EXPORT_SYMBOL_GPL(ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) const struct fwnode_operations acpi_static_fwnode_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) bool is_acpi_device_node(const struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) return !IS_ERR_OR_NULL(fwnode) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) fwnode->ops == &acpi_device_fwnode_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) EXPORT_SYMBOL(is_acpi_device_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) bool is_acpi_data_node(const struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) EXPORT_SYMBOL(is_acpi_data_node);