diff options
author | Kevin Hilman <khilman@linaro.org> | 2013-12-09 18:38:00 -0500 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2013-12-09 18:38:41 -0500 |
commit | ed16c8c50e26df3c16e40d35c9a4c0e9f032656c (patch) | |
tree | f268748e4bd3a6ceb08b7a7a70fb86c4dfce0e02 /arch/arm/mach-omap2/omap_hwmod.c | |
parent | 8ae19ec3356901bafa64816d9ea9378896f8979c (diff) | |
parent | f2e2c9d9b4087b74eb9e00d8dfac148354cb0b71 (diff) |
Merge tag 'omap-for-v3.13/yet-more-dt-regressions-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes
A rather big fix for a regression where we have dropped omap4 hwmod
data earlier but are not initializing it from device tree. In addition
to this fix we eventually also be fix the issues in the .dts files
and drivers, but that's too intrusive for the -rc cycle and must be
done later on.
Also a fix for a regression where we now are wrongly trying to initialize
devices on secure omaps like n900 and n9* when booted using device tree.
We need to set aes, sham and timer12 to disabled mode for secure
devices as they are claimed by the firmware running in the secure mode.
And two more legacy booting vs device tree based booting fixes for
am3517 that I did not notice earlier until Nishant Menon reported
these to me few days ago. With these we're good to go having v3.13
working both for legacy booting and device tree based booting, and we
can then go ahed and drop the legacy booting for mach-omap2 for v3.14.
* tag 'omap-for-v3.13/yet-more-dt-regressions-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (494 commits)
ARM: dts: Fix booting for secure omaps
ARM: OMAP2+: Fix the machine entry for am3517
ARM: dts: Fix missing entries for am3517
ARM: OMAP2+: Fix overwriting hwmod data with data from device tree
+Linux 3.13-rc3
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); |