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

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
Loading
Loading
Loading
Loading
+37 −31
Original line number Original line Diff line number Diff line
@@ -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 {
	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,40 +632,46 @@ 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;
}
}


	writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
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);

	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)


	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)
		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