123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-09-23 GuEe-GUI first version
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #define DBG_TAG "pcie.dw.platfrom"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include "pcie-dw.h"
- struct dw_dw_platform_pcie_soc_data
- {
- enum dw_pcie_device_mode mode;
- };
- struct dw_platform_pcie
- {
- struct dw_pcie *pci;
- struct rt_syscon *regmap;
- const struct dw_dw_platform_pcie_soc_data *soc_data;
- };
- static rt_err_t dw_platform_pcie_host_init(struct dw_pcie_port *port)
- {
- struct dw_pcie *pci = to_dw_pcie_from_port(port);
- dw_pcie_setup_rc(port);
- dw_pcie_wait_for_link(pci);
- dw_pcie_msi_init(port);
- return RT_EOK;
- }
- static void dw_platform_set_irq_count(struct dw_pcie_port *pp)
- {
- pp->irq_count = MAX_MSI_IRQS;
- }
- static const struct dw_pcie_host_ops dw_platform_pcie_host_ops =
- {
- .host_init = dw_platform_pcie_host_init,
- .set_irq_count = dw_platform_set_irq_count,
- };
- static rt_err_t dw_platform_pcie_establish_link(struct dw_pcie *pci)
- {
- return RT_EOK;
- }
- static const struct dw_pcie_ops dw_platform_pcie_ops =
- {
- .start_link = dw_platform_pcie_establish_link,
- };
- static rt_err_t dw_platform_pcie_ep_init(struct dw_pcie_ep *ep)
- {
- struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
- for (int bar = 0; bar < PCI_STD_NUM_BARS; ++bar)
- {
- dw_pcie_ep_reset_bar(pci, bar);
- }
- return RT_EOK;
- }
- static rt_err_t dw_platform_pcie_ep_raise_irq(struct dw_pcie_ep *ep,
- rt_uint8_t func_no, enum rt_pci_ep_irq type, unsigned irq)
- {
- switch (type)
- {
- case RT_PCI_EP_IRQ_LEGACY:
- return dw_pcie_ep_raise_legacy_irq(ep, func_no);
- case RT_PCI_EP_IRQ_MSI:
- return dw_pcie_ep_raise_msi_irq(ep, func_no, irq);
- case RT_PCI_EP_IRQ_MSIX:
- return dw_pcie_ep_raise_msix_irq(ep, func_no, irq);
- default:
- LOG_E("Unknown IRQ type = %d", type);
- }
- return RT_EOK;
- }
- static const struct dw_pcie_ep_ops dw_platform_pcie_ep_ops =
- {
- .ep_init = dw_platform_pcie_ep_init,
- .raise_irq = dw_platform_pcie_ep_raise_irq,
- };
- static rt_err_t dw_platform_add_pcie_port(struct dw_platform_pcie *plat_pcie,
- struct rt_device *dev)
- {
- rt_err_t err;
- struct dw_pcie *pci = plat_pcie->pci;
- struct dw_pcie_port *port = &pci->port;
- port->sys_irq = rt_dm_dev_get_irq(dev, 1);
- if (port->sys_irq < 0)
- {
- return port->sys_irq;
- }
- #ifdef RT_PCI_MSI
- port->msi_irq = rt_dm_dev_get_irq(dev, 0);
- if (port->msi_irq < 0)
- {
- return port->msi_irq;
- }
- #endif
- port->ops = &dw_platform_pcie_host_ops;
- if ((err = dw_pcie_host_init(port)))
- {
- LOG_E("Failed to initialize host");
- return err;
- }
- return RT_EOK;
- }
- static rt_err_t dw_platform_add_pcie_ep(struct dw_platform_pcie *plat_pcie,
- struct rt_device *dev)
- {
- rt_err_t err;
- struct dw_pcie *pci = plat_pcie->pci;
- struct dw_pcie_ep *ep = &pci->endpoint;
- pci->dbi_base2 = rt_dm_dev_iomap_by_name(dev, "dbi2");
- if (!pci->dbi_base2)
- {
- return -RT_EIO;
- }
- err = rt_dm_dev_get_address_by_name(dev, "addr_space", &ep->aspace, &ep->aspace_size);
- if (err)
- {
- rt_iounmap(pci->dbi_base2);
- return err;
- }
- ep->ops = &dw_platform_pcie_ep_ops;
- if ((err = dw_pcie_ep_init(ep)))
- {
- LOG_E("Failed to initialize endpoint");
- return err;
- }
- return RT_EOK;
- }
- static rt_err_t dw_platform_pcie_probe(struct rt_platform_device *pdev)
- {
- rt_err_t err;
- struct dw_pcie *pci = RT_NULL;
- struct dw_platform_pcie *plat_pcie;
- struct rt_device *dev = &pdev->parent;
- if (!(plat_pcie = rt_calloc(1, sizeof(*plat_pcie))))
- {
- return -RT_ENOMEM;
- }
- if (!(pci = rt_calloc(1, sizeof(*pci))))
- {
- err = -RT_ENOMEM;
- goto _fail;
- }
- plat_pcie->pci = pci;
- plat_pcie->soc_data = pdev->id->data;
- pci->dev = dev;
- pci->ops = &dw_platform_pcie_ops;
- pci->dbi_base = rt_dm_dev_iomap_by_name(dev, "dbi");
- if (!pci->dbi_base)
- {
- err = -RT_EIO;
- goto _fail;
- }
- dev->user_data = plat_pcie;
- switch (plat_pcie->soc_data->mode)
- {
- case DW_PCIE_RC_TYPE:
- if (!RT_KEY_ENABLED(RT_PCI_DW_HOST))
- {
- err = -RT_ENOSYS;
- goto _fail;
- }
- if ((err = dw_platform_add_pcie_port(plat_pcie, dev)))
- {
- goto _fail;
- }
- break;
- case DW_PCIE_EP_TYPE:
- if (!RT_KEY_ENABLED(RT_PCI_DW_EP))
- {
- err = -RT_ENOSYS;
- goto _fail;
- }
- if ((err = dw_platform_add_pcie_ep(plat_pcie, dev)))
- {
- goto _fail;
- }
- break;
- default:
- LOG_E("Invalid device type %d", plat_pcie->soc_data->mode);
- err = -RT_EINVAL;
- goto _fail;
- }
- return RT_EOK;
- _fail:
- if (pci)
- {
- if (pci->dbi_base)
- {
- rt_iounmap(pci->dbi_base);
- }
- rt_free(pci);
- }
- rt_free(plat_pcie);
- return err;
- }
- static rt_err_t dw_platform_pcie_remove(struct rt_platform_device *pdev)
- {
- struct dw_platform_pcie *plat_pcie = pdev->parent.user_data;
- rt_pci_host_bridge_remove(plat_pcie->pci->port.bridge);
- dw_pcie_host_free(&plat_pcie->pci->port);
- rt_iounmap(plat_pcie->pci->dbi_base);
- rt_free(plat_pcie->pci);
- rt_free(plat_pcie);
- return RT_EOK;
- }
- static const struct dw_dw_platform_pcie_soc_data dw_platform_pcie_rc_soc_data =
- {
- .mode = DW_PCIE_RC_TYPE,
- };
- static const struct dw_dw_platform_pcie_soc_data dw_platform_pcie_ep_soc_data =
- {
- .mode = DW_PCIE_EP_TYPE,
- };
- static const struct rt_ofw_node_id dw_platform_pcie_ofw_ids[] =
- {
- { .compatible = "snps,dw-pcie", .data = &dw_platform_pcie_rc_soc_data },
- { .compatible = "snps,dw-pcie-ep", .data = &dw_platform_pcie_ep_soc_data },
- { /* sentinel */ }
- };
- static struct rt_platform_driver dw_platform_pcie_driver =
- {
- .name = "dw-pcie",
- .ids = dw_platform_pcie_ofw_ids,
- .probe = dw_platform_pcie_probe,
- .remove = dw_platform_pcie_remove,
- };
- RT_PLATFORM_DRIVER_EXPORT(dw_platform_pcie_driver);
|