Beispiel #1
0
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;
}
Beispiel #2
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);
}
Beispiel #3
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);
}
Beispiel #4
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;
}