summaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc/pcie-designware-ep.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-designware-ep.c')
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-ep.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 8d79dd0e1d..c2630db745 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -6,6 +6,8 @@
* Author: Kishon Vijay Abraham I <kishon@ti.com>
*/
+#include <linux/align.h>
+#include <linux/bitfield.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -52,21 +54,35 @@ static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
return func_offset;
}
+static unsigned int dw_pcie_ep_get_dbi2_offset(struct dw_pcie_ep *ep, u8 func_no)
+{
+ unsigned int dbi2_offset = 0;
+
+ if (ep->ops->get_dbi2_offset)
+ dbi2_offset = ep->ops->get_dbi2_offset(ep, func_no);
+ else if (ep->ops->func_conf_select) /* for backward compatibility */
+ dbi2_offset = ep->ops->func_conf_select(ep, func_no);
+
+ return dbi2_offset;
+}
+
static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
enum pci_barno bar, int flags)
{
- u32 reg;
- unsigned int func_offset = 0;
+ unsigned int func_offset, dbi2_offset;
struct dw_pcie_ep *ep = &pci->ep;
+ u32 reg, reg_dbi2;
func_offset = dw_pcie_ep_func_select(ep, func_no);
+ dbi2_offset = dw_pcie_ep_get_dbi2_offset(ep, func_no);
reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
+ reg_dbi2 = dbi2_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
dw_pcie_dbi_ro_wr_en(pci);
- dw_pcie_writel_dbi2(pci, reg, 0x0);
+ dw_pcie_writel_dbi2(pci, reg_dbi2, 0x0);
dw_pcie_writel_dbi(pci, reg, 0x0);
if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- dw_pcie_writel_dbi2(pci, reg + 4, 0x0);
+ dw_pcie_writel_dbi2(pci, reg_dbi2 + 4, 0x0);
dw_pcie_writel_dbi(pci, reg + 4, 0x0);
}
dw_pcie_dbi_ro_wr_dis(pci);
@@ -228,16 +244,18 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
{
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ unsigned int func_offset, dbi2_offset;
enum pci_barno bar = epf_bar->barno;
size_t size = epf_bar->size;
int flags = epf_bar->flags;
- unsigned int func_offset = 0;
+ u32 reg, reg_dbi2;
int ret, type;
- u32 reg;
func_offset = dw_pcie_ep_func_select(ep, func_no);
+ dbi2_offset = dw_pcie_ep_get_dbi2_offset(ep, func_no);
reg = PCI_BASE_ADDRESS_0 + (4 * bar) + func_offset;
+ reg_dbi2 = PCI_BASE_ADDRESS_0 + (4 * bar) + dbi2_offset;
if (!(flags & PCI_BASE_ADDRESS_SPACE))
type = PCIE_ATU_TYPE_MEM;
@@ -253,11 +271,11 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
dw_pcie_dbi_ro_wr_en(pci);
- dw_pcie_writel_dbi2(pci, reg, lower_32_bits(size - 1));
+ dw_pcie_writel_dbi2(pci, reg_dbi2, lower_32_bits(size - 1));
dw_pcie_writel_dbi(pci, reg, flags);
if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- dw_pcie_writel_dbi2(pci, reg + 4, upper_32_bits(size - 1));
+ dw_pcie_writel_dbi2(pci, reg_dbi2 + 4, upper_32_bits(size - 1));
dw_pcie_writel_dbi(pci, reg + 4, 0);
}
@@ -334,7 +352,7 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
if (!(val & PCI_MSI_FLAGS_ENABLE))
return -EINVAL;
- val = (val & PCI_MSI_FLAGS_QSIZE) >> 4;
+ val = FIELD_GET(PCI_MSI_FLAGS_QSIZE, val);
return val;
}
@@ -357,7 +375,7 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
val &= ~PCI_MSI_FLAGS_QMASK;
- val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK;
+ val |= FIELD_PREP(PCI_MSI_FLAGS_QMASK, interrupts);
dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_writew_dbi(pci, reg, val);
dw_pcie_dbi_ro_wr_dis(pci);
@@ -584,7 +602,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;
tbl_offset = dw_pcie_readl_dbi(pci, reg);
- bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
+ bir = FIELD_GET(PCI_MSIX_TABLE_BIR, tbl_offset);
tbl_offset &= PCI_MSIX_TABLE_OFFSET;
msix_tbl = ep->epf_bar[bir]->addr + tbl_offset;
@@ -598,7 +616,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
}
aligned_offset = msg_addr & (epc->mem->window.page_size - 1);
- msg_addr &= ~aligned_offset;
+ msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size);
ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr,
epc->mem->window.page_size);
if (ret)
@@ -622,7 +640,11 @@ void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
epc->mem->window.page_size);
pci_epc_mem_exit(epc);
+
+ if (ep->ops->deinit)
+ ep->ops->deinit(ep);
}
+EXPORT_SYMBOL_GPL(dw_pcie_ep_exit);
static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap)
{
@@ -724,6 +746,9 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
ep->phys_base = res->start;
ep->addr_size = resource_size(res);
+ if (ep->ops->pre_init)
+ ep->ops->pre_init(ep);
+
dw_pcie_version_detect(pci);
dw_pcie_iatu_detect(pci);
@@ -778,7 +803,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
ep->page_size);
if (ret < 0) {
dev_err(dev, "Failed to initialize address space\n");
- return ret;
+ goto err_ep_deinit;
}
ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys,
@@ -815,6 +840,10 @@ err_free_epc_mem:
err_exit_epc_mem:
pci_epc_mem_exit(epc);
+err_ep_deinit:
+ if (ep->ops->deinit)
+ ep->ops->deinit(ep);
+
return ret;
}
EXPORT_SYMBOL_GPL(dw_pcie_ep_init);