2 * Memory arbiter functions. Allocates bandwith through the
3 * arbiter and sets up arbiter breakpoints.
5 * The algorithm first assigns slots to the clients that has specified
6 * bandwith (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 <linux/config.h>
13 #include <asm/arch/hwregs/reg_map.h>
14 #include <asm/arch/hwregs/reg_rdwr.h>
15 #include <asm/arch/hwregs/marb_defs.h>
16 #include <asm/arch/arbiter.h>
17 #include <asm/arch/hwregs/intr_vect.h>
18 #include <linux/interrupt.h>
19 #include <linux/signal.h>
20 #include <linux/errno.h>
21 #include <linux/spinlock.h>
24 struct crisv32_watch_entry
26 unsigned long instance
;
33 #define NUMBER_OF_BP 4
34 #define NBR_OF_CLIENTS 14
35 #define NBR_OF_SLOTS 64
36 #define SDRAM_BANDWIDTH 100000000 /* Some kind of expected value */
37 #define INTMEM_BANDWIDTH 400000000
38 #define NBR_OF_REGIONS 2
40 static struct crisv32_watch_entry watches
[NUMBER_OF_BP
] =
48 static int requested_slots
[NBR_OF_REGIONS
][NBR_OF_CLIENTS
];
49 static int active_clients
[NBR_OF_REGIONS
][NBR_OF_CLIENTS
];
50 static int max_bandwidth
[NBR_OF_REGIONS
] = {SDRAM_BANDWIDTH
, INTMEM_BANDWIDTH
};
52 DEFINE_SPINLOCK(arbiter_lock
);
55 crisv32_arbiter_irq(int irq
, void* dev_id
, struct pt_regs
* regs
);
57 static void crisv32_arbiter_config(int region
)
62 int val
[NBR_OF_SLOTS
];
64 for (slot
= 0; slot
< NBR_OF_SLOTS
; slot
++)
65 val
[slot
] = NBR_OF_CLIENTS
+ 1;
67 for (client
= 0; client
< NBR_OF_CLIENTS
; client
++)
70 if (!requested_slots
[region
][client
])
72 interval
= NBR_OF_SLOTS
/ requested_slots
[region
][client
];
74 while (pos
< NBR_OF_SLOTS
)
76 if (val
[pos
] != NBR_OF_CLIENTS
+ 1)
87 for (slot
= 0; slot
< NBR_OF_SLOTS
; slot
++)
89 if (val
[slot
] == NBR_OF_CLIENTS
+ 1)
92 while(!active_clients
[region
][client
]) {
93 client
= (client
+ 1) % NBR_OF_CLIENTS
;
98 client
= (client
+ 1) % NBR_OF_CLIENTS
;
100 if (region
== EXT_REGION
)
101 REG_WR_INT_VECT(marb
, regi_marb
, rw_ext_slots
, slot
, val
[slot
]);
102 else if (region
== INT_REGION
)
103 REG_WR_INT_VECT(marb
, regi_marb
, rw_int_slots
, slot
, val
[slot
]);
107 extern char _stext
, _etext
;
109 static void crisv32_arbiter_init(void)
111 static int initialized
= 0;
118 /* CPU caches are active. */
119 active_clients
[EXT_REGION
][10] = active_clients
[EXT_REGION
][11] = 1;
120 crisv32_arbiter_config(EXT_REGION
);
121 crisv32_arbiter_config(INT_REGION
);
123 if (request_irq(MEMARB_INTR_VECT
, crisv32_arbiter_irq
, SA_INTERRUPT
,
125 printk(KERN_ERR
"Couldn't allocate arbiter IRQ\n");
127 #ifndef CONFIG_ETRAX_KGDB
128 /* Global watch for writes to kernel text segment. */
129 crisv32_arbiter_watch(virt_to_phys(&_stext
), &_etext
- &_stext
,
130 arbiter_all_clients
, arbiter_all_write
, NULL
);
136 int crisv32_arbiter_allocate_bandwith(int client
, int region
,
137 unsigned long bandwidth
)
140 int total_assigned
= 0;
141 int total_clients
= 0;
144 crisv32_arbiter_init();
146 for (i
= 0; i
< NBR_OF_CLIENTS
; i
++)
148 total_assigned
+= requested_slots
[region
][i
];
149 total_clients
+= active_clients
[region
][i
];
151 req
= NBR_OF_SLOTS
/ (max_bandwidth
[region
] / bandwidth
);
153 if (total_assigned
+ total_clients
+ req
+ 1 > NBR_OF_SLOTS
)
156 active_clients
[region
][client
] = 1;
157 requested_slots
[region
][client
] = req
;
158 crisv32_arbiter_config(region
);
163 int crisv32_arbiter_watch(unsigned long start
, unsigned long size
,
164 unsigned long clients
, unsigned long accesses
,
169 crisv32_arbiter_init();
171 if (start
> 0x80000000) {
172 printk("Arbiter: %lX doesn't look like a physical address", start
);
176 spin_lock(&arbiter_lock
);
178 for (i
= 0; i
< NUMBER_OF_BP
; i
++) {
179 if (!watches
[i
].used
) {
180 reg_marb_rw_intr_mask intr_mask
= REG_RD(marb
, regi_marb
, rw_intr_mask
);
183 watches
[i
].start
= start
;
184 watches
[i
].end
= start
+ size
;
187 REG_WR_INT(marb_bp
, watches
[i
].instance
, rw_first_addr
, watches
[i
].start
);
188 REG_WR_INT(marb_bp
, watches
[i
].instance
, rw_last_addr
, watches
[i
].end
);
189 REG_WR_INT(marb_bp
, watches
[i
].instance
, rw_op
, accesses
);
190 REG_WR_INT(marb_bp
, watches
[i
].instance
, rw_clients
, clients
);
193 intr_mask
.bp0
= regk_marb_yes
;
195 intr_mask
.bp1
= regk_marb_yes
;
197 intr_mask
.bp2
= regk_marb_yes
;
199 intr_mask
.bp3
= regk_marb_yes
;
201 REG_WR(marb
, regi_marb
, rw_intr_mask
, intr_mask
);
202 spin_unlock(&arbiter_lock
);
207 spin_unlock(&arbiter_lock
);
211 int crisv32_arbiter_unwatch(int id
)
213 reg_marb_rw_intr_mask intr_mask
= REG_RD(marb
, regi_marb
, rw_intr_mask
);
215 crisv32_arbiter_init();
217 spin_lock(&arbiter_lock
);
219 if ((id
< 0) || (id
>= NUMBER_OF_BP
) || (!watches
[id
].used
)) {
220 spin_unlock(&arbiter_lock
);
224 memset(&watches
[id
], 0, sizeof(struct crisv32_watch_entry
));
227 intr_mask
.bp0
= regk_marb_no
;
229 intr_mask
.bp2
= regk_marb_no
;
231 intr_mask
.bp2
= regk_marb_no
;
233 intr_mask
.bp3
= regk_marb_no
;
235 REG_WR(marb
, regi_marb
, rw_intr_mask
, intr_mask
);
237 spin_unlock(&arbiter_lock
);
241 extern void show_registers(struct pt_regs
*regs
);
244 crisv32_arbiter_irq(int irq
, void* dev_id
, struct pt_regs
* regs
)
246 reg_marb_r_masked_intr masked_intr
= REG_RD(marb
, regi_marb
, r_masked_intr
);
247 reg_marb_bp_r_brk_clients r_clients
;
248 reg_marb_bp_r_brk_addr r_addr
;
249 reg_marb_bp_r_brk_op r_op
;
250 reg_marb_bp_r_brk_first_client r_first
;
251 reg_marb_bp_r_brk_size r_size
;
252 reg_marb_bp_rw_ack ack
= {0};
253 reg_marb_rw_ack_intr ack_intr
= {.bp0
=1,.bp1
=1,.bp2
=1,.bp3
=1};
254 struct crisv32_watch_entry
* watch
;
256 if (masked_intr
.bp0
) {
258 ack_intr
.bp0
= regk_marb_yes
;
259 } else if (masked_intr
.bp1
) {
261 ack_intr
.bp1
= regk_marb_yes
;
262 } else if (masked_intr
.bp2
) {
264 ack_intr
.bp2
= regk_marb_yes
;
265 } else if (masked_intr
.bp3
) {
267 ack_intr
.bp3
= regk_marb_yes
;
272 /* Retrieve all useful information and print it. */
273 r_clients
= REG_RD(marb_bp
, watch
->instance
, r_brk_clients
);
274 r_addr
= REG_RD(marb_bp
, watch
->instance
, r_brk_addr
);
275 r_op
= REG_RD(marb_bp
, watch
->instance
, r_brk_op
);
276 r_first
= REG_RD(marb_bp
, watch
->instance
, r_brk_first_client
);
277 r_size
= REG_RD(marb_bp
, watch
->instance
, r_brk_size
);
279 printk("Arbiter IRQ\n");
280 printk("Clients %X addr %X op %X first %X size %X\n",
281 REG_TYPE_CONV(int, reg_marb_bp_r_brk_clients
, r_clients
),
282 REG_TYPE_CONV(int, reg_marb_bp_r_brk_addr
, r_addr
),
283 REG_TYPE_CONV(int, reg_marb_bp_r_brk_op
, r_op
),
284 REG_TYPE_CONV(int, reg_marb_bp_r_brk_first_client
, r_first
),
285 REG_TYPE_CONV(int, reg_marb_bp_r_brk_size
, r_size
));
287 REG_WR(marb_bp
, watch
->instance
, rw_ack
, ack
);
288 REG_WR(marb
, regi_marb
, rw_ack_intr
, ack_intr
);
290 printk("IRQ occured at %lX\n", regs
->erp
);