aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRichard Zhu <r65037@freescale.com>2013-08-14 00:15:38 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:01:30 -0400
commit32bca9520106a8a2733bfad4328e3f2252fa76e3 (patch)
tree73430398d1f365aeff34d948c8fad6c0b985f7b0 /arch
parent0a42956e57a08e7b9e8629c87c5d6e83cb4f2702 (diff)
ENGR00275213-1 arm: pcie: enable pcie on imx6 platforms
Add PCIe related clocks definitions and select pci on imx6 platforms toggle bit18 of grp1 fix pcie pm issue: Set bit18 of gpr1 before enter into supend, and clean it after resume, can fix the following errata. Errata ERR005723_PCIe PCIe does not support L2 Power Down. Signed-off-by: Richard Zhu <r65037@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/Kconfig2
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c16
-rw-r--r--arch/arm/mach-imx/pm-imx6.c28
3 files changed, 45 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 0633cf9cc01f..c26aac0a203d 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -809,6 +809,8 @@ config SOC_IMX6Q
809 select HAVE_IMX_SRC 809 select HAVE_IMX_SRC
810 select HAVE_SMP 810 select HAVE_SMP
811 select MFD_SYSCON 811 select MFD_SYSCON
812 select MIGHT_HAVE_PCI
813 select PCI_DOMAINS if PCI
812 select PINCTRL 814 select PINCTRL
813 select PINCTRL_IMX6Q 815 select PINCTRL_IMX6Q
814 select PL310_ERRATA_588369 if CACHE_PL310 816 select PL310_ERRATA_588369 if CACHE_PL310
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index f39e7706c5c5..e9f068c646a1 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -58,6 +58,8 @@ static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m",
58static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div", 58static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
59 "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0", 59 "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
60 "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_aduio_div", }; 60 "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_aduio_div", };
61static const char *lvds_sels[] = { "arm", "pll1_sys", "dummy", "dummy", "dummy", "dummy", "dummy", "pll5_video_div",
62 "dummy", "dummy", "pcie_ref", "sata_ref", "usbphy1", "usbphy2", };
61static const char *cko2_sels[] = { 63static const char *cko2_sels[] = {
62 "mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1", 64 "mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1",
63 "gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi", 65 "gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi",
@@ -105,7 +107,7 @@ enum mx6q_clks {
105 usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, 107 usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
106 spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, gpt_3m, video_27m, 108 spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, gpt_3m, video_27m,
107 ldb_di0_div_7, ldb_di1_div_7, ldb_di0_div_sel, ldb_di1_div_sel, 109 ldb_di0_div_7, ldb_di1_div_7, ldb_di0_div_sel, ldb_di1_div_sel,
108 pll4_audio_div, clk_max 110 pll4_audio_div, lvds1_sel, lvds1_in, lvds1_out, clk_max
109}; 111};
110 112
111static struct clk *clk[clk_max]; 113static struct clk *clk[clk_max];
@@ -170,6 +172,9 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
170 clk[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3); 172 clk[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3);
171 clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3); 173 clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3);
172 174
175 /* name reg shift width parent_names num_parents */
176 clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
177
173 /* 178 /*
174 * Bit 20 is the reserved and read-only bit, we do this only for: 179 * Bit 20 is the reserved and read-only bit, we do this only for:
175 * - Do nothing for usbphy clk_enable/disable 180 * - Do nothing for usbphy clk_enable/disable
@@ -188,6 +193,9 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
188 193
189 clk[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5); 194 clk[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
190 clk[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4); 195 clk[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
196 /* NOTICE: The gate of the lvds1 in/out is used to select the clk direction */
197 clk[lvds1_in] = imx_clk_gate("lvds1_in", NULL, base + 0x160, 12);
198 clk[lvds1_out] = imx_clk_gate("lvds1_out", "lvds1_sel", base + 0x160, 10);
191 199
192 clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20); 200 clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
193 clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19); 201 clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
@@ -448,6 +456,12 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
448 */ 456 */
449 clk_set_parent(clk[enfc_sel], clk[pll2_pfd2_396m]); 457 clk_set_parent(clk[enfc_sel], clk[pll2_pfd2_396m]);
450 458
459 /* Set the parent clks of PCIe lvds1 and pcie_axi to be sata ref, axi */
460 if (clk_set_parent(clk[lvds1_sel], clk[sata_ref]))
461 pr_err("Failed to set PCIe bus parent clk.\n");
462 if (clk_set_parent(clk[pcie_axi_sel], clk[axi]))
463 pr_err("Failed to set PCIe parent clk.\n");
464
451 /* gpu clock initilazation */ 465 /* gpu clock initilazation */
452 clk_set_parent(clk[gpu3d_shader_sel], clk[pll2_pfd1_594m]); 466 clk_set_parent(clk[gpu3d_shader_sel], clk[pll2_pfd1_594m]);
453 clk_set_rate(clk[gpu3d_shader], 594000000); 467 clk_set_rate(clk[gpu3d_shader], 594000000);
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 1f75d059a887..acb32940b39b 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -18,6 +18,9 @@
18#include <linux/of_irq.h> 18#include <linux/of_irq.h>
19#include <linux/suspend.h> 19#include <linux/suspend.h>
20#include <linux/genalloc.h> 20#include <linux/genalloc.h>
21#include <linux/regmap.h>
22#include <linux/mfd/syscon.h>
23#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
21#include <asm/cacheflush.h> 24#include <asm/cacheflush.h>
22#include <asm/fncpy.h> 25#include <asm/fncpy.h>
23#include <asm/proc-fns.h> 26#include <asm/proc-fns.h>
@@ -229,6 +232,22 @@ static int imx6_suspend_finish(unsigned long val)
229 232
230static int imx6_pm_enter(suspend_state_t state) 233static int imx6_pm_enter(suspend_state_t state)
231{ 234{
235 struct regmap *gpr;
236
237 /*
238 * L2 can exit by 'reset' or Inband beacon (from remote EP)
239 * toggling phy_powerdown has same effect as 'inband beacon'
240 * So, toggle bit18 of GPR1, to fix errata
241 * "PCIe PCIe does not support L2 Power Down"
242 */
243 gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
244 if (IS_ERR(gpr)) {
245 pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
246 return PTR_ERR(gpr);
247 }
248 regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD,
249 IMX6Q_GPR1_PCIE_TEST_PD);
250
232 switch (state) { 251 switch (state) {
233 case PM_SUSPEND_STANDBY: 252 case PM_SUSPEND_STANDBY:
234 imx6_set_lpm(STOP_POWER_ON); 253 imx6_set_lpm(STOP_POWER_ON);
@@ -258,6 +277,15 @@ static int imx6_pm_enter(suspend_state_t state)
258 return -EINVAL; 277 return -EINVAL;
259 } 278 }
260 279
280 /*
281 * L2 can exit by 'reset' or Inband beacon (from remote EP)
282 * toggling phy_powerdown has same effect as 'inband beacon'
283 * So, toggle bit18 of GPR1, to fix errata
284 * "PCIe PCIe does not support L2 Power Down"
285 */
286 regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD,
287 !IMX6Q_GPR1_PCIE_TEST_PD);
288
261 return 0; 289 return 0;
262} 290}
263 291