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.
132 * xgene_ahci_restart_engine - Restart the dma engine.
140 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_restart_engine()
141 struct ahci_port_priv *pp = ap->private_data; in xgene_ahci_restart_engine()
153 return -EBUSY; in xgene_ahci_restart_engine()
155 hpriv->stop_engine(ap); in xgene_ahci_restart_engine()
162 if (pp->fbs_supported) { in xgene_ahci_restart_engine()
168 hpriv->start_engine(ap); in xgene_ahci_restart_engine()
174 * xgene_ahci_qc_issue - Issue commands to the device
191 struct ata_port *ap = qc->ap; in xgene_ahci_qc_issue()
192 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_qc_issue()
193 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_qc_issue()
202 if (ctx->class[ap->port_no] == ATA_DEV_PMP) { in xgene_ahci_qc_issue()
205 port_fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET; in xgene_ahci_qc_issue()
209 if (unlikely((ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA) || in xgene_ahci_qc_issue()
210 (ctx->last_cmd[ap->port_no] == ATA_CMD_PACKET) || in xgene_ahci_qc_issue()
211 (ctx->last_cmd[ap->port_no] == ATA_CMD_SMART))) in xgene_ahci_qc_issue()
217 ctx->last_cmd[ap->port_no] = qc->tf.command; in xgene_ahci_qc_issue()
224 void __iomem *diagcsr = ctx->csr_diag; in xgene_ahci_is_memram_inited()
231 * xgene_ahci_read_id - Read ID data from the specified device
250 * bit15-8: reserved in xgene_ahci_read_id()
254 * bit4: In-order sata delivery supported in xgene_ahci_read_id()
256 * bit2: DMA Setup FIS Auto-Activate optimization supported in xgene_ahci_read_id()
257 * bit1: DMA Setup FIX non-Zero buffer offsets supported in xgene_ahci_read_id()
269 void __iomem *mmio = ctx->hpriv->mmio; in xgene_ahci_set_phy_cfg() local
272 dev_dbg(ctx->dev, "port configure mmio 0x%p channel %d\n", in xgene_ahci_set_phy_cfg()
273 mmio, channel); in xgene_ahci_set_phy_cfg()
274 val = readl(mmio + PORTCFG); in xgene_ahci_set_phy_cfg()
276 writel(val, mmio + PORTCFG); in xgene_ahci_set_phy_cfg()
277 readl(mmio + PORTCFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
279 writel(0x0001fffe, mmio + PORTPHY1CFG); in xgene_ahci_set_phy_cfg()
280 readl(mmio + PORTPHY1CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
281 writel(0x28183219, mmio + PORTPHY2CFG); in xgene_ahci_set_phy_cfg()
282 readl(mmio + PORTPHY2CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
283 writel(0x13081008, mmio + PORTPHY3CFG); in xgene_ahci_set_phy_cfg()
284 readl(mmio + PORTPHY3CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
285 writel(0x00480815, mmio + PORTPHY4CFG); in xgene_ahci_set_phy_cfg()
286 readl(mmio + PORTPHY4CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
288 val = readl(mmio + PORTPHY5CFG); in xgene_ahci_set_phy_cfg()
290 writel(val, mmio + PORTPHY5CFG); in xgene_ahci_set_phy_cfg()
291 readl(mmio + PORTPHY5CFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
292 val = readl(mmio + PORTAXICFG); in xgene_ahci_set_phy_cfg()
295 writel(val, mmio + PORTAXICFG); in xgene_ahci_set_phy_cfg()
296 readl(mmio + PORTAXICFG); /* Force a barrier */ in xgene_ahci_set_phy_cfg()
298 val = readl(mmio + PORTRANSCFG); in xgene_ahci_set_phy_cfg()
300 writel(val, mmio + PORTRANSCFG); in xgene_ahci_set_phy_cfg()
304 * xgene_ahci_do_hardreset - Issue the actual COMRESET
310 * required for each supported disk speed - Gen3 (6.0Gbps), Gen2 (3.0Gbps),
353 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); in xgene_ahci_do_hardreset()
354 struct ata_port *ap = link->ap; in xgene_ahci_do_hardreset()
355 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_do_hardreset()
356 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_do_hardreset()
357 struct ahci_port_priv *pp = ap->private_data; in xgene_ahci_do_hardreset()
358 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; in xgene_ahci_do_hardreset()
367 ata_tf_init(link->device, &tf); in xgene_ahci_do_hardreset()
375 dev_warn(ctx->dev, "link has error\n"); in xgene_ahci_do_hardreset()
393 struct ata_port *ap = link->ap; in xgene_ahci_hardreset()
394 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_hardreset()
411 hpriv->stop_engine(ap); in xgene_ahci_hardreset()
422 hpriv->start_engine(ap); in xgene_ahci_hardreset()
432 struct ahci_host_priv *hpriv = host->private_data; in xgene_ahci_host_stop()
438 * xgene_ahci_pmp_softreset - Issue the softreset to the drives connected
455 struct ata_port *ap = link->ap; in xgene_ahci_pmp_softreset()
475 * xgene_ahci_softreset - Issue the softreset to the drive.
489 * 0xF for both PMP/NON-PMP initially
499 struct ata_port *ap = link->ap; in xgene_ahci_softreset()
500 struct ahci_host_priv *hpriv = ap->host->private_data; in xgene_ahci_softreset()
501 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_softreset()
523 ctx->class[ap->port_no] = *class; in xgene_ahci_softreset()
529 if (retry--) { in xgene_ahci_softreset()
539 * xgene_ahci_handle_broken_edge_irq - Handle the broken irq.
565 struct ahci_host_priv *hpriv = host->private_data; in xgene_ahci_handle_broken_edge_irq()
569 if (!readl(hpriv->mmio + HOST_IRQ_STAT)) { in xgene_ahci_handle_broken_edge_irq()
570 for (i = 0; i < host->n_ports; i++) { in xgene_ahci_handle_broken_edge_irq()
574 port_mmio = ahci_port_base(host->ports[i]); in xgene_ahci_handle_broken_edge_irq()
588 void __iomem *mmio; in xgene_ahci_irq_intr() local
593 hpriv = host->private_data; in xgene_ahci_irq_intr()
594 mmio = hpriv->mmio; in xgene_ahci_irq_intr()
597 irq_stat = readl(mmio + HOST_IRQ_STAT); in xgene_ahci_irq_intr()
601 irq_masked = irq_stat & hpriv->port_map; in xgene_ahci_irq_intr()
603 spin_lock(&host->lock); in xgene_ahci_irq_intr()
609 writel(irq_stat, mmio + HOST_IRQ_STAT); in xgene_ahci_irq_intr()
613 spin_unlock(&host->lock); in xgene_ahci_irq_intr()
653 struct xgene_ahci_context *ctx = hpriv->plat_data; in xgene_ahci_hw_init()
667 writel(0xffffffff, hpriv->mmio + HOST_IRQ_STAT); in xgene_ahci_hw_init()
668 readl(hpriv->mmio + HOST_IRQ_STAT); /* Force a barrier */ in xgene_ahci_hw_init()
669 writel(0, ctx->csr_core + INTSTATUSMASK); in xgene_ahci_hw_init()
670 val = readl(ctx->csr_core + INTSTATUSMASK); /* Force a barrier */ in xgene_ahci_hw_init()
671 dev_dbg(ctx->dev, "top level interrupt mask 0x%X value 0x%08X\n", in xgene_ahci_hw_init()
674 writel(0x0, ctx->csr_core + ERRINTSTATUSMASK); in xgene_ahci_hw_init()
675 readl(ctx->csr_core + ERRINTSTATUSMASK); /* Force a barrier */ in xgene_ahci_hw_init()
676 writel(0x0, ctx->csr_axi + INT_SLV_TMOMASK); in xgene_ahci_hw_init()
677 readl(ctx->csr_axi + INT_SLV_TMOMASK); in xgene_ahci_hw_init()
680 writel(0xffffffff, ctx->csr_core + SLVRDERRATTRIBUTES); in xgene_ahci_hw_init()
681 writel(0xffffffff, ctx->csr_core + SLVWRERRATTRIBUTES); in xgene_ahci_hw_init()
682 writel(0xffffffff, ctx->csr_core + MSTRDERRATTRIBUTES); in xgene_ahci_hw_init()
683 writel(0xffffffff, ctx->csr_core + MSTWRERRATTRIBUTES); in xgene_ahci_hw_init()
686 val = readl(ctx->csr_core + BUSCTLREG); in xgene_ahci_hw_init()
689 writel(val, ctx->csr_core + BUSCTLREG); in xgene_ahci_hw_init()
691 val = readl(ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
694 writel(val, ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
695 val = readl(ctx->csr_core + IOFMSTRWAUX); in xgene_ahci_hw_init()
696 dev_dbg(ctx->dev, "coherency 0x%X value 0x%08X\n", in xgene_ahci_hw_init()
706 /* Check for optional MUX resource */ in xgene_ahci_mux_select()
707 if (!ctx->csr_mux) in xgene_ahci_mux_select()
710 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
712 writel(val, ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
713 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); in xgene_ahci_mux_select()
714 return val & CFG_SATA_ENET_SELECT_MASK ? -1 : 0; in xgene_ahci_mux_select()
731 {.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
732 {.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
739 struct device *dev = &pdev->dev; in xgene_ahci_probe()
755 return -ENOMEM; in xgene_ahci_probe()
757 hpriv->plat_data = ctx; in xgene_ahci_probe()
758 ctx->hpriv = hpriv; in xgene_ahci_probe()
759 ctx->dev = dev; in xgene_ahci_probe()
763 ctx->csr_core = devm_ioremap_resource(dev, res); in xgene_ahci_probe()
764 if (IS_ERR(ctx->csr_core)) in xgene_ahci_probe()
765 return PTR_ERR(ctx->csr_core); in xgene_ahci_probe()
769 ctx->csr_diag = devm_ioremap_resource(dev, res); in xgene_ahci_probe()
770 if (IS_ERR(ctx->csr_diag)) in xgene_ahci_probe()
771 return PTR_ERR(ctx->csr_diag); in xgene_ahci_probe()
775 ctx->csr_axi = devm_ioremap_resource(dev, res); in xgene_ahci_probe()
776 if (IS_ERR(ctx->csr_axi)) in xgene_ahci_probe()
777 return PTR_ERR(ctx->csr_axi); in xgene_ahci_probe()
779 /* Retrieve the optional IP mux resource */ in xgene_ahci_probe()
786 ctx->csr_mux = csr; in xgene_ahci_probe()
791 if (of_devid->data) in xgene_ahci_probe()
792 version = (enum xgene_ahci_version) of_devid->data; in xgene_ahci_probe()
800 acpi_id = acpi_match_device(xgene_ahci_acpi_match, &pdev->dev); in xgene_ahci_probe()
802 dev_warn(&pdev->dev, "No node entry in ACPI table. Assume version1\n"); in xgene_ahci_probe()
804 } else if (acpi_id->driver_data) { in xgene_ahci_probe()
805 version = (enum xgene_ahci_version) acpi_id->driver_data; in xgene_ahci_probe()
806 status = acpi_get_object_info(ACPI_HANDLE(&pdev->dev), &info); in xgene_ahci_probe()
808 dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n", in xgene_ahci_probe()
812 if (info->valid & ACPI_VALID_CID) in xgene_ahci_probe()
820 dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core, in xgene_ahci_probe()
821 hpriv->mmio); in xgene_ahci_probe()
825 dev_err(dev, "SATA mux selection failed error %d\n", rc); in xgene_ahci_probe()
826 return -ENODEV; in xgene_ahci_probe()
850 hpriv->flags = AHCI_HFLAG_NO_NCQ; in xgene_ahci_probe()
853 hpriv->flags |= AHCI_HFLAG_YES_FBS; in xgene_ahci_probe()
854 hpriv->irq_handler = xgene_ahci_irq_intr; in xgene_ahci_probe()
860 rc = ahci_platform_init_host(pdev, hpriv, ppi[version - 1], in xgene_ahci_probe()
865 dev_dbg(dev, "X-Gene SATA host controller initialized\n"); in xgene_ahci_probe()
885 MODULE_DESCRIPTION("APM X-Gene AHCI SATA driver");