1 /* 2 * Copyright (C) 2020, Red Hat Inc, Eric Auger <eric.auger@redhat.com> 3 * 4 * This work is licensed under the terms of the GNU LGPL, version 2. 5 */ 6 #include <asm/gic.h> 7 #include <alloc_page.h> 8 9 void its_parse_typer(void) 10 { 11 u64 typer = readq(gicv3_its_base() + GITS_TYPER); 12 struct its_typer *t = &its_data.typer; 13 14 t->ite_size = ((typer & GITS_TYPER_ITT_ENTRY_SIZE) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) + 1; 15 t->pta = typer & GITS_TYPER_PTA; 16 t->eventid_bits = ((typer & GITS_TYPER_IDBITS) >> GITS_TYPER_IDBITS_SHIFT) + 1; 17 t->deviceid_bits = ((typer & GITS_TYPER_DEVBITS) >> GITS_TYPER_DEVBITS_SHIFT) + 1; 18 19 if (typer & GITS_TYPER_CIL) 20 t->collid_bits = ((typer & GITS_TYPER_CIDBITS) >> GITS_TYPER_CIDBITS_SHIFT) + 1; 21 else 22 t->collid_bits = 16; 23 24 t->virt_lpi = typer & GITS_TYPER_VLPIS; 25 t->phys_lpi = typer & GITS_TYPER_PLPIS; 26 } 27 28 int its_baser_lookup(int type, struct its_baser *baser) 29 { 30 int i; 31 32 for (i = 0; i < GITS_BASER_NR_REGS; i++) { 33 void *reg_addr = gicv3_its_base() + GITS_BASER + i * 8; 34 u64 val = readq(reg_addr); 35 36 if (GITS_BASER_TYPE(val) == type) { 37 assert((val & GITS_BASER_PAGE_SIZE_MASK) == GITS_BASER_PAGE_SIZE_64K); 38 baser->esz = GITS_BASER_ENTRY_SIZE(val); 39 baser->indirect = val & GITS_BASER_INDIRECT; 40 baser->index = i; 41 return 0; 42 } 43 } 44 return -1; 45 } 46 47 /* 48 * Allocate the BASER table (a single page of size @baser->psz) 49 * and set the BASER valid 50 */ 51 static void its_baser_alloc_table(struct its_baser *baser, size_t size) 52 { 53 unsigned long order = get_order(size >> PAGE_SHIFT); 54 void *reg_addr = gicv3_its_base() + GITS_BASER + baser->index * 8; 55 u64 val = readq(reg_addr); 56 57 baser->table_addr = alloc_pages(order); 58 59 val |= virt_to_phys(baser->table_addr) | GITS_BASER_VALID; 60 61 writeq(val, reg_addr); 62 } 63 64 /* 65 * init_cmd_queue - Allocate the command queue and initialize 66 * CBASER, CWRITER 67 */ 68 static void its_cmd_queue_init(void) 69 { 70 unsigned long order = get_order(SZ_64K >> PAGE_SHIFT); 71 u64 cbaser; 72 73 its_data.cmd_base = alloc_pages(order); 74 75 cbaser = virt_to_phys(its_data.cmd_base) | (SZ_64K / SZ_4K - 1) | GITS_CBASER_VALID; 76 77 writeq(cbaser, its_data.base + GITS_CBASER); 78 79 its_data.cmd_write = its_data.cmd_base; 80 writeq(0, its_data.base + GITS_CWRITER); 81 } 82 83 void its_init(void) 84 { 85 if (!its_data.base) 86 return; 87 88 its_parse_typer(); 89 90 assert(!its_baser_lookup(GITS_BASER_TYPE_DEVICE, &its_data.device_baser)); 91 assert(!its_baser_lookup(GITS_BASER_TYPE_COLLECTION, &its_data.coll_baser)); 92 93 its_baser_alloc_table(&its_data.device_baser, SZ_64K); 94 its_baser_alloc_table(&its_data.coll_baser, SZ_64K); 95 96 its_cmd_queue_init(); 97 } 98 99 /* must be called after gicv3_enable_defaults */ 100 void its_enable_defaults(void) 101 { 102 int cpu; 103 104 /* Allocate LPI config and pending tables */ 105 gicv3_lpi_alloc_tables(); 106 107 for_each_online_cpu(cpu) 108 gicv3_lpi_rdist_enable(cpu); 109 110 writel(GITS_CTLR_ENABLE, its_data.base + GITS_CTLR); 111 } 112 113 struct its_device *its_create_device(u32 device_id, int nr_ites) 114 { 115 struct its_device *new; 116 unsigned long n; 117 118 assert(its_data.nr_devices < GITS_MAX_DEVICES); 119 120 new = &its_data.devices[its_data.nr_devices]; 121 122 new->device_id = device_id; 123 new->nr_ites = nr_ites; 124 125 n = (its_data.typer.ite_size * nr_ites) >> PAGE_SHIFT; 126 new->itt = alloc_pages(get_order(n)); 127 128 its_data.nr_devices++; 129 return new; 130 } 131 132 struct its_collection *its_create_collection(u16 col_id, u32 pe) 133 { 134 struct its_collection *new; 135 136 assert(its_data.nr_collections < GITS_MAX_COLLECTIONS); 137 138 new = &its_data.collections[its_data.nr_collections]; 139 140 new->col_id = col_id; 141 142 if (its_data.typer.pta) 143 new->target_address = (u64)gicv3_data.redist_base[pe]; 144 else 145 new->target_address = pe << 16; 146 147 its_data.nr_collections++; 148 return new; 149 } 150 151 struct its_device *its_get_device(u32 id) 152 { 153 int i; 154 155 for (i = 0; i < GITS_MAX_DEVICES; i++) { 156 if (its_data.devices[i].device_id == id) 157 return &its_data.devices[i]; 158 } 159 assert(0); 160 } 161 162 struct its_collection *its_get_collection(u32 id) 163 { 164 int i; 165 166 for (i = 0; i < GITS_MAX_COLLECTIONS; i++) { 167 if (its_data.collections[i].col_id == id) 168 return &its_data.collections[i]; 169 } 170 assert(0); 171 } 172