linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jingoo Han <jg1.han@samsung.com>
To: "'linux-pci'" <linux-pci@vger.kernel.org>,
	"'Bjorn Helgaas'" <bhelgaas@google.com>
Cc: linux-arm-kernel@lists.infradead.org,
	linaro-kernel@lists.linaro.org, linux-kernel@vger.kernel.org,
	"'Liviu Dudau'" <Liviu.Dudau@arm.com>,
	"'Arnd Bergmann'" <arnd@arndb.de>,
	"'Kukjin Kim'" <kgene.kim@samsung.com>,
	"'Jingoo Han'" <jg1.han@samsung.com>
Subject: [RFC PATCH 2/2] PCI: exynos: Add PCIe support for Samsung GH7 SoC
Date: Wed, 16 Apr 2014 13:43:26 +0900	[thread overview]
Message-ID: <000a01cf592e$67e592e0$37b0b8a0$%han@samsung.com> (raw)
In-Reply-To: <000801cf592e$30b7bff0$92273fd0$%han@samsung.com>

Samsung GH7 has four PCIe controllers which can be used as root
complex for PCIe interface.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 drivers/pci/host/Kconfig      |    2 +-
 drivers/pci/host/pci-exynos.c |  135 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 126 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index a6f67ec..3be047c 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -11,7 +11,7 @@ config PCIE_DW
 
 config PCI_EXYNOS
 	bool "Samsung Exynos PCIe controller"
-	depends on SOC_EXYNOS5440
+	depends on SOC_EXYNOS5440 || ARCH_GH7
 	select PCIEPORTBUS
 	select PCIE_DW
 
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index 3de6bfb..6e845ca 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -57,6 +57,8 @@ struct exynos_pcie {
 #define PCIE_NONSTICKY_RESET		0x024
 #define PCIE_APP_INIT_RESET		0x028
 #define PCIE_APP_LTSSM_ENABLE		0x02c
+#define PCIE_SYS_AUX_PWR_DET		0x038
+#define PCIE_SYS_AUX_PWR_ENABLE		(0x1 << 0)
 #define PCIE_ELBI_RDLH_LINKUP		0x064
 #define PCIE_ELBI_LTSSM_ENABLE		0x1
 #define PCIE_ELBI_SLV_AWMISC		0x11c
@@ -72,6 +74,23 @@ struct exynos_pcie {
 #define PCIE_PHY_TRSVREG_RESET		0x020
 #define PCIE_PHY_TRSV_RESET		0x024
 
+/* PCIe PHY glue registers */
+#define PCIE_PHY_GLUE_REG0		0x000
+#define PCIE_PHY_GLUE_GLOBAL_RESET	(0x1 << 0)
+#define PCIE_PHY_GLUE_COMMON_RESET	(0x1 << 1)
+#define PCIE_PHY_GLUE_MAC_RESET		(0x1 << 11)
+#define PCIE_PHY_GLUE_REG2		0x008
+#define PCIE_PHY_GLUE_CLK100M_DS_MAX	(0x7 << 0)
+#define PCIE_PHY_GLUE_CLK100M_RFCLK	(0x1 << 3)
+#define PCIE_PHY_GLUE_CLK100M_ENABLE	(0x1 << 4)
+#define PCIE_PHY_GLUE_PLL_BUF_ENABLE	(0x1 << 8)
+#define PCIE_PHY_GLUE_PLL_DIV_ENABLE	(0x1 << 9)
+#define PCIE_PHY_GLUE_REFCLK_IN(x)	(((x) & 0xf) << 10)
+#define PCIE_PHY_GLUE_REG3		0x00c
+#define PCIE_PHY_GLUE_REF_RATE_100MHZ	(0x2 << 0)
+#define PCIE_PHY_GLUE_REG4		0x010
+#define PCIE_PHY_GLUE_MODE_PCIE		(0x0 << 0)
+
 /* PCIe PHY registers */
 #define PCIE_PHY_IMPEDANCE		0x004
 #define PCIE_PHY_PLL_DIV_0		0x008
@@ -164,11 +183,45 @@ static void exynos_pcie_sideband_dbi_r_mode(struct pcie_port *pp, bool on)
 	}
 }
 
+static void exynos_pcie_set_phy_mode(struct pcie_port *pp)
+{
+	u32 val;
+	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+
+	if (!of_device_is_compatible(pp->dev->of_node, "samsung,gh7-pcie"))
+		return;
+
+	/* configure phy reference clock setting */
+	val = exynos_blk_readl(exynos_pcie, PCIE_PHY_GLUE_REG2);
+	val |= PCIE_PHY_GLUE_CLK100M_ENABLE | PCIE_PHY_GLUE_CLK100M_RFCLK |
+		PCIE_PHY_GLUE_CLK100M_DS_MAX;
+	exynos_blk_writel(exynos_pcie, val, PCIE_PHY_GLUE_REG2);
+
+	val = exynos_blk_readl(exynos_pcie, PCIE_PHY_GLUE_REG2);
+	val |= PCIE_PHY_GLUE_PLL_DIV_ENABLE | PCIE_PHY_GLUE_PLL_BUF_ENABLE;
+	exynos_blk_writel(exynos_pcie, val, PCIE_PHY_GLUE_REG2);
+
+	val = exynos_blk_readl(exynos_pcie, PCIE_PHY_GLUE_REG2);
+	val |= PCIE_PHY_GLUE_REFCLK_IN(6);
+	exynos_blk_writel(exynos_pcie, val, PCIE_PHY_GLUE_REG2);
+
+	/* set phy reference clock  */
+	exynos_blk_writel(exynos_pcie, PCIE_PHY_GLUE_REF_RATE_100MHZ,
+			  PCIE_PHY_GLUE_REG3);
+
+	/* set phy mode to pcie mode */
+	exynos_blk_writel(exynos_pcie, PCIE_PHY_GLUE_MODE_PCIE,
+			  PCIE_PHY_GLUE_REG4);
+}
+
 static void exynos_pcie_assert_core_reset(struct pcie_port *pp)
 {
 	u32 val;
 	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
 
+	if (of_device_is_compatible(pp->dev->of_node, "samsung,gh7-pcie"))
+		return;
+
 	val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET);
 	val &= ~PCIE_CORE_RESET_ENABLE;
 	exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET);
@@ -190,27 +243,48 @@ static void exynos_pcie_deassert_core_reset(struct pcie_port *pp)
 	exynos_elb_writel(exynos_pcie, 1, PCIE_NONSTICKY_RESET);
 	exynos_elb_writel(exynos_pcie, 1, PCIE_APP_INIT_RESET);
 	exynos_elb_writel(exynos_pcie, 0, PCIE_APP_INIT_RESET);
-	exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_MAC_RESET);
+
+	if (of_device_is_compatible(pp->dev->of_node, "samsung,gh7-pcie")) {
+		val = exynos_blk_readl(exynos_pcie, PCIE_PHY_GLUE_REG0);
+		val |= PCIE_PHY_GLUE_MAC_RESET;
+		exynos_blk_writel(exynos_pcie, val, PCIE_PHY_GLUE_REG0);
+	} else {
+		exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_MAC_RESET);
+	}
 }
 
 static void exynos_pcie_assert_phy_reset(struct pcie_port *pp)
 {
 	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
 
+	if (of_device_is_compatible(pp->dev->of_node, "samsung,gh7-pcie"))
+		return;
+
 	exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_MAC_RESET);
 	exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_GLOBAL_RESET);
 }
 
 static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp)
 {
+	u32 val;
 	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
 
-	exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_GLOBAL_RESET);
-	exynos_elb_writel(exynos_pcie, 1, PCIE_PWR_RESET);
-	exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
-	exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_CMN_REG);
-	exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSVREG_RESET);
-	exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET);
+	if (of_device_is_compatible(pp->dev->of_node, "samsung,gh7-pcie")) {
+		val = exynos_blk_readl(exynos_pcie, PCIE_PHY_GLUE_REG0);
+		val |= PCIE_PHY_GLUE_GLOBAL_RESET;
+		exynos_blk_writel(exynos_pcie, val, PCIE_PHY_GLUE_REG0);
+		exynos_elb_writel(exynos_pcie, 1, PCIE_PWR_RESET);
+		val = exynos_blk_readl(exynos_pcie, PCIE_PHY_GLUE_REG0);
+		val |= PCIE_PHY_GLUE_COMMON_RESET;
+		exynos_blk_writel(exynos_pcie, val, PCIE_PHY_GLUE_REG0);
+	} else {
+		exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_GLOBAL_RESET);
+		exynos_elb_writel(exynos_pcie, 1, PCIE_PWR_RESET);
+		exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
+		exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_CMN_REG);
+		exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSVREG_RESET);
+		exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET);
+	}
 }
 
 static void exynos_pcie_power_on_phy(struct pcie_port *pp)
@@ -269,6 +343,9 @@ static void exynos_pcie_init_phy(struct pcie_port *pp)
 {
 	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
 
+	if (of_device_is_compatible(pp->dev->of_node, "samsung,gh7-pcie"))
+		return;
+
 	/* DCC feedback control off */
 	exynos_phy_writel(exynos_pcie, 0x29, PCIE_PHY_DCC_FEEDBACK);
 
@@ -305,6 +382,26 @@ static void exynos_pcie_init_phy(struct pcie_port *pp)
 	exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV3_LVCC);
 }
 
+static void exynos_pcie_pulse_common_reset(struct pcie_port *pp)
+{
+	u32 val;
+	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+
+	if (of_device_is_compatible(pp->dev->of_node, "samsung,gh7-pcie")) {
+		val = exynos_blk_readl(exynos_pcie, PCIE_PHY_GLUE_REG0);
+		val &= ~PCIE_PHY_GLUE_COMMON_RESET;
+		exynos_blk_writel(exynos_pcie, val, PCIE_PHY_GLUE_REG0);
+		udelay(500);
+		val = exynos_blk_readl(exynos_pcie, PCIE_PHY_GLUE_REG0);
+		val |= PCIE_PHY_GLUE_COMMON_RESET;
+		exynos_blk_writel(exynos_pcie, val, PCIE_PHY_GLUE_REG0);
+	} else {
+		exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_COMMON_RESET);
+		udelay(500);
+		exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
+	}
+}
+
 static void exynos_pcie_assert_reset(struct pcie_port *pp)
 {
 	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
@@ -326,6 +423,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
 		return 0;
 	}
 
+	/* set phy mode */
+	exynos_pcie_set_phy_mode(pp);
+
 	/* assert reset signals */
 	exynos_pcie_assert_core_reset(pp);
 	exynos_pcie_assert_phy_reset(pp);
@@ -340,9 +440,7 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
 	exynos_pcie_init_phy(pp);
 
 	/* pulse for common reset */
-	exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_COMMON_RESET);
-	udelay(500);
-	exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
+	exynos_pcie_pulse_common_reset(pp);
 
 	/* de-assert core reset */
 	exynos_pcie_deassert_core_reset(pp);
@@ -357,6 +455,12 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
 	exynos_elb_writel(exynos_pcie, PCIE_ELBI_LTSSM_ENABLE,
 			  PCIE_APP_LTSSM_ENABLE);
 
+	if (of_device_is_compatible(pp->dev->of_node, "samsung,gh7-pcie")) {
+		/* supply auxiliary power */
+		exynos_elb_writel(exynos_pcie, PCIE_SYS_AUX_PWR_ENABLE,
+				  PCIE_SYS_AUX_PWR_DET);
+	}
+
 	/* check if the link is up or not */
 	while (!dw_pcie_link_up(pp)) {
 		mdelay(100);
@@ -564,6 +668,7 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
 	struct resource *elbi_base;
 	struct resource *phy_base;
 	struct resource *block_base;
+	 struct resource *dbi_base;
 	int ret;
 
 	exynos_pcie = devm_kzalloc(&pdev->dev, sizeof(*exynos_pcie),
@@ -619,6 +724,15 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
 		goto fail_bus_clk;
 	}
 
+	if (of_device_is_compatible(pdev->dev.of_node, "samsung,gh7-pcie")) {
+		dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+		pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
+		if (IS_ERR(pp->dbi_base)) {
+			ret = PTR_ERR(pp->dbi_base);
+			goto fail_bus_clk;
+		}
+	}
+
 	ret = add_pcie_port(pp, pdev);
 	if (ret < 0)
 		goto fail_bus_clk;
@@ -645,6 +759,7 @@ static int __exit exynos_pcie_remove(struct platform_device *pdev)
 
 static const struct of_device_id exynos_pcie_of_match[] = {
 	{ .compatible = "samsung,exynos5440-pcie", },
+	{ .compatible = "samsung,gh7-pcie", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, exynos_pcie_of_match);
-- 
1.7.10.4



  parent reply	other threads:[~2014-04-16  4:43 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-16  4:41 [RFC PATCH 0/2] Add support for Samsung GH7 PCIe controller Jingoo Han
2014-04-16  4:42 ` [RFC PATCH 1/2] PCI: designware: Add ARM64 PCI support Jingoo Han
2014-04-16 16:57   ` Liviu Dudau
2014-04-16 18:26     ` Arnd Bergmann
2014-04-21  1:54       ` Jingoo Han
2014-04-21  9:58         ` Jingoo Han
2014-04-22 13:01           ` Liviu Dudau
2014-04-22 15:39           ` Rob Herring
2014-04-22 12:59         ` Liviu Dudau
2014-04-22 12:54       ` Liviu Dudau
2014-04-16  4:43 ` Jingoo Han [this message]
2014-04-22 14:11   ` [RFC PATCH 2/2] PCI: exynos: Add PCIe support for Samsung GH7 SoC Arnd Bergmann
2014-04-23  9:19     ` Kukjin Kim
2014-04-23 11:03       ` Arnd Bergmann
2014-04-23 14:23         ` Liviu Dudau
2014-04-23 16:20           ` Arnd Bergmann
2014-04-24  4:53             ` Kukjin Kim
2014-04-24  9:49               ` Arnd Bergmann
2014-04-23 13:00       ` Liviu Dudau
2014-04-24 12:25         ` Arnd Bergmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='000a01cf592e$67e592e0$37b0b8a0$%han@samsung.com' \
    --to=jg1.han@samsung.com \
    --cc=Liviu.Dudau@arm.com \
    --cc=arnd@arndb.de \
    --cc=bhelgaas@google.com \
    --cc=kgene.kim@samsung.com \
    --cc=linaro-kernel@lists.linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).