X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fata%2Fahci.c;h=c35912bd3341f97423d6bde0ab7ed71b95ed592b;hb=b1f2b72e39465f2d4582bb4d8c426489ee94e2d9;hp=2cc604b3f48246ded00c7cdb7f03fadc74212d32;hpb=1dc64f6c00e89f11e3615403459207405ab0efda;p=u-boot diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2cc604b3f4..c35912bd33 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1,11 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) Freescale Semiconductor, Inc. 2006. * Author: Jason Jin * Zhang Wei * - * SPDX-License-Identifier: GPL-2.0+ - * * with the reference on libata and ahci drvier in kernel + * + * This driver provides a SCSI interface to SATA. */ #include @@ -17,15 +18,19 @@ #include #include #include +#include #include #include #include #include +#include +#include -static int ata_io_flush(u8 port); +static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port); -struct ahci_probe_ent *probe_ent = NULL; -u16 *ataid[AHCI_MAX_PORTS]; +#ifndef CONFIG_DM_SCSI +struct ahci_uc_priv *probe_ent = NULL; +#endif #define writel_with_flush(a,b) do { writel(a,b); readl(b); } while (0) @@ -109,11 +114,11 @@ static int waiting_for_cmd_completed(void __iomem *offset, return (i < timeout_msec) ? 0 : -1; } -int __weak ahci_link_up(struct ahci_probe_ent *probe_ent, u8 port) +int __weak ahci_link_up(struct ahci_uc_priv *uc_priv, u8 port) { u32 tmp; int j = 0; - void __iomem *port_mmio = probe_ent->port[port].port_mmio; + void __iomem *port_mmio = uc_priv->port[port].port_mmio; /* * Bring up SATA link. @@ -166,19 +171,19 @@ int ahci_reset(void __iomem *base) return 0; } -static int ahci_host_init(struct ahci_probe_ent *probe_ent) +static int ahci_host_init(struct ahci_uc_priv *uc_priv) { #if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # ifdef CONFIG_DM_PCI - struct udevice *dev = probe_ent->dev; + struct udevice *dev = uc_priv->dev; struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); # else - pci_dev_t pdev = probe_ent->dev; + pci_dev_t pdev = uc_priv->dev; unsigned short vendor; # endif u16 tmp16; #endif - void __iomem *mmio = probe_ent->mmio_base; + void __iomem *mmio = uc_priv->mmio_base; u32 tmp, cap_save, cmd; int i, j, ret; void __iomem *port_mmio; @@ -190,7 +195,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) cap_save &= ((1 << 28) | (1 << 17)); cap_save |= (1 << 27); /* Staggered Spin-up. Not needed. */ - ret = ahci_reset(probe_ent->mmio_base); + ret = ahci_reset(uc_priv->mmio_base); if (ret) return ret; @@ -217,23 +222,23 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) } # endif #endif - probe_ent->cap = readl(mmio + HOST_CAP); - probe_ent->port_map = readl(mmio + HOST_PORTS_IMPL); - port_map = probe_ent->port_map; - probe_ent->n_ports = (probe_ent->cap & 0x1f) + 1; + uc_priv->cap = readl(mmio + HOST_CAP); + uc_priv->port_map = readl(mmio + HOST_PORTS_IMPL); + port_map = uc_priv->port_map; + uc_priv->n_ports = (uc_priv->cap & 0x1f) + 1; debug("cap 0x%x port_map 0x%x n_ports %d\n", - probe_ent->cap, probe_ent->port_map, probe_ent->n_ports); + uc_priv->cap, uc_priv->port_map, uc_priv->n_ports); - if (probe_ent->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID) - probe_ent->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID; + if (uc_priv->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID) + uc_priv->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID; - for (i = 0; i < probe_ent->n_ports; i++) { + for (i = 0; i < uc_priv->n_ports; i++) { if (!(port_map & (1 << i))) continue; - probe_ent->port[i].port_mmio = ahci_port_base(mmio, i); - port_mmio = (u8 *) probe_ent->port[i].port_mmio; - ahci_setup_port(&probe_ent->port[i], mmio, i); + uc_priv->port[i].port_mmio = ahci_port_base(mmio, i); + port_mmio = (u8 *)uc_priv->port[i].port_mmio; + ahci_setup_port(&uc_priv->port[i], mmio, i); /* make sure port is not active */ tmp = readl(port_mmio + PORT_CMD); @@ -262,7 +267,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel_with_flush(cmd, port_mmio + PORT_CMD); /* Bring up SATA link. */ - ret = ahci_link_up(probe_ent, i); + ret = ahci_link_up(uc_priv, i); if (ret) { printf("SATA link %d timeout.\n", i); continue; @@ -319,7 +324,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) tmp = readl(port_mmio + PORT_SCR_STAT); debug("SATA port %d status: 0x%x\n", i, tmp); if ((tmp & PORT_SCR_STAT_DET_MASK) == PORT_SCR_STAT_DET_PHYRDY) - probe_ent->link_port_map |= (0x01 << i); + uc_priv->link_port_map |= (0x01 << i); } tmp = readl(mmio + HOST_CTL); @@ -344,25 +349,25 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) } -static void ahci_print_info(struct ahci_probe_ent *probe_ent) +static void ahci_print_info(struct ahci_uc_priv *uc_priv) { #if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) # if defined(CONFIG_DM_PCI) - struct udevice *dev = probe_ent->dev; + struct udevice *dev = uc_priv->dev; # else - pci_dev_t pdev = probe_ent->dev; + pci_dev_t pdev = uc_priv->dev; # endif u16 cc; #endif - void __iomem *mmio = probe_ent->mmio_base; + void __iomem *mmio = uc_priv->mmio_base; u32 vers, cap, cap2, impl, speed; const char *speed_s; const char *scc_s; vers = readl(mmio + HOST_VERSION); - cap = probe_ent->cap; + cap = uc_priv->cap; cap2 = readl(mmio + HOST_CAP2); - impl = probe_ent->port_map; + impl = uc_priv->port_map; speed = (cap >> 20) & 0xf; if (speed == 1) @@ -425,11 +430,11 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) cap2 & (1 << 0) ? "boh " : ""); } -#ifndef CONFIG_SCSI_AHCI_PLAT +#if defined(CONFIG_DM_SCSI) || !defined(CONFIG_SCSI_AHCI_PLAT) # if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) -static int ahci_init_one(struct udevice *dev) +static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev) # else -static int ahci_init_one(pci_dev_t dev) +static int ahci_init_one(struct ahci_uc_priv *uc_priv, pci_dev_t dev) # endif { #if !defined(CONFIG_DM_SCSI) @@ -437,26 +442,19 @@ static int ahci_init_one(pci_dev_t dev) #endif int rc; - probe_ent = malloc(sizeof(struct ahci_probe_ent)); - if (!probe_ent) { - printf("%s: No memory for probe_ent\n", __func__); - return -ENOMEM; - } - - memset(probe_ent, 0, sizeof(struct ahci_probe_ent)); - probe_ent->dev = dev; + uc_priv->dev = dev; - probe_ent->host_flags = ATA_FLAG_SATA + uc_priv->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NO_ATAPI; - probe_ent->pio_mask = 0x1f; - probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ + uc_priv->pio_mask = 0x1f; + uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ #if !defined(CONFIG_DM_SCSI) #ifdef CONFIG_DM_PCI - probe_ent->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, + uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, PCI_REGION_MEM); /* Take from kernel: @@ -467,7 +465,7 @@ static int ahci_init_one(pci_dev_t dev) if (vendor == 0x197b) dm_pci_write_config8(dev, 0x41, 0xa1); #else - probe_ent->mmio_base = pci_map_bar(dev, PCI_BASE_ADDRESS_5, + uc_priv->mmio_base = pci_map_bar(dev, PCI_BASE_ADDRESS_5, PCI_REGION_MEM); /* Take from kernel: @@ -480,16 +478,16 @@ static int ahci_init_one(pci_dev_t dev) #endif #else struct scsi_platdata *plat = dev_get_uclass_platdata(dev); - probe_ent->mmio_base = (void *)plat->base; + uc_priv->mmio_base = (void *)plat->base; #endif - debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base); + debug("ahci mmio_base=0x%p\n", uc_priv->mmio_base); /* initialize adapter */ - rc = ahci_host_init(probe_ent); + rc = ahci_host_init(uc_priv); if (rc) goto err_out; - ahci_print_info(probe_ent); + ahci_print_info(uc_priv); return 0; @@ -500,9 +498,10 @@ static int ahci_init_one(pci_dev_t dev) #define MAX_DATA_BYTE_COUNT (4*1024*1024) -static int ahci_fill_sg(u8 port, unsigned char *buf, int buf_len) +static int ahci_fill_sg(struct ahci_uc_priv *uc_priv, u8 port, + unsigned char *buf, int buf_len) { - struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_ioports *pp = &(uc_priv->port[port]); struct ahci_sg *ahci_sg = pp->cmd_tbl_sg; u32 sg_count; int i; @@ -555,9 +554,9 @@ static int wait_spinup(void __iomem *port_mmio) return -ETIMEDOUT; } -static int ahci_port_start(u8 port) +static int ahci_port_start(struct ahci_uc_priv *uc_priv, u8 port) { - struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_ioports *pp = &(uc_priv->port[port]); void __iomem *port_mmio = pp->port_mmio; u32 port_status; void __iomem *mem; @@ -630,11 +629,11 @@ static int ahci_port_start(u8 port) } -static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, - int buf_len, u8 is_write) +static int ahci_device_data_io(struct ahci_uc_priv *uc_priv, u8 port, u8 *fis, + int fis_len, u8 *buf, int buf_len, u8 is_write) { - struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_ioports *pp = &(uc_priv->port[port]); void __iomem *port_mmio = pp->port_mmio; u32 opts; u32 port_status; @@ -642,7 +641,7 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, debug("Enter %s: for port %d\n", __func__, port); - if (port > probe_ent->n_ports) { + if (port > uc_priv->n_ports) { printf("Invalid port number %d\n", port); return -1; } @@ -655,7 +654,7 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, memcpy((unsigned char *)pp->cmd_tbl, fis, fis_len); - sg_count = ahci_fill_sg(port, buf, buf_len); + sg_count = ahci_fill_sg(uc_priv, port, buf, buf_len); opts = (fis_len >> 2) | (sg_count << 16) | (is_write << 6); ahci_fill_cmd_slot(pp, opts); @@ -689,7 +688,8 @@ static char *ata_id_strcpy(u16 *target, u16 *src, int len) /* * SCSI INQUIRY command operation. */ -static int ata_scsiop_inquiry(struct scsi_cmd *pccb) +static int ata_scsiop_inquiry(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb) { static const u8 hdr[] = { 0, @@ -720,21 +720,21 @@ static int ata_scsiop_inquiry(struct scsi_cmd *pccb) /* Read id from sata */ port = pccb->target; - if (ahci_device_data_io(port, (u8 *) &fis, sizeof(fis), (u8 *)tmpid, - ATA_ID_WORDS * 2, 0)) { + if (ahci_device_data_io(uc_priv, port, (u8 *)&fis, sizeof(fis), + (u8 *)tmpid, ATA_ID_WORDS * 2, 0)) { debug("scsi_ahci: SCSI inquiry command failure.\n"); return -EIO; } - if (!ataid[port]) { - ataid[port] = malloc(ATA_ID_WORDS * 2); - if (!ataid[port]) { + if (!uc_priv->ataid[port]) { + uc_priv->ataid[port] = malloc(ATA_ID_WORDS * 2); + if (!uc_priv->ataid[port]) { printf("%s: No memory for ataid[port]\n", __func__); return -ENOMEM; } } - idbuf = ataid[port]; + idbuf = uc_priv->ataid[port]; memcpy(idbuf, tmpid, ATA_ID_WORDS * 2); ata_swap_buf_le16(idbuf, ATA_ID_WORDS); @@ -753,7 +753,8 @@ static int ata_scsiop_inquiry(struct scsi_cmd *pccb) /* * SCSI READ10/WRITE10 command operation. */ -static int ata_scsiop_read_write(struct scsi_cmd *pccb, u8 is_write) +static int ata_scsiop_read_write(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb, u8 is_write) { lbaint_t lba = 0; u16 blocks = 0; @@ -833,8 +834,8 @@ static int ata_scsiop_read_write(struct scsi_cmd *pccb, u8 is_write) fis[13] = (now_blocks >> 8) & 0xff; /* Read/Write from ahci */ - if (ahci_device_data_io(pccb->target, (u8 *) &fis, sizeof(fis), - user_buffer, transfer_size, + if (ahci_device_data_io(uc_priv, pccb->target, (u8 *)&fis, + sizeof(fis), user_buffer, transfer_size, is_write)) { debug("scsi_ahci: SCSI %s10 command failure.\n", is_write ? "WRITE" : "READ"); @@ -848,7 +849,7 @@ static int ata_scsiop_read_write(struct scsi_cmd *pccb, u8 is_write) * usually, one extra flush when the rare writes do happen. */ if (is_write) { - if (-EIO == ata_io_flush(pccb->target)) + if (-EIO == ata_io_flush(uc_priv, pccb->target)) return -EIO; } user_buffer += transfer_size; @@ -864,20 +865,21 @@ static int ata_scsiop_read_write(struct scsi_cmd *pccb, u8 is_write) /* * SCSI READ CAPACITY10 command operation. */ -static int ata_scsiop_read_capacity10(struct scsi_cmd *pccb) +static int ata_scsiop_read_capacity10(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb) { u32 cap; u64 cap64; u32 block_size; - if (!ataid[pccb->target]) { + if (!uc_priv->ataid[pccb->target]) { printf("scsi_ahci: SCSI READ CAPACITY10 command failure. " "\tNo ATA info!\n" "\tPlease run SCSI command INQUIRY first!\n"); return -EPERM; } - cap64 = ata_id_n_sectors(ataid[pccb->target]); + cap64 = ata_id_n_sectors(uc_priv->ataid[pccb->target]); if (cap64 > 0x100000000ULL) cap64 = 0xffffffff; @@ -894,19 +896,20 @@ static int ata_scsiop_read_capacity10(struct scsi_cmd *pccb) /* * SCSI READ CAPACITY16 command operation. */ -static int ata_scsiop_read_capacity16(struct scsi_cmd *pccb) +static int ata_scsiop_read_capacity16(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb) { u64 cap; u64 block_size; - if (!ataid[pccb->target]) { + if (!uc_priv->ataid[pccb->target]) { printf("scsi_ahci: SCSI READ CAPACITY16 command failure. " "\tNo ATA info!\n" "\tPlease run SCSI command INQUIRY first!\n"); return -EPERM; } - cap = ata_id_n_sectors(ataid[pccb->target]); + cap = ata_id_n_sectors(uc_priv->ataid[pccb->target]); cap = cpu_to_be64(cap); memcpy(pccb->pdata, &cap, sizeof(cap)); @@ -920,59 +923,87 @@ static int ata_scsiop_read_capacity16(struct scsi_cmd *pccb) /* * SCSI TEST UNIT READY command operation. */ -static int ata_scsiop_test_unit_ready(struct scsi_cmd *pccb) +static int ata_scsiop_test_unit_ready(struct ahci_uc_priv *uc_priv, + struct scsi_cmd *pccb) { - return (ataid[pccb->target]) ? 0 : -EPERM; + return (uc_priv->ataid[pccb->target]) ? 0 : -EPERM; } -int scsi_exec(struct scsi_cmd *pccb) +static int ahci_scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) { + struct ahci_uc_priv *uc_priv; +#ifdef CONFIG_DM_SCSI + uc_priv = dev_get_uclass_priv(dev->parent); +#else + uc_priv = probe_ent; +#endif int ret; switch (pccb->cmd[0]) { case SCSI_READ16: case SCSI_READ10: - ret = ata_scsiop_read_write(pccb, 0); + ret = ata_scsiop_read_write(uc_priv, pccb, 0); break; case SCSI_WRITE10: - ret = ata_scsiop_read_write(pccb, 1); + ret = ata_scsiop_read_write(uc_priv, pccb, 1); break; case SCSI_RD_CAPAC10: - ret = ata_scsiop_read_capacity10(pccb); + ret = ata_scsiop_read_capacity10(uc_priv, pccb); break; case SCSI_RD_CAPAC16: - ret = ata_scsiop_read_capacity16(pccb); + ret = ata_scsiop_read_capacity16(uc_priv, pccb); break; case SCSI_TST_U_RDY: - ret = ata_scsiop_test_unit_ready(pccb); + ret = ata_scsiop_test_unit_ready(uc_priv, pccb); break; case SCSI_INQUIRY: - ret = ata_scsiop_inquiry(pccb); + ret = ata_scsiop_inquiry(uc_priv, pccb); break; default: printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]); - return false; + return -ENOTSUPP; } if (ret) { debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret); - return false; + return ret; } - return true; + return 0; } -#if defined(CONFIG_DM_SCSI) -void scsi_low_level_init(int busdevfunc, struct udevice *dev) -#else -void scsi_low_level_init(int busdevfunc) -#endif +static int ahci_start_ports(struct ahci_uc_priv *uc_priv) { - int i; u32 linkmap; + int i; + + linkmap = uc_priv->link_port_map; + + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { + if (((linkmap >> i) & 0x01)) { + if (ahci_port_start(uc_priv, (u8) i)) { + printf("Can not start port %d\n", i); + continue; + } + } + } + + return 0; +} + +#ifndef CONFIG_DM_SCSI +void scsi_low_level_init(int busdevfunc) +{ + struct ahci_uc_priv *uc_priv; #ifndef CONFIG_SCSI_AHCI_PLAT + probe_ent = calloc(1, sizeof(struct ahci_uc_priv)); + if (!probe_ent) { + printf("%s: No memory for uc_priv\n", __func__); + return; + } + uc_priv = probe_ent; # if defined(CONFIG_DM_PCI) struct udevice *dev; int ret; @@ -980,76 +1011,94 @@ void scsi_low_level_init(int busdevfunc) ret = dm_pci_bus_find_bdf(busdevfunc, &dev); if (ret) return; - ahci_init_one(dev); -# elif defined(CONFIG_DM_SCSI) - ahci_init_one(dev); + ahci_init_one(uc_priv, dev); # else - ahci_init_one(busdevfunc); + ahci_init_one(uc_priv, busdevfunc); # endif +#else + uc_priv = probe_ent; #endif - linkmap = probe_ent->link_port_map; + ahci_start_ports(uc_priv); +} +#endif - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - if (((linkmap >> i) & 0x01)) { - if (ahci_port_start((u8) i)) { - printf("Can not start port %d\n", i); - continue; - } - } - } +#ifndef CONFIG_SCSI_AHCI_PLAT +# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) +int ahci_init_one_dm(struct udevice *dev) +{ + struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev); + + return ahci_init_one(uc_priv, dev); } +#endif +#endif -#ifdef CONFIG_SCSI_AHCI_PLAT -int ahci_init(void __iomem *base) +int ahci_start_ports_dm(struct udevice *dev) { - int i, rc = 0; - u32 linkmap; + struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev); - probe_ent = malloc(sizeof(struct ahci_probe_ent)); - if (!probe_ent) { - printf("%s: No memory for probe_ent\n", __func__); - return -ENOMEM; - } + return ahci_start_ports(uc_priv); +} - memset(probe_ent, 0, sizeof(struct ahci_probe_ent)); +#ifdef CONFIG_SCSI_AHCI_PLAT +static int ahci_init_common(struct ahci_uc_priv *uc_priv, void __iomem *base) +{ + int rc; - probe_ent->host_flags = ATA_FLAG_SATA + uc_priv->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NO_ATAPI; - probe_ent->pio_mask = 0x1f; - probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ + uc_priv->pio_mask = 0x1f; + uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ - probe_ent->mmio_base = base; + uc_priv->mmio_base = base; /* initialize adapter */ - rc = ahci_host_init(probe_ent); + rc = ahci_host_init(uc_priv); if (rc) goto err_out; - ahci_print_info(probe_ent); + ahci_print_info(uc_priv); - linkmap = probe_ent->link_port_map; + rc = ahci_start_ports(uc_priv); - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - if (((linkmap >> i) & 0x01)) { - if (ahci_port_start((u8) i)) { - printf("Can not start port %d\n", i); - continue; - } - } - } err_out: return rc; } +#ifndef CONFIG_DM_SCSI +int ahci_init(void __iomem *base) +{ + struct ahci_uc_priv *uc_priv; + + probe_ent = malloc(sizeof(struct ahci_uc_priv)); + if (!probe_ent) { + printf("%s: No memory for uc_priv\n", __func__); + return -ENOMEM; + } + + uc_priv = probe_ent; + memset(uc_priv, 0, sizeof(struct ahci_uc_priv)); + + return ahci_init_common(uc_priv, base); +} +#endif + +int ahci_init_dm(struct udevice *dev, void __iomem *base) +{ + struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev); + + return ahci_init_common(uc_priv, base); +} + void __weak scsi_init(void) { } -#endif +#endif /* CONFIG_SCSI_AHCI_PLAT */ /* * In the general case of generic rotating media it makes sense to have a @@ -1060,10 +1109,10 @@ void __weak scsi_init(void) * is the last write is difficult. Because writing to the disk in u-boot is * very rare, this flush command will be invoked after every block write. */ -static int ata_io_flush(u8 port) +static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port) { u8 fis[20]; - struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_ioports *pp = &(uc_priv->port[port]); void __iomem *port_mmio = pp->port_mmio; u32 cmd_fis_len = 5; /* five dwords */ @@ -1087,8 +1136,85 @@ static int ata_io_flush(u8 port) return 0; } +static int ahci_scsi_bus_reset(struct udevice *dev) +{ + /* Not implemented */ + + return 0; +} -__weak void scsi_bus_reset(void) +#ifdef CONFIG_DM_SCSI +int ahci_bind_scsi(struct udevice *ahci_dev, struct udevice **devp) { - /*Not implement*/ + struct udevice *dev; + int ret; + + ret = device_bind_driver(ahci_dev, "ahci_scsi", "ahci_scsi", &dev); + if (ret) + return ret; + *devp = dev; + + return 0; } + +int ahci_probe_scsi(struct udevice *ahci_dev, ulong base) +{ + struct ahci_uc_priv *uc_priv; + struct scsi_platdata *uc_plat; + struct udevice *dev; + int ret; + + device_find_first_child(ahci_dev, &dev); + if (!dev) + return -ENODEV; + uc_plat = dev_get_uclass_platdata(dev); + uc_plat->base = base; + uc_plat->max_lun = 1; + uc_plat->max_id = 2; + + uc_priv = dev_get_uclass_priv(ahci_dev); + ret = ahci_init_one(uc_priv, dev); + if (ret) + return ret; + ret = ahci_start_ports(uc_priv); + if (ret) + return ret; + + return 0; +} + +#ifdef CONFIG_DM_PCI +int ahci_probe_scsi_pci(struct udevice *ahci_dev) +{ + ulong base; + + base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5, + PCI_REGION_MEM); + + return ahci_probe_scsi(ahci_dev, base); +} +#endif + +struct scsi_ops scsi_ops = { + .exec = ahci_scsi_exec, + .bus_reset = ahci_scsi_bus_reset, +}; + +U_BOOT_DRIVER(ahci_scsi) = { + .name = "ahci_scsi", + .id = UCLASS_SCSI, + .ops = &scsi_ops, +}; +#else +int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) +{ + return ahci_scsi_exec(dev, pccb); +} + +__weak int scsi_bus_reset(struct udevice *dev) +{ + return ahci_scsi_bus_reset(dev); + + return 0; +} +#endif