sunxi: remove h6 pcie support

This will cause orangepi 3 to fail to boot on 5.10, so remove it.
This commit is contained in:
AmadeusGhost 2022-03-27 23:50:08 +08:00
parent 7a6d119cc1
commit dd5c4f4d6d
7 changed files with 4 additions and 742 deletions

View File

@ -19,13 +19,12 @@ PKG_MIRROR_HASH:=b212d369a5286ebbf6a5616486efa05fa54d4294fd6e9ba2e54fdfae9eda918
PKG_LICENSE:=BSD-3-Clause
PKG_LICENSE_FILES:=license.md
PKG_CONFIG_DEPENDS:=ARM_TRUSTED_FIRMWARE_SUNXI_WRAPPED_PCIE
PKG_MAINTAINER:=Hauke Mehrtens <hauke@hauke-m.de>
include $(INCLUDE_DIR)/trusted-firmware-a.mk
include $(INCLUDE_DIR)/package.mk
define Package/arm-trusted-firmware-sunxi/Default
SECTION:=boot
CATEGORY:=Boot Loaders
@ -43,22 +42,11 @@ define Package/arm-trusted-firmware-sunxi-h6
VARIANT:=sun50i_h6
endef
define Package/arm-trusted-firmware-sunxi-h6/config
config ARM_TRUSTED_FIRMAWRE_SUNXI_WRAPPED_PCIE
depends on PACKAGE_arm-trusted-firmware-sunxi-h6
bool "Enable sunxi wrapped PCIe driver support"
endef
export GCC_HONOUR_COPTS=s
MAKE_VARS = \
CROSS_COMPILE="$(TARGET_CROSS)"
ifneq ($(CONFIG_ARM_TRUSTED_FIRMAWRE_SUNXI_WRAPPED_PCIE),)
MAKE_FLAGS += \
PRELOADED_BL33_BASE=0x40010000
endif
MAKE_FLAGS += \
PLAT=$(BUILD_VARIANT) \
bl31

View File

@ -240,13 +240,10 @@ endef
define U-Boot/orangepi_3
BUILD_SUBTARGET:=cortexa53
NAME:=Orange Pi 3 (H6)
DEPENDS:=+PACKAGE_u-boot-orangepi_3:arm-trusted-firmware-sunxi-h6 \
+@PACKAGE_u-boot-orangepi_3:ARM_TRUSTED_FIRMAWRE_SUNXI_WRAPPED_PCIE \
+PACKAGE_u-boot-orangepi_3:aw-el2-barebone
DEPENDS:=+PACKAGE_u-boot-orangepi_3:arm-trusted-firmware-sunxi-h6
BUILD_DEVICES:=xunlong_orangepi-3
UENV:=h6
ATF:=h6
HYP:=1
endef
define U-Boot/pangolin
@ -398,8 +395,7 @@ UBOOT_TARGETS := \
UBOOT_CONFIGURE_VARS += USE_PRIVATE_LIBGCC=yes
UBOOT_MAKE_FLAGS += \
BL31=$(STAGING_DIR_IMAGE)/bl31_sun50i_$(ATF).bin \
$(if $(HYP),HYP=$(STAGING_DIR_IMAGE)/hyp.bin)
BL31=$(STAGING_DIR_IMAGE)/bl31_sun50i_$(ATF).bin
define Build/InstallDev
$(INSTALL_DIR) $(STAGING_DIR_IMAGE)

View File

@ -176,7 +176,6 @@ CONFIG_DWMAC_SUNXI=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EEPROM_AT24=y
CONFIG_ELF_CORE=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_EXT4_FS=y

View File

@ -69,13 +69,11 @@ CONFIG_ARM64_VA_BITS_39=y
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y
CONFIG_ARM_AMBA=y
CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y
CONFIG_ARM_GIC_V2M=y
CONFIG_ARM_GIC_V3_ITS_PCI=y
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
CONFIG_BLK_MQ_PCI=y
CONFIG_DMA_DIRECT_REMAP=y
CONFIG_DRM_RCAR_WRITEBACK=y
CONFIG_DWMAC_SUN8I=y
CONFIG_EEPROM_AT24=y
CONFIG_EFI_EARLYCON=y
# CONFIG_FLATMEM_MANUAL is not set
CONFIG_FRAME_POINTER=y
@ -102,10 +100,6 @@ CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y
CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_HAVE_PATA_PLATFORM=y
CONFIG_HOLES_IN_ZONE=y
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_CPCI is not set
# CONFIG_HOTPLUG_PCI_PCIE is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_INLINE_READ_LOCK=y
CONFIG_INLINE_READ_LOCK_BH=y
@ -136,25 +130,6 @@ CONFIG_MUSB_PIO_ONLY=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NO_IOPORT_MAP=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_PCI=y
CONFIG_PCIEAER=y
CONFIG_PCIEASPM=y
# CONFIG_PCIEASPM_DEBUG is not set
CONFIG_PCIEASPM_DEFAULT=y
# CONFIG_PCIEASPM_PERFORMANCE is not set
# CONFIG_PCIEASPM_POWERSAVE is not set
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_DW=y
CONFIG_PCIE_DW_HOST=y
CONFIG_PCIE_PME=y
CONFIG_PCIE_SUNXI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PCI_STUB=y
CONFIG_PHY_SUN50I_USB3=y
CONFIG_PINCTRL_SUN50I_A64=y
CONFIG_PINCTRL_SUN50I_A64_R=y
CONFIG_PINCTRL_SUN50I_H5=y
@ -165,7 +140,6 @@ CONFIG_QUEUED_SPINLOCKS=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_SUN6I=y
# CONFIG_SENSORS_DRIVETEMP is not set
# CONFIG_SND_SUN50I_CODEC_ANALOG is not set
CONFIG_SOUND_OSS_CORE_PRECLAIM=y
CONFIG_SPARSEMEM=y

View File

@ -1,589 +0,0 @@
// SPDX-License-Identifier : GPL-2.0
/*
* PCIe RC driver for Allwinner DW PCIe controllers
*
* Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
*
* Copyright (C) 2016 Allwinner Co., Ltd.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/resource.h>
#include <linux/signal.h>
#include <linux/types.h>
#include "pcie-designware.h"
#define PCIE_RC_LCR 0x7c
#define USER_DEFINED_REGISTER_LIST 0x1000
#define PCIE_LTSSM_ENABLE 0x1000
#define PCIE_INT_PENDING 0x1018
#define PCIE_ADDR_PAGE_CFG 0x1020
#define PCIE_AWMISC_INF0_CTRL 0x1030
#define PCIE_ARMISC_INF0_CTRL 0x1034
#define PCIE_LINK_STATUS 0x143C
#define PCIE_PHY_CFG 0x1800
#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1
#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2
#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf
#define SYS_CLK 0
#define PAD_CLK 1
#define RDLH_LINK_UP BIT(1)
#define SMLH_LINK_UP BIT(0)
#define PCIE_LINK_TRAINING BIT(0)
#define PCIE_LINK_UP_MASK (0x3 << 16)
#define LINK_WAIT_MAX_RETRIES 10
#define LINK_WAIT_USLEEP_MIN 90000
#define LINK_WAIT_USLEEP_MAX 100000
#define PERST_DELAY_US 1000
#define PCIE_BAR_NUM 6
#define PCIE_MEM_FLAGS 0x4
#define PCIE_IO_FLAGS 0x1
#define PCIE_BAR_REG 0x4
#define HIGH16_MASK GENMASK(31, 16)
#define LOW16_MASK GENMASK(15, 0)
#define to_sunxi_pcie(x) dev_get_drvdata((x)->dev)
struct sunxi_pcie {
struct dw_pcie *pci;
int link_irq;
int msi_irq;
int speed_gen;
int io_voltage;
struct clk *pcie_ref;
struct clk *pcie_axi;
struct clk *pcie_aux;
struct clk *pcie_bus;
struct reset_control *pcie_power_rst;
struct reset_control *pcie_bus_rst;
struct regulator *reg_vcc;
struct regulator *reg_vdd;
struct regulator *reg_slot;
struct gpio_desc *perst_gpio;
};
static void sunxi_pcie_perst_gpio_assert(struct sunxi_pcie *pcie)
{
gpiod_set_value_cansleep(pcie->perst_gpio, 1);
usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
}
static void sunxi_pcie_perst_gpio_deassert(struct sunxi_pcie *pcie)
{
gpiod_set_value_cansleep(pcie->perst_gpio, 0);
usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
}
static void sunxi_pcie_clk_select(struct dw_pcie *pci, int status)
{
u32 val;
val = dw_pcie_readl_dbi(pci, PCIE_PHY_CFG);
val &= ~(0x1 << 31);
val |= status << 31;
dw_pcie_writel_dbi(pci, PCIE_PHY_CFG, val);
}
static void sunxi_pcie_ltssm_enable(struct dw_pcie *pci)
{
u32 val;
val = dw_pcie_readl_dbi(pci, PCIE_LTSSM_ENABLE);
val |= PCIE_LINK_TRAINING;
dw_pcie_writel_dbi(pci, PCIE_LTSSM_ENABLE, val);
}
static void sunxi_pcie_irqpending(struct dw_pcie *pci)
{
u32 val;
val = dw_pcie_readl_dbi(pci, PCIE_INT_PENDING);
val &= ~(0x3<<16);
dw_pcie_writel_dbi(pci, PCIE_INT_PENDING, val);
}
static void sunxi_pcie_phy_cfg(struct dw_pcie *pci, int enable)
{
u32 val;
val = dw_pcie_readl_dbi(pci, PCIE_PHY_CFG);
if (enable)
val |= 0x1<<0;
else
val &= ~(0x1<<0);
dw_pcie_writel_dbi(pci, PCIE_PHY_CFG, val);
}
static void sunxi_pcie_irqmask(struct dw_pcie *pci)
{
u32 val;
val = dw_pcie_readl_dbi(pci, PCIE_INT_PENDING);
val |= 0x3<<16;
dw_pcie_writel_dbi(pci, PCIE_INT_PENDING, val);
}
static void sunxi_pcie_ltssm_disable(struct dw_pcie *pci)
{
u32 val;
val = dw_pcie_readl_dbi(pci, PCIE_LTSSM_ENABLE);
val &= ~PCIE_LINK_TRAINING;
dw_pcie_writel_dbi(pci, PCIE_LTSSM_ENABLE, val);
}
static int sunxi_pcie_wait_for_speed_change(struct dw_pcie *pci)
{
u32 tmp;
unsigned int retries;
for (retries = 0; retries < 200; retries++) {
tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
/* Test if the speed change finished. */
if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
return 0;
usleep_range(100, 1000);
}
dev_err(pci->dev, "Speed change timeout\n");
return -EINVAL;
}
static int sunxi_pcie_link_up_status(struct dw_pcie *pci)
{
u32 rc;
int ret;
rc = dw_pcie_readl_dbi(pci, PCIE_LINK_STATUS);
if ((rc & RDLH_LINK_UP) && (rc & SMLH_LINK_UP))
ret = 1;
else
ret = 0;
return ret;
}
static int sunxi_pcie_speed_change(struct dw_pcie *pci, int gen)
{
int val;
int ret;
if (gen == 2) {
val = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
val &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
val |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
dw_pcie_writel_dbi(pci, PCIE_RC_LCR, val);
/*
* Start Directed Speed Change so the best possible
* speed both link partners support can be negotiated.
*/
val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
val |= PORT_LOGIC_SPEED_CHANGE;
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
ret = sunxi_pcie_wait_for_speed_change(pci);
if (!ret)
dev_info(pci->dev, "PCI-e speed of Gen%d\n", gen);
else
dev_info(pci->dev, "PCI-e speed of Gen1\n");
} else {
dev_info(pci->dev, "PCI-e speed of Gen1\n");
}
return 0;
}
static int sunxi_pcie_establish_link(struct dw_pcie *pci)
{
struct sunxi_pcie *pcie = to_sunxi_pcie(pci);
if (dw_pcie_link_up(pci)) {
dev_err(pcie->pci->dev, "link is already up\n");
return 0;
}
sunxi_pcie_ltssm_enable(pci);
dw_pcie_wait_for_link(pci);
return 0;
}
static int sunxi_pcie_reset_deassert(struct sunxi_pcie *pcie)
{
int ret;
ret = reset_control_deassert(pcie->pcie_bus_rst);
if (ret) {
dev_err(pcie->pci->dev, "unable to deassert bus reset\n");
return ret;
}
usleep_range(1000, 2000);
if (pcie->io_voltage < 2000000)
sunxi_pcie_phy_cfg(pcie->pci, 1);
else
sunxi_pcie_phy_cfg(pcie->pci, 0);
usleep_range(1000, 2000);
ret = reset_control_deassert(pcie->pcie_power_rst);
if (ret) {
dev_err(pcie->pci->dev, "unable to deassert power reset\n");
goto bus_reset_assert;
}
return 0;
bus_reset_assert:
reset_control_assert(pcie->pcie_bus_rst);
return ret;
}
static int sunxi_pcie_clk_setup(struct sunxi_pcie *pcie)
{
int ret;
ret = clk_prepare_enable(pcie->pcie_ref);
if (ret) {
dev_err(pcie->pci->dev, "unable to enable pcie_ref clock\n");
return ret;
}
ret = clk_prepare_enable(pcie->pcie_axi);
if (ret) {
dev_err(pcie->pci->dev, "unable to enable pcie_axi clock\n");
goto disable_ref;
}
ret = clk_prepare_enable(pcie->pcie_aux);
if (ret) {
dev_err(pcie->pci->dev, "unable to enable pcie_aux clock\n");
goto disable_axi;
}
ret = clk_prepare_enable(pcie->pcie_bus);
if (ret) {
dev_err(pcie->pci->dev, "unable to enable pcie_bus clock\n");
goto disable_aux;
}
return 0;
disable_aux:
clk_disable_unprepare(pcie->pcie_aux);
disable_axi:
clk_disable_unprepare(pcie->pcie_axi);
disable_ref:
clk_disable_unprepare(pcie->pcie_ref);
return ret;
}
static int sunxi_pcie_regulator_enable(struct sunxi_pcie *pcie)
{
int ret;
ret = regulator_enable(pcie->reg_vcc);
if (ret)
return ret;
pcie->io_voltage = regulator_get_voltage(pcie->reg_vcc);
if (pcie->io_voltage < 0) {
ret = pcie->io_voltage;
goto disable_vcc;
}
ret = regulator_enable(pcie->reg_vdd);
if (ret)
goto disable_vcc;
ret = regulator_enable(pcie->reg_slot);
if (ret)
goto disable_vdd;
return 0;
disable_vdd:
regulator_disable(pcie->reg_vdd);
disable_vcc:
regulator_disable(pcie->reg_vcc);
return ret;
}
static irqreturn_t sunxi_pcie_msi_irq_handler(int irq, void *arg)
{
struct sunxi_pcie *pcie = (struct sunxi_pcie *)arg;
return dw_handle_msi_irq(&pcie->pci->pp);
}
static irqreturn_t sunxi_pcie_linkup_handler(int irq, void *arg)
{
struct sunxi_pcie *pcie = (struct sunxi_pcie *)arg;
sunxi_pcie_irqpending(pcie->pci);
return IRQ_HANDLED;
}
static int sunxi_pcie_get_clk_rst(struct platform_device *pdev,
struct sunxi_pcie *pcie)
{
struct device *dev = &pdev->dev;
pcie->pcie_ref = devm_clk_get(dev, "ref");
if (IS_ERR(pcie->pcie_ref)) {
dev_err(dev, "failed to get pcie ref clk\n");
return PTR_ERR(pcie->pcie_ref);
}
pcie->pcie_axi = devm_clk_get(dev, "axi");
if (IS_ERR(pcie->pcie_axi)) {
dev_err(dev, "failed to get pcie axi clk\n");
return PTR_ERR(pcie->pcie_axi);
}
pcie->pcie_aux = devm_clk_get(dev, "aux");
if (IS_ERR(pcie->pcie_aux)) {
dev_err(dev, "failed to get pcie aux clk\n");
return PTR_ERR(pcie->pcie_aux);
}
pcie->pcie_bus = devm_clk_get(dev, "bus");
if (IS_ERR(pcie->pcie_bus)) {
dev_err(dev, "failed to get pcie bus clk\n");
return PTR_ERR(pcie->pcie_bus);
}
pcie->pcie_bus_rst = devm_reset_control_get(dev, "bus");
if (IS_ERR(pcie->pcie_bus_rst)) {
dev_err(dev, "failed to get pcie bus reset\n");
return PTR_ERR(pcie->pcie_bus_rst);
}
pcie->pcie_power_rst = devm_reset_control_get(dev, "power");
if (IS_ERR(pcie->pcie_power_rst)) {
dev_err(dev, "failed to get pcie power reset\n");
return PTR_ERR(pcie->pcie_power_rst);
}
return 0;
}
static int sunxi_pcie_get_regulator(struct platform_device *pdev,
struct sunxi_pcie *pcie)
{
struct device *dev = &pdev->dev;
pcie->reg_vcc = devm_regulator_get(dev, "vcc");
if (IS_ERR(pcie->reg_vcc)) {
dev_err(dev, "failed to get pcie vcc supply\n");
return PTR_ERR(pcie->reg_vcc);
}
pcie->reg_vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(pcie->reg_vdd)) {
dev_err(dev, "failed to get pcie vdd supply\n");
return PTR_ERR(pcie->reg_vdd);
}
pcie->reg_slot = devm_regulator_get(dev, "slot");
if (IS_ERR(pcie->reg_slot)) {
dev_err(dev, "failed to get pcie slot supply\n");
return PTR_ERR(pcie->reg_slot);
}
return 0;
}
static int sunxi_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct sunxi_pcie *pcie = to_sunxi_pcie(pci);
sunxi_pcie_ltssm_disable(pci);
sunxi_pcie_clk_select(pci, PAD_CLK);
dw_pcie_setup_rc(pp);
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_MEM, pp->mem_base,
pp->mem_bus_addr, pp->mem_size);
if (pci->num_viewport > 2)
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2,
PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
sunxi_pcie_establish_link(pci);
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
sunxi_pcie_speed_change(pci, pcie->speed_gen);
return 0;
}
static const struct dw_pcie_host_ops sunxi_pcie_host_ops = {
.host_init = sunxi_pcie_host_init,
};
static const struct dw_pcie_ops sunxi_pcie_ops = {
.link_up = sunxi_pcie_link_up_status,
};
static int sunxi_add_pcie_port(struct sunxi_pcie *pcie,
struct platform_device *pdev)
{
int ret;
struct pcie_port *pp = &pcie->pci->pp;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
pp->msi_irq = platform_get_irq_byname(pdev, "msi");
if (pp->msi_irq < 0)
return pp->msi_irq;
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
sunxi_pcie_msi_irq_handler,
IRQF_SHARED, "sunxi-pcie-msi", pcie);
if (ret) {
dev_err(&pdev->dev, "failed to request MSI IRQ\n");
return ret;
}
}
pp->root_bus_nr = -1;
pp->ops = &sunxi_pcie_host_ops;
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(&pdev->dev, "failed to initialize host\n");
return ret;
}
return 0;
}
static int sunxi_pcie_probe(struct platform_device *pdev)
{
struct sunxi_pcie *sunxi_pcie;
struct dw_pcie *pci;
struct resource *dbi_res;
int ret;
sunxi_pcie = devm_kzalloc(&pdev->dev, sizeof(*sunxi_pcie),
GFP_KERNEL);
if (!sunxi_pcie)
return -ENOMEM;
pci = devm_kzalloc(&pdev->dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
sunxi_pcie->pci = pci;
pci->dev = &pdev->dev;
pci->ops = &sunxi_pcie_ops;
platform_set_drvdata(pdev, sunxi_pcie);
dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
if (!dbi_res)
return -ENODEV;
pci->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_res);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
ret = sunxi_pcie_get_clk_rst(pdev, sunxi_pcie);
if (ret)
return ret;
ret = sunxi_pcie_get_regulator(pdev, sunxi_pcie);
if (ret)
return ret;
sunxi_pcie->perst_gpio = devm_gpiod_get_optional(&pdev->dev, "perst", GPIOD_OUT_LOW);
if (IS_ERR(sunxi_pcie->perst_gpio))
return PTR_ERR(sunxi_pcie->perst_gpio);
ret = of_property_read_u32(pdev->dev.of_node, "max-link-speed", &sunxi_pcie->speed_gen);
if (ret) {
dev_info(&pdev->dev, "No speed generation info specified, fallback to Gen1\n");
sunxi_pcie->speed_gen = 0x1;
}
ret = sunxi_pcie_regulator_enable(sunxi_pcie);
if (ret)
return ret;
ret = sunxi_pcie_clk_setup(sunxi_pcie);
if (ret)
return ret;
ret = sunxi_pcie_reset_deassert(sunxi_pcie);
if (ret)
return ret;
sunxi_pcie_perst_gpio_deassert(sunxi_pcie);
sunxi_pcie_irqmask(pci);
sunxi_pcie->link_irq = platform_get_irq_byname(pdev, "linkup");
ret = devm_request_irq(&pdev->dev, sunxi_pcie->link_irq,
sunxi_pcie_linkup_handler,
IRQF_SHARED, "sunxi-pcie-linkup", sunxi_pcie);
if (ret) {
dev_err(&pdev->dev, "failed to request linkup IRQ\n");
return ret;
}
ret = sunxi_add_pcie_port(sunxi_pcie, pdev);
if (ret < 0)
return ret;
return 0;
}
static int sunxi_pcie_remove(struct platform_device *pdev)
{
struct sunxi_pcie *pcie = platform_get_drvdata(pdev);
sunxi_pcie_perst_gpio_assert(pcie);
reset_control_assert(pcie->pcie_bus_rst);
reset_control_assert(pcie->pcie_power_rst);
clk_disable_unprepare(pcie->pcie_ref);
clk_disable_unprepare(pcie->pcie_axi);
clk_disable_unprepare(pcie->pcie_aux);
clk_disable_unprepare(pcie->pcie_bus);
return 0;
}
static const struct of_device_id sunxi_pcie_of_match[] = {
{ .compatible = "allwinner,sun50i-h6-pcie", },
{},
};
MODULE_DEVICE_TABLE(of, sunxi_pcie_of_match);
static struct platform_driver sunxi_pcie_driver = {
.driver = {
.name = "sunxi-pcie",
.suppress_bind_attrs = true,
.of_match_table = sunxi_pcie_of_match,
},
.remove = sunxi_pcie_remove,
.probe = sunxi_pcie_probe,
};
builtin_platform_driver(sunxi_pcie_driver);

View File

@ -1,89 +0,0 @@
From 9e57b0de548676f361ff5085f3b44f48fd91784f Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sun, 29 Mar 2020 10:56:16 +0800
Subject: [PATCH] add wrapped PCIe for sunxi
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 31 +
drivers/pci/controller/dwc/Kconfig | 8 +
drivers/pci/controller/dwc/Makefile | 1 +
.../pci/controller/dwc/pcie-sunxi.c | 589 ++++++++++++++++++
4 files changed, 629 insertions(+)
create mode 100644 drivers/pci/controller/dwc/pcie-sunxi.c
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -13,6 +13,8 @@
#include <dt-bindings/reset/sun8i-de2.h>
#include <dt-bindings/thermal/thermal.h>
+/memreserve/ 0x40010000 0x00070000;
+
/ {
interrupt-parent = <&gic>;
#address-cells = <1>;
@@ -764,6 +766,36 @@
status = "disabled";
};
+ /* On Allwinner H6 PCIe is quirky and needs to be wrapped */
+ pcie: pcie@5400000 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ compatible = "allwinner,sun50i-h6-pcie";
+ reg = <0x05400000 0x4000>,
+ <0x05410000 0x10000>;
+ reg-names = "dbi", "config";
+ device_type = "pci";
+ bus-range = <0x00 0xff>;
+ ranges = <0x81000000 0 0 0x05e00000 0 0x00010000 /* downstream I/O */
+ 0x82000000 0 0x05500000 0x05500000 0 0x00800000>; /* non-prefetchable memory */
+ num-lanes = <1>;
+ max-link-speed = <2>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "linkup";
+ clocks = <&ccu CLK_PCIE_REF_OUT>,
+ <&ccu CLK_PCIE_MAXI>,
+ <&ccu CLK_PCIE_AUX>,
+ <&ccu CLK_BUS_PCIE>;
+ clock-names = "ref", "axi", "aux", "bus";
+ resets = <&ccu RST_PCIE_POWERUP>, <&ccu RST_BUS_PCIE>;
+ reset-names = "power", "bus";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 1 &gic GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
hdmi: hdmi@6000000 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun50i-h6-dw-hdmi";
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -236,6 +236,14 @@ config PCI_MESON
and therefore the driver re-uses the DesignWare core functions to
implement the driver.
+config PCIE_SUNXI
+ bool "Allwinner SoCs PCIe controllers"
+ depends on PCI_MSI_IRQ_DOMAIN
+ select PCIE_DW_HOST
+ help
+ Say Y here it you want PCIe controller support on Allwinner H6, wrapped
+ to a regular PCIe controller by a hypervisor.
+
config PCIE_TEGRA194
tristate "NVIDIA Tegra194 (and later) PCIe controller"
depends on ARCH_TEGRA_194_SOC || COMPILE_TEST
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o
obj-$(CONFIG_PCIE_HISI_STB) += pcie-histb.o
obj-$(CONFIG_PCI_MESON) += pci-meson.o
obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o
+obj-$(CONFIG_PCIE_SUNXI) += pcie-sunxi.o
obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o
# The following drivers are for devices that use the generic ACPI

View File

@ -1,17 +0,0 @@
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
@@ -207,6 +207,14 @@
status = "okay";
};
+&pcie {
+ vcc-supply = <&reg_bldo2>;
+ vdd-supply = <&reg_dcdcd>;
+ slot-supply = <&reg_aldo3>;
+ perst-gpio = <&pio 3 17 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
&pio {
vcc-pc-supply = <&reg_bldo2>;
vcc-pd-supply = <&reg_cldo1>;