diff options
author | Richard Zhu <r65037@freescale.com> | 2013-08-14 00:15:38 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:01:30 -0400 |
commit | 32bca9520106a8a2733bfad4328e3f2252fa76e3 (patch) | |
tree | 73430398d1f365aeff34d948c8fad6c0b985f7b0 /arch | |
parent | 0a42956e57a08e7b9e8629c87c5d6e83cb4f2702 (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/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx6q.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-imx/pm-imx6.c | 28 |
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", | |||
58 | static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div", | 58 | static 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", }; |
61 | static const char *lvds_sels[] = { "arm", "pll1_sys", "dummy", "dummy", "dummy", "dummy", "dummy", "pll5_video_div", | ||
62 | "dummy", "dummy", "pcie_ref", "sata_ref", "usbphy1", "usbphy2", }; | ||
61 | static const char *cko2_sels[] = { | 63 | static 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 | ||
111 | static struct clk *clk[clk_max]; | 113 | static 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 | ||
230 | static int imx6_pm_enter(suspend_state_t state) | 233 | static 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 | ||