Lines Matching +full:host +full:- +full:port

1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright 2004-2005 Red Hat, Inc.
28 static void ahci_host_stop(struct ata_host *host);
37 * ahci_platform_enable_phys - Enable PHYs
38 * @hpriv: host private area to store config values
40 * This function enables all the PHYs found in hpriv->phys, if any.
51 for (i = 0; i < hpriv->nports; i++) { in ahci_platform_enable_phys()
55 rc = phy_init(hpriv->phys[i]); in ahci_platform_enable_phys()
59 rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA); in ahci_platform_enable_phys()
61 phy_exit(hpriv->phys[i]); in ahci_platform_enable_phys()
65 rc = phy_power_on(hpriv->phys[i]); in ahci_platform_enable_phys()
67 phy_exit(hpriv->phys[i]); in ahci_platform_enable_phys()
75 while (--i >= 0) { in ahci_platform_enable_phys()
79 phy_power_off(hpriv->phys[i]); in ahci_platform_enable_phys()
80 phy_exit(hpriv->phys[i]); in ahci_platform_enable_phys()
87 * ahci_platform_disable_phys - Disable PHYs
88 * @hpriv: host private area to store config values
90 * This function disables all PHYs found in hpriv->phys.
96 for (i = 0; i < hpriv->nports; i++) { in ahci_platform_disable_phys()
100 phy_power_off(hpriv->phys[i]); in ahci_platform_disable_phys()
101 phy_exit(hpriv->phys[i]); in ahci_platform_disable_phys()
107 * ahci_platform_find_clk - Find platform clock
108 * @hpriv: host private area to store config values
121 for (i = 0; i < hpriv->n_clks; i++) { in ahci_platform_find_clk()
122 if (hpriv->clks[i].id && !strcmp(hpriv->clks[i].id, con_id)) in ahci_platform_find_clk()
123 return hpriv->clks[i].clk; in ahci_platform_find_clk()
131 * ahci_platform_enable_clks - Enable platform clocks
132 * @hpriv: host private area to store config values
141 return clk_bulk_prepare_enable(hpriv->n_clks, hpriv->clks); in ahci_platform_enable_clks()
146 * ahci_platform_disable_clks - Disable platform clocks
147 * @hpriv: host private area to store config values
150 * (bulk-clocks-disable function is supposed to do that in reverse
155 clk_bulk_disable_unprepare(hpriv->n_clks, hpriv->clks); in ahci_platform_disable_clks()
160 * ahci_platform_deassert_rsts - Deassert/trigger platform resets
161 * @hpriv: host private area to store config values
171 if (hpriv->f_rsts & AHCI_PLATFORM_RST_TRIGGER) in ahci_platform_deassert_rsts()
172 return reset_control_reset(hpriv->rsts); in ahci_platform_deassert_rsts()
174 return reset_control_deassert(hpriv->rsts); in ahci_platform_deassert_rsts()
179 * ahci_platform_assert_rsts - Assert/rearm platform resets
180 * @hpriv: host private area to store config values
182 * This function asserts or rearms (for self-deasserting resets) all
190 if (hpriv->f_rsts & AHCI_PLATFORM_RST_TRIGGER) in ahci_platform_assert_rsts()
191 return reset_control_rearm(hpriv->rsts); in ahci_platform_assert_rsts()
193 return reset_control_assert(hpriv->rsts); in ahci_platform_assert_rsts()
198 * ahci_platform_enable_regulators - Enable regulators
199 * @hpriv: host private area to store config values
202 * hpriv->target_pwrs, if any. If a regulator fails to be enabled, it
213 rc = regulator_enable(hpriv->ahci_regulator); in ahci_platform_enable_regulators()
217 rc = regulator_enable(hpriv->phy_regulator); in ahci_platform_enable_regulators()
221 for (i = 0; i < hpriv->nports; i++) { in ahci_platform_enable_regulators()
222 if (!hpriv->target_pwrs[i]) in ahci_platform_enable_regulators()
225 rc = regulator_enable(hpriv->target_pwrs[i]); in ahci_platform_enable_regulators()
233 while (--i >= 0) in ahci_platform_enable_regulators()
234 if (hpriv->target_pwrs[i]) in ahci_platform_enable_regulators()
235 regulator_disable(hpriv->target_pwrs[i]); in ahci_platform_enable_regulators()
237 regulator_disable(hpriv->phy_regulator); in ahci_platform_enable_regulators()
239 regulator_disable(hpriv->ahci_regulator); in ahci_platform_enable_regulators()
245 * ahci_platform_disable_regulators - Disable regulators
246 * @hpriv: host private area to store config values
248 * This function disables all regulators found in hpriv->target_pwrs and
255 for (i = 0; i < hpriv->nports; i++) { in ahci_platform_disable_regulators()
256 if (!hpriv->target_pwrs[i]) in ahci_platform_disable_regulators()
258 regulator_disable(hpriv->target_pwrs[i]); in ahci_platform_disable_regulators()
261 regulator_disable(hpriv->ahci_regulator); in ahci_platform_disable_regulators()
262 regulator_disable(hpriv->phy_regulator); in ahci_platform_disable_regulators()
266 * ahci_platform_enable_resources - Enable platform resources
267 * @hpriv: host private area to store config values
318 * ahci_platform_disable_resources - Disable platform resources
319 * @hpriv: host private area to store config values
345 if (hpriv->got_runtime_pm) { in ahci_platform_put_resources()
355 for (c = 0; c < hpriv->nports; c++) in ahci_platform_put_resources()
356 if (hpriv->target_pwrs && hpriv->target_pwrs[c]) in ahci_platform_put_resources()
357 regulator_put(hpriv->target_pwrs[c]); in ahci_platform_put_resources()
359 kfree(hpriv->target_pwrs); in ahci_platform_put_resources()
362 static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port, in ahci_platform_get_phy() argument
367 hpriv->phys[port] = devm_of_phy_get(dev, node, NULL); in ahci_platform_get_phy()
369 if (!IS_ERR(hpriv->phys[port])) in ahci_platform_get_phy()
372 rc = PTR_ERR(hpriv->phys[port]); in ahci_platform_get_phy()
374 case -ENOSYS: in ahci_platform_get_phy()
383 case -ENODEV: in ahci_platform_get_phy()
385 hpriv->phys[port] = NULL; in ahci_platform_get_phy()
388 case -EPROBE_DEFER: in ahci_platform_get_phy()
403 static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, in ahci_platform_get_regulator() argument
412 hpriv->target_pwrs[port] = target_pwr; in ahci_platform_get_regulator()
422 u32 port; in ahci_platform_get_firmware() local
424 if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap)) in ahci_platform_get_firmware()
425 hpriv->saved_cap &= (HOST_CAP_SSS | HOST_CAP_MPS); in ahci_platform_get_firmware()
427 of_property_read_u32(dev->of_node, in ahci_platform_get_firmware()
428 "ports-implemented", &hpriv->saved_port_map); in ahci_platform_get_firmware()
430 for_each_child_of_node_scoped(dev->of_node, child) { in ahci_platform_get_firmware()
434 if (of_property_read_u32(child, "reg", &port)) in ahci_platform_get_firmware()
435 return -EINVAL; in ahci_platform_get_firmware()
437 if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port])) in ahci_platform_get_firmware()
438 hpriv->saved_port_cap[port] &= PORT_CMD_CAP; in ahci_platform_get_firmware()
448 for_each_child_of_node_scoped(dev->of_node, child) { in ahci_platform_find_max_port_id()
449 u32 port; in ahci_platform_find_max_port_id() local
451 if (!of_property_read_u32(child, "reg", &port)) in ahci_platform_find_max_port_id()
452 max_port = max(max_port, port); in ahci_platform_find_max_port_id()
459 * ahci_platform_get_resources - Get platform resources
470 * clock for non-OF platforms (optional)
480 int child_nodes, rc = -ENOMEM, enabled_ports = 0; in ahci_platform_get_resources()
481 struct device *dev = &pdev->dev; in ahci_platform_get_resources()
487 return ERR_PTR(-ENOMEM); in ahci_platform_get_resources()
501 hpriv->mmio = devm_platform_ioremap_resource_byname(pdev, "ahci"); in ahci_platform_get_resources()
503 hpriv->mmio = devm_platform_ioremap_resource(pdev, 0); in ahci_platform_get_resources()
504 if (IS_ERR(hpriv->mmio)) { in ahci_platform_get_resources()
505 rc = PTR_ERR(hpriv->mmio); in ahci_platform_get_resources()
511 * running on a non-OF platform or due to the clocks being defined in in ahci_platform_get_resources()
516 rc = devm_clk_bulk_get_all(dev, &hpriv->clks); in ahci_platform_get_resources()
522 hpriv->n_clks = rc; in ahci_platform_get_resources()
528 hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL); in ahci_platform_get_resources()
529 if (!hpriv->clks) { in ahci_platform_get_resources()
530 rc = -ENOMEM; in ahci_platform_get_resources()
533 hpriv->clks->clk = devm_clk_get_optional(dev, NULL); in ahci_platform_get_resources()
534 if (IS_ERR(hpriv->clks->clk)) { in ahci_platform_get_resources()
535 rc = PTR_ERR(hpriv->clks->clk); in ahci_platform_get_resources()
537 } else if (hpriv->clks->clk) { in ahci_platform_get_resources()
538 hpriv->clks->id = "ahci"; in ahci_platform_get_resources()
539 hpriv->n_clks = 1; in ahci_platform_get_resources()
543 hpriv->ahci_regulator = devm_regulator_get(dev, "ahci"); in ahci_platform_get_resources()
544 if (IS_ERR(hpriv->ahci_regulator)) { in ahci_platform_get_resources()
545 rc = PTR_ERR(hpriv->ahci_regulator); in ahci_platform_get_resources()
550 hpriv->phy_regulator = devm_regulator_get(dev, "phy"); in ahci_platform_get_resources()
551 if (IS_ERR(hpriv->phy_regulator)) { in ahci_platform_get_resources()
552 rc = PTR_ERR(hpriv->phy_regulator); in ahci_platform_get_resources()
557 hpriv->rsts = devm_reset_control_array_get_optional_shared(dev); in ahci_platform_get_resources()
558 if (IS_ERR(hpriv->rsts)) { in ahci_platform_get_resources()
559 rc = PTR_ERR(hpriv->rsts); in ahci_platform_get_resources()
563 hpriv->f_rsts = flags & AHCI_PLATFORM_RST_TRIGGER; in ahci_platform_get_resources()
567 * Too many sub-nodes most likely means having something wrong with in ahci_platform_get_resources()
570 child_nodes = of_get_child_count(dev->of_node); in ahci_platform_get_resources()
572 rc = -EINVAL; in ahci_platform_get_resources()
576 /* find maximum port id for allocating structures */ in ahci_platform_get_resources()
579 * Set nports according to maximum port id. Clamp at in ahci_platform_get_resources()
580 * AHCI_MAX_PORTS, warning message for invalid port id in ahci_platform_get_resources()
582 * When DT has no sub-nodes max_port is 0, nports is 1, in ahci_platform_get_resources()
586 hpriv->nports = min(AHCI_MAX_PORTS, max_port + 1); in ahci_platform_get_resources()
588 hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL); in ahci_platform_get_resources()
589 if (!hpriv->phys) { in ahci_platform_get_resources()
590 rc = -ENOMEM; in ahci_platform_get_resources()
597 hpriv->target_pwrs = kcalloc(hpriv->nports, sizeof(*hpriv->target_pwrs), GFP_KERNEL); in ahci_platform_get_resources()
598 if (!hpriv->target_pwrs) { in ahci_platform_get_resources()
599 rc = -ENOMEM; in ahci_platform_get_resources()
604 for_each_child_of_node_scoped(dev->of_node, child) { in ahci_platform_get_resources()
605 u32 port; in ahci_platform_get_resources() local
611 if (of_property_read_u32(child, "reg", &port)) { in ahci_platform_get_resources()
612 rc = -EINVAL; in ahci_platform_get_resources()
616 if (port >= hpriv->nports) { in ahci_platform_get_resources()
617 dev_warn(dev, "invalid port number %d\n", port); in ahci_platform_get_resources()
620 mask_port_map |= BIT(port); in ahci_platform_get_resources()
628 rc = ahci_platform_get_regulator(hpriv, port, in ahci_platform_get_resources()
629 &port_dev->dev); in ahci_platform_get_resources()
630 if (rc == -EPROBE_DEFER) in ahci_platform_get_resources()
635 rc = ahci_platform_get_phy(hpriv, port, dev, child); in ahci_platform_get_resources()
642 dev_warn(dev, "No port enabled\n"); in ahci_platform_get_resources()
643 rc = -ENODEV; in ahci_platform_get_resources()
647 if (!hpriv->mask_port_map) in ahci_platform_get_resources()
648 hpriv->mask_port_map = mask_port_map; in ahci_platform_get_resources()
651 * If no sub-node was found, keep this for device tree in ahci_platform_get_resources()
654 rc = ahci_platform_get_phy(hpriv, 0, dev, dev->of_node); in ahci_platform_get_resources()
659 if (rc == -EPROBE_DEFER) in ahci_platform_get_resources()
664 * Retrieve firmware-specific flags which then will be used to set in ahci_platform_get_resources()
665 * the HW-init fields of HBA and its ports in ahci_platform_get_resources()
673 hpriv->got_runtime_pm = true; in ahci_platform_get_resources()
685 * ahci_platform_init_host - Bring up an ahci-platform host
686 * @pdev: platform device pointer for the host
687 * @hpriv: ahci-host private data for the host
692 * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
703 struct device *dev = &pdev->dev; in ahci_platform_init_host()
706 struct ata_host *host; in ahci_platform_init_host() local
713 return -EINVAL; in ahci_platform_init_host()
715 hpriv->irq = irq; in ahci_platform_init_host()
717 /* prepare host */ in ahci_platform_init_host()
718 pi.private_data = (void *)(unsigned long)hpriv->flags; in ahci_platform_init_host()
722 if (hpriv->cap & HOST_CAP_NCQ) in ahci_platform_init_host()
725 if (hpriv->cap & HOST_CAP_PMP) in ahci_platform_init_host()
731 * port, at other times, that of the last possible port, so in ahci_platform_init_host()
732 * determining the maximum port number requires looking at in ahci_platform_init_host()
735 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); in ahci_platform_init_host()
737 host = ata_host_alloc_pinfo(dev, ppi, n_ports); in ahci_platform_init_host()
738 if (!host) in ahci_platform_init_host()
739 return -ENOMEM; in ahci_platform_init_host()
741 host->private_data = hpriv; in ahci_platform_init_host()
743 if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) in ahci_platform_init_host()
744 host->flags |= ATA_HOST_PARALLEL_SCAN; in ahci_platform_init_host()
749 ahci_reset_em(host); in ahci_platform_init_host()
751 for (i = 0; i < host->n_ports; i++) { in ahci_platform_init_host()
752 struct ata_port *ap = host->ports[i]; in ahci_platform_init_host()
756 ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); in ahci_platform_init_host()
759 if (ap->flags & ATA_FLAG_EM) in ahci_platform_init_host()
760 ap->em_message_type = hpriv->em_msg_type; in ahci_platform_init_host()
762 /* disabled/not-implemented port */ in ahci_platform_init_host()
763 if (!(hpriv->port_map & (1 << i))) in ahci_platform_init_host()
764 ap->ops = &ata_dummy_port_ops; in ahci_platform_init_host()
767 if (hpriv->cap & HOST_CAP_64) { in ahci_platform_init_host()
770 dev_err(dev, "Failed to enable 64-bit DMA.\n"); in ahci_platform_init_host()
775 rc = ahci_reset_controller(host); in ahci_platform_init_host()
779 ahci_init_controller(host); in ahci_platform_init_host()
780 ahci_print_info(host, "platform"); in ahci_platform_init_host()
782 return ahci_host_activate(host, sht); in ahci_platform_init_host()
786 static void ahci_host_stop(struct ata_host *host) in ahci_host_stop() argument
788 struct ahci_host_priv *hpriv = host->private_data; in ahci_host_stop()
794 * ahci_platform_shutdown - Disable interrupts and stop DMA for host ports
795 * @pdev: platform device pointer for the host
798 * deconfiguration required to ensure that an ahci_platform host cannot
803 struct ata_host *host = platform_get_drvdata(pdev); in ahci_platform_shutdown() local
804 struct ahci_host_priv *hpriv = host->private_data; in ahci_platform_shutdown()
805 void __iomem *mmio = hpriv->mmio; in ahci_platform_shutdown()
808 for (i = 0; i < host->n_ports; i++) { in ahci_platform_shutdown()
809 struct ata_port *ap = host->ports[i]; in ahci_platform_shutdown()
811 /* Disable port interrupts */ in ahci_platform_shutdown()
812 if (ap->ops->freeze) in ahci_platform_shutdown()
813 ap->ops->freeze(ap); in ahci_platform_shutdown()
815 /* Stop the port DMA engines */ in ahci_platform_shutdown()
816 if (ap->ops->port_stop) in ahci_platform_shutdown()
817 ap->ops->port_stop(ap); in ahci_platform_shutdown()
820 /* Disable and clear host interrupts */ in ahci_platform_shutdown()
823 writel(GENMASK(host->n_ports, 0), mmio + HOST_IRQ_STAT); in ahci_platform_shutdown()
829 * ahci_platform_suspend_host - Suspend an ahci-platform host
830 * @dev: device pointer for the host
833 * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
841 struct ata_host *host = dev_get_drvdata(dev); in ahci_platform_suspend_host() local
842 struct ahci_host_priv *hpriv = host->private_data; in ahci_platform_suspend_host()
843 void __iomem *mmio = hpriv->mmio; in ahci_platform_suspend_host()
846 if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { in ahci_platform_suspend_host()
848 return -EIO; in ahci_platform_suspend_host()
861 if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS) in ahci_platform_suspend_host()
864 ata_host_suspend(host, PMSG_SUSPEND); in ahci_platform_suspend_host()
870 * ahci_platform_resume_host - Resume an ahci-platform host
871 * @dev: device pointer for the host
873 * This function does all the usual steps needed to resume an ahci-platform
874 * host, note any necessary resources (ie clks, phys, etc.) must be
882 struct ata_host *host = dev_get_drvdata(dev); in ahci_platform_resume_host() local
883 struct ahci_host_priv *hpriv = host->private_data; in ahci_platform_resume_host()
886 if (dev->power.power_state.event == PM_EVENT_SUSPEND) { in ahci_platform_resume_host()
887 rc = ahci_reset_controller(host); in ahci_platform_resume_host()
891 ahci_init_controller(host); in ahci_platform_resume_host()
894 if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS) in ahci_platform_resume_host()
897 ata_host_resume(host); in ahci_platform_resume_host()
904 * ahci_platform_suspend - Suspend an ahci-platform device
907 * This function suspends the host associated with the device, followed by
915 struct ata_host *host = dev_get_drvdata(dev); in ahci_platform_suspend() local
916 struct ahci_host_priv *hpriv = host->private_data; in ahci_platform_suspend()
930 * ahci_platform_resume - Resume an ahci-platform device
934 * resuming the host associated with the device.
941 struct ata_host *host = dev_get_drvdata(dev); in ahci_platform_resume() local
942 struct ahci_host_priv *hpriv = host->private_data; in ahci_platform_resume()