From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- arch/arm/mach-imx/Kconfig | 850 ++++++++++ arch/arm/mach-imx/Makefile | 96 ++ arch/arm/mach-imx/Makefile.boot | 45 + arch/arm/mach-imx/clock-imx1.c | 636 +++++++ arch/arm/mach-imx/clock-imx21.c | 1239 ++++++++++++++ arch/arm/mach-imx/clock-imx25.c | 346 ++++ arch/arm/mach-imx/clock-imx27.c | 785 +++++++++ arch/arm/mach-imx/clock-imx31.c | 630 +++++++ arch/arm/mach-imx/clock-imx35.c | 536 ++++++ arch/arm/mach-imx/clock-imx6q.c | 2111 ++++++++++++++++++++++++ arch/arm/mach-imx/clock-mx51-mx53.c | 1675 +++++++++++++++++++ arch/arm/mach-imx/cpu-imx25.c | 41 + arch/arm/mach-imx/cpu-imx27.c | 74 + arch/arm/mach-imx/cpu-imx31.c | 62 + arch/arm/mach-imx/cpu-imx35.c | 42 + arch/arm/mach-imx/cpu-imx5.c | 151 ++ arch/arm/mach-imx/cpu_op-mx51.c | 30 + arch/arm/mach-imx/cpu_op-mx51.h | 14 + arch/arm/mach-imx/crm-regs-imx5.h | 600 +++++++ arch/arm/mach-imx/crmregs-imx3.h | 262 +++ arch/arm/mach-imx/devices-imx1.h | 31 + arch/arm/mach-imx/devices-imx21.h | 60 + arch/arm/mach-imx/devices-imx25.h | 90 + arch/arm/mach-imx/devices-imx27.h | 84 + arch/arm/mach-imx/devices-imx31.h | 84 + arch/arm/mach-imx/devices-imx35.h | 87 + arch/arm/mach-imx/devices-imx50.h | 34 + arch/arm/mach-imx/devices-imx51.h | 71 + arch/arm/mach-imx/devices-imx53.h | 48 + arch/arm/mach-imx/efika.h | 10 + arch/arm/mach-imx/ehci-imx25.c | 80 + arch/arm/mach-imx/ehci-imx27.c | 82 + arch/arm/mach-imx/ehci-imx31.c | 82 + arch/arm/mach-imx/ehci-imx35.c | 79 + arch/arm/mach-imx/ehci-imx5.c | 156 ++ arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | 350 ++++ arch/arm/mach-imx/eukrea_mbimx51-baseboard.c | 206 +++ arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c | 145 ++ arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 268 +++ arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 280 ++++ arch/arm/mach-imx/gpc.c | 113 ++ arch/arm/mach-imx/head-v7.S | 106 ++ arch/arm/mach-imx/hotplug.c | 84 + arch/arm/mach-imx/imx27-dt.c | 91 + arch/arm/mach-imx/imx51-dt.c | 120 ++ arch/arm/mach-imx/imx53-dt.c | 130 ++ arch/arm/mach-imx/include/mach/dma-mx1-mx2.h | 10 + arch/arm/mach-imx/iomux-imx31.c | 180 ++ arch/arm/mach-imx/lluart.c | 32 + arch/arm/mach-imx/mach-apf9328.c | 153 ++ arch/arm/mach-imx/mach-armadillo5x0.c | 574 +++++++ arch/arm/mach-imx/mach-bug.c | 69 + arch/arm/mach-imx/mach-cpuimx27.c | 322 ++++ arch/arm/mach-imx/mach-cpuimx35.c | 211 +++ arch/arm/mach-imx/mach-cpuimx51.c | 301 ++++ arch/arm/mach-imx/mach-cpuimx51sd.c | 339 ++++ arch/arm/mach-imx/mach-eukrea_cpuimx25.c | 174 ++ arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 422 +++++ arch/arm/mach-imx/mach-imx27ipcam.c | 82 + arch/arm/mach-imx/mach-imx27lite.c | 88 + arch/arm/mach-imx/mach-imx6q.c | 147 ++ arch/arm/mach-imx/mach-kzm_arm11_01.c | 292 ++++ arch/arm/mach-imx/mach-mx1ads.c | 162 ++ arch/arm/mach-imx/mach-mx21ads.c | 330 ++++ arch/arm/mach-imx/mach-mx25_3ds.c | 274 +++ arch/arm/mach-imx/mach-mx27_3ds.c | 537 ++++++ arch/arm/mach-imx/mach-mx27ads.c | 355 ++++ arch/arm/mach-imx/mach-mx31_3ds.c | 773 +++++++++ arch/arm/mach-imx/mach-mx31ads.c | 575 +++++++ arch/arm/mach-imx/mach-mx31lilly.c | 316 ++++ arch/arm/mach-imx/mach-mx31lite.c | 300 ++++ arch/arm/mach-imx/mach-mx31moboard.c | 605 +++++++ arch/arm/mach-imx/mach-mx35_3ds.c | 444 +++++ arch/arm/mach-imx/mach-mx50_rdp.c | 226 +++ arch/arm/mach-imx/mach-mx51_3ds.c | 179 ++ arch/arm/mach-imx/mach-mx51_babbage.c | 430 +++++ arch/arm/mach-imx/mach-mx51_efikamx.c | 297 ++++ arch/arm/mach-imx/mach-mx51_efikasb.c | 292 ++++ arch/arm/mach-imx/mach-mx53_ard.c | 270 +++ arch/arm/mach-imx/mach-mx53_evk.c | 178 ++ arch/arm/mach-imx/mach-mx53_loco.c | 320 ++++ arch/arm/mach-imx/mach-mx53_smd.c | 167 ++ arch/arm/mach-imx/mach-mxt_td60.c | 278 ++++ arch/arm/mach-imx/mach-pca100.c | 433 +++++ arch/arm/mach-imx/mach-pcm037.c | 708 ++++++++ arch/arm/mach-imx/mach-pcm037_eet.c | 179 ++ arch/arm/mach-imx/mach-pcm038.c | 361 ++++ arch/arm/mach-imx/mach-pcm043.c | 416 +++++ arch/arm/mach-imx/mach-qong.c | 277 ++++ arch/arm/mach-imx/mach-scb9328.c | 148 ++ arch/arm/mach-imx/mach-vpr200.c | 326 ++++ arch/arm/mach-imx/mm-imx1.c | 61 + arch/arm/mach-imx/mm-imx21.c | 94 ++ arch/arm/mach-imx/mm-imx25.c | 103 ++ arch/arm/mach-imx/mm-imx27.c | 96 ++ arch/arm/mach-imx/mm-imx3.c | 286 ++++ arch/arm/mach-imx/mm-imx5.c | 236 +++ arch/arm/mach-imx/mmdc.c | 72 + arch/arm/mach-imx/mx1-camera-fiq-ksym.c | 18 + arch/arm/mach-imx/mx1-camera-fiq.S | 35 + arch/arm/mach-imx/mx31lilly-db.c | 216 +++ arch/arm/mach-imx/mx31lite-db.c | 196 +++ arch/arm/mach-imx/mx31moboard-devboard.c | 248 +++ arch/arm/mach-imx/mx31moboard-marxbot.c | 372 +++++ arch/arm/mach-imx/mx31moboard-smartbot.c | 209 +++ arch/arm/mach-imx/mx51_efika.c | 632 +++++++ arch/arm/mach-imx/pcm037.h | 11 + arch/arm/mach-imx/pcm970-baseboard.c | 231 +++ arch/arm/mach-imx/platsmp.c | 85 + arch/arm/mach-imx/pm-imx27.c | 48 + arch/arm/mach-imx/pm-imx3.c | 37 + arch/arm/mach-imx/pm-imx5.c | 153 ++ arch/arm/mach-imx/pm-imx6q.c | 72 + arch/arm/mach-imx/src.c | 75 + 114 files changed, 30334 insertions(+) create mode 100644 arch/arm/mach-imx/Kconfig create mode 100644 arch/arm/mach-imx/Makefile create mode 100644 arch/arm/mach-imx/Makefile.boot create mode 100644 arch/arm/mach-imx/clock-imx1.c create mode 100644 arch/arm/mach-imx/clock-imx21.c create mode 100644 arch/arm/mach-imx/clock-imx25.c create mode 100644 arch/arm/mach-imx/clock-imx27.c create mode 100644 arch/arm/mach-imx/clock-imx31.c create mode 100644 arch/arm/mach-imx/clock-imx35.c create mode 100644 arch/arm/mach-imx/clock-imx6q.c create mode 100644 arch/arm/mach-imx/clock-mx51-mx53.c create mode 100644 arch/arm/mach-imx/cpu-imx25.c create mode 100644 arch/arm/mach-imx/cpu-imx27.c create mode 100644 arch/arm/mach-imx/cpu-imx31.c create mode 100644 arch/arm/mach-imx/cpu-imx35.c create mode 100644 arch/arm/mach-imx/cpu-imx5.c create mode 100644 arch/arm/mach-imx/cpu_op-mx51.c create mode 100644 arch/arm/mach-imx/cpu_op-mx51.h create mode 100644 arch/arm/mach-imx/crm-regs-imx5.h create mode 100644 arch/arm/mach-imx/crmregs-imx3.h create mode 100644 arch/arm/mach-imx/devices-imx1.h create mode 100644 arch/arm/mach-imx/devices-imx21.h create mode 100644 arch/arm/mach-imx/devices-imx25.h create mode 100644 arch/arm/mach-imx/devices-imx27.h create mode 100644 arch/arm/mach-imx/devices-imx31.h create mode 100644 arch/arm/mach-imx/devices-imx35.h create mode 100644 arch/arm/mach-imx/devices-imx50.h create mode 100644 arch/arm/mach-imx/devices-imx51.h create mode 100644 arch/arm/mach-imx/devices-imx53.h create mode 100644 arch/arm/mach-imx/efika.h create mode 100644 arch/arm/mach-imx/ehci-imx25.c create mode 100644 arch/arm/mach-imx/ehci-imx27.c create mode 100644 arch/arm/mach-imx/ehci-imx31.c create mode 100644 arch/arm/mach-imx/ehci-imx35.c create mode 100644 arch/arm/mach-imx/ehci-imx5.c create mode 100644 arch/arm/mach-imx/eukrea_mbimx27-baseboard.c create mode 100644 arch/arm/mach-imx/eukrea_mbimx51-baseboard.c create mode 100644 arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c create mode 100644 arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c create mode 100644 arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c create mode 100644 arch/arm/mach-imx/gpc.c create mode 100644 arch/arm/mach-imx/head-v7.S create mode 100644 arch/arm/mach-imx/hotplug.c create mode 100644 arch/arm/mach-imx/imx27-dt.c create mode 100644 arch/arm/mach-imx/imx51-dt.c create mode 100644 arch/arm/mach-imx/imx53-dt.c create mode 100644 arch/arm/mach-imx/include/mach/dma-mx1-mx2.h create mode 100644 arch/arm/mach-imx/iomux-imx31.c create mode 100644 arch/arm/mach-imx/lluart.c create mode 100644 arch/arm/mach-imx/mach-apf9328.c create mode 100644 arch/arm/mach-imx/mach-armadillo5x0.c create mode 100644 arch/arm/mach-imx/mach-bug.c create mode 100644 arch/arm/mach-imx/mach-cpuimx27.c create mode 100644 arch/arm/mach-imx/mach-cpuimx35.c create mode 100644 arch/arm/mach-imx/mach-cpuimx51.c create mode 100644 arch/arm/mach-imx/mach-cpuimx51sd.c create mode 100644 arch/arm/mach-imx/mach-eukrea_cpuimx25.c create mode 100644 arch/arm/mach-imx/mach-imx27_visstrim_m10.c create mode 100644 arch/arm/mach-imx/mach-imx27ipcam.c create mode 100644 arch/arm/mach-imx/mach-imx27lite.c create mode 100644 arch/arm/mach-imx/mach-imx6q.c create mode 100644 arch/arm/mach-imx/mach-kzm_arm11_01.c create mode 100644 arch/arm/mach-imx/mach-mx1ads.c create mode 100644 arch/arm/mach-imx/mach-mx21ads.c create mode 100644 arch/arm/mach-imx/mach-mx25_3ds.c create mode 100644 arch/arm/mach-imx/mach-mx27_3ds.c create mode 100644 arch/arm/mach-imx/mach-mx27ads.c create mode 100644 arch/arm/mach-imx/mach-mx31_3ds.c create mode 100644 arch/arm/mach-imx/mach-mx31ads.c create mode 100644 arch/arm/mach-imx/mach-mx31lilly.c create mode 100644 arch/arm/mach-imx/mach-mx31lite.c create mode 100644 arch/arm/mach-imx/mach-mx31moboard.c create mode 100644 arch/arm/mach-imx/mach-mx35_3ds.c create mode 100644 arch/arm/mach-imx/mach-mx50_rdp.c create mode 100644 arch/arm/mach-imx/mach-mx51_3ds.c create mode 100644 arch/arm/mach-imx/mach-mx51_babbage.c create mode 100644 arch/arm/mach-imx/mach-mx51_efikamx.c create mode 100644 arch/arm/mach-imx/mach-mx51_efikasb.c create mode 100644 arch/arm/mach-imx/mach-mx53_ard.c create mode 100644 arch/arm/mach-imx/mach-mx53_evk.c create mode 100644 arch/arm/mach-imx/mach-mx53_loco.c create mode 100644 arch/arm/mach-imx/mach-mx53_smd.c create mode 100644 arch/arm/mach-imx/mach-mxt_td60.c create mode 100644 arch/arm/mach-imx/mach-pca100.c create mode 100644 arch/arm/mach-imx/mach-pcm037.c create mode 100644 arch/arm/mach-imx/mach-pcm037_eet.c create mode 100644 arch/arm/mach-imx/mach-pcm038.c create mode 100644 arch/arm/mach-imx/mach-pcm043.c create mode 100644 arch/arm/mach-imx/mach-qong.c create mode 100644 arch/arm/mach-imx/mach-scb9328.c create mode 100644 arch/arm/mach-imx/mach-vpr200.c create mode 100644 arch/arm/mach-imx/mm-imx1.c create mode 100644 arch/arm/mach-imx/mm-imx21.c create mode 100644 arch/arm/mach-imx/mm-imx25.c create mode 100644 arch/arm/mach-imx/mm-imx27.c create mode 100644 arch/arm/mach-imx/mm-imx3.c create mode 100644 arch/arm/mach-imx/mm-imx5.c create mode 100644 arch/arm/mach-imx/mmdc.c create mode 100644 arch/arm/mach-imx/mx1-camera-fiq-ksym.c create mode 100644 arch/arm/mach-imx/mx1-camera-fiq.S create mode 100644 arch/arm/mach-imx/mx31lilly-db.c create mode 100644 arch/arm/mach-imx/mx31lite-db.c create mode 100644 arch/arm/mach-imx/mx31moboard-devboard.c create mode 100644 arch/arm/mach-imx/mx31moboard-marxbot.c create mode 100644 arch/arm/mach-imx/mx31moboard-smartbot.c create mode 100644 arch/arm/mach-imx/mx51_efika.c create mode 100644 arch/arm/mach-imx/pcm037.h create mode 100644 arch/arm/mach-imx/pcm970-baseboard.c create mode 100644 arch/arm/mach-imx/platsmp.c create mode 100644 arch/arm/mach-imx/pm-imx27.c create mode 100644 arch/arm/mach-imx/pm-imx3.c create mode 100644 arch/arm/mach-imx/pm-imx5.c create mode 100644 arch/arm/mach-imx/pm-imx6q.c create mode 100644 arch/arm/mach-imx/src.c (limited to 'arch/arm/mach-imx') diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig new file mode 100644 index 00000000..7561eca1 --- /dev/null +++ b/arch/arm/mach-imx/Kconfig @@ -0,0 +1,850 @@ +config HAVE_IMX_GPC + bool + +config HAVE_IMX_MMDC + bool + +config HAVE_IMX_SRC + bool + +config ARCH_MX1 + bool + +config MACH_MX21 + bool + +config ARCH_MX25 + bool + +config MACH_MX27 + bool + +config ARCH_MX5 + bool + +config ARCH_MX50 + bool + +config ARCH_MX51 + bool + +config ARCH_MX53 + bool + +config SOC_IMX1 + bool + select ARCH_MX1 + select CPU_ARM920T + select IMX_HAVE_IOMUX_V1 + select MXC_AVIC + +config SOC_IMX21 + bool + select MACH_MX21 + select CPU_ARM926T + select IMX_HAVE_IOMUX_V1 + select MXC_AVIC + +config SOC_IMX25 + bool + select ARCH_MX25 + select CPU_ARM926T + select ARCH_MXC_IOMUX_V3 + select MXC_AVIC + +config SOC_IMX27 + bool + select MACH_MX27 + select CPU_ARM926T + select IMX_HAVE_IOMUX_V1 + select MXC_AVIC + +config SOC_IMX31 + bool + select CPU_V6 + select IMX_HAVE_PLATFORM_MXC_RNGA + select MXC_AVIC + select SMP_ON_UP if SMP + +config SOC_IMX35 + bool + select CPU_V6 + select ARCH_MXC_IOMUX_V3 + select HAVE_EPIT + select MXC_AVIC + select SMP_ON_UP if SMP + +config SOC_IMX5 + select CPU_V7 + select MXC_TZIC + select ARCH_MXC_IOMUX_V3 + select ARCH_HAS_CPUFREQ + select ARCH_MX5 + bool + +config SOC_IMX50 + bool + select SOC_IMX5 + select ARCH_MX50 + +config SOC_IMX51 + bool + select SOC_IMX5 + select ARCH_MX5 + select ARCH_MX51 + +config SOC_IMX53 + bool + select SOC_IMX5 + select ARCH_MX5 + select ARCH_MX53 + +if ARCH_IMX_V4_V5 + +comment "MX1 platforms:" +config MACH_MXLADS + bool + +config ARCH_MX1ADS + bool "MX1ADS platform" + select MACH_MXLADS + select SOC_IMX1 + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + help + Say Y here if you are using Motorola MX1ADS/MXLADS boards + +config MACH_SCB9328 + bool "Synertronixx scb9328" + select IMX_HAVE_PLATFORM_IMX_UART + help + Say Y here if you are using a Synertronixx scb9328 board + +config MACH_APF9328 + bool "APF9328" + select SOC_IMX1 + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + help + Say Yes here if you are using the Armadeus APF9328 development board + +comment "MX21 platforms:" + +config MACH_MX21ADS + bool "MX21ADS platform" + select SOC_IMX21 + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for MX21ADS platform. This includes specific + configurations for the board and its peripherals. + +comment "MX25 platforms:" + +config MACH_MX25_3DS + bool "Support MX25PDK (3DS) Platform" + select SOC_IMX25 + select IMX_HAVE_PLATFORM_FLEXCAN + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMXDI_RTC + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + +config MACH_EUKREA_CPUIMX25SD + bool "Support Eukrea CPUIMX25 Platform" + select SOC_IMX25 + select IMX_HAVE_PLATFORM_FLEXCAN + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMXDI_RTC + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + 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 + +choice + prompt "Baseboard" + depends on MACH_EUKREA_CPUIMX25SD + default MACH_EUKREA_MBIMXSD25_BASEBOARD + +config MACH_EUKREA_MBIMXSD25_BASEBOARD + bool "Eukrea MBIMXSD development board" + select IMX_HAVE_PLATFORM_GPIO_KEYS + select IMX_HAVE_PLATFORM_IMX_SSI + select LEDS_GPIO_REGISTER + help + This adds board specific devices that can be found on Eukrea's + MBIMXSD evaluation board. + +endchoice + +comment "MX27 platforms:" + +config MACH_MX27ADS + bool "MX27ADS platform" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_MXC_W1 + help + Include support for MX27ADS platform. This includes specific + configurations for the board and its peripherals. + +config MACH_PCM038 + bool "Phytec phyCORE-i.MX27 CPU module (pcm038)" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_MXC_W1 + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_ULPI if USB_ULPI + help + Include support for phyCORE-i.MX27 (aka pcm038) platform. This + includes specific configurations for the module and its peripherals. + +choice + prompt "Baseboard" + depends on MACH_PCM038 + default MACH_PCM970_BASEBOARD + +config MACH_PCM970_BASEBOARD + bool "PHYTEC PCM970 development board" + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_MXC_MMC + help + This adds board specific devices that can be found on Phytec's + PCM970 evaluation board. + +endchoice + +config MACH_CPUIMX27 + bool "Eukrea CPUIMX27 module" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_MXC_W1 + select MXC_ULPI if USB_ULPI + help + Include support for Eukrea CPUIMX27 platform. This includes + specific configurations for the module and its peripherals. + +config MACH_EUKREA_CPUIMX27_USESDHC2 + bool "CPUIMX27 integrates SDHC2 module" + depends on MACH_CPUIMX27 + select IMX_HAVE_PLATFORM_MXC_MMC + help + This adds support for the internal SDHC2 used on CPUIMX27 + for wifi or eMMC. + +config MACH_EUKREA_CPUIMX27_USEUART4 + bool "CPUIMX27 integrates UART4 module" + depends on MACH_CPUIMX27 + help + This adds support for the internal UART4 used on CPUIMX27 + for bluetooth. + +choice + prompt "Baseboard" + depends on MACH_CPUIMX27 + default MACH_EUKREA_MBIMX27_BASEBOARD + +config MACH_EUKREA_MBIMX27_BASEBOARD + bool "Eukrea MBIMX27 development board" + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_SPI_IMX + select LEDS_GPIO_REGISTER + help + This adds board specific devices that can be found on Eukrea's + MBIMX27 evaluation board. + +endchoice + +config MACH_MX27_3DS + bool "MX27PDK platform" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MX2_CAMERA + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_DEBUG_BOARD + select MXC_ULPI if USB_ULPI + help + Include support for MX27PDK platform. This includes specific + configurations for the board and its peripherals. + +config MACH_IMX27_VISSTRIM_M10 + bool "Vista Silicon i.MX27 Visstrim_m10" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_GPIO_KEYS + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MX2_CAMERA + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select LEDS_GPIO_REGISTER + help + Include support for Visstrim_m10 platform and its different variants. + This includes specific configurations for the board and its + peripherals. + +config MACH_IMX27LITE + bool "LogicPD MX27 LITEKIT platform" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IMX_SSI + help + Include support for MX27 LITEKIT platform. This includes specific + configurations for the board and its peripherals. + +config MACH_PCA100 + bool "Phytec phyCARD-s (pca100)" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_MXC_W1 + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_ULPI if USB_ULPI + help + Include support for phyCARD-s (aka pca100) platform. This + includes specific configurations for the module and its peripherals. + +config MACH_MXT_TD60 + bool "Maxtrack i-MXT TD60" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_IMX_FB + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for i-MXT (aka td60) platform. This + includes specific configurations for the module and its peripherals. + +config MACH_IMX27IPCAM + bool "IMX27 IPCAM platform" + select SOC_IMX27 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_UART + help + Include support for IMX27 IPCAM platform. This includes specific + configurations for the board and its peripherals. + +config MACH_IMX27_DT + bool "Support i.MX27 platforms from device tree" + select SOC_IMX27 + select USE_OF + help + Include support for Freescale i.MX27 based platforms + using the device tree for discovery + +endif + +if ARCH_IMX_V6_V7 + +comment "MX31 platforms:" + +config MACH_MX31ADS + bool "Support MX31ADS platforms" + select SOC_IMX31 + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_IMX_UART + default y + help + Include support for MX31ADS platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX31ADS_WM1133_EV1 + bool "Support Wolfson Microelectronics 1133-EV1 module" + depends on MACH_MX31ADS + depends on MFD_WM8350_I2C + depends on REGULATOR_WM8350 + select MFD_WM8350_CONFIG_MODE_0 + select MFD_WM8352_CONFIG_MODE_0 + help + Include support for the Wolfson Microelectronics 1133-EV1 PMU + and audio module for the MX31ADS platform. + +config MACH_MX31LILLY + bool "Support MX31 LILLY-1131 platforms (INCO startec)" + select SOC_IMX31 + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IPU_CORE + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_ULPI if USB_ULPI + help + Include support for mx31 based LILLY1131 modules. This includes + specific configurations for the board and its peripherals. + +config MACH_MX31LITE + bool "Support MX31 LITEKIT (LogicPD)" + select SOC_IMX31 + select MXC_ULPI if USB_ULPI + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_MXC_RTC + select IMX_HAVE_PLATFORM_SPI_IMX + select LEDS_GPIO_REGISTER + help + Include support for MX31 LITEKIT platform. This includes specific + configurations for the board and its peripherals. + +config MACH_PCM037 + bool "Support Phytec pcm037 (i.MX31) platforms" + select SOC_IMX31 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IPU_CORE + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_MXC_W1 + select MXC_ULPI if USB_ULPI + help + Include support for Phytec pcm037 platform. This includes + specific configurations for the board and its peripherals. + +config MACH_PCM037_EET + bool "Support pcm037 EET board extensions" + depends on MACH_PCM037 + select IMX_HAVE_PLATFORM_GPIO_KEYS + select IMX_HAVE_PLATFORM_SPI_IMX + help + Add support for PCM037 EET baseboard extensions. If you are using the + OLED display with EET, use "video=mx3fb:CMEL-OLED" kernel + command-line parameter. + +config MACH_MX31_3DS + bool "Support MX31PDK (3DS)" + select SOC_IMX31 + select MXC_DEBUG_BOARD + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IPU_CORE + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_ULPI if USB_ULPI + help + Include support for MX31PDK (3DS) platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX31_3DS_MXC_NAND_USE_BBT + bool "Make the MXC NAND driver use the in flash Bad Block Table" + depends on MACH_MX31_3DS + depends on MTD_NAND_MXC + help + Enable this if you want that the MXC NAND driver uses the in flash + Bad Block Table to know what blocks are bad instead of scanning the + entire flash looking for bad block markers. + +config MACH_MX31MOBOARD + bool "Support mx31moboard platforms (EPFL Mobots group)" + select SOC_IMX31 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IPU_CORE + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_SPI_IMX + select LEDS_GPIO_REGISTER + select MXC_ULPI if USB_ULPI + help + Include support for mx31moboard platform. This includes specific + configurations for the board and its peripherals. + +config MACH_QONG + bool "Support Dave/DENX QongEVB-LITE platform" + select SOC_IMX31 + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IMX2_WDT + help + Include support for Dave/DENX QongEVB-LITE platform. This includes + specific configurations for the board and its peripherals. + +config MACH_ARMADILLO5X0 + bool "Support Atmark Armadillo-500 Development Base Board" + select SOC_IMX31 + select IMX_HAVE_PLATFORM_GPIO_KEYS + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IPU_CORE + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_MMC + select IMX_HAVE_PLATFORM_MXC_NAND + select MXC_ULPI if USB_ULPI + help + Include support for Atmark Armadillo-500 platform. This includes + specific configurations for the board and its peripherals. + +config MACH_KZM_ARM11_01 + bool "Support KZM-ARM11-01(Kyoto Microcomputer)" + select SOC_IMX31 + select IMX_HAVE_PLATFORM_IMX_UART + help + Include support for KZM-ARM11-01. This includes specific + configurations for the board and its peripherals. + +config MACH_BUG + bool "Support Buglabs BUGBase platform" + select SOC_IMX31 + select IMX_HAVE_PLATFORM_IMX_UART + default y + help + Include support for BUGBase 1.3 platform. This includes specific + configurations for the board and its peripherals. + +comment "MX35 platforms:" + +config MACH_PCM043 + bool "Support Phytec pcm043 (i.MX35) platforms" + select SOC_IMX35 + select IMX_HAVE_PLATFORM_FLEXCAN + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IPU_CORE + 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 + help + Include support for Phytec pcm043 platform. This includes + specific configurations for the board and its peripherals. + +config MACH_MX35_3DS + bool "Support MX35PDK platform" + select SOC_IMX35 + select MXC_DEBUG_BOARD + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + help + Include support for MX35PDK platform. This includes specific + configurations for the board and its peripherals. + +config MACH_EUKREA_CPUIMX35SD + bool "Support Eukrea CPUIMX35 Platform" + select SOC_IMX35 + select IMX_HAVE_PLATFORM_FLEXCAN + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + 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 + help + Include support for Eukrea CPUIMX35 platform. This includes + specific configurations for the board and its peripherals. + +choice + prompt "Baseboard" + depends on MACH_EUKREA_CPUIMX35SD + default MACH_EUKREA_MBIMXSD35_BASEBOARD + +config MACH_EUKREA_MBIMXSD35_BASEBOARD + bool "Eukrea MBIMXSD development board" + select IMX_HAVE_PLATFORM_GPIO_KEYS + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_IPU_CORE + select LEDS_GPIO_REGISTER + help + This adds board specific devices that can be found on Eukrea's + MBIMXSD evaluation board. + +endchoice + +config MACH_VPR200 + bool "Support VPR200 platform" + select SOC_IMX35 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_GPIO_KEYS + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IPU_CORE + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + help + Include support for VPR200 platform. This includes specific + configurations for the board and its peripherals. + +comment "i.MX5 platforms:" + +config MACH_MX50_RDP + bool "Support MX50 reference design platform" + depends on BROKEN + select SOC_IMX50 + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + help + Include support for MX50 reference design platform (RDP) board. This + includes specific configurations for the board and its peripherals. + +comment "i.MX51 machines:" + +config MACH_IMX51_DT + bool "Support i.MX51 platforms from device tree" + select SOC_IMX51 + select USE_OF + select MACH_MX51_BABBAGE + help + Include support for Freescale i.MX51 based platforms + using the device tree for discovery + +config MACH_MX51_BABBAGE + bool "Support MX51 BABBAGE platforms" + select SOC_IMX51 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + help + Include support for MX51 Babbage platform, also known as MX51EVK in + u-boot. This includes specific configurations for the board and its + peripherals. + +config MACH_MX51_3DS + bool "Support MX51PDK (3DS)" + select SOC_IMX51 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_DEBUG_BOARD + help + Include support for MX51PDK (3DS) platform. This includes specific + configurations for the board and its peripherals. + +config MACH_EUKREA_CPUIMX51 + bool "Support Eukrea CPUIMX51 module" + select SOC_IMX51 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SPI_IMX + help + Include support for Eukrea CPUIMX51 platform. This includes + specific configurations for the module and its peripherals. + +choice + prompt "Baseboard" + depends on MACH_EUKREA_CPUIMX51 + default MACH_EUKREA_MBIMX51_BASEBOARD + +config MACH_EUKREA_MBIMX51_BASEBOARD + prompt "Eukrea MBIMX51 development board" + bool + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select LEDS_GPIO_REGISTER + help + This adds board specific devices that can be found on Eukrea's + MBIMX51 evaluation board. + +endchoice + +config MACH_EUKREA_CPUIMX51SD + bool "Support Eukrea CPUIMX51SD module" + select SOC_IMX51 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SPI_IMX + help + Include support for Eukrea CPUIMX51SD platform. This includes + specific configurations for the module and its peripherals. + +choice + prompt "Baseboard" + depends on MACH_EUKREA_CPUIMX51SD + default MACH_EUKREA_MBIMXSD51_BASEBOARD + +config MACH_EUKREA_MBIMXSD51_BASEBOARD + prompt "Eukrea MBIMXSD development board" + bool + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select LEDS_GPIO_REGISTER + help + This adds board specific devices that can be found on Eukrea's + MBIMXSD evaluation board. + +endchoice + +config MX51_EFIKA_COMMON + bool + select SOC_IMX51 + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_PATA_IMX + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_ULPI if USB_ULPI + +config MACH_MX51_EFIKAMX + bool "Support MX51 Genesi Efika MX nettop" + select LEDS_GPIO_REGISTER + select MX51_EFIKA_COMMON + help + Include support for Genesi Efika MX nettop. This includes specific + configurations for the board and its peripherals. + +config MACH_MX51_EFIKASB + bool "Support MX51 Genesi Efika Smartbook" + select LEDS_GPIO_REGISTER + select MX51_EFIKA_COMMON + help + Include support for Genesi Efika Smartbook. This includes specific + configurations for the board and its peripherals. + +comment "i.MX53 machines:" + +config MACH_IMX53_DT + bool "Support i.MX53 platforms from device tree" + select SOC_IMX53 + select USE_OF + select MACH_MX53_ARD + select MACH_MX53_EVK + select MACH_MX53_LOCO + select MACH_MX53_SMD + help + Include support for Freescale i.MX53 based platforms + using the device tree for discovery + +config MACH_MX53_EVK + bool "Support MX53 EVK platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + select LEDS_GPIO_REGISTER + help + Include support for MX53 EVK platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX53_SMD + bool "Support MX53 SMD platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + help + Include support for MX53 SMD platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX53_LOCO + bool "Support MX53 LOCO platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_GPIO_KEYS + select LEDS_GPIO_REGISTER + help + Include support for MX53 LOCO platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX53_ARD + bool "Support MX53 ARD platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_GPIO_KEYS + help + Include support for MX53 ARD platform. This includes specific + configurations for the board and its peripherals. + +comment "i.MX6 family:" + +config SOC_IMX6Q + bool "i.MX6 Quad support" + select ARM_CPU_SUSPEND if PM + select ARM_GIC + select CPU_V7 + select HAVE_ARM_SCU + select HAVE_IMX_GPC + select HAVE_IMX_MMDC + select HAVE_IMX_SRC + select HAVE_SMP + select USE_OF + + help + This enables support for Freescale i.MX6 Quad processor. + +endif diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile new file mode 100644 index 00000000..ab939c50 --- /dev/null +++ b/arch/arm/mach-imx/Makefile @@ -0,0 +1,96 @@ +obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o +obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o + +obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o + +obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o +obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o + +obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o +obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-imx3.o + +obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o + +# Support for CMOS sensor interface +obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o + +# i.MX1 based machines +obj-$(CONFIG_ARCH_MX1ADS) += mach-mx1ads.o +obj-$(CONFIG_MACH_SCB9328) += mach-scb9328.o +obj-$(CONFIG_MACH_APF9328) += mach-apf9328.o + +# i.MX21 based machines +obj-$(CONFIG_MACH_MX21ADS) += mach-mx21ads.o + +# i.MX25 based machines +obj-$(CONFIG_MACH_MX25_3DS) += mach-mx25_3ds.o +obj-$(CONFIG_MACH_EUKREA_CPUIMX25SD) += mach-eukrea_cpuimx25.o +obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD) += eukrea_mbimxsd25-baseboard.o + +# i.MX27 based machines +obj-$(CONFIG_MACH_MX27ADS) += mach-mx27ads.o +obj-$(CONFIG_MACH_PCM038) += mach-pcm038.o +obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o +obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o +obj-$(CONFIG_MACH_IMX27LITE) += mach-imx27lite.o +obj-$(CONFIG_MACH_IMX27_VISSTRIM_M10) += mach-imx27_visstrim_m10.o +obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o +obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o +obj-$(CONFIG_MACH_PCA100) += mach-pca100.o +obj-$(CONFIG_MACH_MXT_TD60) += mach-mxt_td60.o +obj-$(CONFIG_MACH_IMX27IPCAM) += mach-imx27ipcam.o +obj-$(CONFIG_MACH_IMX27_DT) += imx27-dt.o + +# i.MX31 based machines +obj-$(CONFIG_MACH_MX31ADS) += mach-mx31ads.o +obj-$(CONFIG_MACH_MX31LILLY) += mach-mx31lilly.o mx31lilly-db.o +obj-$(CONFIG_MACH_MX31LITE) += mach-mx31lite.o mx31lite-db.o +obj-$(CONFIG_MACH_PCM037) += mach-pcm037.o +obj-$(CONFIG_MACH_PCM037_EET) += mach-pcm037_eet.o +obj-$(CONFIG_MACH_MX31_3DS) += mach-mx31_3ds.o +obj-$(CONFIG_MACH_MX31MOBOARD) += mach-mx31moboard.o mx31moboard-devboard.o \ + mx31moboard-marxbot.o mx31moboard-smartbot.o +obj-$(CONFIG_MACH_QONG) += mach-qong.o +obj-$(CONFIG_MACH_ARMADILLO5X0) += mach-armadillo5x0.o +obj-$(CONFIG_MACH_KZM_ARM11_01) += mach-kzm_arm11_01.o +obj-$(CONFIG_MACH_BUG) += mach-bug.o + +# i.MX35 based machines +obj-$(CONFIG_MACH_PCM043) += mach-pcm043.o +obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o +obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o +obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o +obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o + +obj-$(CONFIG_DEBUG_LL) += lluart.o +obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o +obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o +obj-$(CONFIG_HAVE_IMX_SRC) += src.o +obj-$(CONFIG_CPU_V7) += head-v7.o +AFLAGS_head-v7.o :=-Wa,-march=armv7-a +obj-$(CONFIG_SMP) += platsmp.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o + +ifeq ($(CONFIG_PM),y) +obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o +endif + +# i.MX5 based machines +obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o +obj-$(CONFIG_MACH_MX51_3DS) += mach-mx51_3ds.o +obj-$(CONFIG_MACH_MX53_EVK) += mach-mx53_evk.o +obj-$(CONFIG_MACH_MX53_SMD) += mach-mx53_smd.o +obj-$(CONFIG_MACH_MX53_LOCO) += mach-mx53_loco.o +obj-$(CONFIG_MACH_MX53_ARD) += mach-mx53_ard.o +obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += mach-cpuimx51.o +obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o +obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o +obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o +obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o +obj-$(CONFIG_MACH_MX51_EFIKAMX) += mach-mx51_efikamx.o +obj-$(CONFIG_MACH_MX51_EFIKASB) += mach-mx51_efikasb.o +obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o + +obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o +obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot new file mode 100644 index 00000000..3851d8a2 --- /dev/null +++ b/arch/arm/mach-imx/Makefile.boot @@ -0,0 +1,45 @@ +zreladdr-$(CONFIG_SOC_IMX1) += 0x08008000 +params_phys-$(CONFIG_SOC_IMX1) := 0x08000100 +initrd_phys-$(CONFIG_SOC_IMX1) := 0x08800000 + +zreladdr-$(CONFIG_SOC_IMX21) += 0xC0008000 +params_phys-$(CONFIG_SOC_IMX21) := 0xC0000100 +initrd_phys-$(CONFIG_SOC_IMX21) := 0xC0800000 + +zreladdr-$(CONFIG_SOC_IMX25) += 0x80008000 +params_phys-$(CONFIG_SOC_IMX25) := 0x80000100 +initrd_phys-$(CONFIG_SOC_IMX25) := 0x80800000 + +zreladdr-$(CONFIG_SOC_IMX27) += 0xA0008000 +params_phys-$(CONFIG_SOC_IMX27) := 0xA0000100 +initrd_phys-$(CONFIG_SOC_IMX27) := 0xA0800000 + +zreladdr-$(CONFIG_SOC_IMX31) += 0x80008000 +params_phys-$(CONFIG_SOC_IMX31) := 0x80000100 +initrd_phys-$(CONFIG_SOC_IMX31) := 0x80800000 + +zreladdr-$(CONFIG_SOC_IMX35) += 0x80008000 +params_phys-$(CONFIG_SOC_IMX35) := 0x80000100 +initrd_phys-$(CONFIG_SOC_IMX35) := 0x80800000 + +zreladdr-$(CONFIG_SOC_IMX50) += 0x70008000 +params_phys-$(CONFIG_SOC_IMX50) := 0x70000100 +initrd_phys-$(CONFIG_SOC_IMX50) := 0x70800000 + +zreladdr-$(CONFIG_SOC_IMX51) += 0x90008000 +params_phys-$(CONFIG_SOC_IMX51) := 0x90000100 +initrd_phys-$(CONFIG_SOC_IMX51) := 0x90800000 + +zreladdr-$(CONFIG_SOC_IMX53) += 0x70008000 +params_phys-$(CONFIG_SOC_IMX53) := 0x70000100 +initrd_phys-$(CONFIG_SOC_IMX53) := 0x70800000 + +zreladdr-$(CONFIG_SOC_IMX6Q) += 0x10008000 +params_phys-$(CONFIG_SOC_IMX6Q) := 0x10000100 +initrd_phys-$(CONFIG_SOC_IMX6Q) := 0x10800000 + +dtb-$(CONFIG_MACH_IMX51_DT) += imx51-babbage.dtb +dtb-$(CONFIG_MACH_IMX53_DT) += imx53-ard.dtb imx53-evk.dtb \ + imx53-qsb.dtb imx53-smd.dtb +dtb-$(CONFIG_SOC_IMX6Q) += imx6q-arm2.dtb \ + imx6q-sabrelite.dtb diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c new file mode 100644 index 00000000..4aabeb24 --- /dev/null +++ b/arch/arm/mach-imx/clock-imx1.c @@ -0,0 +1,636 @@ +/* + * Copyright (C) 2008 Sascha Hauer , Pengutronix + * + * 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. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define IO_ADDR_CCM(off) (MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off))) + +/* CCM register addresses */ +#define CCM_CSCR IO_ADDR_CCM(0x0) +#define CCM_MPCTL0 IO_ADDR_CCM(0x4) +#define CCM_SPCTL0 IO_ADDR_CCM(0xc) +#define CCM_PCDR IO_ADDR_CCM(0x20) + +#define CCM_CSCR_CLKO_OFFSET 29 +#define CCM_CSCR_CLKO_MASK (0x7 << 29) +#define CCM_CSCR_USB_OFFSET 26 +#define CCM_CSCR_USB_MASK (0x7 << 26) +#define CCM_CSCR_OSC_EN_SHIFT 17 +#define CCM_CSCR_SYSTEM_SEL (1 << 16) +#define CCM_CSCR_BCLK_OFFSET 10 +#define CCM_CSCR_BCLK_MASK (0xf << 10) +#define CCM_CSCR_PRESC (1 << 15) + +#define CCM_PCDR_PCLK3_OFFSET 16 +#define CCM_PCDR_PCLK3_MASK (0x7f << 16) +#define CCM_PCDR_PCLK2_OFFSET 4 +#define CCM_PCDR_PCLK2_MASK (0xf << 4) +#define CCM_PCDR_PCLK1_OFFSET 0 +#define CCM_PCDR_PCLK1_MASK 0xf + +#define IO_ADDR_SCM(off) (MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off))) + +/* SCM register addresses */ +#define SCM_GCCR IO_ADDR_SCM(0xc) + +#define SCM_GCCR_DMA_CLK_EN_OFFSET 3 +#define SCM_GCCR_CSI_CLK_EN_OFFSET 2 +#define SCM_GCCR_MMA_CLK_EN_OFFSET 1 +#define SCM_GCCR_USBD_CLK_EN_OFFSET 0 + +static int _clk_enable(struct clk *clk) +{ + unsigned int reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void _clk_disable(struct clk *clk) +{ + unsigned int reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static int _clk_can_use_parent(const struct clk *clk_arr[], unsigned int size, + struct clk *parent) +{ + int i; + + for (i = 0; i < size; i++) + if (parent == clk_arr[i]) + return i; + + return -EINVAL; +} + +static unsigned long +_clk_simple_round_rate(struct clk *clk, unsigned long rate, unsigned int limit) +{ + int div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > limit) + div = limit; + + return parent_rate / div; +} + +static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->round_rate(clk->parent, rate); +} + +static int _clk_parent_set_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->set_rate(clk->parent, rate); +} + +static unsigned long clk16m_get_rate(struct clk *clk) +{ + return 16000000; +} + +static struct clk clk16m = { + .get_rate = clk16m_get_rate, + .enable = _clk_enable, + .enable_reg = CCM_CSCR, + .enable_shift = CCM_CSCR_OSC_EN_SHIFT, + .disable = _clk_disable, +}; + +/* in Hz */ +static unsigned long clk32_rate; + +static unsigned long clk32_get_rate(struct clk *clk) +{ + return clk32_rate; +} + +static struct clk clk32 = { + .get_rate = clk32_get_rate, +}; + +static unsigned long clk32_premult_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) * 512; +} + +static struct clk clk32_premult = { + .parent = &clk32, + .get_rate = clk32_premult_get_rate, +}; + +static const struct clk *prem_clk_clocks[] = { + &clk32_premult, + &clk16m, +}; + +static int prem_clk_set_parent(struct clk *clk, struct clk *parent) +{ + int i; + unsigned int reg = __raw_readl(CCM_CSCR); + + i = _clk_can_use_parent(prem_clk_clocks, ARRAY_SIZE(prem_clk_clocks), + parent); + + switch (i) { + case 0: + reg &= ~CCM_CSCR_SYSTEM_SEL; + break; + case 1: + reg |= CCM_CSCR_SYSTEM_SEL; + break; + default: + return i; + } + + __raw_writel(reg, CCM_CSCR); + + return 0; +} + +static struct clk prem_clk = { + .set_parent = prem_clk_set_parent, +}; + +static unsigned long system_clk_get_rate(struct clk *clk) +{ + return mxc_decode_pll(__raw_readl(CCM_SPCTL0), + clk_get_rate(clk->parent)); +} + +static struct clk system_clk = { + .parent = &prem_clk, + .get_rate = system_clk_get_rate, +}; + +static unsigned long mcu_clk_get_rate(struct clk *clk) +{ + return mxc_decode_pll(__raw_readl(CCM_MPCTL0), + clk_get_rate(clk->parent)); +} + +static struct clk mcu_clk = { + .parent = &clk32_premult, + .get_rate = mcu_clk_get_rate, +}; + +static unsigned long fclk_get_rate(struct clk *clk) +{ + unsigned long fclk = clk_get_rate(clk->parent); + + if (__raw_readl(CCM_CSCR) & CCM_CSCR_PRESC) + fclk /= 2; + + return fclk; +} + +static struct clk fclk = { + .parent = &mcu_clk, + .get_rate = fclk_get_rate, +}; + +/* + * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA ) + */ +static unsigned long hclk_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) & + CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET) + 1); +} + +static unsigned long hclk_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 16); +} + +static int hclk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 16 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_CSCR); + reg &= ~CCM_CSCR_BCLK_MASK; + reg |= div << CCM_CSCR_BCLK_OFFSET; + __raw_writel(reg, CCM_CSCR); + + return 0; +} + +static struct clk hclk = { + .parent = &system_clk, + .get_rate = hclk_get_rate, + .round_rate = hclk_round_rate, + .set_rate = hclk_set_rate, +}; + +static unsigned long clk48m_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) & + CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET) + 1); +} + +static unsigned long clk48m_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 8); +} + +static int clk48m_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 8 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_CSCR); + reg &= ~CCM_CSCR_USB_MASK; + reg |= div << CCM_CSCR_USB_OFFSET; + __raw_writel(reg, CCM_CSCR); + + return 0; +} + +static struct clk clk48m = { + .parent = &system_clk, + .get_rate = clk48m_get_rate, + .round_rate = clk48m_round_rate, + .set_rate = clk48m_set_rate, +}; + +/* + * get peripheral clock 1 ( UART[12], Timer[12], PWM ) + */ +static unsigned long perclk1_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) & + CCM_PCDR_PCLK1_MASK) >> CCM_PCDR_PCLK1_OFFSET) + 1); +} + +static unsigned long perclk1_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 16); +} + +static int perclk1_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 16 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_PCDR); + reg &= ~CCM_PCDR_PCLK1_MASK; + reg |= div << CCM_PCDR_PCLK1_OFFSET; + __raw_writel(reg, CCM_PCDR); + + return 0; +} + +/* + * get peripheral clock 2 ( LCD, SD, SPI[12] ) + */ +static unsigned long perclk2_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) & + CCM_PCDR_PCLK2_MASK) >> CCM_PCDR_PCLK2_OFFSET) + 1); +} + +static unsigned long perclk2_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 16); +} + +static int perclk2_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 16 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_PCDR); + reg &= ~CCM_PCDR_PCLK2_MASK; + reg |= div << CCM_PCDR_PCLK2_OFFSET; + __raw_writel(reg, CCM_PCDR); + + return 0; +} + +/* + * get peripheral clock 3 ( SSI ) + */ +static unsigned long perclk3_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) & + CCM_PCDR_PCLK3_MASK) >> CCM_PCDR_PCLK3_OFFSET) + 1); +} + +static unsigned long perclk3_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 128); +} + +static int perclk3_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 128 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_PCDR); + reg &= ~CCM_PCDR_PCLK3_MASK; + reg |= div << CCM_PCDR_PCLK3_OFFSET; + __raw_writel(reg, CCM_PCDR); + + return 0; +} + +static struct clk perclk[] = { + { + .id = 0, + .parent = &system_clk, + .get_rate = perclk1_get_rate, + .round_rate = perclk1_round_rate, + .set_rate = perclk1_set_rate, + }, { + .id = 1, + .parent = &system_clk, + .get_rate = perclk2_get_rate, + .round_rate = perclk2_round_rate, + .set_rate = perclk2_set_rate, + }, { + .id = 2, + .parent = &system_clk, + .get_rate = perclk3_get_rate, + .round_rate = perclk3_round_rate, + .set_rate = perclk3_set_rate, + } +}; + +static const struct clk *clko_clocks[] = { + &perclk[0], + &hclk, + &clk48m, + &clk16m, + &prem_clk, + &fclk, +}; + +static int clko_set_parent(struct clk *clk, struct clk *parent) +{ + int i; + unsigned int reg; + + i = _clk_can_use_parent(clko_clocks, ARRAY_SIZE(clko_clocks), parent); + if (i < 0) + return i; + + reg = __raw_readl(CCM_CSCR) & ~CCM_CSCR_CLKO_MASK; + reg |= i << CCM_CSCR_CLKO_OFFSET; + __raw_writel(reg, CCM_CSCR); + + if (clko_clocks[i]->set_rate && clko_clocks[i]->round_rate) { + clk->set_rate = _clk_parent_set_rate; + clk->round_rate = _clk_parent_round_rate; + } else { + clk->set_rate = NULL; + clk->round_rate = NULL; + } + + return 0; +} + +static struct clk clko_clk = { + .set_parent = clko_set_parent, +}; + +static struct clk dma_clk = { + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + .enable = _clk_enable, + .enable_reg = SCM_GCCR, + .enable_shift = SCM_GCCR_DMA_CLK_EN_OFFSET, + .disable = _clk_disable, +}; + +static struct clk csi_clk = { + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + .enable = _clk_enable, + .enable_reg = SCM_GCCR, + .enable_shift = SCM_GCCR_CSI_CLK_EN_OFFSET, + .disable = _clk_disable, +}; + +static struct clk mma_clk = { + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + .enable = _clk_enable, + .enable_reg = SCM_GCCR, + .enable_shift = SCM_GCCR_MMA_CLK_EN_OFFSET, + .disable = _clk_disable, +}; + +static struct clk usbd_clk = { + .parent = &clk48m, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + .enable = _clk_enable, + .enable_reg = SCM_GCCR, + .enable_shift = SCM_GCCR_USBD_CLK_EN_OFFSET, + .disable = _clk_disable, +}; + +static struct clk gpt_clk = { + .parent = &perclk[0], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk uart_clk = { + .parent = &perclk[0], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk i2c_clk = { + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk spi_clk = { + .parent = &perclk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk sdhc_clk = { + .parent = &perclk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk lcdc_clk = { + .parent = &perclk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk mshc_clk = { + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk ssi_clk = { + .parent = &perclk[2], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk rtc_clk = { + .parent = &clk32, +}; + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, +static struct clk_lookup lookups[] __initdata = { + _REGISTER_CLOCK(NULL, "dma", dma_clk) + _REGISTER_CLOCK("mx1-camera.0", NULL, csi_clk) + _REGISTER_CLOCK(NULL, "mma", mma_clk) + _REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk) + _REGISTER_CLOCK(NULL, "gpt", gpt_clk) + _REGISTER_CLOCK("imx1-uart.0", NULL, uart_clk) + _REGISTER_CLOCK("imx1-uart.1", NULL, uart_clk) + _REGISTER_CLOCK("imx1-uart.2", NULL, uart_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk) + _REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk) + _REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk) + _REGISTER_CLOCK("imx-mmc.0", NULL, sdhc_clk) + _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) + _REGISTER_CLOCK(NULL, "mshc", mshc_clk) + _REGISTER_CLOCK(NULL, "ssi", ssi_clk) + _REGISTER_CLOCK("mxc_rtc.0", NULL, rtc_clk) +}; + +int __init mx1_clocks_init(unsigned long fref) +{ + unsigned int reg; + + /* disable clocks we are able to */ + __raw_writel(0, SCM_GCCR); + + clk32_rate = fref; + reg = __raw_readl(CCM_CSCR); + + /* detect clock reference for system PLL */ + if (reg & CCM_CSCR_SYSTEM_SEL) { + prem_clk.parent = &clk16m; + } else { + /* ensure that oscillator is disabled */ + reg &= ~(1 << CCM_CSCR_OSC_EN_SHIFT); + __raw_writel(reg, CCM_CSCR); + prem_clk.parent = &clk32_premult; + } + + /* detect reference for CLKO */ + reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET; + clko_clk.parent = (struct clk *)clko_clocks[reg]; + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + clk_enable(&hclk); + clk_enable(&fclk); + + mxc_timer_init(&gpt_clk, MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), + MX1_TIM1_INT); + + return 0; +} diff --git a/arch/arm/mach-imx/clock-imx21.c b/arch/arm/mach-imx/clock-imx21.c new file mode 100644 index 00000000..ee15d8c9 --- /dev/null +++ b/arch/arm/mach-imx/clock-imx21.c @@ -0,0 +1,1239 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com + * + * 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 +#include +#include +#include + +#include +#include +#include +#include + +#define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off))) + +/* Register offsets */ +#define CCM_CSCR IO_ADDR_CCM(0x0) +#define CCM_MPCTL0 IO_ADDR_CCM(0x4) +#define CCM_MPCTL1 IO_ADDR_CCM(0x8) +#define CCM_SPCTL0 IO_ADDR_CCM(0xc) +#define CCM_SPCTL1 IO_ADDR_CCM(0x10) +#define CCM_OSC26MCTL IO_ADDR_CCM(0x14) +#define CCM_PCDR0 IO_ADDR_CCM(0x18) +#define CCM_PCDR1 IO_ADDR_CCM(0x1c) +#define CCM_PCCR0 IO_ADDR_CCM(0x20) +#define CCM_PCCR1 IO_ADDR_CCM(0x24) +#define CCM_CCSR IO_ADDR_CCM(0x28) +#define CCM_PMCTL IO_ADDR_CCM(0x2c) +#define CCM_PMCOUNT IO_ADDR_CCM(0x30) +#define CCM_WKGDCTL IO_ADDR_CCM(0x34) + +#define CCM_CSCR_PRESC_OFFSET 29 +#define CCM_CSCR_PRESC_MASK (0x7 << CCM_CSCR_PRESC_OFFSET) + +#define CCM_CSCR_USB_OFFSET 26 +#define CCM_CSCR_USB_MASK (0x7 << CCM_CSCR_USB_OFFSET) +#define CCM_CSCR_SD_OFFSET 24 +#define CCM_CSCR_SD_MASK (0x3 << CCM_CSCR_SD_OFFSET) +#define CCM_CSCR_SPLLRES (1 << 22) +#define CCM_CSCR_MPLLRES (1 << 21) +#define CCM_CSCR_SSI2_OFFSET 20 +#define CCM_CSCR_SSI2 (1 << CCM_CSCR_SSI2_OFFSET) +#define CCM_CSCR_SSI1_OFFSET 19 +#define CCM_CSCR_SSI1 (1 << CCM_CSCR_SSI1_OFFSET) +#define CCM_CSCR_FIR_OFFSET 18 +#define CCM_CSCR_FIR (1 << CCM_CSCR_FIR_OFFSET) +#define CCM_CSCR_SP (1 << 17) +#define CCM_CSCR_MCU (1 << 16) +#define CCM_CSCR_BCLK_OFFSET 10 +#define CCM_CSCR_BCLK_MASK (0xf << CCM_CSCR_BCLK_OFFSET) +#define CCM_CSCR_IPDIV_OFFSET 9 +#define CCM_CSCR_IPDIV (1 << CCM_CSCR_IPDIV_OFFSET) + +#define CCM_CSCR_OSC26MDIV (1 << 4) +#define CCM_CSCR_OSC26M (1 << 3) +#define CCM_CSCR_FPM (1 << 2) +#define CCM_CSCR_SPEN (1 << 1) +#define CCM_CSCR_MPEN 1 + +#define CCM_MPCTL0_CPLM (1 << 31) +#define CCM_MPCTL0_PD_OFFSET 26 +#define CCM_MPCTL0_PD_MASK (0xf << 26) +#define CCM_MPCTL0_MFD_OFFSET 16 +#define CCM_MPCTL0_MFD_MASK (0x3ff << 16) +#define CCM_MPCTL0_MFI_OFFSET 10 +#define CCM_MPCTL0_MFI_MASK (0xf << 10) +#define CCM_MPCTL0_MFN_OFFSET 0 +#define CCM_MPCTL0_MFN_MASK 0x3ff + +#define CCM_MPCTL1_LF (1 << 15) +#define CCM_MPCTL1_BRMO (1 << 6) + +#define CCM_SPCTL0_CPLM (1 << 31) +#define CCM_SPCTL0_PD_OFFSET 26 +#define CCM_SPCTL0_PD_MASK (0xf << 26) +#define CCM_SPCTL0_MFD_OFFSET 16 +#define CCM_SPCTL0_MFD_MASK (0x3ff << 16) +#define CCM_SPCTL0_MFI_OFFSET 10 +#define CCM_SPCTL0_MFI_MASK (0xf << 10) +#define CCM_SPCTL0_MFN_OFFSET 0 +#define CCM_SPCTL0_MFN_MASK 0x3ff + +#define CCM_SPCTL1_LF (1 << 15) +#define CCM_SPCTL1_BRMO (1 << 6) + +#define CCM_OSC26MCTL_PEAK_OFFSET 16 +#define CCM_OSC26MCTL_PEAK_MASK (0x3 << 16) +#define CCM_OSC26MCTL_AGC_OFFSET 8 +#define CCM_OSC26MCTL_AGC_MASK (0x3f << 8) +#define CCM_OSC26MCTL_ANATEST_OFFSET 0 +#define CCM_OSC26MCTL_ANATEST_MASK 0x3f + +#define CCM_PCDR0_SSI2BAUDDIV_OFFSET 26 +#define CCM_PCDR0_SSI2BAUDDIV_MASK (0x3f << 26) +#define CCM_PCDR0_SSI1BAUDDIV_OFFSET 16 +#define CCM_PCDR0_SSI1BAUDDIV_MASK (0x3f << 16) +#define CCM_PCDR0_NFCDIV_OFFSET 12 +#define CCM_PCDR0_NFCDIV_MASK (0xf << 12) +#define CCM_PCDR0_48MDIV_OFFSET 5 +#define CCM_PCDR0_48MDIV_MASK (0x7 << CCM_PCDR0_48MDIV_OFFSET) +#define CCM_PCDR0_FIRIDIV_OFFSET 0 +#define CCM_PCDR0_FIRIDIV_MASK 0x1f +#define CCM_PCDR1_PERDIV4_OFFSET 24 +#define CCM_PCDR1_PERDIV4_MASK (0x3f << 24) +#define CCM_PCDR1_PERDIV3_OFFSET 16 +#define CCM_PCDR1_PERDIV3_MASK (0x3f << 16) +#define CCM_PCDR1_PERDIV2_OFFSET 8 +#define CCM_PCDR1_PERDIV2_MASK (0x3f << 8) +#define CCM_PCDR1_PERDIV1_OFFSET 0 +#define CCM_PCDR1_PERDIV1_MASK 0x3f + +#define CCM_PCCR_HCLK_CSI_OFFSET 31 +#define CCM_PCCR_HCLK_CSI_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_DMA_OFFSET 30 +#define CCM_PCCR_HCLK_DMA_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_BROM_OFFSET 28 +#define CCM_PCCR_HCLK_BROM_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_EMMA_OFFSET 27 +#define CCM_PCCR_HCLK_EMMA_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_LCDC_OFFSET 26 +#define CCM_PCCR_HCLK_LCDC_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_SLCDC_OFFSET 25 +#define CCM_PCCR_HCLK_SLCDC_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_USBOTG_OFFSET 24 +#define CCM_PCCR_HCLK_USBOTG_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_BMI_OFFSET 23 +#define CCM_PCCR_BMI_MASK (1 << CCM_PCCR_BMI_MASK) +#define CCM_PCCR_HCLK_BMI_REG CCM_PCCR0 +#define CCM_PCCR_PERCLK4_OFFSET 22 +#define CCM_PCCR_PERCLK4_REG CCM_PCCR0 +#define CCM_PCCR_SLCDC_OFFSET 21 +#define CCM_PCCR_SLCDC_REG CCM_PCCR0 +#define CCM_PCCR_FIRI_BAUD_OFFSET 20 +#define CCM_PCCR_FIRI_BAUD_MASK (1 << CCM_PCCR_FIRI_BAUD_MASK) +#define CCM_PCCR_FIRI_BAUD_REG CCM_PCCR0 +#define CCM_PCCR_NFC_OFFSET 19 +#define CCM_PCCR_NFC_REG CCM_PCCR0 +#define CCM_PCCR_LCDC_OFFSET 18 +#define CCM_PCCR_LCDC_REG CCM_PCCR0 +#define CCM_PCCR_SSI1_BAUD_OFFSET 17 +#define CCM_PCCR_SSI1_BAUD_REG CCM_PCCR0 +#define CCM_PCCR_SSI2_BAUD_OFFSET 16 +#define CCM_PCCR_SSI2_BAUD_REG CCM_PCCR0 +#define CCM_PCCR_EMMA_OFFSET 15 +#define CCM_PCCR_EMMA_REG CCM_PCCR0 +#define CCM_PCCR_USBOTG_OFFSET 14 +#define CCM_PCCR_USBOTG_REG CCM_PCCR0 +#define CCM_PCCR_DMA_OFFSET 13 +#define CCM_PCCR_DMA_REG CCM_PCCR0 +#define CCM_PCCR_I2C1_OFFSET 12 +#define CCM_PCCR_I2C1_REG CCM_PCCR0 +#define CCM_PCCR_GPIO_OFFSET 11 +#define CCM_PCCR_GPIO_REG CCM_PCCR0 +#define CCM_PCCR_SDHC2_OFFSET 10 +#define CCM_PCCR_SDHC2_REG CCM_PCCR0 +#define CCM_PCCR_SDHC1_OFFSET 9 +#define CCM_PCCR_SDHC1_REG CCM_PCCR0 +#define CCM_PCCR_FIRI_OFFSET 8 +#define CCM_PCCR_FIRI_MASK (1 << CCM_PCCR_BAUD_MASK) +#define CCM_PCCR_FIRI_REG CCM_PCCR0 +#define CCM_PCCR_SSI2_IPG_OFFSET 7 +#define CCM_PCCR_SSI2_REG CCM_PCCR0 +#define CCM_PCCR_SSI1_IPG_OFFSET 6 +#define CCM_PCCR_SSI1_REG CCM_PCCR0 +#define CCM_PCCR_CSPI2_OFFSET 5 +#define CCM_PCCR_CSPI2_REG CCM_PCCR0 +#define CCM_PCCR_CSPI1_OFFSET 4 +#define CCM_PCCR_CSPI1_REG CCM_PCCR0 +#define CCM_PCCR_UART4_OFFSET 3 +#define CCM_PCCR_UART4_REG CCM_PCCR0 +#define CCM_PCCR_UART3_OFFSET 2 +#define CCM_PCCR_UART3_REG CCM_PCCR0 +#define CCM_PCCR_UART2_OFFSET 1 +#define CCM_PCCR_UART2_REG CCM_PCCR0 +#define CCM_PCCR_UART1_OFFSET 0 +#define CCM_PCCR_UART1_REG CCM_PCCR0 + +#define CCM_PCCR_OWIRE_OFFSET 31 +#define CCM_PCCR_OWIRE_REG CCM_PCCR1 +#define CCM_PCCR_KPP_OFFSET 30 +#define CCM_PCCR_KPP_REG CCM_PCCR1 +#define CCM_PCCR_RTC_OFFSET 29 +#define CCM_PCCR_RTC_REG CCM_PCCR1 +#define CCM_PCCR_PWM_OFFSET 28 +#define CCM_PCCR_PWM_REG CCM_PCCR1 +#define CCM_PCCR_GPT3_OFFSET 27 +#define CCM_PCCR_GPT3_REG CCM_PCCR1 +#define CCM_PCCR_GPT2_OFFSET 26 +#define CCM_PCCR_GPT2_REG CCM_PCCR1 +#define CCM_PCCR_GPT1_OFFSET 25 +#define CCM_PCCR_GPT1_REG CCM_PCCR1 +#define CCM_PCCR_WDT_OFFSET 24 +#define CCM_PCCR_WDT_REG CCM_PCCR1 +#define CCM_PCCR_CSPI3_OFFSET 23 +#define CCM_PCCR_CSPI3_REG CCM_PCCR1 + +#define CCM_PCCR_CSPI1_MASK (1 << CCM_PCCR_CSPI1_OFFSET) +#define CCM_PCCR_CSPI2_MASK (1 << CCM_PCCR_CSPI2_OFFSET) +#define CCM_PCCR_CSPI3_MASK (1 << CCM_PCCR_CSPI3_OFFSET) +#define CCM_PCCR_DMA_MASK (1 << CCM_PCCR_DMA_OFFSET) +#define CCM_PCCR_EMMA_MASK (1 << CCM_PCCR_EMMA_OFFSET) +#define CCM_PCCR_GPIO_MASK (1 << CCM_PCCR_GPIO_OFFSET) +#define CCM_PCCR_GPT1_MASK (1 << CCM_PCCR_GPT1_OFFSET) +#define CCM_PCCR_GPT2_MASK (1 << CCM_PCCR_GPT2_OFFSET) +#define CCM_PCCR_GPT3_MASK (1 << CCM_PCCR_GPT3_OFFSET) +#define CCM_PCCR_HCLK_BROM_MASK (1 << CCM_PCCR_HCLK_BROM_OFFSET) +#define CCM_PCCR_HCLK_CSI_MASK (1 << CCM_PCCR_HCLK_CSI_OFFSET) +#define CCM_PCCR_HCLK_DMA_MASK (1 << CCM_PCCR_HCLK_DMA_OFFSET) +#define CCM_PCCR_HCLK_EMMA_MASK (1 << CCM_PCCR_HCLK_EMMA_OFFSET) +#define CCM_PCCR_HCLK_LCDC_MASK (1 << CCM_PCCR_HCLK_LCDC_OFFSET) +#define CCM_PCCR_HCLK_SLCDC_MASK (1 << CCM_PCCR_HCLK_SLCDC_OFFSET) +#define CCM_PCCR_HCLK_USBOTG_MASK (1 << CCM_PCCR_HCLK_USBOTG_OFFSET) +#define CCM_PCCR_I2C1_MASK (1 << CCM_PCCR_I2C1_OFFSET) +#define CCM_PCCR_KPP_MASK (1 << CCM_PCCR_KPP_OFFSET) +#define CCM_PCCR_LCDC_MASK (1 << CCM_PCCR_LCDC_OFFSET) +#define CCM_PCCR_NFC_MASK (1 << CCM_PCCR_NFC_OFFSET) +#define CCM_PCCR_OWIRE_MASK (1 << CCM_PCCR_OWIRE_OFFSET) +#define CCM_PCCR_PERCLK4_MASK (1 << CCM_PCCR_PERCLK4_OFFSET) +#define CCM_PCCR_PWM_MASK (1 << CCM_PCCR_PWM_OFFSET) +#define CCM_PCCR_RTC_MASK (1 << CCM_PCCR_RTC_OFFSET) +#define CCM_PCCR_SDHC1_MASK (1 << CCM_PCCR_SDHC1_OFFSET) +#define CCM_PCCR_SDHC2_MASK (1 << CCM_PCCR_SDHC2_OFFSET) +#define CCM_PCCR_SLCDC_MASK (1 << CCM_PCCR_SLCDC_OFFSET) +#define CCM_PCCR_SSI1_BAUD_MASK (1 << CCM_PCCR_SSI1_BAUD_OFFSET) +#define CCM_PCCR_SSI1_IPG_MASK (1 << CCM_PCCR_SSI1_IPG_OFFSET) +#define CCM_PCCR_SSI2_BAUD_MASK (1 << CCM_PCCR_SSI2_BAUD_OFFSET) +#define CCM_PCCR_SSI2_IPG_MASK (1 << CCM_PCCR_SSI2_IPG_OFFSET) +#define CCM_PCCR_UART1_MASK (1 << CCM_PCCR_UART1_OFFSET) +#define CCM_PCCR_UART2_MASK (1 << CCM_PCCR_UART2_OFFSET) +#define CCM_PCCR_UART3_MASK (1 << CCM_PCCR_UART3_OFFSET) +#define CCM_PCCR_UART4_MASK (1 << CCM_PCCR_UART4_OFFSET) +#define CCM_PCCR_USBOTG_MASK (1 << CCM_PCCR_USBOTG_OFFSET) +#define CCM_PCCR_WDT_MASK (1 << CCM_PCCR_WDT_OFFSET) + +#define CCM_CCSR_32KSR (1 << 15) + +#define CCM_CCSR_CLKMODE1 (1 << 9) +#define CCM_CCSR_CLKMODE0 (1 << 8) + +#define CCM_CCSR_CLKOSEL_OFFSET 0 +#define CCM_CCSR_CLKOSEL_MASK 0x1f + +#define SYS_FMCR 0x14 /* Functional Muxing Control Reg */ +#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */ + +static int _clk_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + return 0; +} + +static void _clk_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static unsigned long _clk_generic_round_rate(struct clk *clk, + unsigned long rate, + u32 max_divisor) +{ + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > max_divisor) + div = max_divisor; + + return parent_rate / div; +} + +static int _clk_spll_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(CCM_CSCR); + reg |= CCM_CSCR_SPEN; + __raw_writel(reg, CCM_CSCR); + + while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0) + ; + return 0; +} + +static void _clk_spll_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(CCM_CSCR); + reg &= ~CCM_CSCR_SPEN; + __raw_writel(reg, CCM_CSCR); +} + + +#define CSCR() (__raw_readl(CCM_CSCR)) +#define PCDR0() (__raw_readl(CCM_PCDR0)) +#define PCDR1() (__raw_readl(CCM_PCDR1)) + +static unsigned long _clk_perclkx_round_rate(struct clk *clk, + unsigned long rate) +{ + return _clk_generic_round_rate(clk, rate, 64); +} + +static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->id < 0 || clk->id > 3) + return -EINVAL; + + div = parent_rate / rate; + if (div > 64 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + div--; + + reg = + __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK << + (clk->id << 3)); + reg |= div << (clk->id << 3); + __raw_writel(reg, CCM_PCDR1); + + return 0; +} + +static unsigned long _clk_usb_recalc(struct clk *clk) +{ + unsigned long usb_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET; + + return parent_rate / (usb_pdf + 1U); +} + +static unsigned long _clk_usb_round_rate(struct clk *clk, + unsigned long rate) +{ + return _clk_generic_round_rate(clk, rate, 8); +} + +static int _clk_usb_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (div > 8 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + div--; + + reg = CSCR() & ~CCM_CSCR_USB_MASK; + reg |= div << CCM_CSCR_USB_OFFSET; + __raw_writel(reg, CCM_CSCR); + + return 0; +} + +static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf) +{ + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */ + + return 2UL * parent_rate / pdf; +} + +static unsigned long _clk_ssi1_recalc(struct clk *clk) +{ + return _clk_ssix_recalc(clk, + (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) + >> CCM_PCDR0_SSI1BAUDDIV_OFFSET); +} + +static unsigned long _clk_ssi2_recalc(struct clk *clk) +{ + return _clk_ssix_recalc(clk, + (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >> + CCM_PCDR0_SSI2BAUDDIV_OFFSET); +} + +static unsigned long _clk_nfc_recalc(struct clk *clk) +{ + unsigned long nfc_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + nfc_pdf = (PCDR0() & CCM_PCDR0_NFCDIV_MASK) + >> CCM_PCDR0_NFCDIV_OFFSET; + + return parent_rate / (nfc_pdf + 1); +} + +static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->round_rate(clk->parent, rate); +} + +static int _clk_parent_set_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->set_rate(clk->parent, rate); +} + +static unsigned long external_high_reference; /* in Hz */ + +static unsigned long get_high_reference_clock_rate(struct clk *clk) +{ + return external_high_reference; +} + +/* + * the high frequency external clock reference + * Default case is 26MHz. + */ +static struct clk ckih_clk = { + .get_rate = get_high_reference_clock_rate, +}; + +static unsigned long external_low_reference; /* in Hz */ + +static unsigned long get_low_reference_clock_rate(struct clk *clk) +{ + return external_low_reference; +} + +/* + * the low frequency external clock reference + * Default case is 32.768kHz. + */ +static struct clk ckil_clk = { + .get_rate = get_low_reference_clock_rate, +}; + + +static unsigned long _clk_fpm_recalc(struct clk *clk) +{ + return clk_get_rate(clk->parent) * 512; +} + +/* Output of frequency pre multiplier */ +static struct clk fpm_clk = { + .parent = &ckil_clk, + .get_rate = _clk_fpm_recalc, +}; + +static unsigned long get_mpll_clk(struct clk *clk) +{ + uint32_t reg; + unsigned long ref_clk; + unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0; + unsigned long long temp; + + ref_clk = clk_get_rate(clk->parent); + + reg = __raw_readl(CCM_MPCTL0); + pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET; + mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET; + mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET; + mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET; + + mfi = (mfi <= 5) ? 5 : mfi; + temp = 2LL * ref_clk * mfn; + do_div(temp, mfd + 1); + temp = 2LL * ref_clk * mfi + temp; + do_div(temp, pdf + 1); + + return (unsigned long)temp; +} + +static struct clk mpll_clk = { + .parent = &ckih_clk, + .get_rate = get_mpll_clk, +}; + +static unsigned long _clk_fclk_get_rate(struct clk *clk) +{ + unsigned long parent_rate; + u32 div; + + div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET; + parent_rate = clk_get_rate(clk->parent); + + return parent_rate / (div+1); +} + +static struct clk fclk_clk = { + .parent = &mpll_clk, + .get_rate = _clk_fclk_get_rate +}; + +static unsigned long get_spll_clk(struct clk *clk) +{ + uint32_t reg; + unsigned long ref_clk; + unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0; + unsigned long long temp; + + ref_clk = clk_get_rate(clk->parent); + + reg = __raw_readl(CCM_SPCTL0); + pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET; + mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET; + mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET; + mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET; + + mfi = (mfi <= 5) ? 5 : mfi; + temp = 2LL * ref_clk * mfn; + do_div(temp, mfd + 1); + temp = 2LL * ref_clk * mfi + temp; + do_div(temp, pdf + 1); + + return (unsigned long)temp; +} + +static struct clk spll_clk = { + .parent = &ckih_clk, + .get_rate = get_spll_clk, + .enable = _clk_spll_enable, + .disable = _clk_spll_disable, +}; + +static unsigned long get_hclk_clk(struct clk *clk) +{ + unsigned long rate; + unsigned long bclk_pdf; + + bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK) + >> CCM_CSCR_BCLK_OFFSET; + + rate = clk_get_rate(clk->parent); + return rate / (bclk_pdf + 1); +} + +static struct clk hclk_clk = { + .parent = &fclk_clk, + .get_rate = get_hclk_clk, +}; + +static unsigned long get_ipg_clk(struct clk *clk) +{ + unsigned long rate; + unsigned long ipg_pdf; + + ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET; + + rate = clk_get_rate(clk->parent); + return rate / (ipg_pdf + 1); +} + +static struct clk ipg_clk = { + .parent = &hclk_clk, + .get_rate = get_ipg_clk, +}; + +static unsigned long _clk_perclkx_recalc(struct clk *clk) +{ + unsigned long perclk_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->id < 0 || clk->id > 3) + return 0; + + perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK; + + return parent_rate / (perclk_pdf + 1); +} + +static struct clk per_clk[] = { + { + .id = 0, + .parent = &mpll_clk, + .get_rate = _clk_perclkx_recalc, + }, { + .id = 1, + .parent = &mpll_clk, + .get_rate = _clk_perclkx_recalc, + }, { + .id = 2, + .parent = &mpll_clk, + .round_rate = _clk_perclkx_round_rate, + .set_rate = _clk_perclkx_set_rate, + .get_rate = _clk_perclkx_recalc, + /* Enable/Disable done via lcd_clkc[1] */ + }, { + .id = 3, + .parent = &mpll_clk, + .round_rate = _clk_perclkx_round_rate, + .set_rate = _clk_perclkx_set_rate, + .get_rate = _clk_perclkx_recalc, + /* Enable/Disable done via csi_clk[1] */ + }, +}; + +static struct clk uart_ipg_clk[]; + +static struct clk uart_clk[] = { + { + .id = 0, + .parent = &per_clk[0], + .secondary = &uart_ipg_clk[0], + }, { + .id = 1, + .parent = &per_clk[0], + .secondary = &uart_ipg_clk[1], + }, { + .id = 2, + .parent = &per_clk[0], + .secondary = &uart_ipg_clk[2], + }, { + .id = 3, + .parent = &per_clk[0], + .secondary = &uart_ipg_clk[3], + }, +}; + +static struct clk uart_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_UART1_REG, + .enable_shift = CCM_PCCR_UART1_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_UART2_REG, + .enable_shift = CCM_PCCR_UART2_OFFSET, + .disable = _clk_disable, + }, { + .id = 2, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_UART3_REG, + .enable_shift = CCM_PCCR_UART3_OFFSET, + .disable = _clk_disable, + }, { + .id = 3, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_UART4_REG, + .enable_shift = CCM_PCCR_UART4_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk gpt_ipg_clk[]; + +static struct clk gpt_clk[] = { + { + .id = 0, + .parent = &per_clk[0], + .secondary = &gpt_ipg_clk[0], + }, { + .id = 1, + .parent = &per_clk[0], + .secondary = &gpt_ipg_clk[1], + }, { + .id = 2, + .parent = &per_clk[0], + .secondary = &gpt_ipg_clk[2], + }, +}; + +static struct clk gpt_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_GPT1_REG, + .enable_shift = CCM_PCCR_GPT1_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_GPT2_REG, + .enable_shift = CCM_PCCR_GPT2_OFFSET, + .disable = _clk_disable, + }, { + .id = 2, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_GPT3_REG, + .enable_shift = CCM_PCCR_GPT3_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk pwm_clk[] = { + { + .parent = &per_clk[0], + .secondary = &pwm_clk[1], + }, { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_PWM_REG, + .enable_shift = CCM_PCCR_PWM_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk sdhc_ipg_clk[]; + +static struct clk sdhc_clk[] = { + { + .id = 0, + .parent = &per_clk[1], + .secondary = &sdhc_ipg_clk[0], + }, { + .id = 1, + .parent = &per_clk[1], + .secondary = &sdhc_ipg_clk[1], + }, +}; + +static struct clk sdhc_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SDHC1_REG, + .enable_shift = CCM_PCCR_SDHC1_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SDHC2_REG, + .enable_shift = CCM_PCCR_SDHC2_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk cspi_ipg_clk[]; + +static struct clk cspi_clk[] = { + { + .id = 0, + .parent = &per_clk[1], + .secondary = &cspi_ipg_clk[0], + }, { + .id = 1, + .parent = &per_clk[1], + .secondary = &cspi_ipg_clk[1], + }, { + .id = 2, + .parent = &per_clk[1], + .secondary = &cspi_ipg_clk[2], + }, +}; + +static struct clk cspi_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_CSPI1_REG, + .enable_shift = CCM_PCCR_CSPI1_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_CSPI2_REG, + .enable_shift = CCM_PCCR_CSPI2_OFFSET, + .disable = _clk_disable, + }, { + .id = 3, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_CSPI3_REG, + .enable_shift = CCM_PCCR_CSPI3_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk lcdc_clk[] = { + { + .parent = &per_clk[2], + .secondary = &lcdc_clk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + }, { + .parent = &ipg_clk, + .secondary = &lcdc_clk[2], + .enable = _clk_enable, + .enable_reg = CCM_PCCR_LCDC_REG, + .enable_shift = CCM_PCCR_LCDC_OFFSET, + .disable = _clk_disable, + }, { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_LCDC_REG, + .enable_shift = CCM_PCCR_HCLK_LCDC_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk csi_clk[] = { + { + .parent = &per_clk[3], + .secondary = &csi_clk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + }, { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_CSI_REG, + .enable_shift = CCM_PCCR_HCLK_CSI_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk usb_clk[] = { + { + .parent = &spll_clk, + .secondary = &usb_clk[1], + .get_rate = _clk_usb_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_USBOTG_REG, + .enable_shift = CCM_PCCR_USBOTG_OFFSET, + .disable = _clk_disable, + .round_rate = _clk_usb_round_rate, + .set_rate = _clk_usb_set_rate, + }, { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_USBOTG_REG, + .enable_shift = CCM_PCCR_HCLK_USBOTG_OFFSET, + .disable = _clk_disable, + } +}; + +static struct clk ssi_ipg_clk[]; + +static struct clk ssi_clk[] = { + { + .id = 0, + .parent = &mpll_clk, + .secondary = &ssi_ipg_clk[0], + .get_rate = _clk_ssi1_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SSI1_BAUD_REG, + .enable_shift = CCM_PCCR_SSI1_BAUD_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &mpll_clk, + .secondary = &ssi_ipg_clk[1], + .get_rate = _clk_ssi2_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SSI2_BAUD_REG, + .enable_shift = CCM_PCCR_SSI2_BAUD_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk ssi_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SSI1_REG, + .enable_shift = CCM_PCCR_SSI1_IPG_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SSI2_REG, + .enable_shift = CCM_PCCR_SSI2_IPG_OFFSET, + .disable = _clk_disable, + }, +}; + + +static struct clk nfc_clk = { + .parent = &fclk_clk, + .get_rate = _clk_nfc_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_NFC_REG, + .enable_shift = CCM_PCCR_NFC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk dma_clk[] = { + { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_DMA_REG, + .enable_shift = CCM_PCCR_DMA_OFFSET, + .disable = _clk_disable, + .secondary = &dma_clk[1], + }, { + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_DMA_REG, + .enable_shift = CCM_PCCR_HCLK_DMA_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk brom_clk = { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_BROM_REG, + .enable_shift = CCM_PCCR_HCLK_BROM_OFFSET, + .disable = _clk_disable, +}; + +static struct clk emma_clk[] = { + { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_EMMA_REG, + .enable_shift = CCM_PCCR_EMMA_OFFSET, + .disable = _clk_disable, + .secondary = &emma_clk[1], + }, { + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_EMMA_REG, + .enable_shift = CCM_PCCR_HCLK_EMMA_OFFSET, + .disable = _clk_disable, + } +}; + +static struct clk slcdc_clk[] = { + { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SLCDC_REG, + .enable_shift = CCM_PCCR_SLCDC_OFFSET, + .disable = _clk_disable, + .secondary = &slcdc_clk[1], + }, { + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_SLCDC_REG, + .enable_shift = CCM_PCCR_HCLK_SLCDC_OFFSET, + .disable = _clk_disable, + } +}; + +static struct clk wdog_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_WDT_REG, + .enable_shift = CCM_PCCR_WDT_OFFSET, + .disable = _clk_disable, +}; + +static struct clk gpio_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_GPIO_REG, + .enable_shift = CCM_PCCR_GPIO_OFFSET, + .disable = _clk_disable, +}; + +static struct clk i2c_clk = { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_I2C1_REG, + .enable_shift = CCM_PCCR_I2C1_OFFSET, + .disable = _clk_disable, +}; + +static struct clk kpp_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_KPP_REG, + .enable_shift = CCM_PCCR_KPP_OFFSET, + .disable = _clk_disable, +}; + +static struct clk owire_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_OWIRE_REG, + .enable_shift = CCM_PCCR_OWIRE_OFFSET, + .disable = _clk_disable, +}; + +static struct clk rtc_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_RTC_REG, + .enable_shift = CCM_PCCR_RTC_OFFSET, + .disable = _clk_disable, +}; + +static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_generic_round_rate(clk, rate, 8); +} + +static int _clk_clko_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 8 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + div--; + + reg = __raw_readl(CCM_PCDR0); + + if (clk->parent == &usb_clk[0]) { + reg &= ~CCM_PCDR0_48MDIV_MASK; + reg |= div << CCM_PCDR0_48MDIV_OFFSET; + } + __raw_writel(reg, CCM_PCDR0); + + return 0; +} + +static unsigned long _clk_clko_recalc(struct clk *clk) +{ + u32 div = 0; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->parent == &usb_clk[0]) /* 48M */ + div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_48MDIV_MASK + >> CCM_PCDR0_48MDIV_OFFSET; + div++; + + return parent_rate / div; +} + +static struct clk clko_clk; + +static int _clk_clko_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK; + + if (parent == &ckil_clk) + reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &fpm_clk) + reg |= 1 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &ckih_clk) + reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == mpll_clk.parent) + reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == spll_clk.parent) + reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &mpll_clk) + reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &spll_clk) + reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &fclk_clk) + reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &hclk_clk) + reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &ipg_clk) + reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &per_clk[0]) + reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &per_clk[1]) + reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &per_clk[2]) + reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &per_clk[3]) + reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &ssi_clk[0]) + reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &ssi_clk[1]) + reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &nfc_clk) + reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &usb_clk[0]) + reg |= 0x14 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &clko_clk) + reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET; + else + return -EINVAL; + + __raw_writel(reg, CCM_CCSR); + + return 0; +} + +static struct clk clko_clk = { + .get_rate = _clk_clko_recalc, + .set_rate = _clk_clko_set_rate, + .round_rate = _clk_clko_round_rate, + .set_parent = _clk_clko_set_parent, +}; + + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, +static struct clk_lookup lookups[] = { +/* It's unlikely that any driver wants one of them directly: + _REGISTER_CLOCK(NULL, "ckih", ckih_clk) + _REGISTER_CLOCK(NULL, "ckil", ckil_clk) + _REGISTER_CLOCK(NULL, "fpm", fpm_clk) + _REGISTER_CLOCK(NULL, "mpll", mpll_clk) + _REGISTER_CLOCK(NULL, "spll", spll_clk) + _REGISTER_CLOCK(NULL, "fclk", fclk_clk) + _REGISTER_CLOCK(NULL, "hclk", hclk_clk) + _REGISTER_CLOCK(NULL, "ipg", ipg_clk) +*/ + _REGISTER_CLOCK(NULL, "perclk1", per_clk[0]) + _REGISTER_CLOCK(NULL, "perclk2", per_clk[1]) + _REGISTER_CLOCK(NULL, "perclk3", per_clk[2]) + _REGISTER_CLOCK(NULL, "perclk4", per_clk[3]) + _REGISTER_CLOCK(NULL, "clko", clko_clk) + _REGISTER_CLOCK("imx21-uart.0", NULL, uart_clk[0]) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart_clk[1]) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart_clk[2]) + _REGISTER_CLOCK("imx21-uart.3", NULL, uart_clk[3]) + _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0]) + _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1]) + _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2]) + _REGISTER_CLOCK(NULL, "pwm", pwm_clk[0]) + _REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0]) + _REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1]) + _REGISTER_CLOCK("imx21-cspi.0", NULL, cspi_clk[0]) + _REGISTER_CLOCK("imx21-cspi.1", NULL, cspi_clk[1]) + _REGISTER_CLOCK("imx21-cspi.2", NULL, cspi_clk[2]) + _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0]) + _REGISTER_CLOCK(NULL, "csi", csi_clk[0]) + _REGISTER_CLOCK("imx21-hcd.0", NULL, usb_clk[0]) + _REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0]) + _REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1]) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) + _REGISTER_CLOCK(NULL, "dma", dma_clk[0]) + _REGISTER_CLOCK(NULL, "brom", brom_clk) + _REGISTER_CLOCK(NULL, "emma", emma_clk[0]) + _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0]) + _REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk) + _REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk) + _REGISTER_CLOCK(NULL, "owire", owire_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) +}; + +/* + * must be called very early to get information about the + * available clock rate when the timer framework starts + */ +int __init mx21_clocks_init(unsigned long lref, unsigned long href) +{ + u32 cscr; + + external_low_reference = lref; + external_high_reference = href; + + /* detect clock reference for both system PLL */ + cscr = CSCR(); + if (cscr & CCM_CSCR_MCU) + mpll_clk.parent = &ckih_clk; + else + mpll_clk.parent = &fpm_clk; + + if (cscr & CCM_CSCR_SP) + spll_clk.parent = &ckih_clk; + else + spll_clk.parent = &fpm_clk; + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + /* Turn off all clock gates */ + __raw_writel(0, CCM_PCCR0); + __raw_writel(CCM_PCCR_GPT1_MASK, CCM_PCCR1); + + /* This turns of the serial PLL as well */ + spll_clk.disable(&spll_clk); + + /* This will propagate to all children and init all the clock rates. */ + clk_enable(&per_clk[0]); + clk_enable(&gpio_clk); + +#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) + clk_enable(&uart_clk[0]); +#endif + + mxc_timer_init(&gpt_clk[0], MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR), + MX21_INT_GPT1); + return 0; +} diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c new file mode 100644 index 00000000..b0fec74c --- /dev/null +++ b/arch/arm/mach-imx/clock-imx25.c @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2009 by Sascha Hauer, Pengutronix + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define CRM_BASE MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR) + +#define CCM_MPCTL 0x00 +#define CCM_UPCTL 0x04 +#define CCM_CCTL 0x08 +#define CCM_CGCR0 0x0C +#define CCM_CGCR1 0x10 +#define CCM_CGCR2 0x14 +#define CCM_PCDR0 0x18 +#define CCM_PCDR1 0x1C +#define CCM_PCDR2 0x20 +#define CCM_PCDR3 0x24 +#define CCM_RCSR 0x28 +#define CCM_CRDR 0x2C +#define CCM_DCVR0 0x30 +#define CCM_DCVR1 0x34 +#define CCM_DCVR2 0x38 +#define CCM_DCVR3 0x3c +#define CCM_LTR0 0x40 +#define CCM_LTR1 0x44 +#define CCM_LTR2 0x48 +#define CCM_LTR3 0x4c + +static unsigned long get_rate_mpll(void) +{ + ulong mpctl = __raw_readl(CRM_BASE + CCM_MPCTL); + + return mxc_decode_pll(mpctl, 24000000); +} + +static unsigned long get_rate_upll(void) +{ + ulong mpctl = __raw_readl(CRM_BASE + CCM_UPCTL); + + return mxc_decode_pll(mpctl, 24000000); +} + +unsigned long get_rate_arm(struct clk *clk) +{ + unsigned long cctl = readl(CRM_BASE + CCM_CCTL); + unsigned long rate = get_rate_mpll(); + + if (cctl & (1 << 14)) + rate = (rate * 3) >> 2; + + return rate / ((cctl >> 30) + 1); +} + +static unsigned long get_rate_ahb(struct clk *clk) +{ + unsigned long cctl = readl(CRM_BASE + CCM_CCTL); + + return get_rate_arm(NULL) / (((cctl >> 28) & 0x3) + 1); +} + +static unsigned long get_rate_ipg(struct clk *clk) +{ + return get_rate_ahb(NULL) >> 1; +} + +static unsigned long get_rate_per(int per) +{ + unsigned long ofs = (per & 0x3) * 8; + unsigned long reg = per & ~0x3; + unsigned long val = (readl(CRM_BASE + CCM_PCDR0 + reg) >> ofs) & 0x3f; + unsigned long fref; + + if (readl(CRM_BASE + 0x64) & (1 << per)) + fref = get_rate_upll(); + else + fref = get_rate_ahb(NULL); + + return fref / (val + 1); +} + +static unsigned long get_rate_uart(struct clk *clk) +{ + return get_rate_per(15); +} + +static unsigned long get_rate_ssi2(struct clk *clk) +{ + return get_rate_per(14); +} + +static unsigned long get_rate_ssi1(struct clk *clk) +{ + return get_rate_per(13); +} + +static unsigned long get_rate_i2c(struct clk *clk) +{ + return get_rate_per(6); +} + +static unsigned long get_rate_nfc(struct clk *clk) +{ + return get_rate_per(8); +} + +static unsigned long get_rate_gpt(struct clk *clk) +{ + return get_rate_per(5); +} + +static unsigned long get_rate_lcdc(struct clk *clk) +{ + return get_rate_per(7); +} + +static unsigned long get_rate_esdhc1(struct clk *clk) +{ + return get_rate_per(3); +} + +static unsigned long get_rate_esdhc2(struct clk *clk) +{ + return get_rate_per(4); +} + +static unsigned long get_rate_csi(struct clk *clk) +{ + return get_rate_per(0); +} + +static unsigned long get_rate_otg(struct clk *clk) +{ + unsigned long cctl = readl(CRM_BASE + CCM_CCTL); + unsigned long rate = get_rate_upll(); + + return (cctl & (1 << 23)) ? 0 : rate / ((0x3F & (cctl >> 16)) + 1); +} + +static int clk_cgcr_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void clk_cgcr_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +#define DEFINE_CLOCK(name, i, er, es, gr, sr, s) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = CRM_BASE + er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .set_rate = sr, \ + .enable = clk_cgcr_enable, \ + .disable = clk_cgcr_disable, \ + .secondary = s, \ + } + +/* + * Note: the following IPG clock gating bits are wrongly marked "Reserved" in + * the i.MX25 Reference Manual Rev 1, table 15-13. The information below is + * taken from the Freescale released BSP. + * + * bit reg offset clock + * + * 0 CGCR1 0 AUDMUX + * 12 CGCR1 12 ESAI + * 16 CGCR1 16 GPIO1 + * 17 CGCR1 17 GPIO2 + * 18 CGCR1 18 GPIO3 + * 23 CGCR1 23 I2C1 + * 24 CGCR1 24 I2C2 + * 25 CGCR1 25 I2C3 + * 27 CGCR1 27 IOMUXC + * 28 CGCR1 28 KPP + * 30 CGCR1 30 OWIRE + * 36 CGCR2 4 RTIC + * 51 CGCR2 19 WDOG + */ + +DEFINE_CLOCK(gpt_clk, 0, CCM_CGCR0, 5, get_rate_gpt, NULL, NULL); +DEFINE_CLOCK(uart_per_clk, 0, CCM_CGCR0, 15, get_rate_uart, NULL, NULL); +DEFINE_CLOCK(ssi1_per_clk, 0, CCM_CGCR0, 13, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(ssi2_per_clk, 0, CCM_CGCR0, 14, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(cspi1_clk, 0, CCM_CGCR1, 5, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(cspi2_clk, 0, CCM_CGCR1, 6, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(cspi3_clk, 0, CCM_CGCR1, 7, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(esdhc1_ahb_clk, 0, CCM_CGCR0, 21, get_rate_esdhc1, NULL, NULL); +DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0, 3, get_rate_esdhc1, NULL, + &esdhc1_ahb_clk); +DEFINE_CLOCK(esdhc2_ahb_clk, 0, CCM_CGCR0, 22, get_rate_esdhc2, NULL, NULL); +DEFINE_CLOCK(esdhc2_per_clk, 0, CCM_CGCR0, 4, get_rate_esdhc2, NULL, + &esdhc2_ahb_clk); +DEFINE_CLOCK(sdma_ahb_clk, 0, CCM_CGCR0, 26, NULL, NULL, NULL); +DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL, NULL, NULL); +DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL, NULL, NULL); +DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0, 7, NULL, NULL, &lcdc_ahb_clk); +DEFINE_CLOCK(csi_ahb_clk, 0, CCM_CGCR0, 18, get_rate_csi, NULL, NULL); +DEFINE_CLOCK(csi_per_clk, 0, CCM_CGCR0, 0, get_rate_csi, NULL, &csi_ahb_clk); +DEFINE_CLOCK(uart1_clk, 0, CCM_CGCR2, 14, get_rate_uart, NULL, &uart_per_clk); +DEFINE_CLOCK(uart2_clk, 0, CCM_CGCR2, 15, get_rate_uart, NULL, &uart_per_clk); +DEFINE_CLOCK(uart3_clk, 0, CCM_CGCR2, 16, get_rate_uart, NULL, &uart_per_clk); +DEFINE_CLOCK(uart4_clk, 0, CCM_CGCR2, 17, get_rate_uart, NULL, &uart_per_clk); +DEFINE_CLOCK(uart5_clk, 0, CCM_CGCR2, 18, get_rate_uart, NULL, &uart_per_clk); +DEFINE_CLOCK(nfc_clk, 0, CCM_CGCR0, 8, get_rate_nfc, NULL, NULL); +DEFINE_CLOCK(usbotg_clk, 0, CCM_CGCR0, 28, get_rate_otg, NULL, NULL); +DEFINE_CLOCK(pwm1_clk, 0, CCM_CGCR1, 31, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(pwm2_clk, 0, CCM_CGCR2, 0, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(pwm3_clk, 0, CCM_CGCR2, 1, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(pwm4_clk, 0, CCM_CGCR2, 2, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(kpp_clk, 0, CCM_CGCR1, 28, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(tsc_clk, 0, CCM_CGCR2, 13, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(i2c_clk, 0, CCM_CGCR0, 6, get_rate_i2c, NULL, NULL); +DEFINE_CLOCK(fec_clk, 0, CCM_CGCR1, 15, get_rate_ipg, NULL, &fec_ahb_clk); +DEFINE_CLOCK(dryice_clk, 0, CCM_CGCR1, 8, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(lcdc_clk, 0, CCM_CGCR1, 29, get_rate_lcdc, NULL, &lcdc_per_clk); +DEFINE_CLOCK(wdt_clk, 0, CCM_CGCR2, 19, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(ssi1_clk, 0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk); +DEFINE_CLOCK(ssi2_clk, 1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk); +DEFINE_CLOCK(sdma_clk, 0, CCM_CGCR2, 6, get_rate_ipg, NULL, &sdma_ahb_clk); +DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGCR1, 13, get_rate_esdhc1, NULL, + &esdhc1_per_clk); +DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGCR1, 14, get_rate_esdhc2, NULL, + &esdhc2_per_clk); +DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL); +DEFINE_CLOCK(csi_clk, 0, CCM_CGCR1, 4, get_rate_csi, NULL, &csi_per_clk); +DEFINE_CLOCK(can1_clk, 0, CCM_CGCR1, 2, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(can2_clk, 1, CCM_CGCR1, 3, get_rate_ipg, NULL, NULL); +DEFINE_CLOCK(iim_clk, 0, CCM_CGCR1, 26, NULL, NULL, NULL); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] = { + /* i.mx25 has the i.mx21 type uart */ + _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) + /* i.mx25 has the i.mx35 type cspi */ + _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk) + _REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk) + _REGISTER_CLOCK("imx35-cspi.2", NULL, cspi3_clk) + _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk) + _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk) + _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk) + _REGISTER_CLOCK("mxc_pwm.3", NULL, pwm4_clk) + _REGISTER_CLOCK("imx-keypad", NULL, kpp_clk) + _REGISTER_CLOCK("mx25-adc", NULL, tsc_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk) + _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk) + _REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk) + _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) + _REGISTER_CLOCK("imx2-wdt.0", NULL, wdt_clk) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx25.0", NULL, esdhc1_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx25.1", NULL, esdhc2_clk) + _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk) + _REGISTER_CLOCK(NULL, "audmux", audmux_clk) + _REGISTER_CLOCK("flexcan.0", NULL, can1_clk) + _REGISTER_CLOCK("flexcan.1", NULL, can2_clk) + /* i.mx25 has the i.mx35 type sdma */ + _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) + _REGISTER_CLOCK(NULL, "iim", iim_clk) +}; + +int __init mx25_clocks_init(void) +{ + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + /* Turn off all clocks except the ones we need to survive, namely: + * EMI, GPIO1-3 (CCM_CGCR1[18:16]), GPT1, IOMUXC (CCM_CGCR1[27]), IIM, + * SCC + */ + __raw_writel((1 << 19), CRM_BASE + CCM_CGCR0); + __raw_writel((0xf << 16) | (3 << 26), CRM_BASE + CCM_CGCR1); + __raw_writel((1 << 5), CRM_BASE + CCM_CGCR2); +#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) + clk_enable(&uart1_clk); +#endif + + /* Clock source for lcdc and csi is upll */ + __raw_writel(__raw_readl(CRM_BASE+0x64) | (1 << 7) | (1 << 0), + CRM_BASE + 0x64); + + /* Clock source for gpt is ahb_div */ + __raw_writel(__raw_readl(CRM_BASE+0x64) & ~(1 << 5), CRM_BASE + 0x64); + + clk_enable(&iim_clk); + imx_print_silicon_rev("i.MX25", mx25_revision()); + clk_disable(&iim_clk); + + mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54); + + return 0; +} diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c new file mode 100644 index 00000000..98e04f5a --- /dev/null +++ b/arch/arm/mach-imx/clock-imx27.c @@ -0,0 +1,785 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com + * + * 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 +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define IO_ADDR_CCM(off) (MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off))) + +/* Register offsets */ +#define CCM_CSCR IO_ADDR_CCM(0x0) +#define CCM_MPCTL0 IO_ADDR_CCM(0x4) +#define CCM_MPCTL1 IO_ADDR_CCM(0x8) +#define CCM_SPCTL0 IO_ADDR_CCM(0xc) +#define CCM_SPCTL1 IO_ADDR_CCM(0x10) +#define CCM_OSC26MCTL IO_ADDR_CCM(0x14) +#define CCM_PCDR0 IO_ADDR_CCM(0x18) +#define CCM_PCDR1 IO_ADDR_CCM(0x1c) +#define CCM_PCCR0 IO_ADDR_CCM(0x20) +#define CCM_PCCR1 IO_ADDR_CCM(0x24) +#define CCM_CCSR IO_ADDR_CCM(0x28) +#define CCM_PMCTL IO_ADDR_CCM(0x2c) +#define CCM_PMCOUNT IO_ADDR_CCM(0x30) +#define CCM_WKGDCTL IO_ADDR_CCM(0x34) + +#define CCM_CSCR_UPDATE_DIS (1 << 31) +#define CCM_CSCR_SSI2 (1 << 23) +#define CCM_CSCR_SSI1 (1 << 22) +#define CCM_CSCR_VPU (1 << 21) +#define CCM_CSCR_MSHC (1 << 20) +#define CCM_CSCR_SPLLRES (1 << 19) +#define CCM_CSCR_MPLLRES (1 << 18) +#define CCM_CSCR_SP (1 << 17) +#define CCM_CSCR_MCU (1 << 16) +#define CCM_CSCR_OSC26MDIV (1 << 4) +#define CCM_CSCR_OSC26M (1 << 3) +#define CCM_CSCR_FPM (1 << 2) +#define CCM_CSCR_SPEN (1 << 1) +#define CCM_CSCR_MPEN (1 << 0) + +/* i.MX27 TO 2+ */ +#define CCM_CSCR_ARM_SRC (1 << 15) + +#define CCM_SPCTL1_LF (1 << 15) +#define CCM_SPCTL1_BRMO (1 << 6) + +static struct clk mpll_main1_clk, mpll_main2_clk; + +static int clk_pccr_enable(struct clk *clk) +{ + unsigned long reg; + + if (!clk->enable_reg) + return 0; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void clk_pccr_disable(struct clk *clk) +{ + unsigned long reg; + + if (!clk->enable_reg) + return; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static int clk_spll_enable(struct clk *clk) +{ + unsigned long reg; + + reg = __raw_readl(CCM_CSCR); + reg |= CCM_CSCR_SPEN; + __raw_writel(reg, CCM_CSCR); + + while (!(__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF)); + + return 0; +} + +static void clk_spll_disable(struct clk *clk) +{ + unsigned long reg; + + reg = __raw_readl(CCM_CSCR); + reg &= ~CCM_CSCR_SPEN; + __raw_writel(reg, CCM_CSCR); +} + +static int clk_cpu_set_parent(struct clk *clk, struct clk *parent) +{ + int cscr = __raw_readl(CCM_CSCR); + + if (clk->parent == parent) + return 0; + + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) { + if (parent == &mpll_main1_clk) { + cscr |= CCM_CSCR_ARM_SRC; + } else { + if (parent == &mpll_main2_clk) + cscr &= ~CCM_CSCR_ARM_SRC; + else + return -EINVAL; + } + __raw_writel(cscr, CCM_CSCR); + clk->parent = parent; + return 0; + } + return -ENODEV; +} + +static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate) +{ + int div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > 4) + div = 4; + + return parent_rate / div; +} + +static int set_rate_cpu(struct clk *clk, unsigned long rate) +{ + unsigned int div; + uint32_t reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 4 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_CSCR); + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) { + reg &= ~(3 << 12); + reg |= div << 12; + reg &= ~(CCM_CSCR_FPM | CCM_CSCR_SPEN); + __raw_writel(reg | CCM_CSCR_UPDATE_DIS, CCM_CSCR); + } else { + printk(KERN_ERR "Can't set CPU frequency!\n"); + } + + return 0; +} + +static unsigned long round_rate_per(struct clk *clk, unsigned long rate) +{ + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > 64) + div = 64; + + return parent_rate / div; +} + +static int set_rate_per(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->id < 0 || clk->id > 3) + return -EINVAL; + + div = parent_rate / rate; + if (div > 64 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + div--; + + reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3)); + reg |= div << (clk->id << 3); + __raw_writel(reg, CCM_PCDR1); + + return 0; +} + +static unsigned long get_rate_usb(struct clk *clk) +{ + unsigned long usb_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7; + + return parent_rate / (usb_pdf + 1U); +} + +static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf) +{ + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) + pdf += 4; /* MX27 TO2+ */ + else + pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */ + + return 2UL * parent_rate / pdf; +} + +static unsigned long get_rate_ssi1(struct clk *clk) +{ + return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f); +} + +static unsigned long get_rate_ssi2(struct clk *clk) +{ + return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f); +} + +static unsigned long get_rate_nfc(struct clk *clk) +{ + unsigned long nfc_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) + nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf; + else + nfc_pdf = (__raw_readl(CCM_PCDR0) >> 12) & 0xf; + + return parent_rate / (nfc_pdf + 1); +} + +static unsigned long get_rate_vpu(struct clk *clk) +{ + unsigned long vpu_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) { + vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f; + vpu_pdf += 4; + } else { + vpu_pdf = (__raw_readl(CCM_PCDR0) >> 8) & 0xf; + vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf; + } + + return 2UL * parent_rate / vpu_pdf; +} + +static unsigned long round_rate_parent(struct clk *clk, unsigned long rate) +{ + return clk->parent->round_rate(clk->parent, rate); +} + +static unsigned long get_rate_parent(struct clk *clk) +{ + return clk_get_rate(clk->parent); +} + +static int set_rate_parent(struct clk *clk, unsigned long rate) +{ + return clk->parent->set_rate(clk->parent, rate); +} + +/* in Hz */ +static unsigned long external_high_reference = 26000000; + +static unsigned long get_rate_high_reference(struct clk *clk) +{ + return external_high_reference; +} + +/* in Hz */ +static unsigned long external_low_reference = 32768; + +static unsigned long get_rate_low_reference(struct clk *clk) +{ + return external_low_reference; +} + +static unsigned long get_rate_fpm(struct clk *clk) +{ + return clk_get_rate(clk->parent) * 1024; +} + +static unsigned long get_rate_mpll(struct clk *clk) +{ + return mxc_decode_pll(__raw_readl(CCM_MPCTL0), + clk_get_rate(clk->parent)); +} + +static unsigned long get_rate_mpll_main(struct clk *clk) +{ + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + /* i.MX27 TO2: + * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2 + * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3 + */ + if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk->id == 1) + return 2UL * parent_rate / 3UL; + + return parent_rate; +} + +static unsigned long get_rate_spll(struct clk *clk) +{ + uint32_t reg; + unsigned long rate; + + rate = clk_get_rate(clk->parent); + + reg = __raw_readl(CCM_SPCTL0); + + /* On TO2 we have to write the value back. Otherwise we + * read 0 from this register the next time. + */ + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) + __raw_writel(reg, CCM_SPCTL0); + + return mxc_decode_pll(reg, rate); +} + +static unsigned long get_rate_cpu(struct clk *clk) +{ + u32 div; + unsigned long rate; + + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) + div = (__raw_readl(CCM_CSCR) >> 12) & 0x3; + else + div = (__raw_readl(CCM_CSCR) >> 13) & 0x7; + + rate = clk_get_rate(clk->parent); + return rate / (div + 1); +} + +static unsigned long get_rate_ahb(struct clk *clk) +{ + unsigned long rate, bclk_pdf; + + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) + bclk_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3; + else + bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf; + + rate = clk_get_rate(clk->parent); + return rate / (bclk_pdf + 1); +} + +static unsigned long get_rate_ipg(struct clk *clk) +{ + unsigned long rate, ipg_pdf; + + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) + return clk_get_rate(clk->parent); + else + ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1; + + rate = clk_get_rate(clk->parent); + return rate / (ipg_pdf + 1); +} + +static unsigned long get_rate_per(struct clk *clk) +{ + unsigned long perclk_pdf, parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->id < 0 || clk->id > 3) + return 0; + + perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f; + + return parent_rate / (perclk_pdf + 1); +} + +/* + * the high frequency external clock reference + * Default case is 26MHz. Could be changed at runtime + * with a call to change_external_high_reference() + */ +static struct clk ckih_clk = { + .get_rate = get_rate_high_reference, +}; + +static struct clk mpll_clk = { + .parent = &ckih_clk, + .get_rate = get_rate_mpll, +}; + +/* For i.MX27 TO2, it is the MPLL path 1 of ARM core + * It provides the clock source whose rate is same as MPLL + */ +static struct clk mpll_main1_clk = { + .id = 0, + .parent = &mpll_clk, + .get_rate = get_rate_mpll_main, +}; + +/* For i.MX27 TO2, it is the MPLL path 2 of ARM core + * It provides the clock source whose rate is same MPLL * 2 / 3 + */ +static struct clk mpll_main2_clk = { + .id = 1, + .parent = &mpll_clk, + .get_rate = get_rate_mpll_main, +}; + +static struct clk ahb_clk = { + .parent = &mpll_main2_clk, + .get_rate = get_rate_ahb, +}; + +static struct clk ipg_clk = { + .parent = &ahb_clk, + .get_rate = get_rate_ipg, +}; + +static struct clk cpu_clk = { + .parent = &mpll_main2_clk, + .set_parent = clk_cpu_set_parent, + .round_rate = round_rate_cpu, + .get_rate = get_rate_cpu, + .set_rate = set_rate_cpu, +}; + +static struct clk spll_clk = { + .parent = &ckih_clk, + .get_rate = get_rate_spll, + .enable = clk_spll_enable, + .disable = clk_spll_disable, +}; + +/* + * the low frequency external clock reference + * Default case is 32.768kHz. + */ +static struct clk ckil_clk = { + .get_rate = get_rate_low_reference, +}; + +/* Output of frequency pre multiplier */ +static struct clk fpm_clk = { + .parent = &ckil_clk, + .get_rate = get_rate_fpm, +}; + +#define PCCR0 CCM_PCCR0 +#define PCCR1 CCM_PCCR1 + +#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .enable = clk_pccr_enable, \ + .disable = clk_pccr_disable, \ + .secondary = s, \ + .parent = p, \ + } + +#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = get_rate_##getsetround, \ + .set_rate = set_rate_##getsetround, \ + .round_rate = round_rate_##getsetround, \ + .enable = clk_pccr_enable, \ + .disable = clk_pccr_disable, \ + .secondary = s, \ + .parent = p, \ + } + +/* Forward declaration to keep the following list in order */ +static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1, + dma_clk1, lcdc_clk2, vpu_clk1; + +/* All clocks we can gate through PCCRx in the order of PCCRx bits */ +DEFINE_CLOCK(ssi2_clk1, 1, PCCR0, 0, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(ssi1_clk1, 0, PCCR0, 1, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(slcdc_clk, 0, PCCR0, 2, NULL, &slcdc_clk1, &ahb_clk); +DEFINE_CLOCK(sdhc3_clk1, 0, PCCR0, 3, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(sdhc2_clk1, 0, PCCR0, 4, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(sdhc1_clk1, 0, PCCR0, 5, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(scc_clk, 0, PCCR0, 6, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(sahara2_clk, 0, PCCR0, 7, NULL, &sahara2_clk1, &ahb_clk); +DEFINE_CLOCK(rtic_clk, 0, PCCR0, 8, NULL, &rtic_clk1, &ahb_clk); +DEFINE_CLOCK(rtc_clk, 0, PCCR0, 9, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(pwm_clk1, 0, PCCR0, 11, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(owire_clk, 0, PCCR0, 12, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(mstick_clk1, 0, PCCR0, 13, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(lcdc_clk1, 0, PCCR0, 14, NULL, &lcdc_clk2, &ipg_clk); +DEFINE_CLOCK(kpp_clk, 0, PCCR0, 15, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(iim_clk, 0, PCCR0, 16, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(i2c2_clk, 1, PCCR0, 17, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(i2c1_clk, 0, PCCR0, 18, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt6_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt5_clk1, 0, PCCR0, 20, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt4_clk1, 0, PCCR0, 21, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt3_clk1, 0, PCCR0, 22, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt2_clk1, 0, PCCR0, 23, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt1_clk1, 0, PCCR0, 24, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpio_clk, 0, PCCR0, 25, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(fec_clk, 0, PCCR0, 26, NULL, &fec_clk1, &ahb_clk); +DEFINE_CLOCK(emma_clk, 0, PCCR0, 27, NULL, &emma_clk1, &ahb_clk); +DEFINE_CLOCK(dma_clk, 0, PCCR0, 28, NULL, &dma_clk1, &ahb_clk); +DEFINE_CLOCK(cspi13_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(cspi2_clk1, 0, PCCR0, 30, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(cspi1_clk1, 0, PCCR0, 31, NULL, NULL, &ipg_clk); + +DEFINE_CLOCK(mstick_clk, 0, PCCR1, 2, NULL, &mstick_clk1, &ipg_clk); +DEFINE_CLOCK(nfc_clk, 0, PCCR1, 3, get_rate_nfc, NULL, &cpu_clk); +DEFINE_CLOCK(ssi2_clk, 1, PCCR1, 4, get_rate_ssi2, &ssi2_clk1, &mpll_main2_clk); +DEFINE_CLOCK(ssi1_clk, 0, PCCR1, 5, get_rate_ssi1, &ssi1_clk1, &mpll_main2_clk); +DEFINE_CLOCK(vpu_clk, 0, PCCR1, 6, get_rate_vpu, &vpu_clk1, &mpll_main2_clk); +DEFINE_CLOCK1(per4_clk, 3, PCCR1, 7, per, NULL, &mpll_main2_clk); +DEFINE_CLOCK1(per3_clk, 2, PCCR1, 8, per, NULL, &mpll_main2_clk); +DEFINE_CLOCK1(per2_clk, 1, PCCR1, 9, per, NULL, &mpll_main2_clk); +DEFINE_CLOCK1(per1_clk, 0, PCCR1, 10, per, NULL, &mpll_main2_clk); +DEFINE_CLOCK(usb_clk1, 0, PCCR1, 11, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(slcdc_clk1, 0, PCCR1, 12, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(sahara2_clk1, 0, PCCR1, 13, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(rtic_clk1, 0, PCCR1, 14, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(lcdc_clk2, 0, PCCR1, 15, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(vpu_clk1, 0, PCCR1, 16, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(fec_clk1, 0, PCCR1, 17, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(emma_clk1, 0, PCCR1, 18, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(emi_clk, 0, PCCR1, 19, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(dma_clk1, 0, PCCR1, 20, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(csi_clk1, 0, PCCR1, 21, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(brom_clk, 0, PCCR1, 22, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(pata_clk, 0, PCCR1, 23, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(wdog_clk, 0, PCCR1, 24, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(usb_clk, 0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk); +DEFINE_CLOCK(uart6_clk1, 0, PCCR1, 26, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart5_clk1, 0, PCCR1, 27, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart4_clk1, 0, PCCR1, 28, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart3_clk1, 0, PCCR1, 29, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart2_clk1, 0, PCCR1, 30, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart1_clk1, 0, PCCR1, 31, NULL, NULL, &ipg_clk); + +/* Clocks we cannot directly gate, but drivers need their rates */ +DEFINE_CLOCK(cspi1_clk, 0, NULL, 0, NULL, &cspi1_clk1, &per2_clk); +DEFINE_CLOCK(cspi2_clk, 1, NULL, 0, NULL, &cspi2_clk1, &per2_clk); +DEFINE_CLOCK(cspi3_clk, 2, NULL, 0, NULL, &cspi13_clk1, &per2_clk); +DEFINE_CLOCK(sdhc1_clk, 0, NULL, 0, NULL, &sdhc1_clk1, &per2_clk); +DEFINE_CLOCK(sdhc2_clk, 1, NULL, 0, NULL, &sdhc2_clk1, &per2_clk); +DEFINE_CLOCK(sdhc3_clk, 2, NULL, 0, NULL, &sdhc3_clk1, &per2_clk); +DEFINE_CLOCK(pwm_clk, 0, NULL, 0, NULL, &pwm_clk1, &per1_clk); +DEFINE_CLOCK(gpt1_clk, 0, NULL, 0, NULL, &gpt1_clk1, &per1_clk); +DEFINE_CLOCK(gpt2_clk, 1, NULL, 0, NULL, &gpt2_clk1, &per1_clk); +DEFINE_CLOCK(gpt3_clk, 2, NULL, 0, NULL, &gpt3_clk1, &per1_clk); +DEFINE_CLOCK(gpt4_clk, 3, NULL, 0, NULL, &gpt4_clk1, &per1_clk); +DEFINE_CLOCK(gpt5_clk, 4, NULL, 0, NULL, &gpt5_clk1, &per1_clk); +DEFINE_CLOCK(gpt6_clk, 5, NULL, 0, NULL, &gpt6_clk1, &per1_clk); +DEFINE_CLOCK(uart1_clk, 0, NULL, 0, NULL, &uart1_clk1, &per1_clk); +DEFINE_CLOCK(uart2_clk, 1, NULL, 0, NULL, &uart2_clk1, &per1_clk); +DEFINE_CLOCK(uart3_clk, 2, NULL, 0, NULL, &uart3_clk1, &per1_clk); +DEFINE_CLOCK(uart4_clk, 3, NULL, 0, NULL, &uart4_clk1, &per1_clk); +DEFINE_CLOCK(uart5_clk, 4, NULL, 0, NULL, &uart5_clk1, &per1_clk); +DEFINE_CLOCK(uart6_clk, 5, NULL, 0, NULL, &uart6_clk1, &per1_clk); +DEFINE_CLOCK1(lcdc_clk, 0, NULL, 0, parent, &lcdc_clk1, &per3_clk); +DEFINE_CLOCK1(csi_clk, 0, NULL, 0, parent, &csi_clk1, &per4_clk); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] = { + /* i.mx27 has the i.mx21 type uart */ + _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK("imx21-uart.5", NULL, uart6_clk) + _REGISTER_CLOCK(NULL, "gpt1", gpt1_clk) + _REGISTER_CLOCK(NULL, "gpt2", gpt2_clk) + _REGISTER_CLOCK(NULL, "gpt3", gpt3_clk) + _REGISTER_CLOCK(NULL, "gpt4", gpt4_clk) + _REGISTER_CLOCK(NULL, "gpt5", gpt5_clk) + _REGISTER_CLOCK(NULL, "gpt6", gpt6_clk) + _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk) + _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) + _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) + _REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk) + _REGISTER_CLOCK("imx27-cspi.0", NULL, cspi1_clk) + _REGISTER_CLOCK("imx27-cspi.1", NULL, cspi2_clk) + _REGISTER_CLOCK("imx27-cspi.2", NULL, cspi3_clk) + _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) + _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) + _REGISTER_CLOCK(NULL, "vpu", vpu_clk) + _REGISTER_CLOCK(NULL, "dma", dma_clk) + _REGISTER_CLOCK(NULL, "rtic", rtic_clk) + _REGISTER_CLOCK(NULL, "brom", brom_clk) + _REGISTER_CLOCK(NULL, "emma", emma_clk) + _REGISTER_CLOCK("m2m-emmaprp.0", NULL, emma_clk) + _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk) + _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) + _REGISTER_CLOCK(NULL, "emi", emi_clk) + _REGISTER_CLOCK(NULL, "sahara2", sahara2_clk) + _REGISTER_CLOCK("pata_imx", NULL, pata_clk) + _REGISTER_CLOCK(NULL, "mstick", mstick_clk) + _REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK(NULL, "iim", iim_clk) + _REGISTER_CLOCK(NULL, "kpp", kpp_clk) + _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) + _REGISTER_CLOCK(NULL, "scc", scc_clk) +}; + +/* Adjust the clock path for TO2 and later */ +static void __init to2_adjust_clocks(void) +{ + unsigned long cscr = __raw_readl(CCM_CSCR); + + if (mx27_revision() >= IMX_CHIP_REVISION_2_0) { + if (cscr & CCM_CSCR_ARM_SRC) + cpu_clk.parent = &mpll_main1_clk; + + if (!(cscr & CCM_CSCR_SSI2)) + ssi1_clk.parent = &spll_clk; + + if (!(cscr & CCM_CSCR_SSI1)) + ssi1_clk.parent = &spll_clk; + + if (!(cscr & CCM_CSCR_VPU)) + vpu_clk.parent = &spll_clk; + } else { + cpu_clk.parent = &mpll_clk; + cpu_clk.set_parent = NULL; + cpu_clk.round_rate = NULL; + cpu_clk.set_rate = NULL; + ahb_clk.parent = &mpll_clk; + + per1_clk.parent = &mpll_clk; + per2_clk.parent = &mpll_clk; + per3_clk.parent = &mpll_clk; + per4_clk.parent = &mpll_clk; + + ssi1_clk.parent = &mpll_clk; + ssi2_clk.parent = &mpll_clk; + + vpu_clk.parent = &mpll_clk; + } +} + +/* + * must be called very early to get information about the + * available clock rate when the timer framework starts + */ +int __init mx27_clocks_init(unsigned long fref) +{ + u32 cscr = __raw_readl(CCM_CSCR); + + external_high_reference = fref; + + /* detect clock reference for both system PLLs */ + if (cscr & CCM_CSCR_MCU) + mpll_clk.parent = &ckih_clk; + else + mpll_clk.parent = &fpm_clk; + + if (cscr & CCM_CSCR_SP) + spll_clk.parent = &ckih_clk; + else + spll_clk.parent = &fpm_clk; + + to2_adjust_clocks(); + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + /* Turn off all clocks we do not need */ + __raw_writel(0, CCM_PCCR0); + __raw_writel((1 << 10) | (1 << 19), CCM_PCCR1); + + spll_clk.disable(&spll_clk); + + /* enable basic clocks */ + clk_enable(&per1_clk); + clk_enable(&gpio_clk); + clk_enable(&emi_clk); + clk_enable(&iim_clk); + imx_print_silicon_rev("i.MX27", mx27_revision()); + clk_disable(&iim_clk); + +#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) + clk_enable(&uart1_clk); +#endif + + mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), + MX27_INT_GPT1); + + return 0; +} + +#ifdef CONFIG_OF +int __init mx27_clocks_init_dt(void) +{ + struct device_node *np; + u32 fref = 26000000; /* default */ + + for_each_compatible_node(np, NULL, "fixed-clock") { + if (!of_device_is_compatible(np, "fsl,imx-osc26m")) + continue; + + if (!of_property_read_u32(np, "clock-frequency", &fref)) + break; + } + + return mx27_clocks_init(fref); +} +#endif diff --git a/arch/arm/mach-imx/clock-imx31.c b/arch/arm/mach-imx/clock-imx31.c new file mode 100644 index 00000000..3a943cd4 --- /dev/null +++ b/arch/arm/mach-imx/clock-imx31.c @@ -0,0 +1,630 @@ +/* + * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2008 by Sascha Hauer + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "crmregs-imx3.h" + +#define PRE_DIV_MIN_FREQ 10000000 /* Minimum Frequency after Predivider */ + +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post) +{ + u32 min_pre, temp_pre, old_err, err; + + if (div >= 512) { + *pre = 8; + *post = 64; + } else if (div >= 64) { + min_pre = (div - 1) / 64 + 1; + old_err = 8; + for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) { + err = div % temp_pre; + if (err == 0) { + *pre = temp_pre; + break; + } + err = temp_pre - err; + if (err < old_err) { + old_err = err; + *pre = temp_pre; + } + } + *post = (div + *pre - 1) / *pre; + } else if (div <= 8) { + *pre = div; + *post = 1; + } else { + *pre = 1; + *post = div; + } +} + +static struct clk mcu_pll_clk; +static struct clk serial_pll_clk; +static struct clk ipg_clk; +static struct clk ckih_clk; + +static int cgr_enable(struct clk *clk) +{ + u32 reg; + + if (!clk->enable_reg) + return 0; + + reg = __raw_readl(clk->enable_reg); + reg |= 3 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void cgr_disable(struct clk *clk) +{ + u32 reg; + + if (!clk->enable_reg) + return; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(3 << clk->enable_shift); + + /* special case for EMI clock */ + if (clk->enable_reg == MXC_CCM_CGR2 && clk->enable_shift == 8) + reg |= (1 << clk->enable_shift); + + __raw_writel(reg, clk->enable_reg); +} + +static unsigned long pll_ref_get_rate(void) +{ + unsigned long ccmr; + unsigned int prcs; + + ccmr = __raw_readl(MXC_CCM_CCMR); + prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET; + if (prcs == 0x1) + return CKIL_CLK_FREQ * 1024; + else + return clk_get_rate(&ckih_clk); +} + +static unsigned long usb_pll_get_rate(struct clk *clk) +{ + unsigned long reg; + + reg = __raw_readl(MXC_CCM_UPCTL); + + return mxc_decode_pll(reg, pll_ref_get_rate()); +} + +static unsigned long serial_pll_get_rate(struct clk *clk) +{ + unsigned long reg; + + reg = __raw_readl(MXC_CCM_SRPCTL); + + return mxc_decode_pll(reg, pll_ref_get_rate()); +} + +static unsigned long mcu_pll_get_rate(struct clk *clk) +{ + unsigned long reg, ccmr; + + ccmr = __raw_readl(MXC_CCM_CCMR); + + if (!(ccmr & MXC_CCM_CCMR_MPE) || (ccmr & MXC_CCM_CCMR_MDS)) + return clk_get_rate(&ckih_clk); + + reg = __raw_readl(MXC_CCM_MPCTL); + + return mxc_decode_pll(reg, pll_ref_get_rate()); +} + +static int usb_pll_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CCMR); + reg |= MXC_CCM_CCMR_UPE; + __raw_writel(reg, MXC_CCM_CCMR); + + /* No lock bit on MX31, so using max time from spec */ + udelay(80); + + return 0; +} + +static void usb_pll_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CCMR); + reg &= ~MXC_CCM_CCMR_UPE; + __raw_writel(reg, MXC_CCM_CCMR); +} + +static int serial_pll_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CCMR); + reg |= MXC_CCM_CCMR_SPE; + __raw_writel(reg, MXC_CCM_CCMR); + + /* No lock bit on MX31, so using max time from spec */ + udelay(80); + + return 0; +} + +static void serial_pll_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CCMR); + reg &= ~MXC_CCM_CCMR_SPE; + __raw_writel(reg, MXC_CCM_CCMR); +} + +#define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off) +#define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off) +#define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off) + +static unsigned long mcu_main_get_rate(struct clk *clk) +{ + u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0); + + if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL) + return clk_get_rate(&serial_pll_clk); + else + return clk_get_rate(&mcu_pll_clk); +} + +static unsigned long ahb_get_rate(struct clk *clk) +{ + unsigned long max_pdf; + + max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK, + MXC_CCM_PDR0_MAX_PODF_OFFSET); + return clk_get_rate(clk->parent) / (max_pdf + 1); +} + +static unsigned long ipg_get_rate(struct clk *clk) +{ + unsigned long ipg_pdf; + + ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK, + MXC_CCM_PDR0_IPG_PODF_OFFSET); + return clk_get_rate(clk->parent) / (ipg_pdf + 1); +} + +static unsigned long nfc_get_rate(struct clk *clk) +{ + unsigned long nfc_pdf; + + nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK, + MXC_CCM_PDR0_NFC_PODF_OFFSET); + return clk_get_rate(clk->parent) / (nfc_pdf + 1); +} + +static unsigned long hsp_get_rate(struct clk *clk) +{ + unsigned long hsp_pdf; + + hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK, + MXC_CCM_PDR0_HSP_PODF_OFFSET); + return clk_get_rate(clk->parent) / (hsp_pdf + 1); +} + +static unsigned long usb_get_rate(struct clk *clk) +{ + unsigned long usb_pdf, usb_prepdf; + + usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK, + MXC_CCM_PDR1_USB_PODF_OFFSET); + usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK, + MXC_CCM_PDR1_USB_PRDF_OFFSET); + return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1); +} + +static unsigned long csi_get_rate(struct clk *clk) +{ + u32 reg, pre, post; + + reg = __raw_readl(MXC_CCM_PDR0); + pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >> + MXC_CCM_PDR0_CSI_PRDF_OFFSET; + pre++; + post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >> + MXC_CCM_PDR0_CSI_PODF_OFFSET; + post++; + return clk_get_rate(clk->parent) / (pre * post); +} + +static unsigned long csi_round_rate(struct clk *clk, unsigned long rate) +{ + u32 pre, post, parent = clk_get_rate(clk->parent); + u32 div = parent / rate; + + if (parent % rate) + div++; + + __calc_pre_post_dividers(div, &pre, &post); + + return parent / (pre * post); +} + +static int csi_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div, pre, post, parent = clk_get_rate(clk->parent); + + div = parent / rate; + + if ((parent / div) != rate) + return -EINVAL; + + __calc_pre_post_dividers(div, &pre, &post); + + /* Set CSI clock divider */ + reg = __raw_readl(MXC_CCM_PDR0) & + ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK); + reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET; + reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET; + __raw_writel(reg, MXC_CCM_PDR0); + + return 0; +} + +static unsigned long ssi1_get_rate(struct clk *clk) +{ + unsigned long ssi1_pdf, ssi1_prepdf; + + ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK, + MXC_CCM_PDR1_SSI1_PODF_OFFSET); + ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK, + MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET); + return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1); +} + +static unsigned long ssi2_get_rate(struct clk *clk) +{ + unsigned long ssi2_pdf, ssi2_prepdf; + + ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK, + MXC_CCM_PDR1_SSI2_PODF_OFFSET); + ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK, + MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET); + return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1); +} + +static unsigned long firi_get_rate(struct clk *clk) +{ + unsigned long firi_pdf, firi_prepdf; + + firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK, + MXC_CCM_PDR1_FIRI_PODF_OFFSET); + firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK, + MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET); + return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1); +} + +static unsigned long firi_round_rate(struct clk *clk, unsigned long rate) +{ + u32 pre, post; + u32 parent = clk_get_rate(clk->parent); + u32 div = parent / rate; + + if (parent % rate) + div++; + + __calc_pre_post_dividers(div, &pre, &post); + + return parent / (pre * post); + +} + +static int firi_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div, pre, post, parent = clk_get_rate(clk->parent); + + div = parent / rate; + + if ((parent / div) != rate) + return -EINVAL; + + __calc_pre_post_dividers(div, &pre, &post); + + /* Set FIRI clock divider */ + reg = __raw_readl(MXC_CCM_PDR1) & + ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK); + reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET; + reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_PDR1); + + return 0; +} + +static unsigned long mbx_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 2; +} + +static unsigned long mstick1_get_rate(struct clk *clk) +{ + unsigned long msti_pdf; + + msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK, + MXC_CCM_PDR2_MST1_PDF_OFFSET); + return clk_get_rate(clk->parent) / (msti_pdf + 1); +} + +static unsigned long mstick2_get_rate(struct clk *clk) +{ + unsigned long msti_pdf; + + msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK, + MXC_CCM_PDR2_MST2_PDF_OFFSET); + return clk_get_rate(clk->parent) / (msti_pdf + 1); +} + +static unsigned long ckih_rate; + +static unsigned long clk_ckih_get_rate(struct clk *clk) +{ + return ckih_rate; +} + +static unsigned long clk_ckil_get_rate(struct clk *clk) +{ + return CKIL_CLK_FREQ; +} + +static struct clk ckih_clk = { + .get_rate = clk_ckih_get_rate, +}; + +static struct clk mcu_pll_clk = { + .parent = &ckih_clk, + .get_rate = mcu_pll_get_rate, +}; + +static struct clk mcu_main_clk = { + .parent = &mcu_pll_clk, + .get_rate = mcu_main_get_rate, +}; + +static struct clk serial_pll_clk = { + .parent = &ckih_clk, + .get_rate = serial_pll_get_rate, + .enable = serial_pll_enable, + .disable = serial_pll_disable, +}; + +static struct clk usb_pll_clk = { + .parent = &ckih_clk, + .get_rate = usb_pll_get_rate, + .enable = usb_pll_enable, + .disable = usb_pll_disable, +}; + +static struct clk ahb_clk = { + .parent = &mcu_main_clk, + .get_rate = ahb_get_rate, +}; + +#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .enable = cgr_enable, \ + .disable = cgr_disable, \ + .secondary = s, \ + .parent = p, \ + } + +#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = getsetround##_get_rate, \ + .set_rate = getsetround##_set_rate, \ + .round_rate = getsetround##_round_rate, \ + .enable = cgr_enable, \ + .disable = cgr_disable, \ + .secondary = s, \ + .parent = p, \ + } + +DEFINE_CLOCK(perclk_clk, 0, NULL, 0, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(ckil_clk, 0, NULL, 0, clk_ckil_get_rate, NULL, NULL); + +DEFINE_CLOCK(sdhc1_clk, 0, MXC_CCM_CGR0, 0, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(sdhc2_clk, 1, MXC_CCM_CGR0, 2, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CGR0, 4, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(epit1_clk, 0, MXC_CCM_CGR0, 6, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(epit2_clk, 1, MXC_CCM_CGR0, 8, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(iim_clk, 0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(sdma_clk1, 0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(cspi3_clk, 2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(rng_clk, 0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CGR0, 22, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CGR0, 24, ssi1_get_rate, NULL, &serial_pll_clk); +DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CGR0, 26, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CGR0, 28, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(i2c3_clk, 2, MXC_CCM_CGR0, 30, NULL, NULL, &perclk_clk); + +DEFINE_CLOCK(mpeg4_clk, 0, MXC_CCM_CGR1, 0, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1, 2, mstick1_get_rate, NULL, &usb_pll_clk); +DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1, 4, mstick2_get_rate, NULL, &usb_pll_clk); +DEFINE_CLOCK1(csi_clk, 0, MXC_CCM_CGR1, 6, csi, NULL, &serial_pll_clk); +DEFINE_CLOCK(rtc_clk, 0, MXC_CCM_CGR1, 8, NULL, NULL, &ckil_clk); +DEFINE_CLOCK(wdog_clk, 0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(pwm_clk, 0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(usb_clk2, 0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk); +DEFINE_CLOCK(kpp_clk, 0, MXC_CCM_CGR1, 20, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(ipu_clk, 0, MXC_CCM_CGR1, 22, hsp_get_rate, NULL, &mcu_main_clk); +DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CGR1, 24, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CGR1, 26, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CGR1, 28, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(owire_clk, 0, MXC_CCM_CGR1, 30, NULL, NULL, &perclk_clk); + +DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CGR2, 0, ssi2_get_rate, NULL, &serial_pll_clk); +DEFINE_CLOCK(cspi1_clk, 0, MXC_CCM_CGR2, 2, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(cspi2_clk, 1, MXC_CCM_CGR2, 4, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(mbx_clk, 0, MXC_CCM_CGR2, 6, mbx_get_rate, NULL, &ahb_clk); +DEFINE_CLOCK(emi_clk, 0, MXC_CCM_CGR2, 8, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(rtic_clk, 0, MXC_CCM_CGR2, 10, NULL, NULL, &ahb_clk); +DEFINE_CLOCK1(firi_clk, 0, MXC_CCM_CGR2, 12, firi, NULL, &usb_pll_clk); + +DEFINE_CLOCK(sdma_clk2, 0, NULL, 0, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(usb_clk1, 0, NULL, 0, usb_get_rate, NULL, &usb_pll_clk); +DEFINE_CLOCK(nfc_clk, 0, NULL, 0, nfc_get_rate, NULL, &ahb_clk); +DEFINE_CLOCK(scc_clk, 0, NULL, 0, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] = { + _REGISTER_CLOCK(NULL, "emi", emi_clk) + _REGISTER_CLOCK("imx31-cspi.0", NULL, cspi1_clk) + _REGISTER_CLOCK("imx31-cspi.1", NULL, cspi2_clk) + _REGISTER_CLOCK("imx31-cspi.2", NULL, cspi3_clk) + _REGISTER_CLOCK(NULL, "gpt", gpt_clk) + _REGISTER_CLOCK(NULL, "pwm", pwm_clk) + _REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) + _REGISTER_CLOCK(NULL, "epit", epit1_clk) + _REGISTER_CLOCK(NULL, "epit", epit2_clk) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) + _REGISTER_CLOCK("ipu-core", NULL, ipu_clk) + _REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk) + _REGISTER_CLOCK(NULL, "kpp", kpp_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk2) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk2) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk2) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2) + _REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk) + /* i.mx31 has the i.mx21 type uart */ + _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk) + _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) + _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) + _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK(NULL, "firi", firi_clk) + _REGISTER_CLOCK("pata_imx", NULL, pata_clk) + _REGISTER_CLOCK(NULL, "rtic", rtic_clk) + _REGISTER_CLOCK(NULL, "rng", rng_clk) + _REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1) + _REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2) + _REGISTER_CLOCK(NULL, "mstick", mstick1_clk) + _REGISTER_CLOCK(NULL, "mstick", mstick2_clk) + _REGISTER_CLOCK(NULL, "scc", scc_clk) + _REGISTER_CLOCK(NULL, "iim", iim_clk) + _REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk) + _REGISTER_CLOCK(NULL, "mbx", mbx_clk) +}; + +int __init mx31_clocks_init(unsigned long fref) +{ + u32 reg; + + ckih_rate = fref; + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + /* change the csi_clk parent if necessary */ + reg = __raw_readl(MXC_CCM_CCMR); + if (!(reg & MXC_CCM_CCMR_CSCS)) + if (clk_set_parent(&csi_clk, &usb_pll_clk)) + pr_err("%s: error changing csi_clk parent\n", __func__); + + + /* Turn off all possible clocks */ + __raw_writel((3 << 4), MXC_CCM_CGR0); + __raw_writel(0, MXC_CCM_CGR1); + __raw_writel((3 << 8) | (3 << 14) | (3 << 16)| + 1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for + MX32, but still required to be set */ + MXC_CCM_CGR2); + + /* + * Before turning off usb_pll make sure ipg_per_clk is generated + * by ipg_clk and not usb_pll. + */ + __raw_writel(__raw_readl(MXC_CCM_CCMR) | (1 << 24), MXC_CCM_CCMR); + + usb_pll_disable(&usb_pll_clk); + + pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk)); + + clk_enable(&gpt_clk); + clk_enable(&emi_clk); + clk_enable(&iim_clk); + mx31_revision(); + clk_disable(&iim_clk); + + clk_enable(&serial_pll_clk); + + if (mx31_revision() >= IMX_CHIP_REVISION_2_0) { + reg = __raw_readl(MXC_CCM_PMCR1); + /* No PLL restart on DVFS switch; enable auto EMI handshake */ + reg |= MXC_CCM_PMCR1_PLLRDIS | MXC_CCM_PMCR1_EMIRQ_EN; + __raw_writel(reg, MXC_CCM_PMCR1); + } + + mxc_timer_init(&ipg_clk, MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR), + MX31_INT_GPT); + + return 0; +} diff --git a/arch/arm/mach-imx/clock-imx35.c b/arch/arm/mach-imx/clock-imx35.c new file mode 100644 index 00000000..e56c1a83 --- /dev/null +++ b/arch/arm/mach-imx/clock-imx35.c @@ -0,0 +1,536 @@ +/* + * Copyright (C) 2009 by Sascha Hauer, Pengutronix + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "crmregs-imx3.h" + +#ifdef HAVE_SET_RATE_SUPPORT +static void calc_dividers(u32 div, u32 *pre, u32 *post, u32 maxpost) +{ + u32 min_pre, temp_pre, old_err, err; + + min_pre = (div - 1) / maxpost + 1; + old_err = 8; + + for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) { + if (div > (temp_pre * maxpost)) + break; + + if (div < (temp_pre * temp_pre)) + continue; + + err = div % temp_pre; + + if (err == 0) { + *pre = temp_pre; + break; + } + + err = temp_pre - err; + + if (err < old_err) { + old_err = err; + *pre = temp_pre; + } + } + + *post = (div + *pre - 1) / *pre; +} + +/* get the best values for a 3-bit divider combined with a 6-bit divider */ +static void calc_dividers_3_6(u32 div, u32 *pre, u32 *post) +{ + if (div >= 512) { + *pre = 8; + *post = 64; + } else if (div >= 64) { + calc_dividers(div, pre, post, 64); + } else if (div <= 8) { + *pre = div; + *post = 1; + } else { + *pre = 1; + *post = div; + } +} + +/* get the best values for two cascaded 3-bit dividers */ +static void calc_dividers_3_3(u32 div, u32 *pre, u32 *post) +{ + if (div >= 64) { + *pre = *post = 8; + } else if (div > 8) { + calc_dividers(div, pre, post, 8); + } else { + *pre = 1; + *post = div; + } +} +#endif + +static unsigned long get_rate_mpll(void) +{ + ulong mpctl = __raw_readl(MX35_CCM_MPCTL); + + return mxc_decode_pll(mpctl, 24000000); +} + +static unsigned long get_rate_ppll(void) +{ + ulong ppctl = __raw_readl(MX35_CCM_PPCTL); + + return mxc_decode_pll(ppctl, 24000000); +} + +struct arm_ahb_div { + unsigned char arm, ahb, sel; +}; + +static struct arm_ahb_div clk_consumer[] = { + { .arm = 1, .ahb = 4, .sel = 0}, + { .arm = 1, .ahb = 3, .sel = 1}, + { .arm = 2, .ahb = 2, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 4, .ahb = 1, .sel = 0}, + { .arm = 1, .ahb = 5, .sel = 0}, + { .arm = 1, .ahb = 8, .sel = 0}, + { .arm = 1, .ahb = 6, .sel = 1}, + { .arm = 2, .ahb = 4, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 4, .ahb = 2, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, +}; + +static unsigned long get_rate_arm(void) +{ + unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0); + struct arm_ahb_div *aad; + unsigned long fref = get_rate_mpll(); + + aad = &clk_consumer[(pdr0 >> 16) & 0xf]; + if (aad->sel) + fref = fref * 3 / 4; + + return fref / aad->arm; +} + +static unsigned long get_rate_ahb(struct clk *clk) +{ + unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0); + struct arm_ahb_div *aad; + unsigned long fref = get_rate_arm(); + + aad = &clk_consumer[(pdr0 >> 16) & 0xf]; + + return fref / aad->ahb; +} + +static unsigned long get_rate_ipg(struct clk *clk) +{ + return get_rate_ahb(NULL) >> 1; +} + +static unsigned long get_rate_uart(struct clk *clk) +{ + unsigned long pdr3 = __raw_readl(MX35_CCM_PDR3); + unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4); + unsigned long div = ((pdr4 >> 10) & 0x3f) + 1; + + if (pdr3 & (1 << 14)) + return get_rate_arm() / div; + else + return get_rate_ppll() / div; +} + +static unsigned long get_rate_sdhc(struct clk *clk) +{ + unsigned long pdr3 = __raw_readl(MX35_CCM_PDR3); + unsigned long div, rate; + + if (pdr3 & (1 << 6)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + switch (clk->id) { + default: + case 0: + div = pdr3 & 0x3f; + break; + case 1: + div = (pdr3 >> 8) & 0x3f; + break; + case 2: + div = (pdr3 >> 16) & 0x3f; + break; + } + + return rate / (div + 1); +} + +static unsigned long get_rate_mshc(struct clk *clk) +{ + unsigned long pdr1 = __raw_readl(MXC_CCM_PDR1); + unsigned long div1, div2, rate; + + if (pdr1 & (1 << 7)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + div1 = (pdr1 >> 29) & 0x7; + div2 = (pdr1 >> 22) & 0x3f; + + return rate / ((div1 + 1) * (div2 + 1)); +} + +static unsigned long get_rate_ssi(struct clk *clk) +{ + unsigned long pdr2 = __raw_readl(MX35_CCM_PDR2); + unsigned long div1, div2, rate; + + if (pdr2 & (1 << 6)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + switch (clk->id) { + default: + case 0: + div1 = pdr2 & 0x3f; + div2 = (pdr2 >> 24) & 0x7; + break; + case 1: + div1 = (pdr2 >> 8) & 0x3f; + div2 = (pdr2 >> 27) & 0x7; + break; + } + + return rate / ((div1 + 1) * (div2 + 1)); +} + +static unsigned long get_rate_csi(struct clk *clk) +{ + unsigned long pdr2 = __raw_readl(MX35_CCM_PDR2); + unsigned long rate; + + if (pdr2 & (1 << 7)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + return rate / (((pdr2 >> 16) & 0x3f) + 1); +} + +static unsigned long get_rate_otg(struct clk *clk) +{ + unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4); + unsigned long rate; + + if (pdr4 & (1 << 9)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + return rate / (((pdr4 >> 22) & 0x3f) + 1); +} + +static unsigned long get_rate_ipg_per(struct clk *clk) +{ + unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0); + unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4); + unsigned long div; + + if (pdr0 & (1 << 26)) { + div = (pdr4 >> 16) & 0x3f; + return get_rate_arm() / (div + 1); + } else { + div = (pdr0 >> 12) & 0x7; + return get_rate_ahb(NULL) / (div + 1); + } +} + +static unsigned long get_rate_hsp(struct clk *clk) +{ + unsigned long hsp_podf = (__raw_readl(MXC_CCM_PDR0) >> 20) & 0x03; + unsigned long fref = get_rate_mpll(); + + if (fref > 400 * 1000 * 1000) { + switch (hsp_podf) { + case 0: + return fref >> 2; + case 1: + return fref >> 3; + case 2: + return fref / 3; + } + } else { + switch (hsp_podf) { + case 0: + case 2: + return fref / 3; + case 1: + return fref / 6; + } + } + + return 0; +} + +static int clk_cgr_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 3 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void clk_cgr_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(3 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +#define DEFINE_CLOCK(name, i, er, es, gr, sr) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .set_rate = sr, \ + .enable = clk_cgr_enable, \ + .disable = clk_cgr_disable, \ + } + +DEFINE_CLOCK(asrc_clk, 0, MX35_CCM_CGR0, 0, NULL, NULL); +DEFINE_CLOCK(pata_clk, 0, MX35_CCM_CGR0, 2, get_rate_ipg, NULL); +/* DEFINE_CLOCK(audmux_clk, 0, MX35_CCM_CGR0, 4, NULL, NULL); */ +DEFINE_CLOCK(can1_clk, 0, MX35_CCM_CGR0, 6, get_rate_ipg, NULL); +DEFINE_CLOCK(can2_clk, 1, MX35_CCM_CGR0, 8, get_rate_ipg, NULL); +DEFINE_CLOCK(cspi1_clk, 0, MX35_CCM_CGR0, 10, get_rate_ipg, NULL); +DEFINE_CLOCK(cspi2_clk, 1, MX35_CCM_CGR0, 12, get_rate_ipg, NULL); +DEFINE_CLOCK(ect_clk, 0, MX35_CCM_CGR0, 14, get_rate_ipg, NULL); +DEFINE_CLOCK(edio_clk, 0, MX35_CCM_CGR0, 16, NULL, NULL); +DEFINE_CLOCK(emi_clk, 0, MX35_CCM_CGR0, 18, get_rate_ipg, NULL); +DEFINE_CLOCK(epit1_clk, 0, MX35_CCM_CGR0, 20, get_rate_ipg, NULL); +DEFINE_CLOCK(epit2_clk, 1, MX35_CCM_CGR0, 22, get_rate_ipg, NULL); +DEFINE_CLOCK(esai_clk, 0, MX35_CCM_CGR0, 24, NULL, NULL); +DEFINE_CLOCK(esdhc1_clk, 0, MX35_CCM_CGR0, 26, get_rate_sdhc, NULL); +DEFINE_CLOCK(esdhc2_clk, 1, MX35_CCM_CGR0, 28, get_rate_sdhc, NULL); +DEFINE_CLOCK(esdhc3_clk, 2, MX35_CCM_CGR0, 30, get_rate_sdhc, NULL); + +DEFINE_CLOCK(fec_clk, 0, MX35_CCM_CGR1, 0, get_rate_ipg, NULL); +DEFINE_CLOCK(gpio1_clk, 0, MX35_CCM_CGR1, 2, NULL, NULL); +DEFINE_CLOCK(gpio2_clk, 1, MX35_CCM_CGR1, 4, NULL, NULL); +DEFINE_CLOCK(gpio3_clk, 2, MX35_CCM_CGR1, 6, NULL, NULL); +DEFINE_CLOCK(gpt_clk, 0, MX35_CCM_CGR1, 8, get_rate_ipg, NULL); +DEFINE_CLOCK(i2c1_clk, 0, MX35_CCM_CGR1, 10, get_rate_ipg_per, NULL); +DEFINE_CLOCK(i2c2_clk, 1, MX35_CCM_CGR1, 12, get_rate_ipg_per, NULL); +DEFINE_CLOCK(i2c3_clk, 2, MX35_CCM_CGR1, 14, get_rate_ipg_per, NULL); +DEFINE_CLOCK(iomuxc_clk, 0, MX35_CCM_CGR1, 16, NULL, NULL); +DEFINE_CLOCK(ipu_clk, 0, MX35_CCM_CGR1, 18, get_rate_hsp, NULL); +DEFINE_CLOCK(kpp_clk, 0, MX35_CCM_CGR1, 20, get_rate_ipg, NULL); +DEFINE_CLOCK(mlb_clk, 0, MX35_CCM_CGR1, 22, get_rate_ahb, NULL); +DEFINE_CLOCK(mshc_clk, 0, MX35_CCM_CGR1, 24, get_rate_mshc, NULL); +DEFINE_CLOCK(owire_clk, 0, MX35_CCM_CGR1, 26, get_rate_ipg_per, NULL); +DEFINE_CLOCK(pwm_clk, 0, MX35_CCM_CGR1, 28, get_rate_ipg_per, NULL); +DEFINE_CLOCK(rngc_clk, 0, MX35_CCM_CGR1, 30, get_rate_ipg, NULL); + +DEFINE_CLOCK(rtc_clk, 0, MX35_CCM_CGR2, 0, get_rate_ipg, NULL); +DEFINE_CLOCK(rtic_clk, 0, MX35_CCM_CGR2, 2, get_rate_ahb, NULL); +DEFINE_CLOCK(scc_clk, 0, MX35_CCM_CGR2, 4, get_rate_ipg, NULL); +DEFINE_CLOCK(sdma_clk, 0, MX35_CCM_CGR2, 6, NULL, NULL); +DEFINE_CLOCK(spba_clk, 0, MX35_CCM_CGR2, 8, get_rate_ipg, NULL); +DEFINE_CLOCK(spdif_clk, 0, MX35_CCM_CGR2, 10, NULL, NULL); +DEFINE_CLOCK(ssi1_clk, 0, MX35_CCM_CGR2, 12, get_rate_ssi, NULL); +DEFINE_CLOCK(ssi2_clk, 1, MX35_CCM_CGR2, 14, get_rate_ssi, NULL); +DEFINE_CLOCK(uart1_clk, 0, MX35_CCM_CGR2, 16, get_rate_uart, NULL); +DEFINE_CLOCK(uart2_clk, 1, MX35_CCM_CGR2, 18, get_rate_uart, NULL); +DEFINE_CLOCK(uart3_clk, 2, MX35_CCM_CGR2, 20, get_rate_uart, NULL); +DEFINE_CLOCK(usbotg_clk, 0, MX35_CCM_CGR2, 22, get_rate_otg, NULL); +DEFINE_CLOCK(wdog_clk, 0, MX35_CCM_CGR2, 24, NULL, NULL); +DEFINE_CLOCK(max_clk, 0, MX35_CCM_CGR2, 26, NULL, NULL); +DEFINE_CLOCK(audmux_clk, 0, MX35_CCM_CGR2, 30, NULL, NULL); + +DEFINE_CLOCK(csi_clk, 0, MX35_CCM_CGR3, 0, get_rate_csi, NULL); +DEFINE_CLOCK(iim_clk, 0, MX35_CCM_CGR3, 2, NULL, NULL); +DEFINE_CLOCK(gpu2d_clk, 0, MX35_CCM_CGR3, 4, NULL, NULL); + +DEFINE_CLOCK(usbahb_clk, 0, 0, 0, get_rate_ahb, NULL); + +static int clk_dummy_enable(struct clk *clk) +{ + return 0; +} + +static void clk_dummy_disable(struct clk *clk) +{ +} + +static unsigned long get_rate_nfc(struct clk *clk) +{ + unsigned long div1; + + div1 = (__raw_readl(MX35_CCM_PDR4) >> 28) + 1; + + return get_rate_ahb(NULL) / div1; +} + +/* NAND Controller: It seems it can't be disabled */ +static struct clk nfc_clk = { + .id = 0, + .enable_reg = 0, + .enable_shift = 0, + .get_rate = get_rate_nfc, + .set_rate = NULL, /* set_rate_nfc, */ + .enable = clk_dummy_enable, + .disable = clk_dummy_disable +}; + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] = { + _REGISTER_CLOCK(NULL, "asrc", asrc_clk) + _REGISTER_CLOCK("pata_imx", NULL, pata_clk) + _REGISTER_CLOCK("flexcan.0", NULL, can1_clk) + _REGISTER_CLOCK("flexcan.1", NULL, can2_clk) + _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk) + _REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk) + _REGISTER_CLOCK(NULL, "ect", ect_clk) + _REGISTER_CLOCK(NULL, "edio", edio_clk) + _REGISTER_CLOCK(NULL, "emi", emi_clk) + _REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk) + _REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk) + _REGISTER_CLOCK(NULL, "esai", esai_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx35.0", NULL, esdhc1_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx35.1", NULL, esdhc2_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx35.2", NULL, esdhc3_clk) + /* i.mx35 has the i.mx27 type fec */ + _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio1_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio2_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio3_clk) + _REGISTER_CLOCK("gpt.0", NULL, gpt_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk) + _REGISTER_CLOCK(NULL, "iomuxc", iomuxc_clk) + _REGISTER_CLOCK("ipu-core", NULL, ipu_clk) + _REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk) + _REGISTER_CLOCK(NULL, "kpp", kpp_clk) + _REGISTER_CLOCK(NULL, "mlb", mlb_clk) + _REGISTER_CLOCK(NULL, "mshc", mshc_clk) + _REGISTER_CLOCK("mxc_w1", NULL, owire_clk) + _REGISTER_CLOCK(NULL, "pwm", pwm_clk) + _REGISTER_CLOCK(NULL, "rngc", rngc_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) + _REGISTER_CLOCK(NULL, "rtic", rtic_clk) + _REGISTER_CLOCK(NULL, "scc", scc_clk) + _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) + _REGISTER_CLOCK(NULL, "spba", spba_clk) + _REGISTER_CLOCK(NULL, "spdif", spdif_clk) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + /* i.mx35 has the i.mx21 type uart */ + _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usbahb_clk) + _REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk) + _REGISTER_CLOCK(NULL, "max", max_clk) + _REGISTER_CLOCK(NULL, "audmux", audmux_clk) + _REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk) + _REGISTER_CLOCK(NULL, "iim", iim_clk) + _REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) +}; + +int __init mx35_clocks_init() +{ + unsigned int cgr2 = 3 << 26; + +#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) + cgr2 |= 3 << 16; +#endif + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + /* Turn off all clocks except the ones we need to survive, namely: + * EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart + */ + __raw_writel((3 << 18), MX35_CCM_CGR0); + __raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16), + MX35_CCM_CGR1); + __raw_writel(cgr2, MX35_CCM_CGR2); + __raw_writel(0, MX35_CCM_CGR3); + + clk_enable(&iim_clk); + imx_print_silicon_rev("i.MX35", mx35_revision()); + clk_disable(&iim_clk); + + /* + * Check if we came up in internal boot mode. If yes, we need some + * extra clocks turned on, otherwise the MX35 boot ROM code will + * hang after a watchdog reset. + */ + if (!(__raw_readl(MX35_CCM_RCSR) & (3 << 10))) { + /* Additionally turn on UART1, SCC, and IIM clocks */ + clk_enable(&iim_clk); + clk_enable(&uart1_clk); + clk_enable(&scc_clk); + } + +#ifdef CONFIG_MXC_USE_EPIT + epit_timer_init(&epit1_clk, + MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1); +#else + mxc_timer_init(&gpt_clk, + MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT); +#endif + + return 0; +} diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c new file mode 100644 index 00000000..111c328f --- /dev/null +++ b/arch/arm/mach-imx/clock-imx6q.c @@ -0,0 +1,2111 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLL_BASE IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR) +#define PLL1_SYS (PLL_BASE + 0x000) +#define PLL2_BUS (PLL_BASE + 0x030) +#define PLL3_USB_OTG (PLL_BASE + 0x010) +#define PLL4_AUDIO (PLL_BASE + 0x070) +#define PLL5_VIDEO (PLL_BASE + 0x0a0) +#define PLL6_MLB (PLL_BASE + 0x0d0) +#define PLL7_USB_HOST (PLL_BASE + 0x020) +#define PLL8_ENET (PLL_BASE + 0x0e0) +#define PFD_480 (PLL_BASE + 0x0f0) +#define PFD_528 (PLL_BASE + 0x100) +#define PLL_NUM_OFFSET 0x010 +#define PLL_DENOM_OFFSET 0x020 + +#define PFD0 7 +#define PFD1 15 +#define PFD2 23 +#define PFD3 31 +#define PFD_FRAC_MASK 0x3f + +#define BM_PLL_BYPASS (0x1 << 16) +#define BM_PLL_ENABLE (0x1 << 13) +#define BM_PLL_POWER_DOWN (0x1 << 12) +#define BM_PLL_LOCK (0x1 << 31) +#define BP_PLL_SYS_DIV_SELECT 0 +#define BM_PLL_SYS_DIV_SELECT (0x7f << 0) +#define BP_PLL_BUS_DIV_SELECT 0 +#define BM_PLL_BUS_DIV_SELECT (0x1 << 0) +#define BP_PLL_USB_DIV_SELECT 0 +#define BM_PLL_USB_DIV_SELECT (0x3 << 0) +#define BP_PLL_AV_DIV_SELECT 0 +#define BM_PLL_AV_DIV_SELECT (0x7f << 0) +#define BP_PLL_ENET_DIV_SELECT 0 +#define BM_PLL_ENET_DIV_SELECT (0x3 << 0) +#define BM_PLL_ENET_EN_PCIE (0x1 << 19) +#define BM_PLL_ENET_EN_SATA (0x1 << 20) + +#define CCM_BASE IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR) +#define CCR (CCM_BASE + 0x00) +#define CCDR (CCM_BASE + 0x04) +#define CSR (CCM_BASE + 0x08) +#define CCSR (CCM_BASE + 0x0c) +#define CACRR (CCM_BASE + 0x10) +#define CBCDR (CCM_BASE + 0x14) +#define CBCMR (CCM_BASE + 0x18) +#define CSCMR1 (CCM_BASE + 0x1c) +#define CSCMR2 (CCM_BASE + 0x20) +#define CSCDR1 (CCM_BASE + 0x24) +#define CS1CDR (CCM_BASE + 0x28) +#define CS2CDR (CCM_BASE + 0x2c) +#define CDCDR (CCM_BASE + 0x30) +#define CHSCCDR (CCM_BASE + 0x34) +#define CSCDR2 (CCM_BASE + 0x38) +#define CSCDR3 (CCM_BASE + 0x3c) +#define CSCDR4 (CCM_BASE + 0x40) +#define CWDR (CCM_BASE + 0x44) +#define CDHIPR (CCM_BASE + 0x48) +#define CDCR (CCM_BASE + 0x4c) +#define CTOR (CCM_BASE + 0x50) +#define CLPCR (CCM_BASE + 0x54) +#define CISR (CCM_BASE + 0x58) +#define CIMR (CCM_BASE + 0x5c) +#define CCOSR (CCM_BASE + 0x60) +#define CGPR (CCM_BASE + 0x64) +#define CCGR0 (CCM_BASE + 0x68) +#define CCGR1 (CCM_BASE + 0x6c) +#define CCGR2 (CCM_BASE + 0x70) +#define CCGR3 (CCM_BASE + 0x74) +#define CCGR4 (CCM_BASE + 0x78) +#define CCGR5 (CCM_BASE + 0x7c) +#define CCGR6 (CCM_BASE + 0x80) +#define CCGR7 (CCM_BASE + 0x84) +#define CMEOR (CCM_BASE + 0x88) + +#define CG0 0 +#define CG1 2 +#define CG2 4 +#define CG3 6 +#define CG4 8 +#define CG5 10 +#define CG6 12 +#define CG7 14 +#define CG8 16 +#define CG9 18 +#define CG10 20 +#define CG11 22 +#define CG12 24 +#define CG13 26 +#define CG14 28 +#define CG15 30 + +#define BM_CCSR_PLL1_SW_SEL (0x1 << 2) +#define BM_CCSR_STEP_SEL (0x1 << 8) + +#define BP_CACRR_ARM_PODF 0 +#define BM_CACRR_ARM_PODF (0x7 << 0) + +#define BP_CBCDR_PERIPH2_CLK2_PODF 0 +#define BM_CBCDR_PERIPH2_CLK2_PODF (0x7 << 0) +#define BP_CBCDR_MMDC_CH1_AXI_PODF 3 +#define BM_CBCDR_MMDC_CH1_AXI_PODF (0x7 << 3) +#define BP_CBCDR_AXI_SEL 6 +#define BM_CBCDR_AXI_SEL (0x3 << 6) +#define BP_CBCDR_IPG_PODF 8 +#define BM_CBCDR_IPG_PODF (0x3 << 8) +#define BP_CBCDR_AHB_PODF 10 +#define BM_CBCDR_AHB_PODF (0x7 << 10) +#define BP_CBCDR_AXI_PODF 16 +#define BM_CBCDR_AXI_PODF (0x7 << 16) +#define BP_CBCDR_MMDC_CH0_AXI_PODF 19 +#define BM_CBCDR_MMDC_CH0_AXI_PODF (0x7 << 19) +#define BP_CBCDR_PERIPH_CLK_SEL 25 +#define BM_CBCDR_PERIPH_CLK_SEL (0x1 << 25) +#define BP_CBCDR_PERIPH2_CLK_SEL 26 +#define BM_CBCDR_PERIPH2_CLK_SEL (0x1 << 26) +#define BP_CBCDR_PERIPH_CLK2_PODF 27 +#define BM_CBCDR_PERIPH_CLK2_PODF (0x7 << 27) + +#define BP_CBCMR_GPU2D_AXI_SEL 0 +#define BM_CBCMR_GPU2D_AXI_SEL (0x1 << 0) +#define BP_CBCMR_GPU3D_AXI_SEL 1 +#define BM_CBCMR_GPU3D_AXI_SEL (0x1 << 1) +#define BP_CBCMR_GPU3D_CORE_SEL 4 +#define BM_CBCMR_GPU3D_CORE_SEL (0x3 << 4) +#define BP_CBCMR_GPU3D_SHADER_SEL 8 +#define BM_CBCMR_GPU3D_SHADER_SEL (0x3 << 8) +#define BP_CBCMR_PCIE_AXI_SEL 10 +#define BM_CBCMR_PCIE_AXI_SEL (0x1 << 10) +#define BP_CBCMR_VDO_AXI_SEL 11 +#define BM_CBCMR_VDO_AXI_SEL (0x1 << 11) +#define BP_CBCMR_PERIPH_CLK2_SEL 12 +#define BM_CBCMR_PERIPH_CLK2_SEL (0x3 << 12) +#define BP_CBCMR_VPU_AXI_SEL 14 +#define BM_CBCMR_VPU_AXI_SEL (0x3 << 14) +#define BP_CBCMR_GPU2D_CORE_SEL 16 +#define BM_CBCMR_GPU2D_CORE_SEL (0x3 << 16) +#define BP_CBCMR_PRE_PERIPH_CLK_SEL 18 +#define BM_CBCMR_PRE_PERIPH_CLK_SEL (0x3 << 18) +#define BP_CBCMR_PERIPH2_CLK2_SEL 20 +#define BM_CBCMR_PERIPH2_CLK2_SEL (0x1 << 20) +#define BP_CBCMR_PRE_PERIPH2_CLK_SEL 21 +#define BM_CBCMR_PRE_PERIPH2_CLK_SEL (0x3 << 21) +#define BP_CBCMR_GPU2D_CORE_PODF 23 +#define BM_CBCMR_GPU2D_CORE_PODF (0x7 << 23) +#define BP_CBCMR_GPU3D_CORE_PODF 26 +#define BM_CBCMR_GPU3D_CORE_PODF (0x7 << 26) +#define BP_CBCMR_GPU3D_SHADER_PODF 29 +#define BM_CBCMR_GPU3D_SHADER_PODF (0x7 << 29) + +#define BP_CSCMR1_PERCLK_PODF 0 +#define BM_CSCMR1_PERCLK_PODF (0x3f << 0) +#define BP_CSCMR1_SSI1_SEL 10 +#define BM_CSCMR1_SSI1_SEL (0x3 << 10) +#define BP_CSCMR1_SSI2_SEL 12 +#define BM_CSCMR1_SSI2_SEL (0x3 << 12) +#define BP_CSCMR1_SSI3_SEL 14 +#define BM_CSCMR1_SSI3_SEL (0x3 << 14) +#define BP_CSCMR1_USDHC1_SEL 16 +#define BM_CSCMR1_USDHC1_SEL (0x1 << 16) +#define BP_CSCMR1_USDHC2_SEL 17 +#define BM_CSCMR1_USDHC2_SEL (0x1 << 17) +#define BP_CSCMR1_USDHC3_SEL 18 +#define BM_CSCMR1_USDHC3_SEL (0x1 << 18) +#define BP_CSCMR1_USDHC4_SEL 19 +#define BM_CSCMR1_USDHC4_SEL (0x1 << 19) +#define BP_CSCMR1_EMI_PODF 20 +#define BM_CSCMR1_EMI_PODF (0x7 << 20) +#define BP_CSCMR1_EMI_SLOW_PODF 23 +#define BM_CSCMR1_EMI_SLOW_PODF (0x7 << 23) +#define BP_CSCMR1_EMI_SEL 27 +#define BM_CSCMR1_EMI_SEL (0x3 << 27) +#define BP_CSCMR1_EMI_SLOW_SEL 29 +#define BM_CSCMR1_EMI_SLOW_SEL (0x3 << 29) + +#define BP_CSCMR2_CAN_PODF 2 +#define BM_CSCMR2_CAN_PODF (0x3f << 2) +#define BM_CSCMR2_LDB_DI0_IPU_DIV (0x1 << 10) +#define BM_CSCMR2_LDB_DI1_IPU_DIV (0x1 << 11) +#define BP_CSCMR2_ESAI_SEL 19 +#define BM_CSCMR2_ESAI_SEL (0x3 << 19) + +#define BP_CSCDR1_UART_PODF 0 +#define BM_CSCDR1_UART_PODF (0x3f << 0) +#define BP_CSCDR1_USDHC1_PODF 11 +#define BM_CSCDR1_USDHC1_PODF (0x7 << 11) +#define BP_CSCDR1_USDHC2_PODF 16 +#define BM_CSCDR1_USDHC2_PODF (0x7 << 16) +#define BP_CSCDR1_USDHC3_PODF 19 +#define BM_CSCDR1_USDHC3_PODF (0x7 << 19) +#define BP_CSCDR1_USDHC4_PODF 22 +#define BM_CSCDR1_USDHC4_PODF (0x7 << 22) +#define BP_CSCDR1_VPU_AXI_PODF 25 +#define BM_CSCDR1_VPU_AXI_PODF (0x7 << 25) + +#define BP_CS1CDR_SSI1_PODF 0 +#define BM_CS1CDR_SSI1_PODF (0x3f << 0) +#define BP_CS1CDR_SSI1_PRED 6 +#define BM_CS1CDR_SSI1_PRED (0x7 << 6) +#define BP_CS1CDR_ESAI_PRED 9 +#define BM_CS1CDR_ESAI_PRED (0x7 << 9) +#define BP_CS1CDR_SSI3_PODF 16 +#define BM_CS1CDR_SSI3_PODF (0x3f << 16) +#define BP_CS1CDR_SSI3_PRED 22 +#define BM_CS1CDR_SSI3_PRED (0x7 << 22) +#define BP_CS1CDR_ESAI_PODF 25 +#define BM_CS1CDR_ESAI_PODF (0x7 << 25) + +#define BP_CS2CDR_SSI2_PODF 0 +#define BM_CS2CDR_SSI2_PODF (0x3f << 0) +#define BP_CS2CDR_SSI2_PRED 6 +#define BM_CS2CDR_SSI2_PRED (0x7 << 6) +#define BP_CS2CDR_LDB_DI0_SEL 9 +#define BM_CS2CDR_LDB_DI0_SEL (0x7 << 9) +#define BP_CS2CDR_LDB_DI1_SEL 12 +#define BM_CS2CDR_LDB_DI1_SEL (0x7 << 12) +#define BP_CS2CDR_ENFC_SEL 16 +#define BM_CS2CDR_ENFC_SEL (0x3 << 16) +#define BP_CS2CDR_ENFC_PRED 18 +#define BM_CS2CDR_ENFC_PRED (0x7 << 18) +#define BP_CS2CDR_ENFC_PODF 21 +#define BM_CS2CDR_ENFC_PODF (0x3f << 21) + +#define BP_CDCDR_ASRC_SERIAL_SEL 7 +#define BM_CDCDR_ASRC_SERIAL_SEL (0x3 << 7) +#define BP_CDCDR_ASRC_SERIAL_PODF 9 +#define BM_CDCDR_ASRC_SERIAL_PODF (0x7 << 9) +#define BP_CDCDR_ASRC_SERIAL_PRED 12 +#define BM_CDCDR_ASRC_SERIAL_PRED (0x7 << 12) +#define BP_CDCDR_SPDIF_SEL 20 +#define BM_CDCDR_SPDIF_SEL (0x3 << 20) +#define BP_CDCDR_SPDIF_PODF 22 +#define BM_CDCDR_SPDIF_PODF (0x7 << 22) +#define BP_CDCDR_SPDIF_PRED 25 +#define BM_CDCDR_SPDIF_PRED (0x7 << 25) +#define BP_CDCDR_HSI_TX_PODF 29 +#define BM_CDCDR_HSI_TX_PODF (0x7 << 29) +#define BP_CDCDR_HSI_TX_SEL 28 +#define BM_CDCDR_HSI_TX_SEL (0x1 << 28) + +#define BP_CHSCCDR_IPU1_DI0_SEL 0 +#define BM_CHSCCDR_IPU1_DI0_SEL (0x7 << 0) +#define BP_CHSCCDR_IPU1_DI0_PRE_PODF 3 +#define BM_CHSCCDR_IPU1_DI0_PRE_PODF (0x7 << 3) +#define BP_CHSCCDR_IPU1_DI0_PRE_SEL 6 +#define BM_CHSCCDR_IPU1_DI0_PRE_SEL (0x7 << 6) +#define BP_CHSCCDR_IPU1_DI1_SEL 9 +#define BM_CHSCCDR_IPU1_DI1_SEL (0x7 << 9) +#define BP_CHSCCDR_IPU1_DI1_PRE_PODF 12 +#define BM_CHSCCDR_IPU1_DI1_PRE_PODF (0x7 << 12) +#define BP_CHSCCDR_IPU1_DI1_PRE_SEL 15 +#define BM_CHSCCDR_IPU1_DI1_PRE_SEL (0x7 << 15) + +#define BP_CSCDR2_IPU2_DI0_SEL 0 +#define BM_CSCDR2_IPU2_DI0_SEL (0x7) +#define BP_CSCDR2_IPU2_DI0_PRE_PODF 3 +#define BM_CSCDR2_IPU2_DI0_PRE_PODF (0x7 << 3) +#define BP_CSCDR2_IPU2_DI0_PRE_SEL 6 +#define BM_CSCDR2_IPU2_DI0_PRE_SEL (0x7 << 6) +#define BP_CSCDR2_IPU2_DI1_SEL 9 +#define BM_CSCDR2_IPU2_DI1_SEL (0x7 << 9) +#define BP_CSCDR2_IPU2_DI1_PRE_PODF 12 +#define BM_CSCDR2_IPU2_DI1_PRE_PODF (0x7 << 12) +#define BP_CSCDR2_IPU2_DI1_PRE_SEL 15 +#define BM_CSCDR2_IPU2_DI1_PRE_SEL (0x7 << 15) +#define BP_CSCDR2_ECSPI_CLK_PODF 19 +#define BM_CSCDR2_ECSPI_CLK_PODF (0x3f << 19) + +#define BP_CSCDR3_IPU1_HSP_SEL 9 +#define BM_CSCDR3_IPU1_HSP_SEL (0x3 << 9) +#define BP_CSCDR3_IPU1_HSP_PODF 11 +#define BM_CSCDR3_IPU1_HSP_PODF (0x7 << 11) +#define BP_CSCDR3_IPU2_HSP_SEL 14 +#define BM_CSCDR3_IPU2_HSP_SEL (0x3 << 14) +#define BP_CSCDR3_IPU2_HSP_PODF 16 +#define BM_CSCDR3_IPU2_HSP_PODF (0x7 << 16) + +#define BM_CDHIPR_AXI_PODF_BUSY (0x1 << 0) +#define BM_CDHIPR_AHB_PODF_BUSY (0x1 << 1) +#define BM_CDHIPR_MMDC_CH1_PODF_BUSY (0x1 << 2) +#define BM_CDHIPR_PERIPH2_SEL_BUSY (0x1 << 3) +#define BM_CDHIPR_MMDC_CH0_PODF_BUSY (0x1 << 4) +#define BM_CDHIPR_PERIPH_SEL_BUSY (0x1 << 5) +#define BM_CDHIPR_ARM_PODF_BUSY (0x1 << 16) + +#define BP_CLPCR_LPM 0 +#define BM_CLPCR_LPM (0x3 << 0) +#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2) +#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) +#define BM_CLPCR_SBYOS (0x1 << 6) +#define BM_CLPCR_DIS_REF_OSC (0x1 << 7) +#define BM_CLPCR_VSTBY (0x1 << 8) +#define BP_CLPCR_STBY_COUNT 9 +#define BM_CLPCR_STBY_COUNT (0x3 << 9) +#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11) +#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16) +#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17) +#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19) +#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21) +#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22) +#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23) +#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24) +#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25) +#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) +#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) + +#define BP_CCOSR_CKO1_EN 7 +#define BP_CCOSR_CKO1_PODF 4 +#define BM_CCOSR_CKO1_PODF (0x7 << 4) +#define BP_CCOSR_CKO1_SEL 0 +#define BM_CCOSR_CKO1_SEL (0xf << 0) + +#define FREQ_480M 480000000 +#define FREQ_528M 528000000 +#define FREQ_594M 594000000 +#define FREQ_650M 650000000 +#define FREQ_1300M 1300000000 + +static struct clk pll1_sys; +static struct clk pll2_bus; +static struct clk pll3_usb_otg; +static struct clk pll4_audio; +static struct clk pll5_video; +static struct clk pll6_mlb; +static struct clk pll7_usb_host; +static struct clk pll8_enet; +static struct clk apbh_dma_clk; +static struct clk arm_clk; +static struct clk ipg_clk; +static struct clk ahb_clk; +static struct clk axi_clk; +static struct clk mmdc_ch0_axi_clk; +static struct clk mmdc_ch1_axi_clk; +static struct clk periph_clk; +static struct clk periph_pre_clk; +static struct clk periph_clk2_clk; +static struct clk periph2_clk; +static struct clk periph2_pre_clk; +static struct clk periph2_clk2_clk; +static struct clk gpu2d_core_clk; +static struct clk gpu3d_core_clk; +static struct clk gpu3d_shader_clk; +static struct clk ipg_perclk; +static struct clk emi_clk; +static struct clk emi_slow_clk; +static struct clk can1_clk; +static struct clk uart_clk; +static struct clk usdhc1_clk; +static struct clk usdhc2_clk; +static struct clk usdhc3_clk; +static struct clk usdhc4_clk; +static struct clk vpu_clk; +static struct clk hsi_tx_clk; +static struct clk ipu1_di0_pre_clk; +static struct clk ipu1_di1_pre_clk; +static struct clk ipu2_di0_pre_clk; +static struct clk ipu2_di1_pre_clk; +static struct clk ipu1_clk; +static struct clk ipu2_clk; +static struct clk ssi1_clk; +static struct clk ssi3_clk; +static struct clk esai_clk; +static struct clk ssi2_clk; +static struct clk spdif_clk; +static struct clk asrc_serial_clk; +static struct clk gpu2d_axi_clk; +static struct clk gpu3d_axi_clk; +static struct clk pcie_clk; +static struct clk vdo_axi_clk; +static struct clk ldb_di0_clk; +static struct clk ldb_di1_clk; +static struct clk ipu1_di0_clk; +static struct clk ipu1_di1_clk; +static struct clk ipu2_di0_clk; +static struct clk ipu2_di1_clk; +static struct clk enfc_clk; +static struct clk cko1_clk; +static struct clk dummy_clk = {}; + +static unsigned long external_high_reference; +static unsigned long external_low_reference; +static unsigned long oscillator_reference; + +static unsigned long get_oscillator_reference_clock_rate(struct clk *clk) +{ + return oscillator_reference; +} + +static unsigned long get_high_reference_clock_rate(struct clk *clk) +{ + return external_high_reference; +} + +static unsigned long get_low_reference_clock_rate(struct clk *clk) +{ + return external_low_reference; +} + +static struct clk ckil_clk = { + .get_rate = get_low_reference_clock_rate, +}; + +static struct clk ckih_clk = { + .get_rate = get_high_reference_clock_rate, +}; + +static struct clk osc_clk = { + .get_rate = get_oscillator_reference_clock_rate, +}; + +static inline void __iomem *pll_get_reg_addr(struct clk *pll) +{ + if (pll == &pll1_sys) + return PLL1_SYS; + else if (pll == &pll2_bus) + return PLL2_BUS; + else if (pll == &pll3_usb_otg) + return PLL3_USB_OTG; + else if (pll == &pll4_audio) + return PLL4_AUDIO; + else if (pll == &pll5_video) + return PLL5_VIDEO; + else if (pll == &pll6_mlb) + return PLL6_MLB; + else if (pll == &pll7_usb_host) + return PLL7_USB_HOST; + else if (pll == &pll8_enet) + return PLL8_ENET; + else + BUG(); + + return NULL; +} + +static int pll_enable(struct clk *clk) +{ + int timeout = 0x100000; + void __iomem *reg; + u32 val; + + reg = pll_get_reg_addr(clk); + val = readl_relaxed(reg); + val &= ~BM_PLL_BYPASS; + val &= ~BM_PLL_POWER_DOWN; + /* 480MHz PLLs have the opposite definition for power bit */ + if (clk == &pll3_usb_otg || clk == &pll7_usb_host) + val |= BM_PLL_POWER_DOWN; + writel_relaxed(val, reg); + + /* Wait for PLL to lock */ + while (!(readl_relaxed(reg) & BM_PLL_LOCK) && --timeout) + cpu_relax(); + + if (unlikely(!timeout)) + return -EBUSY; + + /* Enable the PLL output now */ + val = readl_relaxed(reg); + val |= BM_PLL_ENABLE; + writel_relaxed(val, reg); + + return 0; +} + +static void pll_disable(struct clk *clk) +{ + void __iomem *reg; + u32 val; + + reg = pll_get_reg_addr(clk); + val = readl_relaxed(reg); + val &= ~BM_PLL_ENABLE; + val |= BM_PLL_BYPASS; + val |= BM_PLL_POWER_DOWN; + if (clk == &pll3_usb_otg || clk == &pll7_usb_host) + val &= ~BM_PLL_POWER_DOWN; + writel_relaxed(val, reg); +} + +static unsigned long pll1_sys_get_rate(struct clk *clk) +{ + u32 div = (readl_relaxed(PLL1_SYS) & BM_PLL_SYS_DIV_SELECT) >> + BP_PLL_SYS_DIV_SELECT; + + return clk_get_rate(clk->parent) * div / 2; +} + +static int pll1_sys_set_rate(struct clk *clk, unsigned long rate) +{ + u32 val, div; + + if (rate < FREQ_650M || rate > FREQ_1300M) + return -EINVAL; + + div = rate * 2 / clk_get_rate(clk->parent); + val = readl_relaxed(PLL1_SYS); + val &= ~BM_PLL_SYS_DIV_SELECT; + val |= div << BP_PLL_SYS_DIV_SELECT; + writel_relaxed(val, PLL1_SYS); + + return 0; +} + +static unsigned long pll8_enet_get_rate(struct clk *clk) +{ + u32 div = (readl_relaxed(PLL8_ENET) & BM_PLL_ENET_DIV_SELECT) >> + BP_PLL_ENET_DIV_SELECT; + + switch (div) { + case 0: + return 25000000; + case 1: + return 50000000; + case 2: + return 100000000; + case 3: + return 125000000; + } + + return 0; +} + +static int pll8_enet_set_rate(struct clk *clk, unsigned long rate) +{ + u32 val, div; + + switch (rate) { + case 25000000: + div = 0; + break; + case 50000000: + div = 1; + break; + case 100000000: + div = 2; + break; + case 125000000: + div = 3; + break; + default: + return -EINVAL; + } + + val = readl_relaxed(PLL8_ENET); + val &= ~BM_PLL_ENET_DIV_SELECT; + val |= div << BP_PLL_ENET_DIV_SELECT; + writel_relaxed(val, PLL8_ENET); + + return 0; +} + +static unsigned long pll_av_get_rate(struct clk *clk) +{ + void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO; + unsigned long parent_rate = clk_get_rate(clk->parent); + u32 mfn = readl_relaxed(reg + PLL_NUM_OFFSET); + u32 mfd = readl_relaxed(reg + PLL_DENOM_OFFSET); + u32 div = (readl_relaxed(reg) & BM_PLL_AV_DIV_SELECT) >> + BP_PLL_AV_DIV_SELECT; + + return (parent_rate * div) + ((parent_rate / mfd) * mfn); +} + +static int pll_av_set_rate(struct clk *clk, unsigned long rate) +{ + void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO; + unsigned int parent_rate = clk_get_rate(clk->parent); + u32 val, div; + u32 mfn, mfd = 1000000; + s64 temp64; + + if (rate < FREQ_650M || rate > FREQ_1300M) + return -EINVAL; + + div = rate / parent_rate; + temp64 = (u64) (rate - div * parent_rate); + temp64 *= mfd; + do_div(temp64, parent_rate); + mfn = temp64; + + val = readl_relaxed(reg); + val &= ~BM_PLL_AV_DIV_SELECT; + val |= div << BP_PLL_AV_DIV_SELECT; + writel_relaxed(val, reg); + writel_relaxed(mfn, reg + PLL_NUM_OFFSET); + writel_relaxed(mfd, reg + PLL_DENOM_OFFSET); + + return 0; +} + +static void __iomem *pll_get_div_reg_bit(struct clk *clk, u32 *bp, u32 *bm) +{ + void __iomem *reg; + + if (clk == &pll2_bus) { + reg = PLL2_BUS; + *bp = BP_PLL_BUS_DIV_SELECT; + *bm = BM_PLL_BUS_DIV_SELECT; + } else if (clk == &pll3_usb_otg) { + reg = PLL3_USB_OTG; + *bp = BP_PLL_USB_DIV_SELECT; + *bm = BM_PLL_USB_DIV_SELECT; + } else if (clk == &pll7_usb_host) { + reg = PLL7_USB_HOST; + *bp = BP_PLL_USB_DIV_SELECT; + *bm = BM_PLL_USB_DIV_SELECT; + } else { + BUG(); + } + + return reg; +} + +static unsigned long pll_get_rate(struct clk *clk) +{ + void __iomem *reg; + u32 div, bp, bm; + + reg = pll_get_div_reg_bit(clk, &bp, &bm); + div = (readl_relaxed(reg) & bm) >> bp; + + return (div == 1) ? clk_get_rate(clk->parent) * 22 : + clk_get_rate(clk->parent) * 20; +} + +static int pll_set_rate(struct clk *clk, unsigned long rate) +{ + void __iomem *reg; + u32 val, div, bp, bm; + + if (rate == FREQ_528M) + div = 1; + else if (rate == FREQ_480M) + div = 0; + else + return -EINVAL; + + reg = pll_get_div_reg_bit(clk, &bp, &bm); + val = readl_relaxed(reg); + val &= ~bm; + val |= div << bp; + writel_relaxed(val, reg); + + return 0; +} + +#define pll2_bus_get_rate pll_get_rate +#define pll2_bus_set_rate pll_set_rate +#define pll3_usb_otg_get_rate pll_get_rate +#define pll3_usb_otg_set_rate pll_set_rate +#define pll7_usb_host_get_rate pll_get_rate +#define pll7_usb_host_set_rate pll_set_rate +#define pll4_audio_get_rate pll_av_get_rate +#define pll4_audio_set_rate pll_av_set_rate +#define pll5_video_get_rate pll_av_get_rate +#define pll5_video_set_rate pll_av_set_rate +#define pll6_mlb_get_rate NULL +#define pll6_mlb_set_rate NULL + +#define DEF_PLL(name) \ + static struct clk name = { \ + .enable = pll_enable, \ + .disable = pll_disable, \ + .get_rate = name##_get_rate, \ + .set_rate = name##_set_rate, \ + .parent = &osc_clk, \ + } + +DEF_PLL(pll1_sys); +DEF_PLL(pll2_bus); +DEF_PLL(pll3_usb_otg); +DEF_PLL(pll4_audio); +DEF_PLL(pll5_video); +DEF_PLL(pll6_mlb); +DEF_PLL(pll7_usb_host); +DEF_PLL(pll8_enet); + +static unsigned long pfd_get_rate(struct clk *clk) +{ + u64 tmp = (u64) clk_get_rate(clk->parent) * 18; + u32 frac, bp_frac; + + if (apbh_dma_clk.usecount == 0) + apbh_dma_clk.enable(&apbh_dma_clk); + + bp_frac = clk->enable_shift - 7; + frac = readl_relaxed(clk->enable_reg) >> bp_frac & PFD_FRAC_MASK; + do_div(tmp, frac); + + return tmp; +} + +static int pfd_set_rate(struct clk *clk, unsigned long rate) +{ + u32 val, frac, bp_frac; + u64 tmp = (u64) clk_get_rate(clk->parent) * 18; + + if (apbh_dma_clk.usecount == 0) + apbh_dma_clk.enable(&apbh_dma_clk); + + /* + * Round up the divider so that we don't set a rate + * higher than what is requested + */ + tmp += rate / 2; + do_div(tmp, rate); + frac = tmp; + frac = (frac < 12) ? 12 : frac; + frac = (frac > 35) ? 35 : frac; + + /* + * The frac field always starts from 7 bits lower + * position of enable bit + */ + bp_frac = clk->enable_shift - 7; + val = readl_relaxed(clk->enable_reg); + val &= ~(PFD_FRAC_MASK << bp_frac); + val |= frac << bp_frac; + writel_relaxed(val, clk->enable_reg); + + tmp = (u64) clk_get_rate(clk->parent) * 18; + do_div(tmp, frac); + + if (apbh_dma_clk.usecount == 0) + apbh_dma_clk.disable(&apbh_dma_clk); + + return 0; +} + +static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate) +{ + u32 frac; + u64 tmp; + + tmp = (u64) clk_get_rate(clk->parent) * 18; + tmp += rate / 2; + do_div(tmp, rate); + frac = tmp; + frac = (frac < 12) ? 12 : frac; + frac = (frac > 35) ? 35 : frac; + tmp = (u64) clk_get_rate(clk->parent) * 18; + do_div(tmp, frac); + + return tmp; +} + +static int pfd_enable(struct clk *clk) +{ + u32 val; + + if (apbh_dma_clk.usecount == 0) + apbh_dma_clk.enable(&apbh_dma_clk); + + val = readl_relaxed(clk->enable_reg); + val &= ~(1 << clk->enable_shift); + writel_relaxed(val, clk->enable_reg); + + if (apbh_dma_clk.usecount == 0) + apbh_dma_clk.disable(&apbh_dma_clk); + + return 0; +} + +static void pfd_disable(struct clk *clk) +{ + u32 val; + + if (apbh_dma_clk.usecount == 0) + apbh_dma_clk.enable(&apbh_dma_clk); + + val = readl_relaxed(clk->enable_reg); + val |= 1 << clk->enable_shift; + writel_relaxed(val, clk->enable_reg); + + if (apbh_dma_clk.usecount == 0) + apbh_dma_clk.disable(&apbh_dma_clk); +} + +#define DEF_PFD(name, er, es, p) \ + static struct clk name = { \ + .enable_reg = er, \ + .enable_shift = es, \ + .enable = pfd_enable, \ + .disable = pfd_disable, \ + .get_rate = pfd_get_rate, \ + .set_rate = pfd_set_rate, \ + .round_rate = pfd_round_rate, \ + .parent = p, \ + } + +DEF_PFD(pll2_pfd_352m, PFD_528, PFD0, &pll2_bus); +DEF_PFD(pll2_pfd_594m, PFD_528, PFD1, &pll2_bus); +DEF_PFD(pll2_pfd_400m, PFD_528, PFD2, &pll2_bus); +DEF_PFD(pll3_pfd_720m, PFD_480, PFD0, &pll3_usb_otg); +DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg); +DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg); +DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg); + +static unsigned long twd_clk_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 2; +} + +static struct clk twd_clk = { + .parent = &arm_clk, + .get_rate = twd_clk_get_rate, +}; + +static unsigned long pll2_200m_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 2; +} + +static struct clk pll2_200m = { + .parent = &pll2_pfd_400m, + .get_rate = pll2_200m_get_rate, +}; + +static unsigned long pll3_120m_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 4; +} + +static struct clk pll3_120m = { + .parent = &pll3_usb_otg, + .get_rate = pll3_120m_get_rate, +}; + +static unsigned long pll3_80m_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 6; +} + +static struct clk pll3_80m = { + .parent = &pll3_usb_otg, + .get_rate = pll3_80m_get_rate, +}; + +static unsigned long pll3_60m_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 8; +} + +static struct clk pll3_60m = { + .parent = &pll3_usb_otg, + .get_rate = pll3_60m_get_rate, +}; + +static int pll1_sw_clk_set_parent(struct clk *clk, struct clk *parent) +{ + u32 val = readl_relaxed(CCSR); + + if (parent == &pll1_sys) { + val &= ~BM_CCSR_PLL1_SW_SEL; + val &= ~BM_CCSR_STEP_SEL; + } else if (parent == &osc_clk) { + val |= BM_CCSR_PLL1_SW_SEL; + val &= ~BM_CCSR_STEP_SEL; + } else if (parent == &pll2_pfd_400m) { + val |= BM_CCSR_PLL1_SW_SEL; + val |= BM_CCSR_STEP_SEL; + } else { + return -EINVAL; + } + + writel_relaxed(val, CCSR); + + return 0; +} + +static struct clk pll1_sw_clk = { + .parent = &pll1_sys, + .set_parent = pll1_sw_clk_set_parent, +}; + +static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf) +{ + u32 min_pred, temp_pred, old_err, err; + + if (div >= 512) { + *pred = 8; + *podf = 64; + } else if (div >= 8) { + min_pred = (div - 1) / 64 + 1; + old_err = 8; + for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) { + err = div % temp_pred; + if (err == 0) { + *pred = temp_pred; + break; + } + err = temp_pred - err; + if (err < old_err) { + old_err = err; + *pred = temp_pred; + } + } + *podf = (div + *pred - 1) / *pred; + } else if (div < 8) { + *pred = div; + *podf = 1; + } +} + +static int _clk_enable(struct clk *clk) +{ + u32 reg; + reg = readl_relaxed(clk->enable_reg); + reg |= 0x3 << clk->enable_shift; + writel_relaxed(reg, clk->enable_reg); + + return 0; +} + +static void _clk_disable(struct clk *clk) +{ + u32 reg; + reg = readl_relaxed(clk->enable_reg); + reg &= ~(0x3 << clk->enable_shift); + writel_relaxed(reg, clk->enable_reg); +} + +static int _clk_enable_1b(struct clk *clk) +{ + u32 reg; + reg = readl_relaxed(clk->enable_reg); + reg |= 0x1 << clk->enable_shift; + writel_relaxed(reg, clk->enable_reg); + + return 0; +} + +static void _clk_disable_1b(struct clk *clk) +{ + u32 reg; + reg = readl_relaxed(clk->enable_reg); + reg &= ~(0x1 << clk->enable_shift); + writel_relaxed(reg, clk->enable_reg); +} + +struct divider { + struct clk *clk; + void __iomem *reg; + u32 bp_pred; + u32 bm_pred; + u32 bp_podf; + u32 bm_podf; +}; + +#define DEF_CLK_DIV1(d, c, r, b) \ + static struct divider d = { \ + .clk = c, \ + .reg = r, \ + .bp_podf = BP_##r##_##b##_PODF, \ + .bm_podf = BM_##r##_##b##_PODF, \ + } + +DEF_CLK_DIV1(arm_div, &arm_clk, CACRR, ARM); +DEF_CLK_DIV1(ipg_div, &ipg_clk, CBCDR, IPG); +DEF_CLK_DIV1(ahb_div, &ahb_clk, CBCDR, AHB); +DEF_CLK_DIV1(axi_div, &axi_clk, CBCDR, AXI); +DEF_CLK_DIV1(mmdc_ch0_axi_div, &mmdc_ch0_axi_clk, CBCDR, MMDC_CH0_AXI); +DEF_CLK_DIV1(mmdc_ch1_axi_div, &mmdc_ch1_axi_clk, CBCDR, MMDC_CH1_AXI); +DEF_CLK_DIV1(periph_clk2_div, &periph_clk2_clk, CBCDR, PERIPH_CLK2); +DEF_CLK_DIV1(periph2_clk2_div, &periph2_clk2_clk, CBCDR, PERIPH2_CLK2); +DEF_CLK_DIV1(gpu2d_core_div, &gpu2d_core_clk, CBCMR, GPU2D_CORE); +DEF_CLK_DIV1(gpu3d_core_div, &gpu3d_core_clk, CBCMR, GPU3D_CORE); +DEF_CLK_DIV1(gpu3d_shader_div, &gpu3d_shader_clk, CBCMR, GPU3D_SHADER); +DEF_CLK_DIV1(ipg_perclk_div, &ipg_perclk, CSCMR1, PERCLK); +DEF_CLK_DIV1(emi_div, &emi_clk, CSCMR1, EMI); +DEF_CLK_DIV1(emi_slow_div, &emi_slow_clk, CSCMR1, EMI_SLOW); +DEF_CLK_DIV1(can_div, &can1_clk, CSCMR2, CAN); +DEF_CLK_DIV1(uart_div, &uart_clk, CSCDR1, UART); +DEF_CLK_DIV1(usdhc1_div, &usdhc1_clk, CSCDR1, USDHC1); +DEF_CLK_DIV1(usdhc2_div, &usdhc2_clk, CSCDR1, USDHC2); +DEF_CLK_DIV1(usdhc3_div, &usdhc3_clk, CSCDR1, USDHC3); +DEF_CLK_DIV1(usdhc4_div, &usdhc4_clk, CSCDR1, USDHC4); +DEF_CLK_DIV1(vpu_div, &vpu_clk, CSCDR1, VPU_AXI); +DEF_CLK_DIV1(hsi_tx_div, &hsi_tx_clk, CDCDR, HSI_TX); +DEF_CLK_DIV1(ipu1_di0_pre_div, &ipu1_di0_pre_clk, CHSCCDR, IPU1_DI0_PRE); +DEF_CLK_DIV1(ipu1_di1_pre_div, &ipu1_di1_pre_clk, CHSCCDR, IPU1_DI1_PRE); +DEF_CLK_DIV1(ipu2_di0_pre_div, &ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE); +DEF_CLK_DIV1(ipu2_di1_pre_div, &ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE); +DEF_CLK_DIV1(ipu1_div, &ipu1_clk, CSCDR3, IPU1_HSP); +DEF_CLK_DIV1(ipu2_div, &ipu2_clk, CSCDR3, IPU2_HSP); +DEF_CLK_DIV1(cko1_div, &cko1_clk, CCOSR, CKO1); + +#define DEF_CLK_DIV2(d, c, r, b) \ + static struct divider d = { \ + .clk = c, \ + .reg = r, \ + .bp_pred = BP_##r##_##b##_PRED, \ + .bm_pred = BM_##r##_##b##_PRED, \ + .bp_podf = BP_##r##_##b##_PODF, \ + .bm_podf = BM_##r##_##b##_PODF, \ + } + +DEF_CLK_DIV2(ssi1_div, &ssi1_clk, CS1CDR, SSI1); +DEF_CLK_DIV2(ssi3_div, &ssi3_clk, CS1CDR, SSI3); +DEF_CLK_DIV2(esai_div, &esai_clk, CS1CDR, ESAI); +DEF_CLK_DIV2(ssi2_div, &ssi2_clk, CS2CDR, SSI2); +DEF_CLK_DIV2(enfc_div, &enfc_clk, CS2CDR, ENFC); +DEF_CLK_DIV2(spdif_div, &spdif_clk, CDCDR, SPDIF); +DEF_CLK_DIV2(asrc_serial_div, &asrc_serial_clk, CDCDR, ASRC_SERIAL); + +static struct divider *dividers[] = { + &arm_div, + &ipg_div, + &ahb_div, + &axi_div, + &mmdc_ch0_axi_div, + &mmdc_ch1_axi_div, + &periph_clk2_div, + &periph2_clk2_div, + &gpu2d_core_div, + &gpu3d_core_div, + &gpu3d_shader_div, + &ipg_perclk_div, + &emi_div, + &emi_slow_div, + &can_div, + &uart_div, + &usdhc1_div, + &usdhc2_div, + &usdhc3_div, + &usdhc4_div, + &vpu_div, + &hsi_tx_div, + &ipu1_di0_pre_div, + &ipu1_di1_pre_div, + &ipu2_di0_pre_div, + &ipu2_di1_pre_div, + &ipu1_div, + &ipu2_div, + &ssi1_div, + &ssi3_div, + &esai_div, + &ssi2_div, + &enfc_div, + &spdif_div, + &asrc_serial_div, + &cko1_div, +}; + +static unsigned long ldb_di_clk_get_rate(struct clk *clk) +{ + u32 val = readl_relaxed(CSCMR2); + + val &= (clk == &ldb_di0_clk) ? BM_CSCMR2_LDB_DI0_IPU_DIV : + BM_CSCMR2_LDB_DI1_IPU_DIV; + if (val) + return clk_get_rate(clk->parent) / 7; + else + return clk_get_rate(clk->parent) * 2 / 7; +} + +static int ldb_di_clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + u32 val = readl_relaxed(CSCMR2); + + if (rate * 7 <= parent_rate + parent_rate / 20) + val |= BM_CSCMR2_LDB_DI0_IPU_DIV; + else + val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV; + + writel_relaxed(val, CSCMR2); + + return 0; +} + +static unsigned long ldb_di_clk_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + + if (rate * 7 <= parent_rate + parent_rate / 20) + return parent_rate / 7; + else + return 2 * parent_rate / 7; +} + +static unsigned long _clk_get_rate(struct clk *clk) +{ + struct divider *d; + u32 val, pred, podf; + int i, num; + + if (clk == &ldb_di0_clk || clk == &ldb_di1_clk) + return ldb_di_clk_get_rate(clk); + + num = ARRAY_SIZE(dividers); + for (i = 0; i < num; i++) + if (dividers[i]->clk == clk) { + d = dividers[i]; + break; + } + if (i == num) + return clk_get_rate(clk->parent); + + val = readl_relaxed(d->reg); + pred = ((val & d->bm_pred) >> d->bp_pred) + 1; + podf = ((val & d->bm_podf) >> d->bp_podf) + 1; + + return clk_get_rate(clk->parent) / (pred * podf); +} + +static int clk_busy_wait(struct clk *clk) +{ + int timeout = 0x100000; + u32 bm; + + if (clk == &axi_clk) + bm = BM_CDHIPR_AXI_PODF_BUSY; + else if (clk == &ahb_clk) + bm = BM_CDHIPR_AHB_PODF_BUSY; + else if (clk == &mmdc_ch0_axi_clk) + bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY; + else if (clk == &periph_clk) + bm = BM_CDHIPR_PERIPH_SEL_BUSY; + else if (clk == &arm_clk) + bm = BM_CDHIPR_ARM_PODF_BUSY; + else + return -EINVAL; + + while ((readl_relaxed(CDHIPR) & bm) && --timeout) + cpu_relax(); + + if (unlikely(!timeout)) + return -EBUSY; + + return 0; +} + +static int _clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + struct divider *d; + u32 val, div, max_div, pred = 0, podf; + int i, num; + + if (clk == &ldb_di0_clk || clk == &ldb_di1_clk) + return ldb_di_clk_set_rate(clk, rate); + + num = ARRAY_SIZE(dividers); + for (i = 0; i < num; i++) + if (dividers[i]->clk == clk) { + d = dividers[i]; + break; + } + if (i == num) + return -EINVAL; + + max_div = ((d->bm_pred >> d->bp_pred) + 1) * + ((d->bm_podf >> d->bp_podf) + 1); + + div = parent_rate / rate; + if (div == 0) + div++; + + if ((parent_rate / div != rate) || div > max_div) + return -EINVAL; + + if (d->bm_pred) { + calc_pred_podf_dividers(div, &pred, &podf); + } else { + pred = 1; + podf = div; + } + + val = readl_relaxed(d->reg); + val &= ~(d->bm_pred | d->bm_podf); + val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf; + writel_relaxed(val, d->reg); + + if (clk == &axi_clk || clk == &ahb_clk || + clk == &mmdc_ch0_axi_clk || clk == &arm_clk) + return clk_busy_wait(clk); + + return 0; +} + +static unsigned long _clk_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + u32 div = parent_rate / rate; + u32 div_max, pred = 0, podf; + struct divider *d; + int i, num; + + if (clk == &ldb_di0_clk || clk == &ldb_di1_clk) + return ldb_di_clk_round_rate(clk, rate); + + num = ARRAY_SIZE(dividers); + for (i = 0; i < num; i++) + if (dividers[i]->clk == clk) { + d = dividers[i]; + break; + } + if (i == num) + return -EINVAL; + + if (div == 0 || parent_rate % rate) + div++; + + if (d->bm_pred) { + calc_pred_podf_dividers(div, &pred, &podf); + div = pred * podf; + } else { + div_max = (d->bm_podf >> d->bp_podf) + 1; + if (div > div_max) + div = div_max; + } + + return parent_rate / div; +} + +struct multiplexer { + struct clk *clk; + void __iomem *reg; + u32 bp; + u32 bm; + int pnum; + struct clk *parents[]; +}; + +static struct multiplexer axi_mux = { + .clk = &axi_clk, + .reg = CBCDR, + .bp = BP_CBCDR_AXI_SEL, + .bm = BM_CBCDR_AXI_SEL, + .parents = { + &periph_clk, + &pll2_pfd_400m, + &pll3_pfd_540m, + NULL + }, +}; + +static struct multiplexer periph_mux = { + .clk = &periph_clk, + .reg = CBCDR, + .bp = BP_CBCDR_PERIPH_CLK_SEL, + .bm = BM_CBCDR_PERIPH_CLK_SEL, + .parents = { + &periph_pre_clk, + &periph_clk2_clk, + NULL + }, +}; + +static struct multiplexer periph_pre_mux = { + .clk = &periph_pre_clk, + .reg = CBCMR, + .bp = BP_CBCMR_PRE_PERIPH_CLK_SEL, + .bm = BM_CBCMR_PRE_PERIPH_CLK_SEL, + .parents = { + &pll2_bus, + &pll2_pfd_400m, + &pll2_pfd_352m, + &pll2_200m, + NULL + }, +}; + +static struct multiplexer periph_clk2_mux = { + .clk = &periph_clk2_clk, + .reg = CBCMR, + .bp = BP_CBCMR_PERIPH_CLK2_SEL, + .bm = BM_CBCMR_PERIPH_CLK2_SEL, + .parents = { + &pll3_usb_otg, + &osc_clk, + NULL + }, +}; + +static struct multiplexer periph2_mux = { + .clk = &periph2_clk, + .reg = CBCDR, + .bp = BP_CBCDR_PERIPH2_CLK_SEL, + .bm = BM_CBCDR_PERIPH2_CLK_SEL, + .parents = { + &periph2_pre_clk, + &periph2_clk2_clk, + NULL + }, +}; + +static struct multiplexer periph2_pre_mux = { + .clk = &periph2_pre_clk, + .reg = CBCMR, + .bp = BP_CBCMR_PRE_PERIPH2_CLK_SEL, + .bm = BM_CBCMR_PRE_PERIPH2_CLK_SEL, + .parents = { + &pll2_bus, + &pll2_pfd_400m, + &pll2_pfd_352m, + &pll2_200m, + NULL + }, +}; + +static struct multiplexer periph2_clk2_mux = { + .clk = &periph2_clk2_clk, + .reg = CBCMR, + .bp = BP_CBCMR_PERIPH2_CLK2_SEL, + .bm = BM_CBCMR_PERIPH2_CLK2_SEL, + .parents = { + &pll3_usb_otg, + &osc_clk, + NULL + }, +}; + +static struct multiplexer gpu2d_axi_mux = { + .clk = &gpu2d_axi_clk, + .reg = CBCMR, + .bp = BP_CBCMR_GPU2D_AXI_SEL, + .bm = BM_CBCMR_GPU2D_AXI_SEL, + .parents = { + &axi_clk, + &ahb_clk, + NULL + }, +}; + +static struct multiplexer gpu3d_axi_mux = { + .clk = &gpu3d_axi_clk, + .reg = CBCMR, + .bp = BP_CBCMR_GPU3D_AXI_SEL, + .bm = BM_CBCMR_GPU3D_AXI_SEL, + .parents = { + &axi_clk, + &ahb_clk, + NULL + }, +}; + +static struct multiplexer gpu3d_core_mux = { + .clk = &gpu3d_core_clk, + .reg = CBCMR, + .bp = BP_CBCMR_GPU3D_CORE_SEL, + .bm = BM_CBCMR_GPU3D_CORE_SEL, + .parents = { + &mmdc_ch0_axi_clk, + &pll3_usb_otg, + &pll2_pfd_594m, + &pll2_pfd_400m, + NULL + }, +}; + +static struct multiplexer gpu3d_shader_mux = { + .clk = &gpu3d_shader_clk, + .reg = CBCMR, + .bp = BP_CBCMR_GPU3D_SHADER_SEL, + .bm = BM_CBCMR_GPU3D_SHADER_SEL, + .parents = { + &mmdc_ch0_axi_clk, + &pll3_usb_otg, + &pll2_pfd_594m, + &pll3_pfd_720m, + NULL + }, +}; + +static struct multiplexer pcie_axi_mux = { + .clk = &pcie_clk, + .reg = CBCMR, + .bp = BP_CBCMR_PCIE_AXI_SEL, + .bm = BM_CBCMR_PCIE_AXI_SEL, + .parents = { + &axi_clk, + &ahb_clk, + NULL + }, +}; + +static struct multiplexer vdo_axi_mux = { + .clk = &vdo_axi_clk, + .reg = CBCMR, + .bp = BP_CBCMR_VDO_AXI_SEL, + .bm = BM_CBCMR_VDO_AXI_SEL, + .parents = { + &axi_clk, + &ahb_clk, + NULL + }, +}; + +static struct multiplexer vpu_axi_mux = { + .clk = &vpu_clk, + .reg = CBCMR, + .bp = BP_CBCMR_VPU_AXI_SEL, + .bm = BM_CBCMR_VPU_AXI_SEL, + .parents = { + &axi_clk, + &pll2_pfd_400m, + &pll2_pfd_352m, + NULL + }, +}; + +static struct multiplexer gpu2d_core_mux = { + .clk = &gpu2d_core_clk, + .reg = CBCMR, + .bp = BP_CBCMR_GPU2D_CORE_SEL, + .bm = BM_CBCMR_GPU2D_CORE_SEL, + .parents = { + &axi_clk, + &pll3_usb_otg, + &pll2_pfd_352m, + &pll2_pfd_400m, + NULL + }, +}; + +#define DEF_SSI_MUX(id) \ + static struct multiplexer ssi##id##_mux = { \ + .clk = &ssi##id##_clk, \ + .reg = CSCMR1, \ + .bp = BP_CSCMR1_SSI##id##_SEL, \ + .bm = BM_CSCMR1_SSI##id##_SEL, \ + .parents = { \ + &pll3_pfd_508m, \ + &pll3_pfd_454m, \ + &pll4_audio, \ + NULL \ + }, \ + } + +DEF_SSI_MUX(1); +DEF_SSI_MUX(2); +DEF_SSI_MUX(3); + +#define DEF_USDHC_MUX(id) \ + static struct multiplexer usdhc##id##_mux = { \ + .clk = &usdhc##id##_clk, \ + .reg = CSCMR1, \ + .bp = BP_CSCMR1_USDHC##id##_SEL, \ + .bm = BM_CSCMR1_USDHC##id##_SEL, \ + .parents = { \ + &pll2_pfd_400m, \ + &pll2_pfd_352m, \ + NULL \ + }, \ + } + +DEF_USDHC_MUX(1); +DEF_USDHC_MUX(2); +DEF_USDHC_MUX(3); +DEF_USDHC_MUX(4); + +static struct multiplexer emi_mux = { + .clk = &emi_clk, + .reg = CSCMR1, + .bp = BP_CSCMR1_EMI_SEL, + .bm = BM_CSCMR1_EMI_SEL, + .parents = { + &axi_clk, + &pll3_usb_otg, + &pll2_pfd_400m, + &pll2_pfd_352m, + NULL + }, +}; + +static struct multiplexer emi_slow_mux = { + .clk = &emi_slow_clk, + .reg = CSCMR1, + .bp = BP_CSCMR1_EMI_SLOW_SEL, + .bm = BM_CSCMR1_EMI_SLOW_SEL, + .parents = { + &axi_clk, + &pll3_usb_otg, + &pll2_pfd_400m, + &pll2_pfd_352m, + NULL + }, +}; + +static struct multiplexer esai_mux = { + .clk = &esai_clk, + .reg = CSCMR2, + .bp = BP_CSCMR2_ESAI_SEL, + .bm = BM_CSCMR2_ESAI_SEL, + .parents = { + &pll4_audio, + &pll3_pfd_508m, + &pll3_pfd_454m, + &pll3_usb_otg, + NULL + }, +}; + +#define DEF_LDB_DI_MUX(id) \ + static struct multiplexer ldb_di##id##_mux = { \ + .clk = &ldb_di##id##_clk, \ + .reg = CS2CDR, \ + .bp = BP_CS2CDR_LDB_DI##id##_SEL, \ + .bm = BM_CS2CDR_LDB_DI##id##_SEL, \ + .parents = { \ + &pll5_video, \ + &pll2_pfd_352m, \ + &pll2_pfd_400m, \ + &pll3_pfd_540m, \ + &pll3_usb_otg, \ + NULL \ + }, \ + } + +DEF_LDB_DI_MUX(0); +DEF_LDB_DI_MUX(1); + +static struct multiplexer enfc_mux = { + .clk = &enfc_clk, + .reg = CS2CDR, + .bp = BP_CS2CDR_ENFC_SEL, + .bm = BM_CS2CDR_ENFC_SEL, + .parents = { + &pll2_pfd_352m, + &pll2_bus, + &pll3_usb_otg, + &pll2_pfd_400m, + NULL + }, +}; + +static struct multiplexer spdif_mux = { + .clk = &spdif_clk, + .reg = CDCDR, + .bp = BP_CDCDR_SPDIF_SEL, + .bm = BM_CDCDR_SPDIF_SEL, + .parents = { + &pll4_audio, + &pll3_pfd_508m, + &pll3_pfd_454m, + &pll3_usb_otg, + NULL + }, +}; + +static struct multiplexer asrc_serial_mux = { + .clk = &asrc_serial_clk, + .reg = CDCDR, + .bp = BP_CDCDR_ASRC_SERIAL_SEL, + .bm = BM_CDCDR_ASRC_SERIAL_SEL, + .parents = { + &pll4_audio, + &pll3_pfd_508m, + &pll3_pfd_454m, + &pll3_usb_otg, + NULL + }, +}; + +static struct multiplexer hsi_tx_mux = { + .clk = &hsi_tx_clk, + .reg = CDCDR, + .bp = BP_CDCDR_HSI_TX_SEL, + .bm = BM_CDCDR_HSI_TX_SEL, + .parents = { + &pll3_120m, + &pll2_pfd_400m, + NULL + }, +}; + +#define DEF_IPU_DI_PRE_MUX(r, i, d) \ + static struct multiplexer ipu##i##_di##d##_pre_mux = { \ + .clk = &ipu##i##_di##d##_pre_clk, \ + .reg = r, \ + .bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL, \ + .bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL, \ + .parents = { \ + &mmdc_ch0_axi_clk, \ + &pll3_usb_otg, \ + &pll5_video, \ + &pll2_pfd_352m, \ + &pll2_pfd_400m, \ + &pll3_pfd_540m, \ + NULL \ + }, \ + } + +DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 0); +DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 1); +DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 0); +DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 1); + +#define DEF_IPU_DI_MUX(r, i, d) \ + static struct multiplexer ipu##i##_di##d##_mux = { \ + .clk = &ipu##i##_di##d##_clk, \ + .reg = r, \ + .bp = BP_##r##_IPU##i##_DI##d##_SEL, \ + .bm = BM_##r##_IPU##i##_DI##d##_SEL, \ + .parents = { \ + &ipu##i##_di##d##_pre_clk, \ + &dummy_clk, \ + &dummy_clk, \ + &ldb_di0_clk, \ + &ldb_di1_clk, \ + NULL \ + }, \ + } + +DEF_IPU_DI_MUX(CHSCCDR, 1, 0); +DEF_IPU_DI_MUX(CHSCCDR, 1, 1); +DEF_IPU_DI_MUX(CSCDR2, 2, 0); +DEF_IPU_DI_MUX(CSCDR2, 2, 1); + +#define DEF_IPU_MUX(id) \ + static struct multiplexer ipu##id##_mux = { \ + .clk = &ipu##id##_clk, \ + .reg = CSCDR3, \ + .bp = BP_CSCDR3_IPU##id##_HSP_SEL, \ + .bm = BM_CSCDR3_IPU##id##_HSP_SEL, \ + .parents = { \ + &mmdc_ch0_axi_clk, \ + &pll2_pfd_400m, \ + &pll3_120m, \ + &pll3_pfd_540m, \ + NULL \ + }, \ + } + +DEF_IPU_MUX(1); +DEF_IPU_MUX(2); + +static struct multiplexer cko1_mux = { + .clk = &cko1_clk, + .reg = CCOSR, + .bp = BP_CCOSR_CKO1_SEL, + .bm = BM_CCOSR_CKO1_SEL, + .parents = { + &pll3_usb_otg, + &pll2_bus, + &pll1_sys, + &pll5_video, + &dummy_clk, + &axi_clk, + &enfc_clk, + &ipu1_di0_clk, + &ipu1_di1_clk, + &ipu2_di0_clk, + &ipu2_di1_clk, + &ahb_clk, + &ipg_clk, + &ipg_perclk, + &ckil_clk, + &pll4_audio, + NULL + }, +}; + +static struct multiplexer *multiplexers[] = { + &axi_mux, + &periph_mux, + &periph_pre_mux, + &periph_clk2_mux, + &periph2_mux, + &periph2_pre_mux, + &periph2_clk2_mux, + &gpu2d_axi_mux, + &gpu3d_axi_mux, + &gpu3d_core_mux, + &gpu3d_shader_mux, + &pcie_axi_mux, + &vdo_axi_mux, + &vpu_axi_mux, + &gpu2d_core_mux, + &ssi1_mux, + &ssi2_mux, + &ssi3_mux, + &usdhc1_mux, + &usdhc2_mux, + &usdhc3_mux, + &usdhc4_mux, + &emi_mux, + &emi_slow_mux, + &esai_mux, + &ldb_di0_mux, + &ldb_di1_mux, + &enfc_mux, + &spdif_mux, + &asrc_serial_mux, + &hsi_tx_mux, + &ipu1_di0_pre_mux, + &ipu1_di0_mux, + &ipu1_di1_pre_mux, + &ipu1_di1_mux, + &ipu2_di0_pre_mux, + &ipu2_di0_mux, + &ipu2_di1_pre_mux, + &ipu2_di1_mux, + &ipu1_mux, + &ipu2_mux, + &cko1_mux, +}; + +static int _clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct multiplexer *m; + int i, num; + u32 val; + + num = ARRAY_SIZE(multiplexers); + for (i = 0; i < num; i++) + if (multiplexers[i]->clk == clk) { + m = multiplexers[i]; + break; + } + if (i == num) + return -EINVAL; + + i = 0; + while (m->parents[i]) { + if (parent == m->parents[i]) + break; + i++; + } + if (!m->parents[i] || m->parents[i] == &dummy_clk) + return -EINVAL; + + val = readl_relaxed(m->reg); + val &= ~m->bm; + val |= i << m->bp; + writel_relaxed(val, m->reg); + + if (clk == &periph_clk) + return clk_busy_wait(clk); + + return 0; +} + +#define DEF_NG_CLK(name, p) \ + static struct clk name = { \ + .get_rate = _clk_get_rate, \ + .set_rate = _clk_set_rate, \ + .round_rate = _clk_round_rate, \ + .set_parent = _clk_set_parent, \ + .parent = p, \ + } + +DEF_NG_CLK(periph_clk2_clk, &osc_clk); +DEF_NG_CLK(periph_pre_clk, &pll2_bus); +DEF_NG_CLK(periph_clk, &periph_pre_clk); +DEF_NG_CLK(periph2_clk2_clk, &osc_clk); +DEF_NG_CLK(periph2_pre_clk, &pll2_bus); +DEF_NG_CLK(periph2_clk, &periph2_pre_clk); +DEF_NG_CLK(axi_clk, &periph_clk); +DEF_NG_CLK(emi_clk, &axi_clk); +DEF_NG_CLK(arm_clk, &pll1_sw_clk); +DEF_NG_CLK(ahb_clk, &periph_clk); +DEF_NG_CLK(ipg_clk, &ahb_clk); +DEF_NG_CLK(ipg_perclk, &ipg_clk); +DEF_NG_CLK(ipu1_di0_pre_clk, &pll3_pfd_540m); +DEF_NG_CLK(ipu1_di1_pre_clk, &pll3_pfd_540m); +DEF_NG_CLK(ipu2_di0_pre_clk, &pll3_pfd_540m); +DEF_NG_CLK(ipu2_di1_pre_clk, &pll3_pfd_540m); +DEF_NG_CLK(asrc_serial_clk, &pll3_usb_otg); + +#define DEF_CLK(name, er, es, p, s) \ + static struct clk name = { \ + .enable_reg = er, \ + .enable_shift = es, \ + .enable = _clk_enable, \ + .disable = _clk_disable, \ + .get_rate = _clk_get_rate, \ + .set_rate = _clk_set_rate, \ + .round_rate = _clk_round_rate, \ + .set_parent = _clk_set_parent, \ + .parent = p, \ + .secondary = s, \ + } + +#define DEF_CLK_1B(name, er, es, p, s) \ + static struct clk name = { \ + .enable_reg = er, \ + .enable_shift = es, \ + .enable = _clk_enable_1b, \ + .disable = _clk_disable_1b, \ + .get_rate = _clk_get_rate, \ + .set_rate = _clk_set_rate, \ + .round_rate = _clk_round_rate, \ + .set_parent = _clk_set_parent, \ + .parent = p, \ + .secondary = s, \ + } + +DEF_CLK(aips_tz1_clk, CCGR0, CG0, &ahb_clk, NULL); +DEF_CLK(aips_tz2_clk, CCGR0, CG1, &ahb_clk, NULL); +DEF_CLK(apbh_dma_clk, CCGR0, CG2, &ahb_clk, NULL); +DEF_CLK(asrc_clk, CCGR0, CG3, &pll4_audio, NULL); +DEF_CLK(can1_serial_clk, CCGR0, CG8, &pll3_usb_otg, NULL); +DEF_CLK(can1_clk, CCGR0, CG7, &pll3_usb_otg, &can1_serial_clk); +DEF_CLK(can2_serial_clk, CCGR0, CG10, &pll3_usb_otg, NULL); +DEF_CLK(can2_clk, CCGR0, CG9, &pll3_usb_otg, &can2_serial_clk); +DEF_CLK(ecspi1_clk, CCGR1, CG0, &pll3_60m, NULL); +DEF_CLK(ecspi2_clk, CCGR1, CG1, &pll3_60m, NULL); +DEF_CLK(ecspi3_clk, CCGR1, CG2, &pll3_60m, NULL); +DEF_CLK(ecspi4_clk, CCGR1, CG3, &pll3_60m, NULL); +DEF_CLK(ecspi5_clk, CCGR1, CG4, &pll3_60m, NULL); +DEF_CLK(enet_clk, CCGR1, CG5, &ipg_clk, NULL); +DEF_CLK(esai_clk, CCGR1, CG8, &pll3_usb_otg, NULL); +DEF_CLK(gpt_serial_clk, CCGR1, CG11, &ipg_perclk, NULL); +DEF_CLK(gpt_clk, CCGR1, CG10, &ipg_perclk, &gpt_serial_clk); +DEF_CLK(gpu2d_core_clk, CCGR1, CG12, &pll2_pfd_352m, &gpu2d_axi_clk); +DEF_CLK(gpu3d_core_clk, CCGR1, CG13, &pll2_pfd_594m, &gpu3d_axi_clk); +DEF_CLK(gpu3d_shader_clk, CCGR1, CG13, &pll3_pfd_720m, &gpu3d_axi_clk); +DEF_CLK(hdmi_iahb_clk, CCGR2, CG0, &ahb_clk, NULL); +DEF_CLK(hdmi_isfr_clk, CCGR2, CG2, &pll3_pfd_540m, &hdmi_iahb_clk); +DEF_CLK(i2c1_clk, CCGR2, CG3, &ipg_perclk, NULL); +DEF_CLK(i2c2_clk, CCGR2, CG4, &ipg_perclk, NULL); +DEF_CLK(i2c3_clk, CCGR2, CG5, &ipg_perclk, NULL); +DEF_CLK(iim_clk, CCGR2, CG6, &ipg_clk, NULL); +DEF_CLK(enfc_clk, CCGR2, CG7, &pll2_pfd_352m, NULL); +DEF_CLK(ipu1_clk, CCGR3, CG0, &mmdc_ch0_axi_clk, NULL); +DEF_CLK(ipu1_di0_clk, CCGR3, CG1, &ipu1_di0_pre_clk, NULL); +DEF_CLK(ipu1_di1_clk, CCGR3, CG2, &ipu1_di1_pre_clk, NULL); +DEF_CLK(ipu2_clk, CCGR3, CG3, &mmdc_ch0_axi_clk, NULL); +DEF_CLK(ipu2_di0_clk, CCGR3, CG4, &ipu2_di0_pre_clk, NULL); +DEF_CLK(ipu2_di1_clk, CCGR3, CG5, &ipu2_di1_pre_clk, NULL); +DEF_CLK(ldb_di0_clk, CCGR3, CG6, &pll3_pfd_540m, NULL); +DEF_CLK(ldb_di1_clk, CCGR3, CG7, &pll3_pfd_540m, NULL); +DEF_CLK(hsi_tx_clk, CCGR3, CG8, &pll2_pfd_400m, NULL); +DEF_CLK(mlb_clk, CCGR3, CG9, &pll6_mlb, NULL); +DEF_CLK(mmdc_ch0_ipg_clk, CCGR3, CG12, &ipg_clk, NULL); +DEF_CLK(mmdc_ch0_axi_clk, CCGR3, CG10, &periph_clk, &mmdc_ch0_ipg_clk); +DEF_CLK(mmdc_ch1_ipg_clk, CCGR3, CG13, &ipg_clk, NULL); +DEF_CLK(mmdc_ch1_axi_clk, CCGR3, CG11, &periph2_clk, &mmdc_ch1_ipg_clk); +DEF_CLK(openvg_axi_clk, CCGR3, CG13, &axi_clk, NULL); +DEF_CLK(pwm1_clk, CCGR4, CG8, &ipg_perclk, NULL); +DEF_CLK(pwm2_clk, CCGR4, CG9, &ipg_perclk, NULL); +DEF_CLK(pwm3_clk, CCGR4, CG10, &ipg_perclk, NULL); +DEF_CLK(pwm4_clk, CCGR4, CG11, &ipg_perclk, NULL); +DEF_CLK(gpmi_bch_apb_clk, CCGR4, CG12, &usdhc3_clk, NULL); +DEF_CLK(gpmi_bch_clk, CCGR4, CG13, &usdhc4_clk, &gpmi_bch_apb_clk); +DEF_CLK(gpmi_apb_clk, CCGR4, CG15, &usdhc3_clk, &gpmi_bch_clk); +DEF_CLK(gpmi_io_clk, CCGR4, CG14, &enfc_clk, &gpmi_apb_clk); +DEF_CLK(sdma_clk, CCGR5, CG3, &ahb_clk, NULL); +DEF_CLK(spba_clk, CCGR5, CG6, &ipg_clk, NULL); +DEF_CLK(spdif_clk, CCGR5, CG7, &pll3_usb_otg, &spba_clk); +DEF_CLK(ssi1_clk, CCGR5, CG9, &pll3_pfd_508m, NULL); +DEF_CLK(ssi2_clk, CCGR5, CG10, &pll3_pfd_508m, NULL); +DEF_CLK(ssi3_clk, CCGR5, CG11, &pll3_pfd_508m, NULL); +DEF_CLK(uart_serial_clk, CCGR5, CG13, &pll3_usb_otg, NULL); +DEF_CLK(uart_clk, CCGR5, CG12, &pll3_80m, &uart_serial_clk); +DEF_CLK(usboh3_clk, CCGR6, CG0, &ipg_clk, NULL); +DEF_CLK(usdhc1_clk, CCGR6, CG1, &pll2_pfd_400m, NULL); +DEF_CLK(usdhc2_clk, CCGR6, CG2, &pll2_pfd_400m, NULL); +DEF_CLK(usdhc3_clk, CCGR6, CG3, &pll2_pfd_400m, NULL); +DEF_CLK(usdhc4_clk, CCGR6, CG4, &pll2_pfd_400m, NULL); +DEF_CLK(emi_slow_clk, CCGR6, CG5, &axi_clk, NULL); +DEF_CLK(vdo_axi_clk, CCGR6, CG6, &axi_clk, NULL); +DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, NULL); +DEF_CLK_1B(cko1_clk, CCOSR, BP_CCOSR_CKO1_EN, &pll2_bus, NULL); + +static int pcie_clk_enable(struct clk *clk) +{ + u32 val; + + val = readl_relaxed(PLL8_ENET); + val |= BM_PLL_ENET_EN_PCIE; + writel_relaxed(val, PLL8_ENET); + + return _clk_enable(clk); +} + +static void pcie_clk_disable(struct clk *clk) +{ + u32 val; + + _clk_disable(clk); + + val = readl_relaxed(PLL8_ENET); + val &= BM_PLL_ENET_EN_PCIE; + writel_relaxed(val, PLL8_ENET); +} + +static struct clk pcie_clk = { + .enable_reg = CCGR4, + .enable_shift = CG0, + .enable = pcie_clk_enable, + .disable = pcie_clk_disable, + .set_parent = _clk_set_parent, + .parent = &axi_clk, + .secondary = &pll8_enet, +}; + +static int sata_clk_enable(struct clk *clk) +{ + u32 val; + + val = readl_relaxed(PLL8_ENET); + val |= BM_PLL_ENET_EN_SATA; + writel_relaxed(val, PLL8_ENET); + + return _clk_enable(clk); +} + +static void sata_clk_disable(struct clk *clk) +{ + u32 val; + + _clk_disable(clk); + + val = readl_relaxed(PLL8_ENET); + val &= BM_PLL_ENET_EN_SATA; + writel_relaxed(val, PLL8_ENET); +} + +static struct clk sata_clk = { + .enable_reg = CCGR5, + .enable_shift = CG2, + .enable = sata_clk_enable, + .disable = sata_clk_disable, + .parent = &ipg_clk, + .secondary = &pll8_enet, +}; + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + } + +static struct clk_lookup lookups[] = { + _REGISTER_CLOCK("2020000.uart", NULL, uart_clk), + _REGISTER_CLOCK("21e8000.uart", NULL, uart_clk), + _REGISTER_CLOCK("21ec000.uart", NULL, uart_clk), + _REGISTER_CLOCK("21f0000.uart", NULL, uart_clk), + _REGISTER_CLOCK("21f4000.uart", NULL, uart_clk), + _REGISTER_CLOCK("2188000.enet", NULL, enet_clk), + _REGISTER_CLOCK("2190000.usdhc", NULL, usdhc1_clk), + _REGISTER_CLOCK("2194000.usdhc", NULL, usdhc2_clk), + _REGISTER_CLOCK("2198000.usdhc", NULL, usdhc3_clk), + _REGISTER_CLOCK("219c000.usdhc", NULL, usdhc4_clk), + _REGISTER_CLOCK("21a0000.i2c", NULL, i2c1_clk), + _REGISTER_CLOCK("21a4000.i2c", NULL, i2c2_clk), + _REGISTER_CLOCK("21a8000.i2c", NULL, i2c3_clk), + _REGISTER_CLOCK("2008000.ecspi", NULL, ecspi1_clk), + _REGISTER_CLOCK("200c000.ecspi", NULL, ecspi2_clk), + _REGISTER_CLOCK("2010000.ecspi", NULL, ecspi3_clk), + _REGISTER_CLOCK("2014000.ecspi", NULL, ecspi4_clk), + _REGISTER_CLOCK("2018000.ecspi", NULL, ecspi5_clk), + _REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk), + _REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk), + _REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk), + _REGISTER_CLOCK("smp_twd", NULL, twd_clk), + _REGISTER_CLOCK(NULL, "ckih", ckih_clk), + _REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk), + _REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk), + _REGISTER_CLOCK(NULL, "aips_tz2_clk", aips_tz2_clk), + _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk), + _REGISTER_CLOCK(NULL, "can2_clk", can2_clk), + _REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_isfr_clk), + _REGISTER_CLOCK(NULL, "iim_clk", iim_clk), + _REGISTER_CLOCK(NULL, "mlb_clk", mlb_clk), + _REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk), + _REGISTER_CLOCK(NULL, "pwm1_clk", pwm1_clk), + _REGISTER_CLOCK(NULL, "pwm2_clk", pwm2_clk), + _REGISTER_CLOCK(NULL, "pwm3_clk", pwm3_clk), + _REGISTER_CLOCK(NULL, "pwm4_clk", pwm4_clk), + _REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk), + _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk), + _REGISTER_CLOCK(NULL, "sata_clk", sata_clk), + _REGISTER_CLOCK(NULL, "cko1_clk", cko1_clk), +}; + +int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) +{ + u32 val = readl_relaxed(CLPCR); + + val &= ~BM_CLPCR_LPM; + switch (mode) { + case WAIT_CLOCKED: + break; + case WAIT_UNCLOCKED: + val |= 0x1 << BP_CLPCR_LPM; + break; + case STOP_POWER_ON: + val |= 0x2 << BP_CLPCR_LPM; + break; + case WAIT_UNCLOCKED_POWER_OFF: + val |= 0x1 << BP_CLPCR_LPM; + val &= ~BM_CLPCR_VSTBY; + val &= ~BM_CLPCR_SBYOS; + break; + case STOP_POWER_OFF: + val |= 0x2 << BP_CLPCR_LPM; + val |= 0x3 << BP_CLPCR_STBY_COUNT; + val |= BM_CLPCR_VSTBY; + val |= BM_CLPCR_SBYOS; + break; + default: + return -EINVAL; + } + writel_relaxed(val, CLPCR); + + return 0; +} + +static struct map_desc imx6q_clock_desc[] = { + imx_map_entry(MX6Q, CCM, MT_DEVICE), + imx_map_entry(MX6Q, ANATOP, MT_DEVICE), +}; + +void __init imx6q_clock_map_io(void) +{ + iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc)); +} + +int __init mx6q_clocks_init(void) +{ + struct device_node *np; + void __iomem *base; + int i, irq; + + /* 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")) + external_low_reference = rate; + else if (of_device_is_compatible(np, "fsl,imx-ckih1")) + external_high_reference = rate; + else if (of_device_is_compatible(np, "fsl,imx-osc")) + oscillator_reference = rate; + } + + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + + /* only keep necessary clocks on */ + writel_relaxed(0x3 << CG0 | 0x3 << CG1 | 0x3 << CG2, CCGR0); + writel_relaxed(0x3 << CG8 | 0x3 << CG9 | 0x3 << CG10, CCGR2); + writel_relaxed(0x3 << CG10 | 0x3 << CG12, CCGR3); + writel_relaxed(0x3 << CG4 | 0x3 << CG6 | 0x3 << CG7, CCGR4); + writel_relaxed(0x3 << CG0, CCGR5); + writel_relaxed(0, CCGR6); + writel_relaxed(0, CCGR7); + + clk_enable(&uart_clk); + clk_enable(&mmdc_ch0_axi_clk); + + clk_set_rate(&pll4_audio, FREQ_650M); + clk_set_rate(&pll5_video, FREQ_650M); + clk_set_parent(&ipu1_di0_clk, &ipu1_di0_pre_clk); + clk_set_parent(&ipu1_di0_pre_clk, &pll5_video); + clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594m); + clk_set_rate(&gpu3d_shader_clk, FREQ_594M); + clk_set_parent(&gpu3d_core_clk, &mmdc_ch0_axi_clk); + clk_set_rate(&gpu3d_core_clk, FREQ_528M); + clk_set_parent(&asrc_serial_clk, &pll3_usb_otg); + clk_set_rate(&asrc_serial_clk, 1500000); + clk_set_rate(&enfc_clk, 11000000); + + /* + * Before pinctrl API is available, we have to rely on the pad + * configuration set up by bootloader. For usdhc example here, + * u-boot sets up the pads for 49.5 MHz case, and we have to lower + * the usdhc clock from 198 to 49.5 MHz to match the pad configuration. + * + * FIXME: This is should be removed after pinctrl API is available. + * At that time, usdhc driver can call pinctrl API to change pad + * configuration dynamically per different usdhc clock settings. + */ + clk_set_rate(&usdhc1_clk, 49500000); + clk_set_rate(&usdhc2_clk, 49500000); + clk_set_rate(&usdhc3_clk, 49500000); + clk_set_rate(&usdhc4_clk, 49500000); + + clk_set_parent(&cko1_clk, &ahb_clk); + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); + base = of_iomap(np, 0); + WARN_ON(!base); + irq = irq_of_parse_and_map(np, 0); + mxc_timer_init(&gpt_clk, base, irq); + + return 0; +} diff --git a/arch/arm/mach-imx/clock-mx51-mx53.c b/arch/arm/mach-imx/clock-mx51-mx53.c new file mode 100644 index 00000000..08470504 --- /dev/null +++ b/arch/arm/mach-imx/clock-mx51-mx53.c @@ -0,0 +1,1675 @@ +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2009-2010 Amit Kucheria + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "crm-regs-imx5.h" + +/* External clock values passed-in by the board code */ +static unsigned long external_high_reference, external_low_reference; +static unsigned long oscillator_reference, ckih2_reference; + +static struct clk osc_clk; +static struct clk pll1_main_clk; +static struct clk pll1_sw_clk; +static struct clk pll2_sw_clk; +static struct clk pll3_sw_clk; +static struct clk mx53_pll4_sw_clk; +static struct clk lp_apm_clk; +static struct clk periph_apm_clk; +static struct clk ahb_clk; +static struct clk ipg_clk; +static struct clk usboh3_clk; +static struct clk emi_fast_clk; +static struct clk ipu_clk; +static struct clk mipi_hsc1_clk; +static struct clk esdhc1_clk; +static struct clk esdhc2_clk; +static struct clk esdhc3_mx53_clk; + +#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ + +/* calculate best pre and post dividers to get the required divider */ +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post, + u32 max_pre, u32 max_post) +{ + if (div >= max_pre * max_post) { + *pre = max_pre; + *post = max_post; + } else if (div >= max_pre) { + u32 min_pre, temp_pre, old_err, err; + min_pre = DIV_ROUND_UP(div, max_post); + old_err = max_pre; + for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) { + err = div % temp_pre; + if (err == 0) { + *pre = temp_pre; + break; + } + err = temp_pre - err; + if (err < old_err) { + old_err = err; + *pre = temp_pre; + } + } + *post = DIV_ROUND_UP(div, *pre); + } else { + *pre = div; + *post = 1; + } +} + +static void _clk_ccgr_setclk(struct clk *clk, unsigned mode) +{ + u32 reg = __raw_readl(clk->enable_reg); + + reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift); + reg |= mode << clk->enable_shift; + + __raw_writel(reg, clk->enable_reg); +} + +static int _clk_ccgr_enable(struct clk *clk) +{ + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON); + return 0; +} + +static void _clk_ccgr_disable(struct clk *clk) +{ + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF); +} + +static int _clk_ccgr_enable_inrun(struct clk *clk) +{ + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE); + return 0; +} + +static void _clk_ccgr_disable_inwait(struct clk *clk) +{ + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE); +} + +/* + * For the 4-to-1 muxed input clock + */ +static inline u32 _get_mux(struct clk *parent, struct clk *m0, + struct clk *m1, struct clk *m2, struct clk *m3) +{ + if (parent == m0) + return 0; + else if (parent == m1) + return 1; + else if (parent == m2) + return 2; + else if (parent == m3) + return 3; + else + BUG(); + + return -EINVAL; +} + +static inline void __iomem *_mx51_get_pll_base(struct clk *pll) +{ + if (pll == &pll1_main_clk) + return MX51_DPLL1_BASE; + else if (pll == &pll2_sw_clk) + return MX51_DPLL2_BASE; + else if (pll == &pll3_sw_clk) + return MX51_DPLL3_BASE; + else + BUG(); + + return NULL; +} + +static inline void __iomem *_mx53_get_pll_base(struct clk *pll) +{ + if (pll == &pll1_main_clk) + return MX53_DPLL1_BASE; + else if (pll == &pll2_sw_clk) + return MX53_DPLL2_BASE; + else if (pll == &pll3_sw_clk) + return MX53_DPLL3_BASE; + else if (pll == &mx53_pll4_sw_clk) + return MX53_DPLL4_BASE; + else + BUG(); + + return NULL; +} + +static inline void __iomem *_get_pll_base(struct clk *pll) +{ + if (cpu_is_mx51()) + return _mx51_get_pll_base(pll); + else + return _mx53_get_pll_base(pll); +} + +static unsigned long clk_pll_get_rate(struct clk *clk) +{ + long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; + unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl; + void __iomem *pllbase; + s64 temp; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + pllbase = _get_pll_base(clk); + + dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); + pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; + dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; + + if (pll_hfsm == 0) { + dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); + } else { + dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN); + } + pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; + mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; + mfi = (mfi <= 5) ? 5 : mfi; + mfd = dp_mfd & MXC_PLL_DP_MFD_MASK; + mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK; + /* Sign extend to 32-bits */ + if (mfn >= 0x04000000) { + mfn |= 0xFC000000; + mfn_abs = -mfn; + } + + ref_clk = 2 * parent_rate; + if (dbl != 0) + ref_clk *= 2; + + ref_clk /= (pdf + 1); + temp = (u64) ref_clk * mfn_abs; + do_div(temp, mfd + 1); + if (mfn < 0) + temp = -temp; + temp = (ref_clk * mfi) + temp; + + return temp; +} + +static int _clk_pll_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + void __iomem *pllbase; + + long mfi, pdf, mfn, mfd = 999999; + s64 temp64; + unsigned long quad_parent_rate; + unsigned long pll_hfsm, dp_ctl; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + pllbase = _get_pll_base(clk); + + quad_parent_rate = 4 * parent_rate; + pdf = mfi = -1; + while (++pdf < 16 && mfi < 5) + mfi = rate * (pdf+1) / quad_parent_rate; + if (mfi > 15) + return -EINVAL; + pdf--; + + temp64 = rate * (pdf+1) - quad_parent_rate * mfi; + do_div(temp64, quad_parent_rate/1000000); + mfn = (long)temp64; + + dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); + /* use dpdck0_2 */ + __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); + pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; + if (pll_hfsm == 0) { + reg = mfi << 4 | pdf; + __raw_writel(reg, pllbase + MXC_PLL_DP_OP); + __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD); + __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN); + } else { + reg = mfi << 4 | pdf; + __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP); + __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD); + __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN); + } + + return 0; +} + +static int _clk_pll_enable(struct clk *clk) +{ + u32 reg; + void __iomem *pllbase; + int i = 0; + + pllbase = _get_pll_base(clk); + reg = __raw_readl(pllbase + MXC_PLL_DP_CTL); + if (reg & MXC_PLL_DP_CTL_UPEN) + return 0; + + reg |= MXC_PLL_DP_CTL_UPEN; + __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); + + /* Wait for lock */ + do { + reg = __raw_readl(pllbase + MXC_PLL_DP_CTL); + if (reg & MXC_PLL_DP_CTL_LRF) + break; + + udelay(1); + } while (++i < MAX_DPLL_WAIT_TRIES); + + if (i == MAX_DPLL_WAIT_TRIES) { + pr_err("MX5: pll locking failed\n"); + return -EINVAL; + } + + return 0; +} + +static void _clk_pll_disable(struct clk *clk) +{ + u32 reg; + void __iomem *pllbase; + + pllbase = _get_pll_base(clk); + reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN; + __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); +} + +static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, step; + + reg = __raw_readl(MXC_CCM_CCSR); + + /* When switching from pll_main_clk to a bypass clock, first select a + * multiplexed clock in 'step_sel', then shift the glitchless mux + * 'pll1_sw_clk_sel'. + * + * When switching back, do it in reverse order + */ + if (parent == &pll1_main_clk) { + /* Switch to pll1_main_clk */ + reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + __raw_writel(reg, MXC_CCM_CCSR); + /* step_clk mux switched to lp_apm, to save power. */ + reg = __raw_readl(MXC_CCM_CCSR); + reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK; + reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM << + MXC_CCM_CCSR_STEP_SEL_OFFSET); + } else { + if (parent == &lp_apm_clk) { + step = MXC_CCM_CCSR_STEP_SEL_LP_APM; + } else if (parent == &pll2_sw_clk) { + step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED; + } else if (parent == &pll3_sw_clk) { + step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED; + } else + return -EINVAL; + + reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK; + reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET); + + __raw_writel(reg, MXC_CCM_CCSR); + /* Switch to step_clk */ + reg = __raw_readl(MXC_CCM_CCSR); + reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + } + __raw_writel(reg, MXC_CCM_CCSR); + return 0; +} + +static unsigned long clk_pll1_sw_get_rate(struct clk *clk) +{ + u32 reg, div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + reg = __raw_readl(MXC_CCM_CCSR); + + if (clk->parent == &pll2_sw_clk) { + div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >> + MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1; + } else if (clk->parent == &pll3_sw_clk) { + div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >> + MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1; + } else + div = 1; + return parent_rate / div; +} + +static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CCSR); + + if (parent == &pll2_sw_clk) + reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL; + else + reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL; + + __raw_writel(reg, MXC_CCM_CCSR); + return 0; +} + +static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + if (parent == &osc_clk) + reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL; + else + return -EINVAL; + + __raw_writel(reg, MXC_CCM_CCSR); + + return 0; +} + +static unsigned long clk_cpu_get_rate(struct clk *clk) +{ + u32 cacrr, div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + cacrr = __raw_readl(MXC_CCM_CACRR); + div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1; + + return parent_rate / div; +} + +static int clk_cpu_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, cpu_podf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + cpu_podf = parent_rate / rate - 1; + /* use post divider to change freq */ + reg = __raw_readl(MXC_CCM_CACRR); + reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK; + reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CACRR); + + return 0; +} + +static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + int i = 0; + + mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL); + + reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CBCMR); + + /* Wait for lock */ + do { + reg = __raw_readl(MXC_CCM_CDHIPR); + if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY)) + break; + + udelay(1); + } while (++i < MAX_DPLL_WAIT_TRIES); + + if (i == MAX_DPLL_WAIT_TRIES) { + pr_err("MX5: Set parent for periph_apm clock failed\n"); + return -EINVAL; + } + + return 0; +} + +static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CBCDR); + + if (parent == &pll2_sw_clk) + reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL; + else if (parent == &periph_apm_clk) + reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL; + else + return -EINVAL; + + __raw_writel(reg, MXC_CCM_CBCDR); + + return 0; +} + +static struct clk main_bus_clk = { + .parent = &pll2_sw_clk, + .set_parent = _clk_main_bus_set_parent, +}; + +static unsigned long clk_ahb_get_rate(struct clk *clk) +{ + u32 reg, div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >> + MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1; + return parent_rate / div; +} + + +static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + unsigned long parent_rate; + int i = 0; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (div > 8 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + + /* Wait for lock */ + do { + reg = __raw_readl(MXC_CCM_CDHIPR); + if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY)) + break; + + udelay(1); + } while (++i < MAX_DPLL_WAIT_TRIES); + + if (i == MAX_DPLL_WAIT_TRIES) { + pr_err("MX5: clk_ahb_set_rate failed\n"); + return -EINVAL; + } + + return 0; +} + +static unsigned long _clk_ahb_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return parent_rate / div; +} + + +static int _clk_max_enable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_enable(clk); + + /* Handshake with MAX when LPM is entered. */ + reg = __raw_readl(MXC_CCM_CLPCR); + if (cpu_is_mx51()) + reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS; + else if (cpu_is_mx53()) + reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static void _clk_max_disable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_disable_inwait(clk); + + /* No Handshake with MAX when LPM is entered as its disabled. */ + reg = __raw_readl(MXC_CCM_CLPCR); + if (cpu_is_mx51()) + reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS; + else if (cpu_is_mx53()) + reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + +static unsigned long clk_ipg_get_rate(struct clk *clk) +{ + u32 reg, div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >> + MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1; + + return parent_rate / div; +} + +static unsigned long clk_ipg_per_get_rate(struct clk *clk) +{ + u32 reg, prediv1, prediv2, podf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) { + /* the main_bus_clk is the one before the DVFS engine */ + reg = __raw_readl(MXC_CCM_CBCDR); + prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1; + prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1; + podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >> + MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1; + return parent_rate / (prediv1 * prediv2 * podf); + } else if (clk->parent == &ipg_clk) + return parent_rate; + else + BUG(); +} + +static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CBCMR); + + reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL; + reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL; + + if (parent == &ipg_clk) + reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL; + else if (parent == &lp_apm_clk) + reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL; + else if (parent != &main_bus_clk) + return -EINVAL; + + __raw_writel(reg, MXC_CCM_CBCMR); + + return 0; +} + +#define clk_nfc_set_parent NULL + +static unsigned long clk_nfc_get_rate(struct clk *clk) +{ + unsigned long rate; + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >> + MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1; + rate = clk_get_rate(clk->parent) / div; + WARN_ON(rate == 0); + return rate; +} + +static unsigned long clk_nfc_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + unsigned long parent_rate = clk_get_rate(clk->parent); + + if (!rate) + return -EINVAL; + + div = parent_rate / rate; + + if (parent_rate % rate) + div++; + + if (div > 8) + return -EINVAL; + + return parent_rate / div; + +} + +static int clk_nfc_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + + div = clk_get_rate(clk->parent) / rate; + if (div == 0) + div++; + if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8)) + return -EINVAL; + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + + while (__raw_readl(MXC_CCM_CDHIPR) & + MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){ + } + + return 0; +} + +static unsigned long get_high_reference_clock_rate(struct clk *clk) +{ + return external_high_reference; +} + +static unsigned long get_low_reference_clock_rate(struct clk *clk) +{ + return external_low_reference; +} + +static unsigned long get_oscillator_reference_clock_rate(struct clk *clk) +{ + return oscillator_reference; +} + +static unsigned long get_ckih2_reference_clock_rate(struct clk *clk) +{ + return ckih2_reference; +} + +static unsigned long clk_emi_slow_get_rate(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >> + MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1; + + return clk_get_rate(clk->parent) / div; +} + +static unsigned long _clk_ddr_hf_get_rate(struct clk *clk) +{ + unsigned long rate; + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >> + MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1; + rate = clk_get_rate(clk->parent) / div; + + return rate; +} + +/* External high frequency clock */ +static struct clk ckih_clk = { + .get_rate = get_high_reference_clock_rate, +}; + +static struct clk ckih2_clk = { + .get_rate = get_ckih2_reference_clock_rate, +}; + +static struct clk osc_clk = { + .get_rate = get_oscillator_reference_clock_rate, +}; + +/* External low frequency (32kHz) clock */ +static struct clk ckil_clk = { + .get_rate = get_low_reference_clock_rate, +}; + +static struct clk pll1_main_clk = { + .parent = &osc_clk, + .get_rate = clk_pll_get_rate, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, +}; + +/* Clock tree block diagram (WIP): + * CCM: Clock Controller Module + * + * PLL output -> | + * | CCM Switcher -> CCM_CLK_ROOT_GEN -> + * PLL bypass -> | + * + */ + +/* PLL1 SW supplies to ARM core */ +static struct clk pll1_sw_clk = { + .parent = &pll1_main_clk, + .set_parent = _clk_pll1_sw_set_parent, + .get_rate = clk_pll1_sw_get_rate, +}; + +/* PLL2 SW supplies to AXI/AHB/IP buses */ +static struct clk pll2_sw_clk = { + .parent = &osc_clk, + .get_rate = clk_pll_get_rate, + .set_rate = _clk_pll_set_rate, + .set_parent = _clk_pll2_sw_set_parent, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, +}; + +/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */ +static struct clk pll3_sw_clk = { + .parent = &osc_clk, + .set_rate = _clk_pll_set_rate, + .get_rate = clk_pll_get_rate, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, +}; + +/* PLL4 SW supplies to LVDS Display Bridge(LDB) */ +static struct clk mx53_pll4_sw_clk = { + .parent = &osc_clk, + .set_rate = _clk_pll_set_rate, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, +}; + +/* Low-power Audio Playback Mode clock */ +static struct clk lp_apm_clk = { + .parent = &osc_clk, + .set_parent = _clk_lp_apm_set_parent, +}; + +static struct clk periph_apm_clk = { + .parent = &pll1_sw_clk, + .set_parent = _clk_periph_apm_set_parent, +}; + +static struct clk cpu_clk = { + .parent = &pll1_sw_clk, + .get_rate = clk_cpu_get_rate, + .set_rate = clk_cpu_set_rate, +}; + +static struct clk ahb_clk = { + .parent = &main_bus_clk, + .get_rate = clk_ahb_get_rate, + .set_rate = _clk_ahb_set_rate, + .round_rate = _clk_ahb_round_rate, +}; + +static struct clk iim_clk = { + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET, +}; + +/* Main IP interface clock for access to registers */ +static struct clk ipg_clk = { + .parent = &ahb_clk, + .get_rate = clk_ipg_get_rate, +}; + +static struct clk ipg_perclk = { + .parent = &lp_apm_clk, + .get_rate = clk_ipg_per_get_rate, + .set_parent = _clk_ipg_per_set_parent, +}; + +static struct clk ahb_max_clk = { + .parent = &ahb_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, +}; + +static struct clk aips_tz1_clk = { + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable_inwait, +}; + +static struct clk aips_tz2_clk = { + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable_inwait, +}; + +static struct clk gpc_dvfs_clk = { + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable, +}; + +static struct clk gpt_32k_clk = { + .id = 0, + .parent = &ckil_clk, +}; + +static struct clk dummy_clk = { + .id = 0, +}; + +static struct clk emi_slow_clk = { + .parent = &pll2_sw_clk, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable_inwait, + .get_rate = clk_emi_slow_get_rate, +}; + +static int clk_ipu_enable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_enable(clk); + + /* Enable handshake with IPU when certain clock rates are changed */ + reg = __raw_readl(MXC_CCM_CCDR); + reg &= ~MXC_CCM_CCDR_IPU_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + /* Enable handshake with IPU when LPM is entered */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static void clk_ipu_disable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_disable(clk); + + /* Disable handshake with IPU whe dividers are changed */ + reg = __raw_readl(MXC_CCM_CCDR); + reg |= MXC_CCM_CCDR_IPU_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + /* Disable handshake with IPU when LPM is entered */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + +static struct clk ahbmux1_clk = { + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable_inwait, +}; + +static struct clk ipu_sec_clk = { + .parent = &emi_fast_clk, + .secondary = &ahbmux1_clk, +}; + +static struct clk ddr_hf_clk = { + .parent = &pll1_sw_clk, + .get_rate = _clk_ddr_hf_get_rate, +}; + +static struct clk ddr_clk = { + .parent = &ddr_hf_clk, +}; + +/* clock definitions for MIPI HSC unit which has been removed + * from documentation, but not from hardware + */ +static int _clk_hsc_enable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_enable(clk); + /* Handshake with IPU when certain clock rates are changed. */ + reg = __raw_readl(MXC_CCM_CCDR); + reg &= ~MXC_CCM_CCDR_HSC_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + reg = __raw_readl(MXC_CCM_CLPCR); + reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static void _clk_hsc_disable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_disable(clk); + /* No handshake with HSC as its not enabled. */ + reg = __raw_readl(MXC_CCM_CCDR); + reg |= MXC_CCM_CCDR_HSC_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + +static struct clk mipi_hsp_clk = { + .parent = &ipu_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, + .enable = _clk_hsc_enable, + .disable = _clk_hsc_disable, + .secondary = &mipi_hsc1_clk, +}; + +#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = pfx##_get_rate, \ + .set_rate = pfx##_set_rate, \ + .round_rate = pfx##_round_rate, \ + .set_parent = pfx##_set_parent, \ + .enable = _clk_ccgr_enable, \ + .disable = _clk_ccgr_disable, \ + .parent = p, \ + .secondary = s, \ + } + +#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = pfx##_get_rate, \ + .set_rate = pfx##_set_rate, \ + .set_parent = pfx##_set_parent, \ + .enable = _clk_max_enable, \ + .disable = _clk_max_disable, \ + .parent = p, \ + .secondary = s, \ + } + +#define CLK_GET_RATE(name, nr, bitsname) \ +static unsigned long clk_##name##_get_rate(struct clk *clk) \ +{ \ + u32 reg, pred, podf; \ + \ + reg = __raw_readl(MXC_CCM_CSCDR##nr); \ + pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \ + >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ + podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \ + >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ + \ + return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \ + (pred + 1) * (podf + 1)); \ +} + +#define CLK_SET_PARENT(name, nr, bitsname) \ +static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \ +{ \ + u32 reg, mux; \ + \ + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \ + &pll3_sw_clk, &lp_apm_clk); \ + reg = __raw_readl(MXC_CCM_CSCMR##nr) & \ + ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \ + reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \ + __raw_writel(reg, MXC_CCM_CSCMR##nr); \ + \ + return 0; \ +} + +#define CLK_SET_RATE(name, nr, bitsname) \ +static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \ +{ \ + u32 reg, div, parent_rate; \ + u32 pre = 0, post = 0; \ + \ + parent_rate = clk_get_rate(clk->parent); \ + div = parent_rate / rate; \ + \ + if ((parent_rate / div) != rate) \ + return -EINVAL; \ + \ + __calc_pre_post_dividers(div, &pre, &post, \ + (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \ + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \ + (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \ + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\ + \ + /* Set sdhc1 clock divider */ \ + reg = __raw_readl(MXC_CCM_CSCDR##nr) & \ + ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \ + | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \ + reg |= (post - 1) << \ + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ + reg |= (pre - 1) << \ + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ + __raw_writel(reg, MXC_CCM_CSCDR##nr); \ + \ + return 0; \ +} + +/* UART */ +CLK_GET_RATE(uart, 1, UART) +CLK_SET_PARENT(uart, 1, UART) + +static struct clk uart_root_clk = { + .parent = &pll2_sw_clk, + .get_rate = clk_uart_get_rate, + .set_parent = clk_uart_set_parent, +}; + +/* USBOH3 */ +CLK_GET_RATE(usboh3, 1, USBOH3) +CLK_SET_PARENT(usboh3, 1, USBOH3) + +static struct clk usboh3_clk = { + .parent = &pll2_sw_clk, + .get_rate = clk_usboh3_get_rate, + .set_parent = clk_usboh3_set_parent, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET, +}; + +static struct clk usb_ahb_clk = { + .parent = &ipg_clk, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET, +}; + +static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL; + + if (parent == &pll3_sw_clk) + reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET; + + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk usb_phy1_clk = { + .parent = &pll3_sw_clk, + .set_parent = clk_usb_phy1_set_parent, + .enable = _clk_ccgr_enable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET, + .disable = _clk_ccgr_disable, +}; + +/* eCSPI */ +CLK_GET_RATE(ecspi, 2, CSPI) +CLK_SET_PARENT(ecspi, 1, CSPI) + +static struct clk ecspi_main_clk = { + .parent = &pll3_sw_clk, + .get_rate = clk_ecspi_get_rate, + .set_parent = clk_ecspi_set_parent, +}; + +/* eSDHC */ +CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1) +CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1) +CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1) + +/* mx51 specific */ +CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2) +CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2) +CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2) + +static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk) + reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL; + else if (parent == &esdhc2_clk) + reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL; + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk) + reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else if (parent == &esdhc2_clk) + reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +/* mx53 specific */ +static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk) + reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL; + else if (parent == &esdhc3_mx53_clk) + reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL; + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53) +CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53) +CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53) + +static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk) + reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else if (parent == &esdhc3_mx53_clk) + reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .set_rate = sr, \ + .enable = e, \ + .disable = d, \ + .parent = p, \ + .secondary = s, \ + } + +#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \ + DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s) + +/* Shared peripheral bus arbiter */ +DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET, + NULL, NULL, &ipg_clk, NULL); + +/* UART */ +DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET, + NULL, NULL, &ipg_clk, &aips_tz1_clk); +DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET, + NULL, NULL, &ipg_clk, &aips_tz1_clk); +DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET, + NULL, NULL, &ipg_clk, &spba_clk); +DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET, + NULL, NULL, &ipg_clk, &spba_clk); +DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, &ipg_clk, &spba_clk); +DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET, + NULL, NULL, &uart_root_clk, &uart1_ipg_clk); +DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, &uart_root_clk, &uart2_ipg_clk); +DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET, + NULL, NULL, &uart_root_clk, &uart3_ipg_clk); +DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET, + NULL, NULL, &uart_root_clk, &uart4_ipg_clk); +DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET, + NULL, NULL, &uart_root_clk, &uart5_ipg_clk); + +/* GPT */ +DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, &ipg_clk, &gpt_ipg_clk); + +DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, &ipg_perclk, NULL); +DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET, + NULL, NULL, &ipg_perclk, NULL); + +/* I2C */ +DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, &ipg_perclk, NULL); +DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET, + NULL, NULL, &ipg_perclk, NULL); +DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET, + NULL, NULL, &ipg_perclk, NULL); + +/* FEC */ +DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET, + NULL, NULL, &ipg_clk, NULL); + +/* NFC */ +DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET, + clk_nfc, &emi_slow_clk, NULL); + +/* SSI */ +DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk); +DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET, + NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk); +DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET, + NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk); + +/* eCSPI */ +DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable, + &ipg_clk, &spba_clk); +DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET, + NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk); +DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET, + NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable, + &ipg_clk, &aips_tz2_clk); +DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET, + NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk); + +/* CSPI */ +DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, &ipg_clk, &aips_tz2_clk); +DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET, + NULL, NULL, &ipg_clk, &cspi_ipg_clk); + +/* SDMA */ +DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET, + NULL, NULL, &ahb_clk, NULL); + +/* eSDHC */ +DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET, + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); +DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET, + clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk); +DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET, + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); +DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET, + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); +DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); + +/* mx51 specific */ +DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET, + clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk); + +static struct clk esdhc3_clk = { + .id = 2, + .parent = &esdhc1_clk, + .set_parent = clk_esdhc3_set_parent, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, + .secondary = &esdhc3_ipg_clk, +}; +static struct clk esdhc4_clk = { + .id = 3, + .parent = &esdhc1_clk, + .set_parent = clk_esdhc4_set_parent, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, + .secondary = &esdhc4_ipg_clk, +}; + +/* mx53 specific */ +static struct clk esdhc2_mx53_clk = { + .id = 2, + .parent = &esdhc1_clk, + .set_parent = clk_esdhc2_mx53_set_parent, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, + .secondary = &esdhc3_ipg_clk, +}; + +DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET, + clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk); + +static struct clk esdhc4_mx53_clk = { + .id = 3, + .parent = &esdhc1_clk, + .set_parent = clk_esdhc4_mx53_set_parent, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, + .secondary = &esdhc4_ipg_clk, +}; + +static struct clk sata_clk = { + .parent = &ipg_clk, + .enable = _clk_max_enable, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET, + .disable = _clk_max_disable, +}; + +static struct clk ahci_phy_clk = { + .parent = &usb_phy1_clk, +}; + +static struct clk ahci_dma_clk = { + .parent = &ahb_clk, +}; + +DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk); +DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk); +DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk); + +/* IPU */ +DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET, + NULL, NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk); + +DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET, + NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait, + &ddr_clk, NULL); + +DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET, + NULL, NULL, &pll3_sw_clk, NULL); +DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, &pll3_sw_clk, NULL); + +/* PATA */ +DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET, + NULL, NULL, &ipg_clk, &spba_clk); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup mx51_lookups[] = { + /* i.mx51 has the i.mx21 type uart */ + _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK(NULL, "gpt", gpt_clk) + /* i.mx51 has the i.mx27 type fec */ + _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) + _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk) + _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk) + _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk) + _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk) + /* i.mx51 has the i.mx35 type sdma */ + _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) + _REGISTER_CLOCK(NULL, "ckih", ckih_clk) + _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk) + _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk) + _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) + _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) + /* i.mx51 has the i.mx35 type cspi */ + _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk) + _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk) + _REGISTER_CLOCK(NULL, "iim_clk", iim_clk) + _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk) + _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk) + _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk) + _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk) + _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk) + _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk) + _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk) + _REGISTER_CLOCK("pata_imx", NULL, pata_clk) +}; + +static struct clk_lookup mx53_lookups[] = { + /* i.mx53 has the i.mx21 type uart */ + _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK(NULL, "gpt", gpt_clk) + /* i.mx53 has the i.mx25 type fec */ + _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk) + _REGISTER_CLOCK(NULL, "iim_clk", iim_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk) + /* i.mx53 has the i.mx51 type ecspi */ + _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) + _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) + /* i.mx53 has the i.mx25 type cspi */ + _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk) + _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk) + _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk) + /* i.mx53 has the i.mx35 type sdma */ + _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk) + _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk) + _REGISTER_CLOCK("pata_imx", NULL, pata_clk) + _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk) + _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk) + _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk) +}; + +static void clk_tree_init(void) +{ + u32 reg; + + ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk); + + /* + * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at + * 8MHz, its derived from lp_apm. + * + * FIXME: Verify if true for all boards + */ + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK; + reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK; + reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK; + reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET); + __raw_writel(reg, MXC_CCM_CBCDR); +} + +int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, + unsigned long ckih1, unsigned long ckih2) +{ + int i; + + external_low_reference = ckil; + external_high_reference = ckih1; + ckih2_reference = ckih2; + oscillator_reference = osc; + + for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++) + clkdev_add(&mx51_lookups[i]); + + clk_tree_init(); + + clk_enable(&cpu_clk); + clk_enable(&main_bus_clk); + + clk_enable(&iim_clk); + imx_print_silicon_rev("i.MX51", mx51_revision()); + clk_disable(&iim_clk); + + /* move usb_phy_clk to 24MHz */ + clk_set_parent(&usb_phy1_clk, &osc_clk); + + /* set the usboh3_clk parent to pll2_sw_clk */ + clk_set_parent(&usboh3_clk, &pll2_sw_clk); + + /* Set SDHC parents to be PLL2 */ + clk_set_parent(&esdhc1_clk, &pll2_sw_clk); + clk_set_parent(&esdhc2_clk, &pll2_sw_clk); + + /* set SDHC root clock as 166.25MHZ*/ + clk_set_rate(&esdhc1_clk, 166250000); + clk_set_rate(&esdhc2_clk, 166250000); + + /* System timer */ + mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), + MX51_INT_GPT); + return 0; +} + +int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, + unsigned long ckih1, unsigned long ckih2) +{ + int i; + + external_low_reference = ckil; + external_high_reference = ckih1; + ckih2_reference = ckih2; + oscillator_reference = osc; + + for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++) + clkdev_add(&mx53_lookups[i]); + + clk_tree_init(); + + clk_set_parent(&uart_root_clk, &pll3_sw_clk); + clk_enable(&cpu_clk); + clk_enable(&main_bus_clk); + + clk_enable(&iim_clk); + imx_print_silicon_rev("i.MX53", mx53_revision()); + clk_disable(&iim_clk); + + /* Set SDHC parents to be PLL2 */ + clk_set_parent(&esdhc1_clk, &pll2_sw_clk); + clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk); + + /* set SDHC root clock as 200MHZ*/ + clk_set_rate(&esdhc1_clk, 200000000); + clk_set_rate(&esdhc3_mx53_clk, 200000000); + + /* System timer */ + mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), + MX53_INT_GPT); + 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); +} + +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); +} +#endif diff --git a/arch/arm/mach-imx/cpu-imx25.c b/arch/arm/mach-imx/cpu-imx25.c new file mode 100644 index 00000000..6914bcbf --- /dev/null +++ b/arch/arm/mach-imx/cpu-imx25.c @@ -0,0 +1,41 @@ +/* + * MX25 CPU type detection + * + * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved + * + * 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 +#include +#include +#include + +static int mx25_cpu_rev = -1; + +static int mx25_read_cpu_rev(void) +{ + u32 rev; + + rev = __raw_readl(MX25_IO_ADDRESS(MX25_IIM_BASE_ADDR + MXC_IIMSREV)); + switch (rev) { + case 0x00: + return IMX_CHIP_REVISION_1_0; + case 0x01: + return IMX_CHIP_REVISION_1_1; + default: + return IMX_CHIP_REVISION_UNKNOWN; + } +} + +int mx25_revision(void) +{ + if (mx25_cpu_rev == -1) + mx25_cpu_rev = mx25_read_cpu_rev(); + + return mx25_cpu_rev; +} +EXPORT_SYMBOL(mx25_revision); diff --git a/arch/arm/mach-imx/cpu-imx27.c b/arch/arm/mach-imx/cpu-imx27.c new file mode 100644 index 00000000..ff38e150 --- /dev/null +++ b/arch/arm/mach-imx/cpu-imx27.c @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.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. + */ + +/* + * i.MX27 specific CPU detection code + */ + +#include +#include + +#include + +static int mx27_cpu_rev = -1; +static int mx27_cpu_partnumber; + +#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */ + +static int mx27_read_cpu_rev(void) +{ + u32 val; + /* + * now we have access to the IO registers. As we need + * the silicon revision very early we read it here to + * avoid any further hooks + */ + val = __raw_readl(MX27_IO_ADDRESS(MX27_SYSCTRL_BASE_ADDR + + SYS_CHIP_ID)); + + mx27_cpu_partnumber = (int)((val >> 12) & 0xFFFF); + + switch (val >> 28) { + case 0: + return IMX_CHIP_REVISION_1_0; + case 1: + return IMX_CHIP_REVISION_2_0; + case 2: + return IMX_CHIP_REVISION_2_1; + default: + return IMX_CHIP_REVISION_UNKNOWN; + } +} + +/* + * Returns: + * the silicon revision of the cpu + * -EINVAL - not a mx27 + */ +int mx27_revision(void) +{ + if (mx27_cpu_rev == -1) + mx27_cpu_rev = mx27_read_cpu_rev(); + + if (mx27_cpu_partnumber != 0x8821) + return -EINVAL; + + return mx27_cpu_rev; +} +EXPORT_SYMBOL(mx27_revision); diff --git a/arch/arm/mach-imx/cpu-imx31.c b/arch/arm/mach-imx/cpu-imx31.c new file mode 100644 index 00000000..3f2345f0 --- /dev/null +++ b/arch/arm/mach-imx/cpu-imx31.c @@ -0,0 +1,62 @@ +/* + * MX31 CPU type detection + * + * Copyright (c) 2009 Daniel Mack + * + * 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 +#include +#include +#include +#include + +static int mx31_cpu_rev = -1; + +static struct { + u8 srev; + const char *name; + unsigned int rev; +} mx31_cpu_type[] = { + { .srev = 0x00, .name = "i.MX31(L)", .rev = IMX_CHIP_REVISION_1_0 }, + { .srev = 0x10, .name = "i.MX31", .rev = IMX_CHIP_REVISION_1_1 }, + { .srev = 0x11, .name = "i.MX31L", .rev = IMX_CHIP_REVISION_1_1 }, + { .srev = 0x12, .name = "i.MX31", .rev = IMX_CHIP_REVISION_1_1 }, + { .srev = 0x13, .name = "i.MX31L", .rev = IMX_CHIP_REVISION_1_1 }, + { .srev = 0x14, .name = "i.MX31", .rev = IMX_CHIP_REVISION_1_2 }, + { .srev = 0x15, .name = "i.MX31L", .rev = IMX_CHIP_REVISION_1_2 }, + { .srev = 0x28, .name = "i.MX31", .rev = IMX_CHIP_REVISION_2_0 }, + { .srev = 0x29, .name = "i.MX31L", .rev = IMX_CHIP_REVISION_2_0 }, +}; + +static int mx31_read_cpu_rev(void) +{ + u32 i, srev; + + /* read SREV register from IIM module */ + srev = __raw_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV)); + srev &= 0xff; + + for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++) + if (srev == mx31_cpu_type[i].srev) { + imx_print_silicon_rev(mx31_cpu_type[i].name, + mx31_cpu_type[i].rev); + return mx31_cpu_type[i].rev; + } + + imx_print_silicon_rev("i.MX31", IMX_CHIP_REVISION_UNKNOWN); + return IMX_CHIP_REVISION_UNKNOWN; +} + +int mx31_revision(void) +{ + if (mx31_cpu_rev == -1) + mx31_cpu_rev = mx31_read_cpu_rev(); + + return mx31_cpu_rev; +} +EXPORT_SYMBOL(mx31_revision); diff --git a/arch/arm/mach-imx/cpu-imx35.c b/arch/arm/mach-imx/cpu-imx35.c new file mode 100644 index 00000000..846e46eb --- /dev/null +++ b/arch/arm/mach-imx/cpu-imx35.c @@ -0,0 +1,42 @@ +/* + * MX35 CPU type detection + * + * Copyright (c) 2009 Daniel Mack + * + * 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 +#include +#include +#include + +static int mx35_cpu_rev = -1; + +static int mx35_read_cpu_rev(void) +{ + u32 rev; + + rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV)); + switch (rev) { + case 0x00: + return IMX_CHIP_REVISION_1_0; + case 0x10: + return IMX_CHIP_REVISION_2_0; + case 0x11: + return IMX_CHIP_REVISION_2_1; + default: + return IMX_CHIP_REVISION_UNKNOWN; + } +} + +int mx35_revision(void) +{ + if (mx35_cpu_rev == -1) + mx35_cpu_rev = mx35_read_cpu_rev(); + + return mx35_cpu_rev; +} +EXPORT_SYMBOL(mx35_revision); diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c new file mode 100644 index 00000000..aa15c517 --- /dev/null +++ b/arch/arm/mach-imx/cpu-imx5.c @@ -0,0 +1,151 @@ +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + * + * This file contains the CPU initialization code. + */ + +#include +#include +#include +#include +#include +#include + +static int mx5_cpu_rev = -1; + +#define IIM_SREV 0x24 +#define MX50_HW_ADADIG_DIGPROG 0xB0 + +static int get_mx51_srev(void) +{ + void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR); + u32 rev = readl(iim_base + IIM_SREV) & 0xff; + + switch (rev) { + case 0x0: + return IMX_CHIP_REVISION_2_0; + case 0x10: + return IMX_CHIP_REVISION_3_0; + default: + return IMX_CHIP_REVISION_UNKNOWN; + } +} + +/* + * Returns: + * the silicon revision of the cpu + * -EINVAL - not a mx51 + */ +int mx51_revision(void) +{ + if (!cpu_is_mx51()) + return -EINVAL; + + if (mx5_cpu_rev == -1) + mx5_cpu_rev = get_mx51_srev(); + + return mx5_cpu_rev; +} +EXPORT_SYMBOL(mx51_revision); + +#ifdef CONFIG_NEON + +/* + * All versions of the silicon before Rev. 3 have broken NEON implementations. + * Dependent on link order - so the assumption is that vfp_init is called + * before us. + */ +static int __init mx51_neon_fixup(void) +{ + if (!cpu_is_mx51()) + return 0; + + if (mx51_revision() < IMX_CHIP_REVISION_3_0 && + (elf_hwcap & HWCAP_NEON)) { + elf_hwcap &= ~HWCAP_NEON; + pr_info("Turning off NEON support, detected broken NEON implementation\n"); + } + return 0; +} + +late_initcall(mx51_neon_fixup); +#endif + +static int get_mx53_srev(void) +{ + void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR); + u32 rev = readl(iim_base + IIM_SREV) & 0xff; + + switch (rev) { + case 0x0: + return IMX_CHIP_REVISION_1_0; + case 0x2: + return IMX_CHIP_REVISION_2_0; + case 0x3: + return IMX_CHIP_REVISION_2_1; + default: + return IMX_CHIP_REVISION_UNKNOWN; + } +} + +/* + * Returns: + * the silicon revision of the cpu + * -EINVAL - not a mx53 + */ +int mx53_revision(void) +{ + if (!cpu_is_mx53()) + return -EINVAL; + + if (mx5_cpu_rev == -1) + mx5_cpu_rev = get_mx53_srev(); + + return mx5_cpu_rev; +} +EXPORT_SYMBOL(mx53_revision); + +static int get_mx50_srev(void) +{ + void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K); + u32 rev; + + if (!anatop) { + mx5_cpu_rev = -EINVAL; + return 0; + } + + rev = readl(anatop + MX50_HW_ADADIG_DIGPROG); + rev &= 0xff; + + iounmap(anatop); + if (rev == 0x0) + return IMX_CHIP_REVISION_1_0; + else if (rev == 0x1) + return IMX_CHIP_REVISION_1_1; + return 0; +} + +/* + * Returns: + * the silicon revision of the cpu + * -EINVAL - not a mx50 + */ +int mx50_revision(void) +{ + if (!cpu_is_mx50()) + return -EINVAL; + + if (mx5_cpu_rev == -1) + mx5_cpu_rev = get_mx50_srev(); + + return mx5_cpu_rev; +} +EXPORT_SYMBOL(mx50_revision); diff --git a/arch/arm/mach-imx/cpu_op-mx51.c b/arch/arm/mach-imx/cpu_op-mx51.c new file mode 100644 index 00000000..7b92cd6d --- /dev/null +++ b/arch/arm/mach-imx/cpu_op-mx51.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include + +static struct cpu_op mx51_cpu_op[] = { + { + .cpu_rate = 160000000,}, + { + .cpu_rate = 800000000,}, +}; + +struct cpu_op *mx51_get_cpu_op(int *op) +{ + *op = ARRAY_SIZE(mx51_cpu_op); + return mx51_cpu_op; +} diff --git a/arch/arm/mach-imx/cpu_op-mx51.h b/arch/arm/mach-imx/cpu_op-mx51.h new file mode 100644 index 00000000..97477fec --- /dev/null +++ b/arch/arm/mach-imx/cpu_op-mx51.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +extern struct cpu_op *mx51_get_cpu_op(int *op); diff --git a/arch/arm/mach-imx/crm-regs-imx5.h b/arch/arm/mach-imx/crm-regs-imx5.h new file mode 100644 index 00000000..5e3f1f0f --- /dev/null +++ b/arch/arm/mach-imx/crm-regs-imx5.h @@ -0,0 +1,600 @@ +/* + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__ + +#define MX51_CCM_BASE MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR) +#define MX51_DPLL1_BASE MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR) +#define MX51_DPLL2_BASE MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR) +#define MX51_DPLL3_BASE MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR) +#define MX51_CORTEXA8_BASE MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR) +#define MX51_GPC_BASE MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR) + +/*MX53*/ +#define MX53_CCM_BASE MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR) +#define MX53_DPLL1_BASE MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR) +#define MX53_DPLL2_BASE MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR) +#define MX53_DPLL3_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) +#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL4_BASE_ADDR) + +/* PLL Register Offsets */ +#define MXC_PLL_DP_CTL 0x00 +#define MXC_PLL_DP_CONFIG 0x04 +#define MXC_PLL_DP_OP 0x08 +#define MXC_PLL_DP_MFD 0x0C +#define MXC_PLL_DP_MFN 0x10 +#define MXC_PLL_DP_MFNMINUS 0x14 +#define MXC_PLL_DP_MFNPLUS 0x18 +#define MXC_PLL_DP_HFS_OP 0x1C +#define MXC_PLL_DP_HFS_MFD 0x20 +#define MXC_PLL_DP_HFS_MFN 0x24 +#define MXC_PLL_DP_MFN_TOGC 0x28 +#define MXC_PLL_DP_DESTAT 0x2c + +/* PLL Register Bit definitions */ +#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000 +#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000 +#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12 +#define MXC_PLL_DP_CTL_ADE 0x800 +#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400 +#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8) +#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8 +#define MXC_PLL_DP_CTL_HFSM 0x80 +#define MXC_PLL_DP_CTL_PRE 0x40 +#define MXC_PLL_DP_CTL_UPEN 0x20 +#define MXC_PLL_DP_CTL_RST 0x10 +#define MXC_PLL_DP_CTL_RCP 0x8 +#define MXC_PLL_DP_CTL_PLM 0x4 +#define MXC_PLL_DP_CTL_BRM0 0x2 +#define MXC_PLL_DP_CTL_LRF 0x1 + +#define MXC_PLL_DP_CONFIG_BIST 0x8 +#define MXC_PLL_DP_CONFIG_SJC_CE 0x4 +#define MXC_PLL_DP_CONFIG_AREN 0x2 +#define MXC_PLL_DP_CONFIG_LDREQ 0x1 + +#define MXC_PLL_DP_OP_MFI_OFFSET 4 +#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4) +#define MXC_PLL_DP_OP_PDF_OFFSET 0 +#define MXC_PLL_DP_OP_PDF_MASK 0xF + +#define MXC_PLL_DP_MFD_OFFSET 0 +#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF + +#define MXC_PLL_DP_MFN_OFFSET 0x0 +#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF + +#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17) +#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16) +#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0 +#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF + +#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31) +#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF + +/* Register addresses of CCM*/ +#define MXC_CCM_CCR (MX51_CCM_BASE + 0x00) +#define MXC_CCM_CCDR (MX51_CCM_BASE + 0x04) +#define MXC_CCM_CSR (MX51_CCM_BASE + 0x08) +#define MXC_CCM_CCSR (MX51_CCM_BASE + 0x0C) +#define MXC_CCM_CACRR (MX51_CCM_BASE + 0x10) +#define MXC_CCM_CBCDR (MX51_CCM_BASE + 0x14) +#define MXC_CCM_CBCMR (MX51_CCM_BASE + 0x18) +#define MXC_CCM_CSCMR1 (MX51_CCM_BASE + 0x1C) +#define MXC_CCM_CSCMR2 (MX51_CCM_BASE + 0x20) +#define MXC_CCM_CSCDR1 (MX51_CCM_BASE + 0x24) +#define MXC_CCM_CS1CDR (MX51_CCM_BASE + 0x28) +#define MXC_CCM_CS2CDR (MX51_CCM_BASE + 0x2C) +#define MXC_CCM_CDCDR (MX51_CCM_BASE + 0x30) +#define MXC_CCM_CHSCDR (MX51_CCM_BASE + 0x34) +#define MXC_CCM_CSCDR2 (MX51_CCM_BASE + 0x38) +#define MXC_CCM_CSCDR3 (MX51_CCM_BASE + 0x3C) +#define MXC_CCM_CSCDR4 (MX51_CCM_BASE + 0x40) +#define MXC_CCM_CWDR (MX51_CCM_BASE + 0x44) +#define MXC_CCM_CDHIPR (MX51_CCM_BASE + 0x48) +#define MXC_CCM_CDCR (MX51_CCM_BASE + 0x4C) +#define MXC_CCM_CTOR (MX51_CCM_BASE + 0x50) +#define MXC_CCM_CLPCR (MX51_CCM_BASE + 0x54) +#define MXC_CCM_CISR (MX51_CCM_BASE + 0x58) +#define MXC_CCM_CIMR (MX51_CCM_BASE + 0x5C) +#define MXC_CCM_CCOSR (MX51_CCM_BASE + 0x60) +#define MXC_CCM_CGPR (MX51_CCM_BASE + 0x64) +#define MXC_CCM_CCGR0 (MX51_CCM_BASE + 0x68) +#define MXC_CCM_CCGR1 (MX51_CCM_BASE + 0x6C) +#define MXC_CCM_CCGR2 (MX51_CCM_BASE + 0x70) +#define MXC_CCM_CCGR3 (MX51_CCM_BASE + 0x74) +#define MXC_CCM_CCGR4 (MX51_CCM_BASE + 0x78) +#define MXC_CCM_CCGR5 (MX51_CCM_BASE + 0x7C) +#define MXC_CCM_CCGR6 (MX51_CCM_BASE + 0x80) +#define MXC_CCM_CCGR7 (MX51_CCM_BASE + 0x84) + +#define MXC_CCM_CMEOR (MX51_CCM_BASE + 0x84) + +/* Define the bits in register CCR */ +#define MXC_CCM_CCR_COSC_EN (1 << 12) +#define MXC_CCM_CCR_FPM_MULT_MASK (1 << 11) +#define MXC_CCM_CCR_CAMP2_EN (1 << 10) +#define MXC_CCM_CCR_CAMP1_EN (1 << 9) +#define MXC_CCM_CCR_FPM_EN (1 << 8) +#define MXC_CCM_CCR_OSCNT_OFFSET (0) +#define MXC_CCM_CCR_OSCNT_MASK (0xFF) + +/* Define the bits in register CCDR */ +#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18) +#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17) +#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16) + +/* Define the bits in register CSR */ +#define MXC_CCM_CSR_COSR_READY (1 << 5) +#define MXC_CCM_CSR_LVS_VALUE (1 << 4) +#define MXC_CCM_CSR_CAMP2_READY (1 << 3) +#define MXC_CCM_CSR_CAMP1_READY (1 << 2) +#define MXC_CCM_CSR_FPM_READY (1 << 1) +#define MXC_CCM_CSR_REF_EN_B (1 << 0) + +/* Define the bits in register CCSR */ +#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9) +#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7) +#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7) +#define MXC_CCM_CCSR_STEP_SEL_LP_APM 0 +#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS 1 /* Only when JTAG connected? */ +#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2 +#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3 +#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5) +#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5) +#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3) +#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3) +#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) /* 0: pll1_main_clk, + 1: step_clk */ +#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1) +#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0) + +/* Define the bits in register CACRR */ +#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0) +#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7) + +/* Define the bits in register CBCDR */ +#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26) +#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25) +#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET (30) +#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30) +#define MXC_CCM_CBCDR_DDR_PODF_OFFSET (27) +#define MXC_CCM_CBCDR_DDR_PODF_MASK (0x7 << 27) +#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22) +#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22) +#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19) +#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19) +#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16) +#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16) +#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13) +#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13) +#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10) +#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10) +#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8) +#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8) +#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6) +#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6) +#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3) +#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3) +#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0) +#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7) + +/* Define the bits in register CBCMR */ +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14) +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12) +#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10) +#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10) +#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8) +#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6) +#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6) +#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4) +#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (14) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0) + +/* Define the bits in register CSCMR1 */ +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30) +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28) +#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26) +#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24) +#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22) +#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22) +#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20) +#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20) +#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL (0x1 << 19) +#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11) +#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7) +#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2) +#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2) +#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1) + +/* Define the bits in register CSCMR2 */ +#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n) (26+n*3) +#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n) (0x7 << (26+n*3)) +#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24) +#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24) +#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22) +#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22) +#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20) +#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20) +#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18) +#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18) +#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10) +#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10) +#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9) +#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6) +#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6) +#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5) +#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4) +#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2) +#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2) +#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0) +#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3) + +/* Define the bits in register CSCDR1 */ +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19) +#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET (22) +#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK (0x7 << 19) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7) + +/* Define the bits in register CS1CDR and CS2CDR */ +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F) + +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CDCDR */ +#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28) +#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6) +#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3) +#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3) +#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0) +#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7) + +/* Define the bits in register CHSCCDR */ +#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12) +#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12) +#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6) +#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6) +#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3) +#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3) +#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7) + +/* Define the bits in register CSCDR2 */ +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19) +#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0) +#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F) + +/* Define the bits in register CSCDR3 */ +#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CSCDR4 */ +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CDHIPR */ +#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16) +#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY (1 << 8) +#define MXC_CCM_CDHIPR_DDR_PODF_BUSY (1 << 7) +#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY (1 << 6) +#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5) +#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY (1 << 4) +#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3) +#define MXC_CCM_CDHIPR_EMI_PODF_BUSY (1 << 2) +#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1) +#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0) + +/* Define the bits in register CDCR */ +#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2) +#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0) +#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3) + +/* Define the bits in register CLPCR */ +#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23) +#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22) +#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21) +#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 25) +#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20) +#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19) +#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18) +#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17) +#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16) +#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11) +#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9) +#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9) +#define MXC_CCM_CLPCR_VSTBY (0x1 << 8) +#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7) +#define MXC_CCM_CLPCR_SBYOS (0x1 << 6) +#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) +#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3) +#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3) +#define MXC_CCM_CLPCR_LPM_OFFSET (0) +#define MXC_CCM_CLPCR_LPM_MASK (0x3) + +/* Define the bits in register CISR */ +#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25) +#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) +#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20) +#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19) +#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18) +#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17) +#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16) +#define MXC_CCM_CISR_COSC_READY (0x1 << 6) +#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5) +#define MXC_CCM_CISR_CKIH_READY (0x1 << 4) +#define MXC_CCM_CISR_FPM_READY (0x1 << 3) +#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2) +#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1) +#define MXC_CCM_CISR_LRF_PLL1 (0x1) + +/* Define the bits in register CIMR */ +#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25) +#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) +#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20) +#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19) +#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18) +#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17) +#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16) +#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5) +#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4) +#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3) +#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2) +#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1) +#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1) + +/* Define the bits in register CCOSR */ +#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24) +#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21) +#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21) +#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16) +#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16) +#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7) +#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4) +#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4) +#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0) +#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF) + +/* Define the bits in registers CGPR */ +#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4) +#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3) +#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0) +#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7) + +/* Define the bits in registers CCGRx */ +#define MXC_CCM_CCGRx_CG_MASK 0x3 +#define MXC_CCM_CCGRx_MOD_OFF 0x0 +#define MXC_CCM_CCGRx_MOD_ON 0x3 +#define MXC_CCM_CCGRx_MOD_IDLE 0x1 + +#define MXC_CCM_CCGRx_CG15_MASK (0x3 << 30) +#define MXC_CCM_CCGRx_CG14_MASK (0x3 << 28) +#define MXC_CCM_CCGRx_CG13_MASK (0x3 << 26) +#define MXC_CCM_CCGRx_CG12_MASK (0x3 << 24) +#define MXC_CCM_CCGRx_CG11_MASK (0x3 << 22) +#define MXC_CCM_CCGRx_CG10_MASK (0x3 << 20) +#define MXC_CCM_CCGRx_CG9_MASK (0x3 << 18) +#define MXC_CCM_CCGRx_CG8_MASK (0x3 << 16) +#define MXC_CCM_CCGRx_CG5_MASK (0x3 << 10) +#define MXC_CCM_CCGRx_CG4_MASK (0x3 << 8) +#define MXC_CCM_CCGRx_CG3_MASK (0x3 << 6) +#define MXC_CCM_CCGRx_CG2_MASK (0x3 << 4) +#define MXC_CCM_CCGRx_CG1_MASK (0x3 << 2) +#define MXC_CCM_CCGRx_CG0_MASK (0x3 << 0) + +#define MXC_CCM_CCGRx_CG15_OFFSET 30 +#define MXC_CCM_CCGRx_CG14_OFFSET 28 +#define MXC_CCM_CCGRx_CG13_OFFSET 26 +#define MXC_CCM_CCGRx_CG12_OFFSET 24 +#define MXC_CCM_CCGRx_CG11_OFFSET 22 +#define MXC_CCM_CCGRx_CG10_OFFSET 20 +#define MXC_CCM_CCGRx_CG9_OFFSET 18 +#define MXC_CCM_CCGRx_CG8_OFFSET 16 +#define MXC_CCM_CCGRx_CG7_OFFSET 14 +#define MXC_CCM_CCGRx_CG6_OFFSET 12 +#define MXC_CCM_CCGRx_CG5_OFFSET 10 +#define MXC_CCM_CCGRx_CG4_OFFSET 8 +#define MXC_CCM_CCGRx_CG3_OFFSET 6 +#define MXC_CCM_CCGRx_CG2_OFFSET 4 +#define MXC_CCM_CCGRx_CG1_OFFSET 2 +#define MXC_CCM_CCGRx_CG0_OFFSET 0 + +#define MXC_DPTC_LP_BASE (MX51_GPC_BASE + 0x80) +#define MXC_DPTC_GP_BASE (MX51_GPC_BASE + 0x100) +#define MXC_DVFS_CORE_BASE (MX51_GPC_BASE + 0x180) +#define MXC_DPTC_PER_BASE (MX51_GPC_BASE + 0x1C0) +#define MXC_PGC_IPU_BASE (MX51_GPC_BASE + 0x220) +#define MXC_PGC_VPU_BASE (MX51_GPC_BASE + 0x240) +#define MXC_PGC_GPU_BASE (MX51_GPC_BASE + 0x260) +#define MXC_SRPG_NEON_BASE (MX51_GPC_BASE + 0x280) +#define MXC_SRPG_ARM_BASE (MX51_GPC_BASE + 0x2A0) +#define MXC_SRPG_EMPGC0_BASE (MX51_GPC_BASE + 0x2C0) +#define MXC_SRPG_EMPGC1_BASE (MX51_GPC_BASE + 0x2D0) +#define MXC_SRPG_MEGAMIX_BASE (MX51_GPC_BASE + 0x2E0) +#define MXC_SRPG_EMI_BASE (MX51_GPC_BASE + 0x300) + +/* CORTEXA8 platform */ +#define MXC_CORTEXA8_PLAT_PVID (MX51_CORTEXA8_BASE + 0x0) +#define MXC_CORTEXA8_PLAT_GPC (MX51_CORTEXA8_BASE + 0x4) +#define MXC_CORTEXA8_PLAT_PIC (MX51_CORTEXA8_BASE + 0x8) +#define MXC_CORTEXA8_PLAT_LPC (MX51_CORTEXA8_BASE + 0xC) +#define MXC_CORTEXA8_PLAT_NEON_LPC (MX51_CORTEXA8_BASE + 0x10) +#define MXC_CORTEXA8_PLAT_ICGC (MX51_CORTEXA8_BASE + 0x14) +#define MXC_CORTEXA8_PLAT_AMC (MX51_CORTEXA8_BASE + 0x18) +#define MXC_CORTEXA8_PLAT_NMC (MX51_CORTEXA8_BASE + 0x20) +#define MXC_CORTEXA8_PLAT_NMS (MX51_CORTEXA8_BASE + 0x24) + +/* DVFS CORE */ +#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00) +#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04) +#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08) +#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C) +#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10) +#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14) +#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18) +#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C) +#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20) +#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24) +#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28) +#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C) +#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30) +#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34) +#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38) +#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C) +#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40) + +/* GPC */ +#define MXC_GPC_CNTR (MX51_GPC_BASE + 0x0) +#define MXC_GPC_PGR (MX51_GPC_BASE + 0x4) +#define MXC_GPC_VCR (MX51_GPC_BASE + 0x8) +#define MXC_GPC_ALL_PU (MX51_GPC_BASE + 0xC) +#define MXC_GPC_NEON (MX51_GPC_BASE + 0x10) +#define MXC_GPC_PGR_ARMPG_OFFSET 8 +#define MXC_GPC_PGR_ARMPG_MASK (3 << 8) + +/* PGC */ +#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0) +#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC) +#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0) +#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC) +#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0) +#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC) + +#define MXC_PGCR_PCR 1 +#define MXC_SRPGCR_PCR 1 +#define MXC_EMPGCR_PCR 1 +#define MXC_PGSR_PSR 1 + + +#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0) +#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1) + +/* SRPG */ +#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0) +#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4) +#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8) + +#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0) +#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4) +#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8) + +#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0) +#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4) +#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8) + +#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0) +#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4) +#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8) + +#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0) +#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4) +#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8) + +#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0) +#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4) +#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8) + +#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */ diff --git a/arch/arm/mach-imx/crmregs-imx3.h b/arch/arm/mach-imx/crmregs-imx3.h new file mode 100644 index 00000000..53141273 --- /dev/null +++ b/arch/arm/mach-imx/crmregs-imx3.h @@ -0,0 +1,262 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2008 by Sascha Hauer + * + * 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. + */ + +#ifndef __ARCH_ARM_MACH_MX3_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX3_CRM_REGS_H__ + +#define CKIH_CLK_FREQ 26000000 +#define CKIH_CLK_FREQ_27MHZ 27000000 +#define CKIL_CLK_FREQ 32768 + +#define MXC_CCM_BASE (cpu_is_mx31() ? \ +MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR) : MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR)) + +/* Register addresses */ +#define MXC_CCM_CCMR (MXC_CCM_BASE + 0x00) +#define MXC_CCM_PDR0 (MXC_CCM_BASE + 0x04) +#define MXC_CCM_PDR1 (MXC_CCM_BASE + 0x08) +#define MX35_CCM_PDR2 (MXC_CCM_BASE + 0x0C) +#define MXC_CCM_RCSR (MXC_CCM_BASE + 0x0C) +#define MX35_CCM_PDR3 (MXC_CCM_BASE + 0x10) +#define MXC_CCM_MPCTL (MXC_CCM_BASE + 0x10) +#define MX35_CCM_PDR4 (MXC_CCM_BASE + 0x14) +#define MXC_CCM_UPCTL (MXC_CCM_BASE + 0x14) +#define MX35_CCM_RCSR (MXC_CCM_BASE + 0x18) +#define MXC_CCM_SRPCTL (MXC_CCM_BASE + 0x18) +#define MX35_CCM_MPCTL (MXC_CCM_BASE + 0x1C) +#define MXC_CCM_COSR (MXC_CCM_BASE + 0x1C) +#define MX35_CCM_PPCTL (MXC_CCM_BASE + 0x20) +#define MXC_CCM_CGR0 (MXC_CCM_BASE + 0x20) +#define MX35_CCM_ACMR (MXC_CCM_BASE + 0x24) +#define MXC_CCM_CGR1 (MXC_CCM_BASE + 0x24) +#define MX35_CCM_COSR (MXC_CCM_BASE + 0x28) +#define MXC_CCM_CGR2 (MXC_CCM_BASE + 0x28) +#define MX35_CCM_CGR0 (MXC_CCM_BASE + 0x2C) +#define MXC_CCM_WIMR (MXC_CCM_BASE + 0x2C) +#define MX35_CCM_CGR1 (MXC_CCM_BASE + 0x30) +#define MXC_CCM_LDC (MXC_CCM_BASE + 0x30) +#define MX35_CCM_CGR2 (MXC_CCM_BASE + 0x34) +#define MXC_CCM_DCVR0 (MXC_CCM_BASE + 0x34) +#define MX35_CCM_CGR3 (MXC_CCM_BASE + 0x38) +#define MXC_CCM_DCVR1 (MXC_CCM_BASE + 0x38) +#define MXC_CCM_DCVR2 (MXC_CCM_BASE + 0x3C) +#define MXC_CCM_DCVR3 (MXC_CCM_BASE + 0x40) +#define MXC_CCM_LTR0 (MXC_CCM_BASE + 0x44) +#define MXC_CCM_LTR1 (MXC_CCM_BASE + 0x48) +#define MXC_CCM_LTR2 (MXC_CCM_BASE + 0x4C) +#define MXC_CCM_LTR3 (MXC_CCM_BASE + 0x50) +#define MXC_CCM_LTBR0 (MXC_CCM_BASE + 0x54) +#define MXC_CCM_LTBR1 (MXC_CCM_BASE + 0x58) +#define MXC_CCM_PMCR0 (MXC_CCM_BASE + 0x5C) +#define MXC_CCM_PMCR1 (MXC_CCM_BASE + 0x60) +#define MXC_CCM_PDR2 (MXC_CCM_BASE + 0x64) + +/* Register bit definitions */ +#define MXC_CCM_CCMR_WBEN (1 << 27) +#define MXC_CCM_CCMR_CSCS (1 << 25) +#define MXC_CCM_CCMR_PERCS (1 << 24) +#define MXC_CCM_CCMR_SSI1S_OFFSET 18 +#define MXC_CCM_CCMR_SSI1S_MASK (0x3 << 18) +#define MXC_CCM_CCMR_SSI2S_OFFSET 21 +#define MXC_CCM_CCMR_SSI2S_MASK (0x3 << 21) +#define MXC_CCM_CCMR_LPM_OFFSET 14 +#define MXC_CCM_CCMR_LPM_MASK (0x3 << 14) +#define MXC_CCM_CCMR_LPM_WAIT_MX35 (0x1 << 14) +#define MXC_CCM_CCMR_FIRS_OFFSET 11 +#define MXC_CCM_CCMR_FIRS_MASK (0x3 << 11) +#define MXC_CCM_CCMR_UPE (1 << 9) +#define MXC_CCM_CCMR_SPE (1 << 8) +#define MXC_CCM_CCMR_MDS (1 << 7) +#define MXC_CCM_CCMR_SBYCS (1 << 4) +#define MXC_CCM_CCMR_MPE (1 << 3) +#define MXC_CCM_CCMR_PRCS_OFFSET 1 +#define MXC_CCM_CCMR_PRCS_MASK (0x3 << 1) + +#define MXC_CCM_PDR0_CSI_PODF_OFFSET 26 +#define MXC_CCM_PDR0_CSI_PODF_MASK (0x3F << 26) +#define MXC_CCM_PDR0_CSI_PRDF_OFFSET 23 +#define MXC_CCM_PDR0_CSI_PRDF_MASK (0x7 << 23) +#define MXC_CCM_PDR0_PER_PODF_OFFSET 16 +#define MXC_CCM_PDR0_PER_PODF_MASK (0x1F << 16) +#define MXC_CCM_PDR0_HSP_PODF_OFFSET 11 +#define MXC_CCM_PDR0_HSP_PODF_MASK (0x7 << 11) +#define MXC_CCM_PDR0_NFC_PODF_OFFSET 8 +#define MXC_CCM_PDR0_NFC_PODF_MASK (0x7 << 8) +#define MXC_CCM_PDR0_IPG_PODF_OFFSET 6 +#define MXC_CCM_PDR0_IPG_PODF_MASK (0x3 << 6) +#define MXC_CCM_PDR0_MAX_PODF_OFFSET 3 +#define MXC_CCM_PDR0_MAX_PODF_MASK (0x7 << 3) +#define MXC_CCM_PDR0_MCU_PODF_OFFSET 0 +#define MXC_CCM_PDR0_MCU_PODF_MASK 0x7 + +#define MXC_CCM_PDR1_USB_PRDF_OFFSET 30 +#define MXC_CCM_PDR1_USB_PRDF_MASK (0x3 << 30) +#define MXC_CCM_PDR1_USB_PODF_OFFSET 27 +#define MXC_CCM_PDR1_USB_PODF_MASK (0x7 << 27) +#define MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET 24 +#define MXC_CCM_PDR1_FIRI_PRE_PODF_MASK (0x7 << 24) +#define MXC_CCM_PDR1_FIRI_PODF_OFFSET 18 +#define MXC_CCM_PDR1_FIRI_PODF_MASK (0x3F << 18) +#define MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET 15 +#define MXC_CCM_PDR1_SSI2_PRE_PODF_MASK (0x7 << 15) +#define MXC_CCM_PDR1_SSI2_PODF_OFFSET 9 +#define MXC_CCM_PDR1_SSI2_PODF_MASK (0x3F << 9) +#define MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET 6 +#define MXC_CCM_PDR1_SSI1_PRE_PODF_MASK (0x7 << 6) +#define MXC_CCM_PDR1_SSI1_PODF_OFFSET 0 +#define MXC_CCM_PDR1_SSI1_PODF_MASK 0x3F + +/* Bit definitions for RCSR */ +#define MXC_CCM_RCSR_NF16B 0x80000000 + +/* + * LTR0 register offsets + */ +#define MXC_CCM_LTR0_DIV3CK_OFFSET 1 +#define MXC_CCM_LTR0_DIV3CK_MASK (0x3 << 1) +#define MXC_CCM_LTR0_DNTHR_OFFSET 16 +#define MXC_CCM_LTR0_DNTHR_MASK (0x3F << 16) +#define MXC_CCM_LTR0_UPTHR_OFFSET 22 +#define MXC_CCM_LTR0_UPTHR_MASK (0x3F << 22) + +/* + * LTR1 register offsets + */ +#define MXC_CCM_LTR1_PNCTHR_OFFSET 0 +#define MXC_CCM_LTR1_PNCTHR_MASK 0x3F +#define MXC_CCM_LTR1_UPCNT_OFFSET 6 +#define MXC_CCM_LTR1_UPCNT_MASK (0xFF << 6) +#define MXC_CCM_LTR1_DNCNT_OFFSET 14 +#define MXC_CCM_LTR1_DNCNT_MASK (0xFF << 14) +#define MXC_CCM_LTR1_LTBRSR_MASK 0x400000 +#define MXC_CCM_LTR1_LTBRSR_OFFSET 22 +#define MXC_CCM_LTR1_LTBRSR 0x400000 +#define MXC_CCM_LTR1_LTBRSH 0x800000 + +/* + * LTR2 bit definitions. x ranges from 0 for WSW9 to 6 for WSW15 + */ +#define MXC_CCM_LTR2_WSW_OFFSET(x) (11 + (x) * 3) +#define MXC_CCM_LTR2_WSW_MASK(x) (0x7 << \ + MXC_CCM_LTR2_WSW_OFFSET((x))) +#define MXC_CCM_LTR2_EMAC_OFFSET 0 +#define MXC_CCM_LTR2_EMAC_MASK 0x1FF + +/* + * LTR3 bit definitions. x ranges from 0 for WSW0 to 8 for WSW8 + */ +#define MXC_CCM_LTR3_WSW_OFFSET(x) (5 + (x) * 3) +#define MXC_CCM_LTR3_WSW_MASK(x) (0x7 << \ + MXC_CCM_LTR3_WSW_OFFSET((x))) + +#define MXC_CCM_PMCR0_DFSUP1 0x80000000 +#define MXC_CCM_PMCR0_DFSUP1_SPLL (0 << 31) +#define MXC_CCM_PMCR0_DFSUP1_MPLL (1 << 31) +#define MXC_CCM_PMCR0_DFSUP0 0x40000000 +#define MXC_CCM_PMCR0_DFSUP0_PLL (0 << 30) +#define MXC_CCM_PMCR0_DFSUP0_PDR (1 << 30) +#define MXC_CCM_PMCR0_DFSUP_MASK (0x3 << 30) + +#define DVSUP_TURBO 0 +#define DVSUP_HIGH 1 +#define DVSUP_MEDIUM 2 +#define DVSUP_LOW 3 +#define MXC_CCM_PMCR0_DVSUP_TURBO (DVSUP_TURBO << 28) +#define MXC_CCM_PMCR0_DVSUP_HIGH (DVSUP_HIGH << 28) +#define MXC_CCM_PMCR0_DVSUP_MEDIUM (DVSUP_MEDIUM << 28) +#define MXC_CCM_PMCR0_DVSUP_LOW (DVSUP_LOW << 28) +#define MXC_CCM_PMCR0_DVSUP_OFFSET 28 +#define MXC_CCM_PMCR0_DVSUP_MASK (0x3 << 28) +#define MXC_CCM_PMCR0_UDSC 0x08000000 +#define MXC_CCM_PMCR0_UDSC_MASK (1 << 27) +#define MXC_CCM_PMCR0_UDSC_UP (1 << 27) +#define MXC_CCM_PMCR0_UDSC_DOWN (0 << 27) + +#define MXC_CCM_PMCR0_VSCNT_1 (0x0 << 24) +#define MXC_CCM_PMCR0_VSCNT_2 (0x1 << 24) +#define MXC_CCM_PMCR0_VSCNT_3 (0x2 << 24) +#define MXC_CCM_PMCR0_VSCNT_4 (0x3 << 24) +#define MXC_CCM_PMCR0_VSCNT_5 (0x4 << 24) +#define MXC_CCM_PMCR0_VSCNT_6 (0x5 << 24) +#define MXC_CCM_PMCR0_VSCNT_7 (0x6 << 24) +#define MXC_CCM_PMCR0_VSCNT_8 (0x7 << 24) +#define MXC_CCM_PMCR0_VSCNT_OFFSET 24 +#define MXC_CCM_PMCR0_VSCNT_MASK (0x7 << 24) +#define MXC_CCM_PMCR0_DVFEV 0x00800000 +#define MXC_CCM_PMCR0_DVFIS 0x00400000 +#define MXC_CCM_PMCR0_LBMI 0x00200000 +#define MXC_CCM_PMCR0_LBFL 0x00100000 +#define MXC_CCM_PMCR0_LBCF_4 (0x0 << 18) +#define MXC_CCM_PMCR0_LBCF_8 (0x1 << 18) +#define MXC_CCM_PMCR0_LBCF_12 (0x2 << 18) +#define MXC_CCM_PMCR0_LBCF_16 (0x3 << 18) +#define MXC_CCM_PMCR0_LBCF_OFFSET 18 +#define MXC_CCM_PMCR0_LBCF_MASK (0x3 << 18) +#define MXC_CCM_PMCR0_PTVIS 0x00020000 +#define MXC_CCM_PMCR0_UPDTEN 0x00010000 +#define MXC_CCM_PMCR0_UPDTEN_MASK (0x1 << 16) +#define MXC_CCM_PMCR0_FSVAIM 0x00008000 +#define MXC_CCM_PMCR0_FSVAI_OFFSET 13 +#define MXC_CCM_PMCR0_FSVAI_MASK (0x3 << 13) +#define MXC_CCM_PMCR0_DPVCR 0x00001000 +#define MXC_CCM_PMCR0_DPVV 0x00000800 +#define MXC_CCM_PMCR0_WFIM 0x00000400 +#define MXC_CCM_PMCR0_DRCE3 0x00000200 +#define MXC_CCM_PMCR0_DRCE2 0x00000100 +#define MXC_CCM_PMCR0_DRCE1 0x00000080 +#define MXC_CCM_PMCR0_DRCE0 0x00000040 +#define MXC_CCM_PMCR0_DCR 0x00000020 +#define MXC_CCM_PMCR0_DVFEN 0x00000010 +#define MXC_CCM_PMCR0_PTVAIM 0x00000008 +#define MXC_CCM_PMCR0_PTVAI_OFFSET 1 +#define MXC_CCM_PMCR0_PTVAI_MASK (0x3 << 1) +#define MXC_CCM_PMCR0_DPTEN 0x00000001 + +#define MXC_CCM_PMCR1_DVGP_OFFSET 0 +#define MXC_CCM_PMCR1_DVGP_MASK (0xF) + +#define MXC_CCM_PMCR1_PLLRDIS (0x1 << 7) +#define MXC_CCM_PMCR1_EMIRQ_EN (0x1 << 8) + +#define MXC_CCM_DCVR_ULV_MASK (0x3FF << 22) +#define MXC_CCM_DCVR_ULV_OFFSET 22 +#define MXC_CCM_DCVR_LLV_MASK (0x3FF << 12) +#define MXC_CCM_DCVR_LLV_OFFSET 12 +#define MXC_CCM_DCVR_ELV_MASK (0x3FF << 2) +#define MXC_CCM_DCVR_ELV_OFFSET 2 + +#define MXC_CCM_PDR2_MST2_PDF_MASK (0x3F << 7) +#define MXC_CCM_PDR2_MST2_PDF_OFFSET 7 +#define MXC_CCM_PDR2_MST1_PDF_MASK 0x3F +#define MXC_CCM_PDR2_MST1_PDF_OFFSET 0 + +#define MXC_CCM_COSR_CLKOSEL_MASK 0x0F +#define MXC_CCM_COSR_CLKOSEL_OFFSET 0 +#define MXC_CCM_COSR_CLKOUTDIV_MASK (0x07 << 6) +#define MXC_CCM_COSR_CLKOUTDIV_OFFSET 6 +#define MXC_CCM_COSR_CLKOEN (1 << 9) + +/* + * PMCR0 register offsets + */ +#define MXC_CCM_PMCR0_LBFL_OFFSET 20 +#define MXC_CCM_PMCR0_DFSUP0_OFFSET 30 +#define MXC_CCM_PMCR0_DFSUP1_OFFSET 31 + +#endif /* __ARCH_ARM_MACH_MX3_CRM_REGS_H__ */ diff --git a/arch/arm/mach-imx/devices-imx1.h b/arch/arm/mach-imx/devices-imx1.h new file mode 100644 index 00000000..3aad1e70 --- /dev/null +++ b/arch/arm/mach-imx/devices-imx1.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig + * + * 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 +#include + +extern const struct imx_imx_fb_data imx1_imx_fb_data; +#define imx1_add_imx_fb(pdata) \ + imx_add_imx_fb(&imx1_imx_fb_data, pdata) + +extern const struct imx_imx_i2c_data imx1_imx_i2c_data; +#define imx1_add_imx_i2c(pdata) \ + imx_add_imx_i2c(&imx1_imx_i2c_data, pdata) + +extern const struct imx_imx_uart_3irq_data imx1_imx_uart_data[]; +#define imx1_add_imx_uart(id, pdata) \ + imx_add_imx_uart_3irq(&imx1_imx_uart_data[id], pdata) +#define imx1_add_imx_uart0(pdata) imx1_add_imx_uart(0, pdata) +#define imx1_add_imx_uart1(pdata) imx1_add_imx_uart(1, pdata) + +extern const struct imx_spi_imx_data imx1_cspi_data[]; +#define imx1_add_cspi(id, pdata) \ + imx_add_spi_imx(&imx1_cspi_data[id], pdata) + +#define imx1_add_spi_imx0(pdata) imx1_add_cspi(0, pdata) +#define imx1_add_spi_imx1(pdata) imx1_add_cspi(1, pdata) diff --git a/arch/arm/mach-imx/devices-imx21.h b/arch/arm/mach-imx/devices-imx21.h new file mode 100644 index 00000000..2628e0c4 --- /dev/null +++ b/arch/arm/mach-imx/devices-imx21.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig + * + * 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 +#include + +extern const struct imx_imx21_hcd_data imx21_imx21_hcd_data; +#define imx21_add_imx21_hcd(pdata) \ + imx_add_imx21_hcd(&imx21_imx21_hcd_data, pdata) + +extern const struct imx_imx2_wdt_data imx21_imx2_wdt_data; +#define imx21_add_imx2_wdt(pdata) \ + imx_add_imx2_wdt(&imx21_imx2_wdt_data) + +extern const struct imx_imx_fb_data imx21_imx_fb_data; +#define imx21_add_imx_fb(pdata) \ + imx_add_imx_fb(&imx21_imx_fb_data, pdata) + +extern const struct imx_imx_i2c_data imx21_imx_i2c_data; +#define imx21_add_imx_i2c(pdata) \ + imx_add_imx_i2c(&imx21_imx_i2c_data, pdata) + +extern const struct imx_imx_keypad_data imx21_imx_keypad_data; +#define imx21_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx21_imx_keypad_data, pdata) + +extern const struct imx_imx_ssi_data imx21_imx_ssi_data[]; +#define imx21_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx21_imx_ssi_data[id], pdata) + +extern const struct imx_imx_uart_1irq_data imx21_imx_uart_data[]; +#define imx21_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx21_imx_uart_data[id], pdata) +#define imx21_add_imx_uart0(pdata) imx21_add_imx_uart(0, pdata) +#define imx21_add_imx_uart1(pdata) imx21_add_imx_uart(1, pdata) +#define imx21_add_imx_uart2(pdata) imx21_add_imx_uart(2, pdata) +#define imx21_add_imx_uart3(pdata) imx21_add_imx_uart(3, pdata) + +extern const struct imx_mxc_mmc_data imx21_mxc_mmc_data[]; +#define imx21_add_mxc_mmc(id, pdata) \ + imx_add_mxc_mmc(&imx21_mxc_mmc_data[id], pdata) + +extern const struct imx_mxc_nand_data imx21_mxc_nand_data; +#define imx21_add_mxc_nand(pdata) \ + imx_add_mxc_nand(&imx21_mxc_nand_data, pdata) + +extern const struct imx_mxc_w1_data imx21_mxc_w1_data; +#define imx21_add_mxc_w1(pdata) \ + imx_add_mxc_w1(&imx21_mxc_w1_data) + +extern const struct imx_spi_imx_data imx21_cspi_data[]; +#define imx21_add_cspi(id, pdata) \ + imx_add_spi_imx(&imx21_cspi_data[id], pdata) +#define imx21_add_spi_imx0(pdata) imx21_add_cspi(0, pdata) +#define imx21_add_spi_imx1(pdata) imx21_add_cspi(1, pdata) diff --git a/arch/arm/mach-imx/devices-imx25.h b/arch/arm/mach-imx/devices-imx25.h new file mode 100644 index 00000000..efa0761c --- /dev/null +++ b/arch/arm/mach-imx/devices-imx25.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig + * + * 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 +#include + +extern const struct imx_fec_data imx25_fec_data; +#define imx25_add_fec(pdata) \ + imx_add_fec(&imx25_fec_data, pdata) + +extern const struct imx_flexcan_data imx25_flexcan_data[]; +#define imx25_add_flexcan(id, pdata) \ + imx_add_flexcan(&imx25_flexcan_data[id], pdata) +#define imx25_add_flexcan0(pdata) imx25_add_flexcan(0, pdata) +#define imx25_add_flexcan1(pdata) imx25_add_flexcan(1, pdata) + +extern const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data; +#define imx25_add_fsl_usb2_udc(pdata) \ + imx_add_fsl_usb2_udc(&imx25_fsl_usb2_udc_data, pdata) + +extern struct imx_imxdi_rtc_data imx25_imxdi_rtc_data; +#define imx25_add_imxdi_rtc(pdata) \ + imx_add_imxdi_rtc(&imx25_imxdi_rtc_data) + +extern const struct imx_imx2_wdt_data imx25_imx2_wdt_data; +#define imx25_add_imx2_wdt(pdata) \ + imx_add_imx2_wdt(&imx25_imx2_wdt_data) + +extern const struct imx_imx_fb_data imx25_imx_fb_data; +#define imx25_add_imx_fb(pdata) \ + imx_add_imx_fb(&imx25_imx_fb_data, pdata) + +extern const struct imx_imx_i2c_data imx25_imx_i2c_data[]; +#define imx25_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx25_imx_i2c_data[id], pdata) +#define imx25_add_imx_i2c0(pdata) imx25_add_imx_i2c(0, pdata) +#define imx25_add_imx_i2c1(pdata) imx25_add_imx_i2c(1, pdata) +#define imx25_add_imx_i2c2(pdata) imx25_add_imx_i2c(2, pdata) + +extern const struct imx_imx_keypad_data imx25_imx_keypad_data; +#define imx25_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx25_imx_keypad_data, pdata) + +extern const struct imx_imx_ssi_data imx25_imx_ssi_data[]; +#define imx25_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx25_imx_ssi_data[id], pdata) + +extern const struct imx_imx_uart_1irq_data imx25_imx_uart_data[]; +#define imx25_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx25_imx_uart_data[id], pdata) +#define imx25_add_imx_uart0(pdata) imx25_add_imx_uart(0, pdata) +#define imx25_add_imx_uart1(pdata) imx25_add_imx_uart(1, pdata) +#define imx25_add_imx_uart2(pdata) imx25_add_imx_uart(2, pdata) +#define imx25_add_imx_uart3(pdata) imx25_add_imx_uart(3, pdata) +#define imx25_add_imx_uart4(pdata) imx25_add_imx_uart(4, pdata) + +extern const struct imx_mx2_camera_data imx25_mx2_camera_data; +#define imx25_add_mx2_camera(pdata) \ + imx_add_mx2_camera(&imx25_mx2_camera_data, pdata) + +extern const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data; +#define imx25_add_mxc_ehci_otg(pdata) \ + imx_add_mxc_ehci(&imx25_mxc_ehci_otg_data, pdata) +extern const struct imx_mxc_ehci_data imx25_mxc_ehci_hs_data; +#define imx25_add_mxc_ehci_hs(pdata) \ + imx_add_mxc_ehci(&imx25_mxc_ehci_hs_data, pdata) + +extern const struct imx_mxc_nand_data imx25_mxc_nand_data; +#define imx25_add_mxc_nand(pdata) \ + imx_add_mxc_nand(&imx25_mxc_nand_data, pdata) + +extern const struct imx_sdhci_esdhc_imx_data imx25_sdhci_esdhc_imx_data[]; +#define imx25_add_sdhci_esdhc_imx(id, pdata) \ + imx_add_sdhci_esdhc_imx(&imx25_sdhci_esdhc_imx_data[id], pdata) + +extern const struct imx_spi_imx_data imx25_cspi_data[]; +#define imx25_add_spi_imx(id, pdata) \ + imx_add_spi_imx(&imx25_cspi_data[id], pdata) +#define imx25_add_spi_imx0(pdata) imx25_add_spi_imx(0, pdata) +#define imx25_add_spi_imx1(pdata) imx25_add_spi_imx(1, pdata) +#define imx25_add_spi_imx2(pdata) imx25_add_spi_imx(2, pdata) + +extern struct imx_mxc_pwm_data imx25_mxc_pwm_data[]; +#define imx25_add_mxc_pwm(id) \ + imx_add_mxc_pwm(&imx25_mxc_pwm_data[id]) diff --git a/arch/arm/mach-imx/devices-imx27.h b/arch/arm/mach-imx/devices-imx27.h new file mode 100644 index 00000000..28537a5d --- /dev/null +++ b/arch/arm/mach-imx/devices-imx27.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig + * + * 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 +#include + +extern const struct imx_fec_data imx27_fec_data; +#define imx27_add_fec(pdata) \ + imx_add_fec(&imx27_fec_data, pdata) + +extern const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data; +#define imx27_add_fsl_usb2_udc(pdata) \ + imx_add_fsl_usb2_udc(&imx27_fsl_usb2_udc_data, pdata) + +extern const struct imx_imx2_wdt_data imx27_imx2_wdt_data; +#define imx27_add_imx2_wdt(pdata) \ + imx_add_imx2_wdt(&imx27_imx2_wdt_data) + +extern const struct imx_imx_fb_data imx27_imx_fb_data; +#define imx27_add_imx_fb(pdata) \ + imx_add_imx_fb(&imx27_imx_fb_data, pdata) + +extern const struct imx_imx_i2c_data imx27_imx_i2c_data[]; +#define imx27_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx27_imx_i2c_data[id], pdata) + +extern const struct imx_imx_keypad_data imx27_imx_keypad_data; +#define imx27_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx27_imx_keypad_data, pdata) + +extern const struct imx_imx_ssi_data imx27_imx_ssi_data[]; +#define imx27_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx27_imx_ssi_data[id], pdata) + +extern const struct imx_imx_uart_1irq_data imx27_imx_uart_data[]; +#define imx27_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx27_imx_uart_data[id], pdata) +#define imx27_add_imx_uart0(pdata) imx27_add_imx_uart(0, pdata) +#define imx27_add_imx_uart1(pdata) imx27_add_imx_uart(1, pdata) +#define imx27_add_imx_uart2(pdata) imx27_add_imx_uart(2, pdata) +#define imx27_add_imx_uart3(pdata) imx27_add_imx_uart(3, pdata) +#define imx27_add_imx_uart4(pdata) imx27_add_imx_uart(4, pdata) +#define imx27_add_imx_uart5(pdata) imx27_add_imx_uart(5, pdata) + +extern const struct imx_mx2_camera_data imx27_mx2_camera_data; +#define imx27_add_mx2_camera(pdata) \ + imx_add_mx2_camera(&imx27_mx2_camera_data, pdata) +#define imx27_add_mx2_emmaprp(pdata) \ + imx_add_mx2_emmaprp(&imx27_mx2_camera_data) + +extern const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data; +#define imx27_add_mxc_ehci_otg(pdata) \ + imx_add_mxc_ehci(&imx27_mxc_ehci_otg_data, pdata) +extern const struct imx_mxc_ehci_data imx27_mxc_ehci_hs_data[]; +#define imx27_add_mxc_ehci_hs(id, pdata) \ + imx_add_mxc_ehci(&imx27_mxc_ehci_hs_data[id - 1], pdata) + +extern const struct imx_mxc_mmc_data imx27_mxc_mmc_data[]; +#define imx27_add_mxc_mmc(id, pdata) \ + imx_add_mxc_mmc(&imx27_mxc_mmc_data[id], pdata) + +extern const struct imx_mxc_nand_data imx27_mxc_nand_data; +#define imx27_add_mxc_nand(pdata) \ + imx_add_mxc_nand(&imx27_mxc_nand_data, pdata) + +extern const struct imx_mxc_w1_data imx27_mxc_w1_data; +#define imx27_add_mxc_w1(pdata) \ + imx_add_mxc_w1(&imx27_mxc_w1_data) + +extern const struct imx_spi_imx_data imx27_cspi_data[]; +#define imx27_add_cspi(id, pdata) \ + imx_add_spi_imx(&imx27_cspi_data[id], pdata) +#define imx27_add_spi_imx0(pdata) imx27_add_cspi(0, pdata) +#define imx27_add_spi_imx1(pdata) imx27_add_cspi(1, pdata) +#define imx27_add_spi_imx2(pdata) imx27_add_cspi(2, pdata) + +extern const struct imx_pata_imx_data imx27_pata_imx_data; +#define imx27_add_pata_imx() \ + imx_add_pata_imx(&imx27_pata_imx_data) diff --git a/arch/arm/mach-imx/devices-imx31.h b/arch/arm/mach-imx/devices-imx31.h new file mode 100644 index 00000000..488e241a --- /dev/null +++ b/arch/arm/mach-imx/devices-imx31.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig + * + * 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 +#include + +extern const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data; +#define imx31_add_fsl_usb2_udc(pdata) \ + imx_add_fsl_usb2_udc(&imx31_fsl_usb2_udc_data, pdata) + +extern const struct imx_imx2_wdt_data imx31_imx2_wdt_data; +#define imx31_add_imx2_wdt(pdata) \ + imx_add_imx2_wdt(&imx31_imx2_wdt_data) + +extern const struct imx_imx_i2c_data imx31_imx_i2c_data[]; +#define imx31_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx31_imx_i2c_data[id], pdata) +#define imx31_add_imx_i2c0(pdata) imx31_add_imx_i2c(0, pdata) +#define imx31_add_imx_i2c1(pdata) imx31_add_imx_i2c(1, pdata) +#define imx31_add_imx_i2c2(pdata) imx31_add_imx_i2c(2, pdata) + +extern const struct imx_imx_keypad_data imx31_imx_keypad_data; +#define imx31_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx31_imx_keypad_data, pdata) + +extern const struct imx_imx_ssi_data imx31_imx_ssi_data[]; +#define imx31_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx31_imx_ssi_data[id], pdata) + +extern const struct imx_imx_uart_1irq_data imx31_imx_uart_data[]; +#define imx31_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx31_imx_uart_data[id], pdata) +#define imx31_add_imx_uart0(pdata) imx31_add_imx_uart(0, pdata) +#define imx31_add_imx_uart1(pdata) imx31_add_imx_uart(1, pdata) +#define imx31_add_imx_uart2(pdata) imx31_add_imx_uart(2, pdata) +#define imx31_add_imx_uart3(pdata) imx31_add_imx_uart(3, pdata) +#define imx31_add_imx_uart4(pdata) imx31_add_imx_uart(4, pdata) + +extern const struct imx_ipu_core_data imx31_ipu_core_data; +#define imx31_add_ipu_core(pdata) \ + imx_add_ipu_core(&imx31_ipu_core_data, pdata) +#define imx31_alloc_mx3_camera(pdata) \ + imx_alloc_mx3_camera(&imx31_ipu_core_data, pdata) +#define imx31_add_mx3_sdc_fb(pdata) \ + imx_add_mx3_sdc_fb(&imx31_ipu_core_data, pdata) + +extern const struct imx_mxc_ehci_data imx31_mxc_ehci_otg_data; +#define imx31_add_mxc_ehci_otg(pdata) \ + imx_add_mxc_ehci(&imx31_mxc_ehci_otg_data, pdata) +extern const struct imx_mxc_ehci_data imx31_mxc_ehci_hs_data[]; +#define imx31_add_mxc_ehci_hs(id, pdata) \ + imx_add_mxc_ehci(&imx31_mxc_ehci_hs_data[id - 1], pdata) + +extern const struct imx_mxc_mmc_data imx31_mxc_mmc_data[]; +#define imx31_add_mxc_mmc(id, pdata) \ + imx_add_mxc_mmc(&imx31_mxc_mmc_data[id], pdata) + +extern const struct imx_mxc_nand_data imx31_mxc_nand_data; +#define imx31_add_mxc_nand(pdata) \ + imx_add_mxc_nand(&imx31_mxc_nand_data, pdata) + +extern const struct imx_mxc_rtc_data imx31_mxc_rtc_data; +#define imx31_add_mxc_rtc(pdata) \ + imx_add_mxc_rtc(&imx31_mxc_rtc_data) + +extern const struct imx_mxc_w1_data imx31_mxc_w1_data; +#define imx31_add_mxc_w1(pdata) \ + imx_add_mxc_w1(&imx31_mxc_w1_data) + +extern const struct imx_spi_imx_data imx31_cspi_data[]; +#define imx31_add_cspi(id, pdata) \ + imx_add_spi_imx(&imx31_cspi_data[id], pdata) +#define imx31_add_spi_imx0(pdata) imx31_add_cspi(0, pdata) +#define imx31_add_spi_imx1(pdata) imx31_add_cspi(1, pdata) +#define imx31_add_spi_imx2(pdata) imx31_add_cspi(2, pdata) + +extern const struct imx_pata_imx_data imx31_pata_imx_data; +#define imx31_add_pata_imx() \ + imx_add_pata_imx(&imx31_pata_imx_data) diff --git a/arch/arm/mach-imx/devices-imx35.h b/arch/arm/mach-imx/devices-imx35.h new file mode 100644 index 00000000..7b99ef0b --- /dev/null +++ b/arch/arm/mach-imx/devices-imx35.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig + * + * 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 +#include + +extern const struct imx_fec_data imx35_fec_data; +#define imx35_add_fec(pdata) \ + imx_add_fec(&imx35_fec_data, pdata) + +extern const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data; +#define imx35_add_fsl_usb2_udc(pdata) \ + imx_add_fsl_usb2_udc(&imx35_fsl_usb2_udc_data, pdata) + +extern const struct imx_flexcan_data imx35_flexcan_data[]; +#define imx35_add_flexcan(id, pdata) \ + imx_add_flexcan(&imx35_flexcan_data[id], pdata) +#define imx35_add_flexcan0(pdata) imx35_add_flexcan(0, pdata) +#define imx35_add_flexcan1(pdata) imx35_add_flexcan(1, pdata) + +extern const struct imx_imx2_wdt_data imx35_imx2_wdt_data; +#define imx35_add_imx2_wdt(pdata) \ + imx_add_imx2_wdt(&imx35_imx2_wdt_data) + +extern const struct imx_imx_i2c_data imx35_imx_i2c_data[]; +#define imx35_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx35_imx_i2c_data[id], pdata) +#define imx35_add_imx_i2c0(pdata) imx35_add_imx_i2c(0, pdata) +#define imx35_add_imx_i2c1(pdata) imx35_add_imx_i2c(1, pdata) +#define imx35_add_imx_i2c2(pdata) imx35_add_imx_i2c(2, pdata) + +extern const struct imx_imx_keypad_data imx35_imx_keypad_data; +#define imx35_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx35_imx_keypad_data, pdata) + +extern const struct imx_imx_ssi_data imx35_imx_ssi_data[]; +#define imx35_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx35_imx_ssi_data[id], pdata) + +extern const struct imx_imx_uart_1irq_data imx35_imx_uart_data[]; +#define imx35_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx35_imx_uart_data[id], pdata) +#define imx35_add_imx_uart0(pdata) imx35_add_imx_uart(0, pdata) +#define imx35_add_imx_uart1(pdata) imx35_add_imx_uart(1, pdata) +#define imx35_add_imx_uart2(pdata) imx35_add_imx_uart(2, pdata) + +extern const struct imx_ipu_core_data imx35_ipu_core_data; +#define imx35_add_ipu_core(pdata) \ + imx_add_ipu_core(&imx35_ipu_core_data, pdata) +#define imx35_alloc_mx3_camera(pdata) \ + imx_alloc_mx3_camera(&imx35_ipu_core_data, pdata) +#define imx35_add_mx3_sdc_fb(pdata) \ + imx_add_mx3_sdc_fb(&imx35_ipu_core_data, pdata) + +extern const struct imx_mxc_ehci_data imx35_mxc_ehci_otg_data; +#define imx35_add_mxc_ehci_otg(pdata) \ + imx_add_mxc_ehci(&imx35_mxc_ehci_otg_data, pdata) +extern const struct imx_mxc_ehci_data imx35_mxc_ehci_hs_data; +#define imx35_add_mxc_ehci_hs(pdata) \ + imx_add_mxc_ehci(&imx35_mxc_ehci_hs_data, pdata) + +extern const struct imx_mxc_nand_data imx35_mxc_nand_data; +#define imx35_add_mxc_nand(pdata) \ + imx_add_mxc_nand(&imx35_mxc_nand_data, pdata) + +extern const struct imx_mxc_w1_data imx35_mxc_w1_data; +#define imx35_add_mxc_w1(pdata) \ + imx_add_mxc_w1(&imx35_mxc_w1_data) + +extern const struct imx_sdhci_esdhc_imx_data imx35_sdhci_esdhc_imx_data[]; +#define imx35_add_sdhci_esdhc_imx(id, pdata) \ + imx_add_sdhci_esdhc_imx(&imx35_sdhci_esdhc_imx_data[id], pdata) + +extern const struct imx_spi_imx_data imx35_cspi_data[]; +#define imx35_add_cspi(id, pdata) \ + imx_add_spi_imx(&imx35_cspi_data[id], pdata) +#define imx35_add_spi_imx0(pdata) imx35_add_cspi(0, pdata) +#define imx35_add_spi_imx1(pdata) imx35_add_cspi(1, pdata) + +extern const struct imx_pata_imx_data imx35_pata_imx_data; +#define imx35_add_pata_imx() \ + imx_add_pata_imx(&imx35_pata_imx_data) diff --git a/arch/arm/mach-imx/devices-imx50.h b/arch/arm/mach-imx/devices-imx50.h new file mode 100644 index 00000000..7216667e --- /dev/null +++ b/arch/arm/mach-imx/devices-imx50.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * 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 +#include + +extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[]; +#define imx50_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata) + +extern const struct imx_fec_data imx50_fec_data; +#define imx50_add_fec(pdata) \ + imx_add_fec(&imx50_fec_data, pdata) + +extern const struct imx_imx_i2c_data imx50_imx_i2c_data[]; +#define imx50_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata) diff --git a/arch/arm/mach-imx/devices-imx51.h b/arch/arm/mach-imx/devices-imx51.h new file mode 100644 index 00000000..af488bc0 --- /dev/null +++ b/arch/arm/mach-imx/devices-imx51.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig + * + * 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 +#include + +extern const struct imx_fec_data imx51_fec_data; +#define imx51_add_fec(pdata) \ + imx_add_fec(&imx51_fec_data, pdata) + +extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data; +#define imx51_add_fsl_usb2_udc(pdata) \ + imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata) + +extern const struct imx_imx_i2c_data imx51_imx_i2c_data[]; +#define imx51_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata) +#define imx51_add_hsi2c(pdata) \ + imx51_add_imx_i2c(2, pdata) + +extern const struct imx_imx_ssi_data imx51_imx_ssi_data[]; +#define imx51_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata) + +extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[]; +#define imx51_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata) + +extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data; +#define imx51_add_mxc_ehci_otg(pdata) \ + imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata) +extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[]; +#define imx51_add_mxc_ehci_hs(id, pdata) \ + imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata) + +extern const struct imx_mxc_nand_data imx51_mxc_nand_data; +#define imx51_add_mxc_nand(pdata) \ + imx_add_mxc_nand(&imx51_mxc_nand_data, pdata) + +extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[]; +#define imx51_add_sdhci_esdhc_imx(id, pdata) \ + imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata) + +extern const struct imx_spi_imx_data imx51_cspi_data; +#define imx51_add_cspi(pdata) \ + imx_add_spi_imx(&imx51_cspi_data, pdata) + +extern const struct imx_spi_imx_data imx51_ecspi_data[]; +#define imx51_add_ecspi(id, pdata) \ + imx_add_spi_imx(&imx51_ecspi_data[id], pdata) + +extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[]; +#define imx51_add_imx2_wdt(id, pdata) \ + imx_add_imx2_wdt(&imx51_imx2_wdt_data[id]) + +extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[]; +#define imx51_add_mxc_pwm(id) \ + imx_add_mxc_pwm(&imx51_mxc_pwm_data[id]) + +extern const struct imx_imx_keypad_data imx51_imx_keypad_data; +#define imx51_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx51_imx_keypad_data, pdata) + +extern const struct imx_pata_imx_data imx51_pata_imx_data; +#define imx51_add_pata_imx() \ + imx_add_pata_imx(&imx51_pata_imx_data) diff --git a/arch/arm/mach-imx/devices-imx53.h b/arch/arm/mach-imx/devices-imx53.h new file mode 100644 index 00000000..6e1e5d1f --- /dev/null +++ b/arch/arm/mach-imx/devices-imx53.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 Yong Shen. + * + * 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 +#include + +extern const struct imx_fec_data imx53_fec_data; +#define imx53_add_fec(pdata) \ + imx_add_fec(&imx53_fec_data, pdata) + +extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[]; +#define imx53_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata) + + +extern const struct imx_imx_i2c_data imx53_imx_i2c_data[]; +#define imx53_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata) + +extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[]; +#define imx53_add_sdhci_esdhc_imx(id, pdata) \ + imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata) + +extern const struct imx_spi_imx_data imx53_ecspi_data[]; +#define imx53_add_ecspi(id, pdata) \ + imx_add_spi_imx(&imx53_ecspi_data[id], pdata) + +extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[]; +#define imx53_add_imx2_wdt(id, pdata) \ + imx_add_imx2_wdt(&imx53_imx2_wdt_data[id]) + +extern const struct imx_imx_ssi_data imx53_imx_ssi_data[]; +#define imx53_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata) + +extern const struct imx_imx_keypad_data imx53_imx_keypad_data; +#define imx53_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx53_imx_keypad_data, pdata) + +extern const struct imx_pata_imx_data imx53_pata_imx_data; +#define imx53_add_pata_imx() \ + imx_add_pata_imx(&imx53_pata_imx_data) + +extern struct platform_device *__init imx53_add_ahci_imx(void); diff --git a/arch/arm/mach-imx/efika.h b/arch/arm/mach-imx/efika.h new file mode 100644 index 00000000..014aa985 --- /dev/null +++ b/arch/arm/mach-imx/efika.h @@ -0,0 +1,10 @@ +#ifndef _EFIKA_H +#define _EFIKA_H + +#define EFIKA_WLAN_EN IMX_GPIO_NR(2, 16) +#define EFIKA_WLAN_RESET IMX_GPIO_NR(2, 10) +#define EFIKA_USB_PHY_RESET IMX_GPIO_NR(2, 9) + +void __init efika_board_common_init(void); + +#endif diff --git a/arch/arm/mach-imx/ehci-imx25.c b/arch/arm/mach-imx/ehci-imx25.c new file mode 100644 index 00000000..865daf0b --- /dev/null +++ b/arch/arm/mach-imx/ehci-imx25.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2010 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. + * + * 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. + */ + +#include +#include + +#include +#include + +#define USBCTRL_OTGBASE_OFFSET 0x600 + +#define MX25_OTG_SIC_SHIFT 29 +#define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT) +#define MX25_OTG_PM_BIT (1 << 24) + +#define MX25_H1_SIC_SHIFT 21 +#define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT) +#define MX25_H1_PM_BIT (1 << 8) +#define MX25_H1_IPPUE_UP_BIT (1 << 7) +#define MX25_H1_IPPUE_DOWN_BIT (1 << 6) +#define MX25_H1_TLL_BIT (1 << 5) +#define MX25_H1_USBTE_BIT (1 << 4) + +int mx25_initialize_usb_hw(int port, unsigned int flags) +{ + unsigned int v; + + v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET)); + + switch (port) { + case 0: /* OTG port */ + v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX25_OTG_PM_BIT; + + break; + case 1: /* H1 port */ + v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_TLL_BIT | + MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX25_H1_PM_BIT; + + if (!(flags & MXC_EHCI_TTL_ENABLED)) + v |= MX25_H1_TLL_BIT; + + if (flags & MXC_EHCI_INTERNAL_PHY) + v |= MX25_H1_USBTE_BIT; + + if (flags & MXC_EHCI_IPPUE_DOWN) + v |= MX25_H1_IPPUE_DOWN_BIT; + + if (flags & MXC_EHCI_IPPUE_UP) + v |= MX25_H1_IPPUE_UP_BIT; + + break; + default: + return -EINVAL; + } + + writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET)); + + return 0; +} + diff --git a/arch/arm/mach-imx/ehci-imx27.c b/arch/arm/mach-imx/ehci-imx27.c new file mode 100644 index 00000000..fa69419e --- /dev/null +++ b/arch/arm/mach-imx/ehci-imx27.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2010 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. + * + * 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. + */ + +#include +#include + +#include +#include + +#define USBCTRL_OTGBASE_OFFSET 0x600 + +#define MX27_OTG_SIC_SHIFT 29 +#define MX27_OTG_SIC_MASK (0x3 << MX27_OTG_SIC_SHIFT) +#define MX27_OTG_PM_BIT (1 << 24) + +#define MX27_H2_SIC_SHIFT 21 +#define MX27_H2_SIC_MASK (0x3 << MX27_H2_SIC_SHIFT) +#define MX27_H2_PM_BIT (1 << 16) +#define MX27_H2_DT_BIT (1 << 5) + +#define MX27_H1_SIC_SHIFT 13 +#define MX27_H1_SIC_MASK (0x3 << MX27_H1_SIC_SHIFT) +#define MX27_H1_PM_BIT (1 << 8) +#define MX27_H1_DT_BIT (1 << 4) + +int mx27_initialize_usb_hw(int port, unsigned int flags) +{ + unsigned int v; + + v = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET)); + + switch (port) { + case 0: /* OTG port */ + v &= ~(MX27_OTG_SIC_MASK | MX27_OTG_PM_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_OTG_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX27_OTG_PM_BIT; + break; + case 1: /* H1 port */ + v &= ~(MX27_H1_SIC_MASK | MX27_H1_PM_BIT | MX27_H1_DT_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_H1_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX27_H1_PM_BIT; + + if (!(flags & MXC_EHCI_TTL_ENABLED)) + v |= MX27_H1_DT_BIT; + + break; + case 2: /* H2 port */ + v &= ~(MX27_H2_SIC_MASK | MX27_H2_PM_BIT | MX27_H2_DT_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_H2_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX27_H2_PM_BIT; + + if (!(flags & MXC_EHCI_TTL_ENABLED)) + v |= MX27_H2_DT_BIT; + + break; + default: + return -EINVAL; + } + + writel(v, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET)); + + return 0; +} + diff --git a/arch/arm/mach-imx/ehci-imx31.c b/arch/arm/mach-imx/ehci-imx31.c new file mode 100644 index 00000000..faad0f15 --- /dev/null +++ b/arch/arm/mach-imx/ehci-imx31.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2010 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. + * + * 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. + */ + +#include +#include + +#include +#include + +#define USBCTRL_OTGBASE_OFFSET 0x600 + +#define MX31_OTG_SIC_SHIFT 29 +#define MX31_OTG_SIC_MASK (0x3 << MX31_OTG_SIC_SHIFT) +#define MX31_OTG_PM_BIT (1 << 24) + +#define MX31_H2_SIC_SHIFT 21 +#define MX31_H2_SIC_MASK (0x3 << MX31_H2_SIC_SHIFT) +#define MX31_H2_PM_BIT (1 << 16) +#define MX31_H2_DT_BIT (1 << 5) + +#define MX31_H1_SIC_SHIFT 13 +#define MX31_H1_SIC_MASK (0x3 << MX31_H1_SIC_SHIFT) +#define MX31_H1_PM_BIT (1 << 8) +#define MX31_H1_DT_BIT (1 << 4) + +int mx31_initialize_usb_hw(int port, unsigned int flags) +{ + unsigned int v; + + v = readl(MX31_IO_ADDRESS(MX31_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET)); + + switch (port) { + case 0: /* OTG port */ + v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX31_OTG_PM_BIT; + + break; + case 1: /* H1 port */ + v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX31_H1_PM_BIT; + + if (!(flags & MXC_EHCI_TTL_ENABLED)) + v |= MX31_H1_DT_BIT; + + break; + case 2: /* H2 port */ + v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX31_H2_PM_BIT; + + if (!(flags & MXC_EHCI_TTL_ENABLED)) + v |= MX31_H2_DT_BIT; + + break; + default: + return -EINVAL; + } + + writel(v, MX31_IO_ADDRESS(MX31_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET)); + + return 0; +} diff --git a/arch/arm/mach-imx/ehci-imx35.c b/arch/arm/mach-imx/ehci-imx35.c new file mode 100644 index 00000000..001ec397 --- /dev/null +++ b/arch/arm/mach-imx/ehci-imx35.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2010 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. + * + * 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. + */ + +#include +#include + +#include +#include + +#define USBCTRL_OTGBASE_OFFSET 0x600 + +#define MX35_OTG_SIC_SHIFT 29 +#define MX35_OTG_SIC_MASK (0x3 << MX35_OTG_SIC_SHIFT) +#define MX35_OTG_PM_BIT (1 << 24) + +#define MX35_H1_SIC_SHIFT 21 +#define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT) +#define MX35_H1_PM_BIT (1 << 8) +#define MX35_H1_IPPUE_UP_BIT (1 << 7) +#define MX35_H1_IPPUE_DOWN_BIT (1 << 6) +#define MX35_H1_TLL_BIT (1 << 5) +#define MX35_H1_USBTE_BIT (1 << 4) + +int mx35_initialize_usb_hw(int port, unsigned int flags) +{ + unsigned int v; + + v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET)); + + switch (port) { + case 0: /* OTG port */ + v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX35_OTG_PM_BIT; + + break; + case 1: /* H1 port */ + v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT | + MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT; + + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX35_H1_PM_BIT; + + if (!(flags & MXC_EHCI_TTL_ENABLED)) + v |= MX35_H1_TLL_BIT; + + if (flags & MXC_EHCI_INTERNAL_PHY) + v |= MX35_H1_USBTE_BIT; + + if (flags & MXC_EHCI_IPPUE_DOWN) + v |= MX35_H1_IPPUE_DOWN_BIT; + + if (flags & MXC_EHCI_IPPUE_UP) + v |= MX35_H1_IPPUE_UP_BIT; + + break; + default: + return -EINVAL; + } + + writel(v, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET)); + + return 0; +} diff --git a/arch/arm/mach-imx/ehci-imx5.c b/arch/arm/mach-imx/ehci-imx5.c new file mode 100644 index 00000000..c17fa131 --- /dev/null +++ b/arch/arm/mach-imx/ehci-imx5.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2010 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. + * + * 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. + */ + +#include +#include + +#include +#include + +#define MXC_OTG_OFFSET 0 +#define MXC_H1_OFFSET 0x200 +#define MXC_H2_OFFSET 0x400 + +/* USB_CTRL */ +#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */ +#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */ +#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */ +#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */ +#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */ + +/* USB_PHY_CTRL_FUNC */ +#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */ +#define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */ + +/* USBH2CTRL */ +#define MXC_H2_UCTRL_H2UIE_BIT (1 << 8) +#define MXC_H2_UCTRL_H2WIE_BIT (1 << 7) +#define MXC_H2_UCTRL_H2PM_BIT (1 << 4) + +#define MXC_USBCMD_OFFSET 0x140 + +/* USBCMD */ +#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */ + +int mx51_initialize_usb_hw(int port, unsigned int flags) +{ + unsigned int v; + void __iomem *usb_base; + void __iomem *usbotg_base; + void __iomem *usbother_base; + int ret = 0; + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) { + printk(KERN_ERR "%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + switch (port) { + case 0: /* OTG port */ + usbotg_base = usb_base + MXC_OTG_OFFSET; + break; + case 1: /* Host 1 port */ + usbotg_base = usb_base + MXC_H1_OFFSET; + break; + case 2: /* Host 2 port */ + usbotg_base = usb_base + MXC_H2_OFFSET; + break; + default: + printk(KERN_ERR"%s no such port %d\n", __func__, port); + ret = -ENOENT; + goto error; + } + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + switch (port) { + case 0: /*OTG port */ + if (flags & MXC_EHCI_INTERNAL_PHY) { + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + if (flags & MXC_EHCI_POWER_PINS_ENABLED) { + /* OC/USBPWR is not used */ + v |= MXC_OTG_PHYCTRL_OC_DIS_BIT; + } else { + /* OC/USBPWR is used */ + v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT; + } + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); + if (flags & MXC_EHCI_WAKEUP_ENABLED) + v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */ + else + v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */ + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v |= MXC_OTG_UCTRL_OPM_BIT; + else + v &= ~MXC_OTG_UCTRL_OPM_BIT; + __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); + } + break; + case 1: /* Host 1 */ + /*Host ULPI */ + v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); + if (flags & MXC_EHCI_WAKEUP_ENABLED) { + /* HOST1 wakeup/ULPI intr enable */ + v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT); + } else { + /* HOST1 wakeup/ULPI intr disable */ + v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT); + } + + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ + else + v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ + __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); + + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */ + else + v |= MXC_H1_OC_DIS_BIT; /* OC is not used */ + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET); + if (flags & MXC_EHCI_ITC_NO_THRESHOLD) + /* Interrupt Threshold Control:Immediate (no threshold) */ + v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK; + __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET); + break; + case 2: /* Host 2 ULPI */ + v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET); + if (flags & MXC_EHCI_WAKEUP_ENABLED) { + /* HOST1 wakeup/ULPI intr enable */ + v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT); + } else { + /* HOST1 wakeup/ULPI intr disable */ + v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT); + } + + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/ + else + v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/ + __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET); + break; + } + +error: + iounmap(usb_base); + return ret; +} + diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c new file mode 100644 index 00000000..5f2f91d1 --- /dev/null +++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2009-2010 Eric Benard - eric@eukrea.com + * + * Based on pcm970-baseboard.c which is : + * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.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 +#include +#include +#include +#include +#include +#include