Lines Matching +full:ahci +full:- +full:port

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AppliedMicro X-Gene SoC SATA Host Controller Driver
18 #include "ahci.h"
20 #define DRV_NAME "xgene-ahci"
40 /* SATA host AHCI CSR */
91 dev_dbg(ctx->dev, "Release memory from shutdown\n"); in xgene_ahci_init_memram()
92 writel(0x0, ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN); in xgene_ahci_init_memram()
93 readl(ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN); /* Force a barrier */ in xgene_ahci_init_memram()
95 if (readl(ctx->csr_diag + BLOCK_MEM_RDY) != 0xFFFFFFFF) { in xgene_ahci_init_memram()
96 dev_err(ctx->dev, "failed to release memory from shutdown\n"); in xgene_ahci_init_memram()
97 return -ENODEV; in xgene_ahci_init_memram()
103 * xgene_ahci_poll_reg_val- Poll a register on a specific value.
104 * @ap : ATA port of interest.
129 * xgene_ahci_restart_engine - Restart the dma engine.
130 * @ap : ATA port of interest
137 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_restart_engine()
138 struct ahci_port_priv *pp = ap->private_data; in xgene_ahci_restart_engine()
150 return -EBUSY; in xgene_ahci_restart_engine()
152 hpriv->stop_engine(ap); in xgene_ahci_restart_engine()
159 if (pp->fbs_supported) { in xgene_ahci_restart_engine()
165 hpriv->start_engine(ap); in xgene_ahci_restart_engine()
171 * xgene_ahci_qc_issue - Issue commands to the device
181 * When the device returns the PMP port field in the D2H FIS, there is
188 struct ata_port *ap = qc->ap; in xgene_ahci_qc_issue()
189 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_qc_issue()
190 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_qc_issue()
197 * for case of Port Mulitplier. in xgene_ahci_qc_issue()
199 if (ctx->class[ap->port_no] == ATA_DEV_PMP) { in xgene_ahci_qc_issue()
202 port_fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET; in xgene_ahci_qc_issue()
206 if (unlikely((ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA) || in xgene_ahci_qc_issue()
207 (ctx->last_cmd[ap->port_no] == ATA_CMD_PACKET) || in xgene_ahci_qc_issue()
208 (ctx->last_cmd[ap->port_no] == ATA_CMD_SMART))) in xgene_ahci_qc_issue()
214 ctx->last_cmd[ap->port_no] = qc->tf.command; in xgene_ahci_qc_issue()
221 void __iomem *diagcsr = ctx->csr_diag; in xgene_ahci_is_memram_inited()
228 * xgene_ahci_read_id - Read ID data from the specified device
247 * bit15-8: reserved in xgene_ahci_read_id()
251 * bit4: In-order sata delivery supported in xgene_ahci_read_id()
253 * bit2: DMA Setup FIS Auto-Activate optimization supported in xgene_ahci_read_id()
254 * bit1: DMA Setup FIX non-Zero buffer offsets supported in xgene_ahci_read_id()
266 void __iomem *mmio = ctx->hpriv->mmio; in xgene_ahci_set_phy_cfg()
269 dev_dbg(ctx->dev, "port configure mmio 0x%p channel %d\n", in xgene_ahci_set_phy_cfg()
301 * xgene_ahci_do_hardreset - Issue the actual COMRESET
307 * required for each supported disk speed - Gen3 (6.0Gbps), Gen2 (3.0Gbps),
350 const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context); in xgene_ahci_do_hardreset()
351 struct ata_port *ap = link->ap; in xgene_ahci_do_hardreset()
352 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_do_hardreset()
353 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_do_hardreset()
354 struct ahci_port_priv *pp = ap->private_data; in xgene_ahci_do_hardreset()
355 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; in xgene_ahci_do_hardreset()
364 ata_tf_init(link->device, &tf); in xgene_ahci_do_hardreset()
372 dev_warn(ctx->dev, "link has error\n"); in xgene_ahci_do_hardreset()
390 struct ata_port *ap = link->ap; in xgene_ahci_hardreset()
391 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_hardreset()
408 hpriv->stop_engine(ap); in xgene_ahci_hardreset()
419 hpriv->start_engine(ap); in xgene_ahci_hardreset()
429 struct ahci_host_priv *hpriv = host->private_data; in xgene_ahci_host_stop()
435 * xgene_ahci_pmp_softreset - Issue the softreset to the drives connected
436 * to Port Multiplier.
443 * When the device returns the PMP port field in the D2H FIS, there is
452 struct ata_port *ap = link->ap; in xgene_ahci_pmp_softreset()
469 * xgene_ahci_softreset - Issue the softreset to the drive.
476 * When the device returns the PMP port field in the D2H FIS, there is
483 * 0xF for both PMP/NON-PMP initially
493 struct ata_port *ap = link->ap; in xgene_ahci_softreset()
494 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_softreset()
495 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_softreset()
517 ctx->class[ap->port_no] = *class; in xgene_ahci_softreset()
523 if (retry--) { in xgene_ahci_softreset()
533 * xgene_ahci_handle_broken_edge_irq - Handle the broken irq.
548 * traverse the rest of port's PORT_IRQ_STAT register
553 * 6. Handle port interrupts.
559 struct ahci_host_priv *hpriv = host->private_data; in xgene_ahci_handle_broken_edge_irq()
563 if (!readl(hpriv->mmio + HOST_IRQ_STAT)) { in xgene_ahci_handle_broken_edge_irq()
564 for (i = 0; i < host->n_ports; i++) { in xgene_ahci_handle_broken_edge_irq()
568 port_mmio = ahci_port_base(host->ports[i]); in xgene_ahci_handle_broken_edge_irq()
585 hpriv = host->private_data; in xgene_ahci_irq_intr()
586 mmio = hpriv->mmio; in xgene_ahci_irq_intr()
593 irq_masked = irq_stat & hpriv->port_map; in xgene_ahci_irq_intr()
595 spin_lock(&host->lock); in xgene_ahci_irq_intr()
599 * it should be cleared before all the port events are cleared. in xgene_ahci_irq_intr()
605 spin_unlock(&host->lock); in xgene_ahci_irq_intr()
643 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_hw_init()
657 writel(0xffffffff, hpriv->mmio + HOST_IRQ_STAT); in xgene_ahci_hw_init()
658 readl(hpriv->mmio + HOST_IRQ_STAT); /* Force a barrier */ in xgene_ahci_hw_init()
659 writel(0, ctx->csr_core + INTSTATUSMASK); in xgene_ahci_hw_init()
660 val = readl(ctx->csr_core + INTSTATUSMASK); /* Force a barrier */ in xgene_ahci_hw_init()
661 dev_dbg(ctx->dev, "top level interrupt mask 0x%X value 0x%08X\n", in xgene_ahci_hw_init()
664 writel(0x0, ctx->csr_core + ERRINTSTATUSMASK); in xgene_ahci_hw_init()
665 readl(ctx->csr_core + ERRINTSTATUSMASK); /* Force a barrier */ in xgene_ahci_hw_init()
666 writel(0x0, ctx->csr_axi + INT_SLV_TMOMASK); in xgene_ahci_hw_init()
667 readl(ctx->csr_axi + INT_SLV_TMOMASK); in xgene_ahci_hw_init()
670 writel(0xffffffff, ctx->csr_core + SLVRDERRATTRIBUTES); in xgene_ahci_hw_init()
671 writel(0xffffffff, ctx->csr_core + SLVWRERRATTRIBUTES); in xgene_ahci_hw_init()
672 writel(0xffffffff, ctx->csr_core + MSTRDERRATTRIBUTES); in xgene_ahci_hw_init()
673 writel(0xffffffff, ctx->csr_core + MSTWRERRATTRIBUTES); in xgene_ahci_hw_init()
676 val = readl(ctx->csr_core + BUSCTLREG); in xgene_ahci_hw_init()
679 writel(val, ctx->csr_core + BUSCTLREG); in xgene_ahci_hw_init()
681 val = readl(ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
684 writel(val, ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
685 val = readl(ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
686 dev_dbg(ctx->dev, "coherency 0x%X value 0x%08X\n", in xgene_ahci_hw_init()
697 if (!ctx->csr_mux) in xgene_ahci_mux_select()
700 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
702 writel(val, ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
703 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
704 return val & CFG_SATA_ENET_SELECT_MASK ? -1 : 0; in xgene_ahci_mux_select()
721 {.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
722 {.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
729 struct device *dev = &pdev->dev; in xgene_ahci_probe()
744 return -ENOMEM; in xgene_ahci_probe()
746 hpriv->plat_data = ctx; in xgene_ahci_probe()
747 ctx->hpriv = hpriv; in xgene_ahci_probe()
748 ctx->dev = dev; in xgene_ahci_probe()
751 ctx->csr_core = devm_platform_ioremap_resource(pdev, 1); in xgene_ahci_probe()
752 if (IS_ERR(ctx->csr_core)) in xgene_ahci_probe()
753 return PTR_ERR(ctx->csr_core); in xgene_ahci_probe()
756 ctx->csr_diag = devm_platform_ioremap_resource(pdev, 2); in xgene_ahci_probe()
757 if (IS_ERR(ctx->csr_diag)) in xgene_ahci_probe()
758 return PTR_ERR(ctx->csr_diag); in xgene_ahci_probe()
761 ctx->csr_axi = devm_platform_ioremap_resource(pdev, 3); in xgene_ahci_probe()
762 if (IS_ERR(ctx->csr_axi)) in xgene_ahci_probe()
763 return PTR_ERR(ctx->csr_axi); in xgene_ahci_probe()
772 ctx->csr_mux = csr; in xgene_ahci_probe()
775 if (dev->of_node) { in xgene_ahci_probe()
784 acpi_id = acpi_match_device(xgene_ahci_acpi_match, &pdev->dev); in xgene_ahci_probe()
786 dev_warn(&pdev->dev, "No node entry in ACPI table. Assume version1\n"); in xgene_ahci_probe()
788 } else if (acpi_id->driver_data) { in xgene_ahci_probe()
789 version = (enum xgene_ahci_version) acpi_id->driver_data; in xgene_ahci_probe()
790 status = acpi_get_object_info(ACPI_HANDLE(&pdev->dev), &info); in xgene_ahci_probe()
792 dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n", in xgene_ahci_probe()
796 if (info->valid & ACPI_VALID_CID) in xgene_ahci_probe()
804 dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core, in xgene_ahci_probe()
805 hpriv->mmio); in xgene_ahci_probe()
810 return -ENODEV; in xgene_ahci_probe()
834 hpriv->flags = AHCI_HFLAG_NO_NCQ; in xgene_ahci_probe()
837 hpriv->flags |= AHCI_HFLAG_YES_FBS; in xgene_ahci_probe()
838 hpriv->irq_handler = xgene_ahci_irq_intr; in xgene_ahci_probe()
844 rc = ahci_platform_init_host(pdev, hpriv, ppi[version - 1], in xgene_ahci_probe()
849 dev_dbg(dev, "X-Gene SATA host controller initialized\n"); in xgene_ahci_probe()
869 MODULE_DESCRIPTION("APM X-Gene AHCI SATA driver");