Lines Matching +full:mmio +full:- +full:mux
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AppliedMicro X-Gene SoC SATA Host Controller Driver
22 #define DRV_NAME "xgene-ahci"
27 /* MUX CSR */
88 void __iomem *csr_mux; /* MUX CSR address of IP */
93 dev_dbg(ctx->dev, "Release memory from shutdown\n"); in xgene_ahci_init_memram()
94 writel(0x0, ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN); in xgene_ahci_init_memram()
95 readl(ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN); /* Force a barrier */ in xgene_ahci_init_memram()
97 if (readl(ctx->csr_diag + BLOCK_MEM_RDY) != 0xFFFFFFFF) { in xgene_ahci_init_memram()
98 dev_err(ctx->dev, "failed to release memory from shutdown\n"); in xgene_ahci_init_memram()
99 return -ENODEV; in xgene_ahci_init_memram()
105 * xgene_ahci_poll_reg_val- Poll a register on a specific value.
131 * xgene_ahci_restart_engine - Restart the dma engine.
139 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_restart_engine()
140 struct ahci_port_priv *pp = ap->private_data; in xgene_ahci_restart_engine()
152 return -EBUSY; in xgene_ahci_restart_engine()
154 hpriv->stop_engine(ap); in xgene_ahci_restart_engine()
161 if (pp->fbs_supported) { in xgene_ahci_restart_engine()
167 hpriv->start_engine(ap); in xgene_ahci_restart_engine()
173 * xgene_ahci_qc_issue - Issue commands to the device
190 struct ata_port *ap = qc->ap; in xgene_ahci_qc_issue()
191 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_qc_issue()
192 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_qc_issue()
201 if (ctx->class[ap->port_no] == ATA_DEV_PMP) { in xgene_ahci_qc_issue()
204 port_fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET; in xgene_ahci_qc_issue()
208 if (unlikely((ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA) || in xgene_ahci_qc_issue()
209 (ctx->last_cmd[ap->port_no] == ATA_CMD_PACKET) || in xgene_ahci_qc_issue()
210 (ctx->last_cmd[ap->port_no] == ATA_CMD_SMART))) in xgene_ahci_qc_issue()
216 ctx->last_cmd[ap->port_no] = qc->tf.command; in xgene_ahci_qc_issue()
223 void __iomem *diagcsr = ctx->csr_diag; in xgene_ahci_is_memram_inited()
230 * xgene_ahci_read_id - Read ID data from the specified device
249 * bit15-8: reserved in xgene_ahci_read_id()
253 * bit4: In-order sata delivery supported in xgene_ahci_read_id()
255 * bit2: DMA Setup FIS Auto-Activate optimization supported in xgene_ahci_read_id()
256 * bit1: DMA Setup FIX non-Zero buffer offsets supported in xgene_ahci_read_id()
268 void __iomem *mmio = ctx->hpriv->mmio; in xgene_ahci_set_phy_cfg() local
271 dev_dbg(ctx->dev, "port configure mmio 0x%p channel %d\n", in xgene_ahci_set_phy_cfg()
272 mmio, channel); in xgene_ahci_set_phy_cfg()
273 val = readl(mmio + PORTCFG); in xgene_ahci_set_phy_cfg()
275 writel(val, mmio + PORTCFG); in xgene_ahci_set_phy_cfg()
276 readl(mmio + PORTCFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
278 writel(0x0001fffe, mmio + PORTPHY1CFG); in xgene_ahci_set_phy_cfg()
279 readl(mmio + PORTPHY1CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
280 writel(0x28183219, mmio + PORTPHY2CFG); in xgene_ahci_set_phy_cfg()
281 readl(mmio + PORTPHY2CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
282 writel(0x13081008, mmio + PORTPHY3CFG); in xgene_ahci_set_phy_cfg()
283 readl(mmio + PORTPHY3CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
284 writel(0x00480815, mmio + PORTPHY4CFG); in xgene_ahci_set_phy_cfg()
285 readl(mmio + PORTPHY4CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
287 val = readl(mmio + PORTPHY5CFG); in xgene_ahci_set_phy_cfg()
289 writel(val, mmio + PORTPHY5CFG); in xgene_ahci_set_phy_cfg()
290 readl(mmio + PORTPHY5CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
291 val = readl(mmio + PORTAXICFG); in xgene_ahci_set_phy_cfg()
294 writel(val, mmio + PORTAXICFG); in xgene_ahci_set_phy_cfg()
295 readl(mmio + PORTAXICFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
297 val = readl(mmio + PORTRANSCFG); in xgene_ahci_set_phy_cfg()
299 writel(val, mmio + PORTRANSCFG); in xgene_ahci_set_phy_cfg()
303 * xgene_ahci_do_hardreset - Issue the actual COMRESET
309 * required for each supported disk speed - Gen3 (6.0Gbps), Gen2 (3.0Gbps),
352 const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context); in xgene_ahci_do_hardreset()
353 struct ata_port *ap = link->ap; in xgene_ahci_do_hardreset()
354 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_do_hardreset()
355 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_do_hardreset()
356 struct ahci_port_priv *pp = ap->private_data; in xgene_ahci_do_hardreset()
357 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; in xgene_ahci_do_hardreset()
366 ata_tf_init(link->device, &tf); in xgene_ahci_do_hardreset()
374 dev_warn(ctx->dev, "link has error\n"); in xgene_ahci_do_hardreset()
392 struct ata_port *ap = link->ap; in xgene_ahci_hardreset()
393 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_hardreset()
410 hpriv->stop_engine(ap); in xgene_ahci_hardreset()
421 hpriv->start_engine(ap); in xgene_ahci_hardreset()
431 struct ahci_host_priv *hpriv = host->private_data; in xgene_ahci_host_stop()
437 * xgene_ahci_pmp_softreset - Issue the softreset to the drives connected
454 struct ata_port *ap = link->ap; in xgene_ahci_pmp_softreset()
474 * xgene_ahci_softreset - Issue the softreset to the drive.
488 * 0xF for both PMP/NON-PMP initially
498 struct ata_port *ap = link->ap; in xgene_ahci_softreset()
499 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_softreset()
500 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_softreset()
522 ctx->class[ap->port_no] = *class; in xgene_ahci_softreset()
528 if (retry--) { in xgene_ahci_softreset()
538 * xgene_ahci_handle_broken_edge_irq - Handle the broken irq.
564 struct ahci_host_priv *hpriv = host->private_data; in xgene_ahci_handle_broken_edge_irq()
568 if (!readl(hpriv->mmio + HOST_IRQ_STAT)) { in xgene_ahci_handle_broken_edge_irq()
569 for (i = 0; i < host->n_ports; i++) { in xgene_ahci_handle_broken_edge_irq()
573 port_mmio = ahci_port_base(host->ports[i]); in xgene_ahci_handle_broken_edge_irq()
587 void __iomem *mmio; in xgene_ahci_irq_intr() local
590 hpriv = host->private_data; in xgene_ahci_irq_intr()
591 mmio = hpriv->mmio; in xgene_ahci_irq_intr()
594 irq_stat = readl(mmio + HOST_IRQ_STAT); in xgene_ahci_irq_intr()
598 irq_masked = irq_stat & hpriv->port_map; in xgene_ahci_irq_intr()
600 spin_lock(&host->lock); in xgene_ahci_irq_intr()
606 writel(irq_stat, mmio + HOST_IRQ_STAT); in xgene_ahci_irq_intr()
610 spin_unlock(&host->lock); in xgene_ahci_irq_intr()
648 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_hw_init()
662 writel(0xffffffff, hpriv->mmio + HOST_IRQ_STAT); in xgene_ahci_hw_init()
663 readl(hpriv->mmio + HOST_IRQ_STAT); /* Force a barrier */ in xgene_ahci_hw_init()
664 writel(0, ctx->csr_core + INTSTATUSMASK); in xgene_ahci_hw_init()
665 val = readl(ctx->csr_core + INTSTATUSMASK); /* Force a barrier */ in xgene_ahci_hw_init()
666 dev_dbg(ctx->dev, "top level interrupt mask 0x%X value 0x%08X\n", in xgene_ahci_hw_init()
669 writel(0x0, ctx->csr_core + ERRINTSTATUSMASK); in xgene_ahci_hw_init()
670 readl(ctx->csr_core + ERRINTSTATUSMASK); /* Force a barrier */ in xgene_ahci_hw_init()
671 writel(0x0, ctx->csr_axi + INT_SLV_TMOMASK); in xgene_ahci_hw_init()
672 readl(ctx->csr_axi + INT_SLV_TMOMASK); in xgene_ahci_hw_init()
675 writel(0xffffffff, ctx->csr_core + SLVRDERRATTRIBUTES); in xgene_ahci_hw_init()
676 writel(0xffffffff, ctx->csr_core + SLVWRERRATTRIBUTES); in xgene_ahci_hw_init()
677 writel(0xffffffff, ctx->csr_core + MSTRDERRATTRIBUTES); in xgene_ahci_hw_init()
678 writel(0xffffffff, ctx->csr_core + MSTWRERRATTRIBUTES); in xgene_ahci_hw_init()
681 val = readl(ctx->csr_core + BUSCTLREG); in xgene_ahci_hw_init()
684 writel(val, ctx->csr_core + BUSCTLREG); in xgene_ahci_hw_init()
686 val = readl(ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
689 writel(val, ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
690 val = readl(ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
691 dev_dbg(ctx->dev, "coherency 0x%X value 0x%08X\n", in xgene_ahci_hw_init()
701 /* Check for optional MUX resource */ in xgene_ahci_mux_select()
702 if (!ctx->csr_mux) in xgene_ahci_mux_select()
705 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
707 writel(val, ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
708 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
709 return val & CFG_SATA_ENET_SELECT_MASK ? -1 : 0; in xgene_ahci_mux_select()
726 {.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
727 {.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
734 struct device *dev = &pdev->dev; in xgene_ahci_probe()
750 return -ENOMEM; in xgene_ahci_probe()
752 hpriv->plat_data = ctx; in xgene_ahci_probe()
753 ctx->hpriv = hpriv; in xgene_ahci_probe()
754 ctx->dev = dev; in xgene_ahci_probe()
757 ctx->csr_core = devm_platform_ioremap_resource(pdev, 1); in xgene_ahci_probe()
758 if (IS_ERR(ctx->csr_core)) in xgene_ahci_probe()
759 return PTR_ERR(ctx->csr_core); in xgene_ahci_probe()
762 ctx->csr_diag = devm_platform_ioremap_resource(pdev, 2); in xgene_ahci_probe()
763 if (IS_ERR(ctx->csr_diag)) in xgene_ahci_probe()
764 return PTR_ERR(ctx->csr_diag); in xgene_ahci_probe()
767 ctx->csr_axi = devm_platform_ioremap_resource(pdev, 3); in xgene_ahci_probe()
768 if (IS_ERR(ctx->csr_axi)) in xgene_ahci_probe()
769 return PTR_ERR(ctx->csr_axi); in xgene_ahci_probe()
771 /* Retrieve the optional IP mux resource */ in xgene_ahci_probe()
778 ctx->csr_mux = csr; in xgene_ahci_probe()
783 if (of_devid->data) in xgene_ahci_probe()
784 version = (unsigned long) of_devid->data; in xgene_ahci_probe()
792 acpi_id = acpi_match_device(xgene_ahci_acpi_match, &pdev->dev); in xgene_ahci_probe()
794 dev_warn(&pdev->dev, "No node entry in ACPI table. Assume version1\n"); in xgene_ahci_probe()
796 } else if (acpi_id->driver_data) { in xgene_ahci_probe()
797 version = (enum xgene_ahci_version) acpi_id->driver_data; in xgene_ahci_probe()
798 status = acpi_get_object_info(ACPI_HANDLE(&pdev->dev), &info); in xgene_ahci_probe()
800 dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n", in xgene_ahci_probe()
804 if (info->valid & ACPI_VALID_CID) in xgene_ahci_probe()
812 dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core, in xgene_ahci_probe()
813 hpriv->mmio); in xgene_ahci_probe()
817 dev_err(dev, "SATA mux selection failed error %d\n", rc); in xgene_ahci_probe()
818 return -ENODEV; in xgene_ahci_probe()
842 hpriv->flags = AHCI_HFLAG_NO_NCQ; in xgene_ahci_probe()
845 hpriv->flags |= AHCI_HFLAG_YES_FBS; in xgene_ahci_probe()
846 hpriv->irq_handler = xgene_ahci_irq_intr; in xgene_ahci_probe()
852 rc = ahci_platform_init_host(pdev, hpriv, ppi[version - 1], in xgene_ahci_probe()
857 dev_dbg(dev, "X-Gene SATA host controller initialized\n"); in xgene_ahci_probe()
877 MODULE_DESCRIPTION("APM X-Gene AHCI SATA driver");