Lines Matching +full:port +full:- +full:base

1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe host bridge driver for Apple system-on-chips.
6 * the driver mostly deals MSI mapping and handling of per-port
26 #include <linux/irqchip/irq-msi-lib.h>
32 #include <linux/pci-ecam.h>
34 #include "pci-host-common.h"
48 #define CORE_PHY_DEFAULT_BASE(port) (0x84000 + 0x4000 * (port)) argument
130 /* T602x (M2-pro and co) */
143 * address (in the bottom 4GB, as the base register is only 32bit).
186 void __iomem *base; member
200 void __iomem *base; member
224 msg->address_hi = upper_32_bits(DOORBELL_ADDR); in apple_msi_compose_msg()
225 msg->address_lo = lower_32_bits(DOORBELL_ADDR); in apple_msi_compose_msg()
226 msg->data = data->hwirq; in apple_msi_compose_msg()
242 struct apple_pcie *pcie = domain->host_data; in apple_msi_domain_alloc()
243 struct irq_fwspec fwspec = pcie->fwspec; in apple_msi_domain_alloc()
247 mutex_lock(&pcie->lock); in apple_msi_domain_alloc()
249 hwirq = bitmap_find_free_region(pcie->bitmap, pcie->nvecs, in apple_msi_domain_alloc()
252 mutex_unlock(&pcie->lock); in apple_msi_domain_alloc()
255 return -ENOSPC; in apple_msi_domain_alloc()
257 fwspec.param[fwspec.param_count - 2] += hwirq; in apple_msi_domain_alloc()
275 struct apple_pcie *pcie = domain->host_data; in apple_msi_domain_free()
277 mutex_lock(&pcie->lock); in apple_msi_domain_free()
279 bitmap_release_region(pcie->bitmap, d->hwirq, order_base_2(nr_irqs)); in apple_msi_domain_free()
281 mutex_unlock(&pcie->lock); in apple_msi_domain_free()
291 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_mask() local
293 guard(raw_spinlock_irqsave)(&port->lock); in apple_port_irq_mask()
294 rmw_set(BIT(data->hwirq), port->base + PORT_INTMSK); in apple_port_irq_mask()
299 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_unmask() local
301 guard(raw_spinlock_irqsave)(&port->lock); in apple_port_irq_unmask()
302 rmw_clear(BIT(data->hwirq), port->base + PORT_INTMSK); in apple_port_irq_unmask()
312 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_ack() local
314 if (!hwirq_is_intx(data->hwirq)) in apple_port_irq_ack()
315 writel_relaxed(BIT(data->hwirq), port->base + PORT_INTSTAT); in apple_port_irq_ack()
325 if (hwirq_is_intx(data->hwirq) ^ !!(type & IRQ_TYPE_LEVEL_MASK)) in apple_port_irq_set_type()
326 return -EINVAL; in apple_port_irq_set_type()
344 struct apple_pcie_port *port = domain->host_data; in apple_port_irq_domain_alloc() local
352 if (hwirq_is_intx(fwspec->param[0] + i)) { in apple_port_irq_domain_alloc()
357 irq_domain_set_info(domain, virq + i, fwspec->param[0] + i, in apple_port_irq_domain_alloc()
358 &apple_port_irqchip, port, flow, in apple_port_irq_domain_alloc()
388 struct apple_pcie_port *port = irq_desc_get_handler_data(desc); in apple_port_irq_handler() local
395 stat = readl_relaxed(port->base + PORT_INTSTAT); in apple_port_irq_handler()
398 generic_handle_domain_irq(port->domain, i); in apple_port_irq_handler()
403 static int apple_pcie_port_setup_irq(struct apple_pcie_port *port) in apple_pcie_port_setup_irq() argument
405 struct fwnode_handle *fwnode = &port->np->fwnode; in apple_pcie_port_setup_irq()
406 struct apple_pcie *pcie = port->pcie; in apple_pcie_port_setup_irq()
410 /* FIXME: consider moving each interrupt under each port */ in apple_pcie_port_setup_irq()
411 irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)), in apple_pcie_port_setup_irq()
412 port->idx); in apple_pcie_port_setup_irq()
414 return -ENXIO; in apple_pcie_port_setup_irq()
416 port->domain = irq_domain_create_linear(fwnode, 32, in apple_pcie_port_setup_irq()
418 port); in apple_pcie_port_setup_irq()
419 if (!port->domain) in apple_pcie_port_setup_irq()
420 return -ENOMEM; in apple_pcie_port_setup_irq()
423 writel_relaxed(~0, port->base + PORT_INTMSK); in apple_pcie_port_setup_irq()
424 writel_relaxed(~0, port->base + PORT_INTSTAT); in apple_pcie_port_setup_irq()
425 writel_relaxed(~0, port->base + PORT_LINKCMDSTS); in apple_pcie_port_setup_irq()
427 irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port); in apple_pcie_port_setup_irq()
429 /* Configure MSI base address */ in apple_pcie_port_setup_irq()
432 port->base + pcie->hw->port_msiaddr); in apple_pcie_port_setup_irq()
433 if (pcie->hw->port_msiaddr_hi) in apple_pcie_port_setup_irq()
434 writel_relaxed(0, port->base + pcie->hw->port_msiaddr_hi); in apple_pcie_port_setup_irq()
437 if (pcie->hw->port_msimap) { in apple_pcie_port_setup_irq()
438 for (int i = 0; i < pcie->nvecs; i++) in apple_pcie_port_setup_irq()
441 port->base + pcie->hw->port_msimap + 4 * i); in apple_pcie_port_setup_irq()
443 writel_relaxed(0, port->base + PORT_MSIBASE); in apple_pcie_port_setup_irq()
444 val = ilog2(pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT; in apple_pcie_port_setup_irq()
447 writel_relaxed(val | PORT_MSICFG_EN, port->base + PORT_MSICFG); in apple_pcie_port_setup_irq()
453 struct apple_pcie_port *port = data; in apple_pcie_port_irq() local
454 unsigned int hwirq = irq_domain_get_irq_data(port->domain, irq)->hwirq; in apple_pcie_port_irq()
458 dev_info_ratelimited(port->pcie->dev, "Link up on %pOF\n", in apple_pcie_port_irq()
459 port->np); in apple_pcie_port_irq()
460 complete_all(&port->pcie->event); in apple_pcie_port_irq()
463 dev_info_ratelimited(port->pcie->dev, "Link down on %pOF\n", in apple_pcie_port_irq()
464 port->np); in apple_pcie_port_irq()
473 static int apple_pcie_port_register_irqs(struct apple_pcie_port *port) in apple_pcie_port_register_irqs() argument
486 .fwnode = &port->np->fwnode, in apple_pcie_port_register_irqs()
495 irq = irq_domain_alloc_irqs(port->domain, 1, NUMA_NO_NODE, in apple_pcie_port_register_irqs()
501 port_irqs[i].name, port); in apple_pcie_port_register_irqs()
509 struct apple_pcie_port *port) in apple_pcie_setup_refclk() argument
514 if (pcie->hw->phy_lane_ctl) in apple_pcie_setup_refclk()
515 rmw_set(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl); in apple_pcie_setup_refclk()
517 rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG); in apple_pcie_setup_refclk()
519 res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG, in apple_pcie_setup_refclk()
525 rmw_set(PHY_LANE_CFG_REFCLK1REQ, port->phy + PHY_LANE_CFG); in apple_pcie_setup_refclk()
526 res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG, in apple_pcie_setup_refclk()
533 if (pcie->hw->phy_lane_ctl) in apple_pcie_setup_refclk()
534 rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl); in apple_pcie_setup_refclk()
536 rmw_set(PHY_LANE_CFG_REFCLKEN, port->phy + PHY_LANE_CFG); in apple_pcie_setup_refclk()
538 if (pcie->hw->port_refclk) in apple_pcie_setup_refclk()
539 rmw_set(PORT_REFCLK_EN, port->base + pcie->hw->port_refclk); in apple_pcie_setup_refclk()
544 static void __iomem *port_rid2sid_addr(struct apple_pcie_port *port, int idx) in port_rid2sid_addr() argument
546 return port->base + port->pcie->hw->port_rid2sid + 4 * idx; in port_rid2sid_addr()
549 static u32 apple_pcie_rid2sid_write(struct apple_pcie_port *port, in apple_pcie_rid2sid_write() argument
552 writel_relaxed(val, port_rid2sid_addr(port, idx)); in apple_pcie_rid2sid_write()
554 return readl_relaxed(port_rid2sid_addr(port, idx)); in apple_pcie_rid2sid_write()
560 struct platform_device *platform = to_platform_device(pcie->dev); in apple_pcie_setup_port()
561 struct apple_pcie_port *port; in apple_pcie_setup_port() local
568 reset = devm_fwnode_gpiod_get(pcie->dev, of_fwnode_handle(np), "reset", in apple_pcie_setup_port()
573 port = devm_kzalloc(pcie->dev, sizeof(*port), GFP_KERNEL); in apple_pcie_setup_port()
574 if (!port) in apple_pcie_setup_port()
575 return -ENOMEM; in apple_pcie_setup_port()
577 port->sid_map = devm_bitmap_zalloc(pcie->dev, pcie->hw->max_rid2sid, GFP_KERNEL); in apple_pcie_setup_port()
578 if (!port->sid_map) in apple_pcie_setup_port()
579 return -ENOMEM; in apple_pcie_setup_port()
585 /* Use the first reg entry to work out the port index */ in apple_pcie_setup_port()
586 port->idx = idx >> 11; in apple_pcie_setup_port()
587 port->pcie = pcie; in apple_pcie_setup_port()
588 port->np = np; in apple_pcie_setup_port()
590 raw_spin_lock_init(&port->lock); in apple_pcie_setup_port()
592 snprintf(name, sizeof(name), "port%d", port->idx); in apple_pcie_setup_port()
595 res = platform_get_resource(platform, IORESOURCE_MEM, port->idx + 2); in apple_pcie_setup_port()
597 port->base = devm_ioremap_resource(&platform->dev, res); in apple_pcie_setup_port()
598 if (IS_ERR(port->base)) in apple_pcie_setup_port()
599 return PTR_ERR(port->base); in apple_pcie_setup_port()
601 snprintf(name, sizeof(name), "phy%d", port->idx); in apple_pcie_setup_port()
604 port->phy = devm_ioremap_resource(&platform->dev, res); in apple_pcie_setup_port()
606 port->phy = pcie->base + CORE_PHY_DEFAULT_BASE(port->idx); in apple_pcie_setup_port()
608 rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK); in apple_pcie_setup_port()
613 ret = apple_pcie_setup_refclk(pcie, port); in apple_pcie_setup_port()
617 /* The minimal Tperst-clk value is 100us (PCIe CEM r5.0, 2.9.2) */ in apple_pcie_setup_port()
621 rmw_set(PORT_PERST_OFF, port->base + pcie->hw->port_perst); in apple_pcie_setup_port()
627 ret = readl_relaxed_poll_timeout(port->base + PORT_STATUS, stat, in apple_pcie_setup_port()
630 dev_err(pcie->dev, "port %pOF ready wait timeout\n", np); in apple_pcie_setup_port()
634 if (pcie->hw->port_refclk) in apple_pcie_setup_port()
635 rmw_clear(PORT_REFCLK_CGDIS, port->base + pcie->hw->port_refclk); in apple_pcie_setup_port()
637 rmw_set(PHY_LANE_CFG_REFCLKCGEN, port->phy + PHY_LANE_CFG); in apple_pcie_setup_port()
639 rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK); in apple_pcie_setup_port()
641 ret = apple_pcie_port_setup_irq(port); in apple_pcie_setup_port()
646 for (i = 0; i < pcie->hw->max_rid2sid; i++) { in apple_pcie_setup_port()
647 if (apple_pcie_rid2sid_write(port, i, 0xbad1d) != 0xbad1d) in apple_pcie_setup_port()
649 apple_pcie_rid2sid_write(port, i, 0); in apple_pcie_setup_port()
652 dev_dbg(pcie->dev, "%pOF: %d RID/SID mapping entries\n", np, i); in apple_pcie_setup_port()
654 port->sid_map_sz = i; in apple_pcie_setup_port()
656 list_add_tail(&port->entry, &pcie->ports); in apple_pcie_setup_port()
657 init_completion(&pcie->event); in apple_pcie_setup_port()
662 ret = apple_pcie_port_register_irqs(port); in apple_pcie_setup_port()
665 writel_relaxed(PORT_LTSSMCTL_START, port->base + PORT_LTSSMCTL); in apple_pcie_setup_port()
667 if (!wait_for_completion_timeout(&pcie->event, HZ / 10)) in apple_pcie_setup_port()
668 dev_warn(pcie->dev, "%pOF link didn't come up\n", np); in apple_pcie_setup_port()
687 struct fwnode_handle *fwnode = dev_fwnode(pcie->dev); in apple_msi_init()
691 .size = pcie->nvecs, in apple_msi_init()
697 ret = of_parse_phandle_with_args(to_of_node(fwnode), "msi-ranges", in apple_msi_init()
698 "#interrupt-cells", 0, &args); in apple_msi_init()
702 ret = of_property_read_u32_index(to_of_node(fwnode), "msi-ranges", in apple_msi_init()
703 args.args_count + 1, &pcie->nvecs); in apple_msi_init()
708 &pcie->fwspec); in apple_msi_init()
710 pcie->bitmap = devm_bitmap_zalloc(pcie->dev, pcie->nvecs, GFP_KERNEL); in apple_msi_init()
711 if (!pcie->bitmap) in apple_msi_init()
712 return -ENOMEM; in apple_msi_init()
714 info.parent = irq_find_matching_fwspec(&pcie->fwspec, DOMAIN_BUS_WIRED); in apple_msi_init()
716 dev_err(pcie->dev, "failed to find parent domain\n"); in apple_msi_init()
717 return -ENXIO; in apple_msi_init()
721 dev_err(pcie->dev, "failed to create IRQ domain\n"); in apple_msi_init()
722 return -ENOMEM; in apple_msi_init()
731 list_add_tail(&pcie->entry, &pcie_list); in apple_pcie_register()
738 list_del(&pcie->entry); in apple_pcie_unregister()
748 if (pcie->dev == dev) in apple_pcie_lookup()
757 struct pci_config_window *cfg = pdev->sysdata; in apple_pcie_get_port()
760 struct apple_pcie_port *port; in apple_pcie_get_port() local
762 pcie = apple_pcie_lookup(cfg->parent); in apple_pcie_get_port()
766 /* Find the root port this device is on */ in apple_pcie_get_port()
769 /* If finding the port itself, nothing to do */ in apple_pcie_get_port()
773 list_for_each_entry(port, &pcie->ports, entry) { in apple_pcie_get_port()
774 if (port->idx == PCI_SLOT(port_pdev->devfn)) in apple_pcie_get_port()
775 return port; in apple_pcie_get_port()
784 struct apple_pcie_port *port; in apple_pcie_enable_device() local
787 port = apple_pcie_get_port(pdev); in apple_pcie_enable_device()
788 if (!port) in apple_pcie_enable_device()
791 dev_dbg(&pdev->dev, "added to bus %s, index %d\n", in apple_pcie_enable_device()
792 pci_name(pdev->bus->self), port->idx); in apple_pcie_enable_device()
794 err = of_map_id(port->pcie->dev->of_node, rid, "iommu-map", in apple_pcie_enable_device()
795 "iommu-map-mask", NULL, &sid); in apple_pcie_enable_device()
799 mutex_lock(&port->pcie->lock); in apple_pcie_enable_device()
801 idx = bitmap_find_free_region(port->sid_map, port->sid_map_sz, 0); in apple_pcie_enable_device()
803 apple_pcie_rid2sid_write(port, idx, in apple_pcie_enable_device()
807 dev_dbg(&pdev->dev, "mapping RID%x to SID%x (index %d)\n", in apple_pcie_enable_device()
811 mutex_unlock(&port->pcie->lock); in apple_pcie_enable_device()
813 return idx >= 0 ? 0 : -ENOSPC; in apple_pcie_enable_device()
818 struct apple_pcie_port *port; in apple_pcie_disable_device() local
822 port = apple_pcie_get_port(pdev); in apple_pcie_disable_device()
823 if (!port) in apple_pcie_disable_device()
826 mutex_lock(&port->pcie->lock); in apple_pcie_disable_device()
828 for_each_set_bit(idx, port->sid_map, port->sid_map_sz) { in apple_pcie_disable_device()
831 val = readl_relaxed(port_rid2sid_addr(port, idx)); in apple_pcie_disable_device()
833 apple_pcie_rid2sid_write(port, idx, 0); in apple_pcie_disable_device()
834 bitmap_release_region(port->sid_map, idx, 0); in apple_pcie_disable_device()
835 dev_dbg(&pdev->dev, "Released %x (%d)\n", val, idx); in apple_pcie_disable_device()
840 mutex_unlock(&port->pcie->lock); in apple_pcie_disable_device()
845 struct device *dev = cfg->parent; in apple_pcie_init()
851 return -ENOENT; in apple_pcie_init()
853 for_each_available_child_of_node_scoped(dev->of_node, of_port) { in apple_pcie_init()
856 dev_err(dev, "Port %pOF setup fail: %d\n", of_port, ret); in apple_pcie_init()
877 struct device *dev = &pdev->dev; in apple_pcie_probe()
883 return -ENOMEM; in apple_pcie_probe()
885 pcie->dev = dev; in apple_pcie_probe()
886 pcie->hw = of_device_get_match_data(dev); in apple_pcie_probe()
887 if (!pcie->hw) in apple_pcie_probe()
888 return -ENODEV; in apple_pcie_probe()
889 pcie->base = devm_platform_ioremap_resource(pdev, 1); in apple_pcie_probe()
890 if (IS_ERR(pcie->base)) in apple_pcie_probe()
891 return PTR_ERR(pcie->base); in apple_pcie_probe()
893 mutex_init(&pcie->lock); in apple_pcie_probe()
894 INIT_LIST_HEAD(&pcie->ports); in apple_pcie_probe()
910 { .compatible = "apple,t6020-pcie", .data = &t602x_hw },
919 .name = "pcie-apple",