arbiter.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. * Memory arbiter functions. Allocates bandwidth through the
  3. * arbiter and sets up arbiter breakpoints.
  4. *
  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.
  8. *
  9. * Copyright (c) 2004, 2005 Axis Communications AB.
  10. */
  11. #include <asm/arch/hwregs/reg_map.h>
  12. #include <asm/arch/hwregs/reg_rdwr.h>
  13. #include <asm/arch/hwregs/marb_defs.h>
  14. #include <asm/arch/arbiter.h>
  15. #include <asm/arch/hwregs/intr_vect.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/signal.h>
  18. #include <linux/errno.h>
  19. #include <linux/spinlock.h>
  20. #include <asm/io.h>
  21. struct crisv32_watch_entry
  22. {
  23. unsigned long instance;
  24. watch_callback* cb;
  25. unsigned long start;
  26. unsigned long end;
  27. int used;
  28. };
  29. #define NUMBER_OF_BP 4
  30. #define NBR_OF_CLIENTS 14
  31. #define NBR_OF_SLOTS 64
  32. #define SDRAM_BANDWIDTH 100000000 /* Some kind of expected value */
  33. #define INTMEM_BANDWIDTH 400000000
  34. #define NBR_OF_REGIONS 2
  35. static struct crisv32_watch_entry watches[NUMBER_OF_BP] =
  36. {
  37. {regi_marb_bp0},
  38. {regi_marb_bp1},
  39. {regi_marb_bp2},
  40. {regi_marb_bp3}
  41. };
  42. static int requested_slots[NBR_OF_REGIONS][NBR_OF_CLIENTS];
  43. static int active_clients[NBR_OF_REGIONS][NBR_OF_CLIENTS];
  44. static int max_bandwidth[NBR_OF_REGIONS] = {SDRAM_BANDWIDTH, INTMEM_BANDWIDTH};
  45. DEFINE_SPINLOCK(arbiter_lock);
  46. static irqreturn_t
  47. crisv32_arbiter_irq(int irq, void* dev_id, struct pt_regs* regs);
  48. static void crisv32_arbiter_config(int region)
  49. {
  50. int slot;
  51. int client;
  52. int interval = 0;
  53. int val[NBR_OF_SLOTS];
  54. for (slot = 0; slot < NBR_OF_SLOTS; slot++)
  55. val[slot] = NBR_OF_CLIENTS + 1;
  56. for (client = 0; client < NBR_OF_CLIENTS; client++)
  57. {
  58. int pos;
  59. if (!requested_slots[region][client])
  60. continue;
  61. interval = NBR_OF_SLOTS / requested_slots[region][client];
  62. pos = 0;
  63. while (pos < NBR_OF_SLOTS)
  64. {
  65. if (val[pos] != NBR_OF_CLIENTS + 1)
  66. pos++;
  67. else
  68. {
  69. val[pos] = client;
  70. pos += interval;
  71. }
  72. }
  73. }
  74. client = 0;
  75. for (slot = 0; slot < NBR_OF_SLOTS; slot++)
  76. {
  77. if (val[slot] == NBR_OF_CLIENTS + 1)
  78. {
  79. int first = client;
  80. while(!active_clients[region][client]) {
  81. client = (client + 1) % NBR_OF_CLIENTS;
  82. if (client == first)
  83. break;
  84. }
  85. val[slot] = client;
  86. client = (client + 1) % NBR_OF_CLIENTS;
  87. }
  88. if (region == EXT_REGION)
  89. REG_WR_INT_VECT(marb, regi_marb, rw_ext_slots, slot, val[slot]);
  90. else if (region == INT_REGION)
  91. REG_WR_INT_VECT(marb, regi_marb, rw_int_slots, slot, val[slot]);
  92. }
  93. }
  94. extern char _stext, _etext;
  95. static void crisv32_arbiter_init(void)
  96. {
  97. static int initialized = 0;
  98. if (initialized)
  99. return;
  100. initialized = 1;
  101. /* CPU caches are active. */
  102. active_clients[EXT_REGION][10] = active_clients[EXT_REGION][11] = 1;
  103. crisv32_arbiter_config(EXT_REGION);
  104. crisv32_arbiter_config(INT_REGION);
  105. if (request_irq(MEMARB_INTR_VECT, crisv32_arbiter_irq, IRQF_DISABLED,
  106. "arbiter", NULL))
  107. printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
  108. #ifndef CONFIG_ETRAX_KGDB
  109. /* Global watch for writes to kernel text segment. */
  110. crisv32_arbiter_watch(virt_to_phys(&_stext), &_etext - &_stext,
  111. arbiter_all_clients, arbiter_all_write, NULL);
  112. #endif
  113. }
  114. int crisv32_arbiter_allocate_bandwidth(int client, int region,
  115. unsigned long bandwidth)
  116. {
  117. int i;
  118. int total_assigned = 0;
  119. int total_clients = 0;
  120. int req;
  121. crisv32_arbiter_init();
  122. for (i = 0; i < NBR_OF_CLIENTS; i++)
  123. {
  124. total_assigned += requested_slots[region][i];
  125. total_clients += active_clients[region][i];
  126. }
  127. req = NBR_OF_SLOTS / (max_bandwidth[region] / bandwidth);
  128. if (total_assigned + total_clients + req + 1 > NBR_OF_SLOTS)
  129. return -ENOMEM;
  130. active_clients[region][client] = 1;
  131. requested_slots[region][client] = req;
  132. crisv32_arbiter_config(region);
  133. return 0;
  134. }
  135. int crisv32_arbiter_watch(unsigned long start, unsigned long size,
  136. unsigned long clients, unsigned long accesses,
  137. watch_callback* cb)
  138. {
  139. int i;
  140. crisv32_arbiter_init();
  141. if (start > 0x80000000) {
  142. printk("Arbiter: %lX doesn't look like a physical address", start);
  143. return -EFAULT;
  144. }
  145. spin_lock(&arbiter_lock);
  146. for (i = 0; i < NUMBER_OF_BP; i++) {
  147. if (!watches[i].used) {
  148. reg_marb_rw_intr_mask intr_mask = REG_RD(marb, regi_marb, rw_intr_mask);
  149. watches[i].used = 1;
  150. watches[i].start = start;
  151. watches[i].end = start + size;
  152. watches[i].cb = cb;
  153. REG_WR_INT(marb_bp, watches[i].instance, rw_first_addr, watches[i].start);
  154. REG_WR_INT(marb_bp, watches[i].instance, rw_last_addr, watches[i].end);
  155. REG_WR_INT(marb_bp, watches[i].instance, rw_op, accesses);
  156. REG_WR_INT(marb_bp, watches[i].instance, rw_clients, clients);
  157. if (i == 0)
  158. intr_mask.bp0 = regk_marb_yes;
  159. else if (i == 1)
  160. intr_mask.bp1 = regk_marb_yes;
  161. else if (i == 2)
  162. intr_mask.bp2 = regk_marb_yes;
  163. else if (i == 3)
  164. intr_mask.bp3 = regk_marb_yes;
  165. REG_WR(marb, regi_marb, rw_intr_mask, intr_mask);
  166. spin_unlock(&arbiter_lock);
  167. return i;
  168. }
  169. }
  170. spin_unlock(&arbiter_lock);
  171. return -ENOMEM;
  172. }
  173. int crisv32_arbiter_unwatch(int id)
  174. {
  175. reg_marb_rw_intr_mask intr_mask = REG_RD(marb, regi_marb, rw_intr_mask);
  176. crisv32_arbiter_init();
  177. spin_lock(&arbiter_lock);
  178. if ((id < 0) || (id >= NUMBER_OF_BP) || (!watches[id].used)) {
  179. spin_unlock(&arbiter_lock);
  180. return -EINVAL;
  181. }
  182. memset(&watches[id], 0, sizeof(struct crisv32_watch_entry));
  183. if (id == 0)
  184. intr_mask.bp0 = regk_marb_no;
  185. else if (id == 1)
  186. intr_mask.bp2 = regk_marb_no;
  187. else if (id == 2)
  188. intr_mask.bp2 = regk_marb_no;
  189. else if (id == 3)
  190. intr_mask.bp3 = regk_marb_no;
  191. REG_WR(marb, regi_marb, rw_intr_mask, intr_mask);
  192. spin_unlock(&arbiter_lock);
  193. return 0;
  194. }
  195. extern void show_registers(struct pt_regs *regs);
  196. static irqreturn_t
  197. crisv32_arbiter_irq(int irq, void* dev_id, struct pt_regs* regs)
  198. {
  199. reg_marb_r_masked_intr masked_intr = REG_RD(marb, regi_marb, r_masked_intr);
  200. reg_marb_bp_r_brk_clients r_clients;
  201. reg_marb_bp_r_brk_addr r_addr;
  202. reg_marb_bp_r_brk_op r_op;
  203. reg_marb_bp_r_brk_first_client r_first;
  204. reg_marb_bp_r_brk_size r_size;
  205. reg_marb_bp_rw_ack ack = {0};
  206. reg_marb_rw_ack_intr ack_intr = {.bp0=1,.bp1=1,.bp2=1,.bp3=1};
  207. struct crisv32_watch_entry* watch;
  208. if (masked_intr.bp0) {
  209. watch = &watches[0];
  210. ack_intr.bp0 = regk_marb_yes;
  211. } else if (masked_intr.bp1) {
  212. watch = &watches[1];
  213. ack_intr.bp1 = regk_marb_yes;
  214. } else if (masked_intr.bp2) {
  215. watch = &watches[2];
  216. ack_intr.bp2 = regk_marb_yes;
  217. } else if (masked_intr.bp3) {
  218. watch = &watches[3];
  219. ack_intr.bp3 = regk_marb_yes;
  220. } else {
  221. return IRQ_NONE;
  222. }
  223. /* Retrieve all useful information and print it. */
  224. r_clients = REG_RD(marb_bp, watch->instance, r_brk_clients);
  225. r_addr = REG_RD(marb_bp, watch->instance, r_brk_addr);
  226. r_op = REG_RD(marb_bp, watch->instance, r_brk_op);
  227. r_first = REG_RD(marb_bp, watch->instance, r_brk_first_client);
  228. r_size = REG_RD(marb_bp, watch->instance, r_brk_size);
  229. printk("Arbiter IRQ\n");
  230. printk("Clients %X addr %X op %X first %X size %X\n",
  231. REG_TYPE_CONV(int, reg_marb_bp_r_brk_clients, r_clients),
  232. REG_TYPE_CONV(int, reg_marb_bp_r_brk_addr, r_addr),
  233. REG_TYPE_CONV(int, reg_marb_bp_r_brk_op, r_op),
  234. REG_TYPE_CONV(int, reg_marb_bp_r_brk_first_client, r_first),
  235. REG_TYPE_CONV(int, reg_marb_bp_r_brk_size, r_size));
  236. REG_WR(marb_bp, watch->instance, rw_ack, ack);
  237. REG_WR(marb, regi_marb, rw_ack_intr, ack_intr);
  238. printk("IRQ occured at %lX\n", regs->erp);
  239. if (watch->cb)
  240. watch->cb();
  241. return IRQ_HANDLED;
  242. }