diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e3f0ecaf87dd..ee655dab672f 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -2326,38 +2326,80 @@ static int _shutdown(struct omap_hwmod *oh) | |||
2326 | return 0; | 2326 | return 0; |
2327 | } | 2327 | } |
2328 | 2328 | ||
2329 | static int of_dev_find_hwmod(struct device_node *np, | ||
2330 | struct omap_hwmod *oh) | ||
2331 | { | ||
2332 | int count, i, res; | ||
2333 | const char *p; | ||
2334 | |||
2335 | count = of_property_count_strings(np, "ti,hwmods"); | ||
2336 | if (count < 1) | ||
2337 | return -ENODEV; | ||
2338 | |||
2339 | for (i = 0; i < count; i++) { | ||
2340 | res = of_property_read_string_index(np, "ti,hwmods", | ||
2341 | i, &p); | ||
2342 | if (res) | ||
2343 | continue; | ||
2344 | if (!strcmp(p, oh->name)) { | ||
2345 | pr_debug("omap_hwmod: dt %s[%i] uses hwmod %s\n", | ||
2346 | np->name, i, oh->name); | ||
2347 | return i; | ||
2348 | } | ||
2349 | } | ||
2350 | |||
2351 | return -ENODEV; | ||
2352 | } | ||
2353 | |||
2329 | /** | 2354 | /** |
2330 | * of_dev_hwmod_lookup - look up needed hwmod from dt blob | 2355 | * of_dev_hwmod_lookup - look up needed hwmod from dt blob |
2331 | * @np: struct device_node * | 2356 | * @np: struct device_node * |
2332 | * @oh: struct omap_hwmod * | 2357 | * @oh: struct omap_hwmod * |
2358 | * @index: index of the entry found | ||
2359 | * @found: struct device_node * found or NULL | ||
2333 | * | 2360 | * |
2334 | * Parse the dt blob and find out needed hwmod. Recursive function is | 2361 | * Parse the dt blob and find out needed hwmod. Recursive function is |
2335 | * implemented to take care hierarchical dt blob parsing. | 2362 | * implemented to take care hierarchical dt blob parsing. |
2336 | * Return: The device node on success or NULL on failure. | 2363 | * Return: Returns 0 on success, -ENODEV when not found. |
2337 | */ | 2364 | */ |
2338 | static struct device_node *of_dev_hwmod_lookup(struct device_node *np, | 2365 | static int of_dev_hwmod_lookup(struct device_node *np, |
2339 | struct omap_hwmod *oh) | 2366 | struct omap_hwmod *oh, |
2367 | int *index, | ||
2368 | struct device_node **found) | ||
2340 | { | 2369 | { |
2341 | struct device_node *np0 = NULL, *np1 = NULL; | 2370 | struct device_node *np0 = NULL; |
2342 | const char *p; | 2371 | int res; |
2372 | |||
2373 | res = of_dev_find_hwmod(np, oh); | ||
2374 | if (res >= 0) { | ||
2375 | *found = np; | ||
2376 | *index = res; | ||
2377 | return 0; | ||
2378 | } | ||
2343 | 2379 | ||
2344 | for_each_child_of_node(np, np0) { | 2380 | for_each_child_of_node(np, np0) { |
2345 | if (of_find_property(np0, "ti,hwmods", NULL)) { | 2381 | struct device_node *fc; |
2346 | p = of_get_property(np0, "ti,hwmods", NULL); | 2382 | int i; |
2347 | if (!strcmp(p, oh->name)) | 2383 | |
2348 | return np0; | 2384 | res = of_dev_hwmod_lookup(np0, oh, &i, &fc); |
2349 | np1 = of_dev_hwmod_lookup(np0, oh); | 2385 | if (res == 0) { |
2350 | if (np1) | 2386 | *found = fc; |
2351 | return np1; | 2387 | *index = i; |
2388 | return 0; | ||
2352 | } | 2389 | } |
2353 | } | 2390 | } |
2354 | return NULL; | 2391 | |
2392 | *found = NULL; | ||
2393 | *index = 0; | ||
2394 | |||
2395 | return -ENODEV; | ||
2355 | } | 2396 | } |
2356 | 2397 | ||
2357 | /** | 2398 | /** |
2358 | * _init_mpu_rt_base - populate the virtual address for a hwmod | 2399 | * _init_mpu_rt_base - populate the virtual address for a hwmod |
2359 | * @oh: struct omap_hwmod * to locate the virtual address | 2400 | * @oh: struct omap_hwmod * to locate the virtual address |
2360 | * @data: (unused, caller should pass NULL) | 2401 | * @data: (unused, caller should pass NULL) |
2402 | * @index: index of the reg entry iospace in device tree | ||
2361 | * @np: struct device_node * of the IP block's device node in the DT data | 2403 | * @np: struct device_node * of the IP block's device node in the DT data |
2362 | * | 2404 | * |
2363 | * Cache the virtual address used by the MPU to access this IP block's | 2405 | * Cache the virtual address used by the MPU to access this IP block's |
@@ -2368,7 +2410,7 @@ static struct device_node *of_dev_hwmod_lookup(struct device_node *np, | |||
2368 | * -ENXIO on absent or invalid register target address space. | 2410 | * -ENXIO on absent or invalid register target address space. |
2369 | */ | 2411 | */ |
2370 | static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, | 2412 | static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, |
2371 | struct device_node *np) | 2413 | int index, struct device_node *np) |
2372 | { | 2414 | { |
2373 | struct omap_hwmod_addr_space *mem; | 2415 | struct omap_hwmod_addr_space *mem; |
2374 | void __iomem *va_start = NULL; | 2416 | void __iomem *va_start = NULL; |
@@ -2390,13 +2432,17 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, | |||
2390 | if (!np) | 2432 | if (!np) |
2391 | return -ENXIO; | 2433 | return -ENXIO; |
2392 | 2434 | ||
2393 | va_start = of_iomap(np, oh->mpu_rt_idx); | 2435 | va_start = of_iomap(np, index + oh->mpu_rt_idx); |
2394 | } else { | 2436 | } else { |
2395 | va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); | 2437 | va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); |
2396 | } | 2438 | } |
2397 | 2439 | ||
2398 | if (!va_start) { | 2440 | if (!va_start) { |
2399 | pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name); | 2441 | if (mem) |
2442 | pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name); | ||
2443 | else | ||
2444 | pr_err("omap_hwmod: %s: Missing dt reg%i for %s\n", | ||
2445 | oh->name, index, np->full_name); | ||
2400 | return -ENXIO; | 2446 | return -ENXIO; |
2401 | } | 2447 | } |
2402 | 2448 | ||
@@ -2422,17 +2468,29 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, | |||
2422 | */ | 2468 | */ |
2423 | static int __init _init(struct omap_hwmod *oh, void *data) | 2469 | static int __init _init(struct omap_hwmod *oh, void *data) |
2424 | { | 2470 | { |
2425 | int r; | 2471 | int r, index; |
2426 | struct device_node *np = NULL; | 2472 | struct device_node *np = NULL; |
2427 | 2473 | ||
2428 | if (oh->_state != _HWMOD_STATE_REGISTERED) | 2474 | if (oh->_state != _HWMOD_STATE_REGISTERED) |
2429 | return 0; | 2475 | return 0; |
2430 | 2476 | ||
2431 | if (of_have_populated_dt()) | 2477 | if (of_have_populated_dt()) { |
2432 | np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh); | 2478 | struct device_node *bus; |
2479 | |||
2480 | bus = of_find_node_by_name(NULL, "ocp"); | ||
2481 | if (!bus) | ||
2482 | return -ENODEV; | ||
2483 | |||
2484 | r = of_dev_hwmod_lookup(bus, oh, &index, &np); | ||
2485 | if (r) | ||
2486 | pr_debug("omap_hwmod: %s missing dt data\n", oh->name); | ||
2487 | else if (np && index) | ||
2488 | pr_warn("omap_hwmod: %s using broken dt data from %s\n", | ||
2489 | oh->name, np->name); | ||
2490 | } | ||
2433 | 2491 | ||
2434 | if (oh->class->sysc) { | 2492 | if (oh->class->sysc) { |
2435 | r = _init_mpu_rt_base(oh, NULL, np); | 2493 | r = _init_mpu_rt_base(oh, NULL, index, np); |
2436 | if (r < 0) { | 2494 | if (r < 0) { |
2437 | WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n", | 2495 | WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n", |
2438 | oh->name); | 2496 | oh->name); |