summaryrefslogtreecommitdiff
path: root/drivers/ata
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/fsl_sata.c58
-rw-r--r--drivers/ata/sata_sil.c60
2 files changed, 107 insertions, 11 deletions
diff --git a/drivers/ata/fsl_sata.c b/drivers/ata/fsl_sata.c
index 6609bf8a76..c6680dc1c9 100644
--- a/drivers/ata/fsl_sata.c
+++ b/drivers/ata/fsl_sata.c
@@ -22,6 +22,7 @@
#include <dm.h>
#include <ahci.h>
#include <blk.h>
+#include <dm/device-internal.h>
#else
#ifndef CONFIG_SYS_SATA1_FLAGS
#define CONFIG_SYS_SATA1_FLAGS FLAGS_DMA
@@ -122,7 +123,7 @@ static int init_sata(struct fsl_ata_priv *priv, int dev)
/* Zero all of the device driver struct */
memset((void *)sata, 0, sizeof(fsl_sata_t));
- snprintf(sata->name, 12, "SATA%d:\n", dev);
+ snprintf(sata->name, 12, "SATA%d:", dev);
/* Set the controller register base address to device struct */
#if !CONFIG_IS_ENABLED(BLK)
@@ -233,10 +234,7 @@ static int init_sata(struct fsl_ata_priv *priv, int dev)
mdelay(100);
/* print sata device name */
- if (!dev)
- printf("%s ", sata->name);
- else
- printf(" %s ", sata->name);
+ printf("%s ", sata->name);
/* Wait PHY RDY signal changed for 500ms */
ata_wait_register(&reg->hstatus, HSTATUS_PHY_RDY,
@@ -917,15 +915,32 @@ static int fsl_ata_ofdata_to_platdata(struct udevice *dev)
return 0;
}
+static int fsl_unbind_device(struct udevice *dev)
+{
+ int ret;
+
+ ret = device_remove(dev, DM_REMOVE_NORMAL);
+ if (ret)
+ return ret;
+
+ ret = device_unbind(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int fsl_ata_probe(struct udevice *dev)
{
struct fsl_ata_priv *blk_priv, *priv;
struct udevice *blk;
+ int failed_number;
char sata_name[10];
int nr_ports;
int ret;
int i;
+ failed_number = 0;
priv = dev_get_priv(dev);
nr_ports = priv->number;
nr_ports = min(nr_ports, CONFIG_SYS_SATA_MAX_DEVICE);
@@ -943,7 +958,12 @@ static int fsl_ata_probe(struct udevice *dev)
ret = init_sata(priv, i);
if (ret) {
debug("%s: Failed to init sata\n", __func__);
- return ret;
+ ret = fsl_unbind_device(blk);
+ if (ret)
+ return ret;
+
+ failed_number++;
+ continue;
}
blk_priv = dev_get_platdata(blk);
@@ -952,10 +972,33 @@ static int fsl_ata_probe(struct udevice *dev)
ret = scan_sata(blk);
if (ret) {
debug("%s: Failed to scan bus\n", __func__);
- return ret;
+ ret = fsl_unbind_device(blk);
+ if (ret)
+ return ret;
+
+ failed_number++;
+ continue;
}
}
+ if (failed_number == nr_ports)
+ return -ENODEV;
+ else
+ return 0;
+}
+
+static int fsl_ata_remove(struct udevice *dev)
+{
+ fsl_sata_t *sata;
+ struct fsl_ata_priv *priv;
+
+ priv = dev_get_priv(dev);
+ sata = priv->fsl_sata;
+
+ free(sata->cmd_hdr_tbl_offset);
+ free(sata->cmd_desc_offset);
+ free(sata);
+
return 0;
}
@@ -982,6 +1025,7 @@ U_BOOT_DRIVER(fsl_ahci) = {
.ops = &sata_fsl_ahci_ops,
.ofdata_to_platdata = fsl_ata_ofdata_to_platdata,
.probe = fsl_ata_probe,
+ .remove = fsl_ata_remove,
.priv_auto_alloc_size = sizeof(struct fsl_ata_priv),
};
#endif
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 4a50460c5a..71ee0c04ef 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -20,6 +20,7 @@
#if CONFIG_IS_ENABLED(BLK)
#include <dm.h>
#include <blk.h>
+#include <dm/device-internal.h>
#endif
#include "sata_sil.h"
@@ -763,15 +764,33 @@ U_BOOT_DRIVER(sata_sil_driver) = {
.platdata_auto_alloc_size = sizeof(struct sil_sata_priv),
};
+static int sil_unbind_device(struct udevice *dev)
+{
+ int ret;
+
+ ret = device_remove(dev, DM_REMOVE_NORMAL);
+ if (ret)
+ return ret;
+
+ ret = device_unbind(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int sil_pci_probe(struct udevice *dev)
{
struct udevice *blk;
+ int failed_number;
char sata_name[10];
pci_dev_t devno;
u16 word;
int ret;
int i;
+ failed_number = 0;
+
/* Get PCI device number */
devno = dm_pci_get_bdf(dev);
if (devno == -1)
@@ -824,12 +843,44 @@ static int sil_pci_probe(struct udevice *dev)
}
ret = sil_init_sata(blk, i);
- if (ret)
- return -ENODEV;
+ if (ret) {
+ ret = sil_unbind_device(blk);
+ if (ret)
+ return ret;
+
+ failed_number++;
+ continue;
+ }
ret = scan_sata(blk, i);
- if (ret)
- return -ENODEV;
+ if (ret) {
+ ret = sil_unbind_device(blk);
+ if (ret)
+ return ret;
+
+ failed_number++;
+ continue;
+ }
+ }
+
+ if (failed_number == sata_info.maxport)
+ return -ENODEV;
+ else
+ return 0;
+}
+
+static int sil_pci_remove(struct udevice *dev)
+{
+ int i;
+ struct sil_sata *sata;
+ struct sil_sata_priv *priv;
+
+ priv = dev_get_priv(dev);
+
+ for (i = sata_info.portbase; i < sata_info.maxport; i++) {
+ sata = priv->sil_sata_desc[i];
+ if (sata)
+ free(sata);
}
return 0;
@@ -857,6 +908,7 @@ U_BOOT_DRIVER(sil_ahci_pci) = {
.of_match = sil_pci_ids,
.ops = &sata_sil_ops,
.probe = sil_pci_probe,
+ .remove = sil_pci_remove,
.priv_auto_alloc_size = sizeof(struct sil_sata_priv),
};