Exemplo n.º 1
0
static int
amdsbwd_attach(device_t dev)
{
	struct amdsbwd_softc	*sc;
	int			rc;

	sc = &amdsbwd_sc;
	sc->dev = dev;

	rc = amdsbwd_attach_sb(dev, sc);
	if (rc != 0)
		goto fail;

#ifdef AMDSBWD_DEBUG
	device_printf(dev, "wd ctrl = %#04x\n", wdctrl_read(sc));
	device_printf(dev, "wd count = %#04x\n", wdcount_read(sc));
#endif

	/* Setup initial state of Watchdog Control. */
	wdctrl_write(sc, AMDSB_WD_FIRED);

	if (wdctrl_read(sc) & AMDSB_WD_DISABLE) {
		device_printf(dev, "watchdog hardware is disabled\n");
		goto fail;
	}

	wdog_register(&amdsb_wdog);

	return (0);

fail:
	amdsbwd_detach(dev);
	return (ENXIO);
}
Exemplo n.º 2
0
void
pmc_attach(struct device *parent, struct device *self, void *aux)
{
	struct pmc_softc *sc = (void *)self;
	struct ebus_attach_args *ea = aux;

	/* Use prom address if available, otherwise map it. */
	if (ea->ea_nvaddrs) {
		if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
		    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh)) {
			printf(": can't map PROM register space\n");
			return;
		}
		sc->sc_iot = ea->ea_memtag;
	} else if (ebus_bus_map(ea->ea_iotag, 0,
	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
		sc->sc_iot = ea->ea_iotag;
	} else if (ebus_bus_map(ea->ea_memtag, 0,
	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
		sc->sc_iot = ea->ea_memtag;
	} else {
		printf("%s: can't map register space\n", self->dv_xname);
		return;
	}

	printf("\n");

	wdog_register(sc, pmc_wdog_cb);
}
Exemplo n.º 3
0
Arquivo: wdt.c Projeto: bluhm/sys
void
wdt_attach(struct device *parent, struct device *self, void *aux)
{
	struct wdt_softc *wdt = (struct wdt_softc *)self;
	struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
	bus_size_t iosize;

	/* retrieve the I/O region (BAR2) */
	if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_IO, 0,
	    &wdt->sc_iot, &wdt->sc_ioh, NULL, &iosize, 0) != 0) {
		printf("%s: couldn't find PCI I/O region\n",
		    wdt->sc_dev.dv_xname);
		return;
	}

	/* sanity check I/O size */
	if (iosize != (bus_size_t)16) {
		printf("%s: invalid I/O region size\n",
		    wdt->sc_dev.dv_xname);
		return;
	}

	/* initialize the watchdog timer structure */

	/* check the feature set available */
	if (wdt_is501(wdt))
		wdt->sc_features = 1;
	else
		wdt->sc_features = 0;

	if (wdt->sc_features) {
		/*
		 * turn off the buzzer, it may have been activated
		 * by a previous timeout
		 */
		wdt_buzzer_off(wdt);

		wdt_buzzer_enable(wdt);
	}

	/* initialize the timer modes and the lower 16-bit counter */
	wdt_init_timer(wdt);

	/*
	 * ensure that the watchdog is disabled
	 */
	wdt_timer_disable(wdt);

	/*
	 * register with the watchdog framework
	 */
	wdog_register(wdt_set_timeout, wdt);
}
Exemplo n.º 4
0
void
viasio_wdg_init(struct viasio_softc *sc)
{
	u_int8_t reg0, reg1;
	u_int16_t iobase;

	printf(" WDG");

	/* Select WDG logical device */
	viasio_conf_write(sc->sc_iot, sc->sc_ioh, VT1211_LDN, VT1211_LDN_WDG);

	/*
	 * Check if logical device is activated by firmware.  If not
	 * try to activate it only if requested.
	 */
	reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ACT);
	DPRINTF((": ACT 0x%02x", reg0));
	if ((reg0 & VT1211_WDG_ACT_EN) == 0) {
		if ((sc->sc_dev.dv_cfdata->cf_flags &
		    VIASIO_CFFLAGS_WDG_ENABLE) != 0) {
			reg0 |= VT1211_WDG_ACT_EN;
			viasio_conf_write(sc->sc_iot, sc->sc_ioh,
			    VT1211_WDG_ACT, reg0);
			reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh,
			    VT1211_WDG_ACT);
			DPRINTF((", new ACT 0x%02x", reg0));
			if ((reg0 & VT1211_WDG_ACT_EN) == 0) {
				printf(": failed to activate");
				return;
			}
		} else {
			printf(": not activated");
			return;
		}
	}

	/* Read WDG I/O space address */
	reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ADDR_LSB);
	reg1 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ADDR_MSB);
	iobase = (reg1 << 8) | reg0;
	DPRINTF((", addr 0x%04x", iobase));

	/* Map WDG I/O space */
	if (bus_space_map(sc->sc_iot, iobase, VT1211_WDG_IOSIZE, 0,
	    &sc->sc_wdg_ioh)) {
		printf(": can't map I/O space");
		return;
	}

	/* Register new watchdog */
	wdog_register(sc, viasio_wdg_cb);
}
Exemplo n.º 5
0
void
geodesc_attach(struct device *parent, struct device *self, void *aux)
{
	struct geodesc_softc *sc = (void *) self;
	struct pci_attach_args *pa = aux;
	uint16_t cnfg, cba;
	uint8_t sts, rev, iid;
	pcireg_t reg;
	extern void (*cpuresetfn)(void);

	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, SC1100_F5_SCRATCHPAD);
	sc->sc_iot = pa->pa_iot;
	if (reg == 0 ||
	    bus_space_map(sc->sc_iot, reg, 64, 0, &sc->sc_ioh)) {
		printf(": unable to map registers at 0x%x\n", reg);
		return;
	}
	cba = bus_space_read_2(sc->sc_iot, sc->sc_ioh, GCB_CBA);
	if (cba != reg) {
		printf(": cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg);
		bus_space_unmap(sc->sc_iot, sc->sc_ioh, 64);
		return;
	}
	sts = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_WDSTS);
	cnfg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, GCB_WDCNFG);
	iid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_IID);
	rev = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_REV);

	printf(": iid %d revision %d wdstatus %b\n", iid, rev, sts, WDSTSBITS);

#ifndef SMALL_KERNEL
	/* setup and register watchdog */
	bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDTO, 0);
	sts |= WDOVF_CLEAR;
	bus_space_write_1(sc->sc_iot, sc->sc_ioh, GCB_WDSTS, sts);
	cnfg &= ~WDCNFG_MASK;
	cnfg |= WDTYPE1_RESET|WDPRES_DIV_512;
	bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDCNFG, cnfg);

	wdog_register(sc, geodesc_wdogctl_cb);
#endif /* SMALL_KERNEL */

#ifdef __HAVE_TIMECOUNTER
	bus_space_write_4(sc->sc_iot, sc->sc_ioh, GCB_TSCNFG, TSC_ENABLE);
	/* Hook into the kern_tc */
	geodesc_timecounter.tc_priv = sc;
	tc_init(&geodesc_timecounter);
#endif /* __HAVE_TIMECOUNTER */

	/* We have a special way to reset the CPU on the SC1100 */
	cpuresetfn = sc1100_sysreset;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
void
pwdog_attach(struct device *parent, struct device *self, void *aux)
{
    struct pwdog_softc *pwdog = (struct pwdog_softc *)self;
    struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
    pcireg_t memtype;
    bus_size_t iosize;

    memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
    if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &pwdog->iot,
                       &pwdog->ioh, NULL, &iosize, 0)) {
        printf("\n%s: PCI %s region not found\n",
               pwdog->pwdog_dev.dv_xname,
               memtype == PCI_MAPREG_TYPE_IO ? "I/O" : "memory");
        return;
    }
    printf("\n");
    bus_space_write_1(pwdog->iot, pwdog->ioh, PWDOG_DISABLE, 0);
    wdog_register(pwdog_set_timeout, pwdog);
}
Exemplo n.º 8
0
void
schsio_wdt_init(struct schsio_softc *sc)
{
	u_int8_t reg;

	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_GPIO);
	if ((reg & SCHSIO_WDT_GPIO_MASK) != SCHSIO_WDT_GPIO_OUT) {
		if (sc->sc_dev.dv_cfdata->cf_flags & SCHSIO_CFFLAGS_WDTEN) {
			reg &= ~0x0f;
			reg |= SCHSIO_WDT_GPIO_OUT;
			bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr,
			    SCHSIO_WDT_GPIO, reg);
		}
		else {
			printf(", watchdog disabled");
			return;
		}
	}

	/* First of all, make sure the wdt is disabled */
	bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, 0);

	/* Clear triggered status */
	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CTRL);
	if (reg & SCHSIO_WDT_CTRL_TRIGGERED) {
		printf(", warning: watchdog triggered");
		reg &= ~SCHSIO_WDT_CTRL_TRIGGERED;
		bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr,
		    SCHSIO_WDT_CTRL, reg);
	}

	/* Disable wdt reset by mouse and kbd */
	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG);
	reg &= ~(SCHSIO_WDT_CFG_MSEN | SCHSIO_WDT_CFG_MSEN);
	bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG, reg);

	wdog_register(schsio_wdt_cb, sc);
}
Exemplo n.º 9
0
void
berkwdt_attach(struct device *parent, struct device *self, void *aux)
{
	struct berkwdt_softc *sc = (struct berkwdt_softc *)self;
	struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
	bus_size_t iosize;
	u_int8_t reg;

	/* retrieve the I/O region (BAR 0) */
	if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0,
	    &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0) != 0) {
		printf(": couldn't find PCI I/O region\n");
		return;
	}

	/* Check for reboot by the card */
	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, PCWD_PCI_CS1);
	if (reg & WD_PCI_WTRP) {
		printf(", warning: watchdog triggered");

		if (reg & WD_PCI_TTRP)
			printf(", overheat detected");

		/* clear trip status & LED and keep mode of relay 2 */
		reg &= WD_PCI_R2DS;
		reg |= WD_PCI_WTRP;
		bus_space_write_1(sc->sc_iot, sc->sc_ioh, PCWD_PCI_CS1, reg);
	}

	printf("\n");

	/* ensure that the watchdog is disabled */
	berkwdt_stop(sc);
	sc->sc_period = 0;

	/* register with the watchdog framework */
	wdog_register(berkwdt_set_timeout, sc);
}
Exemplo n.º 10
0
void
bcmpm_attach(struct device *parent, struct device *self, void *args)
{
	struct bcmpm_softc *sc = (struct bcmpm_softc *)self;
	struct armv7_attach_args *aa = args;
	struct fdt_memory mem;

	sc->sc_iot = aa->aa_iot;
	if (fdt_get_memory_address(aa->aa_node, 0, &mem))
		panic("%s: could not extract memory data from FDT",
		    __func__);

	if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh))
		panic("%s: bus_space_map failed!", __func__);

	printf("\n");

	bcmpm_sc = sc;

	extern void (*fdt_platform_watchdog_reset_fn)(void);
	fdt_platform_watchdog_reset_fn = bcmpm_wdog_reset;

	wdog_register(bcmpm_wdog_cb, sc);
}
Exemplo n.º 11
0
void
tcpcib_attach(struct device *parent, struct device *self, void *aux)
{
	struct tcpcib_softc *sc = (struct tcpcib_softc *)self;
	struct pci_attach_args *pa = aux;
	struct timecounter *tc = &sc->sc_hpet_timecounter;
	u_int32_t reg, wdtbase;

	sc->sc_active = 0;

	/* High Precision Event Timer */
	sc->sc_hpet_iot = pa->pa_memt;
	if (bus_space_map(sc->sc_hpet_iot, E600_HPET_BASE, E600_HPET_SIZE, 0,
	    &sc->sc_hpet_ioh) == 0) {
		tc->tc_get_timecount = tcpcib_hpet_get_timecount;
		/* XXX 64-bit counter is not supported! */
		tc->tc_counter_mask = 0xffffffff;

		reg = bus_space_read_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
		    E600_HPET_PERIOD);
		/* femtosecs -> Hz */
		tc->tc_frequency = 1000000000000000ULL / reg;

		tc->tc_name = sc->sc_dev.dv_xname;
		tc->tc_quality = 2000;
		tc->tc_priv = sc;
		tc_init(tc);

		/* Enable counting */
		bus_space_write_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
		    E600_HPET_GC, E600_HPET_GC_ENABLE);

		sc->sc_active |= E600_HPET_ACTIVE;

		printf(": %llu Hz timer", tc->tc_frequency);
	}

	/* Map Watchdog I/O space */
	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, E600_LPC_WDTBA);
	wdtbase = reg & 0xffff;
	sc->sc_wdt_iot = pa->pa_iot;
	if (reg & (1U << 31) && wdtbase) {
		if (PCI_MAPREG_IO_ADDR(wdtbase) == 0 ||
		    bus_space_map(sc->sc_wdt_iot, PCI_MAPREG_IO_ADDR(wdtbase),
		    E600_WDT_SIZE, 0, &sc->sc_wdt_ioh)) {
			printf("%c can't map watchdog I/O space",
			    sc->sc_active ? ',' : ':');
			goto corepcib;
		}
		printf("%c watchdog", sc->sc_active ? ',' : ':');

		/* Check for reboot on timeout */
		reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh,
		    E600_WDT_RR1);
		if (reg & E600_WDT_RR1_TIMEOUT) {
			printf(", reboot on timeout");

			/* Clear timeout bit */
			tcpcib_wdt_unlock(sc);
			bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh,
			    E600_WDT_RR1, E600_WDT_RR1_TIMEOUT);
		}

		/* Check it's not locked already */
		reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh,
		    E600_WDT_WDTLR);
		if (reg & E600_WDT_WDTLR_LOCK) {
			printf(", locked");
			goto corepcib;
		}

		/* Disable watchdog */
		tcpcib_wdt_stop(sc);
		sc->sc_wdt_period = 0;

		sc->sc_active |= E600_WDT_ACTIVE;

		/* Register new watchdog */
		wdog_register(tcpcib_wdt_cb, sc);
	}

corepcib:
	/* Provide core pcib(4) functionality */
	pcibattach(parent, self, aux);
}
Exemplo n.º 12
0
void
glxpcib_attach(struct device *parent, struct device *self, void *aux)
{
	struct glxpcib_softc *sc = (struct glxpcib_softc *)self;
	struct timecounter *tc = &sc->sc_timecounter;
#ifndef SMALL_KERNEL
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	u_int64_t wa;
#if NGPIO > 0
	u_int64_t ga;
	struct gpiobus_attach_args gba;
	int i, gpio = 0;
#endif
	u_int64_t sa;
	struct i2cbus_attach_args iba;
	int i2c = 0;
	bus_space_handle_t tmpioh;
#endif
	tc->tc_get_timecount = glxpcib_get_timecount;
	tc->tc_counter_mask = 0xffffffff;
	tc->tc_frequency = 3579545;
	tc->tc_name = "CS5536";
	tc->tc_quality = 1000;
	tc->tc_priv = sc;
	tc_init(tc);

	printf(": rev %d, 32-bit %lluHz timer",
	    (int)rdmsr(AMD5536_REV) & AMD5536_REV_MASK,
	    tc->tc_frequency);

#ifndef SMALL_KERNEL
	/* Attach the watchdog timer */
	sc->sc_iot = pa->pa_iot;
	wa = rdmsr(MSR_LBAR_MFGPT);
	if (wa & MSR_LBAR_ENABLE &&
	    !bus_space_map(sc->sc_iot, wa & MSR_MFGPT_ADDR_MASK,
	    MSR_MFGPT_SIZE, 0, &sc->sc_ioh)) {
		/* count in seconds (as upper level desires) */
		bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_SETUP,
		    AMD5536_MFGPT_CNT_EN | AMD5536_MFGPT_CMP2EV |
		    AMD5536_MFGPT_CMP2 | AMD5536_MFGPT_DIV_MASK |
		    AMD5536_MFGPT_STOP_EN);
		wdog_register(glxpcib_wdogctl_cb, sc);
		sc->sc_wdog = 1;
		printf(", watchdog");
	}

#if NGPIO > 0
	/* map GPIO I/O space */
	sc->sc_gpio_iot = pa->pa_iot;
	ga = rdmsr(MSR_LBAR_GPIO);
	if (ga & MSR_LBAR_ENABLE &&
	    !bus_space_map(sc->sc_gpio_iot, ga & MSR_GPIO_ADDR_MASK,
	    MSR_GPIO_SIZE, 0, &sc->sc_gpio_ioh)) {
		printf(", gpio");

		/* initialize pin array */
		for (i = 0; i < AMD5536_GPIO_NPINS; i++) {
			sc->sc_gpio_pins[i].pin_num = i;
			sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
			    GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN |
			    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN |
			    GPIO_PIN_INVIN | GPIO_PIN_INVOUT;

			/* read initial state */
			sc->sc_gpio_pins[i].pin_state =
			    glxpcib_gpio_pin_read(sc, i);
		}

		/* create controller tag */
		sc->sc_gpio_gc.gp_cookie = sc;
		sc->sc_gpio_gc.gp_pin_read = glxpcib_gpio_pin_read;
		sc->sc_gpio_gc.gp_pin_write = glxpcib_gpio_pin_write;
		sc->sc_gpio_gc.gp_pin_ctl = glxpcib_gpio_pin_ctl;

		gba.gba_name = "gpio";
		gba.gba_gc = &sc->sc_gpio_gc;
		gba.gba_pins = sc->sc_gpio_pins;
		gba.gba_npins = AMD5536_GPIO_NPINS;
		gpio = 1;

	}
#endif /* NGPIO */

	/* Map SMB I/O space */
	sc->sc_smb_iot = pa->pa_iot;
	sa = rdmsr(MSR_LBAR_SMB);
	if (sa & MSR_LBAR_ENABLE &&
	    !bus_space_map(sc->sc_smb_iot, sa & MSR_SMB_ADDR_MASK,
	    MSR_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
		printf(", i2c");

		/* Enable controller */
		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
		    AMD5536_SMB_CTL2, AMD5536_SMB_CTL2_EN |
		    AMD5536_SMB_CTL2_FREQ);

		/* Disable interrupts */
		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
		    AMD5536_SMB_CTL1, 0);

		/* Disable slave address */
		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
		    AMD5536_SMB_ADDR, 0);

		/* Stall the bus after start */
		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
		    AMD5536_SMB_CTL1, AMD5536_SMB_CTL1_STASTRE);

		/* Attach I2C framework */
		sc->sc_smb_ic.ic_cookie = sc;
		sc->sc_smb_ic.ic_acquire_bus = glxpcib_smb_acquire_bus;
		sc->sc_smb_ic.ic_release_bus = glxpcib_smb_release_bus;
		sc->sc_smb_ic.ic_send_start = glxpcib_smb_send_start;
		sc->sc_smb_ic.ic_send_stop = glxpcib_smb_send_stop;
		sc->sc_smb_ic.ic_initiate_xfer = glxpcib_smb_initiate_xfer;
		sc->sc_smb_ic.ic_read_byte = glxpcib_smb_read_byte;
		sc->sc_smb_ic.ic_write_byte = glxpcib_smb_write_byte;

		rw_init(&sc->sc_smb_lck, "iiclk");

		bzero(&iba, sizeof(iba));
		iba.iba_name = "iic";
		iba.iba_tag = &sc->sc_smb_ic;
		i2c = 1;
	}

	/* Map PMS I/O space and enable the ``Power Immediate'' feature */
	sa = rdmsr(MSR_LBAR_PMS);
	if (sa & MSR_LBAR_ENABLE &&
	    !bus_space_map(pa->pa_iot, sa & MSR_PMS_ADDR_MASK,
	    MSR_PMS_SIZE, 0, &tmpioh)) {
		bus_space_write_4(pa->pa_iot, tmpioh, AMD5536_PMS_SSC,
		    AMD5536_PMS_SSC_SET_PI);
		bus_space_barrier(pa->pa_iot, tmpioh, AMD5536_PMS_SSC, 4,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
		bus_space_unmap(pa->pa_iot, tmpioh, MSR_PMS_SIZE);
	}
#endif /* SMALL_KERNEL */
	pcibattach(parent, self, aux);

#ifndef SMALL_KERNEL
#if NGPIO > 0
	if (gpio)
		config_found(&sc->sc_dev, &gba, gpiobus_print);
#endif
	if (i2c)
		config_found(&sc->sc_dev, &iba, iicbus_print);

	config_search(glxpcib_search, self, pa);
#endif
}
Exemplo n.º 13
0
void
imc_attach(struct device *parent, struct device *self, void *aux)
{
	struct imc_attach_args iaa;
#if NEISA > 0
	struct eisabus_attach_args eba;
#endif
	uint32_t reg, lastreg;
	uint32_t id, rev;
	int have_eisa;

	id = imc_read(IMC_SYSID);
	rev = id & IMC_SYSID_REVMASK;

	/* EISA exists on Indigo2 only */
	if (sys_config.system_type != SGI_IP20 &&
	    sys_config.system_subtype == IP22_INDIGO2)
		have_eisa = (id & IMC_SYSID_HAVEISA) != 0;
	else
		have_eisa = 0;

	printf(": revision %d\n", rev);

	/* Clear CPU/GIO error status registers to clear any leftover bits. */
	imc_bus_reset();

	/* Disable watchdog if leftover from previous reboot */
	imc_watchdog_cb(self, 0);

	/* Hook the bus error handler into the ISR */
	set_intr(INTPRI_BUSERR, CR_INT_4, imc_bus_error);

	/*
	 * Enable parity reporting on GIO/main memory transactions, except
	 * on systems with the ECC memory controller, where enabling parity
	 * interferes with regular operation and causes sticky false errors.
	 *
	 * Disable parity checking on CPU bus transactions (as turning
	 * it on seems to cause spurious bus errors), but enable parity
	 * checking on CPU reads from main memory (note that this bit
	 * has the opposite sense... Turning it on turns the checks off!).
	 *
	 * Finally, turn on interrupt writes to the CPU from the MC.
	 */
	reg = imc_read(IMC_CPUCTRL0);
	if (ip22_ecc)
		reg &= ~(IMC_CPUCTRL0_GPR | IMC_CPUCTRL0_MPR);
	else
		reg |= IMC_CPUCTRL0_GPR | IMC_CPUCTRL0_MPR;
	reg &= ~IMC_CPUCTRL0_NCHKMEMPAR;
	reg |= IMC_CPUCTRL0_INTENA;
	imc_write(IMC_CPUCTRL0, reg);

	/* Setup the MC write buffer depth */
	/*
	 * XXX This hardcoded value is not documented anywhere, and can be
	 * XXX traced back to DaveM's internship at SGI in 1996, so it can
	 * XXX be considered correct at least for IP24 (and, to a lesser
	 * XXX extent, IP22). IP20 and IP28 systems seem to run happy with
	 * XXX this value as well.
	 */
	reg = imc_read(IMC_CPUCTRL1);
	reg = (reg & ~IMC_CPUCTRL1_MCHWMSK) | 13;

	/*
	 * Force endianness on the onboard HPC and both slots.
	 * This should be safe for Fullhouse, but leave it conditional
	 * for now.
	 */
	switch (sys_config.system_type) {
	case SGI_IP22:
		if (sys_config.system_subtype == IP22_INDIGO2)
			break;
		/* FALLTHROUGH */
	case SGI_IP20:
		reg |= IMC_CPUCTRL1_HPCFX;
		reg |= IMC_CPUCTRL1_EXP0FX;
		reg |= IMC_CPUCTRL1_EXP1FX;
		reg &= ~IMC_CPUCTRL1_HPCLITTLE;
		reg &= ~IMC_CPUCTRL1_EXP0LITTLE;
		reg &= ~IMC_CPUCTRL1_EXP1LITTLE;
		break;
	}
	imc_write(IMC_CPUCTRL1, reg);

	/*
	 * Try and read the GIO64 arbitrator configuration register value.
	 * See comments above the declaration of imc_arb_value for why we
	 * are doing this.
	 */
	reg = 0; lastreg = ~reg;
	while (reg != lastreg || (reg & ~0xffff) != 0) {
		lastreg = reg;
		reg = imc_read(IMC_GIO64ARB);
		/* read another harmless register */
		(void)imc_read(IMC_CPUCTRL0);
	}

	/*
	 * Set GIO64 arbitrator configuration register:
	 *
	 * Preserve PROM-set graphics-related bits, as they seem to depend
	 * on the graphics variant present and I'm not sure how to figure
	 * that out or 100% sure what the correct settings are for each.
	 */
	reg &= (IMC_GIO64ARB_GRX64 | IMC_GIO64ARB_GRXRT | IMC_GIO64ARB_GRXMST);

	/*
	 * Rest of settings are machine/board dependent
	 */
	switch (sys_config.system_type) {
	case SGI_IP20:
		reg |= IMC_GIO64ARB_ONEGIO;
		reg |= IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1RT;
		reg |= IMC_GIO64ARB_EXP0MST | IMC_GIO64ARB_EXP1MST;
		reg &= ~(IMC_GIO64ARB_HPC64 |
		     IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EISA64 |
		     IMC_GIO64ARB_EXP064 | IMC_GIO64ARB_EXP164 |
		     IMC_GIO64ARB_EXP0PIPE | IMC_GIO64ARB_EXP1PIPE);
		break;
	default:
		/*
		 * GIO64 invariant for all IP22 platforms: one GIO bus,
		 * HPC1 @ 64
		 */
		reg |= IMC_GIO64ARB_ONEGIO | IMC_GIO64ARB_HPC64;

		switch (sys_config.system_subtype) {
		default:
		case IP22_INDY:
		case IP22_CHALLS:
			/* XXX is MST mutually exclusive? */
			reg |= IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1RT;
			reg |= IMC_GIO64ARB_EXP0MST | IMC_GIO64ARB_EXP1MST;

			/* EISA (VINO, really) can bus-master, is 64-bit */
			reg |= IMC_GIO64ARB_EISAMST | IMC_GIO64ARB_EISA64;
			break;

		case IP22_INDIGO2:
			/*
			 * All Fullhouse boards have a 64-bit HPC2 and pipelined
			 * EXP0 slot.
			 */
			reg |= IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EXP0PIPE;

			/*
			 * The EISA bus is the real thing, and is a 32-bit bus.
			 */
			reg &= ~IMC_GIO64ARB_EISA64;

			if (rev < 2) {
				/* EXP0 realtime, EXP1 can master */
				reg |= IMC_GIO64ARB_EXP0RT |
				    IMC_GIO64ARB_EXP1MST;
			} else {
				/* EXP1 pipelined as well, EISA masters */
				reg |= IMC_GIO64ARB_EXP1PIPE |
				    IMC_GIO64ARB_EISAMST;
			}
			break;
		}
	}

	imc_write(IMC_GIO64ARB, reg);
	imc_arb_value = reg;

	memset(&iaa, 0, sizeof(iaa));
	iaa.iaa_name = "gio";
	iaa.iaa_st = &imcbus_tag;
	iaa.iaa_dmat = &imc_bus_dma_tag;
	config_found(self, &iaa, imc_print);

#if NEISA > 0
	if (have_eisa) {
		memset(&eba, 0, sizeof(eba));
		eba.eba_busname = "eisa";
		eba.eba_iot = &imcbus_eisa_io_tag;
		eba.eba_memt = &imcbus_eisa_mem_tag;
		eba.eba_dmat = &imc_bus_dma_tag;
		eba.eba_ec = NULL;
		config_found(self, &eba, imc_print);
	}
#endif

	/* Register watchdog */
	wdog_register(imc_watchdog_cb, self);
}
Exemplo n.º 14
0
void
elansc_attach(struct device *parent, struct device *self, void *aux)
{
	struct elansc_softc *sc = (void *) self;
	struct pci_attach_args *pa = aux;
	struct gpiobus_attach_args gba;
	struct timecounter *tc;
	uint16_t rev, data;
	uint8_t ressta, cpuctl, tmr;
	int pin, reg, shift;

	sc->sc_memt = pa->pa_memt;
	if (bus_space_map(sc->sc_memt, MMCR_BASE_ADDR, NBPG, 0,
	    &sc->sc_memh) != 0) {
		printf(": unable to map registers\n");
		return;
	}

	rev = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_REVID);
	cpuctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_CPUCTL);
	ressta = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA);

	printf(": product %d stepping %d.%d, CPU clock %s, reset %b\n",
	    (rev & REVID_PRODID) >> REVID_PRODID_SHIFT,
	    (rev & REVID_MAJSTEP) >> REVID_MAJSTEP_SHIFT,
	    (rev & REVID_MINSTEP),
	    elansc_speeds[cpuctl & CPUCTL_CPU_CLK_SPD_MASK],
	    ressta, RSTBITS);

	/*
	 * Determine cause of the last reset, and issue a warning if it
	 * was due to watchdog expiry.
	 */
	if (ressta & RESSTA_WDT_RST_DET)
		printf("%s: WARNING: LAST RESET DUE TO WATCHDOG EXPIRATION!\n",
		    sc->sc_dev.dv_xname);
	bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA, ressta);

	/* Set up the watchdog registers with some defaults. */
	elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30);

	/* ...and clear it. */
	elansc_wdogctl_reset(sc);

	wdog_register(elansc_wdogctl_cb, sc);
	elansc = sc;
	cpu_setperf = elansc_setperf;
	cpu_cpuspeed = elansc_cpuspeed;
	elansc_update_cpuspeed();

	/* Initialize GPIO pins array */
	for (pin = 0; pin < ELANSC_PIO_NPINS; pin++) {
		sc->sc_gpio_pins[pin].pin_num = pin;
		sc->sc_gpio_pins[pin].pin_caps = GPIO_PIN_INPUT |
		    GPIO_PIN_OUTPUT;

		/* Read initial state */
		reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16);
		shift = pin % 16;
		data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
		if ((data & (1 << shift)) == 0)
			sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_INPUT;
		else
			sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_OUTPUT;
		if (elansc_gpio_pin_read(sc, pin) == 0)
			sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW;
		else
			sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH;
	}

	/* Create controller tag */
	sc->sc_gpio_gc.gp_cookie = sc;
	sc->sc_gpio_gc.gp_pin_read = elansc_gpio_pin_read;
	sc->sc_gpio_gc.gp_pin_write = elansc_gpio_pin_write;
	sc->sc_gpio_gc.gp_pin_ctl = elansc_gpio_pin_ctl;

	gba.gba_name = "gpio";
	gba.gba_gc = &sc->sc_gpio_gc;
	gba.gba_pins = sc->sc_gpio_pins;
	gba.gba_npins = ELANSC_PIO_NPINS;

	/* Attach GPIO framework */
	config_found(&sc->sc_dev, &gba, gpiobus_print);

	/* Disable GP1/2, clear the current count, and set the period to max */
	bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CTL,
		GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP |
		GPTMRCTL_PSC_SEL | GPTMRCTL_RTG);
	bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CNT, 0);
	bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1MAXCMPA, 0);

	bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CTL,
		GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP);
	bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CNT, 0);
	bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2MAXCMPA, 0);

	tmr = bus_space_read_1(sc->sc_memt, sc->sc_memh, SWTMRCFG);

	/* Enable GP1/2 */
	bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CTL,
		GPTMRCTL_ENB | GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP |
		GPTMRCTL_PSC_SEL | GPTMRCTL_RTG);
	bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CTL,
		GPTMRCTL_ENB | GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP);

	/* Attach timer */
	tc = &sc->sc_tc;
	tc->tc_get_timecount = elansc_tc_read;
	tc->tc_poll_pps = NULL;
	tc->tc_counter_mask = ~0;
	tc->tc_frequency = (tmr & 1) ? (33000000 / 4) : (33333333 / 4);
	tc->tc_name = sc->sc_dev.dv_xname;
	tc->tc_quality = 1000;
	tc->tc_priv = sc;
	tc_init(tc);
}