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
30 #include <linux/pci-ecam.h>
42 #define CORE_LANE_CFG(port) (0x84000 + 0x4000 * (port)) argument
48 #define CORE_LANE_CTL(port) (0x84004 + 0x4000 * (port)) argument
126 * address (in the bottom 4GB, as the base register is only 32bit).
135 void __iomem *base; member
147 void __iomem *base; member
188 msg->address_hi = upper_32_bits(DOORBELL_ADDR); in apple_msi_compose_msg()
189 msg->address_lo = lower_32_bits(DOORBELL_ADDR); in apple_msi_compose_msg()
190 msg->data = data->hwirq; in apple_msi_compose_msg()
206 struct apple_pcie *pcie = domain->host_data; in apple_msi_domain_alloc()
207 struct irq_fwspec fwspec = pcie->fwspec; in apple_msi_domain_alloc()
211 mutex_lock(&pcie->lock); in apple_msi_domain_alloc()
213 hwirq = bitmap_find_free_region(pcie->bitmap, pcie->nvecs, in apple_msi_domain_alloc()
216 mutex_unlock(&pcie->lock); in apple_msi_domain_alloc()
219 return -ENOSPC; in apple_msi_domain_alloc()
221 fwspec.param[fwspec.param_count - 2] += hwirq; in apple_msi_domain_alloc()
230 domain->host_data); in apple_msi_domain_alloc()
240 struct apple_pcie *pcie = domain->host_data; in apple_msi_domain_free()
242 mutex_lock(&pcie->lock); in apple_msi_domain_free()
244 bitmap_release_region(pcie->bitmap, d->hwirq, order_base_2(nr_irqs)); in apple_msi_domain_free()
246 mutex_unlock(&pcie->lock); in apple_msi_domain_free()
262 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_mask() local
264 writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKSET); in apple_port_irq_mask()
269 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_unmask() local
271 writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKCLR); in apple_port_irq_unmask()
281 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_ack() local
283 if (!hwirq_is_intx(data->hwirq)) in apple_port_irq_ack()
284 writel_relaxed(BIT(data->hwirq), port->base + PORT_INTSTAT); in apple_port_irq_ack()
294 if (hwirq_is_intx(data->hwirq) ^ !!(type & IRQ_TYPE_LEVEL_MASK)) in apple_port_irq_set_type()
295 return -EINVAL; in apple_port_irq_set_type()
313 struct apple_pcie_port *port = domain->host_data; in apple_port_irq_domain_alloc() local
321 if (hwirq_is_intx(fwspec->param[0] + i)) { in apple_port_irq_domain_alloc()
326 irq_domain_set_info(domain, virq + i, fwspec->param[0] + i, in apple_port_irq_domain_alloc()
327 &apple_port_irqchip, port, flow, in apple_port_irq_domain_alloc()
357 struct apple_pcie_port *port = irq_desc_get_handler_data(desc); in apple_port_irq_handler() local
364 stat = readl_relaxed(port->base + PORT_INTSTAT); in apple_port_irq_handler()
367 generic_handle_domain_irq(port->domain, i); in apple_port_irq_handler()
372 static int apple_pcie_port_setup_irq(struct apple_pcie_port *port) in apple_pcie_port_setup_irq() argument
374 struct fwnode_handle *fwnode = &port->np->fwnode; in apple_pcie_port_setup_irq()
377 /* FIXME: consider moving each interrupt under each port */ in apple_pcie_port_setup_irq()
378 irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)), in apple_pcie_port_setup_irq()
379 port->idx); in apple_pcie_port_setup_irq()
381 return -ENXIO; in apple_pcie_port_setup_irq()
383 port->domain = irq_domain_create_linear(fwnode, 32, in apple_pcie_port_setup_irq()
385 port); in apple_pcie_port_setup_irq()
386 if (!port->domain) in apple_pcie_port_setup_irq()
387 return -ENOMEM; in apple_pcie_port_setup_irq()
390 writel_relaxed(~0, port->base + PORT_INTMSKSET); in apple_pcie_port_setup_irq()
391 writel_relaxed(~0, port->base + PORT_INTSTAT); in apple_pcie_port_setup_irq()
393 irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port); in apple_pcie_port_setup_irq()
395 /* Configure MSI base address */ in apple_pcie_port_setup_irq()
397 writel_relaxed(lower_32_bits(DOORBELL_ADDR), port->base + PORT_MSIADDR); in apple_pcie_port_setup_irq()
400 writel_relaxed(0, port->base + PORT_MSIBASE); in apple_pcie_port_setup_irq()
401 writel_relaxed((ilog2(port->pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT) | in apple_pcie_port_setup_irq()
402 PORT_MSICFG_EN, port->base + PORT_MSICFG); in apple_pcie_port_setup_irq()
409 struct apple_pcie_port *port = data; in apple_pcie_port_irq() local
410 unsigned int hwirq = irq_domain_get_irq_data(port->domain, irq)->hwirq; in apple_pcie_port_irq()
414 dev_info_ratelimited(port->pcie->dev, "Link up on %pOF\n", in apple_pcie_port_irq()
415 port->np); in apple_pcie_port_irq()
416 complete_all(&port->pcie->event); in apple_pcie_port_irq()
419 dev_info_ratelimited(port->pcie->dev, "Link down on %pOF\n", in apple_pcie_port_irq()
420 port->np); in apple_pcie_port_irq()
429 static int apple_pcie_port_register_irqs(struct apple_pcie_port *port) in apple_pcie_port_register_irqs() argument
442 .fwnode = &port->np->fwnode, in apple_pcie_port_register_irqs()
451 irq = irq_domain_alloc_irqs(port->domain, 1, NUMA_NO_NODE, in apple_pcie_port_register_irqs()
457 port_irqs[i].name, port); in apple_pcie_port_register_irqs()
465 struct apple_pcie_port *port) in apple_pcie_setup_refclk() argument
470 res = readl_relaxed_poll_timeout(pcie->base + CORE_RC_PHYIF_STAT, stat, in apple_pcie_setup_refclk()
476 rmw_set(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx)); in apple_pcie_setup_refclk()
477 rmw_set(CORE_LANE_CFG_REFCLK0REQ, pcie->base + CORE_LANE_CFG(port->idx)); in apple_pcie_setup_refclk()
479 res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx), in apple_pcie_setup_refclk()
485 rmw_set(CORE_LANE_CFG_REFCLK1REQ, pcie->base + CORE_LANE_CFG(port->idx)); in apple_pcie_setup_refclk()
486 res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx), in apple_pcie_setup_refclk()
493 rmw_clear(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx)); in apple_pcie_setup_refclk()
495 rmw_set(CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx)); in apple_pcie_setup_refclk()
496 rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK); in apple_pcie_setup_refclk()
501 static u32 apple_pcie_rid2sid_write(struct apple_pcie_port *port, in apple_pcie_rid2sid_write() argument
504 writel_relaxed(val, port->base + PORT_RID2SID(idx)); in apple_pcie_rid2sid_write()
506 return readl_relaxed(port->base + PORT_RID2SID(idx)); in apple_pcie_rid2sid_write()
512 struct platform_device *platform = to_platform_device(pcie->dev); in apple_pcie_setup_port()
513 struct apple_pcie_port *port; in apple_pcie_setup_port() local
518 reset = devm_fwnode_gpiod_get(pcie->dev, of_fwnode_handle(np), "reset", in apple_pcie_setup_port()
523 port = devm_kzalloc(pcie->dev, sizeof(*port), GFP_KERNEL); in apple_pcie_setup_port()
524 if (!port) in apple_pcie_setup_port()
525 return -ENOMEM; in apple_pcie_setup_port()
531 /* Use the first reg entry to work out the port index */ in apple_pcie_setup_port()
532 port->idx = idx >> 11; in apple_pcie_setup_port()
533 port->pcie = pcie; in apple_pcie_setup_port()
534 port->np = np; in apple_pcie_setup_port()
536 port->base = devm_platform_ioremap_resource(platform, port->idx + 2); in apple_pcie_setup_port()
537 if (IS_ERR(port->base)) in apple_pcie_setup_port()
538 return PTR_ERR(port->base); in apple_pcie_setup_port()
540 rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK); in apple_pcie_setup_port()
545 ret = apple_pcie_setup_refclk(pcie, port); in apple_pcie_setup_port()
549 /* The minimal Tperst-clk value is 100us (PCIe CEM r5.0, 2.9.2) */ in apple_pcie_setup_port()
553 rmw_set(PORT_PERST_OFF, port->base + PORT_PERST); in apple_pcie_setup_port()
559 ret = readl_relaxed_poll_timeout(port->base + PORT_STATUS, stat, in apple_pcie_setup_port()
562 dev_err(pcie->dev, "port %pOF ready wait timeout\n", np); in apple_pcie_setup_port()
566 rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK); in apple_pcie_setup_port()
567 rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK); in apple_pcie_setup_port()
569 ret = apple_pcie_port_setup_irq(port); in apple_pcie_setup_port()
575 if (apple_pcie_rid2sid_write(port, i, 0xbad1d) != 0xbad1d) in apple_pcie_setup_port()
577 apple_pcie_rid2sid_write(port, i, 0); in apple_pcie_setup_port()
580 dev_dbg(pcie->dev, "%pOF: %d RID/SID mapping entries\n", np, i); in apple_pcie_setup_port()
582 port->sid_map_sz = i; in apple_pcie_setup_port()
584 list_add_tail(&port->entry, &pcie->ports); in apple_pcie_setup_port()
585 init_completion(&pcie->event); in apple_pcie_setup_port()
587 ret = apple_pcie_port_register_irqs(port); in apple_pcie_setup_port()
590 writel_relaxed(PORT_LTSSMCTL_START, port->base + PORT_LTSSMCTL); in apple_pcie_setup_port()
592 if (!wait_for_completion_timeout(&pcie->event, HZ / 10)) in apple_pcie_setup_port()
593 dev_warn(pcie->dev, "%pOF link didn't come up\n", np); in apple_pcie_setup_port()
600 struct fwnode_handle *fwnode = dev_fwnode(pcie->dev); in apple_msi_init()
605 ret = of_parse_phandle_with_args(to_of_node(fwnode), "msi-ranges", in apple_msi_init()
606 "#interrupt-cells", 0, &args); in apple_msi_init()
610 ret = of_property_read_u32_index(to_of_node(fwnode), "msi-ranges", in apple_msi_init()
611 args.args_count + 1, &pcie->nvecs); in apple_msi_init()
616 &pcie->fwspec); in apple_msi_init()
618 pcie->bitmap = devm_bitmap_zalloc(pcie->dev, pcie->nvecs, GFP_KERNEL); in apple_msi_init()
619 if (!pcie->bitmap) in apple_msi_init()
620 return -ENOMEM; in apple_msi_init()
622 parent = irq_find_matching_fwspec(&pcie->fwspec, DOMAIN_BUS_WIRED); in apple_msi_init()
624 dev_err(pcie->dev, "failed to find parent domain\n"); in apple_msi_init()
625 return -ENXIO; in apple_msi_init()
628 parent = irq_domain_create_hierarchy(parent, 0, pcie->nvecs, fwnode, in apple_msi_init()
631 dev_err(pcie->dev, "failed to create IRQ domain\n"); in apple_msi_init()
632 return -ENOMEM; in apple_msi_init()
636 pcie->domain = pci_msi_create_irq_domain(fwnode, &apple_msi_info, in apple_msi_init()
638 if (!pcie->domain) { in apple_msi_init()
639 dev_err(pcie->dev, "failed to create MSI domain\n"); in apple_msi_init()
641 return -ENOMEM; in apple_msi_init()
649 struct pci_config_window *cfg = pdev->sysdata; in apple_pcie_get_port()
650 struct apple_pcie *pcie = cfg->priv; in apple_pcie_get_port()
652 struct apple_pcie_port *port; in apple_pcie_get_port() local
654 /* Find the root port this device is on */ in apple_pcie_get_port()
657 /* If finding the port itself, nothing to do */ in apple_pcie_get_port()
661 list_for_each_entry(port, &pcie->ports, entry) { in apple_pcie_get_port()
662 if (port->idx == PCI_SLOT(port_pdev->devfn)) in apple_pcie_get_port()
663 return port; in apple_pcie_get_port()
672 struct apple_pcie_port *port; in apple_pcie_enable_device() local
675 port = apple_pcie_get_port(pdev); in apple_pcie_enable_device()
676 if (!port) in apple_pcie_enable_device()
679 dev_dbg(&pdev->dev, "added to bus %s, index %d\n", in apple_pcie_enable_device()
680 pci_name(pdev->bus->self), port->idx); in apple_pcie_enable_device()
682 err = of_map_id(port->pcie->dev->of_node, rid, "iommu-map", in apple_pcie_enable_device()
683 "iommu-map-mask", NULL, &sid); in apple_pcie_enable_device()
687 mutex_lock(&port->pcie->lock); in apple_pcie_enable_device()
689 idx = bitmap_find_free_region(port->sid_map, port->sid_map_sz, 0); in apple_pcie_enable_device()
691 apple_pcie_rid2sid_write(port, idx, in apple_pcie_enable_device()
695 dev_dbg(&pdev->dev, "mapping RID%x to SID%x (index %d)\n", in apple_pcie_enable_device()
699 mutex_unlock(&port->pcie->lock); in apple_pcie_enable_device()
701 return idx >= 0 ? 0 : -ENOSPC; in apple_pcie_enable_device()
706 struct apple_pcie_port *port; in apple_pcie_disable_device() local
710 port = apple_pcie_get_port(pdev); in apple_pcie_disable_device()
711 if (!port) in apple_pcie_disable_device()
714 mutex_lock(&port->pcie->lock); in apple_pcie_disable_device()
716 for_each_set_bit(idx, port->sid_map, port->sid_map_sz) { in apple_pcie_disable_device()
719 val = readl_relaxed(port->base + PORT_RID2SID(idx)); in apple_pcie_disable_device()
721 apple_pcie_rid2sid_write(port, idx, 0); in apple_pcie_disable_device()
722 bitmap_release_region(port->sid_map, idx, 0); in apple_pcie_disable_device()
723 dev_dbg(&pdev->dev, "Released %x (%d)\n", val, idx); in apple_pcie_disable_device()
728 mutex_unlock(&port->pcie->lock); in apple_pcie_disable_device()
733 struct device *dev = cfg->parent; in apple_pcie_init()
740 return -ENOMEM; in apple_pcie_init()
742 pcie->dev = dev; in apple_pcie_init()
744 mutex_init(&pcie->lock); in apple_pcie_init()
746 pcie->base = devm_platform_ioremap_resource(platform, 1); in apple_pcie_init()
747 if (IS_ERR(pcie->base)) in apple_pcie_init()
748 return PTR_ERR(pcie->base); in apple_pcie_init()
750 cfg->priv = pcie; in apple_pcie_init()
751 INIT_LIST_HEAD(&pcie->ports); in apple_pcie_init()
757 for_each_child_of_node_scoped(dev->of_node, of_port) { in apple_pcie_init()
760 dev_err(pcie->dev, "Port %pOF setup fail: %d\n", of_port, ret); in apple_pcie_init()
788 .name = "pcie-apple",