Skip to content

Commit 76c9113

Browse files
mindachen1987bjorn-helgaas
authored andcommitted
PCI: plda: Add host init/deinit and map bus functions
Add PLDA host plda_pcie_host_init()/plda_pcie_host_deinit() and map bus function so vendors can use it to init PLDA PCIe host core. Link: https://lore.kernel.org/linux-pci/[email protected] Signed-off-by: Minda Chen <[email protected]> Signed-off-by: Krzysztof Wilczyński <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Mason Huo <[email protected]>
1 parent a576fff commit 76c9113

File tree

2 files changed

+139
-14
lines changed

2 files changed

+139
-14
lines changed

drivers/pci/controller/plda/pcie-plda-host.c

Lines changed: 117 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* PLDA PCIe XpressRich host controller driver
44
*
55
* Copyright (C) 2023 Microchip Co. Ltd
6+
* StarFive Co. Ltd
67
*
78
* Author: Daire McNamara <[email protected]>
89
*/
@@ -15,6 +16,15 @@
1516

1617
#include "pcie-plda.h"
1718

19+
void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
20+
int where)
21+
{
22+
struct plda_pcie_rp *pcie = bus->sysdata;
23+
24+
return pcie->config_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
25+
}
26+
EXPORT_SYMBOL_GPL(plda_pcie_map_bus);
27+
1828
static void plda_handle_msi(struct irq_desc *desc)
1929
{
2030
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
@@ -420,9 +430,7 @@ int plda_init_interrupts(struct platform_device *pdev,
420430
const struct plda_event *event)
421431
{
422432
struct device *dev = &pdev->dev;
423-
int irq;
424-
int intx_irq, msi_irq, event_irq;
425-
int ret;
433+
int event_irq, ret;
426434
u32 i;
427435

428436
if (!port->event_ops)
@@ -437,8 +445,8 @@ int plda_init_interrupts(struct platform_device *pdev,
437445
return ret;
438446
}
439447

440-
irq = platform_get_irq(pdev, 0);
441-
if (irq < 0)
448+
port->irq = platform_get_irq(pdev, 0);
449+
if (port->irq < 0)
442450
return -ENODEV;
443451

444452
for_each_set_bit(i, &port->events_bitmap, port->num_events) {
@@ -461,26 +469,26 @@ int plda_init_interrupts(struct platform_device *pdev,
461469
}
462470
}
463471

464-
intx_irq = irq_create_mapping(port->event_domain,
465-
event->intx_event);
466-
if (!intx_irq) {
472+
port->intx_irq = irq_create_mapping(port->event_domain,
473+
event->intx_event);
474+
if (!port->intx_irq) {
467475
dev_err(dev, "failed to map INTx interrupt\n");
468476
return -ENXIO;
469477
}
470478

471479
/* Plug the INTx chained handler */
472-
irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
480+
irq_set_chained_handler_and_data(port->intx_irq, plda_handle_intx, port);
473481

474-
msi_irq = irq_create_mapping(port->event_domain,
475-
event->msi_event);
476-
if (!msi_irq)
482+
port->msi_irq = irq_create_mapping(port->event_domain,
483+
event->msi_event);
484+
if (!port->msi_irq)
477485
return -ENXIO;
478486

479487
/* Plug the MSI chained handler */
480-
irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
488+
irq_set_chained_handler_and_data(port->msi_irq, plda_handle_msi, port);
481489

482490
/* Plug the main event chained handler */
483-
irq_set_chained_handler_and_data(irq, plda_handle_event, port);
491+
irq_set_chained_handler_and_data(port->irq, plda_handle_event, port);
484492

485493
return 0;
486494
}
@@ -547,3 +555,98 @@ int plda_pcie_setup_iomems(struct platform_device *pdev,
547555
return 0;
548556
}
549557
EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems);
558+
559+
static void plda_pcie_irq_domain_deinit(struct plda_pcie_rp *pcie)
560+
{
561+
irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
562+
irq_set_chained_handler_and_data(pcie->msi_irq, NULL, NULL);
563+
irq_set_chained_handler_and_data(pcie->intx_irq, NULL, NULL);
564+
565+
irq_domain_remove(pcie->msi.msi_domain);
566+
irq_domain_remove(pcie->msi.dev_domain);
567+
568+
irq_domain_remove(pcie->intx_domain);
569+
irq_domain_remove(pcie->event_domain);
570+
}
571+
572+
int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops,
573+
const struct plda_event *plda_event)
574+
{
575+
struct device *dev = port->dev;
576+
struct pci_host_bridge *bridge;
577+
struct platform_device *pdev = to_platform_device(dev);
578+
struct resource *cfg_res;
579+
int ret;
580+
581+
pdev = to_platform_device(dev);
582+
583+
port->bridge_addr =
584+
devm_platform_ioremap_resource_byname(pdev, "apb");
585+
586+
if (IS_ERR(port->bridge_addr))
587+
return dev_err_probe(dev, PTR_ERR(port->bridge_addr),
588+
"failed to map reg memory\n");
589+
590+
cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
591+
if (!cfg_res)
592+
return dev_err_probe(dev, -ENODEV,
593+
"failed to get config memory\n");
594+
595+
port->config_base = devm_ioremap_resource(dev, cfg_res);
596+
if (IS_ERR(port->config_base))
597+
return dev_err_probe(dev, PTR_ERR(port->config_base),
598+
"failed to map config memory\n");
599+
600+
bridge = devm_pci_alloc_host_bridge(dev, 0);
601+
if (!bridge)
602+
return dev_err_probe(dev, -ENOMEM,
603+
"failed to alloc bridge\n");
604+
605+
if (port->host_ops && port->host_ops->host_init) {
606+
ret = port->host_ops->host_init(port);
607+
if (ret)
608+
return ret;
609+
}
610+
611+
port->bridge = bridge;
612+
plda_pcie_setup_window(port->bridge_addr, 0, cfg_res->start, 0,
613+
resource_size(cfg_res));
614+
plda_pcie_setup_iomems(bridge, port);
615+
plda_set_default_msi(&port->msi);
616+
ret = plda_init_interrupts(pdev, port, plda_event);
617+
if (ret)
618+
goto err_host;
619+
620+
/* Set default bus ops */
621+
bridge->ops = ops;
622+
bridge->sysdata = port;
623+
624+
ret = pci_host_probe(bridge);
625+
if (ret < 0) {
626+
dev_err_probe(dev, ret, "failed to probe pci host\n");
627+
goto err_probe;
628+
}
629+
630+
return ret;
631+
632+
err_probe:
633+
plda_pcie_irq_domain_deinit(port);
634+
err_host:
635+
if (port->host_ops && port->host_ops->host_deinit)
636+
port->host_ops->host_deinit(port);
637+
638+
return ret;
639+
}
640+
EXPORT_SYMBOL_GPL(plda_pcie_host_init);
641+
642+
void plda_pcie_host_deinit(struct plda_pcie_rp *port)
643+
{
644+
pci_stop_root_bus(port->bridge->bus);
645+
pci_remove_root_bus(port->bridge->bus);
646+
647+
plda_pcie_irq_domain_deinit(port);
648+
649+
if (port->host_ops && port->host_ops->host_deinit)
650+
port->host_ops->host_deinit(port);
651+
}
652+
EXPORT_SYMBOL_GPL(plda_pcie_host_deinit);

drivers/pci/controller/plda/pcie-plda.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ struct plda_event_ops {
142142
u32 (*get_events)(struct plda_pcie_rp *pcie);
143143
};
144144

145+
struct plda_pcie_host_ops {
146+
int (*host_init)(struct plda_pcie_rp *pcie);
147+
void (*host_deinit)(struct plda_pcie_rp *pcie);
148+
};
149+
145150
struct plda_msi {
146151
struct mutex lock; /* Protect used bitmap */
147152
struct irq_domain *msi_domain;
@@ -153,14 +158,20 @@ struct plda_msi {
153158

154159
struct plda_pcie_rp {
155160
struct device *dev;
161+
struct pci_host_bridge *bridge;
156162
struct irq_domain *intx_domain;
157163
struct irq_domain *event_domain;
158164
raw_spinlock_t lock;
159165
struct plda_msi msi;
160166
const struct plda_event_ops *event_ops;
161167
const struct irq_chip *event_irq_chip;
168+
const struct plda_pcie_host_ops *host_ops;
162169
void __iomem *bridge_addr;
170+
void __iomem *config_base;
163171
unsigned long events_bitmap;
172+
int irq;
173+
int msi_irq;
174+
int intx_irq;
164175
int num_events;
165176
};
166177

@@ -171,6 +182,8 @@ struct plda_event {
171182
int msi_event;
172183
};
173184

185+
void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
186+
int where);
174187
int plda_init_interrupts(struct platform_device *pdev,
175188
struct plda_pcie_rp *port,
176189
const struct plda_event *event);
@@ -179,4 +192,13 @@ void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
179192
size_t size);
180193
int plda_pcie_setup_iomems(struct platform_device *pdev,
181194
struct plda_pcie_rp *port);
195+
int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops,
196+
const struct plda_event *plda_event);
197+
void plda_pcie_host_deinit(struct plda_pcie_rp *pcie);
198+
199+
static inline void plda_set_default_msi(struct plda_msi *msi)
200+
{
201+
msi->vector_phy = IMSI_ADDR;
202+
msi->num_vectors = PLDA_MAX_NUM_MSI_IRQS;
203+
}
182204
#endif

0 commit comments

Comments
 (0)