Add PCI power management control. If the power state of a bridge is

not D0 at device attaching or resuming, set the bridge D0 mode.
This commit is contained in:
haya 2001-11-02 03:32:33 +00:00
parent 1226af2bc4
commit 2c903bf2c0
2 changed files with 48 additions and 3 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pccbb.c,v 1.69 2001/10/17 10:25:51 haya Exp $ */
/* $NetBSD: pccbb.c,v 1.70 2001/11/02 03:32:33 haya Exp $ */
/*
* Copyright (c) 1998, 1999 and 2000
@ -422,6 +422,7 @@ pccbbattach(parent, self, aux)
bus_addr_t sockbase;
char devinfo[256];
int flags;
int pwrmgt_offs;
sc->sc_chipset = cb_chipset(pa->pa_id, &flags);
@ -447,6 +448,22 @@ pccbbattach(parent, self, aux)
sc->sc_base_memh = 0;
/* power management: set D0 state */
sc->sc_pwrmgt_offs = 0;
if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT,
&pwrmgt_offs, 0)) {
reg = pci_conf_read(pc, pa->pa_tag, pwrmgt_offs + 4);
if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0 ||
reg & 0x100 /* PCI_PMCSR_PME_EN */) {
reg &= ~PCI_PMCSR_STATE_MASK;
reg |= PCI_PMCSR_STATE_D0;
reg &= ~(0x100 /* PCI_PMCSR_PME_EN */);
pci_conf_write(pc, pa->pa_tag, pwrmgt_offs + 4, reg);
}
sc->sc_pwrmgt_offs = pwrmgt_offs;
}
/*
* MAP socket registers and ExCA registers on memory-space
* When no valid address is set on socket base registers (on pci
@ -3253,7 +3270,7 @@ pccbb_powerhook(why, arg)
void *arg;
{
struct pccbb_softc *sc = arg;
u_int32_t reg;
pcireg_t reg;
bus_space_tag_t base_memt = sc->sc_base_memt; /* socket regs memory */
bus_space_handle_t base_memh = sc->sc_base_memh;
@ -3271,6 +3288,32 @@ pccbb_powerhook(why, arg)
}
if (why == PWR_RESUME) {
if (sc->sc_pwrmgt_offs != 0) {
reg = pci_conf_read(sc->sc_pc, sc->sc_tag,
sc->sc_pwrmgt_offs + 4);
if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0 ||
reg & 0x100) {
/* powrstate != D0 */
printf("%s going back to D0 mode\n",
sc->sc_dev.dv_xname);
reg &= ~PCI_PMCSR_STATE_MASK;
reg |= PCI_PMCSR_STATE_D0;
reg &= ~(0x100 /* PCI_PMCSR_PME_EN */);
pci_conf_write(sc->sc_pc, sc->sc_tag,
sc->sc_pwrmgt_offs + 4, reg);
pci_conf_write(sc->sc_pc, sc->sc_tag,
PCI_SOCKBASE, sc->sc_sockbase);
pci_conf_write(sc->sc_pc, sc->sc_tag,
PCI_BUSNUM, sc->sc_busnum);
pccbb_chipinit(sc);
/* setup memory and io space window for CB */
pccbb_winset(0x1000, sc, sc->sc_memt);
pccbb_winset(0x04, sc, sc->sc_iot);
}
}
if (pci_conf_read (sc->sc_pc, sc->sc_tag, PCI_SOCKBASE) == 0)
/* BIOS did not recover this register */
pci_conf_write (sc->sc_pc, sc->sc_tag,

View File

@ -1,4 +1,4 @@
/* $NetBSD: pccbbvar.h,v 1.16 2001/07/06 18:07:00 mcr Exp $ */
/* $NetBSD: pccbbvar.h,v 1.17 2001/11/02 03:32:34 haya Exp $ */
/*
* Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved.
*
@ -160,6 +160,8 @@ struct pccbb_softc {
/* interrupt handler list on the bridge */
struct pccbb_intrhand_list *sc_pil;
int sc_pil_intr_enable; /* can i call intr handler for child device? */
int sc_pwrmgt_offs; /* Offset for power management capability */
};
/*