Cleanup ThunderX quirk and print cache / shareability details for ITT tables

This commit is contained in:
jmcneill 2019-06-30 17:33:59 +00:00
parent 180fc3b4ec
commit af57b7fff7

View File

@ -1,4 +1,4 @@
/* $NetBSD: gicv3_its.c,v 1.20 2019/06/30 10:10:19 jmcneill Exp $ */
/* $NetBSD: gicv3_its.c,v 1.21 2019/06/30 17:33:59 jmcneill Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@ -32,7 +32,7 @@
#define _INTR_PRIVATE
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.20 2019/06/30 10:10:19 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.21 2019/06/30 17:33:59 jmcneill Exp $");
#include <sys/param.h>
#include <sys/kmem.h>
@ -61,7 +61,29 @@ __KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.20 2019/06/30 10:10:19 jmcneill Exp
*/
#define GITS_IIDR_PID_CAVIUM_THUNDERX 0xa1
#define GITS_IIDR_IMP_CAVIUM 0x34c
#define GITS_IIDR_CAVIUM_ERRATA_MASK (GITS_IIDR_Implementor|GITS_IIDR_ProductID|GITS_IIDR_Variant)
#define GITS_IIDR_CAVIUM_ERRATA_VALUE \
(__SHIFTIN(GITS_IIDR_IMP_CAVIUM, GITS_IIDR_Implementor) | \
__SHIFTIN(GITS_IIDR_PID_CAVIUM_THUNDERX, GITS_IIDR_ProductID) | \
__SHIFTIN(0, GITS_IIDR_Variant))
static const char * gits_cache_type[] = {
[GITS_Cache_DEVICE_nGnRnE] = "Device-nGnRnE",
[GITS_Cache_NORMAL_NC] = "Non-cacheable",
[GITS_Cache_NORMAL_RA_WT] = "Cacheable RA WT",
[GITS_Cache_NORMAL_RA_WB] = "Cacheable RA WB",
[GITS_Cache_NORMAL_WA_WT] = "Cacheable WA WT",
[GITS_Cache_NORMAL_WA_WB] = "Cacheable WA WB",
[GITS_Cache_NORMAL_RA_WA_WT] = "Cacheable RA WA WT",
[GITS_Cache_NORMAL_RA_WA_WB] = "Cacheable RA WA WB",
};
static const char * gits_share_type[] = {
[GITS_Shareability_NS] = "Non-shareable",
[GITS_Shareability_IS] = "Inner shareable",
[GITS_Shareability_OS] = "Outer shareable",
[3] = "(Reserved)",
};
static inline uint32_t
gits_read_4(struct gicv3_its *its, bus_size_t reg)
@ -616,35 +638,37 @@ gicv3_its_command_init(struct gicv3_softc *sc, struct gicv3_its *its)
gits_write_8(its, GITS_CWRITER, 0);
}
static void
gicv3_its_table_params(struct gicv3_softc *sc, struct gicv3_its *its,
u_int *devbits, u_int *innercache, u_int *share)
{
const uint64_t typer = gits_read_8(its, GITS_TYPER);
const uint32_t iidr = gits_read_4(its, GITS_IIDR);
/* Default values */
*devbits = __SHIFTOUT(typer, GITS_TYPER_Devbits) + 1;
*innercache = GITS_Cache_NORMAL_WA_WB;
*share = GITS_Shareability_IS;
/* Cavium ThunderX errata */
if ((iidr & GITS_IIDR_CAVIUM_ERRATA_MASK) == GITS_IIDR_CAVIUM_ERRATA_VALUE) {
*devbits = 20; /* 8Mb */
*innercache = GITS_Cache_DEVICE_nGnRnE;
aprint_normal_dev(sc->sc_dev, "Cavium ThunderX errata detected\n");
}
}
static void
gicv3_its_table_init(struct gicv3_softc *sc, struct gicv3_its *its)
{
u_int table_size, page_size, table_align;
u_int devbits, innercache, share;
const char *table_type;
uint64_t baser;
int tab;
const uint64_t typer = gits_read_8(its, GITS_TYPER);
/* devbits and innercache defaults */
u_int devbits = __SHIFTOUT(typer, GITS_TYPER_Devbits) + 1;
u_int innercache = GITS_Cache_NORMAL_WA_WB;
u_int share = GITS_Shareability_IS;
uint32_t iidr = gits_read_4(its, GITS_IIDR);
const uint32_t ctx =
__SHIFTIN(GITS_IIDR_IMP_CAVIUM, GITS_IIDR_Implementor) |
__SHIFTIN(GITS_IIDR_PID_CAVIUM_THUNDERX, GITS_IIDR_ProductID) |
__SHIFTIN(0, GITS_IIDR_Variant);
const uint32_t mask =
GITS_IIDR_Implementor |
GITS_IIDR_ProductID |
GITS_IIDR_Variant;
if ((iidr & mask) == ctx) {
devbits = 20; /* 8Mb */
innercache = GITS_Cache_DEVICE_nGnRnE;
aprint_normal_dev(sc->sc_dev, "Cavium ThunderX errata detected\n");
}
gicv3_its_table_params(sc, its, &devbits, &innercache, &share);
for (tab = 0; tab < 8; tab++) {
baser = gits_read_8(its, GITS_BASERn(tab));
@ -673,12 +697,14 @@ gicv3_its_table_init(struct gicv3_softc *sc, struct gicv3_its *its)
* Table size scales with the width of the DeviceID.
*/
table_size = roundup(entry_size * (1 << devbits), page_size);
table_type = "Devices";
break;
case GITS_Type_InterruptCollections:
/*
* Allocate space for one interrupt collection per CPU.
*/
table_size = roundup(entry_size * MAXCPUS, page_size);
table_type = "Collections";
break;
default:
table_size = 0;
@ -688,7 +714,6 @@ gicv3_its_table_init(struct gicv3_softc *sc, struct gicv3_its *its)
if (table_size == 0)
continue;
aprint_normal_dev(sc->sc_dev, "ITS TT%u type %#x size %#x\n", tab, (u_int)__SHIFTOUT(baser, GITS_BASER_Type), table_size);
gicv3_dma_alloc(sc, &its->its_tab[tab], table_size, table_align);
baser &= ~GITS_BASER_Size;
@ -710,6 +735,12 @@ gicv3_its_table_init(struct gicv3_softc *sc, struct gicv3_its *its)
gits_write_8(its, GITS_BASERn(tab), baser);
}
baser = gits_read_8(its, GITS_BASERn(tab));
aprint_normal_dev(sc->sc_dev, "ITS [#%d] %s table @ %#lx/%#x, %s, %s\n",
tab, table_type, its->its_tab[tab].segs[0].ds_addr, table_size,
gits_cache_type[__SHIFTOUT(baser, GITS_BASER_InnerCache)],
gits_share_type[__SHIFTOUT(baser, GITS_BASER_Shareability)]);
}
}