pcie: fix pcie power on timing.

PD#147564: pcie: fix pxie power on timing.

Change-Id: I28d39f0ed030f8886adecc9b575540c0ffc13716
Signed-off-by: Yue Wang <yue.wang@amlogic.com>
This commit is contained in:
Yue Wang
2017-07-17 11:46:55 +08:00
committed by Jianxin Pan
parent 043ff0471e
commit baf42f6dbb
10 changed files with 219 additions and 94 deletions

View File

@@ -13921,6 +13921,7 @@ F: drivers/amlogic/pci/pcie-amlogic.c
F: drivers/amlogic/pci/pcie-amlogic.h
F: drivers/amlogic/pci/Kconfig
F: drivers/amlogic/pci/Makefile
F: include/dt-bindings/phy/phy-amlogic-pcie.h
AMLOGIC AXG ADD EMMC AND SDIO SUPPORT FOR NEW HOST CONTROLLER
M: Long Yu <long.yu@amlogic.com>

View File

@@ -295,11 +295,11 @@
pcie_A: pcieA@f9800000 {
compatible = "amlogic, amlogic-pcie", "snps,dw-pcie";
reg = <0x0 0xf9800000 0x0 0x400000
0x0 0xff644000 0x0 0x2000
0x0 0xff646000 0x0 0x2000
0x0 0xffd01080 0x0 0x10
0x0 0xf9f00000 0x0 0x100000>;
reg-names = "elbi", "phy", "cfg", "reset", "config";
0x0 0xf9f00000 0x0 0x100000
0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE
0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>;
reg-names = "elbi", "cfg", "config", "phy", "reset";
reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
interrupts = <0 177 0>, <0 179 0>;
#interrupt-cells = <1>;
@@ -313,9 +313,11 @@
pcie-num = <1>;
clocks = <&clkc CLKID_PCIE_PLL
&clkc CLKID_PCIE_A>;
&clkc CLKID_PCIE_A
&clkc CLKID_PCIE_CML_EN0>;
clock-names = "pcie_refpll",
"pcie_a";
"pcie",
"port";
/*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/
gpio-type = <2>;
status = "okay";
@@ -324,11 +326,11 @@
pcie_B: pcieB@fa000000 {
compatible = "amlogic, amlogic-pcie", "snps,dw-pcie";
reg = <0x0 0xfa000000 0x0 0x400000
0x0 0xff644000 0x0 0x2000
0x0 0xff648000 0x0 0x2000
0x0 0xffd01080 0x0 0x10
0x0 0xfa400000 0x0 0x100000>;
reg-names = "elbi", "phy", "cfg", "reset", "config";
0x0 0xfa400000 0x0 0x100000
0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE
0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>;
reg-names = "elbi", "cfg", "config", "phy", "reset";
reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
interrupts = <0 167 0>, <0 169 0>;
#interrupt-cells = <1>;
@@ -344,9 +346,11 @@
pcie-num = <2>;
clocks = <&clkc CLKID_PCIE_PLL
&clkc CLKID_PCIE_B>;
&clkc CLKID_PCIE_B
&clkc CLKID_PCIE_CML_EN1>;
clock-names = "pcie_refpll",
"pcie_b";
"pcie",
"port";
/*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/
gpio-type = <0>;
status = "okay";

View File

@@ -303,11 +303,11 @@
pcie_A: pcieA@f9800000 {
compatible = "amlogic, amlogic-pcie", "snps,dw-pcie";
reg = <0x0 0xf9800000 0x0 0x400000
0x0 0xff644000 0x0 0x2000
0x0 0xff646000 0x0 0x2000
0x0 0xffd01080 0x0 0x10
0x0 0xf9f00000 0x0 0x100000>;
reg-names = "elbi", "phy", "cfg", "reset", "config";
0x0 0xf9f00000 0x0 0x100000
0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE
0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>;
reg-names = "elbi", "cfg", "config", "phy", "reset";
reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
interrupts = <0 177 0>, <0 179 0>;
#interrupt-cells = <1>;
@@ -321,22 +321,24 @@
pcie-num = <1>;
clocks = <&clkc CLKID_PCIE_PLL
&clkc CLKID_PCIE_A>;
&clkc CLKID_PCIE_A
&clkc CLKID_PCIE_CML_EN0>;
clock-names = "pcie_refpll",
"pcie_a";
"pcie",
"port";
/*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/
gpio-type = <2>;
status = "okay";
};
pcie_B: pcieB@fa000000 {
pcie_B: pcieB@fa000000 {
compatible = "amlogic, amlogic-pcie", "snps,dw-pcie";
reg = <0x0 0xfa000000 0x0 0x400000
0x0 0xff644000 0x0 0x2000
0x0 0xff648000 0x0 0x2000
0x0 0xffd01080 0x0 0x10
0x0 0xfa400000 0x0 0x100000>;
reg-names = "elbi", "phy", "cfg", "reset", "config";
0x0 0xfa400000 0x0 0x100000
0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE
0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>;
reg-names = "elbi", "cfg", "config", "phy", "reset";
reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>;
interrupts = <0 167 0>, <0 169 0>;
#interrupt-cells = <1>;
@@ -352,14 +354,17 @@
pcie-num = <2>;
clocks = <&clkc CLKID_PCIE_PLL
&clkc CLKID_PCIE_B>;
&clkc CLKID_PCIE_B
&clkc CLKID_PCIE_CML_EN1>;
clock-names = "pcie_refpll",
"pcie_b";
"pcie",
"port";
/*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/
gpio-type = <1>;
status = "okay";
};
uart_A: serial@ffd24000 {
compatible = "amlogic, meson-uart";
reg = <0x0 0xffd24000 0x0 0x18>;

View File

@@ -25,6 +25,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/input/meson_rc.h>
#include <dt-bindings/phy/phy-amlogic-pcie.h>
/ {
cpus:cpus {

View File

@@ -386,6 +386,31 @@ static struct clk_mux axg_pcie_ref = {
},
};
static struct clk_gate axg_pcie_cml_en0 = {
.reg = (void *)HHI_PCIE_PLL_CNTL6,
.bit_idx = 4,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data) {
.name = "axg_pcie_cml_en0",
.ops = &clk_gate_ops,
.parent_names = (const char *[]){ "axg_pcie_ref" },
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
},
};
static struct clk_gate axg_pcie_cml_en1 = {
.reg = (void *)HHI_PCIE_PLL_CNTL6,
.bit_idx = 3,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data) {
.name = "axg_pcie_cml_en1",
.ops = &clk_gate_ops,
.parent_names = (const char *[]){ "axg_pcie_ref" },
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
},
};
/*
* FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
* post-dividers and should be modelled with their respective PLLs via the
@@ -700,7 +725,8 @@ static struct clk_hw *axg_clk_hws[] = {
[CLKID_PCIE_PLL] = &axg_pcie_pll.hw,
[CLKID_PCIE_MUX] = &axg_pcie_mux.hw,
[CLKID_PCIE_REF] = &axg_pcie_ref.hw,
// [CLKID_PCIE_INPUT_GATE] = &axg_pcie_input_gate.hw,
[CLKID_PCIE_CML_EN0] = &axg_pcie_cml_en0.hw,
[CLKID_PCIE_CML_EN1] = &axg_pcie_cml_en1.hw,
};
/* Convenience tables to populate base addresses in .probe */
@@ -806,6 +832,9 @@ static void __init axg_clkc_init(struct device_node *np)
axg_pcie_mux.reg = clk_base + (u64)axg_pcie_mux.reg;
axg_pcie_ref.reg = clk_base + (u64)axg_pcie_ref.reg;
axg_pcie_cml_en0.reg = clk_base + (u64)axg_pcie_cml_en0.reg;
axg_pcie_cml_en1.reg = clk_base + (u64)axg_pcie_cml_en1.reg;
/* Populate base address for gates */
for (i = 0; i < ARRAY_SIZE(axg_clk_gates); i++)
axg_clk_gates[i]->reg = clk_base +

View File

@@ -66,7 +66,7 @@
#define AXG_PCIE_PLL_CNTL3 0x0a47488e
#define AXG_PCIE_PLL_CNTL4 0xc000004d
#define AXG_PCIE_PLL_CNTL5 0x00078000
#define AXG_PCIE_PLL_CNTL6 0x002323de
#define AXG_PCIE_PLL_CNTL6 0x002323c6
#define AXG_HIFI_PLL_CNTL1 0xc084b000
#define AXG_HIFI_PLL_CNTL2 0xb75020be

View File

@@ -31,22 +31,25 @@
#include "../drivers/pci/host/pcie-designware.h"
#include "pcie-amlogic.h"
struct amlogic_pcie {
struct pcie_port pp;
struct pcie_phy *phy;
void __iomem *elbi_base; /* DT 0th resource */
void __iomem *phy_base; /* DT 1st resource */
void __iomem *cfg_base; /* DT 2nd resource */
void __iomem *reset_base;/* DT 3nd resource */
int reset_gpio;
struct clk *clk;
struct clk *bus_clk;
struct clk *port_clk;
int pcie_num;
int gpio_type;
u32 port_num;
};
#define to_amlogic_pcie(x) container_of(x, struct amlogic_pcie, pp)
struct amlogic_pcie *g_amlogic_pcie;
struct pcie_phy_aml_regs pcie_aml_regs;
struct pcie_phy *g_pcie_phy;
static void amlogic_elb_writel(struct amlogic_pcie *amlogic_pcie, u32 val,
u32 reg)
@@ -362,20 +365,6 @@ void amlogic_set_max_rd_req_size(struct amlogic_pcie *amlogic_pcie, int size)
static void amlogic_pcie_init_dw(struct amlogic_pcie *amlogic_pcie)
{
u32 val = 0;
#if 0
if (amlogic_pcie->pcie_num == 1) {
val = readl(amlogic_pcie->reset_base);
val &= ~((0x3<<6) | (0x3<<1));
writel(val, amlogic_pcie->reset_base);
mdelay(10);
val = readl(amlogic_pcie->reset_base);
val |= (0x3<<6) | (0x3<<1);
writel(val, amlogic_pcie->reset_base);
}
mdelay(10);
#endif
val = amlogic_cfg_readl(amlogic_pcie, PCIE_CFG0);
val |= APP_LTSSM_ENABLE;
@@ -631,16 +620,20 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev)
struct amlogic_pcie *amlogic_pcie;
struct pcie_port *pp;
struct device_node *np = dev->of_node;
struct pcie_phy *phy;
struct resource *elbi_base;
struct resource *phy_base;
struct resource *cfg_base;
struct resource *reset_base;
int ret;
int pcie_num = 0;
int num_lanes = 0;
int gpio_type = 0;
unsigned long rate = 100000000;
int err;
int j = 0;
u32 val = 0;
static u32 port_num;
dev_info(&pdev->dev, "amlogic_pcie_probe!\n");
@@ -650,31 +643,49 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev)
pp = &amlogic_pcie->pp;
pp->dev = dev;
port_num++;
amlogic_pcie->port_num = port_num;
if (amlogic_pcie->port_num == 1) {
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
port_num--;
return -ENOMEM;
}
g_pcie_phy = phy;
}
amlogic_pcie->phy = g_pcie_phy;
ret = of_property_read_u32(np, "pcie-num", &pcie_num);
if (ret)
pp->lanes = 0;
amlogic_pcie->pcie_num = 0;
amlogic_pcie->pcie_num = pcie_num;
if (amlogic_pcie->pcie_num == 1)
g_amlogic_pcie = amlogic_pcie;
ret = of_property_read_u32(np, "num-lanes", &num_lanes);
if (ret)
pp->lanes = 0;
pp->lanes = num_lanes;
if (amlogic_pcie->pcie_num == 1) {
if (!amlogic_pcie->phy->phy_base) {
phy_base = platform_get_resource_byname(
pdev, IORESOURCE_MEM, "phy");
amlogic_pcie->phy_base = devm_ioremap_resource(dev, phy_base);
if (IS_ERR(amlogic_pcie->phy_base)) {
ret = PTR_ERR(amlogic_pcie->phy_base);
amlogic_pcie->phy->phy_base =
devm_ioremap_resource(dev, phy_base);
if (IS_ERR(amlogic_pcie->phy->phy_base)) {
ret = PTR_ERR(amlogic_pcie->phy->phy_base);
port_num--;
return ret;
}
}
if (!amlogic_pcie->phy->power_state) {
for (j = 0; j < 7; j++)
pcie_aml_regs.pcie_phy_r[j] = (void __iomem *)
((unsigned long)amlogic_pcie->phy_base + 4*j);
((unsigned long)amlogic_pcie->phy->phy_base
+ 4*j);
writel(0x1c, pcie_aml_regs.pcie_phy_r[0]);
} else {
amlogic_pcie->phy_base = g_amlogic_pcie->phy_base;
amlogic_pcie->phy->power_state = 1;
}
ret = of_property_read_u32(np, "gpio-type", &gpio_type);
@@ -682,35 +693,91 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev)
amlogic_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
if (amlogic_pcie->pcie_num == 1)
amlogic_pcie->clk = devm_clk_get(dev, "pcie_a");
else
amlogic_pcie->clk = devm_clk_get(dev, "pcie_b");
if (IS_ERR(amlogic_pcie->clk)) {
dev_err(dev, "Failed to get pcie rc clock\n");
return PTR_ERR(amlogic_pcie->clk);
if (!amlogic_pcie->phy->reset_base) {
reset_base = platform_get_resource_byname(
pdev, IORESOURCE_MEM, "reset");
amlogic_pcie->phy->reset_base = devm_ioremap_resource(
dev, reset_base);
if (IS_ERR(amlogic_pcie->phy->reset_base)) {
ret = PTR_ERR(amlogic_pcie->phy->reset_base);
goto fail_pcie;
}
}
ret = clk_prepare_enable(amlogic_pcie->clk);
if (ret)
return ret;
/* RESET0[1,2,6,7] = 0*/
if (!amlogic_pcie->phy->reset_state) {
val = readl(amlogic_pcie->phy->reset_base);
val &= ~((0x3<<6) | (0x3<<1));
writel(val, amlogic_pcie->phy->reset_base);
}
amlogic_pcie->bus_clk = devm_clk_get(dev, "pcie_refpll");
if (IS_ERR(amlogic_pcie->bus_clk)) {
dev_err(dev, "Failed to get pcie bus clock\n");
ret = PTR_ERR(amlogic_pcie->bus_clk);
goto fail_pcie;
}
if (!amlogic_pcie->phy->reset_state) {
err = clk_set_rate(amlogic_pcie->bus_clk, rate);
if (err) {
ret = err;
goto fail_pcie;
}
if (clk_get_rate(amlogic_pcie->bus_clk) == rate) {
ret = -ENODEV;
goto fail_pcie;
}
}
ret = clk_prepare_enable(amlogic_pcie->bus_clk);
if (ret)
goto fail_pcie;
/*RESET0[6,7] = 1*/
if (!amlogic_pcie->phy->reset_state) {
val = readl(amlogic_pcie->phy->reset_base);
val |= (0x3<<6);
writel(val, amlogic_pcie->phy->reset_base);
mdelay(10);
}
amlogic_pcie->clk = devm_clk_get(dev, "pcie");
if (IS_ERR(amlogic_pcie->clk)) {
dev_err(dev, "Failed to get pcie rc clock\n");
ret = PTR_ERR(amlogic_pcie->clk);
goto fail_bus_clk;
}
ret = clk_prepare_enable(amlogic_pcie->clk);
if (ret)
goto fail_bus_clk;
/*RESET0[1,2] = 1*/
if (amlogic_pcie->pcie_num == 1) {
val = readl(amlogic_pcie->phy->reset_base);
val |= (0x1<<1);
writel(val, amlogic_pcie->phy->reset_base);
mdelay(10);
} else {
val = readl(amlogic_pcie->phy->reset_base);
val |= (0x1<<2);
writel(val, amlogic_pcie->phy->reset_base);
mdelay(10);
}
amlogic_pcie->phy->reset_state = 1;
amlogic_pcie->port_clk = devm_clk_get(dev, "port");
if (IS_ERR(amlogic_pcie->port_clk)) {
dev_err(dev, "Failed to get pcie rc clock\n");
ret = PTR_ERR(amlogic_pcie->port_clk);
goto fail_clk;
}
err = clk_set_rate(amlogic_pcie->bus_clk, rate);
if (err)
goto fail_clk;
if (clk_get_rate(amlogic_pcie->bus_clk) == rate)
goto fail_clk;
ret = clk_prepare_enable(amlogic_pcie->bus_clk);
ret = clk_prepare_enable(amlogic_pcie->port_clk);
if (ret)
goto fail_clk;
@@ -718,43 +785,33 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev)
amlogic_pcie->elbi_base = devm_ioremap_resource(dev, elbi_base);
if (IS_ERR(amlogic_pcie->elbi_base)) {
ret = PTR_ERR(amlogic_pcie->elbi_base);
goto fail_bus_clk;
goto fail_port_clk;
}
cfg_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
amlogic_pcie->cfg_base = devm_ioremap_resource(dev, cfg_base);
if (IS_ERR(amlogic_pcie->cfg_base)) {
ret = PTR_ERR(amlogic_pcie->cfg_base);
goto fail_bus_clk;
}
if (amlogic_pcie->pcie_num == 1) {
reset_base = platform_get_resource_byname(
pdev, IORESOURCE_MEM, "reset");
amlogic_pcie->reset_base = devm_ioremap_resource(
dev, reset_base);
if (IS_ERR(amlogic_pcie->reset_base)) {
ret = PTR_ERR(amlogic_pcie->reset_base);
goto fail_bus_clk;
}
} else {
amlogic_pcie->reset_base = g_amlogic_pcie->reset_base;
goto fail_port_clk;
}
ret = amlogic_add_pcie_port(amlogic_pcie, pdev);
if (ret < 0)
goto fail_bus_clk;
goto fail_port_clk;
platform_set_drvdata(pdev, amlogic_pcie);
device_create_file(&pdev->dev, &dev_attr_phyread);
device_create_file(&pdev->dev, &dev_attr_phywrite);
return 0;
fail_bus_clk:
clk_disable_unprepare(amlogic_pcie->bus_clk);
fail_port_clk:
clk_disable_unprepare(amlogic_pcie->port_clk);
fail_clk:
clk_disable_unprepare(amlogic_pcie->clk);
fail_bus_clk:
clk_disable_unprepare(amlogic_pcie->bus_clk);
fail_pcie:
port_num--;
return ret;
}
@@ -784,7 +841,7 @@ static struct platform_driver amlogic_pcie_driver = {
},
};
/* Exynos PCIe driver does not allow module unload */
/* AMLOGIC PCIe driver does not allow module unload */
static int __init amlogic_pcie_init(void)
{
return platform_driver_probe(&amlogic_pcie_driver, amlogic_pcie_probe);

View File

@@ -150,5 +150,12 @@ struct pcie_phy_aml_regs {
void __iomem *pcie_phy_r[7];
};
struct pcie_phy {
u32 power_state;
u32 reset_state;
void __iomem *phy_base; /* DT 1st resource */
void __iomem *reset_base;/* DT 3nd resource */
};
#endif

View File

@@ -50,6 +50,8 @@
#define CLKID_PCIE_MUX 25
#define CLKID_PCIE_REF 26
#define CLKID_PCIE_INPUT_GATE 27
#define CLKID_PCIE_CML_EN0 28
#define CLKID_PCIE_CML_EN1 29
/*HHI_GCLK_MPEG0: 0x50*/
#define GATE_BASE0 25

View File

@@ -0,0 +1,19 @@
/*
*
* This header provides constants for the AMLOGIC PCIE phy
*
* Copyright (C) 2017 AMLOGIC.INC
* Author: Yue Wang <yue.wang@amlogic.com>
* License terms: GNU General Public License (GPL), version 2
*/
#ifndef _DT_AMLOGIC_PCIE_PHY
#define _DT_AMLOGIC_PCIE_PHY
#define PCIE_PHY_REG 0xff644000
#define PCIE_PHY_SIZE 0x2000
#define PCIE_RESET_REG 0xffd01080
#define PCIE_RESET_SIZE 0x10
#endif /* _DT_AMLOGIC_PCIE_PHY */