Commit 203ef6c4 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

ahci: implement SCR_NOTIFICATION r/w

Make ahci_scr_read/write() handle SCR_NOTIFICATION if the controller
supports it.  Also, print "sntf" in the cap line if supported.

While at it, convert eight space into a tab in ahci_print_info().
Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 274c1fde
...@@ -99,6 +99,7 @@ enum { ...@@ -99,6 +99,7 @@ enum {
HOST_CAP_SSC = (1 << 14), /* Slumber capable */ HOST_CAP_SSC = (1 << 14), /* Slumber capable */
HOST_CAP_CLO = (1 << 24), /* Command List Override support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */
HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
HOST_CAP_SNTF = (1 << 29), /* SNotification register */
HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
...@@ -113,11 +114,11 @@ enum { ...@@ -113,11 +114,11 @@ enum {
PORT_TFDATA = 0x20, /* taskfile data */ PORT_TFDATA = 0x20, /* taskfile data */
PORT_SIG = 0x24, /* device TF signature */ PORT_SIG = 0x24, /* device TF signature */
PORT_CMD_ISSUE = 0x38, /* command issue */ PORT_CMD_ISSUE = 0x38, /* command issue */
PORT_SCR = 0x28, /* SATA phy register block */
PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */ PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */
PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */ PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */
PORT_SCR_ERR = 0x30, /* SATA phy register: SError */ PORT_SCR_ERR = 0x30, /* SATA phy register: SError */
PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */ PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
/* PORT_IRQ_{STAT,MASK} bits */ /* PORT_IRQ_{STAT,MASK} bits */
PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */ PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
...@@ -631,39 +632,45 @@ static void ahci_restore_initial_config(struct ata_host *host) ...@@ -631,39 +632,45 @@ static void ahci_restore_initial_config(struct ata_host *host)
(void) readl(mmio + HOST_PORTS_IMPL); /* flush */ (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
} }
static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
{ {
unsigned int sc_reg; static const int offset[] = {
[SCR_STATUS] = PORT_SCR_STAT,
switch (sc_reg_in) { [SCR_CONTROL] = PORT_SCR_CTL,
case SCR_STATUS: sc_reg = 0; break; [SCR_ERROR] = PORT_SCR_ERR,
case SCR_CONTROL: sc_reg = 1; break; [SCR_ACTIVE] = PORT_SCR_ACT,
case SCR_ERROR: sc_reg = 2; break; [SCR_NOTIFICATION] = PORT_SCR_NTF,
case SCR_ACTIVE: sc_reg = 3; break; };
default: struct ahci_host_priv *hpriv = ap->host->private_data;
return -EINVAL;
}
*val = readl(ap->ioaddr.scr_addr + (sc_reg * 4)); if (sc_reg < ARRAY_SIZE(offset) &&
(sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
return offset[sc_reg];
return 0; return 0;
} }
static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
{ {
unsigned int sc_reg; void __iomem *port_mmio = ahci_port_base(ap);
int offset = ahci_scr_offset(ap, sc_reg);
switch (sc_reg_in) {
case SCR_STATUS: sc_reg = 0; break; if (offset) {
case SCR_CONTROL: sc_reg = 1; break; *val = readl(port_mmio + offset);
case SCR_ERROR: sc_reg = 2; break; return 0;
case SCR_ACTIVE: sc_reg = 3; break;
default:
return -EINVAL;
} }
return -EINVAL;
}
static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
{
void __iomem *port_mmio = ahci_port_base(ap);
int offset = ahci_scr_offset(ap, sc_reg);
writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); if (offset) {
writel(val, port_mmio + offset);
return 0; return 0;
}
return -EINVAL;
} }
static void ahci_start_engine(struct ata_port *ap) static void ahci_start_engine(struct ata_port *ap)
...@@ -1768,12 +1775,13 @@ static void ahci_print_info(struct ata_host *host) ...@@ -1768,12 +1775,13 @@ static void ahci_print_info(struct ata_host *host)
dev_printk(KERN_INFO, &pdev->dev, dev_printk(KERN_INFO, &pdev->dev,
"flags: " "flags: "
"%s%s%s%s%s%s" "%s%s%s%s%s%s%s"
"%s%s%s%s%s%s%s\n" "%s%s%s%s%s%s%s\n"
, ,
cap & (1 << 31) ? "64bit " : "", cap & (1 << 31) ? "64bit " : "",
cap & (1 << 30) ? "ncq " : "", cap & (1 << 30) ? "ncq " : "",
cap & (1 << 29) ? "sntf " : "",
cap & (1 << 28) ? "ilck " : "", cap & (1 << 28) ? "ilck " : "",
cap & (1 << 27) ? "stag " : "", cap & (1 << 27) ? "stag " : "",
cap & (1 << 26) ? "pm " : "", cap & (1 << 26) ? "pm " : "",
...@@ -1842,10 +1850,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1842,10 +1850,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem *port_mmio = ahci_port_base(ap); void __iomem *port_mmio = ahci_port_base(ap);
/* standard SATA port setup */ /* standard SATA port setup */
if (hpriv->port_map & (1 << i)) { if (hpriv->port_map & (1 << i))
ap->ioaddr.cmd_addr = port_mmio; ap->ioaddr.cmd_addr = port_mmio;
ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
}
/* disabled/not-implemented port */ /* disabled/not-implemented port */
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment