diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 13:43:38 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 13:43:38 -0700 |
commit | 3883cbb6c1bda013a3ce2dbdab7dc97c52e4a232 (patch) | |
tree | 5b69f83b049d24ac81123ac954ca8c9128e48443 /arch/arm/mach-imx | |
parent | d2033f2c1d1de2239ded15e478ddb4028f192a15 (diff) | |
parent | 1eb92b24e243085d242cf5ffd64829bba70972e1 (diff) | |
download | linux-rt-3883cbb6c1bda013a3ce2dbdab7dc97c52e4a232.tar.gz |
Merge tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC specific changes from Arnd Bergmann:
"These changes are all to SoC-specific code, a total of 33 branches on
17 platforms were pulled into this. Like last time, Renesas sh-mobile
is now the platform with the most changes, followed by OMAP and
EXYNOS.
Two new platforms, TI Keystone and Rockchips RK3xxx are added in this
branch, both containing almost no platform specific code at all, since
they are using generic subsystem interfaces for clocks, pinctrl,
interrupts etc. The device drivers are getting merged through the
respective subsystem maintainer trees.
One more SoC (u300) is now multiplatform capable and several others
(shmobile, exynos, msm, integrator, kirkwood, clps711x) are moving
towards that goal with this series but need more work.
Also noteworthy is the work on PCI here, which is traditionally part
of the SoC specific code. With the changes done by Thomas Petazzoni,
we can now more easily have PCI host controller drivers as loadable
modules and keep them separate from the platform code in
drivers/pci/host. This has already led to the discovery that three
platforms (exynos, spear and imx) are actually using an identical PCIe
host controller and will be able to share a driver once support for
spear and imx is added."
* tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (480 commits)
ARM: integrator: let pciv3 use mem/premem from device tree
ARM: integrator: set local side PCI addresses right
ARM: dts: Add pcie controller node for exynos5440-ssdk5440
ARM: dts: Add pcie controller node for Samsung EXYNOS5440 SoC
ARM: EXYNOS: Enable PCIe support for Exynos5440
pci: Add PCIe driver for Samsung Exynos
ARM: OMAP5: voltagedomain data: remove temporary OMAP4 voltage data
ARM: keystone: Move CPU bringup code to dedicated asm file
ARM: multiplatform: always pick one CPU type
ARM: imx: select syscon for IMX6SL
ARM: keystone: select ARM_ERRATA_798181 only for SMP
ARM: imx: Synertronixx scb9328 needs to select SOC_IMX1
ARM: OMAP2+: AM43x: resolve SMP related build error
dmaengine: edma: enable build for AM33XX
ARM: edma: Add EDMA crossbar event mux support
ARM: edma: Add DT and runtime PM support to the private EDMA API
dmaengine: edma: Add TI EDMA device tree binding
arm: add basic support for Rockchip RK3066a boards
arm: add debug uarts for rockchip rk29xx and rk3xxx series
arm: Add basic clocks for Rockchip rk3066a SoCs
...
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 ba44328464f3..60661a4b0e24 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 70ae7c490ac0..e20f22d58fd8 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 6fc486b6a3c6..04b1bad68350 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 4e3148ce852d..4282e99f5ca1 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 000000000000..a307ac22dffe --- /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 d09bc3df9a7a..a9fad5f8d340 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 000000000000..d617c0b7c809 --- /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 37e884ed1cd4..55bc80a00666 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 d9d9d9c66dff..0e4e8bb261b9 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 c08ae3f99cee..ee78847abf47 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 356131f7b591..a3b0b04b45c9 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 82348391582a..3e1ec5ffe630 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 4aaead0a77ff..4e235ecb4021 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 67de611e29ab..818a1cc2fe45 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 ab24cc322111..53e43e579dd7 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 4b34f52dc46b..0a920d184867 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 f579c616feed..74e7b94c22e7 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 5536fd81379a..f5965220a4d8 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 000000000000..132db2609507 --- /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 b8b15bb1ffdf..19bb6441a7d4 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 000000000000..816991deb9b8 --- /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 3c609c52d3eb..e065fedb3ad4 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 d8ccd3a8ec53..2e91ab2ca378 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 9357707bb7af..e065c117f5a6 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 4f1be65a7b5f..7d82a5a5b16b 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 e0e69a682174..8f0f60697f55 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 b7c4e70e5081..cf193d87274a 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 695e0d73bf85..7cdc79a9657c 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 0f051957d10c..000000000000 --- 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 42bdaca6d7d9..23f5c0349e80 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 */ |