diff options
Diffstat (limited to 'arch/arm/mach-imx')
30 files changed, 984 insertions, 232 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index ba44328464f..60661a4b0e2 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -56,9 +56,6 @@ config MXC_USE_EPIT uses the same clocks as the GPT. Anyway, on some systems the GPT may be in use for other purposes. -config MXC_ULPI - bool - config ARCH_HAS_RNGA bool @@ -176,6 +173,7 @@ config ARCH_MX1ADS config MACH_SCB9328 bool "Synertronixx scb9328" select IMX_HAVE_PLATFORM_IMX_UART + select SOC_IMX1 help Say Y here if you are using a Synertronixx scb9328 board @@ -233,7 +231,7 @@ config MACH_EUKREA_CPUIMX25SD select IMX_HAVE_PLATFORM_MXC_EHCI select IMX_HAVE_PLATFORM_MXC_NAND select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX25 choice @@ -284,7 +282,7 @@ config MACH_PCM038 select IMX_HAVE_PLATFORM_MXC_NAND select IMX_HAVE_PLATFORM_MXC_W1 select IMX_HAVE_PLATFORM_SPI_IMX - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX27 help Include support for phyCORE-i.MX27 (aka pcm038) platform. This @@ -314,7 +312,7 @@ config MACH_CPUIMX27 select IMX_HAVE_PLATFORM_MXC_EHCI select IMX_HAVE_PLATFORM_MXC_NAND select IMX_HAVE_PLATFORM_MXC_W1 - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX27 help Include support for Eukrea CPUIMX27 platform. This includes @@ -369,7 +367,7 @@ config MACH_MX27_3DS select IMX_HAVE_PLATFORM_MXC_MMC select IMX_HAVE_PLATFORM_SPI_IMX select MXC_DEBUG_BOARD - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX27 help Include support for MX27PDK platform. This includes specific @@ -414,7 +412,7 @@ config MACH_PCA100 select IMX_HAVE_PLATFORM_MXC_NAND select IMX_HAVE_PLATFORM_MXC_W1 select IMX_HAVE_PLATFORM_SPI_IMX - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX27 help Include support for phyCARD-s (aka pca100) platform. This @@ -481,7 +479,7 @@ config MACH_MX31LILLY select IMX_HAVE_PLATFORM_MXC_EHCI select IMX_HAVE_PLATFORM_MXC_MMC select IMX_HAVE_PLATFORM_SPI_IMX - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX31 help Include support for mx31 based LILLY1131 modules. This includes @@ -497,7 +495,7 @@ config MACH_MX31LITE select IMX_HAVE_PLATFORM_MXC_RTC select IMX_HAVE_PLATFORM_SPI_IMX select LEDS_GPIO_REGISTER - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX31 help Include support for MX31 LITEKIT platform. This includes specific @@ -514,7 +512,7 @@ config MACH_PCM037 select IMX_HAVE_PLATFORM_MXC_MMC select IMX_HAVE_PLATFORM_MXC_NAND select IMX_HAVE_PLATFORM_MXC_W1 - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX31 help Include support for Phytec pcm037 platform. This includes @@ -544,7 +542,7 @@ config MACH_MX31_3DS select IMX_HAVE_PLATFORM_MXC_NAND select IMX_HAVE_PLATFORM_SPI_IMX select MXC_DEBUG_BOARD - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX31 help Include support for MX31PDK (3DS) platform. This includes specific @@ -571,7 +569,7 @@ config MACH_MX31MOBOARD select IMX_HAVE_PLATFORM_MXC_MMC select IMX_HAVE_PLATFORM_SPI_IMX select LEDS_GPIO_REGISTER - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX31 help Include support for mx31moboard platform. This includes specific @@ -595,7 +593,7 @@ config MACH_ARMADILLO5X0 select IMX_HAVE_PLATFORM_MXC_EHCI select IMX_HAVE_PLATFORM_MXC_MMC select IMX_HAVE_PLATFORM_MXC_NAND - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX31 help Include support for Atmark Armadillo-500 platform. This includes @@ -639,7 +637,7 @@ config MACH_PCM043 select IMX_HAVE_PLATFORM_MXC_EHCI select IMX_HAVE_PLATFORM_MXC_NAND select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX35 help Include support for Phytec pcm043 platform. This includes @@ -673,7 +671,7 @@ config MACH_EUKREA_CPUIMX35SD select IMX_HAVE_PLATFORM_MXC_EHCI select IMX_HAVE_PLATFORM_MXC_NAND select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select MXC_ULPI if USB_ULPI + select USB_ULPI_VIEWPORT if USB_ULPI select SOC_IMX35 help Include support for Eukrea CPUIMX35 platform. This includes @@ -816,6 +814,41 @@ config SOC_IMX6Q help This enables support for Freescale i.MX6 Quad processor. +config SOC_IMX6SL + bool "i.MX6 SoloLite support" + select ARM_ERRATA_754322 + select ARM_ERRATA_775420 + select ARM_GIC + select CPU_V7 + select HAVE_IMX_ANATOP + select HAVE_IMX_GPC + select HAVE_IMX_MMDC + select HAVE_IMX_SRC + select MFD_SYSCON + select PINCTRL + select PINCTRL_IMX6SL + select PL310_ERRATA_588369 if CACHE_PL310 + select PL310_ERRATA_727915 if CACHE_PL310 + select PL310_ERRATA_769419 if CACHE_PL310 + + help + This enables support for Freescale i.MX6 SoloLite processor. + +config SOC_VF610 + bool "Vybrid Family VF610 support" + select CPU_V7 + select ARM_GIC + select CLKSRC_OF + select PINCTRL + select PINCTRL_VF610 + select VF_PIT_TIMER + select PL310_ERRATA_588369 if CACHE_PL310 + select PL310_ERRATA_727915 if CACHE_PL310 + select PL310_ERRATA_769419 if CACHE_PL310 + + help + This enable support for Freescale Vybrid VF610 processor. + endif source "arch/arm/mach-imx/devices/Kconfig" diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 70ae7c490ac..e20f22d58fd 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o obj-$(CONFIG_MXC_TZIC) += tzic.o obj-$(CONFIG_MXC_AVIC) += avic.o -obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_MXC_USE_EPIT) += epit.o obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o @@ -98,6 +97,7 @@ AFLAGS_headsmp.o :=-Wa,-march=armv7-a obj-$(CONFIG_SMP) += headsmp.o platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o +obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o ifeq ($(CONFIG_PM),y) obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o @@ -111,4 +111,6 @@ obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd51-baseboard.o obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o obj-$(CONFIG_SOC_IMX53) += mach-imx53.o +obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o + obj-y += devices/ diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index 6fc486b6a3c..04b1bad6835 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -73,6 +73,12 @@ static const char *mx53_cko2_sel[] = { "tve_sel", "lp_apm", "uart_root", "dummy"/* spdif0_clk_root */, "dummy", "dummy", }; +static const char *mx51_spdif_xtal_sel[] = { "osc", "ckih", "ckih2", }; +static const char *mx53_spdif_xtal_sel[] = { "osc", "ckih", "ckih2", "pll4_sw", }; +static const char *spdif_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "spdif_xtal_sel", }; +static const char *spdif0_com_sel[] = { "spdif0_podf", "ssi1_root_gate", }; +static const char *mx51_spdif1_com_sel[] = { "spdif1_podf", "ssi2_root_gate", }; + enum imx5_clks { dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred, @@ -110,7 +116,9 @@ enum imx5_clks { owire_gate, gpu3d_s, gpu2d_s, gpu3d_gate, gpu2d_gate, garb_gate, cko1_sel, cko1_podf, cko1, cko2_sel, cko2_podf, cko2, - srtc_gate, pata_gate, + srtc_gate, pata_gate, sata_gate, spdif_xtal_sel, spdif0_sel, + spdif1_sel, spdif0_pred, spdif0_podf, spdif1_pred, spdif1_podf, + spdif0_com_s, spdif1_com_sel, spdif0_gate, spdif1_gate, spdif_ipg_gate, clk_max }; @@ -123,11 +131,13 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, { int i; + of_clk_init(NULL); + clk[dummy] = imx_clk_fixed("dummy", 0); - clk[ckil] = imx_clk_fixed("ckil", rate_ckil); - clk[osc] = imx_clk_fixed("osc", rate_osc); - clk[ckih1] = imx_clk_fixed("ckih1", rate_ckih1); - clk[ckih2] = imx_clk_fixed("ckih2", rate_ckih2); + clk[ckil] = imx_obtain_fixed_clock("ckil", rate_ckil); + clk[osc] = imx_obtain_fixed_clock("osc", rate_osc); + clk[ckih1] = imx_obtain_fixed_clock("ckih1", rate_ckih1); + clk[ckih2] = imx_obtain_fixed_clock("ckih2", rate_ckih2); clk[lp_apm] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1, lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); @@ -267,6 +277,13 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk[owire_gate] = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22); clk[srtc_gate] = imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28); clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0); + clk[spdif0_sel] = imx_clk_mux("spdif0_sel", MXC_CCM_CSCMR2, 0, 2, spdif_sel, ARRAY_SIZE(spdif_sel)); + clk[spdif0_pred] = imx_clk_divider("spdif0_pred", "spdif0_sel", MXC_CCM_CDCDR, 25, 3); + clk[spdif0_podf] = imx_clk_divider("spdif0_podf", "spdif0_pred", MXC_CCM_CDCDR, 19, 6); + clk[spdif0_com_s] = imx_clk_mux_flags("spdif0_com_sel", MXC_CCM_CSCMR2, 4, 1, + spdif0_com_sel, ARRAY_SIZE(spdif0_com_sel), CLK_SET_RATE_PARENT); + clk[spdif0_gate] = imx_clk_gate2("spdif0_gate", "spdif0_com_sel", MXC_CCM_CCGR5, 26); + clk[spdif_ipg_gate] = imx_clk_gate2("spdif_ipg_gate", "ipg", MXC_CCM_CCGR5, 30); for (i = 0; i < ARRAY_SIZE(clk); i++) if (IS_ERR(clk[i])) @@ -378,6 +395,15 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk[mipi_hsc2_gate] = imx_clk_gate2("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8); clk[mipi_esc_gate] = imx_clk_gate2("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10); clk[mipi_hsp_gate] = imx_clk_gate2("mipi_hsp_gate", "ipg", MXC_CCM_CCGR4, 12); + clk[spdif_xtal_sel] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2, + mx51_spdif_xtal_sel, ARRAY_SIZE(mx51_spdif_xtal_sel)); + clk[spdif1_sel] = imx_clk_mux("spdif1_sel", MXC_CCM_CSCMR2, 2, 2, + spdif_sel, ARRAY_SIZE(spdif_sel)); + clk[spdif1_pred] = imx_clk_divider("spdif1_podf", "spdif1_sel", MXC_CCM_CDCDR, 16, 3); + clk[spdif1_podf] = imx_clk_divider("spdif1_podf", "spdif1_pred", MXC_CCM_CDCDR, 9, 6); + clk[spdif1_com_sel] = imx_clk_mux("spdif1_com_sel", MXC_CCM_CSCMR2, 5, 1, + mx51_spdif1_com_sel, ARRAY_SIZE(mx51_spdif1_com_sel)); + clk[spdif1_gate] = imx_clk_gate2("spdif1_gate", "spdif1_com_sel", MXC_CCM_CCGR5, 28); for (i = 0; i < ARRAY_SIZE(clk); i++) if (IS_ERR(clk[i])) @@ -485,6 +511,7 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk[can2_serial_gate] = imx_clk_gate2("can2_serial_gate", "can_sel", MXC_CCM_CCGR4, 8); clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6); clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22); + clk[sata_gate] = imx_clk_gate2("sata_gate", "ipg", MXC_CCM_CCGR4, 2); clk[cko1_sel] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4, mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel)); @@ -495,6 +522,8 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel)); clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3); clk[cko2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24); + clk[spdif_xtal_sel] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2, + mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel)); for (i = 0; i < ARRAY_SIZE(clk); i++) if (IS_ERR(clk[i])) @@ -542,42 +571,12 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, return 0; } -#ifdef CONFIG_OF -static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc, - unsigned long *ckih1, unsigned long *ckih2) -{ - struct device_node *np; - - /* retrieve the freqency of fixed clocks from device tree */ - for_each_compatible_node(np, NULL, "fixed-clock") { - u32 rate; - if (of_property_read_u32(np, "clock-frequency", &rate)) - continue; - - if (of_device_is_compatible(np, "fsl,imx-ckil")) - *ckil = rate; - else if (of_device_is_compatible(np, "fsl,imx-osc")) - *osc = rate; - else if (of_device_is_compatible(np, "fsl,imx-ckih1")) - *ckih1 = rate; - else if (of_device_is_compatible(np, "fsl,imx-ckih2")) - *ckih2 = rate; - } -} - int __init mx51_clocks_init_dt(void) { - unsigned long ckil, osc, ckih1, ckih2; - - clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2); - return mx51_clocks_init(ckil, osc, ckih1, ckih2); + return mx51_clocks_init(0, 0, 0, 0); } int __init mx53_clocks_init_dt(void) { - unsigned long ckil, osc, ckih1, ckih2; - - clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2); - return mx53_clocks_init(ckil, osc, ckih1, ckih2); + return mx53_clocks_init(0, 0, 0, 0); } -#endif diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 4e3148ce852..4282e99f5ca 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -238,7 +238,7 @@ enum mx6q_clks { pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg, ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, - usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, clk_max + usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, clk_max }; static struct clk *clk[clk_max]; @@ -270,27 +270,16 @@ static struct clk_div_table video_div_table[] = { { } }; -int __init mx6q_clocks_init(void) +static void __init imx6q_clocks_init(struct device_node *ccm_node) { struct device_node *np; void __iomem *base; int i, irq; clk[dummy] = imx_clk_fixed("dummy", 0); - - /* retrieve the freqency of fixed clocks from device tree */ - for_each_compatible_node(np, NULL, "fixed-clock") { - u32 rate; - if (of_property_read_u32(np, "clock-frequency", &rate)) - continue; - - if (of_device_is_compatible(np, "fsl,imx-ckil")) - clk[ckil] = imx_clk_fixed("ckil", rate); - else if (of_device_is_compatible(np, "fsl,imx-ckih1")) - clk[ckih] = imx_clk_fixed("ckih", rate); - else if (of_device_is_compatible(np, "fsl,imx-osc")) - clk[osc] = imx_clk_fixed("osc", rate); - } + clk[ckil] = imx_obtain_fixed_clock("ckil", 0); + clk[ckih] = imx_obtain_fixed_clock("ckih1", 0); + clk[osc] = imx_obtain_fixed_clock("osc", 0); np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); base = of_iomap(np, 0); @@ -312,7 +301,6 @@ int __init mx6q_clocks_init(void) clk[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f); clk[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3); clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3); - clk[pll8_mlb] = imx_clk_pllv3(IMX_PLLV3_MLB, "pll8_mlb", "osc", base + 0xd0, 0x0); /* * Bit 20 is the reserved and read-only bit, we do this only for: @@ -360,7 +348,7 @@ int __init mx6q_clocks_init(void) clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm"); + np = ccm_node; base = of_iomap(np, 0); WARN_ON(!base); ccm_base = base; @@ -481,7 +469,14 @@ int __init mx6q_clocks_init(void) clk[esai] = imx_clk_gate2("esai", "esai_podf", base + 0x6c, 16); clk[gpt_ipg] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20); clk[gpt_ipg_per] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22); - clk[gpu2d_core] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24); + if (cpu_is_imx6dl()) + /* + * The multiplexer and divider of imx6q clock gpu3d_shader get + * redefined/reused as gpu2d_core_sel and gpu2d_core_podf on imx6dl. + */ + clk[gpu2d_core] = imx_clk_gate2("gpu2d_core", "gpu3d_shader", base + 0x6c, 24); + else + clk[gpu2d_core] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24); clk[gpu3d_core] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26); clk[hdmi_iahb] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0); clk[hdmi_isfr] = imx_clk_gate2("hdmi_isfr", "pll3_pfd1_540m", base + 0x70, 4); @@ -499,7 +494,14 @@ int __init mx6q_clocks_init(void) clk[ldb_di1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", base + 0x74, 14); clk[ipu2_di1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", base + 0x74, 10); clk[hsi_tx] = imx_clk_gate2("hsi_tx", "hsi_tx_podf", base + 0x74, 16); - clk[mlb] = imx_clk_gate2("mlb", "axi", base + 0x74, 18); + if (cpu_is_imx6dl()) + /* + * The multiplexer and divider of the imx6q clock gpu2d get + * redefined/reused as mlb_sys_sel and mlb_sys_clk_podf on imx6dl. + */ + clk[mlb] = imx_clk_gate2("mlb", "gpu2d_core_podf", base + 0x74, 18); + else + clk[mlb] = imx_clk_gate2("mlb", "axi", base + 0x74, 18); clk[mmdc_ch0_axi] = imx_clk_gate2("mmdc_ch0_axi", "mmdc_ch0_axi_podf", base + 0x74, 20); clk[mmdc_ch1_axi] = imx_clk_gate2("mmdc_ch1_axi", "mmdc_ch1_axi_podf", base + 0x74, 22); clk[ocram] = imx_clk_gate2("ocram", "ahb", base + 0x74, 28); @@ -528,6 +530,7 @@ int __init mx6q_clocks_init(void) clk[usdhc2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); clk[usdhc3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); clk[usdhc4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); + clk[eim_slow] = imx_clk_gate2("eim_slow", "emi_slow_podf", base + 0x80, 10); clk[vdo_axi] = imx_clk_gate2("vdo_axi", "vdo_axi_sel", base + 0x80, 12); clk[vpu_axi] = imx_clk_gate2("vpu_axi", "vpu_axi_podf", base + 0x80, 14); clk[cko1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7); @@ -547,6 +550,8 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[ahb], "ahb", NULL); clk_register_clkdev(clk[cko1], "cko1", NULL); clk_register_clkdev(clk[arm], NULL, "cpu0"); + clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL); + clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL); if (imx6q_revision() != IMX_CHIP_REVISION_1_0) { clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]); @@ -576,6 +581,5 @@ int __init mx6q_clocks_init(void) WARN_ON(!base); irq = irq_of_parse_and_map(np, 0); mxc_timer_init(base, irq); - - return 0; } +CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init); diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c new file mode 100644 index 00000000000..a307ac22dff --- /dev/null +++ b/arch/arm/mach-imx/clk-imx6sl.c @@ -0,0 +1,267 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <dt-bindings/clock/imx6sl-clock.h> + +#include "clk.h" +#include "common.h" + +static const char const *step_sels[] = { "osc", "pll2_pfd2", }; +static const char const *pll1_sw_sels[] = { "pll1_sys", "step", }; +static const char const *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", }; +static const char const *ocram_sels[] = { "periph", "ocram_alt_sels", }; +static const char const *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", }; +static const char const *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", }; +static const char const *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", }; +static const char const *periph_sels[] = { "pre_periph_sel", "periph_clk2_podf", }; +static const char const *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2_podf", }; +static const char const *csi_lcdif_sels[] = { "mmdc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", }; +static const char const *usdhc_sels[] = { "pll2_pfd2", "pll2_pfd0", }; +static const char const *ssi_sels[] = { "pll3_pfd2", "pll3_pfd3", "pll4_post_div", "dummy", }; +static const char const *perclk_sels[] = { "ipg", "osc", }; +static const char const *epdc_pxp_sels[] = { "mmdc", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd1", }; +static const char const *gpu2d_ovg_sels[] = { "pll3_pfd1", "pll3_usb_otg", "pll2_bus", "pll2_pfd2", }; +static const char const *gpu2d_sels[] = { "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", "pll2_bus", }; +static const char const *lcdif_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll3_pfd0", "pll3_pfd1", }; +static const char const *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", }; +static const char const *audio_sels[] = { "pll4_post_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", }; +static const char const *ecspi_sels[] = { "pll3_60m", "osc", }; +static const char const *uart_sels[] = { "pll3_80m", "osc", }; + +static struct clk_div_table clk_enet_ref_table[] = { + { .val = 0, .div = 20, }, + { .val = 1, .div = 10, }, + { .val = 2, .div = 5, }, + { .val = 3, .div = 4, }, + { } +}; + +static struct clk_div_table post_div_table[] = { + { .val = 2, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 0, .div = 4, }, + { } +}; + +static struct clk_div_table video_div_table[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 2, .div = 1, }, + { .val = 3, .div = 4, }, + { } +}; + +static struct clk *clks[IMX6SL_CLK_CLK_END]; +static struct clk_onecell_data clk_data; + +static void __init imx6sl_clocks_init(struct device_node *ccm_node) +{ + struct device_node *np; + void __iomem *base; + int irq; + int i; + + clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0); + clks[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0); + clks[IMX6SL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0); + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop"); + base = of_iomap(np, 0); + WARN_ON(!base); + + /* type name parent base div_mask */ + clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); + clks[IMX6SL_CLK_PLL2_BUS] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1); + clks[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3); + clks[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f); + clks[IMX6SL_CLK_PLL5_VIDEO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f); + clks[IMX6SL_CLK_PLL6_ENET] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3); + clks[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host", "osc", base + 0x20, 0x3); + + /* + * usbphy1 and usbphy2 are implemented as dummy gates using reserve + * bit 20. They are used by phy driver to keep the refcount of + * parent PLL correct. usbphy1_gate and usbphy2_gate only needs to be + * turned on during boot, and software will not need to control it + * anymore after that. + */ + clks[IMX6SL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20); + clks[IMX6SL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20); + clks[IMX6SL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6); + clks[IMX6SL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6); + + /* dev name parent_name flags reg shift width div: flags, div_table lock */ + clks[IMX6SL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); + clks[IMX6SL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); + clks[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); + clks[IMX6SL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0, base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock); + + /* name parent_name reg idx */ + clks[IMX6SL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0", "pll2_bus", base + 0x100, 0); + clks[IMX6SL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_bus", base + 0x100, 1); + clks[IMX6SL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_bus", base + 0x100, 2); + clks[IMX6SL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0", "pll3_usb_otg", base + 0xf0, 0); + clks[IMX6SL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_usb_otg", base + 0xf0, 1); + clks[IMX6SL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", base + 0xf0, 2); + clks[IMX6SL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", base + 0xf0, 3); + + /* name parent_name mult div */ + clks[IMX6SL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2", 1, 2); + clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); + clks[IMX6SL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); + clks[IMX6SL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); + + np = ccm_node; + base = of_iomap(np, 0); + WARN_ON(!base); + + /* name reg shift width parent_names num_parents */ + clks[IMX6SL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); + clks[IMX6SL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); + clks[IMX6SL_CLK_OCRAM_ALT_SEL] = imx_clk_mux("ocram_alt_sel", base + 0x14, 7, 1, ocram_alt_sels, ARRAY_SIZE(ocram_alt_sels)); + clks[IMX6SL_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 1, ocram_sels, ARRAY_SIZE(ocram_sels)); + clks[IMX6SL_CLK_PRE_PERIPH2_SEL] = imx_clk_mux("pre_periph2_sel", base + 0x18, 21, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); + clks[IMX6SL_CLK_PRE_PERIPH_SEL] = imx_clk_mux("pre_periph_sel", base + 0x18, 18, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); + clks[IMX6SL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); + clks[IMX6SL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); + clks[IMX6SL_CLK_CSI_SEL] = imx_clk_mux("csi_sel", base + 0x3c, 9, 2, csi_lcdif_sels, ARRAY_SIZE(csi_lcdif_sels)); + clks[IMX6SL_CLK_LCDIF_AXI_SEL] = imx_clk_mux("lcdif_axi_sel", base + 0x3c, 14, 2, csi_lcdif_sels, ARRAY_SIZE(csi_lcdif_sels)); + clks[IMX6SL_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SL_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SL_CLK_USDHC3_SEL] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SL_CLK_USDHC4_SEL] = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SL_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); + clks[IMX6SL_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); + clks[IMX6SL_CLK_SSI3_SEL] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); + clks[IMX6SL_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels)); + clks[IMX6SL_CLK_PXP_AXI_SEL] = imx_clk_mux("pxp_axi_sel", base + 0x34, 6, 3, epdc_pxp_sels, ARRAY_SIZE(epdc_pxp_sels)); + clks[IMX6SL_CLK_EPDC_AXI_SEL] = imx_clk_mux("epdc_axi_sel", base + 0x34, 15, 3, epdc_pxp_sels, ARRAY_SIZE(epdc_pxp_sels)); + clks[IMX6SL_CLK_GPU2D_OVG_SEL] = imx_clk_mux("gpu2d_ovg_sel", base + 0x18, 4, 2, gpu2d_ovg_sels, ARRAY_SIZE(gpu2d_ovg_sels)); + clks[IMX6SL_CLK_GPU2D_SEL] = imx_clk_mux("gpu2d_sel", base + 0x18, 8, 2, gpu2d_sels, ARRAY_SIZE(gpu2d_sels)); + clks[IMX6SL_CLK_LCDIF_PIX_SEL] = imx_clk_mux("lcdif_pix_sel", base + 0x38, 6, 3, lcdif_pix_sels, ARRAY_SIZE(lcdif_pix_sels)); + clks[IMX6SL_CLK_EPDC_PIX_SEL] = imx_clk_mux("epdc_pix_sel", base + 0x38, 15, 3, epdc_pix_sels, ARRAY_SIZE(epdc_pix_sels)); + clks[IMX6SL_CLK_SPDIF0_SEL] = imx_clk_mux("spdif0_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels)); + clks[IMX6SL_CLK_SPDIF1_SEL] = imx_clk_mux("spdif1_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels)); + clks[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels)); + clks[IMX6SL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); + clks[IMX6SL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels)); + + /* name reg shift width busy: reg, shift parent_names num_parents */ + clks[IMX6SL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); + clks[IMX6SL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels)); + + /* name parent_name reg shift width */ + clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3); + clks[IMX6SL_CLK_PERIPH_CLK2_PODF] = imx_clk_divider("periph_clk2_podf", "periph_clk2_sel", base + 0x14, 27, 3); + clks[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_divider("periph2_clk2_podf", "periph2_clk2_sel", base + 0x14, 0, 3); + clks[IMX6SL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); + clks[IMX6SL_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3); + clks[IMX6SL_CLK_LCDIF_AXI_PODF] = imx_clk_divider("lcdif_axi_podf", "lcdif_axi_sel", base + 0x3c, 16, 3); + clks[IMX6SL_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3); + clks[IMX6SL_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3); + clks[IMX6SL_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3); + clks[IMX6SL_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); + clks[IMX6SL_CLK_SSI1_PRED] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3); + clks[IMX6SL_CLK_SSI1_PODF] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6); + clks[IMX6SL_CLK_SSI2_PRED] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3); + clks[IMX6SL_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6); + clks[IMX6SL_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3); + clks[IMX6SL_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6); + clks[IMX6SL_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6); + clks[IMX6SL_CLK_PXP_AXI_PODF] = imx_clk_divider("pxp_axi_podf", "pxp_axi_sel", base + 0x34, 3, 3); + clks[IMX6SL_CLK_EPDC_AXI_PODF] = imx_clk_divider("epdc_axi_podf", "epdc_axi_sel", base + 0x34, 12, 3); + clks[IMX6SL_CLK_GPU2D_OVG_PODF] = imx_clk_divider("gpu2d_ovg_podf", "gpu2d_ovg_sel", base + 0x18, 26, 3); + clks[IMX6SL_CLK_GPU2D_PODF] = imx_clk_divider("gpu2d_podf", "gpu2d_sel", base + 0x18, 29, 3); + clks[IMX6SL_CLK_LCDIF_PIX_PRED] = imx_clk_divider("lcdif_pix_pred", "lcdif_pix_sel", base + 0x38, 3, 3); + clks[IMX6SL_CLK_EPDC_PIX_PRED] = imx_clk_divider("epdc_pix_pred", "epdc_pix_sel", base + 0x38, 12, 3); + clks[IMX6SL_CLK_LCDIF_PIX_PODF] = imx_clk_divider("lcdif_pix_podf", "lcdif_pix_pred", base + 0x1c, 20, 3); + clks[IMX6SL_CLK_EPDC_PIX_PODF] = imx_clk_divider("epdc_pix_podf", "epdc_pix_pred", base + 0x18, 23, 3); + clks[IMX6SL_CLK_SPDIF0_PRED] = imx_clk_divider("spdif0_pred", "spdif0_sel", base + 0x30, 25, 3); + clks[IMX6SL_CLK_SPDIF0_PODF] = imx_clk_divider("spdif0_podf", "spdif0_pred", base + 0x30, 22, 3); + clks[IMX6SL_CLK_SPDIF1_PRED] = imx_clk_divider("spdif1_pred", "spdif1_sel", base + 0x30, 12, 3); + clks[IMX6SL_CLK_SPDIF1_PODF] = imx_clk_divider("spdif1_podf", "spdif1_pred", base + 0x30, 9, 3); + clks[IMX6SL_CLK_EXTERN_AUDIO_PRED] = imx_clk_divider("extern_audio_pred", "extern_audio_sel", base + 0x28, 9, 3); + clks[IMX6SL_CLK_EXTERN_AUDIO_PODF] = imx_clk_divider("extern_audio_podf", "extern_audio_pred", base + 0x28, 25, 3); + clks[IMX6SL_CLK_ECSPI_ROOT] = imx_clk_divider("ecspi_root", "ecspi_sel", base + 0x38, 19, 6); + clks[IMX6SL_CLK_UART_ROOT] = imx_clk_divider("uart_root", "uart_sel", base + 0x24, 0, 6); + + /* name parent_name reg shift width busy: reg, shift */ + clks[IMX6SL_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1); + clks[IMX6SL_CLK_MMDC_ROOT] = imx_clk_busy_divider("mmdc", "periph2", base + 0x14, 3, 3, base + 0x48, 2); + clks[IMX6SL_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16); + + /* name parent_name reg shift */ + clks[IMX6SL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0); + clks[IMX6SL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2); + clks[IMX6SL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4); + clks[IMX6SL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6); + clks[IMX6SL_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12); + clks[IMX6SL_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14); + clks[IMX6SL_CLK_EXTERN_AUDIO] = imx_clk_gate2("extern_audio", "extern_audio_podf", base + 0x6c, 16); + clks[IMX6SL_CLK_GPT] = imx_clk_gate2("gpt", "perclk", base + 0x6c, 20); + clks[IMX6SL_CLK_GPT_SERIAL] = imx_clk_gate2("gpt_serial", "perclk", base + 0x6c, 22); + clks[IMX6SL_CLK_GPU2D_OVG] = imx_clk_gate2("gpu2d_ovg", "gpu2d_ovg_podf", base + 0x6c, 26); + clks[IMX6SL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6); + clks[IMX6SL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8); + clks[IMX6SL_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10); + clks[IMX6SL_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12); + clks[IMX6SL_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x74, 0); + clks[IMX6SL_CLK_PXP_AXI] = imx_clk_gate2("pxp_axi", "pxp_axi_podf", base + 0x74, 2); + clks[IMX6SL_CLK_EPDC_AXI] = imx_clk_gate2("epdc_axi", "epdc_axi_podf", base + 0x74, 4); + clks[IMX6SL_CLK_LCDIF_AXI] = imx_clk_gate2("lcdif_axi", "lcdif_axi_podf", base + 0x74, 6); + clks[IMX6SL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_pix_podf", base + 0x74, 8); + clks[IMX6SL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_pix_podf", base + 0x74, 10); + clks[IMX6SL_CLK_OCRAM] = imx_clk_gate2("ocram", "ocram_podf", base + 0x74, 28); + clks[IMX6SL_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16); + clks[IMX6SL_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18); + clks[IMX6SL_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20); + clks[IMX6SL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22); + clks[IMX6SL_CLK_SDMA] = imx_clk_gate2("sdma", "ipg", base + 0x7c, 6); + clks[IMX6SL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif0_podf", base + 0x7c, 14); + clks[IMX6SL_CLK_SSI1] = imx_clk_gate2("ssi1", "ssi1_podf", base + 0x7c, 18); + clks[IMX6SL_CLK_SSI2] = imx_clk_gate2("ssi2", "ssi2_podf", base + 0x7c, 20); + clks[IMX6SL_CLK_SSI3] = imx_clk_gate2("ssi3", "ssi3_podf", base + 0x7c, 22); + clks[IMX6SL_CLK_UART] = imx_clk_gate2("uart", "ipg", base + 0x7c, 24); + clks[IMX6SL_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_root", base + 0x7c, 26); + clks[IMX6SL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); + clks[IMX6SL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2); + clks[IMX6SL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); + clks[IMX6SL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); + clks[IMX6SL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); + + for (i = 0; i < ARRAY_SIZE(clks); i++) + if (IS_ERR(clks[i])) + pr_err("i.MX6SL clk %d: register failed with %ld\n", + i, PTR_ERR(clks[i])); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0"); + clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0"); + + if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { + clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]); + clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]); + } + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt"); + base = of_iomap(np, 0); + WARN_ON(!base); + irq = irq_of_parse_and_map(np, 0); + mxc_timer_init(base, irq); +} +CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init); diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index d09bc3df9a7..a9fad5f8d34 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -296,13 +296,6 @@ static const struct clk_ops clk_pllv3_enet_ops = { .recalc_rate = clk_pllv3_enet_recalc_rate, }; -static const struct clk_ops clk_pllv3_mlb_ops = { - .prepare = clk_pllv3_prepare, - .unprepare = clk_pllv3_unprepare, - .enable = clk_pllv3_enable, - .disable = clk_pllv3_disable, -}; - struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, const char *parent_name, void __iomem *base, u32 div_mask) @@ -330,9 +323,6 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, case IMX_PLLV3_ENET: ops = &clk_pllv3_enet_ops; break; - case IMX_PLLV3_MLB: - ops = &clk_pllv3_mlb_ops; - break; default: ops = &clk_pllv3_ops; } diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c new file mode 100644 index 00000000000..d617c0b7c80 --- /dev/null +++ b/arch/arm/mach-imx/clk-vf610.c @@ -0,0 +1,319 @@ +/* + * Copyright 2012-2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/of_address.h> +#include <linux/clk.h> +#include <dt-bindings/clock/vf610-clock.h> + +#include "clk.h" + +#define CCM_CCR (ccm_base + 0x00) +#define CCM_CSR (ccm_base + 0x04) +#define CCM_CCSR (ccm_base + 0x08) +#define CCM_CACRR (ccm_base + 0x0c) +#define CCM_CSCMR1 (ccm_base + 0x10) +#define CCM_CSCDR1 (ccm_base + 0x14) +#define CCM_CSCDR2 (ccm_base + 0x18) +#define CCM_CSCDR3 (ccm_base + 0x1c) +#define CCM_CSCMR2 (ccm_base + 0x20) +#define CCM_CSCDR4 (ccm_base + 0x24) +#define CCM_CLPCR (ccm_base + 0x2c) +#define CCM_CISR (ccm_base + 0x30) +#define CCM_CIMR (ccm_base + 0x34) +#define CCM_CGPR (ccm_base + 0x3c) +#define CCM_CCGR0 (ccm_base + 0x40) +#define CCM_CCGR1 (ccm_base + 0x44) +#define CCM_CCGR2 (ccm_base + 0x48) +#define CCM_CCGR3 (ccm_base + 0x4c) +#define CCM_CCGR4 (ccm_base + 0x50) +#define CCM_CCGR5 (ccm_base + 0x54) +#define CCM_CCGR6 (ccm_base + 0x58) +#define CCM_CCGR7 (ccm_base + 0x5c) +#define CCM_CCGR8 (ccm_base + 0x60) +#define CCM_CCGR9 (ccm_base + 0x64) +#define CCM_CCGR10 (ccm_base + 0x68) +#define CCM_CCGR11 (ccm_base + 0x6c) +#define CCM_CMEOR0 (ccm_base + 0x70) +#define CCM_CMEOR1 (ccm_base + 0x74) +#define CCM_CMEOR2 (ccm_base + 0x78) +#define CCM_CMEOR3 (ccm_base + 0x7c) +#define CCM_CMEOR4 (ccm_base + 0x80) +#define CCM_CMEOR5 (ccm_base + 0x84) +#define CCM_CPPDSR (ccm_base + 0x88) +#define CCM_CCOWR (ccm_base + 0x8c) +#define CCM_CCPGR0 (ccm_base + 0x90) +#define CCM_CCPGR1 (ccm_base + 0x94) +#define CCM_CCPGR2 (ccm_base + 0x98) +#define CCM_CCPGR3 (ccm_base + 0x9c) + +#define CCM_CCGRx_CGn(n) ((n) * 2) + +#define PFD_PLL1_BASE (anatop_base + 0x2b0) +#define PFD_PLL2_BASE (anatop_base + 0x100) +#define PFD_PLL3_BASE (anatop_base + 0xf0) + +static void __iomem *anatop_base; +static void __iomem *ccm_base; + +/* sources for multiplexer clocks, this is used multiple times */ +static const char const *fast_sels[] = { "firc", "fxosc", }; +static const char const *slow_sels[] = { "sirc_32k", "sxosc", }; +static const char const *pll1_sels[] = { "pll1_main", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", }; +static const char const *pll2_sels[] = { "pll2_main", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", }; +static const char const *sys_sels[] = { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_main", "pll1_pfd_sel", "pll3_main", }; +static const char const *ddr_sels[] = { "pll2_pfd2", "sys_sel", }; +static const char const *rmii_sels[] = { "enet_ext", "audio_ext", "enet_50m", "enet_25m", }; +static const char const *enet_ts_sels[] = { "enet_ext", "fxosc", "audio_ext", "usb", "enet_ts", "enet_25m", "enet_50m", }; +static const char const *esai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", }; +static const char const *sai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", }; +static const char const *nfc_sels[] = { "platform_bus", "pll1_pfd1", "pll3_pfd1", "pll3_pfd3", }; +static const char const *qspi_sels[] = { "pll3_main", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", }; +static const char const *esdhc_sels[] = { "pll3_main", "pll3_pfd3", "pll1_pfd3", "platform_bus", }; +static const char const *dcu_sels[] = { "pll1_pfd2", "pll3_main", }; +static const char const *gpu_sels[] = { "pll2_pfd2", "pll3_pfd2", }; +static const char const *vadc_sels[] = { "pll6_main_div", "pll3_main_div", "pll3_main", }; +/* FTM counter clock source, not module clock */ +static const char const *ftm_ext_sels[] = {"sirc_128k", "sxosc", "fxosc_half", "audio_ext", }; +static const char const *ftm_fix_sels[] = { "sxosc", "ipg_bus", }; + +static struct clk_div_table pll4_main_div_table[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 6 }, + { .val = 3, .div = 8 }, + { .val = 4, .div = 10 }, + { .val = 5, .div = 12 }, + { .val = 6, .div = 14 }, + { .val = 7, .div = 16 }, + { } +}; + +static struct clk *clk[VF610_CLK_END]; +static struct clk_onecell_data clk_data; + +static void __init vf610_clocks_init(struct device_node *ccm_node) +{ + struct device_node *np; + + clk[VF610_CLK_DUMMY] = imx_clk_fixed("dummy", 0); + clk[VF610_CLK_SIRC_128K] = imx_clk_fixed("sirc_128k", 128000); + clk[VF610_CLK_SIRC_32K] = imx_clk_fixed("sirc_32k", 32000); + clk[VF610_CLK_FIRC] = imx_clk_fixed("firc", 24000000); + + clk[VF610_CLK_SXOSC] = imx_obtain_fixed_clock("sxosc", 0); + clk[VF610_CLK_FXOSC] = imx_obtain_fixed_clock("fxosc", 0); + clk[VF610_CLK_AUDIO_EXT] = imx_obtain_fixed_clock("audio_ext", 0); + clk[VF610_CLK_ENET_EXT] = imx_obtain_fixed_clock("enet_ext", 0); + + clk[VF610_CLK_FXOSC_HALF] = imx_clk_fixed_factor("fxosc_half", "fxosc", 1, 2); + + np = of_find_compatible_node(NULL, NULL, "fsl,vf610-anatop"); + anatop_base = of_iomap(np, 0); + BUG_ON(!anatop_base); + + np = ccm_node; + ccm_base = of_iomap(np, 0); + BUG_ON(!ccm_base); + + clk[VF610_CLK_SLOW_CLK_SEL] = imx_clk_mux("slow_clk_sel", CCM_CCSR, 4, 1, slow_sels, ARRAY_SIZE(slow_sels)); + clk[VF610_CLK_FASK_CLK_SEL] = imx_clk_mux("fast_clk_sel", CCM_CCSR, 5, 1, fast_sels, ARRAY_SIZE(fast_sels)); + + clk[VF610_CLK_PLL1_MAIN] = imx_clk_fixed_factor("pll1_main", "fast_clk_sel", 22, 1); + clk[VF610_CLK_PLL1_PFD1] = imx_clk_pfd("pll1_pfd1", "pll1_main", PFD_PLL1_BASE, 0); + clk[VF610_CLK_PLL1_PFD2] = imx_clk_pfd("pll1_pfd2", "pll1_main", PFD_PLL1_BASE, 1); + clk[VF610_CLK_PLL1_PFD3] = imx_clk_pfd("pll1_pfd3", "pll1_main", PFD_PLL1_BASE, 2); + clk[VF610_CLK_PLL1_PFD4] = imx_clk_pfd("pll1_pfd4", "pll1_main", PFD_PLL1_BASE, 3); + + clk[VF610_CLK_PLL2_MAIN] = imx_clk_fixed_factor("pll2_main", "fast_clk_sel", 22, 1); + clk[VF610_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_main", PFD_PLL2_BASE, 0); + clk[VF610_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_main", PFD_PLL2_BASE, 1); + clk[VF610_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3", "pll2_main", PFD_PLL2_BASE, 2); + clk[VF610_CLK_PLL2_PFD4] = imx_clk_pfd("pll2_pfd4", "pll2_main", PFD_PLL2_BASE, 3); + + clk[VF610_CLK_PLL3_MAIN] = imx_clk_fixed_factor("pll3_main", "fast_clk_sel", 20, 1); + clk[VF610_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_main", PFD_PLL3_BASE, 0); + clk[VF610_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_main", PFD_PLL3_BASE, 1); + clk[VF610_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_main", PFD_PLL3_BASE, 2); + clk[VF610_CLK_PLL3_PFD4] = imx_clk_pfd("pll3_pfd4", "pll3_main", PFD_PLL3_BASE, 3); + + clk[VF610_CLK_PLL4_MAIN] = imx_clk_fixed_factor("pll4_main", "fast_clk_sel", 25, 1); + /* Enet pll: fixed 50Mhz */ + clk[VF610_CLK_PLL5_MAIN] = imx_clk_fixed_factor("pll5_main", "fast_clk_sel", 125, 6); + /* pll6: default 960Mhz */ + clk[VF610_CLK_PLL6_MAIN] = imx_clk_fixed_factor("pll6_main", "fast_clk_sel", 40, 1); + clk[VF610_CLK_PLL1_PFD_SEL] = imx_clk_mux("pll1_pfd_sel", CCM_CCSR, 16, 3, pll1_sels, 5); + clk[VF610_CLK_PLL2_PFD_SEL] = imx_clk_mux("pll2_pfd_sel", CCM_CCSR, 19, 3, pll2_sels, 5); + clk[VF610_CLK_SYS_SEL] = imx_clk_mux("sys_sel", CCM_CCSR, 0, 3, sys_sels, ARRAY_SIZE(sys_sels)); + clk[VF610_CLK_DDR_SEL] = imx_clk_mux("ddr_sel", CCM_CCSR, 6, 1, ddr_sels, ARRAY_SIZE(ddr_sels)); + clk[VF610_CLK_SYS_BUS] = imx_clk_divider("sys_bus", "sys_sel", CCM_CACRR, 0, 3); + clk[VF610_CLK_PLATFORM_BUS] = imx_clk_divider("platform_bus", "sys_bus", CCM_CACRR, 3, 3); + clk[VF610_CLK_IPG_BUS] = imx_clk_divider("ipg_bus", "platform_bus", CCM_CACRR, 11, 2); + + clk[VF610_CLK_PLL3_MAIN_DIV] = imx_clk_divider("pll3_main_div", "pll3_main", CCM_CACRR, 20, 1); + clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_main_div", "pll4_main", 0, CCM_CACRR, 6, 3, 0, pll4_main_div_table, &imx_ccm_lock); + clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_main_div", "pll6_main", CCM_CACRR, 21, 1); + + clk[VF610_CLK_USBC0] = imx_clk_gate2("usbc0", "pll3_main", CCM_CCGR1, CCM_CCGRx_CGn(4)); + clk[VF610_CLK_USBC1] = imx_clk_gate2("usbc1", "pll3_main", CCM_CCGR7, CCM_CCGRx_CGn(4)); + + clk[VF610_CLK_QSPI0_SEL] = imx_clk_mux("qspi0_sel", CCM_CSCMR1, 22, 2, qspi_sels, 4); + clk[VF610_CLK_QSPI0_EN] = imx_clk_gate("qspi0_en", "qspi0_sel", CCM_CSCDR3, 4); + clk[VF610_CLK_QSPI0_X4_DIV] = imx_clk_divider("qspi0_x4", "qspi0_en", CCM_CSCDR3, 0, 2); + clk[VF610_CLK_QSPI0_X2_DIV] = imx_clk_divider("qspi0_x2", "qspi0_x4", CCM_CSCDR3, 2, 1); + clk[VF610_CLK_QSPI0_X1_DIV] = imx_clk_divider("qspi0_x1", "qspi0_x2", CCM_CSCDR3, 3, 1); + clk[VF610_CLK_QSPI0] = imx_clk_gate2("qspi0", "qspi0_x1", CCM_CCGR2, CCM_CCGRx_CGn(4)); + + clk[VF610_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel", CCM_CSCMR1, 24, 2, qspi_sels, 4); + clk[VF610_CLK_QSPI1_EN] = imx_clk_gate("qspi1_en", "qspi1_sel", CCM_CSCDR3, 12); + clk[VF610_CLK_QSPI1_X4_DIV] = imx_clk_divider("qspi1_x4", "qspi1_en", CCM_CSCDR3, 8, 2); + clk[VF610_CLK_QSPI1_X2_DIV] = imx_clk_divider("qspi1_x2", "qspi1_x4", CCM_CSCDR3, 10, 1); + clk[VF610_CLK_QSPI1_X1_DIV] = imx_clk_divider("qspi1_x1", "qspi1_x2", CCM_CSCDR3, 11, 1); + clk[VF610_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_x1", CCM_CCGR8, CCM_CCGRx_CGn(4)); + + clk[VF610_CLK_ENET_50M] = imx_clk_fixed_factor("enet_50m", "pll5_main", 1, 10); + clk[VF610_CLK_ENET_25M] = imx_clk_fixed_factor("enet_25m", "pll5_main", 1, 20); + clk[VF610_CLK_ENET_SEL] = imx_clk_mux("enet_sel", CCM_CSCMR2, 4, 2, rmii_sels, 4); + clk[VF610_CLK_ENET_TS_SEL] = imx_clk_mux("enet_ts_sel", CCM_CSCMR2, 0, 3, enet_ts_sels, 7); + clk[VF610_CLK_ENET] = imx_clk_gate("enet", "enet_sel", CCM_CSCDR1, 24); + clk[VF610_CLK_ENET_TS] = imx_clk_gate("enet_ts", "enet_ts_sel", CCM_CSCDR1, 23); + + clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(7)); + + clk[VF610_CLK_UART0] = imx_clk_gate2("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7)); + clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9)); + clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10)); + + clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6)); + clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7)); + + clk[VF610_CLK_DSPI0] = imx_clk_gate2("dspi0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(12)); + clk[VF610_CLK_DSPI1] = imx_clk_gate2("dspi1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(13)); + clk[VF610_CLK_DSPI2] = imx_clk_gate2("dspi2", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(12)); + clk[VF610_CLK_DSPI3] = imx_clk_gate2("dspi3", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(13)); + + clk[VF610_CLK_WDT] = imx_clk_gate2("wdt", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(14)); + + clk[VF610_CLK_ESDHC0_SEL] = imx_clk_mux("esdhc0_sel", CCM_CSCMR1, 16, 2, esdhc_sels, 4); + clk[VF610_CLK_ESDHC0_EN] = imx_clk_gate("esdhc0_en", "esdhc0_sel", CCM_CSCDR2, 28); + clk[VF610_CLK_ESDHC0_DIV] = imx_clk_divider("esdhc0_div", "esdhc0_en", CCM_CSCDR2, 16, 4); + clk[VF610_CLK_ESDHC0] = imx_clk_gate2("eshc0", "esdhc0_div", CCM_CCGR7, CCM_CCGRx_CGn(1)); + + clk[VF610_CLK_ESDHC1_SEL] = imx_clk_mux("esdhc1_sel", CCM_CSCMR1, 18, 2, esdhc_sels, 4); + clk[VF610_CLK_ESDHC1_EN] = imx_clk_gate("esdhc1_en", "esdhc1_sel", CCM_CSCDR2, 29); + clk[VF610_CLK_ESDHC1_DIV] = imx_clk_divider("esdhc1_div", "esdhc1_en", CCM_CSCDR2, 20, 4); + clk[VF610_CLK_ESDHC1] = imx_clk_gate2("eshc1", "esdhc1_div", CCM_CCGR7, CCM_CCGRx_CGn(2)); + + /* + * ftm_ext_clk and ftm_fix_clk are FTM timer counter's + * selectable clock sources, both use a common enable bit + * in CCM_CSCDR1, selecting "dummy" clock as parent of + * "ftm0_ext_fix" make it serve only for enable/disable. + */ + clk[VF610_CLK_FTM0_EXT_SEL] = imx_clk_mux("ftm0_ext_sel", CCM_CSCMR2, 6, 2, ftm_ext_sels, 4); + clk[VF610_CLK_FTM0_FIX_SEL] = imx_clk_mux("ftm0_fix_sel", CCM_CSCMR2, 14, 1, ftm_fix_sels, 2); + clk[VF610_CLK_FTM0_EXT_FIX_EN] = imx_clk_gate("ftm0_ext_fix_en", "dummy", CCM_CSCDR1, 25); + clk[VF610_CLK_FTM1_EXT_SEL] = imx_clk_mux("ftm1_ext_sel", CCM_CSCMR2, 8, 2, ftm_ext_sels, 4); + clk[VF610_CLK_FTM1_FIX_SEL] = imx_clk_mux("ftm1_fix_sel", CCM_CSCMR2, 15, 1, ftm_fix_sels, 2); + clk[VF610_CLK_FTM1_EXT_FIX_EN] = imx_clk_gate("ftm1_ext_fix_en", "dummy", CCM_CSCDR1, 26); + clk[VF610_CLK_FTM2_EXT_SEL] = imx_clk_mux("ftm2_ext_sel", CCM_CSCMR2, 10, 2, ftm_ext_sels, 4); + clk[VF610_CLK_FTM2_FIX_SEL] = imx_clk_mux("ftm2_fix_sel", CCM_CSCMR2, 16, 1, ftm_fix_sels, 2); + clk[VF610_CLK_FTM2_EXT_FIX_EN] = imx_clk_gate("ftm2_ext_fix_en", "dummy", CCM_CSCDR1, 27); + clk[VF610_CLK_FTM3_EXT_SEL] = imx_clk_mux("ftm3_ext_sel", CCM_CSCMR2, 12, 2, ftm_ext_sels, 4); + clk[VF610_CLK_FTM3_FIX_SEL] = imx_clk_mux("ftm3_fix_sel", CCM_CSCMR2, 17, 1, ftm_fix_sels, 2); + clk[VF610_CLK_FTM3_EXT_FIX_EN] = imx_clk_gate("ftm3_ext_fix_en", "dummy", CCM_CSCDR1, 28); + + /* ftm(n)_clk are FTM module operation clock */ + clk[VF610_CLK_FTM0] = imx_clk_gate2("ftm0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_FTM1] = imx_clk_gate2("ftm1", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(9)); + clk[VF610_CLK_FTM2] = imx_clk_gate2("ftm2", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_FTM3] = imx_clk_gate2("ftm3", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(9)); + + clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2); + clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19); + clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3); + clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "dcu0_div", CCM_CCGR3, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2); + clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23); + clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3); + clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8)); + + clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4); + clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30); + clk[VF610_CLK_ESAI_DIV] = imx_clk_divider("esai_div", "esai_en", CCM_CSCDR2, 24, 4); + clk[VF610_CLK_ESAI] = imx_clk_gate2("esai", "esai_div", CCM_CCGR4, CCM_CCGRx_CGn(2)); + + clk[VF610_CLK_SAI0_SEL] = imx_clk_mux("sai0_sel", CCM_CSCMR1, 0, 2, sai_sels, 4); + clk[VF610_CLK_SAI0_EN] = imx_clk_gate("sai0_en", "sai0_sel", CCM_CSCDR1, 16); + clk[VF610_CLK_SAI0_DIV] = imx_clk_divider("sai0_div", "sai0_en", CCM_CSCDR1, 0, 4); + clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "sai0_div", CCM_CCGR0, CCM_CCGRx_CGn(15)); + + clk[VF610_CLK_SAI1_SEL] = imx_clk_mux("sai1_sel", CCM_CSCMR1, 2, 2, sai_sels, 4); + clk[VF610_CLK_SAI1_EN] = imx_clk_gate("sai1_en", "sai1_sel", CCM_CSCDR1, 17); + clk[VF610_CLK_SAI1_DIV] = imx_clk_divider("sai1_div", "sai1_en", CCM_CSCDR1, 4, 4); + clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "sai1_div", CCM_CCGR1, CCM_CCGRx_CGn(0)); + + clk[VF610_CLK_SAI2_SEL] = imx_clk_mux("sai2_sel", CCM_CSCMR1, 4, 2, sai_sels, 4); + clk[VF610_CLK_SAI2_EN] = imx_clk_gate("sai2_en", "sai2_sel", CCM_CSCDR1, 18); + clk[VF610_CLK_SAI2_DIV] = imx_clk_divider("sai2_div", "sai2_en", CCM_CSCDR1, 8, 4); + clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "sai2_div", CCM_CCGR1, CCM_CCGRx_CGn(1)); + + clk[VF610_CLK_SAI3_SEL] = imx_clk_mux("sai3_sel", CCM_CSCMR1, 6, 2, sai_sels, 4); + clk[VF610_CLK_SAI3_EN] = imx_clk_gate("sai3_en", "sai3_sel", CCM_CSCDR1, 19); + clk[VF610_CLK_SAI3_DIV] = imx_clk_divider("sai3_div", "sai3_en", CCM_CSCDR1, 12, 4); + clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "sai3_div", CCM_CCGR1, CCM_CCGRx_CGn(2)); + + clk[VF610_CLK_NFC_SEL] = imx_clk_mux("nfc_sel", CCM_CSCMR1, 12, 2, nfc_sels, 4); + clk[VF610_CLK_NFC_EN] = imx_clk_gate("nfc_en", "nfc_sel", CCM_CSCDR2, 9); + clk[VF610_CLK_NFC_PRE_DIV] = imx_clk_divider("nfc_pre_div", "nfc_en", CCM_CSCDR3, 13, 3); + clk[VF610_CLK_NFC_FRAC_DIV] = imx_clk_divider("nfc_frac_div", "nfc_pre_div", CCM_CSCDR2, 4, 4); + clk[VF610_CLK_NFC] = imx_clk_gate2("nfc", "nfc_frac_div", CCM_CCGR10, CCM_CCGRx_CGn(0)); + + clk[VF610_CLK_GPU_SEL] = imx_clk_mux("gpu_sel", CCM_CSCMR1, 14, 1, gpu_sels, 2); + clk[VF610_CLK_GPU_EN] = imx_clk_gate("gpu_en", "gpu_sel", CCM_CSCDR2, 10); + clk[VF610_CLK_GPU2D] = imx_clk_gate2("gpu", "gpu_en", CCM_CCGR8, CCM_CCGRx_CGn(15)); + + clk[VF610_CLK_VADC_SEL] = imx_clk_mux("vadc_sel", CCM_CSCMR1, 8, 2, vadc_sels, 3); + clk[VF610_CLK_VADC_EN] = imx_clk_gate("vadc_en", "vadc_sel", CCM_CSCDR1, 22); + clk[VF610_CLK_VADC_DIV] = imx_clk_divider("vadc_div", "vadc_en", CCM_CSCDR1, 20, 2); + clk[VF610_CLK_VADC_DIV_HALF] = imx_clk_fixed_factor("vadc_div_half", "vadc_div", 1, 2); + clk[VF610_CLK_VADC] = imx_clk_gate2("vadc", "vadc_div", CCM_CCGR8, CCM_CCGRx_CGn(7)); + + clk[VF610_CLK_ADC0] = imx_clk_gate2("adc0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(11)); + clk[VF610_CLK_ADC1] = imx_clk_gate2("adc1", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(11)); + clk[VF610_CLK_DAC0] = imx_clk_gate2("dac0", "ipg_bus", CCM_CCGR8, CCM_CCGRx_CGn(12)); + clk[VF610_CLK_DAC1] = imx_clk_gate2("dac1", "ipg_bus", CCM_CCGR8, CCM_CCGRx_CGn(13)); + + clk[VF610_CLK_ASRC] = imx_clk_gate2("asrc", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(1)); + + clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(0)); + clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(4)); + + clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]); + clk_set_rate(clk[VF610_CLK_QSPI0_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_SEL]) / 2); + clk_set_rate(clk[VF610_CLK_QSPI0_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X4_DIV]) / 2); + clk_set_rate(clk[VF610_CLK_QSPI0_X1_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X2_DIV]) / 2); + + clk_set_parent(clk[VF610_CLK_QSPI1_SEL], clk[VF610_CLK_PLL1_PFD4]); + clk_set_rate(clk[VF610_CLK_QSPI1_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_SEL]) / 2); + clk_set_rate(clk[VF610_CLK_QSPI1_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_X4_DIV]) / 2); + clk_set_rate(clk[VF610_CLK_QSPI1_X1_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_X2_DIV]) / 2); + + clk_set_parent(clk[VF610_CLK_SAI0_SEL], clk[VF610_CLK_AUDIO_EXT]); + clk_set_parent(clk[VF610_CLK_SAI1_SEL], clk[VF610_CLK_AUDIO_EXT]); + clk_set_parent(clk[VF610_CLK_SAI2_SEL], clk[VF610_CLK_AUDIO_EXT]); + clk_set_parent(clk[VF610_CLK_SAI3_SEL], clk[VF610_CLK_AUDIO_EXT]); + + /* Add the clocks to provider list */ + clk_data.clks = clk; + clk_data.clk_num = ARRAY_SIZE(clk); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); +} +CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init); diff --git a/arch/arm/mach-imx/clk.c b/arch/arm/mach-imx/clk.c index 37e884ed1cd..55bc80a0066 100644 --- a/arch/arm/mach-imx/clk.c +++ b/arch/arm/mach-imx/clk.c @@ -1,4 +1,39 @@ +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/slab.h> #include <linux/spinlock.h> #include "clk.h" DEFINE_SPINLOCK(imx_ccm_lock); + +static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name) +{ + struct of_phandle_args phandle; + struct clk *clk = ERR_PTR(-ENODEV); + char *path; + + path = kasprintf(GFP_KERNEL, "/clocks/%s", name); + if (!path) + return ERR_PTR(-ENOMEM); + + phandle.np = of_find_node_by_path(path); + kfree(path); + + if (phandle.np) { + clk = of_clk_get_from_provider(&phandle); + of_node_put(phandle.np); + } + return clk; +} + +struct clk * __init imx_obtain_fixed_clock( + const char *name, unsigned long rate) +{ + struct clk *clk; + + clk = imx_obtain_fixed_clock_from_dt(name); + if (IS_ERR(clk)) + clk = imx_clk_fixed(name, rate); + return clk; +} diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index d9d9d9c66df..0e4e8bb261b 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -18,7 +18,6 @@ enum imx_pllv3_type { IMX_PLLV3_USB, IMX_PLLV3_AV, IMX_PLLV3_ENET, - IMX_PLLV3_MLB, }; struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, @@ -29,6 +28,9 @@ struct clk *clk_register_gate2(struct device *dev, const char *name, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock); +struct clk * imx_obtain_fixed_clock( + const char *name, unsigned long rate); + static inline struct clk *imx_clk_gate2(const char *name, const char *parent, void __iomem *reg, u8 shift) { diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index c08ae3f99ce..ee78847abf4 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -68,12 +68,12 @@ extern int mx27_clocks_init_dt(void); extern int mx31_clocks_init_dt(void); extern int mx51_clocks_init_dt(void); extern int mx53_clocks_init_dt(void); -extern int mx6q_clocks_init(void); extern struct platform_device *mxc_register_gpio(char *name, int id, resource_size_t iobase, resource_size_t iosize, int irq, int irq_high); extern void mxc_set_cpu_type(unsigned int type); extern void mxc_restart(char, const char *); extern void mxc_arch_reset_init(void __iomem *); +extern void mxc_arch_reset_init_dt(void); extern int mx53_revision(void); extern int imx6q_revision(void); extern int mx53_display_revision(void); diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h index 356131f7b59..a3b0b04b45c 100644 --- a/arch/arm/mach-imx/hardware.h +++ b/arch/arm/mach-imx/hardware.h @@ -20,6 +20,7 @@ #ifndef __ASM_ARCH_MXC_HARDWARE_H__ #define __ASM_ARCH_MXC_HARDWARE_H__ +#include <asm/io.h> #include <asm/sizes.h> #define addr_in_module(addr, mod) \ diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c index 82348391582..3e1ec5ffe63 100644 --- a/arch/arm/mach-imx/imx25-dt.c +++ b/arch/arm/mach-imx/imx25-dt.c @@ -19,6 +19,8 @@ static void __init imx25_dt_init(void) { + mxc_arch_reset_init_dt(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index 4aaead0a77f..4e235ecb402 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -22,6 +22,8 @@ static void __init imx27_dt_init(void) { struct platform_device_info devinfo = { .name = "cpufreq-cpu0", }; + mxc_arch_reset_init_dt(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); platform_device_register_full(&devinfo); diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c index 67de611e29a..818a1cc2fe4 100644 --- a/arch/arm/mach-imx/imx31-dt.c +++ b/arch/arm/mach-imx/imx31-dt.c @@ -20,6 +20,8 @@ static void __init imx31_dt_init(void) { + mxc_arch_reset_init_dt(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c index ab24cc32211..53e43e579dd 100644 --- a/arch/arm/mach-imx/imx51-dt.c +++ b/arch/arm/mach-imx/imx51-dt.c @@ -23,6 +23,8 @@ static void __init imx51_dt_init(void) { struct platform_device_info devinfo = { .name = "cpufreq-cpu0", }; + mxc_arch_reset_init_dt(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); platform_device_register_full(&devinfo); } diff --git a/arch/arm/mach-imx/irq-common.c b/arch/arm/mach-imx/irq-common.c index 4b34f52dc46..0a920d18486 100644 --- a/arch/arm/mach-imx/irq-common.c +++ b/arch/arm/mach-imx/irq-common.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/irq.h> +#include <linux/platform_data/asoc-imx-ssi.h> #include "irq-common.h" diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c index f579c616fee..74e7b94c22e 100644 --- a/arch/arm/mach-imx/mach-imx53.c +++ b/arch/arm/mach-imx/mach-imx53.c @@ -21,6 +21,7 @@ #include <asm/mach/time.h> #include "common.h" +#include "hardware.h" #include "mx53.h" static void __init imx53_qsb_init(void) @@ -38,6 +39,8 @@ static void __init imx53_qsb_init(void) static void __init imx53_dt_init(void) { + mxc_arch_reset_init_dt(); + if (of_machine_is_compatible("fsl,imx53-qsb")) imx53_qsb_init(); diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 5536fd81379..f5965220a4d 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -11,6 +11,7 @@ */ #include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/clocksource.h> #include <linux/cpu.h> @@ -145,6 +146,45 @@ static void __init imx6q_sabrelite_init(void) imx6q_sabrelite_cko1_setup(); } +static void __init imx6q_sabresd_cko1_setup(void) +{ + struct clk *cko1_sel, *pll4, *pll4_post, *cko1; + unsigned long rate; + + cko1_sel = clk_get_sys(NULL, "cko1_sel"); + pll4 = clk_get_sys(NULL, "pll4_audio"); + pll4_post = clk_get_sys(NULL, "pll4_post_div"); + cko1 = clk_get_sys(NULL, "cko1"); + if (IS_ERR(cko1_sel) || IS_ERR(pll4) + || IS_ERR(pll4_post) || IS_ERR(cko1)) { + pr_err("cko1 setup failed!\n"); + goto put_clk; + } + /* + * Setting pll4 at 768MHz (24MHz * 32) + * So its child clock can get 24MHz easily + */ + clk_set_rate(pll4, 768000000); + + clk_set_parent(cko1_sel, pll4_post); + rate = clk_round_rate(cko1, 24000000); + clk_set_rate(cko1, rate); +put_clk: + if (!IS_ERR(cko1_sel)) + clk_put(cko1_sel); + if (!IS_ERR(pll4_post)) + clk_put(pll4_post); + if (!IS_ERR(pll4)) + clk_put(pll4); + if (!IS_ERR(cko1)) + clk_put(cko1); +} + +static void __init imx6q_sabresd_init(void) +{ + imx6q_sabresd_cko1_setup(); +} + static void __init imx6q_1588_init(void) { struct regmap *gpr; @@ -165,6 +205,9 @@ static void __init imx6q_init_machine(void) { if (of_machine_is_compatible("fsl,imx6q-sabrelite")) imx6q_sabrelite_init(); + else if (of_machine_is_compatible("fsl,imx6q-sabresd") || + of_machine_is_compatible("fsl,imx6dl-sabresd")) + imx6q_sabresd_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); @@ -253,10 +296,44 @@ static void __init imx6q_map_io(void) imx_scu_map_io(); } +#ifdef CONFIG_CACHE_L2X0 +static void __init imx6q_init_l2cache(void) +{ + void __iomem *l2x0_base; + struct device_node *np; + unsigned int val; + + np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache"); + if (!np) + goto out; + + l2x0_base = of_iomap(np, 0); + if (!l2x0_base) { + of_node_put(np); + goto out; + } + + /* Configure the L2 PREFETCH and POWER registers */ + val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); + val |= 0x70800000; + writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL); + val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN; + writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL); + + iounmap(l2x0_base); + of_node_put(np); + +out: + l2x0_of_init(0, ~0UL); +} +#else +static inline void imx6q_init_l2cache(void) {} +#endif + static void __init imx6q_init_irq(void) { imx6q_init_revision(); - l2x0_of_init(0, ~0UL); + imx6q_init_l2cache(); imx_src_init(); imx_gpc_init(); irqchip_init(); @@ -264,7 +341,7 @@ static void __init imx6q_init_irq(void) static void __init imx6q_timer_init(void) { - mx6q_clocks_init(); + of_clk_init(NULL); clocksource_of_init(); imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q", imx6q_revision()); diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c new file mode 100644 index 00000000000..132db260950 --- /dev/null +++ b/arch/arm/mach-imx/mach-imx6sl.c @@ -0,0 +1,52 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/clk-provider.h> +#include <linux/irqchip.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <asm/hardware/cache-l2x0.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include "common.h" + +static void __init imx6sl_init_machine(void) +{ + mxc_arch_reset_init_dt(); + + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static void __init imx6sl_init_irq(void) +{ + l2x0_of_init(0, ~0UL); + imx_src_init(); + imx_gpc_init(); + irqchip_init(); +} + +static void __init imx6sl_timer_init(void) +{ + of_clk_init(NULL); +} + +static const char *imx6sl_dt_compat[] __initdata = { + "fsl,imx6sl", + NULL, +}; + +DT_MACHINE_START(IMX6SL, "Freescale i.MX6 SoloLite (Device Tree)") + .map_io = debug_ll_io_init, + .init_irq = imx6sl_init_irq, + .init_time = imx6sl_timer_init, + .init_machine = imx6sl_init_machine, + .dt_compat = imx6sl_dt_compat, + .restart = mxc_restart, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index b8b15bb1ffd..19bb6441a7d 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -398,8 +398,8 @@ static void __init pca100_init(void) imx27_add_fsl_usb2_udc(&otg_device_pdata); } - usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops, - ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); + usbh2_pdata.otg = imx_otg_ulpi_create( + ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); if (usbh2_pdata.otg) imx27_add_mxc_ehci_hs(2, &usbh2_pdata); diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c new file mode 100644 index 00000000000..816991deb9b --- /dev/null +++ b/arch/arm/mach-imx/mach-vf610.c @@ -0,0 +1,48 @@ +/* + * Copyright 2012-2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/of_platform.h> +#include <linux/clocksource.h> +#include <linux/irqchip.h> +#include <linux/clk-provider.h> +#include <asm/mach/arch.h> +#include <asm/hardware/cache-l2x0.h> + +#include "common.h" + +static void __init vf610_init_machine(void) +{ + mxc_arch_reset_init_dt(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static void __init vf610_init_irq(void) +{ + l2x0_of_init(0, ~0UL); + irqchip_init(); +} + +static void __init vf610_init_time(void) +{ + of_clk_init(NULL); + clocksource_of_init(); +} + +static const char *vf610_dt_compat[] __initdata = { + "fsl,vf610", + NULL, +}; + +DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") + .init_irq = vf610_init_irq, + .init_time = vf610_init_time, + .init_machine = vf610_init_machine, + .dt_compat = vf610_dt_compat, + .restart = mxc_restart, +MACHINE_END diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c index 3c609c52d3e..e065fedb3ad 100644 --- a/arch/arm/mach-imx/mm-imx1.c +++ b/arch/arm/mach-imx/mm-imx1.c @@ -39,7 +39,6 @@ void __init mx1_map_io(void) void __init imx1_init_early(void) { mxc_set_cpu_type(MXC_CPU_MX1); - mxc_arch_reset_init(MX1_IO_ADDRESS(MX1_WDT_BASE_ADDR)); imx_iomuxv1_init(MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR), MX1_NUM_GPIO_PORT); } @@ -51,6 +50,7 @@ void __init mx1_init_irq(void) void __init imx1_soc_init(void) { + mxc_arch_reset_init(MX1_IO_ADDRESS(MX1_WDT_BASE_ADDR)); mxc_device_init(); mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256, diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c index d8ccd3a8ec5..2e91ab2ca37 100644 --- a/arch/arm/mach-imx/mm-imx21.c +++ b/arch/arm/mach-imx/mm-imx21.c @@ -66,7 +66,6 @@ void __init mx21_map_io(void) void __init imx21_init_early(void) { mxc_set_cpu_type(MXC_CPU_MX21); - mxc_arch_reset_init(MX21_IO_ADDRESS(MX21_WDOG_BASE_ADDR)); imx_iomuxv1_init(MX21_IO_ADDRESS(MX21_GPIO_BASE_ADDR), MX21_NUM_GPIO_PORT); } @@ -82,6 +81,7 @@ static const struct resource imx21_audmux_res[] __initconst = { void __init imx21_soc_init(void) { + mxc_arch_reset_init(MX21_IO_ADDRESS(MX21_WDOG_BASE_ADDR)); mxc_device_init(); mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0); diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c index 9357707bb7a..e065c117f5a 100644 --- a/arch/arm/mach-imx/mm-imx25.c +++ b/arch/arm/mach-imx/mm-imx25.c @@ -54,7 +54,6 @@ void __init imx25_init_early(void) { mxc_set_cpu_type(MXC_CPU_MX25); mxc_iomux_v3_init(MX25_IO_ADDRESS(MX25_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR)); } void __init mx25_init_irq(void) @@ -89,6 +88,7 @@ static const struct resource imx25_audmux_res[] __initconst = { void __init imx25_soc_init(void) { + mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR)); mxc_device_init(); /* i.mx25 has the i.mx35 type gpio */ diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c index 4f1be65a7b5..7d82a5a5b16 100644 --- a/arch/arm/mach-imx/mm-imx27.c +++ b/arch/arm/mach-imx/mm-imx27.c @@ -66,7 +66,6 @@ void __init mx27_map_io(void) void __init imx27_init_early(void) { mxc_set_cpu_type(MXC_CPU_MX27); - mxc_arch_reset_init(MX27_IO_ADDRESS(MX27_WDOG_BASE_ADDR)); imx_iomuxv1_init(MX27_IO_ADDRESS(MX27_GPIO_BASE_ADDR), MX27_NUM_GPIO_PORT); } @@ -82,6 +81,7 @@ static const struct resource imx27_audmux_res[] __initconst = { void __init imx27_soc_init(void) { + mxc_arch_reset_init(MX27_IO_ADDRESS(MX27_WDOG_BASE_ADDR)); mxc_device_init(); /* i.mx27 has the i.mx21 type gpio */ diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c index e0e69a68217..8f0f60697f5 100644 --- a/arch/arm/mach-imx/mm-imx3.c +++ b/arch/arm/mach-imx/mm-imx3.c @@ -138,7 +138,6 @@ void __init mx31_map_io(void) void __init imx31_init_early(void) { mxc_set_cpu_type(MXC_CPU_MX31); - mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR)); arch_ioremap_caller = imx3_ioremap_caller; arm_pm_idle = imx3_idle; mx3_ccm_base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR); @@ -174,6 +173,7 @@ void __init imx31_soc_init(void) imx3_init_l2x0(); + mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR)); mxc_device_init(); mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0); @@ -216,7 +216,6 @@ void __init imx35_init_early(void) { mxc_set_cpu_type(MXC_CPU_MX35); mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR)); arm_pm_idle = imx3_idle; arch_ioremap_caller = imx3_ioremap_caller; mx3_ccm_base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR); @@ -272,6 +271,7 @@ void __init imx35_soc_init(void) imx3_init_l2x0(); + mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR)); mxc_device_init(); mxc_register_gpio("imx35-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0); diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c index b7c4e70e508..cf193d87274 100644 --- a/arch/arm/mach-imx/mm-imx5.c +++ b/arch/arm/mach-imx/mm-imx5.c @@ -83,7 +83,6 @@ void __init imx51_init_early(void) imx51_ipu_mipi_setup(); mxc_set_cpu_type(MXC_CPU_MX51); mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR)); imx_src_init(); } @@ -91,7 +90,6 @@ void __init imx53_init_early(void) { mxc_set_cpu_type(MXC_CPU_MX53); mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR)); imx_src_init(); } @@ -129,6 +127,7 @@ static const struct resource imx51_audmux_res[] __initconst = { void __init imx51_soc_init(void) { + mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR)); mxc_device_init(); /* i.mx51 has the i.mx35 type gpio */ diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index 695e0d73bf8..7cdc79a9657 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -21,6 +21,8 @@ #include <linux/io.h> #include <linux/err.h> #include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_address.h> #include <asm/system_misc.h> #include <asm/proc-fns.h> @@ -30,6 +32,7 @@ #include "hardware.h" static void __iomem *wdog_base; +static struct clk *wdog_clk; /* * Reset the system. It is called by machine_restart(). @@ -38,16 +41,13 @@ void mxc_restart(char mode, const char *cmd) { unsigned int wcr_enable; - if (cpu_is_mx1()) { - wcr_enable = (1 << 0); - } else { - struct clk *clk; + if (wdog_clk) + clk_enable(wdog_clk); - clk = clk_get_sys("imx2-wdt.0", NULL); - if (!IS_ERR(clk)) - clk_prepare_enable(clk); + if (cpu_is_mx1()) + wcr_enable = (1 << 0); + else wcr_enable = (1 << 2); - } /* Assert SRS signal */ __raw_writew(wcr_enable, wdog_base); @@ -55,7 +55,7 @@ void mxc_restart(char mode, const char *cmd) /* wait for reset to assert... */ mdelay(500); - printk(KERN_ERR "Watchdog reset failed to assert reset\n"); + pr_err("%s: Watchdog reset failed to assert reset\n", __func__); /* delay to allow the serial port to show the message */ mdelay(50); @@ -64,7 +64,34 @@ void mxc_restart(char mode, const char *cmd) soft_restart(0); } -void mxc_arch_reset_init(void __iomem *base) +void __init mxc_arch_reset_init(void __iomem *base) { wdog_base = base; + + wdog_clk = clk_get_sys("imx2-wdt.0", NULL); + if (IS_ERR(wdog_clk)) { + pr_warn("%s: failed to get wdog clock\n", __func__); + wdog_clk = NULL; + return; + } + + clk_prepare(wdog_clk); +} + +void __init mxc_arch_reset_init_dt(void) +{ + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx21-wdt"); + wdog_base = of_iomap(np, 0); + WARN_ON(!wdog_base); + + wdog_clk = of_clk_get(np, 0); + if (IS_ERR(wdog_clk)) { + pr_warn("%s: failed to get wdog clock\n", __func__); + wdog_clk = NULL; + return; + } + + clk_prepare(wdog_clk); } diff --git a/arch/arm/mach-imx/ulpi.c b/arch/arm/mach-imx/ulpi.c deleted file mode 100644 index 0f051957d10..00000000000 --- a/arch/arm/mach-imx/ulpi.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> - * Copyright 2009 Daniel Mack <daniel@caiaq.de> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <linux/usb/otg.h> -#include <linux/usb/ulpi.h> - -#include "ulpi.h" - -/* ULPIVIEW register bits */ -#define ULPIVW_WU (1 << 31) /* Wakeup */ -#define ULPIVW_RUN (1 << 30) /* read/write run */ -#define ULPIVW_WRITE (1 << 29) /* 0 = read 1 = write */ -#define ULPIVW_SS (1 << 27) /* SyncState */ -#define ULPIVW_PORT_MASK 0x07 /* Port field */ -#define ULPIVW_PORT_SHIFT 24 -#define ULPIVW_ADDR_MASK 0xff /* data address field */ -#define ULPIVW_ADDR_SHIFT 16 -#define ULPIVW_RDATA_MASK 0xff /* read data field */ -#define ULPIVW_RDATA_SHIFT 8 -#define ULPIVW_WDATA_MASK 0xff /* write data field */ -#define ULPIVW_WDATA_SHIFT 0 - -static int ulpi_poll(void __iomem *view, u32 bit) -{ - int timeout = 10000; - - while (timeout--) { - u32 data = __raw_readl(view); - - if (!(data & bit)) - return 0; - - cpu_relax(); - }; - - printk(KERN_WARNING "timeout polling for ULPI device\n"); - - return -ETIMEDOUT; -} - -static int ulpi_read(struct usb_phy *otg, u32 reg) -{ - int ret; - void __iomem *view = otg->io_priv; - - /* make sure interface is running */ - if (!(__raw_readl(view) & ULPIVW_SS)) { - __raw_writel(ULPIVW_WU, view); - - /* wait for wakeup */ - ret = ulpi_poll(view, ULPIVW_WU); - if (ret) - return ret; - } - - /* read the register */ - __raw_writel((ULPIVW_RUN | (reg << ULPIVW_ADDR_SHIFT)), view); - - /* wait for completion */ - ret = ulpi_poll(view, ULPIVW_RUN); - if (ret) - return ret; - - return (__raw_readl(view) >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK; -} - -static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg) -{ - int ret; - void __iomem *view = otg->io_priv; - - /* make sure the interface is running */ - if (!(__raw_readl(view) & ULPIVW_SS)) { - __raw_writel(ULPIVW_WU, view); - /* wait for wakeup */ - ret = ulpi_poll(view, ULPIVW_WU); - if (ret) - return ret; - } - - __raw_writel((ULPIVW_RUN | ULPIVW_WRITE | - (reg << ULPIVW_ADDR_SHIFT) | - ((val & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)), view); - - /* wait for completion */ - return ulpi_poll(view, ULPIVW_RUN); -} - -struct usb_phy_io_ops mxc_ulpi_access_ops = { - .read = ulpi_read, - .write = ulpi_write, -}; -EXPORT_SYMBOL_GPL(mxc_ulpi_access_ops); - -struct usb_phy *imx_otg_ulpi_create(unsigned int flags) -{ - return otg_ulpi_create(&mxc_ulpi_access_ops, flags); -} diff --git a/arch/arm/mach-imx/ulpi.h b/arch/arm/mach-imx/ulpi.h index 42bdaca6d7d..23f5c0349e8 100644 --- a/arch/arm/mach-imx/ulpi.h +++ b/arch/arm/mach-imx/ulpi.h @@ -1,8 +1,13 @@ #ifndef __MACH_ULPI_H #define __MACH_ULPI_H -#ifdef CONFIG_USB_ULPI -struct usb_phy *imx_otg_ulpi_create(unsigned int flags); +#include <linux/usb/ulpi.h> + +#ifdef CONFIG_USB_ULPI_VIEWPORT +static inline struct usb_phy *imx_otg_ulpi_create(unsigned int flags) +{ + return otg_ulpi_create(&ulpi_viewport_access_ops, flags); +} #else static inline struct usb_phy *imx_otg_ulpi_create(unsigned int flags) { @@ -10,7 +15,5 @@ static inline struct usb_phy *imx_otg_ulpi_create(unsigned int flags) } #endif -extern struct usb_phy_io_ops mxc_ulpi_access_ops; - #endif /* __MACH_ULPI_H */ |