aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2012-04-19 06:04:30 -0400
committerPaul Walmsley <paul@pwsan.com>2012-04-19 06:04:30 -0400
commit2221b5cddc2ebcfa4b0217266d2edc98e7eec93b (patch)
tree41ab66741f2851614762657b3c02a0c5da1dbf71 /arch/arm/mach-omap2/omap_hwmod.c
parent24dbc2130179ebd493a241f6f5972cf6524b933a (diff)
ARM: OMAP2+: hwmod: add support for link registration
Add support for direct IP block interconnect ("link") registration to the hwmod code via a new function, omap_hwmod_register_links(). This will replace direct registration of hwmods, and a subsequent patch will remove omap_hwmod_register(). This change will allow a subsequent patch to remove the hwmod data link arrays. This will reduce the size of the hwmod static data and also make it easier to generate the data files. It will also make it possible to share some of the struct omap_hwmod records across multiple SoCs, since the link array pointers will be removed from the struct omap_hwmod. The downside is that boot time will increase. Minimizing boot time was the reason why the link arrays were originally introduced. Removing them will require extra computation during boot to allocate memory and associate IP blocks with their interconnects. However, since the current kernel development focus is on reducing the number of lines in arch/arm/mach-omap2/, boot time impact is now seemingly considered a lower priority. This patch contains additional complexity to reduce the number of memory allocations required for this change. This reduces the boot time impact: total hwmod link registration time was ~ 2655 microseconds with a simple allocation strategy, but is now ~ 549 microseconds[1] with the approach taken by this patch. 1. Measured on a BeagleBoard 35xx @ 500MHz MPU/333 MHz CORE, average of 7 samples. Total uncertainty is +/- 61 microseconds. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: BenoƮt Cousson <b-cousson@ti.com>
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c297
1 files changed, 281 insertions, 16 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 8cf837d2332a..99b913aa0cb9 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -137,6 +137,7 @@
137#include <linux/mutex.h> 137#include <linux/mutex.h>
138#include <linux/spinlock.h> 138#include <linux/spinlock.h>
139#include <linux/slab.h> 139#include <linux/slab.h>
140#include <linux/bootmem.h>
140 141
141#include "common.h" 142#include "common.h"
142#include <plat/cpu.h> 143#include <plat/cpu.h>
@@ -159,25 +160,54 @@
159/* Name of the OMAP hwmod for the MPU */ 160/* Name of the OMAP hwmod for the MPU */
160#define MPU_INITIATOR_NAME "mpu" 161#define MPU_INITIATOR_NAME "mpu"
161 162
163/*
164 * Number of struct omap_hwmod_link records per struct
165 * omap_hwmod_ocp_if record (master->slave and slave->master)
166 */
167#define LINKS_PER_OCP_IF 2
168
162/* omap_hwmod_list contains all registered struct omap_hwmods */ 169/* omap_hwmod_list contains all registered struct omap_hwmods */
163static LIST_HEAD(omap_hwmod_list); 170static LIST_HEAD(omap_hwmod_list);
164 171
165/* mpu_oh: used to add/remove MPU initiator from sleepdep list */ 172/* mpu_oh: used to add/remove MPU initiator from sleepdep list */
166static struct omap_hwmod *mpu_oh; 173static struct omap_hwmod *mpu_oh;
167 174
175/*
176 * link_registration: set to true if hwmod interfaces are being registered
177 * directly; set to false if hwmods are being registered directly
178 */
179static bool link_registration;
180
181/*
182 * linkspace: ptr to a buffer that struct omap_hwmod_link records are
183 * allocated from - used to reduce the number of small memory
184 * allocations, which has a significant impact on performance
185 */
186static struct omap_hwmod_link *linkspace;
187
188/*
189 * free_ls, max_ls: array indexes into linkspace; representing the
190 * next free struct omap_hwmod_link index, and the maximum number of
191 * struct omap_hwmod_link records allocated (respectively)
192 */
193static unsigned short free_ls, max_ls, ls_supp;
168 194
169/* Private functions */ 195/* Private functions */
170 196
171/** 197/**
172 * _fetch_next_ocp_if - return @i'th OCP interface in an array 198 * _fetch_next_ocp_if - return next OCP interface in an array or list
173 * @p: ptr to a ptr to the list_head inside the ocp_if to return (not yet used) 199 * @p: ptr to a ptr to the list_head inside the ocp_if to return
174 * @old: ptr to an array of struct omap_hwmod_ocp_if records 200 * @old: ptr to an array of struct omap_hwmod_ocp_if records
175 * @i: pointer to the index into the @old array 201 * @i: pointer to the index into the @old array
176 * 202 *
177 * Return a pointer to the next struct omap_hwmod_ocp_if record in a 203 * Return a pointer to the next struct omap_hwmod_ocp_if record in a
178 * sequence. Currently returns a struct omap_hwmod_ocp_if record 204 * sequence. If hwmods are being registered directly, then return a
179 * corresponding to the element index pointed to by @i in the @old 205 * struct omap_hwmod_ocp_if record corresponding to the element index
180 * array, and increments the index pointed to by @i. 206 * pointed to by @i in the
207 * @old array. Otherwise, return a pointer to the struct
208 * omap_hwmod_ocp_if record containing the struct list_head record pointed
209 * to by @p, and set the pointer pointed to by @p to point to the next
210 * struct list_head record in the list.
181 */ 211 */
182static struct omap_hwmod_ocp_if *_fetch_next_ocp_if(struct list_head **p, 212static struct omap_hwmod_ocp_if *_fetch_next_ocp_if(struct list_head **p,
183 struct omap_hwmod_ocp_if **old, 213 struct omap_hwmod_ocp_if **old,
@@ -185,7 +215,13 @@ static struct omap_hwmod_ocp_if *_fetch_next_ocp_if(struct list_head **p,
185{ 215{
186 struct omap_hwmod_ocp_if *oi; 216 struct omap_hwmod_ocp_if *oi;
187 217
188 oi = old[*i]; 218 if (!link_registration) {
219 oi = old[*i];
220 } else {
221 oi = list_entry(*p, struct omap_hwmod_link, node)->ocp_if;
222 *p = (*p)->next;
223 }
224
189 *i = *i + 1; 225 *i = *i + 1;
190 226
191 return oi; 227 return oi;
@@ -606,12 +642,16 @@ static int _init_main_clk(struct omap_hwmod *oh)
606static int _init_interface_clks(struct omap_hwmod *oh) 642static int _init_interface_clks(struct omap_hwmod *oh)
607{ 643{
608 struct omap_hwmod_ocp_if *os; 644 struct omap_hwmod_ocp_if *os;
645 struct list_head *p = NULL;
609 struct clk *c; 646 struct clk *c;
610 int i = 0; 647 int i = 0;
611 int ret = 0; 648 int ret = 0;
612 649
650 if (link_registration)
651 p = oh->slave_ports.next;
652
613 while (i < oh->slaves_cnt) { 653 while (i < oh->slaves_cnt) {
614 os = _fetch_next_ocp_if(NULL, oh->slaves, &i); 654 os = _fetch_next_ocp_if(&p, oh->slaves, &i);
615 if (!os->clk) 655 if (!os->clk)
616 continue; 656 continue;
617 657
@@ -664,6 +704,7 @@ static int _init_opt_clks(struct omap_hwmod *oh)
664static int _enable_clocks(struct omap_hwmod *oh) 704static int _enable_clocks(struct omap_hwmod *oh)
665{ 705{
666 struct omap_hwmod_ocp_if *os; 706 struct omap_hwmod_ocp_if *os;
707 struct list_head *p = NULL;
667 int i = 0; 708 int i = 0;
668 709
669 pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name); 710 pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
@@ -671,8 +712,11 @@ static int _enable_clocks(struct omap_hwmod *oh)
671 if (oh->_clk) 712 if (oh->_clk)
672 clk_enable(oh->_clk); 713 clk_enable(oh->_clk);
673 714
715 if (link_registration)
716 p = oh->slave_ports.next;
717
674 while (i < oh->slaves_cnt) { 718 while (i < oh->slaves_cnt) {
675 os = _fetch_next_ocp_if(NULL, oh->slaves, &i); 719 os = _fetch_next_ocp_if(&p, oh->slaves, &i);
676 720
677 if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) 721 if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
678 clk_enable(os->_clk); 722 clk_enable(os->_clk);
@@ -692,6 +736,7 @@ static int _enable_clocks(struct omap_hwmod *oh)
692static int _disable_clocks(struct omap_hwmod *oh) 736static int _disable_clocks(struct omap_hwmod *oh)
693{ 737{
694 struct omap_hwmod_ocp_if *os; 738 struct omap_hwmod_ocp_if *os;
739 struct list_head *p = NULL;
695 int i = 0; 740 int i = 0;
696 741
697 pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name); 742 pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name);
@@ -699,8 +744,11 @@ static int _disable_clocks(struct omap_hwmod *oh)
699 if (oh->_clk) 744 if (oh->_clk)
700 clk_disable(oh->_clk); 745 clk_disable(oh->_clk);
701 746
747 if (link_registration)
748 p = oh->slave_ports.next;
749
702 while (i < oh->slaves_cnt) { 750 while (i < oh->slaves_cnt) {
703 os = _fetch_next_ocp_if(NULL, oh->slaves, &i); 751 os = _fetch_next_ocp_if(&p, oh->slaves, &i);
704 752
705 if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) 753 if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
706 clk_disable(os->_clk); 754 clk_disable(os->_clk);
@@ -975,8 +1023,12 @@ static int _get_addr_space_by_name(struct omap_hwmod *oh, const char *name,
975{ 1023{
976 int i, j; 1024 int i, j;
977 struct omap_hwmod_ocp_if *os; 1025 struct omap_hwmod_ocp_if *os;
1026 struct list_head *p = NULL;
978 bool found = false; 1027 bool found = false;
979 1028
1029 if (link_registration)
1030 p = oh->slave_ports.next;
1031
980 i = 0; 1032 i = 0;
981 while (i < oh->slaves_cnt) { 1033 while (i < oh->slaves_cnt) {
982 os = _fetch_next_ocp_if(NULL, oh->slaves, &i); 1034 os = _fetch_next_ocp_if(NULL, oh->slaves, &i);
@@ -1019,6 +1071,7 @@ static int _get_addr_space_by_name(struct omap_hwmod *oh, const char *name,
1019static void __init _save_mpu_port_index(struct omap_hwmod *oh) 1071static void __init _save_mpu_port_index(struct omap_hwmod *oh)
1020{ 1072{
1021 struct omap_hwmod_ocp_if *os = NULL; 1073 struct omap_hwmod_ocp_if *os = NULL;
1074 struct list_head *p = NULL;
1022 int i = 0; 1075 int i = 0;
1023 1076
1024 if (!oh) 1077 if (!oh)
@@ -1026,9 +1079,13 @@ static void __init _save_mpu_port_index(struct omap_hwmod *oh)
1026 1079
1027 oh->_int_flags |= _HWMOD_NO_MPU_PORT; 1080 oh->_int_flags |= _HWMOD_NO_MPU_PORT;
1028 1081
1082 if (link_registration)
1083 p = oh->slave_ports.next;
1084
1029 while (i < oh->slaves_cnt) { 1085 while (i < oh->slaves_cnt) {
1030 os = _fetch_next_ocp_if(NULL, oh->slaves, &i); 1086 os = _fetch_next_ocp_if(&p, oh->slaves, &i);
1031 if (os->user & OCP_USER_MPU) { 1087 if (os->user & OCP_USER_MPU) {
1088 oh->_mpu_port = os;
1032 oh->_mpu_port_index = i - 1; 1089 oh->_mpu_port_index = i - 1;
1033 oh->_int_flags &= ~_HWMOD_NO_MPU_PORT; 1090 oh->_int_flags &= ~_HWMOD_NO_MPU_PORT;
1034 break; 1091 break;
@@ -1056,7 +1113,10 @@ static struct omap_hwmod_ocp_if *_find_mpu_rt_port(struct omap_hwmod *oh)
1056 if (!oh || oh->_int_flags & _HWMOD_NO_MPU_PORT || oh->slaves_cnt == 0) 1113 if (!oh || oh->_int_flags & _HWMOD_NO_MPU_PORT || oh->slaves_cnt == 0)
1057 return NULL; 1114 return NULL;
1058 1115
1059 return oh->slaves[oh->_mpu_port_index]; 1116 if (!link_registration)
1117 return oh->slaves[oh->_mpu_port_index];
1118 else
1119 return oh->_mpu_port;
1060}; 1120};
1061 1121
1062/** 1122/**
@@ -1976,6 +2036,8 @@ static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data)
1976 if (!oh) 2036 if (!oh)
1977 return; 2037 return;
1978 2038
2039 _save_mpu_port_index(oh);
2040
1979 if (oh->_int_flags & _HWMOD_NO_MPU_PORT) 2041 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
1980 return; 2042 return;
1981 2043
@@ -2042,13 +2104,16 @@ static int __init _init(struct omap_hwmod *oh, void *data)
2042static void __init _setup_iclk_autoidle(struct omap_hwmod *oh) 2104static void __init _setup_iclk_autoidle(struct omap_hwmod *oh)
2043{ 2105{
2044 struct omap_hwmod_ocp_if *os; 2106 struct omap_hwmod_ocp_if *os;
2107 struct list_head *p = NULL;
2045 int i = 0; 2108 int i = 0;
2046 if (oh->_state != _HWMOD_STATE_INITIALIZED) 2109 if (oh->_state != _HWMOD_STATE_INITIALIZED)
2047 return; 2110 return;
2048 2111
2112 if (link_registration)
2113 p = oh->slave_ports.next;
2049 2114
2050 while (i < oh->slaves_cnt) { 2115 while (i < oh->slaves_cnt) {
2051 os = _fetch_next_ocp_if(NULL, oh->slaves, &i); 2116 os = _fetch_next_ocp_if(&p, oh->slaves, &i);
2052 if (!os->_clk) 2117 if (!os->_clk)
2053 continue; 2118 continue;
2054 2119
@@ -2219,10 +2284,10 @@ static int __init _register(struct omap_hwmod *oh)
2219 if (_lookup(oh->name)) 2284 if (_lookup(oh->name))
2220 return -EEXIST; 2285 return -EEXIST;
2221 2286
2222 _save_mpu_port_index(oh);
2223
2224 list_add_tail(&oh->node, &omap_hwmod_list); 2287 list_add_tail(&oh->node, &omap_hwmod_list);
2225 2288
2289 INIT_LIST_HEAD(&oh->master_ports);
2290 INIT_LIST_HEAD(&oh->slave_ports);
2226 spin_lock_init(&oh->_lock); 2291 spin_lock_init(&oh->_lock);
2227 2292
2228 oh->_state = _HWMOD_STATE_REGISTERED; 2293 oh->_state = _HWMOD_STATE_REGISTERED;
@@ -2237,6 +2302,160 @@ static int __init _register(struct omap_hwmod *oh)
2237 return 0; 2302 return 0;
2238} 2303}
2239 2304
2305/**
2306 * _alloc_links - return allocated memory for hwmod links
2307 * @ml: pointer to a struct omap_hwmod_link * for the master link
2308 * @sl: pointer to a struct omap_hwmod_link * for the slave link
2309 *
2310 * Return pointers to two struct omap_hwmod_link records, via the
2311 * addresses pointed to by @ml and @sl. Will first attempt to return
2312 * memory allocated as part of a large initial block, but if that has
2313 * been exhausted, will allocate memory itself. Since ideally this
2314 * second allocation path will never occur, the number of these
2315 * 'supplemental' allocations will be logged when debugging is
2316 * enabled. Returns 0.
2317 */
2318static int __init _alloc_links(struct omap_hwmod_link **ml,
2319 struct omap_hwmod_link **sl)
2320{
2321 unsigned int sz;
2322
2323 if ((free_ls + LINKS_PER_OCP_IF) <= max_ls) {
2324 *ml = &linkspace[free_ls++];
2325 *sl = &linkspace[free_ls++];
2326 return 0;
2327 }
2328
2329 sz = sizeof(struct omap_hwmod_link) * LINKS_PER_OCP_IF;
2330
2331 *sl = NULL;
2332 *ml = alloc_bootmem(sz);
2333
2334 memset(*ml, 0, sz);
2335
2336 *sl = (void *)(*ml) + sizeof(struct omap_hwmod_link);
2337
2338 ls_supp++;
2339 pr_debug("omap_hwmod: supplemental link allocations needed: %d\n",
2340 ls_supp * LINKS_PER_OCP_IF);
2341
2342 return 0;
2343};
2344
2345/**
2346 * _add_link - add an interconnect between two IP blocks
2347 * @oi: pointer to a struct omap_hwmod_ocp_if record
2348 *
2349 * Add struct omap_hwmod_link records connecting the master IP block
2350 * specified in @oi->master to @oi, and connecting the slave IP block
2351 * specified in @oi->slave to @oi. This code is assumed to run before
2352 * preemption or SMP has been enabled, thus avoiding the need for
2353 * locking in this code. Changes to this assumption will require
2354 * additional locking. Returns 0.
2355 */
2356static int __init _add_link(struct omap_hwmod_ocp_if *oi)
2357{
2358 struct omap_hwmod_link *ml, *sl;
2359
2360 pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name,
2361 oi->slave->name);
2362
2363 _alloc_links(&ml, &sl);
2364
2365 ml->ocp_if = oi;
2366 INIT_LIST_HEAD(&ml->node);
2367 list_add(&ml->node, &oi->master->master_ports);
2368 oi->master->masters_cnt++;
2369
2370 sl->ocp_if = oi;
2371 INIT_LIST_HEAD(&sl->node);
2372 list_add(&sl->node, &oi->slave->slave_ports);
2373 oi->slave->slaves_cnt++;
2374
2375 return 0;
2376}
2377
2378/**
2379 * _register_link - register a struct omap_hwmod_ocp_if
2380 * @oi: struct omap_hwmod_ocp_if *
2381 *
2382 * Registers the omap_hwmod_ocp_if record @oi. Returns -EEXIST if it
2383 * has already been registered; -EINVAL if @oi is NULL or if the
2384 * record pointed to by @oi is missing required fields; or 0 upon
2385 * success.
2386 *
2387 * XXX The data should be copied into bootmem, so the original data
2388 * should be marked __initdata and freed after init. This would allow
2389 * unneeded omap_hwmods to be freed on multi-OMAP configurations.
2390 */
2391static int __init _register_link(struct omap_hwmod_ocp_if *oi)
2392{
2393 if (!oi || !oi->master || !oi->slave || !oi->user)
2394 return -EINVAL;
2395
2396 if (oi->_int_flags & _OCPIF_INT_FLAGS_REGISTERED)
2397 return -EEXIST;
2398
2399 pr_debug("omap_hwmod: registering link from %s to %s\n",
2400 oi->master->name, oi->slave->name);
2401
2402 /*
2403 * Register the connected hwmods, if they haven't been
2404 * registered already
2405 */
2406 if (oi->master->_state != _HWMOD_STATE_REGISTERED)
2407 _register(oi->master);
2408
2409 if (oi->slave->_state != _HWMOD_STATE_REGISTERED)
2410 _register(oi->slave);
2411
2412 _add_link(oi);
2413
2414 oi->_int_flags |= _OCPIF_INT_FLAGS_REGISTERED;
2415
2416 return 0;
2417}
2418
2419/**
2420 * _alloc_linkspace - allocate large block of hwmod links
2421 * @ois: pointer to an array of struct omap_hwmod_ocp_if records to count
2422 *
2423 * Allocate a large block of struct omap_hwmod_link records. This
2424 * improves boot time significantly by avoiding the need to allocate
2425 * individual records one by one. If the number of records to
2426 * allocate in the block hasn't been manually specified, this function
2427 * will count the number of struct omap_hwmod_ocp_if records in @ois
2428 * and use that to determine the allocation size. For SoC families
2429 * that require multiple list registrations, such as OMAP3xxx, this
2430 * estimation process isn't optimal, so manual estimation is advised
2431 * in those cases. Returns -EEXIST if the allocation has already occurred
2432 * or 0 upon success.
2433 */
2434static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
2435{
2436 unsigned int i = 0;
2437 unsigned int sz;
2438
2439 if (linkspace) {
2440 WARN(1, "linkspace already allocated\n");
2441 return -EEXIST;
2442 }
2443
2444 if (max_ls == 0)
2445 while (ois[i++])
2446 max_ls += LINKS_PER_OCP_IF;
2447
2448 sz = sizeof(struct omap_hwmod_link) * max_ls;
2449
2450 pr_debug("omap_hwmod: %s: allocating %d byte linkspace (%d links)\n",
2451 __func__, sz, max_ls);
2452
2453 linkspace = alloc_bootmem(sz);
2454
2455 memset(linkspace, 0, sz);
2456
2457 return 0;
2458}
2240 2459
2241/* Public functions */ 2460/* Public functions */
2242 2461
@@ -2376,6 +2595,9 @@ int __init omap_hwmod_register(struct omap_hwmod **ohs)
2376{ 2595{
2377 int r, i; 2596 int r, i;
2378 2597
2598 if (link_registration)
2599 return -EINVAL;
2600
2379 if (!ohs) 2601 if (!ohs)
2380 return 0; 2602 return 0;
2381 2603
@@ -2390,6 +2612,41 @@ int __init omap_hwmod_register(struct omap_hwmod **ohs)
2390} 2612}
2391 2613
2392/** 2614/**
2615 * omap_hwmod_register_links - register an array of hwmod links
2616 * @ois: pointer to an array of omap_hwmod_ocp_if to register
2617 *
2618 * Intended to be called early in boot before the clock framework is
2619 * initialized. If @ois is not null, will register all omap_hwmods
2620 * listed in @ois that are valid for this chip. Returns 0.
2621 */
2622int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois)
2623{
2624 int r, i;
2625
2626 if (!ois)
2627 return 0;
2628
2629 link_registration = true;
2630
2631 if (!linkspace) {
2632 if (_alloc_linkspace(ois)) {
2633 pr_err("omap_hwmod: could not allocate link space\n");
2634 return -ENOMEM;
2635 }
2636 }
2637
2638 i = 0;
2639 do {
2640 r = _register_link(ois[i]);
2641 WARN(r && r != -EEXIST,
2642 "omap_hwmod: _register_link(%s -> %s) returned %d\n",
2643 ois[i]->master->name, ois[i]->slave->name, r);
2644 } while (ois[++i]);
2645
2646 return 0;
2647}
2648
2649/**
2393 * _ensure_mpu_hwmod_is_setup - ensure the MPU SS hwmod is init'ed and set up 2650 * _ensure_mpu_hwmod_is_setup - ensure the MPU SS hwmod is init'ed and set up
2394 * @oh: pointer to the hwmod currently being set up (usually not the MPU) 2651 * @oh: pointer to the hwmod currently being set up (usually not the MPU)
2395 * 2652 *
@@ -2631,13 +2888,17 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
2631int omap_hwmod_count_resources(struct omap_hwmod *oh) 2888int omap_hwmod_count_resources(struct omap_hwmod *oh)
2632{ 2889{
2633 struct omap_hwmod_ocp_if *os; 2890 struct omap_hwmod_ocp_if *os;
2891 struct list_head *p = NULL;
2634 int ret; 2892 int ret;
2635 int i = 0; 2893 int i = 0;
2636 2894
2637 ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh); 2895 ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh);
2638 2896
2897 if (link_registration)
2898 p = oh->slave_ports.next;
2899
2639 while (i < oh->slaves_cnt) { 2900 while (i < oh->slaves_cnt) {
2640 os = _fetch_next_ocp_if(NULL, oh->slaves, &i); 2901 os = _fetch_next_ocp_if(&p, oh->slaves, &i);
2641 ret += _count_ocp_if_addr_spaces(os); 2902 ret += _count_ocp_if_addr_spaces(os);
2642 } 2903 }
2643 2904
@@ -2657,6 +2918,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
2657int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res) 2918int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
2658{ 2919{
2659 struct omap_hwmod_ocp_if *os; 2920 struct omap_hwmod_ocp_if *os;
2921 struct list_head *p = NULL;
2660 int i, j, mpu_irqs_cnt, sdma_reqs_cnt, addr_cnt; 2922 int i, j, mpu_irqs_cnt, sdma_reqs_cnt, addr_cnt;
2661 int r = 0; 2923 int r = 0;
2662 2924
@@ -2680,9 +2942,12 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
2680 r++; 2942 r++;
2681 } 2943 }
2682 2944
2945 if (link_registration)
2946 p = oh->slave_ports.next;
2947
2683 i = 0; 2948 i = 0;
2684 while (i < oh->slaves_cnt) { 2949 while (i < oh->slaves_cnt) {
2685 os = _fetch_next_ocp_if(NULL, oh->slaves, &i); 2950 os = _fetch_next_ocp_if(&p, oh->slaves, &i);
2686 addr_cnt = _count_ocp_if_addr_spaces(os); 2951 addr_cnt = _count_ocp_if_addr_spaces(os);
2687 2952
2688 for (j = 0; j < addr_cnt; j++) { 2953 for (j = 0; j < addr_cnt; j++) {