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