* [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