2 * Memory arbiter functions. Allocates bandwidth through the
3 * arbiter and sets up arbiter breakpoints.
5 * The algorithm first assigns slots to the clients that has specified
6 * bandwidth (e.g. ethernet) and then the remaining slots are divided
7 * on all the active clients.
9 * Copyright (c) 2004, 2005 Axis Communications AB.
12 #include <asm/arch/hwregs/reg_map.h>
13 #include <asm/arch/hwregs/reg_rdwr.h>
14 #include <asm/arch/hwregs/marb_defs.h>
15 #include <asm/arch/arbiter.h>
16 #include <asm/arch/hwregs/intr_vect.h>
17 #include <linux/interrupt.h>
18 #include <linux/signal.h>
19 #include <linux/errno.h>
20 #include <linux/spinlock.h>
23 struct crisv32_watch_entry
25 unsigned long instance
;
32 #define NUMBER_OF_BP 4
33 #define NBR_OF_CLIENTS 14
34 #define NBR_OF_SLOTS 64
35 #define SDRAM_BANDWIDTH 100000000 /* Some kind of expected value */
36 #define INTMEM_BANDWIDTH 400000000
37 #define NBR_OF_REGIONS 2
39 static struct crisv32_watch_entry watches
[NUMBER_OF_BP
] =
47 static int requested_slots
[NBR_OF_REGIONS
][NBR_OF_CLIENTS
];
48 static int active_clients
[NBR_OF_REGIONS
][NBR_OF_CLIENTS
];
49 static int max_bandwidth
[NBR_OF_REGIONS
] = {SDRAM_BANDWIDTH
, INTMEM_BANDWIDTH
};
51 DEFINE_SPINLOCK(arbiter_lock
);
54 crisv32_arbiter_irq(int irq
, void* dev_id
, struct pt_regs
* regs
);
56 static void crisv32_arbiter_config(int region
)
61 int val
[NBR_OF_SLOTS
];
63 for (slot
= 0; slot
< NBR_OF_SLOTS
; slot
++)
64 val
[slot
] = NBR_OF_CLIENTS
+ 1;
66 for (client
= 0; client
< NBR_OF_CLIENTS
; client
++)
69 if (!requested_slots
[region
][client
])
71 interval
= NBR_OF_SLOTS
/ requested_slots
[region
][client
];
73 while (pos
< NBR_OF_SLOTS
)
75 if (val
[pos
] != NBR_OF_CLIENTS
+ 1)
86 for (slot
= 0; slot
< NBR_OF_SLOTS
; slot
++)
88 if (val
[slot
] == NBR_OF_CLIENTS
+ 1)
91 while(!active_clients
[region
][client
]) {
92 client
= (client
+ 1) % NBR_OF_CLIENTS
;
97 client
= (client
+ 1) % NBR_OF_CLIENTS
;
99 if (region
== EXT_REGION
)
100 REG_WR_INT_VECT(marb
, regi_marb
, rw_ext_slots
, slot
, val
[slot
]);
101 else if (region
== INT_REGION
)
102 REG_WR_INT_VECT(marb
, regi_marb
, rw_int_slots
, slot
, val
[slot
]);
106 extern char _stext
, _etext
;
108 static void crisv32_arbiter_init(void)
110 static int initialized
= 0;
117 /* CPU caches are active. */
118 active_clients
[EXT_REGION
][10] = active_clients
[EXT_REGION
][11] = 1;
119 crisv32_arbiter_config(EXT_REGION
);
120 crisv32_arbiter_config(INT_REGION
);
122 if (request_irq(MEMARB_INTR_VECT
, crisv32_arbiter_irq
, IRQF_DISABLED
,
124 printk(KERN_ERR
"Couldn't allocate arbiter IRQ\n");
126 #ifndef CONFIG_ETRAX_KGDB
127 /* Global watch for writes to kernel text segment. */
128 crisv32_arbiter_watch(virt_to_phys(&_stext
), &_etext
- &_stext
,
129 arbiter_all_clients
, arbiter_all_write
, NULL
);
135 int crisv32_arbiter_allocate_bandwidth(int client
, int region
,
136 unsigned long bandwidth
)
139 int total_assigned
= 0;
140 int total_clients
= 0;
143 crisv32_arbiter_init();
145 for (i
= 0; i
< NBR_OF_CLIENTS
; i
++)
147 total_assigned
+= requested_slots
[region
][i
];
148 total_clients
+= active_clients
[region
][i
];
150 req
= NBR_OF_SLOTS
/ (max_bandwidth
[region
] / bandwidth
);
152 if (total_assigned
+ total_clients
+ req
+ 1 > NBR_OF_SLOTS
)
155 active_clients
[region
][client
] = 1;
156 requested_slots
[region
][client
] = req
;
157 crisv32_arbiter_config(region
);
162 int crisv32_arbiter_watch(unsigned long start
, unsigned long size
,
163 unsigned long clients
, unsigned long accesses
,
168 crisv32_arbiter_init();
170 if (start
> 0x80000000) {
171 printk("Arbiter: %lX doesn't look like a physical address", start
);
175 spin_lock(&arbiter_lock
);
177 for (i
= 0; i
< NUMBER_OF_BP
; i
++) {
178 if (!watches
[i
].used
) {
179 reg_marb_rw_intr_mask intr_mask
= REG_RD(marb
, regi_marb
, rw_intr_mask
);
182 watches
[i
].start
= start
;
183 watches
[i
].end
= start
+ size
;
186 REG_WR_INT(marb_bp
, watches
[i
].instance
, rw_first_addr
, watches
[i
].start
);
187 REG_WR_INT(marb_bp
, watches
[i
].instance
, rw_last_addr
, watches
[i
].end
);
188 REG_WR_INT(marb_bp
, watches
[i
].instance
, rw_op
, accesses
);
189 REG_WR_INT(marb_bp
, watches
[i
].instance
, rw_clients
, clients
);
192 intr_mask
.bp0
= regk_marb_yes
;
194 intr_mask
.bp1
= regk_marb_yes
;
196 intr_mask
.bp2
= regk_marb_yes
;
198 intr_mask
.bp3
= regk_marb_yes
;
200 REG_WR(marb
, regi_marb
, rw_intr_mask
, intr_mask
);
201 spin_unlock(&arbiter_lock
);
206 spin_unlock(&arbiter_lock
);
210 int crisv32_arbiter_unwatch(int id
)
212 reg_marb_rw_intr_mask intr_mask
= REG_RD(marb
, regi_marb
, rw_intr_mask
);
214 crisv32_arbiter_init();
216 spin_lock(&arbiter_lock
);
218 if ((id
< 0) || (id
>= NUMBER_OF_BP
) || (!watches
[id
].used
)) {
219 spin_unlock(&arbiter_lock
);
223 memset(&watches
[id
], 0, sizeof(struct crisv32_watch_entry
));
226 intr_mask
.bp0
= regk_marb_no
;
228 intr_mask
.bp2
= regk_marb_no
;
230 intr_mask
.bp2
= regk_marb_no
;
232 intr_mask
.bp3
= regk_marb_no
;
234 REG_WR(marb
, regi_marb
, rw_intr_mask
, intr_mask
);
236 spin_unlock(&arbiter_lock
);
240 extern void show_registers(struct pt_regs
*regs
);
243 crisv32_arbiter_irq(int irq
, void* dev_id
, struct pt_regs
* regs
)
245 reg_marb_r_masked_intr masked_intr
= REG_RD(marb
, regi_marb
, r_masked_intr
);
246 reg_marb_bp_r_brk_clients r_clients
;
247 reg_marb_bp_r_brk_addr r_addr
;
248 reg_marb_bp_r_brk_op r_op
;
249 reg_marb_bp_r_brk_first_client r_first
;
250 reg_marb_bp_r_brk_size r_size
;
251 reg_marb_bp_rw_ack ack
= {0};
252 reg_marb_rw_ack_intr ack_intr
= {.bp0
=1,.bp1
=1,.bp2
=1,.bp3
=1};
253 struct crisv32_watch_entry
* watch
;
255 if (masked_intr
.bp0
) {
257 ack_intr
.bp0
= regk_marb_yes
;
258 } else if (masked_intr
.bp1
) {
260 ack_intr
.bp1
= regk_marb_yes
;
261 } else if (masked_intr
.bp2
) {
263 ack_intr
.bp2
= regk_marb_yes
;
264 } else if (masked_intr
.bp3
) {
266 ack_intr
.bp3
= regk_marb_yes
;
271 /* Retrieve all useful information and print it. */
272 r_clients
= REG_RD(marb_bp
, watch
->instance
, r_brk_clients
);
273 r_addr
= REG_RD(marb_bp
, watch
->instance
, r_brk_addr
);
274 r_op
= REG_RD(marb_bp
, watch
->instance
, r_brk_op
);
275 r_first
= REG_RD(marb_bp
, watch
->instance
, r_brk_first_client
);
276 r_size
= REG_RD(marb_bp
, watch
->instance
, r_brk_size
);
278 printk("Arbiter IRQ\n");
279 printk("Clients %X addr %X op %X first %X size %X\n",
280 REG_TYPE_CONV(int, reg_marb_bp_r_brk_clients
, r_clients
),
281 REG_TYPE_CONV(int, reg_marb_bp_r_brk_addr
, r_addr
),
282 REG_TYPE_CONV(int, reg_marb_bp_r_brk_op
, r_op
),
283 REG_TYPE_CONV(int, reg_marb_bp_r_brk_first_client
, r_first
),
284 REG_TYPE_CONV(int, reg_marb_bp_r_brk_size
, r_size
));
286 REG_WR(marb_bp
, watch
->instance
, rw_ack
, ack
);
287 REG_WR(marb
, regi_marb
, rw_ack_intr
, ack_intr
);
289 printk("IRQ occured at %lX\n", regs
->erp
);