Skip to contentSkip to conversation

ahci: definition of ahci_port_standby() and ahci_port_spinup()

PATCH New zhao, forrest 1 participant 1 message Jul 20, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 2/5 ahci: definition of ahci_port_standby() and ahci_port_spinup()

Put port power management and staggered-spinup related operations during the power state transition into ahci_port_standby() and ahci_port_spinup ().

---

 drivers/scsi/ahci.c |   98 ++++++++++++++++++++++++++++++++++++++++++++
+++++++
 1 files changed, 98 insertions(+), 0 deletions(-)

9ea9213fa3b37b84727d2ab1d911a84f8e205412

drivers/scsi/ahci.c +1 -0
index 5bed7c3..f4386c5 100644
@@ -92,7 +92,9 @@ enum {
        HOST_AHCI_EN            = (1 << 31), /* AHCI enabled */
 
        /* HOST_CAP bits */
+       HOST_CAP_SSC            = (1 << 14), /* Slumber capable */
        HOST_CAP_CLO            = (1 << 24), /* Command List Override

support */
+ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing
*/

        HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA)

support */

@@ -155,6 +157,7 @@ enum {
PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
PORT_CMD_START = (1 << 0), /* Enable port DMA engine */

+ PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */

        PORT_CMD_ICC_ACTIVE     = (0x1 << 28), /* Put i/f in active
state */
        PORT_CMD_ICC_PARTIAL    = (0x2 << 28), /* Put i/f in partial
state */
        PORT_CMD_ICC_SLUMBER    = (0x6 << 28), /* Put i/f in slumber

state */
@@ -218,6 +221,8 @@ static void ahci_freeze(struct ata_port
static void ahci_thaw(struct ata_port *ap);
static void ahci_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+static int ahci_port_standby(void __iomem *port_mmio, u32 cap); +static int ahci_port_spinup(void __iomem *port_mmio, u32 cap);
static void ahci_remove_one (struct pci_dev *pdev);

static struct scsi_host_template ahci_sht = {
@@ -645,6 +650,99 @@ static void ahci_start_fis_rx(void __iom
readl(port_mmio + PORT_CMD); /* flush */
}

+static int ahci_port_standby(void __iomem *port_mmio, u32 cap) +{
+ u32 tmp, scontrol, sstatus;
+
+ tmp = readl(port_mmio + PORT_CMD);
+ /*

+        * AHCI Rev1.1 Section 5.3.2.3:
+        * Software is only allowed to program the PxCMD.FRE,
+        * PxCMD.POD, PxSCTL.DET, and PxCMD.SUD register bits
+        * when PxCMD.ST is set to '0'
+        */

+ if (tmp & PORT_CMD_START)
+ return -EBUSY;
+
+ if (cap & HOST_CAP_SSC) {
+ /*
+ * Enable transitions to slumber mode
+ */
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
+ if ((scontrol & 0x0f00) > 0x100) {
+ scontrol &= ~0xf00;
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
+ }
+ /*
+ * Put device into slumber mode
+ */

+               tmp |= PORT_CMD_ICC_SLUMBER;
+               writel(tmp, port_mmio + PORT_CMD);
+               tmp = readl(port_mmio + PORT_CMD);
+
+               /*
+                * Actually, we should wait for the device to
+                * enter slumber mode by checking
+                * sstatus & 0xf00 == 6
+                */

+ sstatus = readl(port_mmio + PORT_SCR_STAT);
+ }
+
+ /*
+ * Put device into listen mode
+ */
+ if (cap & HOST_CAP_SSS) {
+ /*
+ * first set PxSCTL.DET to 0
+ */

+               scontrol = readl(port_mmio + PORT_SCR_CTL);
+               scontrol &= ~0xf;
+               writel(scontrol, port_mmio + PORT_SCR_CTL);

+
+ /*
+ * then set PxCMD.SUD to 0
+ */

+               tmp = readl(port_mmio + PORT_CMD);
+               tmp &= ~PORT_CMD_SPIN_UP;
+               writel(tmp, port_mmio + PORT_CMD);
+               readl(port_mmio + PORT_CMD); /* flush */

+ }
+
+ return 0;
+}
+
+static int ahci_port_spinup(void __iomem *port_mmio, u32 cap) +{
+ u32 tmp;
+
+ tmp = readl(port_mmio + PORT_CMD);
+ /*

+        * AHCI Rev1.1 Section 5.3.2.3:
+        * Software is only allowed to program the PxCMD.FRE,
+        * PxCMD.POD, PxSCTL.DET, and PxCMD.SUD register bits
+        * when PxCMD.ST is set to '0'
+        */

+ if (tmp & PORT_CMD_START)
+ return -EBUSY;
+
+ /*
+ * Spin up device
+ */
+ if (cap & HOST_CAP_SSS) {

+               tmp |= PORT_CMD_SPIN_UP;
+               writel(tmp, port_mmio + PORT_CMD);
+               tmp = readl(port_mmio + PORT_CMD);
+       }
+
+       if ((tmp & PORT_CMD_ICC_MASK) != PORT_CMD_ICC_ACTIVE) {
+               tmp |= PORT_CMD_ICC_ACTIVE;
+               writel(tmp, port_mmio + PORT_CMD);
+               tmp = readl(port_mmio + PORT_CMD);

+ }
+
+ return 0;
+}
+
static unsigned int ahci_dev_classify(struct ata_port *ap)

 {
        void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
Signature · 1 line
1.2.6