mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] ata/ahci work
@ 2013-03-08 10:35 Sascha Hauer
  2013-03-08 10:35 ` [PATCH 1/5] ata: ahci: fix wrong link check Sascha Hauer
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Sascha Hauer @ 2013-03-08 10:35 UTC (permalink / raw)
  To: barebox

disks need a long time to spin up, so only initialize them when
they are needed. This series adds a ata logical device and attaches
a probe parameter to it, similar to what MMC does.

Also, some refactoring of the ahci driver.

Sascha

----------------------------------------------------------------
Sascha Hauer (5):
      ata: ahci: fix wrong link check
      ata: add ata logical device to defer probe
      ata: Add init callback to ata_port_operations
      ata: ahci: implement init callback
      ata: ahci: refactor init functions

 drivers/ata/ahci.c           | 170 ++++++++++++++++++-------------------------
 drivers/ata/ahci.h           |   1 -
 drivers/ata/disk_ata_drive.c |  63 ++++++++++++++--
 include/ata_drive.h          |   3 +
 4 files changed, 129 insertions(+), 108 deletions(-)

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/5] ata: ahci: fix wrong link check
  2013-03-08 10:35 [PATCH] ata/ahci work Sascha Hauer
@ 2013-03-08 10:35 ` Sascha Hauer
  2013-03-08 10:35 ` [PATCH 2/5] ata: add ata logical device to defer probe Sascha Hauer
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2013-03-08 10:35 UTC (permalink / raw)
  To: barebox

The following commit accidently bailed out if the link is up, not
when it's down as stated in the commit message.

| commit a3f74d928ce73f37eab5b398e018aaeb42fd2ba4
| Author: Rob Herring <rob.herring@calxeda.com>
| Date:   Mon Feb 11 18:02:00 2013 +0100
|
|     ahci: handle COMINIT received during spin-up
|
|     Some Intel SSDs can send a COMINIT after the initial COMRESET. This causes
|     the link to go down and we need to re-initialize the link.
|
|     Signed-off-by: Rob Herring <rob.herring@calxeda.com>
|     Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|     Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
|

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/ata/ahci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 4d5b52a..1712006 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -387,7 +387,7 @@ static int ahci_init_port(struct ahci_port *ahci_port)
 	ret = wait_on_timeout(WAIT_SPINUP,
 			((readl(port_mmio + PORT_TFDATA) &
 			 (ATA_STATUS_BUSY | ATA_STATUS_DRQ)) == 0)
-			|| !((readl(port_mmio + PORT_SCR_STAT) & 0xf) == 1));
+			|| ((readl(port_mmio + PORT_SCR_STAT) & 0xf) == 1));
 	if (ret) {
 		ahci_port_info(ahci_port, "timeout.\n");
 		ret = -ENODEV;
-- 
1.8.2.rc2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/5] ata: add ata logical device to defer probe
  2013-03-08 10:35 [PATCH] ata/ahci work Sascha Hauer
  2013-03-08 10:35 ` [PATCH 1/5] ata: ahci: fix wrong link check Sascha Hauer
@ 2013-03-08 10:35 ` Sascha Hauer
  2013-03-08 10:35 ` [PATCH 3/5] ata: Add init callback to ata_port_operations Sascha Hauer
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2013-03-08 10:35 UTC (permalink / raw)
  To: barebox

ata device usually take a long time to spin up, so it makes sense
to only spend this time when the device is actually used.

This adds a logical ata device and attaches a 'probe' parameter
to it, similar to what MMC does.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/ata/disk_ata_drive.c | 57 +++++++++++++++++++++++++++++++++++++-------
 include/ata_drive.h          |  2 ++
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c
index 923be9a..a6deb74 100644
--- a/drivers/ata/disk_ata_drive.c
+++ b/drivers/ata/disk_ata_drive.c
@@ -255,17 +255,11 @@ static struct block_device_ops ata_ops = {
 #endif
 };
 
-/**
- * Register an ATA drive behind an IDE like interface
- * @param dev The interface device
- * @param io ATA register file description
- * @return 0 on success
- */
-int ata_port_register(struct ata_port *port)
+static int ata_port_init(struct ata_port *port)
 {
 	int rc;
 	struct ata_port_operations *ops = port->ops;
-	struct device_d *dev = port->dev;
+	struct device_d *dev = &port->class_dev;
 
 	port->id = dma_alloc(SECTOR_SIZE);
 
@@ -325,6 +319,53 @@ on_error:
 	return rc;
 }
 
+static int ata_set_probe(struct device_d *class_dev, struct param_d *param,
+				const char *val)
+{
+	struct ata_port *port = container_of(class_dev, struct ata_port, class_dev);
+	int ret, probe;
+
+	if (port->initialized) {
+		dev_info(class_dev, "already initialized\n");
+		return 0;
+	}
+
+	probe = !!simple_strtoul(val, NULL, 0);
+	if (!probe)
+		return 0;
+
+	ret = ata_port_init(port);
+	if (ret)
+		return ret;
+
+	port->initialized = 1;
+
+	return dev_param_set_generic(class_dev, param, "1");
+}
+
+/**
+ * Register an ATA drive behind an IDE like interface
+ * @param dev The interface device
+ * @param io ATA register file description
+ * @return 0 on success
+ */
+int ata_port_register(struct ata_port *port)
+{
+	int ret;
+
+	port->class_dev.id = DEVICE_ID_DYNAMIC;
+	strcpy(port->class_dev.name, "ata");
+	port->class_dev.parent = port->dev;
+
+	ret = register_device(&port->class_dev);
+	if (ret)
+		return ret;
+
+	dev_add_param(&port->class_dev, "probe", ata_set_probe, NULL, 0);
+
+	return ret;
+}
+
 /**
  * @file
  * @brief Generic ATA disk drive support
diff --git a/include/ata_drive.h b/include/ata_drive.h
index 1996321..876aa74 100644
--- a/include/ata_drive.h
+++ b/include/ata_drive.h
@@ -89,9 +89,11 @@ struct ata_port_operations {
 struct ata_port {
 	struct ata_port_operations *ops;
 	struct device_d *dev;
+	struct device_d class_dev;
 	void *drvdata;
 	struct block_device blk;
 	uint16_t *id;
+	int initialized;
 };
 
 int ide_port_register(struct device_d *, struct ata_ioports *);
-- 
1.8.2.rc2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/5] ata: Add init callback to ata_port_operations
  2013-03-08 10:35 [PATCH] ata/ahci work Sascha Hauer
  2013-03-08 10:35 ` [PATCH 1/5] ata: ahci: fix wrong link check Sascha Hauer
  2013-03-08 10:35 ` [PATCH 2/5] ata: add ata logical device to defer probe Sascha Hauer
@ 2013-03-08 10:35 ` Sascha Hauer
  2013-03-08 10:35 ` [PATCH 4/5] ata: ahci: implement init callback Sascha Hauer
  2013-03-08 10:35 ` [PATCH 5/5] ata: ahci: refactor init functions Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2013-03-08 10:35 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/ata/disk_ata_drive.c | 6 ++++++
 include/ata_drive.h          | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c
index a6deb74..6fe526a 100644
--- a/drivers/ata/disk_ata_drive.c
+++ b/drivers/ata/disk_ata_drive.c
@@ -261,6 +261,12 @@ static int ata_port_init(struct ata_port *port)
 	struct ata_port_operations *ops = port->ops;
 	struct device_d *dev = &port->class_dev;
 
+	if (ops->init) {
+		rc = ops->init(port);
+		if (rc)
+			return rc;
+	}
+
 	port->id = dma_alloc(SECTOR_SIZE);
 
 	port->blk.dev = dev;
diff --git a/include/ata_drive.h b/include/ata_drive.h
index 876aa74..4f8b6c0 100644
--- a/include/ata_drive.h
+++ b/include/ata_drive.h
@@ -80,6 +80,7 @@ struct ata_ioports {
 struct ata_port;
 
 struct ata_port_operations {
+	int (*init)(struct ata_port *port);
 	int (*read)(struct ata_port *port, void *buf, unsigned int block, int num_blocks);
 	int (*write)(struct ata_port *port, const void *buf, unsigned int block, int num_blocks);
 	int (*read_id)(struct ata_port *port, void *buf);
-- 
1.8.2.rc2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 4/5] ata: ahci: implement init callback
  2013-03-08 10:35 [PATCH] ata/ahci work Sascha Hauer
                   ` (2 preceding siblings ...)
  2013-03-08 10:35 ` [PATCH 3/5] ata: Add init callback to ata_port_operations Sascha Hauer
@ 2013-03-08 10:35 ` Sascha Hauer
  2013-03-08 10:35 ` [PATCH 5/5] ata: ahci: refactor init functions Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2013-03-08 10:35 UTC (permalink / raw)
  To: barebox

Now that we have framework support for delayed probing of
ata devices implement it in the ahci driver to actually make use
of it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/ata/ahci.c | 68 ++++++++++++++++++++++++------------------------------
 drivers/ata/ahci.h |  1 -
 2 files changed, 30 insertions(+), 39 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 1712006..46abbc2 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -275,12 +275,6 @@ static int ahci_write(struct ata_port *ata, const void *buf, unsigned int block,
 	return ahci_rw(ata, NULL, buf, block, num_blocks);
 }
 
-static struct ata_port_operations ahci_ops = {
-	.read_id = ahci_read_id,
-	.read = ahci_read,
-	.write = ahci_write,
-};
-
 static int ahci_init_port(struct ahci_port *ahci_port)
 {
 	void __iomem *port_mmio;
@@ -421,8 +415,6 @@ static int ahci_init_port(struct ahci_port *ahci_port)
 
 	ahci_port_debug(ahci_port, "status: 0x%08x\n", val);
 
-	ahci_port->ata.ops = &ahci_ops;
-
 	if ((val & 0xf) == 0x03)
 		return 0;
 
@@ -438,6 +430,33 @@ err_alloc:
 	return ret;
 }
 
+static int ahci_port_start(struct ata_port *ata_port)
+{
+	struct ahci_port *ahci_port = container_of(ata_port, struct ahci_port, ata);
+	int ret;
+
+	ret = ahci_init_port(ahci_port);
+	if (ret)
+		return ret;
+
+	if (!ahci_link_ok(ahci_port, 1))
+		return -EIO;
+
+	ahci_port_write_f(ahci_port, PORT_CMD,
+			PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
+			PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
+			PORT_CMD_START);
+
+	return 0;
+}
+
+static struct ata_port_operations ahci_ops = {
+	.init = ahci_port_start,
+	.read_id = ahci_read_id,
+	.read = ahci_read,
+	.write = ahci_write,
+};
+
 static int ahci_host_init(struct ahci_device *ahci)
 {
 	u8 *mmio = (u8 *)ahci->mmio_base;
@@ -483,9 +502,8 @@ static int ahci_host_init(struct ahci_device *ahci)
 		ahci_port->ahci = ahci;
 		ahci_port->ata.dev = ahci->dev;
 		ahci_port->port_mmio = ahci_port_base(mmio, i);
-		ret = ahci_init_port(ahci_port);
-		if (!ret)
-			ahci->link_port_map |= 1 << i;
+		ahci_port->ata.ops = &ahci_ops;
+		ata_port_register(&ahci_port->ata);
 	}
 
 	tmp = ahci_ioread(ahci, HOST_CTL);
@@ -495,25 +513,9 @@ static int ahci_host_init(struct ahci_device *ahci)
 	return 0;
 }
 
-static int ahci_port_start(struct ahci_port *ahci_port, u8 port)
-{
-	if (!ahci_link_ok(ahci_port, 1))
-		return -EIO;
-
-	ahci_port_write_f(ahci_port, PORT_CMD,
-			PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
-			PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
-			PORT_CMD_START);
-
-	ata_port_register(&ahci_port->ata);
-
-	return 0;
-}
-
 static int __ahci_host_init(struct ahci_device *ahci)
 {
-	int i, rc = 0;
-	u32 linkmap;
+	int rc = 0;
 
 	ahci->host_flags = ATA_FLAG_SATA
 				| ATA_FLAG_NO_LEGACY
@@ -528,16 +530,6 @@ static int __ahci_host_init(struct ahci_device *ahci)
 	if (rc)
 		goto err_out;
 
-	linkmap = ahci->link_port_map;
-
-	for (i = 0; i < 32; i++) {
-		if (((linkmap >> i) & 0x01)) {
-			if (ahci_port_start(&ahci->ports[i], i)) {
-				printf("Can not start port %d\n", i);
-				continue;
-			}
-		}
-	}
 err_out:
 	return rc;
 }
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 72e5c1a..6324bf5 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -169,7 +169,6 @@ struct ahci_device {
 	void __iomem		*mmio_base;
 	u32			cap;		/* cache of HOST_CAP register */
 	u32			port_map;	/* cache of HOST_PORTS_IMPL reg */
-	u32			link_port_map;	/* linkup port map */
 	u32			pio_mask;
 	u32			udma_mask;
 	u32			host_flags;
-- 
1.8.2.rc2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 5/5] ata: ahci: refactor init functions
  2013-03-08 10:35 [PATCH] ata/ahci work Sascha Hauer
                   ` (3 preceding siblings ...)
  2013-03-08 10:35 ` [PATCH 4/5] ata: ahci: implement init callback Sascha Hauer
@ 2013-03-08 10:35 ` Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2013-03-08 10:35 UTC (permalink / raw)
  To: barebox

Fold ahci_host_init and __ahci_host_init into ahci_add_host

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/ata/ahci.c | 136 +++++++++++++++++++++++------------------------------
 1 file changed, 58 insertions(+), 78 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 46abbc2..37419f2 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -457,83 +457,6 @@ static struct ata_port_operations ahci_ops = {
 	.write = ahci_write,
 };
 
-static int ahci_host_init(struct ahci_device *ahci)
-{
-	u8 *mmio = (u8 *)ahci->mmio_base;
-	u32 tmp, cap_save;
-	int i, ret;
-
-	ahci_debug(ahci, "ahci_host_init: start\n");
-
-	cap_save = readl(mmio + HOST_CAP);
-	cap_save &= ((1 << 28) | (1 << 17));
-	cap_save |= (1 << 27);  /* Staggered Spin-up. Not needed. */
-
-	/* global controller reset */
-	tmp = ahci_ioread(ahci, HOST_CTL);
-	if ((tmp & HOST_RESET) == 0)
-		ahci_iowrite_f(ahci, HOST_CTL, tmp | HOST_RESET);
-
-	/*
-	 * reset must complete within 1 second, or
-	 * the hardware should be considered fried.
-	 */
-	ret = wait_on_timeout(SECOND, (readl(mmio + HOST_CTL) & HOST_RESET) == 0);
-	if (ret) {
-		ahci_debug(ahci,"controller reset failed (0x%x)\n", tmp);
-		return -ENODEV;
-	}
-
-	ahci_iowrite_f(ahci, HOST_CTL, HOST_AHCI_EN);
-	ahci_iowrite(ahci, HOST_CAP, cap_save);
-	ahci_iowrite_f(ahci, HOST_PORTS_IMPL, 0xf);
-
-	ahci->cap = ahci_ioread(ahci, HOST_CAP);
-	ahci->port_map = ahci_ioread(ahci, HOST_PORTS_IMPL);
-	ahci->n_ports = (ahci->cap & 0x1f) + 1;
-
-	ahci_debug(ahci, "cap 0x%x  port_map 0x%x  n_ports %d\n",
-	      ahci->cap, ahci->port_map, ahci->n_ports);
-
-	for (i = 0; i < ahci->n_ports; i++) {
-		struct ahci_port *ahci_port = &ahci->ports[i];
-
-		ahci_port->num = i;
-		ahci_port->ahci = ahci;
-		ahci_port->ata.dev = ahci->dev;
-		ahci_port->port_mmio = ahci_port_base(mmio, i);
-		ahci_port->ata.ops = &ahci_ops;
-		ata_port_register(&ahci_port->ata);
-	}
-
-	tmp = ahci_ioread(ahci, HOST_CTL);
-	ahci_iowrite(ahci, HOST_CTL, tmp | HOST_IRQ_EN);
-	tmp = ahci_ioread(ahci, HOST_CTL);
-
-	return 0;
-}
-
-static int __ahci_host_init(struct ahci_device *ahci)
-{
-	int rc = 0;
-
-	ahci->host_flags = ATA_FLAG_SATA
-				| ATA_FLAG_NO_LEGACY
-				| ATA_FLAG_MMIO
-				| ATA_FLAG_PIO_DMA
-				| ATA_FLAG_NO_ATAPI;
-	ahci->pio_mask = 0x1f;
-	ahci->udma_mask = 0x7f;	/* FIXME: assume to support UDMA6 */
-
-	/* initialize adapter */
-	rc = ahci_host_init(ahci);
-	if (rc)
-		goto err_out;
-
-err_out:
-	return rc;
-}
-
 #if 0
 /*
  * In the general case of generic rotating media it makes sense to have a
@@ -637,7 +560,64 @@ void ahci_info(struct device_d *dev)
 
 int ahci_add_host(struct ahci_device *ahci)
 {
-	__ahci_host_init(ahci);
+	u8 *mmio = (u8 *)ahci->mmio_base;
+	u32 tmp, cap_save;
+	int i, ret;
+
+	ahci->host_flags = ATA_FLAG_SATA
+				| ATA_FLAG_NO_LEGACY
+				| ATA_FLAG_MMIO
+				| ATA_FLAG_PIO_DMA
+				| ATA_FLAG_NO_ATAPI;
+	ahci->pio_mask = 0x1f;
+	ahci->udma_mask = 0x7f;	/* FIXME: assume to support UDMA6 */
+
+	ahci_debug(ahci, "ahci_host_init: start\n");
+
+	cap_save = readl(mmio + HOST_CAP);
+	cap_save &= ((1 << 28) | (1 << 17));
+	cap_save |= (1 << 27);  /* Staggered Spin-up. Not needed. */
+
+	/* global controller reset */
+	tmp = ahci_ioread(ahci, HOST_CTL);
+	if ((tmp & HOST_RESET) == 0)
+		ahci_iowrite_f(ahci, HOST_CTL, tmp | HOST_RESET);
+
+	/*
+	 * reset must complete within 1 second, or
+	 * the hardware should be considered fried.
+	 */
+	ret = wait_on_timeout(SECOND, (readl(mmio + HOST_CTL) & HOST_RESET) == 0);
+	if (ret) {
+		ahci_debug(ahci,"controller reset failed (0x%x)\n", tmp);
+		return -ENODEV;
+	}
+
+	ahci_iowrite_f(ahci, HOST_CTL, HOST_AHCI_EN);
+	ahci_iowrite(ahci, HOST_CAP, cap_save);
+	ahci_iowrite_f(ahci, HOST_PORTS_IMPL, 0xf);
+
+	ahci->cap = ahci_ioread(ahci, HOST_CAP);
+	ahci->port_map = ahci_ioread(ahci, HOST_PORTS_IMPL);
+	ahci->n_ports = (ahci->cap & 0x1f) + 1;
+
+	ahci_debug(ahci, "cap 0x%x  port_map 0x%x  n_ports %d\n",
+	      ahci->cap, ahci->port_map, ahci->n_ports);
+
+	for (i = 0; i < ahci->n_ports; i++) {
+		struct ahci_port *ahci_port = &ahci->ports[i];
+
+		ahci_port->num = i;
+		ahci_port->ahci = ahci;
+		ahci_port->ata.dev = ahci->dev;
+		ahci_port->port_mmio = ahci_port_base(mmio, i);
+		ahci_port->ata.ops = &ahci_ops;
+		ata_port_register(&ahci_port->ata);
+	}
+
+	tmp = ahci_ioread(ahci, HOST_CTL);
+	ahci_iowrite(ahci, HOST_CTL, tmp | HOST_IRQ_EN);
+	tmp = ahci_ioread(ahci, HOST_CTL);
 
 	return 0;
 }
-- 
1.8.2.rc2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-03-08 10:36 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-08 10:35 [PATCH] ata/ahci work Sascha Hauer
2013-03-08 10:35 ` [PATCH 1/5] ata: ahci: fix wrong link check Sascha Hauer
2013-03-08 10:35 ` [PATCH 2/5] ata: add ata logical device to defer probe Sascha Hauer
2013-03-08 10:35 ` [PATCH 3/5] ata: Add init callback to ata_port_operations Sascha Hauer
2013-03-08 10:35 ` [PATCH 4/5] ata: ahci: implement init callback Sascha Hauer
2013-03-08 10:35 ` [PATCH 5/5] ata: ahci: refactor init functions Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox