aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c98
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
2329static 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 */
2338static struct device_node *of_dev_hwmod_lookup(struct device_node *np, 2365static 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 */
2370static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, 2412static 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 */
2423static int __init _init(struct omap_hwmod *oh, void *data) 2469static 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);