From patchwork Tue Mar 30 07:36:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Green Wan X-Patchwork-Id: 1459918 X-Patchwork-Delegate: uboot@andestech.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4F8hBS1xnvz9sWF for ; Tue, 30 Mar 2021 18:38:08 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E0F8B82952; Tue, 30 Mar 2021 09:37:51 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 9731F82937; Tue, 30 Mar 2021 09:37:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE, SPF_HELO_NONE,UNPARSEABLE_RELAY autolearn=no autolearn_force=no version=3.4.2 Received: from transporter.internal.sifive.com (unknown [64.62.193.209]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9C7DF82900 for ; Tue, 30 Mar 2021 09:37:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=green.wan@sifive.com Received: from gamma15.internal.sifive.com (gamma15.internal.sifive.com [10.14.21.64]) by transporter.internal.sifive.com (Postfix) with ESMTPS id 67D7D201FD; Tue, 30 Mar 2021 00:37:35 -0700 (PDT) Received: from localhost (gamma15.internal.sifive.com [local]) by gamma15.internal.sifive.com (OpenSMTPD) with ESMTPA id 39527a90; Tue, 30 Mar 2021 07:37:33 +0000 (UTC) From: Green Wan To: Cc: bmeng.cn@gmail.com, narmstrong@baylibre.com, Green Wan , Rick Chen , Paul Walmsley , Pragnesh Patel , u-boot@lists.denx.de (open list) Subject: [RFC PATCH 2/3] drivers: pci: refactor SiFive pcie to use designware common code Date: Tue, 30 Mar 2021 00:36:13 -0700 Message-Id: <20210330073615.38787-3-green.wan@sifive.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210330073615.38787-1-green.wan@sifive.com> References: <20210330073615.38787-1-green.wan@sifive.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.4 at phobos.denx.de X-Virus-Status: Clean Refactor pcie_sifive.c to use pcie_dw_common.c. - Add DW_COMMON to defconfig and Kconfig - Move common iomem base address into 'struct pcie_dw' - Remove unnecessary/unused functions after code merge - Rename 'perstn-gpios' to 'reset-gpios' - Remove drivers/pci/pcie_sifive.h Signed-off-by: Green Wan --- configs/sifive_unmatched_defconfig | 1 + drivers/pci/Kconfig | 1 + drivers/pci/pcie_sifive.c | 735 +++++++++-------------------- drivers/pci/pcie_sifive.h | 374 --------------- 4 files changed, 225 insertions(+), 886 deletions(-) delete mode 100644 drivers/pci/pcie_sifive.h diff --git a/configs/sifive_unmatched_defconfig b/configs/sifive_unmatched_defconfig index c5ca0be0bf..7769e366dc 100644 --- a/configs/sifive_unmatched_defconfig +++ b/configs/sifive_unmatched_defconfig @@ -51,3 +51,4 @@ CONFIG_CLK_SIFIVE_PRCI=y CONFIG_DM_PWM=y CONFIG_PWM_SIFIVE=y CONFIG_CMD_PWM=y +CONFIG_PCIE_DW_COMMON=y diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 842240ba42..fd24cef45f 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -102,6 +102,7 @@ config PCIE_SIFIVE_FU740 depends on CLK_SIFIVE_PRCI depends on RESET_SIFIVE depends on SIFIVE_GPIO + select PCIE_DW_COMMON help Say Y here if you want to enable PCIe controller support on FU740. diff --git a/drivers/pci/pcie_sifive.c b/drivers/pci/pcie_sifive.c index ada60876bc..599eb0ece2 100644 --- a/drivers/pci/pcie_sifive.c +++ b/drivers/pci/pcie_sifive.c @@ -11,24 +11,131 @@ * * Based on driver from author: Alan Mikhak */ -#include "pcie_sifive.h" +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcie_dw_common.h" + +struct pcie_sifive { + /* Must be first member of the struct */ + struct pcie_dw dw; + + /* private control regs */ + void __iomem *priv_base; + + /* reset, power, clock resources */ + int sys_int_pin; + struct gpio_desc pwren_gpio; + struct gpio_desc reset_gpio; + struct clk aux_ck; + struct reset_ctl reset; +}; + +enum pcie_sifive_devtype { + SV_PCIE_UNKNOWN_TYPE = 0, + SV_PCIE_ENDPOINT_TYPE = 1, + SV_PCIE_HOST_TYPE = 3 +}; -/* Host Bridge Identification */ -#define DEVICE_NAME "SiFive FU740 PCIe Host Controller" -#define VENDOR_ID 0x51fe -#define DEVICE_ID 0x51fe +#define ASSERTION_DELAY 100 +#define PCIE_PERST_ASSERT 0x0 +#define PCIE_PERST_DEASSERT 0x1 +#define PCIE_PHY_RESET 0x1 +#define PCIE_PHY_RESET_DEASSERT 0x0 +#define GPIO_LOW 0x0 +#define GPIO_HIGH 0x1 +#define PCIE_PHY_SEL 0x1 + +#define sv_info(sv, fmt, arg...) printf(fmt, ## arg) +#define sv_warn(sv, fmt, arg...) printf(fmt, ## arg) +#define sv_debug(sv, fmt, arg...) debug(fmt, ## arg) +#define sv_err(sv, fmt, arg...) printf(fmt, ## arg) + +/* Doorbell Interface */ +#define DBI_OFFSET 0x0 +#define DBI_SIZE 0x1000 + +#define PL_OFFSET 0x700 + +#define PHY_DEBUG_R0 (PL_OFFSET + 0x28) + +#define PHY_DEBUG_R1 (PL_OFFSET + 0x2c) +#define PHY_DEBUG_R1_LINK_UP (0x1 << 4) +#define PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29) + +#define PCIE_MISC_CONTROL_1 0x8bc +#define DBI_RO_WR_EN BIT(0) + +/* pcie reset */ +#define PCIEX8MGMT_PERST_N 0x0 + +/* LTSSM */ +#define PCIEX8MGMT_APP_LTSSM_ENABLE 0x10 +#define LTSSM_ENABLE_BIT BIT(0) + +/* phy reset */ +#define PCIEX8MGMT_APP_HOLD_PHY_RST 0x18 + +/* device type */ +#define PCIEX8MGMT_DEVICE_TYPE 0x708 +#define DEVICE_TYPE_EP 0x0 +#define DEVICE_TYPE_RC 0x4 + +/* phy control registers*/ +#define PCIEX8MGMT_PHY0_CR_PARA_ADDR 0x860 +#define PCIEX8MGMT_PHY0_CR_PARA_RD_EN 0x870 +#define PCIEX8MGMT_PHY0_CR_PARA_RD_DATA 0x878 +#define PCIEX8MGMT_PHY0_CR_PARA_SEL 0x880 +#define PCIEX8MGMT_PHY0_CR_PARA_WR_DATA 0x888 +#define PCIEX8MGMT_PHY0_CR_PARA_WR_EN 0x890 +#define PCIEX8MGMT_PHY0_CR_PARA_ACK 0x898 +#define PCIEX8MGMT_PHY1_CR_PARA_ADDR 0x8a0 +#define PCIEX8MGMT_PHY1_CR_PARA_RD_EN 0x8b0 +#define PCIEX8MGMT_PHY1_CR_PARA_RD_DATA 0x8b8 +#define PCIEX8MGMT_PHY1_CR_PARA_SEL 0x8c0 +#define PCIEX8MGMT_PHY1_CR_PARA_WR_DATA 0x8c8 +#define PCIEX8MGMT_PHY1_CR_PARA_WR_EN 0x8d0 +#define PCIEX8MGMT_PHY1_CR_PARA_ACK 0x8d8 + +#define PCIEX8MGMT_LANE_NUM 8 +#define PCIEX8MGMT_LANE 0x1008 +#define PCIEX8MGMT_LANE_OFF 0x100 +#define PCIEX8MGMT_TERM_MODE 0x0e21 + +#define PCIE_CAP_BASE 0x70 +#define PCI_CONFIG(r) (DBI_OFFSET + (r)) +#define PCIE_CAPABILITIES(r) PCI_CONFIG(PCIE_CAP_BASE + (r)) + +/* Link capability */ +#define PF0_PCIE_CAP_LINK_CAP PCIE_CAPABILITIES(0xc) +#define PCIE_LINK_CAP_MAX_SPEED_MASK 0xf +#define PCIE_LINK_CAP_MAX_SPEED_GEN1 BIT(0) +#define PCIE_LINK_CAP_MAX_SPEED_GEN2 BIT(1) +#define PCIE_LINK_CAP_MAX_SPEED_GEN3 BIT(2) +#define PCIE_LINK_CAP_MAX_SPEED_GEN4 BIT(3) static enum pcie_sifive_devtype pcie_sifive_get_devtype(struct pcie_sifive *sv) { u32 val; - val = readl(sv->priv.iobase + MGMT_MISC_DEVICE_TYPE_OFFSET); + val = readl(sv->priv_base + PCIEX8MGMT_DEVICE_TYPE); switch (val) { - case MGMT_MISC_DEVICE_TYPE_RC: + case DEVICE_TYPE_RC: return SV_PCIE_HOST_TYPE; - case MGMT_MISC_DEVICE_TYPE_EP: + case DEVICE_TYPE_EP: return SV_PCIE_ENDPOINT_TYPE; default: return SV_PCIE_UNKNOWN_TYPE; @@ -40,29 +147,29 @@ static void pcie_sifive_priv_set_state(struct pcie_sifive *sv, u32 reg, { u32 val; - val = readl(sv->priv.iobase + reg); + val = readl(sv->priv_base + reg); val = state ? (val | bits) : (val & !bits); - writel(val, sv->priv.iobase + reg); + writel(val, sv->priv_base + reg); } -static void pcie_sifive_assert_perstn(struct pcie_sifive *sv) +static void pcie_sifive_assert_reset(struct pcie_sifive *sv) { - dm_gpio_set_value(&sv->perstn_gpio, 0); - writel(0x0, sv->priv.iobase + PCIEX8MGMT_PERST_N); - mdelay(100); + dm_gpio_set_value(&sv->reset_gpio, GPIO_LOW); + writel(PCIE_PERST_ASSERT, sv->priv_base + PCIEX8MGMT_PERST_N); + mdelay(ASSERTION_DELAY); } static void pcie_sifive_power_on(struct pcie_sifive *sv) { - dm_gpio_set_value(&sv->pwren_gpio, 1); - mdelay(100); + dm_gpio_set_value(&sv->pwren_gpio, GPIO_HIGH); + mdelay(ASSERTION_DELAY); } -static void pcie_sifive_deassert_perstn(struct pcie_sifive *sv) +static void pcie_sifive_deassert_reset(struct pcie_sifive *sv) { - writel(0x1, sv->priv.iobase + PCIEX8MGMT_PERST_N); - dm_gpio_set_value(&sv->perstn_gpio, 1); - mdelay(100); + writel(PCIE_PERST_DEASSERT, sv->priv_base + PCIEX8MGMT_PERST_N); + dm_gpio_set_value(&sv->reset_gpio, GPIO_HIGH); + mdelay(ASSERTION_DELAY); } static int pcie_sifive_setphy(const u8 phy, const u8 write, @@ -75,22 +182,22 @@ static int pcie_sifive_setphy(const u8 phy, const u8 write, return -2; /* setup phy para */ - writel(addr, sv->priv.iobase + + writel(addr, sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_ADDR : PCIEX8MGMT_PHY0_CR_PARA_ADDR)); if (write) - writel(wrdata, sv->priv.iobase + + writel(wrdata, sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_WR_DATA : PCIEX8MGMT_PHY0_CR_PARA_WR_DATA)); /* enable access if write */ if (write) - writel(1, sv->priv.iobase + + writel(1, sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_WR_EN : PCIEX8MGMT_PHY0_CR_PARA_WR_EN)); else - writel(1, sv->priv.iobase + + writel(1, sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_RD_EN : PCIEX8MGMT_PHY0_CR_PARA_RD_EN)); @@ -98,13 +205,13 @@ static int pcie_sifive_setphy(const u8 phy, const u8 write, do { u32 val; - val = readl(sv->priv.iobase + + val = readl(sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_ACK : PCIEX8MGMT_PHY0_CR_PARA_ACK)); if (val) { ack = 1; if (!write) - readl(sv->priv.iobase + + readl(sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_RD_DATA : PCIEX8MGMT_PHY0_CR_PARA_RD_DATA)); mdelay(1); @@ -113,15 +220,15 @@ static int pcie_sifive_setphy(const u8 phy, const u8 write, /* clear */ if (write) - writel(0, sv->priv.iobase + + writel(0, sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_WR_EN : PCIEX8MGMT_PHY0_CR_PARA_WR_EN)); else - writel(0, sv->priv.iobase + + writel(0, sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_RD_EN : PCIEX8MGMT_PHY0_CR_PARA_RD_EN)); - while (readl(sv->priv.iobase + + while (readl(sv->priv_base + (phy ? PCIEX8MGMT_PHY1_CR_PARA_ACK : PCIEX8MGMT_PHY0_CR_PARA_ACK))) { /* wait for ~wait_idle */ @@ -135,8 +242,8 @@ static void pcie_sifive_init_phy(struct pcie_sifive *sv) int lane; /* enable phy cr_para_sel interfaces */ - writel(0x1, sv->priv.iobase + PCIEX8MGMT_PHY0_CR_PARA_SEL); - writel(0x1, sv->priv.iobase + PCIEX8MGMT_PHY1_CR_PARA_SEL); + writel(PCIE_PHY_SEL, sv->priv_base + PCIEX8MGMT_PHY0_CR_PARA_SEL); + writel(PCIE_PHY_SEL, sv->priv_base + PCIEX8MGMT_PHY1_CR_PARA_SEL); mdelay(1); /* set PHY AC termination mode */ @@ -152,103 +259,11 @@ static void pcie_sifive_init_phy(struct pcie_sifive *sv) } } -static void pcie_sifive_set_pci_int_pin(struct pcie_sifive *sv, - enum pci_interrupt_pin pin) -{ - u32 val; - - /* ctrl_ro_wr_enable */ - val = readl(sv->ctrl.iobase + PCIE_MISC_CONTROL_1); - val |= DBI_RO_WR_EN; - writel(val, sv->ctrl.iobase + PCIE_MISC_CONTROL_1); - - writeb(pin, sv->ctrl.iobase + PCI_CONFIG(PCI_INTERRUPT_PIN)); - - /* ctrl_ro_wr_disable */ - val &= ~DBI_RO_WR_EN; - writel(val, sv->ctrl.iobase + PCIE_MISC_CONTROL_1); -} - -static int pcie_sifive_get_property(struct pcie_sifive *sv, - const char *property) -{ - u32 value = 0; - - if (dev_read_u32(sv->pci.dev, property, &value)) - return 0; - - return value; -} - -static int pcie_sifive_get_required_property(struct pcie_sifive *sv, - const char *property) -{ - int value; - - value = pcie_sifive_get_property(sv, property); - if (value == -EINVAL) - sv_err(sv, "Unable to read %s property\n", property); - - return value; -} - -static u32 pcie_sifive_get_link_width_mask(struct pcie_sifive *sv, int lanes) -{ - switch (lanes) { - case 1: return LINK_WIDTH_1_LANE; - case 2: return LINK_WIDTH_2_LANES; - case 4: return LINK_WIDTH_4_LANES; - case 8: return LINK_WIDTH_8_LANES; - default: return 0; - } -} - -static u32 pcie_sifive_get_link_lanes_mask(struct pcie_sifive *sv, int lanes) -{ - switch (lanes) { - case 1: return LINK_MODE_1_LANE; - case 2: return LINK_MODE_2_LANES; - case 4: return LINK_MODE_4_LANES; - case 8: return LINK_MODE_8_LANES; - default: return 0; - } -} - -static void pcie_sifive_set_link_num_lanes(struct pcie_sifive *sv, int lanes) -{ - u32 mode; - - mode = pcie_sifive_get_link_lanes_mask(sv, lanes); - if (mode) { - u32 val; - - val = readl(sv->ctrl.iobase + LINK_CONTROL); - val &= ~LINK_MODE_MASK; - val |= mode; - writel(val, sv->ctrl.iobase + LINK_CONTROL); - } -} - -static void pcie_sifive_set_link_width(struct pcie_sifive *sv, int lanes) -{ - u32 lwidth; - - lwidth = pcie_sifive_get_link_width_mask(sv, lanes); - if (lwidth) { - u32 val; - - val = readl(sv->ctrl.iobase + LINK_WIDTH_SPEED_CONTROL); - val &= ~LINK_WIDTH_MASK; - val |= lwidth; - writel(val, sv->ctrl.iobase + LINK_WIDTH_SPEED_CONTROL); - } -} - static int pcie_sifive_check_link(struct pcie_sifive *sv) { u32 val; - val = readl(sv->ctrl.iobase + PHY_DEBUG_R1); + val = readl(sv->dw.dbi_base + PHY_DEBUG_R1); return (val & PHY_DEBUG_R1_LINK_UP) && !(val & PHY_DEBUG_R1_LINK_IN_TRAINING); } @@ -264,141 +279,25 @@ static void pcie_sifive_force_gen1(struct pcie_sifive *sv) */ /* ctrl_ro_wr_enable */ - val = readl(sv->ctrl.iobase + PCIE_MISC_CONTROL_1); + val = readl(sv->dw.dbi_base + PCIE_MISC_CONTROL_1); val |= DBI_RO_WR_EN; - writel(val, sv->ctrl.iobase + PCIE_MISC_CONTROL_1); + writel(val, sv->dw.dbi_base + PCIE_MISC_CONTROL_1); /* configure link cap */ - linkcap = readl(sv->ctrl.iobase + PF0_PCIE_CAP_LINK_CAP); + linkcap = readl(sv->dw.dbi_base + PF0_PCIE_CAP_LINK_CAP); linkcap |= PCIE_LINK_CAP_MAX_SPEED_MASK; - writel(linkcap, sv->ctrl.iobase + PF0_PCIE_CAP_LINK_CAP); + writel(linkcap, sv->dw.dbi_base + PF0_PCIE_CAP_LINK_CAP); /* ctrl_ro_wr_disable */ val &= ~DBI_RO_WR_EN; - writel(val, sv->ctrl.iobase + PCIE_MISC_CONTROL_1); + writel(val, sv->dw.dbi_base + PCIE_MISC_CONTROL_1); } static void pcie_sifive_print_phy_debug(struct pcie_sifive *sv) { sv_err(sv, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n", - readl(sv->ctrl.iobase + PHY_DEBUG_R0), - readl(sv->ctrl.iobase + PHY_DEBUG_R1)); -} - -static int pcie_sifive_set_check_atu(struct pcie_sifive *sv, u32 region) -{ - u32 retries, val; - - /* - * Make sure ATU enable takes effect before any subsequent config - * and I/O accesses. - */ - for (retries = 0; retries < ATU_WAIT_MAX_RETRIES; retries++) { - val = readl(sv->ctrl.iobase + region + ATU_REGION_CTRL2); - if (val & ATU_ENABLE) - return 0; - - mdelay(ATU_WAIT); - } - - return -EBUSY; -} - -static void pcie_sifive_set_atu(struct pcie_sifive *sv, u32 region, - u32 ctrl1, u32 ctrl2, u64 size, - u64 base_addr, u64 target_addr) -{ - u64 limit_addr = base_addr + size - 1; - - if (upper_32_bits(size)) - ctrl1 |= ATU_INCREASE_REGION_SIZE; - - writel(lower_32_bits(base_addr), - sv->ctrl.iobase + region + ATU_LOWER_BASE); - writel(upper_32_bits(base_addr), - sv->ctrl.iobase + region + ATU_UPPER_BASE); - writel(lower_32_bits(limit_addr), - sv->ctrl.iobase + region + ATU_LOWER_LIMIT); - writel(upper_32_bits(limit_addr), - sv->ctrl.iobase + region + ATU_UPPER_LIMIT); - writel(lower_32_bits(target_addr), - sv->ctrl.iobase + region + ATU_LOWER_TARGET); - writel(upper_32_bits(target_addr), - sv->ctrl.iobase + region + ATU_UPPER_TARGET); - writel(ctrl1, sv->ctrl.iobase + region + ATU_REGION_CTRL1); - writel(ctrl2 | ATU_ENABLE, sv->ctrl.iobase + region + ATU_REGION_CTRL2); -} - -static void pcie_sifive_set_outbound_atu(struct pcie_sifive *sv, - u32 index, u32 ctrl1, u32 ctrl2, - u64 size, u64 cpu_addr, u64 pci_addr) -{ - u32 region = ATU_CONFIG(ATU_OUTBOUND_REGION(index)); - - pcie_sifive_set_atu(sv, region, ctrl1, ctrl2, size, cpu_addr, pci_addr); - - if (pcie_sifive_set_check_atu(sv, region)) - sv_err(sv, "Outbound ATU could not be enabled\n"); -} - -static void __iomem *pcie_sifive_cfg_outbound_atu(struct pcie_sifive *sv, - u32 bdf, u32 where) -{ - u32 bus, ctrl1; - - where &= ~0x3; - - bus = ((bdf >> 16) & 0xff) - sv->pci.pp.root_bus_nr; - if (!bus) - return sv->ctrl.iobase + PCI_CONFIG(where); - - if (bus == 1) - ctrl1 = ATU_TYPE_CFG0; - else - ctrl1 = ATU_TYPE_CFG1; - - bdf = (bus << 16) | (bdf & 0xffff); - pcie_sifive_set_outbound_atu(sv, 1, ctrl1, 0, SZ_4K, - sv->pci.pp.cfg1_base, - (u64)(bdf << 8)); - - return sv->pci.pp.va_cfg1_base + where; -} - -static void pcie_sifive_set_outbound_mem_atu(struct pcie_sifive *sv, u32 index, - u64 size, u64 cpu_addr, - u64 pci_addr) -{ - pcie_sifive_set_outbound_atu(sv, index, ATU_TYPE_MEM, 0, - size, cpu_addr, pci_addr); -} - -static void pcie_sifive_set_outbound_io_atu(struct pcie_sifive *sv, u32 index, - u64 size, u64 cpu_addr, - u64 pci_addr) -{ - pcie_sifive_set_outbound_atu(sv, index, ATU_TYPE_IO, 0, - size, cpu_addr, pci_addr); -} - -static int pcie_sifive_set_outbound_ecam_atu(struct pcie_sifive *sv, u32 index, - u64 cpu_addr) -{ - pcie_sifive_set_outbound_atu(sv, index++, - ATU_TYPE_CFG0, ATU_CFG_SHIFT_MODE, - SZ_4K, cpu_addr, 0); - - pcie_sifive_set_outbound_atu(sv, index++, - ATU_TYPE_CFG1, ATU_CFG_SHIFT_MODE, - SZ_256M - SZ_1M, - cpu_addr + SZ_1M, - SZ_1M); - return index; -} - -static void pcie_sifive_assert_phy_reset(struct pcie_sifive *sv) -{ - writel(0x1, sv->priv.iobase + PCIEX8MGMT_APP_HOLD_PHY_RST); + readl(sv->dw.dbi_base + PHY_DEBUG_R0), + readl(sv->dw.dbi_base + PHY_DEBUG_R1)); } static int pcie_sifive_wait_for_link(struct pcie_sifive *sv) @@ -414,33 +313,19 @@ static int pcie_sifive_wait_for_link(struct pcie_sifive *sv) mdelay(1); } while (--timeout && !pcie_sifive_check_link(sv)); - val = readl(sv->ctrl.iobase + PHY_DEBUG_R1); + val = readl(sv->dw.dbi_base + PHY_DEBUG_R1); if (!(val & PHY_DEBUG_R1_LINK_UP) || (val & PHY_DEBUG_R1_LINK_IN_TRAINING)) { sv_info(sv, "Failed to negotiate PCIe link!\n"); pcie_sifive_print_phy_debug(sv); - pcie_sifive_assert_phy_reset(sv); + writel(PCIE_PHY_RESET, + sv->priv_base + PCIEX8MGMT_APP_HOLD_PHY_RST); return -ETIMEDOUT; } - sv_info(sv, "PCIe Link up, Gen%i\n", - readw(sv->ctrl.iobase + PF0_PCIE_CAP_LINK_STATUS) & - PCIE_LINK_STATUS_SPEED_MASK); - return 0; } -static void pcie_sifive_setup_link(struct pcie_sifive *sv) -{ - u32 lanes; - - lanes = pcie_sifive_get_required_property(sv, "num-lanes"); - if (lanes > 0) { - pcie_sifive_set_link_num_lanes(sv, lanes); - pcie_sifive_set_link_width(sv, lanes); - } -} - static int pcie_sifive_start_link(struct pcie_sifive *sv) { if (pcie_sifive_check_link(sv)) @@ -449,226 +334,72 @@ static int pcie_sifive_start_link(struct pcie_sifive *sv) pcie_sifive_force_gen1(sv); /* set ltssm */ - pcie_sifive_priv_set_state(sv, MGMT_MISC_LTSSM_ENABLE_OFFSET, - MGMT_MISC_LTSSM_ENABLE_BIT, 1); - return 0; -} - -static void pcie_sifive_setup_host_atu(struct pcie_sifive *sv) -{ - pcie_sifive_set_outbound_mem_atu(sv, 0, - sv->pci.pp.mem_size, - sv->pci.pp.mem_base, - sv->pci.pp.mem_bus_addr); - - if (sv->pci.num_viewport > 2) - pcie_sifive_set_outbound_io_atu(sv, 2, - sv->pci.pp.io_size, - sv->pci.pp.io_base, - sv->pci.pp.io_bus_addr); - - if (sv->pci.pp.ecam.iobase) - pcie_sifive_set_outbound_ecam_atu(sv, 3, - (u64)sv->pci.pp.ecam.iobase); -} - -static void pcie_sifive_setup_host_prefetch(struct pcie_sifive *sv) -{ - u32 val; - - /* ctrl_ro_wr_enable */ - val = readl(sv->ctrl.iobase + PCIE_MISC_CONTROL_1); - val |= DBI_RO_WR_EN; - writel(val, sv->ctrl.iobase + PCIE_MISC_CONTROL_1); - - writew(0xf, sv->ctrl.iobase + PCI_CONFIG(PCI_PREF_MEMORY_BASE)); - writew(0xf, sv->ctrl.iobase + PCI_CONFIG(PCI_PREF_MEMORY_LIMIT)); - writel(0x20, sv->ctrl.iobase + PCI_CONFIG(PCI_PREF_BASE_UPPER32)); - writel(0x40, sv->ctrl.iobase + PCI_CONFIG(PCI_PREF_LIMIT_UPPER32)); - - /* ctrl_ro_wr_disable */ - val &= ~DBI_RO_WR_EN; - writel(val, sv->ctrl.iobase + PCIE_MISC_CONTROL_1); -} - -static void pcie_sifive_setup_host(struct pcie_sifive *sv) -{ - u32 val; - - sv->pci.iatu_unroll_enabled = true; - - pcie_sifive_setup_link(sv); - - /* ctrl_ro_wr_enable */ - val = readl(sv->ctrl.iobase + PCIE_MISC_CONTROL_1); - val |= DBI_RO_WR_EN; - writel(val, sv->ctrl.iobase + PCIE_MISC_CONTROL_1); - - /* Setup correct class code for host bridge */ - writew(PCI_CLASS_BRIDGE_PCI, - sv->ctrl.iobase + PCI_CONFIG(PCI_CLASS_DEVICE)); - - /* ctrl_ro_wr_disable */ - val &= ~DBI_RO_WR_EN; - writel(val, sv->ctrl.iobase + PCIE_MISC_CONTROL_1); - - writeb(PCI_HEADER_TYPE_BRIDGE, - sv->ctrl.iobase + PCI_CONFIG(PCI_HEADER_TYPE)); - - /* Setup RC BARs */ - writel(0x4, sv->ctrl.iobase + PCI_CONFIG(PCI_BASE_ADDRESS_0)); - writel(0x0, sv->ctrl.iobase + PCI_CONFIG(PCI_BASE_ADDRESS_1)); - - pcie_sifive_set_pci_int_pin(sv, PCI_INTERRUPT_INTA); - - /* Setup bus numbers */ - val = readl(sv->ctrl.iobase + PCI_CONFIG(PCI_PRIMARY_BUS)) & - ~0x00ffffff; - val |= 0x00ff0100; - writel(val, sv->ctrl.iobase + PCI_CONFIG(PCI_PRIMARY_BUS)); - - /* Setup command register */ - writew(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | - PCI_COMMAND_SERR, sv->ctrl.iobase + PCI_CONFIG(PCI_COMMAND)); - - pcie_sifive_setup_host_atu(sv); - - writel(0x0, sv->ctrl.iobase + PCI_CONFIG(PCI_BASE_ADDRESS_0)); - - pcie_sifive_setup_host_prefetch(sv); -} - -static int pcie_sifive_init_host(struct pcie_sifive *sv) -{ - pcie_sifive_setup_host(sv); - - if (pcie_sifive_start_link(sv) == -EALREADY) - sv_info(sv, "PCIe link is already up\n"); - else if (pcie_sifive_wait_for_link(sv) == -ETIMEDOUT) - return -ETIMEDOUT; - - return 0; -} - -static int pcie_sifive_addr_valid(struct pcie_sifive *sv, pci_dev_t bdf) -{ - if ((PCI_BUS(bdf) == sv->pci.pp.root_bus_nr) && (PCI_DEV(bdf) > 0)) - return 0; - if ((PCI_BUS(bdf) == sv->pci.pp.root_bus_nr + 1) && (PCI_DEV(bdf) > 0)) - return 0; - - return 1; -} - -static int pcie_sifive_read_config(const struct udevice *bus, pci_dev_t bdf, - uint offset, ulong *valuep, - enum pci_size_t size) -{ - struct pcie_sifive *sv = dev_get_priv(bus); - void __iomem *va; - ulong value; - - sv_debug(sv, "PCIe CFG read: (b,d,f)=(%2d,%2d,%2d) ", - PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); - - if (!pcie_sifive_addr_valid(sv, bdf)) { - sv_debug(sv, "- out of range\n"); - *valuep = pci_get_ff(size); - return 0; - } - - va = pcie_sifive_cfg_outbound_atu(sv, bdf, offset); - value = readl(va); - - sv_debug(sv, "(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); - *valuep = pci_conv_32_to_size(value, offset, size); - - if (sv->pci.num_viewport <= 2) - pcie_sifive_set_outbound_io_atu(sv, 1, - sv->pci.pp.io_size, - sv->pci.pp.io_base, - sv->pci.pp.io_bus_addr); - return 0; -} - -static int pcie_sifive_write_config(struct udevice *bus, pci_dev_t bdf, - uint offset, ulong value, - enum pci_size_t size) -{ - struct pcie_sifive *sv = dev_get_priv(bus); - void __iomem *va; - ulong old; - - sv_debug(sv, "PCIe CFG write: (b,d,f)=(%2d,%2d,%2d) ", - PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); - sv_debug(sv, "(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); - - if (!pcie_sifive_addr_valid(sv, bdf)) { - sv_debug(sv, "- out of range\n"); - return 0; - } - - va = pcie_sifive_cfg_outbound_atu(sv, bdf, offset); - old = readl(va); - value = pci_conv_size_to_32(old, value, offset, size); - writel(value, va); - - if (sv->pci.num_viewport <= 2) - pcie_sifive_set_outbound_io_atu(sv, 1, - sv->pci.pp.io_size, - sv->pci.pp.io_base, - sv->pci.pp.io_bus_addr); + pcie_sifive_priv_set_state(sv, PCIEX8MGMT_APP_LTSSM_ENABLE, + LTSSM_ENABLE_BIT, 1); return 0; } -bool pcie_sifive_set_mode(struct pcie_sifive *sv, enum pcie_sifive_devtype mode) +static int pcie_sifive_init_port(struct udevice *dev, + enum pcie_sifive_devtype mode) { + struct pcie_sifive *sv = dev_get_priv(dev); int ret; - pcie_sifive_assert_perstn(sv); + /* Power on reset */ + pcie_sifive_assert_reset(sv); pcie_sifive_power_on(sv); - pcie_sifive_deassert_perstn(sv); + pcie_sifive_deassert_reset(sv); - clk_enable(&sv->aux_ck); + /* Enable pcieauxclk */ + ret = clk_enable(&sv->aux_ck); + if (ret) + dev_err(dev, "unable to enable pcie_aux clock\n"); /* * assert hold_phy_rst (hold the controller LTSSM in reset * after power_up_rst_n for register programming with cr_para) */ - pcie_sifive_assert_phy_reset(sv); + writel(PCIE_PHY_RESET, sv->priv_base + PCIEX8MGMT_APP_HOLD_PHY_RST); /* deassert power_up_rst_n */ ret = reset_deassert(&sv->reset); if (ret < 0) { - pr_err("reset_assert() failed: %d", ret); - return false; + dev_err(dev, "failed to deassert reset"); + return -EINVAL; } pcie_sifive_init_phy(sv); + /* disable pcieauxclk */ clk_disable(&sv->aux_ck); - /* deassert phy reset */ - writel(0x0, sv->priv.iobase + PCIEX8MGMT_APP_HOLD_PHY_RST); + /* deassert hold_phy_rst */ + writel(PCIE_PHY_RESET_DEASSERT, + sv->priv_base + PCIEX8MGMT_APP_HOLD_PHY_RST); /* enable pcieauxclk */ clk_enable(&sv->aux_ck); /* Set desired mode while core is not operational */ if (mode == SV_PCIE_HOST_TYPE) - writel(MGMT_MISC_DEVICE_TYPE_RC, - sv->priv.iobase + MGMT_MISC_DEVICE_TYPE_OFFSET); + writel(DEVICE_TYPE_RC, + sv->priv_base + PCIEX8MGMT_DEVICE_TYPE); else - writel(MGMT_MISC_DEVICE_TYPE_EP, - sv->priv.iobase + MGMT_MISC_DEVICE_TYPE_OFFSET); + writel(DEVICE_TYPE_EP, + sv->priv_base + PCIEX8MGMT_DEVICE_TYPE); /* Confirm desired mode from operational core */ if (pcie_sifive_get_devtype(sv) != mode) - return false; + return -EINVAL; - sv->mode = mode; + pcie_dw_setup_host(&sv->dw); - return true; + if (pcie_sifive_start_link(sv) == -EALREADY) + sv_info(sv, "PCIe link is already up\n"); + else if (pcie_sifive_wait_for_link(sv) == -ETIMEDOUT) + return -ETIMEDOUT; + + return 0; } static int pcie_sifive_probe(struct udevice *dev) @@ -678,32 +409,51 @@ static int pcie_sifive_probe(struct udevice *dev) struct pci_controller *hose = dev_get_uclass_priv(parent); int err; - sv->ctrl.iobase = (void __iomem *)sv->ctrl.phys_base; - sv->priv.iobase = (void __iomem *)sv->priv.phys_base; + sv->dw.first_busno = dev_seq(dev); + sv->dw.dev = dev; + + err = pcie_sifive_init_port(dev, SV_PCIE_HOST_TYPE); + if (err) { + sv_info(sv, "Failed to init port.\n"); + return err; + } - sv->pci.dev = dev; - sv->pci.pp.root_bus_nr = dev_seq(dev); + printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", + dev_seq(dev), pcie_dw_get_link_speed(&sv->dw), + pcie_dw_get_link_width(&sv->dw), + hose->first_busno); - sv->pci.pp.io_size = hose->regions[0].size; - sv->pci.pp.io_base = hose->regions[0].phys_start; - sv->pci.pp.io_bus_addr = hose->regions[0].bus_start; + return pcie_dw_prog_outbound_atu_unroll(&sv->dw, + PCIE_ATU_REGION_INDEX0, + PCIE_ATU_TYPE_MEM, + sv->dw.mem.phys_start, + sv->dw.mem.bus_start, + sv->dw.mem.size); +} + +static void __iomem *get_fdt_addr(struct udevice *dev, const char *name) +{ + fdt_addr_t addr; - sv->pci.pp.mem_size = hose->regions[1].size; - sv->pci.pp.mem_base = hose->regions[1].phys_start; - sv->pci.pp.mem_bus_addr = hose->regions[1].bus_start; + addr = dev_read_addr_name(dev, name); - sv->pci.pp.config.iobase = (void __iomem *)sv->pci.pp.config.phys_base; - sv->pci.pp.ecam.iobase = (void __iomem *)sv->pci.pp.ecam.phys_base; + return (addr == FDT_ADDR_T_NONE) ? NULL : (void __iomem *)addr; +} - sv->pci.pp.cfg0_base = sv->pci.pp.config.phys_base; - sv->pci.pp.va_cfg0_base = (void __iomem *)sv->pci.pp.cfg0_base; - sv->pci.pp.cfg0_size = SZ_4K; +static int pcie_sifive_of_to_plat(struct udevice *dev) +{ + struct pcie_sifive *sv = dev_get_priv(dev); + int err; - sv->pci.pp.cfg1_base = sv->pci.pp.cfg0_base + sv->pci.pp.cfg0_size; - sv->pci.pp.va_cfg1_base = (void __iomem *)sv->pci.pp.cfg1_base; - sv->pci.pp.cfg1_size = SZ_4K; + /* get designware DBI base addr */ + sv->dw.dbi_base = get_fdt_addr(dev, "dbi"); + if (!sv->dw.dbi_base) + return -EINVAL; - sv->pci.pp.msi_data = sv->pci.pp.cfg1_base + sv->pci.pp.cfg1_size; + /* get private control base addr */ + sv->priv_base = get_fdt_addr(dev, "mgmt"); + if (!sv->priv_base) + return -EINVAL; gpio_request_by_name(dev, "pwren-gpios", 0, &sv->pwren_gpio, GPIOD_IS_OUT); @@ -713,11 +463,11 @@ static int pcie_sifive_probe(struct udevice *dev) return -EINVAL; } - gpio_request_by_name(dev, "perstn-gpios", 0, &sv->perstn_gpio, + gpio_request_by_name(dev, "reset-gpios", 0, &sv->reset_gpio, GPIOD_IS_OUT); - if (!dm_gpio_is_valid(&sv->perstn_gpio)) { - sv_info(sv, "perstn_gpio is invalid\n"); + if (!dm_gpio_is_valid(&sv->reset_gpio)) { + sv_info(sv, "reset_gpio is invalid\n"); return -EINVAL; } @@ -733,51 +483,12 @@ static int pcie_sifive_probe(struct udevice *dev) return err; } - if (!pcie_sifive_set_mode(sv, SV_PCIE_HOST_TYPE)) { - sv_info(sv, "Unable to set desired PCIe operation mode\n"); - return -EINVAL; - } - - return pcie_sifive_init_host(sv); -} - -static int pcie_sifive_of_to_plat(struct udevice *dev) -{ - struct pcie_sifive *sv = dev_get_priv(dev); - - sv->pci.dev = dev; - - sv->ctrl.phys_base = dev_read_addr_size_name(dev, "dbi", - &sv->ctrl.iosize); - if (sv->ctrl.phys_base == FDT_ADDR_T_NONE) - return -EINVAL; - - sv->priv.phys_base = dev_read_addr_size_name(dev, "mgmt", - &sv->priv.iosize); - if (sv->priv.phys_base == FDT_ADDR_T_NONE) - return -EINVAL; - - sv->pci.pp.config.phys_base = - dev_read_addr_size_name(dev, "config", - &sv->pci.pp.config.iosize); - if (sv->pci.pp.config.phys_base == FDT_ADDR_T_NONE) - return -EINVAL; - - sv->pci.pp.ecam.phys_base = - dev_read_addr_size_name(dev, "ecam", &sv->pci.pp.ecam.iosize); - if (sv->pci.pp.config.phys_base == FDT_ADDR_T_NONE) - sv->pci.pp.ecam.phys_base = 0; - - sv->pci.num_viewport = pcie_sifive_get_property(sv, "num-viewport"); - if (sv->pci.num_viewport == 0) - sv->pci.num_viewport = 2; - return 0; } static const struct dm_pci_ops pcie_sifive_ops = { - .read_config = pcie_sifive_read_config, - .write_config = pcie_sifive_write_config + .read_config = pcie_dw_read_config, + .write_config = pcie_dw_write_config, }; static const struct udevice_id pcie_sifive_ids[] = { diff --git a/drivers/pci/pcie_sifive.h b/drivers/pci/pcie_sifive.h deleted file mode 100644 index d12c1f715e..0000000000 --- a/drivers/pci/pcie_sifive.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * SiFive FU740 DesignWare PCIe Controller - * - * Copyright (C) 2020-2021 SiFive, Inc. - * - * Based in early part on the i.MX6 PCIe host controller shim which is: - * - * Copyright (C) 2013 Kosagi - * http://www.kosagi.com - * - * Based on driver from author: Alan Mikhak - */ - -#ifndef __PCIE_SIFIVE_H__ -#define __PCIE_SIFIVE_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_MSI_IRQS 256 -#define MAX_MSI_IRQS_PER_CTRL 32 -#define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL) - -enum pcie_sifive_devtype { - SV_PCIE_UNKNOWN_TYPE = 0, - SV_PCIE_ENDPOINT_TYPE = 1, - SV_PCIE_HOST_TYPE = 3 -}; - -struct sv_iomem { - fdt_size_t iosize; - void __iomem *iobase; - fdt_addr_t phys_base; -}; - -struct pcie_sifive { - struct { - struct udevice *dev; - u32 num_viewport; - u8 iatu_unroll_enabled; - struct { - u8 root_bus_nr; - u64 cfg0_base; - void __iomem *va_cfg0_base; - fdt_size_t cfg0_size; - u64 cfg1_base; - void __iomem *va_cfg1_base; - fdt_size_t cfg1_size; - u32 io_size; - u64 io_base; - u64 io_bus_addr; - u64 mem_size; - u64 mem_base; - u64 mem_bus_addr; - u64 msi_data; - u32 num_vectors; - u32 irq_mask[MAX_MSI_CTRLS]; - struct sv_iomem config; - struct sv_iomem ecam; - } pp; - } pci; - struct sv_iomem ctrl; - struct sv_iomem priv; - enum pcie_sifive_devtype mode; - int sys_int_pin; - struct gpio_desc pwren_gpio; - struct gpio_desc perstn_gpio; - struct clk aux_ck; - struct reset_ctl reset; -}; - -#define sv_info(sv, fmt, arg...) printf(fmt, ## arg) -#define sv_warn(sv, fmt, arg...) printf(fmt, ## arg) -#define sv_debug(sv, fmt, arg...) debug(fmt, ## arg) -#define sv_err(sv, fmt, arg...) printf(fmt, ## arg) - -#define pci_epf_header pci_ep_header - -#define VENDOR_ID_MASK GENMASK(15, 0) -#define DEVICE_ID_SHIFT 16 - -#ifndef PCI_MSIX_FLAGS -#define PCI_MSIX_FLAGS 2 /* Message Control */ -#define PCI_MSIX_FLAGS_QSIZE 0x07FF /* Table size */ -#define PCI_MSIX_FLAGS_MASKALL 0x4000 /* Mask all vectors */ -#define PCI_MSIX_FLAGS_ENABLE 0x8000 /* MSI-X enable */ -#endif - -#ifndef PCI_REBAR_CAP -#define PCI_REBAR_CAP 4 /* capability register */ -#define PCI_REBAR_CAP_SIZES 0x00FFFFF0 /* supported BAR sizes */ -#endif - -#ifndef PCI_REBAR_CTRL -#define PCI_REBAR_CTRL 8 /* control register */ -#define PCI_REBAR_CTRL_BAR_IDX 0x00000007 /* BAR index */ -#define PCI_REBAR_CTRL_NBAR_MASK 0x000000E0 /* # of resizable BARs */ -#define PCI_REBAR_CTRL_NBAR_SHIFT 5 /* shift for # of BARs */ -#define PCI_REBAR_CTRL_BAR_SIZE 0x00001F00 /* BAR size */ -#define PCI_REBAR_CTRL_BAR_SHIFT 8 /* shift for BAR size */ -#endif - -#define MGMT_MISC_LTSSM_ENABLE_OFFSET 0x10 -#define MGMT_MISC_SYS_INT_OFFSET 0x238 -#define MGMT_MISC_EDMA_XFER_PEND_OFFSET 0x4d0 -#define MGMT_MISC_EDMA_INT_OFFSET 0x630 -#define MGMT_MISC_DEVICE_TYPE_OFFSET 0x708 - -#define MGMT_MISC_LTSSM_ENABLE_BIT BIT(0) -#define MGMT_MISC_EDMA_XFER_PEND_BIT BIT(0) -#define MGMT_MISC_EDMA_INT_BITS (BIT(1) | BIT(0)) - -#define MGMT_MISC_DEVICE_TYPE_EP 0x0 -#define MGMT_MISC_DEVICE_TYPE_RC 0x4 - -/* Doorbell Interface */ -#define DBI_OFFSET 0x0 -#define DBI_SIZE 0x1000 - -/* Doorbell Interface 2 */ -#define DBI2_OFFSET 0x100000 -#define DBI2_SIZE 0x80 - -/* Address Translation Units */ -#define ATU_OFFSET 0x300000 -#define ATU_SIZE 0x80000 - -/* DMA Engines */ -#define DMA_OFFSET 0x380000 -#define DMA_SIZE 0x80000 - -#define DMA_WRITE_ENGINE_EN_OFFSET 0x0C - -#define DMA_WRITE_DOORBELL_OFFSET 0x10 - -#define DMA_READ_ENGINE_EN_OFFSET 0x2C - -#define DMA_READ_DOORBELL_OFFSET 0x30 - -#define DMA_WRITE_INT_STATUS_OFFSET 0x4C -#define DMA_WRITE_INT_MASK_OFFSET 0x54 -#define DMA_WRITE_INT_CLEAR_OFFSET 0x58 - -#define DMA_READ_INT_STATUS_OFFSET 0xA0 -#define DMA_READ_INT_MASK_OFFSET 0xA8 -#define DMA_READ_INT_CLEAR_OFFSET 0xAC - -#define DMA_WRITE_LL_ERR_EN_OFFSET 0x90 - -#define DMA_READ_LL_ERR_EN_OFFSET 0xC4 - -#define DMA_WRITE_CONTROL1_OFFSET 0x200 -#define DMA_WRITE_TRANSFER_SIZE_OFFSET 0x208 -#define DMA_WRITE_SAR_LOW_OFFSET 0x20C -#define DMA_WRITE_SAR_HI_OFFSET 0x210 -#define DMA_WRITE_DAR_LOW_OFFSET 0x214 -#define DMA_WRITE_DAR_HI_OFFSET 0x218 - -#define DMA_READ_CONTROL1_OFFSET 0x300 -#define DMA_READ_TRANSFER_SIZE_OFFSET 0x308 -#define DMA_READ_SAR_LOW_OFFSET 0x30C -#define DMA_READ_SAR_HI_OFFSET 0x310 -#define DMA_READ_DAR_LOW_OFFSET 0x314 -#define DMA_READ_DAR_HI_OFFSET 0x318 - -#define DMA_CHAN_BIT(chan) (BIT(chan)) -#define DMA_ENABLE_BIT_CHAN(chan) DMA_CHAN_BIT(chan) -#define DMA_LLLAIE_BIT_CHAN(chan) DMA_CHAN_BIT(chan) -#define DMA_INT_DONE_BIT_CHAN(chan) DMA_CHAN_BIT(chan) -#define DMA_INT_ABORT_BIT_CHAN(chan) (BIT((chan) + 16)) - -/* PCIe Port Logic registers (memory-mapped) */ -#define PL_OFFSET 0x700 -#define PCIE_PL_PFLR (PL_OFFSET + 0x08) -#define PCIE_PL_PFLR_LINK_STATE (0x3f << 16) -#define PCIE_PL_PFLR_FORCE_LINK BIT(15) - -#define LINK_CONTROL (PL_OFFSET + 0x10) -#define LINK_MODE(n) ((n) << 16) -#define LINK_MODE_MASK LINK_MODE(0x3f) -#define LINK_MODE_1_LANE LINK_MODE(0x1) -#define LINK_MODE_2_LANES LINK_MODE(0x3) -#define LINK_MODE_4_LANES LINK_MODE(0x7) -#define LINK_MODE_8_LANES LINK_MODE(0xf) - -#define PHY_DEBUG_R0 (PL_OFFSET + 0x28) - -#define PHY_DEBUG_R1 (PL_OFFSET + 0x2c) -#define PHY_DEBUG_R1_LINK_UP (0x1 << 4) -#define PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29) - -#define LINK_WIDTH_SPEED_CONTROL (PL_OFFSET + 0x10c) -#define LINK_WIDTH(n) ((n) << 8) -#define LINK_WIDTH_MASK LINK_WIDTH(0x1f) -#define LINK_WIDTH_1_LANE LINK_WIDTH(0x1) -#define LINK_WIDTH_2_LANES LINK_WIDTH(0x2) -#define LINK_WIDTH_4_LANES LINK_WIDTH(0x4) -#define LINK_WIDTH_8_LANES LINK_WIDTH(0x8) - -#define PHY_STAT (PL_OFFSET + 0x110) -#define PHY_STAT_ACK_LOC 16 - -#define PHY_CTRL (PL_OFFSET + 0x114) -#define PHY_CTRL_DATA_LOC 0 -#define PHY_CTRL_CAP_ADR_LOC 16 -#define PHY_CTRL_CAP_DAT_LOC 17 -#define PHY_CTRL_WR_LOC 18 -#define PHY_CTRL_RD_LOC 19 - -#define MSI_CTRL_BLOCK_SIZE 12 -#define MSI_CTRL_BLOCK(ctrl) ((ctrl) * MSI_CTRL_BLOCK_SIZE) -#define MSI_CTRL_INT_ENABLE(ctrl) (0x828 + MSI_CTRL_BLOCK(ctrl)) -#define MSI_CTRL_INT_MASK(ctrl) (0x82c + MSI_CTRL_BLOCK(ctrl)) -#define MSI_CTRL_INT_STATUS(ctrl) (0x830 + MSI_CTRL_BLOCK(ctrl)) - -#define PCIE_MISC_CONTROL_1 0x8bc -#define DBI_RO_WR_EN BIT(0) - -#define ATU_VIEWPORT 0x900 -#define ATU_REGION_MIN_SIZE BIT(16) -#define ATU_REGION_INBOUND BIT(31) -#define ATU_REGION_OUTBOUND 0 - -#define ATU_VIEWPORT_CTRL_1 0x904 -#define ATU_TYPE_MASK 0xf -#define ATU_TYPE_MEM 0x0 -#define ATU_TYPE_IO 0x2 -#define ATU_TYPE_CFG0 0x4 -#define ATU_TYPE_CFG1 0x5 -#ifdef CONFIG_PCI_ALMOND_FPGA_REV8 -#define ATU_INCREASE_REGION_SIZE 0 -#else -#define ATU_INCREASE_REGION_SIZE BIT(13) -#endif - -#define ATU_VIEWPORT_CTRL_2 0x908 -#define ATU_CFG_SHIFT_MODE BIT(28) -#define ATU_BAR_MATCH_MODE BIT(30) -#define ATU_ENABLE BIT(31) -#define ATU_DISABLE (u32)~ATU_ENABLE - -#define ATU_MAX_IN 16 -#define ATU_MAX_OUT 16 - -#define ATU_WAIT_MAX_RETRIES 5 -#define ATU_WAIT 9 - -/* - * iATU Unroll-specific register definitions - * From 4.80 core version the address translation will be made by unroll - */ -#define ATU_REGION_CTRL1 0x00 -#define ATU_REGION_CTRL2 0x04 -#define ATU_LOWER_BASE 0x08 -#define ATU_UPPER_BASE 0x0C -#define ATU_LOWER_LIMIT 0x10 -#define ATU_LOWER_TARGET 0x14 -#define ATU_UPPER_TARGET 0x18 -#define ATU_UPPER_LIMIT 0x20 - -#define ATU_OUTBOUND_REGION(region) ((region) << 9) -#define ATU_INBOUND_REGION(region) (((region) << 9) | BIT(8)) - -#define SIFIVE_PCIEAUXGATECFG 0x14 -#define SIFIVE_DEVICESRESETREG 0x28 - -#define PCIEX8MGMT_PERST_N 0x0 -#define PCIEX8MGMT_APP_LTSSM_ENABLE 0x10 -#define PCIEX8MGMT_APP_HOLD_PHY_RST 0x18 -#define PCIEX8MGMT_DEVICE_TYPE 0x708 -#define PCIEX8MGMT_PHY0_CR_PARA_ADDR 0x860 -#define PCIEX8MGMT_PHY0_CR_PARA_RD_EN 0x870 -#define PCIEX8MGMT_PHY0_CR_PARA_RD_DATA 0x878 -#define PCIEX8MGMT_PHY0_CR_PARA_SEL 0x880 -#define PCIEX8MGMT_PHY0_CR_PARA_WR_DATA 0x888 -#define PCIEX8MGMT_PHY0_CR_PARA_WR_EN 0x890 -#define PCIEX8MGMT_PHY0_CR_PARA_ACK 0x898 -#define PCIEX8MGMT_PHY1_CR_PARA_ADDR 0x8a0 -#define PCIEX8MGMT_PHY1_CR_PARA_RD_EN 0x8b0 -#define PCIEX8MGMT_PHY1_CR_PARA_RD_DATA 0x8b8 -#define PCIEX8MGMT_PHY1_CR_PARA_SEL 0x8c0 -#define PCIEX8MGMT_PHY1_CR_PARA_WR_DATA 0x8c8 -#define PCIEX8MGMT_PHY1_CR_PARA_WR_EN 0x8d0 -#define PCIEX8MGMT_PHY1_CR_PARA_ACK 0x8d8 - -#define PCIEX8MGMT_LANE_NUM 8 -#define PCIEX8MGMT_LANE 0x1008 -#define PCIEX8MGMT_LANE_OFF 0x100 -#define PCIEX8MGMT_TERM_MODE 0x0e21 - -/* PCIe Port Logic registers (memory-mapped) */ -#define PL_OFFSET 0x700 -#define PCIE_PL_PFLR (PL_OFFSET + 0x08) -#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16) -#define PCIE_PL_PFLR_FORCE_LINK BIT(15) -#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) -#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) -#define PCIE_PL_GEN2_CTRL_OFF (PL_OFFSET + 0x10c) -#define PCIE_PL_DIRECTED_SPEED_CHANGE_OFF 0x20000 - -#define PCIE_PHY_CTRL (PL_OFFSET + 0x114) -#define PCIE_PHY_CTRL_DATA_LOC 0 -#define PCIE_PHY_CTRL_CAP_ADR_LOC 16 -#define PCIE_PHY_CTRL_CAP_DAT_LOC 17 -#define PCIE_PHY_CTRL_WR_LOC 18 -#define PCIE_PHY_CTRL_RD_LOC 19 - -#define PCIE_PHY_STAT (PL_OFFSET + 0x110) -#define PCIE_PHY_STAT_ACK_LOC 16 - -#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C - -/* PCIe Root Complex registers (memory-mapped) */ -#define PCIE_RC_PF0_MSI_CAP 0x50 -#define PCI_MSI_CAP_ID_NEXT_CTRL_REG (PCIE_RC_PF0_MSI_CAP + 0x0) - -#define PCIE_RC_PF0_MSIX_CAP 0x0 - -#define PCIE_DSP_PF0_PCIE_CAP_BASE 0x70 -#define PCIE_RC_LCR (PCIE_DSP_PF0_PCIE_CAP_BASE + 0xc) -#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_GEN3 0x3 -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf - -#define PCIE_RC_LCSR (PCIE_DSP_PF0_PCIE_CAP_BASE + 0x10) - -#define DMA_CONFIG(r) (DMA_OFFSET + (r)) -#define ATU_CONFIG(r) (ATU_OFFSET + (r)) -#define PCI_SHADOW(r) (DBI2_OFFSET + (r)) -#define PCI_CONFIG(r) (DBI_OFFSET + (r)) -#define MSI_CAPABILITIES(r) PCI_CONFIG(PCIE_RC_PF0_MSI_CAP + (r)) -#define MSIX_CAPABILITIES(r) PCI_CONFIG(PCIE_RC_PF0_MSIX_CAP + (r)) -#define PCIE_CAPABILITIES(r) PCI_CONFIG(PCIE_DSP_PF0_PCIE_CAP_BASE + (r)) - -#define PF0_PCIE_CAP_LINK_CAP PCIE_CAPABILITIES(0xc) -#define PCIE_LINK_CAP_MAX_SPEED_MASK 0xf -#define PCIE_LINK_CAP_MAX_SPEED_GEN1 BIT(0) -#define PCIE_LINK_CAP_MAX_SPEED_GEN2 BIT(1) -#define PCIE_LINK_CAP_MAX_SPEED_GEN3 BIT(2) -#define PCIE_LINK_CAP_MAX_SPEED_GEN4 BIT(3) - -#define PF0_PCIE_CAP_LINK_CONTROL PCIE_CAPABILITIES(0x10) - -#define PF0_PCIE_CAP_LINK_STATUS PCIE_CAPABILITIES(0x12) -#define PCIE_LINK_STATUS_SPEED_MASK 0xf - -#define PCI_CFG0_REGION_OFFSET 0x00000000 -#define PCI_CFG0_REGION_SIZE 0x00001000 /* 2^12 = 4KB */ -#define PCI_CFG1_REGION_OFFSET 0x00001000 -#define PCI_CFG1_REGION_SIZE 0x00001000 /* 2^12 = 4KB */ -#define PCI_MSI_REGION_OFFSET 0x00002000 -#define PCI_MSI_REGION_SIZE 0x00001000 /* 2^12 = 4KB */ -#define PCI_IO_REGION_OFFSET 0x00080000 -#define PCI_IO_REGION_SIZE 0x00010000 /* 2^16 = 64KB */ -#define PCI_MEM_REGION_OFFSET 0x04000000 -#define PCI_MEM_REGION_SIZE 0x04000000 /* 2^26 = 64MB */ -#define PCI_AUTOCFG_REGION_OFFSET 0x08000000 -#define PCI_AUTOCFG_REGION_SIZE 0x08000000 /* 2^27 = 128MB */ -#define PCI_ECAM_REGION_OFFSET 0x10000000 -#define PCI_ECAM_REGION_SIZE 0x10000000 /* 2^28 = 256MB */ - -#endif /* __PCIE_SIFIVE_H__ */