Re: [PATCH v3 3/6] pci: Add Rockchip PCIe controller driver
On Sat, May 9, 2020 at 10:26 PM Jagan Teki wrote: > Add Rockchip PCIe controller driver for rk3399 platform. > > Driver support Gen1 by operating as a Root complex. > > Thanks to Patrick for initial work. > > Signed-off-by: Patrick Wildt > Signed-off-by: Jagan Teki > Reviewed-by: Kever Yang > --- > Changes for v3: > - none > > drivers/pci/Kconfig | 8 + > drivers/pci/Makefile| 1 + > drivers/pci/pcie_rockchip.c | 467 > drivers/pci/pcie_rockchip.h | 79 ++ > 4 files changed, 555 insertions(+) > create mode 100644 drivers/pci/pcie_rockchip.c > create mode 100644 drivers/pci/pcie_rockchip.h > > diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig > index 437cd9a055..3dba84103b 100644 > --- a/drivers/pci/Kconfig > +++ b/drivers/pci/Kconfig > @@ -197,4 +197,12 @@ config PCIE_MEDIATEK > Say Y here if you want to enable Gen2 PCIe controller, > which could be found on MT7623 SoC family. > > +config PCIE_ROCKCHIP > + bool "Enable Rockchip PCIe driver" > + select DM_PCI > + default y if ROCKCHIP_RK3399 > + help > + Say Y here if you want to enable PCIe controller support on > + Rockchip SoCs. > + > endif > diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile > index c051ecc9f3..493e9354dd 100644 > --- a/drivers/pci/Makefile > +++ b/drivers/pci/Makefile > @@ -43,3 +43,4 @@ obj-$(CONFIG_PCI_PHYTIUM) += pcie_phytium.o > obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o > obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o > obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o > +obj-$(CONFIG_PCIE_ROCKCHIP) += pcie_rockchip.o > diff --git a/drivers/pci/pcie_rockchip.c b/drivers/pci/pcie_rockchip.c > new file mode 100644 > index 00..3f06f783ca > --- /dev/null > +++ b/drivers/pci/pcie_rockchip.c > @@ -0,0 +1,467 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Rockchip AXI PCIe host controller driver > + * > + * Copyright (c) 2016 Rockchip, Inc. > + * Copyright (c) 2020 Amarula Solutions(India) > + * Copyright (c) 2020 Jagan Teki > + * Copyright (c) 2019 Patrick Wildt > + * Copyright (c) 2018 Mark Kettenis > + * > + * Bits taken from Linux Rockchip PCIe host controller. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "pcie_rockchip.h" > + > +DECLARE_GLOBAL_DATA_PTR; > + > +static int rockchip_pcie_off_conf(pci_dev_t bdf, uint offset) > +{ > + unsigned int bus = PCI_BUS(bdf); > + unsigned int dev = PCI_DEV(bdf); > + unsigned int func = PCI_FUNC(bdf); > + > + return (bus << 20) | (dev << 15) | (func << 12) | (offset & ~0x3); > +} > + > +static int rockchip_pcie_rd_conf(const struct udevice *udev, pci_dev_t > bdf, > +uint offset, ulong *valuep, > +enum pci_size_t size) > +{ > + struct rockchip_pcie *priv = dev_get_priv(udev); > + unsigned int bus = PCI_BUS(bdf); > + unsigned int dev = PCI_DEV(bdf); > + int where = rockchip_pcie_off_conf(bdf, offset); > + ulong value; > + > + if (bus == priv->first_busno && dev == 0) { > + value = readl(priv->apb_base + PCIE_RC_NORMAL_BASE + > where); > + *valuep = pci_conv_32_to_size(value, offset, size); > + return 0; > + } > + > + if ((bus == priv->first_busno + 1) && dev == 0) { > + value = readl(priv->axi_base + where); > + *valuep = pci_conv_32_to_size(value, offset, size); > + return 0; > + } > + > + *valuep = pci_get_ff(size); > + > + return 0; > +} > + > +static int rockchip_pcie_wr_conf(struct udevice *udev, pci_dev_t bdf, > +uint offset, ulong value, > +enum pci_size_t size) > +{ > + struct rockchip_pcie *priv = dev_get_priv(udev); > + unsigned int bus = PCI_BUS(bdf); > + unsigned int dev = PCI_DEV(bdf); > + int where = rockchip_pcie_off_conf(bdf, offset); > + ulong old; > + > + if (bus == priv->first_busno && dev == 0) { > + old = readl(priv->apb_base + PCIE_RC_NORMAL_BASE + where); > + value = pci_conv_size_to_32(old, value, offset, size); > + writel(value, priv->apb_base + PCIE_RC_NORMAL_BASE + > where); > + return 0; > + } > + > + if ((bus == priv->first_busno + 1) && dev == 0) { > + old = readl(priv->axi_base + where); > + value = pci_conv_size_to_32(old, value, offset, size); > + writel(value, priv->axi_base + where); > + return 0; > + } > + > + return 0; > +} > + > +static int rockchip_pcie_atr_init(struct rockchip_pcie *priv) > +{ > + struct udevice *ctlr = pci_get_controller(priv->dev); > + struct
[PATCH v3 3/6] pci: Add Rockchip PCIe controller driver
Add Rockchip PCIe controller driver for rk3399 platform. Driver support Gen1 by operating as a Root complex. Thanks to Patrick for initial work. Signed-off-by: Patrick Wildt Signed-off-by: Jagan Teki Reviewed-by: Kever Yang --- Changes for v3: - none drivers/pci/Kconfig | 8 + drivers/pci/Makefile| 1 + drivers/pci/pcie_rockchip.c | 467 drivers/pci/pcie_rockchip.h | 79 ++ 4 files changed, 555 insertions(+) create mode 100644 drivers/pci/pcie_rockchip.c create mode 100644 drivers/pci/pcie_rockchip.h diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 437cd9a055..3dba84103b 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -197,4 +197,12 @@ config PCIE_MEDIATEK Say Y here if you want to enable Gen2 PCIe controller, which could be found on MT7623 SoC family. +config PCIE_ROCKCHIP + bool "Enable Rockchip PCIe driver" + select DM_PCI + default y if ROCKCHIP_RK3399 + help + Say Y here if you want to enable PCIe controller support on + Rockchip SoCs. + endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index c051ecc9f3..493e9354dd 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -43,3 +43,4 @@ obj-$(CONFIG_PCI_PHYTIUM) += pcie_phytium.o obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o +obj-$(CONFIG_PCIE_ROCKCHIP) += pcie_rockchip.o diff --git a/drivers/pci/pcie_rockchip.c b/drivers/pci/pcie_rockchip.c new file mode 100644 index 00..3f06f783ca --- /dev/null +++ b/drivers/pci/pcie_rockchip.c @@ -0,0 +1,467 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Rockchip AXI PCIe host controller driver + * + * Copyright (c) 2016 Rockchip, Inc. + * Copyright (c) 2020 Amarula Solutions(India) + * Copyright (c) 2020 Jagan Teki + * Copyright (c) 2019 Patrick Wildt + * Copyright (c) 2018 Mark Kettenis + * + * Bits taken from Linux Rockchip PCIe host controller. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcie_rockchip.h" + +DECLARE_GLOBAL_DATA_PTR; + +static int rockchip_pcie_off_conf(pci_dev_t bdf, uint offset) +{ + unsigned int bus = PCI_BUS(bdf); + unsigned int dev = PCI_DEV(bdf); + unsigned int func = PCI_FUNC(bdf); + + return (bus << 20) | (dev << 15) | (func << 12) | (offset & ~0x3); +} + +static int rockchip_pcie_rd_conf(const struct udevice *udev, pci_dev_t bdf, +uint offset, ulong *valuep, +enum pci_size_t size) +{ + struct rockchip_pcie *priv = dev_get_priv(udev); + unsigned int bus = PCI_BUS(bdf); + unsigned int dev = PCI_DEV(bdf); + int where = rockchip_pcie_off_conf(bdf, offset); + ulong value; + + if (bus == priv->first_busno && dev == 0) { + value = readl(priv->apb_base + PCIE_RC_NORMAL_BASE + where); + *valuep = pci_conv_32_to_size(value, offset, size); + return 0; + } + + if ((bus == priv->first_busno + 1) && dev == 0) { + value = readl(priv->axi_base + where); + *valuep = pci_conv_32_to_size(value, offset, size); + return 0; + } + + *valuep = pci_get_ff(size); + + return 0; +} + +static int rockchip_pcie_wr_conf(struct udevice *udev, pci_dev_t bdf, +uint offset, ulong value, +enum pci_size_t size) +{ + struct rockchip_pcie *priv = dev_get_priv(udev); + unsigned int bus = PCI_BUS(bdf); + unsigned int dev = PCI_DEV(bdf); + int where = rockchip_pcie_off_conf(bdf, offset); + ulong old; + + if (bus == priv->first_busno && dev == 0) { + old = readl(priv->apb_base + PCIE_RC_NORMAL_BASE + where); + value = pci_conv_size_to_32(old, value, offset, size); + writel(value, priv->apb_base + PCIE_RC_NORMAL_BASE + where); + return 0; + } + + if ((bus == priv->first_busno + 1) && dev == 0) { + old = readl(priv->axi_base + where); + value = pci_conv_size_to_32(old, value, offset, size); + writel(value, priv->axi_base + where); + return 0; + } + + return 0; +} + +static int rockchip_pcie_atr_init(struct rockchip_pcie *priv) +{ + struct udevice *ctlr = pci_get_controller(priv->dev); + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + u64 addr, size, offset; + u32 type; + int i, region; + + /* Use region 0 to map PCI configuration space. */ + writel(25 - 1, priv->apb_base + PCIE_ATR_OB_ADDR0(0)); + writel(0, priv->apb_base + PCIE_ATR_OB_ADDR1(0)); + writel(PCIE_ATR_HDR_CFG_TYPE0 | PCIE_ATR_HDR_RID, +