Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -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;
+9 −0
Original line number Diff line number Diff line
@@ -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)
{
}