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
31 #include <linux/pci-ecam.h>
43 #define CORE_LANE_CFG(port) (0x84000 + 0x4000 * (port)) argument
49 #define CORE_LANE_CTL(port) (0x84004 + 0x4000 * (port)) argument
127 * address (in the bottom 4GB, as the base register is only 32bit).
136 void __iomem *base; member
148 void __iomem *base; member
189 msg->address_hi = upper_32_bits(DOORBELL_ADDR); in apple_msi_compose_msg()
190 msg->address_lo = lower_32_bits(DOORBELL_ADDR); in apple_msi_compose_msg()
191 msg->data = data->hwirq; in apple_msi_compose_msg()
207 struct apple_pcie *pcie = domain->host_data; in apple_msi_domain_alloc()
208 struct irq_fwspec fwspec = pcie->fwspec; in apple_msi_domain_alloc()
212 mutex_lock(&pcie->lock); in apple_msi_domain_alloc()
214 hwirq = bitmap_find_free_region(pcie->bitmap, pcie->nvecs, in apple_msi_domain_alloc()
217 mutex_unlock(&pcie->lock); in apple_msi_domain_alloc()
220 return -ENOSPC; in apple_msi_domain_alloc()
222 fwspec.param[fwspec.param_count - 2] += hwirq; in apple_msi_domain_alloc()
231 domain->host_data); in apple_msi_domain_alloc()
241 struct apple_pcie *pcie = domain->host_data; in apple_msi_domain_free()
243 mutex_lock(&pcie->lock); in apple_msi_domain_free()
245 bitmap_release_region(pcie->bitmap, d->hwirq, order_base_2(nr_irqs)); in apple_msi_domain_free()
247 mutex_unlock(&pcie->lock); in apple_msi_domain_free()
263 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_mask() local
265 writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKSET); in apple_port_irq_mask()
270 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_unmask() local
272 writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKCLR); in apple_port_irq_unmask()
282 struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); in apple_port_irq_ack() local
284 if (!hwirq_is_intx(data->hwirq)) in apple_port_irq_ack()
285 writel_relaxed(BIT(data->hwirq), port->base + PORT_INTSTAT); in apple_port_irq_ack()
295 if (hwirq_is_intx(data->hwirq) ^ !!(type & IRQ_TYPE_LEVEL_MASK)) in apple_port_irq_set_type()
296 return -EINVAL; in apple_port_irq_set_type()
314 struct apple_pcie_port *port = domain->host_data; in apple_port_irq_domain_alloc() local
322 if (hwirq_is_intx(fwspec->param[0] + i)) { in apple_port_irq_domain_alloc()
327 irq_domain_set_info(domain, virq + i, fwspec->param[0] + i, in apple_port_irq_domain_alloc()
328 &apple_port_irqchip, port, flow, in apple_port_irq_domain_alloc()
358 struct apple_pcie_port *port = irq_desc_get_handler_data(desc); in apple_port_irq_handler() local
365 stat = readl_relaxed(port->base + PORT_INTSTAT); in apple_port_irq_handler()
368 generic_handle_domain_irq(port->domain, i); in apple_port_irq_handler()
373 static int apple_pcie_port_setup_irq(struct apple_pcie_port *port) in apple_pcie_port_setup_irq() argument
375 struct fwnode_handle *fwnode = &port->np->fwnode; in apple_pcie_port_setup_irq()
378 /* FIXME: consider moving each interrupt under each port */ in apple_pcie_port_setup_irq()
379 irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)), in apple_pcie_port_setup_irq()
380 port->idx); in apple_pcie_port_setup_irq()
382 return -ENXIO; in apple_pcie_port_setup_irq()
384 port->domain = irq_domain_create_linear(fwnode, 32, in apple_pcie_port_setup_irq()
386 port); in apple_pcie_port_setup_irq()
387 if (!port->domain) in apple_pcie_port_setup_irq()
388 return -ENOMEM; in apple_pcie_port_setup_irq()
391 writel_relaxed(~0, port->base + PORT_INTMSKSET); in apple_pcie_port_setup_irq()
392 writel_relaxed(~0, port->base + PORT_INTSTAT); in apple_pcie_port_setup_irq()
394 irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port); in apple_pcie_port_setup_irq()
396 /* Configure MSI base address */ in apple_pcie_port_setup_irq()
398 writel_relaxed(lower_32_bits(DOORBELL_ADDR), port->base + PORT_MSIADDR); in apple_pcie_port_setup_irq()
401 writel_relaxed(0, port->base + PORT_MSIBASE); in apple_pcie_port_setup_irq()
402 writel_relaxed((ilog2(port->pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT) | in apple_pcie_port_setup_irq()
403 PORT_MSICFG_EN, port->base + PORT_MSICFG); in apple_pcie_port_setup_irq()
410 struct apple_pcie_port *port = data; in apple_pcie_port_irq() local
411 unsigned int hwirq = irq_domain_get_irq_data(port->domain, irq)->hwirq; in apple_pcie_port_irq()
415 dev_info_ratelimited(port->pcie->dev, "Link up on %pOF\n", in apple_pcie_port_irq()
416 port->np); in apple_pcie_port_irq()
417 complete_all(&port->pcie->event); in apple_pcie_port_irq()
420 dev_info_ratelimited(port->pcie->dev, "Link down on %pOF\n", in apple_pcie_port_irq()
421 port->np); in apple_pcie_port_irq()
430 static int apple_pcie_port_register_irqs(struct apple_pcie_port *port) in apple_pcie_port_register_irqs() argument
443 .fwnode = &port->np->fwnode, in apple_pcie_port_register_irqs()
452 irq = irq_domain_alloc_irqs(port->domain, 1, NUMA_NO_NODE, in apple_pcie_port_register_irqs()
458 port_irqs[i].name, port); in apple_pcie_port_register_irqs()
466 struct apple_pcie_port *port) in apple_pcie_setup_refclk() argument
471 res = readl_relaxed_poll_timeout(pcie->base + CORE_RC_PHYIF_STAT, stat, in apple_pcie_setup_refclk()
477 rmw_set(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx)); in apple_pcie_setup_refclk()
478 rmw_set(CORE_LANE_CFG_REFCLK0REQ, pcie->base + CORE_LANE_CFG(port->idx)); in apple_pcie_setup_refclk()
480 res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx), in apple_pcie_setup_refclk()
486 rmw_set(CORE_LANE_CFG_REFCLK1REQ, pcie->base + CORE_LANE_CFG(port->idx)); in apple_pcie_setup_refclk()
487 res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx), in apple_pcie_setup_refclk()
494 rmw_clear(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx)); in apple_pcie_setup_refclk()
496 rmw_set(CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx)); in apple_pcie_setup_refclk()
497 rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK); in apple_pcie_setup_refclk()
502 static u32 apple_pcie_rid2sid_write(struct apple_pcie_port *port, in apple_pcie_rid2sid_write() argument
505 writel_relaxed(val, port->base + PORT_RID2SID(idx)); in apple_pcie_rid2sid_write()
507 return readl_relaxed(port->base + PORT_RID2SID(idx)); in apple_pcie_rid2sid_write()
513 struct platform_device *platform = to_platform_device(pcie->dev); in apple_pcie_setup_port()
514 struct apple_pcie_port *port; in apple_pcie_setup_port() local
519 reset = devm_fwnode_gpiod_get(pcie->dev, of_fwnode_handle(np), "reset", in apple_pcie_setup_port()
524 port = devm_kzalloc(pcie->dev, sizeof(*port), GFP_KERNEL); in apple_pcie_setup_port()
525 if (!port) in apple_pcie_setup_port()
526 return -ENOMEM; in apple_pcie_setup_port()
532 /* Use the first reg entry to work out the port index */ in apple_pcie_setup_port()
533 port->idx = idx >> 11; in apple_pcie_setup_port()
534 port->pcie = pcie; in apple_pcie_setup_port()
535 port->np = np; in apple_pcie_setup_port()
537 port->base = devm_platform_ioremap_resource(platform, port->idx + 2); in apple_pcie_setup_port()
538 if (IS_ERR(port->base)) in apple_pcie_setup_port()
539 return PTR_ERR(port->base); in apple_pcie_setup_port()
541 rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK); in apple_pcie_setup_port()
546 ret = apple_pcie_setup_refclk(pcie, port); in apple_pcie_setup_port()
550 /* The minimal Tperst-clk value is 100us (PCIe CEM r5.0, 2.9.2) */ in apple_pcie_setup_port()
554 rmw_set(PORT_PERST_OFF, port->base + PORT_PERST); in apple_pcie_setup_port()
560 ret = readl_relaxed_poll_timeout(port->base + PORT_STATUS, stat, in apple_pcie_setup_port()
563 dev_err(pcie->dev, "port %pOF ready wait timeout\n", np); in apple_pcie_setup_port()
567 rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK); in apple_pcie_setup_port()
568 rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK); in apple_pcie_setup_port()
570 ret = apple_pcie_port_setup_irq(port); in apple_pcie_setup_port()
576 if (apple_pcie_rid2sid_write(port, i, 0xbad1d) != 0xbad1d) in apple_pcie_setup_port()
578 apple_pcie_rid2sid_write(port, i, 0); in apple_pcie_setup_port()
581 dev_dbg(pcie->dev, "%pOF: %d RID/SID mapping entries\n", np, i); in apple_pcie_setup_port()
583 port->sid_map_sz = i; in apple_pcie_setup_port()
585 list_add_tail(&port->entry, &pcie->ports); in apple_pcie_setup_port()
586 init_completion(&pcie->event); in apple_pcie_setup_port()
588 ret = apple_pcie_port_register_irqs(port); in apple_pcie_setup_port()
591 writel_relaxed(PORT_LTSSMCTL_START, port->base + PORT_LTSSMCTL); in apple_pcie_setup_port()
593 if (!wait_for_completion_timeout(&pcie->event, HZ / 10)) in apple_pcie_setup_port()
594 dev_warn(pcie->dev, "%pOF link didn't come up\n", np); in apple_pcie_setup_port()
601 struct fwnode_handle *fwnode = dev_fwnode(pcie->dev); in apple_msi_init()
606 ret = of_parse_phandle_with_args(to_of_node(fwnode), "msi-ranges", in apple_msi_init()
607 "#interrupt-cells", 0, &args); in apple_msi_init()
611 ret = of_property_read_u32_index(to_of_node(fwnode), "msi-ranges", in apple_msi_init()
612 args.args_count + 1, &pcie->nvecs); in apple_msi_init()
617 &pcie->fwspec); in apple_msi_init()
619 pcie->bitmap = devm_bitmap_zalloc(pcie->dev, pcie->nvecs, GFP_KERNEL); in apple_msi_init()
620 if (!pcie->bitmap) in apple_msi_init()
621 return -ENOMEM; in apple_msi_init()
623 parent = irq_find_matching_fwspec(&pcie->fwspec, DOMAIN_BUS_WIRED); in apple_msi_init()
625 dev_err(pcie->dev, "failed to find parent domain\n"); in apple_msi_init()
626 return -ENXIO; in apple_msi_init()
629 parent = irq_domain_create_hierarchy(parent, 0, pcie->nvecs, fwnode, in apple_msi_init()
632 dev_err(pcie->dev, "failed to create IRQ domain\n"); in apple_msi_init()
633 return -ENOMEM; in apple_msi_init()
637 pcie->domain = pci_msi_create_irq_domain(fwnode, &apple_msi_info, in apple_msi_init()
639 if (!pcie->domain) { in apple_msi_init()
640 dev_err(pcie->dev, "failed to create MSI domain\n"); in apple_msi_init()
642 return -ENOMEM; in apple_msi_init()
650 struct pci_config_window *cfg = pdev->sysdata; in apple_pcie_get_port()
651 struct apple_pcie *pcie = cfg->priv; in apple_pcie_get_port()
653 struct apple_pcie_port *port; in apple_pcie_get_port() local
655 /* Find the root port this device is on */ in apple_pcie_get_port()
658 /* If finding the port itself, nothing to do */ in apple_pcie_get_port()
662 list_for_each_entry(port, &pcie->ports, entry) { in apple_pcie_get_port()
663 if (port->idx == PCI_SLOT(port_pdev->devfn)) in apple_pcie_get_port()
664 return port; in apple_pcie_get_port()
670 static int apple_pcie_add_device(struct apple_pcie_port *port, in apple_pcie_add_device() argument
676 dev_dbg(&pdev->dev, "added to bus %s, index %d\n", in apple_pcie_add_device()
677 pci_name(pdev->bus->self), port->idx); in apple_pcie_add_device()
679 err = of_map_id(port->pcie->dev->of_node, rid, "iommu-map", in apple_pcie_add_device()
680 "iommu-map-mask", NULL, &sid); in apple_pcie_add_device()
684 mutex_lock(&port->pcie->lock); in apple_pcie_add_device()
686 idx = bitmap_find_free_region(port->sid_map, port->sid_map_sz, 0); in apple_pcie_add_device()
688 apple_pcie_rid2sid_write(port, idx, in apple_pcie_add_device()
692 dev_dbg(&pdev->dev, "mapping RID%x to SID%x (index %d)\n", in apple_pcie_add_device()
696 mutex_unlock(&port->pcie->lock); in apple_pcie_add_device()
698 return idx >= 0 ? 0 : -ENOSPC; in apple_pcie_add_device()
701 static void apple_pcie_release_device(struct apple_pcie_port *port, in apple_pcie_release_device() argument
707 mutex_lock(&port->pcie->lock); in apple_pcie_release_device()
709 for_each_set_bit(idx, port->sid_map, port->sid_map_sz) { in apple_pcie_release_device()
712 val = readl_relaxed(port->base + PORT_RID2SID(idx)); in apple_pcie_release_device()
714 apple_pcie_rid2sid_write(port, idx, 0); in apple_pcie_release_device()
715 bitmap_release_region(port->sid_map, idx, 0); in apple_pcie_release_device()
716 dev_dbg(&pdev->dev, "Released %x (%d)\n", val, idx); in apple_pcie_release_device()
721 mutex_unlock(&port->pcie->lock); in apple_pcie_release_device()
730 struct apple_pcie_port *port; in apple_pcie_bus_notifier() local
739 port = apple_pcie_get_port(pdev); in apple_pcie_bus_notifier()
740 if (!port) in apple_pcie_bus_notifier()
745 err = apple_pcie_add_device(port, pdev); in apple_pcie_bus_notifier()
750 apple_pcie_release_device(port, pdev); in apple_pcie_bus_notifier()
765 struct device *dev = cfg->parent; in apple_pcie_init()
773 return -ENOMEM; in apple_pcie_init()
775 pcie->dev = dev; in apple_pcie_init()
777 mutex_init(&pcie->lock); in apple_pcie_init()
779 pcie->base = devm_platform_ioremap_resource(platform, 1); in apple_pcie_init()
780 if (IS_ERR(pcie->base)) in apple_pcie_init()
781 return PTR_ERR(pcie->base); in apple_pcie_init()
783 cfg->priv = pcie; in apple_pcie_init()
784 INIT_LIST_HEAD(&pcie->ports); in apple_pcie_init()
790 for_each_child_of_node(dev->of_node, of_port) { in apple_pcie_init()
793 dev_err(pcie->dev, "Port %pOF setup fail: %d\n", of_port, ret); in apple_pcie_init()
835 .name = "pcie-apple",