static int geode_attach(device_t self) { u_int32_t reg; u_int16_t cnfg, cba; u_int8_t sts, rev, iid; /* * The address of the CBA is written to this register * by the bios, see p161 in data sheet. */ reg = pci_read_config(self, SC1100_F5_SCRATCHPAD, 4); if (reg == 0) return ENODEV; /* bus_space_map(sc->sc_iot, reg, 64, 0, &sc->sc_ioh)) */ geode_sc.sc_iot = I386_BUS_SPACE_IO; geode_sc.sc_ioh = reg; cba = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_CBA); if (cba != reg) { kprintf("Geode LX: cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg); return ENODEV; } /* outl(cba + 0x0d, 2); ??? */ sts = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDSTS); cnfg = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDCNFG); iid = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_IID); rev = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_REV); #define WDSTSBITS "\20\x04WDRST\x03WDSMI\x02WDINT\x01WDOVF" kprintf("Geode LX: iid %d revision %d wdstatus %b\n", iid, rev, sts, WDSTSBITS); /* enable timer */ bus_space_write_4(geode_sc.sc_iot, geode_sc.sc_iot, GCB_TSCNFG, TSC_ENABLE); cputimer_register(&geode_timer); cputimer_select(&geode_timer, 0); /* enable watchdog and configure */ bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDTO, 0); sts |= WDOVF_CLEAR; bus_space_write_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDSTS, sts); cnfg &= ~WDCNFG_MASK; cnfg |= WDTYPE1_RESET | WDPRES_DIV_512; bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDCNFG, cnfg); wdog_register(&geode_wdog); return 0; }
static int acpi_timer_attach(device_t dev) { char desc[40]; int i, j; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); /* * If all tests of the counter succeed, use the ACPI-fast method. If * at least one failed, default to using the safe routine, which reads * the timer multiple times to get a consistent value before returning. */ j = 0; for (i = 0; i < 10; i++) j += acpi_timer_test(); if (j == 10) { if (acpi_timer_resolution == 32) { acpi_cputimer.name = "ACPI-fast"; acpi_cputimer.count = acpi_timer_get_timecount; } else { acpi_cputimer.name = "ACPI-fast24"; acpi_cputimer.count = acpi_timer_get_timecount24; } } else { if (acpi_timer_resolution == 32) acpi_cputimer.name = "ACPI-safe"; else acpi_cputimer.name = "ACPI-safe24"; acpi_cputimer.count = acpi_timer_get_timecount_safe; } ksprintf(desc, "%u-bit timer at 3.579545MHz", acpi_timer_resolution); device_set_desc_copy(dev, desc); cputimer_register(&acpi_cputimer); cputimer_select(&acpi_cputimer, 0); return (0); }
static int acpi_timer_probe(device_t dev) { char desc[40]; int i, j, rid, rtype; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); if (dev != acpi_timer_dev) return (ENXIO); rid = 0; rtype = AcpiGbl_FADT.XPmTimerBlock.SpaceId ? SYS_RES_IOPORT : SYS_RES_MEMORY; acpi_timer_reg = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE); if (acpi_timer_reg == NULL) { device_printf(dev, "couldn't allocate resource (%s 0x%lx)\n", (rtype == SYS_RES_IOPORT) ? "port" : "mem", (u_long)AcpiGbl_FADT.XPmTimerBlock.Address); return (ENXIO); } acpi_timer_bsh = rman_get_bushandle(acpi_timer_reg); acpi_timer_bst = rman_get_bustag(acpi_timer_reg); if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) != 0) acpi_counter_mask = 0xffffffff; else acpi_counter_mask = 0x00ffffff; /* * If all tests of the counter succeed, use the ACPI-fast method. If * at least one failed, default to using the safe routine, which reads * the timer multiple times to get a consistent value before returning. */ j = 0; for (i = 0; i < 10; i++) j += acpi_timer_test(); if (j == 10) { if (acpi_counter_mask == 0xffffffff) { acpi_cputimer.name = "ACPI-fast"; acpi_cputimer.count = acpi_timer_get_timecount; } else { acpi_cputimer.name = "ACPI-fast24"; acpi_cputimer.count = acpi_timer_get_timecount24; } } else { if (acpi_counter_mask == 0xffffffff) acpi_cputimer.name = "ACPI-safe"; else acpi_cputimer.name = "ACPI-safe24"; acpi_cputimer.count = acpi_timer_get_timecount_safe; } ksprintf(desc, "%d-bit timer at 3.579545MHz", (AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) ? 32 : 24); device_set_desc_copy(dev, desc); cputimer_register(&acpi_cputimer); cputimer_select(&acpi_cputimer, 0); /* Release the resource, we'll allocate it again during attach. */ bus_release_resource(dev, rtype, rid, acpi_timer_reg); return (0); }
static int acpi_hpet_attach(device_t dev) { struct acpi_hpet_softc *sc; int rid; uint32_t val, val2; uintmax_t freq; ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); sc = device_get_softc(dev); sc->dev = dev; sc->handle = acpi_get_handle(dev); rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { /* * We only need to make sure that main counter * is accessable. */ device_printf(dev, "can't map %dB register space, try %dB\n", HPET_MEM_WIDTH, HPET_MEM_WIDTH_MIN); rid = 0; sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, acpi_hpet_res_start, acpi_hpet_res_start + HPET_MEM_WIDTH_MIN - 1, HPET_MEM_WIDTH_MIN, RF_ACTIVE); 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_MIN) { device_printf(dev, "memory region width %ld too small\n", rman_get_size(sc->mem_res)); bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res); return ENXIO; } acpi_hpet_bsh = rman_get_bushandle(sc->mem_res); acpi_hpet_bst = rman_get_bustag(sc->mem_res); /* Be sure timer is enabled. */ acpi_hpet_enable(sc); /* Read basic statistics about the timer. */ val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_PERIOD); if (val == 0) { device_printf(dev, "invalid period\n"); acpi_hpet_disable(sc); bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res); return ENXIO; } freq = (1000000000000000LL + val / 2) / val; if (bootverbose) { val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_CAPABILITIES); device_printf(dev, "vend: 0x%x, rev: 0x%x, num: %d, opts:%s%s\n", val >> 16, val & HPET_CAP_REV_ID, (val & HPET_CAP_NUM_TIM) >> 8, (val & HPET_CAP_LEG_RT) ? " legacy_route" : "", (val & HPET_CAP_COUNT_SIZE) ? " 64-bit" : ""); } if (ktestenv("debug.acpi.hpet_test")) acpi_hpet_test(sc); /* * Don't attach if the timer never increments. Since the spec * requires it to be at least 10 MHz, it has to change in 1 us. */ val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_MAIN_COUNTER); DELAY(1); val2 = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_MAIN_COUNTER); if (val == val2) { device_printf(dev, "HPET never increments, disabling\n"); acpi_hpet_disable(sc); bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res); return ENXIO; } acpi_hpet_timer.freq = freq; device_printf(dev, "frequency %u\n", acpi_hpet_timer.freq); cputimer_register(&acpi_hpet_timer); cputimer_select(&acpi_hpet_timer, 0); return 0; }