hpet: Allow a MMIO window smaller than 1K

Some new AMD systems provide a HPET MMIO region smaller than the 1KB
specified, and a correspondingly small number of timers.  Handle this in
the HPET driver rather than requiring a 1KB window.  This allows the
HPET driver to attach on such systems.

PR:		262638
Reviewed by:	markj
MFC after:	1 month
This commit is contained in:
John F. Carr 2022-03-19 18:51:43 -04:00 committed by Mark Johnston
parent dea368bc5e
commit 964bf2f902
2 changed files with 18 additions and 3 deletions

View File

@ -477,6 +477,7 @@ hpet_attach(device_t dev)
struct make_dev_args mda;
int i, j, num_msi, num_timers, num_percpu_et, num_percpu_t, cur_cpu;
int pcpu_master, error;
rman_res_t hpet_region_size;
static int maxhpetet = 0;
uint32_t val, val2, cvectors, dvectors;
uint16_t vendor, rev;
@ -493,10 +494,11 @@ hpet_attach(device_t dev)
if (sc->mem_res == NULL)
return (ENOMEM);
/* Validate that we can access the whole region. */
if (rman_get_size(sc->mem_res) < HPET_MEM_WIDTH) {
hpet_region_size = rman_get_size(sc->mem_res);
/* Validate that the region is big enough for the control registers. */
if (hpet_region_size < HPET_MEM_MIN_WIDTH) {
device_printf(dev, "memory region width %jd too small\n",
rman_get_size(sc->mem_res));
hpet_region_size);
bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
return (ENXIO);
}
@ -526,6 +528,18 @@ hpet_attach(device_t dev)
*/
if (vendor == HPET_VENDID_AMD && rev < 0x10 && num_timers > 0)
num_timers--;
/*
* Now validate that the region is big enough to address all counters.
*/
if (hpet_region_size < HPET_TIMER_CAP_CNF(num_timers)) {
device_printf(dev,
"memory region width %jd too small for %d timers\n",
hpet_region_size, num_timers);
hpet_disable(sc);
bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
return (ENXIO);
}
sc->num_timers = num_timers;
if (bootverbose) {
device_printf(dev,

View File

@ -30,6 +30,7 @@
#define __ACPI_HPET_H__
#define HPET_MEM_WIDTH 0x400 /* Expected memory region size */
#define HPET_MEM_MIN_WIDTH 0x100 /* Minimum memory region size */
/* General registers */
#define HPET_CAPABILITIES 0x0 /* General capabilities and ID */