diff --git a/MAINTAINERS b/MAINTAINERS index 5ba6554f2b0c..0383a4c8b949 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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 diff --git a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts index 7813e69410d6..cd01809acd14 100644 --- a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts @@ -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"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index 6c5a273d91be..12b1cf7d3c47 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -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>; diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index f07fa3ae08ef..6cf323a1df99 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -25,6 +25,7 @@ #include #include #include +#include / { cpus:cpus { diff --git a/drivers/amlogic/clk/axg/axg.c b/drivers/amlogic/clk/axg/axg.c index 829c1f28daba..6c80432225f8 100644 --- a/drivers/amlogic/clk/axg/axg.c +++ b/drivers/amlogic/clk/axg/axg.c @@ -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 + diff --git a/drivers/amlogic/clk/axg/axg_clk-pll.c b/drivers/amlogic/clk/axg/axg_clk-pll.c index 5e58d3d1a35f..28c45ef068e2 100644 --- a/drivers/amlogic/clk/axg/axg_clk-pll.c +++ b/drivers/amlogic/clk/axg/axg_clk-pll.c @@ -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 diff --git a/drivers/amlogic/pci/pcie-amlogic.c b/drivers/amlogic/pci/pcie-amlogic.c index 5075ccb7be68..e9907d4a5a8b 100644 --- a/drivers/amlogic/pci/pcie-amlogic.c +++ b/drivers/amlogic/pci/pcie-amlogic.c @@ -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); diff --git a/drivers/amlogic/pci/pcie-amlogic.h b/drivers/amlogic/pci/pcie-amlogic.h index 3a0b394c7705..e5e2531a74e4 100644 --- a/drivers/amlogic/pci/pcie-amlogic.h +++ b/drivers/amlogic/pci/pcie-amlogic.h @@ -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 diff --git a/include/dt-bindings/clock/amlogic,axg-clkc.h b/include/dt-bindings/clock/amlogic,axg-clkc.h index b6d299f356b4..85d292457392 100644 --- a/include/dt-bindings/clock/amlogic,axg-clkc.h +++ b/include/dt-bindings/clock/amlogic,axg-clkc.h @@ -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 diff --git a/include/dt-bindings/phy/phy-amlogic-pcie.h b/include/dt-bindings/phy/phy-amlogic-pcie.h new file mode 100644 index 000000000000..adf66c995f18 --- /dev/null +++ b/include/dt-bindings/phy/phy-amlogic-pcie.h @@ -0,0 +1,19 @@ +/* + * + * This header provides constants for the AMLOGIC PCIE phy + * + * Copyright (C) 2017 AMLOGIC.INC + * Author: Yue Wang + * 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 */