From patchwork Wed Jan 11 12:53:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daire.McNamara@microchip.com X-Patchwork-Id: 641449 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37305C46467 for ; Wed, 11 Jan 2023 12:54:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233116AbjAKMyN (ORCPT ); Wed, 11 Jan 2023 07:54:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56956 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232120AbjAKMxl (ORCPT ); Wed, 11 Jan 2023 07:53:41 -0500 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.154.123]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3232618B1F; Wed, 11 Jan 2023 04:53:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1673441621; x=1704977621; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=x0S9JzNXpNTeJ8BFLbomIJarWQeVxG/Tkx1sxIwVd6Q=; b=gmDgbS54CpTwmgI3vBr2LDzyHlVJSinAq1bEIqMMAX16u5lmXzfegksC MdoIUI4TScvEwCVw2e4xm5uNUeiaTShjrpbVxiut/X7LwCgPi07jmAz76 YRag1XCZrAppP3RwnljxKAi/kElvVmTL/d6DM9+YOIvuiVQpxnvNCLA2S HftpJzvu3+bkzzAmVVgx6VJ6kXOhP0D4yUMujoeyXs+tbwFQBNI1y/gWy qndPy0knwdYYz7Us1v1EJdrJSjZZEJXmVpWYrXoAu1dkHLeufxxhkkDo2 QP+9EkkDUtq4LWXmq1DyS5OCAhN7MllL+rv34zmY41ZT4Xcw8t5Kfg1Ms w==; X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="191745177" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 11 Jan 2023 05:53:40 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Wed, 11 Jan 2023 05:53:37 -0700 Received: from daire-X570.amer.actel.com (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Wed, 11 Jan 2023 05:53:34 -0700 From: To: , , , , , , , , , , , CC: Daire McNamara Subject: [PATCH v3 02/11] PCI: microchip: Remove cast warning for devm_add_action_or_reset() arg Date: Wed, 11 Jan 2023 12:53:14 +0000 Message-ID: <20230111125323.1911373-3-daire.mcnamara@microchip.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230111125323.1911373-1-daire.mcnamara@microchip.com> References: <20230111125323.1911373-1-daire.mcnamara@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Daire McNamara The kernel test robot reported that the ugly cast from void(*)(struct clk *) to void (*)(void *) converts to incompatible function type. This commit adopts the common convention of creating a trivial stub function that takes a void * and passes it to the underlying function that expects the more specific type. Fixes: 6f15a9c9f941 ("PCI: microchip: Add Microchip PolarFire PCIe controller driver") Signed-off-by: Daire McNamara --- drivers/pci/controller/pcie-microchip-host.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/pcie-microchip-host.c index 5c89caaab8c9..5efd480e42fa 100644 --- a/drivers/pci/controller/pcie-microchip-host.c +++ b/drivers/pci/controller/pcie-microchip-host.c @@ -848,6 +848,13 @@ static const struct irq_domain_ops event_domain_ops = { .map = mc_pcie_event_map, }; +static inline void mc_pcie_chip_off_action(void *data) +{ + struct clk *clk = data; + + clk_disable_unprepare(clk); +} + static inline struct clk *mc_pcie_init_clk(struct device *dev, const char *id) { struct clk *clk; @@ -863,8 +870,7 @@ static inline struct clk *mc_pcie_init_clk(struct device *dev, const char *id) if (ret) return ERR_PTR(ret); - devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, - clk); + devm_add_action_or_reset(dev, mc_pcie_chip_off_action, clk); return clk; } From patchwork Wed Jan 11 12:53:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daire.McNamara@microchip.com X-Patchwork-Id: 641448 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E7A5C678D6 for ; Wed, 11 Jan 2023 12:54:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236446AbjAKMyQ (ORCPT ); Wed, 11 Jan 2023 07:54:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57044 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234357AbjAKMxo (ORCPT ); Wed, 11 Jan 2023 07:53:44 -0500 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E729319286; Wed, 11 Jan 2023 04:53:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1673441624; x=1704977624; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ZNue7NifwnVEDIxRwj5YcGOlgVFtkgjYvNNA9HhCHm8=; b=cc4KSK0FRjAMV1QmfAYlBeY9w1ue1hcTji5RSEsM97MZzvds8S/esew/ zbrbtwJqItkkz2KoBFTiXnR8zjkhBGn03fp3GZ8GQ9EwZltEWi30e3Ouo 3tENDS2YpdXzrZrZyQxE6yIIYA4G/C/6rrZI2LsuMn41pFuYj6PPBlqRB 7Z+IqJs2CxQ8+0TAltW6V6AOFtqPW+qQf4LZyrkoh7m0/liNtiXaz/2ev dLGRlklV6OY1lBDgRP24iqnCIly4UIAFlkm+EgCtJ4hAxBdDzw2xNWqVa Q9YwTNA7xTVkd8/mpjTk8904omOWV1/uDlbDp6qG+jyJu+BU28ptO33xN Q==; X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="196330337" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa5.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 11 Jan 2023 05:53:44 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Wed, 11 Jan 2023 05:53:42 -0700 Received: from daire-X570.amer.actel.com (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Wed, 11 Jan 2023 05:53:40 -0700 From: To: , , , , , , , , , , , CC: Daire McNamara Subject: [PATCH v3 04/11] PCI: microchip: Align register, offset, and mask names with hw docs Date: Wed, 11 Jan 2023 12:53:16 +0000 Message-ID: <20230111125323.1911373-5-daire.mcnamara@microchip.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230111125323.1911373-1-daire.mcnamara@microchip.com> References: <20230111125323.1911373-1-daire.mcnamara@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Daire McNamara Minor re-organisation so that macros representing registers ascend in numerical order and use the same names as their hardware documentation. Removed registers not used by the driver. Signed-off-by: Daire McNamara Reviewed-by: Conor Dooley --- drivers/pci/controller/pcie-microchip-host.c | 122 +++++++++---------- 1 file changed, 60 insertions(+), 62 deletions(-) diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/pcie-microchip-host.c index 5efd480e42fa..2efd48ef79d8 100644 --- a/drivers/pci/controller/pcie-microchip-host.c +++ b/drivers/pci/controller/pcie-microchip-host.c @@ -30,66 +30,7 @@ #define MC_PCIE_BRIDGE_ADDR (MC_PCIE1_BRIDGE_ADDR) #define MC_PCIE_CTRL_ADDR (MC_PCIE1_CTRL_ADDR) -/* PCIe Controller Phy Regs */ -#define SEC_ERROR_CNT 0x20 -#define DED_ERROR_CNT 0x24 -#define SEC_ERROR_INT 0x28 -#define SEC_ERROR_INT_TX_RAM_SEC_ERR_INT GENMASK(3, 0) -#define SEC_ERROR_INT_RX_RAM_SEC_ERR_INT GENMASK(7, 4) -#define SEC_ERROR_INT_PCIE2AXI_RAM_SEC_ERR_INT GENMASK(11, 8) -#define SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT GENMASK(15, 12) -#define NUM_SEC_ERROR_INTS (4) -#define SEC_ERROR_INT_MASK 0x2c -#define DED_ERROR_INT 0x30 -#define DED_ERROR_INT_TX_RAM_DED_ERR_INT GENMASK(3, 0) -#define DED_ERROR_INT_RX_RAM_DED_ERR_INT GENMASK(7, 4) -#define DED_ERROR_INT_PCIE2AXI_RAM_DED_ERR_INT GENMASK(11, 8) -#define DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT GENMASK(15, 12) -#define NUM_DED_ERROR_INTS (4) -#define DED_ERROR_INT_MASK 0x34 -#define ECC_CONTROL 0x38 -#define ECC_CONTROL_TX_RAM_INJ_ERROR_0 BIT(0) -#define ECC_CONTROL_TX_RAM_INJ_ERROR_1 BIT(1) -#define ECC_CONTROL_TX_RAM_INJ_ERROR_2 BIT(2) -#define ECC_CONTROL_TX_RAM_INJ_ERROR_3 BIT(3) -#define ECC_CONTROL_RX_RAM_INJ_ERROR_0 BIT(4) -#define ECC_CONTROL_RX_RAM_INJ_ERROR_1 BIT(5) -#define ECC_CONTROL_RX_RAM_INJ_ERROR_2 BIT(6) -#define ECC_CONTROL_RX_RAM_INJ_ERROR_3 BIT(7) -#define ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_0 BIT(8) -#define ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_1 BIT(9) -#define ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_2 BIT(10) -#define ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_3 BIT(11) -#define ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_0 BIT(12) -#define ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_1 BIT(13) -#define ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_2 BIT(14) -#define ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_3 BIT(15) -#define ECC_CONTROL_TX_RAM_ECC_BYPASS BIT(24) -#define ECC_CONTROL_RX_RAM_ECC_BYPASS BIT(25) -#define ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS BIT(26) -#define ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS BIT(27) -#define LTSSM_STATE 0x5c -#define LTSSM_L0_STATE 0x10 -#define PCIE_EVENT_INT 0x14c -#define PCIE_EVENT_INT_L2_EXIT_INT BIT(0) -#define PCIE_EVENT_INT_HOTRST_EXIT_INT BIT(1) -#define PCIE_EVENT_INT_DLUP_EXIT_INT BIT(2) -#define PCIE_EVENT_INT_MASK GENMASK(2, 0) -#define PCIE_EVENT_INT_L2_EXIT_INT_MASK BIT(16) -#define PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK BIT(17) -#define PCIE_EVENT_INT_DLUP_EXIT_INT_MASK BIT(18) -#define PCIE_EVENT_INT_ENB_MASK GENMASK(18, 16) -#define PCIE_EVENT_INT_ENB_SHIFT 16 -#define NUM_PCIE_EVENTS (3) - /* PCIe Bridge Phy Regs */ -#define PCIE_PCI_IDS_DW1 0x9c - -/* PCIe Config space MSI capability structure */ -#define MC_MSI_CAP_CTRL_OFFSET 0xe0u -#define MC_MSI_MAX_Q_AVAIL (MC_NUM_MSI_IRQS_CODED << 1) -#define MC_MSI_Q_SIZE (MC_NUM_MSI_IRQS_CODED << 4) - #define IMASK_LOCAL 0x180 #define DMA_END_ENGINE_0_MASK 0x00000000u #define DMA_END_ENGINE_0_SHIFT 0 @@ -137,7 +78,8 @@ #define ISTATUS_LOCAL 0x184 #define IMASK_HOST 0x188 #define ISTATUS_HOST 0x18c -#define MSI_ADDR 0x190 +#define IMSI_ADDR 0x190 +#define MSI_ADDR 0x190 #define ISTATUS_MSI 0x194 /* PCIe Master table init defines */ @@ -162,6 +104,62 @@ #define ATR_ENTRY_SIZE 32 +/* PCIe Controller Phy Regs */ +#define SEC_ERROR_EVENT_CNT 0x20 +#define DED_ERROR_EVENT_CNT 0x24 +#define SEC_ERROR_INT 0x28 +#define SEC_ERROR_INT_TX_RAM_SEC_ERR_INT GENMASK(3, 0) +#define SEC_ERROR_INT_RX_RAM_SEC_ERR_INT GENMASK(7, 4) +#define SEC_ERROR_INT_PCIE2AXI_RAM_SEC_ERR_INT GENMASK(11, 8) +#define SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT GENMASK(15, 12) +#define NUM_SEC_ERROR_INTS (4) +#define SEC_ERROR_INT_MASK 0x2c +#define DED_ERROR_INT 0x30 +#define DED_ERROR_INT_TX_RAM_DED_ERR_INT GENMASK(3, 0) +#define DED_ERROR_INT_RX_RAM_DED_ERR_INT GENMASK(7, 4) +#define DED_ERROR_INT_PCIE2AXI_RAM_DED_ERR_INT GENMASK(11, 8) +#define DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT GENMASK(15, 12) +#define NUM_DED_ERROR_INTS (4) +#define DED_ERROR_INT_MASK 0x34 +#define ECC_CONTROL 0x38 +#define ECC_CONTROL_TX_RAM_INJ_ERROR_0 BIT(0) +#define ECC_CONTROL_TX_RAM_INJ_ERROR_1 BIT(1) +#define ECC_CONTROL_TX_RAM_INJ_ERROR_2 BIT(2) +#define ECC_CONTROL_TX_RAM_INJ_ERROR_3 BIT(3) +#define ECC_CONTROL_RX_RAM_INJ_ERROR_0 BIT(4) +#define ECC_CONTROL_RX_RAM_INJ_ERROR_1 BIT(5) +#define ECC_CONTROL_RX_RAM_INJ_ERROR_2 BIT(6) +#define ECC_CONTROL_RX_RAM_INJ_ERROR_3 BIT(7) +#define ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_0 BIT(8) +#define ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_1 BIT(9) +#define ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_2 BIT(10) +#define ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_3 BIT(11) +#define ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_0 BIT(12) +#define ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_1 BIT(13) +#define ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_2 BIT(14) +#define ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_3 BIT(15) +#define ECC_CONTROL_TX_RAM_ECC_BYPASS BIT(24) +#define ECC_CONTROL_RX_RAM_ECC_BYPASS BIT(25) +#define ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS BIT(26) +#define ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS BIT(27) +#define PCIE_EVENT_INT 0x14c +#define PCIE_EVENT_INT_L2_EXIT_INT BIT(0) +#define PCIE_EVENT_INT_HOTRST_EXIT_INT BIT(1) +#define PCIE_EVENT_INT_DLUP_EXIT_INT BIT(2) +#define PCIE_EVENT_INT_MASK GENMASK(2, 0) +#define PCIE_EVENT_INT_L2_EXIT_INT_MASK BIT(16) +#define PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK BIT(17) +#define PCIE_EVENT_INT_DLUP_EXIT_INT_MASK BIT(18) +#define PCIE_EVENT_INT_ENB_MASK GENMASK(18, 16) +#define PCIE_EVENT_INT_ENB_SHIFT 16 +#define NUM_PCIE_EVENTS (3) + +/* PCIe Config space MSI capability structure */ +#define MC_MSI_CAP_CTRL_OFFSET 0xe0u +#define MC_MSI_MAX_Q_AVAIL (MC_NUM_MSI_IRQS_CODED << 1) +#define MC_MSI_Q_SIZE (MC_NUM_MSI_IRQS_CODED << 4) + +/* Events */ #define EVENT_PCIE_L2_EXIT 0 #define EVENT_PCIE_HOTRST_EXIT 1 #define EVENT_PCIE_DLUP_EXIT 2 @@ -1092,7 +1090,7 @@ static int mc_platform_init(struct pci_config_window *cfg) SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT; writel_relaxed(val, ctrl_base_addr + SEC_ERROR_INT); writel_relaxed(0, ctrl_base_addr + SEC_ERROR_INT_MASK); - writel_relaxed(0, ctrl_base_addr + SEC_ERROR_CNT); + writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT); val = DED_ERROR_INT_TX_RAM_DED_ERR_INT | DED_ERROR_INT_RX_RAM_DED_ERR_INT | @@ -1100,7 +1098,7 @@ static int mc_platform_init(struct pci_config_window *cfg) DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT; writel_relaxed(val, ctrl_base_addr + DED_ERROR_INT); writel_relaxed(0, ctrl_base_addr + DED_ERROR_INT_MASK); - writel_relaxed(0, ctrl_base_addr + DED_ERROR_CNT); + writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT); writel_relaxed(0, bridge_base_addr + IMASK_HOST); writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST); From patchwork Wed Jan 11 12:53:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daire.McNamara@microchip.com X-Patchwork-Id: 641447 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 82192C678D9 for ; Wed, 11 Jan 2023 12:54:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238193AbjAKMyS (ORCPT ); Wed, 11 Jan 2023 07:54:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57340 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238687AbjAKMxx (ORCPT ); Wed, 11 Jan 2023 07:53:53 -0500 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F09918E18; Wed, 11 Jan 2023 04:53:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1673441629; x=1704977629; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=u8TV9mXCtw966AkKCyV+JI7CAHPwslqmyDM5t6gJDWc=; b=OoVugpqvLV17QrmDANvNMEdZzmz7hsw4qOVX4/cWgWnGXF0a7+j2TMPb VkM7rH5tGGJmi0KJpHMJ/tyv2/04LhlZWxW4cg63MrSqgERBgAHlVFFs1 CRbLA3RYt52Z9gpRSqowuCl64RaXKpSMhyakKXbqLIswsn3gusx8yV/qk ysFkdusxO0bbb+CKo2k8VuYGvB6qCGIzFFiT4xLt39ORVinpVD2BO+NzP IsDYOpnpDG/Uw0cPsJv2uenpIGr3EEOBekmyVSal8AZplWnewND66IQSu N8Zr36yjZg6OSa1/co3CvaSLcMHW4XOcfFCoFNe/EH1j68rux7iJllpJ5 w==; X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="196198543" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 11 Jan 2023 05:53:48 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Wed, 11 Jan 2023 05:53:48 -0700 Received: from daire-X570.amer.actel.com (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Wed, 11 Jan 2023 05:53:45 -0700 From: To: , , , , , , , , , , , CC: Daire McNamara Subject: [PATCH v3 06/11] PCI: microchip: Clean up initialisation of interrupts Date: Wed, 11 Jan 2023 12:53:18 +0000 Message-ID: <20230111125323.1911373-7-daire.mcnamara@microchip.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230111125323.1911373-1-daire.mcnamara@microchip.com> References: <20230111125323.1911373-1-daire.mcnamara@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Daire McNamara Refactor interrupt handling in _init() function into disable_interrupts(), init_interrupts(), clear_sec_errors() and clear ded_errors(). It was unwieldy and prone to bugs. Then clearly disable interrupts as soon as possible and only enable interrupts after address translation is setup to prevent spurious axi2pcie and pcie2axi translation errors being reported Signed-off-by: Daire McNamara Reviewed-by: Conor Dooley --- drivers/pci/controller/pcie-microchip-host.c | 156 ++++++++++++------- 1 file changed, 100 insertions(+), 56 deletions(-) diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/pcie-microchip-host.c index 444ba99b070b..751f0243deb4 100644 --- a/drivers/pci/controller/pcie-microchip-host.c +++ b/drivers/pci/controller/pcie-microchip-host.c @@ -112,6 +112,7 @@ #define SEC_ERROR_INT_RX_RAM_SEC_ERR_INT GENMASK(7, 4) #define SEC_ERROR_INT_PCIE2AXI_RAM_SEC_ERR_INT GENMASK(11, 8) #define SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT GENMASK(15, 12) +#define SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT GENMASK(15, 0) #define NUM_SEC_ERROR_INTS (4) #define SEC_ERROR_INT_MASK 0x2c #define DED_ERROR_INT 0x30 @@ -119,6 +120,7 @@ #define DED_ERROR_INT_RX_RAM_DED_ERR_INT GENMASK(7, 4) #define DED_ERROR_INT_PCIE2AXI_RAM_DED_ERR_INT GENMASK(11, 8) #define DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT GENMASK(15, 12) +#define DED_ERROR_INT_ALL_RAM_DED_ERR_INT GENMASK(15, 0) #define NUM_DED_ERROR_INTS (4) #define DED_ERROR_INT_MASK 0x34 #define ECC_CONTROL 0x38 @@ -992,39 +994,73 @@ static int mc_pcie_setup_windows(struct platform_device *pdev, return 0; } -static int mc_platform_init(struct pci_config_window *cfg) +static inline void mc_clear_secs(struct mc_pcie *port) { - struct device *dev = cfg->parent; - struct platform_device *pdev = to_platform_device(dev); - struct mc_pcie *port; - void __iomem *bridge_base_addr; - void __iomem *ctrl_base_addr; - int ret; - int irq; - int i, intx_irq, msi_irq, event_irq; + void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR; + + writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr + + SEC_ERROR_INT); + writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT); +} + +static inline void mc_clear_deds(struct mc_pcie *port) +{ + void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR; + + writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr + + DED_ERROR_INT); + writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT); +} + +static void mc_disable_interrupts(struct mc_pcie *port) +{ + void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; + void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR; u32 val; - int err; - port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); - if (!port) - return -ENOMEM; - port->dev = dev; + /* Ensure ECC bypass is enabled */ + val = ECC_CONTROL_TX_RAM_ECC_BYPASS | + ECC_CONTROL_RX_RAM_ECC_BYPASS | + ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS | + ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS; + writel_relaxed(val, ctrl_base_addr + ECC_CONTROL); - ret = mc_pcie_init_clks(dev); - if (ret) { - dev_err(dev, "failed to get clock resources, error %d\n", ret); - return -ENODEV; - } + /* Disable SEC errors and clear any outstanding */ + writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr + + SEC_ERROR_INT_MASK); + mc_clear_secs(port); - port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(port->axi_base_addr)) - return PTR_ERR(port->axi_base_addr); + /* Disable DED errors and clear any outstanding */ + writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr + + DED_ERROR_INT_MASK); + mc_clear_deds(port); - bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR; + /* Disable local interrupts and clear any outstanding */ + writel_relaxed(0, bridge_base_addr + IMASK_LOCAL); + writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_LOCAL); + writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_MSI); + + /* Disable PCIe events and clear any outstanding */ + val = PCIE_EVENT_INT_L2_EXIT_INT | + PCIE_EVENT_INT_HOTRST_EXIT_INT | + PCIE_EVENT_INT_DLUP_EXIT_INT | + PCIE_EVENT_INT_L2_EXIT_INT_MASK | + PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK | + PCIE_EVENT_INT_DLUP_EXIT_INT_MASK; + writel_relaxed(val, ctrl_base_addr + PCIE_EVENT_INT); + + /* Disable host interrupts and clear any outstanding */ + writel_relaxed(0, bridge_base_addr + IMASK_HOST); + writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST); +} + +static int mc_init_interrupts(struct platform_device *pdev, struct mc_pcie *port) +{ + struct device *dev = &pdev->dev; + int irq; + int i, intx_irq, msi_irq, event_irq; + int ret; - port->msi.vector_phy = MSI_ADDR; - port->msi.num_vectors = MC_NUM_MSI_IRQS; ret = mc_pcie_init_irq_domains(port); if (ret) { dev_err(dev, "failed creating IRQ domains\n"); @@ -1042,11 +1078,11 @@ static int mc_platform_init(struct pci_config_window *cfg) return -ENXIO; } - err = devm_request_irq(dev, event_irq, mc_event_handler, + ret = devm_request_irq(dev, event_irq, mc_event_handler, 0, event_cause[i].sym, port); - if (err) { + if (ret) { dev_err(dev, "failed to request IRQ %d\n", event_irq); - return err; + return ret; } } @@ -1071,44 +1107,52 @@ static int mc_platform_init(struct pci_config_window *cfg) /* Plug the main event chained handler */ irq_set_chained_handler_and_data(irq, mc_handle_event, port); - /* Hardware doesn't setup MSI by default */ - mc_pcie_enable_msi(port, cfg->win); + return 0; +} - val = readl_relaxed(bridge_base_addr + IMASK_LOCAL); - val |= PM_MSI_INT_INTX_MASK; - writel_relaxed(val, bridge_base_addr + IMASK_LOCAL); +static int mc_platform_init(struct pci_config_window *cfg) +{ + struct device *dev = cfg->parent; + struct platform_device *pdev = to_platform_device(dev); + struct mc_pcie *port; + void __iomem *bridge_base_addr; + int ret; - writel_relaxed(val, ctrl_base_addr + ECC_CONTROL); + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!port) + return -ENOMEM; + port->dev = dev; - val = PCIE_EVENT_INT_L2_EXIT_INT | - PCIE_EVENT_INT_HOTRST_EXIT_INT | - PCIE_EVENT_INT_DLUP_EXIT_INT; - writel_relaxed(val, ctrl_base_addr + PCIE_EVENT_INT); + ret = mc_pcie_init_clks(dev); + if (ret) { + dev_err(dev, "failed to get clock resources, error %d\n", ret); + return -ENODEV; + } - val = SEC_ERROR_INT_TX_RAM_SEC_ERR_INT | - SEC_ERROR_INT_RX_RAM_SEC_ERR_INT | - SEC_ERROR_INT_PCIE2AXI_RAM_SEC_ERR_INT | - SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT; - writel_relaxed(val, ctrl_base_addr + SEC_ERROR_INT); - writel_relaxed(0, ctrl_base_addr + SEC_ERROR_INT_MASK); - writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT); + port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(port->axi_base_addr)) + return PTR_ERR(port->axi_base_addr); - val = DED_ERROR_INT_TX_RAM_DED_ERR_INT | - DED_ERROR_INT_RX_RAM_DED_ERR_INT | - DED_ERROR_INT_PCIE2AXI_RAM_DED_ERR_INT | - DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT; - writel_relaxed(val, ctrl_base_addr + DED_ERROR_INT); - writel_relaxed(0, ctrl_base_addr + DED_ERROR_INT_MASK); - writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT); + mc_disable_interrupts(port); - writel_relaxed(0, bridge_base_addr + IMASK_HOST); - writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST); + bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; + + port->msi.vector_phy = MSI_ADDR; + port->msi.num_vectors = MC_NUM_MSI_IRQS; + + /* Hardware doesn't setup MSI by default */ + mc_pcie_enable_msi(port, cfg->win); /* Configure Address Translation Table 0 for PCIe config space */ mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start & 0xffffffff, cfg->res.start, resource_size(&cfg->res)); - return mc_pcie_setup_windows(pdev, port); + ret = mc_pcie_setup_windows(pdev, port); + if (ret) + return ret; + + /* Address translation is up; safe to enable interrupts */ + return mc_init_interrupts(pdev, port); } static const struct pci_ecam_ops mc_ecam_ops = { From patchwork Wed Jan 11 12:53:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daire.McNamara@microchip.com X-Patchwork-Id: 641446 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AFBACC678DE for ; Wed, 11 Jan 2023 12:54:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238311AbjAKMyU (ORCPT ); Wed, 11 Jan 2023 07:54:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238753AbjAKMxy (ORCPT ); Wed, 11 Jan 2023 07:53:54 -0500 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1614318B3C; Wed, 11 Jan 2023 04:53:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1673441633; x=1704977633; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GdmPZlXUoj4chdSTWuH5rSmXdg6XqEIMz3x/YoPgOQ8=; b=vluzP8GqxmBHsgZSt2kUfd0Tmmw20eM9goSXPA/597JjtgEi9akezbmJ KZqxKhKeX4G1JQDO45tMA7y1iFeS+veMy7Ux1p2Proql3aB9vel8Ndsri hDH1Yxxg/DJIhdUtYMu8aQBIoYOEnrZO299O62pDXsRbbamQn6mHo/6Ap IcCFF6ZmwQKSrwYenteLg1BxvYjUEPCXudyPlL5brV+BDUEso4RzQMBGL pyZwv6aiAO42hWNEG1wxBWb75Mzf6e6UiowzK1PcRZI4jafY1JHa10jLz TikVgKXb2B+fW0iKElZgsjWOqRZAaka1IILBFO6eFSY3HbL1i+mZ0CgPf g==; X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="196198579" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 11 Jan 2023 05:53:52 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Wed, 11 Jan 2023 05:53:50 -0700 Received: from daire-X570.amer.actel.com (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Wed, 11 Jan 2023 05:53:48 -0700 From: To: , , , , , , , , , , , CC: Daire McNamara Subject: [PATCH v3 07/11] PCI: microchip: Gather MSI information from hardware config registers Date: Wed, 11 Jan 2023 12:53:19 +0000 Message-ID: <20230111125323.1911373-8-daire.mcnamara@microchip.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230111125323.1911373-1-daire.mcnamara@microchip.com> References: <20230111125323.1911373-1-daire.mcnamara@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Daire McNamara The PCIe Root Complex on PolarFire SoC is configured at bitstream creation time using Libero. Key MSI-related parameters include the number of MSIs (1/2/4/8/16/32) and the MSI address. In the device driver, extract this information from hw registers at init time, and use it to configure MSI system, including configuring MSI capability structure correctly in configuration space. Signed-off-by: Daire McNamara Reviewed-by: Conor Dooley --- drivers/pci/controller/pcie-microchip-host.c | 73 +++++++++++--------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/pcie-microchip-host.c index 751f0243deb4..9ff0fb04b953 100644 --- a/drivers/pci/controller/pcie-microchip-host.c +++ b/drivers/pci/controller/pcie-microchip-host.c @@ -20,8 +20,7 @@ #include "../pci.h" /* Number of MSI IRQs */ -#define MC_NUM_MSI_IRQS 32 -#define MC_NUM_MSI_IRQS_CODED 5 +#define MC_MAX_NUM_MSI_IRQS 32 /* PCIe Bridge Phy and Controller Phy offsets */ #define MC_PCIE1_BRIDGE_ADDR 0x00008000u @@ -31,6 +30,11 @@ #define MC_PCIE_CTRL_ADDR (MC_PCIE1_CTRL_ADDR) /* PCIe Bridge Phy Regs */ +#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 IMASK_LOCAL 0x180 #define DMA_END_ENGINE_0_MASK 0x00000000u #define DMA_END_ENGINE_0_SHIFT 0 @@ -79,7 +83,6 @@ #define IMASK_HOST 0x188 #define ISTATUS_HOST 0x18c #define IMSI_ADDR 0x190 -#define MSI_ADDR 0x190 #define ISTATUS_MSI 0x194 /* PCIe Master table init defines */ @@ -158,8 +161,6 @@ /* PCIe Config space MSI capability structure */ #define MC_MSI_CAP_CTRL_OFFSET 0xe0u -#define MC_MSI_MAX_Q_AVAIL (MC_NUM_MSI_IRQS_CODED << 1) -#define MC_MSI_Q_SIZE (MC_NUM_MSI_IRQS_CODED << 4) /* Events */ #define EVENT_PCIE_L2_EXIT 0 @@ -259,7 +260,7 @@ struct mc_msi { struct irq_domain *dev_domain; u32 num_vectors; u64 vector_phy; - DECLARE_BITMAP(used, MC_NUM_MSI_IRQS); + DECLARE_BITMAP(used, MC_MAX_NUM_MSI_IRQS); }; struct mc_pcie { @@ -382,25 +383,29 @@ static struct { static char poss_clks[][5] = { "fic0", "fic1", "fic2", "fic3" }; -static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *base) +static void mc_pcie_fixup_ecam(struct mc_pcie *port, void __iomem *ecam) { struct mc_msi *msi = &port->msi; - u32 cap_offset = MC_MSI_CAP_CTRL_OFFSET; - u16 msg_ctrl = readw_relaxed(base + cap_offset + PCI_MSI_FLAGS); - - msg_ctrl |= PCI_MSI_FLAGS_ENABLE; - msg_ctrl &= ~PCI_MSI_FLAGS_QMASK; - msg_ctrl |= MC_MSI_MAX_Q_AVAIL; - msg_ctrl &= ~PCI_MSI_FLAGS_QSIZE; - msg_ctrl |= MC_MSI_Q_SIZE; - msg_ctrl |= PCI_MSI_FLAGS_64BIT; - - writew_relaxed(msg_ctrl, base + cap_offset + PCI_MSI_FLAGS); - + u16 reg; + u8 queue_size; + + /* Fixup MSI enable flag */ + reg = readw_relaxed(ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS); + reg |= PCI_MSI_FLAGS_ENABLE; + writew_relaxed(reg, ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS); + + /* Fixup PCI MSI queue flags */ + queue_size = reg & PCI_MSI_FLAGS_QMASK; + queue_size >>= 1; + reg &= ~PCI_MSI_FLAGS_QSIZE; + reg |= queue_size << 4; + writew_relaxed(reg, ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS); + + /* Fixup MSI addr fields */ writel_relaxed(lower_32_bits(msi->vector_phy), - base + cap_offset + PCI_MSI_ADDRESS_LO); + ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_LO); writel_relaxed(upper_32_bits(msi->vector_phy), - base + cap_offset + PCI_MSI_ADDRESS_HI); + ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI); } static void mc_handle_msi(struct irq_desc *desc) @@ -473,10 +478,7 @@ static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq, { struct mc_pcie *port = domain->host_data; struct mc_msi *msi = &port->msi; - void __iomem *bridge_base_addr = - port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; unsigned long bit; - u32 val; mutex_lock(&msi->lock); bit = find_first_zero_bit(msi->used, msi->num_vectors); @@ -490,11 +492,6 @@ static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_domain_set_info(domain, virq, bit, &mc_msi_bottom_irq_chip, domain->host_data, handle_edge_irq, NULL, NULL); - /* Enable MSI interrupts */ - val = readl_relaxed(bridge_base_addr + IMASK_LOCAL); - val |= PM_MSI_INT_MSI_MASK; - writel_relaxed(val, bridge_base_addr + IMASK_LOCAL); - mutex_unlock(&msi->lock); return 0; @@ -1117,6 +1114,7 @@ static int mc_platform_init(struct pci_config_window *cfg) struct mc_pcie *port; void __iomem *bridge_base_addr; int ret; + u32 val; port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); if (!port) @@ -1137,11 +1135,20 @@ static int mc_platform_init(struct pci_config_window *cfg) bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - port->msi.vector_phy = MSI_ADDR; - port->msi.num_vectors = MC_NUM_MSI_IRQS; + /* Allow enabling MSI by disabling MSI-X */ + val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0); + val &= ~MSIX_CAP_MASK; + writel(val, bridge_base_addr + PCIE_PCI_IRQ_DW0); + + /* Pick num vectors from bitfile programmed onto FPGA fabric */ + val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0); + val &= NUM_MSI_MSGS_MASK; + val >>= NUM_MSI_MSGS_SHIFT; + + port->msi.num_vectors = 1 << val; - /* Hardware doesn't setup MSI by default */ - mc_pcie_enable_msi(port, cfg->win); + /* Pick vector address from design */ + port->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR); /* Configure Address Translation Table 0 for PCIe config space */ mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start & 0xffffffff, From patchwork Wed Jan 11 12:53:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daire.McNamara@microchip.com X-Patchwork-Id: 641445 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BEB4EC678DD for ; Wed, 11 Jan 2023 12:54:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238405AbjAKMyV (ORCPT ); Wed, 11 Jan 2023 07:54:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57106 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238761AbjAKMx6 (ORCPT ); Wed, 11 Jan 2023 07:53:58 -0500 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.154.123]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E87F18B29; Wed, 11 Jan 2023 04:53:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1673441637; x=1704977637; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XjZzyEA3Mqhn9lEm8z2k6gwTcJJ3OWBzPlGR+w1KPQ4=; b=IMTg8AOIz24EHYsog3IEPi74FEpWvQtM6zJD7vcDBsRgAYLA9avvYoNX aIhc+Q3Q1IOoibx9yffn0+49fVl9ISfEf+y0E/gs9Y7ZnaxmoPNzOQhvy bQ6S4h/ZuAGwyuhrHor/OddivL9Uwp4lk7gYZqhqNgz+fHZKneH5o7TTk 4boFGJW/LgyqZqk0hNZ2UDc8UDY15RbqLZscr1w34ZIbXAHfe7+SPmIsP orUMfRItx1rTfLvjIhA7qwMk3aUFvMGrGLPUAhhY/ExVrAWRu6UzELtQt H1ff0NPjYeAXVJq2uvEmQz9DbV5EFxAbh/p2TMdisihZ/5mEGR7PQFMMq A==; X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="195261339" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa2.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 11 Jan 2023 05:53:56 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Wed, 11 Jan 2023 05:53:56 -0700 Received: from daire-X570.amer.actel.com (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Wed, 11 Jan 2023 05:53:53 -0700 From: To: , , , , , , , , , , , CC: Daire McNamara Subject: [PATCH v3 09/11] PCI: microchip: Partition outbound address translation Date: Wed, 11 Jan 2023 12:53:21 +0000 Message-ID: <20230111125323.1911373-10-daire.mcnamara@microchip.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230111125323.1911373-1-daire.mcnamara@microchip.com> References: <20230111125323.1911373-1-daire.mcnamara@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Daire McNamara On Microchip PolarFire SoC the PCIe Root Port is behind a set of Fabric Interface Controller (FIC) buses that encapsulate buses like ABP/AHP and AXI-M. Depending on which FIC(s) the Root Port is wired through to cpu space, the Root Port driver needs to take account of the address translation done by a parent (e.g. fabric) node before setting up its own outbound address translation tables to config space and attached devices. Parse the range properties to determine how much address translation needs to be done in the Root Port. Signed-off-by: Daire McNamara Reviewed-by: Conor Dooley --- drivers/pci/controller/pcie-microchip-host.c | 109 +++++++++++++++---- 1 file changed, 86 insertions(+), 23 deletions(-) diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/pcie-microchip-host.c index c55911c48ec6..f3dfcdf39c8a 100644 --- a/drivers/pci/controller/pcie-microchip-host.c +++ b/drivers/pci/controller/pcie-microchip-host.c @@ -85,27 +85,42 @@ #define IMSI_ADDR 0x190 #define ISTATUS_MSI 0x194 +#define ATR_WINDOW_DESC_SIZE 32 +#define ATR_PCIE_ATR_SIZE 0x25 +#define ATR_SIZE_SHIFT 1 +#define ATR_IMPL_ENABLE 1 + /* PCIe Master table init defines */ #define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u -#define ATR0_PCIE_ATR_SIZE 0x25 -#define ATR0_PCIE_ATR_SIZE_SHIFT 1 #define ATR0_PCIE_WIN0_SRC_ADDR 0x604u #define ATR0_PCIE_WIN0_TRSL_ADDR_LSB 0x608u #define ATR0_PCIE_WIN0_TRSL_ADDR_UDW 0x60cu #define ATR0_PCIE_WIN0_TRSL_PARAM 0x610u +enum { + TRSL_ID_PCIE_TXRX, + TRSL_ID_PCIE_CONFIG, + TRSL_ID_AXI4_LITE_MASTER, + TRSL_ID_AXI4_MASTER_0 = 4, + TRSL_ID_AXI4_MASTER_1, + TRSL_ID_AXI4_MASTER_2, + TRSL_ID_AXI4_MASTER_3, + TRSL_ID_AXI4_STREAM_0, + TRSL_ID_AXI4_STREAM_1, + TRSL_ID_AXI4_STREAM_2, + TRSL_ID_AXI4_STREAM_3, + TRSL_ID_INTERNAL_BRIDGE_REGISTERS +}; + +#define ATR0_PCIE_WIN0_TRSL_MASK_LSB 0x618u +#define ATR0_PCIE_WIN0_TRSL_MASK_UDW 0x61cu + /* PCIe AXI slave table init defines */ #define ATR0_AXI4_SLV0_SRCADDR_PARAM 0x800u -#define ATR_SIZE_SHIFT 1 -#define ATR_IMPL_ENABLE 1 #define ATR0_AXI4_SLV0_SRC_ADDR 0x804u #define ATR0_AXI4_SLV0_TRSL_ADDR_LSB 0x808u #define ATR0_AXI4_SLV0_TRSL_ADDR_UDW 0x80cu #define ATR0_AXI4_SLV0_TRSL_PARAM 0x810u -#define PCIE_TX_RX_INTERFACE 0x00000000u -#define PCIE_CONFIG_INTERFACE 0x00000001u - -#define ATR_ENTRY_SIZE 32 /* PCIe Controller Phy Regs */ #define SEC_ERROR_EVENT_CNT 0x20 @@ -270,6 +285,7 @@ struct mc_pcie { struct irq_domain *event_domain; raw_spinlock_t lock; struct mc_msi msi; + u64 outbound_range_offset; }; struct cause { @@ -936,36 +952,36 @@ static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index, phys_addr_t axi_addr, phys_addr_t pci_addr, size_t size) { - u32 atr_sz = ilog2(size) - 1; + u32 atr_size = ilog2(size) - 1; u32 val; if (index == 0) - val = PCIE_CONFIG_INTERFACE; + val = TRSL_ID_PCIE_CONFIG; else - val = PCIE_TX_RX_INTERFACE; + val = TRSL_ID_PCIE_TXRX; - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + writel(val, bridge_base_addr + (index * ATR_WINDOW_DESC_SIZE) + ATR0_AXI4_SLV0_TRSL_PARAM); - val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) | + val = lower_32_bits(axi_addr) | (atr_size << ATR_SIZE_SHIFT) | ATR_IMPL_ENABLE; - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + writel(val, bridge_base_addr + (index * ATR_WINDOW_DESC_SIZE) + ATR0_AXI4_SLV0_SRCADDR_PARAM); val = upper_32_bits(axi_addr); - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + writel(val, bridge_base_addr + (index * ATR_WINDOW_DESC_SIZE) + ATR0_AXI4_SLV0_SRC_ADDR); val = lower_32_bits(pci_addr); - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + writel(val, bridge_base_addr + (index * ATR_WINDOW_DESC_SIZE) + ATR0_AXI4_SLV0_TRSL_ADDR_LSB); val = upper_32_bits(pci_addr); - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + writel(val, bridge_base_addr + (index * ATR_WINDOW_DESC_SIZE) + ATR0_AXI4_SLV0_TRSL_ADDR_UDW); val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); - val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT); + val |= (ATR_PCIE_ATR_SIZE << ATR_SIZE_SHIFT); writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR); } @@ -978,14 +994,14 @@ static int mc_pcie_setup_windows(struct platform_device *pdev, struct pci_host_bridge *bridge = platform_get_drvdata(pdev); struct resource_entry *entry; u64 pci_addr; - u32 index = 1; + u32 index = 1; /* Window 0 used for config space */ resource_list_for_each_entry(entry, &bridge->windows) { if (resource_type(entry->res) == IORESOURCE_MEM) { pci_addr = entry->res->start - entry->offset; mc_pcie_setup_window(bridge_base_addr, index, - entry->res->start, pci_addr, - resource_size(entry->res)); + entry->res->start - port->outbound_range_offset, + pci_addr, resource_size(entry->res)); index++; } } @@ -1109,6 +1125,44 @@ static int mc_init_interrupts(struct platform_device *pdev, struct mc_pcie *port return 0; } +static int mc_check_for_parent_range_handling(struct platform_device *pdev, struct mc_pcie *port) +{ + struct device *dev = &pdev->dev; + struct device_node *dn = dev->of_node; + struct of_range_parser parser; + struct of_range range; + u64 cpu_addr; + + /* Find any pcie range */ + if (of_range_parser_init(&parser, dn)) { + dev_err(dev, "missing ranges property\n"); + return -EINVAL; + } + + for_each_of_range(&parser, &range) { + cpu_addr = range.cpu_addr; + /* + * First range is enough - extend if anyone ever needs more + * than one fabric interface + */ + break; + } + + /* Check for one level up; that is enough */ + dn = of_get_parent(dn); + if (dn) { + of_range_parser_init(&parser, dn); + for_each_of_range(&parser, &range) { + /* Find the parent range that contains cpu_addr */ + if (range.cpu_addr > port->outbound_range_offset && + range.cpu_addr < cpu_addr) + port->outbound_range_offset = range.cpu_addr; + } + } + + return 0; +} + static int mc_platform_init(struct pci_config_window *cfg) { struct device *dev = cfg->parent; @@ -1117,9 +1171,18 @@ static int mc_platform_init(struct pci_config_window *cfg) port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; int ret; + /* + * Need information about any parent bus that may be performing some + * of the outbound address translation to setup outbound address + * translation tables later + */ + ret = mc_check_for_parent_range_handling(pdev, port); + if (ret) + return ret; + /* Configure address translation table 0 for PCIe config space */ - mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start, - cfg->res.start, + mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start - port->outbound_range_offset, + cfg->res.start - port->outbound_range_offset, resource_size(&cfg->res)); /* Need some fixups in config space */ From patchwork Wed Jan 11 12:53:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daire.McNamara@microchip.com X-Patchwork-Id: 641444 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2BEE9C71131 for ; Wed, 11 Jan 2023 12:54:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238687AbjAKMy2 (ORCPT ); Wed, 11 Jan 2023 07:54:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57470 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238774AbjAKMyC (ORCPT ); Wed, 11 Jan 2023 07:54:02 -0500 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.154.123]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 133CF15F35; Wed, 11 Jan 2023 04:54:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1673441641; x=1704977641; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=d3ILmxLhUQCg16hzLFqT6vDkBfV/GFcRb/040yX8hPI=; b=siESYRlYcIag5zKexm+C02QI6bjHbmJbbVGEUPBgidXQNcYeFrSDM22Z VrdV1B1t1fMkdoIIsfFhJufpzjELPhiCDeytiO/6B5lawLHW9W1FAwdxs rZy8WNID3RpqrV/t0kfDZUAG38yFfnwhhcW5kcz6Pc4DzeZ2ZxV30bQCO RV9sSMCuBAjV7H4+ryp8bJMmPDDuHkKn9uDeaxIzM6OSuQ74IkDFDXDwP pJivdIPUKL2dnf7tHCTQWjrGeIOtmboeKu6Ja647IDXiDdCaZ0EtHd1hU gzBXtAVIRfFZH9ocyuzOI6VAlUpQ5W8D2HAZmQsFXuMG+G9btzg/raS3P A==; X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="195261380" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa2.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 11 Jan 2023 05:54:00 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Wed, 11 Jan 2023 05:53:58 -0700 Received: from daire-X570.amer.actel.com (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Wed, 11 Jan 2023 05:53:56 -0700 From: To: , , , , , , , , , , , CC: Daire McNamara Subject: [PATCH v3 10/11] PCI: microchip: Partition inbound address translation Date: Wed, 11 Jan 2023 12:53:22 +0000 Message-ID: <20230111125323.1911373-11-daire.mcnamara@microchip.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230111125323.1911373-1-daire.mcnamara@microchip.com> References: <20230111125323.1911373-1-daire.mcnamara@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Daire McNamara On Microchip PolarFire SoC the PCIe Root Port is behind a set of Fabric Interface Controller (FIC) buses that encapsulate buses like ABP/AHP, AXI-S, and AXI-M. Depending on which FIC(s) the Root Port is wired through to cpu space, the Root Port driver needs to take account of the address translation done by a parent (e.g. fabric) node before setting up its own inbound address translation tables from attached devices. Parse the dma-range properties to determine how much address translation to perform in the Root Port and how much is being provided by the fabric. Signed-off-by: Daire McNamara Reviewed-by: Conor Dooley --- drivers/pci/controller/pcie-microchip-host.c | 178 ++++++++++++++++++- 1 file changed, 172 insertions(+), 6 deletions(-) diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/pcie-microchip-host.c index f3dfcdf39c8a..2eb70fd01879 100644 --- a/drivers/pci/controller/pcie-microchip-host.c +++ b/drivers/pci/controller/pcie-microchip-host.c @@ -22,6 +22,9 @@ /* Number of MSI IRQs */ #define MC_MAX_NUM_MSI_IRQS 32 +#define MC_MAX_NUM_INBOUND_WINDOWS 8 +#define MC_ATT_MASK GENMASK_ULL(63, 31) + /* PCIe Bridge Phy and Controller Phy offsets */ #define MC_PCIE1_BRIDGE_ADDR 0x00008000u #define MC_PCIE1_CTRL_ADDR 0x0000a000u @@ -86,10 +89,13 @@ #define ISTATUS_MSI 0x194 #define ATR_WINDOW_DESC_SIZE 32 -#define ATR_PCIE_ATR_SIZE 0x25 #define ATR_SIZE_SHIFT 1 #define ATR_IMPL_ENABLE 1 +#define ATR_PCIE_WIN0_SRCADDR 0x80000000 +#define ATR_PCIE_ATR_SIZE (512 * 1024 * 1024ul) +#define ATR_PCIE_NUM_WINDOWS 8 + /* PCIe Master table init defines */ #define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u #define ATR0_PCIE_WIN0_SRC_ADDR 0x604u @@ -278,6 +284,12 @@ struct mc_msi { DECLARE_BITMAP(used, MC_MAX_NUM_MSI_IRQS); }; +struct inbound_windows { + u64 axi_addr; + u64 pci_addr; + u64 size; +}; + struct mc_pcie { void __iomem *axi_base_addr; struct device *dev; @@ -286,6 +298,8 @@ struct mc_pcie { raw_spinlock_t lock; struct mc_msi msi; u64 outbound_range_offset; + u32 num_inbound_windows; + struct inbound_windows inbound_windows[MC_MAX_NUM_INBOUND_WINDOWS]; }; struct cause { @@ -948,6 +962,43 @@ static int mc_pcie_init_irq_domains(struct mc_pcie *port) return mc_allocate_msi_domains(port); } +static int mc_pcie_setup_inbound_ranges(struct platform_device *pdev, struct mc_pcie *port) +{ + void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; + phys_addr_t pcie_addr; + phys_addr_t axi_addr; + u32 atr_size; + u32 val; + int i; + + for (i = 0; i < port->num_inbound_windows; i++) { + atr_size = ilog2(port->inbound_windows[i].size) - 1; + atr_size &= GENMASK(5, 0); + + pcie_addr = port->inbound_windows[i].pci_addr; + + val = lower_32_bits(pcie_addr) & GENMASK(31, 12); + val |= (atr_size << ATR_SIZE_SHIFT); + val |= ATR_IMPL_ENABLE; + writel(val, bridge_base_addr + + ATR0_PCIE_WIN0_SRCADDR_PARAM + (i * ATR_WINDOW_DESC_SIZE)); + writel(upper_32_bits(pcie_addr), bridge_base_addr + + ATR0_PCIE_WIN0_SRC_ADDR + (i * ATR_WINDOW_DESC_SIZE)); + + axi_addr = port->inbound_windows[i].axi_addr; + + writel(lower_32_bits(axi_addr), bridge_base_addr + + ATR0_PCIE_WIN0_TRSL_ADDR_LSB + (i * ATR_WINDOW_DESC_SIZE)); + writel(upper_32_bits(axi_addr), bridge_base_addr + + ATR0_PCIE_WIN0_TRSL_ADDR_UDW + (i * ATR_WINDOW_DESC_SIZE)); + + writel(TRSL_ID_AXI4_MASTER_0, bridge_base_addr + + ATR0_PCIE_WIN0_TRSL_PARAM + (i * ATR_WINDOW_DESC_SIZE)); + } + + return 0; +} + static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index, phys_addr_t axi_addr, phys_addr_t pci_addr, size_t size) @@ -979,11 +1030,6 @@ static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index, val = upper_32_bits(pci_addr); writel(val, bridge_base_addr + (index * ATR_WINDOW_DESC_SIZE) + ATR0_AXI4_SLV0_TRSL_ADDR_UDW); - - val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); - val |= (ATR_PCIE_ATR_SIZE << ATR_SIZE_SHIFT); - writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); - writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR); } static int mc_pcie_setup_windows(struct platform_device *pdev, @@ -1163,6 +1209,116 @@ static int mc_check_for_parent_range_handling(struct platform_device *pdev, stru return 0; } +static int mc_check_for_parent_dma_range_handling(struct platform_device *pdev, + struct mc_pcie *port) +{ + struct device *dev = &pdev->dev; + struct device_node *dn = dev->of_node; + struct of_range_parser parser; + struct of_range range; + int num_parent_ranges = 0; + int num_ranges = 0; + struct inbound_windows ranges[MC_MAX_NUM_INBOUND_WINDOWS] = { 0 }; + u64 start_axi = GENMASK_ULL(63, 0); + u64 end_axi = 0; + u64 start_pci = GENMASK_ULL(63, 0); + s64 size; + u64 window_size; + int i; + + /* Find all dma-ranges */ + if (of_pci_dma_range_parser_init(&parser, dn)) { + dev_err(dev, "missing dma-ranges property\n"); + return -EINVAL; + } + + for_each_of_range(&parser, &range) { + if (num_ranges > MC_MAX_NUM_INBOUND_WINDOWS) { + dev_err(dev, "too many inbound ranges; %d available tables\n", + MC_MAX_NUM_INBOUND_WINDOWS); + return -EINVAL; + } + ranges[num_ranges].axi_addr = range.cpu_addr; + ranges[num_ranges].pci_addr = range.pci_addr; + ranges[num_ranges].size = range.size; + + num_ranges++; + } + + /* + * Check for one level up; will need to adjust address translation + * tables for these + */ + dn = of_get_parent(dn); + if (dn) { + of_pci_dma_range_parser_init(&parser, dn); + + for_each_of_range(&parser, &range) { + if (num_parent_ranges > MC_MAX_NUM_INBOUND_WINDOWS) { + dev_err(dev, "too many parent inbound ranges; %d available tables\n", + MC_MAX_NUM_INBOUND_WINDOWS); + return -EINVAL; + } + ranges[num_parent_ranges].axi_addr = range.pci_addr; + num_parent_ranges++; + } + } + + if (num_parent_ranges) { + if (num_ranges != num_parent_ranges) { + dev_err(dev, "num parent inbound ranges must be 0 or match num inbound ranges\n"); + return -EINVAL; + } + } + + /* Merge ranges */ + for (i = 0; i < num_ranges; i++) { + struct inbound_windows *range = &ranges[i]; + + if (range->axi_addr < start_axi) { + start_axi = range->axi_addr; + start_pci = range->pci_addr; + } + + if (range->axi_addr + range->size > end_axi) + end_axi = range->axi_addr + range->size; + } + + /* Move starts back as far as possible */ + start_axi &= MC_ATT_MASK; + start_pci &= MC_ATT_MASK; + + /* Adjust size to take account of that change */ + size = end_axi - start_axi; + + /* May need to adjust size up to the next largest power of 2 */ + if (size < 1ull << ilog2(size)) + size = 1ull << (ilog2(size) + 1); + + window_size = 1ull << (ilog2(size) - 1); + + /* Divide merged range into windows */ + i = 0; + while (size > 0 && i < MC_MAX_NUM_INBOUND_WINDOWS) { + port->inbound_windows[i].axi_addr = start_axi; + port->inbound_windows[i].pci_addr = start_pci; + port->inbound_windows[i].size = window_size; + + size -= window_size; + start_axi += window_size; + start_pci += window_size; + i++; + port->num_inbound_windows = i; + } + + if (size < 0) { + dev_err(dev, "insufficient windows to map inbound ranges\n"); + return -EINVAL; + } + + return 0; +} + static int mc_platform_init(struct pci_config_window *cfg) { struct device *dev = cfg->parent; @@ -1180,6 +1336,11 @@ static int mc_platform_init(struct pci_config_window *cfg) if (ret) return ret; + /* And similarly, check for inbound address translation */ + ret = mc_check_for_parent_dma_range_handling(pdev, port); + if (ret) + return ret; + /* Configure address translation table 0 for PCIe config space */ mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start - port->outbound_range_offset, cfg->res.start - port->outbound_range_offset, @@ -1193,6 +1354,11 @@ static int mc_platform_init(struct pci_config_window *cfg) if (ret) return ret; + /* Configure inbound translation tables */ + ret = mc_pcie_setup_inbound_ranges(pdev, port); + if (ret) + return ret; + /* Address translation is up; safe to enable interrupts */ ret = mc_init_interrupts(pdev, port); if (ret)