diff options
-rw-r--r-- | drivers/ata/dwc_ahsata.c | 236 |
1 files changed, 131 insertions, 105 deletions
diff --git a/drivers/ata/dwc_ahsata.c b/drivers/ata/dwc_ahsata.c index 2695bef222..1e3ddd75db 100644 --- a/drivers/ata/dwc_ahsata.c +++ b/drivers/ata/dwc_ahsata.c @@ -10,6 +10,7 @@ #include <fis.h> #include <libata.h> #include <malloc.h> +#include <memalign.h> #include <sata.h> #include <asm/io.h> #include <asm/arch/clock.h> @@ -720,6 +721,130 @@ static u32 ata_low_level_rw_lba28(struct ahci_uc_priv *uc_priv, u32 blknr, return blkcnt; } +static int dwc_ahci_start_ports(struct ahci_uc_priv *uc_priv) +{ + u32 linkmap; + int i; + + linkmap = uc_priv->link_port_map; + + if (0 == linkmap) { + printf("No port device detected!\n"); + return -ENXIO; + } + + for (i = 0; i < uc_priv->n_ports; i++) { + if ((linkmap >> i) && ((linkmap >> i) & 0x01)) { + if (ahci_port_start(uc_priv, (u8)i)) { + printf("Can not start port %d\n", i); + return 1; + } + uc_priv->hard_port_no = i; + break; + } + } + + return 0; +} + +static int dwc_ahsata_scan_common(struct ahci_uc_priv *uc_priv, + struct blk_desc *pdev) +{ + u8 serial[ATA_ID_SERNO_LEN + 1] = { 0 }; + u8 firmware[ATA_ID_FW_REV_LEN + 1] = { 0 }; + u8 product[ATA_ID_PROD_LEN + 1] = { 0 }; + u64 n_sectors; + u8 port = uc_priv->hard_port_no; + ALLOC_CACHE_ALIGN_BUFFER(u16, id, ATA_ID_WORDS); + + /* Identify device to get information */ + dwc_ahsata_identify(uc_priv, id); + + /* Serial number */ + ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); + memcpy(pdev->product, serial, sizeof(serial)); + + /* Firmware version */ + ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); + memcpy(pdev->revision, firmware, sizeof(firmware)); + + /* Product model */ + ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); + memcpy(pdev->vendor, product, sizeof(product)); + + /* Totoal sectors */ + n_sectors = ata_id_n_sectors(id); + pdev->lba = (u32)n_sectors; + + pdev->type = DEV_TYPE_HARDDISK; + pdev->blksz = ATA_SECT_SIZE; + pdev->lun = 0; + + /* Check if support LBA48 */ + if (ata_id_has_lba48(id)) { + pdev->lba48 = 1; + debug("Device support LBA48\n\r"); + } + + /* Get the NCQ queue depth from device */ + uc_priv->flags &= (~SATA_FLAG_Q_DEP_MASK); + uc_priv->flags |= ata_id_queue_depth(id); + + /* Get the xfer mode from device */ + dwc_ahsata_xfer_mode(uc_priv, id); + + /* Get the write cache status from device */ + dwc_ahsata_init_wcache(uc_priv, id); + + /* Set the xfer mode to highest speed */ + ahci_set_feature(uc_priv, port); + + dwc_ahsata_print_info(pdev); + + return 0; +} + +/* + * SATA interface between low level driver and command layer + */ +static ulong sata_read_common(struct ahci_uc_priv *uc_priv, + struct blk_desc *desc, ulong blknr, + lbaint_t blkcnt, void *buffer) +{ + u32 rc; + + if (desc->lba48) + rc = ata_low_level_rw_lba48(uc_priv, blknr, blkcnt, buffer, + READ_CMD); + else + rc = ata_low_level_rw_lba28(uc_priv, blknr, blkcnt, buffer, + READ_CMD); + + return rc; +} + +static ulong sata_write_common(struct ahci_uc_priv *uc_priv, + struct blk_desc *desc, ulong blknr, + lbaint_t blkcnt, const void *buffer) +{ + u32 rc; + u32 flags = uc_priv->flags; + + if (desc->lba48) { + rc = ata_low_level_rw_lba48(uc_priv, blknr, blkcnt, buffer, + WRITE_CMD); + if ((flags & SATA_FLAG_WCACHE) && (flags & SATA_FLAG_FLUSH_EXT)) + dwc_ahsata_flush_cache_ext(uc_priv); + } else { + rc = ata_low_level_rw_lba28(uc_priv, blknr, blkcnt, buffer, + WRITE_CMD); + if ((flags & SATA_FLAG_WCACHE) && (flags & SATA_FLAG_FLUSH)) + dwc_ahsata_flush_cache(uc_priv); + } + + return rc; +} + static int ahci_init_one(int pdev) { int rc; @@ -755,8 +880,6 @@ err_out: int init_sata(int dev) { - int i; - u32 linkmap; struct ahci_uc_priv *uc_priv = NULL; #if defined(CONFIG_MX6) @@ -771,25 +894,8 @@ int init_sata(int dev) ahci_init_one(dev); uc_priv = sata_dev_desc[dev].priv; - linkmap = uc_priv->link_port_map; - - if (0 == linkmap) { - printf("No port device detected!\n"); - return 1; - } - - for (i = 0; i < uc_priv->n_ports; i++) { - if ((linkmap >> i) && ((linkmap >> i) & 0x01)) { - if (ahci_port_start(uc_priv, (u8)i)) { - printf("Can not start port %d\n", i); - return 1; - } - uc_priv->hard_port_no = i; - break; - } - } - return 0; + return dwc_ahci_start_ports(uc_priv) ? 1 : 0; } int reset_sata(int dev) @@ -838,103 +944,23 @@ int sata_port_status(int dev, int port) ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) { struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv; - u32 rc; - if (sata_dev_desc[dev].lba48) - rc = ata_low_level_rw_lba48(uc_priv, blknr, blkcnt, - buffer, READ_CMD); - else - rc = ata_low_level_rw_lba28(uc_priv, blknr, blkcnt, - buffer, READ_CMD); - return rc; + return sata_read_common(uc_priv, &sata_dev_desc[dev], blknr, blkcnt, + buffer); } ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) { - u32 rc; struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv; - u32 flags = uc_priv->flags; - if (sata_dev_desc[dev].lba48) { - rc = ata_low_level_rw_lba48(uc_priv, blknr, blkcnt, buffer, - WRITE_CMD); - if ((flags & SATA_FLAG_WCACHE) && - (flags & SATA_FLAG_FLUSH_EXT)) - dwc_ahsata_flush_cache_ext(uc_priv); - } else { - rc = ata_low_level_rw_lba28(uc_priv, blknr, blkcnt, buffer, - WRITE_CMD); - if ((flags & SATA_FLAG_WCACHE) && - (flags & SATA_FLAG_FLUSH)) - dwc_ahsata_flush_cache(uc_priv); - } - return rc; + return sata_write_common(uc_priv, &sata_dev_desc[dev], blknr, blkcnt, + buffer); } int scan_sata(int dev) { - u8 serial[ATA_ID_SERNO_LEN + 1] = { 0 }; - u8 firmware[ATA_ID_FW_REV_LEN + 1] = { 0 }; - u8 product[ATA_ID_PROD_LEN + 1] = { 0 }; - u16 *id; - u64 n_sectors; struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv; - u8 port = uc_priv->hard_port_no; struct blk_desc *pdev = &sata_dev_desc[dev]; - id = (u16 *)memalign(ARCH_DMA_MINALIGN, - roundup(ARCH_DMA_MINALIGN, - (ATA_ID_WORDS * 2))); - if (!id) { - printf("id malloc failed\n\r"); - return -1; - } - - /* Identify device to get information */ - dwc_ahsata_identify(uc_priv, id); - - /* Serial number */ - ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); - memcpy(pdev->product, serial, sizeof(serial)); - - /* Firmware version */ - ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); - memcpy(pdev->revision, firmware, sizeof(firmware)); - - /* Product model */ - ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); - memcpy(pdev->vendor, product, sizeof(product)); - - /* Totoal sectors */ - n_sectors = ata_id_n_sectors(id); - pdev->lba = (u32)n_sectors; - - pdev->type = DEV_TYPE_HARDDISK; - pdev->blksz = ATA_SECT_SIZE; - pdev->lun = 0 ; - - /* Check if support LBA48 */ - if (ata_id_has_lba48(id)) { - pdev->lba48 = 1; - debug("Device support LBA48\n\r"); - } - - /* Get the NCQ queue depth from device */ - uc_priv->flags &= (~SATA_FLAG_Q_DEP_MASK); - uc_priv->flags |= ata_id_queue_depth(id); - - /* Get the xfer mode from device */ - dwc_ahsata_xfer_mode(uc_priv, id); - - /* Get the write cache status from device */ - dwc_ahsata_init_wcache(uc_priv, id); - - /* Set the xfer mode to highest speed */ - ahci_set_feature(uc_priv, port); - - free((void *)id); - - dwc_ahsata_print_info(&sata_dev_desc[dev]); - - return 0; + return dwc_ahsata_scan_common(uc_priv, pdev); } |