Commit 39b91eb4 authored by Minda Chen's avatar Minda Chen Committed by Bjorn Helgaas

PCI: starfive: Add JH7110 PCIe controller

Add StarFive JH7110 SoC PCIe controller platform driver code, JH7110
with PLDA host PCIe core.

Link: https://lore.kernel.org/linux-pci/20240328091835.14797-22-minda.chen@starfivetech.comCo-developed-by: default avatarKevin Xie <kevin.xie@starfivetech.com>
Signed-off-by: default avatarMinda Chen <minda.chen@starfivetech.com>
Signed-off-by: default avatarKrzysztof Wilczyński <kwilczynski@kernel.org>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarMason Huo <mason.huo@starfivetech.com>
parent 22fe3223
......@@ -17492,6 +17492,7 @@ M: Kevin Xie <kevin.xie@starfivetech.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
F: drivers/pci/controller/plda/pcie-starfive.c
PCIE ENDPOINT DRIVER FOR QUALCOMM
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
......
......@@ -15,4 +15,16 @@ config PCIE_MICROCHIP_HOST
Say Y here if you want kernel to support the Microchip AXI PCIe
Host Bridge driver.
config PCIE_STARFIVE_HOST
tristate "StarFive PCIe host controller"
depends on PCI_MSI && OF
depends on ARCH_STARFIVE || COMPILE_TEST
select PCIE_PLDA_HOST
help
Say Y here if you want to support the StarFive PCIe controller in
host mode. StarFive PCIe controller uses PLDA PCIe core.
If you choose to build this driver as module it will be dynamically
linked and module will be called pcie-starfive.ko.
endmenu
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PCIE_PLDA_HOST) += pcie-plda-host.o
obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
obj-$(CONFIG_PCIE_STARFIVE_HOST) += pcie-starfive.o
......@@ -10,10 +10,20 @@
#define PLDA_MAX_NUM_MSI_IRQS 32
/* PCIe Bridge Phy Regs */
#define GEN_SETTINGS 0x80
#define RP_ENABLE 1
#define PCIE_PCI_IDS_DW1 0x9c
#define IDS_CLASS_CODE_SHIFT 16
#define REVISION_ID_MASK GENMASK(7, 0)
#define CLASS_CODE_ID_MASK GENMASK(31, 8)
#define PCIE_PCI_IRQ_DW0 0xa8
#define MSIX_CAP_MASK BIT(31)
#define NUM_MSI_MSGS_MASK GENMASK(6, 4)
#define NUM_MSI_MSGS_SHIFT 4
#define PCI_MISC 0xb4
#define PHY_FUNCTION_DIS BIT(15)
#define PCIE_WINROM 0xfc
#define PREF_MEM_WIN_64_SUPPORT BIT(3)
#define IMASK_LOCAL 0x180
#define DMA_END_ENGINE_0_MASK 0x00000000u
......@@ -65,6 +75,8 @@
#define ISTATUS_HOST 0x18c
#define IMSI_ADDR 0x190
#define ISTATUS_MSI 0x194
#define PMSG_SUPPORT_RX 0x3f0
#define PMSG_LTR_SUPPORT BIT(2)
/* PCIe Master table init defines */
#define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u
......@@ -86,6 +98,8 @@
#define PCIE_TX_RX_INTERFACE 0x00000000u
#define PCIE_CONFIG_INTERFACE 0x00000001u
#define CONFIG_SPACE_ADDR_OFFSET 0x1000u
#define ATR_ENTRY_SIZE 32
enum plda_int_event {
......@@ -201,4 +215,59 @@ static inline void plda_set_default_msi(struct plda_msi *msi)
msi->vector_phy = IMSI_ADDR;
msi->num_vectors = PLDA_MAX_NUM_MSI_IRQS;
}
#endif
static inline void plda_pcie_enable_root_port(struct plda_pcie_rp *plda)
{
u32 value;
value = readl_relaxed(plda->bridge_addr + GEN_SETTINGS);
value |= RP_ENABLE;
writel_relaxed(value, plda->bridge_addr + GEN_SETTINGS);
}
static inline void plda_pcie_set_standard_class(struct plda_pcie_rp *plda)
{
u32 value;
/* set class code and reserve revision id */
value = readl_relaxed(plda->bridge_addr + PCIE_PCI_IDS_DW1);
value &= REVISION_ID_MASK;
value |= (PCI_CLASS_BRIDGE_PCI << IDS_CLASS_CODE_SHIFT);
writel_relaxed(value, plda->bridge_addr + PCIE_PCI_IDS_DW1);
}
static inline void plda_pcie_set_pref_win_64bit(struct plda_pcie_rp *plda)
{
u32 value;
value = readl_relaxed(plda->bridge_addr + PCIE_WINROM);
value |= PREF_MEM_WIN_64_SUPPORT;
writel_relaxed(value, plda->bridge_addr + PCIE_WINROM);
}
static inline void plda_pcie_disable_ltr(struct plda_pcie_rp *plda)
{
u32 value;
value = readl_relaxed(plda->bridge_addr + PMSG_SUPPORT_RX);
value &= ~PMSG_LTR_SUPPORT;
writel_relaxed(value, plda->bridge_addr + PMSG_SUPPORT_RX);
}
static inline void plda_pcie_disable_func(struct plda_pcie_rp *plda)
{
u32 value;
value = readl_relaxed(plda->bridge_addr + PCI_MISC);
value |= PHY_FUNCTION_DIS;
writel_relaxed(value, plda->bridge_addr + PCI_MISC);
}
static inline void plda_pcie_write_rc_bar(struct plda_pcie_rp *plda, u64 val)
{
void __iomem *addr = plda->bridge_addr + CONFIG_SPACE_ADDR_OFFSET;
writel_relaxed(lower_32_bits(val), addr + PCI_BASE_ADDRESS_0);
writel_relaxed(upper_32_bits(val), addr + PCI_BASE_ADDRESS_1);
}
#endif /* _PCIE_PLDA_H */
This diff is collapsed.
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