diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_mv.c | 29 | ||||
-rw-r--r-- | drivers/pci/pci-aardvark.c | 52 |
2 files changed, 53 insertions, 28 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 1012cb53742..dadb2c7c2e7 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -809,6 +809,7 @@ static int mv_ata_exec_ata_cmd_nondma(struct udevice *dev, int port, static int mv_sata_identify(struct udevice *dev, int port, u16 *id) { struct sata_fis_h2d h2d; + int len; memset(&h2d, 0, sizeof(struct sata_fis_h2d)); @@ -818,8 +819,32 @@ static int mv_sata_identify(struct udevice *dev, int port, u16 *id) /* Give device time to get operational */ mdelay(10); - return mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id, - ATA_ID_WORDS * 2, READ_CMD); + /* During cold start, with some HDDs, the first ATA ID command does + * not populate the ID words. In fact, the first ATA ID + * command will only power up the drive, and then the ATA ID command + * processing is lost in the process. + */ + len = mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id, + ATA_ID_WORDS * 2, READ_CMD); + + /* If drive capacity has been filled in, then it was successfully + * identified (the drive has been powered up before, i.e. + * this function is invoked during a reboot) + */ + if (ata_id_n_sectors(id) != 0) + return len; + + /* Issue the 2nd ATA ID command to make sure the ID words are + * populated properly. + */ + mdelay(10); + len = mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id, + ATA_ID_WORDS * 2, READ_CMD); + if (ata_id_n_sectors(id) != 0) + return len; + + printf("Err: Failed to identify SATA device %d\n", port); + return -ENODEV; } static void mv_sata_xfer_mode(struct udevice *dev, int port, u16 *id) diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c index 1b9bae7cca7..815b26162f1 100644 --- a/drivers/pci/pci-aardvark.c +++ b/drivers/pci/pci-aardvark.c @@ -177,7 +177,6 @@ #define LINK_MAX_RETRIES 10 #define LINK_WAIT_TIMEOUT 100000 -#define CFG_RD_UR_VAL 0xFFFFFFFF #define CFG_RD_CRS_VAL 0xFFFF0001 /** @@ -263,12 +262,12 @@ static int pcie_advk_wait_pio(struct pcie_advk *pcie) * pcie_advk_check_pio_status() - Validate PIO status and get the read result * * @pcie: Pointer to the PCI bus - * @read: Read from or write to configuration space - true(read) false(write) - * @read_val: Pointer to the read result, only valid when read is true + * @allow_crs: Only for read requests, if CRS response is allowed + * @read_val: Pointer to the read result * */ static int pcie_advk_check_pio_status(struct pcie_advk *pcie, - bool read, + bool allow_crs, uint *read_val) { uint reg; @@ -286,22 +285,16 @@ static int pcie_advk_check_pio_status(struct pcie_advk *pcie, break; } /* Get the read result */ - if (read) + if (read_val) *read_val = advk_readl(pcie, PIO_RD_DATA); /* No error */ strcomp_status = NULL; break; case PIO_COMPLETION_STATUS_UR: - if (read) { - /* For reading, UR is not an error status. */ - *read_val = CFG_RD_UR_VAL; - strcomp_status = NULL; - } else { - strcomp_status = "UR"; - } + strcomp_status = "UR"; break; case PIO_COMPLETION_STATUS_CRS: - if (read) { + if (allow_crs && read_val) { /* For reading, CRS is not an error status. */ *read_val = CFG_RD_CRS_VAL; strcomp_status = NULL; @@ -352,6 +345,7 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, enum pci_size_t size) { struct pcie_advk *pcie = dev_get_priv(bus); + bool allow_crs; uint reg; int ret; @@ -364,13 +358,17 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, return 0; } + allow_crs = (offset == PCI_VENDOR_ID) && (size == 4); + if (advk_readl(pcie, PIO_START)) { dev_err(pcie->dev, "Previous PIO read/write transfer is still running\n"); - if (offset != PCI_VENDOR_ID) - return -EINVAL; - *valuep = CFG_RD_CRS_VAL; - return 0; + if (allow_crs) { + *valuep = CFG_RD_CRS_VAL; + return 0; + } + *valuep = pci_get_ff(size); + return -EINVAL; } /* Program the control register */ @@ -392,16 +390,20 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, advk_writel(pcie, 1, PIO_START); if (!pcie_advk_wait_pio(pcie)) { - if (offset != PCI_VENDOR_ID) - return -EINVAL; - *valuep = CFG_RD_CRS_VAL; - return 0; + if (allow_crs) { + *valuep = CFG_RD_CRS_VAL; + return 0; + } + *valuep = pci_get_ff(size); + return -EINVAL; } /* Check PIO status and get the read result */ - ret = pcie_advk_check_pio_status(pcie, true, ®); - if (ret) + ret = pcie_advk_check_pio_status(pcie, allow_crs, ®); + if (ret) { + *valuep = pci_get_ff(size); return ret; + } dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08x)\n", offset, size, reg); @@ -511,9 +513,7 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf, } /* Check PIO status */ - pcie_advk_check_pio_status(pcie, false, ®); - - return 0; + return pcie_advk_check_pio_status(pcie, false, NULL); } /** |