1 #include <lunaix/mm/valloc.h>
2 #include <lunaix/mm/page.h>
4 #include <asm/soc/gic.h>
7 gic_its_create(struct arm_gic* gic, ptr_t regs)
11 its = valloc(sizeof(*its));
14 its->cmd_queue_ptr = gic_regptr(its->reg->base, GITS_CBASER);
15 its->table_ptr = gic_regptr(its->reg->base, GITS_BASER);
17 llist_append(&gic->its, &its->its);
18 hashtable_init(its->devmaps);
24 __pack_base_reg(struct leaflet* page, int ic, int oc)
28 reg |= GITS_BASER_VALID;
29 BITS_SET(reg, GITS_BASER_ICACHE, ic);
30 BITS_SET(reg, GITS_BASER_OCACHE, oc);
31 BITS_SET(reg, GITS_BASER_PA, leaflet_addr(page));
32 BITS_SET(reg, GITS_BASER_SIZE, 1);
33 BITS_SET(reg, GITS_BASER_SHARE, 0b01);
39 __configure_table_desc(struct gic_its* its, unsigned int off)
42 unsigned int type, sz;
44 val = its->tables->base[off];
45 type = BITS_GET(val, GITS_BASERn_TYPE);
46 sz = BITS_GET(val, GITS_BASERn_EntSz) + 1;
50 case 0b001: // DeviceID
51 its->nr_devid = PAGE_SIZE / sz;
53 case 0b100: // CollectionID
54 its->nr_cid = PAGE_SIZE / sz;
60 val = __pack_base_reg(alloc_leaflet(0), 0, 0);
61 BITS_SET(val, GITS_BASERn_TYPE, type);
62 BITS_SET(val, GITS_BASERn_EntSz, sz);
63 BITS_SET(val, GITS_BASERn_PGSZ, 0); // 4K
65 its->tables->base[off] = val;
69 __configure_one_its(struct arm_gic* gic, struct gic_its* its)
71 struct leaflet *leaflet;
72 struct gic_its_regs *reg;
74 unsigned int field_val;
77 wait_until(!(val = reg->base[GITS_CTLR]) & GITS_CTLR_QS);
78 reg->base[GITS_CTLR] = val & ~GITS_CTLR_EN;
80 val = reg->base[GITS_TYPER];
82 field_val = BITS_GET(val, GITS_TYPER_Devbits);
83 its->nr_devid = 1 << (field_val + 1);
85 field_val = BITS_GET(val, GITS_TYPER_ID_bits);
86 its->nr_evtid = 1 << (field_val + 1);
88 field_val = BITS_GET(val, GITS_TYPER_ITTe_sz);
89 its->nr_evtid = field_val + 1;
91 if (!(val & GITS_TYPER_CIL)) {
92 its->nr_cid = BITS_GET(val, GITS_TYPER_HCC);
95 field_val = BITS_GET(val, GITS_TYPER_CIDbits);
96 its->nr_cid = field_val + 1;
100 its->pta = !!(val & GITS_TYPER_PTA);
102 leaflet = alloc_leaflet_pinned(0);
103 val = __pack_base_reg(leaflet, 0, 0);
104 its->cmd_queue->base = val;
105 its->cmd_queue->wr_ptr = 0;
106 its->cmds_ptr = vmap(leaflet, KERNEL_DATA);
107 its->max_cmd = leaflet_size(leaflet) / sizeof(struct gic_its_cmd);
109 // total of 8 GITS_BASER<n> registers
110 for (int i = 0; i < 8; i++)
112 __configure_table_desc(its, i);
115 reg->base[GITS_CTLR] |= GITS_CTLR_EN;
119 __submit_itscmd(struct gic_its* its, struct gic_its_cmd* cmd)
124 reg = its->cmd_queue->wr_ptr;
126 wrp = BITS_GET(reg, GITS_CWRRD_OFF);
128 if (wrp == its->max_cmd) {
130 it is very unlikely we will submit the commands fast
131 enough to satiate the entire queue. so we just roll
132 back to front, assume the ITS always keeping up.
137 its->cmds[wrp++] = *cmd;
139 reg = BITS_SET(reg, GITS_CWRRD_OFF, wrp);
140 its->cmd_queue->wr_ptr = reg;
144 __build_mapc(struct gic_its *its, struct gic_its_cmd* cmd,
145 struct gic_rd* rd, unsigned int cid)
150 cmd->dw[2] = (1UL << 63) |
151 (__ptr(rd) & ~0xffff) |
156 __build_mapd(struct gic_its *its, struct gic_its_cmd* cmd,
157 struct leaflet *itt_page, unsigned int devid)
159 cmd->dw[0] = ((gicreg64_t)devid << 32) | 0x08;
160 cmd->dw[1] = ilog2(its->nr_evtid);
162 cmd->dw[2] = (1UL << 63) |
163 (leaflet_addr(itt_page));
167 __build_mapti(struct gic_its *its, struct gic_its_cmd* cmd,
168 unsigned int devid, unsigned int evtid,
169 unsigned int lpid, unsigned int cid)
171 cmd->dw[0] = ((gicreg64_t)devid << 32) | 0x0A;
172 cmd->dw[1] = ((gicreg64_t)evtid << 32) | evtid;
174 cmd->dw[2] = (cid & 0xffff);
178 __alloc_evtid(struct gic_its *its, unsigned int devid)
181 struct gic_its_devmap *pos, *n;
182 struct gic_its_cmd cmd;
184 hashtable_hash_foreach(its->devmaps, devid, pos, n, node)
186 if (pos->devid == devid) {
191 pos = valloc(sizeof(*pos));
194 hashtable_hash_in(its->devmaps, &pos->node, devid);
196 __build_mapd(its, &cmd, alloc_leaflet_pinned(0), devid);
197 __submit_itscmd(its, &cmd);
200 evtid = pos->next_evtid++;
202 assert(pos->next_evtid < its->nr_evtid);
208 gic_its_map_lpi(struct gic_its* its,
209 unsigned int devid, unsigned int lpid)
212 struct gic_its_cmd cmd;
214 evtid = __alloc_evtid(its, devid);
216 __build_mapti(its, &cmd, devid, evtid, lpid, 0);
217 __submit_itscmd(its, &cmd);
223 gic_configure_its(struct arm_gic* gic)
225 struct gic_its *pos, *n;
226 struct gic_its_cmd cmd;
228 llist_for_each(pos, n, &gic->its, its)
230 __configure_one_its(gic, pos);
233 // halt the cpu for a while to let ITS warming up
234 wait_until_expire(true, 10000);
236 // identity map every re-distributor to collection
237 llist_for_each(pos, n, &gic->its, its)
239 for (int i = 0; i < NR_CPU; i++)
241 __build_mapc(pos, &cmd, gic->pes[i]._rd, i);
242 __submit_itscmd(pos, &cmd);