Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Add PCI power management control. If the power ...



details:   https://anonhg.NetBSD.org/src/rev/6b36494251ab
branches:  trunk
changeset: 516921:6b36494251ab
user:      haya <haya%NetBSD.org@localhost>
date:      Fri Nov 02 03:32:33 2001 +0000

description:
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.

diffstat:

 sys/dev/pci/pccbb.c    |  47 +++++++++++++++++++++++++++++++++++++++++++++--
 sys/dev/pci/pccbbvar.h |   4 +++-
 2 files changed, 48 insertions(+), 3 deletions(-)

diffs (100 lines):

diff -r 458f670af839 -r 6b36494251ab sys/dev/pci/pccbb.c
--- a/sys/dev/pci/pccbb.c       Fri Nov 02 03:12:48 2001 +0000
+++ b/sys/dev/pci/pccbb.c       Fri Nov 02 03:32:33 2001 +0000
@@ -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 @@
        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 @@
 
        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 @@
        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 @@
        }
 
        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,
diff -r 458f670af839 -r 6b36494251ab sys/dev/pci/pccbbvar.h
--- a/sys/dev/pci/pccbbvar.h    Fri Nov 02 03:12:48 2001 +0000
+++ b/sys/dev/pci/pccbbvar.h    Fri Nov 02 03:32:33 2001 +0000
@@ -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 @@
        /* 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 */
 };
 
 /*



Home | Main Index | Thread Index | Old Index