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
next prev 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).