From patchwork Thu Dec 31 10:18:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongtao Wu X-Patchwork-Id: 1421520 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=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=fspu6YW/; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4D63zx4D0Kz9sRN for ; Thu, 31 Dec 2020 21:19:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726480AbgLaKTV (ORCPT ); Thu, 31 Dec 2020 05:19:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726155AbgLaKTV (ORCPT ); Thu, 31 Dec 2020 05:19:21 -0500 Received: from mail-pg1-x52a.google.com (mail-pg1-x52a.google.com [IPv6:2607:f8b0:4864:20::52a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C7C2EC061575; Thu, 31 Dec 2020 02:18:40 -0800 (PST) Received: by mail-pg1-x52a.google.com with SMTP id i5so12905504pgo.1; Thu, 31 Dec 2020 02:18:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wt9aTWsCxTK7BCW3efLWqM4G7L9tFvgWhfSlVEaResA=; b=fspu6YW/lHUq6ophkaJE7TRHExxHRWfEDUYUMRj5a4s2+pQQRpa9nEjW9mlx2TlayK zXpX4/J7dhktZJotqLAYGLd2y240jq2Y7z0e+5o1VPCXxFZIbRxt+9kevPafIzi9AuY7 D+fSr1LoMLn8oLp96udArYLDe+DEvTRz8KSYTPbmJ0D08RatDNtc0gUhKEttodQYGA9V Z22sdm8c68Tk6OQjhNKxSv887MnH8Ua2Vg0OtOUgtGrGN0ANHNhenYjXliFqOs+vnXb/ UzNDDrnb8/WsdJjBnKsLVdZykPhBxTFi5IiknrnqlZtjIt99x0bwgRAaY7FZfkbpUphD Lfrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wt9aTWsCxTK7BCW3efLWqM4G7L9tFvgWhfSlVEaResA=; b=lSKDLYFF4nKF4A640D1HJZftJhM6+AE6mN4u+mPqO8BE9Knoyn+juv9tIzmSdP4Gr1 4lXw+Gf3ELZhSiamJZUnGCTHMS9y4aRp5pdS92wReouNWFvlwQq2d+cSz+RLnOv1m4DC W6BVlffRVJH1ZQIrJavgom9/Rl6/4NV8M87Fgui+046E1ZJrCH0OpDuhgGX4ou+VzLZD Tjp8JX4u5L3HzNgH9Ti8DGGC2b+PFFwJKK618OYFdRp5dhWjuOnZgSguOcfJMQJ1CxXe QVvpKSzDgL/tNZBpreftg/ZpzN6UzrHEsfPxvyeOg0PVulg0Ohp3YTFhRv6EQNkcppFo 1Aaw== X-Gm-Message-State: AOAM532oqNNEUQiuWPbeepK1ZZ9ytyBM3jPdwKE+rNldQqoOYzsLxmTL bdDlyXKt5wAel11xkxk4r78= X-Google-Smtp-Source: ABdhPJw5KXc3ZEYv5eTvl93pa6DdukkfZWQ7S9owJ3qhd5bekszmoRBHslBh11Nohgeq2eheG7iQPw== X-Received: by 2002:a63:4d59:: with SMTP id n25mr37051821pgl.122.1609409920399; Thu, 31 Dec 2020 02:18:40 -0800 (PST) Received: from sh05419pcu.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id a141sm45470937pfa.189.2020.12.31.02.18.36 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 31 Dec 2020 02:18:39 -0800 (PST) From: Hongtao Wu To: Lorenzo Pieralisi , Rob Herring Cc: Orson Zhai , Baolin Wang , Chunyan Zhang , linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Hongtao Wu Subject: [PATCH v5 1/2] dt-bindings: PCI: sprd: Document Unisoc PCIe RC host controller Date: Thu, 31 Dec 2020 18:18:24 +0800 Message-Id: <1609409905-30721-2-git-send-email-wuht06@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1609409905-30721-1-git-send-email-wuht06@gmail.com> References: <1609409905-30721-1-git-send-email-wuht06@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Hongtao Wu This series adds PCIe bindings for Unisoc SoCs. This controller is based on DesignWare PCIe IP. Signed-off-by: Hongtao Wu Reviewed-by: Rob Herring --- .../devicetree/bindings/pci/sprd-pcie.yaml | 93 ++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/sprd-pcie.yaml -- 2.7.4 diff --git a/Documentation/devicetree/bindings/pci/sprd-pcie.yaml b/Documentation/devicetree/bindings/pci/sprd-pcie.yaml new file mode 100644 index 0000000..ede06a8 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/sprd-pcie.yaml @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/sprd-pcie.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SoC PCIe Host Controller Device Tree Bindings + +maintainers: + - Hongtao Wu + +allOf: + - $ref: /schemas/pci/pci-bus.yaml# + +properties: + compatible: + items: + - const: sprd,ums9520-pcie + + reg: + minItems: 2 + items: + - description: Controller control and status registers. + - description: PCIe configuration registers. + + reg-names: + items: + - const: dbi + - const: config + + ranges: + maxItems: 2 + + num-lanes: + maximum: 1 + description: Number of lanes to use for this port. + + interrupts: + minItems: 1 + description: Builtin MSI controller and PCIe host controller. + + interrupt-names: + items: + - const: msi + + sprd,regmap-aon: + $ref: '/schemas/types.yaml#/definitions/phandle' + description: + Phandle to the AON system controller node (to access the + AON_ACCESS_PCIE_EN register on ums9520). + sprd,regmap-pmu: + $ref: '/schemas/types.yaml#/definitions/phandle' + description: + Phandle to the PMU system controller node (to access the PERST_N_ASSERT + register on ums9520). + +required: + - compatible + - reg + - reg-names + - num-lanes + - ranges + - interrupts + - interrupt-names + +additionalProperties: true + +examples: + - | + #include + + ipa { + #address-cells = <2>; + #size-cells = <2>; + + pcie0: pcie@2b100000 { + compatible = "sprd,ums9520-pcie"; + reg = <0x0 0x2b100000 0x0 0x2000>, + <0x2 0x00000000 0x0 0x2000>; + reg-names = "dbi", "config"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges = <0x01000000 0x0 0x00000000 0x2 0x00002000 0x0 0x00010000>, + <0x03000000 0x0 0x10000000 0x2 0x10000000 0x1 0xefffffff>; + num-lanes = <1>; + interrupts = ; + interrupt-names = "msi"; + + sprd,regmap-aon = <&aon_regs>; + sprd,regmap-pmu = <&pmu_regs>; + }; + }; From patchwork Thu Dec 31 10:18:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongtao Wu X-Patchwork-Id: 1421521 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=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=GnESWj2j; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4D63zy01Llz9sRf for ; Thu, 31 Dec 2020 21:19:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726524AbgLaKT0 (ORCPT ); Thu, 31 Dec 2020 05:19:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37840 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726155AbgLaKTZ (ORCPT ); Thu, 31 Dec 2020 05:19:25 -0500 Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 14F66C061799; Thu, 31 Dec 2020 02:18:45 -0800 (PST) Received: by mail-pf1-x42c.google.com with SMTP id t8so11060488pfg.8; Thu, 31 Dec 2020 02:18:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Xw698ctg4Ze5W/87ncdseRGuPD3JOZ7supZFvs8H2cs=; b=GnESWj2jam8dYagjQrsGx+sfk6YpRaQ5Pk2awXCQY4gXnSdrRzX2hfcmEU+3yuQyGw pjPX1tjVCnxUXNO2gnoht0RiOA4diL3wSiVmpJS/GTNsxzFk9/KtY7yvRHSI0Q7Yk/po NU7DREleeXy1QDrkjGGnvnrTm4YQkUypwtv2gQhDdcnXg73M76IdkLiHboIs6g8anANo QfFvPSVPf2ZyOb0+W4qZoY4QjcwGFhBdTNfIJm4gseruH2/u5+CopfX6TzG3nQzdXyGb IrlrwagjUXhuTSiCqu0TIysi4DV5Z0qL0Rn402iNZ6DS8QoQdUNnJXwsKkrQsp/i0gNc U6uA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Xw698ctg4Ze5W/87ncdseRGuPD3JOZ7supZFvs8H2cs=; b=MD0x8YQi9lr1X3e3HntCqg+9UXlTHLyLjZ+b9ilmsO4sHjiJFrGM4HeenI++i6W++/ tAu1aGUfkljYsK6vKPP0Ta1dC4gKo+JQwa5SnLuW+pX2mwmt0yKM+erKY+jVeQToowhy AMZd27jgLXlzHlTqSUX9zOtZdAH8WQEulzavaa+n9FHatsm0h0UW5L6q1RxbzIrrN+oZ QO4FZyTtDmTdLFElrd3HDM/dRFdmRWf/SKfEGtJhozq3wBVWyIOFLvppwqOw3zUABe9J sQEOHJ8P5ukEoTj8Qv6LJwYQPzyOK5bmlTZVtQFEbmkTQCKff8rH3iLFb4t7KuWHpR23 K/dg== X-Gm-Message-State: AOAM5334sRrRgp9cNdVDSo6AqhYqkmXg3GQ7SitZNlsEx/WUIbhBcBku 88pasl6Ow95MKnbdgANTFZk= X-Google-Smtp-Source: ABdhPJzhh9x8UuD7p0Hxj4Gg5iJpIjYvufvPp88dNcIwAvyOsbGJ8XFoajJIsiN0+xq4h3CDlI8JMA== X-Received: by 2002:a62:7d90:0:b029:19d:917b:6c65 with SMTP id y138-20020a627d900000b029019d917b6c65mr31766577pfc.28.1609409924556; Thu, 31 Dec 2020 02:18:44 -0800 (PST) Received: from sh05419pcu.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id a141sm45470937pfa.189.2020.12.31.02.18.40 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 31 Dec 2020 02:18:43 -0800 (PST) From: Hongtao Wu To: Lorenzo Pieralisi , Rob Herring Cc: Orson Zhai , Baolin Wang , Chunyan Zhang , linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Hongtao Wu Subject: [PATCH v5 2/2] PCI: sprd: Add support for Unisoc SoCs' PCIe controller Date: Thu, 31 Dec 2020 18:18:25 +0800 Message-Id: <1609409905-30721-3-git-send-email-wuht06@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1609409905-30721-1-git-send-email-wuht06@gmail.com> References: <1609409905-30721-1-git-send-email-wuht06@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Hongtao Wu This series adds PCIe controller driver for Unisoc SoCs. This controller is based on DesignWare PCIe IP. Signed-off-by: Hongtao Wu --- drivers/pci/controller/dwc/Kconfig | 12 ++ drivers/pci/controller/dwc/Makefile | 1 + drivers/pci/controller/dwc/pcie-sprd.c | 293 +++++++++++++++++++++++++++++++++ 3 files changed, 306 insertions(+) create mode 100644 drivers/pci/controller/dwc/pcie-sprd.c -- 2.7.4 diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index 22c5529..61f0b79 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -318,4 +318,16 @@ config PCIE_AL required only for DT-based platforms. ACPI platforms with the Annapurna Labs PCIe controller don't need to enable this. +config PCIE_SPRD + tristate "Unisoc PCIe controller - Host Mode" + depends on ARCH_SPRD || COMPILE_TEST + depends on PCI_MSI_IRQ_DOMAIN + select PCIE_DW_HOST + help + Unisoc PCIe controller uses the DesignWare core. It can be configured + as an Endpoint (EP) or a Root complex (RC). In order to enable host + mode (the controller works as RC), PCIE_SPRD must be selected. + Say Y or M here if you want to PCIe RC controller support on Unisoc + SoCs. + endmenu diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile index a751553..eb546e9 100644 --- a/drivers/pci/controller/dwc/Makefile +++ b/drivers/pci/controller/dwc/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_PCI_MESON) += pci-meson.o obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o +obj-$(CONFIG_PCIE_SPRD) += pcie-sprd.o # The following drivers are for devices that use the generic ACPI # pci_root.c driver but don't support standard ECAM config access. diff --git a/drivers/pci/controller/dwc/pcie-sprd.c b/drivers/pci/controller/dwc/pcie-sprd.c new file mode 100644 index 0000000..27d7231 --- /dev/null +++ b/drivers/pci/controller/dwc/pcie-sprd.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCIe host controller driver for Unisoc SoCs + * + * Copyright (C) 2020-2021 Unisoc, Inc. + * + * Author: Hongtao Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcie-designware.h" + +/* aon apb syscon */ +#define IPA_ACCESS_CFG 0xcd8 +#define AON_ACCESS_PCIE_EN BIT(1) + +/* pmu apb syscon */ +#define SNPS_PCIE3_SLP_CTRL 0xac +#define PERST_N_ASSERT BIT(1) +#define PERST_N_AUTO_EN BIT(0) +#define PD_PCIE_CFG_0 0x3e8 +#define PCIE_FORCE_SHUTDOWN BIT(25) + +#define PCIE_SS_REG_BASE 0xE00 +#define APB_CLKFREQ_TIMEOUT 0x4 +#define BUSERR_EN BIT(12) +#define APB_TIMER_DIS BIT(10) +#define APB_TIMER_LIMIT GENMASK(31, 16) + +#define PE0_GEN_CTRL_3 0x58 +#define LTSSM_EN BIT(0) + +struct sprd_pcie_soc_data { + u32 syscon_offset; +}; + +static const struct sprd_pcie_soc_data ums9520_syscon_data = { + .syscon_offset = 0x1000, /* The offset of set/clear register */ +}; + +struct sprd_pcie { + u32 syscon_offset; + struct device *dev; + struct dw_pcie *pci; + struct regmap *aon_map; + struct regmap *pmu_map; + const struct sprd_pcie_soc_data *socdata; +}; + +enum sprd_pcie_syscon_type { + normal_syscon, /* it's not a set/clear register */ + set_syscon, /* set a set/clear register */ + clr_syscon, /* clear a set/clear register */ +}; + +static void sprd_pcie_buserr_enable(struct dw_pcie *pci) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_SS_REG_BASE + APB_CLKFREQ_TIMEOUT); + val &= ~APB_TIMER_DIS; + val |= BUSERR_EN; + val |= APB_TIMER_LIMIT & (0x1f4 << 16); + dw_pcie_writel_dbi(pci, PCIE_SS_REG_BASE + APB_CLKFREQ_TIMEOUT, val); +} + +static void sprd_pcie_ltssm_enable(struct dw_pcie *pci, bool enable) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_SS_REG_BASE + PE0_GEN_CTRL_3); + if (enable) + dw_pcie_writel_dbi(pci, PCIE_SS_REG_BASE + PE0_GEN_CTRL_3, + val | LTSSM_EN); + else + dw_pcie_writel_dbi(pci, PCIE_SS_REG_BASE + PE0_GEN_CTRL_3, + val & ~LTSSM_EN); +} + +static int sprd_pcie_syscon_set(struct sprd_pcie *ctrl, struct regmap *map, + u32 reg, u32 mask, u32 val, + enum sprd_pcie_syscon_type type) +{ + int ret = 0; + u32 read_val; + u32 offset = ctrl->syscon_offset; + struct device *dev = ctrl->pci->dev; + + /* + * Each set/clear register has three registers: + * reg: base register + * reg + offset: set register + * reg + offset * 2: clear register + */ + switch (type) { + case normal_syscon: + ret = regmap_read(map, reg, &read_val); + if (ret) { + dev_err(dev, "failed to read register 0x%x\n", reg); + return ret; + } + read_val &= ~mask; + read_val |= (val & mask); + ret = regmap_write(map, reg, read_val); + break; + case set_syscon: + reg = reg + offset; + ret = regmap_write(map, reg, val); + break; + case clr_syscon: + reg = reg + offset * 2; + ret = regmap_write(map, reg, val); + break; + default: + break; + } + + if (ret) + dev_err(dev, "failed to write register 0x%x\n", reg); + + return ret; +} + +static int sprd_pcie_perst_assert(struct sprd_pcie *ctrl) +{ + return sprd_pcie_syscon_set(ctrl, ctrl->pmu_map, SNPS_PCIE3_SLP_CTRL, + PERST_N_ASSERT, PERST_N_ASSERT, set_syscon); +} + +static int sprd_pcie_perst_deassert(struct sprd_pcie *ctrl) +{ + int ret; + + ret = sprd_pcie_syscon_set(ctrl, ctrl->pmu_map, SNPS_PCIE3_SLP_CTRL, + PERST_N_ASSERT, 0, clr_syscon); + usleep_range(2000, 3000); + + return ret; +} + +static int sprd_pcie_power_on(struct platform_device *pdev) +{ + int ret; + struct sprd_pcie *ctrl = platform_get_drvdata(pdev); + struct dw_pcie *pci = ctrl->pci; + + ret = sprd_pcie_syscon_set(ctrl, ctrl->aon_map, PD_PCIE_CFG_0, + PCIE_FORCE_SHUTDOWN, 0, clr_syscon); + if (ret) + return ret; + + ret = sprd_pcie_syscon_set(ctrl, ctrl->aon_map, IPA_ACCESS_CFG, + AON_ACCESS_PCIE_EN, AON_ACCESS_PCIE_EN, + set_syscon); + if (ret) + return ret; + + ret = sprd_pcie_perst_deassert(ctrl); + if (ret) + return ret; + + sprd_pcie_buserr_enable(pci); + sprd_pcie_ltssm_enable(pci, true); + + return ret; +} + +static int sprd_pcie_power_off(struct platform_device *pdev) +{ + struct sprd_pcie *ctrl = platform_get_drvdata(pdev); + struct dw_pcie *pci = ctrl->pci; + + sprd_pcie_ltssm_enable(pci, false); + + sprd_pcie_perst_assert(ctrl); + sprd_pcie_syscon_set(ctrl, ctrl->aon_map, PD_PCIE_CFG_0, + PCIE_FORCE_SHUTDOWN, PCIE_FORCE_SHUTDOWN, + set_syscon); + sprd_pcie_syscon_set(ctrl, ctrl->aon_map, IPA_ACCESS_CFG, + AON_ACCESS_PCIE_EN, 0, clr_syscon); + + return 0; +} + +static int sprd_add_pcie_port(struct platform_device *pdev) +{ + struct sprd_pcie *ctrl = platform_get_drvdata(pdev); + struct dw_pcie *pci = ctrl->pci; + struct pcie_port *pp = &pci->pp; + + return dw_pcie_host_init(pp); +} + +static int sprd_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sprd_pcie *ctrl; + struct dw_pcie *pci; + int ret; + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + ctrl->socdata = + (struct sprd_pcie_soc_data *)of_device_get_match_data(dev); + if (!ctrl->socdata) { + dev_warn(dev, + "using the default set/clear register offset address"); + ctrl->syscon_offset = 0x1000; + } + ctrl->syscon_offset = ctrl->socdata->syscon_offset; + + ctrl->aon_map = syscon_regmap_lookup_by_phandle(dev->of_node, + "sprd, regmap-aon"); + if (IS_ERR(ctrl->aon_map)) { + dev_err(dev, "failed to get syscon regmap aon\n"); + ret = PTR_ERR(ctrl->aon_map); + goto err; + } + + ctrl->pmu_map = syscon_regmap_lookup_by_phandle(dev->of_node, + "sprd, regmap-pmu"); + if (IS_ERR(ctrl->pmu_map)) { + dev_err(dev, "failed to get syscon regmap pmu\n"); + ret = PTR_ERR(ctrl->pmu_map); + goto err; + } + + pci = ctrl->pci; + pci->dev = dev; + + platform_set_drvdata(pdev, ctrl); + + ret = sprd_pcie_power_on(pdev); + if (ret < 0) { + dev_err(dev, "failed to power on, return %d\n", + ret); + goto err_power_off; + } + + ret = sprd_add_pcie_port(pdev); + if (ret) { + dev_warn(dev, "failed to initialize RC controller\n"); + return ret; + } + + return 0; + +err_power_off: + sprd_pcie_power_off(pdev); +err: + return ret; +} + +static int sprd_pcie_remove(struct platform_device *pdev) +{ + sprd_pcie_power_off(pdev); + + return 0; +} + +static const struct of_device_id sprd_pcie_of_match[] = { + { + .compatible = "sprd,ums9520-pcie", + .data = &ums9520_syscon_data, + }, + {}, +}; + +static struct platform_driver sprd_pcie_driver = { + .probe = sprd_pcie_probe, + .remove = __exit_p(sprd_pcie_remove), + .driver = { + .name = "sprd-pcie", + .of_match_table = sprd_pcie_of_match, + }, +}; + +module_platform_driver(sprd_pcie_driver); + +MODULE_DESCRIPTION("Unisoc PCIe host controller driver"); +MODULE_LICENSE("GPL v2");