diff options
| -rw-r--r-- | sys/dev/ata/ata-all.h | 6 | ||||
| -rw-r--r-- | sys/dev/ata/ata-pci.c | 3 | ||||
| -rw-r--r-- | sys/dev/ata/ata-sata.c | 7 | ||||
| -rw-r--r-- | sys/dev/ata/chipsets/ata-ahci.c | 14 |
4 files changed, 19 insertions, 11 deletions
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index a721d809414b..c590ea2e9678 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -148,9 +148,12 @@ /* SATA AHCI v1.0 register defines */ #define ATA_AHCI_CAP 0x00 -#define ATA_AHCI_NPMASK 0x1f +#define ATA_AHCI_CAP_NPMASK 0x0000001f +#define ATA_AHCI_CAP_PSC 0x00002000 +#define ATA_AHCI_CAP_SSC 0x00004000 #define ATA_AHCI_CAP_SPM 0x00020000 #define ATA_AHCI_CAP_CLO 0x01000000 +#define ATA_AHCI_CAP_SALP 0x04000000 #define ATA_AHCI_CAP_64BIT 0x80000000 #define ATA_AHCI_GHC 0x04 @@ -513,6 +516,7 @@ struct ata_channel { #define ATA_NO_48BIT_DMA 0x08 #define ATA_ALWAYS_DMASTAT 0x10 + int pm_level; /* power management level */ int devices; /* what is present */ #define ATA_ATA_MASTER 0x00000001 #define ATA_ATA_SLAVE 0x00000002 diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index a903da744d08..9a0af1cf55c0 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -556,6 +556,9 @@ ata_pcichannel_attach(device_t dev) ch->unit = (intptr_t)device_get_ivars(dev); + resource_int_value(device_get_name(dev), + device_get_unit(dev), "pm_level", &ch->pm_level); + if ((error = ctlr->ch_attach(dev))) return error; diff --git a/sys/dev/ata/ata-sata.c b/sys/dev/ata/ata-sata.c index 1151ca17b67f..79978a6e9cd9 100644 --- a/sys/dev/ata/ata-sata.c +++ b/sys/dev/ata/ata-sata.c @@ -60,7 +60,7 @@ ata_sata_phy_check_events(device_t dev) ATA_IDX_OUTL(ch, ATA_SERROR, error); /* if we have a connection event deal with it */ - if (error & ATA_SE_PHY_CHANGED) { + if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) { if (bootverbose) { u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS); if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) || @@ -199,9 +199,8 @@ ata_sata_phy_reset(device_t dev, int port, int quick) ata_udelay(5000); for (loop = 0; loop < 10; loop++) { if (ata_sata_scr_write(ch, port, ATA_SCONTROL, - ATA_SC_DET_IDLE | - ATA_SC_IPM_DIS_PARTIAL | - ATA_SC_IPM_DIS_SLUMBER)) + ATA_SC_DET_IDLE | ((ch->pm_level > 0) ? 0 : + ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))) return (0); ata_udelay(100); if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val)) diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c index e89acef21a30..7037f4dd5f0c 100644 --- a/sys/dev/ata/chipsets/ata-ahci.c +++ b/sys/dev/ata/chipsets/ata-ahci.c @@ -131,7 +131,7 @@ ata_ahci_chipinit(device_t dev) ctlr->ichannels = ATA_INL(ctlr->r_res2, ATA_AHCI_PI); ctlr->channels = MAX(flsl(ctlr->ichannels), - (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1); + (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_NPMASK) + 1); ctlr->reset = ata_ahci_reset; ctlr->ch_attach = ata_ahci_ch_attach; @@ -148,7 +148,7 @@ ata_ahci_chipinit(device_t dev) "AHCI Version %x%x.%x%x controller with %d ports PM %s\n", (version >> 24) & 0xff, (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff, - (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1, + (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_NPMASK) + 1, (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) ? "supported" : "not supported"); return 0; @@ -286,7 +286,9 @@ ata_ahci_ch_resume(device_t dev) /* activate the channel and power/spin up device */ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD)); + (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | + ((ch->pm_level > 1) ? ATA_AHCI_P_CMD_ALPE : 0) | + ((ch->pm_level > 2) ? ATA_AHCI_P_CMD_ASP : 0 ))); ata_ahci_start_fr(dev); ata_ahci_start(dev); @@ -818,9 +820,9 @@ ata_ahci_reset(device_t dev) ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | - ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | ATA_AHCI_P_IX_DP | - ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS | - ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)); + ((ch->pm_level == 0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) | + ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | + ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)); /* only probe for PortMultiplier if HW has support */ if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) { |
