|
|
|
@ -468,10 +468,11 @@ static int acpi_data_get_property_array(struct acpi_device_data *data, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* acpi_data_get_property_reference - returns handle to the referenced object |
|
|
|
|
* @data: ACPI device data object containing the property |
|
|
|
|
* __acpi_node_get_property_reference - returns handle to the referenced object |
|
|
|
|
* @fwnode: Firmware node to get the property from |
|
|
|
|
* @propname: Name of the property |
|
|
|
|
* @index: Index of the reference to return |
|
|
|
|
* @num_args: Maximum number of arguments after each reference |
|
|
|
|
* @args: Location to store the returned reference with optional arguments |
|
|
|
|
* |
|
|
|
|
* Find property with @name, verifify that it is a package containing at least |
|
|
|
@ -482,17 +483,40 @@ static int acpi_data_get_property_array(struct acpi_device_data *data, |
|
|
|
|
* If there's more than one reference in the property value package, @index is |
|
|
|
|
* used to select the one to return. |
|
|
|
|
* |
|
|
|
|
* It is possible to leave holes in the property value set like in the |
|
|
|
|
* example below: |
|
|
|
|
* |
|
|
|
|
* Package () { |
|
|
|
|
* "cs-gpios", |
|
|
|
|
* Package () { |
|
|
|
|
* ^GPIO, 19, 0, 0, |
|
|
|
|
* ^GPIO, 20, 0, 0, |
|
|
|
|
* 0, |
|
|
|
|
* ^GPIO, 21, 0, 0, |
|
|
|
|
* } |
|
|
|
|
* } |
|
|
|
|
* |
|
|
|
|
* Calling this function with index %2 return %-ENOENT and with index %3 |
|
|
|
|
* returns the last entry. If the property does not contain any more values |
|
|
|
|
* %-ENODATA is returned. The NULL entry must be single integer and |
|
|
|
|
* preferably contain value %0. |
|
|
|
|
* |
|
|
|
|
* Return: %0 on success, negative error code on failure. |
|
|
|
|
*/ |
|
|
|
|
static int acpi_data_get_property_reference(struct acpi_device_data *data, |
|
|
|
|
const char *propname, size_t index, |
|
|
|
|
struct acpi_reference_args *args) |
|
|
|
|
int __acpi_node_get_property_reference(struct fwnode_handle *fwnode, |
|
|
|
|
const char *propname, size_t index, size_t num_args, |
|
|
|
|
struct acpi_reference_args *args) |
|
|
|
|
{ |
|
|
|
|
const union acpi_object *element, *end; |
|
|
|
|
const union acpi_object *obj; |
|
|
|
|
struct acpi_device_data *data; |
|
|
|
|
struct acpi_device *device; |
|
|
|
|
int ret, idx = 0; |
|
|
|
|
|
|
|
|
|
data = acpi_device_data_of_node(fwnode); |
|
|
|
|
if (!data) |
|
|
|
|
return -EINVAL; |
|
|
|
|
|
|
|
|
|
ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
@ -532,59 +556,54 @@ static int acpi_data_get_property_reference(struct acpi_device_data *data, |
|
|
|
|
while (element < end) { |
|
|
|
|
u32 nargs, i; |
|
|
|
|
|
|
|
|
|
if (element->type != ACPI_TYPE_LOCAL_REFERENCE) |
|
|
|
|
return -EPROTO; |
|
|
|
|
|
|
|
|
|
ret = acpi_bus_get_device(element->reference.handle, &device); |
|
|
|
|
if (ret) |
|
|
|
|
return -ENODEV; |
|
|
|
|
|
|
|
|
|
element++; |
|
|
|
|
nargs = 0; |
|
|
|
|
|
|
|
|
|
/* assume following integer elements are all args */ |
|
|
|
|
for (i = 0; element + i < end; i++) { |
|
|
|
|
int type = element[i].type; |
|
|
|
|
if (element->type == ACPI_TYPE_LOCAL_REFERENCE) { |
|
|
|
|
ret = acpi_bus_get_device(element->reference.handle, |
|
|
|
|
&device); |
|
|
|
|
if (ret) |
|
|
|
|
return -ENODEV; |
|
|
|
|
|
|
|
|
|
nargs = 0; |
|
|
|
|
element++; |
|
|
|
|
|
|
|
|
|
/* assume following integer elements are all args */ |
|
|
|
|
for (i = 0; element + i < end && i < num_args; i++) { |
|
|
|
|
int type = element[i].type; |
|
|
|
|
|
|
|
|
|
if (type == ACPI_TYPE_INTEGER) |
|
|
|
|
nargs++; |
|
|
|
|
else if (type == ACPI_TYPE_LOCAL_REFERENCE) |
|
|
|
|
break; |
|
|
|
|
else |
|
|
|
|
return -EPROTO; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (type == ACPI_TYPE_INTEGER) |
|
|
|
|
nargs++; |
|
|
|
|
else if (type == ACPI_TYPE_LOCAL_REFERENCE) |
|
|
|
|
break; |
|
|
|
|
else |
|
|
|
|
if (nargs > MAX_ACPI_REFERENCE_ARGS) |
|
|
|
|
return -EPROTO; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (idx++ == index) { |
|
|
|
|
args->adev = device; |
|
|
|
|
args->nargs = nargs; |
|
|
|
|
for (i = 0; i < nargs; i++) |
|
|
|
|
args->args[i] = element[i].integer.value; |
|
|
|
|
if (idx == index) { |
|
|
|
|
args->adev = device; |
|
|
|
|
args->nargs = nargs; |
|
|
|
|
for (i = 0; i < nargs; i++) |
|
|
|
|
args->args[i] = element[i].integer.value; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
element += nargs; |
|
|
|
|
} else if (element->type == ACPI_TYPE_INTEGER) { |
|
|
|
|
if (idx == index) |
|
|
|
|
return -ENOENT; |
|
|
|
|
element++; |
|
|
|
|
} else { |
|
|
|
|
return -EPROTO; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
element += nargs; |
|
|
|
|
idx++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return -EPROTO; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* acpi_node_get_property_reference - get a handle to the referenced object. |
|
|
|
|
* @fwnode: Firmware node to get the property from. |
|
|
|
|
* @propname: Name of the property. |
|
|
|
|
* @index: Index of the reference to return. |
|
|
|
|
* @args: Location to store the returned reference with optional arguments. |
|
|
|
|
*/ |
|
|
|
|
int acpi_node_get_property_reference(struct fwnode_handle *fwnode, |
|
|
|
|
const char *name, size_t index, |
|
|
|
|
struct acpi_reference_args *args) |
|
|
|
|
{ |
|
|
|
|
struct acpi_device_data *data = acpi_device_data_of_node(fwnode); |
|
|
|
|
|
|
|
|
|
return data ? acpi_data_get_property_reference(data, name, index, args) : -EINVAL; |
|
|
|
|
return -ENODATA; |
|
|
|
|
} |
|
|
|
|
EXPORT_SYMBOL_GPL(acpi_node_get_property_reference); |
|
|
|
|
EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference); |
|
|
|
|
|
|
|
|
|
static int acpi_data_prop_read_single(struct acpi_device_data *data, |
|
|
|
|
const char *propname, |
|
|
|
|