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:
parent
dea368bc5e
commit
964bf2f902
@ -477,6 +477,7 @@ hpet_attach(device_t dev)
|
|||||||
struct make_dev_args mda;
|
struct make_dev_args mda;
|
||||||
int i, j, num_msi, num_timers, num_percpu_et, num_percpu_t, cur_cpu;
|
int i, j, num_msi, num_timers, num_percpu_et, num_percpu_t, cur_cpu;
|
||||||
int pcpu_master, error;
|
int pcpu_master, error;
|
||||||
|
rman_res_t hpet_region_size;
|
||||||
static int maxhpetet = 0;
|
static int maxhpetet = 0;
|
||||||
uint32_t val, val2, cvectors, dvectors;
|
uint32_t val, val2, cvectors, dvectors;
|
||||||
uint16_t vendor, rev;
|
uint16_t vendor, rev;
|
||||||
@ -493,10 +494,11 @@ hpet_attach(device_t dev)
|
|||||||
if (sc->mem_res == NULL)
|
if (sc->mem_res == NULL)
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
|
|
||||||
/* Validate that we can access the whole region. */
|
hpet_region_size = rman_get_size(sc->mem_res);
|
||||||
if (rman_get_size(sc->mem_res) < HPET_MEM_WIDTH) {
|
/* 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",
|
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);
|
bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
@ -526,6 +528,18 @@ hpet_attach(device_t dev)
|
|||||||
*/
|
*/
|
||||||
if (vendor == HPET_VENDID_AMD && rev < 0x10 && num_timers > 0)
|
if (vendor == HPET_VENDID_AMD && rev < 0x10 && num_timers > 0)
|
||||||
num_timers--;
|
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;
|
sc->num_timers = num_timers;
|
||||||
if (bootverbose) {
|
if (bootverbose) {
|
||||||
device_printf(dev,
|
device_printf(dev,
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#define __ACPI_HPET_H__
|
#define __ACPI_HPET_H__
|
||||||
|
|
||||||
#define HPET_MEM_WIDTH 0x400 /* Expected memory region size */
|
#define HPET_MEM_WIDTH 0x400 /* Expected memory region size */
|
||||||
|
#define HPET_MEM_MIN_WIDTH 0x100 /* Minimum memory region size */
|
||||||
|
|
||||||
/* General registers */
|
/* General registers */
|
||||||
#define HPET_CAPABILITIES 0x0 /* General capabilities and ID */
|
#define HPET_CAPABILITIES 0x0 /* General capabilities and ID */
|
||||||
|
Loading…
Reference in New Issue
Block a user