Merge branch 'pci/controller/rockchip'
- Remove writes to unused registers (Rick Wertenbroek) - Write endpoint Device ID using correct register (Rick Wertenbroek) - Assert PCI Configuration Enable bit after probe so endpoint responds instead of generating Request Retry Status messages (Rick Wertenbroek) - Poll waiting for PHY PLLs to lock (Rick Wertenbroek) - Update RK3399 example DT binding to be valid (Rick Wertenbroek) - Use RK3399 PCIE_CLIENT_LEGACY_INT_CTRL to generate INTx instead of manually generating PCIe message (Rick Wertenbroek) - Use multiple windows to avoid address translation conflicts (Rick Wertenbroek) - Use u32 (not u16) when accessing 32-bit registers (Rick Wertenbroek) - Hide MSI-X Capability, since RK3399 can't generate MSI-X (Rick Wertenbroek) - Set endpoint controller required alignment to 256 (Damien Le Moal) * pci/controller/rockchip: PCI: rockchip: Set address alignment for endpoint mode PCI: rockchip: Don't advertise MSI-X in PCIe capabilities PCI: rockchip: Use u32 variable to access 32-bit registers PCI: rockchip: Fix window mapping and address translation for endpoint PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core dt-bindings: PCI: Update the RK3399 example to a valid one PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked PCI: rockchip: Assert PCI Configuration Enable bit after probe PCI: rockchip: Write PCI Device ID to correct register PCI: rockchip: Remove writes to unused registers
This commit is contained in:
commit
9f5eb1bf55
|
@ -47,7 +47,7 @@ examples:
|
|||
|
||||
pcie-ep@f8000000 {
|
||||
compatible = "rockchip,rk3399-pcie-ep";
|
||||
reg = <0x0 0xfd000000 0x0 0x1000000>, <0x0 0x80000000 0x0 0x20000>;
|
||||
reg = <0x0 0xfd000000 0x0 0x1000000>, <0x0 0xfa000000 0x0 0x2000000>;
|
||||
reg-names = "apb-base", "mem-base";
|
||||
clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>,
|
||||
<&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>;
|
||||
|
@ -63,6 +63,8 @@ examples:
|
|||
phys = <&pcie_phy 0>, <&pcie_phy 1>, <&pcie_phy 2>, <&pcie_phy 3>;
|
||||
phy-names = "pcie-phy-0", "pcie-phy-1", "pcie-phy-2", "pcie-phy-3";
|
||||
rockchip,max-outbound-regions = <16>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie_clkreqnb_cpm>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
|
@ -61,70 +61,38 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip,
|
|||
ROCKCHIP_PCIE_AT_OB_REGION_DESC0(region));
|
||||
rockchip_pcie_write(rockchip, 0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region));
|
||||
rockchip_pcie_write(rockchip, 0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(region));
|
||||
rockchip_pcie_write(rockchip, 0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(region));
|
||||
}
|
||||
|
||||
static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn,
|
||||
u32 r, u32 type, u64 cpu_addr,
|
||||
u64 pci_addr, size_t size)
|
||||
u32 r, u64 cpu_addr, u64 pci_addr,
|
||||
size_t size)
|
||||
{
|
||||
u64 sz = 1ULL << fls64(size - 1);
|
||||
int num_pass_bits = ilog2(sz);
|
||||
u32 addr0, addr1, desc0, desc1;
|
||||
bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG);
|
||||
int num_pass_bits = fls64(size - 1);
|
||||
u32 addr0, addr1, desc0;
|
||||
|
||||
/* The minimal region size is 1MB */
|
||||
if (num_pass_bits < 8)
|
||||
num_pass_bits = 8;
|
||||
|
||||
cpu_addr -= rockchip->mem_res->start;
|
||||
addr0 = ((is_nor_msg ? 0x10 : (num_pass_bits - 1)) &
|
||||
PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
|
||||
(lower_32_bits(cpu_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
|
||||
addr1 = upper_32_bits(is_nor_msg ? cpu_addr : pci_addr);
|
||||
desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | type;
|
||||
desc1 = 0;
|
||||
addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
|
||||
(lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
|
||||
addr1 = upper_32_bits(pci_addr);
|
||||
desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | AXI_WRAPPER_MEM_WRITE;
|
||||
|
||||
if (is_nor_msg) {
|
||||
rockchip_pcie_write(rockchip, 0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r));
|
||||
rockchip_pcie_write(rockchip, 0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r));
|
||||
rockchip_pcie_write(rockchip, desc0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r));
|
||||
rockchip_pcie_write(rockchip, desc1,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r));
|
||||
} else {
|
||||
/* PCI bus address region */
|
||||
rockchip_pcie_write(rockchip, addr0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r));
|
||||
rockchip_pcie_write(rockchip, addr1,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r));
|
||||
rockchip_pcie_write(rockchip, desc0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r));
|
||||
rockchip_pcie_write(rockchip, desc1,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r));
|
||||
|
||||
addr0 =
|
||||
((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
|
||||
(lower_32_bits(cpu_addr) &
|
||||
PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
|
||||
addr1 = upper_32_bits(cpu_addr);
|
||||
}
|
||||
|
||||
/* CPU bus address region */
|
||||
/* PCI bus address region */
|
||||
rockchip_pcie_write(rockchip, addr0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r));
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r));
|
||||
rockchip_pcie_write(rockchip, addr1,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r));
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r));
|
||||
rockchip_pcie_write(rockchip, desc0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r));
|
||||
rockchip_pcie_write(rockchip, 0,
|
||||
ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r));
|
||||
}
|
||||
|
||||
static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn,
|
||||
struct pci_epf_header *hdr)
|
||||
{
|
||||
u32 reg;
|
||||
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
|
||||
struct rockchip_pcie *rockchip = &ep->rockchip;
|
||||
|
||||
|
@ -137,8 +105,9 @@ static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn,
|
|||
PCIE_CORE_CONFIG_VENDOR);
|
||||
}
|
||||
|
||||
rockchip_pcie_write(rockchip, hdr->deviceid << 16,
|
||||
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_VENDOR_ID);
|
||||
reg = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_DID_VID);
|
||||
reg = (reg & 0xFFFF) | (hdr->deviceid << 16);
|
||||
rockchip_pcie_write(rockchip, reg, PCIE_EP_CONFIG_DID_VID);
|
||||
|
||||
rockchip_pcie_write(rockchip,
|
||||
hdr->revid |
|
||||
|
@ -256,26 +225,20 @@ static void rockchip_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, u8 vfn,
|
|||
ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar));
|
||||
}
|
||||
|
||||
static inline u32 rockchip_ob_region(phys_addr_t addr)
|
||||
{
|
||||
return (addr >> ilog2(SZ_1M)) & 0x1f;
|
||||
}
|
||||
|
||||
static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn,
|
||||
phys_addr_t addr, u64 pci_addr,
|
||||
size_t size)
|
||||
{
|
||||
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
|
||||
struct rockchip_pcie *pcie = &ep->rockchip;
|
||||
u32 r;
|
||||
u32 r = rockchip_ob_region(addr);
|
||||
|
||||
r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG);
|
||||
/*
|
||||
* Region 0 is reserved for configuration space and shouldn't
|
||||
* be used elsewhere per TRM, so leave it out.
|
||||
*/
|
||||
if (r >= ep->max_regions - 1) {
|
||||
dev_err(&epc->dev, "no free outbound region\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, AXI_WRAPPER_MEM_WRITE, addr,
|
||||
pci_addr, size);
|
||||
rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, addr, pci_addr, size);
|
||||
|
||||
set_bit(r, &ep->ob_region_map);
|
||||
ep->ob_addr[r] = addr;
|
||||
|
@ -290,15 +253,11 @@ static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
|
|||
struct rockchip_pcie *rockchip = &ep->rockchip;
|
||||
u32 r;
|
||||
|
||||
for (r = 0; r < ep->max_regions - 1; r++)
|
||||
for (r = 0; r < ep->max_regions; r++)
|
||||
if (ep->ob_addr[r] == addr)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Region 0 is reserved for configuration space and shouldn't
|
||||
* be used elsewhere per TRM, so leave it out.
|
||||
*/
|
||||
if (r == ep->max_regions - 1)
|
||||
if (r == ep->max_regions)
|
||||
return;
|
||||
|
||||
rockchip_pcie_clear_ep_ob_atu(rockchip, r);
|
||||
|
@ -312,15 +271,15 @@ static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn,
|
|||
{
|
||||
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
|
||||
struct rockchip_pcie *rockchip = &ep->rockchip;
|
||||
u16 flags;
|
||||
u32 flags;
|
||||
|
||||
flags = rockchip_pcie_read(rockchip,
|
||||
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
|
||||
ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
|
||||
flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK;
|
||||
flags |=
|
||||
((multi_msg_cap << 1) << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) |
|
||||
PCI_MSI_FLAGS_64BIT;
|
||||
(multi_msg_cap << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) |
|
||||
(PCI_MSI_FLAGS_64BIT << ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET);
|
||||
flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP;
|
||||
rockchip_pcie_write(rockchip, flags,
|
||||
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
|
||||
|
@ -332,7 +291,7 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
|
|||
{
|
||||
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
|
||||
struct rockchip_pcie *rockchip = &ep->rockchip;
|
||||
u16 flags;
|
||||
u32 flags;
|
||||
|
||||
flags = rockchip_pcie_read(rockchip,
|
||||
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
|
||||
|
@ -345,48 +304,25 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
|
|||
}
|
||||
|
||||
static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn,
|
||||
u8 intx, bool is_asserted)
|
||||
u8 intx, bool do_assert)
|
||||
{
|
||||
struct rockchip_pcie *rockchip = &ep->rockchip;
|
||||
u32 r = ep->max_regions - 1;
|
||||
u32 offset;
|
||||
u32 status;
|
||||
u8 msg_code;
|
||||
|
||||
if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR ||
|
||||
ep->irq_pci_fn != fn)) {
|
||||
rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r,
|
||||
AXI_WRAPPER_NOR_MSG,
|
||||
ep->irq_phys_addr, 0, 0);
|
||||
ep->irq_pci_addr = ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR;
|
||||
ep->irq_pci_fn = fn;
|
||||
}
|
||||
|
||||
intx &= 3;
|
||||
if (is_asserted) {
|
||||
|
||||
if (do_assert) {
|
||||
ep->irq_pending |= BIT(intx);
|
||||
msg_code = ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx;
|
||||
rockchip_pcie_write(rockchip,
|
||||
PCIE_CLIENT_INT_IN_ASSERT |
|
||||
PCIE_CLIENT_INT_PEND_ST_PEND,
|
||||
PCIE_CLIENT_LEGACY_INT_CTRL);
|
||||
} else {
|
||||
ep->irq_pending &= ~BIT(intx);
|
||||
msg_code = ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx;
|
||||
rockchip_pcie_write(rockchip,
|
||||
PCIE_CLIENT_INT_IN_DEASSERT |
|
||||
PCIE_CLIENT_INT_PEND_ST_NORMAL,
|
||||
PCIE_CLIENT_LEGACY_INT_CTRL);
|
||||
}
|
||||
|
||||
status = rockchip_pcie_read(rockchip,
|
||||
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
|
||||
ROCKCHIP_PCIE_EP_CMD_STATUS);
|
||||
status &= ROCKCHIP_PCIE_EP_CMD_STATUS_IS;
|
||||
|
||||
if ((status != 0) ^ (ep->irq_pending != 0)) {
|
||||
status ^= ROCKCHIP_PCIE_EP_CMD_STATUS_IS;
|
||||
rockchip_pcie_write(rockchip, status,
|
||||
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
|
||||
ROCKCHIP_PCIE_EP_CMD_STATUS);
|
||||
}
|
||||
|
||||
offset =
|
||||
ROCKCHIP_PCIE_MSG_ROUTING(ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX) |
|
||||
ROCKCHIP_PCIE_MSG_CODE(msg_code) | ROCKCHIP_PCIE_MSG_NO_DATA;
|
||||
writel(0, ep->irq_cpu_addr + offset);
|
||||
}
|
||||
|
||||
static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn,
|
||||
|
@ -416,9 +352,10 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn,
|
|||
u8 interrupt_num)
|
||||
{
|
||||
struct rockchip_pcie *rockchip = &ep->rockchip;
|
||||
u16 flags, mme, data, data_mask;
|
||||
u32 flags, mme, data, data_mask;
|
||||
u8 msi_count;
|
||||
u64 pci_addr, pci_addr_mask = 0xff;
|
||||
u64 pci_addr;
|
||||
u32 r;
|
||||
|
||||
/* Check MSI enable bit */
|
||||
flags = rockchip_pcie_read(&ep->rockchip,
|
||||
|
@ -452,21 +389,20 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn,
|
|||
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
|
||||
ROCKCHIP_PCIE_EP_MSI_CTRL_REG +
|
||||
PCI_MSI_ADDRESS_LO);
|
||||
pci_addr &= GENMASK_ULL(63, 2);
|
||||
|
||||
/* Set the outbound region if needed. */
|
||||
if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) ||
|
||||
if (unlikely(ep->irq_pci_addr != (pci_addr & PCIE_ADDR_MASK) ||
|
||||
ep->irq_pci_fn != fn)) {
|
||||
rockchip_pcie_prog_ep_ob_atu(rockchip, fn, ep->max_regions - 1,
|
||||
AXI_WRAPPER_MEM_WRITE,
|
||||
r = rockchip_ob_region(ep->irq_phys_addr);
|
||||
rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r,
|
||||
ep->irq_phys_addr,
|
||||
pci_addr & ~pci_addr_mask,
|
||||
pci_addr_mask + 1);
|
||||
ep->irq_pci_addr = (pci_addr & ~pci_addr_mask);
|
||||
pci_addr & PCIE_ADDR_MASK,
|
||||
~PCIE_ADDR_MASK + 1);
|
||||
ep->irq_pci_addr = (pci_addr & PCIE_ADDR_MASK);
|
||||
ep->irq_pci_fn = fn;
|
||||
}
|
||||
|
||||
writew(data, ep->irq_cpu_addr + (pci_addr & pci_addr_mask));
|
||||
writew(data, ep->irq_cpu_addr + (pci_addr & ~PCIE_ADDR_MASK));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -506,6 +442,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features = {
|
|||
.linkup_notifier = false,
|
||||
.msi_capable = true,
|
||||
.msix_capable = false,
|
||||
.align = 256,
|
||||
};
|
||||
|
||||
static const struct pci_epc_features*
|
||||
|
@ -547,6 +484,8 @@ static int rockchip_pcie_parse_ep_dt(struct rockchip_pcie *rockchip,
|
|||
if (err < 0 || ep->max_regions > MAX_REGION_LIMIT)
|
||||
ep->max_regions = MAX_REGION_LIMIT;
|
||||
|
||||
ep->ob_region_map = 0;
|
||||
|
||||
err = of_property_read_u8(dev->of_node, "max-functions",
|
||||
&ep->epc->max_functions);
|
||||
if (err < 0)
|
||||
|
@ -567,7 +506,9 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
|
|||
struct rockchip_pcie *rockchip;
|
||||
struct pci_epc *epc;
|
||||
size_t max_regions;
|
||||
int err;
|
||||
struct pci_epc_mem_window *windows = NULL;
|
||||
int err, i;
|
||||
u32 cfg_msi, cfg_msix_cp;
|
||||
|
||||
ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
|
||||
if (!ep)
|
||||
|
@ -614,15 +555,27 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
|
|||
/* Only enable function 0 by default */
|
||||
rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG);
|
||||
|
||||
err = pci_epc_mem_init(epc, rockchip->mem_res->start,
|
||||
resource_size(rockchip->mem_res), PAGE_SIZE);
|
||||
windows = devm_kcalloc(dev, ep->max_regions,
|
||||
sizeof(struct pci_epc_mem_window), GFP_KERNEL);
|
||||
if (!windows) {
|
||||
err = -ENOMEM;
|
||||
goto err_uninit_port;
|
||||
}
|
||||
for (i = 0; i < ep->max_regions; i++) {
|
||||
windows[i].phys_base = rockchip->mem_res->start + (SZ_1M * i);
|
||||
windows[i].size = SZ_1M;
|
||||
windows[i].page_size = SZ_1M;
|
||||
}
|
||||
err = pci_epc_multi_mem_init(epc, windows, ep->max_regions);
|
||||
devm_kfree(dev, windows);
|
||||
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to initialize the memory space\n");
|
||||
goto err_uninit_port;
|
||||
}
|
||||
|
||||
ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr,
|
||||
SZ_128K);
|
||||
SZ_1M);
|
||||
if (!ep->irq_cpu_addr) {
|
||||
dev_err(dev, "failed to reserve memory space for MSI\n");
|
||||
err = -ENOMEM;
|
||||
|
@ -631,6 +584,32 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
|
|||
|
||||
ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR;
|
||||
|
||||
/*
|
||||
* MSI-X is not supported but the controller still advertises the MSI-X
|
||||
* capability by default, which can lead to the Root Complex side
|
||||
* allocating MSI-X vectors which cannot be used. Avoid this by skipping
|
||||
* the MSI-X capability entry in the PCIe capabilities linked-list: get
|
||||
* the next pointer from the MSI-X entry and set that in the MSI
|
||||
* capability entry (which is the previous entry). This way the MSI-X
|
||||
* entry is skipped (left out of the linked-list) and not advertised.
|
||||
*/
|
||||
cfg_msi = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE +
|
||||
ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
|
||||
|
||||
cfg_msi &= ~ROCKCHIP_PCIE_EP_MSI_CP1_MASK;
|
||||
|
||||
cfg_msix_cp = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE +
|
||||
ROCKCHIP_PCIE_EP_MSIX_CAP_REG) &
|
||||
ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK;
|
||||
|
||||
cfg_msi |= cfg_msix_cp;
|
||||
|
||||
rockchip_pcie_write(rockchip, cfg_msi,
|
||||
PCIE_EP_CONFIG_BASE + ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
|
||||
|
||||
rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE,
|
||||
PCIE_CLIENT_CONFIG);
|
||||
|
||||
return 0;
|
||||
err_epc_mem_exit:
|
||||
pci_epc_mem_exit(epc);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -153,6 +154,12 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt);
|
||||
|
||||
#define rockchip_pcie_read_addr(addr) rockchip_pcie_read(rockchip, addr)
|
||||
/* 100 ms max wait time for PHY PLLs to lock */
|
||||
#define RK_PHY_PLL_LOCK_TIMEOUT_US 100000
|
||||
/* Sleep should be less than 20ms */
|
||||
#define RK_PHY_PLL_LOCK_SLEEP_US 1000
|
||||
|
||||
int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
|
||||
{
|
||||
struct device *dev = rockchip->dev;
|
||||
|
@ -254,6 +261,16 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
|
|||
}
|
||||
}
|
||||
|
||||
err = readx_poll_timeout(rockchip_pcie_read_addr,
|
||||
PCIE_CLIENT_SIDE_BAND_STATUS,
|
||||
regs, !(regs & PCIE_CLIENT_PHY_ST),
|
||||
RK_PHY_PLL_LOCK_SLEEP_US,
|
||||
RK_PHY_PLL_LOCK_TIMEOUT_US);
|
||||
if (err) {
|
||||
dev_err(dev, "PHY PLLs could not lock, %d\n", err);
|
||||
goto err_power_off_phy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Please don't reorder the deassert sequence of the following
|
||||
* four reset pins.
|
||||
|
|
|
@ -38,6 +38,13 @@
|
|||
#define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0)
|
||||
#define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0)
|
||||
#define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080)
|
||||
#define PCIE_CLIENT_LEGACY_INT_CTRL (PCIE_CLIENT_BASE + 0x0c)
|
||||
#define PCIE_CLIENT_INT_IN_ASSERT HIWORD_UPDATE_BIT(0x0002)
|
||||
#define PCIE_CLIENT_INT_IN_DEASSERT HIWORD_UPDATE(0x0002, 0)
|
||||
#define PCIE_CLIENT_INT_PEND_ST_PEND HIWORD_UPDATE_BIT(0x0001)
|
||||
#define PCIE_CLIENT_INT_PEND_ST_NORMAL HIWORD_UPDATE(0x0001, 0)
|
||||
#define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20)
|
||||
#define PCIE_CLIENT_PHY_ST BIT(12)
|
||||
#define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c)
|
||||
#define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0)
|
||||
#define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18
|
||||
|
@ -132,7 +139,10 @@
|
|||
|
||||
#define PCIE_RC_RP_ATS_BASE 0x400000
|
||||
#define PCIE_RC_CONFIG_NORMAL_BASE 0x800000
|
||||
#define PCIE_EP_PF_CONFIG_REGS_BASE 0x800000
|
||||
#define PCIE_RC_CONFIG_BASE 0xa00000
|
||||
#define PCIE_EP_CONFIG_BASE 0xa00000
|
||||
#define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00)
|
||||
#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
|
||||
#define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4)
|
||||
#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18
|
||||
|
@ -148,10 +158,11 @@
|
|||
#define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274)
|
||||
#define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20)
|
||||
|
||||
#define PCIE_ADDR_MASK 0xffffff00
|
||||
#define PCIE_CORE_AXI_CONF_BASE 0xc00000
|
||||
#define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0)
|
||||
#define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f
|
||||
#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00
|
||||
#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK
|
||||
#define PCIE_CORE_OB_REGION_ADDR1 (PCIE_CORE_AXI_CONF_BASE + 0x4)
|
||||
#define PCIE_CORE_OB_REGION_DESC0 (PCIE_CORE_AXI_CONF_BASE + 0x8)
|
||||
#define PCIE_CORE_OB_REGION_DESC1 (PCIE_CORE_AXI_CONF_BASE + 0xc)
|
||||
|
@ -159,7 +170,7 @@
|
|||
#define PCIE_CORE_AXI_INBOUND_BASE 0xc00800
|
||||
#define PCIE_RP_IB_ADDR0 (PCIE_CORE_AXI_INBOUND_BASE + 0x0)
|
||||
#define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f
|
||||
#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00
|
||||
#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK
|
||||
#define PCIE_RP_IB_ADDR1 (PCIE_CORE_AXI_INBOUND_BASE + 0x4)
|
||||
|
||||
/* Size of one AXI Region (not Region 0) */
|
||||
|
@ -216,21 +227,28 @@
|
|||
#define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4
|
||||
#define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19)
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CP1_OFFSET 8
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CP1_MASK GENMASK(15, 8)
|
||||
#define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17)
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET 20
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK GENMASK(22, 20)
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16)
|
||||
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24)
|
||||
#define ROCKCHIP_PCIE_EP_MSIX_CAP_REG 0xb0
|
||||
#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_OFFSET 8
|
||||
#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK GENMASK(15, 8)
|
||||
#define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1
|
||||
#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3
|
||||
#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12))
|
||||
#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \
|
||||
(PCIE_EP_PF_CONFIG_REGS_BASE + (((fn) << 12) & GENMASK(19, 12)))
|
||||
#define ROCKCHIP_PCIE_EP_VIRT_FUNC_BASE(fn) \
|
||||
(PCIE_EP_PF_CONFIG_REGS_BASE + 0x10000 + (((fn) << 12) & GENMASK(19, 12)))
|
||||
#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \
|
||||
(PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008)
|
||||
(PCIE_CORE_AXI_CONF_BASE + 0x0828 + (fn) * 0x0040 + (bar) * 0x0008)
|
||||
#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \
|
||||
(PCIE_RC_RP_ATS_BASE + 0x0844 + (fn) * 0x0040 + (bar) * 0x0008)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \
|
||||
(PCIE_RC_RP_ATS_BASE + 0x0000 + ((r) & 0x1f) * 0x0020)
|
||||
(PCIE_CORE_AXI_CONF_BASE + 0x082c + (fn) * 0x0040 + (bar) * 0x0008)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK GENMASK(19, 12)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \
|
||||
(((devfn) << 12) & \
|
||||
|
@ -238,20 +256,21 @@
|
|||
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK GENMASK(27, 20)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \
|
||||
(((bus) << 20) & ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK)
|
||||
#define PCIE_RC_EP_ATR_OB_REGIONS_1_32 (PCIE_CORE_AXI_CONF_BASE + 0x0020)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \
|
||||
(PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0000 + ((r) & 0x1f) * 0x0020)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r) \
|
||||
(PCIE_RC_RP_ATS_BASE + 0x0004 + ((r) & 0x1f) * 0x0020)
|
||||
(PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0004 + ((r) & 0x1f) * 0x0020)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID BIT(23)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK GENMASK(31, 24)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \
|
||||
(((devfn) << 24) & ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r) \
|
||||
(PCIE_RC_RP_ATS_BASE + 0x0008 + ((r) & 0x1f) * 0x0020)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \
|
||||
(PCIE_RC_RP_ATS_BASE + 0x000c + ((r) & 0x1f) * 0x0020)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r) \
|
||||
(PCIE_RC_RP_ATS_BASE + 0x0018 + ((r) & 0x1f) * 0x0020)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r) \
|
||||
(PCIE_RC_RP_ATS_BASE + 0x001c + ((r) & 0x1f) * 0x0020)
|
||||
(PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0008 + ((r) & 0x1f) * 0x0020)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \
|
||||
(PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x000c + ((r) & 0x1f) * 0x0020)
|
||||
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC2(r) \
|
||||
(PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0010 + ((r) & 0x1f) * 0x0020)
|
||||
|
||||
#define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn) \
|
||||
(PCIE_CORE_CTRL_MGMT_BASE + 0x0240 + (fn) * 0x0008)
|
||||
|
|
Loading…
Reference in New Issue