Commit 6f6d7873 authored by Niklas Cassel's avatar Niklas Cassel Committed by Lorenzo Pieralisi

PCI: designware-ep: Add generic function for raising MSI irq

Add a generic function for raising MSI irqs that can be used by all
DWC based controllers.

Note that certain controllers, like DRA7xx, have a special convenience
register for raising MSI irqs that doesn't require you to explicitly map
the MSI address. Therefore, it is likely that certain drivers will
not use this generic function, even if they can.
Tested-by: default avatarGustavo Pimentel <gustavo.pimentel@synopsys.com>
Signed-off-by: default avatarNiklas Cassel <niklas.cassel@axis.com>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: default avatarJoao Pinto <jpinto@synopsys.com>
parent 9e718119
......@@ -282,6 +282,41 @@ static const struct pci_epc_ops epc_ops = {
.stop = dw_pcie_ep_stop,
};
int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep,
u8 interrupt_num)
{
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct pci_epc *epc = ep->epc;
u16 msg_ctrl, msg_data;
u32 msg_addr_lower, msg_addr_upper;
u64 msg_addr;
bool has_upper;
int ret;
/* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */
msg_ctrl = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL);
has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT);
msg_addr_lower = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32);
if (has_upper) {
msg_addr_upper = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32);
msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_64);
} else {
msg_addr_upper = 0;
msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_32);
}
msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower;
ret = dw_pcie_ep_map_addr(epc, ep->msi_mem_phys, msg_addr,
epc->mem->page_size);
if (ret)
return ret;
writel(msg_data | (interrupt_num - 1), ep->msi_mem);
dw_pcie_ep_unmap_addr(epc, ep->msi_mem_phys);
return 0;
}
void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
{
struct pci_epc *epc = ep->epc;
......
......@@ -106,6 +106,8 @@
#define MSI_CAP_MME_MASK (7 << MSI_CAP_MME_SHIFT)
#define MSI_MESSAGE_ADDR_L32 0x54
#define MSI_MESSAGE_ADDR_U32 0x58
#define MSI_MESSAGE_DATA_32 0x58
#define MSI_MESSAGE_DATA_64 0x5C
/*
* Maximum number of MSI IRQs can be 256 per controller. But keep
......@@ -338,6 +340,7 @@ static inline int dw_pcie_host_init(struct pcie_port *pp)
void dw_pcie_ep_linkup(struct dw_pcie_ep *ep);
int dw_pcie_ep_init(struct dw_pcie_ep *ep);
void dw_pcie_ep_exit(struct dw_pcie_ep *ep);
int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 interrupt_num);
void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar);
#else
static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
......@@ -353,6 +356,12 @@ static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
{
}
static inline int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep,
u8 interrupt_num)
{
return 0;
}
static inline void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
{
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment