diff options
-rw-r--r-- | drivers/amba/acpi.c | 160 |
1 files changed, 31 insertions, 129 deletions
diff --git a/drivers/amba/acpi.c b/drivers/amba/acpi.c index 9a97cd8ad433..ae180757f335 100644 --- a/drivers/amba/acpi.c +++ b/drivers/amba/acpi.c @@ -25,102 +25,6 @@ struct acpi_amba_bus_info { char *clk_name; }; -/* UUID: a706b112-bf0b-48d2-9fa3-95591a3c4c06 (randomly generated) */ -static const char acpi_amba_dsm_uuid[] = { - 0xa7, 0x06, 0xb1, 0x12, 0xbf, 0x0b, 0x48, 0xd2, - 0x9f, 0xa3, 0x95, 0x59, 0x1a, 0x3c, 0x4c, 0x06 -}; - -/* acpi_amba_dsm_lookup() - * - * Helper to parse through ACPI _DSM object for a device. Each entry - * has three fields. - */ -int acpi_amba_dsm_lookup(acpi_handle handle, - const char *tag, int index, - struct acpi_amba_dsm_entry *entry) -{ - acpi_status status; - struct acpi_object_list input; - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object params[4]; - union acpi_object *obj; - int len, match_count, i; - - /* invalidate output in case there's no entry to supply */ - entry->key = NULL; - entry->value = NULL; - - if (!acpi_has_method(handle, "_DSM")) - return -ENOENT; - - input.count = 4; - params[0].type = ACPI_TYPE_BUFFER; /* UUID */ - params[0].buffer.length = sizeof(acpi_amba_dsm_uuid); - params[0].buffer.pointer = (char *)acpi_amba_dsm_uuid; - params[1].type = ACPI_TYPE_INTEGER; /* Revision */ - params[1].integer.value = 1; - params[2].type = ACPI_TYPE_INTEGER; /* Function # */ - params[2].integer.value = 1; - params[3].type = ACPI_TYPE_PACKAGE; /* Arguments */ - params[3].package.count = 0; - params[3].package.elements = NULL; - input.pointer = params; - - status = acpi_evaluate_object_typed(handle, "_DSM", - &input, &output, ACPI_TYPE_PACKAGE); - if (ACPI_FAILURE(status)) { - pr_err("failed to get _DSM package for this device\n"); - return -ENOENT; - } - - obj = (union acpi_object *)output.pointer; - - /* parse 2 objects per entry */ - match_count = 0; - for (i = 0; (i + 2) <= obj->package.count; i += 2) { - /* key must be a string */ - len = obj->package.elements[i].string.length; - if (len <= 0) - continue; - - /* check to see if this is the entry to return */ - if (strncmp(tag, obj->package.elements[i].string.pointer, - len) != 0 || - match_count < index) { - match_count++; - continue; - } - - /* copy the key */ - entry->key = kmalloc(len + 1, GFP_KERNEL); - strncpy(entry->key, - obj->package.elements[i].string.pointer, - len); - entry->key[len] = '\0'; - - /* value is a string with space-delimited fields if necessary */ - len = obj->package.elements[i + 1].string.length; - if (len > 0) { - entry->value = kmalloc(len + 1, GFP_KERNEL); - strncpy(entry->value, - obj->package.elements[i+1].string.pointer, - len); - entry->value[len] = '\0'; - } - - break; - } - - kfree(output.pointer); - - if (entry->key == NULL) - return -ENOENT; - - return 0; -} -EXPORT_SYMBOL_GPL(acpi_amba_dsm_lookup); - static int acpi_amba_add_resource(struct acpi_resource *ares, void *data) { struct amba_device *dev = data; @@ -157,43 +61,41 @@ static int acpi_amba_add_resource(struct acpi_resource *ares, void *data) static struct clk *acpi_amba_get_clk(acpi_handle handle, int index, char **clk_name) { - struct acpi_amba_dsm_entry entry; acpi_handle clk_handle; struct acpi_device *adev, *clk_adev; - char *clk_path; + const char **clk_paths; struct clk *clk = NULL; - int len; + int ret; if (acpi_bus_get_device(handle, &adev)) { pr_err("cannot get device from handle\n"); return NULL; } - /* key=value format for clocks is: - * "clock-name"="apb_pclk \\_SB.CLK0" - */ - if (acpi_amba_dsm_lookup(handle, "clock-name", index, &entry) != 0) + /* Get number of entries */ + ret = acpi_dev_get_property_array_string(adev, "clocks", NULL, 0); + + if ((ret < 0) || (index >= ret)) return NULL; + clk_paths = kzalloc(sizeof(*clk_paths) * ret, GFP_KERNEL); + /* look under the clock device for the clock that matches the entry */ - *clk_name = NULL; - len = strcspn(entry.value, " "); - if (len > 0 && (len + 1) < strlen(entry.value)) { - clk_path = entry.value + len + 1; - *clk_name = kmalloc(len + 1, GFP_KERNEL); - strncpy(*clk_name, entry.value, len); - (*clk_name)[len] = '\0'; - if (ACPI_FAILURE( - acpi_get_handle(NULL, clk_path, &clk_handle)) == 0 && - acpi_bus_get_device(clk_handle, &clk_adev) == 0) - clk = clk_get_sys(dev_name(&clk_adev->dev), *clk_name); - } else - pr_err("Invalid clock-name value format '%s' for %s\n", - entry.value, dev_name(&adev->dev)); - - kfree(entry.key); - kfree(entry.value); + ret = acpi_dev_get_property_array_string(adev, "clocks", clk_paths, + ret); + + /* Locate the acpi_device from the device name */ + acpi_get_handle(NULL, (acpi_string)clk_paths[index], &clk_handle); + if (!clk_handle) + goto error; + acpi_bus_get_device(clk_handle, &clk_adev); + if (!clk_adev) + goto error; + clk = clk_get_sys(dev_name(&clk_adev->dev), NULL); + +error: + kfree(clk_paths); return clk; } @@ -204,14 +106,6 @@ static void acpi_amba_register_clocks(struct acpi_device *adev, int i; char *clk_name; - if (default_clk) { - /* for amba_get_enable_pclk() ... */ - clk_register_clkdev(default_clk, default_clk_name, - dev_name(&adev->dev)); - /* for devm_clk_get() ... */ - clk_register_clkdev(default_clk, NULL, dev_name(&adev->dev)); - } - for (i = 0;; i++) { clk_name = NULL; clk = acpi_amba_get_clk(ACPI_HANDLE(&adev->dev), i, &clk_name); @@ -222,6 +116,14 @@ static void acpi_amba_register_clocks(struct acpi_device *adev, kfree(clk_name); } + + if (default_clk) { + /* for amba_get_enable_pclk() ... */ + clk_register_clkdev(default_clk, default_clk_name, + dev_name(&adev->dev)); + /* for devm_clk_get() ... */ + clk_register_clkdev(default_clk, NULL, dev_name(&adev->dev)); + } } /* acpi_amba_add_device() @@ -309,7 +211,7 @@ static int acpi_amba_bus_probe(struct platform_device *pdev) } static const struct acpi_device_id amba_bus_acpi_match[] = { - { "AMBA0000", 0 }, + { "LNRO001A", 0 }, { }, }; |