1*ba74b106SEric Auger /* 2*ba74b106SEric Auger * Copyright (C) 2020, Red Hat Inc, Eric Auger <eric.auger@redhat.com> 3*ba74b106SEric Auger * 4*ba74b106SEric Auger * This work is licensed under the terms of the GNU LGPL, version 2. 5*ba74b106SEric Auger */ 6*ba74b106SEric Auger #include <asm/gic.h> 7*ba74b106SEric Auger #include <alloc_page.h> 8*ba74b106SEric Auger 9*ba74b106SEric Auger void its_parse_typer(void) 10*ba74b106SEric Auger { 11*ba74b106SEric Auger u64 typer = readq(gicv3_its_base() + GITS_TYPER); 12*ba74b106SEric Auger struct its_typer *t = &its_data.typer; 13*ba74b106SEric Auger 14*ba74b106SEric Auger t->ite_size = ((typer & GITS_TYPER_ITT_ENTRY_SIZE) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) + 1; 15*ba74b106SEric Auger t->pta = typer & GITS_TYPER_PTA; 16*ba74b106SEric Auger t->eventid_bits = ((typer & GITS_TYPER_IDBITS) >> GITS_TYPER_IDBITS_SHIFT) + 1; 17*ba74b106SEric Auger t->deviceid_bits = ((typer & GITS_TYPER_DEVBITS) >> GITS_TYPER_DEVBITS_SHIFT) + 1; 18*ba74b106SEric Auger 19*ba74b106SEric Auger if (typer & GITS_TYPER_CIL) 20*ba74b106SEric Auger t->collid_bits = ((typer & GITS_TYPER_CIDBITS) >> GITS_TYPER_CIDBITS_SHIFT) + 1; 21*ba74b106SEric Auger else 22*ba74b106SEric Auger t->collid_bits = 16; 23*ba74b106SEric Auger 24*ba74b106SEric Auger t->virt_lpi = typer & GITS_TYPER_VLPIS; 25*ba74b106SEric Auger t->phys_lpi = typer & GITS_TYPER_PLPIS; 26*ba74b106SEric Auger } 27*ba74b106SEric Auger 28*ba74b106SEric Auger int its_baser_lookup(int type, struct its_baser *baser) 29*ba74b106SEric Auger { 30*ba74b106SEric Auger int i; 31*ba74b106SEric Auger 32*ba74b106SEric Auger for (i = 0; i < GITS_BASER_NR_REGS; i++) { 33*ba74b106SEric Auger void *reg_addr = gicv3_its_base() + GITS_BASER + i * 8; 34*ba74b106SEric Auger u64 val = readq(reg_addr); 35*ba74b106SEric Auger 36*ba74b106SEric Auger if (GITS_BASER_TYPE(val) == type) { 37*ba74b106SEric Auger assert((val & GITS_BASER_PAGE_SIZE_MASK) == GITS_BASER_PAGE_SIZE_64K); 38*ba74b106SEric Auger baser->esz = GITS_BASER_ENTRY_SIZE(val); 39*ba74b106SEric Auger baser->indirect = val & GITS_BASER_INDIRECT; 40*ba74b106SEric Auger baser->index = i; 41*ba74b106SEric Auger return 0; 42*ba74b106SEric Auger } 43*ba74b106SEric Auger } 44*ba74b106SEric Auger return -1; 45*ba74b106SEric Auger } 46*ba74b106SEric Auger 47*ba74b106SEric Auger /* 48*ba74b106SEric Auger * Allocate the BASER table (a single page of size @baser->psz) 49*ba74b106SEric Auger * and set the BASER valid 50*ba74b106SEric Auger */ 51*ba74b106SEric Auger static void its_baser_alloc_table(struct its_baser *baser, size_t size) 52*ba74b106SEric Auger { 53*ba74b106SEric Auger unsigned long order = get_order(size >> PAGE_SHIFT); 54*ba74b106SEric Auger void *reg_addr = gicv3_its_base() + GITS_BASER + baser->index * 8; 55*ba74b106SEric Auger u64 val = readq(reg_addr); 56*ba74b106SEric Auger 57*ba74b106SEric Auger baser->table_addr = alloc_pages(order); 58*ba74b106SEric Auger 59*ba74b106SEric Auger val |= virt_to_phys(baser->table_addr) | GITS_BASER_VALID; 60*ba74b106SEric Auger 61*ba74b106SEric Auger writeq(val, reg_addr); 62*ba74b106SEric Auger } 63*ba74b106SEric Auger 64*ba74b106SEric Auger /* 65*ba74b106SEric Auger * init_cmd_queue - Allocate the command queue and initialize 66*ba74b106SEric Auger * CBASER, CWRITER 67*ba74b106SEric Auger */ 68*ba74b106SEric Auger static void its_cmd_queue_init(void) 69*ba74b106SEric Auger { 70*ba74b106SEric Auger unsigned long order = get_order(SZ_64K >> PAGE_SHIFT); 71*ba74b106SEric Auger u64 cbaser; 72*ba74b106SEric Auger 73*ba74b106SEric Auger its_data.cmd_base = alloc_pages(order); 74*ba74b106SEric Auger 75*ba74b106SEric Auger cbaser = virt_to_phys(its_data.cmd_base) | (SZ_64K / SZ_4K - 1) | GITS_CBASER_VALID; 76*ba74b106SEric Auger 77*ba74b106SEric Auger writeq(cbaser, its_data.base + GITS_CBASER); 78*ba74b106SEric Auger 79*ba74b106SEric Auger its_data.cmd_write = its_data.cmd_base; 80*ba74b106SEric Auger writeq(0, its_data.base + GITS_CWRITER); 81*ba74b106SEric Auger } 82*ba74b106SEric Auger 83*ba74b106SEric Auger void its_init(void) 84*ba74b106SEric Auger { 85*ba74b106SEric Auger if (!its_data.base) 86*ba74b106SEric Auger return; 87*ba74b106SEric Auger 88*ba74b106SEric Auger its_parse_typer(); 89*ba74b106SEric Auger 90*ba74b106SEric Auger assert(!its_baser_lookup(GITS_BASER_TYPE_DEVICE, &its_data.device_baser)); 91*ba74b106SEric Auger assert(!its_baser_lookup(GITS_BASER_TYPE_COLLECTION, &its_data.coll_baser)); 92*ba74b106SEric Auger 93*ba74b106SEric Auger its_baser_alloc_table(&its_data.device_baser, SZ_64K); 94*ba74b106SEric Auger its_baser_alloc_table(&its_data.coll_baser, SZ_64K); 95*ba74b106SEric Auger 96*ba74b106SEric Auger its_cmd_queue_init(); 97*ba74b106SEric Auger } 98*ba74b106SEric Auger 99