diff options
author | Venkateswara Rao Mandela <venkat.mandela@ti.com> | 2016-12-08 17:29:04 -0600 |
---|---|---|
committer | David Huang <d-huang@ti.com> | 2017-09-01 13:14:28 -0500 |
commit | 4af733b9c3329015c8cda76a9324f8b53b5ce582 (patch) | |
tree | 5dfbd796aada94d526edb020137bd62046c19c6c | |
parent | 2ae53d8118933b49609250b7dad4f1374807eb2a (diff) | |
download | jacinto6evm-4af733b9c3329015c8cda76a9324f8b53b5ce582.tar.gz |
arch: arm: omap2: optimize hwmod lookup during init
Instead of searching through the device tree for nodes
with "ti,hwmods" property for every hwmod,
1. traverse the tree once and build a list.
2. search in the list for the hwmod.
3. In case the list is empty, fall back to the original
search mechanism.
This approach saves ~100 ms of initialization time on a DRA7xx
processor running at 1 GHz.
TODO: Free the allocated list
TODO: Check if the list can be allocated even earlier.
Change-Id: Ie871a807748a244dd900f228952e994deee70a33
Signed-off-by: Venkateswara Rao Mandela <venkat.mandela@ti.com>
[apply to android branch]
Signed-off-by: Praneeth Bajjuri <praneeth@ti.com>
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index c8eb5f4acfcb..46bb6c37aa70 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -235,6 +235,14 @@ static unsigned short free_ls, max_ls, ls_supp; /* inited: set to true once the hwmod code is initialized */ static bool inited; +static LIST_HEAD(omap_ti_hwmod_list); +struct oh_np_index_list { + struct device_node *np; + int index; + struct list_head node; + const char *name; +}; + /* Private functions */ /** @@ -2347,6 +2355,70 @@ static int of_dev_find_hwmod(struct device_node *np, return -ENODEV; } +static int of_dev_hwmod_list_lookup(const char *oh_name, + int *index, + struct device_node **found) +{ + struct oh_np_index_list *temp_node; + + if (list_empty(&omap_ti_hwmod_list)) + return 1; + + *found = NULL; + *index = 0; + + list_for_each_entry(temp_node, &omap_ti_hwmod_list, node) { + if (strcmp(oh_name, temp_node->name) == 0) { + *index = temp_node->index; + *found = temp_node->np; + return 0; + } + } + + return -ENODEV; +} +/** + * Builds a list of "ti,hwmods" and their indices for use by later + * code. + * + */ +static int __init omap_hwmod_build_ti_hwmod_list(void) +{ + struct device_node *bus; + struct device_node *np; + int count, i, res; + const char *p; + + if (!of_have_populated_dt()) + return 0; + + bus = of_find_node_by_name(NULL, "ocp"); + if (!bus) + return -ENODEV; + + for_each_node_with_property(np, "ti,hwmods") { + count = of_property_count_strings(np, "ti,hwmods"); + if (count < 1) + continue; + for (i = 0; i < count; i++) { + struct oh_np_index_list *item = NULL; + res = of_property_read_string_index(np, "ti,hwmods", + i, &p); + if (res) + continue; + item = kzalloc(sizeof(*item), GFP_KERNEL); + if (!item) + return -ENOMEM; + item->index = i; + item->np = np; + item->name = p; + list_add(&item->node, &omap_ti_hwmod_list); + } + + + } + return 0; +} /** * of_dev_hwmod_lookup - look up needed hwmod from dt blob * @np: struct device_node * @@ -2366,6 +2438,11 @@ static int of_dev_hwmod_lookup(struct device_node *np, struct device_node *np0 = NULL; int res; + res = of_dev_hwmod_list_lookup(oh->name, index, + found); + if (res <= 0) + return res; + res = of_dev_find_hwmod(np, oh); if (res >= 0) { *found = np; @@ -2481,6 +2558,7 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, return 0; } + /** * _init - initialize internal data for the hwmod @oh * @oh: struct omap_hwmod * @@ -3387,8 +3465,8 @@ int __init omap_hwmod_setup_one(const char *oh_name) */ static int __init omap_hwmod_setup_all(void) { + omap_hwmod_build_ti_hwmod_list(); _ensure_mpu_hwmod_is_setup(NULL); - omap_hwmod_for_each(_init, NULL); omap_hwmod_for_each(_setup, NULL); |