aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mx6
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx6')
-rw-r--r--arch/arm/mach-mx6/Kconfig382
-rw-r--r--arch/arm/mach-mx6/Makefile25
-rw-r--r--arch/arm/mach-mx6/Makefile.boot3
-rw-r--r--arch/arm/mach-mx6/board-mx6dl_arm2.h336
-rw-r--r--arch/arm/mach-mx6/board-mx6dl_hdmidongle.h342
-rw-r--r--arch/arm/mach-mx6/board-mx6dl_sabresd.h406
-rw-r--r--arch/arm/mach-mx6/board-mx6q_arm2.c2303
-rw-r--r--arch/arm/mach-mx6/board-mx6q_arm2.h331
-rw-r--r--arch/arm/mach-mx6/board-mx6q_hdmidongle.c800
-rw-r--r--arch/arm/mach-mx6/board-mx6q_hdmidongle.h343
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabreauto.c1764
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabreauto.h376
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabrelite.c1414
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabresd.c2046
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabresd.h309
-rwxr-xr-xarch/arm/mach-mx6/board-mx6sl_arm2.c1313
-rw-r--r--arch/arm/mach-mx6/board-mx6sl_common.h578
-rw-r--r--arch/arm/mach-mx6/board-mx6sl_evk.c1672
-rwxr-xr-xarch/arm/mach-mx6/board-mx6sl_ntx.c3886
-rwxr-xr-xarch/arm/mach-mx6/board-mx6sl_ntx.h306
-rw-r--r--arch/arm/mach-mx6/board-mx6solo_sabreauto.h377
-rw-r--r--arch/arm/mach-mx6/bus_freq.c842
-rw-r--r--arch/arm/mach-mx6/clock.c5736
-rwxr-xr-xarch/arm/mach-mx6/clock_mx6sl.c4182
-rw-r--r--arch/arm/mach-mx6/cpu.c339
-rw-r--r--arch/arm/mach-mx6/cpu_op-mx6.c371
-rw-r--r--arch/arm/mach-mx6/cpu_op-mx6.h18
-rw-r--r--arch/arm/mach-mx6/cpu_regulator-mx6.c191
-rw-r--r--arch/arm/mach-mx6/crm_regs.h569
-rw-r--r--arch/arm/mach-mx6/devices-imx6q.h265
-rw-r--r--arch/arm/mach-mx6/devices.c91
-rw-r--r--arch/arm/mach-mx6/dummy_gpio.c124
-rw-r--r--arch/arm/mach-mx6/etm.c110
-rw-r--r--arch/arm/mach-mx6/headsmp.S79
-rw-r--r--arch/arm/mach-mx6/irq.c148
-rw-r--r--arch/arm/mach-mx6/localtimer.c35
-rw-r--r--arch/arm/mach-mx6/mm.c145
-rw-r--r--arch/arm/mach-mx6/msi.c151
-rw-r--r--arch/arm/mach-mx6/msi.h26
-rw-r--r--arch/arm/mach-mx6/mx6_anatop_regulator.c615
-rw-r--r--arch/arm/mach-mx6/mx6_ddr_freq.S1010
-rw-r--r--arch/arm/mach-mx6/mx6_fec.c56
-rw-r--r--arch/arm/mach-mx6/mx6_mmdc.c367
-rw-r--r--arch/arm/mach-mx6/mx6_suspend.S1713
-rw-r--r--arch/arm/mach-mx6/mx6_wfi.S156
-rw-r--r--arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c545
-rw-r--r--arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c529
-rw-r--r--arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c531
-rw-r--r--arch/arm/mach-mx6/mx6sl_ddr.S570
-rw-r--r--arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c536
-rwxr-xr-xarch/arm/mach-mx6/mx6sl_ntx_io.c2605
-rwxr-xr-xarch/arm/mach-mx6/mx6sl_ntx_pmic_pfuze100.c471
-rw-r--r--arch/arm/mach-mx6/mx6sl_wfi.S727
-rwxr-xr-xarch/arm/mach-mx6/ntx_hwconfig.h267
-rw-r--r--arch/arm/mach-mx6/pcie.c1161
-rw-r--r--arch/arm/mach-mx6/plat_hotplug.c134
-rw-r--r--arch/arm/mach-mx6/platsmp.c152
-rw-r--r--arch/arm/mach-mx6/pm.c600
-rw-r--r--arch/arm/mach-mx6/regs-anadig.h1011
-rw-r--r--arch/arm/mach-mx6/serial.h76
-rw-r--r--arch/arm/mach-mx6/src-reg.h51
-rw-r--r--arch/arm/mach-mx6/system.c682
-rw-r--r--arch/arm/mach-mx6/usb.h85
-rw-r--r--arch/arm/mach-mx6/usb_dr.c795
-rw-r--r--arch/arm/mach-mx6/usb_h1.c497
-rw-r--r--arch/arm/mach-mx6/usb_h2.c249
-rw-r--r--arch/arm/mach-mx6/usb_h3.c240
67 files changed, 49165 insertions, 0 deletions
diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig
new file mode 100644
index 00000000..a8dc8bc1
--- /dev/null
+++ b/arch/arm/mach-mx6/Kconfig
@@ -0,0 +1,382 @@
+if ARCH_MX6
+
+config ARCH_MX6Q
+ bool
+ select USB_ARCH_HAS_EHCI
+ select ARCH_MXC_IOMUX_V3
+ select ARCH_MXC_AUDMUX_V2
+ select ARCH_SUPPORTS_MSI
+ select ARM_GIC
+ select ARCH_HAS_CPUFREQ
+ select OC_ETM
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_IMX_IPUV3
+ select IMX_HAVE_PLATFORM_MXC_PWM
+ select IMX_HAVE_PLATFORM_LDB
+ select IMX_HAVE_PLATFORM_IMX_SPDIF
+ select IMX_HAVE_PLATFORM_IMX_VDOA
+
+config FORCE_MAX_ZONEORDER
+ int "MAX_ORDER"
+ default "13"
+
+config SOC_IMX6Q
+ bool
+
+config SOC_IMX6SL
+ bool
+
+config MACH_MX6Q_ARM2
+ bool "Support i.MX 6Quad Armadillo2 platform"
+ select ARCH_MX6Q
+ select SOC_IMX6Q
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_GPMI_NFC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_VPU
+ select IMX_HAVE_PLATFORM_IMX_DVFS
+ select IMX_HAVE_PLATFORM_IMX_ESAI
+ select IMX_HAVE_PLATFORM_IMX_SSI
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX_VIIM
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_MXC_HDMI
+ select IMX_HAVE_PLATFORM_IMX_ASRC
+ select IMX_HAVE_PLATFORM_IMX_SPDIF
+ select IMX_HAVE_PLATFORM_IMX_MIPI_DSI
+ select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_IMX_MIPI_CSI2
+ select IMX_HAVE_PLATFORM_PERFMON
+ select IMX_HAVE_PLATFORM_MXC_MLB
+ select IMX_HAVE_PLATFORM_IMX_EPDC
+# select IMX_HAVE_PLATFORM_IMX_ELCDIF
+ select IMX_HAVE_PLATFORM_IMX_PXP
+ select IMX_HAVE_PLATFORM_IMX_PCIE
+ select IMX_HAVE_PLATFORM_IMX_CAAM
+ help
+ Include support for i.MX 6Quad Armadillo2 platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX6SL_ARM2
+ bool "Support i.MX 6SoloLite Armadillo2 platform"
+ select ARCH_MX6Q
+ select SOC_IMX6SL
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_DVFS
+ select IMX_HAVE_PLATFORM_IMX_SSI
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX_VIIM
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_IMX_SPDIF
+ select IMX_HAVE_PLATFORM_PERFMON
+ select IMX_HAVE_PLATFORM_IMX_EPDC
+ select IMX_HAVE_PLATFORM_IMX_SPDC
+ select IMX_HAVE_PLATFORM_IMX_PXP
+ select IMX_HAVE_PLATFORM_IMX_KEYPAD
+ select IMX_HAVE_PLATFORM_IMX_DCP
+ select IMX_HAVE_PLATFORM_RANDOM_RNGC
+ select ARCH_HAS_RNGC
+ help
+ Include support for i.MX 6Sololite Armadillo2 platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX6SL_EVK
+ bool "Support i.MX 6SoloLite EVK platform"
+ select ARCH_MX6Q
+ select SOC_IMX6SL
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_DVFS
+ select IMX_HAVE_PLATFORM_IMX_SSI
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX_VIIM
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_IMX_SPDIF
+ select IMX_HAVE_PLATFORM_PERFMON
+ select IMX_HAVE_PLATFORM_IMX_EPDC
+ select IMX_HAVE_PLATFORM_IMX_SPDC
+ select IMX_HAVE_PLATFORM_IMX_PXP
+ select IMX_HAVE_PLATFORM_IMX_FSL_CSI
+ select IMX_HAVE_PLATFORM_IMX_KEYPAD
+ select IMX_HAVE_PLATFORM_IMX_DCP
+ select IMX_HAVE_PLATFORM_RANDOM_RNGC
+ select ARCH_HAS_RNGC
+ help
+ Include support for i.MX 6Sololite EVK platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX6SL_NTX
+ bool "Support i.MX 6SoloLite NTX platform"
+ select ARCH_MX6Q
+ select SOC_IMX6SL
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_DVFS
+ select IMX_HAVE_PLATFORM_IMX_SSI
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX_VIIM
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_IMX_SPDIF
+ select IMX_HAVE_PLATFORM_PERFMON
+ select IMX_HAVE_PLATFORM_IMX_EPDC
+ select IMX_HAVE_PLATFORM_IMX_SPDC
+ select IMX_HAVE_PLATFORM_IMX_PXP
+ select IMX_HAVE_PLATFORM_IMX_FSL_CSI
+ select IMX_HAVE_PLATFORM_IMX_KEYPAD
+ select IMX_HAVE_PLATFORM_IMX_DCP
+ select IMX_HAVE_PLATFORM_RANDOM_RNGC
+ select ARCH_HAS_RNGC
+ help
+ Include support for i.MX 6Sololite NTX platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX6Q_SABRELITE
+ bool "Support i.MX 6Quad SABRE Lite platform"
+ select ARCH_MX6Q
+ select SOC_IMX6Q
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_GPMI_NFC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_VPU
+ select IMX_HAVE_PLATFORM_IMX_SSI
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX_VIIM
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_MXC_HDMI
+ select IMX_HAVE_PLATFORM_IMX_ASRC
+ select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_IMX_CAAM
+ help
+ Include support for i.MX 6Quad SABRE Lite platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX6Q_SABRESD
+ bool "Support i.MX 6Quad SABRESD platform"
+ select ARCH_MX6Q
+ select SOC_IMX6Q
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_GPMI_NFC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_VPU
+ select IMX_HAVE_PLATFORM_IMX_SSI
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX_VIIM
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_MXC_HDMI
+ select IMX_HAVE_PLATFORM_IMX_ASRC
+ select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_IMX_PCIE
+ select IMX_HAVE_PLATFORM_IMX_CAAM
+ help
+ Include support for i.MX 6Quad SABRE SD platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX6Q_SABREAUTO
+ bool "Support i.MX 6Quad SABRE Auto platform"
+ select ARCH_MX6Q
+ select SOC_IMX6Q
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_GPMI_NFC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_VPU
+ select IMX_HAVE_PLATFORM_IMX_DVFS
+ select IMX_HAVE_PLATFORM_IMX_ESAI
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX_VIIM
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_MXC_HDMI
+ select IMX_HAVE_PLATFORM_IMX_ASRC
+ select IMX_HAVE_PLATFORM_IMX_SPDIF
+ select IMX_HAVE_PLATFORM_IMX_MIPI_DSI
+ select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_IMX_MIPI_CSI2
+ select IMX_HAVE_PLATFORM_IMX_PCIE
+ select IMX_HAVE_PLATFORM_IMX_CAAM
+ help
+ Include support for i.MX 6Quad SABRE Auto platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX6Q_HDMIDONGLE
+ bool "Support i.MX 6Quad HDMIDONGLE platform"
+ select ARCH_MX6Q
+ select SOC_IMX6Q
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_GPMI_NFC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_VPU
+ select IMX_HAVE_PLATFORM_IMX_DVFS
+ select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX_VIIM
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_MXC_HDMI
+ select IMX_HAVE_PLATFORM_IMX_PCIE
+ help
+ Include support for i.MX 6Quad HDMI Dongle platform. This includes specific
+ configurations for the board and its peripherals.
+
+comment "MX6 Options:"
+
+config IMX_PCIE
+ bool "PCI Express support"
+ select PCI
+
+config IMX_PCIE_EP_MODE_IN_EP_RC_SYS
+ bool "PCI Express EP mode in the IMX6 RC/EP interconnection system"
+ depends on IMX_PCIE
+
+config IMX_PCIE_RC_MODE_IN_EP_RC_SYS
+ bool "PCI Express RC mode in the IMX6 RC/EP interconnection system"
+ depends on IMX_PCIE
+
+config USB_EHCI_ARC_H1
+ tristate "USB Host 1 support"
+ depends on USB_EHCI_ARC
+
+config USB_FSL_ARC_OTG
+ tristate "FSL USB OTG support"
+
+config USB_ID_WAKEUP_ENABLE
+ bool "Enable USB ID Pin As System Wakeup Source"
+ depends on SOC_IMX6SL
+ default n
+
+config MX6_INTER_LDO_BYPASS
+ bool "Internal LDO in MX6Q/DL bypass"
+ depends on REGULATOR_PFUZE100 && CPU_FREQ_IMX && ARCH_MX6
+ default n
+ help
+ This is choosed for bypass internal LDO in MX6. If choose it, internal
+ LDO will replaced by external pmic regulator(e.g. pfuze100), VDDCORE
+ can be adjust automatically adjust by cpu frequency.
+
+config MX6_CLK_FOR_BOOTUI_TRANS
+ bool "MX6 clk setting for smooth UI transtion from bootloader to kernel"
+ depends on MXC_IPU_V3H
+ default n
+ help
+ This is choosed to keep enable IPU related clocks and PWM clocks and
+ avoid setting IPU related clocks' parents when initializing clock tree
+ so that bootloader splashimage can transition to kernel smoothly.
+
+
+config MX6_ENET_IRQ_TO_GPIO
+ bool "Route ENET interrupts to GPIO"
+ default n
+ help
+ Enabling this will direct all the ENET interrupts to a board specific GPIO.
+ This will allow the system to enter WAIT mode when ENET is active.
+
+config SDMA_IRAM
+ bool "Use Internal RAM for SDMA data structures"
+ depends on IMX_SDMA && SOC_IMX6SL
+ help
+ SDMA buffer or control structures are stored in the IRAM/OCRAM
+
+
+endif
diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile
new file mode 100644
index 00000000..14fbbde2
--- /dev/null
+++ b/arch/arm/mach-mx6/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_h2.o usb_h3.o\
+pm.o cpu_op-mx6.o mx6_wfi.o mx6_fec.o mx6_anatop_regulator.o cpu_regulator-mx6.o \
+mx6_mmdc.o mx6_ddr_freq.o mx6sl_ddr.o mx6sl_wfi.o etm.o
+
+obj-$(CONFIG_ARCH_MX6) += clock.o mx6_suspend.o clock_mx6sl.o
+obj-$(CONFIG_MACH_MX6Q_ARM2) += board-mx6q_arm2.o
+obj-$(CONFIG_MACH_MX6SL_ARM2) += board-mx6sl_arm2.o mx6sl_arm2_pmic_pfuze100.o
+obj-$(CONFIG_MACH_MX6SL_EVK) += board-mx6sl_evk.o mx6sl_evk_pmic_pfuze100.o
+obj-$(CONFIG_MACH_MX6SL_NTX) += board-mx6sl_ntx.o mx6sl_ntx_pmic_pfuze100.o mx6sl_ntx_io.o
+obj-$(CONFIG_MACH_MX6Q_SABRELITE) += board-mx6q_sabrelite.o
+obj-$(CONFIG_MACH_MX6Q_SABRESD) += board-mx6q_sabresd.o mx6q_sabresd_pmic_pfuze100.o
+obj-$(CONFIG_MACH_MX6Q_SABREAUTO) += board-mx6q_sabreauto.o mx6q_sabreauto_pmic_pfuze100.o
+obj-$(CONFIG_MACH_MX6Q_HDMIDONGLE) += board-mx6q_hdmidongle.o
+obj-$(CONFIG_SMP) += plat_hotplug.o platsmp.o headsmp.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_IMX_PCIE) += pcie.o
+obj-$(CONFIG_USB_FSL_ARC_OTG) += usb_dr.o
+obj-$(CONFIG_USB_EHCI_ARC_H1) += usb_h1.o
+obj-$(CONFIG_PCI_MSI) += msi.o
+
diff --git a/arch/arm/mach-mx6/Makefile.boot b/arch/arm/mach-mx6/Makefile.boot
new file mode 100644
index 00000000..dc006a84
--- /dev/null
+++ b/arch/arm/mach-mx6/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-$(CONFIG_ARCH_MX6Q) := 0x10008000
+params_phys-$(CONFIG_ARCH_MX6Q) := 0x10000100
+initrd_phys-$(CONFIG_ARCH_MX6Q) := 0x10800000
diff --git a/arch/arm/mach-mx6/board-mx6dl_arm2.h b/arch/arm/mach-mx6/board-mx6dl_arm2.h
new file mode 100644
index 00000000..dd7e6658
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6dl_arm2.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2012-2013 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 <mach/iomux-mx6dl.h>
+
+static iomux_v3_cfg_t mx6dl_arm2_pads[] = {
+
+ /* UART4 for debug */
+ MX6DL_PAD_KEY_COL0__UART4_TXD,
+ MX6DL_PAD_KEY_ROW0__UART4_RXD,
+ /* USB HSIC ports use the same pin with ENET */
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ /* USB H2 strobe/data pin */
+ MX6DL_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE,
+ MX6DL_PAD_RGMII_TXC__USBOH3_H2_DATA,
+
+ /* USB H3 strobe/data pin */
+ MX6DL_PAD_RGMII_RXC__USBOH3_H3_STROBE,
+ MX6DL_PAD_RGMII_RX_CTL__USBOH3_H3_DATA,
+ /* ENET */
+#else
+ MX6DL_PAD_KEY_COL1__ENET_MDIO,
+ MX6DL_PAD_KEY_COL2__ENET_MDC,
+ MX6DL_PAD_RGMII_TXC__ENET_RGMII_TXC,
+ MX6DL_PAD_RGMII_TD0__ENET_RGMII_TD0,
+ MX6DL_PAD_RGMII_TD1__ENET_RGMII_TD1,
+ MX6DL_PAD_RGMII_TD2__ENET_RGMII_TD2,
+ MX6DL_PAD_RGMII_TD3__ENET_RGMII_TD3,
+ MX6DL_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL,
+ MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK,
+ MX6DL_PAD_RGMII_RXC__ENET_RGMII_RXC,
+ MX6DL_PAD_RGMII_RD0__ENET_RGMII_RD0,
+ MX6DL_PAD_RGMII_RD1__ENET_RGMII_RD1,
+ MX6DL_PAD_RGMII_RD2__ENET_RGMII_RD2,
+ MX6DL_PAD_RGMII_RD3__ENET_RGMII_RD3,
+ MX6DL_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL,
+#ifdef CONFIG_FEC_1588
+ MX6DL_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT,
+#endif
+#endif
+ /* MCLK for csi0 */
+ MX6DL_PAD_GPIO_0__CCM_CLKO,
+ MX6DL_PAD_GPIO_3__CCM_CLKO2,
+
+ /* SD1 */
+ MX6DL_PAD_SD1_CLK__USDHC1_CLK,
+ MX6DL_PAD_SD1_CMD__USDHC1_CMD,
+ MX6DL_PAD_SD1_DAT0__USDHC1_DAT0,
+ MX6DL_PAD_SD1_DAT1__USDHC1_DAT1,
+ MX6DL_PAD_SD1_DAT2__USDHC1_DAT2,
+ MX6DL_PAD_SD1_DAT3__USDHC1_DAT3,
+ /* SD2 */
+ MX6DL_PAD_SD2_CLK__USDHC2_CLK,
+ MX6DL_PAD_SD2_CMD__USDHC2_CMD,
+ MX6DL_PAD_SD2_DAT0__USDHC2_DAT0,
+ MX6DL_PAD_SD2_DAT1__USDHC2_DAT1,
+ MX6DL_PAD_SD2_DAT2__USDHC2_DAT2,
+ MX6DL_PAD_SD2_DAT3__USDHC2_DAT3,
+ /* SD3 */
+ MX6DL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6DL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+ MX6DL_PAD_SD3_RST__USDHC3_RST,
+ /* SD3 VSelect */
+ MX6DL_PAD_GPIO_18__USDHC3_VSELECT,
+ /* SD3_CD and SD3_WP */
+ MX6DL_PAD_NANDF_CS0__GPIO_6_11,
+ MX6DL_PAD_NANDF_CS1__GPIO_6_14,
+ /* SD4 */
+ MX6DL_PAD_SD4_CLK__USDHC4_CLK_50MHZ,
+ MX6DL_PAD_SD4_CMD__USDHC4_CMD_50MHZ,
+ MX6DL_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ,
+ MX6DL_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ,
+ MX6DL_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ,
+ MX6DL_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ,
+ MX6DL_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ,
+ MX6DL_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ,
+ MX6DL_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ,
+ MX6DL_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ,
+ MX6DL_PAD_NANDF_ALE__USDHC4_RST,
+ /* eCSPI1 */
+ MX6DL_PAD_EIM_EB2__ECSPI1_SS0,
+ MX6DL_PAD_EIM_D16__ECSPI1_SCLK,
+ MX6DL_PAD_EIM_D17__ECSPI1_MISO,
+ MX6DL_PAD_EIM_D18__ECSPI1_MOSI,
+ MX6DL_PAD_EIM_D19__ECSPI1_SS1,
+ MX6DL_PAD_EIM_EB2__GPIO_2_30, /*SS0*/
+ MX6DL_PAD_EIM_D19__GPIO_3_19, /*SS1*/
+
+ /* ESAI */
+ MX6DL_PAD_ENET_RXD0__ESAI1_HCKT,
+ MX6DL_PAD_ENET_CRS_DV__ESAI1_SCKT,
+ MX6DL_PAD_ENET_RXD1__ESAI1_FST,
+ MX6DL_PAD_ENET_TX_EN__ESAI1_TX3_RX2,
+ MX6DL_PAD_ENET_TXD1__ESAI1_TX2_RX3,
+ MX6DL_PAD_ENET_TXD0__ESAI1_TX4_RX1,
+ MX6DL_PAD_ENET_MDC__ESAI1_TX5_RX0,
+ MX6DL_PAD_NANDF_CS2__ESAI1_TX0,
+ MX6DL_PAD_NANDF_CS3__ESAI1_TX1,
+
+ /* I2C1 */
+ MX6DL_PAD_CSI0_DAT8__I2C1_SDA,
+ MX6DL_PAD_CSI0_DAT9__I2C1_SCL,
+
+ /* I2C2 */
+ MX6DL_PAD_KEY_COL3__I2C2_SCL,
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA,
+
+ /* DISPLAY */
+ MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6DL_PAD_DI0_PIN15__IPU1_DI0_PIN15,
+ MX6DL_PAD_DI0_PIN2__IPU1_DI0_PIN2,
+ MX6DL_PAD_DI0_PIN3__IPU1_DI0_PIN3,
+ MX6DL_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
+ MX6DL_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
+ MX6DL_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
+ MX6DL_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
+ MX6DL_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
+ MX6DL_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
+ MX6DL_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
+ MX6DL_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
+ MX6DL_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
+ MX6DL_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
+ MX6DL_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
+ MX6DL_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
+ MX6DL_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
+ MX6DL_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
+ MX6DL_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
+ MX6DL_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
+ MX6DL_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
+ MX6DL_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
+ MX6DL_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
+ MX6DL_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
+ MX6DL_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20,
+ MX6DL_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
+ MX6DL_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22,
+ MX6DL_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23,
+
+ MX6DL_PAD_EIM_D24__GPIO_3_24,
+
+ /* UART2 */
+ MX6DL_PAD_EIM_D26__UART2_RXD,
+ MX6DL_PAD_EIM_D27__UART2_TXD,
+ MX6DL_PAD_EIM_D28__UART2_RTS,
+ MX6DL_PAD_EIM_D29__UART2_CTS,
+
+ /* PWM1 */
+ MX6DL_PAD_GPIO_9__PWM1_PWMO,
+
+ /* DISP0 DET */
+ MX6DL_PAD_EIM_D31__GPIO_3_31,
+
+ /* DISP0 RESET */
+ MX6DL_PAD_EIM_WAIT__GPIO_5_0,
+
+ /* HDMI */
+ MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE,
+ MX6DL_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0,
+ MX6DL_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1,
+
+ /* USBOTG ID pin */
+ MX6DL_PAD_GPIO_1__USBOTG_ID,
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ MX6DL_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1,
+#else
+ /* MLB150 */
+ MX6DL_PAD_GPIO_3__MLB_MLBCLK,
+ MX6DL_PAD_GPIO_6__MLB_MLBSIG,
+ MX6DL_PAD_GPIO_2__MLB_MLBDAT,
+#endif
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_epdc_pads[] = {
+ MX6DL_PAD_EIM_A17__GPIO_2_21,
+ MX6DL_PAD_EIM_D17__GPIO_3_17,
+ MX6DL_PAD_EIM_A18__GPIO_2_20,
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_i2c3_pads[] = {
+ MX6DL_PAD_GPIO_5__I2C3_SCL,
+ MX6DL_PAD_GPIO_16__I2C3_SDA,
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_spdif_pads[] = {
+ /* SPDIF */
+ MX6DL_PAD_GPIO_16__SPDIF_IN1,
+ MX6DL_PAD_GPIO_17__SPDIF_OUT1,
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_can_pads[] = {
+ /* CAN1 */
+ MX6DL_PAD_GPIO_7__CAN1_TXCAN,
+ MX6DL_PAD_KEY_ROW2__CAN1_RXCAN,
+ MX6DL_PAD_GPIO_17__GPIO_7_12, /* CAN1 STBY */
+ MX6DL_PAD_GPIO_18__GPIO_7_13, /* CAN1 EN */
+
+ /* CAN2 */
+ MX6DL_PAD_KEY_COL4__CAN2_TXCAN,
+ MX6DL_PAD_KEY_ROW4__CAN2_RXCAN,
+ MX6DL_PAD_CSI0_DAT6__GPIO_5_24, /* CAN2 EN */
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_esai_record_pads[] = {
+ MX6DL_PAD_ENET_RX_ER__ESAI1_HCKR,
+ MX6DL_PAD_ENET_MDIO__ESAI1_SCKR,
+ MX6DL_PAD_ENET_REF_CLK__ESAI1_FSR,
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_csi0_sensor_pads[] = {
+ MX6DL_PAD_GPIO_0__CCM_CLKO,
+ /* ipu1 csi0 */
+ MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+ MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+ /* camera reset */
+ MX6DL_PAD_GPIO_19__GPIO_4_5,
+ /* camera powerdown */
+ MX6DL_PAD_CSI0_DAT5__GPIO_5_23,
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_csi0_tvin_pads[] = {
+ /* ipu1 csi0 */
+ MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+ MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+ /* camera reset */
+ MX6DL_PAD_CSI0_DAT7__GPIO_5_25,
+ /* camera powerdown */
+ MX6DL_PAD_CSI0_DAT5__GPIO_5_23,
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_mipi_sensor_pads[] = {
+ MX6DL_PAD_CSI0_MCLK__CCM_CLKO,
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_audmux_pads[] = {
+
+ /* AUDMUX */
+ MX6DL_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC,
+ MX6DL_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD,
+ MX6DL_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS,
+ MX6DL_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD,
+};
+
+#define MX6DL_USDHC_PAD_SETTING(id, speed) \
+mx6dl_sd##id##_##speed##mhz[] = { \
+ MX6DL_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \
+}
+
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 50);
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 100);
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 200);
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(4, 50);
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(4, 100);
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(4, 200);
+
+/* The GPMI is conflicted with SD3, so init this in the driver. */
+static iomux_v3_cfg_t mx6dl_gpmi_nand[] __initdata = {
+ MX6DL_PAD_NANDF_CLE__RAWNAND_CLE,
+ MX6DL_PAD_NANDF_ALE__RAWNAND_ALE,
+ MX6DL_PAD_NANDF_CS0__RAWNAND_CE0N,
+ MX6DL_PAD_NANDF_CS1__RAWNAND_CE1N,
+ MX6DL_PAD_NANDF_CS2__RAWNAND_CE2N,
+ MX6DL_PAD_NANDF_CS3__RAWNAND_CE3N,
+ MX6DL_PAD_NANDF_RB0__RAWNAND_READY0,
+ MX6DL_PAD_SD4_DAT0__RAWNAND_DQS,
+ MX6DL_PAD_NANDF_D0__RAWNAND_D0,
+ MX6DL_PAD_NANDF_D1__RAWNAND_D1,
+ MX6DL_PAD_NANDF_D2__RAWNAND_D2,
+ MX6DL_PAD_NANDF_D3__RAWNAND_D3,
+ MX6DL_PAD_NANDF_D4__RAWNAND_D4,
+ MX6DL_PAD_NANDF_D5__RAWNAND_D5,
+ MX6DL_PAD_NANDF_D6__RAWNAND_D6,
+ MX6DL_PAD_NANDF_D7__RAWNAND_D7,
+ MX6DL_PAD_SD4_CMD__RAWNAND_RDN,
+ MX6DL_PAD_SD4_CLK__RAWNAND_WRN,
+ MX6DL_PAD_NANDF_WP_B__RAWNAND_RESETN,
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_hdmi_ddc_pads[] = {
+ MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_i2c2_pads[] = {
+ MX6DL_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
diff --git a/arch/arm/mach-mx6/board-mx6dl_hdmidongle.h b/arch/arm/mach-mx6/board-mx6dl_hdmidongle.h
new file mode 100644
index 00000000..b46b6e16
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6dl_hdmidongle.h
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _BOARD_MX6DL_HDMIDONGLE_H
+#define _BOARD_MX6DL_HDMIDONGLE_H
+#include <mach/iomux-mx6dl.h>
+
+static iomux_v3_cfg_t mx6dl_hdmidongle_rev_a_pads[] = {
+ /* SPI2 for PMIC communication port */
+ MX6DL_PAD_EIM_OE__ECSPI2_MISO,
+ MX6DL_PAD_EIM_RW__ECSPI2_SS0,
+ MX6DL_PAD_EIM_CS0__ECSPI2_SCLK,
+ MX6DL_PAD_EIM_CS1__ECSPI2_MOSI,
+
+ /*USB_OTG_DET(USB OTG cable plug detect) */
+ MX6DL_PAD_EIM_A16__GPIO_2_22,
+ /*BT_WAKEUP_HOST(Combo module BT wake-up output) */
+ MX6DL_PAD_EIM_A25__GPIO_5_2,
+ /* HOST_WAKEUP_BT(CPU wakeup BT signal)*/
+ MX6DL_PAD_EIM_D16__GPIO_3_16,
+
+ /* I2C3 */
+ MX6DL_PAD_EIM_D17__I2C3_SCL,
+ MX6DL_PAD_EIM_D18__I2C3_SDA,
+
+ /* USB OC pin */
+ MX6DL_PAD_EIM_D21__USBOH3_USBOTG_OC,
+ /* WLAN_WAKEUP_HOST(Combo module WLAN host wake-up output) */
+ MX6DL_PAD_EIM_D22__GPIO_3_22,
+
+ /* BT_UART2 */
+ MX6DL_PAD_EIM_D26__UART2_TXD,
+ MX6DL_PAD_EIM_D27__UART2_RXD,
+ MX6DL_PAD_EIM_D28__UART2_CTS,
+ MX6DL_PAD_EIM_D29__UART2_RTS,
+
+ /*BT_nRST(Combo module BT reset signal)*/
+ MX6DL_PAD_EIM_DA7__GPIO_3_7,
+
+ /*BT_REG_ON(Combo module BT Internal regulators power enable/disable)*/
+ MX6DL_PAD_EIM_DA9__GPIO_3_9,
+
+ /*WL_REG_ON(Combo module WLAN Internal regulators power enable/disable)*/
+ MX6DL_PAD_EIM_DA10__GPIO_3_10,
+
+ /* GPIO2 */
+ MX6DL_PAD_EIM_A22__GPIO_2_16, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A21__GPIO_2_17, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A20__GPIO_2_18, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A19__GPIO_2_19, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A18__GPIO_2_20, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A17__GPIO_2_21, /* Boot Mode Select */
+ MX6DL_PAD_EIM_RW__GPIO_2_26, /* Boot Mode Select */
+ MX6DL_PAD_EIM_LBA__GPIO_2_27, /* Boot Mode Select */
+ MX6DL_PAD_EIM_EB0__GPIO_2_28, /* Boot Mode Select */
+ MX6DL_PAD_EIM_EB1__GPIO_2_29, /* Boot Mode Select */
+ MX6DL_PAD_EIM_EB2__GPIO_2_30, /* Boot Mode Select */
+ MX6DL_PAD_EIM_EB3__GPIO_2_31, /* Boot Mode Select */
+
+ /* GPIO3 */
+ MX6DL_PAD_EIM_DA0__GPIO_3_0, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA1__GPIO_3_1, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA2__GPIO_3_2, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA3__GPIO_3_3, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA4__GPIO_3_4, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA5__GPIO_3_5, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA6__GPIO_3_6, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA8__GPIO_3_8, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA11__GPIO_3_11, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA12__GPIO_3_12, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA13__GPIO_3_13, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA14__GPIO_3_14, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA15__GPIO_3_15, /* Boot Mode Select */
+
+ /* GPIO5 */
+ MX6DL_PAD_EIM_WAIT__GPIO_5_0, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A24__GPIO_5_4, /* Boot Mode Select */
+
+ /* GPIO6 */
+ MX6DL_PAD_EIM_A23__GPIO_6_6, /* Boot Mode Select */
+
+ /* I2C1 */
+ MX6DL_PAD_CSI0_DAT8__I2C1_SDA,
+ MX6DL_PAD_CSI0_DAT9__I2C1_SCL,
+
+ /* UART1 for debug */
+ MX6DL_PAD_CSI0_DAT10__UART1_TXD,
+ MX6DL_PAD_CSI0_DAT11__UART1_RXD,
+
+ /* SD1 (Combo module WLAN SDIO )*/
+ MX6DL_PAD_SD1_CLK__USDHC1_CLK,
+ MX6DL_PAD_SD1_CMD__USDHC1_CMD,
+ MX6DL_PAD_SD1_DAT0__USDHC1_DAT0,
+ MX6DL_PAD_SD1_DAT1__USDHC1_DAT1,
+ MX6DL_PAD_SD1_DAT2__USDHC1_DAT2,
+ MX6DL_PAD_SD1_DAT3__USDHC1_DAT3,
+
+ /* SD2 (MicroSD SDIO CMD)*/
+ MX6DL_PAD_SD2_CLK__USDHC2_CLK,
+ MX6DL_PAD_SD2_CMD__USDHC2_CMD,
+ MX6DL_PAD_SD2_DAT0__USDHC2_DAT0,
+ MX6DL_PAD_SD2_DAT1__USDHC2_DAT1,
+ MX6DL_PAD_SD2_DAT2__USDHC2_DAT2,
+ MX6DL_PAD_SD2_DAT3__USDHC2_DAT3,
+ /*SD_DET (SD plug-in detect interrupt)*/
+ MX6DL_PAD_GPIO_4__GPIO_1_4,
+
+ /* SD3 (eMMC SDIO)*/
+ MX6DL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6DL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+ MX6DL_PAD_SD3_RST__USDHC3_RST,
+
+ /* UART4 for debug */
+ MX6DL_PAD_KEY_COL0__UART4_TXD,
+ MX6DL_PAD_KEY_ROW0__UART4_RXD,
+
+ /*HDMI CEC communication PIN*/
+ MX6DL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE,
+
+ /* I2C2 */
+ MX6DL_PAD_KEY_COL3__I2C2_SCL, /* GPIO4[12] */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* GPIO4[13] */
+
+ /*DCDC5V_PWREN(5V DCDC BOOST control signal)*/
+ MX6DL_PAD_KEY_COL4__GPIO_4_14,
+
+ /*USB_OTG_PWREN(USB OTG power change control signal)*/
+ MX6DL_PAD_KEY_ROW4__GPIO_4_15,
+
+ /* USBOTG ID pin */
+ MX6DL_PAD_GPIO_1__USBOTG_ID,
+
+ /* I2C3 */
+ MX6DL_PAD_GPIO_5__I2C3_SCL,
+ MX6DL_PAD_GPIO_16__I2C3_SDA,
+
+ /*WDOG(Watch dog output)*/
+ MX6DL_PAD_GPIO_9__GPIO_1_9,
+
+ /*PMIC_nINT(PMIC interrupt signal)*/
+ MX6DL_PAD_NANDF_CS0__GPIO_6_11,
+
+ /*GPIO_nRST(GPIO shutdown control)*/
+ MX6DL_PAD_NANDF_CS1__GPIO_6_14,
+
+ /*PWRKEY_DET(Power key press detection)*/
+ MX6DL_PAD_NANDF_CS3__GPIO_6_16,
+
+ /*CHG_SYS_ON(Charger auto power on control signal)*/
+ MX6DL_PAD_NANDF_D6__GPIO_2_6,
+
+ /*IR_RC*/
+ MX6DL_PAD_SD4_DAT6__GPIO_2_14,
+};
+
+static iomux_v3_cfg_t mx6dl_hdmidongle_rev_b_pads[] = {
+ /* SPI2 for PMIC communication port */
+ MX6DL_PAD_EIM_OE__ECSPI2_MISO,
+ MX6DL_PAD_EIM_RW__ECSPI2_SS0,
+ MX6DL_PAD_EIM_CS0__ECSPI2_SCLK,
+ MX6DL_PAD_EIM_CS1__ECSPI2_MOSI,
+
+ /*USB_OTG_DET(USB OTG cable plug detect) */
+ MX6DL_PAD_EIM_A16__GPIO_2_22,
+ /*WLAN_CLKREQn*/
+ MX6DL_PAD_EIM_A25__GPIO_5_2,
+
+ /* WLAN_ACT */
+ MX6DL_PAD_EIM_D17__GPIO_3_17,
+
+ /*BT_PERI*/
+ MX6DL_PAD_EIM_D18__GPIO_3_18,
+
+ /* USB OC pin */
+ MX6DL_PAD_EIM_D21__USBOH3_USBOTG_OC,
+
+ /* WLAN_WAKEn (PM event, OD, used to reactivate the PCIe main PWR and REF CLK) */
+ MX6DL_PAD_EIM_D22__GPIO_3_22,
+
+
+ /*WLAN_PERSTn (PCIe rst signal, avtive LOW)*/
+ MX6DL_PAD_EIM_DA9__GPIO_3_9,
+
+ /*WLAN_PDn (Externally shutdown RTL8192)*/
+ MX6DL_PAD_EIM_DA10__GPIO_3_10,
+
+ /* GPIO2 */
+ MX6DL_PAD_EIM_A22__GPIO_2_16, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A21__GPIO_2_17, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A20__GPIO_2_18, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A19__GPIO_2_19, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A18__GPIO_2_20, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A17__GPIO_2_21, /* Boot Mode Select */
+ MX6DL_PAD_EIM_RW__GPIO_2_26, /* Boot Mode Select */
+ MX6DL_PAD_EIM_LBA__GPIO_2_27, /* Boot Mode Select */
+ MX6DL_PAD_EIM_EB0__GPIO_2_28, /* Boot Mode Select */
+ MX6DL_PAD_EIM_EB1__GPIO_2_29, /* Boot Mode Select */
+ MX6DL_PAD_EIM_EB2__GPIO_2_30, /* Boot Mode Select */
+ MX6DL_PAD_EIM_EB3__GPIO_2_31, /* Boot Mode Select */
+
+ /* GPIO3 */
+ MX6DL_PAD_EIM_DA0__GPIO_3_0, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA1__GPIO_3_1, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA2__GPIO_3_2, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA3__GPIO_3_3, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA4__GPIO_3_4, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA5__GPIO_3_5, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA6__GPIO_3_6, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA8__GPIO_3_8, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA11__GPIO_3_11, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA12__GPIO_3_12, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA13__GPIO_3_13, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA14__GPIO_3_14, /* Boot Mode Select */
+ MX6DL_PAD_EIM_DA15__GPIO_3_15, /* Boot Mode Select */
+
+ /* GPIO5 */
+ MX6DL_PAD_EIM_WAIT__GPIO_5_0, /* Boot Mode Select */
+ MX6DL_PAD_EIM_A24__GPIO_5_4, /* Boot Mode Select */
+
+ /* GPIO6 */
+ MX6DL_PAD_EIM_A23__GPIO_6_6, /* Boot Mode Select */
+
+ /* SD2 (MicroSD SDIO CMD)*/
+ MX6DL_PAD_SD2_CLK__USDHC2_CLK,
+ MX6DL_PAD_SD2_CMD__USDHC2_CMD,
+ MX6DL_PAD_SD2_DAT0__USDHC2_DAT0,
+ MX6DL_PAD_SD2_DAT1__USDHC2_DAT1,
+ MX6DL_PAD_SD2_DAT2__USDHC2_DAT2,
+ MX6DL_PAD_SD2_DAT3__USDHC2_DAT3,
+ /*SD_DET (SD plug-in detect interrupt)*/
+ MX6DL_PAD_GPIO_4__GPIO_1_4,
+
+ /* SD3 (eMMC SDIO)*/
+ MX6DL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6DL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+ MX6DL_PAD_SD3_RST__USDHC3_RST,
+
+ /* UART4 for debug */
+ MX6DL_PAD_KEY_COL0__UART4_TXD,
+ MX6DL_PAD_KEY_ROW0__UART4_RXD,
+
+ /*SD2_VSELECT (SD2 SDXC power exchange control signal)*/
+ MX6DL_PAD_KEY_ROW1__GPIO_4_9,
+
+ /*HDMI CEC communication PIN*/
+ MX6DL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE,
+
+ /*PWRKEY_DET (Pwr button detection interrupt)*/
+ MX6DL_PAD_ENET_RXD0__GPIO_1_27,
+
+ /*USB_OTG_PWREN(USB OTG power change control signal)*/
+ MX6DL_PAD_KEY_ROW4__GPIO_4_15,
+
+ /* USBOTG ID pin */
+ MX6DL_PAD_GPIO_1__USBOTG_ID,
+
+ /* I2C2 */
+ MX6DL_PAD_KEY_COL3__I2C2_SCL, /* GPIO4[12] */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* GPIO4[13] */
+
+ /* I2C3 */
+ MX6DL_PAD_GPIO_5__I2C3_SCL,
+ MX6DL_PAD_GPIO_16__I2C3_SDA,
+
+ /*WDOG(Watch dog output)*/
+ MX6DL_PAD_GPIO_9__GPIO_1_9,
+
+ /*PMIC_nINT(PMIC interrupt signal)*/
+ MX6DL_PAD_SD4_DAT3__GPIO_2_11,
+
+ /*GPIO_nRST(GPIO shutdown control)*/
+ MX6DL_PAD_SD4_DAT1__GPIO_2_9,
+
+ /*CHG_SYS_ON(Charger auto power on control signal)*/
+ MX6DL_PAD_SD4_DAT6__GPIO_2_14,
+};
+
+/* The GPMI is conflicted with SD3, so init this in the driver. */
+static iomux_v3_cfg_t mx6dl_gpmi_nand[] __initdata = {
+ MX6DL_PAD_NANDF_CLE__RAWNAND_CLE,
+ MX6DL_PAD_NANDF_ALE__RAWNAND_ALE,
+ MX6DL_PAD_NANDF_CS0__RAWNAND_CE0N,
+ MX6DL_PAD_NANDF_CS1__RAWNAND_CE1N,
+ MX6DL_PAD_NANDF_CS2__RAWNAND_CE2N,
+ MX6DL_PAD_NANDF_CS3__RAWNAND_CE3N,
+ MX6DL_PAD_NANDF_RB0__RAWNAND_READY0,
+ MX6DL_PAD_SD4_DAT0__RAWNAND_DQS,
+ MX6DL_PAD_NANDF_D0__RAWNAND_D0,
+ MX6DL_PAD_NANDF_D1__RAWNAND_D1,
+ MX6DL_PAD_NANDF_D2__RAWNAND_D2,
+ MX6DL_PAD_NANDF_D3__RAWNAND_D3,
+ MX6DL_PAD_NANDF_D4__RAWNAND_D4,
+ MX6DL_PAD_NANDF_D5__RAWNAND_D5,
+ MX6DL_PAD_NANDF_D6__RAWNAND_D6,
+ MX6DL_PAD_NANDF_D7__RAWNAND_D7,
+ MX6DL_PAD_SD4_CMD__RAWNAND_RDN,
+ MX6DL_PAD_SD4_CLK__RAWNAND_WRN,
+ MX6DL_PAD_NANDF_WP_B__RAWNAND_RESETN,
+};
+
+static iomux_v3_cfg_t mx6dl_hdmidongle_hdmi_ddc_pads[] = {
+ MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6dl_hdmidongle_i2c2_pads[] = {
+ MX6DL_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
+
+#endif
diff --git a/arch/arm/mach-mx6/board-mx6dl_sabresd.h b/arch/arm/mach-mx6/board-mx6dl_sabresd.h
new file mode 100644
index 00000000..4e2d322f
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6dl_sabresd.h
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2012-2013 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.
+ */
+
+#ifndef _BOARD_MX6DL_SABRESD_H
+#define _BOARD_MX6DL_SABRESD_H
+#include <mach/iomux-mx6dl.h>
+
+static iomux_v3_cfg_t mx6dl_sabresd_pads[] = {
+ /* AUDMUX */
+ MX6DL_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC,
+ MX6DL_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD,
+ MX6DL_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS,
+ MX6DL_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD,
+
+ /* CSPI */
+ MX6DL_PAD_KEY_COL0__ECSPI1_SCLK,
+ MX6DL_PAD_KEY_ROW0__ECSPI1_MOSI,
+ MX6DL_PAD_KEY_COL1__ECSPI1_MISO,
+ MX6DL_PAD_KEY_ROW1__GPIO_4_9,
+
+ /* ENET */
+ MX6DL_PAD_ENET_MDIO__ENET_MDIO,
+ MX6DL_PAD_ENET_MDC__ENET_MDC,
+ MX6DL_PAD_RGMII_TXC__ENET_RGMII_TXC,
+ MX6DL_PAD_RGMII_TD0__ENET_RGMII_TD0,
+ MX6DL_PAD_RGMII_TD1__ENET_RGMII_TD1,
+ MX6DL_PAD_RGMII_TD2__ENET_RGMII_TD2,
+ MX6DL_PAD_RGMII_TD3__ENET_RGMII_TD3,
+ MX6DL_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL,
+ MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK,
+ MX6DL_PAD_RGMII_RXC__ENET_RGMII_RXC,
+ MX6DL_PAD_RGMII_RD0__ENET_RGMII_RD0,
+ MX6DL_PAD_RGMII_RD1__ENET_RGMII_RD1,
+ MX6DL_PAD_RGMII_RD2__ENET_RGMII_RD2,
+ MX6DL_PAD_RGMII_RD3__ENET_RGMII_RD3,
+ MX6DL_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL,
+ /* RGMII_nRST */
+ MX6DL_PAD_ENET_CRS_DV__GPIO_1_25,
+ /* IEEE 1588 clock */
+ MX6DL_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT,
+ /* RGMII Interrupt */
+ MX6DL_PAD_ENET_RXD1__GPIO_1_26,
+
+ /* I2C1 */
+ MX6DL_PAD_CSI0_DAT8__I2C1_SDA,
+ MX6DL_PAD_CSI0_DAT9__I2C1_SCL,
+
+ /* I2C2 */
+ MX6DL_PAD_KEY_COL3__I2C2_SCL,
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA,
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ MX6DL_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1,
+#else
+ /* I2C3 */
+ MX6DL_PAD_GPIO_3__I2C3_SCL,
+ MX6DL_PAD_GPIO_6__I2C3_SDA,
+#endif
+
+ /* DISPLAY */
+ MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6DL_PAD_DI0_PIN15__IPU1_DI0_PIN15, /* DE */
+ MX6DL_PAD_DI0_PIN2__IPU1_DI0_PIN2, /* HSync */
+ MX6DL_PAD_DI0_PIN3__IPU1_DI0_PIN3, /* VSync */
+ MX6DL_PAD_DI0_PIN4__IPU1_DI0_PIN4, /* Contrast */
+ MX6DL_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
+ MX6DL_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
+ MX6DL_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
+ MX6DL_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
+ MX6DL_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
+ MX6DL_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
+ MX6DL_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
+ MX6DL_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
+ MX6DL_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
+ MX6DL_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
+ MX6DL_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
+ MX6DL_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
+ MX6DL_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
+ MX6DL_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
+ MX6DL_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
+ MX6DL_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
+ MX6DL_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
+ MX6DL_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
+ MX6DL_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
+ MX6DL_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
+ MX6DL_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20,
+ MX6DL_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
+ MX6DL_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22,
+ MX6DL_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23,
+
+ /* FlexCAN */
+ MX6DL_PAD_GPIO_7__CAN1_TXCAN,
+ MX6DL_PAD_GPIO_8__CAN1_RXCAN,
+ /* CAN1_STBY */
+ MX6DL_PAD_GPIO_19__GPIO_4_5,
+
+ /* UART1 for debug */
+ MX6DL_PAD_CSI0_DAT10__UART1_TXD,
+ MX6DL_PAD_CSI0_DAT11__UART1_RXD,
+
+ /* UART3 for gps */
+ MX6DL_PAD_EIM_D24__UART3_TXD,
+ MX6DL_PAD_EIM_D25__UART3_RXD,
+
+ /* USB */
+ MX6DL_PAD_ENET_RX_ER__ANATOP_USBOTG_ID,
+ MX6DL_PAD_EIM_D21__USBOH3_USBOTG_OC,
+ /* USB_OTG_PWR_EN */
+ MX6DL_PAD_EIM_D22__GPIO_3_22,
+ MX6DL_PAD_EIM_D30__USBOH3_USBH1_OC,
+ /*USB_H1 PWR EN*/
+ MX6DL_PAD_ENET_TXD1__GPIO_1_29,
+
+ /* USDHC2 */
+ MX6DL_PAD_SD2_CLK__USDHC2_CLK,
+ MX6DL_PAD_SD2_CMD__USDHC2_CMD,
+ MX6DL_PAD_SD2_DAT0__USDHC2_DAT0,
+ MX6DL_PAD_SD2_DAT1__USDHC2_DAT1,
+ MX6DL_PAD_SD2_DAT2__USDHC2_DAT2,
+ MX6DL_PAD_SD2_DAT3__USDHC2_DAT3,
+ MX6DL_PAD_NANDF_D4__USDHC2_DAT4,
+ MX6DL_PAD_NANDF_D5__USDHC2_DAT5,
+ MX6DL_PAD_NANDF_D6__USDHC2_DAT6,
+ MX6DL_PAD_NANDF_D7__USDHC2_DAT7,
+ /* SD2_CD */
+ MX6DL_PAD_NANDF_D2__GPIO_2_2,
+ /* SD2_WP */
+ MX6DL_PAD_NANDF_D3__GPIO_2_3,
+
+ /* USDHC3 */
+ MX6DL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6DL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+ /* SD3_CD */
+ MX6DL_PAD_NANDF_D0__GPIO_2_0,
+ /* SD3_WP */
+ MX6DL_PAD_NANDF_D1__GPIO_2_1,
+
+ /* USDHC4 */
+ MX6DL_PAD_SD4_CLK__USDHC4_CLK_50MHZ,
+ MX6DL_PAD_SD4_CMD__USDHC4_CMD_50MHZ,
+ MX6DL_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ,
+ MX6DL_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ,
+ MX6DL_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ,
+ MX6DL_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ,
+ MX6DL_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ,
+ MX6DL_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ,
+ MX6DL_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ,
+ MX6DL_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ,
+
+ /* HDMI_CEC_IN*/
+ MX6DL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE,
+
+ /* CCM - Audio, Camera clock */
+ MX6DL_PAD_GPIO_0__CCM_CLKO,
+ /* MICROPHONE_DET */
+ MX6DL_PAD_GPIO_9__GPIO_1_9,
+ /* CODEC_PWR_EN */
+ MX6DL_PAD_KEY_COL2__GPIO_4_10,
+ /* HEADPHONE_DET */
+ MX6DL_PAD_SD3_RST__GPIO_7_8,
+
+ /* GPS_RESET_B */
+ MX6DL_PAD_EIM_EB0__GPIO_2_28,
+ /* GPS_PWREN */
+ MX6DL_PAD_EIM_DA0__GPIO_3_0,
+ /* GPS AUX_3V15_EN*/
+ MX6DL_PAD_NANDF_WP_B__GPIO_6_9,
+ /* GPS_PPS */
+ MX6DL_PAD_EIM_D18__GPIO_3_18,
+
+ /* DISP0_RST_B */
+ MX6DL_PAD_EIM_DA8__GPIO_3_8,
+ /* DI0_D0_CS */
+ MX6DL_PAD_EIM_WAIT__GPIO_5_0,
+ /* DI1_D0_CS */
+ MX6DL_PAD_EIM_BCLK__GPIO_6_31,
+ /* DISP_PWM */
+ MX6DL_PAD_SD1_DAT3__PWM1_PWMO,
+ /* DISP0 power enable */
+ MX6DL_PAD_ENET_TXD0__GPIO_1_30,
+ /* DISP0_RD */
+ MX6DL_PAD_EIM_D28__GPIO_3_28,
+ /* DISP_RST_B */
+ MX6DL_PAD_NANDF_CS0__GPIO_6_11,
+ /* DISP_PWR_EN */
+ MX6DL_PAD_NANDF_CS1__GPIO_6_14,
+ /* CABC_EN0 */
+ MX6DL_PAD_NANDF_CS2__GPIO_6_15,
+ /* CABC_EN1 */
+ MX6DL_PAD_NANDF_CS3__GPIO_6_16,
+ /* DISP0_WR */
+ MX6DL_PAD_NANDF_WP_B__GPIO_6_9,
+
+ /* ALS INT */
+ MX6DL_PAD_EIM_DA9__GPIO_3_9,
+ /* BARO_INT */
+ MX6DL_PAD_EIM_DA15__GPIO_3_15,
+
+ /* SW4 , SW5 & SW1 */
+ /* Volume Up */
+ MX6DL_PAD_GPIO_4__GPIO_1_4,
+ /* Volume Down */
+ MX6DL_PAD_GPIO_5__GPIO_1_5,
+ /* power off */
+ MX6DL_PAD_EIM_D29__GPIO_3_29,
+
+ /* CAP_TCH_INT1 */
+ MX6DL_PAD_NANDF_CLE__GPIO_6_7,
+
+ /* CAP_TCH_INT0 */
+ MX6DL_PAD_NANDF_ALE__GPIO_6_8,
+
+ /* AUX_5V Enable */
+ MX6DL_PAD_NANDF_RB0__GPIO_6_10,
+
+ /* PCIE_RST_B */
+ MX6DL_PAD_GPIO_17__GPIO_7_12,
+ /* PCIE_PWR_EN */
+ MX6DL_PAD_EIM_D19__GPIO_3_19,
+ /* PCIE_WAKE_B */
+ MX6DL_PAD_CSI0_DATA_EN__GPIO_5_20,
+ /* PCIE_DIS_B */
+ MX6DL_PAD_KEY_COL4__GPIO_4_14,
+
+ /* PMIC_INT_B */
+ MX6DL_PAD_GPIO_18__GPIO_7_13,
+
+ /* Charge */
+ MX6DL_PAD_EIM_A25__GPIO_5_2, /* FLT_1_B */
+ MX6DL_PAD_EIM_D23__GPIO_3_23, /* CHG_1_B */
+ MX6DL_PAD_EIM_DA13__GPIO_3_13, /* CHG_2_B */
+ MX6DL_PAD_EIM_DA14__GPIO_3_14, /* FLT_2_B */
+
+ MX6DL_PAD_ENET_RXD0__GPIO_1_27, /* UOK_B */
+ MX6DL_PAD_EIM_CS1__GPIO_2_24, /* DOK_B */
+
+ /* TS_INT - MAX11801 */
+ MX6DL_PAD_EIM_D26__GPIO_3_26,
+ /* eCompass int */
+ MX6DL_PAD_EIM_D16__GPIO_3_16,
+
+ /* SENSOR_PWR_EN */
+ MX6DL_PAD_EIM_EB3__GPIO_2_31,
+ /* ACCL_INT_INT */
+ MX6DL_PAD_SD1_CMD__GPIO_1_18,
+
+ /*WDOG_B to reset pmic*/
+ MX6DL_PAD_GPIO_1__WDOG2_WDOG_B,
+ /* USR_DEF_RED_LED */
+ MX6DL_PAD_GPIO_2__GPIO_1_2,
+};
+
+static iomux_v3_cfg_t mx6dl_sabresd_csi0_sensor_pads[] = {
+ /* IPU1 Camera */
+ MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6DL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN,
+ MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+ MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+
+ MX6DL_PAD_GPIO_0__CCM_CLKO, /* camera clk */
+
+ MX6DL_PAD_SD1_DAT0__GPIO_1_16, /* camera PWDN */
+ MX6DL_PAD_SD1_DAT1__GPIO_1_17, /* camera RESET */
+};
+
+static iomux_v3_cfg_t mx6dl_sabresd_mipi_sensor_pads[] = {
+ MX6DL_PAD_GPIO_0__CCM_CLKO, /* camera clk */
+
+ MX6DL_PAD_SD1_DAT2__GPIO_1_19, /* camera PWDN */
+ MX6DL_PAD_SD1_CLK__GPIO_1_20, /* camera RESET */
+};
+
+static iomux_v3_cfg_t mx6dl_sabresd_epdc_enable_pads[] = {
+ /* EPDC */
+ MX6DL_PAD_EIM_A16__EPDC_SDDO_0,
+ MX6DL_PAD_EIM_DA10__EPDC_SDDO_1,
+ MX6DL_PAD_EIM_DA12__EPDC_SDDO_2,
+ MX6DL_PAD_EIM_DA11__EPDC_SDDO_3,
+ MX6DL_PAD_EIM_LBA__EPDC_SDDO_4,
+ MX6DL_PAD_EIM_EB2__EPDC_SDDO_5,
+ MX6DL_PAD_EIM_CS0__EPDC_SDDO_6,
+ MX6DL_PAD_EIM_RW__EPDC_SDDO_7,
+ MX6DL_PAD_EIM_A21__EPDC_GDCLK,
+ MX6DL_PAD_EIM_A22__EPDC_GDSP,
+ MX6DL_PAD_EIM_A23__EPDC_GDOE,
+ MX6DL_PAD_EIM_A24__EPDC_GDRL,
+ MX6DL_PAD_EIM_D31__EPDC_SDCLK,
+ MX6DL_PAD_EIM_D27__EPDC_SDOE,
+ MX6DL_PAD_EIM_DA1__EPDC_SDLE,
+ MX6DL_PAD_EIM_EB1__EPDC_SDSHR,
+ MX6DL_PAD_EIM_DA2__EPDC_BDR_0,
+ MX6DL_PAD_EIM_DA4__EPDC_SDCE_0,
+ MX6DL_PAD_EIM_DA5__EPDC_SDCE_1,
+ MX6DL_PAD_EIM_DA6__EPDC_SDCE_2,
+
+ /* EPD PMIC (Maxim 17135) pins */
+ MX6DL_PAD_EIM_A17__GPIO_2_21, /* EPDC_PWRSTAT */
+ MX6DL_PAD_EIM_D17__GPIO_3_17, /* EPDC_VCOM0 */
+ MX6DL_PAD_EIM_A18__GPIO_2_20, /* EPDC_PWRCTRL0 */
+ MX6DL_PAD_EIM_D20__GPIO_3_20, /* EPDC_PMIC_WAKEUP */
+ /*
+ * Depopulate R121, R123, R133, R138, R139,
+ * R167, R168, and R627 when using E-BOOK
+ * Card in 16-bit Data Mode. Meanwhile, comments
+ * the conflict PIN configurations in above tables
+ */
+ /*
+ MX6DL_PAD_EIM_CS1__EPDC_SDDO_8,
+ MX6DL_PAD_EIM_DA15__EPDC_SDDO_9,
+ MX6DL_PAD_EIM_D16__EPDC_SDDO_10,
+ MX6DL_PAD_EIM_D23__EPDC_SDDO_11
+ MX6DL_PAD_EIM_D19__EPDC_SDDO_12,
+ MX6DL_PAD_EIM_DA13__EPDC_SDDO_13,
+ MX6DL_PAD_EIM_DA14__EPDC_SDDO_14,
+ MX6DL_PAD_EIM_A25__EPDC_SDDO_15,
+ */
+};
+
+static iomux_v3_cfg_t mx6dl_sabresd_epdc_disable_pads[] = {
+ /* EPDC */
+ MX6DL_PAD_EIM_A16__GPIO_2_22,
+ MX6DL_PAD_EIM_DA10__GPIO_3_10,
+ MX6DL_PAD_EIM_DA12__GPIO_3_12,
+ MX6DL_PAD_EIM_DA11__GPIO_3_11,
+ MX6DL_PAD_EIM_LBA__GPIO_2_27,
+ MX6DL_PAD_EIM_EB2__GPIO_2_30,
+ MX6DL_PAD_EIM_CS0__GPIO_2_23,
+ MX6DL_PAD_EIM_RW__GPIO_2_26,
+ MX6DL_PAD_EIM_A21__GPIO_2_17,
+ MX6DL_PAD_EIM_A22__GPIO_2_16,
+ MX6DL_PAD_EIM_A23__GPIO_6_6,
+ MX6DL_PAD_EIM_A24__GPIO_5_4,
+ MX6DL_PAD_EIM_D31__GPIO_3_31,
+ MX6DL_PAD_EIM_D27__GPIO_3_27,
+ MX6DL_PAD_EIM_DA1__GPIO_3_1,
+ MX6DL_PAD_EIM_EB1__GPIO_2_29,
+ MX6DL_PAD_EIM_DA2__GPIO_3_2,
+ MX6DL_PAD_EIM_DA4__GPIO_3_4,
+ MX6DL_PAD_EIM_DA5__GPIO_3_5,
+ MX6DL_PAD_EIM_DA6__GPIO_3_6,
+
+ /*
+ * Depopulate R121, R123, R133, R138, R139,
+ * R167, R168, and R627 when using E-BOOK
+ * Card in 16-bit Data Mode. Meanwhile, comments
+ * the conflict PIN configurations in above tables
+ */
+ /*
+ MX6DL_PAD_EIM_CS1__EPDC_SDDO_8,
+ MX6DL_PAD_EIM_DA15__EPDC_SDDO_9,
+ MX6DL_PAD_EIM_D16__EPDC_SDDO_10,
+ MX6DL_PAD_EIM_D23__EPDC_SDDO_11
+ MX6DL_PAD_EIM_D19__EPDC_SDDO_12,
+ MX6DL_PAD_EIM_DA13__EPDC_SDDO_13,
+ MX6DL_PAD_EIM_DA14__EPDC_SDDO_14,
+ MX6DL_PAD_EIM_A25__EPDC_SDDO_15,
+ */
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_elan_pads[] = {
+ MX6DL_PAD_EIM_A20__GPIO_2_18,
+ MX6DL_PAD_EIM_DA8__GPIO_3_8,
+ MX6DL_PAD_EIM_D28__GPIO_3_28,
+};
+
+static iomux_v3_cfg_t mx6dl_sabresd_hdmi_ddc_pads[] = {
+ MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6dl_sabresd_i2c2_pads[] = {
+ MX6DL_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
+#endif
diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c
new file mode 100644
index 00000000..250ef90a
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_arm2.c
@@ -0,0 +1,2303 @@
+/*
+ * Copyright (C) 2011-2012 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 <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/ion.h>
+#include <linux/etherdevice.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max17135.h>
+#include <sound/pcm.h>
+#include <linux/mxc_asrc.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/memory.h>
+#include <mach/imx-uart.h>
+#include <mach/viv_gpu.h>
+#include <mach/ahci_sata.h>
+#include <mach/ipu-v3.h>
+#include <mach/mxc_hdmi.h>
+#include <mach/mxc_asrc.h>
+#include <mach/mipi_dsi.h>
+#include <mach/mipi_csi2.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "usb.h"
+#include "devices-imx6q.h"
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "board-mx6q_arm2.h"
+#include "board-mx6dl_arm2.h"
+
+/* GPIO PIN, sort by PORT/BIT */
+#define MX6_ARM2_LDB_BACKLIGHT IMX_GPIO_NR(1, 9)
+#define MX6_ARM2_ECSPI1_CS0 IMX_GPIO_NR(2, 30)
+#define MX6_ARM2_ECSPI1_CS1 IMX_GPIO_NR(3, 19)
+#define MX6_ARM2_USB_OTG_PWR IMX_GPIO_NR(3, 22)
+#define MX6_ARM2_DISP0_PWR IMX_GPIO_NR(3, 24)
+#define MX6_ARM2_DISP0_I2C_EN IMX_GPIO_NR(3, 28)
+#define MX6_ARM2_CAP_TCH_INT IMX_GPIO_NR(3, 31)
+#define MX6_ARM2_DISP0_DET_INT IMX_GPIO_NR(3, 31)
+#define MX6_ARM2_CSI0_RST IMX_GPIO_NR(4, 5)
+#define MX6_ARM2_DISP0_RESET IMX_GPIO_NR(5, 0)
+#define MX6_ARM2_CSI0_PWN IMX_GPIO_NR(5, 23)
+#define MX6_ARM2_CAN2_EN IMX_GPIO_NR(5, 24)
+#define MX6_ARM2_CSI0_RST_TVIN IMX_GPIO_NR(5, 25)
+#define MX6_ARM2_SD3_CD IMX_GPIO_NR(6, 11)
+#define MX6_ARM2_SD3_WP IMX_GPIO_NR(6, 14)
+#define MX6_ARM2_CAN1_STBY IMX_GPIO_NR(7, 12)
+#define MX6_ARM2_CAN1_EN IMX_GPIO_NR(7, 13)
+#define MX6_ARM2_MAX7310_1_BASE_ADDR IMX_GPIO_NR(8, 0)
+#define MX6_ARM2_MAX7310_2_BASE_ADDR IMX_GPIO_NR(8, 8)
+#define MX6DL_ARM2_EPDC_SDDO_0 IMX_GPIO_NR(2, 22)
+#define MX6DL_ARM2_EPDC_SDDO_1 IMX_GPIO_NR(3, 10)
+#define MX6DL_ARM2_EPDC_SDDO_2 IMX_GPIO_NR(3, 12)
+#define MX6DL_ARM2_EPDC_SDDO_3 IMX_GPIO_NR(3, 11)
+#define MX6DL_ARM2_EPDC_SDDO_4 IMX_GPIO_NR(2, 27)
+#define MX6DL_ARM2_EPDC_SDDO_5 IMX_GPIO_NR(2, 30)
+#define MX6DL_ARM2_EPDC_SDDO_6 IMX_GPIO_NR(2, 23)
+#define MX6DL_ARM2_EPDC_SDDO_7 IMX_GPIO_NR(2, 26)
+#define MX6DL_ARM2_EPDC_SDDO_8 IMX_GPIO_NR(2, 24)
+#define MX6DL_ARM2_EPDC_SDDO_9 IMX_GPIO_NR(3, 15)
+#define MX6DL_ARM2_EPDC_SDDO_10 IMX_GPIO_NR(3, 16)
+#define MX6DL_ARM2_EPDC_SDDO_11 IMX_GPIO_NR(3, 23)
+#define MX6DL_ARM2_EPDC_SDDO_12 IMX_GPIO_NR(3, 19)
+#define MX6DL_ARM2_EPDC_SDDO_13 IMX_GPIO_NR(3, 13)
+#define MX6DL_ARM2_EPDC_SDDO_14 IMX_GPIO_NR(3, 14)
+#define MX6DL_ARM2_EPDC_SDDO_15 IMX_GPIO_NR(5, 2)
+#define MX6DL_ARM2_EPDC_GDCLK IMX_GPIO_NR(2, 17)
+#define MX6DL_ARM2_EPDC_GDSP IMX_GPIO_NR(2, 16)
+#define MX6DL_ARM2_EPDC_GDOE IMX_GPIO_NR(6, 6)
+#define MX6DL_ARM2_EPDC_GDRL IMX_GPIO_NR(5, 4)
+#define MX6DL_ARM2_EPDC_SDCLK IMX_GPIO_NR(3, 31)
+#define MX6DL_ARM2_EPDC_SDOEZ IMX_GPIO_NR(3, 30)
+#define MX6DL_ARM2_EPDC_SDOED IMX_GPIO_NR(3, 26)
+#define MX6DL_ARM2_EPDC_SDOE IMX_GPIO_NR(3, 27)
+#define MX6DL_ARM2_EPDC_SDLE IMX_GPIO_NR(3, 1)
+#define MX6DL_ARM2_EPDC_SDCLKN IMX_GPIO_NR(3, 0)
+#define MX6DL_ARM2_EPDC_SDSHR IMX_GPIO_NR(2, 29)
+#define MX6DL_ARM2_EPDC_PWRCOM IMX_GPIO_NR(2, 28)
+#define MX6DL_ARM2_EPDC_PWRSTAT IMX_GPIO_NR(2, 21)
+#define MX6DL_ARM2_EPDC_PWRCTRL0 IMX_GPIO_NR(2, 20)
+#define MX6DL_ARM2_EPDC_PWRCTRL1 IMX_GPIO_NR(2, 19)
+#define MX6DL_ARM2_EPDC_PWRCTRL2 IMX_GPIO_NR(2, 18)
+#define MX6DL_ARM2_EPDC_PWRCTRL3 IMX_GPIO_NR(3, 28)
+#define MX6DL_ARM2_EPDC_BDR0 IMX_GPIO_NR(3, 2)
+#define MX6DL_ARM2_EPDC_BDR1 IMX_GPIO_NR(3, 3)
+#define MX6DL_ARM2_EPDC_SDCE0 IMX_GPIO_NR(3, 4)
+#define MX6DL_ARM2_EPDC_SDCE1 IMX_GPIO_NR(3, 5)
+#define MX6DL_ARM2_EPDC_SDCE2 IMX_GPIO_NR(3, 6)
+#define MX6DL_ARM2_EPDC_SDCE3 IMX_GPIO_NR(3, 7)
+#define MX6DL_ARM2_EPDC_SDCE4 IMX_GPIO_NR(3, 8)
+#define MX6DL_ARM2_EPDC_SDCE5 IMX_GPIO_NR(3, 9)
+#define MX6DL_ARM2_EPDC_PMIC_WAKE IMX_GPIO_NR(2, 31)
+#define MX6DL_ARM2_EPDC_PMIC_INT IMX_GPIO_NR(2, 25)
+#define MX6DL_ARM2_EPDC_VCOM IMX_GPIO_NR(3, 17)
+
+#define MX6_ARM2_IO_EXP_GPIO1(x) (MX6_ARM2_MAX7310_1_BASE_ADDR + (x))
+#define MX6_ARM2_IO_EXP_GPIO2(x) (MX6_ARM2_MAX7310_2_BASE_ADDR + (x))
+
+#define MX6_ARM2_PCIE_PWR_EN MX6_ARM2_IO_EXP_GPIO1(2)
+#define MX6_ARM2_PCIE_RESET MX6_ARM2_IO_EXP_GPIO2(2)
+
+#define MX6_ARM2_CAN2_STBY MX6_ARM2_IO_EXP_GPIO2(1)
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+#define MX6_ENET_IRQ IMX_GPIO_NR(1, 6)
+#define IOMUX_OBSRV_MUX1_OFFSET 0x3c
+#define OBSRV_MUX1_MASK 0x3f
+#define OBSRV_MUX1_ENET_IRQ 0x9
+#endif
+
+#define BMCR_PDOWN 0x0800 /* PHY Powerdown */
+
+void __init early_console_setup(unsigned long base, struct clk *clk);
+static struct clk *sata_clk;
+static int esai_record;
+static int sgtl5000_en;
+static int spdif_en;
+static int flexcan_en;
+static int disable_mipi_dsi;
+
+extern struct regulator *(*get_cpu_regulator)(void);
+extern void (*put_cpu_regulator)(void);
+extern char *gp_reg_id;
+extern char *soc_reg_id;
+extern char *pu_reg_id;
+extern int epdc_enabled;
+extern void mx6_cpu_regulator_init(void);
+static int max17135_regulator_init(struct max17135 *max17135);
+
+enum sd_pad_mode {
+ SD_PAD_MODE_LOW_SPEED,
+ SD_PAD_MODE_MED_SPEED,
+ SD_PAD_MODE_HIGH_SPEED,
+};
+
+static int plt_sd_pad_change(unsigned int index, int clock)
+{
+ /* LOW speed is the default state of SD pads */
+ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
+
+ iomux_v3_cfg_t *sd_pads_200mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_100mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_50mhz = NULL;
+
+ u32 sd_pads_200mhz_cnt;
+ u32 sd_pads_100mhz_cnt;
+ u32 sd_pads_50mhz_cnt;
+
+ switch (index) {
+ case 2:
+ if (cpu_is_mx6q()) {
+ sd_pads_200mhz = mx6q_sd3_200mhz;
+ sd_pads_100mhz = mx6q_sd3_100mhz;
+ sd_pads_50mhz = mx6q_sd3_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
+ } else if (cpu_is_mx6dl()) {
+ sd_pads_200mhz = mx6dl_sd3_200mhz;
+ sd_pads_100mhz = mx6dl_sd3_100mhz;
+ sd_pads_50mhz = mx6dl_sd3_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd3_50mhz);
+ }
+ break;
+ case 3:
+ if (cpu_is_mx6q()) {
+ sd_pads_200mhz = mx6q_sd4_200mhz;
+ sd_pads_100mhz = mx6q_sd4_100mhz;
+ sd_pads_50mhz = mx6q_sd4_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd4_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd4_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd4_50mhz);
+ } else if (cpu_is_mx6dl()) {
+ sd_pads_200mhz = mx6dl_sd4_200mhz;
+ sd_pads_100mhz = mx6dl_sd4_100mhz;
+ sd_pads_50mhz = mx6dl_sd4_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd4_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd4_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd4_50mhz);
+ }
+ break;
+ default:
+ printk(KERN_ERR "no such SD host controller index %d\n", index);
+ return -EINVAL;
+ }
+
+ if (clock > 100000000) {
+ if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_200mhz);
+ pad_mode = SD_PAD_MODE_HIGH_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
+ sd_pads_200mhz_cnt);
+ } else if (clock > 52000000) {
+ if (pad_mode == SD_PAD_MODE_MED_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_100mhz);
+ pad_mode = SD_PAD_MODE_MED_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
+ sd_pads_100mhz_cnt);
+ } else {
+ if (pad_mode == SD_PAD_MODE_LOW_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_50mhz);
+ pad_mode = SD_PAD_MODE_LOW_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
+ sd_pads_50mhz_cnt);
+ }
+}
+
+static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = {
+ .cd_gpio = MX6_ARM2_SD3_CD,
+ .wp_gpio = MX6_ARM2_SD3_WP,
+ .support_18v = 1,
+ .support_8bit = 1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+/* No card detect signal for SD4 on ARM2 board*/
+static const struct esdhc_platform_data mx6_arm2_sd4_data __initconst = {
+ .always_present = 1,
+ .support_8bit = 1,
+ .keep_power_at_suspend = 1,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+static int __init gpmi_nand_platform_init(void)
+{
+ iomux_v3_cfg_t *nand_pads = NULL;
+ u32 nand_pads_cnt;
+
+ if (cpu_is_mx6q()) {
+ nand_pads = mx6q_gpmi_nand;
+ nand_pads_cnt = ARRAY_SIZE(mx6dl_gpmi_nand);
+ } else if (cpu_is_mx6dl()) {
+ nand_pads = mx6dl_gpmi_nand;
+ nand_pads_cnt = ARRAY_SIZE(mx6dl_gpmi_nand);
+
+ }
+ BUG_ON(!nand_pads);
+ return mxc_iomux_v3_setup_multiple_pads(nand_pads, nand_pads_cnt);
+}
+
+static struct gpmi_nand_platform_data
+mx6_gpmi_nand_platform_data __initdata = {
+ .platform_init = gpmi_nand_platform_init,
+ .min_prop_delay_in_ns = 5,
+ .max_prop_delay_in_ns = 9,
+ .max_chip_count = 1,
+ .enable_bbt = 1,
+ .enable_ddr = 0,
+};
+
+static int __init board_support_onfi_nand(char *p)
+{
+ mx6_gpmi_nand_platform_data.enable_ddr = 1;
+ return 0;
+}
+
+early_param("onfi_support", board_support_onfi_nand);
+
+static const struct anatop_thermal_platform_data
+ mx6_arm2_anatop_thermal_data __initconst = {
+ .name = "anatop_thermal",
+};
+
+static const struct imxuart_platform_data mx6_arm2_uart1_data __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS | IMXUART_USE_DCEDTE | IMXUART_SDMA,
+ .dma_req_rx = MX6Q_DMA_REQ_UART2_RX,
+ .dma_req_tx = MX6Q_DMA_REQ_UART2_TX,
+};
+
+static inline void mx6_arm2_init_uart(void)
+{
+ imx6q_add_imx_uart(3, NULL);
+ imx6q_add_imx_uart(1, &mx6_arm2_uart1_data);
+}
+
+static int mx6_arm2_fec_phy_init(struct phy_device *phydev)
+{
+ unsigned short val;
+
+ /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
+ phy_write(phydev, 0xd, 0x7);
+ phy_write(phydev, 0xe, 0x8016);
+ phy_write(phydev, 0xd, 0x4007);
+ val = phy_read(phydev, 0xe);
+
+ val &= 0xffe3;
+ val |= 0x18;
+ phy_write(phydev, 0xe, val);
+
+ /* introduce tx clock delay */
+ phy_write(phydev, 0x1d, 0x5);
+ val = phy_read(phydev, 0x1e);
+ val |= 0x0100;
+ phy_write(phydev, 0x1e, val);
+
+ /*check phy power*/
+ val = phy_read(phydev, 0x0);
+ if (val & BMCR_PDOWN)
+ phy_write(phydev, 0x0, (val & ~BMCR_PDOWN));
+ return 0;
+}
+
+static int mx6_arm2_fec_power_hibernate(struct phy_device *phydev)
+{
+ unsigned short val;
+
+ /*set AR8031 debug reg 0xb to hibernate power*/
+ phy_write(phydev, 0x1d, 0xb);
+ val = phy_read(phydev, 0x1e);
+
+ val |= 0x8000;
+ phy_write(phydev, 0x1e, val);
+
+ return 0;
+}
+
+static struct fec_platform_data fec_data __initdata = {
+ .init = mx6_arm2_fec_phy_init,
+ .power_hibernate = mx6_arm2_fec_power_hibernate,
+ .phy = PHY_INTERFACE_MODE_RGMII,
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ .gpio_irq = MX6_ENET_IRQ,
+#endif
+};
+
+static int mx6_arm2_spi_cs[] = {
+ MX6_ARM2_ECSPI1_CS0,
+ MX6_ARM2_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx6_arm2_spi_data __initconst = {
+ .chipselect = mx6_arm2_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx6_arm2_spi_cs),
+};
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition m25p32_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x00100000,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data m25p32_spi_flash_data = {
+ .name = "m25p32",
+ .parts = m25p32_partitions,
+ .nr_parts = ARRAY_SIZE(m25p32_partitions),
+ .type = "m25p32",
+};
+#endif
+
+static struct spi_board_info m25p32_spi0_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80)
+ {
+ /* The modalias must be the same as spi device driver name */
+ .modalias = "m25p80",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .platform_data = &m25p32_spi_flash_data,
+ },
+#endif
+};
+
+static void spi_device_init(void)
+{
+ spi_register_board_info(m25p32_spi0_board_info,
+ ARRAY_SIZE(m25p32_spi0_board_info));
+}
+
+static int max7310_1_setup(struct i2c_client *client,
+ unsigned gpio_base, unsigned ngpio,
+ void *context)
+{
+ int max7310_gpio_value[] = { 0, 1, 0, 1, 0, 0, 0, 0 };
+
+ int n;
+
+ for (n = 0; n < ARRAY_SIZE(max7310_gpio_value); ++n) {
+ gpio_request(gpio_base + n, "MAX7310 1 GPIO Expander");
+ if (max7310_gpio_value[n] < 0)
+ gpio_direction_input(gpio_base + n);
+ else
+ gpio_direction_output(gpio_base + n,
+ max7310_gpio_value[n]);
+ gpio_export(gpio_base + n, 0);
+ }
+
+ return 0;
+}
+
+static struct pca953x_platform_data max7310_platdata = {
+ .gpio_base = MX6_ARM2_MAX7310_1_BASE_ADDR,
+ .invert = 0,
+ .setup = max7310_1_setup,
+};
+
+static int max7310_u48_setup(struct i2c_client *client,
+ unsigned gpio_base, unsigned ngpio,
+ void *context)
+{
+ int max7310_gpio_value[] = { 1, 1, 1, 1, 0, 1, 0, 0 };
+
+ int n;
+
+ for (n = 0; n < ARRAY_SIZE(max7310_gpio_value); ++n) {
+ gpio_request(gpio_base + n, "MAX7310 U48 GPIO Expander");
+ if (max7310_gpio_value[n] < 0)
+ gpio_direction_input(gpio_base + n);
+ else
+ gpio_direction_output(gpio_base + n,
+ max7310_gpio_value[n]);
+ gpio_export(gpio_base + n, 0);
+ }
+
+ return 0;
+}
+
+static struct pca953x_platform_data max7310_u48_platdata = {
+ .gpio_base = MX6_ARM2_MAX7310_2_BASE_ADDR,
+ .invert = 0,
+ .setup = max7310_u48_setup,
+};
+
+static void ddc_dvi_init(void)
+{
+ /* enable DVI I2C */
+ gpio_set_value(MX6_ARM2_DISP0_I2C_EN, 1);
+
+ /* DISP0 Detect */
+ gpio_request(MX6_ARM2_DISP0_DET_INT, "disp0-detect");
+ gpio_direction_input(MX6_ARM2_DISP0_DET_INT);
+}
+
+static int ddc_dvi_update(void)
+{
+ /* DVI cable state */
+ if (gpio_get_value(MX6_ARM2_DISP0_DET_INT) == 1)
+ return 1;
+ return 0;
+}
+
+static struct fsl_mxc_dvi_platform_data sabr_ddc_dvi_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .init = ddc_dvi_init,
+ .update = ddc_dvi_update,
+};
+
+static void mx6_csi0_io_init(void)
+{
+ if (0 == sgtl5000_en) {
+ iomux_v3_cfg_t *sensor_pads = NULL;
+ u32 sensor_pads_cnt;
+
+ if (cpu_is_mx6q()) {
+ sensor_pads = mx6q_arm2_csi0_sensor_pads;
+ sensor_pads_cnt = \
+ ARRAY_SIZE(mx6q_arm2_csi0_sensor_pads);
+ } else if (cpu_is_mx6dl()) {
+ sensor_pads = mx6dl_arm2_csi0_sensor_pads;
+ sensor_pads_cnt = \
+ ARRAY_SIZE(mx6dl_arm2_csi0_sensor_pads);
+ }
+
+ BUG_ON(!sensor_pads);
+ mxc_iomux_v3_setup_multiple_pads(sensor_pads, sensor_pads_cnt);
+ }
+ /* Camera reset */
+ gpio_request(MX6_ARM2_CSI0_RST, "cam-reset");
+ gpio_direction_output(MX6_ARM2_CSI0_RST, 1);
+
+ /* Camera power down */
+ gpio_request(MX6_ARM2_CSI0_PWN, "cam-pwdn");
+ gpio_direction_output(MX6_ARM2_CSI0_PWN, 1);
+ msleep(1);
+ gpio_set_value(MX6_ARM2_CSI0_PWN, 0);
+
+ /* For MX6Q:
+ * GPR1 bit19 and bit20 meaning:
+ * Bit19: 0 - Enable mipi to IPU1 CSI0
+ * virtual channel is fixed to 0
+ * 1 - Enable parallel interface to IPU1 CSI0
+ * Bit20: 0 - Enable mipi to IPU2 CSI1
+ * virtual channel is fixed to 3
+ * 1 - Enable parallel interface to IPU2 CSI1
+ * IPU1 CSI1 directly connect to mipi csi2,
+ * virtual channel is fixed to 1
+ * IPU2 CSI0 directly connect to mipi csi2,
+ * virtual channel is fixed to 2
+ *
+ * For MX6DL:
+ * GPR1 bit 21 and GPR13 bit 0-5, RM has detail information
+ */
+ if (cpu_is_mx6q())
+ mxc_iomux_set_gpr_register(1, 19, 1, 1);
+ else if (cpu_is_mx6dl())
+ mxc_iomux_set_gpr_register(13, 0, 3, 4);
+}
+
+static struct fsl_mxc_camera_platform_data camera_data = {
+ .analog_regulator = "DA9052_LDO7",
+ .core_regulator = "DA9052_LDO9",
+ .mclk = 24000000,
+ .mclk_source = 0,
+ .csi = 0,
+ .io_init = mx6_csi0_io_init,
+};
+
+static void mx6_csi0_tvin_io_init(void)
+{
+ if (0 == sgtl5000_en) {
+ iomux_v3_cfg_t *tvin_pads = NULL;
+ u32 tvin_pads_cnt;
+
+ if (cpu_is_mx6q()) {
+ tvin_pads = mx6q_arm2_csi0_tvin_pads;
+ tvin_pads_cnt = \
+ ARRAY_SIZE(mx6q_arm2_csi0_tvin_pads);
+ } else if (cpu_is_mx6dl()) {
+ tvin_pads = mx6dl_arm2_csi0_tvin_pads;
+ tvin_pads_cnt = \
+ ARRAY_SIZE(mx6dl_arm2_csi0_tvin_pads);
+ }
+
+ BUG_ON(!tvin_pads);
+ mxc_iomux_v3_setup_multiple_pads(tvin_pads, tvin_pads_cnt);
+ }
+ /* Tvin reset */
+ gpio_request(MX6_ARM2_CSI0_RST_TVIN, "tvin-reset");
+ gpio_direction_output(MX6_ARM2_CSI0_RST_TVIN, 1);
+
+ /* Tvin power down */
+ gpio_request(MX6_ARM2_CSI0_PWN, "cam-pwdn");
+ gpio_direction_output(MX6_ARM2_CSI0_PWN, 0);
+ msleep(1);
+ gpio_set_value(MX6_ARM2_CSI0_PWN, 1);
+
+ if (cpu_is_mx6q())
+ mxc_iomux_set_gpr_register(1, 19, 1, 1);
+ else if (cpu_is_mx6dl())
+ mxc_iomux_set_gpr_register(13, 0, 3, 4);
+}
+
+static struct fsl_mxc_tvin_platform_data tvin_data = {
+ .io_init = mx6_csi0_tvin_io_init,
+ .cvbs = false,
+};
+
+static void mx6_mipi_sensor_io_init(void)
+{
+ iomux_v3_cfg_t *mipi_sensor_pads = NULL;
+ u32 mipi_sensor_pads_cnt;
+
+ if (cpu_is_mx6q()) {
+ mipi_sensor_pads = mx6q_arm2_mipi_sensor_pads;
+ mipi_sensor_pads_cnt = ARRAY_SIZE(mx6q_arm2_mipi_sensor_pads);
+ } else if (cpu_is_mx6dl()) {
+ mipi_sensor_pads = mx6dl_arm2_mipi_sensor_pads;
+ mipi_sensor_pads_cnt = ARRAY_SIZE(mx6dl_arm2_mipi_sensor_pads);
+
+ }
+ BUG_ON(!mipi_sensor_pads);
+ mxc_iomux_v3_setup_multiple_pads(mipi_sensor_pads,
+ mipi_sensor_pads_cnt);
+
+ /*for mx6dl, mipi virtual channel 1 connect to csi 1*/
+ if (cpu_is_mx6dl())
+ mxc_iomux_set_gpr_register(13, 3, 3, 1);
+}
+
+static struct fsl_mxc_camera_platform_data ov5640_mipi_data = {
+ .mclk = 24000000,
+ .csi = 1,
+ .mclk_source = 0,
+ .io_init = mx6_mipi_sensor_io_init,
+};
+
+static struct mxc_audio_codec_platform_data cs42888_data = {
+ .rates = (SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_176400),
+};
+
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+static struct regulator_consumer_supply display_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "DISPLAY",
+ },
+};
+
+static struct regulator_consumer_supply vcom_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "VCOM",
+ },
+};
+
+static struct regulator_consumer_supply v3p3_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "V3P3",
+ },
+};
+
+static struct regulator_init_data max17135_init_data[] = {
+ {
+ .constraints = {
+ .name = "DISPLAY",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(display_consumers),
+ .consumer_supplies = display_consumers,
+ }, {
+ .constraints = {
+ .name = "GVDD",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "GVEE",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINN",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINP",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "VCOM",
+ .min_uV = mV_to_uV(-4325),
+ .max_uV = mV_to_uV(-500),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcom_consumers),
+ .consumer_supplies = vcom_consumers,
+ }, {
+ .constraints = {
+ .name = "VNEG",
+ .min_uV = V_to_uV(-15),
+ .max_uV = V_to_uV(-15),
+ },
+ }, {
+ .constraints = {
+ .name = "VPOS",
+ .min_uV = V_to_uV(15),
+ .max_uV = V_to_uV(15),
+ },
+ }, {
+ .constraints = {
+ .name = "V3P3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(v3p3_consumers),
+ .consumer_supplies = v3p3_consumers,
+ },
+};
+
+static struct platform_device max17135_sensor_device = {
+ .name = "max17135_sensor",
+ .id = 0,
+};
+
+static struct max17135_platform_data max17135_pdata __initdata = {
+ .vneg_pwrup = 1,
+ .gvee_pwrup = 1,
+ .vpos_pwrup = 2,
+ .gvdd_pwrup = 1,
+ .gvdd_pwrdn = 1,
+ .vpos_pwrdn = 2,
+ .gvee_pwrdn = 1,
+ .vneg_pwrdn = 1,
+ .gpio_pmic_pwrgood = MX6DL_ARM2_EPDC_PWRSTAT,
+ .gpio_pmic_vcom_ctrl = MX6DL_ARM2_EPDC_VCOM,
+ .gpio_pmic_wakeup = MX6DL_ARM2_EPDC_PMIC_WAKE,
+ .gpio_pmic_v3p3 = MX6DL_ARM2_EPDC_PWRCTRL0,
+ .gpio_pmic_intr = MX6DL_ARM2_EPDC_PMIC_INT,
+ .regulator_init = max17135_init_data,
+ .init = max17135_regulator_init,
+};
+
+static int __init max17135_regulator_init(struct max17135 *max17135)
+{
+ struct max17135_platform_data *pdata = &max17135_pdata;
+ int i, ret;
+
+ if (!epdc_enabled) {
+ printk(KERN_DEBUG
+ "max17135_regulator_init abort: EPDC not enabled\n");
+ return 0;
+ }
+
+ max17135->gvee_pwrup = pdata->gvee_pwrup;
+ max17135->vneg_pwrup = pdata->vneg_pwrup;
+ max17135->vpos_pwrup = pdata->vpos_pwrup;
+ max17135->gvdd_pwrup = pdata->gvdd_pwrup;
+ max17135->gvdd_pwrdn = pdata->gvdd_pwrdn;
+ max17135->vpos_pwrdn = pdata->vpos_pwrdn;
+ max17135->vneg_pwrdn = pdata->vneg_pwrdn;
+ max17135->gvee_pwrdn = pdata->gvee_pwrdn;
+
+ max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup +
+ pdata->gvdd_pwrup + pdata->gvee_pwrup;
+
+ max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood;
+ max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl;
+ max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup;
+ max17135->gpio_pmic_v3p3 = pdata->gpio_pmic_v3p3;
+ max17135->gpio_pmic_intr = pdata->gpio_pmic_intr;
+
+ gpio_request(max17135->gpio_pmic_wakeup, "epdc-pmic-wake");
+ gpio_direction_output(max17135->gpio_pmic_wakeup, 0);
+
+ gpio_request(max17135->gpio_pmic_vcom_ctrl, "epdc-vcom");
+ gpio_direction_output(max17135->gpio_pmic_vcom_ctrl, 0);
+
+ gpio_request(max17135->gpio_pmic_v3p3, "epdc-v3p3");
+ gpio_direction_output(max17135->gpio_pmic_v3p3, 0);
+
+ gpio_request(max17135->gpio_pmic_intr, "epdc-pmic-int");
+ gpio_direction_input(max17135->gpio_pmic_intr);
+
+ gpio_request(max17135->gpio_pmic_pwrgood, "epdc-pwrstat");
+ gpio_direction_input(max17135->gpio_pmic_pwrgood);
+
+ max17135->vcom_setup = false;
+ max17135->init_done = false;
+
+ for (i = 0; i < MAX17135_NUM_REGULATORS; i++) {
+ ret = max17135_register_regulator(max17135, i,
+ &pdata->regulator_init[i]);
+ if (ret != 0) {
+ printk(KERN_ERR"max17135 regulator init failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ regulator_has_full_constraints();
+
+ return 0;
+}
+
+static int sii902x_get_pins(void)
+{
+ /* Sii902x HDMI controller */
+ gpio_request(MX6_ARM2_DISP0_RESET, "disp0-reset");
+ gpio_direction_output(MX6_ARM2_DISP0_RESET, 0);
+ gpio_request(MX6_ARM2_DISP0_DET_INT, "disp0-detect");
+ gpio_direction_input(MX6_ARM2_DISP0_DET_INT);
+ return 1;
+}
+
+static void sii902x_put_pins(void)
+{
+ gpio_free(MX6_ARM2_DISP0_RESET);
+ gpio_free(MX6_ARM2_DISP0_DET_INT);
+}
+
+static void sii902x_hdmi_reset(void)
+{
+ gpio_set_value(MX6_ARM2_DISP0_RESET, 0);
+ msleep(10);
+ gpio_set_value(MX6_ARM2_DISP0_RESET, 1);
+ msleep(10);
+}
+
+static struct fsl_mxc_lcd_platform_data sii902x_hdmi_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .reset = sii902x_hdmi_reset,
+ .get_pins = sii902x_get_pins,
+ .put_pins = sii902x_put_pins,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("cs42888", 0x48),
+ .platform_data = (void *)&cs42888_data,
+ }, {
+ I2C_BOARD_INFO("ov5640", 0x3c),
+ .platform_data = (void *)&camera_data,
+ }, {
+ I2C_BOARD_INFO("adv7180", 0x21),
+ .platform_data = (void *)&tvin_data,
+ },
+};
+
+static struct imxi2c_platform_data mx6_arm2_i2c0_data = {
+ .bitrate = 100000,
+};
+
+static struct imxi2c_platform_data mx6_arm2_i2c1_data = {
+ .bitrate = 100000,
+};
+
+static struct imxi2c_platform_data mx6_arm2_i2c2_data = {
+ .bitrate = 400000,
+};
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("max17135", 0x48),
+ .platform_data = &max17135_pdata,
+ }, {
+ I2C_BOARD_INFO("max7310", 0x1F),
+ .platform_data = &max7310_platdata,
+ }, {
+ I2C_BOARD_INFO("max7310", 0x1B),
+ .platform_data = &max7310_u48_platdata,
+ }, {
+ I2C_BOARD_INFO("mxc_dvi", 0x50),
+ .platform_data = &sabr_ddc_dvi_data,
+ .irq = gpio_to_irq(MX6_ARM2_DISP0_DET_INT),
+ }, {
+ I2C_BOARD_INFO("egalax_ts", 0x4),
+ .irq = gpio_to_irq(MX6_ARM2_CAP_TCH_INT),
+ }, {
+ I2C_BOARD_INFO("sii902x", 0x39),
+ .platform_data = &sii902x_hdmi_data,
+ .irq = gpio_to_irq(MX6_ARM2_DISP0_DET_INT),
+ },
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("egalax_ts", 0x4),
+ .irq = gpio_to_irq(MX6_ARM2_CAP_TCH_INT),
+ }, {
+ I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50),
+ }, {
+ I2C_BOARD_INFO("ov5640_mipi", 0x3c),
+ .platform_data = (void *)&ov5640_mipi_data,
+ }, {
+ I2C_BOARD_INFO("sgtl5000", 0x0a),
+ },
+};
+
+static int epdc_get_pins(void)
+{
+ int ret = 0;
+
+ /* Claim GPIOs for EPDC pins - used during power up/down */
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_0, "epdc_d0");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_1, "epdc_d1");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_2, "epdc_d2");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_3, "epdc_d3");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_4, "epdc_d4");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_5, "epdc_d5");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_6, "epdc_d6");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_7, "epdc_d7");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_GDCLK, "epdc_gdclk");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_GDSP, "epdc_gdsp");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_GDOE, "epdc_gdoe");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_GDRL, "epdc_gdrl");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDCLK, "epdc_sdclk");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDOE, "epdc_sdoe");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDLE, "epdc_sdle");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDSHR, "epdc_sdshr");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_BDR0, "epdc_bdr0");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDCE0, "epdc_sdce0");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDCE1, "epdc_sdce1");
+ ret |= gpio_request(MX6DL_ARM2_EPDC_SDCE2, "epdc_sdce2");
+
+ return ret;
+}
+
+static void epdc_put_pins(void)
+{
+ gpio_free(MX6DL_ARM2_EPDC_SDDO_0);
+ gpio_free(MX6DL_ARM2_EPDC_SDDO_1);
+ gpio_free(MX6DL_ARM2_EPDC_SDDO_2);
+ gpio_free(MX6DL_ARM2_EPDC_SDDO_3);
+ gpio_free(MX6DL_ARM2_EPDC_SDDO_4);
+ gpio_free(MX6DL_ARM2_EPDC_SDDO_5);
+ gpio_free(MX6DL_ARM2_EPDC_SDDO_6);
+ gpio_free(MX6DL_ARM2_EPDC_SDDO_7);
+ gpio_free(MX6DL_ARM2_EPDC_GDCLK);
+ gpio_free(MX6DL_ARM2_EPDC_GDSP);
+ gpio_free(MX6DL_ARM2_EPDC_GDOE);
+ gpio_free(MX6DL_ARM2_EPDC_GDRL);
+ gpio_free(MX6DL_ARM2_EPDC_SDCLK);
+ gpio_free(MX6DL_ARM2_EPDC_SDOE);
+ gpio_free(MX6DL_ARM2_EPDC_SDLE);
+ gpio_free(MX6DL_ARM2_EPDC_SDSHR);
+ gpio_free(MX6DL_ARM2_EPDC_BDR0);
+ gpio_free(MX6DL_ARM2_EPDC_SDCE0);
+ gpio_free(MX6DL_ARM2_EPDC_SDCE1);
+ gpio_free(MX6DL_ARM2_EPDC_SDCE2);
+}
+
+static iomux_v3_cfg_t mx6dl_epdc_pads_enabled[] = {
+ MX6DL_PAD_EIM_A16__EPDC_SDDO_0,
+ MX6DL_PAD_EIM_DA10__EPDC_SDDO_1,
+ MX6DL_PAD_EIM_DA12__EPDC_SDDO_2,
+ MX6DL_PAD_EIM_DA11__EPDC_SDDO_3,
+ MX6DL_PAD_EIM_LBA__EPDC_SDDO_4,
+ MX6DL_PAD_EIM_EB2__EPDC_SDDO_5,
+ MX6DL_PAD_EIM_CS0__EPDC_SDDO_6,
+ MX6DL_PAD_EIM_RW__EPDC_SDDO_7,
+ MX6DL_PAD_EIM_CS1__EPDC_SDDO_8,
+ MX6DL_PAD_EIM_DA15__EPDC_SDDO_9,
+ MX6DL_PAD_EIM_D16__EPDC_SDDO_10,
+ MX6DL_PAD_EIM_D23__EPDC_SDDO_11,
+ MX6DL_PAD_EIM_D19__EPDC_SDDO_12,
+ MX6DL_PAD_EIM_DA13__EPDC_SDDO_13,
+ MX6DL_PAD_EIM_DA14__EPDC_SDDO_14,
+ MX6DL_PAD_EIM_A25__EPDC_SDDO_15,
+ MX6DL_PAD_EIM_A21__EPDC_GDCLK,
+ MX6DL_PAD_EIM_A22__EPDC_GDSP,
+ MX6DL_PAD_EIM_A23__EPDC_GDOE,
+ MX6DL_PAD_EIM_A24__EPDC_GDRL,
+ MX6DL_PAD_EIM_D31__EPDC_SDCLK,
+ MX6DL_PAD_EIM_D27__EPDC_SDOE,
+ MX6DL_PAD_EIM_DA1__EPDC_SDLE,
+ MX6DL_PAD_EIM_EB1__EPDC_SDSHR,
+ MX6DL_PAD_EIM_DA2__EPDC_BDR_0,
+ MX6DL_PAD_EIM_DA4__EPDC_SDCE_0,
+ MX6DL_PAD_EIM_DA5__EPDC_SDCE_1,
+ MX6DL_PAD_EIM_DA6__EPDC_SDCE_2,
+};
+
+static iomux_v3_cfg_t mx6dl_epdc_pads_disabled[] = {
+ MX6DL_PAD_EIM_A16__GPIO_2_22,
+ MX6DL_PAD_EIM_DA10__GPIO_3_10,
+ MX6DL_PAD_EIM_DA12__GPIO_3_12,
+ MX6DL_PAD_EIM_DA11__GPIO_3_11,
+ MX6DL_PAD_EIM_LBA__GPIO_2_27,
+ MX6DL_PAD_EIM_EB2__GPIO_2_30,
+ MX6DL_PAD_EIM_CS0__GPIO_2_23,
+ MX6DL_PAD_EIM_RW__GPIO_2_26,
+ MX6DL_PAD_EIM_CS1__GPIO_2_24,
+ MX6DL_PAD_EIM_DA15__GPIO_3_15,
+ MX6DL_PAD_EIM_D16__GPIO_3_16,
+ MX6DL_PAD_EIM_D23__GPIO_3_23,
+ MX6DL_PAD_EIM_D19__GPIO_3_19,
+ MX6DL_PAD_EIM_DA13__GPIO_3_13,
+ MX6DL_PAD_EIM_DA14__GPIO_3_14,
+ MX6DL_PAD_EIM_A25__GPIO_5_2,
+ MX6DL_PAD_EIM_A21__GPIO_2_17,
+ MX6DL_PAD_EIM_A22__GPIO_2_16,
+ MX6DL_PAD_EIM_A23__GPIO_6_6,
+ MX6DL_PAD_EIM_A24__GPIO_5_4,
+ MX6DL_PAD_EIM_D31__GPIO_3_31,
+ MX6DL_PAD_EIM_D27__GPIO_3_27,
+ MX6DL_PAD_EIM_DA1__GPIO_3_1,
+ MX6DL_PAD_EIM_EB1__GPIO_2_29,
+ MX6DL_PAD_EIM_DA2__GPIO_3_2,
+ MX6DL_PAD_EIM_DA4__GPIO_3_4,
+ MX6DL_PAD_EIM_DA5__GPIO_3_5,
+ MX6DL_PAD_EIM_DA6__GPIO_3_6,
+};
+static void epdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable EPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_epdc_pads_enabled, \
+ ARRAY_SIZE(mx6dl_epdc_pads_enabled));
+
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_0);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_1);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_2);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_3);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_4);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_5);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_6);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_7);
+ gpio_direction_input(MX6DL_ARM2_EPDC_GDCLK);
+ gpio_direction_input(MX6DL_ARM2_EPDC_GDSP);
+ gpio_direction_input(MX6DL_ARM2_EPDC_GDOE);
+ gpio_direction_input(MX6DL_ARM2_EPDC_GDRL);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDCLK);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDOE);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDLE);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDSHR);
+ gpio_direction_input(MX6DL_ARM2_EPDC_BDR0);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDCE0);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDCE1);
+ gpio_direction_input(MX6DL_ARM2_EPDC_SDCE2);
+}
+
+static void epdc_disable_pins(void)
+{
+ /* Configure MUX settings for EPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_epdc_pads_disabled, \
+ ARRAY_SIZE(mx6dl_epdc_pads_disabled));
+
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_0, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_1, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_2, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_3, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_4, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_5, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_6, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_7, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_GDCLK, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_GDSP, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_GDOE, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_GDRL, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDCLK, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDOE, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDLE, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDSHR, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_BDR0, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDCE0, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDCE1, 0);
+ gpio_direction_output(MX6DL_ARM2_EPDC_SDCE2, 0);
+}
+
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 30000000,
+ .left_margin = 8,
+ .right_margin = 164,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+};
+static struct fb_videomode e060scm_mode = {
+ .name = "E060SCM",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 26666667,
+ .left_margin = 8,
+ .right_margin = 100,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct imx_epdc_fb_mode panel_modes[] = {
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 465, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 9, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e060scm_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 419, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 5, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+
+static struct imx_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+ .get_pins = epdc_get_pins,
+ .put_pins = epdc_put_pins,
+ .enable_pins = epdc_enable_pins,
+ .disable_pins = epdc_disable_pins,
+};
+
+static void imx6_arm2_usbotg_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(MX6_ARM2_USB_OTG_PWR, 1);
+ else
+ gpio_set_value(MX6_ARM2_USB_OTG_PWR, 0);
+}
+
+static void __init mx6_arm2_init_usb(void)
+{
+ int ret = 0;
+
+ imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR);
+
+ /* disable external charger detect,
+ * or it will affect signal quality at dp.
+ */
+
+ ret = gpio_request(MX6_ARM2_USB_OTG_PWR, "usb-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO MX6_ARM2_USB_OTG_PWR:%d\n", ret);
+ return;
+ }
+ gpio_direction_output(MX6_ARM2_USB_OTG_PWR, 0);
+ mxc_iomux_set_gpr_register(1, 13, 1, 1);
+
+ mx6_set_otghost_vbus_func(imx6_arm2_usbotg_vbus);
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ mx6_usb_h2_init();
+ mx6_usb_h3_init();
+#endif
+}
+
+static struct viv_gpu_platform_data imx6_gpu_pdata __initdata = {
+ .reserved_mem_size = SZ_128M + SZ_64M,
+};
+
+/* HW Initialization, if return 0, initialization is successful. */
+static int mx6_arm2_sata_init(struct device *dev, void __iomem *addr)
+{
+ u32 tmpdata;
+ int ret = 0;
+ struct clk *clk;
+
+ /* Enable SATA PWR CTRL_0 of MAX7310 */
+ gpio_request(MX6_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN");
+ gpio_direction_output(MX6_ARM2_MAX7310_1_BASE_ADDR, 1);
+
+ sata_clk = clk_get(dev, "imx_sata_clk");
+ if (IS_ERR(sata_clk)) {
+ dev_err(dev, "no sata clock.\n");
+ return PTR_ERR(sata_clk);
+ }
+ ret = clk_enable(sata_clk);
+ if (ret) {
+ dev_err(dev, "can't enable sata clock.\n");
+ goto put_sata_clk;
+ }
+
+ /* Set PHY Paremeters, two steps to configure the GPR13,
+ * one write for rest of parameters, mask of first write is 0x07FFFFFD,
+ * and the other one write for setting the mpll_clk_off_b
+ *.rx_eq_val_0(iomuxc_gpr13[26:24]),
+ *.los_lvl(iomuxc_gpr13[23:19]),
+ *.rx_dpll_mode_0(iomuxc_gpr13[18:16]),
+ *.sata_speed(iomuxc_gpr13[15]),
+ *.mpll_ss_en(iomuxc_gpr13[14]),
+ *.tx_atten_0(iomuxc_gpr13[13:11]),
+ *.tx_boost_0(iomuxc_gpr13[10:7]),
+ *.tx_lvl(iomuxc_gpr13[6:2]),
+ *.mpll_ck_off(iomuxc_gpr13[1]),
+ *.tx_edgerate_0(iomuxc_gpr13[0]),
+ */
+ tmpdata = readl(IOMUXC_GPR13);
+ writel(((tmpdata & ~0x07FFFFFD) | 0x0593A044), IOMUXC_GPR13);
+
+ /* enable SATA_PHY PLL */
+ tmpdata = readl(IOMUXC_GPR13);
+ writel(((tmpdata & ~0x2) | 0x2), IOMUXC_GPR13);
+
+ /* Get the AHB clock rate, and configure the TIMER1MS reg later */
+ clk = clk_get(NULL, "ahb");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "no ahb clock.\n");
+ ret = PTR_ERR(clk);
+ goto release_sata_clk;
+ }
+ tmpdata = clk_get_rate(clk) / 1000;
+ clk_put(clk);
+
+ ret = sata_init(addr, tmpdata);
+ if (ret == 0)
+ return ret;
+
+release_sata_clk:
+ clk_disable(sata_clk);
+put_sata_clk:
+ clk_put(sata_clk);
+ /* Disable SATA PWR CTRL_0 of MAX7310 */
+ gpio_request(MX6_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN");
+ gpio_direction_output(MX6_ARM2_MAX7310_1_BASE_ADDR, 0);
+
+ return ret;
+}
+
+static void mx6_arm2_sata_exit(struct device *dev)
+{
+ clk_disable(sata_clk);
+ clk_put(sata_clk);
+
+ /* Disable SATA PWR CTRL_0 of MAX7310 */
+ gpio_request(MX6_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN");
+ gpio_direction_output(MX6_ARM2_MAX7310_1_BASE_ADDR, 0);
+
+}
+
+static struct ahci_platform_data mx6_arm2_sata_data = {
+ .init = mx6_arm2_sata_init,
+ .exit = mx6_arm2_sata_exit,
+};
+
+static struct imx_asrc_platform_data imx_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 2,
+};
+
+static void mx6_arm2_reset_mipi_dsi(void)
+{
+ gpio_set_value(MX6_ARM2_DISP0_PWR, 1);
+ gpio_set_value(MX6_ARM2_DISP0_RESET, 1);
+ udelay(10);
+ gpio_set_value(MX6_ARM2_DISP0_RESET, 0);
+ udelay(50);
+ gpio_set_value(MX6_ARM2_DISP0_RESET, 1);
+
+ /*
+ * it needs to delay 120ms minimum for reset complete
+ */
+ msleep(120);
+}
+
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+ .ipu_id = 1,
+ .disp_id = 1,
+ .lcd_panel = "TRULY-WVGA",
+ .reset = mx6_arm2_reset_mipi_dsi,
+};
+
+static struct ipuv3_fb_platform_data sabr_fb_data[] = {
+ { /*fb0*/
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-XGA",
+ .default_bpp = 32,
+ .int_clk = false,
+ }, {
+ .disp_dev = "mipi_dsi",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB24,
+ .mode_str = "TRULY-WVGA",
+ .default_bpp = 24,
+ .int_clk = false,
+ }, {
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-XGA",
+ .default_bpp = 32,
+ .int_clk = false,
+ }, {
+ .disp_dev = "lcd",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB565,
+ .mode_str = "CLAA-WVGA",
+ .default_bpp = 16,
+ .int_clk = false,
+ }
+};
+
+static void hdmi_init(int ipu_id, int disp_id)
+{
+ int hdmi_mux_setting;
+ int max_ipu_id = cpu_is_mx6q() ? 1 : 0;
+
+ if ((ipu_id > max_ipu_id) || (ipu_id < 0)) {
+ pr_err("Invalid IPU select for HDMI: %d. Set to 0\n", ipu_id);
+ ipu_id = 0;
+ }
+
+ if ((disp_id > 1) || (disp_id < 0)) {
+ pr_err("Invalid DI select for HDMI: %d. Set to 0\n", disp_id);
+ disp_id = 0;
+ }
+
+ /* Configure the connection between IPU1/2 and HDMI */
+ hdmi_mux_setting = 2 * ipu_id + disp_id;
+
+ /* GPR3, bits 2-3 = HDMI_MUX_CTL */
+ mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
+
+ /* Set HDMI event as SDMA event2 while Chip version later than TO1.2 */
+ if (hdmi_SDMA_check())
+ mxc_iomux_set_gpr_register(0, 0, 1, 1);
+}
+
+/* On mx6x arm2 board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6dl_arm2_hdmi_ddc_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_arm2_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_i2c2_pads,
+ ARRAY_SIZE(mx6dl_arm2_i2c2_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_i2c2_pads,
+ ARRAY_SIZE(mx6q_arm2_i2c2_pads));
+}
+
+static struct fsl_mxc_hdmi_platform_data hdmi_data = {
+ .init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
+};
+
+static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+};
+
+static struct fsl_mxc_lcd_platform_data lcdif_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .default_ifmt = IPU_PIX_FMT_RGB565,
+};
+
+static struct fsl_mxc_ldb_platform_data ldb_data = {
+ .ipu_id = 1,
+ .disp_id = 0,
+ .ext_ref = 1,
+ .mode = LDB_SEP0,
+ .sec_ipu_id = 0,
+ .sec_disp_id = 1,
+};
+
+static struct imx_ipuv3_platform_data ipu_data[] = {
+ {
+ .rev = 4,
+ .csi_clk[0] = "clko_clk",
+ }, {
+ .rev = 4,
+ .csi_clk[0] = "clko_clk",
+ },
+};
+
+static struct platform_pwm_backlight_data mx6_arm2_pwm_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+
+static struct ion_platform_data imx_ion_data = {
+ .nr = 1,
+ .heaps = {
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = "vpu_ion",
+ .size = SZ_64M,
+ },
+ },
+};
+
+static struct gpio mx6_flexcan_gpios[] = {
+ { MX6_ARM2_CAN1_EN, GPIOF_OUT_INIT_LOW, "flexcan1-en" },
+ { MX6_ARM2_CAN1_STBY, GPIOF_OUT_INIT_LOW, "flexcan1-stby" },
+ { MX6_ARM2_CAN2_EN, GPIOF_OUT_INIT_LOW, "flexcan2-en" },
+};
+
+static void mx6_flexcan0_switch(int enable)
+{
+ if (enable) {
+ gpio_set_value(MX6_ARM2_CAN1_EN, 1);
+ gpio_set_value(MX6_ARM2_CAN1_STBY, 1);
+ } else {
+ gpio_set_value(MX6_ARM2_CAN1_EN, 0);
+ gpio_set_value(MX6_ARM2_CAN1_STBY, 0);
+ }
+}
+
+static void mx6_flexcan1_switch(int enable)
+{
+ if (enable) {
+ gpio_set_value(MX6_ARM2_CAN2_EN, 1);
+ gpio_set_value_cansleep(MX6_ARM2_CAN2_STBY, 1);
+ } else {
+ gpio_set_value(MX6_ARM2_CAN2_EN, 0);
+ gpio_set_value_cansleep(MX6_ARM2_CAN2_STBY, 0);
+ }
+}
+
+static const struct flexcan_platform_data
+ mx6_arm2_flexcan_pdata[] __initconst = {
+ {
+ .transceiver_switch = mx6_flexcan0_switch,
+ }, {
+ .transceiver_switch = mx6_flexcan1_switch,
+ }
+};
+
+static struct mipi_csi2_platform_data mipi_csi2_pdata = {
+ .ipu_id = 0,
+ .csi_id = 0,
+ .v_channel = 0,
+ .lanes = 2,
+ .dphy_clk = "mipi_pllref_clk",
+ .pixel_clk = "emi_clk",
+};
+
+static struct fsl_mxc_capture_platform_data capture_data[] = {
+ {
+ .csi = 0,
+ .ipu = 0,
+ .mclk_source = 0,
+ .is_mipi = 0,
+ }, {
+ .csi = 1,
+ .ipu = 0,
+ .mclk_source = 0,
+ .is_mipi = 1,
+ },
+};
+
+
+static void arm2_suspend_enter(void)
+{
+ /* suspend preparation */
+}
+
+static void arm2_suspend_exit(void)
+{
+ /* resmue resore */
+}
+static const struct pm_platform_data mx6_arm2_pm_data __initconst = {
+ .name = "imx_pm",
+ .suspend_enter = arm2_suspend_enter,
+ .suspend_exit = arm2_suspend_exit,
+};
+
+static const struct asrc_p2p_params esai_p2p = {
+ .p2p_rate = 44100,
+ .p2p_width = ASRC_WIDTH_24_BIT,
+};
+
+static struct mxc_audio_platform_data sab_audio_data = {
+ .sysclk = 16934400,
+ .priv = (void *)&esai_p2p,
+};
+
+static struct platform_device sab_audio_device = {
+ .name = "imx-cs42888",
+};
+
+static struct imx_esai_platform_data sab_esai_pdata = {
+ .flags = IMX_ESAI_NET,
+};
+
+static struct regulator_consumer_supply arm2_vmmc_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.3"),
+};
+
+static struct regulator_init_data arm2_vmmc_init = {
+ .num_consumer_supplies = ARRAY_SIZE(arm2_vmmc_consumers),
+ .consumer_supplies = arm2_vmmc_consumers,
+};
+
+static struct fixed_voltage_config arm2_vmmc_reg_config = {
+ .supply_name = "vmmc",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &arm2_vmmc_init,
+};
+
+static struct platform_device arm2_vmmc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &arm2_vmmc_reg_config,
+ },
+};
+
+#ifdef CONFIG_SND_SOC_CS42888
+
+static struct regulator_consumer_supply cs42888_arm2_consumer_va = {
+ .supply = "VA",
+ .dev_name = "0-0048",
+};
+
+static struct regulator_consumer_supply cs42888_arm2_consumer_vd = {
+ .supply = "VD",
+ .dev_name = "0-0048",
+};
+
+static struct regulator_consumer_supply cs42888_arm2_consumer_vls = {
+ .supply = "VLS",
+ .dev_name = "0-0048",
+};
+
+static struct regulator_consumer_supply cs42888_arm2_consumer_vlc = {
+ .supply = "VLC",
+ .dev_name = "0-0048",
+};
+
+static struct regulator_init_data cs42888_arm2_va_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &cs42888_arm2_consumer_va,
+};
+
+static struct regulator_init_data cs42888_arm2_vd_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &cs42888_arm2_consumer_vd,
+};
+
+static struct regulator_init_data cs42888_arm2_vls_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &cs42888_arm2_consumer_vls,
+};
+
+static struct regulator_init_data cs42888_arm2_vlc_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &cs42888_arm2_consumer_vlc,
+};
+
+static struct fixed_voltage_config cs42888_arm2_va_reg_config = {
+ .supply_name = "VA",
+ .microvolts = 2800000,
+ .gpio = -1,
+ .init_data = &cs42888_arm2_va_reg_initdata,
+};
+
+static struct fixed_voltage_config cs42888_arm2_vd_reg_config = {
+ .supply_name = "VD",
+ .microvolts = 2800000,
+ .gpio = -1,
+ .init_data = &cs42888_arm2_vd_reg_initdata,
+};
+
+static struct fixed_voltage_config cs42888_arm2_vls_reg_config = {
+ .supply_name = "VLS",
+ .microvolts = 2800000,
+ .gpio = -1,
+ .init_data = &cs42888_arm2_vls_reg_initdata,
+};
+
+static struct fixed_voltage_config cs42888_arm2_vlc_reg_config = {
+ .supply_name = "VLC",
+ .microvolts = 2800000,
+ .gpio = -1,
+ .init_data = &cs42888_arm2_vlc_reg_initdata,
+};
+
+static struct platform_device cs42888_arm2_va_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 3,
+ .dev = {
+ .platform_data = &cs42888_arm2_va_reg_config,
+ },
+};
+
+static struct platform_device cs42888_arm2_vd_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 4,
+ .dev = {
+ .platform_data = &cs42888_arm2_vd_reg_config,
+ },
+};
+
+static struct platform_device cs42888_arm2_vls_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 5,
+ .dev = {
+ .platform_data = &cs42888_arm2_vls_reg_config,
+ },
+};
+
+static struct platform_device cs42888_arm2_vlc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 6,
+ .dev = {
+ .platform_data = &cs42888_arm2_vlc_reg_config,
+ },
+};
+
+#endif /* CONFIG_SND_SOC_CS42888 */
+
+#ifdef CONFIG_SND_SOC_SGTL5000
+
+static struct regulator_consumer_supply sgtl5000_arm2_consumer_vdda = {
+ .supply = "VDDA",
+ .dev_name = "1-000a",
+};
+
+static struct regulator_consumer_supply sgtl5000_arm2_consumer_vddio = {
+ .supply = "VDDIO",
+ .dev_name = "1-000a",
+};
+
+static struct regulator_consumer_supply sgtl5000_arm2_consumer_vddd = {
+ .supply = "VDDD",
+ .dev_name = "1-000a",
+};
+
+static struct regulator_init_data sgtl5000_arm2_vdda_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &sgtl5000_arm2_consumer_vdda,
+};
+
+static struct regulator_init_data sgtl5000_arm2_vddio_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &sgtl5000_arm2_consumer_vddio,
+};
+
+static struct regulator_init_data sgtl5000_arm2_vddd_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &sgtl5000_arm2_consumer_vddd,
+};
+
+static struct fixed_voltage_config sgtl5000_arm2_vdda_reg_config = {
+ .supply_name = "VDDA",
+ .microvolts = 1800000,
+ .gpio = -1,
+ .init_data = &sgtl5000_arm2_vdda_reg_initdata,
+};
+
+static struct fixed_voltage_config sgtl5000_arm2_vddio_reg_config = {
+ .supply_name = "VDDIO",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &sgtl5000_arm2_vddio_reg_initdata,
+};
+
+static struct fixed_voltage_config sgtl5000_arm2_vddd_reg_config = {
+ .supply_name = "VDDD",
+ .microvolts = 0,
+ .gpio = -1,
+ .init_data = &sgtl5000_arm2_vddd_reg_initdata,
+};
+
+static struct platform_device sgtl5000_arm2_vdda_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 7,
+ .dev = {
+ .platform_data = &sgtl5000_arm2_vdda_reg_config,
+ },
+};
+
+static struct platform_device sgtl5000_arm2_vddio_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 8,
+ .dev = {
+ .platform_data = &sgtl5000_arm2_vddio_reg_config,
+ },
+};
+
+static struct platform_device sgtl5000_arm2_vddd_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 9,
+ .dev = {
+ .platform_data = &sgtl5000_arm2_vddd_reg_config,
+ },
+};
+
+#endif /* CONFIG_SND_SOC_SGTL5000 */
+
+static struct mxc_audio_platform_data mx6_arm2_audio_data;
+
+static int mx6_arm2_sgtl5000_init(void)
+{
+
+ mx6_arm2_audio_data.sysclk = 12000000;
+
+ return 0;
+}
+
+static struct imx_ssi_platform_data mx6_arm2_ssi_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_SYN,
+};
+
+static struct mxc_audio_platform_data mx6_arm2_audio_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .init = mx6_arm2_sgtl5000_init,
+ .hp_gpio = -1,
+};
+
+static struct platform_device mx6_arm2_audio_device = {
+ .name = "imx-sgtl5000",
+};
+
+static int __init mx6_arm2_init_audio(void)
+{
+ struct clk *pll3_pfd, *esai_clk;
+ mxc_register_device(&sab_audio_device, &sab_audio_data);
+ imx6q_add_imx_esai(0, &sab_esai_pdata);
+
+ esai_clk = clk_get(NULL, "esai_clk");
+ if (IS_ERR(esai_clk))
+ return PTR_ERR(esai_clk);
+
+ pll3_pfd = clk_get(NULL, "pll3_pfd_508M");
+ if (IS_ERR(pll3_pfd))
+ return PTR_ERR(pll3_pfd);
+
+ clk_set_parent(esai_clk, pll3_pfd);
+ clk_set_rate(esai_clk, 101647058);
+
+#ifdef CONFIG_SND_SOC_CS42888
+ platform_device_register(&cs42888_arm2_va_reg_devices);
+ platform_device_register(&cs42888_arm2_vd_reg_devices);
+ platform_device_register(&cs42888_arm2_vls_reg_devices);
+ platform_device_register(&cs42888_arm2_vlc_reg_devices);
+#endif
+
+ if (sgtl5000_en) {
+ /* SSI audio init part */
+ mxc_register_device(&mx6_arm2_audio_device,
+ &mx6_arm2_audio_data);
+ imx6q_add_imx_ssi(1, &mx6_arm2_ssi_pdata);
+
+ /*
+ * AUDMUX3 and CSI0_Camera use the same pin
+ * MX6x_PAD_CSI0_DAT5
+ */
+ if (cpu_is_mx6q()) {
+ mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_audmux_pads,
+ ARRAY_SIZE(mx6q_arm2_audmux_pads));
+ } else if (cpu_is_mx6dl()) {
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_audmux_pads,
+ ARRAY_SIZE(mx6dl_arm2_audmux_pads));
+ }
+
+#ifdef CONFIG_SND_SOC_SGTL5000
+ platform_device_register(&sgtl5000_arm2_vdda_reg_devices);
+ platform_device_register(&sgtl5000_arm2_vddio_reg_devices);
+ platform_device_register(&sgtl5000_arm2_vddd_reg_devices);
+#endif
+ }
+
+ return 0;
+}
+
+static int __init early_use_esai_record(char *p)
+{
+ esai_record = 1;
+ return 0;
+}
+
+early_param("esai_record", early_use_esai_record);
+
+static struct mxc_mlb_platform_data mx6_arm2_mlb150_data = {
+ .reg_nvcc = NULL,
+ .mlb_clk = "mlb150_clk",
+ .mlb_pll_clk = "pll6",
+};
+
+static struct mxc_dvfs_platform_data arm2_dvfscore_data = {
+ .reg_id = "cpu_vddgp",
+ .soc_id = "cpu_vddsoc",
+ .pu_id = "cpu_vddvpu",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+};
+
+static void __init mx6_arm2_fixup(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+}
+
+static int __init early_enable_sgtl5000(char *p)
+{
+ sgtl5000_en = 1;
+ return 0;
+}
+
+early_param("sgtl5000", early_enable_sgtl5000);
+
+static int __init early_enable_spdif(char *p)
+{
+ spdif_en = 1;
+ return 0;
+}
+
+early_param("spdif", early_enable_spdif);
+
+static int __init early_enable_can(char *p)
+{
+ flexcan_en = 1;
+ return 0;
+}
+
+early_param("flexcan", early_enable_can);
+
+static int spdif_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long rate_actual;
+ rate_actual = clk_round_rate(clk, rate);
+ clk_set_rate(clk, rate_actual);
+ return 0;
+}
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1, /* enable tx */
+ .spdif_rx = 1, /* enable rx */
+ /*
+ * spdif0_clk will be 454.7MHz divided by ccm dividers.
+ *
+ * 44.1KHz: 454.7MHz / 7 (ccm) / 23 (spdif) = 44,128 Hz ~ 0.06% error
+ * 48KHz: 454.7MHz / 4 (ccm) / 37 (spdif) = 48,004 Hz ~ 0.01% error
+ * 32KHz: 454.7MHz / 6 (ccm) / 37 (spdif) = 32,003 Hz ~ 0.01% error
+ */
+ .spdif_clk_44100 = 1, /* tx clk from spdif0_clk_root */
+ .spdif_clk_48000 = 1, /* tx clk from spdif0_clk_root */
+ .spdif_div_44100 = 23,
+ .spdif_div_48000 = 37,
+ .spdif_div_32000 = 37,
+ .spdif_rx_clk = 0, /* rx clk from spdif stream */
+ .spdif_clk_set_rate = spdif_clk_set_rate,
+ .spdif_clk = NULL, /* spdif bus clk */
+};
+
+static const struct imx_pcie_platform_data mx6_arm2_pcie_data __initconst = {
+ .pcie_pwr_en = MX6_ARM2_PCIE_PWR_EN,
+ .pcie_rst = MX6_ARM2_PCIE_RESET,
+ .pcie_wake_up = -EINVAL,
+ .pcie_dis = -EINVAL,
+};
+
+static int __init early_disable_mipi_dsi(char *p)
+{
+ /*enable on board HDMI*/
+ /*mulplex pin with mipi disp0_reset we should disable mipi reset*/
+ disable_mipi_dsi = 1;
+ return 0;
+}
+
+early_param("disable_mipi_dsi", early_disable_mipi_dsi);
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mx6_arm2_init(void)
+{
+ int i;
+ int ret;
+
+ iomux_v3_cfg_t *common_pads = NULL;
+ iomux_v3_cfg_t *esai_rec_pads = NULL;
+ iomux_v3_cfg_t *spdif_pads = NULL;
+ iomux_v3_cfg_t *flexcan_pads = NULL;
+ iomux_v3_cfg_t *i2c3_pads = NULL;
+ iomux_v3_cfg_t *epdc_pads = NULL;
+
+ int common_pads_cnt;
+ int esai_rec_pads_cnt;
+ int spdif_pads_cnt;
+ int flexcan_pads_cnt;
+ int i2c3_pads_cnt;
+ int epdc_pads_cnt;
+
+
+ /*
+ * common pads: pads are non-shared with others on this board
+ * feature_pds: pads are shared with others on this board
+ */
+
+ if (cpu_is_mx6q()) {
+ common_pads = mx6q_arm2_pads;
+ esai_rec_pads = mx6q_arm2_esai_record_pads;
+ spdif_pads = mx6q_arm2_spdif_pads;
+ flexcan_pads = mx6q_arm2_can_pads;
+ i2c3_pads = mx6q_arm2_i2c3_pads;
+
+ common_pads_cnt = ARRAY_SIZE(mx6q_arm2_pads);
+ esai_rec_pads_cnt = ARRAY_SIZE(mx6q_arm2_esai_record_pads);
+ spdif_pads_cnt = ARRAY_SIZE(mx6q_arm2_spdif_pads);
+ flexcan_pads_cnt = ARRAY_SIZE(mx6q_arm2_can_pads);
+ i2c3_pads_cnt = ARRAY_SIZE(mx6q_arm2_i2c3_pads);
+ } else if (cpu_is_mx6dl()) {
+ common_pads = mx6dl_arm2_pads;
+ esai_rec_pads = mx6dl_arm2_esai_record_pads;
+ spdif_pads = mx6dl_arm2_spdif_pads;
+ flexcan_pads = mx6dl_arm2_can_pads;
+ i2c3_pads = mx6dl_arm2_i2c3_pads;
+ epdc_pads = mx6dl_arm2_epdc_pads;
+
+ common_pads_cnt = ARRAY_SIZE(mx6dl_arm2_pads);
+ esai_rec_pads_cnt = ARRAY_SIZE(mx6dl_arm2_esai_record_pads);
+ spdif_pads_cnt = ARRAY_SIZE(mx6dl_arm2_spdif_pads);
+ flexcan_pads_cnt = ARRAY_SIZE(mx6dl_arm2_can_pads);
+ i2c3_pads_cnt = ARRAY_SIZE(mx6dl_arm2_i2c3_pads);
+ epdc_pads_cnt = ARRAY_SIZE(mx6dl_arm2_epdc_pads);
+ }
+
+ BUG_ON(!common_pads);
+ mxc_iomux_v3_setup_multiple_pads(common_pads, common_pads_cnt);
+
+ if (esai_record) {
+ BUG_ON(!esai_rec_pads);
+ mxc_iomux_v3_setup_multiple_pads(esai_rec_pads,
+ esai_rec_pads_cnt);
+ }
+
+ /*
+ * IEEE-1588 ts_clk, S/PDIF in and i2c3 are mutually exclusive
+ * because all of them use GPIO_16.
+ * S/PDIF out and can1 stby are mutually exclusive because both
+ * use GPIO_17.
+ */
+#ifndef CONFIG_FEC_1588
+ if (spdif_en) {
+ BUG_ON(!spdif_pads);
+ mxc_iomux_v3_setup_multiple_pads(spdif_pads, spdif_pads_cnt);
+ } else {
+ BUG_ON(!i2c3_pads);
+ mxc_iomux_v3_setup_multiple_pads(i2c3_pads, i2c3_pads_cnt);
+ }
+#else
+ /* Set GPIO_16 input for IEEE-1588 ts_clk and RMII reference clock
+ * For MX6 GPR1 bit21 meaning:
+ * Bit21: 0 - GPIO_16 pad output
+ * 1 - GPIO_16 pad input
+ */
+ mxc_iomux_set_gpr_register(1, 21, 1, 1);
+#endif
+
+ if (!spdif_en && flexcan_en) {
+ BUG_ON(!flexcan_pads);
+ mxc_iomux_v3_setup_multiple_pads(flexcan_pads,
+ flexcan_pads_cnt);
+ }
+
+ /*
+ * the following is the common devices support on the shared ARM2 boards
+ * Since i.MX6DQ/DL share the same memory/Register layout, we don't
+ * need to diff the i.MX6DQ or i.MX6DL here. We can simply use the
+ * mx6q_add_features() for the shared devices. For which only exist
+ * on each indivual SOC, we can use cpu_is_mx6q/6dl() to diff it.
+ */
+
+ gp_reg_id = arm2_dvfscore_data.reg_id;
+ soc_reg_id = arm2_dvfscore_data.soc_id;
+ pu_reg_id = arm2_dvfscore_data.pu_id;
+ mx6_arm2_init_uart();
+
+
+ imx6q_add_mipi_csi2(&mipi_csi2_pdata);
+ imx6q_add_mxc_hdmi_core(&hdmi_core_data);
+
+ imx6q_add_ipuv3(0, &ipu_data[0]);
+ if (cpu_is_mx6q())
+ imx6q_add_ipuv3(1, &ipu_data[1]);
+
+ if (cpu_is_mx6dl()) {
+ mipi_dsi_pdata.ipu_id = 0;
+ mipi_dsi_pdata.disp_id = 1;
+ ldb_data.ipu_id = 0;
+ ldb_data.disp_id = 0;
+ for (i = 0; i < ARRAY_SIZE(sabr_fb_data) / 2; i++)
+ imx6q_add_ipuv3fb(i, &sabr_fb_data[i]);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(sabr_fb_data); i++)
+ imx6q_add_ipuv3fb(i, &sabr_fb_data[i]);
+ }
+
+ if (!disable_mipi_dsi)
+ imx6q_add_mipi_dsi(&mipi_dsi_pdata);
+ imx6q_add_vdoa();
+ imx6q_add_lcdif(&lcdif_data);
+ imx6q_add_ldb(&ldb_data);
+ imx6q_add_v4l2_output(0);
+ imx6q_add_v4l2_capture(0, &capture_data[0]);
+ imx6q_add_v4l2_capture(1, &capture_data[1]);
+
+ imx6q_add_imx_snvs_rtc();
+
+ imx6q_add_imx_caam();
+
+ imx6q_add_imx_i2c(0, &mx6_arm2_i2c0_data);
+ imx6q_add_imx_i2c(1, &mx6_arm2_i2c1_data);
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ if (!spdif_en) {
+ if (disable_mipi_dsi)
+ mx6_arm2_i2c2_data.bitrate = 100000;
+ imx6q_add_imx_i2c(2, &mx6_arm2_i2c2_data);
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+ }
+
+ /* SPI */
+ imx6q_add_ecspi(0, &mx6_arm2_spi_data);
+ spi_device_init();
+
+ imx6q_add_mxc_hdmi(&hdmi_data);
+
+ imx6q_add_anatop_thermal_imx(1, &mx6_arm2_anatop_thermal_data);
+
+ if (!esai_record) {
+ imx6_init_fec(fec_data);
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */
+ mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET,
+ OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK);
+#endif
+ }
+
+ imx6q_add_pm_imx(0, &mx6_arm2_pm_data);
+ imx6q_add_sdhci_usdhc_imx(3, &mx6_arm2_sd4_data);
+ imx6q_add_sdhci_usdhc_imx(2, &mx6_arm2_sd3_data);
+ imx_add_viv_gpu(&imx6_gpu_data, &imx6_gpu_pdata);
+ if (cpu_is_mx6q())
+ imx6q_add_ahci(0, &mx6_arm2_sata_data);
+ imx6q_add_vpu();
+ mx6_arm2_init_usb();
+ mx6_arm2_init_audio();
+ platform_device_register(&arm2_vmmc_reg_devices);
+ mx6_cpu_regulator_init();
+
+ imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ imx6q_add_asrc(&imx_asrc_data);
+
+ /* DISP0 Reset - Assert for i2c disabled mode */
+ gpio_request(MX6_ARM2_DISP0_RESET, "disp0-reset");
+ gpio_direction_output(MX6_ARM2_DISP0_RESET, 0);
+
+ /* DISP0 I2C enable */
+ if (!disable_mipi_dsi) {
+ gpio_request(MX6_ARM2_DISP0_I2C_EN, "disp0-i2c");
+ gpio_direction_output(MX6_ARM2_DISP0_I2C_EN, 0);
+ }
+ gpio_request(MX6_ARM2_DISP0_PWR, "disp0-pwr");
+ gpio_direction_output(MX6_ARM2_DISP0_PWR, 1);
+
+ gpio_request(MX6_ARM2_LDB_BACKLIGHT, "ldb-backlight");
+ gpio_direction_output(MX6_ARM2_LDB_BACKLIGHT, 1);
+ imx6q_add_otp();
+ imx6q_add_viim();
+ imx6q_add_imx2_wdt(0, NULL);
+ imx6q_add_dma();
+ imx6q_add_gpmi(&mx6_gpmi_nand_platform_data);
+
+ imx6q_add_dvfs_core(&arm2_dvfscore_data);
+
+ imx6q_add_ion(0, &imx_ion_data,
+ sizeof(imx_ion_data) + sizeof(struct ion_platform_heap));
+
+ imx6q_add_mxc_pwm(0);
+ imx6q_add_mxc_pwm_backlight(0, &mx6_arm2_pwm_backlight_data);
+
+ if (spdif_en) {
+ mxc_spdif_data.spdif_core_clk = clk_get_sys("mxc_spdif.0", NULL);
+ clk_put(mxc_spdif_data.spdif_core_clk);
+ imx6q_add_spdif(&mxc_spdif_data);
+ imx6q_add_spdif_dai();
+ imx6q_add_spdif_audio_device();
+ } else if (flexcan_en) {
+ ret = gpio_request_array(mx6_flexcan_gpios,
+ ARRAY_SIZE(mx6_flexcan_gpios));
+ if (ret) {
+ pr_err("failed to request flexcan-gpios: %d\n", ret);
+ } else {
+ imx6q_add_flexcan0(&mx6_arm2_flexcan_pdata[0]);
+ imx6q_add_flexcan1(&mx6_arm2_flexcan_pdata[1]);
+ }
+ }
+
+ imx6q_add_hdmi_soc();
+ imx6q_add_hdmi_soc_dai();
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
+ imx6q_add_mlb150(&mx6_arm2_mlb150_data);
+
+ if (cpu_is_mx6dl() && epdc_enabled) {
+ BUG_ON(!epdc_pads);
+ mxc_iomux_v3_setup_multiple_pads(epdc_pads, epdc_pads_cnt);
+ imx6dl_add_imx_pxp();
+ imx6dl_add_imx_pxp_client();
+ mxc_register_device(&max17135_sensor_device, NULL);
+ imx6dl_add_imx_epdc(&epdc_data);
+ }
+ /* Add PCIe RC interface support */
+ imx6q_add_pcie(&mx6_arm2_pcie_data);
+ imx6q_add_busfreq();
+}
+
+extern void __iomem *twd_base;
+static void __init mx6_timer_init(void)
+{
+ struct clk *uart_clk;
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ mx6_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(UART4_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx6_timer_init,
+};
+
+static void __init mx6_arm2_reserve(void)
+{
+ phys_addr_t phys;
+#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE)
+ if (imx6_gpu_pdata.reserved_mem_size) {
+ phys = memblock_alloc_base(
+ imx6_gpu_pdata.reserved_mem_size, SZ_4K, SZ_2G);
+ memblock_remove(phys, imx6_gpu_pdata.reserved_mem_size);
+ imx6_gpu_pdata.reserved_mem_base = phys;
+ }
+#endif
+
+#if defined(CONFIG_ION)
+ if (imx_ion_data.heaps[0].size) {
+ phys = memblock_alloc(imx_ion_data.heaps[0].size, SZ_4K);
+ memblock_free(phys, imx_ion_data.heaps[0].size);
+ memblock_remove(phys, imx_ion_data.heaps[0].size);
+ imx_ion_data.heaps[0].base = phys;
+ }
+#endif
+}
+
+MACHINE_START(MX6Q_ARM2, "Freescale i.MX 6Quad/Solo/DualLite Armadillo2 Board")
+ .boot_params = MX6_PHYS_OFFSET + 0x100,
+ .fixup = mx6_arm2_fixup,
+ .map_io = mx6_map_io,
+ .init_irq = mx6_init_irq,
+ .init_machine = mx6_arm2_init,
+ .timer = &mxc_timer,
+ .reserve = mx6_arm2_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.h b/arch/arm/mach-mx6/board-mx6q_arm2.h
new file mode 100644
index 00000000..2a6a2052
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_arm2.h
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2012, 2013 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 <mach/iomux-mx6q.h>
+
+static iomux_v3_cfg_t mx6q_arm2_pads[] = {
+
+ /* UART4 for debug */
+ MX6Q_PAD_KEY_COL0__UART4_TXD,
+ MX6Q_PAD_KEY_ROW0__UART4_RXD,
+ /* USB HSIC ports use the same pin with ENET */
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ /* USB H2 strobe/data pin */
+ MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE,
+ MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA,
+
+ /* USB H3 strobe/data pin */
+ MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE,
+ MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA,
+ /* ENET */
+#else
+ MX6Q_PAD_KEY_COL1__ENET_MDIO,
+ MX6Q_PAD_KEY_COL2__ENET_MDC,
+ MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC,
+ MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0,
+ MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1,
+ MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2,
+ MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3,
+ MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL,
+ MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK,
+ MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC,
+ MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0,
+ MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1,
+ MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2,
+ MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3,
+ MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL,
+#ifdef CONFIG_FEC_1588
+ MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT,
+#endif
+#endif
+ /* MCLK for csi0 */
+ MX6Q_PAD_GPIO_0__CCM_CLKO,
+ MX6Q_PAD_GPIO_3__CCM_CLKO2,
+
+ /* SD1 */
+ MX6Q_PAD_SD1_CLK__USDHC1_CLK,
+ MX6Q_PAD_SD1_CMD__USDHC1_CMD,
+ MX6Q_PAD_SD1_DAT0__USDHC1_DAT0,
+ MX6Q_PAD_SD1_DAT1__USDHC1_DAT1,
+ MX6Q_PAD_SD1_DAT2__USDHC1_DAT2,
+ MX6Q_PAD_SD1_DAT3__USDHC1_DAT3,
+ /* SD2 */
+ MX6Q_PAD_SD2_CLK__USDHC2_CLK,
+ MX6Q_PAD_SD2_CMD__USDHC2_CMD,
+ MX6Q_PAD_SD2_DAT0__USDHC2_DAT0,
+ MX6Q_PAD_SD2_DAT1__USDHC2_DAT1,
+ MX6Q_PAD_SD2_DAT2__USDHC2_DAT2,
+ MX6Q_PAD_SD2_DAT3__USDHC2_DAT3,
+ /* SD3 */
+ MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6Q_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6Q_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6Q_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6Q_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+ MX6Q_PAD_SD3_RST__USDHC3_RST,
+ /* SD3 VSelect */
+ MX6Q_PAD_GPIO_18__USDHC3_VSELECT,
+ /* SD3_CD and SD3_WP */
+ MX6Q_PAD_NANDF_CS0__GPIO_6_11,
+ MX6Q_PAD_NANDF_CS1__GPIO_6_14,
+ /* SD4 */
+ MX6Q_PAD_SD4_CLK__USDHC4_CLK_50MHZ,
+ MX6Q_PAD_SD4_CMD__USDHC4_CMD_50MHZ,
+ MX6Q_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ,
+ MX6Q_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ,
+ MX6Q_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ,
+ MX6Q_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ,
+ MX6Q_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ,
+ MX6Q_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ,
+ MX6Q_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ,
+ MX6Q_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ,
+ MX6Q_PAD_NANDF_ALE__USDHC4_RST,
+ /* eCSPI1 */
+ MX6Q_PAD_EIM_EB2__ECSPI1_SS0,
+ MX6Q_PAD_EIM_D16__ECSPI1_SCLK,
+ MX6Q_PAD_EIM_D17__ECSPI1_MISO,
+ MX6Q_PAD_EIM_D18__ECSPI1_MOSI,
+ MX6Q_PAD_EIM_D19__ECSPI1_SS1,
+ MX6Q_PAD_EIM_EB2__GPIO_2_30, /*SS0*/
+ MX6Q_PAD_EIM_D19__GPIO_3_19, /*SS1*/
+
+ /* ESAI */
+ MX6Q_PAD_ENET_RXD0__ESAI1_HCKT,
+ MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT,
+ MX6Q_PAD_ENET_RXD1__ESAI1_FST,
+ MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2,
+ MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3,
+ MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1,
+ MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0,
+ MX6Q_PAD_NANDF_CS2__ESAI1_TX0,
+ MX6Q_PAD_NANDF_CS3__ESAI1_TX1,
+
+ /* I2C1 */
+ MX6Q_PAD_CSI0_DAT8__I2C1_SDA,
+ MX6Q_PAD_CSI0_DAT9__I2C1_SCL,
+
+ /* I2C2 */
+ MX6Q_PAD_KEY_COL3__I2C2_SCL,
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA,
+
+ /* DISPLAY */
+ MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15,
+ MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2,
+ MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3,
+ MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
+ MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
+ MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
+ MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
+ MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
+ MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
+ MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
+ MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
+ MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
+ MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
+ MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
+ MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
+ MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
+ MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
+ MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
+ MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
+ MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
+ MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
+ MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
+ MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
+ MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20,
+ MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
+ MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22,
+ MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23,
+
+ MX6Q_PAD_EIM_D24__GPIO_3_24,
+
+ /* UART2 */
+ MX6Q_PAD_EIM_D26__UART2_RXD,
+ MX6Q_PAD_EIM_D27__UART2_TXD,
+ MX6Q_PAD_EIM_D28__UART2_RTS,
+ MX6Q_PAD_EIM_D29__UART2_CTS,
+
+ /* PWM1 */
+ MX6Q_PAD_GPIO_9__PWM1_PWMO,
+
+ /* DISP0 DET */
+ MX6Q_PAD_EIM_D31__GPIO_3_31,
+
+ /* DISP0 RESET */
+ MX6Q_PAD_EIM_WAIT__GPIO_5_0,
+
+ /* HDMI */
+ MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE,
+ MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0,
+ MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1,
+
+ /* USBOTG ID pin */
+ MX6Q_PAD_GPIO_1__USBOTG_ID,
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1,
+#else
+ /* MLB150 */
+ MX6Q_PAD_GPIO_3__MLB_MLBCLK,
+ MX6Q_PAD_GPIO_6__MLB_MLBSIG,
+ MX6Q_PAD_GPIO_2__MLB_MLBDAT,
+#endif
+};
+
+static iomux_v3_cfg_t mx6q_arm2_i2c3_pads[] = {
+ MX6Q_PAD_GPIO_5__I2C3_SCL,
+ MX6Q_PAD_GPIO_16__I2C3_SDA,
+};
+
+static iomux_v3_cfg_t mx6q_arm2_spdif_pads[] = {
+ /* SPDIF */
+ MX6Q_PAD_GPIO_16__SPDIF_IN1,
+ MX6Q_PAD_GPIO_17__SPDIF_OUT1,
+};
+
+static iomux_v3_cfg_t mx6q_arm2_can_pads[] = {
+ /* CAN1 */
+ MX6Q_PAD_GPIO_7__CAN1_TXCAN,
+ MX6Q_PAD_KEY_ROW2__CAN1_RXCAN,
+ MX6Q_PAD_GPIO_17__GPIO_7_12, /* CAN1 STBY */
+ MX6Q_PAD_GPIO_18__GPIO_7_13, /* CAN1 EN */
+
+ /* CAN2 */
+ MX6Q_PAD_KEY_COL4__CAN2_TXCAN,
+ MX6Q_PAD_KEY_ROW4__CAN2_RXCAN,
+ MX6Q_PAD_CSI0_DAT6__GPIO_5_24, /* CAN2 EN */
+};
+
+static iomux_v3_cfg_t mx6q_arm2_esai_record_pads[] = {
+ MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR,
+ MX6Q_PAD_ENET_MDIO__ESAI1_SCKR,
+ MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR,
+};
+
+static iomux_v3_cfg_t mx6q_arm2_csi0_sensor_pads[] = {
+ MX6Q_PAD_GPIO_0__CCM_CLKO,
+ /* ipu1 csi0 */
+ MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+ MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+ /* camera reset */
+ MX6Q_PAD_GPIO_19__GPIO_4_5,
+ /* camera powerdown */
+ MX6Q_PAD_CSI0_DAT5__GPIO_5_23,
+};
+
+static iomux_v3_cfg_t mx6q_arm2_csi0_tvin_pads[] = {
+ /* ipu1 csi0 */
+ MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+ MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+ /* camera reset */
+ MX6Q_PAD_CSI0_DAT7__GPIO_5_25,
+ /* camera powerdown */
+ MX6Q_PAD_CSI0_DAT5__GPIO_5_23,
+};
+
+static iomux_v3_cfg_t mx6q_arm2_mipi_sensor_pads[] = {
+ MX6Q_PAD_CSI0_MCLK__CCM_CLKO,
+};
+
+static iomux_v3_cfg_t mx6q_arm2_audmux_pads[] = {
+
+ /* AUDMUX */
+ MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC,
+ MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD,
+ MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS,
+ MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD,
+};
+
+#define MX6Q_USDHC_PAD_SETTING(id, speed) \
+mx6q_sd##id##_##speed##mhz[] = { \
+ MX6Q_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \
+}
+
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 50);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 100);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 200);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 50);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 100);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 200);
+
+
+/* The GPMI is conflicted with SD3, so init this in the driver. */
+static iomux_v3_cfg_t mx6q_gpmi_nand[] __initdata = {
+ MX6Q_PAD_NANDF_CLE__RAWNAND_CLE,
+ MX6Q_PAD_NANDF_ALE__RAWNAND_ALE,
+ MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N,
+ MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N,
+ MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N,
+ MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N,
+ MX6Q_PAD_NANDF_RB0__RAWNAND_READY0,
+ MX6Q_PAD_SD4_DAT0__RAWNAND_DQS,
+ MX6Q_PAD_NANDF_D0__RAWNAND_D0,
+ MX6Q_PAD_NANDF_D1__RAWNAND_D1,
+ MX6Q_PAD_NANDF_D2__RAWNAND_D2,
+ MX6Q_PAD_NANDF_D3__RAWNAND_D3,
+ MX6Q_PAD_NANDF_D4__RAWNAND_D4,
+ MX6Q_PAD_NANDF_D5__RAWNAND_D5,
+ MX6Q_PAD_NANDF_D6__RAWNAND_D6,
+ MX6Q_PAD_NANDF_D7__RAWNAND_D7,
+ MX6Q_PAD_SD4_CMD__RAWNAND_RDN,
+ MX6Q_PAD_SD4_CLK__RAWNAND_WRN,
+ MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN,
+};
+
+static iomux_v3_cfg_t mx6q_arm2_hdmi_ddc_pads[] = {
+ MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_arm2_i2c2_pads[] = {
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
diff --git a/arch/arm/mach-mx6/board-mx6q_hdmidongle.c b/arch/arm/mach-mx6/board-mx6q_hdmidongle.c
new file mode 100644
index 00000000..ffd8d9af
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_hdmidongle.c
@@ -0,0 +1,800 @@
+/*
+ * Copyright (C) 2012-2013 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 <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/etherdevice.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/memory.h>
+#include <mach/iomux-mx6q.h>
+#include <mach/imx-uart.h>
+#include <mach/viv_gpu.h>
+#include <mach/ipu-v3.h>
+#include <mach/mxc_hdmi.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#ifdef CONFIG_MFD_WM831X
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/regulator.h>
+#include <linux/mfd/wm831x/gpio.h>
+#endif
+
+#include "usb.h"
+#include "devices-imx6q.h"
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "board-mx6q_hdmidongle.h"
+#include "board-mx6dl_hdmidongle.h"
+
+#define HDMIDONGLE_USB_OTG_PWR IMX_GPIO_NR(4, 15)
+#define HDMIDONGLE_USB_H1_PWR IMX_GPIO_NR(4, 14)
+#define HDMIDONGLE_ECSPI2_CS0 IMX_GPIO_NR(2, 26)
+#define HDMIDONGLE_HDMI_CEC_IN IMX_GPIO_NR(4, 11)
+
+
+#define HDMIDONGLE_BT_RST IMX_GPIO_NR(3, 7)
+#define HDMIDONGLE_BT_EN IMX_GPIO_NR(3, 9)
+#define HDMIDONGLE_WL_EN IMX_GPIO_NR(3, 10)
+
+#define HDMIDONGLE_SD2_CD IMX_GPIO_NR(1, 4)
+#define HDMIDONGLE_REVA_POWER_KEY IMX_GPIO_NR(6, 16)
+#define HDMIDONGLE_REVB_POWER_KEY IMX_GPIO_NR(1, 27)
+
+#ifdef CONFIG_IMX_PCIE
+#define HDMIDONGLE_PCIE_PWR_EN IMX_GPIO_NR(3, 7) /*fake pcie power enable */
+#define HDMIDONGLE_PCIE_RST IMX_GPIO_NR(3, 9)
+#define HDMIDONGLE_PCIE_WAKE IMX_GPIO_NR(3, 22)
+#define HDMIDONGLE_PCIE_DIS IMX_GPIO_NR(3, 10)
+#endif
+
+extern char *gp_reg_id;
+extern char *soc_reg_id;
+extern char *pu_reg_id;
+
+static const struct esdhc_platform_data mx6q_hdmidongle_sd1_data __initconst = {
+ .always_present = 1,
+};
+
+static const struct esdhc_platform_data mx6q_hdmidongle_sd2_data __initconst = {
+ .cd_gpio = HDMIDONGLE_SD2_CD,
+ .keep_power_at_suspend = 1,
+ .support_8bit = 0,
+ .delay_line = 0,
+ .cd_type = ESDHC_CD_CONTROLLER,
+};
+
+static const struct esdhc_platform_data mx6q_hdmidongle_sd3_data __initconst = {
+ .always_present = 1,
+ .keep_power_at_suspend = 1,
+ .support_8bit = 1,
+ .delay_line = 0,
+ .cd_type = ESDHC_CD_PERMANENT,
+};
+
+static const struct esdhc_platform_data mx6q_hdmidongle_revc_sd3_data __initconst = {
+ .always_present = 1,
+ .keep_power_at_suspend = 1,
+ .support_8bit = 0,
+ .delay_line = 0,
+ .cd_type = ESDHC_CD_PERMANENT,
+};
+
+
+static int __init gpmi_nand_platform_init(void)
+{
+ iomux_v3_cfg_t *nand_pads = NULL;
+ u32 nand_pads_cnt;
+
+ if (cpu_is_mx6q()) {
+ nand_pads = mx6q_gpmi_nand;
+ nand_pads_cnt = ARRAY_SIZE(mx6q_gpmi_nand);
+ } else if (cpu_is_mx6dl()) {
+ nand_pads = mx6dl_gpmi_nand;
+ nand_pads_cnt = ARRAY_SIZE(mx6dl_gpmi_nand);
+
+ }
+ BUG_ON(!nand_pads);
+ return mxc_iomux_v3_setup_multiple_pads(nand_pads, nand_pads_cnt);
+}
+
+static struct gpmi_nand_platform_data
+mx6_gpmi_nand_platform_data __initdata = {
+ .platform_init = gpmi_nand_platform_init,
+ .min_prop_delay_in_ns = 5,
+ .max_prop_delay_in_ns = 9,
+ .max_chip_count = 1,
+ .enable_bbt = 1,
+ .enable_ddr = 0,
+};
+
+static int __init board_support_onfi_nand(char *p)
+{
+ mx6_gpmi_nand_platform_data.enable_ddr = 1;
+ return 0;
+}
+
+early_param("onfi_support", board_support_onfi_nand);
+
+
+static const struct anatop_thermal_platform_data
+ mx6q_hdmidongle_anatop_thermal_data __initconst = {
+ .name = "anatop_thermal",
+};
+
+static inline void mx6q_hdmidongle_init_uart(void)
+{
+ if (board_is_mx6_reva())
+ imx6q_add_imx_uart(1, NULL);
+ imx6q_add_imx_uart(0, NULL);
+ imx6q_add_imx_uart(3, NULL);
+}
+
+static int mx6q_hdmidongle_spi_cs[] = {
+ HDMIDONGLE_ECSPI2_CS0,
+};
+
+static const struct spi_imx_master mx6q_hdmidongle_spi_data __initconst = {
+ .chipselect = mx6q_hdmidongle_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx6q_hdmidongle_spi_cs),
+};
+
+
+
+#ifdef CONFIG_MFD_WM831X
+#if 0
+/* 1.4125, 1.4125. 1.5 */
+#define WM831X_DC1_ON_CONFIG_VAL (0x48<<WM831X_DC1_ON_VSEL_SHIFT)
+#define WM831X_DC2_ON_CONFIG_VAL (0x48<<WM831X_DC2_ON_VSEL_SHIFT)
+#define WM831X_DC3_ON_CONFIG_VAL (0x1A<<WM831X_DC3_ON_VSEL_SHIFT)
+#else
+/* 1.375, 1.375. 1.5 */
+
+#define WM831X_DC1_ON_CONFIG_VAL (0x44<<WM831X_DC1_ON_VSEL_SHIFT)
+#define WM831X_DC2_ON_CONFIG_VAL (0x44<<WM831X_DC2_ON_VSEL_SHIFT)
+#define WM831X_DC3_ON_CONFIG_VAL (0x1A<<WM831X_DC3_ON_VSEL_SHIFT)
+
+#endif
+
+#define WM831X_DC1_DVS_MODE_VAL (0x02<<WM831X_DC1_DVS_SRC_SHIFT)
+#define WM831X_DC2_DVS_MODE_VAL (0x02<<WM831X_DC2_DVS_SRC_SHIFT)
+
+#define WM831X_DC1_DVS_CONTROL_VAL (0x20<<WM831X_DC1_DVS_VSEL_SHIFT)
+#define WM831X_DC2_DVS_CONTROL_VAL (0x20<<WM831X_DC2_DVS_VSEL_SHIFT)
+
+#define WM831X_DC1_DVS_MASK (WM831X_DC1_DVS_SRC_MASK|WM831X_DC1_DVS_VSEL_MASK)
+#define WM831X_DC2_DVS_MASK (WM831X_DC2_DVS_SRC_MASK|WM831X_DC1_DVS_VSEL_MASK)
+
+#define WM831X_DC1_DVS_VAL (WM831X_DC1_DVS_MODE_VAL|WM831X_DC1_DVS_CONTROL_VAL)
+#define WM831X_DC2_DVS_VAL (WM831X_DC2_DVS_MODE_VAL|WM831X_DC2_DVS_CONTROL_VAL)
+
+#define WM831X_GPN_FN_VAL_HW_EN (0x0A<<WM831X_GPN_FN_SHIFT)
+#define WM831X_GPN_FN_VAL_HW_CTL (0x0C<<WM831X_GPN_FN_SHIFT)
+#define WM831X_GPN_FN_VAL_DVS1 (0x08<<WM831X_GPN_FN_SHIFT)
+
+#define WM831X_GPN_DIR_VAL (0x1<<WM831X_GPN_DIR_SHIFT)
+#define WM831X_GPN_PULL_VAL (0x3<<WM831X_GPN_PULL_SHIFT)
+#define WM831X_GPN_INT_MODE_VAL (0x1<<WM831X_GPN_INT_MODE_SHIFT)
+#define WM831X_GPN_POL_VAL (0x1<<WM831X_GPN_POL_SHIFT)
+#define WM831X_GPN_ENA_VAL (0x1<<WM831X_GPN_ENA_SHIFT)
+
+#define WM831X_GPIO7_8_9_MASK (WM831X_GPN_DIR_MASK|WM831X_GPN_INT_MODE_MASK|WM831X_GPN_PULL_MASK|WM831X_GPN_POL_MASK|WM831X_GPN_FN_MASK)
+
+
+#define WM831X_GPIO7_VAL (WM831X_GPN_DIR_VAL|WM831X_GPN_PULL_VAL|WM831X_GPN_INT_MODE_VAL|WM831X_GPN_POL_VAL|WM831X_GPN_ENA_VAL|WM831X_GPN_FN_VAL_HW_EN)
+#define WM831X_GPIO8_VAL (WM831X_GPN_DIR_VAL|WM831X_GPN_PULL_VAL|WM831X_GPN_INT_MODE_VAL|WM831X_GPN_POL_VAL|WM831X_GPN_ENA_VAL|WM831X_GPN_FN_VAL_HW_CTL)
+#define WM831X_GPIO9_VAL (WM831X_GPN_DIR_VAL|WM831X_GPN_PULL_VAL|WM831X_GPN_INT_MODE_VAL|WM831X_GPN_POL_VAL|WM831X_GPN_ENA_VAL|WM831X_GPN_FN_VAL_DVS1)
+
+#define WM831X_STATUS_LED_MASK 0xC000
+#define WM831X_STATUS_LED_ON (0x1 << 14)
+#define WM831X_STATUS_LED_OFF (0x0 << 14)
+
+static int wm8326_post_init(struct wm831x *wm831x)
+{
+ wm831x_set_bits(wm831x, WM831X_DC1_ON_CONFIG, WM831X_DC1_ON_VSEL_MASK, WM831X_DC1_ON_CONFIG_VAL);
+ wm831x_set_bits(wm831x, WM831X_DC2_ON_CONFIG, WM831X_DC2_ON_VSEL_MASK, WM831X_DC2_ON_CONFIG_VAL);
+ wm831x_set_bits(wm831x, WM831X_DC3_ON_CONFIG, WM831X_DC3_ON_VSEL_MASK, WM831X_DC3_ON_CONFIG_VAL);
+
+ wm831x_set_bits(wm831x, WM831X_DC1_DVS_CONTROL, WM831X_DC1_DVS_MASK, WM831X_DC1_DVS_VAL);
+ wm831x_set_bits(wm831x, WM831X_DC2_DVS_CONTROL, WM831X_DC2_DVS_MASK, WM831X_DC2_DVS_VAL);
+
+ wm831x_set_bits(wm831x, WM831X_GPIO7_CONTROL, WM831X_GPIO7_8_9_MASK, WM831X_GPIO7_VAL);
+ wm831x_set_bits(wm831x, WM831X_GPIO8_CONTROL, WM831X_GPIO7_8_9_MASK, WM831X_GPIO8_VAL);
+ wm831x_set_bits(wm831x, WM831X_GPIO9_CONTROL, WM831X_GPIO7_8_9_MASK, WM831X_GPIO9_VAL);
+
+ wm831x_set_bits(wm831x, WM831X_STATUS_LED_1 , WM831X_STATUS_LED_MASK, WM831X_STATUS_LED_OFF);
+ wm831x_set_bits(wm831x, WM831X_STATUS_LED_2 , WM831X_STATUS_LED_MASK, WM831X_STATUS_LED_ON);
+ return 0;
+}
+
+static struct wm831x_pdata hdmidongle_wm8326_pdata = {
+ .post_init = wm8326_post_init,
+};
+#endif
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+#ifdef CONFIG_MFD_WM831X
+ I2C_BOARD_INFO("wm8326", 0x34),
+ .platform_data = &hdmidongle_wm8326_pdata,
+#endif
+ },
+};
+
+static struct spi_board_info wm8326_spi1_board_info[] __initdata = {
+#if defined(CONFIG_MFD_WM831X_SPI)
+ {
+ /* The modalias must be the same as spi device driver name */
+ .modalias = "wm8326",
+ .max_speed_hz = 20000000,
+ .bus_num = 1,
+ .chip_select = 0,
+ },
+#endif
+};
+
+static void spi_device_init(void)
+{
+ spi_register_board_info(wm8326_spi1_board_info,
+ ARRAY_SIZE(wm8326_spi1_board_info));
+}
+
+static struct imxi2c_platform_data mx6q_hdmidongle_i2c_data = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50),
+ },
+};
+
+
+static void imx6q_hdmidongle_usbotg_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(HDMIDONGLE_USB_OTG_PWR, 1);
+ else
+ gpio_set_value(HDMIDONGLE_USB_OTG_PWR, 0);
+}
+
+static void __init imx6q_hdmidongle_init_usb(void)
+{
+ int ret = 0;
+
+ imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR);
+ /* disable external charger detect,
+ * or it will affect signal quality at dp .
+ */
+ ret = gpio_request(HDMIDONGLE_USB_OTG_PWR, "usb-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO HDMIDONGLE_USB_OTG_PWR: %d\n",
+ ret);
+ return;
+ }
+ gpio_direction_output(HDMIDONGLE_USB_OTG_PWR, 0);
+ /* keep USB host1 VBUS always on */
+ if (board_is_mx6_reva()) {
+ ret = gpio_request(HDMIDONGLE_USB_H1_PWR, "usb-h1-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO HDMIDONGLE_USB_H1_PWR: %d\n",
+ ret);
+ return;
+ }
+ gpio_direction_output(HDMIDONGLE_USB_H1_PWR, 1);
+ }
+ mxc_iomux_set_gpr_register(1, 13, 1, 1);
+
+ mx6_set_otghost_vbus_func(imx6q_hdmidongle_usbotg_vbus);
+}
+
+
+static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
+ .reserved_mem_size = SZ_128M + SZ_64M,
+};
+
+
+static struct ipuv3_fb_platform_data hdmidongle_fb_data[] = {
+ {/*fb0*/
+ .disp_dev = "hdmi",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB24,
+ .mode_str = "1920x1080M@60",
+ .default_bpp = 32,
+ .int_clk = false,
+ },
+};
+
+static void hdmi_init(int ipu_id, int disp_id)
+{
+ int hdmi_mux_setting;
+
+ if ((ipu_id > 1) || (ipu_id < 0)) {
+ pr_err("Invalid IPU select for HDMI: %d. Set to 0\n", ipu_id);
+ ipu_id = 0;
+ }
+
+ if ((disp_id > 1) || (disp_id < 0)) {
+ pr_err("Invalid DI select for HDMI: %d. Set to 0\n", disp_id);
+ disp_id = 0;
+ }
+
+ /* Configure the connection between IPU1/2 and HDMI */
+ hdmi_mux_setting = 2*ipu_id + disp_id;
+
+ /* GPR3, bits 2-3 = HDMI_MUX_CTL */
+ mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
+ /* Set HDMI event as SDMA event2 while Chip version later than TO1.2 */
+ if (hdmi_SDMA_check())
+ mxc_iomux_set_gpr_register(0, 0, 1, 1);
+}
+
+/* On mx6x sabresd board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_hdmidongle_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6dl_hdmidongle_hdmi_ddc_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_hdmidongle_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_hdmidongle_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_hdmidongle_i2c2_pads,
+ ARRAY_SIZE(mx6dl_hdmidongle_i2c2_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_hdmidongle_i2c2_pads,
+ ARRAY_SIZE(mx6q_hdmidongle_i2c2_pads));
+}
+
+
+static struct fsl_mxc_hdmi_platform_data hdmi_data = {
+ .init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
+ .phy_reg_vlev = 0x0294,
+ .phy_reg_cksymtx = 0x800d,
+};
+
+static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+};
+
+static struct imx_ipuv3_platform_data ipu_data[] = {
+ {
+ .rev = 4,
+ .csi_clk[0] = "clko_clk",
+ }, {
+ .rev = 4,
+ .csi_clk[0] = "clko_clk",
+ },
+};
+
+static void hdmidongle_suspend_enter(void)
+{
+ /* suspend preparation */
+}
+
+static void hdmidongle_suspend_exit(void)
+{
+ /* resume restore */
+}
+static const struct pm_platform_data mx6q_hdmidongle_pm_data __initconst = {
+ .name = "imx_pm",
+ .suspend_enter = hdmidongle_suspend_enter,
+ .suspend_exit = hdmidongle_suspend_exit,
+};
+
+static struct regulator_consumer_supply hdmidongle_vmmc_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.3"),
+};
+
+static struct regulator_init_data hdmidongle_vmmc_init = {
+ .num_consumer_supplies = ARRAY_SIZE(hdmidongle_vmmc_consumers),
+ .consumer_supplies = hdmidongle_vmmc_consumers,
+};
+
+static struct fixed_voltage_config hdmidongle_vmmc_reg_config = {
+ .supply_name = "vmmc",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &hdmidongle_vmmc_init,
+};
+
+static struct platform_device hdmidongle_vmmc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 3,
+ .dev = {
+ .platform_data = &hdmidongle_vmmc_reg_config,
+ },
+};
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake, debounce) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+ .debounce_interval = debounce, \
+}
+
+static struct gpio_keys_button hdmidongle_reva_buttons[] = {
+ GPIO_BUTTON(HDMIDONGLE_REVA_POWER_KEY, KEY_POWER, 1, "power", 1, 1),
+};
+
+static struct gpio_keys_platform_data hdmidongle_reva_button_data = {
+ .buttons = hdmidongle_reva_buttons,
+ .nbuttons = ARRAY_SIZE(hdmidongle_reva_buttons),
+};
+
+static struct platform_device hdmidongle_reva_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &hdmidongle_reva_button_data,
+ }
+};
+
+static struct gpio_keys_button hdmidongle_revb_buttons[] = {
+ GPIO_BUTTON(HDMIDONGLE_REVB_POWER_KEY, KEY_POWER, 1, "power", 1, 1),
+};
+
+static struct gpio_keys_platform_data hdmidongle_revb_button_data = {
+ .buttons = hdmidongle_revb_buttons,
+ .nbuttons = ARRAY_SIZE(hdmidongle_revb_buttons),
+};
+
+static struct platform_device hdmidongle_revb_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &hdmidongle_revb_button_data,
+ }
+};
+
+
+static void __init imx6q_add_device_buttons(void)
+{
+ if (board_is_mx6_reva())
+ platform_device_register(&hdmidongle_reva_button_device);
+ else
+ platform_device_register(&hdmidongle_revb_button_device);
+}
+#else
+static void __init imx6q_add_device_buttons(void) {}
+#endif
+
+static struct mxc_dvfs_platform_data hdmidongle_dvfscore_data = {
+ #ifdef CONFIG_MX6_INTER_LDO_BYPASS
+ .reg_id = "VDDCORE",
+ #else
+ .reg_id = "cpu_vddgp",
+ .soc_id = "cpu_vddsoc",
+ .pu_id = "cpu_vddvpu",
+ #endif
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+};
+
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ char *str;
+ struct tag *t;
+ int i = 0;
+ struct ipuv3_fb_platform_data *pdata_fb = hdmidongle_fb_data;
+
+ for_each_tag(t, tags) {
+ if (t->hdr.tag == ATAG_CMDLINE) {
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "fbmem=");
+ if (str != NULL) {
+ str += 6;
+ pdata_fb[i++].res_size[0] = memparse(str, &str);
+ while (*str == ',' &&
+ i < ARRAY_SIZE(hdmidongle_fb_data)) {
+ str++;
+ pdata_fb[i++].res_size[0] = memparse(str, &str);
+ }
+ }
+ break;
+ }
+ }
+}
+
+#define SNVS_LPCR 0x38
+static void mx6_snvs_poweroff(void)
+{
+
+ void __iomem *mx6_snvs_base = MX6_IO_ADDRESS(MX6Q_SNVS_BASE_ADDR);
+ u32 value;
+ value = readl(mx6_snvs_base + SNVS_LPCR);
+ /*set TOP and DP_EN bit*/
+ writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
+}
+
+#ifdef CONFIG_IMX_PCIE
+static const struct imx_pcie_platform_data mx6_hdmidongle_pcie_data __initconst = {
+ .pcie_pwr_en = HDMIDONGLE_PCIE_PWR_EN,
+ .pcie_rst = HDMIDONGLE_PCIE_RST,
+ .pcie_wake_up = HDMIDONGLE_PCIE_WAKE,
+ .pcie_dis = HDMIDONGLE_PCIE_DIS,
+};
+#endif
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mx6_hdmidongle_board_init(void)
+{
+ int i;
+
+ if (cpu_is_mx6q()) {
+ if (board_is_mx6_revb() || board_is_mx6_revc())
+ mxc_iomux_v3_setup_multiple_pads(mx6q_hdmidongle_rev_b_pads,
+ ARRAY_SIZE(mx6q_hdmidongle_rev_b_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_hdmidongle_rev_a_pads,
+ ARRAY_SIZE(mx6q_hdmidongle_rev_a_pads));
+ } else if (cpu_is_mx6dl()) {
+ if (board_is_mx6_revb() || board_is_mx6_revc())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_hdmidongle_rev_b_pads,
+ ARRAY_SIZE(mx6dl_hdmidongle_rev_b_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_hdmidongle_rev_a_pads,
+ ARRAY_SIZE(mx6dl_hdmidongle_rev_a_pads));
+ }
+
+ gp_reg_id = hdmidongle_dvfscore_data.reg_id;
+ soc_reg_id = hdmidongle_dvfscore_data.soc_id;
+ pu_reg_id = hdmidongle_dvfscore_data.pu_id;
+ mx6q_hdmidongle_init_uart();
+
+ /*
+ * MX6DL/Solo only supports single IPU
+ * The following codes are used to change ipu id
+ * and display id information for MX6DL/Solo. Then
+ * register 1 IPU device and up to 2 displays for
+ * MX6DL/Solo
+ */
+ if (cpu_is_mx6dl())
+ hdmi_core_data.disp_id = 0;
+
+ imx6q_add_mxc_hdmi_core(&hdmi_core_data);
+
+ imx6q_add_ipuv3(0, &ipu_data[0]);
+ if (cpu_is_mx6q())
+ imx6q_add_ipuv3(1, &ipu_data[1]);
+ for (i = 0; i < ARRAY_SIZE(hdmidongle_fb_data); i++)
+ imx6q_add_ipuv3fb(i, &hdmidongle_fb_data[i]);
+
+ imx6q_add_vdoa();
+
+ imx6q_add_v4l2_output(0);
+
+ imx6q_add_imx_snvs_rtc();
+
+ imx6q_add_imx_i2c(1, &mx6q_hdmidongle_i2c_data);
+ imx6q_add_imx_i2c(2, &mx6q_hdmidongle_i2c_data);
+
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+
+
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+
+
+ /* SPI */
+ imx6q_add_ecspi(1, &mx6q_hdmidongle_spi_data);
+ spi_device_init();
+
+ imx6q_add_mxc_hdmi(&hdmi_data);
+
+ imx6q_add_anatop_thermal_imx(1, &mx6q_hdmidongle_anatop_thermal_data);
+ imx6q_add_pm_imx(0, &mx6q_hdmidongle_pm_data);
+ /* Move sd3 to first because sd3 connect to emmc.
+ Mfgtools want emmc is mmcblk0 and other sd card is mmcblk1.
+ */
+ if (board_is_mx6_revc())
+ imx6q_add_sdhci_usdhc_imx(2, &mx6q_hdmidongle_revc_sd3_data);
+ else
+ imx6q_add_sdhci_usdhc_imx(2, &mx6q_hdmidongle_sd3_data);
+ imx6q_add_sdhci_usdhc_imx(1, &mx6q_hdmidongle_sd2_data);
+ if (board_is_mx6_reva())
+ imx6q_add_sdhci_usdhc_imx(0, &mx6q_hdmidongle_sd1_data);
+ imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata);
+ imx6q_hdmidongle_init_usb();
+
+ imx6q_add_vpu();
+
+ platform_device_register(&hdmidongle_vmmc_reg_devices);
+
+ imx6q_add_otp();
+ imx6q_add_viim();
+ imx6q_add_imx2_wdt(0, NULL);
+ imx6q_add_dma();
+ if (board_is_mx6_revb() || board_is_mx6_revc())
+ imx6q_add_gpmi(&mx6_gpmi_nand_platform_data);
+
+ imx6q_add_dvfs_core(&hdmidongle_dvfscore_data);
+ #ifndef CONFIG_MX6_INTER_LDO_BYPASS
+ mx6_cpu_regulator_init();
+ #endif
+
+ imx6q_add_device_buttons();
+
+ imx6q_add_hdmi_soc();
+ imx6q_add_hdmi_soc_dai();
+
+ if (board_is_mx6_reva()) {
+ gpio_request(HDMIDONGLE_BT_RST, "bt_reset");
+ gpio_direction_output(HDMIDONGLE_BT_RST, 1);
+ gpio_set_value(HDMIDONGLE_BT_RST, 1);
+ msleep(1000);
+ gpio_request(HDMIDONGLE_BT_EN, "bt_en");
+ gpio_direction_output(HDMIDONGLE_BT_EN, 1);
+ gpio_set_value(HDMIDONGLE_BT_EN, 1);
+
+ msleep(1000);
+ gpio_request(HDMIDONGLE_WL_EN, "wl_en");
+ gpio_direction_output(HDMIDONGLE_WL_EN, 1);
+ gpio_set_value(HDMIDONGLE_WL_EN, 1);
+ msleep(1000);
+ } else if (board_is_mx6_revb() || board_is_mx6_revc()) {
+ /* Add PCIe RC interface support */
+#ifdef CONFIG_IMX_PCIE
+ imx6q_add_pcie(&mx6_hdmidongle_pcie_data);
+#endif
+ }
+ pm_power_off = mx6_snvs_poweroff;
+ imx6q_add_busfreq();
+}
+
+extern void __iomem *twd_base;
+static void __init mx6_hdmidongle_timer_init(void)
+{
+ struct clk *uart_clk;
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ mx6_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(UART4_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mx6_hdmidongle_timer = {
+ .init = mx6_hdmidongle_timer_init,
+};
+
+static void __init mx6q_hdmidongle_reserve(void)
+{
+ phys_addr_t phys;
+ int i;
+
+#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE)
+ if (imx6q_gpu_pdata.reserved_mem_size) {
+ phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size,
+ SZ_4K, SZ_1G);
+ memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size);
+ imx6q_gpu_pdata.reserved_mem_base = phys;
+ }
+#endif
+#if defined(CONFIG_ION)
+ if (imx_ion_data.heaps[0].size) {
+ phys = memblock_alloc(imx_ion_data.heaps[0].size, SZ_4K);
+ memblock_remove(phys, imx_ion_data.heaps[0].size);
+ imx_ion_data.heaps[0].base = phys;
+ }
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(hdmidongle_fb_data); i++)
+ if (hdmidongle_fb_data[i].res_size[0]) {
+ /* reserve for background buffer */
+ phys = memblock_alloc(hdmidongle_fb_data[i].res_size[0],
+ SZ_4K);
+ memblock_remove(phys, hdmidongle_fb_data[i].res_size[0]);
+ hdmidongle_fb_data[i].res_base[0] = phys;
+ }
+}
+
+/*
+ * initialize __mach_desc_MX6Q_HDMIDONGLE data structure.
+ */
+MACHINE_START(MX6Q_HDMIDONGLE, "Freescale i.MX 6Quad/DualLite HDMI Dongle Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .boot_params = MX6_PHYS_OFFSET + 0x100,
+ .fixup = fixup_mxc_board,
+ .map_io = mx6_map_io,
+ .init_irq = mx6_init_irq,
+ .init_machine = mx6_hdmidongle_board_init,
+ .timer = &mx6_hdmidongle_timer,
+ .reserve = mx6q_hdmidongle_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-mx6/board-mx6q_hdmidongle.h b/arch/arm/mach-mx6/board-mx6q_hdmidongle.h
new file mode 100644
index 00000000..9338c3e6
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_hdmidongle.h
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _BOARD_MX6Q_HDMIDONGLE_H
+#define _BOARD_MX6Q_HDMIDONGLE_H
+#include <mach/iomux-mx6q.h>
+
+static iomux_v3_cfg_t mx6q_hdmidongle_rev_a_pads[] = {
+ /* SPI2 for PMIC communication port */
+ MX6Q_PAD_EIM_OE__ECSPI2_MISO,
+ MX6Q_PAD_EIM_RW__ECSPI2_SS0,
+ MX6Q_PAD_EIM_CS0__ECSPI2_SCLK,
+ MX6Q_PAD_EIM_CS1__ECSPI2_MOSI,
+
+ /*USB_OTG_DET(USB OTG cable plug detect) */
+ MX6Q_PAD_EIM_A16__GPIO_2_22,
+ /*BT_WAKEUP_HOST(Combo module BT wake-up output) */
+ MX6Q_PAD_EIM_A25__GPIO_5_2,
+ /* HOST_WAKEUP_BT(CPU wakeup BT signal)*/
+ MX6Q_PAD_EIM_D16__GPIO_3_16,
+
+ /* I2C3 */
+ MX6Q_PAD_EIM_D17__I2C3_SCL,
+ MX6Q_PAD_EIM_D18__I2C3_SDA,
+
+ /* USB OC pin */
+ MX6Q_PAD_EIM_D21__USBOH3_USBOTG_OC,
+ /* WLAN_WAKEUP_HOST(Combo module WLAN host wake-up output) */
+ MX6Q_PAD_EIM_D22__GPIO_3_22,
+
+ /* BT_UART2 */
+ MX6Q_PAD_EIM_D26__UART2_TXD,
+ MX6Q_PAD_EIM_D27__UART2_RXD,
+ MX6Q_PAD_EIM_D28__UART2_CTS,
+ MX6Q_PAD_EIM_D29__UART2_RTS,
+
+ /*BT_nRST(Combo module BT reset signal)*/
+ MX6Q_PAD_EIM_DA7__GPIO_3_7,
+
+ /*BT_REG_ON(Combo module BT Internal regulators power enable/disable)*/
+ MX6Q_PAD_EIM_DA9__GPIO_3_9,
+
+ /*WL_REG_ON(Combo module WLAN Internal regulators power enable/disable)*/
+ MX6Q_PAD_EIM_DA10__GPIO_3_10,
+
+ /* GPIO2 */
+ MX6Q_PAD_EIM_A22__GPIO_2_16, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A21__GPIO_2_17, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A20__GPIO_2_18, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A19__GPIO_2_19, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A18__GPIO_2_20, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A17__GPIO_2_21, /* Boot Mode Select */
+ MX6Q_PAD_EIM_RW__GPIO_2_26, /* Boot Mode Select */
+ MX6Q_PAD_EIM_LBA__GPIO_2_27, /* Boot Mode Select */
+ MX6Q_PAD_EIM_EB0__GPIO_2_28, /* Boot Mode Select */
+ MX6Q_PAD_EIM_EB1__GPIO_2_29, /* Boot Mode Select */
+ MX6Q_PAD_EIM_EB2__GPIO_2_30, /* Boot Mode Select */
+ MX6Q_PAD_EIM_EB3__GPIO_2_31, /* Boot Mode Select */
+
+ /* GPIO3 */
+ MX6Q_PAD_EIM_DA0__GPIO_3_0, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA1__GPIO_3_1, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA2__GPIO_3_2, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA3__GPIO_3_3, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA4__GPIO_3_4, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA5__GPIO_3_5, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA6__GPIO_3_6, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA8__GPIO_3_8, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA11__GPIO_3_11, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA12__GPIO_3_12, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA13__GPIO_3_13, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA14__GPIO_3_14, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA15__GPIO_3_15, /* Boot Mode Select */
+
+ /* GPIO5 */
+ MX6Q_PAD_EIM_WAIT__GPIO_5_0, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A24__GPIO_5_4, /* Boot Mode Select */
+
+ /* GPIO6 */
+ MX6Q_PAD_EIM_A23__GPIO_6_6, /* Boot Mode Select */
+
+ /* I2C1 */
+ MX6Q_PAD_CSI0_DAT8__I2C1_SDA,
+ MX6Q_PAD_CSI0_DAT9__I2C1_SCL,
+
+ /* UART1 for debug */
+ MX6Q_PAD_CSI0_DAT10__UART1_TXD,
+ MX6Q_PAD_CSI0_DAT11__UART1_RXD,
+
+ /* SD1 (Combo module WLAN SDIO )*/
+ MX6Q_PAD_SD1_CLK__USDHC1_CLK,
+ MX6Q_PAD_SD1_CMD__USDHC1_CMD,
+ MX6Q_PAD_SD1_DAT0__USDHC1_DAT0,
+ MX6Q_PAD_SD1_DAT1__USDHC1_DAT1,
+ MX6Q_PAD_SD1_DAT2__USDHC1_DAT2,
+ MX6Q_PAD_SD1_DAT3__USDHC1_DAT3,
+
+ /* SD2 (MicroSD SDIO CMD)*/
+ MX6Q_PAD_SD2_CLK__USDHC2_CLK,
+ MX6Q_PAD_SD2_CMD__USDHC2_CMD,
+ MX6Q_PAD_SD2_DAT0__USDHC2_DAT0,
+ MX6Q_PAD_SD2_DAT1__USDHC2_DAT1,
+ MX6Q_PAD_SD2_DAT2__USDHC2_DAT2,
+ MX6Q_PAD_SD2_DAT3__USDHC2_DAT3,
+ /*SD_DET (SD plug-in detect interrupt)*/
+ MX6Q_PAD_GPIO_4__GPIO_1_4,
+
+ /* SD3 (eMMC SDIO)*/
+ MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6Q_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6Q_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6Q_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6Q_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+ MX6Q_PAD_SD3_RST__USDHC3_RST,
+
+ /* UART4 for debug */
+ MX6Q_PAD_KEY_COL0__UART4_TXD,
+ MX6Q_PAD_KEY_ROW0__UART4_RXD,
+
+ /*HDMI CEC communication PIN*/
+ MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE,
+
+ /* I2C2 */
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* GPIO4[12] */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* GPIO4[13] */
+
+ /*DCDC5V_PWREN(5V DCDC BOOST control signal)*/
+ MX6Q_PAD_KEY_COL4__GPIO_4_14,
+
+ /*USB_OTG_PWREN(USB OTG power change control signal)*/
+ MX6Q_PAD_KEY_ROW4__GPIO_4_15,
+
+ /* USBOTG ID pin */
+ MX6Q_PAD_GPIO_1__USBOTG_ID,
+
+ /* I2C3 */
+ MX6Q_PAD_GPIO_5__I2C3_SCL,
+ MX6Q_PAD_GPIO_16__I2C3_SDA,
+
+ /*WDOG(Watch dog output)*/
+ MX6Q_PAD_GPIO_9__GPIO_1_9,
+
+ /*PMIC_nINT(PMIC interrupt signal)*/
+ MX6Q_PAD_NANDF_CS0__GPIO_6_11,
+
+ /*GPIO_nRST(GPIO shutdown control)*/
+ MX6Q_PAD_NANDF_CS1__GPIO_6_14,
+
+ /*PWRKEY_DET(Power key press detection)*/
+ MX6Q_PAD_NANDF_CS3__GPIO_6_16,
+
+ /*CHG_SYS_ON(Charger auto power on control signal)*/
+ MX6Q_PAD_NANDF_D6__GPIO_2_6,
+
+ /*IR_RC*/
+ MX6Q_PAD_SD4_DAT6__GPIO_2_14,
+};
+
+static iomux_v3_cfg_t mx6q_hdmidongle_rev_b_pads[] = {
+ /* SPI2 for PMIC communication port */
+ MX6Q_PAD_EIM_OE__ECSPI2_MISO,
+ MX6Q_PAD_EIM_RW__ECSPI2_SS0,
+ MX6Q_PAD_EIM_CS0__ECSPI2_SCLK,
+ MX6Q_PAD_EIM_CS1__ECSPI2_MOSI,
+
+ /*USB_OTG_DET(USB OTG cable plug detect) */
+ MX6Q_PAD_EIM_A16__GPIO_2_22,
+ /*WLAN_CLKREQn*/
+ MX6Q_PAD_EIM_A25__GPIO_5_2,
+
+ /* WLAN_ACT */
+ MX6Q_PAD_EIM_D17__GPIO_3_17,
+
+ /*BT_PERI*/
+ MX6Q_PAD_EIM_D18__GPIO_3_18,
+
+ /* USB OC pin */
+ MX6Q_PAD_EIM_D21__USBOH3_USBOTG_OC,
+
+ /* WLAN_WAKEn (PM event, OD, used to reactivate the PCIe main PWR and REF CLK) */
+ MX6Q_PAD_EIM_D22__GPIO_3_22,
+
+
+ /*WLAN_PERSTn (PCIe rst signal, avtive LOW)*/
+ MX6Q_PAD_EIM_DA9__GPIO_3_9,
+
+ /*WLAN_PDn (Externally shutdown RTL8192)*/
+ MX6Q_PAD_EIM_DA10__GPIO_3_10,
+
+ /* GPIO2 */
+ MX6Q_PAD_EIM_A22__GPIO_2_16, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A21__GPIO_2_17, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A20__GPIO_2_18, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A19__GPIO_2_19, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A18__GPIO_2_20, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A17__GPIO_2_21, /* Boot Mode Select */
+ MX6Q_PAD_EIM_RW__GPIO_2_26, /* Boot Mode Select */
+ MX6Q_PAD_EIM_LBA__GPIO_2_27, /* Boot Mode Select */
+ MX6Q_PAD_EIM_EB0__GPIO_2_28, /* Boot Mode Select */
+ MX6Q_PAD_EIM_EB1__GPIO_2_29, /* Boot Mode Select */
+ MX6Q_PAD_EIM_EB2__GPIO_2_30, /* Boot Mode Select */
+ MX6Q_PAD_EIM_EB3__GPIO_2_31, /* Boot Mode Select */
+
+ /* GPIO3 */
+ MX6Q_PAD_EIM_DA0__GPIO_3_0, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA1__GPIO_3_1, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA2__GPIO_3_2, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA3__GPIO_3_3, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA4__GPIO_3_4, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA5__GPIO_3_5, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA6__GPIO_3_6, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA8__GPIO_3_8, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA11__GPIO_3_11, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA12__GPIO_3_12, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA13__GPIO_3_13, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA14__GPIO_3_14, /* Boot Mode Select */
+ MX6Q_PAD_EIM_DA15__GPIO_3_15, /* Boot Mode Select */
+
+ /* GPIO5 */
+ MX6Q_PAD_EIM_WAIT__GPIO_5_0, /* Boot Mode Select */
+ MX6Q_PAD_EIM_A24__GPIO_5_4, /* Boot Mode Select */
+
+ /* GPIO6 */
+ MX6Q_PAD_EIM_A23__GPIO_6_6, /* Boot Mode Select */
+
+
+ /* SD2 (MicroSD SDIO CMD)*/
+ MX6Q_PAD_SD2_CLK__USDHC2_CLK,
+ MX6Q_PAD_SD2_CMD__USDHC2_CMD,
+ MX6Q_PAD_SD2_DAT0__USDHC2_DAT0,
+ MX6Q_PAD_SD2_DAT1__USDHC2_DAT1,
+ MX6Q_PAD_SD2_DAT2__USDHC2_DAT2,
+ MX6Q_PAD_SD2_DAT3__USDHC2_DAT3,
+ /*SD_DET (SD plug-in detect interrupt)*/
+ MX6Q_PAD_GPIO_4__GPIO_1_4,
+
+ /* SD3 (eMMC SDIO)*/
+ MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6Q_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6Q_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6Q_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6Q_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+ MX6Q_PAD_SD3_RST__USDHC3_RST,
+
+ /* UART4 for debug */
+ MX6Q_PAD_KEY_COL0__UART4_TXD,
+ MX6Q_PAD_KEY_ROW0__UART4_RXD,
+
+ /*SD2_VSELECT (SD2 SDXC power exchange control signal)*/
+ MX6Q_PAD_KEY_ROW1__GPIO_4_9,
+
+ /*HDMI CEC communication PIN*/
+ MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE,
+
+ /*PWRKEY_DET (Pwr button detection interrupt)*/
+ MX6Q_PAD_ENET_RXD0__GPIO_1_27,
+
+ /*USB_OTG_PWREN(USB OTG power change control signal)*/
+ MX6Q_PAD_KEY_ROW4__GPIO_4_15,
+
+ /* USBOTG ID pin */
+ MX6Q_PAD_GPIO_1__USBOTG_ID,
+
+ /* I2C2 */
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* GPIO4[12] */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* GPIO4[13] */
+
+ /* I2C3 */
+ MX6Q_PAD_GPIO_5__I2C3_SCL,
+ MX6Q_PAD_GPIO_16__I2C3_SDA,
+
+ /*WDOG(Watch dog output)*/
+ MX6Q_PAD_GPIO_9__GPIO_1_9,
+
+ /*PMIC_nINT(PMIC interrupt signal)*/
+ MX6Q_PAD_SD4_DAT3__GPIO_2_11,
+
+ /*GPIO_nRST(GPIO shutdown control)*/
+ MX6Q_PAD_SD4_DAT1__GPIO_2_9,
+
+ /*CHG_SYS_ON(Charger auto power on control signal)*/
+ MX6Q_PAD_SD4_DAT6__GPIO_2_14,
+};
+
+/* The GPMI is conflicted with SD3, so init this in the driver. */
+static iomux_v3_cfg_t mx6q_gpmi_nand[] __initdata = {
+ MX6Q_PAD_NANDF_CLE__RAWNAND_CLE,
+ MX6Q_PAD_NANDF_ALE__RAWNAND_ALE,
+ MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N,
+ MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N,
+ MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N,
+ MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N,
+ MX6Q_PAD_NANDF_RB0__RAWNAND_READY0,
+ MX6Q_PAD_SD4_DAT0__RAWNAND_DQS,
+ MX6Q_PAD_NANDF_D0__RAWNAND_D0,
+ MX6Q_PAD_NANDF_D1__RAWNAND_D1,
+ MX6Q_PAD_NANDF_D2__RAWNAND_D2,
+ MX6Q_PAD_NANDF_D3__RAWNAND_D3,
+ MX6Q_PAD_NANDF_D4__RAWNAND_D4,
+ MX6Q_PAD_NANDF_D5__RAWNAND_D5,
+ MX6Q_PAD_NANDF_D6__RAWNAND_D6,
+ MX6Q_PAD_NANDF_D7__RAWNAND_D7,
+ MX6Q_PAD_SD4_CMD__RAWNAND_RDN,
+ MX6Q_PAD_SD4_CLK__RAWNAND_WRN,
+ MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN,
+};
+
+static iomux_v3_cfg_t mx6q_hdmidongle_hdmi_ddc_pads[] = {
+ MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_hdmidongle_i2c2_pads[] = {
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
+
+#endif
diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c
new file mode 100644
index 00000000..01b07faf
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c
@@ -0,0 +1,1764 @@
+/*
+ * Copyright (C) 2011-2012 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 <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+#include <linux/spi/flash.h>
+#else
+#include <linux/mtd/physmap.h>
+#endif
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/ion.h>
+#include <linux/etherdevice.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mxc_asrc.h>
+#include <sound/pcm.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/memory.h>
+#include <mach/iomux-mx6q.h>
+#include <mach/imx-uart.h>
+#include <mach/viv_gpu.h>
+#include <mach/ahci_sata.h>
+#include <mach/ipu-v3.h>
+#include <mach/mxc_hdmi.h>
+#include <mach/mxc_asrc.h>
+#include <mach/mipi_dsi.h>
+#include <mach/mipi_csi2.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "usb.h"
+#include "devices-imx6q.h"
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "board-mx6q_sabreauto.h"
+#include "board-mx6solo_sabreauto.h"
+
+/* sorted by GPIO_NR */
+#define SABREAUTO_SD1_CD IMX_GPIO_NR(1, 1)
+#define SABREAUTO_ESAI_INT IMX_GPIO_NR(1, 10)
+#define SABREAUTO_ANDROID_HOME IMX_GPIO_NR(1, 11)
+#define SABREAUTO_ANDROID_BACK IMX_GPIO_NR(1, 12)
+#define SABREAUTO_SD3_WP IMX_GPIO_NR(1, 13)
+#define SABREAUTO_I2C_EXP_RST IMX_GPIO_NR(1, 15)
+#define SABREAUTO_USB_OTG_OC IMX_GPIO_NR(2, 8)
+#define SABREAUTO_LDB_BACKLIGHT3 IMX_GPIO_NR(2, 9)
+#define SABREAUTO_LDB_BACKLIGHT4 IMX_GPIO_NR(2, 10)
+#define SABREAUTO_ANDROID_MENU IMX_GPIO_NR(2, 12)
+#define SABREAUTO_ANDROID_VOLUP IMX_GPIO_NR(2, 15)
+#define SABREAUTO_CAP_TCH_INT IMX_GPIO_NR(2, 28)
+#define SABREAUTO_ECSPI1_CS1 IMX_GPIO_NR(3, 19)
+#define SABREAUTO_DISP0_PWR IMX_GPIO_NR(3, 24)
+#define SABREAUTO_DISP0_I2C_EN IMX_GPIO_NR(3, 28)
+#define SABREAUTO_DISP0_DET_INT IMX_GPIO_NR(3, 31)
+#define SABREAUTO_DISP0_RESET IMX_GPIO_NR(5, 0)
+#define SABREAUTO_I2C3_STEER IMX_GPIO_NR(5, 4)
+#define SABREAUTO_WEIM_NOR_WDOG1 IMX_GPIO_NR(4, 29)
+#define SABREAUTO_ANDROID_VOLDOWN IMX_GPIO_NR(5, 14)
+#define SABREAUTO_PMIC_INT IMX_GPIO_NR(5, 16)
+#define SABREAUTO_ALS_INT IMX_GPIO_NR(5, 17)
+#define SABREAUTO_SD1_WP IMX_GPIO_NR(5, 20)
+#define SABREAUTO_USB_HOST1_OC IMX_GPIO_NR(5, 0)
+#define SABREAUTO_SD3_CD IMX_GPIO_NR(6, 15)
+
+#define SABREAUTO_MAX7310_1_BASE_ADDR IMX_GPIO_NR(8, 0)
+#define SABREAUTO_MAX7310_2_BASE_ADDR IMX_GPIO_NR(8, 8)
+#define SABREAUTO_MAX7310_3_BASE_ADDR IMX_GPIO_NR(8, 16)
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+#define MX6_ENET_IRQ IMX_GPIO_NR(1, 6)
+#define IOMUX_OBSRV_MUX1_OFFSET 0x3c
+#define OBSRV_MUX1_MASK 0x3f
+#define OBSRV_MUX1_ENET_IRQ 0x9
+#endif
+
+#define SABREAUTO_IO_EXP_GPIO1(x) (SABREAUTO_MAX7310_1_BASE_ADDR + (x))
+#define SABREAUTO_IO_EXP_GPIO2(x) (SABREAUTO_MAX7310_2_BASE_ADDR + (x))
+#define SABREAUTO_IO_EXP_GPIO3(x) (SABREAUTO_MAX7310_3_BASE_ADDR + (x))
+
+#define SABREAUTO_PCIE_RST_B_REVB (SABREAUTO_MAX7310_1_BASE_ADDR + 2)
+/*
+ * CAN2 STBY and EN lines are the same as the CAN1. These lines are not
+ * independent.
+ */
+#define SABREAUTO_PER_RST SABREAUTO_IO_EXP_GPIO1(3)
+#define SABREAUTO_VIDEOIN_PWR SABREAUTO_IO_EXP_GPIO2(2)
+#define SABREAUTO_CAN1_STEER SABREAUTO_IO_EXP_GPIO2(3)
+#define SABREAUTO_CAN_STBY SABREAUTO_IO_EXP_GPIO2(5)
+#define SABREAUTO_CAN_EN SABREAUTO_IO_EXP_GPIO2(6)
+#define SABREAUTO_USB_HOST1_PWR SABREAUTO_IO_EXP_GPIO2(7)
+#define SABREAUTO_USB_OTG_PWR SABREAUTO_IO_EXP_GPIO3(1)
+#define BMCR_PDOWN 0x0800 /* PHY Powerdown */
+
+extern char *gp_reg_id;
+extern char *soc_reg_id;
+extern char *pu_reg_id;
+
+static int mma8451_position = 3;
+static struct clk *sata_clk;
+static int mipi_sensor;
+static int can0_enable;
+static int uart3_en;
+static int tuner_en;
+static int spinor_en;
+static int weimnor_en;
+
+static int __init spinor_enable(char *p)
+{
+ spinor_en = 1;
+ return 0;
+}
+early_param("spi-nor", spinor_enable);
+
+static int __init weimnor_enable(char *p)
+{
+ weimnor_en = 1;
+ return 0;
+}
+early_param("weim-nor", weimnor_enable);
+
+static int __init uart3_enable(char *p)
+{
+ uart3_en = 1;
+ return 0;
+}
+early_param("uart3", uart3_enable);
+
+static int __init tuner_enable(char *p)
+{
+ tuner_en = 1;
+ return 0;
+}
+early_param("tuner", tuner_enable);
+
+enum sd_pad_mode {
+ SD_PAD_MODE_LOW_SPEED,
+ SD_PAD_MODE_MED_SPEED,
+ SD_PAD_MODE_HIGH_SPEED,
+};
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+}
+
+static struct gpio_keys_button ard_buttons[] = {
+ GPIO_BUTTON(SABREAUTO_ANDROID_HOME, KEY_HOME, 1, "home", 0),
+ GPIO_BUTTON(SABREAUTO_ANDROID_BACK, KEY_BACK, 1, "back", 0),
+ GPIO_BUTTON(SABREAUTO_ANDROID_MENU, KEY_MENU, 1, "menu", 0),
+ GPIO_BUTTON(SABREAUTO_ANDROID_VOLUP, KEY_VOLUMEUP, 1, "volume-up", 0),
+ GPIO_BUTTON(SABREAUTO_ANDROID_VOLDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static struct gpio_keys_platform_data ard_android_button_data = {
+ .buttons = ard_buttons,
+ .nbuttons = ARRAY_SIZE(ard_buttons),
+};
+
+static struct platform_device ard_android_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &ard_android_button_data,
+ }
+};
+
+static void __init imx6q_add_android_device_buttons(void)
+{
+ platform_device_register(&ard_android_button_device);
+}
+#else
+static void __init imx6q_add_android_device_buttons(void) {}
+#endif
+
+static int plt_sd_pad_change(unsigned int index, int clock)
+{
+ /* LOW speed is the default state of SD pads */
+ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
+
+ iomux_v3_cfg_t *sd_pads_200mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_100mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_50mhz = NULL;
+
+ u32 sd_pads_200mhz_cnt;
+ u32 sd_pads_100mhz_cnt;
+ u32 sd_pads_50mhz_cnt;
+
+ if (index != 2) {
+ printk(KERN_ERR"no such SD host controller index %d\n", index);
+ return -EINVAL;
+ }
+
+ if (cpu_is_mx6q()) {
+ sd_pads_200mhz = mx6q_sd3_200mhz;
+ sd_pads_100mhz = mx6q_sd3_100mhz;
+ sd_pads_50mhz = mx6q_sd3_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
+ } else if (cpu_is_mx6dl()) {
+ sd_pads_200mhz = mx6dl_sd3_200mhz;
+ sd_pads_100mhz = mx6dl_sd3_100mhz;
+ sd_pads_50mhz = mx6dl_sd3_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd3_50mhz);
+ }
+
+ if (clock > 100000000) {
+ if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_200mhz);
+ pad_mode = SD_PAD_MODE_HIGH_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
+ sd_pads_200mhz_cnt);
+ } else if (clock > 52000000) {
+ if (pad_mode == SD_PAD_MODE_MED_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_100mhz);
+ pad_mode = SD_PAD_MODE_MED_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
+ sd_pads_100mhz_cnt);
+ } else {
+ if (pad_mode == SD_PAD_MODE_LOW_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_50mhz);
+ pad_mode = SD_PAD_MODE_LOW_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
+ sd_pads_50mhz_cnt);
+ }
+}
+
+static const struct esdhc_platform_data mx6q_sabreauto_sd3_data __initconst = {
+ .cd_gpio = SABREAUTO_SD3_CD,
+ .wp_gpio = SABREAUTO_SD3_WP,
+ .keep_power_at_suspend = 1,
+ .support_18v = 1,
+ .support_8bit = 1,
+ .delay_line = 0,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+static const struct esdhc_platform_data mx6q_sabreauto_sd1_data __initconst = {
+ .cd_gpio = SABREAUTO_SD1_CD,
+ .wp_gpio = SABREAUTO_SD1_WP,
+ .keep_power_at_suspend = 1,
+};
+
+
+static int __init gpmi_nand_platform_init(void)
+{
+ iomux_v3_cfg_t *nand_pads = NULL;
+ u32 nand_pads_cnt;
+
+ if (cpu_is_mx6q()) {
+ nand_pads = mx6q_gpmi_nand;
+ nand_pads_cnt = ARRAY_SIZE(mx6q_gpmi_nand);
+ } else if (cpu_is_mx6dl()) {
+ nand_pads = mx6dl_gpmi_nand;
+ nand_pads_cnt = ARRAY_SIZE(mx6dl_gpmi_nand);
+
+ }
+ BUG_ON(!nand_pads);
+ return mxc_iomux_v3_setup_multiple_pads(nand_pads, nand_pads_cnt);
+}
+
+static const struct gpmi_nand_platform_data
+mx6q_gpmi_nand_platform_data __initconst = {
+ .platform_init = gpmi_nand_platform_init,
+ .min_prop_delay_in_ns = 5,
+ .max_prop_delay_in_ns = 9,
+ .max_chip_count = 1,
+};
+
+static const struct anatop_thermal_platform_data
+mx6q_sabreauto_anatop_thermal_data __initconst = {
+ .name = "anatop_thermal",
+};
+
+static const struct imxuart_platform_data mx6_bt_uart_data __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS | IMXUART_SDMA,
+ .dma_req_rx = MX6Q_DMA_REQ_UART3_RX,
+ .dma_req_tx = MX6Q_DMA_REQ_UART3_TX,
+};
+
+static inline void mx6q_sabreauto_init_uart(void)
+{
+ imx6q_add_imx_uart(1, NULL);
+ imx6q_add_imx_uart(2, &mx6_bt_uart_data);
+ imx6q_add_imx_uart(3, NULL);
+}
+
+static int mx6q_sabreauto_fec_phy_init(struct phy_device *phydev)
+{
+ unsigned short val;
+
+ if (!board_is_mx6_reva()) {
+ /* Ar8031 phy SmartEEE feature cause link status generates
+ * glitch, which cause ethernet link down/up issue, so
+ * disable SmartEEE
+ */
+ phy_write(phydev, 0xd, 0x3);
+ phy_write(phydev, 0xe, 0x805d);
+ phy_write(phydev, 0xd, 0x4003);
+ val = phy_read(phydev, 0xe);
+ val &= ~(0x1 << 8);
+ phy_write(phydev, 0xe, val);
+
+ /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
+ phy_write(phydev, 0xd, 0x7);
+ phy_write(phydev, 0xe, 0x8016);
+ phy_write(phydev, 0xd, 0x4007);
+ val = phy_read(phydev, 0xe);
+
+ val &= 0xffe3;
+ val |= 0x18;
+ phy_write(phydev, 0xe, val);
+
+ /* Introduce tx clock delay */
+ phy_write(phydev, 0x1d, 0x5);
+ val = phy_read(phydev, 0x1e);
+ val |= 0x0100;
+ phy_write(phydev, 0x1e, val);
+
+ /*check phy power*/
+ val = phy_read(phydev, 0x0);
+
+ if (val & BMCR_PDOWN)
+ phy_write(phydev, 0x0, (val & ~BMCR_PDOWN));
+ } else {
+ /* prefer master mode, 1000 Base-T capable */
+ phy_write(phydev, 0x9, 0x0f00);
+
+ /* min rx data delay */
+ phy_write(phydev, 0x0b, 0x8105);
+ phy_write(phydev, 0x0c, 0x0000);
+
+ /* max rx/tx clock delay, min rx/tx control delay */
+ phy_write(phydev, 0x0b, 0x8104);
+ phy_write(phydev, 0x0c, 0xf0f0);
+ phy_write(phydev, 0x0b, 0x104);
+ }
+
+ return 0;
+}
+
+static int mx6q_sabreauto_fec_power_hibernate(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static struct fec_platform_data fec_data __initdata = {
+ .init = mx6q_sabreauto_fec_phy_init,
+ .power_hibernate = mx6q_sabreauto_fec_power_hibernate,
+ .phy = PHY_INTERFACE_MODE_RGMII,
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ .gpio_irq = MX6_ENET_IRQ,
+#endif
+};
+
+static int mx6q_sabreauto_spi_cs[] = {
+ SABREAUTO_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx6q_sabreauto_spi_data __initconst = {
+ .chipselect = mx6q_sabreauto_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx6q_sabreauto_spi_cs),
+};
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition m25p32_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "bootenv",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data m25p32_spi_flash_data = {
+ .name = "m25p32",
+ .parts = m25p32_partitions,
+ .nr_parts = ARRAY_SIZE(m25p32_partitions),
+ .type = "m25p32",
+};
+
+static struct spi_board_info m25p32_spi0_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80)
+ {
+ /* The modalias must be the same as spi device driver name */
+ .modalias = "m25p80",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .platform_data = &m25p32_spi_flash_data,
+ },
+#endif
+};
+static void spi_device_init(void)
+{
+ spi_register_board_info(m25p32_spi0_board_info,
+ ARRAY_SIZE(m25p32_spi0_board_info));
+}
+#else
+static struct mtd_partition mxc_nor_partitions[] = {
+ {
+ .name = "Bootloader",
+ .offset = 0,
+ .size = 0x00080000,
+ }, {
+ .name = "nor.Kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+static struct resource nor_flash_resource = {
+ .start = CS0_BASE_ADDR,
+ .end = CS0_BASE_ADDR + 0x02000000 - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data nor_flash_data = {
+ .probe_type = "cfi_probe",
+ .width = 2,
+ .parts = mxc_nor_partitions,
+ .nr_parts = ARRAY_SIZE(mxc_nor_partitions),
+};
+
+static struct platform_device physmap_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &nor_flash_data,
+ },
+ .resource = &nor_flash_resource,
+ .num_resources = 1,
+};
+
+static void mx6q_setup_weimcs(void)
+{
+ unsigned int reg;
+ void __iomem *nor_reg = MX6_IO_ADDRESS(WEIM_BASE_ADDR);
+ void __iomem *ccm_reg = MX6_IO_ADDRESS(CCM_BASE_ADDR);
+
+ /*CCM_BASE_ADDR + CLKCTL_CCGR6*/
+ reg = readl(ccm_reg + 0x80);
+ reg |= 0x00000C00;
+ writel(reg, ccm_reg + 0x80);
+
+ __raw_writel(0x00620081, nor_reg);
+ __raw_writel(0x1C022000, nor_reg + 0x00000008);
+ __raw_writel(0x0804a240, nor_reg + 0x00000010);
+}
+#endif
+
+static int max7310_1_setup(struct i2c_client *client,
+ unsigned gpio_base, unsigned ngpio,
+ void *context)
+{
+ /* 0 BACKLITE_ON */
+ /* 1 SAT_SHUTDN_B */
+ /* 2 CPU_PER_RST_B */
+ /* 3 MAIN_PER_RST_B */
+ /* 4 IPOD_RST_B */
+ /* 5 MLB_RST_B */
+ /* 6 SSI_STEERING */
+ /* 7 GPS_RST_B */
+
+ int max7310_gpio_value[] = {
+ 0, 1, 1, 1, 0, 0, 1, 0,
+ };
+
+ int n;
+
+ for (n = 0; n < ARRAY_SIZE(max7310_gpio_value); ++n) {
+ gpio_request(gpio_base + n, "MAX7310 1 GPIO Expander");
+ if (max7310_gpio_value[n] < 0)
+ gpio_direction_input(gpio_base + n);
+ else
+ gpio_direction_output(gpio_base + n,
+ max7310_gpio_value[n]);
+ gpio_export(gpio_base + n, 0);
+ }
+
+ return 0;
+}
+
+static struct pca953x_platform_data max7310_platdata = {
+ .gpio_base = SABREAUTO_MAX7310_1_BASE_ADDR,
+ .invert = 0,
+ .setup = max7310_1_setup,
+};
+
+static int max7310_u39_setup(struct i2c_client *client,
+ unsigned gpio_base, unsigned ngpio,
+ void *context)
+{
+ /* 0 not use */
+ /* 1 GPS_PWREN */
+ /* 2 VIDEO_ADC_PWRDN_B */
+ /* 3 ENET_CAN1_STEER */
+ /* 4 EIMD30_BTUART3_STEER */
+ /* 5 CAN_STBY */
+ /* 6 CAN_EN */
+ /* 7 USB_H1_PWR */
+
+ int max7310_gpio_value[] = {
+ 0, 1, 0, 0, 0, 1, 1, 1,
+ };
+
+ int n;
+
+ if (uart3_en)
+ max7310_gpio_value[4] = 1;
+
+ for (n = 0; n < ARRAY_SIZE(max7310_gpio_value); ++n) {
+ gpio_request(gpio_base + n, "MAX7310 U39 GPIO Expander");
+ if (max7310_gpio_value[n] < 0)
+ gpio_direction_input(gpio_base + n);
+ else
+ gpio_direction_output(gpio_base + n,
+ max7310_gpio_value[n]);
+ gpio_export(gpio_base + n, 0);
+ }
+
+ return 0;
+}
+
+static int max7310_u43_setup(struct i2c_client *client,
+ unsigned gpio_base, unsigned ngpio,
+ void *context)
+{
+ /*0 PORT_EXP_C0*/
+ /*1 USB_OTG_PWR_ON */
+ /*2 SAT_RST_B*/
+ /*3 NAND_BT_WIFI_STEER*/
+
+ int max7310_gpio_value[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+ int n;
+
+ if (uart3_en)
+ max7310_gpio_value[3] = 1;
+
+ for (n = 0; n < ARRAY_SIZE(max7310_gpio_value); ++n) {
+ gpio_request(gpio_base + n, "MAX7310 U43 GPIO Expander");
+ if (max7310_gpio_value[n] < 0)
+ gpio_direction_input(gpio_base + n);
+ else
+ gpio_direction_output(gpio_base + n,
+ max7310_gpio_value[n]);
+ gpio_export(gpio_base + n, 0);
+ }
+
+ return 0;
+}
+
+static struct pca953x_platform_data max7310_u39_platdata = {
+ .gpio_base = SABREAUTO_MAX7310_2_BASE_ADDR,
+ .invert = 0,
+ .setup = max7310_u39_setup,
+};
+
+static struct pca953x_platform_data max7310_u43_platdata = {
+ .gpio_base = SABREAUTO_MAX7310_3_BASE_ADDR,
+ .invert = 0,
+ .setup = max7310_u43_setup,
+};
+
+static void adv7180_pwdn(int pwdn)
+{
+ int status = -1;
+
+ status = gpio_request(SABREAUTO_VIDEOIN_PWR, "tvin-pwr");
+
+ if (pwdn)
+ gpio_direction_output(SABREAUTO_VIDEOIN_PWR, 0);
+ else
+ gpio_direction_output(SABREAUTO_VIDEOIN_PWR, 1);
+
+ gpio_free(SABREAUTO_VIDEOIN_PWR);
+}
+
+static struct fsl_mxc_tvin_platform_data adv7180_data = {
+ .dvddio_reg = NULL,
+ .dvdd_reg = NULL,
+ .avdd_reg = NULL,
+ .pvdd_reg = NULL,
+ .pwdn = adv7180_pwdn,
+ .reset = NULL,
+ .cvbs = true,
+};
+
+static struct imxi2c_platform_data mx6q_sabreauto_i2c2_data = {
+ .bitrate = 400000,
+};
+
+static struct imxi2c_platform_data mx6q_sabreauto_i2c1_data = {
+ .bitrate = 100000,
+};
+
+static struct mxc_audio_codec_platform_data cs42888_data = {
+ .rates = (
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000),
+};
+
+static struct fsl_mxc_lightsensor_platform_data ls_data = {
+ .rext = 499,
+};
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("max7310", 0x30),
+ .platform_data = &max7310_platdata,
+ }, {
+ I2C_BOARD_INFO("max7310", 0x32),
+ .platform_data = &max7310_u39_platdata,
+ }, {
+ I2C_BOARD_INFO("max7310", 0x34),
+ .platform_data = &max7310_u43_platdata,
+ }, {
+ I2C_BOARD_INFO("adv7180", 0x21),
+ .platform_data = (void *)&adv7180_data,
+ }, {
+ I2C_BOARD_INFO("isl29023", 0x44),
+ .irq = gpio_to_irq(SABREAUTO_ALS_INT),
+ .platform_data = &ls_data,
+ },
+ {
+ I2C_BOARD_INFO("mma8451", 0x1c),
+ .platform_data = (void *)&mma8451_position,
+ },
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("egalax_ts", 0x04),
+ .irq = gpio_to_irq(SABREAUTO_CAP_TCH_INT),
+ }, {
+ I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50),
+ }, {
+ I2C_BOARD_INFO("cs42888", 0x48),
+ .platform_data = (void *)&cs42888_data,
+ }, {
+ I2C_BOARD_INFO("si4763_i2c", 0x63),
+ },
+};
+
+struct platform_device mxc_si4763_audio_device = {
+ .name = "imx-tuner-si4763",
+ .id = 0,
+};
+
+struct platform_device si4763_codec_device = {
+ .name = "si4763",
+ .id = 0,
+};
+
+static struct imx_ssi_platform_data mx6_sabreauto_ssi1_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_SYN,
+};
+static struct mxc_audio_platform_data si4763_audio_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 5,
+};
+static void imx6q_sabreauto_usbotg_vbus(bool on)
+{
+ if (on)
+ gpio_set_value_cansleep(SABREAUTO_USB_OTG_PWR, 1);
+ else
+ gpio_set_value_cansleep(SABREAUTO_USB_OTG_PWR, 0);
+}
+
+static void imx6q_sabreauto_usbhost1_vbus(bool on)
+{
+ if (on)
+ gpio_set_value_cansleep(SABREAUTO_USB_HOST1_PWR, 1);
+ else
+ gpio_set_value_cansleep(SABREAUTO_USB_HOST1_PWR, 0);
+}
+
+static void __init imx6q_sabreauto_init_usb(void)
+{
+ int ret = 0;
+ imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR);
+
+ ret = gpio_request(SABREAUTO_USB_OTG_OC, "otg-oc");
+ if (ret) {
+ printk(KERN_ERR"failed to get GPIO SABREAUTO_USB_OTG_OC:"
+ " %d\n", ret);
+ return;
+ }
+ gpio_direction_input(SABREAUTO_USB_OTG_OC);
+
+ ret = gpio_request(SABREAUTO_USB_HOST1_OC, "usbh1-oc");
+ if (ret) {
+ printk(KERN_ERR"failed to get SABREAUTO_USB_HOST1_OC:"
+ " %d\n", ret);
+ return;
+ }
+ gpio_direction_input(SABREAUTO_USB_HOST1_OC);
+
+ mxc_iomux_set_gpr_register(1, 13, 1, 0);
+ mx6_set_otghost_vbus_func(imx6q_sabreauto_usbotg_vbus);
+ mx6_usb_dr_init();
+ mx6_set_host1_vbus_func(imx6q_sabreauto_usbhost1_vbus);
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ mx6_usb_h2_init();
+ mx6_usb_h3_init();
+#endif
+}
+
+static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
+ .reserved_mem_size = SZ_128M + SZ_64M,
+};
+
+/* HW Initialization, if return 0, initialization is successful. */
+static int mx6q_sabreauto_sata_init(struct device *dev, void __iomem *addr)
+{
+ u32 tmpdata;
+ int ret = 0;
+ struct clk *clk;
+
+ sata_clk = clk_get(dev, "imx_sata_clk");
+ if (IS_ERR(sata_clk)) {
+ dev_err(dev, "no sata clock.\n");
+ return PTR_ERR(sata_clk);
+ }
+ ret = clk_enable(sata_clk);
+ if (ret) {
+ dev_err(dev, "can't enable sata clock.\n");
+ goto put_sata_clk;
+ }
+
+ /* Set PHY Paremeters, two steps to configure the GPR13,
+ * one write for rest of parameters, mask of first write is 0x07FFFFFD,
+ * and the other one write for setting the mpll_clk_off_b
+ *.rx_eq_val_0(iomuxc_gpr13[26:24]),
+ *.los_lvl(iomuxc_gpr13[23:19]),
+ *.rx_dpll_mode_0(iomuxc_gpr13[18:16]),
+ *.sata_speed(iomuxc_gpr13[15]),
+ *.mpll_ss_en(iomuxc_gpr13[14]),
+ *.tx_atten_0(iomuxc_gpr13[13:11]),
+ *.tx_boost_0(iomuxc_gpr13[10:7]),
+ *.tx_lvl(iomuxc_gpr13[6:2]),
+ *.mpll_ck_off(iomuxc_gpr13[1]),
+ *.tx_edgerate_0(iomuxc_gpr13[0]),
+ */
+ tmpdata = readl(IOMUXC_GPR13);
+ writel(((tmpdata & ~0x07FFFFFD) | 0x0593A044), IOMUXC_GPR13);
+
+ /* enable SATA_PHY PLL */
+ tmpdata = readl(IOMUXC_GPR13);
+ writel(((tmpdata & ~0x2) | 0x2), IOMUXC_GPR13);
+
+ /* Get the AHB clock rate, and configure the TIMER1MS reg later */
+ clk = clk_get(NULL, "ahb");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "no ahb clock.\n");
+ ret = PTR_ERR(clk);
+ goto release_sata_clk;
+ }
+ tmpdata = clk_get_rate(clk) / 1000;
+ clk_put(clk);
+
+#ifdef CONFIG_SATA_AHCI_PLATFORM
+ ret = sata_init(addr, tmpdata);
+ if (ret == 0)
+ return ret;
+#else
+ usleep_range(1000, 2000);
+ /* AHCI PHY enter into PDDQ mode if the AHCI module is not enabled */
+ tmpdata = readl(addr + PORT_PHY_CTL);
+ writel(tmpdata | PORT_PHY_CTL_PDDQ_LOC, addr + PORT_PHY_CTL);
+ pr_info("No AHCI save PWR: PDDQ %s\n", ((readl(addr + PORT_PHY_CTL)
+ >> 20) & 1) ? "enabled" : "disabled");
+#endif
+
+release_sata_clk:
+ /* disable SATA_PHY PLL */
+ writel((readl(IOMUXC_GPR13) & ~0x2), IOMUXC_GPR13);
+ clk_disable(sata_clk);
+put_sata_clk:
+ clk_put(sata_clk);
+
+ return ret;
+}
+
+#ifdef CONFIG_SATA_AHCI_PLATFORM
+static void mx6q_sabreauto_sata_exit(struct device *dev)
+{
+ clk_disable(sata_clk);
+ clk_put(sata_clk);
+
+}
+
+static struct ahci_platform_data mx6q_sabreauto_sata_data = {
+ .init = mx6q_sabreauto_sata_init,
+ .exit = mx6q_sabreauto_sata_exit,
+};
+#endif
+
+static struct imx_asrc_platform_data imx_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 2,
+};
+
+static void mx6q_sabreauto_reset_mipi_dsi(void)
+{
+ gpio_set_value(SABREAUTO_DISP0_PWR, 1);
+ gpio_set_value(SABREAUTO_DISP0_RESET, 1);
+ udelay(10);
+ gpio_set_value(SABREAUTO_DISP0_RESET, 0);
+ udelay(50);
+ gpio_set_value(SABREAUTO_DISP0_RESET, 1);
+
+ /*
+ * it needs to delay 120ms minimum for reset complete
+ */
+ msleep(120);
+}
+
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .lcd_panel = "TRULY-WVGA",
+ .reset = mx6q_sabreauto_reset_mipi_dsi,
+};
+
+static struct ipuv3_fb_platform_data sabr_fb_data[] = {
+ { /*fb0*/
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-XGA",
+ .default_bpp = 32,
+ .int_clk = false,
+ }, {
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-XGA",
+ .default_bpp = 32,
+ .int_clk = false,
+ }, {
+ .disp_dev = "lcd",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB565,
+ .mode_str = "CLAA-WVGA",
+ .default_bpp = 16,
+ .int_clk = false,
+ },
+};
+
+static void hdmi_init(int ipu_id, int disp_id)
+{
+ int hdmi_mux_setting;
+
+ if ((ipu_id > 1) || (ipu_id < 0)) {
+ printk(KERN_ERR"Invalid IPU select for HDMI: %d. Set to 0\n",
+ ipu_id);
+ ipu_id = 0;
+ }
+
+ if ((disp_id > 1) || (disp_id < 0)) {
+ printk(KERN_ERR"Invalid DI select for HDMI: %d. Set to 0\n",
+ disp_id);
+ disp_id = 0;
+ }
+
+ /* Configure the connection between IPU1/2 and HDMI */
+ hdmi_mux_setting = 2*ipu_id + disp_id;
+
+ /* GPR3, bits 2-3 = HDMI_MUX_CTL */
+ mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
+
+ /* Set HDMI event as SDMA event2 while Chip version later than TO1.2 */
+ if (hdmi_SDMA_check())
+ mxc_iomux_set_gpr_register(0, 0, 1, 1);
+}
+
+/* On mx6x sabreauto board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabreauto_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6dl_sabreauto_hdmi_ddc_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_sabreauto_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabreauto_i2c2_pads,
+ ARRAY_SIZE(mx6dl_sabreauto_i2c2_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_i2c2_pads,
+ ARRAY_SIZE(mx6q_sabreauto_i2c2_pads));
+}
+
+static struct fsl_mxc_hdmi_platform_data hdmi_data = {
+ .init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
+};
+
+static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+};
+
+static struct fsl_mxc_lcd_platform_data lcdif_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .default_ifmt = IPU_PIX_FMT_RGB565,
+};
+
+static struct fsl_mxc_ldb_platform_data ldb_data = {
+ .ipu_id = 1,
+ .disp_id = 0,
+ .ext_ref = 1,
+ .mode = LDB_SEP0,
+ .sec_ipu_id = 1,
+ .sec_disp_id = 1,
+};
+
+static struct imx_ipuv3_platform_data ipu_data[] = {
+ {
+ .rev = 4,
+ .csi_clk[0] = "ccm_clk0",
+ }, {
+ .rev = 4,
+ .csi_clk[0] = "ccm_clk0",
+ },
+};
+
+/* Backlight PWM for CPU board lvds*/
+static struct platform_pwm_backlight_data mx6_arm2_pwm_backlight_data3 = {
+ .pwm_id = 2,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+
+static struct ion_platform_data imx_ion_data = {
+ .nr = 1,
+ .heaps = {
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = "vpu_ion",
+ .size = SZ_64M,
+ },
+ },
+};
+
+/* Backlight PWM for Main board lvds*/
+static struct platform_pwm_backlight_data mx6_arm2_pwm_backlight_data4 = {
+ .pwm_id = 3,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+static int flexcan0_en;
+static int flexcan1_en;
+
+static void mx6q_flexcan_switch(void)
+{
+ if (flexcan0_en || flexcan1_en) {
+ /*
+ * The transceiver TJA1041A on sabreauto RevE baseboard will
+ * fail to transit to Normal state if EN/STBY is high by default
+ * after board power up. So we set the EN/STBY initial state to low
+ * first then to high to guarantee the state transition successfully.
+ */
+ gpio_set_value_cansleep(SABREAUTO_CAN_EN, 0);
+ gpio_set_value_cansleep(SABREAUTO_CAN_STBY, 0);
+
+ gpio_set_value_cansleep(SABREAUTO_CAN_EN, 1);
+ gpio_set_value_cansleep(SABREAUTO_CAN_STBY, 1);
+ /* Enable STEER pin if CAN1 interface is required.
+ * STEER pin is used to switch between ENET_MDC
+ * and CAN1_TX functionality. By default ENET_MDC
+ * is active after reset.
+ */
+ if (flexcan0_en)
+ gpio_set_value_cansleep(SABREAUTO_CAN1_STEER, 1);
+
+ } else {
+ /* avoid to disable CAN xcvr if any of the CAN interfaces
+ * are down. XCRV will be disabled only if both CAN2
+ * interfaces are DOWN.
+ */
+ if (!flexcan0_en && !flexcan1_en) {
+ gpio_set_value_cansleep(SABREAUTO_CAN_EN, 0);
+ gpio_set_value_cansleep(SABREAUTO_CAN_STBY, 0);
+ }
+ /* turn down STEER pin only if CAN1 is DOWN */
+ if (!flexcan0_en)
+ gpio_set_value_cansleep(SABREAUTO_CAN1_STEER, 0);
+
+ }
+}
+static void mx6q_flexcan0_switch(int enable)
+{
+ flexcan0_en = enable;
+ mx6q_flexcan_switch();
+}
+
+static void mx6q_flexcan1_switch(int enable)
+{
+ flexcan1_en = enable;
+ mx6q_flexcan_switch();
+}
+
+static const struct flexcan_platform_data
+ mx6q_sabreauto_flexcan_pdata[] __initconst = {
+ {
+ .transceiver_switch = mx6q_flexcan0_switch,
+ }, {
+ .transceiver_switch = mx6q_flexcan1_switch,
+ }
+};
+
+static struct mipi_csi2_platform_data mipi_csi2_pdata = {
+ .ipu_id = 0,
+ .csi_id = 0,
+ .v_channel = 0,
+ .lanes = 2,
+ .dphy_clk = "mipi_pllref_clk",
+ .pixel_clk = "emi_clk",
+};
+
+static void sabreauto_suspend_enter(void)
+{
+ /* suspend preparation */
+}
+
+static void sabreauto_suspend_exit(void)
+{
+ /* resmue resore */
+}
+static const struct pm_platform_data mx6q_sabreauto_pm_data __initconst = {
+ .name = "imx_pm",
+ .suspend_enter = sabreauto_suspend_enter,
+ .suspend_exit = sabreauto_suspend_exit,
+};
+
+static const struct asrc_p2p_params esai_p2p = {
+ .p2p_rate = 48000,
+ .p2p_width = ASRC_WIDTH_24_BIT,
+};
+
+static struct mxc_audio_platform_data sab_audio_data = {
+ .sysclk = 24576000,
+ .codec_name = "cs42888.1-0048",
+ .priv = (void *)&esai_p2p,
+};
+
+static struct platform_device sab_audio_device = {
+ .name = "imx-cs42888",
+};
+
+static struct imx_esai_platform_data sab_esai_pdata = {
+ .flags = IMX_ESAI_NET,
+};
+
+static struct regulator_consumer_supply sabreauto_vmmc_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.3"),
+};
+
+static struct regulator_init_data sabreauto_vmmc_init = {
+ .num_consumer_supplies = ARRAY_SIZE(sabreauto_vmmc_consumers),
+ .consumer_supplies = sabreauto_vmmc_consumers,
+};
+
+static struct fixed_voltage_config sabreauto_vmmc_reg_config = {
+ .supply_name = "vmmc",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &sabreauto_vmmc_init,
+};
+
+static struct platform_device sabreauto_vmmc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &sabreauto_vmmc_reg_config,
+ },
+};
+
+static struct regulator_consumer_supply cs42888_sabreauto_consumer_va = {
+ .supply = "VA",
+ .dev_name = "1-0048",
+};
+
+static struct regulator_consumer_supply cs42888_sabreauto_consumer_vd = {
+ .supply = "VD",
+ .dev_name = "1-0048",
+};
+
+static struct regulator_consumer_supply cs42888_sabreauto_consumer_vls = {
+ .supply = "VLS",
+ .dev_name = "1-0048",
+};
+
+static struct regulator_consumer_supply cs42888_sabreauto_consumer_vlc = {
+ .supply = "VLC",
+ .dev_name = "1-0048",
+};
+
+static struct regulator_init_data cs42888_sabreauto_va_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &cs42888_sabreauto_consumer_va,
+};
+
+static struct regulator_init_data cs42888_sabreauto_vd_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &cs42888_sabreauto_consumer_vd,
+};
+
+static struct regulator_init_data cs42888_sabreauto_vls_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &cs42888_sabreauto_consumer_vls,
+};
+
+static struct regulator_init_data cs42888_sabreauto_vlc_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &cs42888_sabreauto_consumer_vlc,
+};
+
+static struct fixed_voltage_config cs42888_sabreauto_va_reg_config = {
+ .supply_name = "VA",
+ .microvolts = 2800000,
+ .gpio = -1,
+ .init_data = &cs42888_sabreauto_va_reg_initdata,
+};
+
+static struct fixed_voltage_config cs42888_sabreauto_vd_reg_config = {
+ .supply_name = "VD",
+ .microvolts = 2800000,
+ .gpio = -1,
+ .init_data = &cs42888_sabreauto_vd_reg_initdata,
+};
+
+static struct fixed_voltage_config cs42888_sabreauto_vls_reg_config = {
+ .supply_name = "VLS",
+ .microvolts = 2800000,
+ .gpio = -1,
+ .init_data = &cs42888_sabreauto_vls_reg_initdata,
+};
+
+static struct fixed_voltage_config cs42888_sabreauto_vlc_reg_config = {
+ .supply_name = "VLC",
+ .microvolts = 2800000,
+ .gpio = -1,
+ .init_data = &cs42888_sabreauto_vlc_reg_initdata,
+};
+
+static struct platform_device cs42888_sabreauto_va_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 3,
+ .dev = {
+ .platform_data = &cs42888_sabreauto_va_reg_config,
+ },
+};
+
+static struct platform_device cs42888_sabreauto_vd_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 4,
+ .dev = {
+ .platform_data = &cs42888_sabreauto_vd_reg_config,
+ },
+};
+
+static struct platform_device cs42888_sabreauto_vls_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 5,
+ .dev = {
+ .platform_data = &cs42888_sabreauto_vls_reg_config,
+ },
+};
+
+static struct platform_device cs42888_sabreauto_vlc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 6,
+ .dev = {
+ .platform_data = &cs42888_sabreauto_vlc_reg_config,
+ },
+};
+
+static int __init imx6q_init_audio(void)
+{
+ struct clk *pll4_clk, *esai_clk, *anaclk_2;
+
+ mxc_register_device(&sab_audio_device, &sab_audio_data);
+ imx6q_add_imx_esai(0, &sab_esai_pdata);
+
+ gpio_request(SABREAUTO_ESAI_INT, "esai-int");
+ gpio_direction_input(SABREAUTO_ESAI_INT);
+
+ anaclk_2 = clk_get(NULL, "anaclk_2");
+ if (IS_ERR(anaclk_2))
+ return PTR_ERR(anaclk_2);
+ clk_set_rate(anaclk_2, 24576000);
+
+ esai_clk = clk_get(NULL, "esai_clk");
+ if (IS_ERR(esai_clk))
+ return PTR_ERR(esai_clk);
+
+ pll4_clk = clk_get(NULL, "pll4");
+ if (IS_ERR(pll4_clk))
+ return PTR_ERR(pll4_clk);
+
+ clk_set_parent(pll4_clk, anaclk_2);
+ clk_set_parent(esai_clk, pll4_clk);
+ clk_set_rate(pll4_clk, 786432000);
+ clk_set_rate(esai_clk, 24576000);
+
+ platform_device_register(&cs42888_sabreauto_va_reg_devices);
+ platform_device_register(&cs42888_sabreauto_vd_reg_devices);
+ platform_device_register(&cs42888_sabreauto_vls_reg_devices);
+ platform_device_register(&cs42888_sabreauto_vlc_reg_devices);
+ return 0;
+}
+
+static struct mxc_mlb_platform_data mx6_sabreauto_mlb150_data = {
+ .reg_nvcc = NULL,
+ .mlb_clk = "mlb150_clk",
+ .mlb_pll_clk = "pll6",
+};
+
+static struct mxc_dvfs_platform_data sabreauto_dvfscore_data = {
+ .reg_id = "VDDCORE",
+ .soc_id = "VDDSOC",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+};
+
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+}
+
+static int __init early_enable_mipi_sensor(char *p)
+{
+ mipi_sensor = 1;
+ return 0;
+}
+early_param("mipi_sensor", early_enable_mipi_sensor);
+
+static int __init early_enable_can0(char *p)
+{
+ can0_enable = 1;
+ return 0;
+}
+early_param("can0", early_enable_can0);
+
+static inline void __init mx6q_csi0_io_init(void)
+{
+ if (cpu_is_mx6q())
+ mxc_iomux_set_gpr_register(1, 19, 1, 1);
+ else if (cpu_is_mx6dl())
+ mxc_iomux_set_gpr_register(13, 0, 3, 4);
+}
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 0, /* disable tx */
+ .spdif_rx = 1, /* enable rx */
+ .spdif_rx_clk = 0, /* rx clk from spdif stream */
+ .spdif_clk = NULL, /* spdif bus clk */
+};
+
+static struct fsl_mxc_capture_platform_data capture_data[] = {
+ {
+ .csi = 0,
+ .ipu = 0,
+ .mclk_source = 0,
+ .is_mipi = 0,
+ }, {
+ .csi = 1,
+ .ipu = 0,
+ .mclk_source = 0,
+ .is_mipi = 1,
+ },
+};
+
+static const struct imx_pcie_platform_data mx6_sabreauto_pcie_data __initconst = {
+ .pcie_pwr_en = -EINVAL,
+ .pcie_rst = SABREAUTO_PCIE_RST_B_REVB,
+ .pcie_wake_up = -EINVAL,
+ .pcie_dis = -EINVAL,
+};
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mx6_board_init(void)
+{
+ int i;
+ int ret;
+ iomux_v3_cfg_t *common_pads = NULL;
+ iomux_v3_cfg_t *can0_pads = NULL;
+ iomux_v3_cfg_t *can1_pads = NULL;
+ iomux_v3_cfg_t *mipi_sensor_pads = NULL;
+ iomux_v3_cfg_t *i2c3_pads = NULL;
+ iomux_v3_cfg_t *tuner_pads = NULL;
+ iomux_v3_cfg_t *spinor_pads = NULL;
+ iomux_v3_cfg_t *weimnor_pads = NULL;
+ iomux_v3_cfg_t *bluetooth_pads = NULL;
+ iomux_v3_cfg_t *extra_pads = NULL;
+
+ int common_pads_cnt;
+ int can0_pads_cnt;
+ int can1_pads_cnt;
+ int mipi_sensor_pads_cnt;
+ int i2c3_pads_cnt;
+ int tuner_pads_cnt;
+ int spinor_pads_cnt;
+ int weimnor_pads_cnt;
+ int bluetooth_pads_cnt;
+ int extra_pads_cnt;
+
+ if (cpu_is_mx6q()) {
+ common_pads = mx6q_sabreauto_pads;
+ can0_pads = mx6q_sabreauto_can0_pads;
+ can1_pads = mx6q_sabreauto_can1_pads;
+ mipi_sensor_pads = mx6q_sabreauto_mipi_sensor_pads;
+ tuner_pads = mx6q_tuner_pads;
+ spinor_pads = mx6q_spinor_pads;
+ weimnor_pads = mx6q_weimnor_pads;
+ bluetooth_pads = mx6q_bluetooth_pads;
+
+ common_pads_cnt = ARRAY_SIZE(mx6q_sabreauto_pads);
+ can0_pads_cnt = ARRAY_SIZE(mx6q_sabreauto_can0_pads);
+ can1_pads_cnt = ARRAY_SIZE(mx6q_sabreauto_can1_pads);
+ mipi_sensor_pads_cnt = ARRAY_SIZE(mx6q_sabreauto_mipi_sensor_pads);
+ tuner_pads_cnt = ARRAY_SIZE(mx6q_tuner_pads);
+ spinor_pads_cnt = ARRAY_SIZE(mx6q_spinor_pads);
+ weimnor_pads_cnt = ARRAY_SIZE(mx6q_weimnor_pads);
+ bluetooth_pads_cnt = ARRAY_SIZE(mx6q_bluetooth_pads);
+ if (board_is_mx6_reva()) {
+ i2c3_pads = mx6q_i2c3_pads_rev_a;
+ i2c3_pads_cnt = ARRAY_SIZE(mx6q_i2c3_pads_rev_a);
+ mxc_iomux_v3_setup_multiple_pads(i2c3_pads,
+ i2c3_pads_cnt);
+ } else {
+ i2c3_pads = mx6q_i2c3_pads_rev_b;
+ i2c3_pads_cnt = ARRAY_SIZE(mx6q_i2c3_pads_rev_b);
+ extra_pads = mx6q_extra_pads_rev_b;
+ extra_pads_cnt = ARRAY_SIZE(mx6q_extra_pads_rev_b);
+ mxc_iomux_v3_setup_multiple_pads(extra_pads,
+ extra_pads_cnt);
+ }
+ } else if (cpu_is_mx6dl()) {
+ common_pads = mx6dl_sabreauto_pads;
+ can0_pads = mx6dl_sabreauto_can0_pads;
+ can1_pads = mx6dl_sabreauto_can1_pads;
+ mipi_sensor_pads = mx6dl_sabreauto_mipi_sensor_pads;
+ tuner_pads = mx6dl_tuner_pads;
+ spinor_pads = mx6dl_spinor_pads;
+ weimnor_pads = mx6dl_weimnor_pads;
+ bluetooth_pads = mx6dl_bluetooth_pads;
+
+ common_pads_cnt = ARRAY_SIZE(mx6dl_sabreauto_pads);
+ can0_pads_cnt = ARRAY_SIZE(mx6dl_sabreauto_can0_pads);
+ can1_pads_cnt = ARRAY_SIZE(mx6dl_sabreauto_can1_pads);
+ mipi_sensor_pads_cnt = ARRAY_SIZE(mx6dl_sabreauto_mipi_sensor_pads);
+ tuner_pads_cnt = ARRAY_SIZE(mx6dl_tuner_pads);
+ spinor_pads_cnt = ARRAY_SIZE(mx6dl_spinor_pads);
+ weimnor_pads_cnt = ARRAY_SIZE(mx6dl_weimnor_pads);
+ bluetooth_pads_cnt = ARRAY_SIZE(mx6dl_bluetooth_pads);
+
+ if (board_is_mx6_reva()) {
+ i2c3_pads = mx6dl_i2c3_pads_rev_a;
+ i2c3_pads_cnt = ARRAY_SIZE(mx6dl_i2c3_pads_rev_a);
+ mxc_iomux_v3_setup_multiple_pads(i2c3_pads,
+ i2c3_pads_cnt);
+ } else {
+ i2c3_pads = mx6dl_i2c3_pads_rev_b;
+ i2c3_pads_cnt = ARRAY_SIZE(mx6dl_i2c3_pads_rev_b);
+ extra_pads = mx6dl_extra_pads_rev_b;
+ extra_pads_cnt = ARRAY_SIZE(mx6dl_extra_pads_rev_b);
+ mxc_iomux_v3_setup_multiple_pads(extra_pads,
+ extra_pads_cnt);
+ }
+ }
+
+ BUG_ON(!common_pads);
+ mxc_iomux_v3_setup_multiple_pads(common_pads, common_pads_cnt);
+
+ /*If at least one NOR memory is selected we don't
+ * configure IC23 PADS for rev B */
+ if (spinor_en) {
+ BUG_ON(!spinor_pads);
+ mxc_iomux_v3_setup_multiple_pads(spinor_pads, spinor_pads_cnt);
+ } else if (weimnor_en) {
+ BUG_ON(!weimnor_pads);
+ mxc_iomux_v3_setup_multiple_pads(weimnor_pads,
+ weimnor_pads_cnt);
+ } else {
+ if (!board_is_mx6_reva()) {
+ BUG_ON(!i2c3_pads);
+ mxc_iomux_v3_setup_multiple_pads(i2c3_pads,
+ i2c3_pads_cnt);
+ }
+ if (uart3_en) {
+ BUG_ON(!bluetooth_pads);
+ mxc_iomux_v3_setup_multiple_pads(bluetooth_pads,
+ bluetooth_pads_cnt);
+ }
+ }
+
+ if (can0_enable) {
+ BUG_ON(!can0_pads);
+ mxc_iomux_v3_setup_multiple_pads(can0_pads,
+ can0_pads_cnt);
+ }
+
+ BUG_ON(!can1_pads);
+ mxc_iomux_v3_setup_multiple_pads(can1_pads, can1_pads_cnt);
+
+ if (tuner_en) {
+ BUG_ON(!tuner_pads);
+ mxc_iomux_v3_setup_multiple_pads(tuner_pads,
+ tuner_pads_cnt);
+ }
+
+ /* assert i2c-rst */
+ gpio_request(SABREAUTO_I2C_EXP_RST, "i2c-rst");
+ gpio_direction_output(SABREAUTO_I2C_EXP_RST, 1);
+
+ if (!board_is_mx6_reva()) {
+ /* enable either EIM_D18 or i2c3_sda route path */
+ gpio_request(SABREAUTO_I2C3_STEER, "i2c3-steer");
+ if (spinor_en)
+ gpio_direction_output(SABREAUTO_I2C3_STEER, 0);
+ else if (weimnor_en) {
+ /*Put DISP0_DAT8 in ALT5 mode to prevent WDOG1 of
+ resetting WEIM NOR*/
+ gpio_direction_output(SABREAUTO_I2C3_STEER, 0);
+
+ gpio_request(SABREAUTO_WEIM_NOR_WDOG1, "nor-reset");
+ gpio_direction_output(SABREAUTO_WEIM_NOR_WDOG1, 1);
+ } else
+ gpio_direction_output(SABREAUTO_I2C3_STEER, 1);
+ /* Set GPIO_16 input for IEEE-1588 ts_clk and
+ * RMII reference clk
+ * For MX6 GPR1 bit21 meaning:
+ * Bit21: 0 - GPIO_16 pad output
+ * 1 - GPIO_16 pad input
+ */
+ mxc_iomux_set_gpr_register(1, 21, 1, 1);
+ }
+
+ if (mipi_sensor) {
+ BUG_ON(!mipi_sensor_pads);
+ mxc_iomux_v3_setup_multiple_pads(mipi_sensor_pads,
+ mipi_sensor_pads_cnt);
+ }
+
+ gp_reg_id = sabreauto_dvfscore_data.reg_id;
+ soc_reg_id = sabreauto_dvfscore_data.soc_id;
+ mx6q_sabreauto_init_uart();
+ imx6q_add_mipi_csi2(&mipi_csi2_pdata);
+ if (cpu_is_mx6dl()) {
+ mipi_dsi_pdata.ipu_id = 0;
+ mipi_dsi_pdata.disp_id = 1;
+ ldb_data.ipu_id = 0;
+ ldb_data.disp_id = 0;
+ ldb_data.sec_ipu_id = 0;
+ ldb_data.sec_disp_id = 1;
+ hdmi_core_data.disp_id = 1;
+ }
+ imx6q_add_mxc_hdmi_core(&hdmi_core_data);
+
+ imx6q_add_ipuv3(0, &ipu_data[0]);
+ if (cpu_is_mx6q()) {
+ imx6q_add_ipuv3(1, &ipu_data[1]);
+ for (i = 0; i < ARRAY_SIZE(sabr_fb_data); i++)
+ imx6q_add_ipuv3fb(i, &sabr_fb_data[i]);
+ } else if (cpu_is_mx6dl())
+ for (i = 0; i < (ARRAY_SIZE(sabr_fb_data) + 1) / 2; i++)
+ imx6q_add_ipuv3fb(i, &sabr_fb_data[i]);
+
+ imx6q_add_vdoa();
+ imx6q_add_mipi_dsi(&mipi_dsi_pdata);
+ imx6q_add_lcdif(&lcdif_data);
+ imx6q_add_ldb(&ldb_data);
+ imx6q_add_v4l2_output(0);
+ imx6q_add_v4l2_capture(0, &capture_data[0]);
+ imx6q_add_v4l2_capture(1, &capture_data[1]);
+ imx6q_add_android_device_buttons();
+
+ imx6q_add_imx_snvs_rtc();
+
+ imx6q_add_imx_caam();
+
+ imx6q_add_imx_i2c(1, &mx6q_sabreauto_i2c1_data);
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ imx6q_add_imx_i2c(2, &mx6q_sabreauto_i2c2_data);
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+
+ ret = gpio_request(SABREAUTO_PMIC_INT, "pFUZE-int");
+ if (ret) {
+ printk(KERN_ERR"request pFUZE-int error!!\n");
+ return;
+ } else {
+ gpio_direction_input(SABREAUTO_PMIC_INT);
+ mx6q_sabreauto_init_pfuze100(SABREAUTO_PMIC_INT);
+ }
+ /* SPI */
+ imx6q_add_ecspi(0, &mx6q_sabreauto_spi_data);
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+ spi_device_init();
+#else
+ mx6q_setup_weimcs();
+ platform_device_register(&physmap_flash_device);
+#endif
+ imx6q_add_mxc_hdmi(&hdmi_data);
+
+ imx6q_add_anatop_thermal_imx(1, &mx6q_sabreauto_anatop_thermal_data);
+
+ if (!can0_enable) {
+ imx6_init_fec(fec_data);
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */
+ mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET,
+ OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK);
+#endif
+
+ }
+ imx6q_add_pm_imx(0, &mx6q_sabreauto_pm_data);
+
+ imx6q_add_sdhci_usdhc_imx(2, &mx6q_sabreauto_sd3_data);
+ imx6q_add_sdhci_usdhc_imx(0, &mx6q_sabreauto_sd1_data);
+
+ imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata);
+ imx6q_sabreauto_init_usb();
+ if (cpu_is_mx6q()) {
+#ifdef CONFIG_SATA_AHCI_PLATFORM
+ imx6q_add_ahci(0, &mx6q_sabreauto_sata_data);
+#else
+ mx6q_sabreauto_sata_init(NULL,
+ (void __iomem *)ioremap(MX6Q_SATA_BASE_ADDR, SZ_4K));
+#endif
+ }
+ imx6q_add_vpu();
+ imx6q_init_audio();
+ platform_device_register(&sabreauto_vmmc_reg_devices);
+ imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ imx6q_add_asrc(&imx_asrc_data);
+
+ if (!mipi_sensor)
+ mx6q_csi0_io_init();
+
+ /* DISP0 Detect */
+ gpio_request(SABREAUTO_DISP0_DET_INT, "disp0-detect");
+ gpio_direction_input(SABREAUTO_DISP0_DET_INT);
+
+ /* DISP0 Reset - Assert for i2c disabled mode */
+ gpio_request(SABREAUTO_DISP0_RESET, "disp0-reset");
+ gpio_direction_output(SABREAUTO_DISP0_RESET, 0);
+
+ /* DISP0 I2C enable */
+ gpio_request(SABREAUTO_DISP0_I2C_EN, "disp0-i2c");
+ gpio_direction_output(SABREAUTO_DISP0_I2C_EN, 0);
+
+ gpio_request(SABREAUTO_DISP0_PWR, "disp0-pwr");
+ gpio_direction_output(SABREAUTO_DISP0_PWR, 1);
+
+ gpio_request(SABREAUTO_LDB_BACKLIGHT3, "ldb-backlight3");
+ gpio_direction_output(SABREAUTO_LDB_BACKLIGHT3, 1);
+ gpio_request(SABREAUTO_LDB_BACKLIGHT4, "ldb-backlight4");
+ gpio_direction_output(SABREAUTO_LDB_BACKLIGHT4, 1);
+ imx6q_add_otp();
+ imx6q_add_viim();
+ imx6q_add_imx2_wdt(0, NULL);
+ imx6q_add_dma();
+ if (!uart3_en)
+ imx6q_add_gpmi(&mx6q_gpmi_nand_platform_data);
+
+ imx6q_add_dvfs_core(&sabreauto_dvfscore_data);
+
+ imx6q_add_ion(0, &imx_ion_data,
+ sizeof(imx_ion_data) + sizeof(struct ion_platform_heap));
+ imx6q_add_mxc_pwm(2);
+ imx6q_add_mxc_pwm(3);
+ imx6q_add_mxc_pwm_backlight(2, &mx6_arm2_pwm_backlight_data3);
+ imx6q_add_mxc_pwm_backlight(3, &mx6_arm2_pwm_backlight_data4);
+
+ mxc_spdif_data.spdif_core_clk = clk_get_sys("mxc_spdif.0", NULL);
+ clk_put(mxc_spdif_data.spdif_core_clk);
+ imx6q_add_spdif(&mxc_spdif_data);
+ imx6q_add_spdif_dai();
+ imx6q_add_spdif_audio_device();
+
+ if (can0_enable)
+ imx6q_add_flexcan0(&mx6q_sabreauto_flexcan_pdata[0]);
+ imx6q_add_flexcan1(&mx6q_sabreauto_flexcan_pdata[1]);
+ imx6q_add_hdmi_soc();
+ imx6q_add_hdmi_soc_dai();
+ imx6q_add_mlb150(&mx6_sabreauto_mlb150_data);
+
+ /* Tuner audio interface */
+ imx6q_add_imx_ssi(1, &mx6_sabreauto_ssi1_pdata);
+ mxc_register_device(&si4763_codec_device, NULL);
+ mxc_register_device(&mxc_si4763_audio_device, &si4763_audio_data);
+
+ imx6q_add_busfreq();
+
+ /* Add PCIe RC interface support */
+ imx6q_add_pcie(&mx6_sabreauto_pcie_data);
+
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
+}
+
+extern void __iomem *twd_base;
+static void __init mx6_timer_init(void)
+{
+ struct clk *uart_clk;
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ mx6_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(UART4_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx6_timer_init,
+};
+
+static void __init mx6q_reserve(void)
+{
+ phys_addr_t phys;
+#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE)
+ if (imx6q_gpu_pdata.reserved_mem_size) {
+ phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size,
+ SZ_4K, SZ_2G);
+ memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size);
+ imx6q_gpu_pdata.reserved_mem_base = phys;
+ }
+#endif
+
+#if defined(CONFIG_ION)
+ if (imx_ion_data.heaps[0].size) {
+ phys = memblock_alloc(imx_ion_data.heaps[0].size, SZ_4K);
+ memblock_free(phys, imx_ion_data.heaps[0].size);
+ memblock_remove(phys, imx_ion_data.heaps[0].size);
+ imx_ion_data.heaps[0].base = phys;
+ }
+#endif
+}
+
+MACHINE_START(MX6Q_SABREAUTO, "Freescale i.MX 6Quad/DualLite/Solo Sabre Auto Board")
+ .boot_params = MX6_PHYS_OFFSET + 0x100,
+ .fixup = fixup_mxc_board,
+ .map_io = mx6_map_io,
+ .init_irq = mx6_init_irq,
+ .init_machine = mx6_board_init,
+ .timer = &mxc_timer,
+ .reserve = mx6q_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.h b/arch/arm/mach-mx6/board-mx6q_sabreauto.h
new file mode 100644
index 00000000..cec36d57
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.h
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2012-2013 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 <mach/iomux-mx6q.h>
+
+static iomux_v3_cfg_t mx6q_sabreauto_pads[] = {
+
+ /* UART4 for debug */
+ MX6Q_PAD_KEY_COL0__UART4_TXD,
+ MX6Q_PAD_KEY_ROW0__UART4_RXD,
+ /* USB HSIC ports use the same pin with ENET */
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ /* USB H2 strobe/data pin */
+ MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE,
+ MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA,
+
+ /* USB H3 strobe/data pin */
+ MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE,
+ MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA,
+ /* ENET */
+#else
+ MX6Q_PAD_KEY_COL1__ENET_MDIO,
+ MX6Q_PAD_KEY_COL2__ENET_MDC,
+ MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC,
+ MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0,
+ MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1,
+ MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2,
+ MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3,
+ MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL,
+ MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK,
+ MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC,
+ MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0,
+ MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1,
+ MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2,
+ MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3,
+ MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL,
+ /*RGMII Phy Interrupt */
+ MX6Q_PAD_GPIO_19__GPIO_4_5,
+#endif
+ /* MCLK for csi0 */
+ MX6Q_PAD_GPIO_0__CCM_CLKO,
+ /*MX6Q_PAD_GPIO_3__CCM_CLKO2,i*/
+
+ /* Android GPIO keys */
+ MX6Q_PAD_SD2_CMD__GPIO_1_11, /* home */
+ MX6Q_PAD_SD2_DAT3__GPIO_1_12, /* back */
+ MX6Q_PAD_SD4_DAT4__GPIO_2_12, /* prog */
+ MX6Q_PAD_SD4_DAT7__GPIO_2_15, /* vol up */
+ MX6Q_PAD_DISP0_DAT20__GPIO_5_14, /* vol down */
+
+ /* SD1 */
+ MX6Q_PAD_SD1_CLK__USDHC1_CLK_50MHZ_40OHM,
+ MX6Q_PAD_SD1_CMD__USDHC1_CMD_50MHZ_40OHM,
+ MX6Q_PAD_SD1_DAT0__USDHC1_DAT0_50MHZ_40OHM,
+ MX6Q_PAD_SD1_DAT1__USDHC1_DAT1_50MHZ_40OHM,
+ MX6Q_PAD_SD1_DAT2__USDHC1_DAT2_50MHZ_40OHM,
+ MX6Q_PAD_SD1_DAT3__USDHC1_DAT3_50MHZ_40OHM,
+
+ /* SD1_CD and SD1_WP */
+ MX6Q_PAD_GPIO_1__GPIO_1_1,
+ MX6Q_PAD_CSI0_DATA_EN__GPIO_5_20,
+
+ /* SD3 */
+ MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6Q_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6Q_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6Q_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6Q_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+
+ /* SD3 VSelect */
+ MX6Q_PAD_GPIO_18__USDHC3_VSELECT,
+ /* SD3_CD and SD3_WP */
+ MX6Q_PAD_NANDF_CS2__GPIO_6_15,
+ MX6Q_PAD_SD2_DAT2__GPIO_1_13,
+
+ /* ESAI */
+ MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT,
+ MX6Q_PAD_ENET_RXD1__ESAI1_FST,
+ MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2,
+ MX6Q_PAD_GPIO_5__ESAI1_TX2_RX3,
+ MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1,
+ MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0,
+ MX6Q_PAD_GPIO_17__ESAI1_TX0,
+ MX6Q_PAD_NANDF_CS3__ESAI1_TX1,
+ MX6Q_PAD_ENET_MDIO__ESAI1_SCKR,
+ MX6Q_PAD_GPIO_9__ESAI1_FSR,
+ /* esai interrupt */
+ MX6Q_PAD_SD2_CLK__GPIO_1_10,
+
+ /* I2C2 */
+ MX6Q_PAD_EIM_EB2__I2C2_SCL,
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA,
+ MX6Q_PAD_SD2_DAT0__GPIO_1_15,
+
+ /* DISPLAY */
+ MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15,
+ MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2,
+ MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3,
+ MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
+ MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
+ MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
+ MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
+ MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
+ MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
+ MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
+ MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
+ MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
+ MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
+ MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
+ MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
+ MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
+ MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
+ MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
+ MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
+ MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
+ MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
+ MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
+ MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
+ MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
+
+ /* LITE_SENS_INT_B */
+ MX6Q_PAD_DISP0_DAT23__GPIO_5_17,
+ /*PMIC INT*/
+ MX6Q_PAD_DISP0_DAT22__GPIO_5_16,
+
+ /* ipu1 csi0 */
+ MX6Q_PAD_CSI0_DAT4__IPU1_CSI0_D_4,
+ MX6Q_PAD_CSI0_DAT5__IPU1_CSI0_D_5,
+ MX6Q_PAD_CSI0_DAT6__IPU1_CSI0_D_6,
+ MX6Q_PAD_CSI0_DAT7__IPU1_CSI0_D_7,
+ MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_D_8,
+ MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_D_9,
+ MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_D_10,
+ MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_D_11,
+ MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+ MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+
+ /* PWM3 and PMW4 */
+ MX6Q_PAD_SD4_DAT1__PWM3_PWMO,
+ MX6Q_PAD_SD4_DAT2__PWM4_PWMO,
+
+ /* DISP0 RESET */
+ MX6Q_PAD_EIM_WAIT__GPIO_5_0,
+
+ /* SPDIF */
+ MX6Q_PAD_KEY_COL3__SPDIF_IN1,
+
+ /* Touchscreen interrupt */
+ MX6Q_PAD_EIM_EB0__GPIO_2_28,
+
+ /* USBOTG ID pin */
+ MX6Q_PAD_ENET_RX_ER__ANATOP_USBOTG_ID,
+
+ /* VIDEO adv7180 INTRQ */
+ MX6Q_PAD_ENET_RXD0__GPIO_1_27,
+ /* UART 2 */
+ MX6Q_PAD_GPIO_7__UART2_TXD,
+ MX6Q_PAD_GPIO_8__UART2_RXD,
+ MX6Q_PAD_SD4_DAT6__UART2_CTS,
+ MX6Q_PAD_SD4_DAT5__UART2_RTS,
+
+ /*USBs OC pin */
+ MX6Q_PAD_EIM_WAIT__GPIO_5_0, /*HOST1_OC*/
+ MX6Q_PAD_SD4_DAT0__GPIO_2_8, /*OTG_OC*/
+
+ /* DISP0 I2C ENABLE*/
+ MX6Q_PAD_EIM_D28__GPIO_3_28,
+
+ /* DISP0 DET */
+ MX6Q_PAD_EIM_D31__GPIO_3_31,
+
+ /* DISP0 RESET */
+ MX6Q_PAD_EIM_WAIT__GPIO_5_0,
+
+ /* HDMI */
+ MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE,
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1,
+#else
+ /* MLB150 */
+ MX6Q_PAD_ENET_TXD1__MLB_MLBCLK,
+ MX6Q_PAD_GPIO_6__MLB_MLBSIG,
+ MX6Q_PAD_GPIO_2__MLB_MLBDAT,
+#endif
+};
+
+static iomux_v3_cfg_t mx6q_sabreauto_can0_pads[] = {
+ /* CAN1 */
+ MX6Q_PAD_KEY_COL2__CAN1_TXCAN,
+ MX6Q_PAD_KEY_ROW2__CAN1_RXCAN,
+};
+
+
+static iomux_v3_cfg_t mx6q_sabreauto_can1_pads[] = {
+ /* CAN2 */
+ MX6Q_PAD_KEY_COL4__CAN2_TXCAN,
+ MX6Q_PAD_KEY_ROW4__CAN2_RXCAN,
+};
+
+static iomux_v3_cfg_t mx6q_sabreauto_mipi_sensor_pads[] = {
+ MX6Q_PAD_CSI0_MCLK__CCM_CLKO,
+};
+
+#define MX6Q_USDHC_PAD_SETTING(id, speed) \
+mx6q_sd##id##_##speed##mhz[] = { \
+ MX6Q_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \
+}
+
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 50);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 100);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 200);
+
+/* The GPMI is conflicted with SD3, so init this in the driver. */
+static iomux_v3_cfg_t mx6q_gpmi_nand[] __initdata = {
+ MX6Q_PAD_NANDF_CLE__RAWNAND_CLE,
+ MX6Q_PAD_NANDF_ALE__RAWNAND_ALE,
+ MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N,
+ MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N,
+ MX6Q_PAD_NANDF_RB0__RAWNAND_READY0,
+ MX6Q_PAD_SD4_DAT0__RAWNAND_DQS,
+ MX6Q_PAD_NANDF_D0__RAWNAND_D0,
+ MX6Q_PAD_NANDF_D1__RAWNAND_D1,
+ MX6Q_PAD_NANDF_D2__RAWNAND_D2,
+ MX6Q_PAD_NANDF_D3__RAWNAND_D3,
+ MX6Q_PAD_NANDF_D4__RAWNAND_D4,
+ MX6Q_PAD_NANDF_D5__RAWNAND_D5,
+ MX6Q_PAD_NANDF_D6__RAWNAND_D6,
+ MX6Q_PAD_NANDF_D7__RAWNAND_D7,
+ MX6Q_PAD_SD4_CMD__RAWNAND_RDN,
+ MX6Q_PAD_SD4_CLK__RAWNAND_WRN,
+ MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN,
+};
+
+static iomux_v3_cfg_t mx6q_i2c3_pads_rev_a[] __initdata = {
+ MX6Q_PAD_GPIO_3__I2C3_SCL,
+ MX6Q_PAD_GPIO_16__I2C3_SDA,
+};
+static iomux_v3_cfg_t mx6q_i2c3_pads_rev_b[] __initdata = {
+ MX6Q_PAD_GPIO_3__I2C3_SCL,
+ MX6Q_PAD_EIM_D18__I2C3_SDA,
+};
+static iomux_v3_cfg_t mx6q_tuner_pads[] __initdata = {
+ MX6Q_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC,
+ MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS,
+ MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD,
+};
+static iomux_v3_cfg_t mx6q_extra_pads_rev_b[] __initdata = {
+ MX6Q_PAD_EIM_A24__GPIO_5_4,
+ MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT,
+};
+static iomux_v3_cfg_t mx6q_spinor_pads[] __initdata = {
+ /* eCSPI1 */
+ MX6Q_PAD_EIM_D16__ECSPI1_SCLK,
+ MX6Q_PAD_EIM_D17__ECSPI1_MISO,
+ MX6Q_PAD_EIM_D18__ECSPI1_MOSI,
+ MX6Q_PAD_EIM_D19__ECSPI1_SS1,
+
+ MX6Q_PAD_EIM_D19__GPIO_3_19,
+};
+
+/*Bluetooth is conflicted with GMPI and NOR chips*/
+static iomux_v3_cfg_t mx6q_bluetooth_pads[] __initdata = {
+ /* UART 3 */
+ MX6Q_PAD_SD4_CLK__UART3_RXD,
+ MX6Q_PAD_SD4_CMD__UART3_TXD,
+ MX6Q_PAD_EIM_D30__UART3_CTS,
+ MX6Q_PAD_EIM_EB3__UART3_RTS,
+};
+
+static iomux_v3_cfg_t mx6q_weimnor_pads[] __initdata = {
+ /* Parallel NOR */
+ MX6Q_PAD_EIM_OE__WEIM_WEIM_OE,
+ MX6Q_PAD_EIM_RW__WEIM_WEIM_RW,
+ MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT,
+ MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0,
+ /*Control NOR reset using gpio mode*/
+ MX6Q_PAD_DISP0_DAT8__GPIO_4_29,
+
+ MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA,
+ MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK,
+ /* Parallel Nor Data Bus */
+ MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16,
+ MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17,
+ MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18,
+ MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19,
+ MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20,
+ MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21,
+ MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22,
+ MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23,
+ MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24,
+ MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25,
+ MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26,
+ MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27,
+ MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28,
+ MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29,
+ MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30,
+ MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31,
+
+ /* Parallel Nor 25 bit Address Bus */
+ MX6Q_PAD_EIM_A24__GPIO_5_4,
+ MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23,
+ MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22,
+ MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21,
+ MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20,
+ MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19,
+ MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18,
+ MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17,
+ MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16,
+
+ MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15,
+ MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14,
+ MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13,
+ MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12,
+ MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11,
+ MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10,
+ MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9,
+ MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8,
+ MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7,
+ MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6,
+ MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5,
+ MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4,
+ MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3,
+ MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2,
+ MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1,
+ MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0,
+};
+
+static iomux_v3_cfg_t mx6q_sabreauto_hdmi_ddc_pads[] = {
+ MX6Q_PAD_EIM_EB2__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_sabreauto_i2c2_pads[] = {
+ MX6Q_PAD_EIM_EB2__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
diff --git a/arch/arm/mach-mx6/board-mx6q_sabrelite.c b/arch/arm/mach-mx6/board-mx6q_sabrelite.c
new file mode 100644
index 00000000..f13a5d47
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_sabrelite.c
@@ -0,0 +1,1414 @@
+/*
+ * Copyright (C) 2011-2013 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 <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/ion.h>
+#include <linux/etherdevice.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/memory.h>
+#include <mach/iomux-mx6q.h>
+#include <mach/imx-uart.h>
+#include <mach/viv_gpu.h>
+#include <mach/ahci_sata.h>
+#include <mach/ipu-v3.h>
+#include <mach/mxc_hdmi.h>
+#include <mach/mxc_asrc.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "usb.h"
+#include "devices-imx6q.h"
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+
+#define MX6Q_SABRELITE_SD3_CD IMX_GPIO_NR(7, 0)
+#define MX6Q_SABRELITE_SD3_WP IMX_GPIO_NR(7, 1)
+#define MX6Q_SABRELITE_SD4_CD IMX_GPIO_NR(2, 6)
+#define MX6Q_SABRELITE_SD4_WP IMX_GPIO_NR(2, 7)
+#define MX6Q_SABRELITE_ECSPI1_CS1 IMX_GPIO_NR(3, 19)
+#define MX6Q_SABRELITE_USB_OTG_PWR IMX_GPIO_NR(3, 22)
+#define MX6Q_SABRELITE_CAP_TCH_INT1 IMX_GPIO_NR(1, 9)
+#define MX6Q_SABRELITE_USB_HUB_RESET IMX_GPIO_NR(7, 12)
+#define MX6Q_SABRELITE_CAN1_STBY IMX_GPIO_NR(1, 2)
+#define MX6Q_SABRELITE_CAN1_EN IMX_GPIO_NR(1, 4)
+#define MX6Q_SABRELITE_MENU_KEY IMX_GPIO_NR(2, 1)
+#define MX6Q_SABRELITE_BACK_KEY IMX_GPIO_NR(2, 2)
+#define MX6Q_SABRELITE_ONOFF_KEY IMX_GPIO_NR(2, 3)
+#define MX6Q_SABRELITE_HOME_KEY IMX_GPIO_NR(2, 4)
+#define MX6Q_SABRELITE_VOL_UP_KEY IMX_GPIO_NR(7, 13)
+#define MX6Q_SABRELITE_VOL_DOWN_KEY IMX_GPIO_NR(4, 5)
+#define MX6Q_SABRELITE_CSI0_RST IMX_GPIO_NR(1, 8)
+#define MX6Q_SABRELITE_CSI0_PWN IMX_GPIO_NR(1, 6)
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+#define MX6_ENET_IRQ IMX_GPIO_NR(1, 6)
+#define IOMUX_OBSRV_MUX1_OFFSET 0x3c
+#define OBSRV_MUX1_MASK 0x3f
+#define OBSRV_MUX1_ENET_IRQ 0x9
+#endif
+
+#define MX6Q_SABRELITE_SD3_WP_PADCFG (PAD_CTL_PKE | PAD_CTL_PUE | \
+ PAD_CTL_PUS_22K_UP | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+void __init early_console_setup(unsigned long base, struct clk *clk);
+static struct clk *sata_clk;
+
+extern char *gp_reg_id;
+extern char *soc_reg_id;
+extern char *pu_reg_id;
+static int caam_enabled;
+
+extern struct regulator *(*get_cpu_regulator)(void);
+extern void (*put_cpu_regulator)(void);
+
+static iomux_v3_cfg_t mx6q_sabrelite_pads[] = {
+ /* AUDMUX */
+ MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD,
+ MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC,
+ MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD,
+ MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS,
+
+ /* CAN1 */
+ MX6Q_PAD_KEY_ROW2__CAN1_RXCAN,
+ MX6Q_PAD_KEY_COL2__CAN1_TXCAN,
+ MX6Q_PAD_GPIO_2__GPIO_1_2, /* STNDBY */
+ MX6Q_PAD_GPIO_7__GPIO_1_7, /* NERR */
+ MX6Q_PAD_GPIO_4__GPIO_1_4, /* Enable */
+
+ /* CCM */
+ MX6Q_PAD_GPIO_0__CCM_CLKO, /* SGTL500 sys_mclk */
+ MX6Q_PAD_GPIO_3__CCM_CLKO2, /* J5 - Camera MCLK */
+
+ /* ECSPI1 */
+ MX6Q_PAD_EIM_D17__ECSPI1_MISO,
+ MX6Q_PAD_EIM_D18__ECSPI1_MOSI,
+ MX6Q_PAD_EIM_D16__ECSPI1_SCLK,
+ MX6Q_PAD_EIM_D19__GPIO_3_19, /*SS1*/
+
+ /* ENET */
+ MX6Q_PAD_ENET_MDIO__ENET_MDIO,
+ MX6Q_PAD_ENET_MDC__ENET_MDC,
+ MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC,
+ MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0,
+ MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1,
+ MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2,
+ MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3,
+ MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL,
+ MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK,
+ MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC,
+ MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0,
+ MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1,
+ MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2,
+ MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3,
+ MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL,
+ MX6Q_PAD_ENET_TX_EN__GPIO_1_28, /* Micrel RGMII Phy Interrupt */
+ MX6Q_PAD_EIM_D23__GPIO_3_23, /* RGMII reset */
+
+ /* GPIO1 */
+ MX6Q_PAD_ENET_RX_ER__GPIO_1_24, /* J9 - Microphone Detect */
+
+ /* GPIO2 */
+ MX6Q_PAD_NANDF_D1__GPIO_2_1, /* J14 - Menu Button */
+ MX6Q_PAD_NANDF_D2__GPIO_2_2, /* J14 - Back Button */
+ MX6Q_PAD_NANDF_D3__GPIO_2_3, /* J14 - Search Button */
+ MX6Q_PAD_NANDF_D4__GPIO_2_4, /* J14 - Home Button */
+ MX6Q_PAD_EIM_A22__GPIO_2_16, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A21__GPIO_2_17, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A20__GPIO_2_18, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A19__GPIO_2_19, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A18__GPIO_2_20, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A17__GPIO_2_21, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A16__GPIO_2_22, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_RW__GPIO_2_26, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_LBA__GPIO_2_27, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_EB0__GPIO_2_28, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_EB1__GPIO_2_29, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_EB3__GPIO_2_31, /* J12 - Boot Mode Select */
+
+ /* GPIO3 */
+ MX6Q_PAD_EIM_DA0__GPIO_3_0, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA1__GPIO_3_1, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA2__GPIO_3_2, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA3__GPIO_3_3, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA4__GPIO_3_4, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA5__GPIO_3_5, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA6__GPIO_3_6, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA7__GPIO_3_7, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA8__GPIO_3_8, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA9__GPIO_3_9, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA10__GPIO_3_10, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA11__GPIO_3_11, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA12__GPIO_3_12, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA13__GPIO_3_13, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA14__GPIO_3_14, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA15__GPIO_3_15, /* J12 - Boot Mode Select */
+
+ /* GPIO4 */
+ MX6Q_PAD_GPIO_19__GPIO_4_5, /* J14 - Volume Down */
+
+ /* GPIO5 */
+ MX6Q_PAD_EIM_WAIT__GPIO_5_0, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A24__GPIO_5_4, /* J12 - Boot Mode Select */
+
+ /* GPIO6 */
+ MX6Q_PAD_EIM_A23__GPIO_6_6, /* J12 - Boot Mode Select */
+
+ /* GPIO7 */
+ MX6Q_PAD_GPIO_17__GPIO_7_12, /* USB Hub Reset */
+ MX6Q_PAD_GPIO_18__GPIO_7_13, /* J14 - Volume Up */
+
+ /* I2C1, SGTL5000 */
+ MX6Q_PAD_EIM_D21__I2C1_SCL, /* GPIO3[21] */
+ MX6Q_PAD_EIM_D28__I2C1_SDA, /* GPIO3[28] */
+
+ /* I2C2 Camera, MIPI */
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* GPIO4[12] */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* GPIO4[13] */
+
+ /* I2C3 */
+ MX6Q_PAD_GPIO_5__I2C3_SCL, /* GPIO1[5] - J7 - Display card */
+#ifdef CONFIG_FEC_1588
+ MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT,
+#else
+ MX6Q_PAD_GPIO_16__I2C3_SDA, /* GPIO7[11] - J15 - RGB connector */
+#endif
+
+ /* DISPLAY */
+ MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15, /* DE */
+ MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2, /* HSync */
+ MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3, /* VSync */
+ MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN4, /* Contrast */
+ MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
+ MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
+ MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
+ MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
+ MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
+ MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
+ MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
+ MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
+ MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
+ MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
+ MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
+ MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
+ MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
+ MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
+ MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
+ MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
+ MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
+ MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
+ MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
+ MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
+ MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20,
+ MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
+ MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22,
+ MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23,
+ MX6Q_PAD_GPIO_7__GPIO_1_7, /* J7 - Display Connector GP */
+ MX6Q_PAD_GPIO_9__GPIO_1_9, /* J7 - Display Connector GP */
+ MX6Q_PAD_NANDF_D0__GPIO_2_0, /* J6 - LVDS Display contrast */
+
+
+ /* PWM1 */
+ MX6Q_PAD_SD1_DAT3__PWM1_PWMO, /* GPIO1[21] */
+
+ /* PWM2 */
+ MX6Q_PAD_SD1_DAT2__PWM2_PWMO, /* GPIO1[19] */
+
+ /* PWM3 */
+ MX6Q_PAD_SD1_DAT1__PWM3_PWMO, /* GPIO1[17] */
+
+ /* PWM4 */
+ MX6Q_PAD_SD1_CMD__PWM4_PWMO, /* GPIO1[18] */
+
+ /* UART1 */
+ MX6Q_PAD_SD3_DAT7__UART1_TXD,
+ MX6Q_PAD_SD3_DAT6__UART1_RXD,
+
+ /* UART2 for debug */
+ MX6Q_PAD_EIM_D26__UART2_TXD,
+ MX6Q_PAD_EIM_D27__UART2_RXD,
+
+ /* USBOTG ID pin */
+ MX6Q_PAD_GPIO_1__USBOTG_ID,
+
+ /* USB OC pin */
+ MX6Q_PAD_KEY_COL4__USBOH3_USBOTG_OC,
+ MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC,
+
+ /* USDHC3 */
+ MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6Q_PAD_SD3_DAT5__GPIO_7_0, /* J18 - SD3_CD */
+ NEW_PAD_CTRL(MX6Q_PAD_SD3_DAT4__GPIO_7_1, MX6Q_SABRELITE_SD3_WP_PADCFG),
+
+ /* USDHC4 */
+ MX6Q_PAD_SD4_CLK__USDHC4_CLK_50MHZ,
+ MX6Q_PAD_SD4_CMD__USDHC4_CMD_50MHZ,
+ MX6Q_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ,
+ MX6Q_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ,
+ MX6Q_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ,
+ MX6Q_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ,
+ MX6Q_PAD_NANDF_D6__GPIO_2_6, /* J20 - SD4_CD */
+ MX6Q_PAD_NANDF_D7__GPIO_2_7, /* SD4_WP */
+};
+
+static iomux_v3_cfg_t mx6q_sabrelite_csi0_sensor_pads[] = {
+ /* IPU1 Camera */
+ MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_D_8,
+ MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_D_9,
+ MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_D_10,
+ MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_D_11,
+ MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN,
+ MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+ MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ MX6Q_PAD_GPIO_6__GPIO_1_6, /* J5 - Camera GP */
+#endif
+ MX6Q_PAD_GPIO_8__GPIO_1_8, /* J5 - Camera Reset */
+ MX6Q_PAD_SD1_DAT0__GPIO_1_16, /* J5 - Camera GP */
+ MX6Q_PAD_NANDF_D5__GPIO_2_5, /* J16 - MIPI GP */
+ MX6Q_PAD_NANDF_WP_B__GPIO_6_9, /* J16 - MIPI GP */
+};
+
+static iomux_v3_cfg_t mx6q_sabrelite_hdmi_ddc_pads[] = {
+ MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_sabrelite_i2c2_pads[] = {
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
+
+#define MX6Q_USDHC_PAD_SETTING(id, speed) \
+mx6q_sd##id##_##speed##mhz[] = { \
+ MX6Q_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
+ MX6Q_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
+}
+
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 50);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 100);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 200);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 50);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 100);
+static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 200);
+
+enum sd_pad_mode {
+ SD_PAD_MODE_LOW_SPEED,
+ SD_PAD_MODE_MED_SPEED,
+ SD_PAD_MODE_HIGH_SPEED,
+};
+
+static int plt_sd_pad_change(unsigned int index, int clock)
+{
+ /* LOW speed is the default state of SD pads */
+ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
+
+ iomux_v3_cfg_t *sd_pads_200mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_100mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_50mhz = NULL;
+
+ u32 sd_pads_200mhz_cnt;
+ u32 sd_pads_100mhz_cnt;
+ u32 sd_pads_50mhz_cnt;
+
+ switch (index) {
+ case 2:
+ sd_pads_200mhz = mx6q_sd3_200mhz;
+ sd_pads_100mhz = mx6q_sd3_100mhz;
+ sd_pads_50mhz = mx6q_sd3_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
+ break;
+ case 3:
+ sd_pads_200mhz = mx6q_sd4_200mhz;
+ sd_pads_100mhz = mx6q_sd4_100mhz;
+ sd_pads_50mhz = mx6q_sd4_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd4_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd4_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd4_50mhz);
+ break;
+ default:
+ printk(KERN_ERR "no such SD host controller index %d\n", index);
+ return -EINVAL;
+ }
+
+ if (clock > 100000000) {
+ if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_200mhz);
+ pad_mode = SD_PAD_MODE_HIGH_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
+ sd_pads_200mhz_cnt);
+ } else if (clock > 52000000) {
+ if (pad_mode == SD_PAD_MODE_MED_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_100mhz);
+ pad_mode = SD_PAD_MODE_MED_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
+ sd_pads_100mhz_cnt);
+ } else {
+ if (pad_mode == SD_PAD_MODE_LOW_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_50mhz);
+ pad_mode = SD_PAD_MODE_LOW_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
+ sd_pads_50mhz_cnt);
+ }
+}
+
+static const struct esdhc_platform_data mx6q_sabrelite_sd3_data __initconst = {
+ .cd_gpio = MX6Q_SABRELITE_SD3_CD,
+ .wp_gpio = MX6Q_SABRELITE_SD3_WP,
+ .keep_power_at_suspend = 1,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+static const struct esdhc_platform_data mx6q_sabrelite_sd4_data __initconst = {
+ .cd_gpio = MX6Q_SABRELITE_SD4_CD,
+ .wp_gpio = MX6Q_SABRELITE_SD4_WP,
+ .keep_power_at_suspend = 1,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+static const struct anatop_thermal_platform_data
+ mx6q_sabrelite_anatop_thermal_data __initconst = {
+ .name = "anatop_thermal",
+};
+
+static inline void mx6q_sabrelite_init_uart(void)
+{
+ imx6q_add_imx_uart(0, NULL);
+ imx6q_add_imx_uart(1, NULL);
+}
+
+static int mx6q_sabrelite_fec_phy_init(struct phy_device *phydev)
+{
+ /* prefer master mode, disable 1000 Base-T capable */
+ phy_write(phydev, 0x9, 0x1c00);
+
+ /* min rx data delay */
+ phy_write(phydev, 0x0b, 0x8105);
+ phy_write(phydev, 0x0c, 0x0000);
+
+ /* max rx/tx clock delay, min rx/tx control delay */
+ phy_write(phydev, 0x0b, 0x8104);
+ phy_write(phydev, 0x0c, 0xf0f0);
+ phy_write(phydev, 0x0b, 0x104);
+
+ return 0;
+}
+
+static struct fec_platform_data fec_data __initdata = {
+ .init = mx6q_sabrelite_fec_phy_init,
+ .phy = PHY_INTERFACE_MODE_RGMII,
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ .gpio_irq = MX6_ENET_IRQ,
+#endif
+};
+
+static int mx6q_sabrelite_spi_cs[] = {
+ MX6Q_SABRELITE_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx6q_sabrelite_spi_data __initconst = {
+ .chipselect = mx6q_sabrelite_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx6q_sabrelite_spi_cs),
+};
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition imx6_sabrelite_spi_nor_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x00100000,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data imx6_sabrelite__spi_flash_data = {
+ .name = "m25p80",
+ .parts = imx6_sabrelite_spi_nor_partitions,
+ .nr_parts = ARRAY_SIZE(imx6_sabrelite_spi_nor_partitions),
+ .type = "sst25vf016b",
+};
+#endif
+
+static struct spi_board_info imx6_sabrelite_spi_nor_device[] __initdata = {
+#if defined(CONFIG_MTD_M25P80)
+ {
+ .modalias = "m25p80",
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = &imx6_sabrelite__spi_flash_data,
+ },
+#endif
+};
+
+static void spi_device_init(void)
+{
+ spi_register_board_info(imx6_sabrelite_spi_nor_device,
+ ARRAY_SIZE(imx6_sabrelite_spi_nor_device));
+}
+
+static struct mxc_audio_platform_data mx6_sabrelite_audio_data;
+
+static int mx6_sabrelite_sgtl5000_init(void)
+{
+ struct clk *clko;
+ struct clk *new_parent;
+ int rate;
+
+ clko = clk_get(NULL, "clko_clk");
+ if (IS_ERR(clko)) {
+ pr_err("can't get CLKO clock.\n");
+ return PTR_ERR(clko);
+ }
+ new_parent = clk_get(NULL, "ahb");
+ if (!IS_ERR(new_parent)) {
+ clk_set_parent(clko, new_parent);
+ clk_put(new_parent);
+ }
+ rate = clk_round_rate(clko, 16000000);
+ if (rate < 8000000 || rate > 27000000) {
+ pr_err("Error:SGTL5000 mclk freq %d out of range!\n", rate);
+ clk_put(clko);
+ return -1;
+ }
+
+ mx6_sabrelite_audio_data.sysclk = rate;
+ clk_set_rate(clko, rate);
+ clk_enable(clko);
+ return 0;
+}
+
+static struct imx_ssi_platform_data mx6_sabrelite_ssi_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_SYN,
+};
+
+static struct mxc_audio_platform_data mx6_sabrelite_audio_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 4,
+ .init = mx6_sabrelite_sgtl5000_init,
+ .hp_gpio = -1,
+};
+
+static struct platform_device mx6_sabrelite_audio_device = {
+ .name = "imx-sgtl5000",
+};
+
+static struct imxi2c_platform_data mx6q_sabrelite_i2c_data = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("sgtl5000", 0x0a),
+ },
+};
+
+static void mx6q_csi0_cam_powerdown(int powerdown)
+{
+ if (powerdown)
+ gpio_set_value(MX6Q_SABRELITE_CSI0_PWN, 1);
+ else
+ gpio_set_value(MX6Q_SABRELITE_CSI0_PWN, 0);
+
+ msleep(2);
+}
+
+static void mx6q_csi0_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabrelite_csi0_sensor_pads,
+ ARRAY_SIZE(mx6q_sabrelite_csi0_sensor_pads));
+
+ /* Camera power down */
+ gpio_request(MX6Q_SABRELITE_CSI0_PWN, "cam-pwdn");
+ gpio_direction_output(MX6Q_SABRELITE_CSI0_PWN, 1);
+ msleep(1);
+ gpio_set_value(MX6Q_SABRELITE_CSI0_PWN, 0);
+
+ /* Camera reset */
+ gpio_request(MX6Q_SABRELITE_CSI0_RST, "cam-reset");
+ gpio_direction_output(MX6Q_SABRELITE_CSI0_RST, 1);
+
+ gpio_set_value(MX6Q_SABRELITE_CSI0_RST, 0);
+ msleep(1);
+ gpio_set_value(MX6Q_SABRELITE_CSI0_RST, 1);
+
+ /* For MX6Q GPR1 bit19 and bit20 meaning:
+ * Bit19: 0 - Enable mipi to IPU1 CSI0
+ * virtual channel is fixed to 0
+ * 1 - Enable parallel interface to IPU1 CSI0
+ * Bit20: 0 - Enable mipi to IPU2 CSI1
+ * virtual channel is fixed to 3
+ * 1 - Enable parallel interface to IPU2 CSI1
+ * IPU1 CSI1 directly connect to mipi csi2,
+ * virtual channel is fixed to 1
+ * IPU2 CSI0 directly connect to mipi csi2,
+ * virtual channel is fixed to 2
+ */
+ mxc_iomux_set_gpr_register(1, 19, 1, 1);
+}
+
+static struct fsl_mxc_camera_platform_data camera_data = {
+ .mclk = 24000000,
+ .mclk_source = 0,
+ .csi = 0,
+ .io_init = mx6q_csi0_io_init,
+ .pwdn = mx6q_csi0_cam_powerdown,
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50),
+ },
+ {
+ I2C_BOARD_INFO("ov564x", 0x3c),
+ .platform_data = (void *)&camera_data,
+ },
+};
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("egalax_ts", 0x4),
+ .irq = gpio_to_irq(MX6Q_SABRELITE_CAP_TCH_INT1),
+ },
+};
+
+static void imx6q_sabrelite_usbotg_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(MX6Q_SABRELITE_USB_OTG_PWR, 1);
+ else
+ gpio_set_value(MX6Q_SABRELITE_USB_OTG_PWR, 0);
+}
+
+static void __init imx6q_sabrelite_init_usb(void)
+{
+ int ret = 0;
+
+ imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR);
+ /* disable external charger detect,
+ * or it will affect signal quality at dp .
+ */
+ ret = gpio_request(MX6Q_SABRELITE_USB_OTG_PWR, "usb-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO MX6Q_SABRELITE_USB_OTG_PWR: %d\n",
+ ret);
+ return;
+ }
+ gpio_direction_output(MX6Q_SABRELITE_USB_OTG_PWR, 0);
+ mxc_iomux_set_gpr_register(1, 13, 1, 1);
+
+ mx6_set_otghost_vbus_func(imx6q_sabrelite_usbotg_vbus);
+ mx6_usb_dr_init();
+}
+
+/* HW Initialization, if return 0, initialization is successful. */
+static int mx6q_sabrelite_sata_init(struct device *dev, void __iomem *addr)
+{
+ u32 tmpdata;
+ int ret = 0;
+ struct clk *clk;
+
+ sata_clk = clk_get(dev, "imx_sata_clk");
+ if (IS_ERR(sata_clk)) {
+ dev_err(dev, "no sata clock.\n");
+ return PTR_ERR(sata_clk);
+ }
+ ret = clk_enable(sata_clk);
+ if (ret) {
+ dev_err(dev, "can't enable sata clock.\n");
+ goto put_sata_clk;
+ }
+
+ /* Set PHY Paremeters, two steps to configure the GPR13,
+ * one write for rest of parameters, mask of first write is 0x07FFFFFD,
+ * and the other one write for setting the mpll_clk_off_b
+ *.rx_eq_val_0(iomuxc_gpr13[26:24]),
+ *.los_lvl(iomuxc_gpr13[23:19]),
+ *.rx_dpll_mode_0(iomuxc_gpr13[18:16]),
+ *.sata_speed(iomuxc_gpr13[15]),
+ *.mpll_ss_en(iomuxc_gpr13[14]),
+ *.tx_atten_0(iomuxc_gpr13[13:11]),
+ *.tx_boost_0(iomuxc_gpr13[10:7]),
+ *.tx_lvl(iomuxc_gpr13[6:2]),
+ *.mpll_ck_off(iomuxc_gpr13[1]),
+ *.tx_edgerate_0(iomuxc_gpr13[0]),
+ */
+ tmpdata = readl(IOMUXC_GPR13);
+ writel(((tmpdata & ~0x07FFFFFD) | 0x0593A044), IOMUXC_GPR13);
+
+ /* enable SATA_PHY PLL */
+ tmpdata = readl(IOMUXC_GPR13);
+ writel(((tmpdata & ~0x2) | 0x2), IOMUXC_GPR13);
+
+ /* Get the AHB clock rate, and configure the TIMER1MS reg later */
+ clk = clk_get(NULL, "ahb");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "no ahb clock.\n");
+ ret = PTR_ERR(clk);
+ goto release_sata_clk;
+ }
+ tmpdata = clk_get_rate(clk) / 1000;
+ clk_put(clk);
+
+#ifdef CONFIG_SATA_AHCI_PLATFORM
+ ret = sata_init(addr, tmpdata);
+ if (ret == 0)
+ return ret;
+#else
+ usleep_range(1000, 2000);
+ /* AHCI PHY enter into PDDQ mode if the AHCI module is not enabled */
+ tmpdata = readl(addr + PORT_PHY_CTL);
+ writel(tmpdata | PORT_PHY_CTL_PDDQ_LOC, addr + PORT_PHY_CTL);
+ pr_info("No AHCI save PWR: PDDQ %s\n", ((readl(addr + PORT_PHY_CTL)
+ >> 20) & 1) ? "enabled" : "disabled");
+#endif
+
+release_sata_clk:
+ /* disable SATA_PHY PLL */
+ writel((readl(IOMUXC_GPR13) & ~0x2), IOMUXC_GPR13);
+ clk_disable(sata_clk);
+put_sata_clk:
+ clk_put(sata_clk);
+
+ return ret;
+}
+
+#ifdef CONFIG_SATA_AHCI_PLATFORM
+static void mx6q_sabrelite_sata_exit(struct device *dev)
+{
+ clk_disable(sata_clk);
+ clk_put(sata_clk);
+}
+
+static struct ahci_platform_data mx6q_sabrelite_sata_data = {
+ .init = mx6q_sabrelite_sata_init,
+ .exit = mx6q_sabrelite_sata_exit,
+};
+#endif
+
+static struct gpio mx6q_sabrelite_flexcan_gpios[] = {
+ { MX6Q_SABRELITE_CAN1_EN, GPIOF_OUT_INIT_LOW, "flexcan1-en" },
+ { MX6Q_SABRELITE_CAN1_STBY, GPIOF_OUT_INIT_LOW, "flexcan1-stby" },
+};
+
+static void mx6q_sabrelite_flexcan0_switch(int enable)
+{
+ if (enable) {
+ gpio_set_value(MX6Q_SABRELITE_CAN1_EN, 1);
+ gpio_set_value(MX6Q_SABRELITE_CAN1_STBY, 1);
+ } else {
+ gpio_set_value(MX6Q_SABRELITE_CAN1_EN, 0);
+ gpio_set_value(MX6Q_SABRELITE_CAN1_STBY, 0);
+ }
+}
+
+static const struct flexcan_platform_data
+ mx6q_sabrelite_flexcan0_pdata __initconst = {
+ .transceiver_switch = mx6q_sabrelite_flexcan0_switch,
+};
+
+static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
+ .reserved_mem_size = SZ_128M + SZ_64M,
+};
+
+static struct imx_asrc_platform_data imx_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 2,
+};
+
+static struct ipuv3_fb_platform_data sabrelite_fb_data[] = {
+ { /*fb0*/
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-XGA",
+ .default_bpp = 32,
+ .int_clk = false,
+ }, {
+ .disp_dev = "lcd",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB565,
+ .mode_str = "CLAA-WVGA",
+ .default_bpp = 16,
+ .int_clk = false,
+ }, {
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-SVGA",
+ .default_bpp = 16,
+ .int_clk = false,
+ }, {
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-VGA",
+ .default_bpp = 16,
+ .int_clk = false,
+ },
+};
+
+static void hdmi_init(int ipu_id, int disp_id)
+{
+ int hdmi_mux_setting;
+
+ if ((ipu_id > 1) || (ipu_id < 0)) {
+ pr_err("Invalid IPU select for HDMI: %d. Set to 0\n", ipu_id);
+ ipu_id = 0;
+ }
+
+ if ((disp_id > 1) || (disp_id < 0)) {
+ pr_err("Invalid DI select for HDMI: %d. Set to 0\n", disp_id);
+ disp_id = 0;
+ }
+
+ /* Configure the connection between IPU1/2 and HDMI */
+ hdmi_mux_setting = 2*ipu_id + disp_id;
+
+ /* GPR3, bits 2-3 = HDMI_MUX_CTL */
+ mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
+
+ /* Set HDMI event as SDMA event2 while Chip version later than TO1.2 */
+ if ((mx6q_revision() > IMX_CHIP_REVISION_1_1))
+ mxc_iomux_set_gpr_register(0, 0, 1, 1);
+}
+
+/* On mx6x sbarelite board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabrelite_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_sabrelite_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabrelite_i2c2_pads,
+ ARRAY_SIZE(mx6q_sabrelite_i2c2_pads));
+}
+
+static struct fsl_mxc_hdmi_platform_data hdmi_data = {
+ .init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
+};
+
+static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+};
+
+static struct fsl_mxc_lcd_platform_data lcdif_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .default_ifmt = IPU_PIX_FMT_RGB565,
+};
+
+static struct fsl_mxc_ldb_platform_data ldb_data = {
+ .ipu_id = 1,
+ .disp_id = 0,
+ .ext_ref = 1,
+ .mode = LDB_SEP0,
+ .sec_ipu_id = 1,
+ .sec_disp_id = 1,
+};
+
+static struct imx_ipuv3_platform_data ipu_data[] = {
+ {
+ .rev = 4,
+ .csi_clk[0] = "clko2_clk",
+ }, {
+ .rev = 4,
+ .csi_clk[0] = "clko2_clk",
+ },
+};
+
+static struct ion_platform_data imx_ion_data = {
+ .nr = 1,
+ .heaps = {
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = "vpu_ion",
+ .size = SZ_64M,
+ },
+ },
+};
+
+static struct fsl_mxc_capture_platform_data capture_data[] = {
+ {
+ .csi = 0,
+ .ipu = 0,
+ .mclk_source = 0,
+ .is_mipi = 0,
+ }, {
+ .csi = 1,
+ .ipu = 0,
+ .mclk_source = 0,
+ .is_mipi = 1,
+ },
+};
+
+
+struct imx_vout_mem {
+ resource_size_t res_mbase;
+ resource_size_t res_msize;
+};
+
+static struct imx_vout_mem vout_mem __initdata = {
+ .res_msize = SZ_128M,
+};
+
+
+static void sabrelite_suspend_enter(void)
+{
+ /* suspend preparation */
+}
+
+static void sabrelite_suspend_exit(void)
+{
+ /* resume restore */
+}
+static const struct pm_platform_data mx6q_sabrelite_pm_data __initconst = {
+ .name = "imx_pm",
+ .suspend_enter = sabrelite_suspend_enter,
+ .suspend_exit = sabrelite_suspend_exit,
+};
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+}
+
+static struct gpio_keys_button sabrelite_buttons[] = {
+ GPIO_BUTTON(MX6Q_SABRELITE_ONOFF_KEY, KEY_POWER, 1, "key-power", 1),
+ GPIO_BUTTON(MX6Q_SABRELITE_MENU_KEY, KEY_MENU, 1, "key-memu", 0),
+ GPIO_BUTTON(MX6Q_SABRELITE_HOME_KEY, KEY_HOME, 1, "key-home", 0),
+ GPIO_BUTTON(MX6Q_SABRELITE_BACK_KEY, KEY_BACK, 1, "key-back", 0),
+ GPIO_BUTTON(MX6Q_SABRELITE_VOL_UP_KEY, KEY_VOLUMEUP, 1, "volume-up", 0),
+ GPIO_BUTTON(MX6Q_SABRELITE_VOL_DOWN_KEY, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static struct gpio_keys_platform_data sabrelite_button_data = {
+ .buttons = sabrelite_buttons,
+ .nbuttons = ARRAY_SIZE(sabrelite_buttons),
+};
+
+static struct platform_device sabrelite_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &sabrelite_button_data,
+ }
+};
+
+static void __init sabrelite_add_device_buttons(void)
+{
+ platform_device_register(&sabrelite_button_device);
+}
+#else
+static void __init sabrelite_add_device_buttons(void) {}
+#endif
+
+static struct regulator_consumer_supply sabrelite_vmmc_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.3"),
+};
+
+static struct regulator_init_data sabrelite_vmmc_init = {
+ .num_consumer_supplies = ARRAY_SIZE(sabrelite_vmmc_consumers),
+ .consumer_supplies = sabrelite_vmmc_consumers,
+};
+
+static struct fixed_voltage_config sabrelite_vmmc_reg_config = {
+ .supply_name = "vmmc",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &sabrelite_vmmc_init,
+};
+
+static struct platform_device sabrelite_vmmc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 3,
+ .dev = {
+ .platform_data = &sabrelite_vmmc_reg_config,
+ },
+};
+
+#ifdef CONFIG_SND_SOC_SGTL5000
+
+static struct regulator_consumer_supply sgtl5000_sabrelite_consumer_vdda = {
+ .supply = "VDDA",
+ .dev_name = "0-000a",
+};
+
+static struct regulator_consumer_supply sgtl5000_sabrelite_consumer_vddio = {
+ .supply = "VDDIO",
+ .dev_name = "0-000a",
+};
+
+static struct regulator_consumer_supply sgtl5000_sabrelite_consumer_vddd = {
+ .supply = "VDDD",
+ .dev_name = "0-000a",
+};
+
+static struct regulator_init_data sgtl5000_sabrelite_vdda_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &sgtl5000_sabrelite_consumer_vdda,
+};
+
+static struct regulator_init_data sgtl5000_sabrelite_vddio_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &sgtl5000_sabrelite_consumer_vddio,
+};
+
+static struct regulator_init_data sgtl5000_sabrelite_vddd_reg_initdata = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &sgtl5000_sabrelite_consumer_vddd,
+};
+
+static struct fixed_voltage_config sgtl5000_sabrelite_vdda_reg_config = {
+ .supply_name = "VDDA",
+ .microvolts = 2500000,
+ .gpio = -1,
+ .init_data = &sgtl5000_sabrelite_vdda_reg_initdata,
+};
+
+static struct fixed_voltage_config sgtl5000_sabrelite_vddio_reg_config = {
+ .supply_name = "VDDIO",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &sgtl5000_sabrelite_vddio_reg_initdata,
+};
+
+static struct fixed_voltage_config sgtl5000_sabrelite_vddd_reg_config = {
+ .supply_name = "VDDD",
+ .microvolts = 0,
+ .gpio = -1,
+ .init_data = &sgtl5000_sabrelite_vddd_reg_initdata,
+};
+
+static struct platform_device sgtl5000_sabrelite_vdda_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &sgtl5000_sabrelite_vdda_reg_config,
+ },
+};
+
+static struct platform_device sgtl5000_sabrelite_vddio_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &sgtl5000_sabrelite_vddio_reg_config,
+ },
+};
+
+static struct platform_device sgtl5000_sabrelite_vddd_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 2,
+ .dev = {
+ .platform_data = &sgtl5000_sabrelite_vddd_reg_config,
+ },
+};
+
+#endif /* CONFIG_SND_SOC_SGTL5000 */
+
+static int imx6q_init_audio(void)
+{
+ mxc_register_device(&mx6_sabrelite_audio_device,
+ &mx6_sabrelite_audio_data);
+ imx6q_add_imx_ssi(1, &mx6_sabrelite_ssi_pdata);
+#ifdef CONFIG_SND_SOC_SGTL5000
+ platform_device_register(&sgtl5000_sabrelite_vdda_reg_devices);
+ platform_device_register(&sgtl5000_sabrelite_vddio_reg_devices);
+ platform_device_register(&sgtl5000_sabrelite_vddd_reg_devices);
+#endif
+ return 0;
+}
+
+static struct platform_pwm_backlight_data mx6_sabrelite_pwm_backlight_data = {
+ .pwm_id = 3,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+
+static struct mxc_dvfs_platform_data sabrelite_dvfscore_data = {
+ .reg_id = "cpu_vddgp",
+ .soc_id = "cpu_vddsoc",
+ .pu_id = "cpu_vddvpu",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+};
+
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ char *str;
+ struct tag *t;
+ int i = 0;
+ struct ipuv3_fb_platform_data *pdata_fb = sabrelite_fb_data;
+
+ for_each_tag(t, tags) {
+ if (t->hdr.tag == ATAG_CMDLINE) {
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "fbmem=");
+ if (str != NULL) {
+ str += 6;
+ pdata_fb[i++].res_size[0] = memparse(str, &str);
+ while (*str == ',' &&
+ i < ARRAY_SIZE(sabrelite_fb_data)) {
+ str++;
+ pdata_fb[i++].res_size[0] = memparse(str, &str);
+ }
+ }
+ break;
+ }
+ }
+}
+
+static struct mipi_csi2_platform_data mipi_csi2_pdata = {
+ .ipu_id = 0,
+ .csi_id = 0,
+ .v_channel = 0,
+ .lanes = 2,
+ .dphy_clk = "mipi_pllref_clk",
+ .pixel_clk = "emi_clk",
+};
+
+static int __init caam_setup(char *__unused)
+{
+ caam_enabled = 1;
+ return 1;
+}
+early_param("caam", caam_setup);
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mx6_sabrelite_board_init(void)
+{
+ int i;
+ int ret;
+ struct clk *clko2;
+ struct clk *new_parent;
+ int rate;
+ struct platform_device *voutdev;
+
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabrelite_pads,
+ ARRAY_SIZE(mx6q_sabrelite_pads));
+
+#ifdef CONFIG_FEC_1588
+ /* Set GPIO_16 input for IEEE-1588 ts_clk and RMII reference clock
+ * For MX6 GPR1 bit21 meaning:
+ * Bit21: 0 - GPIO_16 pad output
+ * 1 - GPIO_16 pad input
+ */
+ mxc_iomux_set_gpr_register(1, 21, 1, 1);
+#endif
+
+ gp_reg_id = sabrelite_dvfscore_data.reg_id;
+ soc_reg_id = sabrelite_dvfscore_data.soc_id;
+ pu_reg_id = sabrelite_dvfscore_data.pu_id;
+ mx6q_sabrelite_init_uart();
+ imx6q_add_mxc_hdmi_core(&hdmi_core_data);
+
+ imx6q_add_ipuv3(0, &ipu_data[0]);
+ imx6q_add_ipuv3(1, &ipu_data[1]);
+
+ for (i = 0; i < ARRAY_SIZE(sabrelite_fb_data); i++)
+ imx6q_add_ipuv3fb(i, &sabrelite_fb_data[i]);
+
+ imx6q_add_vdoa();
+ imx6q_add_lcdif(&lcdif_data);
+ imx6q_add_ldb(&ldb_data);
+ voutdev = imx6q_add_v4l2_output(0);
+ if (vout_mem.res_msize && voutdev) {
+ dma_declare_coherent_memory(&voutdev->dev,
+ vout_mem.res_mbase,
+ vout_mem.res_mbase,
+ vout_mem.res_msize,
+ (DMA_MEMORY_MAP |
+ DMA_MEMORY_EXCLUSIVE));
+ }
+
+
+ imx6q_add_v4l2_capture(0, &capture_data[0]);
+ imx6q_add_v4l2_capture(1, &capture_data[1]);
+ imx6q_add_mipi_csi2(&mipi_csi2_pdata);
+ imx6q_add_imx_snvs_rtc();
+
+ if (1 == caam_enabled)
+ imx6q_add_imx_caam();
+
+ imx6q_add_imx_i2c(0, &mx6q_sabrelite_i2c_data);
+ imx6q_add_imx_i2c(1, &mx6q_sabrelite_i2c_data);
+ imx6q_add_imx_i2c(2, &mx6q_sabrelite_i2c_data);
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+
+ /* SPI */
+ imx6q_add_ecspi(0, &mx6q_sabrelite_spi_data);
+ spi_device_init();
+
+ imx6q_add_mxc_hdmi(&hdmi_data);
+
+ imx6q_add_anatop_thermal_imx(1, &mx6q_sabrelite_anatop_thermal_data);
+ imx6_init_fec(fec_data);
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */
+ mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET,
+ OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK);
+#endif
+ imx6q_add_pm_imx(0, &mx6q_sabrelite_pm_data);
+ imx6q_add_sdhci_usdhc_imx(3, &mx6q_sabrelite_sd4_data);
+ imx6q_add_sdhci_usdhc_imx(2, &mx6q_sabrelite_sd3_data);
+ imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata);
+ imx6q_sabrelite_init_usb();
+
+ if (cpu_is_mx6q()) {
+#ifdef CONFIG_SATA_AHCI_PLATFORM
+ imx6q_add_ahci(0, &mx6q_sabrelite_sata_data);
+#else
+ mx6q_sabrelite_sata_init(NULL,
+ (void __iomem *)ioremap(MX6Q_SATA_BASE_ADDR, SZ_4K));
+#endif
+ }
+ imx6q_add_vpu();
+ imx6q_init_audio();
+ platform_device_register(&sabrelite_vmmc_reg_devices);
+ imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ imx6q_add_asrc(&imx_asrc_data);
+
+ /* release USB Hub reset */
+ gpio_set_value(MX6Q_SABRELITE_USB_HUB_RESET, 1);
+
+ imx6q_add_mxc_pwm(0);
+ imx6q_add_mxc_pwm(1);
+ imx6q_add_mxc_pwm(2);
+ imx6q_add_mxc_pwm(3);
+ imx6q_add_mxc_pwm_backlight(3, &mx6_sabrelite_pwm_backlight_data);
+
+ imx6q_add_otp();
+ imx6q_add_viim();
+ imx6q_add_imx2_wdt(0, NULL);
+ imx6q_add_dma();
+
+ imx6q_add_dvfs_core(&sabrelite_dvfscore_data);
+
+ imx6q_add_ion(0, &imx_ion_data,
+ sizeof(imx_ion_data) + sizeof(struct ion_platform_heap));
+
+ sabrelite_add_device_buttons();
+
+ imx6q_add_hdmi_soc();
+ imx6q_add_hdmi_soc_dai();
+
+ ret = gpio_request_array(mx6q_sabrelite_flexcan_gpios,
+ ARRAY_SIZE(mx6q_sabrelite_flexcan_gpios));
+ if (ret)
+ pr_err("failed to request flexcan1-gpios: %d\n", ret);
+ else
+ imx6q_add_flexcan0(&mx6q_sabrelite_flexcan0_pdata);
+
+ clko2 = clk_get(NULL, "clko2_clk");
+ if (IS_ERR(clko2))
+ pr_err("can't get CLKO2 clock.\n");
+
+ new_parent = clk_get(NULL, "osc_clk");
+ if (!IS_ERR(new_parent)) {
+ clk_set_parent(clko2, new_parent);
+ clk_put(new_parent);
+ }
+ rate = clk_round_rate(clko2, 24000000);
+ clk_set_rate(clko2, rate);
+ clk_enable(clko2);
+ imx6q_add_busfreq();
+
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
+}
+
+extern void __iomem *twd_base;
+static void __init mx6_sabrelite_timer_init(void)
+{
+ struct clk *uart_clk;
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ mx6_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(UART2_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mx6_sabrelite_timer = {
+ .init = mx6_sabrelite_timer_init,
+};
+
+static void __init mx6q_sabrelite_reserve(void)
+{
+ phys_addr_t phys;
+ int i;
+#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE)
+
+ if (imx6q_gpu_pdata.reserved_mem_size) {
+ phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size,
+ SZ_4K, SZ_1G);
+ memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size);
+ imx6q_gpu_pdata.reserved_mem_base = phys;
+ }
+#endif
+
+#if defined(CONFIG_ION)
+ if (imx_ion_data.heaps[0].size) {
+ phys = memblock_alloc(imx_ion_data.heaps[0].size, SZ_4K);
+ memblock_remove(phys, imx_ion_data.heaps[0].size);
+ imx_ion_data.heaps[0].base = phys;
+ }
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(sabrelite_fb_data); i++)
+ if (sabrelite_fb_data[i].res_size[0]) {
+ /* reserve for background buffer */
+ phys = memblock_alloc(sabrelite_fb_data[i].res_size[0],
+ SZ_4K);
+ memblock_remove(phys, sabrelite_fb_data[i].res_size[0]);
+ sabrelite_fb_data[i].res_base[0] = phys;
+ }
+ if (vout_mem.res_msize) {
+ phys = memblock_alloc_base(vout_mem.res_msize,
+ SZ_4K, SZ_1G);
+ memblock_remove(phys, vout_mem.res_msize);
+ vout_mem.res_mbase = phys;
+ }
+
+}
+
+/*
+ * initialize __mach_desc_MX6Q_SABRELITE data structure.
+ */
+MACHINE_START(MX6Q_SABRELITE, "Freescale i.MX 6Quad Sabre-Lite Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .boot_params = MX6_PHYS_OFFSET + 0x100,
+ .fixup = fixup_mxc_board,
+ .map_io = mx6_map_io,
+ .init_irq = mx6_init_irq,
+ .init_machine = mx6_sabrelite_board_init,
+ .timer = &mx6_sabrelite_timer,
+ .reserve = mx6q_sabrelite_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c
new file mode 100644
index 00000000..f3209116
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c
@@ -0,0 +1,2046 @@
+/*
+ * Copyright (C) 2012 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 <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/ion.h>
+#include <linux/etherdevice.h>
+#include <linux/power/sabresd_battery.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max17135.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/mfd/wm8994/gpio.h>
+#include <sound/wm8962.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/memory.h>
+#include <mach/iomux-mx6q.h>
+#include <mach/imx-uart.h>
+#include <mach/viv_gpu.h>
+#include <mach/ahci_sata.h>
+#include <mach/ipu-v3.h>
+#include <mach/mxc_hdmi.h>
+#include <mach/mxc_asrc.h>
+#include <mach/mipi_dsi.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "usb.h"
+#include "devices-imx6q.h"
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "board-mx6q_sabresd.h"
+#include "board-mx6dl_sabresd.h"
+
+#define SABRESD_USR_DEF_GRN_LED IMX_GPIO_NR(1, 1)
+#define SABRESD_USR_DEF_RED_LED IMX_GPIO_NR(1, 2)
+#define SABRESD_VOLUME_UP IMX_GPIO_NR(1, 4)
+#define SABRESD_VOLUME_DN IMX_GPIO_NR(1, 5)
+#define SABRESD_MICROPHONE_DET IMX_GPIO_NR(1, 9)
+#define SABRESD_CSI0_PWN IMX_GPIO_NR(1, 16)
+#define SABRESD_CSI0_RST IMX_GPIO_NR(1, 17)
+#define SABRESD_ACCL_INT IMX_GPIO_NR(1, 18)
+#define SABRESD_MIPICSI_PWN IMX_GPIO_NR(1, 19)
+#define SABRESD_MIPICSI_RST IMX_GPIO_NR(1, 20)
+#define SABRESD_RGMII_RST IMX_GPIO_NR(1, 25)
+#define SABRESD_RGMII_INT IMX_GPIO_NR(1, 26)
+#define SABRESD_CHARGE_UOK_B IMX_GPIO_NR(1, 27)
+#define SABRESD_USBH1_PWR_EN IMX_GPIO_NR(1, 29)
+#define SABRESD_DISP0_PWR_EN IMX_GPIO_NR(1, 30)
+
+#define SABRESD_SD3_CD IMX_GPIO_NR(2, 0)
+#define SABRESD_SD3_WP IMX_GPIO_NR(2, 1)
+#define SABRESD_SD2_CD IMX_GPIO_NR(2, 2)
+#define SABRESD_SD2_WP IMX_GPIO_NR(2, 3)
+#define SABRESD_CHARGE_DOK_B IMX_GPIO_NR(2, 24)
+#define SABRESD_GPS_RESET IMX_GPIO_NR(2, 28)
+#define SABRESD_SENSOR_EN IMX_GPIO_NR(2, 31)
+
+#define SABRESD_GPS_EN IMX_GPIO_NR(3, 0)
+#define SABRESD_DISP0_RST_B IMX_GPIO_NR(3, 8)
+#define SABRESD_ALS_INT IMX_GPIO_NR(3, 9)
+#define SABRESD_CHARGE_CHG_2_B IMX_GPIO_NR(3, 13)
+#define SABRESD_CHARGE_FLT_2_B IMX_GPIO_NR(3, 14)
+#define SABRESD_BAR0_INT IMX_GPIO_NR(3, 15)
+#define SABRESD_eCOMPASS_INT IMX_GPIO_NR(3, 16)
+#define SABRESD_GPS_PPS IMX_GPIO_NR(3, 18)
+#define SABRESD_PCIE_PWR_EN IMX_GPIO_NR(3, 19)
+#define SABRESD_USB_OTG_PWR IMX_GPIO_NR(3, 22)
+#define SABRESD_USB_H1_PWR IMX_GPIO_NR(1, 29)
+#define SABRESD_CHARGE_CHG_1_B IMX_GPIO_NR(3, 23)
+#define SABRESD_TS_INT IMX_GPIO_NR(3, 26)
+#define SABRESD_DISP0_RD IMX_GPIO_NR(3, 28)
+#define SABRESD_POWER_OFF IMX_GPIO_NR(3, 29)
+
+#define SABRESD_CAN1_STBY IMX_GPIO_NR(4, 5)
+#define SABRESD_ECSPI1_CS0 IMX_GPIO_NR(4, 9)
+#define SABRESD_CODEC_PWR_EN IMX_GPIO_NR(4, 10)
+#define SABRESD_HDMI_CEC_IN IMX_GPIO_NR(4, 11)
+#define SABRESD_PCIE_DIS_B IMX_GPIO_NR(4, 14)
+
+#define SABRESD_DI0_D0_CS IMX_GPIO_NR(5, 0)
+#define SABRESD_CHARGE_FLT_1_B IMX_GPIO_NR(5, 2)
+#define SABRESD_PCIE_WAKE_B IMX_GPIO_NR(5, 20)
+
+#define SABRESD_CAP_TCH_INT1 IMX_GPIO_NR(6, 7)
+#define SABRESD_CAP_TCH_INT0 IMX_GPIO_NR(6, 8)
+#define SABRESD_DISP_RST_B IMX_GPIO_NR(6, 11)
+#define SABRESD_DISP_PWR_EN IMX_GPIO_NR(6, 14)
+#define SABRESD_CABC_EN0 IMX_GPIO_NR(6, 15)
+#define SABRESD_CABC_EN1 IMX_GPIO_NR(6, 16)
+#define SABRESD_AUX_3V15_EN IMX_GPIO_NR(6, 9)
+#define SABRESD_DISP0_WR_REVB IMX_GPIO_NR(6, 9)
+#define SABRESD_AUX_5V_EN IMX_GPIO_NR(6, 10)
+#define SABRESD_DI1_D0_CS IMX_GPIO_NR(6, 31)
+
+#define SABRESD_HEADPHONE_DET IMX_GPIO_NR(7, 8)
+#define SABRESD_PCIE_RST_B_REVB IMX_GPIO_NR(7, 12)
+#define SABRESD_PMIC_INT_B IMX_GPIO_NR(7, 13)
+#define SABRESD_PFUZE_INT IMX_GPIO_NR(7, 13)
+
+#define SABRESD_EPDC_SDDO_0 IMX_GPIO_NR(2, 22)
+#define SABRESD_EPDC_SDDO_1 IMX_GPIO_NR(3, 10)
+#define SABRESD_EPDC_SDDO_2 IMX_GPIO_NR(3, 12)
+#define SABRESD_EPDC_SDDO_3 IMX_GPIO_NR(3, 11)
+#define SABRESD_EPDC_SDDO_4 IMX_GPIO_NR(2, 27)
+#define SABRESD_EPDC_SDDO_5 IMX_GPIO_NR(2, 30)
+#define SABRESD_EPDC_SDDO_6 IMX_GPIO_NR(2, 23)
+#define SABRESD_EPDC_SDDO_7 IMX_GPIO_NR(2, 26)
+#define SABRESD_EPDC_SDDO_8 IMX_GPIO_NR(2, 24)
+#define SABRESD_EPDC_SDDO_9 IMX_GPIO_NR(3, 15)
+#define SABRESD_EPDC_SDDO_10 IMX_GPIO_NR(3, 16)
+#define SABRESD_EPDC_SDDO_11 IMX_GPIO_NR(3, 23)
+#define SABRESD_EPDC_SDDO_12 IMX_GPIO_NR(3, 19)
+#define SABRESD_EPDC_SDDO_13 IMX_GPIO_NR(3, 13)
+#define SABRESD_EPDC_SDDO_14 IMX_GPIO_NR(3, 14)
+#define SABRESD_EPDC_SDDO_15 IMX_GPIO_NR(5, 2)
+#define SABRESD_EPDC_GDCLK IMX_GPIO_NR(2, 17)
+#define SABRESD_EPDC_GDSP IMX_GPIO_NR(2, 16)
+#define SABRESD_EPDC_GDOE IMX_GPIO_NR(6, 6)
+#define SABRESD_EPDC_GDRL IMX_GPIO_NR(5, 4)
+#define SABRESD_EPDC_SDCLK IMX_GPIO_NR(3, 31)
+#define SABRESD_EPDC_SDOEZ IMX_GPIO_NR(3, 30)
+#define SABRESD_EPDC_SDOED IMX_GPIO_NR(3, 26)
+#define SABRESD_EPDC_SDOE IMX_GPIO_NR(3, 27)
+#define SABRESD_EPDC_SDLE IMX_GPIO_NR(3, 1)
+#define SABRESD_EPDC_SDCLKN IMX_GPIO_NR(3, 0)
+#define SABRESD_EPDC_SDSHR IMX_GPIO_NR(2, 29)
+#define SABRESD_EPDC_PWRCOM IMX_GPIO_NR(2, 28)
+#define SABRESD_EPDC_PWRSTAT IMX_GPIO_NR(2, 21)
+#define SABRESD_EPDC_PWRCTRL0 IMX_GPIO_NR(2, 20)
+#define SABRESD_EPDC_PWRCTRL1 IMX_GPIO_NR(2, 19)
+#define SABRESD_EPDC_PWRCTRL2 IMX_GPIO_NR(2, 18)
+#define SABRESD_EPDC_PWRCTRL3 IMX_GPIO_NR(3, 28)
+#define SABRESD_EPDC_BDR0 IMX_GPIO_NR(3, 2)
+#define SABRESD_EPDC_BDR1 IMX_GPIO_NR(3, 3)
+#define SABRESD_EPDC_SDCE0 IMX_GPIO_NR(3, 4)
+#define SABRESD_EPDC_SDCE1 IMX_GPIO_NR(3, 5)
+#define SABRESD_EPDC_SDCE2 IMX_GPIO_NR(3, 6)
+#define SABRESD_EPDC_SDCE3 IMX_GPIO_NR(3, 7)
+#define SABRESD_EPDC_SDCE4 IMX_GPIO_NR(3, 8)
+#define SABRESD_EPDC_PMIC_WAKE IMX_GPIO_NR(3, 20)
+#define SABRESD_EPDC_PMIC_INT IMX_GPIO_NR(2, 25)
+#define SABRESD_EPDC_VCOM IMX_GPIO_NR(3, 17)
+#define SABRESD_CHARGE_NOW IMX_GPIO_NR(1, 2)
+#define SABRESD_CHARGE_DONE IMX_GPIO_NR(1, 1)
+#define SABRESD_ELAN_CE IMX_GPIO_NR(2, 18)
+#define SABRESD_ELAN_RST IMX_GPIO_NR(3, 8)
+#define SABRESD_ELAN_INT IMX_GPIO_NR(3, 28)
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+#define MX6_ENET_IRQ IMX_GPIO_NR(1, 6)
+#define IOMUX_OBSRV_MUX1_OFFSET 0x3c
+#define OBSRV_MUX1_MASK 0x3f
+#define OBSRV_MUX1_ENET_IRQ 0x9
+#endif
+
+static struct clk *sata_clk;
+static struct clk *clko;
+static int mma8451_position = 1;
+static int mag3110_position = 2;
+static int max11801_mode = 1;
+static int enable_lcd_ldb;
+
+static int caam_enabled;
+
+extern char *gp_reg_id;
+extern char *soc_reg_id;
+extern char *pu_reg_id;
+extern int epdc_enabled;
+
+static int max17135_regulator_init(struct max17135 *max17135);
+
+static const struct esdhc_platform_data mx6q_sabresd_sd2_data __initconst = {
+ .cd_gpio = SABRESD_SD2_CD,
+ .wp_gpio = SABRESD_SD2_WP,
+ .keep_power_at_suspend = 1,
+ .support_8bit = 1,
+ .delay_line = 0,
+ .cd_type = ESDHC_CD_CONTROLLER,
+ .runtime_pm = 1,
+};
+
+static const struct esdhc_platform_data mx6q_sabresd_sd3_data __initconst = {
+ .cd_gpio = SABRESD_SD3_CD,
+ .wp_gpio = SABRESD_SD3_WP,
+ .keep_power_at_suspend = 1,
+ .support_8bit = 1,
+ .delay_line = 0,
+ .cd_type = ESDHC_CD_CONTROLLER,
+};
+
+static const struct esdhc_platform_data mx6q_sabresd_sd4_data __initconst = {
+ .always_present = 1,
+ .keep_power_at_suspend = 1,
+ .support_8bit = 1,
+ .delay_line = 0,
+ .cd_type = ESDHC_CD_PERMANENT,
+};
+
+static const struct anatop_thermal_platform_data
+ mx6q_sabresd_anatop_thermal_data __initconst = {
+ .name = "anatop_thermal",
+};
+
+static inline void mx6q_sabresd_init_uart(void)
+{
+ imx6q_add_imx_uart(2, NULL);
+ imx6q_add_imx_uart(0, NULL);
+}
+
+static int mx6q_sabresd_fec_phy_init(struct phy_device *phydev)
+{
+ unsigned short val;
+
+ /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
+ phy_write(phydev, 0xd, 0x7);
+ phy_write(phydev, 0xe, 0x8016);
+ phy_write(phydev, 0xd, 0x4007);
+ val = phy_read(phydev, 0xe);
+
+ val &= 0xffe3;
+ val |= 0x18;
+ phy_write(phydev, 0xe, val);
+
+ /* Introduce tx clock delay */
+ phy_write(phydev, 0x1d, 0x5);
+ val = phy_read(phydev, 0x1e);
+ val |= 0x0100;
+ phy_write(phydev, 0x1e, val);
+
+ /*check phy power*/
+ val = phy_read(phydev, 0x0);
+
+ if (val & BMCR_PDOWN)
+ phy_write(phydev, 0x0, (val & ~BMCR_PDOWN));
+
+ return 0;
+}
+
+static struct fec_platform_data fec_data __initdata = {
+ .init = mx6q_sabresd_fec_phy_init,
+ .phy = PHY_INTERFACE_MODE_RGMII,
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ .gpio_irq = MX6_ENET_IRQ,
+#endif
+};
+
+static int mx6q_sabresd_spi_cs[] = {
+ SABRESD_ECSPI1_CS0,
+};
+
+static const struct spi_imx_master mx6q_sabresd_spi_data __initconst = {
+ .chipselect = mx6q_sabresd_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx6q_sabresd_spi_cs),
+};
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition imx6_sabresd_spi_nor_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x00100000,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data imx6_sabresd__spi_flash_data = {
+ .name = "m25p80",
+ .parts = imx6_sabresd_spi_nor_partitions,
+ .nr_parts = ARRAY_SIZE(imx6_sabresd_spi_nor_partitions),
+ .type = "sst25vf016b",
+};
+#endif
+
+static struct spi_board_info imx6_sabresd_spi_nor_device[] __initdata = {
+#if defined(CONFIG_MTD_M25P80)
+ {
+ .modalias = "m25p80",
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = &imx6_sabresd__spi_flash_data,
+ },
+#endif
+};
+
+static void spi_device_init(void)
+{
+ spi_register_board_info(imx6_sabresd_spi_nor_device,
+ ARRAY_SIZE(imx6_sabresd_spi_nor_device));
+}
+
+static struct imx_ssi_platform_data mx6_sabresd_ssi_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_SYN,
+};
+
+static struct platform_device mx6_sabresd_audio_wm8958_device = {
+ .name = "imx-wm8958",
+};
+
+static struct mxc_audio_platform_data wm8958_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_gpio = SABRESD_HEADPHONE_DET,
+ .hp_active_low = 1,
+};
+
+static struct wm8994_pdata wm8958_config_data = {
+ .gpio_defaults = {
+ [0] = WM8994_GP_FN_GPIO | WM8994_GPN_DB,
+ [1] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ [2] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ [3] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ [4] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ [5] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ [7] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ [8] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ [9] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ [10] = WM8994_GP_FN_GPIO | WM8994_GPN_DB | WM8994_GPN_PD,
+ },
+};
+
+static int mxc_wm8958_init(void)
+{
+ struct clk *clko;
+ int rate;
+
+ clko = clk_get(NULL, "clko_clk");
+ if (IS_ERR(clko)) {
+ pr_err("can't get CLKO clock.\n");
+ return PTR_ERR(clko);
+ }
+ /* both audio codec and comera use CLKO clk*/
+ rate = clk_round_rate(clko, 24000000);
+
+ wm8958_data.sysclk = rate;
+ clk_set_rate(clko, rate);
+
+ /* enable wm8958 4.2v power supply */
+ gpio_request(SABRESD_CODEC_PWR_EN, "aud_4v2");
+ gpio_direction_output(SABRESD_CODEC_PWR_EN, 1);
+ msleep(1);
+ gpio_set_value(SABRESD_CODEC_PWR_EN, 1);
+
+ return 0;
+}
+
+static struct platform_device mx6_sabresd_audio_wm8962_device = {
+ .name = "imx-wm8962",
+};
+
+static struct mxc_audio_platform_data wm8962_data;
+
+static int wm8962_clk_enable(int enable)
+{
+ if (enable)
+ clk_enable(clko);
+ else
+ clk_disable(clko);
+
+ return 0;
+}
+
+static int mxc_wm8962_init(void)
+{
+ int rate;
+
+ clko = clk_get(NULL, "clko_clk");
+ if (IS_ERR(clko)) {
+ pr_err("can't get CLKO clock.\n");
+ return PTR_ERR(clko);
+ }
+ /* both audio codec and comera use CLKO clk*/
+ rate = clk_round_rate(clko, 24000000);
+ clk_set_rate(clko, rate);
+
+ wm8962_data.sysclk = rate;
+
+ return 0;
+}
+
+static struct wm8962_pdata wm8962_config_data = {
+ .gpio_init = {
+ [2] = WM8962_GPIO_FN_DMICCLK,
+ [4] = 0x8000 | WM8962_GPIO_FN_DMICDAT,
+ },
+};
+
+static struct mxc_audio_platform_data wm8962_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_gpio = SABRESD_HEADPHONE_DET,
+ .hp_active_low = 1,
+ .mic_gpio = SABRESD_MICROPHONE_DET,
+ .mic_active_low = 1,
+ .init = mxc_wm8962_init,
+ .clock_enable = wm8962_clk_enable,
+};
+
+static struct regulator_consumer_supply sabresd_vwm8962_consumers[] = {
+ REGULATOR_SUPPLY("SPKVDD1", "0-001a"),
+ REGULATOR_SUPPLY("SPKVDD2", "0-001a"),
+};
+
+static struct regulator_init_data sabresd_vwm8962_init = {
+ .constraints = {
+ .name = "SPKVDD",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sabresd_vwm8962_consumers),
+ .consumer_supplies = sabresd_vwm8962_consumers,
+};
+
+static struct fixed_voltage_config sabresd_vwm8962_reg_config = {
+ .supply_name = "SPKVDD",
+ .microvolts = 4200000,
+ .gpio = SABRESD_CODEC_PWR_EN,
+ .enable_high = 1,
+ .enabled_at_boot = 1,
+ .init_data = &sabresd_vwm8962_init,
+};
+
+static struct platform_device sabresd_vwm8962_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 4,
+ .dev = {
+ .platform_data = &sabresd_vwm8962_reg_config,
+ },
+};
+
+static void mx6q_csi0_cam_powerdown(int powerdown)
+{
+ if (powerdown)
+ gpio_set_value(SABRESD_CSI0_PWN, 1);
+ else
+ gpio_set_value(SABRESD_CSI0_PWN, 0);
+
+ msleep(2);
+}
+
+static void mx6q_csi0_io_init(void)
+{
+ if (cpu_is_mx6q())
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_csi0_sensor_pads,
+ ARRAY_SIZE(mx6q_sabresd_csi0_sensor_pads));
+ else if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_csi0_sensor_pads,
+ ARRAY_SIZE(mx6dl_sabresd_csi0_sensor_pads));
+
+ /* Camera reset */
+ gpio_request(SABRESD_CSI0_RST, "cam-reset");
+ gpio_direction_output(SABRESD_CSI0_RST, 1);
+
+ /* Camera power down */
+ gpio_request(SABRESD_CSI0_PWN, "cam-pwdn");
+ gpio_direction_output(SABRESD_CSI0_PWN, 1);
+ msleep(5);
+ gpio_set_value(SABRESD_CSI0_PWN, 0);
+ msleep(5);
+ gpio_set_value(SABRESD_CSI0_RST, 0);
+ msleep(1);
+ gpio_set_value(SABRESD_CSI0_RST, 1);
+ msleep(5);
+ gpio_set_value(SABRESD_CSI0_PWN, 1);
+
+ /* For MX6Q:
+ * GPR1 bit19 and bit20 meaning:
+ * Bit19: 0 - Enable mipi to IPU1 CSI0
+ * virtual channel is fixed to 0
+ * 1 - Enable parallel interface to IPU1 CSI0
+ * Bit20: 0 - Enable mipi to IPU2 CSI1
+ * virtual channel is fixed to 3
+ * 1 - Enable parallel interface to IPU2 CSI1
+ * IPU1 CSI1 directly connect to mipi csi2,
+ * virtual channel is fixed to 1
+ * IPU2 CSI0 directly connect to mipi csi2,
+ * virtual channel is fixed to 2
+ *
+ * For MX6DL:
+ * GPR13 bit 0-2 IPU_CSI0_MUX
+ * 000 MIPI_CSI0
+ * 100 IPU CSI0
+ */
+ if (cpu_is_mx6q())
+ mxc_iomux_set_gpr_register(1, 19, 1, 1);
+ else if (cpu_is_mx6dl())
+ mxc_iomux_set_gpr_register(13, 0, 3, 4);
+}
+
+static struct fsl_mxc_camera_platform_data camera_data = {
+ .mclk = 24000000,
+ .mclk_source = 0,
+ .csi = 0,
+ .io_init = mx6q_csi0_io_init,
+ .pwdn = mx6q_csi0_cam_powerdown,
+};
+
+static void mx6q_mipi_powerdown(int powerdown)
+{
+ if (powerdown)
+ gpio_set_value(SABRESD_MIPICSI_PWN, 1);
+ else
+ gpio_set_value(SABRESD_MIPICSI_PWN, 0);
+
+ msleep(2);
+}
+
+static void mx6q_mipi_sensor_io_init(void)
+{
+ if (cpu_is_mx6q())
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_mipi_sensor_pads,
+ ARRAY_SIZE(mx6q_sabresd_mipi_sensor_pads));
+ else if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_mipi_sensor_pads,
+ ARRAY_SIZE(mx6dl_sabresd_mipi_sensor_pads));
+
+ /* Camera reset */
+ gpio_request(SABRESD_MIPICSI_RST, "cam-reset");
+ gpio_direction_output(SABRESD_MIPICSI_RST, 1);
+
+ /* Camera power down */
+ gpio_request(SABRESD_MIPICSI_PWN, "cam-pwdn");
+ gpio_direction_output(SABRESD_MIPICSI_PWN, 1);
+ msleep(5);
+ gpio_set_value(SABRESD_MIPICSI_PWN, 0);
+ msleep(5);
+ gpio_set_value(SABRESD_MIPICSI_RST, 0);
+ msleep(1);
+ gpio_set_value(SABRESD_MIPICSI_RST, 1);
+ msleep(5);
+ gpio_set_value(SABRESD_MIPICSI_PWN, 1);
+
+ /*for mx6dl, mipi virtual channel 1 connect to csi 1*/
+ if (cpu_is_mx6dl())
+ mxc_iomux_set_gpr_register(13, 3, 3, 1);
+}
+
+static struct fsl_mxc_camera_platform_data mipi_csi2_data = {
+ .mclk = 24000000,
+ .mclk_source = 0,
+ .csi = 1,
+ .io_init = mx6q_mipi_sensor_io_init,
+ .pwdn = mx6q_mipi_powerdown,
+};
+
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+static struct regulator_consumer_supply display_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "DISPLAY",
+ },
+};
+
+static struct regulator_consumer_supply vcom_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "VCOM",
+ },
+};
+
+static struct regulator_consumer_supply v3p3_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "V3P3",
+ },
+};
+
+static struct regulator_init_data max17135_init_data[] = {
+ {
+ .constraints = {
+ .name = "DISPLAY",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(display_consumers),
+ .consumer_supplies = display_consumers,
+ }, {
+ .constraints = {
+ .name = "GVDD",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "GVEE",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINN",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINP",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "VCOM",
+ .min_uV = mV_to_uV(-4325),
+ .max_uV = mV_to_uV(-500),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcom_consumers),
+ .consumer_supplies = vcom_consumers,
+ }, {
+ .constraints = {
+ .name = "VNEG",
+ .min_uV = V_to_uV(-15),
+ .max_uV = V_to_uV(-15),
+ },
+ }, {
+ .constraints = {
+ .name = "VPOS",
+ .min_uV = V_to_uV(15),
+ .max_uV = V_to_uV(15),
+ },
+ }, {
+ .constraints = {
+ .name = "V3P3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(v3p3_consumers),
+ .consumer_supplies = v3p3_consumers,
+ },
+};
+
+static struct platform_device max17135_sensor_device = {
+ .name = "max17135_sensor",
+ .id = 0,
+};
+
+static struct max17135_platform_data max17135_pdata __initdata = {
+ .vneg_pwrup = 1,
+ .gvee_pwrup = 1,
+ .vpos_pwrup = 2,
+ .gvdd_pwrup = 1,
+ .gvdd_pwrdn = 1,
+ .vpos_pwrdn = 2,
+ .gvee_pwrdn = 1,
+ .vneg_pwrdn = 1,
+ .gpio_pmic_pwrgood = SABRESD_EPDC_PWRSTAT,
+ .gpio_pmic_vcom_ctrl = SABRESD_EPDC_VCOM,
+ .gpio_pmic_wakeup = SABRESD_EPDC_PMIC_WAKE,
+ .gpio_pmic_v3p3 = SABRESD_EPDC_PWRCTRL0,
+ .gpio_pmic_intr = SABRESD_EPDC_PMIC_INT,
+ .regulator_init = max17135_init_data,
+ .init = max17135_regulator_init,
+};
+
+static int __init max17135_regulator_init(struct max17135 *max17135)
+{
+ struct max17135_platform_data *pdata = &max17135_pdata;
+ int i, ret;
+
+ if (!epdc_enabled) {
+ printk(KERN_DEBUG
+ "max17135_regulator_init abort: EPDC not enabled\n");
+ return 0;
+ }
+
+ max17135->gvee_pwrup = pdata->gvee_pwrup;
+ max17135->vneg_pwrup = pdata->vneg_pwrup;
+ max17135->vpos_pwrup = pdata->vpos_pwrup;
+ max17135->gvdd_pwrup = pdata->gvdd_pwrup;
+ max17135->gvdd_pwrdn = pdata->gvdd_pwrdn;
+ max17135->vpos_pwrdn = pdata->vpos_pwrdn;
+ max17135->vneg_pwrdn = pdata->vneg_pwrdn;
+ max17135->gvee_pwrdn = pdata->gvee_pwrdn;
+
+ max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup +
+ pdata->gvdd_pwrup + pdata->gvee_pwrup;
+
+ max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood;
+ max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl;
+ max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup;
+ max17135->gpio_pmic_v3p3 = pdata->gpio_pmic_v3p3;
+ max17135->gpio_pmic_intr = pdata->gpio_pmic_intr;
+
+ gpio_request(max17135->gpio_pmic_wakeup, "epdc-pmic-wake");
+ gpio_direction_output(max17135->gpio_pmic_wakeup, 0);
+
+ gpio_request(max17135->gpio_pmic_vcom_ctrl, "epdc-vcom");
+ gpio_direction_output(max17135->gpio_pmic_vcom_ctrl, 0);
+
+ gpio_request(max17135->gpio_pmic_v3p3, "epdc-v3p3");
+ gpio_direction_output(max17135->gpio_pmic_v3p3, 0);
+
+ gpio_request(max17135->gpio_pmic_intr, "epdc-pmic-int");
+ gpio_direction_input(max17135->gpio_pmic_intr);
+
+ gpio_request(max17135->gpio_pmic_pwrgood, "epdc-pwrstat");
+ gpio_direction_input(max17135->gpio_pmic_pwrgood);
+
+ max17135->vcom_setup = false;
+ max17135->init_done = false;
+
+ for (i = 0; i < MAX17135_NUM_REGULATORS; i++) {
+ ret = max17135_register_regulator(max17135, i,
+ &pdata->regulator_init[i]);
+ if (ret != 0) {
+ printk(KERN_ERR"max17135 regulator init failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /*
+ * TODO: We cannot enable full constraints for now, since
+ * it results in the PFUZE regulators being disabled
+ * at the end of boot, which disables critical regulators.
+ */
+ /*regulator_has_full_constraints();*/
+
+ return 0;
+}
+
+static struct imxi2c_platform_data mx6q_sabresd_i2c_data = {
+ .bitrate = 100000,
+};
+
+static struct fsl_mxc_lightsensor_platform_data ls_data = {
+ .rext = 499, /* calibration: 499K->700K */
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("wm89**", 0x1a),
+ },
+ {
+ I2C_BOARD_INFO("ov5642", 0x3c),
+ .platform_data = (void *)&camera_data,
+ },
+ {
+ I2C_BOARD_INFO("mma8451", 0x1c),
+ .platform_data = (void *)&mma8451_position,
+ },
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50),
+ },
+ {
+ I2C_BOARD_INFO("ov5640_mipi", 0x3c),
+ .platform_data = (void *)&mipi_csi2_data,
+ },
+ {
+ I2C_BOARD_INFO("egalax_ts", 0x4),
+ .irq = gpio_to_irq(SABRESD_CAP_TCH_INT0),
+ },
+ {
+ I2C_BOARD_INFO("max11801", 0x48),
+ .platform_data = (void *)&max11801_mode,
+ .irq = gpio_to_irq(SABRESD_TS_INT),
+ },
+};
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("max17135", 0x48),
+ .platform_data = &max17135_pdata,
+ },
+ {
+ I2C_BOARD_INFO("egalax_ts", 0x4),
+ .irq = gpio_to_irq(SABRESD_CAP_TCH_INT1),
+ },
+ {
+ I2C_BOARD_INFO("mag3110", 0x0e),
+ .irq = gpio_to_irq(SABRESD_eCOMPASS_INT),
+ .platform_data = (void *)&mag3110_position,
+ },
+ {
+ I2C_BOARD_INFO("isl29023", 0x44),
+ .irq = gpio_to_irq(SABRESD_ALS_INT),
+ .platform_data = &ls_data,
+ }, {
+ I2C_BOARD_INFO("elan-touch", 0x10),
+ .irq = gpio_to_irq(SABRESD_ELAN_INT),
+ },
+ {
+ I2C_BOARD_INFO("mxc_ldb_i2c", 0x50),
+ .platform_data = (void *)0,
+ },
+};
+
+static int epdc_get_pins(void)
+{
+ int ret = 0;
+
+ /* Claim GPIOs for EPDC pins - used during power up/down */
+ ret |= gpio_request(SABRESD_EPDC_SDDO_0, "epdc_d0");
+ ret |= gpio_request(SABRESD_EPDC_SDDO_1, "epdc_d1");
+ ret |= gpio_request(SABRESD_EPDC_SDDO_2, "epdc_d2");
+ ret |= gpio_request(SABRESD_EPDC_SDDO_3, "epdc_d3");
+ ret |= gpio_request(SABRESD_EPDC_SDDO_4, "epdc_d4");
+ ret |= gpio_request(SABRESD_EPDC_SDDO_5, "epdc_d5");
+ ret |= gpio_request(SABRESD_EPDC_SDDO_6, "epdc_d6");
+ ret |= gpio_request(SABRESD_EPDC_SDDO_7, "epdc_d7");
+ ret |= gpio_request(SABRESD_EPDC_GDCLK, "epdc_gdclk");
+ ret |= gpio_request(SABRESD_EPDC_GDSP, "epdc_gdsp");
+ ret |= gpio_request(SABRESD_EPDC_GDOE, "epdc_gdoe");
+ ret |= gpio_request(SABRESD_EPDC_GDRL, "epdc_gdrl");
+ ret |= gpio_request(SABRESD_EPDC_SDCLK, "epdc_sdclk");
+ ret |= gpio_request(SABRESD_EPDC_SDOE, "epdc_sdoe");
+ ret |= gpio_request(SABRESD_EPDC_SDLE, "epdc_sdle");
+ ret |= gpio_request(SABRESD_EPDC_SDSHR, "epdc_sdshr");
+ ret |= gpio_request(SABRESD_EPDC_BDR0, "epdc_bdr0");
+ ret |= gpio_request(SABRESD_EPDC_SDCE0, "epdc_sdce0");
+ ret |= gpio_request(SABRESD_EPDC_SDCE1, "epdc_sdce1");
+ ret |= gpio_request(SABRESD_EPDC_SDCE2, "epdc_sdce2");
+
+ return ret;
+}
+
+static void epdc_put_pins(void)
+{
+ gpio_free(SABRESD_EPDC_SDDO_0);
+ gpio_free(SABRESD_EPDC_SDDO_1);
+ gpio_free(SABRESD_EPDC_SDDO_2);
+ gpio_free(SABRESD_EPDC_SDDO_3);
+ gpio_free(SABRESD_EPDC_SDDO_4);
+ gpio_free(SABRESD_EPDC_SDDO_5);
+ gpio_free(SABRESD_EPDC_SDDO_6);
+ gpio_free(SABRESD_EPDC_SDDO_7);
+ gpio_free(SABRESD_EPDC_GDCLK);
+ gpio_free(SABRESD_EPDC_GDSP);
+ gpio_free(SABRESD_EPDC_GDOE);
+ gpio_free(SABRESD_EPDC_GDRL);
+ gpio_free(SABRESD_EPDC_SDCLK);
+ gpio_free(SABRESD_EPDC_SDOE);
+ gpio_free(SABRESD_EPDC_SDLE);
+ gpio_free(SABRESD_EPDC_SDSHR);
+ gpio_free(SABRESD_EPDC_BDR0);
+ gpio_free(SABRESD_EPDC_SDCE0);
+ gpio_free(SABRESD_EPDC_SDCE1);
+ gpio_free(SABRESD_EPDC_SDCE2);
+}
+
+static void epdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable EPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_epdc_enable_pads, \
+ ARRAY_SIZE(mx6dl_sabresd_epdc_enable_pads));
+
+ gpio_direction_input(SABRESD_EPDC_SDDO_0);
+ gpio_direction_input(SABRESD_EPDC_SDDO_1);
+ gpio_direction_input(SABRESD_EPDC_SDDO_2);
+ gpio_direction_input(SABRESD_EPDC_SDDO_3);
+ gpio_direction_input(SABRESD_EPDC_SDDO_4);
+ gpio_direction_input(SABRESD_EPDC_SDDO_5);
+ gpio_direction_input(SABRESD_EPDC_SDDO_6);
+ gpio_direction_input(SABRESD_EPDC_SDDO_7);
+ gpio_direction_input(SABRESD_EPDC_GDCLK);
+ gpio_direction_input(SABRESD_EPDC_GDSP);
+ gpio_direction_input(SABRESD_EPDC_GDOE);
+ gpio_direction_input(SABRESD_EPDC_GDRL);
+ gpio_direction_input(SABRESD_EPDC_SDCLK);
+ gpio_direction_input(SABRESD_EPDC_SDOE);
+ gpio_direction_input(SABRESD_EPDC_SDLE);
+ gpio_direction_input(SABRESD_EPDC_SDSHR);
+ gpio_direction_input(SABRESD_EPDC_BDR0);
+ gpio_direction_input(SABRESD_EPDC_SDCE0);
+ gpio_direction_input(SABRESD_EPDC_SDCE1);
+ gpio_direction_input(SABRESD_EPDC_SDCE2);
+}
+
+static void epdc_disable_pins(void)
+{
+ /* Configure MUX settings for EPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_epdc_disable_pads, \
+ ARRAY_SIZE(mx6dl_sabresd_epdc_disable_pads));
+
+ gpio_direction_output(SABRESD_EPDC_SDDO_0, 0);
+ gpio_direction_output(SABRESD_EPDC_SDDO_1, 0);
+ gpio_direction_output(SABRESD_EPDC_SDDO_2, 0);
+ gpio_direction_output(SABRESD_EPDC_SDDO_3, 0);
+ gpio_direction_output(SABRESD_EPDC_SDDO_4, 0);
+ gpio_direction_output(SABRESD_EPDC_SDDO_5, 0);
+ gpio_direction_output(SABRESD_EPDC_SDDO_6, 0);
+ gpio_direction_output(SABRESD_EPDC_SDDO_7, 0);
+ gpio_direction_output(SABRESD_EPDC_GDCLK, 0);
+ gpio_direction_output(SABRESD_EPDC_GDSP, 0);
+ gpio_direction_output(SABRESD_EPDC_GDOE, 0);
+ gpio_direction_output(SABRESD_EPDC_GDRL, 0);
+ gpio_direction_output(SABRESD_EPDC_SDCLK, 0);
+ gpio_direction_output(SABRESD_EPDC_SDOE, 0);
+ gpio_direction_output(SABRESD_EPDC_SDLE, 0);
+ gpio_direction_output(SABRESD_EPDC_SDSHR, 0);
+ gpio_direction_output(SABRESD_EPDC_BDR0, 0);
+ gpio_direction_output(SABRESD_EPDC_SDCE0, 0);
+ gpio_direction_output(SABRESD_EPDC_SDCE1, 0);
+ gpio_direction_output(SABRESD_EPDC_SDCE2, 0);
+}
+
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 30000000,
+ .left_margin = 8,
+ .right_margin = 164,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+};
+static struct fb_videomode e060scm_mode = {
+ .name = "E060SCM",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 26666667,
+ .left_margin = 8,
+ .right_margin = 100,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct imx_epdc_fb_mode panel_modes[] = {
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 465, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 9, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e060scm_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 419, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 5, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+
+static struct imx_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+ .get_pins = epdc_get_pins,
+ .put_pins = epdc_put_pins,
+ .enable_pins = epdc_enable_pins,
+ .disable_pins = epdc_disable_pins,
+};
+
+static void imx6q_sabresd_usbotg_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(SABRESD_USB_OTG_PWR, 1);
+ else
+ gpio_set_value(SABRESD_USB_OTG_PWR, 0);
+}
+
+static void __init imx6q_sabresd_init_usb(void)
+{
+ int ret = 0;
+
+ imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR);
+ /* disable external charger detect,
+ * or it will affect signal quality at dp .
+ */
+ ret = gpio_request(SABRESD_USB_OTG_PWR, "usb-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO SABRESD_USB_OTG_PWR: %d\n",
+ ret);
+ return;
+ }
+ gpio_direction_output(SABRESD_USB_OTG_PWR, 0);
+ /* keep USB host1 VBUS always on */
+ ret = gpio_request(SABRESD_USB_H1_PWR, "usb-h1-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO SABRESD_USB_H1_PWR: %d\n",
+ ret);
+ return;
+ }
+ gpio_direction_output(SABRESD_USB_H1_PWR, 1);
+ if (board_is_mx6_reva())
+ mxc_iomux_set_gpr_register(1, 13, 1, 1);
+ else
+ mxc_iomux_set_gpr_register(1, 13, 1, 0);
+
+ mx6_set_otghost_vbus_func(imx6q_sabresd_usbotg_vbus);
+}
+
+/* HW Initialization, if return 0, initialization is successful. */
+static int mx6q_sabresd_sata_init(struct device *dev, void __iomem *addr)
+{
+ u32 tmpdata;
+ int ret = 0;
+ struct clk *clk;
+
+ sata_clk = clk_get(dev, "imx_sata_clk");
+ if (IS_ERR(sata_clk)) {
+ dev_err(dev, "no sata clock.\n");
+ return PTR_ERR(sata_clk);
+ }
+ ret = clk_enable(sata_clk);
+ if (ret) {
+ dev_err(dev, "can't enable sata clock.\n");
+ goto put_sata_clk;
+ }
+
+ /* Set PHY Paremeters, two steps to configure the GPR13,
+ * one write for rest of parameters, mask of first write is 0x07FFFFFD,
+ * and the other one write for setting the mpll_clk_off_b
+ *.rx_eq_val_0(iomuxc_gpr13[26:24]),
+ *.los_lvl(iomuxc_gpr13[23:19]),
+ *.rx_dpll_mode_0(iomuxc_gpr13[18:16]),
+ *.sata_speed(iomuxc_gpr13[15]),
+ *.mpll_ss_en(iomuxc_gpr13[14]),
+ *.tx_atten_0(iomuxc_gpr13[13:11]),
+ *.tx_boost_0(iomuxc_gpr13[10:7]),
+ *.tx_lvl(iomuxc_gpr13[6:2]),
+ *.mpll_ck_off(iomuxc_gpr13[1]),
+ *.tx_edgerate_0(iomuxc_gpr13[0]),
+ */
+ tmpdata = readl(IOMUXC_GPR13);
+ writel(((tmpdata & ~0x07FFFFFD) | 0x0593A044), IOMUXC_GPR13);
+
+ /* enable SATA_PHY PLL */
+ tmpdata = readl(IOMUXC_GPR13);
+ writel(((tmpdata & ~0x2) | 0x2), IOMUXC_GPR13);
+
+ /* Get the AHB clock rate, and configure the TIMER1MS reg later */
+ clk = clk_get(NULL, "ahb");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "no ahb clock.\n");
+ ret = PTR_ERR(clk);
+ goto release_sata_clk;
+ }
+ tmpdata = clk_get_rate(clk) / 1000;
+ clk_put(clk);
+
+ ret = sata_init(addr, tmpdata);
+ if (ret == 0)
+ return ret;
+
+release_sata_clk:
+ clk_disable(sata_clk);
+put_sata_clk:
+ clk_put(sata_clk);
+
+ return ret;
+}
+
+static void mx6q_sabresd_sata_exit(struct device *dev)
+{
+ clk_disable(sata_clk);
+ clk_put(sata_clk);
+}
+
+static struct ahci_platform_data mx6q_sabresd_sata_data = {
+ .init = mx6q_sabresd_sata_init,
+ .exit = mx6q_sabresd_sata_exit,
+};
+
+static void mx6q_sabresd_flexcan0_switch(int enable)
+{
+ if (enable) {
+ gpio_set_value(SABRESD_CAN1_STBY, 1);
+ } else {
+ gpio_set_value(SABRESD_CAN1_STBY, 0);
+ }
+}
+
+static const struct flexcan_platform_data
+ mx6q_sabresd_flexcan0_pdata __initconst = {
+ .transceiver_switch = mx6q_sabresd_flexcan0_switch,
+};
+
+static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
+ .reserved_mem_size = SZ_128M + SZ_64M,
+};
+
+static struct imx_asrc_platform_data imx_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 2,
+};
+
+static void mx6_reset_mipi_dsi(void)
+{
+ gpio_set_value(SABRESD_DISP_PWR_EN, 1);
+ gpio_set_value(SABRESD_DISP_RST_B, 1);
+ udelay(10);
+ gpio_set_value(SABRESD_DISP_RST_B, 0);
+ udelay(50);
+ gpio_set_value(SABRESD_DISP_RST_B, 1);
+
+ /*
+ * it needs to delay 120ms minimum for reset complete
+ */
+ msleep(120);
+}
+
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+ .ipu_id = 0,
+ .disp_id = 1,
+ .lcd_panel = "TRULY-WVGA",
+ .reset = mx6_reset_mipi_dsi,
+};
+
+static struct ipuv3_fb_platform_data sabresd_fb_data[] = {
+ { /*fb0*/
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-XGA",
+ .default_bpp = 32,
+ .int_clk = false,
+ .late_init = false,
+ }, {
+ .disp_dev = "hdmi",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB24,
+ .mode_str = "1920x1080M@60",
+ .default_bpp = 32,
+ .int_clk = false,
+ .late_init = false,
+ }, {
+ .disp_dev = "ldb",
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ .mode_str = "LDB-XGA",
+ .default_bpp = 32,
+ .int_clk = false,
+ .late_init = false,
+ },
+};
+
+static void hdmi_init(int ipu_id, int disp_id)
+{
+ int hdmi_mux_setting;
+
+ if ((ipu_id > 1) || (ipu_id < 0)) {
+ pr_err("Invalid IPU select for HDMI: %d. Set to 0\n", ipu_id);
+ ipu_id = 0;
+ }
+
+ if ((disp_id > 1) || (disp_id < 0)) {
+ pr_err("Invalid DI select for HDMI: %d. Set to 0\n", disp_id);
+ disp_id = 0;
+ }
+
+ /* Configure the connection between IPU1/2 and HDMI */
+ hdmi_mux_setting = 2*ipu_id + disp_id;
+
+ /* GPR3, bits 2-3 = HDMI_MUX_CTL */
+ mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
+
+ /* Set HDMI event as SDMA event2 while Chip version later than TO1.2 */
+ if (hdmi_SDMA_check())
+ mxc_iomux_set_gpr_register(0, 0, 1, 1);
+}
+
+/* On mx6x sabresd board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6dl_sabresd_hdmi_ddc_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_sabresd_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_i2c2_pads,
+ ARRAY_SIZE(mx6dl_sabresd_i2c2_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_i2c2_pads,
+ ARRAY_SIZE(mx6q_sabresd_i2c2_pads));
+}
+
+static struct fsl_mxc_hdmi_platform_data hdmi_data = {
+ .init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
+ .phy_reg_vlev = 0x0294,
+ .phy_reg_cksymtx = 0x800d,
+};
+
+static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+};
+
+static struct fsl_mxc_lcd_platform_data lcdif_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .default_ifmt = IPU_PIX_FMT_RGB565,
+};
+
+static struct fsl_mxc_ldb_platform_data ldb_data = {
+ .ipu_id = 1,
+ .disp_id = 1,
+ .ext_ref = 1,
+ .mode = LDB_SEP1,
+ .sec_ipu_id = 1,
+ .sec_disp_id = 0,
+};
+
+static struct max8903_pdata charger1_data = {
+ .dok = SABRESD_CHARGE_DOK_B,
+ .uok = SABRESD_CHARGE_UOK_B,
+ .chg = SABRESD_CHARGE_CHG_1_B,
+ .flt = SABRESD_CHARGE_FLT_1_B,
+ .dcm_always_high = true,
+ .dc_valid = true,
+ .usb_valid = true,
+};
+
+static struct platform_device sabresd_max8903_charger_1 = {
+ .name = "max8903-charger",
+ .id = 1,
+ .dev = {
+ .platform_data = &charger1_data,
+ },
+};
+
+static struct imx_ipuv3_platform_data ipu_data[] = {
+ {
+ .rev = 4,
+ .csi_clk[0] = "clko_clk",
+ .bypass_reset = false,
+ }, {
+ .rev = 4,
+ .csi_clk[0] = "clko_clk",
+ .bypass_reset = false,
+ },
+};
+
+static struct ion_platform_data imx_ion_data = {
+ .nr = 1,
+ .heaps = {
+ {
+ .id = 0,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = "vpu_ion",
+ .size = SZ_64M,
+ },
+ },
+};
+
+static struct fsl_mxc_capture_platform_data capture_data[] = {
+ {
+ .csi = 0,
+ .ipu = 0,
+ .mclk_source = 0,
+ .is_mipi = 0,
+ }, {
+ .csi = 1,
+ .ipu = 0,
+ .mclk_source = 0,
+ .is_mipi = 1,
+ },
+};
+
+
+struct imx_vout_mem {
+ resource_size_t res_mbase;
+ resource_size_t res_msize;
+};
+
+static struct imx_vout_mem vout_mem __initdata = {
+ .res_msize = SZ_128M,
+};
+
+static void sabresd_suspend_enter(void)
+{
+ /* suspend preparation */
+ /* Disable AUX 5V */
+ gpio_set_value(SABRESD_AUX_5V_EN, 0);
+}
+
+static void sabresd_suspend_exit(void)
+{
+ /* resume restore */
+ /* Enable AUX 5V */
+ gpio_set_value(SABRESD_AUX_5V_EN, 1);
+}
+static const struct pm_platform_data mx6q_sabresd_pm_data __initconst = {
+ .name = "imx_pm",
+ .suspend_enter = sabresd_suspend_enter,
+ .suspend_exit = sabresd_suspend_exit,
+};
+
+static struct regulator_consumer_supply sabresd_vmmc_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.3"),
+};
+
+static struct regulator_init_data sabresd_vmmc_init = {
+ .num_consumer_supplies = ARRAY_SIZE(sabresd_vmmc_consumers),
+ .consumer_supplies = sabresd_vmmc_consumers,
+};
+
+static struct fixed_voltage_config sabresd_vmmc_reg_config = {
+ .supply_name = "vmmc",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &sabresd_vmmc_init,
+};
+
+static struct platform_device sabresd_vmmc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 3,
+ .dev = {
+ .platform_data = &sabresd_vmmc_reg_config,
+ },
+};
+
+static int __init imx6q_init_audio(void)
+{
+ if (board_is_mx6_reva()) {
+ mxc_register_device(&mx6_sabresd_audio_wm8958_device,
+ &wm8958_data);
+ imx6q_add_imx_ssi(1, &mx6_sabresd_ssi_pdata);
+
+ mxc_wm8958_init();
+ } else {
+ platform_device_register(&sabresd_vwm8962_reg_devices);
+ mxc_register_device(&mx6_sabresd_audio_wm8962_device,
+ &wm8962_data);
+ imx6q_add_imx_ssi(1, &mx6_sabresd_ssi_pdata);
+
+ mxc_wm8962_init();
+ }
+
+ return 0;
+}
+
+#ifndef CONFIG_IMX_PCIE
+static void pcie_3v3_power(void)
+{
+ /* disable PCIE_3V3 first */
+ gpio_request(SABRESD_PCIE_PWR_EN, "pcie_3v3_en");
+ gpio_direction_output(SABRESD_PCIE_PWR_EN, 0);
+ mdelay(10);
+ /* enable PCIE_3V3 again */
+ gpio_set_value(SABRESD_PCIE_PWR_EN, 1);
+ gpio_free(SABRESD_PCIE_PWR_EN);
+}
+
+static void pcie_3v3_reset(void)
+{
+ /* reset miniPCIe */
+ gpio_request(SABRESD_PCIE_RST_B_REVB, "pcie_reset_rebB");
+ gpio_direction_output(SABRESD_PCIE_RST_B_REVB, 0);
+ /* The PCI Express Mini CEM specification states that PREST# is
+ deasserted minimum 1ms after 3.3vVaux has been applied and stable*/
+ mdelay(1);
+ gpio_set_value(SABRESD_PCIE_RST_B_REVB, 1);
+ gpio_free(SABRESD_PCIE_RST_B_REVB);
+}
+#endif
+
+static void gps_power_on(bool on)
+{
+ /* Enable/disable aux_3v15 */
+ gpio_request(SABRESD_AUX_3V15_EN, "aux_3v15_en");
+ gpio_direction_output(SABRESD_AUX_3V15_EN, 1);
+ gpio_set_value(SABRESD_AUX_3V15_EN, on);
+ gpio_free(SABRESD_AUX_3V15_EN);
+ /*Enable/disable gps_en*/
+ gpio_request(SABRESD_GPS_EN, "gps_en");
+ gpio_direction_output(SABRESD_GPS_EN, 1);
+ gpio_set_value(SABRESD_GPS_EN, on);
+ gpio_free(SABRESD_GPS_EN);
+
+}
+
+#if defined(CONFIG_LEDS_TRIGGER) || defined(CONFIG_LEDS_GPIO)
+
+#define GPIO_LED(gpio_led, name_led, act_low, state_suspend, trigger) \
+{ \
+ .gpio = gpio_led, \
+ .name = name_led, \
+ .active_low = act_low, \
+ .retain_state_suspended = state_suspend, \
+ .default_state = 0, \
+ .default_trigger = "max8903-"trigger, \
+}
+
+/* use to show a external power source is connected
+ * GPIO_LED(SABRESD_CHARGE_DONE, "chg_detect", 0, 1, "ac-online"),
+ */
+static struct gpio_led imx6q_gpio_leds[] = {
+ GPIO_LED(SABRESD_CHARGE_NOW, "chg_now_led", 0, 1,
+ "charger-charging"),
+/* For the latest B4 board, this GPIO_1 is connected to POR_B,
+which will reset the whole board if this pin's level is changed,
+so, for the latest board, we have to avoid using this pin as
+GPIO.
+ GPIO_LED(SABRESD_CHARGE_DONE, "chg_done_led", 0, 1,
+ "charger-full"),
+*/
+};
+
+static struct gpio_led_platform_data imx6q_gpio_leds_data = {
+ .leds = imx6q_gpio_leds,
+ .num_leds = ARRAY_SIZE(imx6q_gpio_leds),
+};
+
+static struct platform_device imx6q_gpio_led_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &imx6q_gpio_leds_data,
+ }
+};
+
+static void __init imx6q_add_device_gpio_leds(void)
+{
+ platform_device_register(&imx6q_gpio_led_device);
+}
+#else
+static void __init imx6q_add_device_gpio_leds(void) {}
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake, debounce) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+ .debounce_interval = debounce, \
+}
+
+static struct gpio_keys_button imx6q_buttons[] = {
+ GPIO_BUTTON(SABRESD_VOLUME_UP, KEY_VOLUMEUP, 1, "volume-up", 0, 1),
+ GPIO_BUTTON(SABRESD_VOLUME_DN, KEY_POWER, 1, "volume-down", 1, 1),
+};
+
+static struct gpio_keys_platform_data imx6q_button_data = {
+ .buttons = imx6q_buttons,
+ .nbuttons = ARRAY_SIZE(imx6q_buttons),
+};
+
+static struct platform_device imx6q_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &imx6q_button_data,
+ }
+};
+
+static void __init imx6q_add_device_buttons(void)
+{
+ platform_device_register(&imx6q_button_device);
+}
+#else
+static void __init imx6q_add_device_buttons(void) {}
+#endif
+
+static struct platform_pwm_backlight_data mx6_sabresd_pwm_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 248,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+
+static struct mxc_dvfs_platform_data sabresd_dvfscore_data = {
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+ .reg_id = "VDDCORE",
+ .soc_id = "VDDSOC",
+#else
+ .reg_id = "cpu_vddgp",
+ .soc_id = "cpu_vddsoc",
+ .pu_id = "cpu_vddvpu",
+#endif
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+};
+
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ char *str;
+ struct tag *t;
+ int i = 0;
+ struct ipuv3_fb_platform_data *pdata_fb = sabresd_fb_data;
+
+ for_each_tag(t, tags) {
+ if (t->hdr.tag == ATAG_CMDLINE) {
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "fbmem=");
+ if (str != NULL) {
+ str += 6;
+ pdata_fb[i++].res_size[0] = memparse(str, &str);
+ while (*str == ',' &&
+ i < ARRAY_SIZE(sabresd_fb_data)) {
+ str++;
+ pdata_fb[i++].res_size[0] = memparse(str, &str);
+ }
+ }
+ break;
+ }
+ }
+}
+
+static struct mipi_csi2_platform_data mipi_csi2_pdata = {
+ .ipu_id = 0,
+ .csi_id = 1,
+ .v_channel = 0,
+ .lanes = 2,
+ .dphy_clk = "mipi_pllref_clk",
+ .pixel_clk = "emi_clk",
+};
+
+#define SNVS_LPCR 0x38
+static void mx6_snvs_poweroff(void)
+{
+
+ void __iomem *mx6_snvs_base = MX6_IO_ADDRESS(MX6Q_SNVS_BASE_ADDR);
+ u32 value;
+ value = readl(mx6_snvs_base + SNVS_LPCR);
+ /*set TOP and DP_EN bit*/
+ writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
+}
+
+static const struct imx_pcie_platform_data mx6_sabresd_pcie_data __initconst = {
+ .pcie_pwr_en = SABRESD_PCIE_PWR_EN,
+ .pcie_rst = SABRESD_PCIE_RST_B_REVB,
+ .pcie_wake_up = SABRESD_PCIE_WAKE_B,
+ .pcie_dis = SABRESD_PCIE_DIS_B,
+#ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS
+ .type_ep = 1,
+#else
+ .type_ep = 0,
+#endif
+};
+
+static int __init early_enable_lcd_ldb(char *p)
+{
+ enable_lcd_ldb = 1;
+ return 0;
+}
+early_param("enable_lcd_ldb", early_enable_lcd_ldb);
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mx6_sabresd_board_init(void)
+{
+ int i;
+ int ret;
+ struct clk *clko, *clko2;
+ struct clk *new_parent;
+ int rate;
+ struct platform_device *voutdev;
+
+ if (cpu_is_mx6q())
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_pads,
+ ARRAY_SIZE(mx6q_sabresd_pads));
+ else if (cpu_is_mx6dl()) {
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_pads,
+ ARRAY_SIZE(mx6dl_sabresd_pads));
+ }
+
+#ifdef CONFIG_FEC_1588
+ /* Set GPIO_16 input for IEEE-1588 ts_clk and RMII reference clock
+ * For MX6 GPR1 bit21 meaning:
+ * Bit21: 0 - GPIO_16 pad output
+ * 1 - GPIO_16 pad input
+ */
+ mxc_iomux_set_gpr_register(1, 21, 1, 1);
+#endif
+
+ gp_reg_id = sabresd_dvfscore_data.reg_id;
+ soc_reg_id = sabresd_dvfscore_data.soc_id;
+ pu_reg_id = sabresd_dvfscore_data.pu_id;
+ mx6q_sabresd_init_uart();
+
+ /*
+ * MX6DL/Solo only supports single IPU
+ * The following codes are used to change ipu id
+ * and display id information for MX6DL/Solo. Then
+ * register 1 IPU device and up to 2 displays for
+ * MX6DL/Solo
+ */
+ if (cpu_is_mx6dl()) {
+ ldb_data.ipu_id = 0;
+ ldb_data.disp_id = 1;
+ hdmi_core_data.disp_id = 0;
+ mipi_dsi_pdata.ipu_id = 0;
+ mipi_dsi_pdata.disp_id = 1;
+ }
+ imx6q_add_mxc_hdmi_core(&hdmi_core_data);
+
+ imx6q_add_ipuv3(0, &ipu_data[0]);
+ if (cpu_is_mx6q()) {
+ imx6q_add_ipuv3(1, &ipu_data[1]);
+ for (i = 0; i < 4 && i < ARRAY_SIZE(sabresd_fb_data); i++)
+ imx6q_add_ipuv3fb(i, &sabresd_fb_data[i]);
+ } else
+ for (i = 0; i < 2 && i < ARRAY_SIZE(sabresd_fb_data); i++)
+ imx6q_add_ipuv3fb(i, &sabresd_fb_data[i]);
+
+ imx6q_add_vdoa();
+ imx6q_add_mipi_dsi(&mipi_dsi_pdata);
+ imx6q_add_lcdif(&lcdif_data);
+ imx6q_add_ldb(&ldb_data);
+ voutdev = imx6q_add_v4l2_output(0);
+ if (vout_mem.res_msize && voutdev) {
+ dma_declare_coherent_memory(&voutdev->dev,
+ vout_mem.res_mbase,
+ vout_mem.res_mbase,
+ vout_mem.res_msize,
+ (DMA_MEMORY_MAP |
+ DMA_MEMORY_EXCLUSIVE));
+ }
+
+ imx6q_add_v4l2_capture(0, &capture_data[0]);
+ imx6q_add_v4l2_capture(1, &capture_data[1]);
+ imx6q_add_mipi_csi2(&mipi_csi2_pdata);
+ imx6q_add_imx_snvs_rtc();
+
+ imx6q_add_imx_caam();
+
+ if (board_is_mx6_reva()) {
+ strcpy(mxc_i2c0_board_info[0].type, "wm8958");
+ mxc_i2c0_board_info[0].platform_data = &wm8958_config_data;
+ } else {
+ strcpy(mxc_i2c0_board_info[0].type, "wm8962");
+ mxc_i2c0_board_info[0].platform_data = &wm8962_config_data;
+ }
+ imx6q_add_device_gpio_leds();
+
+ imx6q_add_imx_i2c(0, &mx6q_sabresd_i2c_data);
+ imx6q_add_imx_i2c(1, &mx6q_sabresd_i2c_data);
+ imx6q_add_imx_i2c(2, &mx6q_sabresd_i2c_data);
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+ ret = gpio_request(SABRESD_PFUZE_INT, "pFUZE-int");
+ if (ret) {
+ printk(KERN_ERR"request pFUZE-int error!!\n");
+ return;
+ } else {
+ gpio_direction_input(SABRESD_PFUZE_INT);
+ mx6q_sabresd_init_pfuze100(SABRESD_PFUZE_INT);
+ }
+ /* SPI */
+ imx6q_add_ecspi(0, &mx6q_sabresd_spi_data);
+ spi_device_init();
+
+ imx6q_add_mxc_hdmi(&hdmi_data);
+
+ imx6q_add_anatop_thermal_imx(1, &mx6q_sabresd_anatop_thermal_data);
+ imx6_init_fec(fec_data);
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */
+ mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET,
+ OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK);
+#endif
+
+ imx6q_add_pm_imx(0, &mx6q_sabresd_pm_data);
+
+ /* Move sd4 to first because sd4 connect to emmc.
+ Mfgtools want emmc is mmcblk0 and other sd card is mmcblk1.
+ */
+ imx6q_add_sdhci_usdhc_imx(3, &mx6q_sabresd_sd4_data);
+ imx6q_add_sdhci_usdhc_imx(2, &mx6q_sabresd_sd3_data);
+ imx6q_add_sdhci_usdhc_imx(1, &mx6q_sabresd_sd2_data);
+ imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata);
+ imx6q_sabresd_init_usb();
+ /* SATA is not supported by MX6DL/Solo */
+ if (cpu_is_mx6q())
+ imx6q_add_ahci(0, &mx6q_sabresd_sata_data);
+ imx6q_add_vpu();
+ imx6q_init_audio();
+ platform_device_register(&sabresd_vmmc_reg_devices);
+ imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ imx6q_add_asrc(&imx_asrc_data);
+
+ /*
+ * Disable HannStar touch panel CABC function,
+ * this function turns the panel's backlight automatically
+ * according to the content shown on the panel which
+ * may cause annoying unstable backlight issue.
+ */
+ gpio_request(SABRESD_CABC_EN0, "cabc-en0");
+ gpio_direction_output(SABRESD_CABC_EN0, 0);
+ gpio_request(SABRESD_CABC_EN1, "cabc-en1");
+ gpio_direction_output(SABRESD_CABC_EN1, 0);
+
+ imx6q_add_mxc_pwm(0);
+ imx6q_add_mxc_pwm(1);
+ imx6q_add_mxc_pwm(2);
+ imx6q_add_mxc_pwm(3);
+ imx6q_add_mxc_pwm_backlight(0, &mx6_sabresd_pwm_backlight_data);
+
+ imx6q_add_otp();
+ imx6q_add_viim();
+ imx6q_add_imx2_wdt(0, NULL);
+ imx6q_add_dma();
+
+ imx6q_add_dvfs_core(&sabresd_dvfscore_data);
+#ifndef CONFIG_MX6_INTER_LDO_BYPASS
+ mx6_cpu_regulator_init();
+#endif
+ imx6q_add_device_buttons();
+
+ /* enable sensor 3v3 and 1v8 */
+ gpio_request(SABRESD_SENSOR_EN, "sensor-en");
+ gpio_direction_output(SABRESD_SENSOR_EN, 1);
+
+ /* enable ecompass intr */
+ gpio_request(SABRESD_eCOMPASS_INT, "ecompass-int");
+ gpio_direction_input(SABRESD_eCOMPASS_INT);
+ /* enable light sensor intr */
+ gpio_request(SABRESD_ALS_INT, "als-int");
+ gpio_direction_input(SABRESD_ALS_INT);
+
+ imx6q_add_hdmi_soc();
+ imx6q_add_hdmi_soc_dai();
+
+ if (cpu_is_mx6dl()) {
+ imx6dl_add_imx_pxp();
+ imx6dl_add_imx_pxp_client();
+ if (epdc_enabled) {
+ mxc_register_device(&max17135_sensor_device, NULL);
+ imx6dl_add_imx_epdc(&epdc_data);
+ }
+ }
+ /*
+ ret = gpio_request_array(mx6q_sabresd_flexcan_gpios,
+ ARRAY_SIZE(mx6q_sabresd_flexcan_gpios));
+ if (ret)
+ pr_err("failed to request flexcan1-gpios: %d\n", ret);
+ else
+ imx6q_add_flexcan0(&mx6q_sabresd_flexcan0_pdata);
+ */
+
+ clko2 = clk_get(NULL, "clko2_clk");
+ if (IS_ERR(clko2))
+ pr_err("can't get CLKO2 clock.\n");
+
+ new_parent = clk_get(NULL, "osc_clk");
+ if (!IS_ERR(new_parent)) {
+ clk_set_parent(clko2, new_parent);
+ clk_put(new_parent);
+ }
+ rate = clk_round_rate(clko2, 24000000);
+ clk_set_rate(clko2, rate);
+ clk_enable(clko2);
+
+ /* Camera and audio use osc clock */
+ clko = clk_get(NULL, "clko_clk");
+ if (!IS_ERR(clko))
+ clk_set_parent(clko, clko2);
+
+ /* Enable Aux_5V */
+ gpio_request(SABRESD_AUX_5V_EN, "aux_5v_en");
+ gpio_direction_output(SABRESD_AUX_5V_EN, 1);
+ gpio_set_value(SABRESD_AUX_5V_EN, 1);
+
+#ifndef CONFIG_IMX_PCIE
+ /* enable pcie 3v3 power without pcie driver */
+ pcie_3v3_power();
+ mdelay(10);
+ pcie_3v3_reset();
+#endif
+
+ gps_power_on(true);
+ /* Register charger chips */
+ platform_device_register(&sabresd_max8903_charger_1);
+ pm_power_off = mx6_snvs_poweroff;
+ imx6q_add_busfreq();
+
+ /* Add PCIe RC interface support */
+ imx6q_add_pcie(&mx6_sabresd_pcie_data);
+ if (cpu_is_mx6dl()) {
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_elan_pads,
+ ARRAY_SIZE(mx6dl_arm2_elan_pads));
+
+ /* ELAN Touchscreen */
+ gpio_request(SABRESD_ELAN_INT, "elan-interrupt");
+ gpio_direction_input(SABRESD_ELAN_INT);
+
+ gpio_request(SABRESD_ELAN_CE, "elan-cs");
+ gpio_direction_output(SABRESD_ELAN_CE, 1);
+ gpio_direction_output(SABRESD_ELAN_CE, 0);
+
+ gpio_request(SABRESD_ELAN_RST, "elan-rst");
+ gpio_direction_output(SABRESD_ELAN_RST, 1);
+ gpio_direction_output(SABRESD_ELAN_RST, 0);
+ mdelay(1);
+ gpio_direction_output(SABRESD_ELAN_RST, 1);
+ gpio_direction_output(SABRESD_ELAN_CE, 1);
+ }
+
+ imx6_add_armpmu();
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
+}
+
+extern void __iomem *twd_base;
+static void __init mx6_sabresd_timer_init(void)
+{
+ struct clk *uart_clk;
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ mx6_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(UART1_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mx6_sabresd_timer = {
+ .init = mx6_sabresd_timer_init,
+};
+
+static void __init mx6q_sabresd_reserve(void)
+{
+ phys_addr_t phys;
+ int i;
+
+#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE)
+ if (imx6q_gpu_pdata.reserved_mem_size) {
+ phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size,
+ SZ_4K, SZ_1G);
+ memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size);
+ imx6q_gpu_pdata.reserved_mem_base = phys;
+ }
+#endif
+
+#if defined(CONFIG_ION)
+ if (imx_ion_data.heaps[0].size) {
+ phys = memblock_alloc(imx_ion_data.heaps[0].size, SZ_4K);
+ memblock_remove(phys, imx_ion_data.heaps[0].size);
+ imx_ion_data.heaps[0].base = phys;
+ }
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(sabresd_fb_data); i++)
+ if (sabresd_fb_data[i].res_size[0]) {
+ /* reserve for background buffer */
+ phys = memblock_alloc(sabresd_fb_data[i].res_size[0],
+ SZ_4K);
+ memblock_remove(phys, sabresd_fb_data[i].res_size[0]);
+ sabresd_fb_data[i].res_base[0] = phys;
+ }
+ if (vout_mem.res_msize) {
+ phys = memblock_alloc_base(vout_mem.res_msize,
+ SZ_4K, SZ_1G);
+ memblock_remove(phys, vout_mem.res_msize);
+ vout_mem.res_mbase = phys;
+ }
+}
+
+/*
+ * initialize __mach_desc_MX6Q_SABRESD data structure.
+ */
+MACHINE_START(MX6Q_SABRESD, "Freescale i.MX 6Quad/DualLite/Solo Sabre-SD Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .boot_params = MX6_PHYS_OFFSET + 0x100,
+ .fixup = fixup_mxc_board,
+ .map_io = mx6_map_io,
+ .init_irq = mx6_init_irq,
+ .init_machine = mx6_sabresd_board_init,
+ .timer = &mx6_sabresd_timer,
+ .reserve = mx6q_sabresd_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.h b/arch/arm/mach-mx6/board-mx6q_sabresd.h
new file mode 100644
index 00000000..b2bb8c92
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6q_sabresd.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2012-2013 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.
+ */
+
+#ifndef _BOARD_MX6Q_SABRESD_H
+#define _BOARD_MX6Q_SABRESD_H
+#include <mach/iomux-mx6q.h>
+
+static iomux_v3_cfg_t mx6q_sabresd_pads[] = {
+ /* AUDMUX */
+ MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC,
+ MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD,
+ MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS,
+ MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD,
+
+ /* CAN1 */
+ MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE,
+ /* MX6Q_PAD_KEY_COL2__CAN1_TXCAN, */
+ MX6Q_PAD_GPIO_1__WDOG2_WDOG_B, /*WDOG_B to reset pmic*/
+ MX6Q_PAD_GPIO_2__GPIO_1_2, /* user defined red led */
+ MX6Q_PAD_GPIO_7__GPIO_1_7, /* NERR */
+
+ /* CCM */
+ MX6Q_PAD_GPIO_0__CCM_CLKO, /* SGTL500 sys_mclk */
+ MX6Q_PAD_GPIO_3__CCM_CLKO2, /* J5 - Camera MCLK */
+
+ /* ECSPI1 */
+ MX6Q_PAD_KEY_COL0__ECSPI1_SCLK,
+ MX6Q_PAD_KEY_ROW0__ECSPI1_MOSI,
+ MX6Q_PAD_KEY_COL1__ECSPI1_MISO,
+ MX6Q_PAD_KEY_ROW1__GPIO_4_9,
+ /* ENET */
+ MX6Q_PAD_ENET_MDIO__ENET_MDIO,
+ MX6Q_PAD_ENET_MDC__ENET_MDC,
+ MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC,
+ MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0,
+ MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1,
+ MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2,
+ MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3,
+ MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL,
+ MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK,
+ MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC,
+ MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0,
+ MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1,
+ MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2,
+ MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3,
+ MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL,
+ MX6Q_PAD_ENET_TX_EN__GPIO_1_28, /* Micrel RGMII Phy Interrupt */
+ MX6Q_PAD_EIM_D23__GPIO_3_23, /* RGMII reset */
+ MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT, /* Internal connect for 1588 TS Clock */
+
+ /* GPIO1 */
+ MX6Q_PAD_ENET_RX_ER__GPIO_1_24, /* J9 - Microphone Detect */
+
+ /* GPIO2 */
+ /* MX6Q_PAD_NANDF_D1__GPIO_2_1,*/ /* J14 - Menu Button */
+ /* MX6Q_PAD_NANDF_D2__GPIO_2_2,*/ /* J14 - Back Button */
+ /* MX6Q_PAD_NANDF_D3__GPIO_2_3,*/ /* J14 - Search Button */
+ /* MX6Q_PAD_NANDF_D4__GPIO_2_4,*/ /* J14 - Home Button */
+ MX6Q_PAD_EIM_A22__GPIO_2_16, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A21__GPIO_2_17, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A20__GPIO_2_18, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A19__GPIO_2_19, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A18__GPIO_2_20, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A17__GPIO_2_21, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A16__GPIO_2_22, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_RW__GPIO_2_26, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_LBA__GPIO_2_27, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_EB0__GPIO_2_28, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_EB1__GPIO_2_29, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_EB3__GPIO_2_31, /* J12 - Boot Mode Select */
+
+ /* GPIO3 */
+ MX6Q_PAD_EIM_DA0__GPIO_3_0, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA1__GPIO_3_1, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA2__GPIO_3_2, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA3__GPIO_3_3, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA4__GPIO_3_4, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA5__GPIO_3_5, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA6__GPIO_3_6, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA7__GPIO_3_7, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA8__GPIO_3_8, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA9__GPIO_3_9, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA10__GPIO_3_10, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA11__GPIO_3_11, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA12__GPIO_3_12, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA13__GPIO_3_13, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA14__GPIO_3_14, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_DA15__GPIO_3_15, /* J12 - Boot Mode Select */
+
+ /* SW4 , SW5 & SW1 */
+ MX6Q_PAD_GPIO_4__GPIO_1_4, /* Volume Up */
+ MX6Q_PAD_GPIO_5__GPIO_1_5, /* Volume Down */
+ MX6Q_PAD_EIM_D29__GPIO_3_29, /* power off */
+
+ /* CAP_TCH_INT1 */
+ MX6Q_PAD_NANDF_CLE__GPIO_6_7,
+
+ /* CAP_TCH_INT0 */
+ MX6Q_PAD_NANDF_ALE__GPIO_6_8,
+
+ /* eCompass int */
+ MX6Q_PAD_EIM_D16__GPIO_3_16,
+
+ /* GPIO5 */
+ MX6Q_PAD_EIM_WAIT__GPIO_5_0, /* J12 - Boot Mode Select */
+ MX6Q_PAD_EIM_A24__GPIO_5_4, /* J12 - Boot Mode Select */
+
+ /* GPIO6 */
+ MX6Q_PAD_EIM_A23__GPIO_6_6, /* J12 - Boot Mode Select */
+ MX6Q_PAD_NANDF_RB0__GPIO_6_10, /* AUX_5V Enable */
+
+ /* I2C1, WM8958 */
+ MX6Q_PAD_CSI0_DAT8__I2C1_SDA,
+ MX6Q_PAD_CSI0_DAT9__I2C1_SCL,
+
+ /* I2C2, Camera, MIPI */
+ MX6Q_PAD_KEY_COL3__I2C2_SCL,
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA,
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1,
+#else
+ /* I2C3 */
+ MX6Q_PAD_GPIO_3__I2C3_SCL, /* GPIO1[3] */
+ MX6Q_PAD_GPIO_6__I2C3_SDA,
+#endif
+
+ /* DISPLAY */
+ MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15, /* DE */
+ MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2, /* HSync */
+ MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3, /* VSync */
+ MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN4, /* Contrast */
+ MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
+ MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
+ MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
+ MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
+ MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
+ MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
+ MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
+ MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
+ MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
+ MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
+ MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
+ MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
+ MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
+ MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
+ MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
+ MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
+ MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
+ MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
+ MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
+ MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
+ MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20,
+ MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
+ MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22,
+ MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23,
+ MX6Q_PAD_GPIO_7__GPIO_1_7, /* J7 - Display Connector GP */
+ MX6Q_PAD_GPIO_9__GPIO_1_9, /* J7 - Display Connector GP */
+ /* MX6Q_PAD_NANDF_D0__GPIO_2_0,*/ /* J6 - LVDS Display contrast */
+
+ /* DISP_PWM */
+ MX6Q_PAD_SD1_DAT3__PWM1_PWMO, /* GPIO1[21] */
+
+ /* UART1 for debug */
+ MX6Q_PAD_CSI0_DAT10__UART1_TXD,
+ MX6Q_PAD_CSI0_DAT11__UART1_RXD,
+
+ /* UART3 for gps */
+ MX6Q_PAD_EIM_D24__UART3_TXD,
+ MX6Q_PAD_EIM_D25__UART3_RXD,
+
+ /* USBOTG ID pin */
+ MX6Q_PAD_ENET_RX_ER__ANATOP_USBOTG_ID,
+
+ /* USB power pin */
+ MX6Q_PAD_EIM_D22__GPIO_3_22,
+ MX6Q_PAD_ENET_TXD1__GPIO_1_29,
+
+ /* USB OC pin */
+ MX6Q_PAD_EIM_D21__USBOH3_USBOTG_OC,
+ MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC,
+
+ /* USDHC2 */
+ MX6Q_PAD_SD2_CLK__USDHC2_CLK,
+ MX6Q_PAD_SD2_CMD__USDHC2_CMD,
+ MX6Q_PAD_SD2_DAT0__USDHC2_DAT0,
+ MX6Q_PAD_SD2_DAT1__USDHC2_DAT1,
+ MX6Q_PAD_SD2_DAT2__USDHC2_DAT2,
+ MX6Q_PAD_SD2_DAT3__USDHC2_DAT3,
+ MX6Q_PAD_NANDF_D4__USDHC2_DAT4,
+ MX6Q_PAD_NANDF_D5__USDHC2_DAT5,
+ MX6Q_PAD_NANDF_D6__USDHC2_DAT6,
+ MX6Q_PAD_NANDF_D7__USDHC2_DAT7,
+ MX6Q_PAD_NANDF_D2__GPIO_2_2, /* SD2_CD */
+ MX6Q_PAD_NANDF_D3__GPIO_2_3, /* SD2_WP */
+
+ /* USDHC3 */
+ MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6Q_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6Q_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6Q_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6Q_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+ MX6Q_PAD_NANDF_D0__GPIO_2_0, /* SD3_CD */
+ MX6Q_PAD_NANDF_D1__GPIO_2_1, /* SD3_WP */
+
+ /* USDHC4 */
+ MX6Q_PAD_SD4_CLK__USDHC4_CLK_50MHZ,
+ MX6Q_PAD_SD4_CMD__USDHC4_CMD_50MHZ,
+ MX6Q_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ,
+ MX6Q_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ,
+ MX6Q_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ,
+ MX6Q_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ,
+ MX6Q_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ,
+ MX6Q_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ,
+ MX6Q_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ,
+ MX6Q_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ,
+
+ /* Charge */
+ MX6Q_PAD_EIM_A25__GPIO_5_2, /* FLT_1_B */
+ MX6Q_PAD_EIM_D23__GPIO_3_23, /* CHG_1_B */
+ MX6Q_PAD_EIM_DA13__GPIO_3_13, /* CHG_2_B */
+ MX6Q_PAD_EIM_DA14__GPIO_3_14, /* FLT_2_B */
+
+ MX6Q_PAD_ENET_RXD0__GPIO_1_27, /* UOK_B */
+ MX6Q_PAD_EIM_CS1__GPIO_2_24, /* DOK_B */
+
+ /* Audio Codec */
+ MX6Q_PAD_KEY_COL2__GPIO_4_10, /* CODEC_PWR_EN */
+ MX6Q_PAD_SD3_RST__GPIO_7_8, /* HEADPHONE_DET */
+ MX6Q_PAD_GPIO_9__GPIO_1_9, /* MICROPHONE_DET */
+
+ /*GPS AUX_3V15_EN*/
+ MX6Q_PAD_NANDF_WP_B__GPIO_6_9,
+
+ /* PCIE */
+ MX6Q_PAD_EIM_D19__GPIO_3_19, /* PCIE_PWR_EN */
+
+ MX6Q_PAD_GPIO_17__GPIO_7_12, /* PCIE_RST */
+ MX6Q_PAD_KEY_COL4__GPIO_4_14, /* PCIE_DIS */
+
+ /* DISP_RST_B */
+ MX6Q_PAD_NANDF_CS0__GPIO_6_11,
+ /* DISP_PWR_EN */
+ MX6Q_PAD_NANDF_CS1__GPIO_6_14,
+ /* CABC_EN0 */
+ MX6Q_PAD_NANDF_CS2__GPIO_6_15,
+ /* CABC_EN1 */
+ MX6Q_PAD_NANDF_CS3__GPIO_6_16,
+};
+
+static iomux_v3_cfg_t mx6q_sabresd_csi0_sensor_pads[] = {
+ /* IPU1 Camera */
+ MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN,
+ MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+ MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+
+ MX6Q_PAD_GPIO_0__CCM_CLKO, /* camera clk */
+
+ MX6Q_PAD_SD1_DAT0__GPIO_1_16, /* camera PWDN */
+ MX6Q_PAD_SD1_DAT1__GPIO_1_17, /* camera RESET */
+};
+
+static iomux_v3_cfg_t mx6q_sabresd_mipi_sensor_pads[] = {
+ MX6Q_PAD_GPIO_0__CCM_CLKO, /* camera clk */
+
+ MX6Q_PAD_SD1_DAT2__GPIO_1_19, /* camera PWDN */
+ MX6Q_PAD_SD1_CLK__GPIO_1_20, /* camera RESET */
+};
+
+static iomux_v3_cfg_t mx6q_sabresd_hdmi_ddc_pads[] = {
+ MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_sabresd_i2c2_pads[] = {
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
+#endif
diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c
new file mode 100755
index 00000000..fbc5d4dd
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c
@@ -0,0 +1,1313 @@
+/*
+ * Copyright (C) 2012 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 <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/etherdevice.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max17135.h>
+#include <sound/wm8962.h>
+#include <sound/pcm.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/memory.h>
+#include <mach/iomux-mx6sl.h>
+#include <mach/imx-uart.h>
+#include <mach/viv_gpu.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "usb.h"
+#include "devices-imx6q.h"
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "board-mx6sl_common.h"
+
+static int spdc_sel;
+static int max17135_regulator_init(struct max17135 *max17135);
+static struct clk *extern_audio_root;
+
+extern char *gp_reg_id;
+extern char *soc_reg_id;
+extern char *pu_reg_id;
+extern int __init mx6sl_arm2_init_pfuze100(u32 int_gpio);
+
+enum sd_pad_mode {
+ SD_PAD_MODE_LOW_SPEED,
+ SD_PAD_MODE_MED_SPEED,
+ SD_PAD_MODE_HIGH_SPEED,
+};
+
+static int plt_sd_pad_change(unsigned int index, int clock)
+{
+ /* LOW speed is the default state of SD pads */
+ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
+
+ iomux_v3_cfg_t *sd_pads_200mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_100mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_50mhz = NULL;
+
+ u32 sd_pads_200mhz_cnt;
+ u32 sd_pads_100mhz_cnt;
+ u32 sd_pads_50mhz_cnt;
+
+ switch (index) {
+ case 0:
+ sd_pads_200mhz = mx6sl_sd1_200mhz;
+ sd_pads_100mhz = mx6sl_sd1_100mhz;
+ sd_pads_50mhz = mx6sl_sd1_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd1_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd1_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd1_50mhz);
+ break;
+ case 1:
+ sd_pads_200mhz = mx6sl_sd2_200mhz;
+ sd_pads_100mhz = mx6sl_sd2_100mhz;
+ sd_pads_50mhz = mx6sl_sd2_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd2_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd2_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd2_50mhz);
+ break;
+ case 2:
+ sd_pads_200mhz = mx6sl_sd3_200mhz;
+ sd_pads_100mhz = mx6sl_sd3_100mhz;
+ sd_pads_50mhz = mx6sl_sd3_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd3_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd3_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd3_50mhz);
+ break;
+ default:
+ printk(KERN_ERR "no such SD host controller index %d\n", index);
+ return -EINVAL;
+ }
+
+ if (clock > 100000000) {
+ if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_200mhz);
+ pad_mode = SD_PAD_MODE_HIGH_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
+ sd_pads_200mhz_cnt);
+ } else if (clock > 52000000) {
+ if (pad_mode == SD_PAD_MODE_MED_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_100mhz);
+ pad_mode = SD_PAD_MODE_MED_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
+ sd_pads_100mhz_cnt);
+ } else {
+ if (pad_mode == SD_PAD_MODE_LOW_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_50mhz);
+ pad_mode = SD_PAD_MODE_LOW_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
+ sd_pads_50mhz_cnt);
+ }
+}
+
+static const struct esdhc_platform_data mx6_arm2_sd1_data __initconst = {
+ .cd_gpio = MX6_BRD_SD1_CD,
+ .wp_gpio = MX6_BRD_SD1_WP,
+ .support_8bit = 1,
+ .support_18v = 1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+static const struct esdhc_platform_data mx6_arm2_sd2_data __initconst = {
+ .cd_gpio = MX6_BRD_SD2_CD,
+ .wp_gpio = MX6_BRD_SD2_WP,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .support_18v = 1,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = {
+ .cd_gpio = MX6_BRD_SD3_CD,
+ .wp_gpio = -1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .support_18v = 1,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+static struct regulator_consumer_supply arm2_vmmc_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"),
+};
+
+static struct regulator_init_data arm2_vmmc_init = {
+ .num_consumer_supplies = ARRAY_SIZE(arm2_vmmc_consumers),
+ .consumer_supplies = arm2_vmmc_consumers,
+};
+
+static struct fixed_voltage_config arm2_vmmc_reg_config = {
+ .supply_name = "vmmc",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &arm2_vmmc_init,
+};
+
+static struct platform_device arm2_vmmc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &arm2_vmmc_reg_config,
+ },
+};
+
+static struct regulator_consumer_supply display_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "DISPLAY",
+ },
+};
+
+static struct regulator_consumer_supply vcom_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "VCOM",
+ },
+};
+
+static struct regulator_consumer_supply v3p3_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "V3P3",
+ },
+};
+
+static struct regulator_init_data max17135_init_data[] = {
+ {
+ .constraints = {
+ .name = "DISPLAY",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(display_consumers),
+ .consumer_supplies = display_consumers,
+ }, {
+ .constraints = {
+ .name = "GVDD",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "GVEE",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINN",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINP",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "VCOM",
+ .min_uV = mV_to_uV(-4325),
+ .max_uV = mV_to_uV(-500),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcom_consumers),
+ .consumer_supplies = vcom_consumers,
+ }, {
+ .constraints = {
+ .name = "VNEG",
+ .min_uV = V_to_uV(-15),
+ .max_uV = V_to_uV(-15),
+ },
+ }, {
+ .constraints = {
+ .name = "VPOS",
+ .min_uV = V_to_uV(15),
+ .max_uV = V_to_uV(15),
+ },
+ }, {
+ .constraints = {
+ .name = "V3P3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(v3p3_consumers),
+ .consumer_supplies = v3p3_consumers,
+ },
+};
+
+static const struct anatop_thermal_platform_data
+ mx6sl_anatop_thermal_data __initconst = {
+ .name = "anatop_thermal",
+ };
+
+static struct platform_device max17135_sensor_device = {
+ .name = "max17135_sensor",
+ .id = 0,
+};
+
+static struct max17135_platform_data max17135_pdata __initdata = {
+ .vneg_pwrup = 1,
+ .gvee_pwrup = 1,
+ .vpos_pwrup = 2,
+ .gvdd_pwrup = 1,
+ .gvdd_pwrdn = 1,
+ .vpos_pwrdn = 2,
+ .gvee_pwrdn = 1,
+ .vneg_pwrdn = 1,
+ .gpio_pmic_pwrgood = MX6SL_BRD_EPDC_PWRSTAT,
+ .gpio_pmic_vcom_ctrl = MX6SL_BRD_EPDC_VCOM,
+ .gpio_pmic_wakeup = MX6SL_BRD_EPDC_PMIC_WAKE,
+ .gpio_pmic_v3p3 = MX6SL_BRD_EPDC_PWRCTRL0,
+ .gpio_pmic_intr = MX6SL_BRD_EPDC_PMIC_INT,
+ .regulator_init = max17135_init_data,
+ .init = max17135_regulator_init,
+};
+
+static int __init max17135_regulator_init(struct max17135 *max17135)
+{
+ struct max17135_platform_data *pdata = &max17135_pdata;
+ int i, ret;
+
+ max17135->gvee_pwrup = pdata->gvee_pwrup;
+ max17135->vneg_pwrup = pdata->vneg_pwrup;
+ max17135->vpos_pwrup = pdata->vpos_pwrup;
+ max17135->gvdd_pwrup = pdata->gvdd_pwrup;
+ max17135->gvdd_pwrdn = pdata->gvdd_pwrdn;
+ max17135->vpos_pwrdn = pdata->vpos_pwrdn;
+ max17135->vneg_pwrdn = pdata->vneg_pwrdn;
+ max17135->gvee_pwrdn = pdata->gvee_pwrdn;
+
+ max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup +
+ pdata->gvdd_pwrup + pdata->gvee_pwrup;
+
+ max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood;
+ max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl;
+ max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup;
+ max17135->gpio_pmic_v3p3 = pdata->gpio_pmic_v3p3;
+ max17135->gpio_pmic_intr = pdata->gpio_pmic_intr;
+
+ gpio_request(max17135->gpio_pmic_wakeup, "epdc-pmic-wake");
+ gpio_direction_output(max17135->gpio_pmic_wakeup, 0);
+
+ gpio_request(max17135->gpio_pmic_vcom_ctrl, "epdc-vcom");
+ gpio_direction_output(max17135->gpio_pmic_vcom_ctrl, 0);
+
+ gpio_request(max17135->gpio_pmic_v3p3, "epdc-v3p3");
+ gpio_direction_output(max17135->gpio_pmic_v3p3, 0);
+
+ gpio_request(max17135->gpio_pmic_intr, "epdc-pmic-int");
+ gpio_direction_input(max17135->gpio_pmic_intr);
+
+ gpio_request(max17135->gpio_pmic_pwrgood, "epdc-pwrstat");
+ gpio_direction_input(max17135->gpio_pmic_pwrgood);
+
+ max17135->vcom_setup = false;
+ max17135->init_done = false;
+
+ for (i = 0; i < MAX17135_NUM_REGULATORS; i++) {
+ ret = max17135_register_regulator(max17135, i,
+ &pdata->regulator_init[i]);
+ if (ret != 0) {
+ printk(KERN_ERR"max17135 regulator init failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /*
+ * TODO: We cannot enable full constraints for now, since
+ * it results in the PFUZE regulators being disabled
+ * at the end of boot, which disables critical regulators.
+ */
+ /*regulator_has_full_constraints();*/
+
+ return 0;
+}
+
+static int mx6_arm2_spi_cs[] = {
+ MX6_BRD_ECSPI1_CS0,
+};
+
+static const struct spi_imx_master mx6_arm2_spi_data __initconst = {
+ .chipselect = mx6_arm2_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx6_arm2_spi_cs),
+};
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition m25p32_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x00100000,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data m25p32_spi_flash_data = {
+ .name = "m25p32",
+ .parts = m25p32_partitions,
+ .nr_parts = ARRAY_SIZE(m25p32_partitions),
+ .type = "m25p32",
+};
+
+static struct spi_board_info m25p32_spi0_board_info[] __initdata = {
+ {
+ /* The modalias must be the same as spi device driver name */
+ .modalias = "m25p80",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = &m25p32_spi_flash_data,
+ },
+};
+#endif
+
+static void spi_device_init(void)
+{
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+ spi_register_board_info(m25p32_spi0_board_info,
+ ARRAY_SIZE(m25p32_spi0_board_info));
+#endif
+}
+
+static struct imx_ssi_platform_data mx6_sabresd_ssi_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_SYN,
+};
+
+static struct mxc_audio_platform_data wm8962_data;
+
+static struct platform_device mx6_sabresd_audio_wm8962_device = {
+ .name = "imx-wm8962",
+};
+
+static struct wm8962_pdata wm8962_config_data = {
+
+};
+
+static int wm8962_clk_enable(int enable)
+{
+ if (enable)
+ clk_enable(extern_audio_root);
+ else
+ clk_disable(extern_audio_root);
+
+ return 0;
+}
+
+static int mxc_wm8962_init(void)
+{
+ struct clk *pll4;
+ int rate;
+
+ extern_audio_root = clk_get(NULL, "extern_audio_clk");
+ if (IS_ERR(extern_audio_root)) {
+ pr_err("can't get extern_audio_root clock.\n");
+ return PTR_ERR(extern_audio_root);
+ }
+
+ pll4 = clk_get(NULL, "pll4");
+ if (IS_ERR(pll4)) {
+ pr_err("can't get pll4 clock.\n");
+ return PTR_ERR(pll4);
+ }
+
+ clk_set_parent(extern_audio_root, pll4);
+
+ rate = 24000000;
+ clk_set_rate(extern_audio_root, 24000000);
+
+ wm8962_data.sysclk = rate;
+
+ return 0;
+}
+
+static struct mxc_audio_platform_data wm8962_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_gpio = MX6_BRD_HEADPHONE_DET,
+ .hp_active_low = 1,
+ .mic_gpio = -1,
+ .mic_active_low = 1,
+ .init = mxc_wm8962_init,
+ .clock_enable = wm8962_clk_enable,
+};
+
+static struct regulator_consumer_supply sabresd_vwm8962_consumers[] = {
+ REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
+ REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+};
+
+static struct regulator_init_data sabresd_vwm8962_init = {
+ .constraints = {
+ .name = "SPKVDD",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sabresd_vwm8962_consumers),
+ .consumer_supplies = sabresd_vwm8962_consumers,
+};
+
+static struct fixed_voltage_config sabresd_vwm8962_reg_config = {
+ .supply_name = "SPKVDD",
+ .microvolts = 4325000,
+ .gpio = -1,
+ .enabled_at_boot = 1,
+ .init_data = &sabresd_vwm8962_init,
+};
+
+static struct platform_device sabresd_vwm8962_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 4,
+ .dev = {
+ .platform_data = &sabresd_vwm8962_reg_config,
+ },
+};
+
+static int __init imx6q_init_audio(void)
+{
+ platform_device_register(&sabresd_vwm8962_reg_devices);
+ mxc_register_device(&mx6_sabresd_audio_wm8962_device,
+ &wm8962_data);
+ imx6q_add_imx_ssi(1, &mx6_sabresd_ssi_pdata);
+
+ return 0;
+}
+
+static struct imxi2c_platform_data mx6_arm2_i2c0_data = {
+ .bitrate = 100000,
+};
+
+static struct imxi2c_platform_data mx6_arm2_i2c1_data = {
+ .bitrate = 100000,
+};
+
+static struct imxi2c_platform_data mx6_arm2_i2c2_data = {
+ .bitrate = 400000,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("max17135", 0x48),
+ .platform_data = &max17135_pdata,
+ }, {
+ I2C_BOARD_INFO("elan-touch", 0x10),
+ .irq = gpio_to_irq(MX6SL_BRD_ELAN_INT),
+ }, {
+ I2C_BOARD_INFO("mma8450", 0x1c),
+ },
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("wm8962", 0x1a),
+ .platform_data = &wm8962_config_data,
+ },
+};
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ },
+};
+
+static struct mxc_dvfs_platform_data mx6sl_arm2_dvfscore_data = {
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+ .reg_id = "VDDCORE",
+ .soc_id = "VDDSOC",
+#else
+ .reg_id = "cpu_vddgp",
+ .soc_id = "cpu_vddsoc",
+ .pu_id = "cpu_vddvpu",
+#endif
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+};
+
+static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
+ .reserved_mem_size = SZ_32M,
+};
+
+void __init early_console_setup(unsigned long base, struct clk *clk);
+
+static inline void mx6_arm2_init_uart(void)
+{
+ imx6q_add_imx_uart(0, NULL); /* DEBUG UART1 */
+}
+
+static int mx6sl_arm2_fec_phy_init(struct phy_device *phydev)
+{
+ int val;
+
+ /* power on FEC phy and reset phy */
+ gpio_request(MX6_BRD_FEC_PWR_EN, "fec-pwr");
+ gpio_direction_output(MX6_BRD_FEC_PWR_EN, 0);
+ /* wait RC ms for hw reset */
+ msleep(1);
+ gpio_direction_output(MX6_BRD_FEC_PWR_EN, 1);
+
+ /* check phy power */
+ val = phy_read(phydev, 0x0);
+ if (val & BMCR_PDOWN) {
+ phy_write(phydev, 0x0, (val & ~BMCR_PDOWN));
+ }
+
+ return 0;
+}
+
+static struct fec_platform_data fec_data __initdata = {
+ .init = mx6sl_arm2_fec_phy_init,
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static int epdc_get_pins(void)
+{
+ int ret = 0;
+
+ /* Claim GPIOs for EPDC pins - used during power up/down */
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "epdc_d0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "epdc_d1");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "epdc_d2");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "epdc_d3");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "epdc_d4");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "epdc_d5");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "epdc_d6");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "epdc_d7");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "epdc_gdclk");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "epdc_gdsp");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "epdc_gdoe");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDRL, "epdc_gdrl");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "epdc_sdclk");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDOE, "epdc_sdoe");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "epdc_sdle");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "epdc_sdshr");
+ ret |= gpio_request(MX6SL_BRD_EPDC_BDR0, "epdc_bdr0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "epdc_sdce0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "epdc_sdce1");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE2, "epdc_sdce2");
+
+ return ret;
+}
+
+static void epdc_put_pins(void)
+{
+ gpio_free(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_7);
+ gpio_free(MX6SL_BRD_EPDC_GDCLK);
+ gpio_free(MX6SL_BRD_EPDC_GDSP);
+ gpio_free(MX6SL_BRD_EPDC_GDOE);
+ gpio_free(MX6SL_BRD_EPDC_GDRL);
+ gpio_free(MX6SL_BRD_EPDC_SDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDOE);
+ gpio_free(MX6SL_BRD_EPDC_SDLE);
+ gpio_free(MX6SL_BRD_EPDC_SDSHR);
+ gpio_free(MX6SL_BRD_EPDC_BDR0);
+ gpio_free(MX6SL_BRD_EPDC_SDCE0);
+ gpio_free(MX6SL_BRD_EPDC_SDCE1);
+ gpio_free(MX6SL_BRD_EPDC_SDCE2);
+}
+
+static void epdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable EPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_epdc_enable_pads));
+
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDSP);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDRL);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDLE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDSHR);
+ gpio_direction_input(MX6SL_BRD_EPDC_BDR0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE2);
+}
+
+static void epdc_disable_pins(void)
+{
+ /* Configure MUX settings for EPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_disable_pads, \
+ ARRAY_SIZE(mx6sl_brd_epdc_disable_pads));
+
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDRL, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_BDR0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE2, 0);
+}
+
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 30000000,
+ .left_margin = 8,
+ .right_margin = 164,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+};
+static struct fb_videomode e060scm_mode = {
+ .name = "E060SCM",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 26666667,
+ .left_margin = 8,
+ .right_margin = 100,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct imx_epdc_fb_mode panel_modes[] = {
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 465, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 9, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e060scm_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 419, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 5, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+
+static struct imx_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+ .get_pins = epdc_get_pins,
+ .put_pins = epdc_put_pins,
+ .enable_pins = epdc_enable_pins,
+ .disable_pins = epdc_disable_pins,
+};
+
+static int spdc_get_pins(void)
+{
+ int ret = 0;
+
+ /* Claim GPIOs for SPDC pins - used during power up/down */
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "SPDC_D0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "SPDC_D1");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "SPDC_D2");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "SPDC_D3");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "SPDC_D4");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "SPDC_D5");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "SPDC_D6");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "SPDC_D7");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "SIPIX_YOE");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_9, "SIPIX_PWR_RDY");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "SIPIX_YDIO");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "SIPIX_YCLK");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "SIPIX_XDIO");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "SIPIX_LD");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "SIPIX_SOE");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "SIPIX_XCLK");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_10, "SIPIX_SHD_N");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "SIPIX2_CE");
+
+ return ret;
+}
+
+static void spdc_put_pins(void)
+{
+ gpio_free(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_7);
+
+ gpio_free(MX6SL_BRD_EPDC_GDOE);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_free(MX6SL_BRD_EPDC_GDSP);
+ gpio_free(MX6SL_BRD_EPDC_GDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDSHR);
+ gpio_free(MX6SL_BRD_EPDC_SDLE);
+ gpio_free(MX6SL_BRD_EPDC_SDCE1);
+ gpio_free(MX6SL_BRD_EPDC_SDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_free(MX6SL_BRD_EPDC_SDCE0);
+}
+
+static void spdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable SPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_spdc_enable_pads));
+
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDSP);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDSHR);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDLE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE0);
+}
+
+static void spdc_disable_pins(void)
+{
+ /* Configure MUX settings for SPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_disable_pads, \
+ ARRAY_SIZE(mx6sl_brd_spdc_disable_pads));
+
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0);
+
+ gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_9, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_10, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0);
+}
+
+static struct imx_spdc_panel_init_set spdc_init_set = {
+ .yoe_pol = false,
+ .dual_gate = false,
+ .resolution = 0,
+ .ud = false,
+ .rl = false,
+ .data_filter_n = true,
+ .power_ready = true,
+ .rgbw_mode_enable = false,
+ .hburst_len_en = true,
+};
+
+static struct fb_videomode erk_1_4_a01 = {
+ .name = "ERK_1_4_A01",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 40000000,
+ .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct imx_spdc_fb_mode spdc_panel_modes[] = {
+ {
+ &erk_1_4_a01,
+ &spdc_init_set,
+ .wave_timing = "pvi"
+ },
+};
+
+static struct imx_spdc_fb_platform_data spdc_data = {
+ .spdc_mode = spdc_panel_modes,
+ .num_modes = ARRAY_SIZE(spdc_panel_modes),
+ .get_pins = spdc_get_pins,
+ .put_pins = spdc_put_pins,
+ .enable_pins = spdc_enable_pins,
+ .disable_pins = spdc_disable_pins,
+};
+
+static int __init early_use_spdc_sel(char *p)
+{
+ spdc_sel = 1;
+ return 0;
+}
+early_param("spdc", early_use_spdc_sel);
+
+static void setup_spdc(void)
+{
+ /* GPR0[8]: 0:EPDC, 1:SPDC */
+ if (spdc_sel)
+ mxc_iomux_set_gpr_register(0, 8, 1, 1);
+}
+
+static void imx6_arm2_usbotg_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(MX6_BRD_USBOTG1_PWR, 1);
+ else
+ gpio_set_value(MX6_BRD_USBOTG1_PWR, 0);
+}
+
+static void __init mx6_arm2_init_usb(void)
+{
+ int ret = 0;
+
+ imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR);
+
+ /* disable external charger detect,
+ * or it will affect signal quality at dp.
+ */
+
+ ret = gpio_request(MX6_BRD_USBOTG1_PWR, "usbotg-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO MX6_BRD_USBOTG1_PWR:%d\n", ret);
+ return;
+ }
+ gpio_direction_output(MX6_BRD_USBOTG1_PWR, 0);
+
+ ret = gpio_request(MX6_BRD_USBOTG2_PWR, "usbh1-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO MX6_BRD_USBOTG2_PWR:%d\n", ret);
+ return;
+ }
+ gpio_direction_output(MX6_BRD_USBOTG2_PWR, 1);
+
+ mx6_set_otghost_vbus_func(imx6_arm2_usbotg_vbus);
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_HSIC_DAT,
+ PAD_CTL_DDR_SEL_DDR3, PAD_CTL_DDR_SEL_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_HSIC_STROBE,
+ PAD_CTL_DDR_SEL_DDR3, PAD_CTL_DDR_SEL_MASK);
+
+ mx6_usb_h2_init();
+#endif
+}
+
+static struct platform_pwm_backlight_data mx6_arm2_pwm_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+static struct fb_videomode video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 32MHz */
+ "SEIKO-WVGA", 60, 800, 480, 29850, 89, 164, 23, 10, 10, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB24,
+ .mode_str = "SEIKO-WVGA",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+};
+
+static struct platform_device lcd_wvga_device = {
+ .name = "lcd_seiko",
+};
+
+static int mx6sl_arm2_keymap[] = {
+ KEY(0, 0, KEY_SELECT),
+ KEY(0, 1, KEY_BACK),
+ KEY(0, 2, KEY_F1),
+ KEY(0, 3, KEY_F2),
+
+ KEY(1, 0, KEY_F3),
+ KEY(1, 1, KEY_F4),
+ KEY(1, 2, KEY_POWER),
+ KEY(1, 3, KEY_MENU),
+
+ KEY(2, 0, KEY_PREVIOUS),
+ KEY(2, 1, KEY_NEXT),
+ KEY(2, 2, KEY_HOME),
+ KEY(2, 3, KEY_NEXT),
+
+ KEY(3, 0, KEY_UP),
+ KEY(3, 1, KEY_LEFT),
+ KEY(3, 2, KEY_RIGHT),
+ KEY(3, 3, KEY_DOWN),
+};
+
+static const struct matrix_keymap_data mx6sl_arm2_map_data __initconst = {
+ .keymap = mx6sl_arm2_keymap,
+ .keymap_size = ARRAY_SIZE(mx6sl_arm2_keymap),
+};
+static void __init elan_ts_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_elan_pads,
+ ARRAY_SIZE(mx6sl_brd_elan_pads));
+
+ /* ELAN Touchscreen */
+ gpio_request(MX6SL_BRD_ELAN_INT, "elan-interrupt");
+ gpio_direction_input(MX6SL_BRD_ELAN_INT);
+
+ gpio_request(MX6SL_BRD_ELAN_CE, "elan-cs");
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 0);
+
+ gpio_request(MX6SL_BRD_ELAN_RST, "elan-rst");
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 0);
+ mdelay(1);
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 1);
+}
+
+#define SNVS_LPCR 0x38
+static void mx6_snvs_poweroff(void)
+{
+ u32 value;
+ void __iomem *mx6_snvs_base = MX6_IO_ADDRESS(MX6Q_SNVS_BASE_ADDR);
+
+ value = readl(mx6_snvs_base + SNVS_LPCR);
+ /* set TOP and DP_EN bit */
+ writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mx6_arm2_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_pads,
+ ARRAY_SIZE(mx6sl_brd_pads));
+
+ elan_ts_init();
+
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+ gp_reg_id = mx6sl_arm2_dvfscore_data.reg_id;
+ soc_reg_id = mx6sl_arm2_dvfscore_data.soc_id;
+#else
+ gp_reg_id = mx6sl_arm2_dvfscore_data.reg_id;
+ soc_reg_id = mx6sl_arm2_dvfscore_data.soc_id;
+ pu_reg_id = mx6sl_arm2_dvfscore_data.pu_id;
+ mx6_cpu_regulator_init();
+#endif
+
+ imx6q_add_imx_snvs_rtc();
+
+ imx6q_add_imx_i2c(0, &mx6_arm2_i2c0_data);
+ imx6q_add_imx_i2c(1, &mx6_arm2_i2c1_data);
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ imx6q_add_imx_i2c(2, &mx6_arm2_i2c2_data);
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+
+ /* SPI */
+ imx6q_add_ecspi(0, &mx6_arm2_spi_data);
+ spi_device_init();
+
+ mx6sl_arm2_init_pfuze100(0);
+
+ imx6q_add_anatop_thermal_imx(1, &mx6sl_anatop_thermal_data);
+
+ mx6_arm2_init_uart();
+ /* get enet tx reference clk from FEC_REF_CLK pad.
+ * GPR1[14] = 0, GPR1[18:17] = 00
+ */
+ mxc_iomux_set_gpr_register(1, 14, 1, 0);
+ mxc_iomux_set_gpr_register(1, 17, 2, 0);
+
+ imx6_init_fec(fec_data);
+
+ platform_device_register(&arm2_vmmc_reg_devices);
+ imx6q_add_sdhci_usdhc_imx(0, &mx6_arm2_sd1_data);
+ imx6q_add_sdhci_usdhc_imx(1, &mx6_arm2_sd2_data);
+ imx6q_add_sdhci_usdhc_imx(2, &mx6_arm2_sd3_data);
+
+ mx6_arm2_init_usb();
+ imx6q_add_otp();
+ imx6q_add_mxc_pwm(0);
+ imx6q_add_mxc_pwm_backlight(0, &mx6_arm2_pwm_backlight_data);
+#ifdef CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF//[
+ imx6dl_add_imx_elcdif(&fb_data[0]);
+#endif //]CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF
+ gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on");
+ gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1);
+ mxc_register_device(&lcd_wvga_device, NULL);
+
+ imx6dl_add_imx_pxp();
+ imx6dl_add_imx_pxp_client();
+ mxc_register_device(&max17135_sensor_device, NULL);
+ setup_spdc();
+ if (!spdc_sel)
+ imx6dl_add_imx_epdc(&epdc_data);
+ else
+ imx6sl_add_imx_spdc(&spdc_data);
+ imx6q_add_dvfs_core(&mx6sl_arm2_dvfscore_data);
+
+ imx6q_init_audio();
+
+ imx6q_add_viim();
+ imx6q_add_imx2_wdt(0, NULL);
+
+ imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata);
+ imx6sl_add_imx_keypad(&mx6sl_arm2_map_data);
+ imx6q_add_busfreq();
+ imx6sl_add_dcp();
+ imx6sl_add_rngb();
+ imx6sl_add_imx_pxp_v4l2();
+
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
+
+ pm_power_off = mx6_snvs_poweroff;
+}
+
+extern void __iomem *twd_base;
+static void __init mx6_timer_init(void)
+{
+ struct clk *uart_clk;
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ mx6sl_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(UART1_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx6_timer_init,
+};
+
+static void __init mx6_arm2_reserve(void)
+{
+#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE)
+ phys_addr_t phys;
+
+ if (imx6q_gpu_pdata.reserved_mem_size) {
+ phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size,
+ SZ_4K, MEMBLOCK_ALLOC_ACCESSIBLE);
+ memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size);
+ imx6q_gpu_pdata.reserved_mem_base = phys;
+ }
+#endif
+}
+
+MACHINE_START(MX6SL_ARM2, "Freescale i.MX 6SoloLite Armadillo2 Board")
+ .boot_params = MX6SL_PHYS_OFFSET + 0x100,
+ .map_io = mx6_map_io,
+ .init_irq = mx6_init_irq,
+ .init_machine = mx6_arm2_init,
+ .timer = &mxc_timer,
+ .reserve = mx6_arm2_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-mx6/board-mx6sl_common.h b/arch/arm/mach-mx6/board-mx6sl_common.h
new file mode 100644
index 00000000..4eab0b35
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6sl_common.h
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _BOARD_MX6SL_COMMON_H
+#define _BOARD_MX6SL_COMMON_H
+#include <mach/iomux-mx6sl.h>
+
+#define MX6_BRD_LCD_RESET IMX_GPIO_NR(2, 19) /* LCD_REST */
+
+#define MX6_BRD_USBOTG1_PWR IMX_GPIO_NR(4, 0) /* KEY_COL4 */
+#define MX6_BRD_USBOTG2_PWR IMX_GPIO_NR(4, 2) /* KEY_COL5 */
+#define MX6_BRD_LCD_PWR_EN IMX_GPIO_NR(4, 3) /* KEY_ROW5 */
+#define MX6_BRD_SD1_WP IMX_GPIO_NR(4, 6) /* KEY_COL7 */
+#define MX6_BRD_SD1_CD IMX_GPIO_NR(4, 7) /* KEY_ROW7 */
+#define MX6_BRD_ECSPI1_CS0 IMX_GPIO_NR(4, 11) /* ECSPI1_SS0 */
+#define MX6_BRD_HEADPHONE_DET IMX_GPIO_NR(4, 19) /* FEC_RX_ER */
+#define MX6_BRD_SD2_WP IMX_GPIO_NR(4, 29) /* SD2_DAT6 */
+#define MX6_BRD_SD2_CD IMX_GPIO_NR(5, 0) /* SD2_DAT7 */
+#define MX6_BRD_SD3_CD IMX_GPIO_NR(3, 22) /* REF_CLK_32K */
+#define MX6_BRD_FEC_PWR_EN IMX_GPIO_NR(4, 21) /* FEC_TX_CLK */
+#define MX6_BRD_CHG_FLT IMX_GPIO_NR(4, 14) /* ECSPI2_MISO */
+#define MX6_BRD_CHG_UOK IMX_GPIO_NR(4, 13) /* ECSPI2_MOSI */
+#define MX6_BRD_CHG_DOK IMX_GPIO_NR(4, 13) /* ECSPI2_MOSI */
+#define MX6_BRD_CHG_STATUS IMX_GPIO_NR(4, 15) /* ECSPI2_SS0 */
+
+/* EPDC GPIO pins */
+#define MX6SL_BRD_EPDC_SDDO_0 IMX_GPIO_NR(1, 7)
+#define MX6SL_BRD_EPDC_SDDO_1 IMX_GPIO_NR(1, 8)
+#define MX6SL_BRD_EPDC_SDDO_2 IMX_GPIO_NR(1, 9)
+#define MX6SL_BRD_EPDC_SDDO_3 IMX_GPIO_NR(1, 10)
+#define MX6SL_BRD_EPDC_SDDO_4 IMX_GPIO_NR(1, 11)
+#define MX6SL_BRD_EPDC_SDDO_5 IMX_GPIO_NR(1, 12)
+#define MX6SL_BRD_EPDC_SDDO_6 IMX_GPIO_NR(1, 13)
+#define MX6SL_BRD_EPDC_SDDO_7 IMX_GPIO_NR(1, 14)
+#define MX6SL_BRD_EPDC_SDDO_8 IMX_GPIO_NR(1, 15)
+#define MX6SL_BRD_EPDC_SDDO_9 IMX_GPIO_NR(1, 16)
+#define MX6SL_BRD_EPDC_SDDO_10 IMX_GPIO_NR(1, 17)
+#define MX6SL_BRD_EPDC_SDDO_11 IMX_GPIO_NR(1, 18)
+#define MX6SL_BRD_EPDC_SDDO_12 IMX_GPIO_NR(1, 19)
+#define MX6SL_BRD_EPDC_SDDO_13 IMX_GPIO_NR(1, 20)
+#define MX6SL_BRD_EPDC_SDDO_14 IMX_GPIO_NR(1, 21)
+#define MX6SL_BRD_EPDC_SDDO_15 IMX_GPIO_NR(1, 22)
+#define MX6SL_BRD_EPDC_GDCLK IMX_GPIO_NR(1, 31)
+#define MX6SL_BRD_EPDC_GDSP IMX_GPIO_NR(2, 2)
+#define MX6SL_BRD_EPDC_GDOE IMX_GPIO_NR(2, 0)
+#define MX6SL_BRD_EPDC_GDRL IMX_GPIO_NR(2, 1)
+#define MX6SL_BRD_EPDC_SDCLK IMX_GPIO_NR(1, 23)
+#define MX6SL_BRD_EPDC_SDOE IMX_GPIO_NR(1, 25)
+#define MX6SL_BRD_EPDC_SDLE IMX_GPIO_NR(1, 24)
+#define MX6SL_BRD_EPDC_SDSHR IMX_GPIO_NR(1, 26)
+#define MX6SL_BRD_EPDC_PWRCOM IMX_GPIO_NR(2, 11)
+#define MX6SL_BRD_EPDC_PWRSTAT IMX_GPIO_NR(2, 13)
+#define MX6SL_BRD_EPDC_PWRCTRL0 IMX_GPIO_NR(2, 7)
+#define MX6SL_BRD_EPDC_PWRCTRL1 IMX_GPIO_NR(2, 8)
+#define MX6SL_BRD_EPDC_PWRCTRL2 IMX_GPIO_NR(2, 9)
+#define MX6SL_BRD_EPDC_PWRCTRL3 IMX_GPIO_NR(2, 10)
+#define MX6SL_BRD_EPDC_BDR0 IMX_GPIO_NR(2, 5)
+#define MX6SL_BRD_EPDC_BDR1 IMX_GPIO_NR(2, 6)
+#define MX6SL_BRD_EPDC_SDCE0 IMX_GPIO_NR(1, 27)
+#define MX6SL_BRD_EPDC_SDCE1 IMX_GPIO_NR(1, 28)
+#define MX6SL_BRD_EPDC_SDCE2 IMX_GPIO_NR(1, 29)
+#define MX6SL_BRD_EPDC_SDCE3 IMX_GPIO_NR(1, 30)
+#define MX6SL_BRD_EPDC_PMIC_WAKE IMX_GPIO_NR(2, 14) /* EPDC_PWRWAKEUP */
+#define MX6SL_BRD_EPDC_PMIC_INT IMX_GPIO_NR(2, 12) /* EPDC_PWRINT */
+#define MX6SL_BRD_EPDC_VCOM IMX_GPIO_NR(2, 3)
+/* ELAN TS */
+#define MX6SL_BRD_ELAN_CE IMX_GPIO_NR(2, 9)
+#define MX6SL_BRD_ELAN_INT IMX_GPIO_NR(2, 10)
+#define MX6SL_BRD_ELAN_RST IMX_GPIO_NR(4, 4)
+/* CSI */
+#define MX6SL_BRD_CSI_PWDN IMX_GPIO_NR(1, 25)
+#define MX6SL_BRD_CSI_RST IMX_GPIO_NR(1, 26)
+
+static iomux_v3_cfg_t mx6sl_brd_pads[] = {
+
+ /* AUDMUX */
+ MX6SL_PAD_AUD_TXC__AUDMUX_AUD3_TXC,
+ MX6SL_PAD_AUD_TXD__AUDMUX_AUD3_TXD,
+ MX6SL_PAD_AUD_TXFS__AUDMUX_AUD3_TXFS,
+ MX6SL_PAD_AUD_RXD__AUDMUX_AUD3_RXD,
+ MX6SL_PAD_AUD_MCLK__AUDMUX_AUDIO_CLK_OUT,
+
+ /* Audio Codec */
+ MX6SL_PAD_FEC_RX_ER__GPIO_4_19, /* HEADPHONE_DET */
+
+ /* SPDIF TX */
+ MX6SL_PAD_SD2_DAT4__SPDIF_OUT1,
+
+ /* UART1 */
+ MX6SL_PAD_UART1_RXD__UART1_RXD,
+ MX6SL_PAD_UART1_TXD__UART1_TXD,
+
+ /* USBOTG ID pin */
+#ifndef CONFIG_USB_ID_WAKEUP_ENABLE
+ MX6SL_PAD_EPDC_PWRCOM__ANATOP_USBOTG1_ID,
+#endif
+
+ /* USBOTG POWER GPIO */
+ MX6SL_PAD_KEY_COL4__GPIO_4_0,
+ MX6SL_PAD_KEY_COL5__GPIO_4_2,
+ /* USB OC pin */
+ MX6SL_PAD_KEY_ROW4__USB_USBOTG1_OC,
+ MX6SL_PAD_ECSPI2_SCLK__USB_USBOTG2_OC,
+ /* USB HSIC pin */
+ MX6SL_PAD_HSIC_STROBE__USB_H_STROBE,
+ MX6SL_PAD_HSIC_DAT__USB_H_DATA,
+
+ /* SD1 */
+ MX6SL_PAD_SD1_CLK__USDHC1_CLK_50MHZ,
+ MX6SL_PAD_SD1_CMD__USDHC1_CMD_50MHZ,
+ MX6SL_PAD_SD1_DAT0__USDHC1_DAT0_50MHZ,
+ MX6SL_PAD_SD1_DAT1__USDHC1_DAT1_50MHZ,
+ MX6SL_PAD_SD1_DAT2__USDHC1_DAT2_50MHZ,
+ MX6SL_PAD_SD1_DAT3__USDHC1_DAT3_50MHZ,
+ MX6SL_PAD_SD1_DAT4__USDHC1_DAT4_50MHZ,
+ MX6SL_PAD_SD1_DAT5__USDHC1_DAT5_50MHZ,
+ MX6SL_PAD_SD1_DAT6__USDHC1_DAT6_50MHZ,
+ MX6SL_PAD_SD1_DAT7__USDHC1_DAT7_50MHZ,
+ /* SD1 CD & WP */
+ MX6SL_PAD_KEY_ROW7__GPIO_4_7,
+ MX6SL_PAD_KEY_COL7__GPIO_4_6,
+ /* SD2 */
+ MX6SL_PAD_SD2_CLK__USDHC2_CLK_50MHZ,
+ MX6SL_PAD_SD2_CMD__USDHC2_CMD_50MHZ,
+ MX6SL_PAD_SD2_DAT0__USDHC2_DAT0_50MHZ,
+ MX6SL_PAD_SD2_DAT1__USDHC2_DAT1_50MHZ,
+ MX6SL_PAD_SD2_DAT2__USDHC2_DAT2_50MHZ,
+ MX6SL_PAD_SD2_DAT3__USDHC2_DAT3_50MHZ,
+ /* SD2 CD & WP */
+ MX6SL_PAD_SD2_DAT7__GPIO_5_0,
+ //MX6SL_PAD_SD2_DAT6__GPIO_4_29,
+ /* SD3 */
+ MX6SL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6SL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6SL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6SL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6SL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6SL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ /* SD3 CD */
+ MX6SL_PAD_REF_CLK_32K__GPIO_3_22,
+
+ /* FEC */
+ MX6SL_PAD_FEC_MDC__FEC_MDC,
+ MX6SL_PAD_FEC_MDIO__FEC_MDIO,
+ MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT, /* clock from anatop */
+ MX6SL_PAD_FEC_RX_ER__GPIO_4_19,
+ MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV,
+ MX6SL_PAD_FEC_RXD0__FEC_RDATA_0,
+ MX6SL_PAD_FEC_RXD1__FEC_RDATA_1,
+ MX6SL_PAD_FEC_TX_EN__FEC_TX_EN,
+ MX6SL_PAD_FEC_TXD0__FEC_TDATA_0,
+ MX6SL_PAD_FEC_TXD1__FEC_TDATA_1,
+ MX6SL_PAD_FEC_TX_CLK__GPIO_4_21, /* Phy power enable */
+
+ /* I2C */
+ MX6SL_PAD_I2C1_SCL__I2C1_SCL,
+ MX6SL_PAD_I2C1_SDA__I2C1_SDA,
+ MX6SL_PAD_I2C2_SCL__I2C2_SCL,
+ MX6SL_PAD_I2C2_SDA__I2C2_SDA,
+
+ /* ECSPI1 */
+ MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO,
+ MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI,
+ MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK,
+ MX6SL_PAD_ECSPI1_SS0__ECSPI1_SS0,
+ MX6SL_PAD_ECSPI1_SS0__GPIO_4_11, /* SS0 */
+
+ /* LCD */
+#if 0//[
+
+ MX6SL_PAD_LCD_CLK__LCDIF_CLK,
+ MX6SL_PAD_LCD_ENABLE__LCDIF_ENABLE,
+ MX6SL_PAD_LCD_HSYNC__LCDIF_HSYNC,
+ MX6SL_PAD_LCD_VSYNC__LCDIF_VSYNC,
+ MX6SL_PAD_LCD_RESET__LCDIF_RESET,
+ MX6SL_PAD_LCD_DAT0__LCDIF_DAT_0,
+ MX6SL_PAD_LCD_DAT1__LCDIF_DAT_1,
+ MX6SL_PAD_LCD_DAT2__LCDIF_DAT_2,
+ MX6SL_PAD_LCD_DAT3__LCDIF_DAT_3,
+ MX6SL_PAD_LCD_DAT4__LCDIF_DAT_4,
+ MX6SL_PAD_LCD_DAT5__LCDIF_DAT_5,
+ MX6SL_PAD_LCD_DAT6__LCDIF_DAT_6,
+ MX6SL_PAD_LCD_DAT7__LCDIF_DAT_7,
+ MX6SL_PAD_LCD_DAT8__LCDIF_DAT_8,
+ MX6SL_PAD_LCD_DAT9__LCDIF_DAT_9,
+ MX6SL_PAD_LCD_DAT10__LCDIF_DAT_10,
+ MX6SL_PAD_LCD_DAT11__LCDIF_DAT_11,
+ MX6SL_PAD_LCD_DAT12__LCDIF_DAT_12,
+ MX6SL_PAD_LCD_DAT13__LCDIF_DAT_13,
+ MX6SL_PAD_LCD_DAT14__LCDIF_DAT_14,
+ MX6SL_PAD_LCD_DAT15__LCDIF_DAT_15,
+ MX6SL_PAD_LCD_DAT16__LCDIF_DAT_16,
+ MX6SL_PAD_LCD_DAT17__LCDIF_DAT_17,
+ MX6SL_PAD_LCD_DAT18__LCDIF_DAT_18,
+ MX6SL_PAD_LCD_DAT19__LCDIF_DAT_19,
+ MX6SL_PAD_LCD_DAT20__LCDIF_DAT_20,
+ MX6SL_PAD_LCD_DAT21__LCDIF_DAT_21,
+ MX6SL_PAD_LCD_DAT22__LCDIF_DAT_22,
+ MX6SL_PAD_LCD_DAT23__LCDIF_DAT_23,
+#else//][!
+
+ MX6SL_PAD_LCD_CLK__GPIO_2_15,
+ MX6SL_PAD_LCD_ENABLE__GPIO_2_16,
+ MX6SL_PAD_LCD_HSYNC__GPIO_2_17,
+ MX6SL_PAD_LCD_VSYNC__GPIO_2_18,
+ MX6SL_PAD_LCD_RESET__GPIO_2_19,
+
+ MX6SL_PAD_LCD_DAT0__GPIO_2_20,
+ MX6SL_PAD_LCD_DAT1__GPIO_2_21,
+ MX6SL_PAD_LCD_DAT2__GPIO_2_22,
+ MX6SL_PAD_LCD_DAT3__GPIO_2_23,
+ MX6SL_PAD_LCD_DAT4__GPIO_2_24,
+ MX6SL_PAD_LCD_DAT5__GPIO_2_25,
+ MX6SL_PAD_LCD_DAT6__GPIO_2_26,
+ MX6SL_PAD_LCD_DAT8__GPIO_2_28,
+ MX6SL_PAD_LCD_DAT9__GPIO_2_29,
+ MX6SL_PAD_LCD_DAT10__GPIO_2_30,
+ MX6SL_PAD_LCD_DAT11__GPIO_2_31,
+ MX6SL_PAD_LCD_DAT12__GPIO_3_0,
+ MX6SL_PAD_LCD_DAT13__GPIO_3_1,
+ MX6SL_PAD_LCD_DAT14__GPIO_3_2,
+ MX6SL_PAD_LCD_DAT15__GPIO_3_3,
+ MX6SL_PAD_LCD_DAT16__GPIO_3_4,
+ MX6SL_PAD_LCD_DAT17__GPIO_3_5,
+ MX6SL_PAD_LCD_DAT18__GPIO_3_6,
+ MX6SL_PAD_LCD_DAT19__GPIO_3_7,
+ MX6SL_PAD_LCD_DAT20__GPIO_3_8,
+ MX6SL_PAD_LCD_DAT21__GPIO_3_9,
+ MX6SL_PAD_LCD_DAT22__GPIO_3_10,
+ MX6SL_PAD_LCD_DAT23__GPIO_3_11,
+
+#endif //]
+
+ /* LCD brightness */
+ MX6SL_PAD_PWM1__PWM1_PWMO,
+ /* LCD power on */
+ //MX6SL_PAD_KEY_ROW5__GPIO_4_3,
+
+ /* keypad on E-Ink add-on board */
+ MX6SL_PAD_KEY_COL0__KPP_COL_0,
+ MX6SL_PAD_KEY_COL1__KPP_COL_1,
+ MX6SL_PAD_KEY_COL2__KPP_COL_2,
+ MX6SL_PAD_KEY_COL3__KPP_COL_3,
+ MX6SL_PAD_KEY_ROW0__KPP_ROW_0,
+ MX6SL_PAD_KEY_ROW1__KPP_ROW_1,
+ MX6SL_PAD_KEY_ROW2__KPP_ROW_2,
+ MX6SL_PAD_KEY_ROW3__KPP_ROW_3,
+
+ /* WDOG */
+ MX6SL_PAD_WDOG_B__WDOG1_WDOG_B,
+
+ /* Charge */
+ MX6SL_PAD_ECSPI2_MISO__GPIO_4_14, /* CHG_FLT */
+ MX6SL_PAD_ECSPI2_SS0__GPIO_4_15, /* CHG_STATUS */
+ MX6SL_PAD_ECSPI2_MOSI__GPIO_4_13, /* CHG_UOK ,CHG_DOK*/
+};
+
+static iomux_v3_cfg_t mx6sl_brd_epdc_enable_pads[] = {
+ /* EPDC */
+ MX6SL_PAD_EPDC_D0__EPDC_SDDO_0,
+ MX6SL_PAD_EPDC_D1__EPDC_SDDO_1,
+ MX6SL_PAD_EPDC_D2__EPDC_SDDO_2,
+ MX6SL_PAD_EPDC_D3__EPDC_SDDO_3,
+ MX6SL_PAD_EPDC_D4__EPDC_SDDO_4,
+ MX6SL_PAD_EPDC_D5__EPDC_SDDO_5,
+ MX6SL_PAD_EPDC_D6__EPDC_SDDO_6,
+ MX6SL_PAD_EPDC_D7__EPDC_SDDO_7,
+ MX6SL_PAD_EPDC_D8__EPDC_SDDO_8,
+ MX6SL_PAD_EPDC_D9__EPDC_SDDO_9,
+ MX6SL_PAD_EPDC_D10__EPDC_SDDO_10,
+ MX6SL_PAD_EPDC_D11__EPDC_SDDO_11,
+ MX6SL_PAD_EPDC_D12__EPDC_SDDO_12,
+ MX6SL_PAD_EPDC_D13__EPDC_SDDO_13,
+ MX6SL_PAD_EPDC_D14__EPDC_SDDO_14,
+ MX6SL_PAD_EPDC_D15__EPDC_SDDO_15,
+
+ MX6SL_PAD_EPDC_GDCLK__EPDC_GDCLK,
+ MX6SL_PAD_EPDC_GDSP__EPDC_GDSP,
+ MX6SL_PAD_EPDC_GDOE__EPDC_GDOE,
+ MX6SL_PAD_EPDC_GDRL__EPDC_GDRL,
+ MX6SL_PAD_EPDC_SDCLK__EPDC_SDCLK,
+ MX6SL_PAD_EPDC_SDOE__EPDC_SDOE,
+ MX6SL_PAD_EPDC_SDLE__EPDC_SDLE,
+ MX6SL_PAD_EPDC_SDSHR__EPDC_SDSHR,
+ MX6SL_PAD_EPDC_BDR0__EPDC_BDR_0,
+ MX6SL_PAD_EPDC_SDCE0__EPDC_SDCE_0,
+ MX6SL_PAD_EPDC_SDCE1__EPDC_SDCE_1,
+// MX6SL_PAD_EPDC_SDCE2__EPDC_SDCE_2,
+
+ /* EPD PMIC (Maxim 17135) pins */
+// MX6SL_PAD_EPDC_VCOM0__GPIO_2_3,
+// MX6SL_PAD_EPDC_PWRSTAT__GPIO_2_13,
+// MX6SL_PAD_EPDC_PWRCTRL0__GPIO_2_7,
+// MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14,
+};
+
+static iomux_v3_cfg_t mx6sl_brd_epdc_disable_pads[] = {
+ /* EPDC */
+ MX6SL_PAD_EPDC_D0__GPIO_1_7,
+ MX6SL_PAD_EPDC_D1__GPIO_1_8,
+ MX6SL_PAD_EPDC_D2__GPIO_1_9,
+ MX6SL_PAD_EPDC_D3__GPIO_1_10,
+ MX6SL_PAD_EPDC_D4__GPIO_1_11,
+ MX6SL_PAD_EPDC_D5__GPIO_1_12,
+ MX6SL_PAD_EPDC_D6__GPIO_1_13,
+ MX6SL_PAD_EPDC_D7__GPIO_1_14,
+ MX6SL_PAD_EPDC_D8__GPIO_1_15,
+ MX6SL_PAD_EPDC_D9__GPIO_1_16,
+ MX6SL_PAD_EPDC_D10__GPIO_1_17,
+ MX6SL_PAD_EPDC_D11__GPIO_1_18,
+ MX6SL_PAD_EPDC_D12__GPIO_1_19,
+ MX6SL_PAD_EPDC_D13__GPIO_1_20,
+ MX6SL_PAD_EPDC_D14__GPIO_1_21,
+ MX6SL_PAD_EPDC_D15__GPIO_1_22,
+
+ MX6SL_PAD_EPDC_GDCLK__GPIO_1_31,
+ MX6SL_PAD_EPDC_GDSP__GPIO_2_2,
+ MX6SL_PAD_EPDC_GDOE__GPIO_2_0,
+ MX6SL_PAD_EPDC_GDRL__GPIO_2_1,
+ MX6SL_PAD_EPDC_SDCLK__GPIO_1_23,
+ MX6SL_PAD_EPDC_SDOE__GPIO_1_25,
+ MX6SL_PAD_EPDC_SDLE__GPIO_1_24,
+ MX6SL_PAD_EPDC_SDSHR__GPIO_1_26,
+ MX6SL_PAD_EPDC_BDR0__GPIO_2_5,
+ MX6SL_PAD_EPDC_SDCE0__GPIO_1_27,
+ MX6SL_PAD_EPDC_SDCE1__GPIO_1_28,
+// MX6SL_PAD_EPDC_SDCE2__GPIO_1_29,
+
+ /* EPD PMIC (Maxim 17135) pins */
+// MX6SL_PAD_EPDC_VCOM0__GPIO_2_3,
+// MX6SL_PAD_EPDC_PWRSTAT__GPIO_2_13,
+// MX6SL_PAD_EPDC_PWRCTRL0__GPIO_2_7,
+// MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14,
+};
+
+static iomux_v3_cfg_t mx6sl_brd_spdc_enable_pads[] = {
+ /* SPDC data*/
+ MX6SL_PAD_EPDC_D0__TCON_E_DATA_0,
+ MX6SL_PAD_EPDC_D1__TCON_E_DATA_1,
+ MX6SL_PAD_EPDC_D2__TCON_E_DATA_2,
+ MX6SL_PAD_EPDC_D3__TCON_E_DATA_3,
+ MX6SL_PAD_EPDC_D4__TCON_E_DATA_4,
+ MX6SL_PAD_EPDC_D5__TCON_E_DATA_5,
+ MX6SL_PAD_EPDC_D6__TCON_E_DATA_6,
+ MX6SL_PAD_EPDC_D7__TCON_E_DATA_7,
+
+ MX6SL_PAD_EPDC_GDOE__TCON_YOEL, /* AUO panel SIPIX_YOE */
+
+ MX6SL_PAD_EPDC_D9__TCON_E_DATA_9, /* AUO panel SIPIX_PWR_RDY*/
+
+// MX6SL_PAD_EPDC_SDCE2__TCON_YDIOUR, /* AUO panel SIPIX_YDIO */
+// MX6SL_PAD_EPDC_SDCE3__TCON_YDIODR, /* AUO panel SIPIX_YDIO */
+ MX6SL_PAD_EPDC_GDRL__TCON_YDIOUL, /* AUO panel SIPIX_YDIO */
+ MX6SL_PAD_EPDC_GDSP__TCON_YDIODL, /* SIPIX_YDIO/SIPIX2_SPV */
+
+ MX6SL_PAD_EPDC_GDCLK__TCON_YCKL, /* SIPIX_YCLK/SIPIX2_CKV */
+
+ MX6SL_PAD_EPDC_SDSHR__TCON_XDIOR, /* AUO panel SIPIX_XDIO */
+ MX6SL_PAD_EPDC_SDOE__TCON_XDIOL, /* SIPIX_XDIO/SIPIX2_OE */
+
+ MX6SL_PAD_EPDC_SDLE__TCON_LD, /* SIPIX_LD/SIPIX2_LE */
+
+ MX6SL_PAD_EPDC_SDCE1__TCON_YOER, /* AUO panel SIPIX_SOE */
+ MX6SL_PAD_EPDC_BDR0__TCON_RL, /* AUO panel SIPIX_SOE */
+ MX6SL_PAD_EPDC_BDR1__TCON_UD, /* AUO panel SIPIX_SOE */
+
+ MX6SL_PAD_EPDC_SDCLK__TCON_CL, /* SIPIX_XCLK/SIPIX2_CL */
+
+ MX6SL_PAD_EPDC_D10__TCON_E_DATA_10, /* AUO panel SIPIX_SHD_N */
+
+ MX6SL_PAD_EPDC_SDCE0__TCON_YCKR, /* LG panel SIPIX2_CE */
+
+ /* EPD PMIC (Maxim 17135) pins */
+ MX6SL_PAD_EPDC_VCOM0__GPIO_2_3, /* PMICA_CEN */
+ MX6SL_PAD_EPDC_PWRSTAT__GPIO_2_13,
+ MX6SL_PAD_EPDC_PWRCTRL0__GPIO_2_7,
+ MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14,
+};
+
+static iomux_v3_cfg_t mx6sl_brd_spdc_disable_pads[] = {
+ MX6SL_PAD_EPDC_D0__GPIO_1_7,
+ MX6SL_PAD_EPDC_D1__GPIO_1_8,
+ MX6SL_PAD_EPDC_D2__GPIO_1_9,
+ MX6SL_PAD_EPDC_D3__GPIO_1_10,
+ MX6SL_PAD_EPDC_D4__GPIO_1_11,
+ MX6SL_PAD_EPDC_D5__GPIO_1_12,
+ MX6SL_PAD_EPDC_D6__GPIO_1_13,
+ MX6SL_PAD_EPDC_D7__GPIO_1_14,
+
+ MX6SL_PAD_EPDC_SDCE1__GPIO_1_28,
+ MX6SL_PAD_EPDC_GDOE__GPIO_2_0,
+ MX6SL_PAD_EPDC_D9__GPIO_1_16,
+// MX6SL_PAD_EPDC_SDCE2__GPIO_1_29,
+// MX6SL_PAD_EPDC_SDCE3__GPIO_1_30,
+ MX6SL_PAD_EPDC_GDRL__GPIO_2_1,
+ MX6SL_PAD_EPDC_GDSP__GPIO_2_2,
+ MX6SL_PAD_EPDC_GDCLK__GPIO_1_31,
+ MX6SL_PAD_EPDC_SDSHR__GPIO_1_26,
+ MX6SL_PAD_EPDC_SDOE__GPIO_1_25,
+ MX6SL_PAD_EPDC_SDLE__GPIO_1_24,
+ MX6SL_PAD_EPDC_SDCE1__GPIO_1_28,
+ MX6SL_PAD_EPDC_BDR0__GPIO_2_5,
+ MX6SL_PAD_EPDC_BDR1__GPIO_2_6,
+ MX6SL_PAD_EPDC_SDCLK__GPIO_1_23,
+ MX6SL_PAD_EPDC_D10__GPIO_1_17,
+ MX6SL_PAD_EPDC_SDCE0__GPIO_1_27,
+
+ /* EPD PMIC (Maxim 17135) pins */
+ MX6SL_PAD_EPDC_VCOM0__GPIO_2_3,
+ MX6SL_PAD_EPDC_PWRSTAT__GPIO_2_13,
+ MX6SL_PAD_EPDC_PWRCTRL0__GPIO_2_7,
+ MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14,
+};
+
+static iomux_v3_cfg_t mx6sl_brd_elan_pads[] = {
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10, /* INT */
+ MX6SL_PAD_EPDC_PWRCTRL2__GPIO_2_9, /* CE */
+ MX6SL_PAD_KEY_COL6__GPIO_4_4, /* RST */
+};
+
+static iomux_v3_cfg_t suspend_enter_pads[] = {
+ /* Audio pads. */
+ MX6SL_PAD_AUD_MCLK__GPIO_1_6,
+ MX6SL_PAD_AUD_RXC__GPIO_1_1,
+ MX6SL_PAD_AUD_RXD__GPIO_1_2,
+ MX6SL_PAD_AUD_RXFS__GPIO_1_0,
+ MX6SL_PAD_AUD_TXC__GPIO_1_3,
+ MX6SL_PAD_AUD_TXD__GPIO_1_5,
+ MX6SL_PAD_AUD_TXFS__GPIO_1_4,
+ /* ECSPI pads. */
+ MX6SL_PAD_ECSPI1_MISO__GPIO_4_10,
+ MX6SL_PAD_ECSPI1_MOSI__GPIO_4_9,
+ MX6SL_PAD_ECSPI1_SCLK__GPIO_4_8,
+ MX6SL_PAD_ECSPI1_SS0__GPIO_4_11,
+ MX6SL_PAD_ECSPI2_SCLK__GPIO_4_12,
+ /* FEC pad*/
+ MX6SL_PAD_FEC_CRS_DV__GPIO_4_25,
+ MX6SL_PAD_FEC_MDC__GPIO_4_23,
+ MX6SL_PAD_FEC_MDIO__GPIO_4_20,
+ MX6SL_PAD_FEC_REF_CLK__GPIO_4_26,
+ MX6SL_PAD_FEC_RXD0__GPIO_4_17,
+ MX6SL_PAD_FEC_RXD1__GPIO_4_18,
+ MX6SL_PAD_FEC_TXD0__GPIO_4_24,
+ MX6SL_PAD_FEC_TXD1__GPIO_4_16,
+ MX6SL_PAD_FEC_TX_CLK__GPIO_4_21,
+ MX6SL_PAD_FEC_TX_EN__GPIO_4_22,
+ /* I2C pads */
+ MX6SL_PAD_I2C1_SCL__GPIO_3_12,
+ MX6SL_PAD_I2C1_SDA__GPIO_3_13,
+ MX6SL_PAD_I2C2_SCL__GPIO_3_14,
+ MX6SL_PAD_I2C2_SDA__GPIO_3_15,
+ /* LCD pads*/
+ MX6SL_PAD_LCD_CLK__GPIO_2_15,
+ MX6SL_PAD_LCD_DAT0__GPIO_2_20,
+ MX6SL_PAD_LCD_DAT1__GPIO_2_21,
+ MX6SL_PAD_LCD_DAT2__GPIO_2_22,
+ MX6SL_PAD_LCD_DAT3__GPIO_2_23,
+ MX6SL_PAD_LCD_DAT4__GPIO_2_24,
+ MX6SL_PAD_LCD_DAT5__GPIO_2_25,
+ MX6SL_PAD_LCD_DAT10__GPIO_2_30,
+ MX6SL_PAD_LCD_DAT11__GPIO_2_31,
+ MX6SL_PAD_LCD_DAT12__GPIO_3_0,
+ MX6SL_PAD_LCD_DAT13__GPIO_3_1,
+ MX6SL_PAD_LCD_DAT14__GPIO_3_2,
+ MX6SL_PAD_LCD_DAT15__GPIO_3_3,
+ MX6SL_PAD_LCD_DAT16__GPIO_3_4,
+ MX6SL_PAD_LCD_DAT17__GPIO_3_5,
+ MX6SL_PAD_LCD_DAT18__GPIO_3_6,
+ MX6SL_PAD_LCD_DAT19__GPIO_3_7,
+ MX6SL_PAD_LCD_DAT20__GPIO_3_8,
+ MX6SL_PAD_LCD_DAT21__GPIO_3_9,
+ MX6SL_PAD_LCD_DAT22__GPIO_3_10,
+ MX6SL_PAD_LCD_DAT23__GPIO_3_11,
+ /* PWM pads */
+ MX6SL_PAD_PWM1__GPIO_3_23,
+ /* SD pads. */
+ MX6SL_PAD_SD1_CLK__GPIO_5_15,
+ MX6SL_PAD_SD1_CMD__GPIO_5_14,
+ MX6SL_PAD_SD1_DAT0__GPIO_5_11,
+ MX6SL_PAD_SD1_DAT1__GPIO_5_8,
+ MX6SL_PAD_SD1_DAT2__GPIO_5_13,
+ MX6SL_PAD_SD1_DAT3__GPIO_5_6,
+ MX6SL_PAD_SD1_DAT4__GPIO_5_12,
+ MX6SL_PAD_SD1_DAT5__GPIO_5_9,
+ MX6SL_PAD_SD1_DAT6__GPIO_5_7,
+ MX6SL_PAD_SD1_DAT7__GPIO_5_10,
+
+ MX6SL_PAD_SD2_CLK__GPIO_5_5,
+ MX6SL_PAD_SD2_CMD__GPIO_5_4,
+ MX6SL_PAD_SD2_DAT0__GPIO_5_1,
+ MX6SL_PAD_SD2_DAT1__GPIO_4_30,
+ MX6SL_PAD_SD2_DAT2__GPIO_5_3,
+ MX6SL_PAD_SD2_DAT3__GPIO_4_28,
+ MX6SL_PAD_SD2_DAT4__GPIO_5_2,
+ MX6SL_PAD_SD2_DAT5__GPIO_4_31,
+
+ MX6SL_PAD_SD3_CLK__GPIO_5_18,
+ MX6SL_PAD_SD3_CMD__GPIO_5_21,
+ MX6SL_PAD_SD3_DAT0__GPIO_5_19,
+ MX6SL_PAD_SD3_DAT1__GPIO_5_20,
+ MX6SL_PAD_SD3_DAT2__GPIO_5_16,
+ MX6SL_PAD_SD3_DAT3__GPIO_5_17,
+
+ /* USBOTG ID pin */
+#ifndef CONFIG_USB_ID_WAKEUP_ENABLE
+ MX6SL_PAD_EPDC_PWRCOM__GPIO_2_11,
+#endif
+ MX6SL_PAD_HSIC_STROBE__GPIO_3_20,
+ MX6SL_PAD_HSIC_DAT__GPIO_3_19,
+
+ /* Key row/column */
+ MX6SL_PAD_KEY_COL0__GPIO_3_24,
+ MX6SL_PAD_KEY_COL1__GPIO_3_26,
+ MX6SL_PAD_KEY_COL2__GPIO_3_28,
+ MX6SL_PAD_KEY_COL3__GPIO_3_30,
+ MX6SL_PAD_KEY_COL6__GPIO_4_4,
+ MX6SL_PAD_KEY_COL7__GPIO_4_6,
+ MX6SL_PAD_KEY_ROW0__GPIO_3_25,
+ MX6SL_PAD_KEY_ROW1__GPIO_3_27,
+ MX6SL_PAD_KEY_ROW2__GPIO_3_29,
+ MX6SL_PAD_KEY_ROW3__GPIO_3_31,
+ MX6SL_PAD_KEY_ROW4__GPIO_4_1,
+ MX6SL_PAD_KEY_ROW5__GPIO_4_3,
+ MX6SL_PAD_KEY_ROW6__GPIO_4_5,
+};
+
+static iomux_v3_cfg_t suspend_exit_pads[ARRAY_SIZE(suspend_enter_pads)];
+
+#define MX6SL_USDHC_8BIT_PAD_SETTING(id, speed) \
+mx6sl_sd##id##_##speed##mhz[] = { \
+ MX6SL_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \
+}
+#define MX6SL_USDHC_4BIT_PAD_SETTING(id, speed) \
+mx6sl_sd##id##_##speed##mhz[] = { \
+ MX6SL_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
+ MX6SL_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
+}
+
+
+static iomux_v3_cfg_t MX6SL_USDHC_8BIT_PAD_SETTING(1, 50);
+static iomux_v3_cfg_t MX6SL_USDHC_8BIT_PAD_SETTING(1, 100);
+static iomux_v3_cfg_t MX6SL_USDHC_8BIT_PAD_SETTING(1, 200);
+static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(2, 50);
+static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(2, 100);
+static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(2, 200);
+static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(3, 50);
+static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(3, 100);
+static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(3, 200);
+
+#endif
diff --git a/arch/arm/mach-mx6/board-mx6sl_evk.c b/arch/arm/mach-mx6/board-mx6sl_evk.c
new file mode 100644
index 00000000..4d09153d
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6sl_evk.c
@@ -0,0 +1,1672 @@
+/*
+ * Copyright (C) 2012 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 <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/etherdevice.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max17135.h>
+#include <sound/wm8962.h>
+#include <sound/pcm.h>
+#include <linux/power/sabresd_battery.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/memory.h>
+#include <mach/iomux-mx6sl.h>
+#include <mach/imx-uart.h>
+#include <mach/viv_gpu.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "usb.h"
+#include "devices-imx6q.h"
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "board-mx6sl_common.h"
+
+
+static int spdc_sel;
+static int max17135_regulator_init(struct max17135 *max17135);
+struct clk *extern_audio_root;
+
+extern char *gp_reg_id;
+extern char *soc_reg_id;
+extern char *pu_reg_id;
+extern int __init mx6sl_evk_init_pfuze100(u32 int_gpio);
+
+static int csi_enabled;
+
+static iomux_v3_cfg_t mx6sl_brd_csi_enable_pads[] = {
+ MX6SL_PAD_EPDC_GDRL__CSI_MCLK,
+ MX6SL_PAD_EPDC_SDCE3__I2C3_SDA,
+ MX6SL_PAD_EPDC_SDCE2__I2C3_SCL,
+ MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK,
+ MX6SL_PAD_EPDC_GDSP__CSI_VSYNC,
+ MX6SL_PAD_EPDC_GDOE__CSI_HSYNC,
+ MX6SL_PAD_EPDC_SDLE__CSI_D_9,
+ MX6SL_PAD_EPDC_SDCLK__CSI_D_8,
+ MX6SL_PAD_EPDC_D7__CSI_D_7,
+ MX6SL_PAD_EPDC_D6__CSI_D_6,
+ MX6SL_PAD_EPDC_D5__CSI_D_5,
+ MX6SL_PAD_EPDC_D4__CSI_D_4,
+ MX6SL_PAD_EPDC_D3__CSI_D_3,
+ MX6SL_PAD_EPDC_D2__CSI_D_2,
+ MX6SL_PAD_EPDC_D1__CSI_D_1,
+ MX6SL_PAD_EPDC_D0__CSI_D_0,
+
+ MX6SL_PAD_EPDC_SDSHR__GPIO_1_26, /* CMOS_RESET_B GPIO */
+ MX6SL_PAD_EPDC_SDOE__GPIO_1_25, /* CMOS_PWDN GPIO */
+};
+
+/* uart2 pins */
+static iomux_v3_cfg_t mx6sl_uart2_pads[] = {
+ MX6SL_PAD_SD2_DAT5__UART2_TXD,
+ MX6SL_PAD_SD2_DAT4__UART2_RXD,
+ MX6SL_PAD_SD2_DAT6__UART2_RTS,
+ MX6SL_PAD_SD2_DAT7__UART2_CTS,
+};
+
+enum sd_pad_mode {
+ SD_PAD_MODE_LOW_SPEED,
+ SD_PAD_MODE_MED_SPEED,
+ SD_PAD_MODE_HIGH_SPEED,
+};
+
+static int __init csi_setup(char *__unused)
+{
+ csi_enabled = 1;
+ return 1;
+}
+__setup("csi", csi_setup);
+
+static int plt_sd_pad_change(unsigned int index, int clock)
+{
+ /* LOW speed is the default state of SD pads */
+ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
+
+ iomux_v3_cfg_t *sd_pads_200mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_100mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_50mhz = NULL;
+
+ u32 sd_pads_200mhz_cnt;
+ u32 sd_pads_100mhz_cnt;
+ u32 sd_pads_50mhz_cnt;
+
+ switch (index) {
+ case 0:
+ sd_pads_200mhz = mx6sl_sd1_200mhz;
+ sd_pads_100mhz = mx6sl_sd1_100mhz;
+ sd_pads_50mhz = mx6sl_sd1_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd1_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd1_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd1_50mhz);
+ break;
+ case 1:
+ sd_pads_200mhz = mx6sl_sd2_200mhz;
+ sd_pads_100mhz = mx6sl_sd2_100mhz;
+ sd_pads_50mhz = mx6sl_sd2_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd2_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd2_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd2_50mhz);
+ break;
+ case 2:
+ sd_pads_200mhz = mx6sl_sd3_200mhz;
+ sd_pads_100mhz = mx6sl_sd3_100mhz;
+ sd_pads_50mhz = mx6sl_sd3_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd3_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd3_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd3_50mhz);
+ break;
+ default:
+ printk(KERN_ERR "no such SD host controller index %d\n", index);
+ return -EINVAL;
+ }
+
+ if (clock > 100000000) {
+ if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_200mhz);
+ pad_mode = SD_PAD_MODE_HIGH_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
+ sd_pads_200mhz_cnt);
+ } else if (clock > 52000000) {
+ if (pad_mode == SD_PAD_MODE_MED_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_100mhz);
+ pad_mode = SD_PAD_MODE_MED_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
+ sd_pads_100mhz_cnt);
+ } else {
+ if (pad_mode == SD_PAD_MODE_LOW_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_50mhz);
+ pad_mode = SD_PAD_MODE_LOW_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
+ sd_pads_50mhz_cnt);
+ }
+}
+
+static const struct esdhc_platform_data mx6_evk_sd1_data __initconst = {
+ .cd_gpio = MX6_BRD_SD1_CD,
+ .wp_gpio = MX6_BRD_SD1_WP,
+ .support_8bit = 1,
+ .support_18v = 1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+static const struct esdhc_platform_data mx6_evk_sd2_data __initconst = {
+ .cd_gpio = MX6_BRD_SD2_CD,
+ .wp_gpio = MX6_BRD_SD2_WP,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .support_18v = 1,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+static const struct esdhc_platform_data mx6_evk_sd3_data __initconst = {
+ .cd_gpio = MX6_BRD_SD3_CD,
+ .wp_gpio = -1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .support_18v = 1,
+ .platform_pad_change = plt_sd_pad_change,
+};
+
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+static struct regulator_consumer_supply evk_vmmc_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"),
+};
+
+static struct regulator_init_data evk_vmmc_init = {
+ .num_consumer_supplies = ARRAY_SIZE(evk_vmmc_consumers),
+ .consumer_supplies = evk_vmmc_consumers,
+};
+
+static struct fixed_voltage_config evk_vmmc_reg_config = {
+ .supply_name = "vmmc",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &evk_vmmc_init,
+};
+
+static struct platform_device evk_vmmc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &evk_vmmc_reg_config,
+ },
+};
+
+static struct regulator_consumer_supply display_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "DISPLAY",
+ },
+};
+
+static struct regulator_consumer_supply vcom_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "VCOM",
+ },
+};
+
+static struct regulator_consumer_supply v3p3_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "V3P3",
+ },
+};
+
+static struct regulator_init_data max17135_init_data[] = {
+ {
+ .constraints = {
+ .name = "DISPLAY",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(display_consumers),
+ .consumer_supplies = display_consumers,
+ }, {
+ .constraints = {
+ .name = "GVDD",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "GVEE",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINN",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINP",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "VCOM",
+ .min_uV = mV_to_uV(-4325),
+ .max_uV = mV_to_uV(-500),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcom_consumers),
+ .consumer_supplies = vcom_consumers,
+ }, {
+ .constraints = {
+ .name = "VNEG",
+ .min_uV = V_to_uV(-15),
+ .max_uV = V_to_uV(-15),
+ },
+ }, {
+ .constraints = {
+ .name = "VPOS",
+ .min_uV = V_to_uV(15),
+ .max_uV = V_to_uV(15),
+ },
+ }, {
+ .constraints = {
+ .name = "V3P3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(v3p3_consumers),
+ .consumer_supplies = v3p3_consumers,
+ },
+};
+
+static const struct anatop_thermal_platform_data
+ mx6sl_anatop_thermal_data __initconst = {
+ .name = "anatop_thermal",
+ };
+
+static struct platform_device max17135_sensor_device = {
+ .name = "max17135_sensor",
+ .id = 0,
+};
+
+static struct max17135_platform_data max17135_pdata __initdata = {
+ .vneg_pwrup = 1,
+ .gvee_pwrup = 1,
+ .vpos_pwrup = 2,
+ .gvdd_pwrup = 1,
+ .gvdd_pwrdn = 1,
+ .vpos_pwrdn = 2,
+ .gvee_pwrdn = 1,
+ .vneg_pwrdn = 1,
+ .gpio_pmic_pwrgood = MX6SL_BRD_EPDC_PWRSTAT,
+ .gpio_pmic_vcom_ctrl = MX6SL_BRD_EPDC_VCOM,
+ .gpio_pmic_wakeup = MX6SL_BRD_EPDC_PMIC_WAKE,
+ .gpio_pmic_v3p3 = MX6SL_BRD_EPDC_PWRCTRL0,
+ .gpio_pmic_intr = MX6SL_BRD_EPDC_PMIC_INT,
+ .regulator_init = max17135_init_data,
+ .init = max17135_regulator_init,
+};
+
+static int __init max17135_regulator_init(struct max17135 *max17135)
+{
+ struct max17135_platform_data *pdata = &max17135_pdata;
+ int i, ret;
+
+ max17135->gvee_pwrup = pdata->gvee_pwrup;
+ max17135->vneg_pwrup = pdata->vneg_pwrup;
+ max17135->vpos_pwrup = pdata->vpos_pwrup;
+ max17135->gvdd_pwrup = pdata->gvdd_pwrup;
+ max17135->gvdd_pwrdn = pdata->gvdd_pwrdn;
+ max17135->vpos_pwrdn = pdata->vpos_pwrdn;
+ max17135->vneg_pwrdn = pdata->vneg_pwrdn;
+ max17135->gvee_pwrdn = pdata->gvee_pwrdn;
+
+ max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup +
+ pdata->gvdd_pwrup + pdata->gvee_pwrup;
+
+ max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood;
+ max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl;
+ max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup;
+ max17135->gpio_pmic_v3p3 = pdata->gpio_pmic_v3p3;
+ max17135->gpio_pmic_intr = pdata->gpio_pmic_intr;
+
+ gpio_request(max17135->gpio_pmic_wakeup, "epdc-pmic-wake");
+ gpio_direction_output(max17135->gpio_pmic_wakeup, 0);
+
+ gpio_request(max17135->gpio_pmic_vcom_ctrl, "epdc-vcom");
+ gpio_direction_output(max17135->gpio_pmic_vcom_ctrl, 0);
+
+ gpio_request(max17135->gpio_pmic_v3p3, "epdc-v3p3");
+ gpio_direction_output(max17135->gpio_pmic_v3p3, 0);
+
+ gpio_request(max17135->gpio_pmic_intr, "epdc-pmic-int");
+ gpio_direction_input(max17135->gpio_pmic_intr);
+
+ gpio_request(max17135->gpio_pmic_pwrgood, "epdc-pwrstat");
+ gpio_direction_input(max17135->gpio_pmic_pwrgood);
+
+ max17135->vcom_setup = false;
+ max17135->init_done = false;
+
+ for (i = 0; i < MAX17135_NUM_REGULATORS; i++) {
+ ret = max17135_register_regulator(max17135, i,
+ &pdata->regulator_init[i]);
+ if (ret != 0) {
+ printk(KERN_ERR"max17135 regulator init failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /*
+ * TODO: We cannot enable full constraints for now, since
+ * it results in the PFUZE regulators being disabled
+ * at the end of boot, which disables critical regulators.
+ */
+ /*regulator_has_full_constraints();*/
+
+ return 0;
+}
+
+static int mx6_evk_spi_cs[] = {
+ MX6_BRD_ECSPI1_CS0,
+};
+
+static const struct spi_imx_master mx6_evk_spi_data __initconst = {
+ .chipselect = mx6_evk_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx6_evk_spi_cs),
+};
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition m25p32_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x00100000,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data m25p32_spi_flash_data = {
+ .name = "m25p32",
+ .parts = m25p32_partitions,
+ .nr_parts = ARRAY_SIZE(m25p32_partitions),
+ .type = "m25p32",
+};
+
+static struct spi_board_info m25p32_spi0_board_info[] __initdata = {
+ {
+ /* The modalias must be the same as spi device driver name */
+ .modalias = "m25p80",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = &m25p32_spi_flash_data,
+ },
+};
+#endif
+
+static void spi_device_init(void)
+{
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+ spi_register_board_info(m25p32_spi0_board_info,
+ ARRAY_SIZE(m25p32_spi0_board_info));
+#endif
+}
+
+static struct imx_ssi_platform_data mx6_sabresd_ssi_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_SYN,
+};
+
+static struct mxc_audio_platform_data wm8962_data;
+
+static struct platform_device mx6_sabresd_audio_wm8962_device = {
+ .name = "imx-wm8962",
+};
+
+static struct wm8962_pdata wm8962_config_data = {
+
+};
+
+static int wm8962_clk_enable(int enable)
+{
+ if (enable)
+ clk_enable(extern_audio_root);
+ else
+ clk_disable(extern_audio_root);
+
+ return 0;
+}
+
+static int mxc_wm8962_init(void)
+{
+ struct clk *pll4;
+ int rate;
+
+ extern_audio_root = clk_get(NULL, "extern_audio_clk");
+ if (IS_ERR(extern_audio_root)) {
+ pr_err("can't get extern_audio_root clock.\n");
+ return PTR_ERR(extern_audio_root);
+ }
+
+ pll4 = clk_get(NULL, "pll4");
+ if (IS_ERR(pll4)) {
+ pr_err("can't get pll4 clock.\n");
+ return PTR_ERR(pll4);
+ }
+
+ clk_set_parent(extern_audio_root, pll4);
+
+ rate = 24000000;
+ clk_set_rate(extern_audio_root, 24000000);
+
+ wm8962_data.sysclk = rate;
+ /* set AUDMUX pads to 1.8v */
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_MCLK,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_RXD,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXC,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXD,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXFS,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+
+ return 0;
+}
+
+static struct mxc_audio_platform_data wm8962_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_gpio = MX6_BRD_HEADPHONE_DET,
+ .hp_active_low = 1,
+ .mic_gpio = -1,
+ .mic_active_low = 1,
+ .init = mxc_wm8962_init,
+ .clock_enable = wm8962_clk_enable,
+};
+
+static struct regulator_consumer_supply sabresd_vwm8962_consumers[] = {
+ REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
+ REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+};
+
+static struct regulator_init_data sabresd_vwm8962_init = {
+ .constraints = {
+ .name = "SPKVDD",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sabresd_vwm8962_consumers),
+ .consumer_supplies = sabresd_vwm8962_consumers,
+};
+
+static struct fixed_voltage_config sabresd_vwm8962_reg_config = {
+ .supply_name = "SPKVDD",
+ .microvolts = 4325000,
+ .gpio = -1,
+ .enabled_at_boot = 1,
+ .init_data = &sabresd_vwm8962_init,
+};
+
+static struct platform_device sabresd_vwm8962_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 4,
+ .dev = {
+ .platform_data = &sabresd_vwm8962_reg_config,
+ },
+};
+
+static int __init imx6q_init_audio(void)
+{
+ platform_device_register(&sabresd_vwm8962_reg_devices);
+ mxc_register_device(&mx6_sabresd_audio_wm8962_device,
+ &wm8962_data);
+ imx6q_add_imx_ssi(1, &mx6_sabresd_ssi_pdata);
+
+ return 0;
+}
+
+static int spdif_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long rate_actual;
+ rate_actual = clk_round_rate(clk, rate);
+ clk_set_rate(clk, rate_actual);
+ return 0;
+}
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = 1,
+ .spdif_clk_48000 = -1,
+ .spdif_div_44100 = 23,
+ .spdif_clk_set_rate = spdif_clk_set_rate,
+ .spdif_clk = NULL,
+};
+
+
+enum DISPLAY_PANEL_MODE {
+ PANEL_MODE_LCD,
+ PANEL_MODE_HDMI,
+ PANEL_MODE_EINK,
+};
+
+static int display_panel_mode = PANEL_MODE_EINK;
+
+static iomux_v3_cfg_t mx6sl_sii902x_hdmi_pads_enabled[] = {
+ MX6SL_PAD_LCD_RESET__GPIO_2_19,
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10,
+};
+
+static int sii902x_get_pins(void)
+{
+ /* Sii902x HDMI controller */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_sii902x_hdmi_pads_enabled, \
+ ARRAY_SIZE(mx6sl_sii902x_hdmi_pads_enabled));
+
+ /* Reset Pin */
+ gpio_request(MX6_BRD_LCD_RESET, "disp0-reset");
+ gpio_direction_output(MX6_BRD_LCD_RESET, 1);
+
+ /* Interrupter pin GPIO */
+ gpio_request(MX6SL_BRD_EPDC_PWRCTRL3, "disp0-detect");
+ gpio_direction_input(MX6SL_BRD_EPDC_PWRCTRL3);
+ return 1;
+}
+
+static void sii902x_put_pins(void)
+{
+ gpio_free(MX6_BRD_LCD_RESET);
+ gpio_free(MX6SL_BRD_EPDC_PWRCTRL3);
+}
+
+static void sii902x_hdmi_reset(void)
+{
+ gpio_set_value(MX6_BRD_LCD_RESET, 0);
+ msleep(10);
+ gpio_set_value(MX6_BRD_LCD_RESET, 1);
+ msleep(10);
+}
+
+static struct fsl_mxc_lcd_platform_data sii902x_hdmi_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .reset = sii902x_hdmi_reset,
+ .get_pins = sii902x_get_pins,
+ .put_pins = sii902x_put_pins,
+};
+
+static void mx6sl_csi_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_csi_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_csi_enable_pads));
+
+ /* Camera reset */
+ gpio_request(MX6SL_BRD_CSI_RST, "cam-reset");
+ gpio_direction_output(MX6SL_BRD_CSI_RST, 1);
+
+ /* Camera power down */
+ gpio_request(MX6SL_BRD_CSI_PWDN, "cam-pwdn");
+ gpio_direction_output(MX6SL_BRD_CSI_PWDN, 1);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 0);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_RST, 0);
+ msleep(1);
+ gpio_set_value(MX6SL_BRD_CSI_RST, 1);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 1);
+}
+
+static void mx6sl_csi_cam_powerdown(int powerdown)
+{
+ if (powerdown)
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 1);
+ else
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 0);
+
+ msleep(2);
+}
+
+static struct fsl_mxc_camera_platform_data camera_data = {
+ .mclk = 24000000,
+ .io_init = mx6sl_csi_io_init,
+ .pwdn = mx6sl_csi_cam_powerdown,
+ .core_regulator = "VGEN2_1V5",
+ .analog_regulator = "VGEN6_2V8",
+};
+
+static struct imxi2c_platform_data mx6_evk_i2c0_data = {
+ .bitrate = 100000,
+};
+
+static struct imxi2c_platform_data mx6_evk_i2c1_data = {
+ .bitrate = 100000,
+};
+
+static struct imxi2c_platform_data mx6_evk_i2c2_data = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("max17135", 0), /*0x48*/
+ .platform_data = &max17135_pdata,
+ }, {
+ I2C_BOARD_INFO("elan-touch", 0), /*0x10*/
+ .irq = gpio_to_irq(MX6SL_BRD_ELAN_INT),
+ }, {
+ I2C_BOARD_INFO("mma8450", 0x1c),
+ },
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("wm8962", 0x1a),
+ .platform_data = &wm8962_config_data,
+ },
+ {
+ I2C_BOARD_INFO("sii902x", 0), /*0x39*/
+ .platform_data = &sii902x_hdmi_data,
+ .irq = gpio_to_irq(MX6SL_BRD_EPDC_PWRCTRL3)
+ },
+};
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("ov5640", 0x3c),
+ .platform_data = (void *)&camera_data,
+ },
+};
+
+static struct mxc_dvfs_platform_data mx6sl_evk_dvfscore_data = {
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+ .reg_id = "VDDCORE",
+ .soc_id = "VDDSOC",
+#else
+ .reg_id = "cpu_vddgp",
+ .soc_id = "cpu_vddsoc",
+ .pu_id = "cpu_vddvpu",
+#endif
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+};
+
+static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
+ .reserved_mem_size = SZ_32M,
+};
+
+void __init early_console_setup(unsigned long base, struct clk *clk);
+
+static const struct imxuart_platform_data mx6sl_evk_uart1_data __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS | IMXUART_SDMA,
+ .dma_req_rx = MX6Q_DMA_REQ_UART2_RX,
+ .dma_req_tx = MX6Q_DMA_REQ_UART2_TX,
+};
+
+static inline void mx6_evk_init_uart(void)
+{
+ imx6q_add_imx_uart(0, NULL); /* DEBUG UART1 */
+}
+
+static int mx6sl_evk_fec_phy_init(struct phy_device *phydev)
+{
+ int val;
+
+ /* power on FEC phy and reset phy */
+ gpio_request(MX6_BRD_FEC_PWR_EN, "fec-pwr");
+ gpio_direction_output(MX6_BRD_FEC_PWR_EN, 0);
+ /* wait RC ms for hw reset */
+ msleep(1);
+ gpio_direction_output(MX6_BRD_FEC_PWR_EN, 1);
+
+ /* check phy power */
+ val = phy_read(phydev, 0x0);
+ if (val & BMCR_PDOWN)
+ phy_write(phydev, 0x0, (val & ~BMCR_PDOWN));
+
+ return 0;
+}
+
+static struct fec_platform_data fec_data __initdata = {
+ .init = mx6sl_evk_fec_phy_init,
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static int epdc_get_pins(void)
+{
+ int ret = 0;
+
+ /* Claim GPIOs for EPDC pins - used during power up/down */
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "epdc_d0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "epdc_d1");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "epdc_d2");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "epdc_d3");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "epdc_d4");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "epdc_d5");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "epdc_d6");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "epdc_d7");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "epdc_gdclk");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "epdc_gdsp");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "epdc_gdoe");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDRL, "epdc_gdrl");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "epdc_sdclk");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDOE, "epdc_sdoe");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "epdc_sdle");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "epdc_sdshr");
+ ret |= gpio_request(MX6SL_BRD_EPDC_BDR0, "epdc_bdr0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "epdc_sdce0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "epdc_sdce1");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE2, "epdc_sdce2");
+
+ return ret;
+}
+
+static void epdc_put_pins(void)
+{
+ gpio_free(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_7);
+ gpio_free(MX6SL_BRD_EPDC_GDCLK);
+ gpio_free(MX6SL_BRD_EPDC_GDSP);
+ gpio_free(MX6SL_BRD_EPDC_GDOE);
+ gpio_free(MX6SL_BRD_EPDC_GDRL);
+ gpio_free(MX6SL_BRD_EPDC_SDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDOE);
+ gpio_free(MX6SL_BRD_EPDC_SDLE);
+ gpio_free(MX6SL_BRD_EPDC_SDSHR);
+ gpio_free(MX6SL_BRD_EPDC_BDR0);
+ gpio_free(MX6SL_BRD_EPDC_SDCE0);
+ gpio_free(MX6SL_BRD_EPDC_SDCE1);
+ gpio_free(MX6SL_BRD_EPDC_SDCE2);
+}
+
+static void epdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable EPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_epdc_enable_pads));
+
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDSP);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDRL);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDLE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDSHR);
+ gpio_direction_input(MX6SL_BRD_EPDC_BDR0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE2);
+}
+
+static void epdc_disable_pins(void)
+{
+ /* Configure MUX settings for EPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_disable_pads, \
+ ARRAY_SIZE(mx6sl_brd_epdc_disable_pads));
+
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDRL, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_BDR0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE2, 0);
+}
+
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 30000000,
+ .left_margin = 8,
+ .right_margin = 164,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+};
+static struct fb_videomode e060scm_mode = {
+ .name = "E060SCM",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 26666667,
+ .left_margin = 8,
+ .right_margin = 100,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct imx_epdc_fb_mode panel_modes[] = {
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 465, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 9, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e060scm_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 419, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 5, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+
+static struct imx_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+ .get_pins = epdc_get_pins,
+ .put_pins = epdc_put_pins,
+ .enable_pins = epdc_enable_pins,
+ .disable_pins = epdc_disable_pins,
+};
+
+static int spdc_get_pins(void)
+{
+ int ret = 0;
+
+ /* Claim GPIOs for SPDC pins - used during power up/down */
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "SPDC_D0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "SPDC_D1");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "SPDC_D2");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "SPDC_D3");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "SPDC_D4");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "SPDC_D5");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "SPDC_D6");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "SPDC_D7");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "SIPIX_YOE");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_9, "SIPIX_PWR_RDY");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "SIPIX_YDIO");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "SIPIX_YCLK");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "SIPIX_XDIO");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "SIPIX_LD");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "SIPIX_SOE");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "SIPIX_XCLK");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_10, "SIPIX_SHD_N");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "SIPIX2_CE");
+
+ return ret;
+}
+
+static void spdc_put_pins(void)
+{
+ gpio_free(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_7);
+
+ gpio_free(MX6SL_BRD_EPDC_GDOE);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_free(MX6SL_BRD_EPDC_GDSP);
+ gpio_free(MX6SL_BRD_EPDC_GDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDSHR);
+ gpio_free(MX6SL_BRD_EPDC_SDLE);
+ gpio_free(MX6SL_BRD_EPDC_SDCE1);
+ gpio_free(MX6SL_BRD_EPDC_SDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_free(MX6SL_BRD_EPDC_SDCE0);
+}
+
+static void spdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable SPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_spdc_enable_pads));
+
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDSP);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDSHR);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDLE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE0);
+}
+
+static void spdc_disable_pins(void)
+{
+ /* Configure MUX settings for SPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_disable_pads, \
+ ARRAY_SIZE(mx6sl_brd_spdc_disable_pads));
+
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0);
+
+ gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_9, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_10, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0);
+}
+
+static struct imx_spdc_panel_init_set spdc_init_set = {
+ .yoe_pol = false,
+ .dual_gate = false,
+ .resolution = 0,
+ .ud = false,
+ .rl = false,
+ .data_filter_n = true,
+ .power_ready = true,
+ .rgbw_mode_enable = false,
+ .hburst_len_en = true,
+};
+
+static struct fb_videomode erk_1_4_a01 = {
+ .name = "ERK_1_4_A01",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 40000000,
+ .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct imx_spdc_fb_mode spdc_panel_modes[] = {
+ {
+ &erk_1_4_a01,
+ &spdc_init_set,
+ .wave_timing = "pvi"
+ },
+};
+
+static struct imx_spdc_fb_platform_data spdc_data = {
+ .spdc_mode = spdc_panel_modes,
+ .num_modes = ARRAY_SIZE(spdc_panel_modes),
+ .get_pins = spdc_get_pins,
+ .put_pins = spdc_put_pins,
+ .enable_pins = spdc_enable_pins,
+ .disable_pins = spdc_disable_pins,
+};
+
+static int __init early_use_spdc_sel(char *p)
+{
+ spdc_sel = 1;
+ return 0;
+}
+early_param("spdc", early_use_spdc_sel);
+
+static void setup_spdc(void)
+{
+ /* GPR0[8]: 0:EPDC, 1:SPDC */
+ if (spdc_sel)
+ mxc_iomux_set_gpr_register(0, 8, 1, 1);
+}
+
+static void imx6_evk_usbotg_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(MX6_BRD_USBOTG1_PWR, 1);
+ else
+ gpio_set_value(MX6_BRD_USBOTG1_PWR, 0);
+}
+
+static void __init mx6_evk_init_usb(void)
+{
+ int ret = 0;
+
+ imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR);
+
+ /* disable external charger detect,
+ * or it will affect signal quality at dp.
+ */
+
+ ret = gpio_request(MX6_BRD_USBOTG1_PWR, "usbotg-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO MX6_BRD_USBOTG1_PWR:%d\n", ret);
+ return;
+ }
+ gpio_direction_output(MX6_BRD_USBOTG1_PWR, 0);
+
+ ret = gpio_request(MX6_BRD_USBOTG2_PWR, "usbh1-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO MX6_BRD_USBOTG2_PWR:%d\n", ret);
+ return;
+ }
+ gpio_direction_output(MX6_BRD_USBOTG2_PWR, 1);
+
+ mx6_set_otghost_vbus_func(imx6_evk_usbotg_vbus);
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ mx6_usb_h2_init();
+#endif
+}
+
+static struct platform_pwm_backlight_data mx6_evk_pwm_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+static struct fb_videomode wvga_video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 32MHz */
+ "SEIKO-WVGA", 60, 800, 480, 29850, 89, 164, 23, 10, 10, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data wvga_fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB24,
+ .mode_str = "SEIKO-WVGA",
+ .mode = wvga_video_modes,
+ .num_modes = ARRAY_SIZE(wvga_video_modes),
+ .panel_type = "lcd",
+ },
+};
+
+static struct platform_device lcd_wvga_device = {
+ .name = "lcd_seiko",
+};
+
+static struct fb_videomode hdmi_video_modes[] = {
+ {
+ /* 1920x1080 @ 60 Hz , pixel clk @ 148MHz */
+ "sii9022x_1080p60", 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data hdmi_fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB24,
+ .mode_str = "1920x1080M@60",
+ .mode = hdmi_video_modes,
+ .num_modes = ARRAY_SIZE(hdmi_video_modes),
+ .panel_type = "hdmi",
+ },
+};
+
+static int mx6sl_evk_keymap[] = {
+ KEY(0, 0, KEY_SELECT), /* EVK:SW6 DC2:SELECT */
+ KEY(0, 1, KEY_BACK), /* EVK:SW7 DC2:BACK */
+ KEY(0, 2, KEY_F1), /* EVK:SW8 DC2:F1 */
+ KEY(0, 3, KEY_F2), /* EVK DC2:F2 */
+
+ KEY(1, 0, KEY_F3), /* EVK:SW9 DC2:F3 */
+ KEY(1, 1, KEY_VOLUMEDOWN), /* EVK:SW10 DC2:F4 */
+ KEY(1, 2, KEY_VOLUMEUP), /* EVK:SW11 DC2:F5 */
+ KEY(1, 3, KEY_MENU), /* EVK DC2:MENU */
+
+ KEY(2, 0, KEY_PREVIOUS), /* EVK:SW12 DC2:PREV */
+ KEY(2, 1, KEY_NEXT), /* EVK:SW13 DC2:NEX1 */
+ KEY(2, 2, KEY_HOME), /* EVK DC2:HOME */
+ KEY(2, 3, KEY_NEXT), /* EVK DC2:NEX2 */
+
+ KEY(3, 0, KEY_UP), /* EVK DC2:UP */
+ KEY(3, 1, KEY_LEFT), /* EVK DC2:LEFT */
+ KEY(3, 2, KEY_RIGHT), /* EVK DC2:RIGHT */
+ KEY(3, 3, KEY_DOWN), /* EVK DC2:DOWN */
+};
+
+static const struct matrix_keymap_data mx6sl_evk_map_data __initconst = {
+ .keymap = mx6sl_evk_keymap,
+ .keymap_size = ARRAY_SIZE(mx6sl_evk_keymap),
+};
+static void __init elan_ts_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_elan_pads,
+ ARRAY_SIZE(mx6sl_brd_elan_pads));
+
+ /* ELAN Touchscreen */
+ gpio_request(MX6SL_BRD_ELAN_INT, "elan-interrupt");
+ gpio_direction_input(MX6SL_BRD_ELAN_INT);
+
+ gpio_request(MX6SL_BRD_ELAN_CE, "elan-cs");
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 0);
+
+ gpio_request(MX6SL_BRD_ELAN_RST, "elan-rst");
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 0);
+ mdelay(1);
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 1);
+}
+
+/*
+ *Usually UOK and DOK should have separate
+ *line to differentiate its behaviour (with different
+ * GPIO irq),because connect max8903 pin UOK to
+ *pin DOK from hardware design,cause software cannot
+ *process and distinguish two interrupt, so default
+ *enable dc_valid for ac charger
+ */
+static struct max8903_pdata charger1_data = {
+ .dok = MX6_BRD_CHG_DOK,
+ .uok = MX6_BRD_CHG_UOK,
+ .chg = MX6_BRD_CHG_STATUS,
+ .flt = MX6_BRD_CHG_FLT,
+ .dcm_always_high = true,
+ .dc_valid = true,
+ .usb_valid = false,
+ .feature_flag = 1,
+};
+
+static struct platform_device evk_max8903_charger_1 = {
+ .name = "max8903-charger",
+ .dev = {
+ .platform_data = &charger1_data,
+ },
+};
+
+/*! Device Definition for csi v4l2 device */
+static struct platform_device csi_v4l2_devices = {
+ .name = "csi_v4l2",
+ .id = 0,
+};
+
+#define SNVS_LPCR 0x38
+static void mx6_snvs_poweroff(void)
+{
+ u32 value;
+ void __iomem *mx6_snvs_base = MX6_IO_ADDRESS(MX6Q_SNVS_BASE_ADDR);
+
+ value = readl(mx6_snvs_base + SNVS_LPCR);
+ /* set TOP and DP_EN bit */
+ writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
+}
+
+static int uart2_enabled;
+static int __init uart2_setup(char * __unused)
+{
+ uart2_enabled = 1;
+ return 1;
+}
+__setup("bluetooth", uart2_setup);
+
+static void __init uart2_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_uart2_pads,
+ ARRAY_SIZE(mx6sl_uart2_pads));
+ imx6sl_add_imx_uart(1, &mx6sl_evk_uart1_data);
+}
+
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+
+#define MX6SL_EVK_POWER_OFF IMX_GPIO_NR(3, 18)
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake, debounce) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+ .debounce_interval = debounce, \
+}
+
+static struct gpio_keys_button imx6sl_buttons[] = {
+ GPIO_BUTTON(MX6SL_EVK_POWER_OFF, KEY_POWER, 1, "power", 1, 1),
+};
+
+static struct gpio_keys_platform_data imx6sl_button_data = {
+ .buttons = imx6sl_buttons,
+ .nbuttons = ARRAY_SIZE(imx6sl_buttons),
+ .rep = 0,
+};
+
+static struct platform_device imx6sl_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &imx6sl_button_data,
+ }
+};
+
+static void __init imx6sl_add_device_buttons(void)
+{
+ platform_device_register(&imx6sl_button_device);
+}
+#else
+static void __init imx6sl_add_device_buttons(void) {}
+#endif
+
+
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mx6_evk_init(void)
+{
+ u32 i;
+
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_pads,
+ ARRAY_SIZE(mx6sl_brd_pads));
+
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+ gp_reg_id = mx6sl_evk_dvfscore_data.reg_id;
+ soc_reg_id = mx6sl_evk_dvfscore_data.soc_id;
+#else
+ gp_reg_id = mx6sl_evk_dvfscore_data.reg_id;
+ soc_reg_id = mx6sl_evk_dvfscore_data.soc_id;
+ pu_reg_id = mx6sl_evk_dvfscore_data.pu_id;
+ mx6_cpu_regulator_init();
+#endif
+
+ imx6q_add_imx_snvs_rtc();
+
+ imx6q_add_imx_i2c(0, &mx6_evk_i2c0_data);
+ imx6q_add_imx_i2c(1, &mx6_evk_i2c1_data);
+
+ /* setting sii902x address when hdmi enabled */
+ switch (display_panel_mode) {
+ case PANEL_MODE_EINK:
+ for (i = 0; i < ARRAY_SIZE(mxc_i2c0_board_info); i++)
+ if (!strcmp(mxc_i2c0_board_info[i].type, "max17135"))
+ mxc_i2c0_board_info[i].addr = 0x48;
+ for (i = 0; i < ARRAY_SIZE(mxc_i2c0_board_info); i++)
+ if (!strcmp(mxc_i2c0_board_info[i].type, "elan-touch"))
+ mxc_i2c0_board_info[i].addr = 0x10;
+ elan_ts_init();
+ mxc_register_device(&max17135_sensor_device, NULL);
+ setup_spdc();
+ if (!spdc_sel)
+ imx6dl_add_imx_epdc(&epdc_data);
+ else
+ imx6sl_add_imx_spdc(&spdc_data);
+ break;
+ case PANEL_MODE_HDMI:
+ for (i = 0; i < ARRAY_SIZE(mxc_i2c1_board_info); i++)
+ if (!strcmp(mxc_i2c1_board_info[i].type, "sii902x"))
+ mxc_i2c1_board_info[i].addr = 0x39;
+#ifdef CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF//[
+ imx6dl_add_imx_elcdif(&hdmi_fb_data[0]);
+#endif //]CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF
+ mxc_spdif_data.spdif_core_clk = clk_get_sys("mxc_spdif.0",
+ NULL);
+ clk_put(mxc_spdif_data.spdif_core_clk);
+ imx6q_add_spdif(&mxc_spdif_data);
+ imx6q_add_spdif_dai();
+ imx6q_add_spdif_audio_device();
+ break;
+ case PANEL_MODE_LCD:
+#ifdef CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF//[
+ imx6dl_add_imx_elcdif(&wvga_fb_data[0]);
+#endif //]CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF
+ gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on");
+ gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1);
+ mxc_register_device(&lcd_wvga_device, NULL);
+ break;
+ default:
+ pr_err("Error display_panel_mode\n");
+ }
+
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+
+ /* only camera on I2C2, that's why we can do so */
+ if (csi_enabled == 1) {
+ mxc_register_device(&csi_v4l2_devices, NULL);
+ imx6q_add_imx_i2c(2, &mx6_evk_i2c2_data);
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+ }
+
+ /* SPI */
+ imx6q_add_ecspi(0, &mx6_evk_spi_data);
+ spi_device_init();
+
+ mx6sl_evk_init_pfuze100(0);
+
+ imx6q_add_anatop_thermal_imx(1, &mx6sl_anatop_thermal_data);
+
+ mx6_evk_init_uart();
+ /* get enet tx reference clk from FEC_REF_CLK pad.
+ * GPR1[14] = 0, GPR1[18:17] = 00
+ */
+ mxc_iomux_set_gpr_register(1, 14, 1, 0);
+ mxc_iomux_set_gpr_register(1, 17, 2, 0);
+
+ imx6_init_fec(fec_data);
+
+ platform_device_register(&evk_vmmc_reg_devices);
+ imx6q_add_sdhci_usdhc_imx(1, &mx6_evk_sd2_data);
+ imx6q_add_sdhci_usdhc_imx(0, &mx6_evk_sd1_data);
+ imx6q_add_sdhci_usdhc_imx(2, &mx6_evk_sd3_data);
+
+ mx6_evk_init_usb();
+ imx6q_add_otp();
+ imx6q_add_mxc_pwm(0);
+ imx6q_add_mxc_pwm_backlight(0, &mx6_evk_pwm_backlight_data);
+#ifdef CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF//[
+ imx6dl_add_imx_elcdif(&wvga_fb_data[0]);
+#endif //] CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF
+
+ gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on");
+ gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1);
+ mxc_register_device(&lcd_wvga_device, NULL);
+
+ imx6dl_add_imx_pxp();
+ imx6dl_add_imx_pxp_client();
+
+ if (csi_enabled) {
+ imx6sl_add_fsl_csi();
+ }
+ imx6q_add_dvfs_core(&mx6sl_evk_dvfscore_data);
+
+ imx6q_init_audio();
+
+ /* uart2 for bluetooth */
+ if (uart2_enabled)
+ uart2_init();
+
+ //mxc_register_device(&mxc_bt_rfkill, &mxc_bt_rfkill_data);
+
+ imx6q_add_viim();
+ imx6q_add_imx2_wdt(0, NULL);
+
+ imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata);
+ imx6sl_add_device_buttons();
+ imx6sl_add_imx_keypad(&mx6sl_evk_map_data);
+ imx6q_add_busfreq();
+ imx6sl_add_dcp();
+ imx6sl_add_rngb();
+ imx6sl_add_imx_pxp_v4l2();
+
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
+ /* Register charger chips */
+ platform_device_register(&evk_max8903_charger_1);
+ pm_power_off = mx6_snvs_poweroff;
+}
+
+extern void __iomem *twd_base;
+static void __init mx6_timer_init(void)
+{
+ struct clk *uart_clk;
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ mx6sl_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(UART1_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx6_timer_init,
+};
+
+static void __init mx6_evk_reserve(void)
+{
+#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE)
+ phys_addr_t phys;
+
+ if (imx6q_gpu_pdata.reserved_mem_size) {
+ phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size,
+ SZ_4K, MEMBLOCK_ALLOC_ACCESSIBLE);
+ memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size);
+ imx6q_gpu_pdata.reserved_mem_base = phys;
+ }
+#endif
+}
+
+static int __init display_panel_setup(char *options)
+{
+ if (!options || !*options) {
+ pr_err("Error panel options\n");
+ return 0;
+ }
+
+ if (!strcmp(options, "lcd"))
+ display_panel_mode = PANEL_MODE_LCD;
+ else if (!strcmp(options, "hdmi"))
+ display_panel_mode = PANEL_MODE_HDMI;
+ else if (!strcmp(options, "eink"))
+ display_panel_mode = PANEL_MODE_EINK;
+ else
+ pr_warn("WARN: invalid display panel mode setting");
+
+ return 1;
+}
+
+__setup("panel=", display_panel_setup);
+
+MACHINE_START(MX6SL_EVK, "Freescale i.MX 6SoloLite EVK Board")
+ .boot_params = MX6SL_PHYS_OFFSET + 0x100,
+ .map_io = mx6_map_io,
+ .init_irq = mx6_init_irq,
+ .init_machine = mx6_evk_init,
+ .timer = &mxc_timer,
+ .reserve = mx6_evk_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-mx6/board-mx6sl_ntx.c b/arch/arm/mach-mx6/board-mx6sl_ntx.c
new file mode 100755
index 00000000..26c3c900
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6sl_ntx.c
@@ -0,0 +1,3886 @@
+/*
+ * Copyright (C) 2012 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 <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/etherdevice.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max17135.h>
+#include <sound/wm8962.h>
+#include <sound/pcm.h>
+#include <linux/power/sabresd_battery.h>
+#include <../drivers/misc/ntx-misc.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/memory.h>
+#include <mach/iomux-mx6sl.h>
+#include <mach/imx-uart.h>
+#include <mach/viv_gpu.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <linux/usbplugevent.h>
+#include <linux/mmc/sdhci.h>
+
+
+#include "usb.h"
+#include "devices-imx6q.h"
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "board-mx6sl_common.h"
+#include "board-mx6sl_ntx.h"
+
+#include "ntx_hwconfig.h"
+
+#include <linux/mfd/ricoh619.h>
+#include <linux/rtc/rtc-ricoh619.h>
+#include <linux/power/ricoh619_battery.h>
+#include <linux/regulator/ricoh619-regulator.h>
+
+#include "../../../drivers/input/keyboard/gpiofn.h"
+#define TOUCH_HOME_LED 1
+#include "../../../drivers/misc/ntx-misc.h"
+
+
+#define GDEBUG 0
+#include <linux/gallen_dbg.h>
+
+
+#define EPD_TIMING_ED068OG1_NUMCE3 1
+#define EPD_TIMING_ED068TG1 1
+
+
+
+extern int gSleep_Mode_Suspend;
+
+
+volatile unsigned gMX6SL_NTX_ACIN_PG = IMX_GPIO_NR(4, 20); /* FEC_MDIO */
+volatile unsigned gMX6SL_NTX_CHG = IMX_GPIO_NR(4, 21); /* FEC_TX_CLK */
+volatile unsigned gMX6SL_MSP_INT = IMX_GPIO_NR(4, 19); /* FEC_RX_ER */
+volatile unsigned gMX6SL_PWR_SW = IMX_GPIO_NR(4, 25); /* FEC_CRS_DV */
+volatile unsigned gMX6SL_IR_TOUCH_INT = IMX_GPIO_NR(4, 24); /* FEC_TXD0 */
+volatile unsigned gMX6SL_IR_TOUCH_RST = IMX_GPIO_NR(4, 17); /* FEC_RXD0 */
+volatile unsigned gMX6SL_HALL_EN = IMX_GPIO_NR(4, 23); /* FEC_MDC */
+volatile unsigned gMX6SL_ON_LED = IMX_GPIO_NR(4, 22); /* FEC_TX_EN */
+volatile unsigned gMX6SL_CHG_LED = IMX_GPIO_NR(4, 16); /* FEC_TXD1 */
+volatile unsigned gMX6SL_ACT_LED = IMX_GPIO_NR(4, 26); /* FEC_REF_CLK */
+volatile unsigned gMX6SL_WIFI_3V3 = IMX_GPIO_NR(5, 0); /* SD2_DAT7 */
+volatile unsigned gMX6SL_WIFI_RST = IMX_GPIO_NR(4, 27); /* SD2_RST */
+volatile unsigned gMX6SL_WIFI_INT = IMX_GPIO_NR(4, 29); /* SD2_DAT6 */
+volatile unsigned gMX6SL_HOME_LED = IMX_GPIO_NR(5, 10); /* SD2_DAT6 */
+
+volatile int giISD_3V3_ON_Ctrl = -1;
+
+static int spdc_sel;
+static int max17135_regulator_init(struct max17135 *max17135);
+
+extern char *gp_reg_id;
+extern char *soc_reg_id;
+extern char *pu_reg_id;
+extern int __init mx6sl_ntx_init_pfuze100(u32 int_gpio);
+extern void tle4913_init(void);
+
+static int csi_enabled;
+
+#define _MYINIT_DATA
+#define _MYINIT_TEXT
+volatile static unsigned char _MYINIT_DATA *gpbHWCFG_paddr;
+//volatile unsigned char *gpbHWCFG_vaddr;
+volatile unsigned long _MYINIT_DATA gdwHWCFG_size;
+volatile int _MYINIT_DATA giBootPort;
+
+volatile NTX_HWCONFIG *gptHWCFG;
+
+static void * _MemoryRequest(void *addr, u32 len, const char * name)
+{
+ void * mem = NULL;
+ do {
+ printk(KERN_DEBUG "***%s:%d: request memory region! addr=%p, len=%hd***\n",
+ __FUNCTION__, __LINE__, addr, len);
+ if (!request_mem_region((u32)addr, len, name)) {
+ printk(KERN_CRIT "%s(): request memory region failed! addr=%p, len %hd\n",__FUNCTION__, addr, len);
+ break;
+ }
+ mem = (void *) ioremap_nocache((u32)addr, len);
+ if (!mem) {
+ printk(KERN_CRIT "***%s:%d: could not ioremap %s***\n", __FUNCTION__, __LINE__, name);
+ release_mem_region((u32)addr, len);
+ break;
+ }
+ } while (0);
+ return mem;
+}
+
+int gIsCustomerUi;
+static int _MYINIT_TEXT hwcfg_p_setup(char *str)
+{
+ gpbHWCFG_paddr = (unsigned char *)simple_strtoul(str,NULL,0);
+ if(NULL==gptHWCFG) {
+ gptHWCFG = (NTX_HWCONFIG *)_MemoryRequest((void *)gpbHWCFG_paddr, gdwHWCFG_size, "hwcfg_p");
+ if(!gptHWCFG) {
+ return 0;
+ }
+ }
+ printk("%s() hwcfg_p=%p,vaddr=%p,size=%d,pcb=0x%x\n",__FUNCTION__,
+ gpbHWCFG_paddr,gptHWCFG,(int)gdwHWCFG_size,gptHWCFG->m_val.bPCB);
+ gIsCustomerUi = (int)gptHWCFG->m_val.bUIStyle;
+
+ return 1;
+}
+
+static int _MYINIT_TEXT hwcfg_size_setup(char *str)
+{
+ gdwHWCFG_size = (unsigned long)simple_strtoul(str,NULL,0);
+ printk("%s() hwcfg_szie=%d\n",__FUNCTION__,(int)gdwHWCFG_size);
+ return 1;
+}
+
+static int _MYINIT_TEXT boot_port_setup(char *str)
+{
+ giBootPort = (int)simple_strtoul(str,NULL,0);
+ printk("%s() boot_port=%d\n",__FUNCTION__,giBootPort);
+ return 1;
+}
+
+static void _parse_cmdline(void)
+{
+ static int iParseCnt = 0;
+ char *pcPatternStart,*pcPatternVal,*pcPatternValEnd,cTempStore;
+ unsigned long ulPatternLen;
+
+ char *szParsePatternA[]={"hwcfg_sz=","hwcfg_p=","boot_port="};
+ int ((*pfnDispatchA[])(char *str))={hwcfg_size_setup,hwcfg_p_setup,boot_port_setup };
+
+ int i;
+ char *pszCmdLineBuf;
+
+
+ if(iParseCnt++>0) {
+ printk("%s : cmdline parse already done .\n",__FUNCTION__);
+ return ;
+ }
+ //printk("%s():cmdline(%d)=%s\n",__FUNCTION__,strlen(saved_command_line),saved_command_line);
+
+ pszCmdLineBuf = kmalloc(strlen(saved_command_line)+1,GFP_KERNEL);
+ //ASSERT(pszCmdLineBuf);
+ strcpy(pszCmdLineBuf,saved_command_line);
+ printk("%s():cp cmdline=%s\n",__FUNCTION__,pszCmdLineBuf);
+
+ for(i=0;i<sizeof(szParsePatternA)/sizeof(szParsePatternA[0]);i++) {
+ ulPatternLen = strlen(szParsePatternA[i]);
+ pcPatternStart = strstr(pszCmdLineBuf,szParsePatternA[i]);
+ if(pcPatternStart) {
+ pcPatternVal=pcPatternStart + ulPatternLen ;
+ pcPatternValEnd = strchr(pcPatternVal,' ');
+ cTempStore='\0';
+ if(pcPatternValEnd) {
+ cTempStore = *pcPatternValEnd;
+ *pcPatternValEnd = '\0';
+ }
+ //printk("%s():pattern \"%s\" ,val=\"%s\"\n",__FUNCTION__,szParsePatternA[i],pcPatternVal);
+ pfnDispatchA[i](pcPatternVal);
+ if(pcPatternValEnd) {
+ *pcPatternValEnd = cTempStore;
+ }
+ }
+ else
+ printk ("[%s-%d] %s not found !!!\n",__func__,__LINE__,szParsePatternA[i]);
+ }
+ if (NULL == gptHWCFG) {
+ printk ("[%s-%d] personal initial hw config.\n",__func__,__LINE__);
+ gptHWCFG = (NTX_HWCONFIG *)kmalloc(sizeof(NTX_HWCONFIG), GFP_KERNEL);
+ gptHWCFG->m_val.bTouchCtrl = 8;
+ }
+}
+
+
+
+/* uart2 pins */
+#if 0 // gallen disabled .
+static iomux_v3_cfg_t mx6sl_uart2_pads[] = {
+ MX6SL_PAD_SD2_DAT5__UART2_TXD,
+ MX6SL_PAD_SD2_DAT4__UART2_RXD,
+ MX6SL_PAD_SD2_DAT6__UART2_RTS,
+ MX6SL_PAD_SD2_DAT7__UART2_CTS,
+};
+#endif
+
+enum sd_pad_mode {
+ SD_PAD_MODE_LOW_SPEED,
+ SD_PAD_MODE_MED_SPEED,
+ SD_PAD_MODE_HIGH_SPEED,
+};
+
+static int plt_sd_pad_change(unsigned int index, int clock)
+{
+ /* LOW speed is the default state of SD pads */
+ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
+
+ iomux_v3_cfg_t *sd_pads_200mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_100mhz = NULL;
+ iomux_v3_cfg_t *sd_pads_50mhz = NULL;
+
+ u32 sd_pads_200mhz_cnt;
+ u32 sd_pads_100mhz_cnt;
+ u32 sd_pads_50mhz_cnt;
+
+ switch (index) {
+ case 0:
+ sd_pads_200mhz = mx6sl_sd1_200mhz;
+ sd_pads_100mhz = mx6sl_sd1_100mhz;
+ sd_pads_50mhz = mx6sl_sd1_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd1_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd1_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd1_50mhz);
+ break;
+ case 1:
+ sd_pads_200mhz = mx6sl_sd2_200mhz;
+ sd_pads_100mhz = mx6sl_sd2_100mhz;
+ sd_pads_50mhz = mx6sl_sd2_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd2_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd2_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd2_50mhz);
+ break;
+ case 2:
+ sd_pads_200mhz = mx6sl_sd3_200mhz;
+ sd_pads_100mhz = mx6sl_sd3_100mhz;
+ sd_pads_50mhz = mx6sl_sd3_50mhz;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd3_200mhz);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd3_100mhz);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd3_50mhz);
+ break;
+ case 3:
+ sd_pads_200mhz = mx6sl_brd_ntx_sd4_pads;
+ sd_pads_100mhz = mx6sl_brd_ntx_sd4_pads;
+ sd_pads_50mhz = mx6sl_brd_ntx_sd4_pads;
+
+ sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_brd_ntx_sd4_pads);
+ sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_brd_ntx_sd4_pads);
+ sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_brd_ntx_sd4_pads);
+ break;
+
+ default:
+ printk(KERN_ERR "no such SD host controller index %d\n", index);
+ return -EINVAL;
+ }
+
+ if (clock > 100000000) {
+ if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_200mhz);
+ pad_mode = SD_PAD_MODE_HIGH_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
+ sd_pads_200mhz_cnt);
+ } else if (clock > 52000000) {
+ if (pad_mode == SD_PAD_MODE_MED_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_100mhz);
+ pad_mode = SD_PAD_MODE_MED_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
+ sd_pads_100mhz_cnt);
+ } else {
+ if (pad_mode == SD_PAD_MODE_LOW_SPEED)
+ return 0;
+ BUG_ON(!sd_pads_50mhz);
+ pad_mode = SD_PAD_MODE_LOW_SPEED;
+ return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
+ sd_pads_50mhz_cnt);
+ }
+}
+
+
+static const struct esdhc_platform_data mx6_ntx_isd_data __initconst = {
+ .always_present = 1,
+ .delay_line = 0,
+ .platform_pad_change = plt_sd_pad_change,
+ .cd_type = ESDHC_CD_PERMANENT,
+};
+static const struct esdhc_platform_data mx6_ntx_isd8bits_data __initconst = {
+ .always_present = 1,
+ .delay_line = 0,
+ .support_8bit = 1,
+ .platform_pad_change = plt_sd_pad_change,
+ .cd_type = ESDHC_CD_PERMANENT,
+};
+
+static const struct esdhc_platform_data mx6_ntx_sd_wifi_data __initconst = {
+ .cd_gpio = MX6SL_WIFI_3V3,
+ .wp_gpio = -1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+// .platform_pad_change = plt_sd_pad_change,
+ .cd_type = ESDHC_CD_WIFI_PWR,
+};
+
+static const struct esdhc_platform_data mx6_ntx_q22_sd_wifi_data __initconst = {
+ .cd_gpio = IMX_GPIO_NR(4, 29),
+ .wp_gpio = -1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+// .platform_pad_change = plt_sd_pad_change,
+ .cd_type = ESDHC_CD_WIFI_PWR,
+};
+
+static const struct esdhc_platform_data mx6_ntx_esd_data __initconst = {
+ .cd_gpio = MX6SL_EXT_SD_CD,
+ .wp_gpio = -1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .platform_pad_change = plt_sd_pad_change,
+ .cd_type = ESDHC_CD_GPIO,
+};
+static const struct esdhc_platform_data mx6_ntx_esd_nocd_data __initconst = {
+ .always_present = 1,
+ .cd_gpio = 0,
+ .wp_gpio = -1,
+ .keep_power_at_suspend = 1,
+ .delay_line = 0,
+ .platform_pad_change = 0,
+ .cd_type = ESDHC_CD_PERMANENT,
+};
+
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+#if 0
+static struct regulator_consumer_supply ntx_vmmc_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.3"),
+};
+
+static struct regulator_init_data ntx_vmmc_init = {
+ .num_consumer_supplies = ARRAY_SIZE(ntx_vmmc_consumers),
+ .consumer_supplies = ntx_vmmc_consumers,
+};
+
+static struct fixed_voltage_config ntx_vmmc_reg_config = {
+ .supply_name = "vmmc",
+ .microvolts = 3300000,
+ .gpio = -1,
+ .init_data = &ntx_vmmc_init,
+};
+
+static struct platform_device ntx_vmmc_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &ntx_vmmc_reg_config,
+ },
+};
+#endif
+
+static struct regulator_consumer_supply display_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "DISPLAY",
+ },
+};
+
+static struct regulator_consumer_supply vcom_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "VCOM",
+ },
+};
+
+static struct regulator_consumer_supply v3p3_consumers[] = {
+ {
+ /* MAX17135 */
+ .supply = "V3P3",
+ },
+};
+
+static struct regulator_init_data max17135_init_data[] = {
+#if 0
+ {
+ .constraints = {
+ .name = "DISPLAY",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(display_consumers),
+ .consumer_supplies = display_consumers,
+ }, {
+ .constraints = {
+ .name = "GVDD",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "GVEE",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINN",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINP",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "VCOM",
+ .min_uV = mV_to_uV(-4325),
+ .max_uV = mV_to_uV(-500),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcom_consumers),
+ .consumer_supplies = vcom_consumers,
+ }, {
+ .constraints = {
+ .name = "VNEG",
+ .min_uV = V_to_uV(-15),
+ .max_uV = V_to_uV(-15),
+ },
+ }, {
+ .constraints = {
+ .name = "VPOS",
+ .min_uV = V_to_uV(15),
+ .max_uV = V_to_uV(15),
+ },
+ }, {
+ .constraints = {
+ .name = "V3P3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(v3p3_consumers),
+ .consumer_supplies = v3p3_consumers,
+ },
+#endif
+};
+
+static const struct anatop_thermal_platform_data
+ mx6sl_anatop_thermal_data __initconst = {
+ .name = "anatop_thermal",
+ };
+
+static struct platform_device max17135_sensor_device = {
+ .name = "max17135_sensor",
+ .id = 0,
+};
+
+static struct max17135_platform_data max17135_pdata __initdata = {
+ .vneg_pwrup = 1,
+ .gvee_pwrup = 1,
+ .vpos_pwrup = 2,
+ .gvdd_pwrup = 1,
+ .gvdd_pwrdn = 1,
+ .vpos_pwrdn = 2,
+ .gvee_pwrdn = 1,
+ .vneg_pwrdn = 1,
+ .gpio_pmic_pwrgood = MX6SL_BRD_EPDC_PWRSTAT,
+ .gpio_pmic_vcom_ctrl = MX6SL_BRD_EPDC_VCOM,
+ .gpio_pmic_wakeup = MX6SL_BRD_EPDC_PMIC_WAKE,
+ .gpio_pmic_v3p3 = MX6SL_BRD_EPDC_PWRCTRL0,
+ .gpio_pmic_intr = MX6SL_BRD_EPDC_PMIC_INT,
+ .regulator_init = max17135_init_data,
+ .init = max17135_regulator_init,
+};
+
+static int __init max17135_regulator_init(struct max17135 *max17135)
+{
+#if 0
+ struct max17135_platform_data *pdata = &max17135_pdata;
+ int i, ret;
+
+ max17135->gvee_pwrup = pdata->gvee_pwrup;
+ max17135->vneg_pwrup = pdata->vneg_pwrup;
+ max17135->vpos_pwrup = pdata->vpos_pwrup;
+ max17135->gvdd_pwrup = pdata->gvdd_pwrup;
+ max17135->gvdd_pwrdn = pdata->gvdd_pwrdn;
+ max17135->vpos_pwrdn = pdata->vpos_pwrdn;
+ max17135->vneg_pwrdn = pdata->vneg_pwrdn;
+ max17135->gvee_pwrdn = pdata->gvee_pwrdn;
+
+ max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup +
+ pdata->gvdd_pwrup + pdata->gvee_pwrup;
+
+ max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood;
+ max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl;
+ max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup;
+ max17135->gpio_pmic_v3p3 = pdata->gpio_pmic_v3p3;
+ max17135->gpio_pmic_intr = pdata->gpio_pmic_intr;
+
+ gpio_request(max17135->gpio_pmic_wakeup, "epdc-pmic-wake");
+ gpio_direction_output(max17135->gpio_pmic_wakeup, 0);
+
+ gpio_request(max17135->gpio_pmic_vcom_ctrl, "epdc-vcom");
+ gpio_direction_output(max17135->gpio_pmic_vcom_ctrl, 0);
+
+ gpio_request(max17135->gpio_pmic_v3p3, "epdc-v3p3");
+ gpio_direction_output(max17135->gpio_pmic_v3p3, 0);
+
+ gpio_request(max17135->gpio_pmic_intr, "epdc-pmic-int");
+ gpio_direction_input(max17135->gpio_pmic_intr);
+
+ gpio_request(max17135->gpio_pmic_pwrgood, "epdc-pwrstat");
+ gpio_direction_input(max17135->gpio_pmic_pwrgood);
+
+ max17135->vcom_setup = false;
+ max17135->init_done = false;
+
+ for (i = 0; i < MAX17135_NUM_REGULATORS; i++) {
+ ret = max17135_register_regulator(max17135, i,
+ &pdata->regulator_init[i]);
+ if (ret != 0) {
+ printk(KERN_ERR"max17135 regulator init failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /*
+ * TODO: We cannot enable full constraints for now, since
+ * it results in the PFUZE regulators being disabled
+ * at the end of boot, which disables critical regulators.
+ */
+ /*regulator_has_full_constraints();*/
+#endif
+ return 0;
+}
+
+static int mx6_ntx_spi_cs[] = {
+ MX6_BRD_ECSPI1_CS0,
+};
+
+static const struct spi_imx_master mx6_ntx_spi_data __initconst = {
+ .chipselect = mx6_ntx_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx6_ntx_spi_cs),
+};
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition m25p32_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x00100000,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data m25p32_spi_flash_data = {
+ .name = "m25p32",
+ .parts = m25p32_partitions,
+ .nr_parts = ARRAY_SIZE(m25p32_partitions),
+ .type = "m25p32",
+};
+
+static struct spi_board_info m25p32_spi0_board_info[] __initdata = {
+ {
+ /* The modalias must be the same as spi device driver name */
+ .modalias = "m25p80",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = &m25p32_spi_flash_data,
+ },
+};
+#endif
+
+static void spi_device_init(void)
+{
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+ spi_register_board_info(m25p32_spi0_board_info,
+ ARRAY_SIZE(m25p32_spi0_board_info));
+#endif
+}
+
+static struct imx_ssi_platform_data mx6_sabresd_ssi_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_SYN,
+};
+
+#if 0
+static struct mxc_audio_platform_data wm8962_data;
+
+static struct platform_device mx6_sabresd_audio_wm8962_device = {
+ .name = "imx-wm8962",
+};
+
+static struct wm8962_pdata wm8962_config_data = {
+
+};
+
+static int wm8962_clk_enable(int enable)
+{
+ if (enable)
+ clk_enable(ntx_extern_audio_root);
+ else
+ clk_disable(ntx_extern_audio_root);
+
+ return 0;
+}
+
+static int mxc_wm8962_init(void)
+{
+ struct clk *pll4;
+ int rate;
+
+ ntx_extern_audio_root = clk_get(NULL, "extern_audio_clk");
+ if (IS_ERR(ntx_extern_audio_root)) {
+ pr_err("can't get ntx_extern_audio_root clock.\n");
+ return PTR_ERR(ntx_extern_audio_root);
+ }
+
+ pll4 = clk_get(NULL, "pll4");
+ if (IS_ERR(pll4)) {
+ pr_err("can't get pll4 clock.\n");
+ return PTR_ERR(pll4);
+ }
+
+ clk_set_parent(ntx_extern_audio_root, pll4);
+
+ rate = clk_round_rate(ntx_extern_audio_root, 26000000);
+ clk_set_rate(ntx_extern_audio_root, rate);
+
+ wm8962_data.sysclk = rate;
+ /* set AUDMUX pads to 1.8v */
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_MCLK,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_RXD,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXC,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXD,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+ mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXFS,
+ PAD_CTL_LVE, PAD_CTL_LVE_MASK);
+
+ return 0;
+}
+
+static struct mxc_audio_platform_data wm8962_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_gpio = MX6_BRD_HEADPHONE_DET,
+ .hp_active_low = 1,
+ .mic_gpio = -1,
+ .mic_active_low = 1,
+ .init = mxc_wm8962_init,
+ .clock_enable = wm8962_clk_enable,
+};
+
+static struct regulator_consumer_supply sabresd_vwm8962_consumers[] = {
+ REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
+ REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+};
+
+static struct regulator_init_data sabresd_vwm8962_init = {
+ .constraints = {
+ .name = "SPKVDD",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sabresd_vwm8962_consumers),
+ .consumer_supplies = sabresd_vwm8962_consumers,
+};
+
+static struct fixed_voltage_config sabresd_vwm8962_reg_config = {
+ .supply_name = "SPKVDD",
+ .microvolts = 4325000,
+ .gpio = -1,
+ .enabled_at_boot = 1,
+ .init_data = &sabresd_vwm8962_init,
+};
+
+static struct platform_device sabresd_vwm8962_reg_devices = {
+ .name = "reg-fixed-voltage",
+ .id = 4,
+ .dev = {
+ .platform_data = &sabresd_vwm8962_reg_config,
+ },
+};
+
+static int __init imx6q_init_audio(void)
+{
+ platform_device_register(&sabresd_vwm8962_reg_devices);
+ mxc_register_device(&mx6_sabresd_audio_wm8962_device,
+ &wm8962_data);
+ imx6q_add_imx_ssi(1, &mx6_sabresd_ssi_pdata);
+
+ return 0;
+}
+
+static int spdif_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long rate_actual;
+ rate_actual = clk_round_rate(clk, rate);
+ clk_set_rate(clk, rate_actual);
+ return 0;
+}
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = 1,
+ .spdif_clk_48000 = -1,
+ .spdif_div_44100 = 23,
+ .spdif_clk_set_rate = spdif_clk_set_rate,
+ .spdif_clk = NULL,
+};
+#endif
+
+
+enum DISPLAY_PANEL_MODE {
+ PANEL_MODE_LCD,
+ PANEL_MODE_HDMI,
+ PANEL_MODE_EINK,
+};
+
+static int display_panel_mode = PANEL_MODE_EINK;
+
+#if 0
+static iomux_v3_cfg_t mx6sl_sii902x_hdmi_pads_enabled[] = {
+ MX6SL_PAD_LCD_RESET__GPIO_2_19,
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10,
+};
+
+static int sii902x_get_pins(void)
+{
+ /* Sii902x HDMI controller */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_sii902x_hdmi_pads_enabled, \
+ ARRAY_SIZE(mx6sl_sii902x_hdmi_pads_enabled));
+
+ /* Reset Pin */
+ gpio_request(MX6_BRD_LCD_RESET, "disp0-reset");
+ gpio_direction_output(MX6_BRD_LCD_RESET, 1);
+
+ /* Interrupter pin GPIO */
+ gpio_request(MX6SL_BRD_EPDC_PWRCTRL3, "disp0-detect");
+ gpio_direction_input(MX6SL_BRD_EPDC_PWRCTRL3);
+ return 1;
+}
+
+static void sii902x_put_pins(void)
+{
+ gpio_free(MX6_BRD_LCD_RESET);
+ gpio_free(MX6SL_BRD_EPDC_PWRCTRL3);
+}
+
+static void sii902x_hdmi_reset(void)
+{
+ gpio_set_value(MX6_BRD_LCD_RESET, 0);
+ msleep(10);
+ gpio_set_value(MX6_BRD_LCD_RESET, 1);
+ msleep(10);
+}
+
+static struct fsl_mxc_lcd_platform_data sii902x_hdmi_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .reset = sii902x_hdmi_reset,
+ .get_pins = sii902x_get_pins,
+ .put_pins = sii902x_put_pins,
+};
+
+static void mx6sl_csi_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_csi_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_csi_enable_pads));
+
+ /* Camera reset */
+ gpio_request(MX6SL_BRD_CSI_RST, "cam-reset");
+ gpio_direction_output(MX6SL_BRD_CSI_RST, 1);
+
+ /* Camera power down */
+ gpio_request(MX6SL_BRD_CSI_PWDN, "cam-pwdn");
+ gpio_direction_output(MX6SL_BRD_CSI_PWDN, 1);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 0);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_RST, 0);
+ msleep(1);
+ gpio_set_value(MX6SL_BRD_CSI_RST, 1);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 1);
+}
+
+static void mx6sl_csi_cam_powerdown(int powerdown)
+{
+ if (powerdown)
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 1);
+ else
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 0);
+
+ msleep(2);
+}
+
+static struct fsl_mxc_camera_platform_data camera_data = {
+ .mclk = 24000000,
+ .io_init = mx6sl_csi_io_init,
+ .pwdn = mx6sl_csi_cam_powerdown,
+ .core_regulator = "VGEN2_1V5",
+ .analog_regulator = "VGEN6_2V8",
+};
+#endif
+
+static struct imxi2c_platform_data mx6_ntx_i2c0_data = {
+ .bitrate = 100000,
+};
+
+static struct imxi2c_platform_data mx6_ntx_i2c1_data = {
+ .bitrate = 100000,
+};
+
+static struct imxi2c_platform_data mx6_ntx_i2c2_data = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info i2c_zforce_ir_touch_binfo = {
+ .type = "zforce-ir-touch",
+ .addr = 0x50,
+ //.platform_data = MX6SL_IR_TOUCH_INT,
+ //.irq = gpio_to_irq(MX6SL_IR_TOUCH_INT),
+};
+
+static struct i2c_board_info i2c_elan_touch_binfo = {
+ .type = "elan-touch",
+ .addr = 0x15,
+};
+
+int ricoh619_init_port(int irq_num)
+{
+ printk("[%s-%d] ...\n",__func__,__LINE__);
+ return 0;
+}
+
+static struct ricoh619_rtc_platform_data ricoh_rtc_data = {
+ .time = {
+ .tm_year = 1970,
+ .tm_mon = 0,
+ .tm_mday = 1,
+ .tm_hour = 0,
+ .tm_min = 0,
+ .tm_sec = 0,
+ },
+};
+
+static struct ricoh619_battery_platform_data ricoh_battery_data = {
+// .irq = RICOH619_IRQ_BASE,
+ .alarm_vol_mv = 3400,
+ // .adc_channel = RICOH619_ADC_CHANNEL_VBAT,
+ .multiple = 100, //100%
+ .monitor_time = 60,
+ /* some parameter is depend of battery type */
+ .type[0] = {
+ .ch_vfchg = 0xFF, /* VFCHG = 0 - 4 (4.05v, 4.10v, 4.15v, 4.20v, 4.35v) */
+ .ch_vrchg = 0xFF, /* VRCHG = 0 - 4 (3.85v, 3.90v, 3.95v, 4.00v, 4.10v) */
+ .ch_vbatovset = 0xFF, /* VBATOVSET = 0 or 1 (0 : 4.38v(up)/3.95v(down) 1: 4.53v(up)/4.10v(down)) */
+ .ch_ichg = 0xFF, /* ICHG = 0 - 0x1D (100mA - 3000mA) */
+ .ch_ilim_adp = 0xFF, /* ILIM_ADP = 0 - 0x1D (100mA - 3000mA) */
+ .ch_ilim_usb = 0xFF, /* ILIM_USB = 0 - 0x1D (100mA - 3000mA) */
+ .ch_icchg = 0, /* ICCHG = 0 - 3 (50mA 100mA 150mA 200mA) */
+ .fg_target_vsys = 0, /* This value is the target one to DSOC=0% */
+ .fg_target_ibat = 0, /* This value is the target one to DSOC=0% */
+ .fg_poff_vbat = 3520, /* setting value of 0 per Vbat */
+ .jt_en = 0, /* JEITA Enable = 0 or 1 (1:enable, 0:disable) */
+ .jt_hw_sw = 1, /* JEITA HW or SW = 0 or 1 (1:HardWare, 0:SoftWare) */
+ .jt_temp_h = 50, /* degree C */
+ .jt_temp_l = 12, /* degree C */
+ .jt_vfchg_h = 0x03, /* VFCHG High = 0 - 4 (4.05v, 4.10v, 4.15v, 4.20v, 4.35v) */
+ .jt_vfchg_l = 0, /* VFCHG High = 0 - 4 (4.05v, 4.10v, 4.15v, 4.20v, 4.35v) */
+ .jt_ichg_h = 0x0D, /* VFCHG Low = 0 - 4 (4.05v, 4.10v, 4.15v, 4.20v, 4.35v) */
+ .jt_ichg_l = 0x09, /* ICHG Low = 0 - 0x1D (100mA - 3000mA) */
+ },
+ /*
+ .type[1] = {
+ .ch_vfchg = 0x0,
+ .ch_vrchg = 0x0,
+ .ch_vbatovset = 0x0,
+ .ch_ichg = 0x0,
+ .ch_ilim_adp = 0x0,
+ .ch_ilim_usb = 0x0,
+ .ch_icchg = 0x00,
+ .fg_target_vsys = 3300,//3000,
+ .fg_target_ibat = 1000,//1000,
+ .jt_en = 0,
+ .jt_hw_sw = 1,
+ .jt_temp_h = 40,
+ .jt_temp_l = 10,
+ .jt_vfchg_h = 0x0,
+ .jt_vfchg_l = 0,
+ .jt_ichg_h = 0x01,
+ .jt_ichg_l = 0x01,
+ },
+ */
+
+/* JEITA Parameter
+*
+* VCHG
+* |
+* jt_vfchg_h~+~~~~~~~~~~~~~~~~~~~+
+* | |
+* jt_vfchg_l-| - - - - - - - - - +~~~~~~~~~~+
+* | Charge area + |
+* -------0--+-------------------+----------+--- Temp
+* ! +
+* ICHG
+* | +
+* jt_ichg_h-+ - -+~~~~~~~~~~~~~~+~~~~~~~~~~+
+* + | + |
+* jt_ichg_l-+~~~~+ Charge area |
+* | + + |
+* 0--+----+--------------+----------+--- Temp
+* 0 jt_temp_l jt_temp_h 55
+*/
+};
+
+#define RICOH_REG(_id, _name, _sname) \
+{ \
+ .id = RICOH619_ID_##_id, \
+ .name = "ricoh61x-regulator", \
+ .platform_data = &pdata_##_name##_##_sname, \
+}
+
+static struct regulator_consumer_supply ricoh619_dc1_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_core2_1v3_soc", NULL),
+};
+static struct regulator_consumer_supply ricoh619_dc2_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_core1_3v3", NULL),
+};
+static struct regulator_consumer_supply ricoh619_dc3_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_core2_1v3_arm", NULL),
+};
+static struct regulator_consumer_supply ricoh619_dc4_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_core4_1v2", NULL),
+};
+static struct regulator_consumer_supply ricoh619_dc5_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_core4_1v8", NULL),
+};
+static struct regulator_consumer_supply ricoh619_ldo1_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_ir_3v3", NULL),
+};
+static struct regulator_consumer_supply ricoh619_ldo2_supply_0[] = {
+};
+static struct regulator_consumer_supply ricoh619_ldo3_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_core5_1v2", NULL),
+};
+static struct regulator_consumer_supply ricoh619_ldo4_supply_0[] = {
+};
+static struct regulator_consumer_supply ricoh619_ldo5_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_spd_3v3", NULL),
+// REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.3"),
+};
+static struct regulator_consumer_supply ricoh619_ldo6_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_ddr_0v6", NULL),
+};
+static struct regulator_consumer_supply ricoh619_ldo7_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_pwm", "0-0007"),
+ REGULATOR_SUPPLY("vdd_fl_0_pwm", "0-0043"),
+ REGULATOR_SUPPLY("vdd_fl_pwm", "2-0043"),
+};
+static struct regulator_consumer_supply ricoh619_ldo8_supply_0[] = {
+ REGULATOR_SUPPLY("ldo_1v8", NULL),
+};
+static struct regulator_consumer_supply ricoh619_ldo9_supply_0[] = {
+};
+static struct regulator_consumer_supply ricoh619_ldo10_supply_0[] = {
+};
+static struct regulator_consumer_supply ricoh619_ldortc1_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_rtc_3v3", NULL),
+};
+static struct regulator_consumer_supply ricoh619_ldortc2_supply_0[] = {
+};
+
+#define RICOH_PDATA_INIT(_name, _sname, _minmv, _maxmv, _supply_reg, _always_on, \
+ _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, _flags, \
+ _ext_contol, _sleep_mV) \
+ static struct ricoh619_regulator_platform_data pdata_##_name##_##_sname = \
+ { \
+ .regulator = { \
+ .constraints = { \
+ .min_uV = (_minmv)*1000, \
+ .max_uV = (_maxmv)*1000, \
+ .valid_modes_mask = (REGULATOR_MODE_NORMAL | \
+ REGULATOR_MODE_STANDBY), \
+ .valid_ops_mask = (REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_STATUS | \
+ REGULATOR_CHANGE_VOLTAGE), \
+ .always_on = _always_on, \
+ .boot_on = _boot_on, \
+ .apply_uV = _apply_uv, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(ricoh619_##_name##_supply_##_sname), \
+ .consumer_supplies = ricoh619_##_name##_supply_##_sname, \
+ .supply_regulator = _supply_reg, \
+ }, \
+ .init_uV = _init_uV * 1000, \
+ .init_enable = _init_enable, \
+ .init_apply = _init_apply, \
+ .sleep_uV = (_sleep_mV)*1000, \
+ .flags = _flags, \
+ .ext_pwr_req = _ext_contol, \
+ }
+
+RICOH_PDATA_INIT(dc1, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 950); // Core2_1V3
+RICOH_PDATA_INIT(dc2, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 0); // Core3_3V3
+RICOH_PDATA_INIT(dc3, 0, 950, 1425, 0, 1, 1, 0, 1425, 1, 1, 0, 0, 950); // Core2_1V3_ARM
+RICOH_PDATA_INIT(dc4, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 0); // Core4_1V2
+RICOH_PDATA_INIT(dc5, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 0); // Core4_1V8
+
+RICOH_PDATA_INIT(ldo1, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 0); // IR_3V3
+RICOH_PDATA_INIT(ldo2, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 0); // Core1_3V3*
+RICOH_PDATA_INIT(ldo3, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 0); // Core5_1V2
+RICOH_PDATA_INIT(ldo4, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0); // Reserved
+RICOH_PDATA_INIT(ldo5, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 0); // SPD_3V3
+RICOH_PDATA_INIT(ldo6, 0, 0, 0, 0, 1, 1, 0, -1, 1, 1, 0, 0, 0); // DDR_0V6
+RICOH_PDATA_INIT(ldo7, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0); // VDD_PWM
+RICOH_PDATA_INIT(ldo8, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0); // ldo_1v8
+//RICOH_PDATA_INIT(ldo8, 0, 3300, 3300, 0, 1, 1, 0, 3300, 1, 1, 0, 0, 3300); // ldo_1v8 output 3V3
+RICOH_PDATA_INIT(ldo9, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0); // Reserved
+RICOH_PDATA_INIT(ldo10, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0); // Reserved
+RICOH_PDATA_INIT(ldortc1, 0,0, 0, 0, 1, 1, 0, -1, 1, 1, -1, -1, -1);
+RICOH_PDATA_INIT(ldortc2, 0,0, 0, 0, 0, 0, 0, -1, 0, 1, -1, -1, -1);
+
+#define RICOH619_DEV_REG \
+ RICOH_REG(DC1, dc1, 0), \
+ RICOH_REG(DC2, dc2, 0), \
+ RICOH_REG(DC3, dc3, 0), \
+ RICOH_REG(DC4, dc4, 0), \
+ RICOH_REG(DC5, dc5, 0), \
+ RICOH_REG(LDO1, ldo1, 0), \
+ RICOH_REG(LDO2, ldo2, 0), \
+ RICOH_REG(LDO3, ldo3, 0), \
+ RICOH_REG(LDO4, ldo4, 0), \
+ RICOH_REG(LDO5, ldo5, 0), \
+ RICOH_REG(LDO6, ldo6, 0), \
+ RICOH_REG(LDO7, ldo7, 0), \
+ RICOH_REG(LDO8, ldo8, 0), \
+ RICOH_REG(LDO9, ldo9, 0), \
+ RICOH_REG(LDO10, ldo10, 0), \
+ RICOH_REG(LDORTC1, ldortc1, 0), \
+ RICOH_REG(LDORTC2, ldortc2, 0)
+
+struct ricoh619_subdev_info ricoh619_sub_data[] = {
+ RICOH619_DEV_REG,
+ {
+ .name = "ricoh619-battery",
+ .id = -1,
+ .platform_data = &ricoh_battery_data,
+ },
+ {
+ .name = "rtc_ricoh619",
+ .id = 0,
+ .platform_data = &ricoh_rtc_data,
+ },
+};
+
+
+#define RICOH_GPIO_INIT(_init_apply, _output_mode, _output_val, _led_mode, _led_func) \
+ { \
+ .output_mode_en = _output_mode, \
+ .output_val = _output_val, \
+ .init_apply = _init_apply, \
+ .led_mode = _led_mode, \
+ .led_func = _led_func, \
+ }
+struct ricoh619_gpio_init_data ricoh_gpio_data[] = {
+ RICOH_GPIO_INIT(false, false, 0, 0, 0),
+ RICOH_GPIO_INIT(false, false, 0, 0, 0),
+ RICOH_GPIO_INIT(false, false, 0, 0, 0),
+ RICOH_GPIO_INIT(false, false, 0, 0, 0),
+};
+
+static struct ricoh619_platform_data ntx_ricoh_data = {
+ .num_subdevs = ARRAY_SIZE(ricoh619_sub_data),
+ .subdevs = ricoh619_sub_data,
+ .gpio_base = 7*32,
+ .gpio_init_data = ricoh_gpio_data,
+ .num_gpioinit_data = ARRAY_SIZE(ricoh_gpio_data),
+ .enable_shutdown_pin = true,
+};
+
+static struct i2c_board_info i2c_sysmp_ricoh619_binfo = {
+ .type = "ricoh619",
+ .addr = 0x32,
+ .platform_data = &ntx_ricoh_data,
+};
+
+static struct i2c_board_info i2c_sysmp_msp430_binfo = {
+ .type = "msp430",
+ .addr = 0x43,
+ //.irq = gpio_to_irq(MX6SL_MSP_INT),
+};
+
+static struct i2c_board_info i2c_ht68f20_binfo = {
+ .type = "ht68f20",
+ .addr = 0x07,
+};
+
+static struct i2c_board_info i2c_kl25_binfo = {
+ .type = "kl25",
+ .addr = 0x5A,
+ .irq = gpio_to_irq(MX6SL_KL25_INT2),
+};
+
+static struct i2c_board_info i2c_mma8652_binfo = {
+ .type = "mma8652",
+ .addr = 0x1D,
+ .irq = gpio_to_irq(MX6SL_KL25_INT2),
+};
+
+static struct i2c_board_info i2c_wacom_binfo = {
+ .type = "wacom_i2c",
+ .addr = 0x09,
+ .irq = gpio_to_irq(MX6SL_WACOM_INT),
+};
+
+static struct i2c_board_info __initdata i2c_waltop_binfo = {
+ .type = "waltop_i2c",
+ .addr = 0x37,
+ .platform_data = MX6SL_WALTOP_RST,
+ .irq = gpio_to_irq(MX6SL_WALTOP_INT),
+};
+#if 0
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+};
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+#if 0
+ {
+ I2C_BOARD_INFO("ov5640", 0x3c),
+ .platform_data = (void *)&camera_data,
+ },
+#endif
+ {
+ .type = "msp430",
+ .addr = 0x43,
+ .irq = gpio_to_irq(MX6SL_MSP_INT),
+ },
+};
+#endif
+
+static struct ntx_misc_platform_data ntx_misc_info;
+
+static struct platform_device ntx_charger = {
+ .name = "pmic_battery",
+ .id = 1,
+ .dev = {
+ .platform_data = &ntx_misc_info,
+ }
+};
+
+static struct platform_device ntx_light_ldm = {
+ .name = "pmic_light",
+ .id = 1,
+};
+
+static struct mxc_dvfs_platform_data mx6sl_ntx_dvfscore_data = {
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+ .reg_id = "VDDCORE",
+ .soc_id = "VDDSOC",
+#else
+ .reg_id = "cpu_vddgp",
+ .soc_id = "cpu_vddsoc",
+ .pu_id = "cpu_vddvpu",
+#endif
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+};
+
+static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
+ .reserved_mem_size = SZ_32M,
+};
+
+void __init early_console_setup(unsigned long base, struct clk *clk);
+
+static const struct imxuart_platform_data mx6sl_ntx_uart1_data __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS | IMXUART_SDMA,
+ .dma_req_rx = MX6Q_DMA_REQ_UART2_RX,
+ .dma_req_tx = MX6Q_DMA_REQ_UART2_TX,
+};
+
+static inline void mx6_ntx_init_uart(void)
+{
+ imx6q_add_imx_uart(0, NULL); /* DEBUG UART1 */
+}
+
+#if 0
+static int mx6sl_ntx_fec_phy_init(struct phy_device *phydev)
+{
+ int val;
+
+ /* power on FEC phy and reset phy */
+ gpio_request(MX6_BRD_FEC_PWR_EN, "fec-pwr");
+ gpio_direction_output(MX6_BRD_FEC_PWR_EN, 0);
+ /* wait RC ms for hw reset */
+ msleep(1);
+ gpio_direction_output(MX6_BRD_FEC_PWR_EN, 1);
+
+ /* check phy power */
+ val = phy_read(phydev, 0x0);
+ if (val & BMCR_PDOWN)
+ phy_write(phydev, 0x0, (val & ~BMCR_PDOWN));
+
+ return 0;
+}
+
+static struct fec_platform_data fec_data __initdata = {
+ .init = mx6sl_ntx_fec_phy_init,
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+#endif
+
+static int epdc_get_pins(void)
+{
+ int ret = 0;
+
+ /* Claim GPIOs for EPDC pins - used during power up/down */
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "epdc_d0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "epdc_d1");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "epdc_d2");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "epdc_d3");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "epdc_d4");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "epdc_d5");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "epdc_d6");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "epdc_d7");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_8 , "epdc_d8");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_9 , "epdc_d9");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_10, "epdc_d10");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_11, "epdc_d11");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_12, "epdc_d12");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_13, "epdc_d13");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_14, "epdc_d14");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_15, "epdc_d15");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "epdc_gdclk");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "epdc_gdsp");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "epdc_gdoe");
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDRL, "epdc_gdrl");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "epdc_sdclk");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDOE, "epdc_sdoe");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "epdc_sdle");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "epdc_sdshr");
+ ret |= gpio_request(MX6SL_BRD_EPDC_BDR0, "epdc_bdr0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "epdc_sdce0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "epdc_sdce1");
+// ret |= gpio_request(MX6SL_BRD_EPDC_SDCE2, "epdc_sdce2");
+
+ return ret;
+}
+
+static void epdc_put_pins(void)
+{
+ gpio_free(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_7);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_8);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_11);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_12);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_13);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_14);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_15);
+ gpio_free(MX6SL_BRD_EPDC_GDCLK);
+ gpio_free(MX6SL_BRD_EPDC_GDSP);
+ gpio_free(MX6SL_BRD_EPDC_GDOE);
+ gpio_free(MX6SL_BRD_EPDC_GDRL);
+ gpio_free(MX6SL_BRD_EPDC_SDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDOE);
+ gpio_free(MX6SL_BRD_EPDC_SDLE);
+ gpio_free(MX6SL_BRD_EPDC_SDSHR);
+ gpio_free(MX6SL_BRD_EPDC_BDR0);
+ gpio_free(MX6SL_BRD_EPDC_SDCE0);
+ gpio_free(MX6SL_BRD_EPDC_SDCE1);
+// gpio_free(MX6SL_BRD_EPDC_SDCE2);
+}
+
+static void mxc_pads_lve_setup(iomux_v3_cfg_t *pad_list, unsigned count,int iIsLVE)
+{
+ iomux_v3_cfg_t tPadctrlOld;
+ iomux_v3_cfg_t tPadctrl;
+ iomux_v3_cfg_t *p = pad_list;
+
+ int i;
+
+ for(i=0;i<count;i++) {
+ tPadctrlOld = tPadctrl = *p ;
+
+#if 0
+ if(tPadctrl&NO_PAD_CTRL) {
+ mxc_iomux_v3_get_pad(&tPadctrlOld);
+ tPadctrl = tPadctrlOld;
+ //tPadctrl &= ~((iomux_v3_cfg_t)NO_PAD_CTRL<<MUX_PAD_CTRL_SHIFT);
+ }
+#endif
+
+ if(iIsLVE) {
+ tPadctrl |= ((iomux_v3_cfg_t)PAD_CTL_LVE<<MUX_PAD_CTRL_SHIFT);
+ }
+ else {
+ tPadctrl &= ~((iomux_v3_cfg_t)PAD_CTL_LVE<<MUX_PAD_CTRL_SHIFT);
+ }
+
+ #if 0
+ printk("PAD LVE 0x%llx:0x%llx->0x%llx \n",
+ pad_list[i],tPadctrlOld,tPadctrl);
+ #endif
+
+ mxc_iomux_v3_setup_pad(tPadctrl);
+ p++;
+ }
+}
+
+
+
+
+
+static void epdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable EPDC use */
+
+ if(NTXHWCFG_TST_FLAG(gptHWCFG->m_val.bPCB_Flags,4)) {
+ // Panel is designed for low voltage .
+ mxc_pads_lve_setup(mx6sl_brd_epdc_enable_pads,\
+ ARRAY_SIZE(mx6sl_brd_epdc_enable_pads),1);
+ }
+ else {
+#if 0
+ mxc_pads_lve_setup(mx6sl_brd_epdc_enable_pads,\
+ ARRAY_SIZE(mx6sl_brd_epdc_enable_pads),0);
+#else
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_epdc_enable_pads));
+#endif
+
+ }
+
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7);
+ //if( 1==gptHWCFG->m_val.bDisplayBusWidth ||
+ // 3==gptHWCFG->m_val.bDisplayBusWidth)
+ {
+ // 16 bits .
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_8);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_11);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_12);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_13);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_14);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_15);
+ }
+ gpio_direction_input(MX6SL_BRD_EPDC_GDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDSP);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDRL);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDLE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDSHR);
+ gpio_direction_input(MX6SL_BRD_EPDC_BDR0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE1);
+// gpio_direction_input(MX6SL_BRD_EPDC_SDCE2);
+}
+
+static void epdc_disable_pins(void)
+{
+ /* Configure MUX settings for EPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_disable_pads, \
+ ARRAY_SIZE(mx6sl_brd_epdc_disable_pads));
+
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0);
+ //if( 1==gptHWCFG->m_val.bDisplayBusWidth ||
+ // 3==gptHWCFG->m_val.bDisplayBusWidth)
+ {
+ // 16 bits .
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_8, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_9, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_10, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_11, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_12, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_13, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_14, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_15, 0);
+ }
+ gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDRL, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_BDR0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0);
+// gpio_direction_output(MX6SL_BRD_EPDC_SDCE2, 0);
+}
+
+#if 1 //[
+static struct fb_videomode ed060scq_mode = {
+.name = "E60SCQ",
+.refresh = 85,
+.xres = 800,
+.yres = 600,
+.pixclock = 25000000,
+.left_margin = 8,
+.right_margin = 60,
+.upper_margin = 4,
+.lower_margin = 10,
+.hsync_len = 8,
+.vsync_len = 4,
+.sync = 0,
+.vmode = FB_VMODE_NONINTERLACED,
+.flag = 0,
+};
+
+static struct fb_videomode ed060sc8_mode = {
+.name = "E60SC8",
+.refresh = 85,
+.xres = 800,
+.yres = 600,
+.pixclock = 30000000,
+.left_margin = 8,
+.right_margin = 164,
+.upper_margin = 4,
+.lower_margin = 18,
+.hsync_len = 4,
+.vsync_len = 1,
+.sync = 0,
+.vmode = FB_VMODE_NONINTERLACED,
+.flag = 0,
+};
+
+// for ED060XC5 release by Freescale Grace 20120726 .
+
+static struct fb_videomode ed060xc1_mode = {
+.name = "E60XC1",
+.refresh = 85,
+.xres = 1024,
+.yres = 768,
+.pixclock = 40000000,
+.left_margin = 12,
+.right_margin = 72,
+.upper_margin = 4,
+.lower_margin = 5,
+.hsync_len = 8,
+.vsync_len = 2,
+.sync = 0,
+.vmode = FB_VMODE_NONINTERLACED,
+.flag = 0,
+};
+
+static struct fb_videomode ed060xc5_mode = {
+.name = "E60XC5",
+.refresh = 85,
+.xres = 1024,
+.yres = 758,
+.pixclock = 40000000,
+.left_margin = 12,
+.right_margin = 76,
+.upper_margin = 4,
+.lower_margin = 5,
+.hsync_len = 12,
+.vsync_len = 2,
+.sync = 0,
+.vmode = FB_VMODE_NONINTERLACED,
+.flag = 0,
+};
+
+static struct fb_videomode e60_v110_mode = {
+.name = "E60_V110",
+.refresh = 50,
+.xres = 800,
+.yres = 600,
+.pixclock = 18604700,
+.left_margin = 8,
+.right_margin = 176,
+.upper_margin = 4,
+.lower_margin = 2,
+.hsync_len = 4,
+.vsync_len = 1,
+.sync = 0,
+.vmode = FB_VMODE_NONINTERLACED,
+.flag = 0,
+};
+
+static struct fb_videomode ed050xxx_mode = {
+ .name="ED050XXXX",
+ .refresh=85,
+ .xres=800,
+ .yres=600,
+ .pixclock=26666667,
+ .left_margin=4,
+ .right_margin=98,
+ .upper_margin=4,
+ .lower_margin=9,
+ .hsync_len=8,
+ .vsync_len=2,
+ .sync=0,
+ .vmode=FB_VMODE_NONINTERLACED,
+ .flag=0,
+};
+
+
+#ifdef EPD_TIMING_ED068TG1 //[
+static struct fb_videomode ed068tg1_mode = {
+.name = "ED068TG1",
+.refresh=85,
+.xres=1440,
+.yres=1080,
+.pixclock=96000000,
+.left_margin=24,
+.right_margin=267,
+.upper_margin=4,
+.lower_margin=5,
+.hsync_len=24,
+.vsync_len=2,
+.sync=0,
+.vmode=FB_VMODE_NONINTERLACED,
+.flag=0,
+};
+#elif defined(EPD_TIMING_ED068OG1_NUMCE3) //][
+/* i.MX508 waveform data timing data structures for ed068og1_numce3 */
+/* Created on - Monday, October 15, 2012 10:36:24
+ Warning: this pixel clock is derived from 480 MHz parent! */
+
+static struct fb_videomode ed068og1_numce3_mode = {
+.name="ED068OG1_NUMCE3",
+.refresh=85,
+.xres=1440,
+.yres=1080,
+.pixclock=96000000,
+.left_margin=24,
+.right_margin=267,
+.upper_margin=4,
+.lower_margin=5,
+.hsync_len=24,
+.vsync_len=2,
+.sync=0,
+.vmode=FB_VMODE_NONINTERLACED,
+.flag=0,
+};
+#else
+static struct fb_videomode ed068og1_mode = {
+.name = "E68OG1",
+.refresh=85,
+.xres=1440,
+.yres=1080,
+.pixclock=120000000,
+.left_margin=32,
+.right_margin=508,
+.upper_margin=4,
+.lower_margin=5,
+.hsync_len=32,
+.vsync_len=2,
+.sync=0,
+.vmode=FB_VMODE_NONINTERLACED,
+.flag=0,
+};
+#endif//]EPD_TIMING_ED068OG1_NUMCE3
+
+static struct fb_videomode peng060d_mode = {
+.name = "PENG060D",
+.refresh=85,
+.xres=1448,
+.yres=1072,
+.pixclock=80000000,
+.left_margin=16,
+.right_margin=102,
+.upper_margin=4,
+.lower_margin=4,
+.hsync_len=28,
+.vsync_len=2,
+.sync=0,
+.vmode=FB_VMODE_NONINTERLACED,
+.flag=0,
+};
+
+static struct fb_videomode ef133ut1sce_mode = {
+.name="EF133UT1SCE",
+.refresh=65,
+.xres=1600,
+.yres=1200,
+.pixclock=72222223,
+.left_margin=8,
+.right_margin=97,
+.upper_margin=4,
+.lower_margin=7,
+.hsync_len=12,
+.vsync_len=1,
+.sync=0,
+.vmode=FB_VMODE_NONINTERLACED,
+.flag=0,
+};
+
+
+
+static struct imx_epdc_fb_mode panel_modes[] = {
+////////////////////
+{
+& ed060sc8_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+465, /* gdclk_hp_offs */
+250, /* gdsp_offs changed delay to 8.3 uS */
+0, /* gdoe_offs */
+8, /* gdclk_offs changed delay to 4.5 SDCLK */
+1, /* num_ce */
+},
+
+////////////////////
+{
+& e60_v110_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+465, /* gdclk_hp_offs */
+250, /* gdsp_offs changed delay to 8.3 uS */
+0, /* gdoe_offs */
+8, /* gdclk_offs changed delay to 4.5 SDCLK */
+1, /* num_ce */
+},
+
+////////////////////
+{
+& ed060xc5_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+524, /* gdclk_hp_offs */
+25, /* gdsp_offs changed delay to 8.3 uS */
+0, /* gdoe_offs */
+19, /* gdclk_offs changed delay to 4.5 SDCLK */
+1, /* num_ce */
+},
+
+////////////////////
+{
+& ed060xc1_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+492, /* gdclk_hp_offs */
+29, /* gdsp_offs changed delay to 8.3 uS */
+0, /* gdoe_offs */
+23, /* gdclk_offs changed delay to 4.5 SDCLK */
+1, /* num_ce */
+},
+
+////////////////////
+{
+ &ed050xxx_mode, /* struct fb_videomode *mode */
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 420, /* GDCLK_HP */
+ 20, /* GDSP_OFF */
+ 0, /* GDOE_OFF */
+ 11, /* gdclk_offs */
+ 3, /* num_ce */
+},
+
+#ifdef EPD_TIMING_ED068TG1 //[
+{
+& ed068tg1_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+665, /* GDCLK_HP */
+718, /* GDSP_OFF */
+0, /* GDOE_OFF */
+199, /* gdclk_offs */
+1, /* num_ce */
+},
+#elif defined(EPD_TIMING_ED068OG1_NUMCE3)//][
+{
+& ed068og1_numce3_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+665, /* GDCLK_HP */
+210, /* GDSP_OFF */
+0, /* GDOE_OFF */
+199, /* gdclk_offs */
+3, /* num_ce */
+},
+#else//][ !EPD_TIMING_ED068OG1_NUMCE3
+{
+& ed068og1_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+831, /* GDCLK_HP */
+285, /* GDSP_OFF */
+0, /* GDOE_OFF */
+271, /* gdclk_offs */
+1, /* num_ce */
+},
+#endif//] EPD_TIMING_ED068OG1_NUMCE3
+
+{
+&peng060d_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+562, /* GDCLK_HP */
+664, /* GDSP_OFF */
+0, /* GDOE_OFF */
+227, /* gdclk_offs */
+3, /* num_ce */
+},
+{
+&ef133ut1sce_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+743, /* GDCLK_HP */
+475, /* GDSP_OFF */
+0, /* GDOE_OFF */
+15, /* gdclk_offs */
+1, /* num_ce */
+},
+{
+&ed060scq_mode,
+4, /* vscan_holdoff */
+10, /* sdoed_width */
+20, /* sdoed_delay */
+10, /* sdoez_width */
+20, /* sdoez_delay */
+438, /* GDCLK_HP */
+263, /* GDSP_OFF */
+0, /* GDOE_OFF */
+23, /* gdclk_offs */
+3, /* num_ce */
+},
+};
+
+
+#else //][!
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 30000000,
+ .left_margin = 8,
+ .right_margin = 164,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+};
+static struct fb_videomode e060scm_mode = {
+ .name = "E060SCM",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 26666667,
+ .left_margin = 8,
+ .right_margin = 100,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct imx_epdc_fb_mode panel_modes[] = {
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 465, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 9, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e060scm_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 419, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 5, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+#endif //]
+
+static struct imx_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+ .get_pins = epdc_get_pins,
+ .put_pins = epdc_put_pins,
+ .enable_pins = epdc_enable_pins,
+ .disable_pins = epdc_disable_pins,
+};
+
+typedef void (*usb_insert_handler) (char inserted);
+usb_insert_handler mxc_misc_report_usb;
+
+static void mxc_register_usb_plug(void* pk_cb)
+{
+ pmic_event_callback_t usb_plug_event;
+
+// usb_plug_event.param = (void *)1;
+// usb_plug_event.func = (void *)pk_cb;
+// pmic_event_subscribe(EVENT_VBUSVI, usb_plug_event);
+ if (gIsCustomerUi)
+ mxc_misc_report_usb = pk_cb;
+ DBG_MSG("%s(),pk_cb=%p\n",__FUNCTION__,pk_cb);
+
+}
+
+
+extern int mxc_usb_plug_getstatus (void);
+
+
+#define SW_USBPLUG 0x0C
+static struct usbplug_event_platform_data usbplug_data = {
+ .usbevent.type = EV_SW,
+ .usbevent.code = SW_USBPLUG,
+ .register_usbplugevent = mxc_register_usb_plug,
+ .get_key_status = mxc_usb_plug_getstatus,
+};
+
+struct platform_device mxc_usb_plug_device = {
+ .name = "usb_plug",
+ .id = 0,
+ };
+
+
+
+static int spdc_get_pins(void)
+{
+ int ret = 0;
+
+ /* Claim GPIOs for SPDC pins - used during power up/down */
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "SPDC_D0");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "SPDC_D1");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "SPDC_D2");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "SPDC_D3");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "SPDC_D4");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "SPDC_D5");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "SPDC_D6");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "SPDC_D7");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "SIPIX_YOE");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_9, "SIPIX_PWR_RDY");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "SIPIX_YDIO");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "SIPIX_YCLK");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "SIPIX_XDIO");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "SIPIX_LD");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "SIPIX_SOE");
+
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "SIPIX_XCLK");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_10, "SIPIX_SHD_N");
+ ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "SIPIX2_CE");
+
+ return ret;
+}
+
+static void spdc_put_pins(void)
+{
+ gpio_free(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_7);
+
+ gpio_free(MX6SL_BRD_EPDC_GDOE);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_free(MX6SL_BRD_EPDC_GDSP);
+ gpio_free(MX6SL_BRD_EPDC_GDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDSHR);
+ gpio_free(MX6SL_BRD_EPDC_SDLE);
+ gpio_free(MX6SL_BRD_EPDC_SDCE1);
+ gpio_free(MX6SL_BRD_EPDC_SDCLK);
+ gpio_free(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_free(MX6SL_BRD_EPDC_SDCE0);
+}
+
+static void spdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable SPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_spdc_enable_pads));
+
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_8);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_11);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_12);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_13);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_14);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_15);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDOE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_9);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDSP);
+ gpio_direction_input(MX6SL_BRD_EPDC_GDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDSHR);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDLE);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE1);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCLK);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDDO_10);
+ gpio_direction_input(MX6SL_BRD_EPDC_SDCE0);
+}
+
+static void spdc_disable_pins(void)
+{
+ /* Configure MUX settings for SPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_disable_pads, \
+ ARRAY_SIZE(mx6sl_brd_spdc_disable_pads));
+
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_8 , 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_9 , 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_10, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_11, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_12, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_13, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_14, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_15, 0);
+
+ gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_9, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDDO_10, 0);
+ gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0);
+}
+
+static struct imx_spdc_panel_init_set spdc_init_set = {
+ .yoe_pol = false,
+ .dual_gate = false,
+ .resolution = 0,
+ .ud = false,
+ .rl = false,
+ .data_filter_n = true,
+ .power_ready = true,
+ .rgbw_mode_enable = false,
+ .hburst_len_en = true,
+};
+
+static struct fb_videomode erk_1_4_a01 = {
+ .name = "ERK_1_4_A01",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 40000000,
+ .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct imx_spdc_fb_mode spdc_panel_modes[] = {
+ {
+ &erk_1_4_a01,
+ &spdc_init_set,
+ .wave_timing = "pvi"
+ },
+};
+
+static struct imx_spdc_fb_platform_data spdc_data = {
+ .spdc_mode = spdc_panel_modes,
+ .num_modes = ARRAY_SIZE(spdc_panel_modes),
+ .get_pins = spdc_get_pins,
+ .put_pins = spdc_put_pins,
+ .enable_pins = spdc_enable_pins,
+ .disable_pins = spdc_disable_pins,
+};
+
+static int __init early_use_spdc_sel(char *p)
+{
+ spdc_sel = 1;
+ return 0;
+}
+early_param("spdc", early_use_spdc_sel);
+
+static void setup_spdc(void)
+{
+ /* GPR0[8]: 0:EPDC, 1:SPDC */
+ if (spdc_sel)
+ mxc_iomux_set_gpr_register(0, 8, 1, 1);
+}
+
+static void imx6_ntx_usbotg_vbus(bool on)
+{
+#if 0
+ if (on)
+ gpio_set_value(MX6_BRD_USBOTG1_PWR, 1);
+ else
+ gpio_set_value(MX6_BRD_USBOTG1_PWR, 0);
+#endif
+}
+
+static void __init mx6_ntx_init_usb(void)
+{
+ int ret = 0;
+
+ imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR);
+
+#if 0
+ /* disable external charger detect,
+ * or it will affect signal quality at dp.
+ */
+
+ ret = gpio_request(MX6_BRD_USBOTG1_PWR, "usbotg-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO MX6_BRD_USBOTG1_PWR:%d\n", ret);
+ return;
+ }
+ gpio_direction_output(MX6_BRD_USBOTG1_PWR, 0);
+
+ ret = gpio_request(MX6_BRD_USBOTG2_PWR, "usbh1-pwr");
+ if (ret) {
+ pr_err("failed to get GPIO MX6_BRD_USBOTG2_PWR:%d\n", ret);
+ return;
+ }
+ gpio_direction_output(MX6_BRD_USBOTG2_PWR, 1);
+#endif
+
+ mx6_set_otghost_vbus_func(imx6_ntx_usbotg_vbus);
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ mx6_usb_h2_init();
+#endif
+}
+
+static struct platform_device mxcbl_device = {
+ .name = "mxc_msp430_fl",
+};
+
+static struct platform_pwm_backlight_data mx6_ntx_pwm_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+static struct fb_videomode wvga_video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 32MHz */
+ "SEIKO-WVGA", 60, 800, 480, 29850, 99, 164, 33, 10, 10, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data wvga_fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB24,
+ .mode_str = "SEIKO-WVGA",
+ .mode = wvga_video_modes,
+ .num_modes = ARRAY_SIZE(wvga_video_modes),
+ .panel_type = "lcd",
+ },
+};
+
+static struct platform_device lcd_wvga_device = {
+ .name = "lcd_seiko",
+};
+
+#if 0
+static struct fb_videomode hdmi_video_modes[] = {
+ {
+ /* 1920x1080 @ 60 Hz , pixel clk @ 148MHz */
+ "sii9022x_1080p60", 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data hdmi_fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB24,
+ .mode_str = "1920x1080M@60",
+ .mode = hdmi_video_modes,
+ .num_modes = ARRAY_SIZE(hdmi_video_modes),
+ .panel_type = "hdmi",
+ },
+};
+#endif
+
+static int mx6sl_ntx_keymap[] = {
+ KEY(0, 0, 90),
+};
+
+static struct platform_device ntx_device_rtc = {
+ .name = "ntx_misc_rtc",
+ .id = 0,
+ .dev = {
+ .platform_data = -1,
+ }
+};
+
+static const struct matrix_keymap_data mx6sl_ntx_map_data __initconst = {
+ .keymap = mx6sl_ntx_keymap,
+ .keymap_size = ARRAY_SIZE(mx6sl_ntx_keymap),
+};
+#if 0
+static void __init elan_ts_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_elan_pads,
+ ARRAY_SIZE(mx6sl_brd_elan_pads));
+
+ /* ELAN Touchscreen */
+ gpio_request(MX6SL_BRD_ELAN_INT, "elan-interrupt");
+ gpio_direction_input(MX6SL_BRD_ELAN_INT);
+
+ gpio_request(MX6SL_BRD_ELAN_CE, "elan-cs");
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 0);
+
+ gpio_request(MX6SL_BRD_ELAN_RST, "elan-rst");
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 0);
+ mdelay(1);
+ gpio_direction_output(MX6SL_BRD_ELAN_RST, 1);
+ gpio_direction_output(MX6SL_BRD_ELAN_CE, 1);
+}
+#endif
+
+/*
+ *Usually UOK and DOK should have separate
+ *line to differentiate its behaviour (with different
+ * GPIO irq),because connect max8903 pin UOK to
+ *pin DOK from hardware design,cause software cannot
+ *process and distinguish two interrupt, so default
+ *enable dc_valid for ac charger
+ */
+static struct max8903_pdata charger1_data = {
+ .dok = MX6_BRD_CHG_DOK,
+ .uok = MX6_BRD_CHG_UOK,
+ .chg = MX6_BRD_CHG_STATUS,
+ .flt = MX6_BRD_CHG_FLT,
+ .dcm_always_high = true,
+ .dc_valid = true,
+ .usb_valid = false,
+ .feature_flag = 1,
+};
+
+static struct platform_device ntx_max8903_charger_1 = {
+ .name = "max8903-charger",
+ .dev = {
+ .platform_data = &charger1_data,
+ },
+};
+
+/*! Device Definition for csi v4l2 device */
+static struct platform_device csi_v4l2_devices = {
+ .name = "csi_v4l2",
+ .id = 0,
+};
+
+#define SNVS_LPCR 0x38
+static void mx6_snvs_poweroff(void)
+{
+ u32 value;
+ void __iomem *mx6_snvs_base = MX6_IO_ADDRESS(MX6Q_SNVS_BASE_ADDR);
+
+ value = readl(mx6_snvs_base + SNVS_LPCR);
+ /* set TOP and DP_EN bit */
+ writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
+}
+
+#if 0
+static int uart2_enabled;
+static int __init uart2_setup(char * __unused)
+{
+ uart2_enabled = 1;
+ return 1;
+}
+__setup("bluetooth", uart2_setup);
+
+static void __init uart2_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_uart2_pads,
+ ARRAY_SIZE(mx6sl_uart2_pads));
+ imx6sl_add_imx_uart(1, &mx6sl_ntx_uart1_data);
+}
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake, debounce) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+ .debounce_interval = debounce, \
+}
+
+static struct gpio_keys_button gpio_key_matrix_FL[] = {
+ GPIO_BUTTON(GPIO_KB_ROW0, 90, 1, "front_light", 1,1), // Front light
+//#ifdef CONFIG_ANDROID //[
+ GPIO_BUTTON(IMX_GPIO_NR(4, 25), KEY_POWER, 1, "power", 1, 1),
+//#endif //]CONFIG_ANDROID
+};
+
+static struct gpio_keys_button gpio_key_HOME_FL[] = {
+ GPIO_BUTTON(GPIO_KB_COL1, 90, 1, "front_light", 1,1), // Front light
+ GPIO_BUTTON(GPIO_KB_COL0, KEY_HOME, 1, "home", 1,1), // home
+//#ifdef CONFIG_ANDROID //[
+ GPIO_BUTTON(IMX_GPIO_NR(5, 8), KEY_POWER, 1, "power", 1, 1),
+//#endif //]CONFIG_ANDROID
+};
+static struct gpio_keys_button gpio_key_RETURN_HOME_MENU[] = {
+ GPIO_BUTTON(GPIO_KB_ROW0, KEY_HOME, 1, "home", 1,1), // home
+ GPIO_BUTTON(GPIO_KB_ROW1, KEY_MENU, 1, "menu", 1,1), // menu
+ GPIO_BUTTON(GPIO_KB_ROW2, KEY_ESC, 1, "return", 1,1), // return
+//#ifdef CONFIG_ANDROID //[
+ GPIO_BUTTON(IMX_GPIO_NR(5, 8), KEY_POWER, 1, "power", 1, 1),
+//#endif //]CONFIG_ANDROID
+};
+
+static struct gpio_keys_button gpio_key_HOME[] = {
+ GPIO_BUTTON(GPIO_KB_COL0, 61, 1, "home", 1, 50), // home
+//#ifdef CONFIG_ANDROID //[
+ GPIO_BUTTON(IMX_GPIO_NR(5, 8), KEY_POWER, 1, "power", 1, 1),
+//#endif //]CONFIG_ANDROID
+};
+
+static struct gpio_keys_button gpio_key_FL[] = {
+ GPIO_BUTTON(GPIO_KB_COL1, 90, 1, "front_light", 1, 10), // Front light
+//#ifdef CONFIG_ANDROID //[
+ GPIO_BUTTON(IMX_GPIO_NR(5, 8), KEY_POWER, 1, "power", 1, 1),
+//#endif //]CONFIG_ANDROID
+};
+
+static struct gpio_keys_button gpio_key_None[] = {
+//#ifdef CONFIG_ANDROID //[
+ GPIO_BUTTON(IMX_GPIO_NR(5, 8), KEY_POWER, 1, "power", 1, 1),
+//#endif //]CONFIG_ANDROID
+};
+
+static struct gpio_keys_button *gptGPIO_HOME_KEY;
+
+static struct gpio_keys_platform_data ntx_gpio_key_data = {
+ .buttons = gpio_key_matrix_FL,
+ .nbuttons = ARRAY_SIZE(gpio_key_matrix_FL),
+};
+
+static struct platform_device ntx_gpio_key_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &ntx_gpio_key_data,
+ }
+};
+
+#ifdef TOUCH_HOME_LED//[
+
+extern int ntx_get_homepad_enabled_status(void);
+
+static int giHomeLED_Delay_Ticks=100;
+static volatile int giCurHomeLED_state;
+static struct delayed_work homeled_pwrdwn_work,homepad_check_work;
+/*
+ * giHomePad_enable :
+ * 0 = disabled .
+ * 1 = enabled home pad/led action .
+ * 2 = enabled home pad/led action and send event to application layer .
+ */
+static int giHomePad_enable=2;
+
+
+static void _homeled_onoff_force(int iIsON)
+{
+ //int iOldHomeLED_state=giCurHomeLED_state;
+ int iIsHOMELED_gpio=1;
+
+ if( 0==gptHWCFG->m_val.bHOME_LED_PWM && \
+ ( 36!=gptHWCFG->m_val.bPCB && 40!=gptHWCFG->m_val.bPCB) )
+ {
+ // HOME_LED_PWM==NO && !=E60Q3X&&E60Q5X
+ return ;
+ }
+
+ if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ printk("MSP430 ");
+ iIsHOMELED_gpio=0;
+ }
+ else {
+ printk("GPIO ");
+ }
+
+ if(iIsON) {
+ giCurHomeLED_state=1;
+ printk("HOME LED [ON]\n");
+ if(iIsHOMELED_gpio) {
+ gpio_direction_output (gMX6SL_HOME_LED, 0);
+ }
+ else {
+ }
+ }
+ else {
+ giCurHomeLED_state=0;
+ printk("HOME LED [OFF]\n");
+ if(iIsHOMELED_gpio) {
+ gpio_direction_output (gMX6SL_HOME_LED, 1);
+ }
+ else {
+ }
+ }
+}
+
+
+static ssize_t homepad_enable_write(struct device *dev,
+ struct device_attribute *attr,const char *buf,size_t count)
+{
+ int iParam;
+ extern void gpiokeys_enable_button(struct gpio_keys_button *button,int iIsEnable);
+
+ iParam = simple_strtol(buf,NULL,0);
+
+ if(iParam!=giHomePad_enable) {
+ switch (iParam) {
+ case 0:
+ if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // HOME LED is controlled by MSP430 .
+ //msp430_homeled_enable(0);
+ }
+ //gpiokeys_enable_button(gptGPIO_HOME_KEY,0);
+ _homeled_onoff_force(0);
+ msp430_homepad_enable(0);
+ giHomePad_enable = iParam;
+ break;
+ case 1:
+ case 2:
+ //gpiokeys_enable_button(gptGPIO_HOME_KEY,1);
+ if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // HOME LED is controlled by MSP430 .
+ //msp430_homeled_enable(1);
+ }
+ msp430_homepad_enable(2);
+ giHomePad_enable = iParam;
+ break;
+ default :
+ printk(KERN_ERR"invalid parameter !\n");
+ return -1;
+ }
+ }
+ else {
+
+ }
+
+ return strlen(buf);
+}
+static ssize_t homepad_enable_read(struct device *dev,
+ struct device_attribute *attr,const char *buf,size_t count)
+{
+ ssize_t szChk=0;
+ sprintf(buf,"%d\n",giHomePad_enable);
+ szChk = strlen(buf);
+ return szChk;
+}
+static DEVICE_ATTR(homepad_enable,0666,
+ homepad_enable_read,
+ homepad_enable_write);
+
+static ssize_t homeled_delayms_show(struct device *dev,
+ struct device_attribute *attr,const char *buf,size_t count)
+{
+ ssize_t szChk=0;
+ sprintf(buf,"%d\n",giHomeLED_Delay_Ticks*(1000/HZ));
+ szChk = strlen(buf);
+ return szChk;
+}
+static ssize_t homeled_delayms_store(struct device *dev,
+ struct device_attribute *attr,const char *buf,size_t count)
+{
+ int iDelayms;
+ ssize_t szChk;
+ iDelayms = simple_strtol(buf,NULL,0);
+ if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // HOME LED is controlled by MSP430 .
+ int iChk = msp430_set_homeled_delayms(iDelayms);
+ if(iChk>=0) {
+ giHomeLED_Delay_Ticks = msecs_to_jiffies(iChk);
+ szChk = strlen(buf);
+ }
+ else {
+ szChk = -1;
+ }
+ }
+ else if (36==gptHWCFG->m_val.bPCB || 2==gptHWCFG->m_val.bHOME_LED_PWM)
+ {
+ // HOME LED is controlled by SOC .
+ giHomeLED_Delay_Ticks = msecs_to_jiffies(iDelayms);
+ szChk = strlen(buf);
+ }
+ return szChk;
+}
+static DEVICE_ATTR(homeled_delayms,0666,
+ homeled_delayms_show,
+ homeled_delayms_store);
+
+static ssize_t homeled_delaylevel_show(struct device *dev,
+ struct device_attribute *attr,const char *buf,size_t count)
+{
+ ssize_t szChk=0;
+ if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // HOME LED is controlled by MSP430 .
+ if(MSP430_HOMELED_TYPE_PWM==msp430_homeled_type_get(0)) {
+ sprintf(buf,"%d\n",msp430_get_homeled_pwm_delaylevel());
+ }
+ else {
+ sprintf(buf,"%d\n",msp430_get_homeled_gpio_delaylevel());
+ }
+ szChk = strlen(buf);
+ }
+ else {
+ }
+ return szChk;
+}
+static ssize_t homeled_delaylevel_store(struct device *dev,
+ struct device_attribute *attr,const char *buf,size_t count)
+{
+ int iDelayLevel;
+
+ iDelayLevel = simple_strtol(buf,NULL,0);
+ if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // HOME LED is controlled by MSP430 .
+ if(MSP430_HOMELED_TYPE_PWM==msp430_homeled_type_get(0)) {
+ msp430_set_homeled_pwm_delaylevel(iDelayLevel);
+ }
+ else {
+ msp430_set_homeled_gpio_delaylevel(iDelayLevel);
+ }
+ return strlen(buf);
+ }
+ else {
+ return (ssize_t)(-1);
+ }
+}
+static DEVICE_ATTR(homeled_delaylevel,0666,
+ homeled_delaylevel_show,
+ homeled_delaylevel_store);
+
+
+static ssize_t homeled_type_show(struct device *dev,
+ struct device_attribute *attr,const char *buf,size_t count)
+{
+ if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // HOME LED is controlled by MSP430 .
+ char *pszHomeLedType;
+
+ msp430_homeled_type_get(&pszHomeLedType);
+ sprintf(buf,"%s\n",pszHomeLedType);
+
+ return strlen(buf);
+ }
+ else {
+ return 0;
+ }
+}
+
+static ssize_t homeled_type_store(struct device *dev,
+ struct device_attribute *attr,const char *buf,size_t count)
+{
+ ssize_t szChk = -1;
+
+ if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // HOME LED is controlled by MSP430 .
+ if( msp430_homeled_type_set_by_name(buf) >=0 ) {
+ szChk = strlen(buf);
+ }
+ }
+ else {
+ printk(KERN_WARNING"Home led control type cannot changed on this hardware \n");
+ }
+
+ return szChk;
+}
+
+static DEVICE_ATTR(homeled_type,0666,
+ homeled_type_show,
+ homeled_type_store);
+
+
+static const struct attribute *sysfs_homepad_attrs[] = {
+ &dev_attr_homepad_enable.attr,
+ NULL
+};
+static const struct attribute *sysfs_homeled_msp430_attrs[] = {
+ &dev_attr_homeled_type.attr,
+ &dev_attr_homeled_delayms.attr,
+ &dev_attr_homeled_delaylevel.attr,
+ NULL
+};
+static const struct attribute *sysfs_homeled_socgpio_attrs[] = {
+ &dev_attr_homeled_delayms.attr,
+ NULL
+};
+
+
+
+static void _homeled_onoff(int iIsON)
+{
+ if(2==gptHWCFG->m_val.bUIStyle) {
+ if(gSleep_Mode_Suspend) {
+ // skip home led control when system want to enter fake hibernation .
+ _homeled_onoff_force(0);
+ return ;
+ }
+ }
+ _homeled_onoff_force(iIsON);
+}
+
+static void _homepad_work_func(struct work_struct *work)
+{
+ int iIsHomePressing,iHomeGPIOVal;
+
+ iHomeGPIOVal=gpio_get_value(gptGPIO_HOME_KEY->gpio);
+ iIsHomePressing = (iHomeGPIOVal?1:0)^gptGPIO_HOME_KEY->active_low;
+ //printk("%s(),\"%s\" gpio=%d,down=%d\n",__FUNCTION__,
+ // gptGPIO_HOME_KEY->desc,iHomeGPIOVal,iIsHomePressing);
+ if(iIsHomePressing) {
+ msp430_homepad_enable(2);
+ }
+}
+static void _homeled_work_func(struct work_struct *work)
+{
+
+ _homeled_onoff(0);
+
+}
+
+static int ntx_touch_home_key_hook(struct gpio_keys_button *I_gpio_btn_data,int state)
+{
+ int iRet = 0;
+ //printk("%s(%p,%d)\n",__FUNCTION__,I_gpio_btn_data,state);
+ /*if(0x03==gptHWCFG->m_val.bUIConfig) {
+ // RD/MP mode .
+ if(!state) {
+ printk("%s():current home led=%d\n",__FUNCTION__,giCurHomeLED_state);
+ _homeled_onoff(!giCurHomeLED_state);
+ }
+ }
+ else*/
+ {
+ if(state) {
+
+ if( 36==gptHWCFG->m_val.bPCB || 2==gptHWCFG->m_val.bHOME_LED_PWM ) {
+ // E60Q3X or HOME LED is GPIO controlled by SOC .
+ cancel_delayed_work_sync(&homeled_pwrdwn_work);
+ cancel_delayed_work_sync(&homepad_check_work);
+ schedule_delayed_work(&homepad_check_work, giHomeLED_Delay_Ticks+400);
+ _homeled_onoff(1);
+ }
+ }
+ else {
+
+ if( 36==gptHWCFG->m_val.bPCB || 2==gptHWCFG->m_val.bHOME_LED_PWM ) {
+ // E60Q3X or HOME LED is GPIO controlled by SOC .
+ cancel_delayed_work_sync(&homeled_pwrdwn_work);
+ schedule_delayed_work(&homeled_pwrdwn_work, giHomeLED_Delay_Ticks);
+ }
+ }
+
+ if(giHomePad_enable<=1) {
+ iRet = -1;
+ }
+ }
+ return iRet;
+}
+
+void homeled_onoff(int iIsON) {
+ _homeled_onoff_force(iIsON);
+}
+
+int ntx_get_homepad_enabled_status(void)
+{
+ return giHomePad_enable;
+}
+
+int ntx_get_homeled_delay_ms(void)
+{
+ return jiffies_to_msecs(giHomeLED_Delay_Ticks);
+}
+
+void ntx_create_homepad_sys_attrs(struct kobject *kobj)
+{
+ int iChk;
+ if(36==gptHWCFG->m_val.bPCB || 40==gptHWCFG->m_val.bPCB || 0!=gptHWCFG->m_val.bHOME_LED_PWM) {
+ iChk = sysfs_create_files(kobj,sysfs_homepad_attrs);
+ if(iChk) {
+ pr_err("Can't create homepad attr sysfs !\n");
+ }
+ if(36==gptHWCFG->m_val.bPCB||2==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // E60Q3X or HOME LED PWM controlled by SOC .
+ iChk = sysfs_create_files(kobj,sysfs_homeled_socgpio_attrs);
+ if(iChk) {
+ pr_err("Can't create homepad soc gpio attr sysfs !\n");
+ }
+ }
+ else if(1==gptHWCFG->m_val.bHOME_LED_PWM) {
+ // HOME LED PWM is controlled by MSP430 .
+ iChk = sysfs_create_files(kobj,sysfs_homeled_msp430_attrs);
+ if(iChk) {
+ pr_err("Can't create homepad msp430 pwm attr sysfs !\n");
+ }
+ }
+ }
+}
+#else //][!TOUCH_HOME_LED
+static void _homeled_onoff(int iIsON) {}
+void homeled_onoff(int iIsON) {}
+#endif //]TOUCH_HOME_LED
+
+#endif
+
+
+
+void *g_wifi_sd_host;
+irq_handler_t g_cd_irq;
+
+void ntx_register_wifi_cd (irq_handler_t handler, void *data)
+{
+ printk ("[%s-%d] register g_cd_irq \n",__func__,__LINE__);
+ g_wifi_sd_host = data;
+ g_cd_irq = handler;
+}
+
+
+static DEFINE_MUTEX(ntx_wifi_power_mutex);
+static int gi_wifi_power_status = -1;
+
+int _ntx_get_wifi_power_status(void)
+{
+ int iWifiPowerStatus;
+
+ mutex_lock(&ntx_wifi_power_mutex);
+ iWifiPowerStatus = gi_wifi_power_status;
+ mutex_unlock(&ntx_wifi_power_mutex);
+
+ return iWifiPowerStatus;
+}
+
+int _ntx_wifi_power_ctrl (int isWifiEnable)
+{
+ int iHWID;
+ int iOldStatus;
+
+ mutex_lock(&ntx_wifi_power_mutex);
+ iOldStatus = gi_wifi_power_status;
+ printk("Wifi / BT power control %d\n", isWifiEnable);
+ if(isWifiEnable == 0){
+ gpio_direction_output (gMX6SL_WIFI_RST, 0);
+ gpio_direction_input (gMX6SL_WIFI_3V3); // turn off Wifi_3V3_on
+
+ msleep(10);
+// DO NOT switch pin functions to GPIO
+/*
+ // sdio port disable ...
+ if(33==gptHWCFG->m_val.bPCB) {
+ //E60Q2X .
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_sd3_gpio_pads, ARRAY_SIZE(mx6sl_ntx_sd3_gpio_pads));
+ gpio_request (MX6SL_SD3_CLK , "MX6SL_SD3_CLK" );
+ gpio_request (MX6SL_SD3_CMD , "MX6SL_SD3_CMD" );
+ gpio_request (MX6SL_SD3_DAT0, "MX6SL_SD3_DAT0");
+ gpio_request (MX6SL_SD3_DAT1, "MX6SL_SD3_DAT1");
+ gpio_request (MX6SL_SD3_DAT2, "MX6SL_SD3_DAT2");
+ gpio_request (MX6SL_SD3_DAT3, "MX6SL_SD3_DAT3");
+ gpio_direction_output (MX6SL_SD3_CLK , 0);
+ gpio_direction_output (MX6SL_SD3_CMD , 0);
+ gpio_direction_output (MX6SL_SD3_DAT0, 0);
+ gpio_direction_output (MX6SL_SD3_DAT1, 0);
+ gpio_direction_output (MX6SL_SD3_DAT2, 0);
+ gpio_direction_output (MX6SL_SD3_DAT3, 0);
+ }
+ else {
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_sd2_gpio_pads, ARRAY_SIZE(mx6sl_ntx_sd2_gpio_pads));
+ gpio_request (MX6SL_SD2_CLK , "MX6SL_SD2_CLK" );
+ gpio_request (MX6SL_SD2_CMD , "MX6SL_SD2_CMD" );
+ gpio_request (MX6SL_SD2_DAT0, "MX6SL_SD2_DAT0");
+ gpio_request (MX6SL_SD2_DAT1, "MX6SL_SD2_DAT1");
+ gpio_request (MX6SL_SD2_DAT2, "MX6SL_SD2_DAT2");
+ gpio_request (MX6SL_SD2_DAT3, "MX6SL_SD2_DAT3");
+ gpio_direction_input (MX6SL_SD2_CLK );
+ gpio_direction_input (MX6SL_SD2_CMD );
+ gpio_direction_input (MX6SL_SD2_DAT0);
+ gpio_direction_input (MX6SL_SD2_DAT1);
+ gpio_direction_input (MX6SL_SD2_DAT2);
+ gpio_direction_input (MX6SL_SD2_DAT3);
+ }
+*/
+
+#ifdef _WIFI_ALWAYS_ON_
+ disable_irq_wake(gpio_to_irq(gMX6SL_WIFI_INT));
+#endif
+ gi_wifi_power_status=0;
+ }
+ else {
+
+
+ // sdio port process ...
+ if(31==gptHWCFG->m_val.bPCB||32==gptHWCFG->m_val.bPCB) {
+ // E60Q0X/E60Q1X
+ gpio_free (MX6SL_SD2_CLK );
+ gpio_free (MX6SL_SD2_CMD );
+ gpio_free (MX6SL_SD2_DAT0);
+ gpio_free (MX6SL_SD2_DAT1);
+ gpio_free (MX6SL_SD2_DAT2);
+ gpio_free (MX6SL_SD2_DAT3);
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_sd2_wifi_pads, ARRAY_SIZE(mx6sl_ntx_sd2_wifi_pads));
+ }
+ else {
+ gpio_free (MX6SL_SD3_CLK );
+ gpio_free (MX6SL_SD3_CMD );
+ gpio_free (MX6SL_SD3_DAT0);
+ gpio_free (MX6SL_SD3_DAT1);
+ gpio_free (MX6SL_SD3_DAT2);
+ gpio_free (MX6SL_SD3_DAT3);
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_sd3_wifi_pads, ARRAY_SIZE(mx6sl_ntx_sd3_wifi_pads));
+ }
+ //msleep(10);
+
+ gpio_direction_output (gMX6SL_WIFI_3V3, 0); // turn on Wifi_3V3_on
+ //schedule_timeout(HZ/50);
+ msleep(10);
+
+ gpio_direction_input (gMX6SL_WIFI_INT);
+ //msleep(10);
+ gpio_direction_output (gMX6SL_WIFI_RST, 1); // turn on wifi_RST
+ //schedule_timeout(HZ/10);
+ msleep(30);
+#ifdef _WIFI_ALWAYS_ON_
+ enable_irq_wake(gpio_to_irq(gMX6SL_WIFI_INT));
+#endif
+ gi_wifi_power_status=1;
+ }
+
+ if (g_cd_irq) {
+ struct sdhci_host *host;
+
+ host = (struct sdhci_host *) g_wifi_sd_host;
+ //g_cd_irq (0, g_wifi_sd_host);
+ //schedule_timeout (100);
+ //msleep(1000);
+ mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+ //msleep(600);
+ schedule_timeout(500);
+ }
+ else {
+ printk ("[%s-%d] not registered.\n",__func__,__LINE__);
+ }
+
+ if(isWifiEnable == 0){ // switch PIN function to GPIO
+ // sdio port disable ...
+ if(31==gptHWCFG->m_val.bPCB||32==gptHWCFG->m_val.bPCB) {
+ // E60Q0X/E60Q1X.
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_sd2_gpio_pads, ARRAY_SIZE(mx6sl_ntx_sd2_gpio_pads));
+ gpio_request (MX6SL_SD2_CLK , "MX6SL_SD2_CLK" );
+ gpio_request (MX6SL_SD2_CMD , "MX6SL_SD2_CMD" );
+ gpio_request (MX6SL_SD2_DAT0, "MX6SL_SD2_DAT0");
+ gpio_request (MX6SL_SD2_DAT1, "MX6SL_SD2_DAT1");
+ gpio_request (MX6SL_SD2_DAT2, "MX6SL_SD2_DAT2");
+ gpio_request (MX6SL_SD2_DAT3, "MX6SL_SD2_DAT3");
+ gpio_direction_input (MX6SL_SD2_CLK );
+ gpio_direction_input (MX6SL_SD2_CMD );
+ gpio_direction_input (MX6SL_SD2_DAT0);
+ gpio_direction_input (MX6SL_SD2_DAT1);
+ gpio_direction_input (MX6SL_SD2_DAT2);
+ gpio_direction_input (MX6SL_SD2_DAT3);
+ }
+ else {
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_sd3_gpio_pads, ARRAY_SIZE(mx6sl_ntx_sd3_gpio_pads));
+ gpio_request (MX6SL_SD3_CLK , "MX6SL_SD3_CLK" );
+ gpio_request (MX6SL_SD3_CMD , "MX6SL_SD3_CMD" );
+ gpio_request (MX6SL_SD3_DAT0, "MX6SL_SD3_DAT0");
+ gpio_request (MX6SL_SD3_DAT1, "MX6SL_SD3_DAT1");
+ gpio_request (MX6SL_SD3_DAT2, "MX6SL_SD3_DAT2");
+ gpio_request (MX6SL_SD3_DAT3, "MX6SL_SD3_DAT3");
+ gpio_direction_output (MX6SL_SD3_CLK , 0);
+ gpio_direction_output (MX6SL_SD3_CMD , 0);
+ gpio_direction_output (MX6SL_SD3_DAT0, 0);
+ gpio_direction_output (MX6SL_SD3_DAT1, 0);
+ gpio_direction_output (MX6SL_SD3_DAT2, 0);
+ gpio_direction_output (MX6SL_SD3_DAT3, 0);
+ }
+ }
+ printk("%s() end.\n",__FUNCTION__);
+ mutex_unlock(&ntx_wifi_power_mutex);
+ return iOldStatus;
+}
+
+void ntx_wifi_power_ctrl(int iIsWifiEnable)
+{
+ _ntx_wifi_power_ctrl(iIsWifiEnable);
+}
+
+EXPORT_SYMBOL(ntx_wifi_power_ctrl);
+
+static iomux_v3_cfg_t mx6sl_ntx_suspend_pads[] = {
+ MX6SL_PAD_I2C2_SCL__GPIO_3_14,
+ MX6SL_PAD_I2C2_SDA__GPIO_3_15,
+};
+
+static iomux_v3_cfg_t mx6sl_ntx_resume_pads[] = {
+ MX6SL_PAD_I2C2_SCL__I2C2_SCL,
+ MX6SL_PAD_I2C2_SDA__I2C2_SDA,
+};
+
+extern void ntx_gpio_suspend (void);
+extern void ntx_gpio_resume (void);
+
+static void ntx_suspend_enter(void)
+{
+// mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_suspend_pads, ARRAY_SIZE(mx6sl_ntx_suspend_pads));
+// gpio_request(MX6SL_I2C2_SCL, "MX6SL_I2C2_SCL");
+// gpio_request(MX6SL_I2C2_SDA, "MX6SL_I2C2_SDA");
+// gpio_direction_output (MX6SL_I2C2_SCL, 0);
+// gpio_direction_output (MX6SL_I2C2_SDA, 0);
+
+#if 0
+ gpio_direction_output (MX6SL_EP_PWRALL, 1);
+ gpio_direction_output (MX6SL_EP_WAKEUP, 0);
+ gpio_direction_output (MX6SL_EP_PWRUP, 0);
+ gpio_direction_output (MX6SL_EP_VCOM, 0);
+ gpio_direction_input (MX6SL_EP_INT);
+ gpio_direction_input (MX6SL_EP_PWRSTAT);
+#endif
+
+ _homeled_onoff_force(0);
+
+ ntx_gpio_suspend ();
+
+#if 0
+ {
+ unsigned int *pIomux = IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR)+0x4C;
+ unsigned int value;
+
+ printk ("Addr , value\n");
+ while (IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR)+0x5A8 >= pIomux) {
+ value = *pIomux;
+ printk ("0x%08X, 0x%08X, %s%s%s\n",pIomux, value,((value&0x2000)?"PUE - ":""),\
+ ((value&0x2000)?((value&0xC000)?"Pull Up - ":"Pull Down - "):""),((value&0x1000)?"PKE":""));
+ ++pIomux;
+ }
+ }
+#endif
+#if 0
+{
+ void __iomem *base = IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR);
+ unsigned int offset = 0x4C;
+ unsigned int addr = 0x20E0000;
+ unsigned int value;
+
+ for(offset=0x4C; offset <=0x884; offset+=4) {
+ value = __raw_readl( base + offset);
+ printk(KERN_DEBUG "addr %08x = %08x\n", addr+offset, value);
+ }
+
+ base = IO_ADDRESS(GPIO1_BASE_ADDR);
+ addr = 0x209C000;
+ for(offset=0; offset<=0x1C; offset+=4) {
+ value = __raw_readl( base + offset);
+ printk(KERN_DEBUG "addr %08x = %08x\n", addr+offset, value);
+ }
+
+ base = IO_ADDRESS(GPIO2_BASE_ADDR);
+ addr = 0x20A0000;
+ for(offset=0; offset<=0x1C; offset+=4) {
+ value = __raw_readl( base + offset);
+ printk(KERN_DEBUG "addr %08x = %08x\n", addr+offset, value);
+ }
+
+ base = IO_ADDRESS(GPIO3_BASE_ADDR);
+ addr = 0x20A4000;
+ for(offset=0; offset<=0x1C; offset+=4) {
+ value = __raw_readl( base + offset);
+ printk(KERN_DEBUG "addr %08x = %08x\n", addr+offset, value);
+ }
+
+ base = IO_ADDRESS(GPIO4_BASE_ADDR);
+ addr = 0x20A8000;
+ for(offset=0; offset<=0x1C; offset+=4) {
+ value = __raw_readl( base + offset);
+ printk(KERN_DEBUG "addr %08x = %08x\n", addr+offset, value);
+ }
+
+ base = IO_ADDRESS(GPIO5_BASE_ADDR);
+ addr = 0x20AC000;
+ for(offset=0; offset<=0x1C; offset+=4) {
+ value = __raw_readl( base + offset);
+ printk(KERN_DEBUG "addr %08x = %08x\n", addr+offset, value);
+ }
+}
+#endif
+}
+
+static void ntx_suspend_exit(void)
+{
+#if 0
+ gpio_direction_output (MX6SL_EP_WAKEUP, 1);
+#endif
+
+// gpio_free(MX6SL_I2C2_SCL);
+// gpio_free(MX6SL_I2C2_SDA);
+// mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_resume_pads, ARRAY_SIZE(mx6sl_ntx_resume_pads));
+ ntx_gpio_resume ();
+
+}
+
+static const struct pm_platform_data mx6sl_ntx_pm_data __initconst = {
+ .name = "imx_pm",
+ .suspend_enter = ntx_suspend_enter,
+ .suspend_exit = ntx_suspend_exit,
+};
+
+void ntx_wacom_reset(bool on) {
+ gpio_direction_output (MX6SL_WACOM_RST, on);
+}
+static void ntx_gpio_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_ntx_pads,
+ ARRAY_SIZE(mx6sl_brd_ntx_pads));
+
+
+
+ if(31==gptHWCFG->m_val.bPCB||32==gptHWCFG->m_val.bPCB) {
+ // E60Q0X|E60Q1X.
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_ntx_sd4_gpio_pads,
+ ARRAY_SIZE(mx6sl_brd_ntx_sd4_gpio_pads));
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_ntx_sd1_pads,
+ ARRAY_SIZE(mx6sl_brd_ntx_sd1_pads));
+#if 1
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_q12_wifictrl_pads,
+ ARRAY_SIZE(mx6sl_ntx_q12_wifictrl_pads));
+#endif
+ giISD_3V3_ON_Ctrl=-1;
+ }
+ else {
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_ntx_sd4_pads,
+ ARRAY_SIZE(mx6sl_brd_ntx_sd4_pads));
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_ntx_sd1_gpio_pads,
+ ARRAY_SIZE(mx6sl_brd_ntx_sd1_gpio_pads));
+
+#if 1
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_ntx_q22_wifictrl_pads,
+ ARRAY_SIZE(mx6sl_ntx_q22_wifictrl_pads));
+#endif
+ if(1==gptHWCFG->m_val.bLed) {
+ // RGB/G type LED .
+ // ON_LED#
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_SD1_DAT2__GPIO_5_13_PULLHIGH);
+ }
+
+ gMX6SL_NTX_ACIN_PG = IMX_GPIO_NR(5, 14);
+ gMX6SL_NTX_CHG = IMX_GPIO_NR(5, 15);
+ gMX6SL_MSP_INT = IMX_GPIO_NR(5, 11);
+ gMX6SL_PWR_SW = IMX_GPIO_NR(5, 8);
+ gMX6SL_IR_TOUCH_INT = IMX_GPIO_NR(5, 6);
+ gMX6SL_IR_TOUCH_RST = IMX_GPIO_NR(5, 9);
+ if(49==gptHWCFG->m_val.bPCB) {
+ // E60QDX
+ gMX6SL_IR_TOUCH_RST = IMX_GPIO_NR(5, 13);
+ }
+
+ gMX6SL_HALL_EN = IMX_GPIO_NR(5, 12);
+
+ // LED assign ...
+ gMX6SL_CHG_LED = IMX_GPIO_NR(5, 10);
+ if(37==gptHWCFG->m_val.bPCB) {
+ // E60QB0 .
+ gMX6SL_ACT_LED = IMX_GPIO_NR(5, 13);
+ gMX6SL_ON_LED = IMX_GPIO_NR(5, 7);
+ }
+ else if(46==gptHWCFG->m_val.bPCB||48==gptHWCFG->m_val.bPCB) {
+ // E60Q9X/E60QAX .
+
+ // ON_LED# pull high .
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_SD1_DAT2__GPIO_5_13_PULLHIGH);
+
+ gMX6SL_ACT_LED = IMX_GPIO_NR(5, 7);
+ gMX6SL_ON_LED = IMX_GPIO_NR(5, 13);
+ }
+ else if(42==gptHWCFG->m_val.bPCB){
+ // E60Q6X
+ gMX6SL_ACT_LED = IMX_GPIO_NR(5, 13);
+ gMX6SL_ON_LED = IMX_GPIO_NR(5, 13);
+ }
+ else {
+ gMX6SL_ACT_LED = IMX_GPIO_NR(5, 7);
+ gMX6SL_ON_LED = IMX_GPIO_NR(5, 7);
+ }
+
+ gMX6SL_WIFI_3V3 = IMX_GPIO_NR(4, 29);
+ gMX6SL_WIFI_RST = IMX_GPIO_NR(5, 0);
+ gMX6SL_WIFI_INT = IMX_GPIO_NR(4, 31);
+
+ if(37==gptHWCFG->m_val.bPCB) {
+ // E60QBX.
+ gpio_request (GPIO_ESD_3V3_ON, "ESD_3V3_ON");
+ gpio_direction_input (GPIO_ESD_3V3_ON);
+ gpio_free (GPIO_ESD_3V3_ON);
+ giISD_3V3_ON_Ctrl = -1;
+ }
+ else {
+ if(36==gptHWCFG->m_val.bPCB || 40==gptHWCFG->m_val.bPCB) {
+ // E60Q3X/E60Q5X
+ gMX6SL_CHG_LED = IMX_GPIO_NR(5, 7);
+ gMX6SL_IR_TOUCH_RST = IMX_GPIO_NR(5, 13);
+ gpio_request (MX6SL_KL25_INT2, "MX6SL_KL25_INT2");
+ gpio_direction_input (MX6SL_KL25_INT2);
+ }
+ else {
+ if(0==gptHWCFG->m_val.bPMIC) {
+ //若有RICOH PMIC則ESD_3V3_ON都會交由PMIC控制.
+ gpio_request (GPIO_ESD_3V3_ON, "ESD_3V3_ON");
+ gpio_direction_output (GPIO_ESD_3V3_ON, 1);
+ }
+ }
+
+ if(0==gptHWCFG->m_val.bPMIC) {
+ gpio_request (GPIO_ISD_3V3_ON, "ISD_3V3_ON");
+ if(33==gptHWCFG->m_val.bPCB) {
+ // E60Q2X .
+ giISD_3V3_ON_Ctrl = 0;
+ }
+ else {
+ giISD_3V3_ON_Ctrl = 1;
+ }
+ }
+ }
+
+
+ gpio_request (GPIO_IR_3V3_ON, "IR_3V3_ON");
+ gpio_direction_output (GPIO_IR_3V3_ON, 1);
+ //gpio_request (GPIO_EP_3V3_ON, "EP_3V3_ON");
+ //gpio_direction_output (GPIO_EP_3V3_ON, 1);
+
+ if(2==gptHWCFG->m_val.bTouch2Ctrl) {
+ // Wacom Digitizer
+ gpio_request (MX6SL_WACOM_PDCT, "MX6SL_WACOM_PDCT");
+ gpio_direction_input (MX6SL_WACOM_PDCT);
+ gpio_request (MX6SL_WACOM_FWE, "MX6SL_WACOM_FWE");
+ gpio_direction_output (MX6SL_WACOM_FWE, 0);
+ gpio_request (MX6SL_WACOM_RST, "MX6SL_WACOM_RST");
+ ntx_wacom_reset(0);
+
+ if(42==gptHWCFG->m_val.bPCB) {
+ // Wacom GPIOs
+ gpio_request (MX6SL_WACOM_INT, "MX6SL_WACOM_INT");
+ gpio_direction_input (MX6SL_WACOM_INT);
+ i2c_register_board_info(1,&i2c_wacom_binfo,1);
+ }
+ else {
+ gpio_request (MX6SL_WACOM_INT_4_1, "MX6SL_WACOM_INT");
+ gpio_direction_input (MX6SL_WACOM_INT_4_1);
+ i2c_register_board_info(0,&i2c_wacom_binfo,1);
+ }
+ }
+ else if(3==gptHWCFG->m_val.bTouch2Ctrl) {
+ if(42==gptHWCFG->m_val.bPCB) {
+ gpio_request (MX6SL_WALTOP_INT_4_0, "MX6SL_WALTOP_INT_4_0");
+ gpio_direction_input (MX6SL_WALTOP_INT_4_0);
+ gpio_request (MX6SL_WALTOP_RST_3_30, "MX6SL_WALTOP_RST_3_30");
+ gpio_direction_output (MX6SL_WALTOP_RST_3_30, 1);
+
+ i2c_waltop_binfo.platform_data = MX6SL_WALTOP_RST_3_30;
+ i2c_waltop_binfo.irq = gpio_to_irq(MX6SL_WALTOP_INT_4_0);
+ i2c_register_board_info(1,&i2c_waltop_binfo,1);
+ } else {
+ gpio_request (MX6SL_WALTOP_INT, "MX6SL_WALTOP_INT");
+ gpio_direction_input (MX6SL_WALTOP_INT);
+ gpio_request (MX6SL_WALTOP_RST, "MX6SL_WALTOP_RST");
+ gpio_direction_output (MX6SL_WALTOP_RST, 1);
+ i2c_register_board_info(0,&i2c_waltop_binfo,1);
+ }
+ }
+ }
+
+ if(-1!=giISD_3V3_ON_Ctrl) {
+ gpio_direction_output (GPIO_ISD_3V3_ON, giISD_3V3_ON_Ctrl?1:0);
+ }
+
+ i2c_zforce_ir_touch_binfo.platform_data = gMX6SL_IR_TOUCH_INT;
+ i2c_zforce_ir_touch_binfo.irq = gpio_to_irq(gMX6SL_IR_TOUCH_INT);
+
+ i2c_elan_touch_binfo.platform_data = gMX6SL_IR_TOUCH_INT;
+ i2c_elan_touch_binfo.irq = gpio_to_irq(gMX6SL_IR_TOUCH_INT);
+ if(47==gptHWCFG->m_val.bPCB) { //ED0Q02
+ i2c_elan_touch_binfo.addr = 0x10;
+ }
+
+ i2c_sysmp_msp430_binfo.irq = gpio_to_irq(gMX6SL_MSP_INT);
+ i2c_sysmp_ricoh619_binfo.irq = gpio_to_irq(gMX6SL_MSP_INT);
+
+ ntx_misc_info.acin_gpio = gMX6SL_NTX_ACIN_PG;
+ ntx_misc_info.chg_gpio = gMX6SL_NTX_CHG;
+
+ if(37!=gptHWCFG->m_val.bPCB) {
+ gpio_request (MX6SL_HW_ID0, "MX6SL_HW_ID0");
+ gpio_request (MX6SL_HW_ID1, "MX6SL_HW_ID1");
+ gpio_request (MX6SL_HW_ID2, "MX6SL_HW_ID2");
+ gpio_request (MX6SL_HW_ID3, "MX6SL_HW_ID3");
+ gpio_request (MX6SL_HW_ID4, "MX6SL_HW_ID4");
+ gpio_direction_input (MX6SL_HW_ID0);
+ gpio_direction_input (MX6SL_HW_ID1);
+ gpio_direction_input (MX6SL_HW_ID2);
+ gpio_direction_input (MX6SL_HW_ID3);
+ gpio_direction_input (MX6SL_HW_ID4);
+ }
+
+ gpio_request (gMX6SL_ON_LED, "MX6SL_ON_LED");
+ gpio_request (gMX6SL_ACT_LED, "MX6SL_ACT_LED");
+ gpio_direction_input (gMX6SL_ACT_LED);
+ gpio_direction_output (gMX6SL_ON_LED, 0);
+
+ if(36==gptHWCFG->m_val.bPCB || 40==gptHWCFG->m_val.bPCB) {
+ // E60Q3X/E60Q5X
+ gpio_request (gMX6SL_HOME_LED, "MX6SL_HOME_LED");
+ }
+ else {
+ gpio_request (gMX6SL_CHG_LED, "MX6SL_CHG_LED");
+ gpio_direction_input (gMX6SL_CHG_LED);
+ }
+
+ gpio_request (gMX6SL_NTX_ACIN_PG, "MX6SL_NTX_ACIN_PG");
+ gpio_direction_input (gMX6SL_NTX_ACIN_PG);
+
+ gpio_request (gMX6SL_NTX_CHG, "MX6SL_NTX_CHG");
+ gpio_direction_input (gMX6SL_NTX_CHG);
+
+ gpio_request (gMX6SL_MSP_INT, "MX6SL_MSP_INT");
+ gpio_direction_input (gMX6SL_MSP_INT);
+ //#ifndef CONFIG_ANDROID //[
+ if(0==gptHWCFG->m_val.bUIStyle) {
+ gpio_request (gMX6SL_PWR_SW, "MX6SL_PWR_SW");
+ gpio_direction_input (gMX6SL_PWR_SW);
+ }
+ //#endif //]CONFIG_ANDROID
+
+ gpio_request (gMX6SL_IR_TOUCH_INT, "MX6SL_IR_TOUCH_INT");
+ gpio_direction_input (gMX6SL_IR_TOUCH_INT);
+
+ gpio_request (gMX6SL_IR_TOUCH_RST, "MX6SL_IR_TOUCH_RST");
+ gpio_direction_output (gMX6SL_IR_TOUCH_RST, 0);
+ mdelay (10);
+ gpio_direction_input (gMX6SL_IR_TOUCH_RST);
+ if(0==gptHWCFG->m_val.bHallSensor) {
+ gpio_request (gMX6SL_HALL_EN, "MX6SL_HALL_EN");
+ gpio_direction_input (gMX6SL_HALL_EN);
+ }
+
+ gpio_request (gMX6SL_WIFI_RST, "MX6SL_WIFI_RST");
+ gpio_request (gMX6SL_WIFI_3V3, "MX6SL_WIFI_3V3");
+ gpio_request (gMX6SL_WIFI_INT, "MX6SL_WIFI_INT");
+ gpio_direction_input (gMX6SL_WIFI_INT);
+ ntx_wifi_power_ctrl (0);
+
+ gpio_request (MX6SL_FL_EN, "MX6SL_FL_EN");
+ gpio_direction_input (MX6SL_FL_EN);
+ gpio_request (MX6SL_FL_R_EN, "MX6SL_FL_R_EN");
+ gpio_direction_input (MX6SL_FL_R_EN);
+
+#if 0 //[
+ gpio_request (MX6SL_EP_PWRALL, "MX6SL_EP_PWRALL" );
+ gpio_request (MX6SL_EP_WAKEUP , "MX6SL_EP_WAKEUP" );
+ gpio_request (MX6SL_EP_PWRUP , "MX6SL_EP_PWRUP" );
+ gpio_request (MX6SL_EP_INT , "MX6SL_EP_INT" );
+ gpio_request (MX6SL_EP_PWRSTAT , "MX6SL_EP_PWRSTAT" );
+ gpio_request (MX6SL_EP_VCOM , "MX6SL_EP_VCOM" );
+ gpio_direction_output (MX6SL_EP_PWRALL, 1);
+ gpio_direction_output (MX6SL_EP_WAKEUP, 0);
+ gpio_direction_output (MX6SL_EP_PWRUP, 0);
+ gpio_direction_output (MX6SL_EP_VCOM, 0);
+ gpio_direction_input (MX6SL_EP_INT);
+ gpio_direction_input (MX6SL_EP_PWRSTAT);
+#endif //]
+
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mx6_ntx_init(void)
+{
+ u32 i;
+ int iMSP430_I2C_Chn;
+ struct esdhc_platform_data *pt_esdhc_ntx_isd_data;
+
+ _parse_cmdline();
+
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_pads,
+ ARRAY_SIZE(mx6sl_brd_pads));
+
+ ntx_gpio_init ();
+
+ gpiofn_init();
+
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+ gp_reg_id = mx6sl_ntx_dvfscore_data.reg_id;
+ soc_reg_id = mx6sl_ntx_dvfscore_data.soc_id;
+#else
+ gp_reg_id = mx6sl_ntx_dvfscore_data.reg_id;
+ soc_reg_id = mx6sl_ntx_dvfscore_data.soc_id;
+ pu_reg_id = mx6sl_ntx_dvfscore_data.pu_id;
+ mx6_cpu_regulator_init();
+#endif
+
+ if( (46==gptHWCFG->m_val.bPCB && gptHWCFG->m_val.bPCB_REV>=0x10) ||
+ 48==gptHWCFG->m_val.bPCB)
+ {
+ // E60Q9X rev >=A10 ...
+ // E60QAX ...
+ // MSP430 @ I2C1
+ iMSP430_I2C_Chn = 0;//I2C1
+ }
+ else {
+ iMSP430_I2C_Chn = 2;//I2C3 in curcuit .
+ if(0==gptHWCFG->m_val.bPMIC) {
+ // 當MSP430å–代為PMIC工作時,它éžå¸¸å¿™éŒ„,高速的頻率有å¯èƒ½æœƒä½¿å®ƒå‡ºéŒ¯ã€‚
+ mx6_ntx_i2c2_data.bitrate = 100000;
+ }
+ }
+// imx6q_add_imx_snvs_rtc();
+
+
+ imx6q_add_imx_i2c(0, &mx6_ntx_i2c0_data);
+ imx6q_add_imx_i2c(1, &mx6_ntx_i2c1_data);
+ imx6q_add_imx_i2c(2, &mx6_ntx_i2c2_data);
+
+ if (4==gptHWCFG->m_val.bTouchType) {
+ // IR touch type
+ if ( 31==gptHWCFG->m_val.bPCB||32==gptHWCFG->m_val.bPCB||
+ 33==gptHWCFG->m_val.bPCB||36==gptHWCFG->m_val.bPCB||
+ 40==gptHWCFG->m_val.bPCB||
+ (46==gptHWCFG->m_val.bPCB&&gptHWCFG->m_val.bPCB_REV<0x10) )
+ {
+ // E60Q2X/E60Q3X/E60Q1X/E60Q2X/E60Q5X/<E60Q9XA10
+ i2c_register_board_info(0,&i2c_zforce_ir_touch_binfo,1);
+ }
+ else {
+ //
+ i2c_register_board_info(1,&i2c_zforce_ir_touch_binfo,1);
+ }
+ }
+ else if (3==gptHWCFG->m_val.bTouchType) {
+ // C touch type .
+ i2c_register_board_info(0,&i2c_elan_touch_binfo,1);
+ }
+ else {
+ printk("TouchType %d do not support yet ! no touch driver will be loaded \n",(int) gptHWCFG->m_val.bTouchType);
+ }
+
+ if(1==gptHWCFG->m_val.bPMIC){
+ // RC5T619 .
+ if(!NTXHWCFG_TST_FLAG(gptHWCFG->m_val.bPCB_Flags,4)) {
+ // Panel is designed for low voltage .
+ printk("ldo8_1v8 ouput 3v3\n");
+ pdata_ldo8_0.regulator.constraints.min_uV = 3300*1000;
+ pdata_ldo8_0.regulator.constraints.max_uV = 3300*1000;
+ //pdata_ldo8_0.regulator.constraints.always_on = 1;
+ //pdata_ldo8_0.regulator.constraints.boot_on = 1;
+ pdata_ldo8_0.init_uV = 3300*1000;
+ //pdata_ldo8_0.init_enable = 1;
+ pdata_ldo8_0.sleep_uV = 3300*1000;
+ }
+
+ // PCB is designed for low voltage .
+ ntx_ricoh_data.irq_base = irq_alloc_descs (-1, 0, RICOH61x_NR_IRQS, "RICOH61x");
+ if (0 < ntx_ricoh_data.irq_base) {
+ ricoh_battery_data.irq = ntx_ricoh_data.irq_base;
+ ricoh_rtc_data.irq = ntx_ricoh_data.irq_base;
+ printk ("[%s-%d] irq_alloc_descs return %d for %d RICOH61x\n",__func__, __LINE__, ntx_ricoh_data.irq_base, RICOH61x_NR_IRQS);
+ }
+ else {
+ printk ("[%s-%d] RICOH61x irq_alloc_descs failed with %d\n",__func__, __LINE__, ntx_ricoh_data.irq_base, RICOH61x_NR_IRQS);
+ }
+ i2c_register_board_info(2,&i2c_sysmp_ricoh619_binfo,1);
+ // platform_device_register(&ricoh_device_rtc);
+ pm_power_off = ricoh619_power_off;
+ }
+
+
+ if(38!=gptHWCFG->m_val.bPCB&&37!=gptHWCFG->m_val.bPCB)
+ {
+ i2c_register_board_info(iMSP430_I2C_Chn,&i2c_sysmp_msp430_binfo,1);
+ }
+
+ if(0==gptHWCFG->m_val.bRTC) {
+ // RTC use MSP430
+ platform_device_register(&ntx_device_rtc);
+ }
+
+ if(1==gptHWCFG->m_val.bFL_PWM){
+ // Front light PWM source is ht68f20
+ i2c_register_board_info(0,&i2c_ht68f20_binfo,1);
+ }
+
+ if(3==gptHWCFG->m_val.bRSensor) {
+ // g-sensor with microP KL25
+ i2c_register_board_info(0,&i2c_kl25_binfo,1);
+ }
+
+
+ if(4==gptHWCFG->m_val.bRSensor) {
+ // g-sensor : MMA8652
+ //if(36!=gptHWCFG->m_val.bPCB)
+ {
+ /* 20140220 temporarily remove MMA8652 from E60Q32 to save power
+ since not currently used but installed (MMA8652 default mode: Standby) */
+ i2c_register_board_info(0,&i2c_mma8652_binfo,1);
+ }
+ }
+
+ //i2c_register_board_info(0, mxc_i2c0_board_info,
+ // ARRAY_SIZE(mxc_i2c0_board_info));
+ //i2c_register_board_info(1, mxc_i2c1_board_info,
+ // ARRAY_SIZE(mxc_i2c1_board_info));
+ //i2c_register_board_info(2, mxc_i2c2_board_info,
+ // ARRAY_SIZE(mxc_i2c2_board_info));
+
+ /* only camera on I2C2, that's why we can do so */
+// if (csi_enabled == 1) {
+// mxc_register_device(&csi_v4l2_devices, NULL);
+// imx6q_add_imx_i2c(2, &mx6_ntx_i2c2_data);
+// }
+// imx6q_add_imx_snvs_rtc();
+
+ /* SPI */
+// imx6q_add_ecspi(0, &mx6_ntx_spi_data);
+// spi_device_init();
+
+// mx6sl_ntx_init_pfuze100(0);
+ imx6q_add_anatop_thermal_imx(1, &mx6sl_anatop_thermal_data);
+ imx6q_add_pm_imx(0, &mx6sl_ntx_pm_data);
+
+ mx6_ntx_init_uart();
+ /* get enet tx reference clk from FEC_REF_CLK pad.
+ * GPR1[14] = 0, GPR1[18:17] = 00
+ */
+// mxc_iomux_set_gpr_register(1, 14, 1, 0);
+// mxc_iomux_set_gpr_register(1, 17, 2, 0);
+
+// imx6_init_fec(fec_data);
+
+ //platform_device_register(&ntx_vmmc_reg_devices);
+
+ if(2==gptHWCFG->m_val.bIFlash) {
+ // eMMC .
+ pt_esdhc_ntx_isd_data = &mx6_ntx_isd8bits_data;
+ }
+ else {
+ pt_esdhc_ntx_isd_data = &mx6_ntx_isd_data;
+ }
+
+ switch(gptHWCFG->m_val.bPCB) {
+ case 31: //E60Q0X .
+ case 32: //E60Q1X .
+ // SD1 = ISD
+ // SD2 = ESD
+ // SD3 = SDIO WIFI
+ // SD4 = GPIO
+ imx6q_add_sdhci_usdhc_imx(giBootPort, pt_esdhc_ntx_isd_data);
+ imx6q_add_sdhci_usdhc_imx(2, &mx6_ntx_esd_data); // mmcblk1
+ imx6q_add_sdhci_usdhc_imx(1, &mx6_ntx_sd_wifi_data);
+ break;
+
+ default:
+ // \C5\FD\B7s\AA\BA\B3]\ADp\BA\FB\AB\F9\A6b\B3o\ADӰ϶\F4\A1A\A5H\BAɥi\AF\E0\B9F\A8줣\ADק\EFCODE\B4N\AF\E0\A5Ψ\EC\B7s\BE\F7\BAؤW\A1C
+ // SD1 = GPIO
+ // SD2 = ESD
+ // SD3 = SDIO WIFI
+ // SD4 = EMMC
+ if(1==giBootPort) {
+ // ESD is boot device .
+ printk("add usdhc %d as mmcblk0\n",giBootPort+1);
+ if(46==gptHWCFG->m_val.bPCB||
+ 48==gptHWCFG->m_val.bPCB)
+ {
+ //
+ imx6q_add_sdhci_usdhc_imx(giBootPort, &mx6_ntx_esd_nocd_data);
+ }
+ else {
+ imx6q_add_sdhci_usdhc_imx(giBootPort, &mx6_ntx_esd_data);
+ }
+ printk("add usdhc 4 as mmcblk1\n");
+ imx6q_add_sdhci_usdhc_imx(3, pt_esdhc_ntx_isd_data); // mmcblk1
+ printk("add usdhc 3 as sdio for wifi\n");
+ imx6q_add_sdhci_usdhc_imx(2, &mx6_ntx_q22_sd_wifi_data);
+ }
+ else {
+ // EMMC is boot device .
+ imx6q_add_sdhci_usdhc_imx(giBootPort, pt_esdhc_ntx_isd_data);
+ imx6q_add_sdhci_usdhc_imx(1, &mx6_ntx_esd_data); // mmcblk1
+ imx6q_add_sdhci_usdhc_imx(2, &mx6_ntx_q22_sd_wifi_data);
+ }
+ break;
+ }
+
+ mx6_ntx_init_usb();
+ imx6q_add_otp();
+// imx6q_add_mxc_pwm(0);
+// imx6q_add_mxc_pwm_backlight(0, &mx6_ntx_pwm_backlight_data);
+
+
+// gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on");
+// gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1);
+ //mxc_register_device(&lcd_wvga_device, NULL);
+
+ imx6dl_add_imx_pxp();
+ imx6dl_add_imx_pxp_client();
+
+ imx6dl_add_imx_epdc(&epdc_data);
+#ifdef CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF //[
+ imx6dl_add_imx_elcdif(&wvga_fb_data[0]);
+#endif //]CONFIG_IMX_HAVE_PLATFORM_IMX_ELCDIF
+ //imx6q_add_dvfs_core(&mx6sl_ntx_dvfscore_data);
+
+ imx6q_add_viim();
+ imx6q_add_imx2_wdt(0, NULL);
+
+
+#ifdef CONFIG_MXC_GPU_VIV//[
+ if(2==gptHWCFG->m_val.bUIStyle)
+ {
+ // only android models needs GPU .
+ imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata);
+ }
+#endif//] CONFIG_MXC_GPU_VIV
+
+ //imx6sl_add_device_buttons();
+ if(!NTXHWCFG_TST_FLAG(gptHWCFG->m_val.bPCB_Flags,0)) {
+ // key matrix : ON
+
+ //mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_ntx_kb_pads,ARRAY_SIZE(mx6sl_brd_ntx_kb_pads));
+ //mdelay(1);
+
+ imx6sl_add_imx_keypad(&mx6sl_ntx_map_data);
+ }
+ //else
+ {
+ // gpio keys
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_ntx_kb_gpio_pads,
+ ARRAY_SIZE(mx6sl_brd_ntx_kb_gpio_pads));
+ udelay(1);
+
+ switch(gptHWCFG->m_val.bPCB) {
+ case 32://E60Q1X
+ case 31://E60Q0X
+ // use gpio instead of keymatrix ...
+ gpio_request (GPIO_KB_COL0, "KB_COL0");
+ gpio_direction_output (GPIO_KB_COL0, 0);
+ gpio_request (GPIO_KB_COL1, "KB_COL1");
+ gpio_direction_output (GPIO_KB_COL1, 0);
+
+ ntx_gpio_key_data.buttons = gpio_key_matrix_FL;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_matrix_FL);
+ break;
+ case 33://E60Q2X
+ ntx_gpio_key_data.buttons = gpio_key_HOME;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_HOME);
+ break;
+ /*case 36://E60Q3X
+ ntx_gpio_key_data.buttons = gpio_key_HOME_FL;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_HOME_FL);
+ break;*/
+ default:
+ switch(gptHWCFG->m_val.bKeyPad) { //key pad define through bKeyPad in hwconfig
+ case 12: // NO_Key
+ ntx_gpio_key_data.buttons = gpio_key_None;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_None);
+ break;
+ case 11: // FL_Key
+ ntx_gpio_key_data.buttons = gpio_key_FL;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_FL);
+ break;
+ case 16: // FL+HOME PAD
+ case 13: // FL+HOME KEY
+ ntx_gpio_key_data.buttons = gpio_key_HOME_FL;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_HOME_FL);
+ break;
+ case 14: // HOME
+ case 18: // HOMEPAD
+ ntx_gpio_key_data.buttons = gpio_key_HOME;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_HOME);
+ break;
+ case 17: // RETURN+HOME+MENU
+ ntx_gpio_key_data.buttons = gpio_key_RETURN_HOME_MENU;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_RETURN_HOME_MENU);
+ break;
+ default: // FL+HOME
+ ntx_gpio_key_data.buttons = gpio_key_HOME_FL;
+ ntx_gpio_key_data.nbuttons = ARRAY_SIZE(gpio_key_HOME_FL);
+ break;
+ }
+ break;
+ }
+
+ for(i=0;i<ntx_gpio_key_data.nbuttons;i++) {
+ if(0==strcmp(ntx_gpio_key_data.buttons[i].desc,"btn home")) {
+
+#ifdef TOUCH_HOME_LED//[
+ if(36==gptHWCFG->m_val.bPCB || 40==gptHWCFG->m_val.bPCB ||
+ 0!=gptHWCFG->m_val.bHOME_LED_PWM)
+ {
+ // E60Q32/E60Q5X/
+ /*
+ * prepare hook functions of keys .
+ */
+ gptGPIO_HOME_KEY = &ntx_gpio_key_data.buttons[i];
+
+ if( 36==gptHWCFG->m_val.bPCB || 2==gptHWCFG->m_val.bHOME_LED_PWM )
+ {
+ // E60Q3X or HOME LED is GPIO controlled by SOC .
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_SD1_DAT7__GPIO_5_10_OUPUT);
+ INIT_DELAYED_WORK(&homeled_pwrdwn_work,_homeled_work_func);
+ INIT_DELAYED_WORK(&homepad_check_work,_homepad_work_func);
+ }
+
+ ntx_gpio_key_data.buttons[i].hook = ntx_touch_home_key_hook;
+ ntx_gpio_key_data.buttons[i].debounce_interval = 50;
+
+ }
+
+
+#endif //]TOUCH_HOME_LED
+
+ if(2==gptHWCFG->m_val.bUIStyle) {
+ ntx_gpio_key_data.buttons[i].code = KEY_HOME;
+ }
+ }
+ else {
+ if(0==gptHWCFG->m_val.bUIStyle) {
+ if(0==strcmp(ntx_gpio_key_data.buttons[i].desc,"btn power")) {
+ printk("%s(),Ebrmain remote power key in gpio keys \n",__FUNCTION__);
+ ntx_gpio_key_data.nbuttons-=1;
+ }
+ }
+ }
+ }
+
+ if( 1==gptHWCFG->m_val.bHOME_LED_PWM ) {
+ // HOME LED is controled by MSP430 .
+ if(MSP430_HOMELED_TYPE_PWM==msp430_homeled_type_get(0)) {
+ giHomeLED_Delay_Ticks = 200;
+ }
+ else {
+ giHomeLED_Delay_Ticks = 100;
+ }
+ }
+
+
+ platform_device_register(&ntx_gpio_key_device);
+ }
+
+ imx6q_add_busfreq();
+ imx6sl_add_dcp();
+ imx6sl_add_rngb();
+ imx6sl_add_imx_pxp_v4l2();
+
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
+ mxc_register_device(&mxcbl_device, NULL);
+
+
+ platform_device_register(&ntx_light_ldm);
+#ifndef CONFIG_ANDROID //[
+ mxc_register_device(&mxc_usb_plug_device, &usbplug_data);
+#endif//]CONFIG_ANDROID
+ if (1==gptHWCFG->m_val.bPMIC) {
+ // RC5T619 .
+ }
+ else {
+ /* Register charger chips */
+ platform_device_register(&ntx_charger);
+
+ }
+
+ if(gptHWCFG) {
+
+ if(1==gptHWCFG->m_val.bHallSensor) {
+ // hall sensor enabled .
+ tle4913_init();
+ }
+
+
+ }
+ else {
+ printk(KERN_ERR "missing ntx hwconfig !!\n");
+ }
+
+}
+
+extern void __iomem *twd_base;
+static void __init mx6_timer_init(void)
+{
+ struct clk *uart_clk;
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256);
+ BUG_ON(!twd_base);
+#endif
+ mx6sl_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(UART1_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx6_timer_init,
+};
+
+static void __init mx6_ntx_reserve(void)
+{
+#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE)
+ phys_addr_t phys;
+
+ if (imx6q_gpu_pdata.reserved_mem_size) {
+ phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size,
+ SZ_4K, MEMBLOCK_ALLOC_ACCESSIBLE);
+ memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size);
+ imx6q_gpu_pdata.reserved_mem_base = phys;
+ }
+#endif
+}
+
+static int __init display_panel_setup(char *options)
+{
+ if (!options || !*options) {
+ pr_err("Error panel options\n");
+ return 0;
+ }
+
+ if (!strcmp(options, "lcd"))
+ display_panel_mode = PANEL_MODE_LCD;
+ else if (!strcmp(options, "hdmi"))
+ display_panel_mode = PANEL_MODE_HDMI;
+ else if (!strcmp(options, "eink"))
+ display_panel_mode = PANEL_MODE_EINK;
+ else
+ pr_warn("WARN: invalid display panel mode setting");
+
+ return 1;
+}
+
+__setup("panel=", display_panel_setup);
+
+MACHINE_START(MX6SL_NTX, "Freescale i.MX 6SoloLite NTX Board")
+ .boot_params = MX6SL_PHYS_OFFSET + 0x100,
+ .map_io = mx6_map_io,
+ .init_irq = mx6_init_irq,
+ .init_machine = mx6_ntx_init,
+ .timer = &mxc_timer,
+ .reserve = mx6_ntx_reserve,
+MACHINE_END
diff --git a/arch/arm/mach-mx6/board-mx6sl_ntx.h b/arch/arm/mach-mx6/board-mx6sl_ntx.h
new file mode 100755
index 00000000..15e6534d
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6sl_ntx.h
@@ -0,0 +1,306 @@
+#ifndef _BOARD_MX6SL_NTX_H
+#define _BOARD_MX6SL_NTX_H
+#include <mach/iomux-mx6sl.h>
+
+
+#define MX6SL_NTX_ACIN_PG gMX6SL_NTX_ACIN_PG
+#define MX6SL_NTX_CHG gMX6SL_NTX_CHG
+#define MX6SL_MSP_INT gMX6SL_MSP_INT
+#define MX6SL_PWR_SW gMX6SL_PWR_SW
+#define MX6SL_IR_TOUCH_INT gMX6SL_IR_TOUCH_INT
+#define MX6SL_IR_TOUCH_RST gMX6SL_IR_TOUCH_RST
+#define MX6SL_HALL_EN gMX6SL_HALL_EN
+#define MX6SL_ON_LED gMX6SL_ON_LED
+#define MX6SL_CHG_LED gMX6SL_CHG_LED
+#define MX6SL_ACT_LED gMX6SL_ACT_LED
+
+#define MX6SL_EXT_SD_CD IMX_GPIO_NR(5, 2) /* SD2_DAT4 */
+#define MX6SL_WIFI_3V3 IMX_GPIO_NR(5, 0) /* SD2_DAT7 */
+#define MX6SL_WIFI_RST IMX_GPIO_NR(4, 27) /* SD2_RST */
+#define MX6SL_WIFI_INT IMX_GPIO_NR(4, 29) /* SD2_DAT6 */
+#define MX6SL_HW_ID0 IMX_GPIO_NR(4, 2) /* KEY_COL5 */
+#define MX6SL_HW_ID1 IMX_GPIO_NR(4, 4) /* KEY_COL6 */
+#define MX6SL_HW_ID2 IMX_GPIO_NR(4, 6) /* KEY_COL7 */
+#define MX6SL_HW_ID3 IMX_GPIO_NR(4, 5) /* KEY_ROW6 */
+#define MX6SL_HW_ID4 IMX_GPIO_NR(4, 7) /* KEY_ROW7 */
+#define MX6SL_FL_EN IMX_GPIO_NR(2, 10) /* EPDC_PWRCTRL3 */
+#define MX6SL_FL_R_EN IMX_GPIO_NR(1, 29) /* EPDC_SDCE2 */
+#define MX6SL_EP_PWRALL IMX_GPIO_NR(2, 14) /* EPDC_PWRWAKEUP */
+#define MX6SL_EP_WAKEUP IMX_GPIO_NR(2, 7) /* EPDC_PWRCTRL0 */
+#define MX6SL_EP_PWRUP IMX_GPIO_NR(2, 8) /* EPDC_PWRCTRL1 */
+#define MX6SL_EP_INT IMX_GPIO_NR(2, 9) /* EPDC_PWRCTRL2 */
+#define MX6SL_EP_PWRSTAT IMX_GPIO_NR(2, 13) /* EPDC_PWRSTAT */
+#define MX6SL_EP_VCOM IMX_GPIO_NR(2, 3) /* EPDC_VCOM0 */
+
+#define MX6SL_SD2_CLK IMX_GPIO_NR(5, 5) /* SD2_CLK */
+#define MX6SL_SD2_CMD IMX_GPIO_NR(5, 4) /* SD2_CMD */
+#define MX6SL_SD2_DAT0 IMX_GPIO_NR(5, 1) /* SD2_DAT0 */
+#define MX6SL_SD2_DAT1 IMX_GPIO_NR(4, 30) /* SD2_DAT1 */
+#define MX6SL_SD2_DAT2 IMX_GPIO_NR(5, 3) /* SD2_DAT2 */
+#define MX6SL_SD2_DAT3 IMX_GPIO_NR(4, 28) /* SD2_DAT3 */
+
+#define MX6SL_SD3_CLK IMX_GPIO_NR(5, 18) /* SD3_CLK */
+#define MX6SL_SD3_CMD IMX_GPIO_NR(5, 21) /* SD3_CMD */
+#define MX6SL_SD3_DAT0 IMX_GPIO_NR(5, 19) /* SD3_DAT0 */
+#define MX6SL_SD3_DAT1 IMX_GPIO_NR(5, 20) /* SD3_DAT1 */
+#define MX6SL_SD3_DAT2 IMX_GPIO_NR(5, 16) /* SD3_DAT2 */
+#define MX6SL_SD3_DAT3 IMX_GPIO_NR(5, 17) /* SD3_DAT3 */
+
+#define MX6SL_I2C2_SCL IMX_GPIO_NR(3, 14) /* I2C2_SCL */
+#define MX6SL_I2C2_SDA IMX_GPIO_NR(3, 15) /* I2C2_SDA */
+#define MX6SL_I2C3_SCL IMX_GPIO_NR(3, 21) /* I2C3_SCL */
+#define MX6SL_I2C3_SDA IMX_GPIO_NR(3, 22) /* I2C3_SDA */
+
+#define GPIO_ESD_3V3_ON IMX_GPIO_NR(3, 29) /* ROW2 */
+#define GPIO_ISD_3V3_ON IMX_GPIO_NR(3, 31) /* ROW3 */
+#define GPIO_IR_3V3_ON IMX_GPIO_NR(4, 1) /* ROW4 */
+//#define GPIO_EP_3V3_ON IMX_GPIO_NR(4, 3) /* ROW5 */
+
+#define GPIO_KB_COL0 IMX_GPIO_NR(3, 24) /* COL0 */
+#define GPIO_KB_COL1 IMX_GPIO_NR(3, 26) /* COL1 */
+
+#define GPIO_KB_ROW0 IMX_GPIO_NR(3, 25) /* ROW0 */
+#define GPIO_KB_ROW1 IMX_GPIO_NR(3, 27) /* ROW1 */
+#define GPIO_KB_ROW2 IMX_GPIO_NR(3, 29) /* ROW2 */
+
+#define MX6SL_KL25_INT2 IMX_GPIO_NR(3, 29) /* ROW2 */
+#if 1
+#define MX6SL_WACOM_INT IMX_GPIO_NR(4, 0) /* COL4 */
+#define MX6SL_WACOM_PDCT IMX_GPIO_NR(4, 2) /* COL5 */
+#else
+#define MX6SL_WACOM_INT IMX_GPIO_NR(4, 2) /* COL5 */
+#define MX6SL_WACOM_PDCT IMX_GPIO_NR(4, 0) /* COL4 */
+#endif
+#define MX6SL_WACOM_INT_4_1 IMX_GPIO_NR(4, 1) /* ROW4 */
+#define MX6SL_WACOM_FWE IMX_GPIO_NR(3, 24) /* COL0 */
+#define MX6SL_WACOM_RST IMX_GPIO_NR(3, 30) /* COL3 */
+
+#define MX6SL_WALTOP_RST IMX_GPIO_NR(3, 31) /* ROW3 */
+#define MX6SL_WALTOP_RST_3_30 IMX_GPIO_NR(3, 30) /* ROW3 */
+#define MX6SL_WALTOP_INT IMX_GPIO_NR(4, 1) /* ROW4 */
+#define MX6SL_WALTOP_INT_4_0 IMX_GPIO_NR(4, 0) /* ROW4 */
+
+
+extern volatile unsigned gMX6SL_NTX_ACIN_PG;
+extern volatile unsigned gMX6SL_NTX_CHG;
+extern volatile unsigned gMX6SL_MSP_INT;
+extern volatile unsigned gMX6SL_PWR_SW;
+extern volatile unsigned gMX6SL_IR_TOUCH_INT;
+extern volatile unsigned gMX6SL_IR_TOUCH_RST;
+extern volatile unsigned gMX6SL_HALL_EN;
+extern volatile unsigned gMX6SL_ON_LED;
+extern volatile unsigned gMX6SL_CHG_LED;
+extern volatile unsigned gMX6SL_ACT_LED;
+extern volatile unsigned gMX6SL_WIFI_3V3;
+extern volatile unsigned gMX6SL_WIFI_RST;
+extern volatile unsigned gMX6SL_WIFI_INT;
+
+static iomux_v3_cfg_t mx6sl_brd_ntx_kb_pads[] = {
+ MX6SL_PAD_KEY_COL0__KPP_COL_0,
+ MX6SL_PAD_KEY_COL1__KPP_COL_1,
+ MX6SL_PAD_KEY_ROW0__KPP_ROW_0,
+ MX6SL_PAD_KEY_ROW1__KPP_ROW_1,
+};
+static iomux_v3_cfg_t mx6sl_brd_ntx_kb_gpio_pads[] = {
+ MX6SL_PAD_KEY_COL0__GPIO_3_24,
+ MX6SL_PAD_KEY_COL1__GPIO_3_26,
+ MX6SL_PAD_KEY_ROW0__GPIO_3_25,
+ MX6SL_PAD_KEY_ROW1__GPIO_3_27,
+ MX6SL_PAD_KEY_ROW2__GPIO_3_29,
+};
+
+static iomux_v3_cfg_t mx6sl_brd_ntx_sd4_pads[] = {
+ MX6SL_PAD_FEC_MDIO__USDHC4_CLK,
+ MX6SL_PAD_FEC_TX_CLK__USDHC4_CMD,
+ MX6SL_PAD_FEC_RX_ER__USDHC4_DAT0,
+ MX6SL_PAD_FEC_CRS_DV__USDHC4_DAT1,
+ MX6SL_PAD_FEC_RXD1__USDHC4_DAT2,
+ MX6SL_PAD_FEC_TXD0__USDHC4_DAT3,
+ MX6SL_PAD_FEC_MDC__USDHC4_DAT4,
+ MX6SL_PAD_FEC_RXD0__USDHC4_DAT5,
+ MX6SL_PAD_FEC_TX_EN__USDHC4_DAT6,
+ MX6SL_PAD_FEC_TXD1__USDHC4_DAT7,
+ MX6SL_PAD_FEC_REF_CLK__GPIO_4_26_PULLHIGH,
+};
+
+static iomux_v3_cfg_t mx6sl_brd_ntx_sd4_gpio_pads[] = {
+ MX6SL_PAD_FEC_MDIO__GPIO_4_20, // PWR_GOOD
+ MX6SL_PAD_FEC_TX_CLK__GPIO_4_21, // CHG#
+ MX6SL_PAD_FEC_RX_ER__GPIO_4_19, // MSP_INT#
+ MX6SL_PAD_FEC_CRS_DV__GPIO_4_25, // PWR_SW
+ MX6SL_PAD_FEC_RXD1__GPIO_4_18, // GS_INT
+ MX6SL_PAD_FEC_TXD0__GPIO_4_24, // IR_TOUCH_INT#
+ MX6SL_PAD_FEC_MDC__GPIO_4_23, // HALL_EN
+ MX6SL_PAD_FEC_RXD0__GPIO_4_17, // IR_RST
+ MX6SL_PAD_FEC_TX_EN__GPIO_4_22, // ACT_LED
+ MX6SL_PAD_FEC_TXD1__GPIO_4_16, // CHG_LED
+ MX6SL_PAD_FEC_REF_CLK__GPIO_4_26, // ON_LED
+};
+
+
+static iomux_v3_cfg_t mx6sl_brd_ntx_sd1_pads[] = {
+ MX6SL_PAD_SD1_CLK__USDHC1_CLK_50MHZ,
+ MX6SL_PAD_SD1_CMD__USDHC1_CMD_50MHZ,
+ MX6SL_PAD_SD1_DAT0__USDHC1_DAT0_50MHZ,
+ MX6SL_PAD_SD1_DAT1__USDHC1_DAT1_50MHZ,
+ MX6SL_PAD_SD1_DAT2__USDHC1_DAT2_50MHZ,
+ MX6SL_PAD_SD1_DAT3__USDHC1_DAT3_50MHZ,
+ MX6SL_PAD_SD1_DAT4__USDHC1_DAT4_50MHZ,
+ MX6SL_PAD_SD1_DAT5__USDHC1_DAT5_50MHZ,
+ MX6SL_PAD_SD1_DAT6__USDHC1_DAT6_50MHZ,
+ MX6SL_PAD_SD1_DAT7__USDHC1_DAT7_50MHZ,
+};
+
+static iomux_v3_cfg_t mx6sl_brd_ntx_sd1_gpio_pads[] = {
+ MX6SL_PAD_SD1_CLK__GPIO_5_15, // CHG#
+ MX6SL_PAD_SD1_CMD__GPIO_5_14, // ACIN_PG#
+ MX6SL_PAD_SD1_DAT0__GPIO_5_11, // MSP_INT#
+ MX6SL_PAD_SD1_DAT1__GPIO_5_8, // PWR_SW#
+ MX6SL_PAD_SD1_DAT2__GPIO_5_13, // TP85
+ MX6SL_PAD_SD1_DAT3__GPIO_5_6, // IR_DataReady
+ MX6SL_PAD_SD1_DAT4__GPIO_5_12, // TP86/Hall_EN#
+ MX6SL_PAD_SD1_DAT5__GPIO_5_9, // V325_RST#
+ MX6SL_PAD_SD1_DAT6__GPIO_5_7, // ACTION_LED_RH#
+ MX6SL_PAD_SD1_DAT7__GPIO_5_10, // TP82/Charge_LED_RH#
+};
+
+
+
+static iomux_v3_cfg_t mx6sl_brd_ntx_pads[] = {
+ MX6SL_PAD_REF_CLK_24M__I2C3_SCL,
+ MX6SL_PAD_REF_CLK_32K__I2C3_SDA,
+
+ /* USBOTG ID pin */
+ MX6SL_PAD_EPDC_PWRCOM__ANATOP_USBOTG1_ID,
+
+ MX6SL_PAD_SD2_DAT4__GPIO_5_2, // EXT_SD_CD
+ MX6SL_PAD_SD2_DAT7__GPIO_5_0, // WIFI_3V3_ON
+ MX6SL_PAD_SD2_RST__GPIO_4_27, // WIFI_RST
+ //MX6SL_PAD_SD2_DAT6__GPIO_4_29_OUTPUT, // WIFI_INT
+
+ MX6SL_PAD_KEY_COL5__GPIO_4_2, // HW_ID0
+ MX6SL_PAD_KEY_COL6__GPIO_4_4, // HW_ID1
+ MX6SL_PAD_KEY_COL7__GPIO_4_6, // HW_ID2
+ MX6SL_PAD_KEY_ROW6__GPIO_4_5, // HW_ID3
+ MX6SL_PAD_KEY_ROW7__GPIO_4_7, // HW_ID4
+
+ MX6SL_PAD_KEY_ROW2__GPIO_3_29, // ESD_3V3_ON(Q22)/BS_INT(Q12)/NA
+ MX6SL_PAD_KEY_ROW3__GPIO_3_31, // ISD_3V3_ON(Q22)/BS_3V3(Q12/NA
+ MX6SL_PAD_KEY_ROW4__GPIO_4_1, // IR_3V3_ON(Q22)/BS_UP(Q12)/NA
+ //MX6SL_PAD_KEY_ROW5__GPIO_4_3, // EP_3V3_ON(Q22)/BS_DN(Q12)/NA
+
+ MX6SL_PAD_KEY_COL2__GPIO_3_28, // BS_Left (Q12)/NA
+ MX6SL_PAD_KEY_COL3__GPIO_3_30, // BS_Right (Q12)/NA
+ MX6SL_PAD_KEY_COL4__GPIO_4_0, // BS_Click (Q12)/NA
+
+#if 0
+ MX6SL_PAD_EPDC_PWRCTRL0__GPIO_2_7, // EP_PWRCTRL0 (WAKEUP#)
+ MX6SL_PAD_EPDC_PWRCTRL1__GPIO_2_8, // EP_PWRCTRL1 (PWRUP)
+ MX6SL_PAD_EPDC_PWRCTRL2__GPIO_2_9, // EP_INT
+ MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14,// PWRALL
+ MX6SL_PAD_EPDC_PWRSTAT__GPIO_2_13, // EP_PWRSTAT (PWR_GOOD)
+ MX6SL_PAD_EPDC_VCOM0__GPIO_2_3, // VCOM_CTRL
+#endif
+
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10, // FL_EN
+ MX6SL_PAD_EPDC_SDCE2__GPIO_1_29, // FL_R_EN
+
+ MX6SL_PAD_LCD_DAT0__GPIO_2_20,
+ MX6SL_PAD_LCD_DAT1__GPIO_2_21,
+ MX6SL_PAD_LCD_DAT2__GPIO_2_22,
+ MX6SL_PAD_LCD_DAT3__GPIO_2_23,
+ MX6SL_PAD_LCD_DAT4__GPIO_2_24,
+ MX6SL_PAD_LCD_DAT5__GPIO_2_25,
+ MX6SL_PAD_LCD_DAT6__GPIO_2_26,
+ MX6SL_PAD_LCD_DAT7__GPIO_2_27,
+ MX6SL_PAD_LCD_DAT8__GPIO_2_28,
+ MX6SL_PAD_LCD_DAT9__GPIO_2_29,
+ MX6SL_PAD_LCD_DAT10__GPIO_2_30,
+ MX6SL_PAD_LCD_DAT11__GPIO_2_31,
+ MX6SL_PAD_LCD_DAT12__GPIO_3_0,
+ MX6SL_PAD_LCD_DAT13__GPIO_3_1,
+ MX6SL_PAD_LCD_DAT14__GPIO_3_2,
+ MX6SL_PAD_LCD_DAT15__GPIO_3_3,
+ MX6SL_PAD_LCD_DAT16__GPIO_3_4,
+ MX6SL_PAD_LCD_DAT17__GPIO_3_5,
+ MX6SL_PAD_LCD_DAT18__GPIO_3_6,
+ MX6SL_PAD_LCD_DAT19__GPIO_3_7,
+ MX6SL_PAD_LCD_DAT20__GPIO_3_8,
+ MX6SL_PAD_LCD_DAT21__GPIO_3_9,
+ MX6SL_PAD_LCD_DAT22__GPIO_3_10,
+ MX6SL_PAD_LCD_DAT23__GPIO_3_11,
+
+ MX6SL_PAD_LCD_CLK__GPIO_2_15,
+ MX6SL_PAD_LCD_ENABLE__GPIO_2_16,
+ MX6SL_PAD_LCD_HSYNC__GPIO_2_17,
+ MX6SL_PAD_LCD_VSYNC__GPIO_2_18,
+ MX6SL_PAD_LCD_RESET__GPIO_2_19,
+
+ MX6SL_PAD_ECSPI1_SCLK__GPIO_4_8,
+ MX6SL_PAD_ECSPI1_MOSI__GPIO_4_9,
+ MX6SL_PAD_ECSPI1_MISO__GPIO_4_10,
+ MX6SL_PAD_ECSPI1_SS0__GPIO_4_11,
+ MX6SL_PAD_ECSPI2_SCLK__GPIO_4_12,
+ MX6SL_PAD_ECSPI2_MOSI__GPIO_4_13,
+ MX6SL_PAD_ECSPI2_MISO__GPIO_4_14,
+ MX6SL_PAD_ECSPI2_SS0__GPIO_4_15,
+ MX6SL_PAD_AUD_RXFS__GPIO_1_0,
+ MX6SL_PAD_AUD_RXC__GPIO_1_1,
+ MX6SL_PAD_AUD_RXD__GPIO_1_2,
+ MX6SL_PAD_AUD_TXC__GPIO_1_3,
+ MX6SL_PAD_AUD_TXFS__GPIO_1_4,
+ MX6SL_PAD_AUD_TXD__GPIO_1_5,
+ MX6SL_PAD_AUD_MCLK__GPIO_1_6,
+ MX6SL_PAD_HSIC_DAT__GPIO_3_19,
+ MX6SL_PAD_HSIC_STROBE__GPIO_3_20,
+ MX6SL_PAD_WDOG_B__GPIO_3_18,
+};
+
+static iomux_v3_cfg_t mx6sl_ntx_sd2_gpio_pads[] = {
+ MX6SL_PAD_SD2_CLK__GPIO_5_5,
+ MX6SL_PAD_SD2_CMD__GPIO_5_4,
+ MX6SL_PAD_SD2_DAT0__GPIO_5_1,
+ MX6SL_PAD_SD2_DAT1__GPIO_4_30,
+ MX6SL_PAD_SD2_DAT2__GPIO_5_3,
+ MX6SL_PAD_SD2_DAT3__GPIO_4_28,
+};
+
+static iomux_v3_cfg_t mx6sl_ntx_sd2_wifi_pads[] = {
+ MX6SL_PAD_SD2_CLK__USDHC2_CLK_50MHZ,
+ MX6SL_PAD_SD2_CMD__USDHC2_CMD_50MHZ,
+ MX6SL_PAD_SD2_DAT0__USDHC2_DAT0_50MHZ,
+ MX6SL_PAD_SD2_DAT1__USDHC2_DAT1_50MHZ,
+ MX6SL_PAD_SD2_DAT2__USDHC2_DAT2_50MHZ,
+ MX6SL_PAD_SD2_DAT3__USDHC2_DAT3_50MHZ,
+};
+
+static iomux_v3_cfg_t mx6sl_ntx_sd3_gpio_pads[] = {
+ MX6SL_PAD_SD3_CLK__GPIO_5_18,
+ MX6SL_PAD_SD3_CMD__GPIO_5_21,
+ MX6SL_PAD_SD3_DAT0__GPIO_5_19,
+ MX6SL_PAD_SD3_DAT1__GPIO_5_20,
+ MX6SL_PAD_SD3_DAT2__GPIO_5_16,
+ MX6SL_PAD_SD3_DAT3__GPIO_5_17,
+};
+
+static iomux_v3_cfg_t mx6sl_ntx_sd3_wifi_pads[] = {
+ MX6SL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6SL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6SL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6SL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6SL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6SL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+};
+
+
+static iomux_v3_cfg_t mx6sl_ntx_q22_wifictrl_pads[] = {
+ MX6SL_PAD_SD2_DAT6__GPIO_4_29_OUTPUT, // WiFi_3V3_ON#
+ MX6SL_PAD_SD2_DAT5__GPIO_4_31_INPUT, // WiFi_INT#
+};
+
+static iomux_v3_cfg_t mx6sl_ntx_q12_wifictrl_pads[] = {
+ MX6SL_PAD_SD2_DAT6__GPIO_4_29, // WiFi_INT#
+ MX6SL_PAD_SD2_DAT5__GPIO_4_31, //NC
+};
+
+#endif
diff --git a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
new file mode 100644
index 00000000..b0edb5e5
--- /dev/null
+++ b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
@@ -0,0 +1,377 @@
+
+/*
+ * Copyright (C) 2012-2013 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 <mach/iomux-mx6dl.h>
+
+static iomux_v3_cfg_t mx6dl_sabreauto_pads[] = {
+
+ /* UART4 for debug */
+ MX6DL_PAD_KEY_COL0__UART4_TXD,
+ MX6DL_PAD_KEY_ROW0__UART4_RXD,
+ /* USB HSIC ports use the same pin with ENET */
+#ifdef CONFIG_USB_EHCI_ARC_HSIC
+ /* USB H2 strobe/data pin */
+ MX6DL_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE,
+ MX6DL_PAD_RGMII_TXC__USBOH3_H2_DATA,
+
+ /* USB H3 strobe/data pin */
+ MX6DL_PAD_RGMII_RXC__USBOH3_H3_STROBE,
+ MX6DL_PAD_RGMII_RX_CTL__USBOH3_H3_DATA,
+ /* ENET */
+#else
+ MX6DL_PAD_KEY_COL1__ENET_MDIO,
+ MX6DL_PAD_KEY_COL2__ENET_MDC,
+ MX6DL_PAD_RGMII_TXC__ENET_RGMII_TXC,
+ MX6DL_PAD_RGMII_TD0__ENET_RGMII_TD0,
+ MX6DL_PAD_RGMII_TD1__ENET_RGMII_TD1,
+ MX6DL_PAD_RGMII_TD2__ENET_RGMII_TD2,
+ MX6DL_PAD_RGMII_TD3__ENET_RGMII_TD3,
+ MX6DL_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL,
+ MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK,
+ MX6DL_PAD_RGMII_RXC__ENET_RGMII_RXC,
+ MX6DL_PAD_RGMII_RD0__ENET_RGMII_RD0,
+ MX6DL_PAD_RGMII_RD1__ENET_RGMII_RD1,
+ MX6DL_PAD_RGMII_RD2__ENET_RGMII_RD2,
+ MX6DL_PAD_RGMII_RD3__ENET_RGMII_RD3,
+ MX6DL_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL,
+ /*RGMII Phy Interrupt */
+ MX6DL_PAD_GPIO_19__GPIO_4_5,
+#endif
+ /* MCLK for csi0 */
+ MX6DL_PAD_GPIO_0__CCM_CLKO,
+ /*MX6DL_PAD_GPIO_3__CCM_CLKO2,i*/
+
+ /* Android GPIO keys */
+ MX6DL_PAD_SD2_CMD__GPIO_1_11, /* home */
+ MX6DL_PAD_SD2_DAT3__GPIO_1_12, /* back */
+ MX6DL_PAD_SD4_DAT4__GPIO_2_12, /* prog */
+ MX6DL_PAD_SD4_DAT7__GPIO_2_15, /* vol up */
+ MX6DL_PAD_DISP0_DAT20__GPIO_5_14, /* vol down */
+
+ /* SD1 */
+ MX6DL_PAD_SD1_CLK__USDHC1_CLK_50MHZ_40OHM,
+ MX6DL_PAD_SD1_CMD__USDHC1_CMD_50MHZ_40OHM,
+ MX6DL_PAD_SD1_DAT0__USDHC1_DAT0_50MHZ_40OHM,
+ MX6DL_PAD_SD1_DAT1__USDHC1_DAT1_50MHZ_40OHM,
+ MX6DL_PAD_SD1_DAT2__USDHC1_DAT2_50MHZ_40OHM,
+ MX6DL_PAD_SD1_DAT3__USDHC1_DAT3_50MHZ_40OHM,
+
+ /* SD1_CD and SD1_WP */
+ MX6DL_PAD_GPIO_1__GPIO_1_1,
+ MX6DL_PAD_CSI0_DATA_EN__GPIO_5_20,
+
+ /* SD3 */
+ MX6DL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
+ MX6DL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
+ MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
+ MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
+ MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
+ MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
+ MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ,
+ MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ,
+ MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ,
+ MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ,
+
+ /* SD3 VSelect */
+ MX6DL_PAD_GPIO_18__USDHC3_VSELECT,
+ /* SD3_CD and SD3_WP */
+ MX6DL_PAD_NANDF_CS2__GPIO_6_15,
+ MX6DL_PAD_SD2_DAT2__GPIO_1_13,
+
+ /* ESAI */
+ MX6DL_PAD_ENET_CRS_DV__ESAI1_SCKT,
+ MX6DL_PAD_ENET_RXD1__ESAI1_FST,
+ MX6DL_PAD_ENET_TX_EN__ESAI1_TX3_RX2,
+ MX6DL_PAD_GPIO_5__ESAI1_TX2_RX3,
+ MX6DL_PAD_ENET_TXD0__ESAI1_TX4_RX1,
+ MX6DL_PAD_ENET_MDC__ESAI1_TX5_RX0,
+ MX6DL_PAD_GPIO_17__ESAI1_TX0,
+ MX6DL_PAD_NANDF_CS3__ESAI1_TX1,
+ MX6DL_PAD_ENET_MDIO__ESAI1_SCKR,
+ MX6DL_PAD_GPIO_9__ESAI1_FSR,
+ /* esai interrupt */
+ MX6DL_PAD_SD2_CLK__GPIO_1_10,
+
+ /* I2C2 */
+ MX6DL_PAD_EIM_EB2__I2C2_SCL,
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA,
+ MX6DL_PAD_SD2_DAT0__GPIO_1_15,
+
+ /* DISPLAY */
+ MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6DL_PAD_DI0_PIN15__IPU1_DI0_PIN15,
+ MX6DL_PAD_DI0_PIN2__IPU1_DI0_PIN2,
+ MX6DL_PAD_DI0_PIN3__IPU1_DI0_PIN3,
+ MX6DL_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
+ MX6DL_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
+ MX6DL_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
+ MX6DL_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
+ MX6DL_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
+ MX6DL_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
+ MX6DL_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
+ MX6DL_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
+ MX6DL_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
+ MX6DL_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
+ MX6DL_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
+ MX6DL_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
+ MX6DL_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
+ MX6DL_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
+ MX6DL_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
+ MX6DL_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
+ MX6DL_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
+ MX6DL_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
+ MX6DL_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
+ MX6DL_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
+ MX6DL_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
+ /* LITE_SENS_INT_B */
+ MX6DL_PAD_DISP0_DAT23__GPIO_5_17,
+ /*PMIC INT*/
+ MX6DL_PAD_DISP0_DAT22__GPIO_5_16,
+
+ /* ipu1 csi0 */
+ MX6DL_PAD_CSI0_DAT4__IPU1_CSI0_D_4,
+ MX6DL_PAD_CSI0_DAT5__IPU1_CSI0_D_5,
+ MX6DL_PAD_CSI0_DAT6__IPU1_CSI0_D_6,
+ MX6DL_PAD_CSI0_DAT7__IPU1_CSI0_D_7,
+ MX6DL_PAD_CSI0_DAT8__IPU1_CSI0_D_8,
+ MX6DL_PAD_CSI0_DAT9__IPU1_CSI0_D_9,
+ MX6DL_PAD_CSI0_DAT10__IPU1_CSI0_D_10,
+ MX6DL_PAD_CSI0_DAT11__IPU1_CSI0_D_11,
+ MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_D_12,
+ MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_D_13,
+ MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_D_14,
+ MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_D_15,
+ MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_D_16,
+ MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_D_17,
+ MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_D_18,
+ MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_D_19,
+ MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,
+ MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,
+ MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,
+
+ /* PWM3 and PMW4 */
+ MX6DL_PAD_SD4_DAT1__PWM3_PWMO,
+ MX6DL_PAD_SD4_DAT2__PWM4_PWMO,
+
+ /* DISP0 RESET */
+ MX6DL_PAD_EIM_WAIT__GPIO_5_0,
+
+ /* SPDIF */
+ MX6DL_PAD_KEY_COL3__SPDIF_IN1,
+
+ /* Touchscreen interrupt */
+ MX6DL_PAD_EIM_EB0__GPIO_2_28,
+
+ /* USBOTG ID pin */
+ MX6DL_PAD_ENET_RX_ER__ANATOP_USBOTG_ID,
+
+ /* VIDEO adv7180 INTRQ */
+ MX6DL_PAD_ENET_RXD0__GPIO_1_27,
+ /* UART 2 */
+ MX6DL_PAD_GPIO_7__UART2_TXD,
+ MX6DL_PAD_GPIO_8__UART2_RXD,
+ MX6DL_PAD_SD4_DAT6__UART2_CTS,
+ MX6DL_PAD_SD4_DAT5__UART2_RTS,
+
+ /*USBs OC pin */
+ MX6DL_PAD_EIM_WAIT__GPIO_5_0, /*HOST1_OC*/
+ MX6DL_PAD_SD4_DAT0__GPIO_2_8, /*OTG_OC*/
+
+ /* DISP0 I2C ENABLE*/
+ MX6DL_PAD_EIM_D28__GPIO_3_28,
+
+ /* DISP0 DET */
+ MX6DL_PAD_EIM_D31__GPIO_3_31,
+
+ /* DISP0 RESET */
+ MX6DL_PAD_EIM_WAIT__GPIO_5_0,
+
+ /* HDMI */
+ MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE,
+
+#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ MX6DL_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1,
+#else
+ /* MLB150 */
+ MX6DL_PAD_ENET_TXD1__MLB_MLBCLK,
+ MX6DL_PAD_GPIO_6__MLB_MLBSIG,
+ MX6DL_PAD_GPIO_2__MLB_MLBDAT,
+#endif
+};
+
+static iomux_v3_cfg_t mx6dl_sabreauto_can0_pads[] = {
+ /* CAN1 */
+ MX6DL_PAD_KEY_COL2__CAN1_TXCAN,
+ MX6DL_PAD_KEY_ROW2__CAN1_RXCAN,
+};
+
+
+static iomux_v3_cfg_t mx6dl_sabreauto_can1_pads[] = {
+ /* CAN2 */
+ MX6DL_PAD_KEY_COL4__CAN2_TXCAN,
+ MX6DL_PAD_KEY_ROW4__CAN2_RXCAN,
+};
+
+static iomux_v3_cfg_t mx6dl_sabreauto_mipi_sensor_pads[] = {
+ MX6DL_PAD_CSI0_MCLK__CCM_CLKO,
+};
+
+#define MX6DL_USDHC_PAD_SETTING(id, speed) \
+mx6dl_sd##id##_##speed##mhz[] = { \
+ MX6DL_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \
+ MX6DL_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \
+}
+
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 50);
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 100);
+static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 200);
+
+/* The GPMI is conflicted with SD3, so init this in the driver. */
+static iomux_v3_cfg_t mx6dl_gpmi_nand[] __initdata = {
+ MX6DL_PAD_NANDF_CLE__RAWNAND_CLE,
+ MX6DL_PAD_NANDF_ALE__RAWNAND_ALE,
+ MX6DL_PAD_NANDF_CS0__RAWNAND_CE0N,
+ MX6DL_PAD_NANDF_CS1__RAWNAND_CE1N,
+ MX6DL_PAD_NANDF_RB0__RAWNAND_READY0,
+ MX6DL_PAD_SD4_DAT0__RAWNAND_DQS,
+ MX6DL_PAD_NANDF_D0__RAWNAND_D0,
+ MX6DL_PAD_NANDF_D1__RAWNAND_D1,
+ MX6DL_PAD_NANDF_D2__RAWNAND_D2,
+ MX6DL_PAD_NANDF_D3__RAWNAND_D3,
+ MX6DL_PAD_NANDF_D4__RAWNAND_D4,
+ MX6DL_PAD_NANDF_D5__RAWNAND_D5,
+ MX6DL_PAD_NANDF_D6__RAWNAND_D6,
+ MX6DL_PAD_NANDF_D7__RAWNAND_D7,
+ MX6DL_PAD_SD4_CMD__RAWNAND_RDN,
+ MX6DL_PAD_SD4_CLK__RAWNAND_WRN,
+ MX6DL_PAD_NANDF_WP_B__RAWNAND_RESETN,
+};
+
+static iomux_v3_cfg_t mx6dl_i2c3_pads_rev_a[] __initdata = {
+ MX6DL_PAD_GPIO_3__I2C3_SCL,
+ MX6DL_PAD_GPIO_16__I2C3_SDA,
+};
+
+static iomux_v3_cfg_t mx6dl_i2c3_pads_rev_b[] __initdata = {
+ MX6DL_PAD_GPIO_3__I2C3_SCL,
+ MX6DL_PAD_EIM_D18__I2C3_SDA,
+};
+static iomux_v3_cfg_t mx6dl_tuner_pads[] __initdata = {
+ MX6DL_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC,
+ MX6DL_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS,
+ MX6DL_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD,
+};
+static iomux_v3_cfg_t mx6dl_extra_pads_rev_b[] __initdata = {
+ MX6DL_PAD_EIM_A24__GPIO_5_4,
+ MX6DL_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT,
+};
+static iomux_v3_cfg_t mx6dl_spinor_pads[] __initdata = {
+ /* eCSPI1 */
+ MX6DL_PAD_EIM_D16__ECSPI1_SCLK,
+ MX6DL_PAD_EIM_D17__ECSPI1_MISO,
+ MX6DL_PAD_EIM_D18__ECSPI1_MOSI,
+ MX6DL_PAD_EIM_D19__ECSPI1_SS1,
+
+ MX6DL_PAD_EIM_D19__GPIO_3_19,
+};
+
+/*Bluetooth is conflicted with GMPI and NOR chips*/
+static iomux_v3_cfg_t mx6dl_bluetooth_pads[] __initdata = {
+ /* UART 3 */
+ MX6DL_PAD_SD4_CLK__UART3_RXD,
+ MX6DL_PAD_SD4_CMD__UART3_TXD,
+ MX6DL_PAD_EIM_D30__UART3_CTS,
+ MX6DL_PAD_EIM_EB3__UART3_RTS,
+};
+
+static iomux_v3_cfg_t mx6dl_weimnor_pads[] __initdata = {
+ /* Parallel NOR */
+ MX6DL_PAD_EIM_OE__WEIM_WEIM_OE,
+ MX6DL_PAD_EIM_RW__WEIM_WEIM_RW,
+ MX6DL_PAD_EIM_WAIT__WEIM_WEIM_WAIT,
+ MX6DL_PAD_EIM_CS0__WEIM_WEIM_CS_0,
+ /*Control NOR reset using gpio mode*/
+ MX6DL_PAD_DISP0_DAT8__GPIO_4_29,
+
+ MX6DL_PAD_EIM_LBA__WEIM_WEIM_LBA,
+ MX6DL_PAD_EIM_BCLK__WEIM_WEIM_BCLK,
+ /* Parallel Nor Data Bus */
+ MX6DL_PAD_EIM_D16__WEIM_WEIM_D_16,
+ MX6DL_PAD_EIM_D17__WEIM_WEIM_D_17,
+ MX6DL_PAD_EIM_D18__WEIM_WEIM_D_18,
+ MX6DL_PAD_EIM_D19__WEIM_WEIM_D_19,
+ MX6DL_PAD_EIM_D20__WEIM_WEIM_D_20,
+ MX6DL_PAD_EIM_D21__WEIM_WEIM_D_21,
+ MX6DL_PAD_EIM_D22__WEIM_WEIM_D_22,
+ MX6DL_PAD_EIM_D23__WEIM_WEIM_D_23,
+ MX6DL_PAD_EIM_D24__WEIM_WEIM_D_24,
+ MX6DL_PAD_EIM_D25__WEIM_WEIM_D_25,
+ MX6DL_PAD_EIM_D26__WEIM_WEIM_D_26,
+ MX6DL_PAD_EIM_D27__WEIM_WEIM_D_27,
+ MX6DL_PAD_EIM_D28__WEIM_WEIM_D_28,
+ MX6DL_PAD_EIM_D29__WEIM_WEIM_D_29,
+ MX6DL_PAD_EIM_D30__WEIM_WEIM_D_30,
+ MX6DL_PAD_EIM_D31__WEIM_WEIM_D_31,
+
+ /* Parallel Nor 25 bit Address Bus */
+ MX6DL_PAD_EIM_A24__GPIO_5_4,
+ MX6DL_PAD_EIM_A23__WEIM_WEIM_A_23,
+ MX6DL_PAD_EIM_A22__WEIM_WEIM_A_22,
+ MX6DL_PAD_EIM_A21__WEIM_WEIM_A_21,
+ MX6DL_PAD_EIM_A20__WEIM_WEIM_A_20,
+ MX6DL_PAD_EIM_A19__WEIM_WEIM_A_19,
+ MX6DL_PAD_EIM_A18__WEIM_WEIM_A_18,
+ MX6DL_PAD_EIM_A17__WEIM_WEIM_A_17,
+ MX6DL_PAD_EIM_A16__WEIM_WEIM_A_16,
+
+ MX6DL_PAD_EIM_DA15__WEIM_WEIM_DA_A_15,
+ MX6DL_PAD_EIM_DA14__WEIM_WEIM_DA_A_14,
+ MX6DL_PAD_EIM_DA13__WEIM_WEIM_DA_A_13,
+ MX6DL_PAD_EIM_DA12__WEIM_WEIM_DA_A_12,
+ MX6DL_PAD_EIM_DA11__WEIM_WEIM_DA_A_11,
+ MX6DL_PAD_EIM_DA10__WEIM_WEIM_DA_A_10,
+ MX6DL_PAD_EIM_DA9__WEIM_WEIM_DA_A_9,
+ MX6DL_PAD_EIM_DA8__WEIM_WEIM_DA_A_8,
+ MX6DL_PAD_EIM_DA7__WEIM_WEIM_DA_A_7,
+ MX6DL_PAD_EIM_DA6__WEIM_WEIM_DA_A_6,
+ MX6DL_PAD_EIM_DA5__WEIM_WEIM_DA_A_5,
+ MX6DL_PAD_EIM_DA4__WEIM_WEIM_DA_A_4,
+ MX6DL_PAD_EIM_DA3__WEIM_WEIM_DA_A_3,
+ MX6DL_PAD_EIM_DA2__WEIM_WEIM_DA_A_2,
+ MX6DL_PAD_EIM_DA1__WEIM_WEIM_DA_A_1,
+ MX6DL_PAD_EIM_DA0__WEIM_WEIM_DA_A_0,
+};
+
+static iomux_v3_cfg_t mx6dl_sabreauto_hdmi_ddc_pads[] = {
+ MX6DL_PAD_EIM_EB2__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6dl_sabreauto_i2c2_pads[] = {
+ MX6DL_PAD_EIM_EB2__I2C2_SCL, /* I2C2 SCL */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c
new file mode 100644
index 00000000..2d408b8b
--- /dev/null
+++ b/arch/arm/mach-mx6/bus_freq.c
@@ -0,0 +1,842 @@
+/*
+ * Copyright (C) 2011-2013 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.
+ */
+
+/*!
+ * @file bus_freq.c
+ *
+ * @brief A common API for the Freescale Semiconductor i.MXC CPUfreq module
+ * and DVFS CORE module.
+ *
+ * The APIs are for setting bus frequency to low or high.
+ *
+ * @ingroup PM
+ */
+#include <asm/io.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mutex.h>
+#include <mach/iram.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/sdram_autogating.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/tlb.h>
+#include "crm_regs.h"
+#include <linux/suspend.h>
+
+#define LPAPM_CLK 24000000
+#define DDR_AUDIO_CLK 100000000
+#define DDR_MED_CLK 400000000
+#define DDR3_NORMAL_CLK 528000000
+#define GPC_PGC_GPU_PGCR_OFFSET 0x260
+#define GPC_CNTR_OFFSET 0x0
+
+static DEFINE_SPINLOCK(freq_lock);
+
+int low_bus_freq_mode;
+int audio_bus_freq_mode;
+int high_bus_freq_mode;
+int med_bus_freq_mode;
+
+int bus_freq_scaling_initialized;
+static struct device *busfreq_dev;
+static int busfreq_suspended;
+
+/* True if bus_frequency is scaled not using DVFS-PER */
+int bus_freq_scaling_is_active;
+
+int lp_high_freq;
+int lp_med_freq;
+int lp_audio_freq;
+int high_cpu_freq;
+unsigned int ddr_low_rate;
+unsigned int ddr_med_rate;
+unsigned int ddr_normal_rate;
+
+int low_freq_bus_used(void);
+void set_ddr_freq(int ddr_freq);
+void *mx6sl_wfi_iram_base;
+unsigned long mx6sl_wfi_iram_phys_addr;
+
+void (*mx6sl_wfi_iram)(int arm_podf, unsigned long wfi_iram_addr,\
+ int audio_mode) = NULL;
+extern void mx6sl_wait (int arm_podf, unsigned long wfi_iram_addr);
+
+void *mx6sl_ddr_freq_base;
+unsigned long mx6sl_ddr_freq_phys_addr;
+void (*mx6sl_ddr_freq_change_iram)(int ddr_freq, int low_bus_freq_mode) = NULL;
+extern void mx6sl_ddr_iram(int ddr_freq);
+
+extern int init_mmdc_settings(void);
+extern struct cpu_op *(*get_cpu_op)(int *op);
+extern int update_ddr_freq(int ddr_rate);
+extern unsigned long save_ttbr1(void);
+extern void restore_ttbr1(u32 ttbr1);
+extern int chip_rev;
+
+DEFINE_MUTEX(bus_freq_mutex);
+
+struct timeval start_time;
+struct timeval end_time;
+
+static int cpu_op_nr;
+static u32 org_arm_podf;
+static struct cpu_op *cpu_op_tbl;
+static struct clk *pll2_400;
+static struct clk *axi_clk;
+static struct clk *ahb_clk;
+static struct clk *periph_clk;
+static struct clk *osc_clk;
+static struct clk *cpu_clk;
+static struct clk *pll3;
+static struct clk *pll2;
+static struct clk *pll1;
+static struct clk *pll1_sw_clk;
+static struct clk *pll3_sw_clk;
+static struct clk *pll2_200;
+struct clk *mmdc_ch0_axi;
+static struct clk *pll3_540;
+
+static struct delayed_work low_bus_freq_handler;
+
+void reduce_bus_freq(void)
+{
+ if (!cpu_is_mx6sl()) {
+ if (cpu_is_mx6dl() &&
+ (clk_get_parent(axi_clk) != periph_clk))
+ /* Set the axi_clk to be sourced from the periph_clk.
+ * So that its frequency can be lowered down to 50MHz
+ * or 24MHz as the case may be.
+ */
+ clk_set_parent(axi_clk, periph_clk);
+
+ clk_enable(pll3);
+ if (lp_audio_freq) {
+ /* Need to ensure that PLL2_PFD_400M is kept ON. */
+ clk_enable(pll2_400);
+ update_ddr_freq(DDR_AUDIO_CLK);
+ /* Make sure periph clk's parent also got updated */
+ clk_set_parent(periph_clk, pll2_200);
+ audio_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ } else {
+ update_ddr_freq(LPAPM_CLK);
+ /* Make sure periph clk's parent also got updated */
+ clk_set_parent(periph_clk, osc_clk);
+ if (audio_bus_freq_mode)
+ clk_disable(pll2_400);
+ low_bus_freq_mode = 1;
+ audio_bus_freq_mode = 0;
+ }
+
+ if (med_bus_freq_mode)
+ clk_disable(pll2_400);
+
+ clk_disable(pll3);
+ med_bus_freq_mode = 0;
+ } else {
+ u32 reg;
+ u32 div;
+ unsigned long flags;
+
+ if (high_bus_freq_mode) {
+ /* Set periph_clk to be sourced from OSC_CLK */
+ /* Set AXI to 24MHz. */
+ clk_set_parent(periph_clk, osc_clk);
+ clk_set_rate(axi_clk,
+ clk_round_rate(axi_clk, LPAPM_CLK));
+ /* Set AHB to 24MHz. */
+ clk_set_rate(ahb_clk,
+ clk_round_rate(ahb_clk, LPAPM_CLK));
+ }
+ if (lp_audio_freq) {
+ u32 ttbr1;
+ /* PLL2 is on in this mode, as DDR is at 100MHz. */
+ /* Now change DDR freq while running from IRAM. */
+
+ /* Set AHB to 24MHz. */
+ clk_set_rate(ahb_clk,
+ clk_round_rate(ahb_clk, LPAPM_CLK / 3));
+
+ spin_lock_irqsave(&freq_lock, flags);
+ /* sync the outer cache. */
+ outer_sync();
+
+ /* Save TTBR1 */
+ ttbr1 = save_ttbr1();
+
+ mx6sl_ddr_freq_change_iram(DDR_AUDIO_CLK,
+ low_bus_freq_mode);
+ restore_ttbr1(ttbr1);
+
+ spin_unlock_irqrestore(&freq_lock, flags);
+
+ if (low_bus_freq_mode) {
+ /* Swtich ARM to run off PLL2_PFD2_400MHz
+ * since DDR is anyway at 100MHz.
+ */
+ clk_set_parent(pll1_sw_clk, pll2_400);
+
+ /* Ensure that the clock will be
+ * at original speed.
+ */
+ reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR);
+ while (__raw_readl(MXC_CCM_CDHIPR))
+ ;
+ /* We have enabled PLL1 in the code below when
+ * ARM is from PLL1, so disable it here.
+ */
+ clk_disable(pll1);
+ }
+ low_bus_freq_mode = 0;
+ audio_bus_freq_mode = 1;
+ } else {
+ u32 ttbr1;
+ /* Set MMDC clk to 24MHz. */
+ /* Since we are going to set PLL2 in bypass mode,
+ * move the CPU clock off PLL2.
+ */
+ /* Ensure that the clock will be at
+ * lowest possible freq.
+ */
+ org_arm_podf = __raw_readl(MXC_CCM_CACRR);
+ /* Need to enable PLL1 before setting its rate. */
+ clk_enable(pll1);
+ clk_set_rate(pll1,
+ cpu_op_tbl[cpu_op_nr - 1].pll_lpm_rate);
+ div = clk_get_rate(pll1) /
+ cpu_op_tbl[cpu_op_nr - 1].cpu_rate;
+
+ reg = __raw_writel(div - 1, MXC_CCM_CACRR);
+ while (__raw_readl(MXC_CCM_CDHIPR))
+ ;
+ clk_set_parent(pll1_sw_clk, pll1);
+
+ spin_lock_irqsave(&freq_lock, flags);
+ /* sync the outer cache. */
+ outer_sync();
+
+ ttbr1 = save_ttbr1();
+ /* Now change DDR freq while running from IRAM. */
+ mx6sl_ddr_freq_change_iram(LPAPM_CLK,
+ low_bus_freq_mode);
+ restore_ttbr1(ttbr1);
+
+ spin_unlock_irqrestore(&freq_lock, flags);
+
+ low_bus_freq_mode = 1;
+ audio_bus_freq_mode = 0;
+ }
+ }
+ high_bus_freq_mode = 0;
+
+}
+
+static void reduce_bus_freq_handler(struct work_struct *work)
+{
+ mutex_lock(&bus_freq_mutex);
+
+ if (!low_freq_bus_used()) {
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ /* If we are already in audio bus freq mode,
+ * just return if lp_audio_freq is true.
+ */
+ if (audio_bus_freq_mode && lp_audio_freq) {
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+
+ /* If we dont want to transition from low bus to
+ * audio bus mode and are already in
+ *low bus mode, then return.
+ */
+ if (!lp_audio_freq && low_bus_freq_mode) {
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ reduce_bus_freq();
+
+ mutex_unlock(&bus_freq_mutex);
+}
+
+/* Set the DDR, AHB to 24MHz.
+ * This mode will be activated only when none of the modules that
+ * need a higher DDR or AHB frequency are active.
+ */
+int set_low_bus_freq(void)
+{
+ if (busfreq_suspended)
+ return 0;
+
+ if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
+ return 0;
+
+ /* Check to see if we need to get from
+ * low bus freq mode to audio bus freq mode.
+ * If so, the change needs to be done immediately.
+ */
+ if (lp_audio_freq && low_bus_freq_mode)
+ reduce_bus_freq();
+ else
+ /* Don't lower the frequency immediately. Instead
+ * scheduled a delayed work and drop the freq if
+ * the conditions still remain the same.
+ */
+ schedule_delayed_work(&low_bus_freq_handler,
+ usecs_to_jiffies(500000));
+ return 0;
+}
+
+/* Set the DDR to either 528MHz or 400MHz for MX6q
+ * or 400MHz for MX6DL.
+ */
+int set_high_bus_freq(int high_bus_freq)
+{
+ if (bus_freq_scaling_initialized && bus_freq_scaling_is_active)
+ cancel_delayed_work_sync(&low_bus_freq_handler);
+
+ if (busfreq_suspended)
+ return 0;
+
+
+ if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
+ return 0;
+
+ if (cpu_is_mx6sl())
+ high_bus_freq = 1;
+
+ if (high_bus_freq_mode && high_bus_freq)
+ return 0;
+
+
+ /* medium bus freq is only supported for MX6DQ */
+ if (cpu_is_mx6q() && med_bus_freq_mode && !high_bus_freq)
+ return 0;
+
+ if (cpu_is_mx6dl() && high_bus_freq)
+ high_bus_freq = 0;
+
+ if (cpu_is_mx6dl() && med_bus_freq_mode)
+ return 0;
+
+ if ((high_bus_freq_mode && (high_bus_freq || lp_high_freq)) ||
+ (med_bus_freq_mode && !high_bus_freq && lp_med_freq &&
+ !lp_high_freq))
+ return 0;
+
+ if (cpu_is_mx6sl()) {
+ u32 reg;
+ unsigned long flags;
+ u32 ttbr1;
+
+ spin_lock_irqsave(&freq_lock, flags);
+ /* sync the outer cache. */
+ outer_sync();
+
+ ttbr1 = save_ttbr1();
+
+ /* Change DDR freq in IRAM. */
+ mx6sl_ddr_freq_change_iram(ddr_normal_rate, low_bus_freq_mode);
+
+ restore_ttbr1(ttbr1);
+
+ spin_unlock_irqrestore(&freq_lock, flags);
+
+ /* Set periph_clk to be sourced from pll2_pfd2_400M */
+ /* First need to set the divider before changing the */
+ /* parent if parent clock is larger than previous one */
+ clk_set_rate(ahb_clk, clk_round_rate(ahb_clk,
+ LPAPM_CLK / 3));
+ clk_set_rate(axi_clk,
+ clk_round_rate(axi_clk, LPAPM_CLK / 2));
+ clk_set_parent(periph_clk, pll2_400);
+
+ if (low_bus_freq_mode) {
+ /* Now move ARM to be sourced from PLL2_400 too. */
+ clk_set_parent(pll1_sw_clk, pll2_400);
+
+ /* Ensure that the clock will be at original speed. */
+ reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR);
+ while (__raw_readl(MXC_CCM_CDHIPR))
+ ;
+ clk_disable(pll1);
+ }
+ high_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ audio_bus_freq_mode = 0;
+ } else {
+ clk_enable(pll3);
+ if (high_bus_freq) {
+ update_ddr_freq(ddr_normal_rate);
+ /* Make sure periph clk's parent also got updated */
+ clk_set_parent(periph_clk, pll2);
+ if (med_bus_freq_mode)
+ clk_disable(pll2_400);
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+ } else {
+ clk_enable(pll2_400);
+ update_ddr_freq(ddr_med_rate);
+ /* Make sure periph clk's parent also got updated */
+ clk_set_parent(periph_clk, pll2_400);
+ high_bus_freq_mode = 0;
+ med_bus_freq_mode = 1;
+ }
+ if (audio_bus_freq_mode)
+ clk_disable(pll2_400);
+
+ /* AXI_CLK is sourced from PLL3_PFD_540 on MX6DL */
+ if (cpu_is_mx6dl() &&
+ clk_get_parent(axi_clk) != pll3_540)
+ clk_set_parent(axi_clk, pll3_540);
+
+ low_bus_freq_mode = 0;
+ audio_bus_freq_mode = 0;
+
+ clk_disable(pll3);
+ }
+ return 0;
+}
+
+int low_freq_bus_used(void)
+{
+ if (!bus_freq_scaling_initialized)
+ return 0;
+
+ /* We only go the lowest setpoint if ARM is also
+ * at the lowest setpoint.
+ */
+ if (high_cpu_freq)
+ return 0;
+
+ if ((lp_high_freq == 0)
+ && (lp_med_freq == 0))
+ return 1;
+ else
+ return 0;
+}
+
+void bus_freq_update(struct clk *clk, bool flag)
+{
+ mutex_lock(&bus_freq_mutex);
+
+ if (flag) {
+ if (clk == cpu_clk) {
+ /* The CPU freq is being increased.
+ * check if we need to increase the bus freq
+ */
+ high_cpu_freq = 1;
+ if (low_bus_freq_mode || audio_bus_freq_mode)
+ set_high_bus_freq(0);
+ } else {
+ /* Update count */
+ if (clk->flags & AHB_HIGH_SET_POINT)
+ lp_high_freq++;
+ else if (clk->flags & AHB_MED_SET_POINT)
+ lp_med_freq++;
+ else if (clk->flags & AHB_AUDIO_SET_POINT)
+ lp_audio_freq++;
+ /* Update bus freq */
+ if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
+ && (clk_get_usecount(clk) == 0)) {
+ if (!(clk->flags &
+ (AHB_HIGH_SET_POINT | AHB_MED_SET_POINT))) {
+ if (low_freq_bus_used())
+ set_low_bus_freq();
+ } else {
+ if ((clk->flags & AHB_MED_SET_POINT)
+ && !med_bus_freq_mode) {
+ /* Set to Medium setpoint */
+ set_high_bus_freq(0);
+ } else if ((clk->flags & AHB_HIGH_SET_POINT)
+ && !high_bus_freq_mode) {
+ /* Currently at low or medium
+ * set point, need to set to
+ * high setpoint
+ */
+ set_high_bus_freq(1);
+ }
+ }
+ }
+ }
+ } else {
+ if (clk == cpu_clk) {
+ /* CPU freq is dropped, check if we can
+ * lower the bus freq.
+ */
+ high_cpu_freq = 0;
+
+ if (low_freq_bus_used() &&
+ !(low_bus_freq_mode || audio_bus_freq_mode))
+ set_low_bus_freq();
+ } else {
+ /* Update count */
+ if (clk->flags & AHB_HIGH_SET_POINT)
+ lp_high_freq--;
+ else if (clk->flags & AHB_MED_SET_POINT)
+ lp_med_freq--;
+ else if (clk->flags & AHB_AUDIO_SET_POINT)
+ lp_audio_freq--;
+ /* Update bus freq */
+ if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
+ && (clk_get_usecount(clk) == 0)) {
+ if (low_freq_bus_used())
+ set_low_bus_freq();
+ else {
+ /* Set to either high or
+ * medium setpoint.
+ */
+ set_high_bus_freq(0);
+ }
+ }
+ }
+ }
+ mutex_unlock(&bus_freq_mutex);
+ return;
+}
+void setup_pll(void)
+{
+}
+
+static ssize_t bus_freq_scaling_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (bus_freq_scaling_is_active)
+ return sprintf(buf, "Bus frequency scaling is enabled\n");
+ else
+ return sprintf(buf, "Bus frequency scaling is disabled\n");
+}
+
+static ssize_t bus_freq_scaling_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ if (strncmp(buf, "1", 1) == 0) {
+#ifdef CONFIG_MX6_VPU_352M
+ if (cpu_is_mx6q())
+ /*do not enable bus freq*/
+ bus_freq_scaling_is_active = 0;
+ printk(KERN_WARNING "Bus frequency can't be enabled if using VPU 352M!\n");
+ return size;
+#else
+ bus_freq_scaling_is_active = 1;
+#endif
+ set_high_bus_freq(0);
+ /* Make sure system can enter low bus mode if it should be in
+ low bus mode */
+ if (low_freq_bus_used() && !low_bus_freq_mode)
+ set_low_bus_freq();
+ } else if (strncmp(buf, "0", 1) == 0) {
+ if (bus_freq_scaling_is_active)
+ set_high_bus_freq(1);
+ bus_freq_scaling_is_active = 0;
+ }
+ return size;
+}
+
+static int busfreq_suspend(struct platform_device *pdev, pm_message_t message)
+{
+ return 0;
+}
+
+static int bus_freq_pm_notify(struct notifier_block *nb, unsigned long event,
+ void *dummy)
+{
+ mutex_lock(&bus_freq_mutex);
+
+ if (event == PM_SUSPEND_PREPARE) {
+ set_high_bus_freq(1);
+ busfreq_suspended = 1;
+ } else if (event == PM_POST_SUSPEND) {
+ busfreq_suspended = 0;
+ }
+
+ mutex_unlock(&bus_freq_mutex);
+
+ return NOTIFY_OK;
+}
+static int busfreq_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+static struct notifier_block imx_bus_freq_pm_notifier = {
+ .notifier_call = bus_freq_pm_notify,
+};
+
+static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
+ bus_freq_scaling_enable_store);
+
+/*!
+ * This is the probe routine for the bus frequency driver.
+ *
+ * @param pdev The platform device structure
+ *
+ * @return The function returns 0 on success
+ *
+ */
+
+static int __devinit busfreq_probe(struct platform_device *pdev)
+{
+ u32 err;
+
+ busfreq_dev = &pdev->dev;
+
+ pll2_400 = clk_get(NULL, "pll2_pfd_400M");
+ if (IS_ERR(pll2_400)) {
+ printk(KERN_DEBUG "%s: failed to get pll2_pfd_400M\n",
+ __func__);
+ return PTR_ERR(pll2_400);
+ }
+
+ pll2_200 = clk_get(NULL, "pll2_200M");
+ if (IS_ERR(pll2_200)) {
+ printk(KERN_DEBUG "%s: failed to get pll2_200M\n",
+ __func__);
+ return PTR_ERR(pll2_200);
+ }
+
+ pll2 = clk_get(NULL, "pll2");
+ if (IS_ERR(pll2)) {
+ printk(KERN_DEBUG "%s: failed to get pll2\n",
+ __func__);
+ return PTR_ERR(pll2);
+ }
+
+ pll1 = clk_get(NULL, "pll1_main_clk");
+ if (IS_ERR(pll1)) {
+ printk(KERN_DEBUG "%s: failed to get pll1\n",
+ __func__);
+ return PTR_ERR(pll1);
+ }
+
+ pll1_sw_clk = clk_get(NULL, "pll1_sw_clk");
+ if (IS_ERR(pll1_sw_clk)) {
+ printk(KERN_DEBUG "%s: failed to get pll1_sw_clk\n",
+ __func__);
+ return PTR_ERR(pll1_sw_clk);
+ }
+
+
+ if (IS_ERR(pll2)) {
+ printk(KERN_DEBUG "%s: failed to get pll2\n",
+ __func__);
+ return PTR_ERR(pll2);
+ }
+
+
+ cpu_clk = clk_get(NULL, "cpu_clk");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_DEBUG "%s: failed to get cpu_clk\n",
+ __func__);
+ return PTR_ERR(cpu_clk);
+ }
+
+ pll3 = clk_get(NULL, "pll3_main_clk");
+ if (IS_ERR(pll3)) {
+ printk(KERN_DEBUG "%s: failed to get pll3\n",
+ __func__);
+ return PTR_ERR(pll3);
+ }
+
+ pll3_540 = clk_get(NULL, "pll3_pfd_540M");
+ if (IS_ERR(pll3_540)) {
+ printk(KERN_DEBUG "%s: failed to get periph_clk\n",
+ __func__);
+ return PTR_ERR(pll3_540);
+ }
+
+ pll3_sw_clk = clk_get(NULL, "pll3_sw_clk");
+ if (IS_ERR(pll3_sw_clk)) {
+ printk(KERN_DEBUG "%s: failed to get pll3_sw_clk\n",
+ __func__);
+ return PTR_ERR(pll3_sw_clk);
+ }
+
+ axi_clk = clk_get(NULL, "axi_clk");
+ if (IS_ERR(axi_clk)) {
+ printk(KERN_DEBUG "%s: failed to get axi_clk\n",
+ __func__);
+ return PTR_ERR(axi_clk);
+ }
+
+ ahb_clk = clk_get(NULL, "ahb");
+ if (IS_ERR(ahb_clk)) {
+ printk(KERN_DEBUG "%s: failed to get ahb_clk\n",
+ __func__);
+ return PTR_ERR(ahb_clk);
+ }
+
+ periph_clk = clk_get(NULL, "periph_clk");
+ if (IS_ERR(periph_clk)) {
+ printk(KERN_DEBUG "%s: failed to get periph_clk\n",
+ __func__);
+ return PTR_ERR(periph_clk);
+ }
+
+ osc_clk = clk_get(NULL, "osc");
+ if (IS_ERR(osc_clk)) {
+ printk(KERN_DEBUG "%s: failed to get osc_clk\n",
+ __func__);
+ return PTR_ERR(osc_clk);
+ }
+
+ mmdc_ch0_axi = clk_get(NULL, "mmdc_ch0_axi");
+ if (IS_ERR(mmdc_ch0_axi)) {
+ printk(KERN_DEBUG "%s: failed to get mmdc_ch0_axi\n",
+ __func__);
+ return PTR_ERR(mmdc_ch0_axi);
+ }
+
+ err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
+ if (err) {
+ printk(KERN_ERR
+ "Unable to register sysdev entry for BUSFREQ");
+ return err;
+ }
+
+ cpu_op_tbl = get_cpu_op(&cpu_op_nr);
+ low_bus_freq_mode = 0;
+ if (cpu_is_mx6dl()) {
+ high_bus_freq_mode = 0;
+ med_bus_freq_mode = 1;
+ /* To make pll2_400 use count right, as when
+ system enter 24M, it will disable pll2_400 */
+ clk_enable(pll2_400);
+ } else if (cpu_is_mx6sl()) {
+ /* Set med_bus_freq_mode to 1 since med_bus_freq_mode
+ is not supported as yet for MX6SL */
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 1;
+ } else {
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+ }
+ bus_freq_scaling_is_active = 0;
+ bus_freq_scaling_initialized = 1;
+
+ if (cpu_is_mx6q()) {
+ ddr_low_rate = LPAPM_CLK;
+ ddr_med_rate = DDR_MED_CLK;
+ ddr_normal_rate = DDR3_NORMAL_CLK;
+ }
+ if (cpu_is_mx6dl() || cpu_is_mx6sl()) {
+ ddr_low_rate = LPAPM_CLK;
+ ddr_normal_rate = ddr_med_rate = DDR_MED_CLK;
+ }
+
+ INIT_DELAYED_WORK(&low_bus_freq_handler, reduce_bus_freq_handler);
+ register_pm_notifier(&imx_bus_freq_pm_notifier);
+
+ if (!cpu_is_mx6sl())
+ init_mmdc_settings();
+ else {
+ /* Use preallocated memory */
+ mx6sl_wfi_iram_phys_addr = MX6SL_WFI_IRAM_CODE;
+
+ /*
+ * Don't ioremap the address, we have fixed the IRAM address
+ * at IRAM_BASE_ADDR_VIRT
+ */
+ mx6sl_wfi_iram_base = (void *)IRAM_BASE_ADDR_VIRT +
+ (mx6sl_wfi_iram_phys_addr - IRAM_BASE_ADDR);
+
+ memcpy(mx6sl_wfi_iram_base, mx6sl_wait, MX6SL_WFI_IRAM_CODE_SIZE);
+ mx6sl_wfi_iram = (void *)mx6sl_wfi_iram_base;
+
+ /* Use preallocated memory */
+ mx6sl_ddr_freq_phys_addr = MX6_DDR_FREQ_IRAM_CODE;
+
+ /*
+ * Don't ioremap the address, we have fixed the IRAM address
+ * at IRAM_BASE_ADDR_VIRT
+ */
+ mx6sl_ddr_freq_base = (void *)IRAM_BASE_ADDR_VIRT +
+ (mx6sl_ddr_freq_phys_addr - IRAM_BASE_ADDR);
+
+ memcpy(mx6sl_ddr_freq_base, mx6sl_ddr_iram, MX6SL_DDR_FREQ_CODE_SIZE);
+ mx6sl_ddr_freq_change_iram = (void *)mx6sl_ddr_freq_base;
+ }
+
+ return 0;
+}
+
+static struct platform_driver busfreq_driver = {
+ .driver = {
+ .name = "imx_busfreq",
+ },
+ .probe = busfreq_probe,
+ .suspend = busfreq_suspend,
+ .resume = busfreq_resume,
+};
+
+/*!
+ * Initialise the busfreq_driver.
+ *
+ * @return The function always returns 0.
+ */
+
+static int __init busfreq_init(void)
+{
+ if (platform_driver_register(&busfreq_driver) != 0) {
+ printk(KERN_ERR "busfreq_driver register failed\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "Bus freq driver module loaded\n");
+
+#ifdef CONFIG_MX6_VPU_352M
+ if (cpu_is_mx6q())
+ bus_freq_scaling_is_active = 0;/*disable bus_freq*/
+
+#else
+ /* Enable busfreq by default. */
+ bus_freq_scaling_is_active = 1;
+#endif
+ if (cpu_is_mx6q())
+ set_high_bus_freq(1);
+ else if (cpu_is_mx6dl())
+ set_high_bus_freq(0);
+
+ printk(KERN_INFO "Bus freq driver Enabled\n");
+ return 0;
+}
+
+static void __exit busfreq_cleanup(void)
+{
+ sysfs_remove_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
+
+ /* Unregister the device structure */
+ platform_driver_unregister(&busfreq_driver);
+ bus_freq_scaling_initialized = 0;
+}
+
+late_initcall(busfreq_init);
+module_exit(busfreq_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("BusFreq driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c
new file mode 100644
index 00000000..9d3dbfa2
--- /dev/null
+++ b/arch/arm/mach-mx6/clock.c
@@ -0,0 +1,5736 @@
+
+/*
+ * Copyright (C) 2012-2014 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/regulator/consumer.h>
+#include <asm/div64.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/ahci_sata.h>
+#include <mach/mxc_hdmi.h>
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "regs-anadig.h"
+
+#ifdef CONFIG_CLK_DEBUG
+#define __INIT_CLK_DEBUG(n) .name = #n,
+#else
+#define __INIT_CLK_DEBUG(n)
+#endif
+
+extern u32 arm_max_freq;
+extern int mxc_jtag_enabled;
+extern struct regulator *cpu_regulator;
+extern struct cpu_op *(*get_cpu_op)(int *op);
+extern int lp_high_freq;
+extern int lp_med_freq;
+extern int wait_mode_arm_podf;
+extern int lp_audio_freq;
+extern int cur_arm_podf;
+extern bool enet_is_active;
+
+void __iomem *apll_base;
+
+static void __iomem *timer_base;
+static struct clk ipu1_clk;
+static struct clk ipu2_clk;
+static struct clk axi_clk;
+static struct clk pll1_sys_main_clk;
+static struct clk pll2_528_bus_main_clk;
+static struct clk pll2_pfd_400M;
+static struct clk pll2_pfd_352M;
+static struct clk pll3_pfd_540M;
+static struct clk pll2_pfd_594M;
+static struct clk pll3_usb_otg_main_clk;
+static struct clk pll4_audio_main_clk;
+static struct clk pll5_video_main_clk;
+static struct clk pll6_mlb150_main_clk;
+static struct clk pll7_usb_host_main_clk;
+static struct clk pll8_enet_main_clk;
+static struct clk apbh_dma_clk;
+static struct clk openvg_axi_clk;
+static struct clk enfc_clk;
+static struct clk usdhc3_clk;
+static struct clk ipg_clk;
+static struct clk gpt_clk[];
+static struct clk clko2_clk;
+
+static struct cpu_op *cpu_op_tbl;
+static int cpu_op_nr;
+static bool pll1_enabled;
+static bool arm_needs_pll2_400;
+
+#define SPIN_DELAY 1200000 /* in nanoseconds */
+
+#define AUDIO_VIDEO_MIN_CLK_FREQ 650000000
+#define AUDIO_VIDEO_MAX_CLK_FREQ 1300000000
+DEFINE_SPINLOCK(clk_lock);
+#define V2_TCN 0x24
+#define V2_TSTAT 0x08
+#define V2_TSTAT_ROV (1 << 5)
+#define V2_TCTL_CLK_OSC_DIV8 (5 << 6)
+#define MXC_TCTL 0x00
+#define MXC_TPRER 0x04
+#define V2_TPRER_PRE24M_OFFSET 12
+#define V2_TPRER_PRE24M_MASK 0xF
+
+/* We need to check the exp status again after timer expiration,
+ * as there might be interrupt coming between the first time exp
+ * and the time reading, then the time reading may be several ms
+ * after the exp checking due to the irq handle, so we need to
+ * check it to make sure the exp return the right value after
+ * timer expiration. */
+#define WAIT(exp, timeout) \
+({ \
+ u32 gpt_rate; \
+ u32 gpt_ticks; \
+ u32 gpt_cnt; \
+ u32 reg; \
+ int result = 1; \
+ gpt_rate = clk_get_rate(&gpt_clk[0]); \
+ gpt_ticks = timeout / (1000000000 / gpt_rate); \
+ reg = __raw_readl(timer_base + V2_TSTAT);\
+ /* Clear the GPT roll over interrupt. */ \
+ if (reg & V2_TSTAT_ROV) { \
+ __raw_writel(V2_TSTAT_ROV, timer_base + V2_TSTAT);\
+ } \
+ gpt_cnt = __raw_readl(timer_base + V2_TCN); \
+ while (!(exp)) { \
+ if ((__raw_readl(timer_base + V2_TCN) - gpt_cnt) > gpt_ticks) { \
+ if (!exp) \
+ result = 0; \
+ break; \
+ } else { \
+ reg = __raw_readl(timer_base + V2_TSTAT);\
+ if (reg & V2_TSTAT_ROV) { \
+ u32 old_cnt = gpt_cnt; \
+ /* Timer has rolled over. \
+ * Calculate the new tick count. \
+ */ \
+ gpt_cnt = __raw_readl(timer_base + V2_TCN); \
+ gpt_ticks -= (0xFFFFFFFF - old_cnt + gpt_cnt); \
+ /* Clear the roll over interrupt. */ \
+ __raw_writel(V2_TSTAT_ROV, \
+ timer_base + V2_TSTAT); \
+ } \
+ } \
+ } \
+ result; \
+})
+
+/* 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 unsigned long anaclk_1_reference, anaclk_2_reference;
+
+/* For MX 6DL/S, Video PLL may be used by synchronous display devices,
+ * such as HDMI or LVDS, and also by the EPDC. If EPDC is in use,
+ * it must use the Video PLL to achieve the clock frequencies it needs.
+ * So if EPDC is in use, the "epdc" string should be added to kernel
+ * parameters, in order to set the EPDC parent clock to the Video PLL.
+ * This will have an impact on the behavior of HDMI and LVDS.
+ */
+int epdc_enabled;
+static int __init epdc_setup(char *__unused)
+{
+ epdc_enabled = 1;
+ return 1;
+}
+__setup("epdc", epdc_setup);
+
+static void __calc_pre_post_dividers(u32 max_podf, u32 div, u32 *pre, u32 *post)
+{
+ u32 min_pre, temp_pre, old_err, err;
+
+ /* Some of the podfs are 3 bits while others are 6 bits.
+ * Handle both cases here.
+ */
+ if (div >= 512 && (max_podf == 64)) {
+ /* For pre = 3bits and podf = 6 bits, max divider is 512. */
+ *pre = 8;
+ *post = 64;
+ } else if (div >= 64 && (max_podf == 8)) {
+ /* For pre = 3bits and podf = 3 bits, max divider is 64. */
+ *pre = 8;
+ *post = 8;
+ } else if (div >= 8) {
+ /* Find the minimum pre-divider for a max podf */
+ if (max_podf == 64)
+ min_pre = (div - 1) / (1 << 6) + 1;
+ else
+ min_pre = (div - 1) / (1 << 3) + 1;
+ old_err = 8;
+ /* Now loop through to find the max pre-divider. */
+ 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;
+ }
+}
+
+static int _clk_enable(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg |= MXC_CCM_CCGRx_CG_MASK << 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 &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+}
+
+static void _clk_disable_inwait(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ reg |= 1 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+}
+
+
+/*
+ * 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 0;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+ if (pll == &pll1_sys_main_clk)
+ return PLL1_SYS_BASE_ADDR;
+ else if (pll == &pll2_528_bus_main_clk)
+ return PLL2_528_BASE_ADDR;
+ else if (pll == &pll3_usb_otg_main_clk)
+ return PLL3_480_USB1_BASE_ADDR;
+ else if (pll == &pll4_audio_main_clk)
+ return PLL4_AUDIO_BASE_ADDR;
+ else if (pll == &pll5_video_main_clk)
+ return PLL5_VIDEO_BASE_ADDR;
+ else if (pll == &pll6_mlb150_main_clk)
+ return PLL6_MLB_BASE_ADDR;
+ else if (pll == &pll7_usb_host_main_clk)
+ return PLL7_480_USB2_BASE_ADDR;
+ else if (pll == &pll8_enet_main_clk)
+ return PLL8_ENET_BASE_ADDR;
+ else
+ BUG();
+ return NULL;
+}
+
+
+/*
+ * For the 6-to-1 muxed input clock
+ */
+static inline u32 _get_mux6(struct clk *parent, struct clk *m0, struct clk *m1,
+ struct clk *m2, struct clk *m3, struct clk *m4,
+ struct clk *m5)
+{
+ if (parent == m0)
+ return 0;
+ else if (parent == m1)
+ return 1;
+ else if (parent == m2)
+ return 2;
+ else if (parent == m3)
+ return 3;
+ else if (parent == m4)
+ return 4;
+ else if (parent == m5)
+ return 5;
+ else
+ BUG();
+
+ 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_anaclk_1_get_rate(struct clk *clk)
+{
+ return anaclk_1_reference;
+}
+
+static int _clk_anaclk_1_set_rate(struct clk *clk, unsigned long rate)
+{
+ anaclk_1_reference = rate;
+ return 0;
+}
+
+static unsigned long _clk_anaclk_2_get_rate(struct clk *clk)
+{
+ return anaclk_2_reference;
+}
+
+static int _clk_anaclk_2_set_rate(struct clk *clk, unsigned long rate)
+{
+ anaclk_2_reference = rate;
+ return 0;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+ __INIT_CLK_DEBUG(ckih_clk)
+ .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+ __INIT_CLK_DEBUG(ckih2_clk)
+ .get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+ __INIT_CLK_DEBUG(osc_clk)
+ .get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+ __INIT_CLK_DEBUG(ckil_clk)
+ .get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk anaclk_1 = {
+ __INIT_CLK_DEBUG(anaclk_1)
+ .get_rate = _clk_anaclk_1_get_rate,
+ .set_rate = _clk_anaclk_1_set_rate,
+};
+
+static struct clk anaclk_2 = {
+ __INIT_CLK_DEBUG(anaclk_2)
+ .get_rate = _clk_anaclk_2_get_rate,
+ .set_rate = _clk_anaclk_2_set_rate,
+};
+
+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 unsigned long pfd_get_rate(struct clk *clk)
+{
+ u32 frac;
+ u64 tmp;
+ tmp = (u64)clk_get_rate(clk->parent) * 18;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ frac = (__raw_readl(clk->enable_reg) >> clk->enable_shift) &
+ ANADIG_PFD_FRAC_MASK;
+
+ do_div(tmp, frac);
+
+ return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 frac;
+ u64 tmp;
+ 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;
+ /* clear clk frac bits */
+ __raw_writel(ANADIG_PFD_FRAC_MASK << clk->enable_shift,
+ (int)clk->enable_reg + 8);
+ /* set clk frac bits */
+ __raw_writel(frac << clk->enable_shift,
+ (int)clk->enable_reg + 4);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+ return 0;
+}
+
+static int _clk_pfd_enable(struct clk *clk)
+{
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ /* clear clk gate bit */
+ __raw_writel((1 << (clk->enable_shift + 7)),
+ (int)clk->enable_reg + 8);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+
+ return 0;
+}
+
+static void _clk_pfd_disable(struct clk *clk)
+{
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ /* set clk gate bit */
+ __raw_writel((1 << (clk->enable_shift + 7)),
+ (int)clk->enable_reg + 4);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+ unsigned int reg;
+ void __iomem *pllbase;
+
+ pllbase = _get_pll_base(clk);
+
+ reg = __raw_readl(pllbase);
+ reg &= ~ANADIG_PLL_POWER_DOWN;
+
+ /* The 480MHz PLLs have the opposite definition for power bit. */
+ if (clk == &pll3_usb_otg_main_clk || clk == &pll7_usb_host_main_clk)
+ reg |= ANADIG_PLL_POWER_DOWN;
+
+ __raw_writel(reg, pllbase);
+
+ /* It will power on pll3 */
+ if (clk == &pll3_usb_otg_main_clk)
+ __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_CLR);
+
+ /* Wait for PLL to lock */
+ if (!WAIT((__raw_readl(pllbase) & ANADIG_PLL_LOCK),
+ SPIN_DELAY))
+ panic("pll enable failed\n");
+
+ /* Enable the PLL output now*/
+ reg = __raw_readl(pllbase);
+ reg &= ~ANADIG_PLL_BYPASS;
+ reg |= ANADIG_PLL_ENABLE;
+ __raw_writel(reg, pllbase);
+
+ return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+ unsigned int reg;
+ void __iomem *pllbase;
+
+ if ((arm_needs_pll2_400) && (clk == &pll2_528_bus_main_clk))
+ return;
+ /*
+ * To support USB remote wake up, need always keep power and enable bit
+ * BM_ANADIG_ANA_MISC2_CONTROL0 will power off PLL3's power
+ * Please see TKT064178 for detail.
+ */
+ if (clk == &pll3_usb_otg_main_clk) {
+ __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_SET);
+ return;
+ }
+
+ pllbase = _get_pll_base(clk);
+
+ reg = __raw_readl(pllbase);
+ reg |= ANADIG_PLL_BYPASS;
+ reg &= ~ANADIG_PLL_ENABLE;
+
+ __raw_writel(reg, pllbase);
+
+}
+
+static unsigned long _clk_pll1_main_get_rate(struct clk *clk)
+{
+ unsigned int div;
+ unsigned long val;
+
+ /* If PLL1 is bypassed, its rate will be from OSC directly */
+ if (__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_SYS_BYPASS_MASK)
+ return clk_get_rate(clk->parent);
+
+ div = __raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_SYS_DIV_SELECT_MASK;
+ val = (clk_get_rate(clk->parent) * div) / 2;
+ return val;
+}
+
+static int _clk_pll1_main_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+
+ if (rate < AUDIO_VIDEO_MIN_CLK_FREQ || rate > AUDIO_VIDEO_MAX_CLK_FREQ)
+ return -EINVAL;
+
+ div = (rate * 2) / clk_get_rate(clk->parent);
+
+ /* Update div */
+ reg = __raw_readl(PLL1_SYS_BASE_ADDR) & ~ANADIG_PLL_SYS_DIV_SELECT_MASK;
+ reg |= div;
+ __raw_writel(reg, PLL1_SYS_BASE_ADDR);
+
+ /* Wait for PLL1 to lock */
+ if (!WAIT((__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_LOCK),
+ SPIN_DELAY))
+ panic("pll1 enable failed\n");
+
+ return 0;
+}
+
+static void _clk_pll1_disable(struct clk *clk)
+{
+ void __iomem *pllbase;
+ u32 reg;
+
+ pll1_enabled = false;
+
+ /* Set PLL1 in bypass mode only. */
+ /* We need to be able to set the ARM-PODF bit
+ * when the system enters WAIT mode. And setting
+ * this bit requires PLL1_main to be enabled.
+ */
+ pllbase = _get_pll_base(clk);
+
+ reg = __raw_readl(pllbase);
+ reg |= ANADIG_PLL_BYPASS;
+ __raw_writel(reg, pllbase);
+}
+
+static int _clk_pll1_enable(struct clk *clk)
+{
+ _clk_pll_enable(clk);
+ pll1_enabled = true;
+ return 0;
+}
+
+static struct clk pll1_sys_main_clk = {
+ __INIT_CLK_DEBUG(pll1_sys_main_clk)
+ .parent = &osc_clk,
+ .get_rate = _clk_pll1_main_get_rate,
+ .set_rate = _clk_pll1_main_set_rate,
+ .enable = _clk_pll1_enable,
+ .disable = _clk_pll1_disable,
+};
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (parent == &pll1_sys_main_clk) {
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* Set the step_clk parent to be lp_apm, to save power. */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL);
+ } else {
+ /* Set STEP_CLK to be the parent*/
+ if (parent == &osc_clk) {
+ /* Set STEP_CLK to be sourced from LPAPM. */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL);
+ __raw_writel(reg, MXC_CCM_CCSR);
+ } else {
+ /* Set STEP_CLK to be sourced from PLL2-PDF (400MHz). */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_STEP_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ }
+ 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)
+{
+ return clk_get_rate(clk->parent);
+}
+
+static struct clk pll1_sw_clk = {
+ __INIT_CLK_DEBUG(pll1_sw_clk)
+ .parent = &pll1_sys_main_clk,
+ .set_parent = _clk_pll1_sw_set_parent,
+ .get_rate = _clk_pll1_sw_get_rate,
+};
+
+static unsigned long _clk_pll2_main_get_rate(struct clk *clk)
+{
+ unsigned int div;
+ unsigned long val;
+
+ div = __raw_readl(PLL2_528_BASE_ADDR) & ANADIG_PLL_528_DIV_SELECT;
+
+ if (div == 1)
+ val = clk_get_rate(clk->parent) * 22;
+
+ else
+ val = clk_get_rate(clk->parent) * 20;
+
+ return val;
+}
+
+static int _clk_pll2_main_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+
+ if (rate == 528000000)
+ div = 1;
+ else if (rate == 480000000)
+ div = 0;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(PLL2_528_BASE_ADDR);
+ reg &= ~ANADIG_PLL_528_DIV_SELECT;
+ reg |= div;
+ __raw_writel(reg, PLL2_528_BASE_ADDR);
+
+ return 0;
+}
+
+static struct clk pll2_528_bus_main_clk = {
+ __INIT_CLK_DEBUG(pll2_528_bus_main_clk)
+ .parent = &osc_clk,
+ .get_rate = _clk_pll2_main_get_rate,
+ .set_rate = _clk_pll2_main_set_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+};
+
+static void _clk_pll2_pfd_400M_disable(struct clk *clk)
+{
+ if (!arm_needs_pll2_400)
+ _clk_pfd_disable(clk);
+}
+
+static struct clk pll2_pfd_400M = {
+ __INIT_CLK_DEBUG(pll2_pfd_400M)
+ .parent = &pll2_528_bus_main_clk,
+ .enable_reg = (void *)PFD_528_BASE_ADDR,
+ .enable_shift = ANADIG_PFD2_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pll2_pfd_400M_disable,
+ .get_rate = pfd_get_rate,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll2_pfd_352M = {
+ __INIT_CLK_DEBUG(pll2_pfd_352M)
+ .parent = &pll2_528_bus_main_clk,
+ .enable_reg = (void *)PFD_528_BASE_ADDR,
+ .enable_shift = ANADIG_PFD0_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll2_pfd_594M = {
+ __INIT_CLK_DEBUG(pll2_pfd_594M)
+ .parent = &pll2_528_bus_main_clk,
+ .enable_reg = (void *)PFD_528_BASE_ADDR,
+ .enable_shift = ANADIG_PFD1_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static unsigned long _clk_pll2_200M_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk pll2_200M = {
+ __INIT_CLK_DEBUG(pll2_200M)
+ .parent = &pll2_pfd_400M,
+ .get_rate = _clk_pll2_200M_get_rate,
+};
+
+static unsigned long _clk_pll3_usb_otg_get_rate(struct clk *clk)
+{
+ unsigned int div;
+ unsigned long val;
+
+ div = __raw_readl(PLL3_480_USB1_BASE_ADDR)
+ & ANADIG_PLL_480_DIV_SELECT_MASK;
+
+ if (div == 1)
+ val = clk_get_rate(clk->parent) * 22;
+ else
+ val = clk_get_rate(clk->parent) * 20;
+ return val;
+}
+
+static int _clk_pll3_usb_otg_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+
+ if (rate == 528000000)
+ div = 1;
+ else if (rate == 480000000)
+ div = 0;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(PLL3_480_USB1_BASE_ADDR);
+ reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK;
+ reg |= div;
+ __raw_writel(reg, PLL3_480_USB1_BASE_ADDR);
+
+ return 0;
+}
+
+
+/* same as pll3_main_clk. These two clocks should always be the same */
+static struct clk pll3_usb_otg_main_clk = {
+ __INIT_CLK_DEBUG(pll3_usb_otg_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_pll3_usb_otg_set_rate,
+ .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* for USB OTG */
+static struct clk usb_phy1_clk = {
+ __INIT_CLK_DEBUG(usb_phy1_clk)
+ .parent = &pll3_usb_otg_main_clk,
+ .set_rate = _clk_pll3_usb_otg_set_rate,
+ .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* For HSIC port 1 */
+static struct clk usb_phy3_clk = {
+ __INIT_CLK_DEBUG(usb_phy3_clk)
+ .parent = &pll3_usb_otg_main_clk,
+ .set_rate = _clk_pll3_usb_otg_set_rate,
+ .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* For HSIC port 2 */
+static struct clk usb_phy4_clk = {
+ __INIT_CLK_DEBUG(usb_phy4_clk)
+ .parent = &pll3_usb_otg_main_clk,
+ .set_rate = _clk_pll3_usb_otg_set_rate,
+ .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+static struct clk pll3_pfd_508M = {
+ __INIT_CLK_DEBUG(pll3_pfd_508M)
+ .parent = &pll3_usb_otg_main_clk,
+ .enable_reg = (void *)PFD_480_BASE_ADDR,
+ .enable_shift = ANADIG_PFD2_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll3_pfd_454M = {
+ __INIT_CLK_DEBUG(pll3_pfd_454M)
+ .parent = &pll3_usb_otg_main_clk,
+ .enable_reg = (void *)PFD_480_BASE_ADDR,
+ .enable_shift = ANADIG_PFD3_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll3_pfd_720M = {
+ __INIT_CLK_DEBUG(pll3_pfd_720M)
+ .parent = &pll3_usb_otg_main_clk,
+ .enable_reg = (void *)PFD_480_BASE_ADDR,
+ .enable_shift = ANADIG_PFD0_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static int pfd_540M_set_rate(struct clk *clk, unsigned long rate)
+{
+ if ((clk_get_parent(&ipu1_clk) == clk) ||
+ (clk_get_parent(&ipu2_clk) == clk) ||
+ (clk_get_parent(&axi_clk) == clk))
+ WARN(1, "CHANGING rate of 540M PFD when IPU and \
+ AXI is sourced from it \n");
+
+ return pfd_set_rate(clk, rate);
+}
+
+static struct clk pll3_pfd_540M = {
+ __INIT_CLK_DEBUG(pll3_pfd_540M)
+ .parent = &pll3_usb_otg_main_clk,
+ .enable_reg = (void *)PFD_480_BASE_ADDR,
+ .enable_shift = ANADIG_PFD1_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_540M_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+ .get_rate = pfd_get_rate,
+};
+
+static unsigned long _clk_pll3_sw_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent);
+}
+
+/* same as pll3_main_clk. These two clocks should always be the same */
+static struct clk pll3_sw_clk = {
+ __INIT_CLK_DEBUG(pll3_sw_clk)
+ .parent = &pll3_usb_otg_main_clk,
+ .get_rate = _clk_pll3_sw_get_rate,
+};
+
+static unsigned long _clk_pll3_120M_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 4;
+}
+
+static struct clk pll3_120M = {
+ __INIT_CLK_DEBUG(pll3_120M)
+ .parent = &pll3_sw_clk,
+ .get_rate = _clk_pll3_120M_get_rate,
+};
+
+static unsigned long _clk_pll3_80M_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 6;
+}
+
+static struct clk pll3_80M = {
+ __INIT_CLK_DEBUG(pll3_80M)
+ .parent = &pll3_sw_clk,
+ .get_rate = _clk_pll3_80M_get_rate,
+};
+
+static unsigned long _clk_pll3_60M_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 8;
+}
+
+static struct clk pll3_60M = {
+ __INIT_CLK_DEBUG(pll3_60M)
+ .parent = &pll3_sw_clk,
+ .get_rate = _clk_pll3_60M_get_rate,
+};
+
+static unsigned long _clk_audio_video_get_rate(struct clk *clk)
+{
+ unsigned int div, mfn, mfd;
+ unsigned long rate;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+ void __iomem *pllbase;
+ int rev = mx6q_revision();
+ unsigned int test_div_sel, control3, post_div = 1;
+
+ if (clk == &pll4_audio_main_clk)
+ pllbase = PLL4_AUDIO_BASE_ADDR;
+ else
+ pllbase = PLL5_VIDEO_BASE_ADDR;
+
+ if ((rev >= IMX_CHIP_REVISION_1_1) || cpu_is_mx6dl()) {
+ test_div_sel = (__raw_readl(pllbase)
+ & ANADIG_PLL_AV_TEST_DIV_SEL_MASK)
+ >> ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET;
+ if (test_div_sel == 0)
+ post_div = 4;
+ else if (test_div_sel == 1)
+ post_div = 2;
+
+ if (clk == &pll5_video_main_clk) {
+ control3 = (__raw_readl(ANA_MISC2_BASE_ADDR)
+ & ANADIG_ANA_MISC2_CONTROL3_MASK)
+ >> ANADIG_ANA_MISC2_CONTROL3_OFFSET;
+ if (control3 == 1)
+ post_div *= 2;
+ else if (control3 == 3)
+ post_div *= 4;
+ }
+ }
+
+ div = __raw_readl(pllbase) & ANADIG_PLL_SYS_DIV_SELECT_MASK;
+ mfn = __raw_readl(pllbase + PLL_NUM_DIV_OFFSET);
+ mfd = __raw_readl(pllbase + PLL_DENOM_DIV_OFFSET);
+
+ rate = (parent_rate * div) + ((parent_rate / mfd) * mfn);
+ rate = rate / post_div;
+
+ return rate;
+}
+
+static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+ unsigned int mfn, mfd = 1000000;
+ s64 temp64;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+ void __iomem *pllbase;
+ unsigned long min_clk_rate, pre_div_rate;
+ int rev = mx6q_revision();
+ u32 test_div_sel = 2;
+ u32 control3 = 0;
+
+ if ((rev < IMX_CHIP_REVISION_1_1) && !cpu_is_mx6dl())
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ;
+ else if (clk == &pll4_audio_main_clk)
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4;
+ else
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 16;
+
+ if ((rate < min_clk_rate) || (rate > AUDIO_VIDEO_MAX_CLK_FREQ))
+ return -EINVAL;
+
+ if (clk == &pll4_audio_main_clk)
+ pllbase = PLL4_AUDIO_BASE_ADDR;
+ else
+ pllbase = PLL5_VIDEO_BASE_ADDR;
+
+ pre_div_rate = rate;
+ if ((rev >= IMX_CHIP_REVISION_1_1) || cpu_is_mx6dl()) {
+ while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) {
+ pre_div_rate *= 2;
+ /*
+ * test_div_sel field values:
+ * 2 -> Divide by 1
+ * 1 -> Divide by 2
+ * 0 -> Divide by 4
+ *
+ * control3 field values:
+ * 0 -> Divide by 1
+ * 1 -> Divide by 2
+ * 3 -> Divide by 4
+ */
+ if (test_div_sel != 0)
+ test_div_sel--;
+ else {
+ control3++;
+ if (control3 == 2)
+ control3++;
+ }
+ }
+ }
+
+ div = pre_div_rate / parent_rate;
+ temp64 = (u64) (pre_div_rate - (div * parent_rate));
+ temp64 *= mfd;
+ do_div(temp64, parent_rate);
+ mfn = temp64;
+
+ reg = __raw_readl(pllbase)
+ & ~ANADIG_PLL_SYS_DIV_SELECT_MASK
+ & ~ANADIG_PLL_AV_TEST_DIV_SEL_MASK;
+ reg |= div |
+ (test_div_sel << ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET);
+ __raw_writel(reg, pllbase);
+ __raw_writel(mfn, pllbase + PLL_NUM_DIV_OFFSET);
+ __raw_writel(mfd, pllbase + PLL_DENOM_DIV_OFFSET);
+
+ if ((rev >= IMX_CHIP_REVISION_1_1) &&
+ (pllbase == PLL5_VIDEO_BASE_ADDR)) {
+ reg = __raw_readl(ANA_MISC2_BASE_ADDR)
+ & ~ANADIG_ANA_MISC2_CONTROL3_MASK;
+ reg |= control3 << ANADIG_ANA_MISC2_CONTROL3_OFFSET;
+ __raw_writel(reg, ANA_MISC2_BASE_ADDR);
+ }
+
+ return 0;
+}
+
+static unsigned long _clk_audio_video_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ unsigned long min_clk_rate;
+ unsigned int div, post_div = 1;
+ unsigned int mfn, mfd = 1000000;
+ s64 temp64;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+ unsigned long pre_div_rate;
+ u32 test_div_sel = 2;
+ u32 control3 = 0;
+ unsigned long final_rate;
+ int rev = mx6q_revision();
+
+ if ((rev < IMX_CHIP_REVISION_1_1) && !cpu_is_mx6dl())
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ;
+ else if (clk == &pll4_audio_main_clk)
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4;
+ else
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 16;
+
+ if (rate < min_clk_rate)
+ return min_clk_rate;
+
+ if (rate > AUDIO_VIDEO_MAX_CLK_FREQ)
+ return AUDIO_VIDEO_MAX_CLK_FREQ;
+
+ pre_div_rate = rate;
+ if ((rev >= IMX_CHIP_REVISION_1_1) || cpu_is_mx6dl()) {
+ while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) {
+ pre_div_rate *= 2;
+ post_div *= 2;
+ if (test_div_sel != 0)
+ test_div_sel--;
+ else {
+ control3++;
+ if (control3 == 2)
+ control3++;
+ }
+ }
+ }
+
+ div = pre_div_rate / parent_rate;
+ temp64 = (u64) (pre_div_rate - (div * parent_rate));
+ temp64 *= mfd;
+ do_div(temp64, parent_rate);
+ mfn = temp64;
+
+ final_rate = (parent_rate * div) + ((parent_rate / mfd) * mfn);
+ final_rate = final_rate / post_div;
+
+ return final_rate;
+}
+
+static int _clk_audio_video_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ int mux;
+ void __iomem *pllbase;
+
+ if (clk == &pll4_audio_main_clk)
+ pllbase = PLL4_AUDIO_BASE_ADDR;
+ else
+ pllbase = PLL5_VIDEO_BASE_ADDR;
+
+ reg = __raw_readl(pllbase) & ~ANADIG_PLL_BYPASS_CLK_SRC_MASK;
+ mux = _get_mux6(parent, &osc_clk, &anaclk_1, &anaclk_2,
+ NULL, NULL, NULL);
+ reg |= mux << ANADIG_PLL_BYPASS_CLK_SRC_OFFSET;
+ __raw_writel(reg, pllbase);
+
+ /* Set anaclk_x as input */
+ if (parent == &anaclk_1) {
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= (ANATOP_LVDS_CLK1_IBEN_MASK &
+ ~ANATOP_LVDS_CLK1_OBEN_MASK);
+ __raw_writel(reg, ANADIG_MISC1_REG);
+ } else if (parent == &anaclk_2) {
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= (ANATOP_LVDS_CLK2_IBEN_MASK &
+ ~ANATOP_LVDS_CLK2_OBEN_MASK);
+ __raw_writel(reg, ANADIG_MISC1_REG);
+ }
+
+ return 0;
+}
+
+static struct clk pll4_audio_main_clk = {
+ __INIT_CLK_DEBUG(pll4_audio_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_audio_video_set_rate,
+ .get_rate = _clk_audio_video_get_rate,
+ .round_rate = _clk_audio_video_round_rate,
+ .set_parent = _clk_audio_video_set_parent,
+};
+
+static struct clk pll5_video_main_clk = {
+ __INIT_CLK_DEBUG(pll5_video_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_audio_video_set_rate,
+ .get_rate = _clk_audio_video_get_rate,
+ .round_rate = _clk_audio_video_round_rate,
+ .set_parent = _clk_audio_video_set_parent,
+};
+
+static int _clk_pll_mlb_main_enable(struct clk *clk)
+{
+ unsigned int reg;
+ void __iomem *pllbase;
+
+ pllbase = _get_pll_base(clk);
+
+ reg = __raw_readl(pllbase);
+ reg &= ~ANADIG_PLL_BYPASS;
+
+ reg = (0x3 << ANADIG_PLL_MLB_FLT_RES_CFG_OFFSET) |
+ (0x3 << ANADIG_PLL_MLB_RX_CLK_DELAY_CFG_OFFSET) |
+ (0x2 << ANADIG_PLL_MLB_VDDD_DELAY_CFG_OFFSET) |
+ (0x1 << ANADIG_PLL_MLB_VDDA_DELAY_CFG_OFFSET) |
+ (ANADIG_PLL_HOLD_RING_OFF);
+ __raw_writel(reg, pllbase);
+
+ return 0;
+}
+
+static void _clk_pll_mlb_main_disable(struct clk *clk)
+{
+ unsigned int reg;
+ void __iomem *pllbase;
+
+ pllbase = _get_pll_base(clk);
+
+ reg = __raw_readl(pllbase);
+
+ reg |= ANADIG_PLL_BYPASS;
+
+ __raw_writel(reg, pllbase);
+}
+
+static struct clk pll6_mlb150_main_clk = {
+ __INIT_CLK_DEBUG(pll6_mlb150_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_mlb_main_enable,
+ .disable = _clk_pll_mlb_main_disable,
+};
+
+static unsigned long _clk_pll7_usb_otg_get_rate(struct clk *clk)
+{
+ unsigned int div;
+ unsigned long val;
+
+ div = __raw_readl(PLL7_480_USB2_BASE_ADDR)
+ & ANADIG_PLL_480_DIV_SELECT_MASK;
+
+ if (div == 1)
+ val = clk_get_rate(clk->parent) * 22;
+ else
+ val = clk_get_rate(clk->parent) * 20;
+ return val;
+}
+
+static int _clk_pll7_usb_otg_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+
+ if (rate == 528000000)
+ div = 1;
+ else if (rate == 480000000)
+ div = 0;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(PLL7_480_USB2_BASE_ADDR);
+ reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK;
+ reg |= div;
+ __raw_writel(reg, PLL7_480_USB2_BASE_ADDR);
+
+ return 0;
+}
+
+static struct clk pll7_usb_host_main_clk = {
+ __INIT_CLK_DEBUG(pll7_usb_host_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_pll7_usb_otg_set_rate,
+ .get_rate = _clk_pll7_usb_otg_get_rate,
+
+};
+
+static struct clk pll8_enet_main_clk = {
+ __INIT_CLK_DEBUG(pll8_enet_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+};
+
+static unsigned long _clk_arm_get_rate(struct clk *clk)
+{
+ u32 cacrr, div;
+
+ cacrr = __raw_readl(MXC_CCM_CACRR);
+ div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_arm_set_rate(struct clk *clk, unsigned long rate)
+{
+ int i;
+ u32 div;
+ unsigned long parent_rate;
+ unsigned long flags;
+ unsigned long ipg_clk_rate, max_arm_wait_clk;
+
+ for (i = 0; i < cpu_op_nr; i++) {
+ if (rate == cpu_op_tbl[i].cpu_rate)
+ break;
+ }
+ if (i >= cpu_op_nr)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clk_lock, flags);
+
+ if (rate <= clk_get_rate(&pll2_pfd_400M)) {
+ /* Source pll1_sw_clk from step_clk which is sourced from
+ * PLL2_PFD_400M.
+ */
+ if (pll1_sw_clk.parent != &pll2_pfd_400M) {
+ if (pll2_pfd_400M.usecount == 0) {
+ /* Check if PLL2 needs to be enabled also. */
+ if (pll2_528_bus_main_clk.usecount == 0)
+ pll2_528_bus_main_clk.enable(&pll2_528_bus_main_clk);
+ /* Ensure parent usecount is
+ * also incremented.
+ */
+ pll2_528_bus_main_clk.usecount++;
+ pll2_pfd_400M.enable(&pll2_pfd_400M);
+ }
+ pll2_pfd_400M.usecount++;
+ arm_needs_pll2_400 = true;
+ pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd_400M);
+ pll1_sw_clk.parent = &pll2_pfd_400M;
+ }
+ } else {
+ /* Make sure PLL1 is enabled */
+ if (!pll1_enabled) {
+ pll1_sys_main_clk.enable(&pll1_sys_main_clk);
+ pll1_sys_main_clk.usecount = 1;
+ }
+ /* Make sure PLL1 rate is what we want */
+ if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) {
+ /* If pll1_sw_clk is from pll1_sys_main_clk, switch it */
+ if (pll1_sw_clk.parent == &pll1_sys_main_clk) {
+ /* Change the PLL1 rate. */
+ if (pll2_pfd_400M.usecount != 0)
+ pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd_400M);
+ else
+ pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk);
+ }
+ pll1_sys_main_clk.set_rate(&pll1_sys_main_clk, cpu_op_tbl[i].pll_rate);
+ }
+ /* Make sure pll1_sw_clk is from pll1_sys_main_clk */
+ pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk);
+ pll1_sw_clk.parent = &pll1_sys_main_clk;
+ if (arm_needs_pll2_400) {
+ pll2_pfd_400M.usecount--;
+ if (pll2_pfd_400M.usecount == 0) {
+ pll2_pfd_400M.disable(&pll2_pfd_400M);
+ /* Ensure parent usecount is
+ * also decremented.
+ */
+ pll2_528_bus_main_clk.usecount--;
+ if (pll2_528_bus_main_clk.usecount == 0)
+ pll2_528_bus_main_clk.disable(&pll2_528_bus_main_clk);
+ }
+ }
+ arm_needs_pll2_400 = false;
+ }
+ parent_rate = clk_get_rate(clk->parent);
+ div = parent_rate / rate;
+ /* Calculate the ARM_PODF to be applied when the system
+ * enters WAIT state. The max ARM clk is decided by the
+ * ipg_clk and has to follow the ratio of ARM_CLK:IPG_CLK of 12:5.
+ * For ex, when IPG is at 66MHz, ARM_CLK cannot be greater
+ * than 158MHz.
+ * Pre-calculate the optimal divider now.
+ */
+ ipg_clk_rate = clk_get_rate(&ipg_clk);
+ max_arm_wait_clk = (12 * ipg_clk_rate) / 5;
+ wait_mode_arm_podf = parent_rate / max_arm_wait_clk;
+
+ if (div == 0)
+ div = 1;
+
+ if ((parent_rate / div) > rate)
+ div++;
+
+ if (div > 8) {
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return -1;
+ }
+
+ cur_arm_podf = div;
+
+ __raw_writel(div - 1, MXC_CCM_CACRR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR))
+ ;
+
+ if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) {
+ pll1_sys_main_clk.disable(&pll1_sys_main_clk);
+ pll1_sys_main_clk.usecount = 0;
+ }
+
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return 0;
+}
+
+static struct clk cpu_clk = {
+ __INIT_CLK_DEBUG(cpu_clk)
+ .parent = &pll1_sw_clk,
+ .set_rate = _clk_arm_set_rate,
+ .get_rate = _clk_arm_get_rate,
+};
+
+static unsigned long _clk_twd_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk twd_clk = {
+ __INIT_CLK_DEBUG(twd_clk)
+ .parent = &cpu_clk,
+ .get_rate = _clk_twd_get_rate,
+};
+
+static int _clk_periph_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ int mux;
+
+ mux = _get_mux6(parent, &pll2_528_bus_main_clk, &pll2_pfd_400M,
+ &pll2_pfd_352M, &pll2_200M, &pll3_sw_clk, &osc_clk);
+
+ if (mux <= 3) {
+ /* Set the pre_periph_clk multiplexer */
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ /* Set the periph_clk_sel multiplexer. */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ } else {
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ /* Set the periph_clk2_podf divider to divide by 1. */
+ reg &= ~MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ /* Set the periph_clk2_sel mux. */
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK;
+ reg |= ((mux - 4) << MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR))
+ ;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ /* Set periph_clk_sel to select periph_clk2. */
+ reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ }
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY), SPIN_DELAY))
+ panic("_clk_periph_set_parent failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_periph_get_rate(struct clk *clk)
+{
+ u32 div = 1;
+ u32 reg;
+ unsigned long val;
+
+ if ((clk->parent == &pll3_sw_clk) || (clk->parent == &osc_clk)) {
+ reg = __raw_readl(MXC_CCM_CBCDR)
+ & MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK;
+ div = (reg >> MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET) + 1;
+ }
+ val = clk_get_rate(clk->parent) / div;
+ return val;
+}
+
+static struct clk periph_clk = {
+ __INIT_CLK_DEBUG(periph_clk)
+ .parent = &pll2_528_bus_main_clk,
+ .set_parent = _clk_periph_set_parent,
+ .get_rate = _clk_periph_get_rate,
+};
+
+static unsigned long _clk_axi_get_rate(struct clk *clk)
+{
+ u32 div, reg;
+ unsigned long val;
+
+ reg = __raw_readl(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_AXI_PODF_MASK;
+ div = (reg >> MXC_CCM_CBCDR_AXI_PODF_OFFSET);
+
+ val = clk_get_rate(clk->parent) / (div + 1);
+ return val;
+}
+
+static int _clk_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AXI_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AXI_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_AXI_PODF_BUSY), SPIN_DELAY))
+ panic("pll _clk_axi_a_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum
+ * value for the clock.
+ * Also prevent a div of 0.
+ */
+
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+
+ return parent_rate / div;
+}
+
+static int _clk_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ int mux;
+
+ mux = _get_mux6(parent, &periph_clk, &pll2_pfd_400M,
+ &pll3_pfd_540M, NULL, NULL, NULL);
+
+ if (mux == 0) {
+ /* Set the AXI_SEL mux */
+ reg = __raw_readl(MXC_CCM_CBCDR) & ~MXC_CCM_CBCDR_AXI_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ } else {
+ /* Set the AXI_ALT_SEL mux. */
+ reg = __raw_readl(MXC_CCM_CBCDR)
+ & ~MXC_CCM_CBCDR_AXI_ALT_SEL_MASK;
+ reg |= ((mux - 1) << MXC_CCM_CBCDR_AXI_ALT_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ /* Set the AXI_SEL mux */
+ reg = __raw_readl(MXC_CCM_CBCDR) & ~MXC_CCM_CBCDR_AXI_SEL;
+ reg |= MXC_CCM_CBCDR_AXI_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ }
+ return 0;
+}
+
+static struct clk axi_clk = {
+ __INIT_CLK_DEBUG(axi_clk)
+ .parent = &periph_clk,
+ .set_parent = _clk_axi_set_parent,
+ .set_rate = _clk_axi_set_rate,
+ .get_rate = _clk_axi_get_rate,
+ .round_rate = _clk_axi_round_rate,
+};
+
+static unsigned long _clk_ahb_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+ MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ 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);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AHB_PODF_BUSY),
+ SPIN_DELAY))
+ panic("_clk_ahb_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static struct clk ahb_clk = {
+ __INIT_CLK_DEBUG(ahb_clk)
+ .parent = &periph_clk,
+ .get_rate = _clk_ahb_get_rate,
+ .set_rate = _clk_ahb_set_rate,
+ .round_rate = _clk_ahb_round_rate,
+};
+
+static unsigned long _clk_ipg_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+ MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+
+static struct clk ipg_clk = {
+ __INIT_CLK_DEBUG(ipg_clk)
+ .parent = &ahb_clk,
+ .get_rate = _clk_ipg_get_rate,
+};
+
+static struct clk tzasc1_clk = {
+ __INIT_CLK_DEBUG(tzasc1_clk)
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk tzasc2_clk = {
+ __INIT_CLK_DEBUG(tzasc2_clk)
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk mx6fast1_clk = {
+ __INIT_CLK_DEBUG(mx6fast1_clk)
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk mx6per1_clk = {
+ __INIT_CLK_DEBUG(mx6per1_clk)
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &mx6fast1_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk mx6per2_clk = {
+ __INIT_CLK_DEBUG(mx6per2_clk)
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static unsigned long _clk_mmdc_ch0_axi_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK) >>
+ MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_mmdc_ch0_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_MMDC_CH0_PODF_BUSY),
+ SPIN_DELAY))
+ panic("_clk_mmdc_ch0_axi_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_mmdc_ch0_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static struct clk mmdc_ch0_axi_clk[] = {
+ {
+ __INIT_CLK_DEBUG(mmdc_ch0_axi_clk)
+ .id = 0,
+ .parent = &periph_clk,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .secondary = &mmdc_ch0_axi_clk[1],
+ .get_rate = _clk_mmdc_ch0_axi_get_rate,
+ .set_rate = _clk_mmdc_ch0_axi_set_rate,
+ .round_rate = _clk_mmdc_ch0_axi_round_rate,
+ },
+ {
+ __INIT_CLK_DEBUG(mmdc_ch0_ipg_clk)
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .secondary = &tzasc1_clk,
+ },
+};
+
+static unsigned long _clk_mmdc_ch1_axi_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK) >>
+ MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_mmdc_ch1_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_MMDC_CH1_PODF_BUSY), SPIN_DELAY))
+ panic("_clk_mmdc_ch1_axi_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_mmdc_ch1_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static struct clk mmdc_ch1_axi_clk[] = {
+ {
+ __INIT_CLK_DEBUG(mmdc_ch1_axi_clk)
+ .id = 0,
+ .parent = &pll2_pfd_400M,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .secondary = &mmdc_ch1_axi_clk[1],
+ .get_rate = _clk_mmdc_ch1_axi_get_rate,
+ .set_rate = _clk_mmdc_ch1_axi_set_rate,
+ .round_rate = _clk_mmdc_ch1_axi_round_rate,
+ },
+ {
+ .id = 1,
+ __INIT_CLK_DEBUG(mmdc_ch1_ipg_clk)
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .secondary = &tzasc2_clk,
+ },
+};
+
+static struct clk ocram_clk = {
+ __INIT_CLK_DEBUG(ocram_clk)
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static unsigned long _clk_ipg_perclk_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ div = ((reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK) >>
+ MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipg_perclk_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 64))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ reg &= ~MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET;
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+
+static unsigned long _clk_ipg_perclk_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 64)
+ div = 64;
+
+ return parent_rate / div;
+}
+
+static struct clk ipg_perclk = {
+ __INIT_CLK_DEBUG(ipg_perclk)
+ .parent = &ipg_clk,
+ .get_rate = _clk_ipg_perclk_get_rate,
+ .set_rate = _clk_ipg_perclk_set_rate,
+ .round_rate = _clk_ipg_perclk_round_rate,
+};
+
+static struct clk spba_clk = {
+ __INIT_CLK_DEBUG(spba_clk)
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static struct clk sdma_clk[] = {
+ {
+ __INIT_CLK_DEBUG(sdma_clk)
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &sdma_clk[1],
+ },
+ {
+ .parent = &mx6per1_clk,
+#ifdef CONFIG_SDMA_IRAM
+ .secondary = &ocram_clk,
+#else
+ .secondary = &mmdc_ch0_axi_clk[0],
+#endif
+ },
+};
+
+static int _clk_gpu2d_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_GPU2D_AXI_CLK_SEL;
+
+ if (parent == &ahb_clk)
+ reg |= MXC_CCM_CBCMR_GPU2D_AXI_CLK_SEL;
+
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk gpu2d_axi_clk = {
+ __INIT_CLK_DEBUG(gpu2d_axi_clk)
+ .parent = &axi_clk,
+ .set_parent = _clk_gpu2d_axi_set_parent,
+};
+
+static int _clk_gpu3d_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_GPU3D_AXI_CLK_SEL;
+
+ if (parent == &ahb_clk)
+ reg |= MXC_CCM_CBCMR_GPU3D_AXI_CLK_SEL;
+
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk gpu3d_axi_clk = {
+ __INIT_CLK_DEBUG(gpu3d_axi_clk)
+ .parent = &axi_clk,
+ .secondary = &mmdc_ch0_axi_clk[0],
+ .set_parent = _clk_gpu3d_axi_set_parent,
+};
+
+static int _clk_pcie_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL;
+
+ if (parent == &ahb_clk)
+ reg |= MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL;
+
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk pcie_axi_clk = {
+ __INIT_CLK_DEBUG(pcie_axi_clk)
+ .parent = &axi_clk,
+ .set_parent = _clk_pcie_axi_set_parent,
+};
+
+static int _clk_vdo_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_VDOAXI_CLK_SEL;
+
+ if (parent == &ahb_clk)
+ reg |= MXC_CCM_CBCMR_VDOAXI_CLK_SEL;
+
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk vdo_axi_clk = {
+ __INIT_CLK_DEBUG(vdo_axi_clk)
+ .parent = &axi_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_vdo_axi_set_parent,
+};
+
+static struct clk vdoa_clk[] = {
+ {
+ __INIT_CLK_DEBUG(vdoa_clk)
+ .id = 0,
+ .parent = &vdo_axi_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &vdoa_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &vdoa_clk[2],
+ },
+ {
+ .parent = &mx6fast1_clk,
+ .secondary = &ocram_clk,
+ },
+};
+
+static unsigned long mx6_timer_rate(void)
+{
+ u32 parent_rate = clk_get_rate(&osc_clk);
+
+ u32 reg = __raw_readl(timer_base + MXC_TCTL);
+ u32 div;
+
+ if ((reg & V2_TCTL_CLK_OSC_DIV8) == V2_TCTL_CLK_OSC_DIV8) {
+ if (cpu_is_mx6q())
+ /* For MX6Q, only options are 24MHz or 24MHz/8*/
+ return parent_rate / 8;
+ else {
+ /* For MX6DLS and MX6Solo, the rate is based on the
+ * divider value set in prescalar register. */
+ div = __raw_readl(timer_base + MXC_TPRER);
+ div = (div >> V2_TPRER_PRE24M_OFFSET) &
+ V2_TPRER_PRE24M_MASK;
+ return parent_rate / (div + 1);
+ }
+ }
+ return 0;
+}
+
+static unsigned long _clk_gpt_get_rate(struct clk *clk)
+{
+ unsigned long rate;
+
+ if (mx6q_revision() == IMX_CHIP_REVISION_1_0)
+ return clk_get_rate(clk->parent);
+
+ rate = mx6_timer_rate();
+ if (!rate)
+ return clk_get_rate(clk->parent);
+
+ return rate;
+}
+
+static struct clk gpt_clk[] = {
+ {
+ __INIT_CLK_DEBUG(gpt_clk)
+ .parent = &osc_clk,
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .get_rate = _clk_gpt_get_rate,
+ .secondary = &gpt_clk[1],
+ },
+ {
+ __INIT_CLK_DEBUG(gpt_serial_clk)
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static unsigned long _clk_iim_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent);
+}
+
+static struct clk iim_clk = {
+ __INIT_CLK_DEBUG(iim_clk)
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .disable = _clk_disable,
+ .get_rate = _clk_iim_get_rate,
+};
+
+static struct clk i2c_clk[] = {
+ {
+ __INIT_CLK_DEBUG(i2c_clk_0)
+ .id = 0,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(i2c_clk_1)
+ .id = 1,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(i2c_clk_2)
+ .id = 2,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static int _clk_vpu_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CBCMR)
+ & ~MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &axi_clk, &pll2_pfd_400M,
+ &pll2_pfd_352M, NULL, NULL, NULL);
+
+ reg |= (mux << MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static unsigned long _clk_vpu_axi_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_VPU_AXI_PODF_MASK) >>
+ MXC_CCM_CSCDR1_VPU_AXI_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_vpu_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_VPU_AXI_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_VPU_AXI_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static unsigned long _clk_vpu_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static struct clk vpu_clk[] = {
+ {
+ __INIT_CLK_DEBUG(vpu_clk)
+ .parent = &axi_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_vpu_axi_set_parent,
+ .round_rate = _clk_vpu_axi_round_rate,
+ .set_rate = _clk_vpu_axi_set_rate,
+ .get_rate = _clk_vpu_axi_get_rate,
+ .secondary = &vpu_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &vpu_clk[2],
+ },
+ {
+ .parent = &mx6fast1_clk,
+ .secondary = &ocram_clk,
+ },
+};
+
+static int _clk_ipu1_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CSCDR3)
+ & ~MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &mmdc_ch0_axi_clk[0],
+ &pll2_pfd_400M, &pll3_120M, &pll3_pfd_540M, NULL, NULL);
+
+ reg |= (mux << MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR3);
+
+ return 0;
+}
+
+static unsigned long _clk_ipu1_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ div = ((reg & MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK) >>
+ MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ reg &= ~MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR3);
+
+ return 0;
+}
+
+static unsigned long _clk_ipu_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static struct clk ipu1_clk = {
+ __INIT_CLK_DEBUG(ipu1_clk)
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mmdc_ch0_axi_clk[0],
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ipu1_set_parent,
+ .round_rate = _clk_ipu_round_rate,
+ .set_rate = _clk_ipu1_set_rate,
+ .get_rate = _clk_ipu1_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_ipu2_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CSCDR3)
+ & ~MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &mmdc_ch0_axi_clk[0],
+ &pll2_pfd_400M, &pll3_120M, &pll3_pfd_540M, NULL, NULL);
+
+ reg |= (mux << MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR3);
+
+ return 0;
+}
+
+static unsigned long _clk_ipu2_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ div = ((reg & MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK) >>
+ MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ reg &= ~MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR3);
+
+ return 0;
+}
+
+static struct clk ipu2_clk = {
+ __INIT_CLK_DEBUG(ipu2_clk)
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mmdc_ch0_axi_clk[0],
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ipu2_set_parent,
+ .round_rate = _clk_ipu_round_rate,
+ .set_rate = _clk_ipu2_set_rate,
+ .get_rate = _clk_ipu2_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk usdhc_dep_clk = {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mx6per1_clk,
+ };
+
+static unsigned long _clk_usdhc_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_usdhc1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC1_CLK_SEL;
+
+ if (parent == &pll2_pfd_352M)
+ reg |= (MXC_CCM_CSCMR1_USDHC1_CLK_SEL);
+
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_usdhc1_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USDHC1_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static struct clk usdhc1_clk = {
+ __INIT_CLK_DEBUG(usdhc1_clk)
+ .id = 0,
+ .parent = &pll2_pfd_400M,
+ .secondary = &usdhc_dep_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_usdhc1_set_parent,
+ .round_rate = _clk_usdhc_round_rate,
+ .set_rate = _clk_usdhc1_set_rate,
+ .get_rate = _clk_usdhc1_get_rate,
+};
+
+static int _clk_usdhc2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC2_CLK_SEL;
+
+ if (parent == &pll2_pfd_352M)
+ reg |= (MXC_CCM_CSCMR1_USDHC2_CLK_SEL);
+
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_usdhc2_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USDHC2_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static struct clk usdhc2_clk = {
+ __INIT_CLK_DEBUG(usdhc2_clk)
+ .id = 1,
+ .parent = &pll2_pfd_400M,
+ .secondary = &usdhc_dep_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_usdhc2_set_parent,
+ .round_rate = _clk_usdhc_round_rate,
+ .set_rate = _clk_usdhc2_set_rate,
+ .get_rate = _clk_usdhc2_get_rate,
+};
+
+static int _clk_usdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC3_CLK_SEL;
+
+ if (parent == &pll2_pfd_352M)
+ reg |= (MXC_CCM_CSCMR1_USDHC3_CLK_SEL);
+
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_usdhc3_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc3_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USDHC3_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+
+static struct clk usdhc3_clk = {
+ __INIT_CLK_DEBUG(usdhc3_clk)
+ .id = 2,
+ .parent = &pll2_pfd_400M,
+ .secondary = &usdhc_dep_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_usdhc3_set_parent,
+ .round_rate = _clk_usdhc_round_rate,
+ .set_rate = _clk_usdhc3_set_rate,
+ .get_rate = _clk_usdhc3_get_rate,
+};
+
+static int _clk_usdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC4_CLK_SEL;
+
+ if (parent == &pll2_pfd_352M)
+ reg |= (MXC_CCM_CSCMR1_USDHC4_CLK_SEL);
+
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_usdhc4_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc4_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USDHC4_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+
+static struct clk usdhc4_clk = {
+ __INIT_CLK_DEBUG(usdhc4_clk)
+ .id = 3,
+ .parent = &pll2_pfd_400M,
+ .secondary = &usdhc_dep_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_usdhc4_set_parent,
+ .round_rate = _clk_usdhc_round_rate,
+ .set_rate = _clk_usdhc4_set_rate,
+ .get_rate = _clk_usdhc4_get_rate,
+};
+
+static unsigned long _clk_ssi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static unsigned long _clk_ssi1_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+
+ prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK)
+ >> MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK)
+ >> MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~(MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK |
+ MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+
+static int _clk_ssi1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1)
+ & ~MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll3_pfd_508M, &pll3_pfd_454M,
+ &pll4_audio_main_clk, NULL, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET);
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi1_clk = {
+ __INIT_CLK_DEBUG(ssi1_clk)
+ .parent = &pll3_pfd_508M,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ssi1_set_parent,
+ .set_rate = _clk_ssi1_set_rate,
+ .round_rate = _clk_ssi_round_rate,
+ .get_rate = _clk_ssi1_get_rate,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &ocram_clk,
+#else
+ .secondary = &mmdc_ch0_axi_clk[0],
+#endif
+ .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_ssi2_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+
+ prediv = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK)
+ >> MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK)
+ >> MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ reg &= ~(MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK |
+ MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ return 0;
+}
+
+
+static int _clk_ssi2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1)
+ & ~MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll3_pfd_508M, &pll3_pfd_454M,
+ &pll4_audio_main_clk, NULL, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET);
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi2_clk = {
+ __INIT_CLK_DEBUG(ssi2_clk)
+ .parent = &pll3_pfd_508M,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ssi2_set_parent,
+ .set_rate = _clk_ssi2_set_rate,
+ .round_rate = _clk_ssi_round_rate,
+ .get_rate = _clk_ssi2_get_rate,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &ocram_clk,
+#else
+ .secondary = &mmdc_ch0_axi_clk[0],
+#endif
+ .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_ssi3_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+
+ prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK)
+ >> MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK)
+ >> MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi3_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~(MXC_CCM_CS1CDR_SSI3_CLK_PODF_MASK|
+ MXC_CCM_CS1CDR_SSI3_CLK_PRED_MASK);
+ reg |= (post - 1) << MXC_CCM_CS1CDR_SSI3_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS1CDR_SSI3_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+
+static int _clk_ssi3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI3_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll3_pfd_508M, &pll3_pfd_454M,
+ &pll4_audio_main_clk, NULL, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET);
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi3_clk = {
+ __INIT_CLK_DEBUG(ssi3_clk)
+ .parent = &pll3_pfd_508M,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ssi3_set_parent,
+ .set_rate = _clk_ssi3_set_rate,
+ .round_rate = _clk_ssi_round_rate,
+ .get_rate = _clk_ssi3_get_rate,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &ocram_clk,
+#else
+ .secondary = &mmdc_ch0_axi_clk[0],
+#endif
+ .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_ldb_di_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 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_ldb_di0_get_rate(struct clk *clk)
+{
+ u32 div;
+
+ div = __raw_readl(MXC_CCM_CSCMR2) &
+ MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
+
+ if (div)
+ return clk_get_rate(clk->parent) / 7;
+
+ return (2 * clk_get_rate(clk->parent)) / 7;
+}
+
+static int _clk_ldb_di0_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div = 0;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if (rate * 7 <= parent_rate + parent_rate/20) {
+ div = 7;
+ rate = parent_rate / 7;
+ } else
+ rate = 2 * parent_rate / 7;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ if (div == 7)
+ reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
+ else
+ reg &= ~MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static int _clk_ldb_di0_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+ int rev = mx6q_revision();
+
+ reg = __raw_readl(MXC_CCM_CS2CDR)
+ & ~MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll5_video_main_clk,
+ &pll2_pfd_352M, &pll2_pfd_400M,
+ (rev == IMX_CHIP_REVISION_1_0) ?
+ &pll3_pfd_540M : /* MX6Q TO1.0 */
+ &mmdc_ch1_axi_clk[0], /* MX6Q TO1.1 and MX6DL */
+ &pll3_usb_otg_main_clk, NULL);
+ reg |= (mux << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ return 0;
+}
+
+static struct clk ldb_di0_clk = {
+ __INIT_CLK_DEBUG(ldb_di0_clk)
+ .id = 0,
+ .parent = &pll2_pfd_352M,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ldb_di0_set_parent,
+ .set_rate = _clk_ldb_di0_set_rate,
+ .round_rate = _clk_ldb_di_round_rate,
+ .get_rate = _clk_ldb_di0_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_ldb_di1_get_rate(struct clk *clk)
+{
+ u32 div;
+
+ div = __raw_readl(MXC_CCM_CSCMR2) &
+ MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
+
+ if (div)
+ return clk_get_rate(clk->parent) / 7;
+
+ return (2 * clk_get_rate(clk->parent)) / 7;
+}
+
+static int _clk_ldb_di1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div = 0;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if (rate * 7 <= parent_rate + parent_rate/20) {
+ div = 7;
+ rate = parent_rate / 7;
+ } else
+ rate = 2 * parent_rate / 7;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ if (div == 7)
+ reg |= MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
+ else
+ reg &= ~MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static int _clk_ldb_di1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+ int rev = mx6q_revision();
+
+ reg = __raw_readl(MXC_CCM_CS2CDR)
+ & ~MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll5_video_main_clk,
+ &pll2_pfd_352M, &pll2_pfd_400M,
+ (rev == IMX_CHIP_REVISION_1_0) ?
+ &pll3_pfd_540M : /* MX6Q TO1.0 */
+ &mmdc_ch1_axi_clk[0], /* MX6Q TO1.1 and MX6DL */
+ &pll3_usb_otg_main_clk, NULL);
+ reg |= (mux << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ return 0;
+}
+
+static struct clk ldb_di1_clk = {
+ __INIT_CLK_DEBUG(ldb_di1_clk)
+ .id = 0,
+ .parent = &pll2_pfd_352M,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ldb_di1_set_parent,
+ .set_rate = _clk_ldb_di1_set_rate,
+ .round_rate = _clk_ldb_di_round_rate,
+ .get_rate = _clk_ldb_di1_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+
+static unsigned long _clk_ipu_di_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk))
+ return parent_rate;
+
+ div = parent_rate / rate;
+ /* Round to closest divisor */
+ if ((parent_rate % rate) > (rate / 2))
+ div++;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static unsigned long _clk_ipu1_di0_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk))
+ return clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR);
+
+ div = ((reg & MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK) >>
+ MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu1_di0_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk)) {
+ if (parent_rate == rate)
+ return 0;
+ else
+ return -EINVAL;
+ }
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR);
+ reg &= ~MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+ return 0;
+}
+
+
+static int _clk_ipu1_di0_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ if (parent == &ldb_di0_clk)
+ mux = 0x3;
+ else if (parent == &ldb_di1_clk)
+ mux = 0x4;
+ else {
+ reg = __raw_readl(MXC_CCM_CHSCCDR)
+ & ~MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &mmdc_ch0_axi_clk[0],
+ &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+ &pll2_pfd_352M, &pll2_pfd_400M, &pll3_pfd_540M);
+ reg |= (mux << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+ /* Derive clock from divided pre-muxed ipu1_di0 clock.*/
+ mux = 0;
+ }
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR)
+ & ~MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK;
+ __raw_writel(reg | (mux << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET),
+ MXC_CCM_CHSCCDR);
+
+ return 0;
+}
+
+static unsigned long _clk_ipu1_di1_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk))
+ return clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR);
+
+ div = ((reg & MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK)
+ >> MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu1_di1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk)) {
+ if (parent_rate == rate)
+ return 0;
+ else
+ return -EINVAL;
+ }
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR);
+ reg &= ~MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+ return 0;
+}
+
+
+static int _clk_ipu1_di1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ if (parent == &ldb_di0_clk)
+ mux = 0x3;
+ else if (parent == &ldb_di1_clk)
+ mux = 0x4;
+ else {
+ reg = __raw_readl(MXC_CCM_CHSCCDR)
+ & ~MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &mmdc_ch0_axi_clk[0],
+ &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+ &pll2_pfd_352M, &pll2_pfd_400M, &pll3_pfd_540M);
+ reg |= (mux << MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+ /* Derive clock from divided pre-muxed ipu1_di0 clock.*/
+ mux = 0;
+ }
+ reg = __raw_readl(MXC_CCM_CHSCCDR)
+ & ~MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_MASK;
+ __raw_writel(reg | (mux << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET),
+ MXC_CCM_CHSCCDR);
+
+ return 0;
+}
+
+static struct clk ipu1_di_clk[] = {
+ {
+ __INIT_CLK_DEBUG(ipu1_di_clk_0)
+ .id = 0,
+ .parent = &pll5_video_main_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ipu1_di0_set_parent,
+ .set_rate = _clk_ipu1_di0_set_rate,
+ .round_rate = _clk_ipu_di_round_rate,
+ .get_rate = _clk_ipu1_di0_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ __INIT_CLK_DEBUG(ipu1_di_clk_1)
+ .id = 1,
+ .parent = &pll5_video_main_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ipu1_di1_set_parent,
+ .set_rate = _clk_ipu1_di1_set_rate,
+ .round_rate = _clk_ipu_di_round_rate,
+ .get_rate = _clk_ipu1_di1_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+};
+
+static unsigned long _clk_ipu2_di0_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk))
+ return clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+
+ div = ((reg & MXC_CCM_CSCDR2_IPU2_DI0_PODF_MASK) >>
+ MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu2_di0_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk)) {
+ if (parent_rate == rate)
+ return 0;
+ else
+ return -EINVAL;
+ }
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ reg &= ~MXC_CCM_CSCDR2_IPU2_DI0_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static int _clk_ipu2_di0_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ if (parent == &ldb_di0_clk)
+ mux = 0x3;
+ else if (parent == &ldb_di1_clk)
+ mux = 0x4;
+ else {
+ reg = __raw_readl(MXC_CCM_CSCDR2)
+ & ~MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &mmdc_ch0_axi_clk[0],
+ &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+ &pll2_pfd_352M, &pll2_pfd_400M, &pll3_pfd_540M);
+ reg |= (mux << MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ /* Derive clock from divided pre-muxed ipu2_di0 clock.*/
+ mux = 0;
+ }
+ reg = __raw_readl(MXC_CCM_CSCDR2)
+ & ~MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_MASK;
+ __raw_writel(reg | (mux << MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_OFFSET),
+ MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static unsigned long _clk_ipu2_di1_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk))
+ return clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+
+ div = ((reg & MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK)
+ >> MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu2_di1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if ((clk->parent == &ldb_di0_clk) ||
+ (clk->parent == &ldb_di1_clk)) {
+ if (parent_rate == rate)
+ return 0;
+ else
+ return -EINVAL;
+ }
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ reg &= ~MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static int _clk_ipu2_di1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ if (parent == &ldb_di0_clk)
+ mux = 0x3;
+ else if (parent == &ldb_di1_clk)
+ mux = 0x4;
+ else {
+ reg = __raw_readl(MXC_CCM_CSCDR2)
+ & ~MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &mmdc_ch0_axi_clk[0],
+ &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+ &pll2_pfd_352M, &pll2_pfd_400M, &pll3_pfd_540M);
+ reg |= (mux << MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ /* Derive clock from divided pre-muxed ipu1_di0 clock.*/
+ mux = 0;
+ }
+ reg = __raw_readl(MXC_CCM_CSCDR2)
+ & ~MXC_CCM_CSCDR2_IPU2_DI1_CLK_SEL_MASK;
+ __raw_writel(reg | (mux << MXC_CCM_CSCDR2_IPU2_DI1_CLK_SEL_OFFSET),
+ MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static struct clk ipu2_di_clk[] = {
+ {
+ __INIT_CLK_DEBUG(ipu2_di_clk_0)
+ .id = 0,
+ .parent = &pll5_video_main_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ipu2_di0_set_parent,
+ .set_rate = _clk_ipu2_di0_set_rate,
+ .round_rate = _clk_ipu_di_round_rate,
+ .get_rate = _clk_ipu2_di0_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ __INIT_CLK_DEBUG(ipu2_di_clk_1)
+ .id = 1,
+ .parent = &pll5_video_main_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ipu2_di1_set_parent,
+ .set_rate = _clk_ipu2_di1_set_rate,
+ .round_rate = _clk_ipu_di_round_rate,
+ .get_rate = _clk_ipu2_di1_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+};
+
+static unsigned long _clk_can_root_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 64)
+ div = 64;
+
+ return parent_rate / div;
+}
+
+static int _clk_can_root_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 64))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2) & MXC_CCM_CSCMR2_CAN_CLK_PODF_MASK;
+ reg |= ((div - 1) << MXC_CCM_CSCMR2_CAN_CLK_PODF_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_can_root_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ unsigned long val;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2) & MXC_CCM_CSCMR2_CAN_CLK_PODF_MASK;
+ div = (reg >> MXC_CCM_CSCMR2_CAN_CLK_PODF_OFFSET) + 1;
+ val = clk_get_rate(clk->parent) / div;
+
+ return val;
+}
+
+static struct clk can_clk_root = {
+ __INIT_CLK_DEBUG(can_clk_root)
+ .parent = &pll3_60M,
+ .set_rate = _clk_can_root_set_rate,
+ .get_rate = _clk_can_root_get_rate,
+ .round_rate = _clk_can_root_round_rate,
+};
+
+static struct clk can2_clk[] = {
+ {
+ __INIT_CLK_DEBUG(can2_module_clk)
+ .id = 0,
+ .parent = &can_clk_root,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &can2_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ __INIT_CLK_DEBUG(can2_serial_clk)
+ .id = 1,
+ .parent = &can_clk_root,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+
+static struct clk can1_clk[] = {
+ {
+ __INIT_CLK_DEBUG(can1_module_clk)
+ .id = 0,
+ .parent = &can_clk_root,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &can1_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ __INIT_CLK_DEBUG(can1_serial_clk)
+ .id = 1,
+ .parent = &can_clk_root,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static unsigned long _clk_spdif_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_spdif0_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CDCDR)
+ & ~MXC_CCM_CDCDR_SPDIF0_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll4_audio_main_clk,
+ &pll3_pfd_508M, &pll3_pfd_454M,
+ &pll3_sw_clk, NULL, NULL);
+ reg |= mux << MXC_CCM_CDCDR_SPDIF0_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ return 0;
+}
+
+static unsigned long _clk_spdif0_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CDCDR);
+
+ pred = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK)
+ >> MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK)
+ >> MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int _clk_spdif0_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 64)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~(MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK|
+ MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ return 0;
+}
+
+static struct clk spdif0_clk[] = {
+ {
+ __INIT_CLK_DEBUG(spdif0_clk_0)
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &spdif0_clk[1],
+ .set_rate = _clk_spdif0_set_rate,
+ .get_rate = _clk_spdif0_get_rate,
+ .set_parent = _clk_spdif0_set_parent,
+ .round_rate = _clk_spdif_round_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ __INIT_CLK_DEBUG(spdif0_clk_1)
+ .id = 1,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ },
+};
+
+static unsigned long _clk_esai_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_esai_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2) & ~MXC_CCM_CSCMR2_ESAI_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll4_audio_main_clk, &pll3_pfd_508M,
+ &pll3_pfd_454M, &pll3_sw_clk, NULL, NULL);
+ reg |= mux << MXC_CCM_CSCMR2_ESAI_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_esai_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+
+ pred = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK)
+ >> MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK)
+ >> MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int _clk_esai_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 64)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~(MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK|
+ MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+static struct clk esai_clk = {
+ __INIT_CLK_DEBUG(esai_clk)
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_rate = _clk_esai_set_rate,
+ .get_rate = _clk_esai_get_rate,
+ .set_parent = _clk_esai_set_parent,
+ .round_rate = _clk_esai_round_rate,
+};
+
+static int _clk_enet_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div = 1;
+
+ 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;
+ }
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg &= ~ANADIG_PLL_ENET_DIV_SELECT_MASK;
+ reg |= (div << ANADIG_PLL_ENET_DIV_SELECT_OFFSET);
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+
+ return 0;
+}
+
+static unsigned long _clk_enet_get_rate(struct clk *clk)
+{
+ unsigned int div;
+
+ div = (__raw_readl(PLL8_ENET_BASE_ADDR))
+ & ANADIG_PLL_ENET_DIV_SELECT_MASK;
+
+ switch (div) {
+ case 0:
+ div = 20;
+ break;
+ case 1:
+ div = 10;
+ break;
+ case 3:
+ div = 5;
+ break;
+ case 4:
+ div = 4;
+ break;
+ }
+
+ return 500000000 / div;
+}
+
+static int _clk_enet_enable(struct clk *clk)
+{
+#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ enet_is_active = true;
+#endif
+ _clk_enable(clk);
+ return 0;
+}
+
+static void _clk_enet_disable(struct clk *clk)
+{
+ _clk_disable(clk);
+#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO
+ enet_is_active = false;
+#endif
+}
+
+static struct clk enet_clk[] = {
+ {
+ __INIT_CLK_DEBUG(enet_clk)
+ .id = 0,
+ .parent = &pll8_enet_main_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enet_enable,
+ .disable = _clk_enet_disable,
+ .set_rate = _clk_enet_set_rate,
+ .get_rate = _clk_enet_get_rate,
+ .secondary = &enet_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mx6per1_clk,
+ },
+};
+
+static unsigned long _clk_enet_mdc_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent);
+}
+
+static struct clk enet_mdc_clk = {
+ __INIT_CLK_DEBUG(enet_mdc_clk)
+ .parent = &ipg_clk,
+ .get_rate = _clk_enet_mdc_get_rate,
+};
+
+static struct clk ecspi_clk[] = {
+ {
+ __INIT_CLK_DEBUG(ecspi0_clk)
+ .id = 0,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(ecspi1_clk)
+ .id = 1,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(ecspi2_clk)
+ .id = 2,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(ecspi3_clk)
+ .id = 3,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(ecspi4_clk)
+ .id = 4,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static unsigned long _clk_emi_slow_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_emi_slow_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1)
+ & ~MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK;
+
+ mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk,
+ &pll2_pfd_400M, &pll2_pfd_352M, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET);
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_emi_slow_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ div = ((reg & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK) >>
+ MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_emi_slow_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET;
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk emi_slow_clk = {
+ __INIT_CLK_DEBUG(emi_slow_clk)
+ .id = 0,
+ .parent = &axi_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_rate = _clk_emi_slow_set_rate,
+ .get_rate = _clk_emi_slow_get_rate,
+ .round_rate = _clk_emi_slow_round_rate,
+ .set_parent = _clk_emi_slow_set_parent,
+};
+
+static unsigned long _clk_emi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_emi_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_ACLK_EMI_MASK;
+
+ /*mux = _get_mux6(parent, &pll2_pfd_400M, &pll3_usb_otg_main_clk,
+ &axi_clk, &pll2_pfd_352M, NULL, NULL);*/
+ mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk,
+ &pll2_pfd_400M, &pll2_pfd_352M, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_ACLK_EMI_OFFSET);
+ /* aclk_podf fixup */
+ reg ^= 0x00600000;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_emi_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ /* ACLK_EMI_PODF read value matches with real divider value */
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ div = ((reg & MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK) >>
+ MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_emi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ /*
+ * This is a software workaround for ACLK_EMI_PODF SoC
+ * implementation bug. The write/read/divider values
+ * have the relationship described by the following table:
+ *
+ * write value read value description
+ * 3b'000 3b'110 divided by 7
+ * 3b'001 3b'111 divided by 8
+ * 3b'010 3b'100 divided by 5
+ * 3b'011 3b'101 divided by 6
+ * 3b'100 3b'010 divided by 3
+ * 3b'101 3b'011 divided by 4
+ * 3b'110 3b'000 divided by 1
+ * 3b'111 3b'001 divided by 2(default)
+ *
+ * That's why we do the xor operation below.
+ */
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK;
+ reg |= ((div - 1)^0x6) << MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk emi_clk = {
+ __INIT_CLK_DEBUG(emi_clk)
+ .id = 0,
+ .parent = &axi_clk,
+ .set_rate = _clk_emi_set_rate,
+ .get_rate = _clk_emi_get_rate,
+ .round_rate = _clk_emi_round_rate,
+ .set_parent = _clk_emi_set_parent,
+};
+
+static unsigned long _clk_enfc_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_enfc_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CS2CDR)
+ & ~MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll2_pfd_352M,
+ &pll2_528_bus_main_clk, &pll3_usb_otg_main_clk,
+ &pll2_pfd_400M, NULL, NULL);
+ reg |= mux << MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ return 0;
+}
+
+static unsigned long _clk_enfc_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+
+ pred = ((reg & MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK)
+ >> MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK)
+ >> MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int _clk_enfc_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ reg &= ~(MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK|
+ MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ return 0;
+}
+
+static struct clk enfc_clk = {
+ __INIT_CLK_DEBUG(enfc_clk)
+ .id = 0,
+ .parent = &pll2_pfd_352M,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_rate = _clk_enfc_set_rate,
+ .get_rate = _clk_enfc_get_rate,
+ .round_rate = _clk_enfc_round_rate,
+ .set_parent = _clk_enfc_set_parent,
+};
+
+static unsigned long _clk_uart_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 64)
+ div = 64;
+
+ return parent_rate / div;
+}
+
+static int _clk_uart_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 64))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1) & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
+ reg |= ((div - 1) << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static unsigned long _clk_uart_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ unsigned long val;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1) & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
+ div = (reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
+ val = clk_get_rate(clk->parent) / div;
+
+ return val;
+}
+
+static struct clk uart_clk[] = {
+ {
+ __INIT_CLK_DEBUG(uart_clk)
+ .id = 0,
+ .parent = &pll3_80M,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &uart_clk[1],
+ .set_rate = _clk_uart_set_rate,
+ .get_rate = _clk_uart_get_rate,
+ .round_rate = _clk_uart_round_rate,
+ },
+ {
+ __INIT_CLK_DEBUG(uart_serial_clk)
+ .id = 1,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static unsigned long _clk_hsi_tx_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_hsi_tx_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CDCDR) & ~MXC_CCM_CDCDR_HSI_TX_CLK_SEL;
+
+ if (parent == &pll2_pfd_400M)
+ reg |= (MXC_CCM_CDCDR_HSI_TX_CLK_SEL);
+
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ return 0;
+}
+
+static unsigned long _clk_hsi_tx_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ div = ((reg & MXC_CCM_CDCDR_HSI_TX_PODF_MASK) >>
+ MXC_CCM_CDCDR_HSI_TX_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_hsi_tx_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~MXC_CCM_CDCDR_HSI_TX_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CDCDR_HSI_TX_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ return 0;
+}
+
+static struct clk hsi_tx_clk[] = {
+ {
+ __INIT_CLK_DEBUG(hsi_tx_clk)
+ .id = 0,
+ .parent = &pll2_pfd_400M,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_hsi_tx_set_parent,
+ .round_rate = _clk_hsi_tx_round_rate,
+ .set_rate = _clk_hsi_tx_set_rate,
+ .get_rate = _clk_hsi_tx_get_rate,
+ .secondary = &hsi_tx_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &mx6per1_clk,
+ .secondary = &mx6per2_clk,
+ },
+};
+
+static struct clk mipi_pllref_clk = {
+ __INIT_CLK_DEBUG(mipi_pllref_clk)
+ .id = 0,
+ .parent = &pll3_pfd_540M,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static struct clk hdmi_clk[] = {
+ {
+ __INIT_CLK_DEBUG(hdmi_isfr_clk)
+ .id = 0,
+ .parent = &pll3_pfd_540M,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(hdmi_iahb_clk)
+ .id = 1,
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk caam_clk[] = {
+ {
+ __INIT_CLK_DEBUG(caam_mem_clk)
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &caam_clk[1],
+ },
+ {
+ __INIT_CLK_DEBUG(caam_aclk_clk)
+ .id = 1,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &caam_clk[2],
+ },
+ {
+ __INIT_CLK_DEBUG(caam_ipg_clk)
+ .id = 2,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mx6per1_clk,
+ },
+};
+
+static int _clk_asrc_serial_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CDCDR) & ~MXC_CCM_CDCDR_SPDIF1_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll4_audio_main_clk, &pll3_pfd_508M,
+ &pll3_pfd_454M, &pll3_sw_clk, NULL, NULL);
+ reg |= mux << MXC_CCM_CDCDR_SPDIF1_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ return 0;
+}
+
+static unsigned long _clk_asrc_serial_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CDCDR);
+
+ pred = ((reg & MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK)
+ >> MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK)
+ >> MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int _clk_asrc_serial_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 64)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~(MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK|
+ MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ return 0;
+}
+
+static unsigned long _clk_asrc_serial_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static struct clk asrc_clk[] = {
+ {
+ __INIT_CLK_DEBUG(asrc_clk)
+ .id = 0,
+ .parent = &pll4_audio_main_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &spba_clk,
+ },
+ {
+ /*In the MX6 spec, asrc_serial_clk is listed as SPDIF1 clk
+ * This clock can never be gated and does not have any
+ * CCGR bits associated with it.
+ */
+ __INIT_CLK_DEBUG(asrc_serial_clk)
+ .id = 1,
+ .parent = &pll3_sw_clk,
+ .set_rate = _clk_asrc_serial_set_rate,
+ .get_rate = _clk_asrc_serial_get_rate,
+ .set_parent = _clk_asrc_serial_set_parent,
+ .round_rate = _clk_asrc_serial_round_rate,
+ },
+};
+
+static struct clk apbh_dma_clk = {
+ __INIT_CLK_DEBUG(apbh_dma_clk)
+ .parent = &usdhc3_clk,
+ .secondary = &mx6per1_clk,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+};
+
+static struct clk aips_tz2_clk = {
+ __INIT_CLK_DEBUG(aips_tz2_clk)
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk aips_tz1_clk = {
+ __INIT_CLK_DEBUG(aips_tz1_clk)
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+
+static struct clk openvg_axi_clk = {
+ __INIT_CLK_DEBUG(openvg_axi_clk)
+ .parent = &gpu2d_axi_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_gpu3d_core_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_gpu3d_core_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CBCMR)
+ & ~MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &mmdc_ch0_axi_clk[0],
+ &pll3_usb_otg_main_clk,
+ &pll2_pfd_594M, &pll2_pfd_400M, NULL, NULL);
+ reg |= (mux << MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static unsigned long _clk_gpu3d_core_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ div = ((reg & MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK) >>
+ MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_gpu3d_core_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (div > 8)
+ div = 8;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk gpu3d_core_clk[] = {
+ {
+ __INIT_CLK_DEBUG(gpu3d_core_clk)
+ .parent = &pll2_pfd_594M,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .set_parent = _clk_gpu3d_core_set_parent,
+ .set_rate = _clk_gpu3d_core_set_rate,
+ .get_rate = _clk_gpu3d_core_get_rate,
+ .round_rate = _clk_gpu3d_core_round_rate,
+ .secondary = &gpu3d_core_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &gpu3d_axi_clk,
+ .secondary = &mx6fast1_clk,
+ },
+};
+
+static unsigned long _clk_gpu2d_core_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_gpu2d_core_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CBCMR) &
+ ~MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK;
+
+ /*on mx6dl, 2d core clock sources from 3d shader core clock*/
+ if (!cpu_is_mx6dl()) {
+ mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk,
+ &pll2_pfd_352M, &pll2_pfd_400M, NULL, NULL);
+ reg |= (mux << MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+ }
+
+ return 0;
+}
+
+static unsigned long _clk_gpu2d_core_get_rate(struct clk *clk)
+{
+ u32 reg, div = 1;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ if (cpu_is_mx6q())
+ div = ((reg & MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK) >>
+ MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET) + 1;
+ else if (cpu_is_mx6dl())
+ /* on i.mx6dl, gpu2d_core_clk source from gpu3d_shader_clk */
+ return clk_get_rate(clk->parent);
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_gpu2d_core_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+static struct clk gpu2d_core_clk[] = {
+ {
+ __INIT_CLK_DEBUG(gpu2d_core_clk)
+ .parent = &pll2_pfd_352M,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .disable = _clk_disable,
+ .set_parent = _clk_gpu2d_core_set_parent,
+ .set_rate = _clk_gpu2d_core_set_rate,
+ .get_rate = _clk_gpu2d_core_get_rate,
+ .round_rate = _clk_gpu2d_core_round_rate,
+ .secondary = &mx6fast1_clk,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+};
+
+static unsigned long _clk_gpu3d_shader_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_gpu3d_shader_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CBCMR)
+ & ~MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &mmdc_ch0_axi_clk[0],
+ &pll3_usb_otg_main_clk,
+ &pll2_pfd_594M, &pll3_pfd_720M, NULL, NULL);
+ reg |= (mux << MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static unsigned long _clk_gpu3d_shader_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ div = ((reg & MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK) >>
+ MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_gpu3d_shader_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (div > 8)
+ div = 8;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+
+static struct clk gpu3d_shader_clk = {
+ __INIT_CLK_DEBUG(gpu3d_shader_clk)
+ .parent = &pll3_pfd_720M,
+ .secondary = &mmdc_ch0_axi_clk[0],
+ .set_parent = _clk_gpu3d_shader_set_parent,
+ .set_rate = _clk_gpu3d_shader_set_rate,
+ .get_rate = _clk_gpu3d_shader_get_rate,
+ .round_rate = _clk_gpu3d_shader_round_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+/* set the parent by the ipcg table */
+static struct clk gpmi_nand_clk[] = {
+ { /* gpmi_io_clk */
+ __INIT_CLK_DEBUG(gpmi_io_clk)
+ .parent = &enfc_clk,
+ .secondary = &gpmi_nand_clk[1],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .disable = _clk_disable,
+ },
+ { /* gpmi_apb_clk */
+ __INIT_CLK_DEBUG(gpmi_apb_clk)
+ .parent = &usdhc3_clk,
+ .secondary = &gpmi_nand_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .disable = _clk_disable,
+ },
+ { /* bch_clk */
+ __INIT_CLK_DEBUG(gpmi_bch_clk)
+ .parent = &usdhc4_clk,
+ .secondary = &gpmi_nand_clk[3],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .disable = _clk_disable,
+ },
+ { /* bch_apb_clk */
+ __INIT_CLK_DEBUG(gpmi_bch_apb_clk)
+ .parent = &usdhc3_clk,
+ .secondary = &gpmi_nand_clk[4],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .disable = _clk_disable,
+ },
+ { /* bch relative clk */
+ __INIT_CLK_DEBUG(pl301_mx6qperl_bch)
+ .parent = &mx6per1_clk,
+ .secondary = &mmdc_ch0_axi_clk[0],
+ },
+};
+
+static struct clk pwm_clk[] = {
+ {
+ __INIT_CLK_DEBUG(pwm_clk_0)
+ .parent = &ipg_perclk,
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(pwm_clk_1)
+ .parent = &ipg_perclk,
+ .id = 1,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(pwm_clk_2)
+ .parent = &ipg_perclk,
+ .id = 2,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(pwm_clk_3)
+ .parent = &ipg_perclk,
+ .id = 3,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static int _clk_sata_enable(struct clk *clk)
+{
+ unsigned int reg;
+
+ /* Enable SATA ref clock */
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg |= ANADIG_PLL_ENET_EN_SATA;
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+
+ _clk_enable(clk);
+
+ return 0;
+}
+
+static void _clk_sata_disable(struct clk *clk)
+{
+ unsigned int reg;
+
+ _clk_disable(clk);
+
+ /* Disable SATA ref clock */
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg &= ~ANADIG_PLL_ENET_EN_SATA;
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+}
+
+static struct clk sata_clk[] = {
+ {
+ __INIT_CLK_DEBUG(sata_clk)
+ .parent = &pll8_enet_main_clk,
+ .enable = _clk_sata_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_sata_disable,
+ .secondary = &sata_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &ipg_clk,
+ .secondary = &sata_clk[2],
+ },
+ {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mx6per1_clk,
+ },
+};
+
+static int _clk_pcie_enable(struct clk *clk)
+{
+ unsigned int reg;
+
+#ifndef CONFIG_IMX_PCIE_RC_MODE_IN_EP_RC_SYS
+ /* Activate LVDS CLK1 (the MiniPCIe slot clock input) */
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg &= ~ANATOP_LVDS_CLK1_IBEN_MASK;
+ __raw_writel(reg, ANADIG_MISC1_REG);
+
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= ANATOP_LVDS_CLK1_SRC_SATA;
+ __raw_writel(reg, ANADIG_MISC1_REG);
+
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= ANATOP_LVDS_CLK1_OBEN_MASK;
+ __raw_writel(reg, ANADIG_MISC1_REG);
+#endif
+
+ /* Enable PCIE ref clock */
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg |= ANADIG_PLL_ENET_EN_PCIE;
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+
+ _clk_enable(clk);
+
+ return 0;
+}
+
+static void _clk_pcie_disable(struct clk *clk)
+{
+ unsigned int reg;
+
+ _clk_disable(clk);
+
+#ifndef CONFIG_IMX_PCIE_RC_MODE_IN_EP_RC_SYS
+ /* De-activate LVDS CLK1 (the MiniPCIe slot clock input) */
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= ANATOP_LVDS_CLK1_IBEN_MASK;
+ __raw_writel(reg, ANADIG_MISC1_REG);
+
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg &= ~ANATOP_LVDS_CLK1_SRC_SATA;
+ __raw_writel(reg, ANADIG_MISC1_REG);
+
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg &= ~ANATOP_LVDS_CLK1_OBEN_MASK;
+ __raw_writel(reg, ANADIG_MISC1_REG);
+#endif
+
+ /* Disable PCIE ref clock */
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg &= ~ANADIG_PLL_ENET_EN_PCIE;
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+}
+
+static struct clk pcie_clk[] = {
+ {
+ __INIT_CLK_DEBUG(pcie_clk)
+ .parent = &pcie_axi_clk,
+ .enable = _clk_pcie_enable,
+ .disable = _clk_pcie_disable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .secondary = &pcie_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ /*
+ * Enable SATA ref clock.
+ * PCIe needs both sides to have the same source of refernce clock,
+ * The SATA reference clock is taken out to link partner.
+ */
+ .parent = &sata_clk[0],
+ .secondary = &pcie_clk[2],
+ },
+ {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mx6fast1_clk,
+ },
+};
+
+static int _clk_pcie_ep_enable(struct clk *clk)
+{
+ unsigned int reg;
+
+ /* Enable PCIE ref clock */
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg |= ANADIG_PLL_ENET_EN_PCIE;
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+
+ _clk_enable(clk);
+
+ return 0;
+}
+
+static void _clk_pcie_ep_disable(struct clk *clk)
+{
+ unsigned int reg;
+
+ _clk_disable(clk);
+
+ /* Disable PCIE ref clock */
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg &= ~ANADIG_PLL_ENET_EN_PCIE;
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+}
+
+static struct clk pcie_ep_clk[] = {
+ {
+ __INIT_CLK_DEBUG(pcie_ep_clk)
+ .parent = &pcie_axi_clk,
+ .enable = _clk_pcie_ep_enable,
+ .disable = _clk_pcie_ep_disable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .secondary = &pcie_ep_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &pll8_enet_main_clk,
+ .secondary = &pcie_ep_clk[2],
+ },
+ {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mx6fast1_clk,
+ },
+};
+
+static struct clk usboh3_clk[] = {
+ {
+ __INIT_CLK_DEBUG(usboh3_clk)
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &usboh3_clk[1],
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &mx6per1_clk,
+ },
+};
+
+static int _clk_mlb_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 sel, cbcmr = __raw_readl(MXC_CCM_CBCMR);
+
+ /*
+ * In Rigel validatioin, the MLB sys_clock isn't using the
+ * right frequency after boot.
+ * In arik, the register CBCMR controls gpu2d clock, not mlb clock,
+ * mlb is sourced from axi clock.
+ * But In rigel, the axi clock is lower than in mx6q, so mlb need to
+ * find a new clock root.
+ * The gpu2d clock is the root of mlb clock in rigel.
+ * Thus we need to add below code in mx6dl.
+ * */
+ sel = _get_mux(parent, &axi_clk, &pll3_sw_clk,
+ &pll2_pfd_352M, &pll2_pfd_400M);
+
+ cbcmr &= ~MXC_CCM_CBCMR_MLB_CLK_SEL_MASK;
+ cbcmr |= sel << MXC_CCM_CBCMR_MLB_CLK_SEL_OFFSET;
+ __raw_writel(cbcmr, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk mlb150_clk = {
+ __INIT_CLK_DEBUG(mlb150_clk)
+ .id = 0,
+ .secondary = &ocram_clk,
+ .set_parent = _clk_mlb_set_parent,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static int _clk_enable1(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_disable1(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(1 << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 sel, reg;
+
+ if (parent == &pll3_usb_otg_main_clk)
+ sel = 0;
+ else if (parent == &pll2_528_bus_main_clk)
+ sel = 1;
+ else if (parent == &pll1_sys_main_clk)
+ sel = 2;
+ else if (parent == &pll5_video_main_clk)
+ sel = 3;
+ else if (parent == &axi_clk)
+ sel = 5;
+ else if (parent == &enfc_clk)
+ sel = 6;
+ else if (parent == &ipu1_di_clk[0])
+ sel = 7;
+ else if (parent == &ipu1_di_clk[1])
+ sel = 8;
+ else if (parent == &ipu2_di_clk[0])
+ sel = 9;
+ else if (parent == &ipu2_di_clk[1])
+ sel = 10;
+ else if (parent == &ahb_clk)
+ sel = 11;
+ else if (parent == &ipg_clk)
+ sel = 12;
+ else if (parent == &ipg_perclk)
+ sel = 13;
+ else if (parent == &ckil_clk)
+ sel = 14;
+ else if (parent == &pll4_audio_main_clk)
+ sel = 15;
+ else if (parent == &clko2_clk) {
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg |= MXC_CCM_CCOSR_CKOL_MIRROR_CKO2_MASK;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+ } else
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~(MXC_CCM_CCOSR_CKOL_MIRROR_CKO2_MASK |
+ MXC_CCM_CCOSR_CKOL_SEL_MASK);
+ reg |= sel << MXC_CCM_CCOSR_CKOL_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static unsigned long _clk_clko_get_rate(struct clk *clk)
+{
+ u32 reg = __raw_readl(MXC_CCM_CCOSR);
+ u32 div = ((reg & MXC_CCM_CCOSR_CKOL_DIV_MASK) >>
+ MXC_CCM_CCOSR_CKOL_DIV_OFFSET) + 1;
+
+ if (clk->parent == &clko2_clk)
+ /* clko may output clko2 without divider */
+ return clk_get_rate(clk->parent);
+ else
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ /* clko may output clko2 without divider */
+ if (clk->parent == &clko2_clk)
+ return 0;
+
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKOL_DIV_MASK;
+ reg |= (div - 1) << MXC_CCM_CCOSR_CKOL_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static unsigned long _clk_clko_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ /* clko may output clko2 without divider */
+ if (clk->parent == &clko2_clk)
+ return parent_rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ else if (parent_rate % rate)
+ div++;
+
+ if (div > 8)
+ div = 8;
+ return parent_rate / div;
+}
+
+static int _clk_clko2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 sel, reg;
+
+ if (parent == &mmdc_ch0_axi_clk[0])
+ sel = 0;
+ else if (parent == &mmdc_ch1_axi_clk[0])
+ sel = 1;
+ else if (parent == &usdhc4_clk)
+ sel = 2;
+ else if (parent == &usdhc1_clk)
+ sel = 3;
+ else if (parent == &gpu2d_axi_clk)
+ sel = 4;
+ else if (parent == &ecspi_clk[0])
+ sel = 6;
+ else if (parent == &gpu3d_axi_clk)
+ sel = 7;
+ else if (parent == &usdhc3_clk)
+ sel = 8;
+ else if (parent == &pcie_clk[0])
+ sel = 9;
+ else if (parent == &ipu1_clk)
+ sel = 11;
+ else if (parent == &ipu2_clk)
+ sel = 12;
+ else if (parent == &vdo_axi_clk)
+ sel = 13;
+ else if (parent == &osc_clk)
+ sel = 14;
+ else if (parent == &gpu2d_core_clk[0])
+ sel = 15;
+ else if (parent == &gpu3d_core_clk[0])
+ sel = 16;
+ else if (parent == &usdhc2_clk)
+ sel = 17;
+ else if (parent == &ssi1_clk)
+ sel = 18;
+ else if (parent == &ssi2_clk)
+ sel = 19;
+ else if (parent == &ssi3_clk)
+ sel = 20;
+ else if (parent == &gpu3d_shader_clk)
+ sel = 21;
+ else if (parent == &can_clk_root)
+ sel = 23;
+ else if (parent == &ldb_di0_clk)
+ sel = 24;
+ else if (parent == &ldb_di1_clk)
+ sel = 25;
+ else if (parent == &esai_clk)
+ sel = 26;
+ else if (parent == &uart_clk[0])
+ sel = 28;
+ else if (parent == &spdif0_clk[0])
+ sel = 29;
+ else if (parent == &hsi_tx_clk[0])
+ sel = 31;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKO2_SEL_MASK;
+ reg |= sel << MXC_CCM_CCOSR_CKO2_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static unsigned long _clk_clko2_get_rate(struct clk *clk)
+{
+ u32 reg = __raw_readl(MXC_CCM_CCOSR);
+ u32 div = ((reg & MXC_CCM_CCOSR_CKO2_DIV_MASK) >>
+ MXC_CCM_CCOSR_CKO2_DIV_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_clko2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKO2_DIV_MASK;
+ reg |= (div - 1) << MXC_CCM_CCOSR_CKO2_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static struct clk clko_clk = {
+ __INIT_CLK_DEBUG(clko_clk)
+ .parent = &pll2_528_bus_main_clk,
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCOSR,
+ .enable_shift = MXC_CCM_CCOSR_CKOL_EN_OFFSET,
+ .disable = _clk_disable1,
+ .set_parent = _clk_clko_set_parent,
+ .set_rate = _clk_clko_set_rate,
+ .get_rate = _clk_clko_get_rate,
+ .round_rate = _clk_clko_round_rate,
+};
+
+static struct clk clko2_clk = {
+ __INIT_CLK_DEBUG(clko2_clk)
+ .parent = &usdhc4_clk,
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCOSR,
+ .enable_shift = MXC_CCM_CCOSR_CKO2_EN_OFFSET,
+ .disable = _clk_disable1,
+ .set_parent = _clk_clko2_set_parent,
+ .set_rate = _clk_clko2_set_rate,
+ .get_rate = _clk_clko2_get_rate,
+ .round_rate = _clk_clko_round_rate,
+};
+
+static struct clk perfmon0_clk = {
+ __INIT_CLK_DEBUG(perfmon0_clk)
+ .parent = &mmdc_ch0_axi_clk[0],
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable1,
+};
+
+static struct clk perfmon1_clk = {
+ __INIT_CLK_DEBUG(perfmon1_clk)
+ .parent = &ipu1_clk,
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable1,
+};
+
+static struct clk perfmon2_clk = {
+ __INIT_CLK_DEBUG(perfmon2_clk)
+ .parent = &mmdc_ch0_axi_clk[0],
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .disable = _clk_disable1,
+};
+
+static struct clk dummy_clk = {
+ .id = 0,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ }
+
+
+static struct clk_lookup lookups[] = {
+ _REGISTER_CLOCK(NULL, "osc", osc_clk),
+ _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+ _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk),
+ _REGISTER_CLOCK(NULL, "ckil", ckil_clk),
+ _REGISTER_CLOCK(NULL, "pll1_main_clk", pll1_sys_main_clk),
+ _REGISTER_CLOCK(NULL, "pll1_sw_clk", pll1_sw_clk),
+ _REGISTER_CLOCK(NULL, "pll2", pll2_528_bus_main_clk),
+ _REGISTER_CLOCK(NULL, "pll2_pfd_400M", pll2_pfd_400M),
+ _REGISTER_CLOCK(NULL, "pll2_pfd_352M", pll2_pfd_352M),
+ _REGISTER_CLOCK(NULL, "pll2_pfd_594M", pll2_pfd_594M),
+ _REGISTER_CLOCK(NULL, "pll2_200M", pll2_200M),
+ _REGISTER_CLOCK(NULL, "pll3_main_clk", pll3_usb_otg_main_clk),
+ _REGISTER_CLOCK(NULL, "pll3_pfd_508M", pll3_pfd_508M),
+ _REGISTER_CLOCK(NULL, "pll3_pfd_454M", pll3_pfd_454M),
+ _REGISTER_CLOCK(NULL, "pll3_pfd_720M", pll3_pfd_720M),
+ _REGISTER_CLOCK(NULL, "pll3_pfd_540M", pll3_pfd_540M),
+ _REGISTER_CLOCK(NULL, "pll3_sw_clk", pll3_sw_clk),
+ _REGISTER_CLOCK(NULL, "pll3_120M", pll3_120M),
+ _REGISTER_CLOCK(NULL, "pll3_120M", pll3_80M),
+ _REGISTER_CLOCK(NULL, "pll3_120M", pll3_60M),
+ _REGISTER_CLOCK(NULL, "pll4", pll4_audio_main_clk),
+ _REGISTER_CLOCK(NULL, "pll5", pll5_video_main_clk),
+ _REGISTER_CLOCK(NULL, "pll6", pll6_mlb150_main_clk),
+ _REGISTER_CLOCK(NULL, "pll3", pll7_usb_host_main_clk),
+ _REGISTER_CLOCK(NULL, "pll4", pll8_enet_main_clk),
+ _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk),
+ _REGISTER_CLOCK("smp_twd", NULL, twd_clk),
+ _REGISTER_CLOCK(NULL, "periph_clk", periph_clk),
+ _REGISTER_CLOCK(NULL, "axi_clk", axi_clk),
+ _REGISTER_CLOCK(NULL, "mmdc_ch0_axi", mmdc_ch0_axi_clk[0]),
+ _REGISTER_CLOCK(NULL, "mmdc_ch1_axi", mmdc_ch1_axi_clk[0]),
+ _REGISTER_CLOCK(NULL, "ahb", ahb_clk),
+ _REGISTER_CLOCK(NULL, "ipg_clk", ipg_clk),
+ _REGISTER_CLOCK(NULL, "ipg_perclk", ipg_perclk),
+ _REGISTER_CLOCK(NULL, "spba", spba_clk),
+ _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk[0]),
+ _REGISTER_CLOCK(NULL, "gpu2d_axi_clk", gpu2d_axi_clk),
+ _REGISTER_CLOCK(NULL, "gpu3d_axi_clk", gpu3d_axi_clk),
+ _REGISTER_CLOCK(NULL, "pcie_axi_clk", pcie_axi_clk),
+ _REGISTER_CLOCK(NULL, "vdo_axi_clk", vdo_axi_clk),
+ _REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+ _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[0]),
+ _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk[1]),
+ _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2]),
+ _REGISTER_CLOCK(NULL, "vpu_clk", vpu_clk[0]),
+ _REGISTER_CLOCK(NULL, "ipu1_clk", ipu1_clk),
+ _REGISTER_CLOCK(NULL, "ipu2_clk", ipu2_clk),
+ _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, usdhc1_clk),
+ _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, usdhc2_clk),
+ _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, usdhc3_clk),
+ _REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, usdhc4_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(NULL, "ipu1_di0_clk", ipu1_di_clk[0]),
+ _REGISTER_CLOCK(NULL, "ipu1_di1_clk", ipu1_di_clk[1]),
+ _REGISTER_CLOCK(NULL, "ipu2_di0_clk", ipu2_di_clk[0]),
+ _REGISTER_CLOCK(NULL, "ipu2_di1_clk", ipu2_di_clk[1]),
+ _REGISTER_CLOCK(NULL, "can_root_clk", can_clk_root),
+ _REGISTER_CLOCK("imx6q-flexcan.0", NULL, can1_clk[0]),
+ _REGISTER_CLOCK("imx6q-flexcan.1", NULL, can2_clk[0]),
+ _REGISTER_CLOCK(NULL, "ldb_di0_clk", ldb_di0_clk),
+ _REGISTER_CLOCK(NULL, "ldb_di1_clk", ldb_di1_clk),
+ _REGISTER_CLOCK("mxc_spdif.0", NULL, spdif0_clk[0]),
+ _REGISTER_CLOCK(NULL, "esai_clk", esai_clk),
+ _REGISTER_CLOCK("imx6q-ecspi.0", NULL, ecspi_clk[0]),
+ _REGISTER_CLOCK("imx6q-ecspi.1", NULL, ecspi_clk[1]),
+ _REGISTER_CLOCK("imx6q-ecspi.2", NULL, ecspi_clk[2]),
+ _REGISTER_CLOCK("imx6q-ecspi.3", NULL, ecspi_clk[3]),
+ _REGISTER_CLOCK("imx6q-ecspi.4", NULL, ecspi_clk[4]),
+ _REGISTER_CLOCK(NULL, "emi_slow_clk", emi_slow_clk),
+ _REGISTER_CLOCK(NULL, "emi_clk", emi_clk),
+ _REGISTER_CLOCK(NULL, "enfc_clk", enfc_clk),
+ _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0]),
+ _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[0]),
+ _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[0]),
+ _REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[0]),
+ _REGISTER_CLOCK("imx-uart.4", NULL, uart_clk[0]),
+ _REGISTER_CLOCK(NULL, "hsi_tx", hsi_tx_clk[0]),
+ _REGISTER_CLOCK(NULL, "caam_clk", caam_clk[0]),
+ _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk[0]),
+ _REGISTER_CLOCK(NULL, "asrc_serial_clk", asrc_clk[1]),
+ _REGISTER_CLOCK(NULL, "mxs-dma-apbh", apbh_dma_clk),
+ _REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
+ _REGISTER_CLOCK(NULL, "gpu3d_clk", gpu3d_core_clk[0]),
+ _REGISTER_CLOCK(NULL, "gpu2d_clk", gpu2d_core_clk[0]),
+ _REGISTER_CLOCK(NULL, "gpu3d_shader_clk", gpu3d_shader_clk),
+ _REGISTER_CLOCK(NULL, "gpt", gpt_clk[0]),
+ _REGISTER_CLOCK("imx6q-gpmi-nand.0", NULL, gpmi_nand_clk[0]),
+ _REGISTER_CLOCK(NULL, "gpmi-apb", gpmi_nand_clk[1]),
+ _REGISTER_CLOCK(NULL, "bch", gpmi_nand_clk[2]),
+ _REGISTER_CLOCK(NULL, "bch-apb", gpmi_nand_clk[3]),
+ _REGISTER_CLOCK(NULL, "pl301_mx6qperl-bch", gpmi_nand_clk[4]),
+ _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk[0]),
+ _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm_clk[1]),
+ _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm_clk[2]),
+ _REGISTER_CLOCK("mxc_pwm.3", NULL, pwm_clk[3]),
+ _REGISTER_CLOCK(NULL, "pcie_clk", pcie_clk[0]),
+ _REGISTER_CLOCK(NULL, "pcie_ep_clk", pcie_ep_clk[0]),
+ _REGISTER_CLOCK(NULL, "fec_clk", enet_clk[0]),
+ _REGISTER_CLOCK(NULL, "fec_mdc_clk", enet_mdc_clk),
+ _REGISTER_CLOCK(NULL, "imx_sata_clk", sata_clk[0]),
+ _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk[0]),
+ _REGISTER_CLOCK(NULL, "usb_phy1_clk", usb_phy1_clk),
+ _REGISTER_CLOCK(NULL, "usb_phy3_clk", usb_phy3_clk),
+ _REGISTER_CLOCK(NULL, "usb_phy4_clk", usb_phy4_clk),
+ _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk),
+ _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk),
+ _REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_clk[0]),
+ _REGISTER_CLOCK(NULL, "hdmi_iahb_clk", hdmi_clk[1]),
+ _REGISTER_CLOCK(NULL, "mipi_pllref_clk", mipi_pllref_clk),
+ _REGISTER_CLOCK(NULL, "vdoa", vdoa_clk[0]),
+ _REGISTER_CLOCK(NULL, NULL, aips_tz2_clk),
+ _REGISTER_CLOCK(NULL, NULL, aips_tz1_clk),
+ _REGISTER_CLOCK(NULL, "clko_clk", clko_clk),
+ _REGISTER_CLOCK(NULL, "clko2_clk", clko2_clk),
+ _REGISTER_CLOCK(NULL, "pxp_axi", ipu2_clk),
+ _REGISTER_CLOCK(NULL, "epdc_axi", ipu2_clk),
+ _REGISTER_CLOCK(NULL, "epdc_pix", ipu2_di_clk[1]),
+ _REGISTER_CLOCK("mxs-perfmon.0", "perfmon", perfmon0_clk),
+ _REGISTER_CLOCK("mxs-perfmon.1", "perfmon", perfmon1_clk),
+ _REGISTER_CLOCK("mxs-perfmon.2", "perfmon", perfmon2_clk),
+ _REGISTER_CLOCK(NULL, "mlb150_clk", mlb150_clk),
+ _REGISTER_CLOCK(NULL, "anaclk_1", anaclk_1),
+ _REGISTER_CLOCK(NULL, "anaclk_2", anaclk_2),
+ _REGISTER_CLOCK(NULL, "apb_pclk", dummy_clk),
+};
+
+static void clk_tree_init(void)
+
+{
+ unsigned int reg;
+
+ reg = __raw_readl(MMDC_MDMISC_OFFSET);
+ if ((reg & MMDC_MDMISC_DDR_TYPE_MASK) ==
+ (0x1 << MMDC_MDMISC_DDR_TYPE_OFFSET) ||
+ cpu_is_mx6dl()) {
+ clk_set_parent(&periph_clk, &pll2_pfd_400M);
+ printk(KERN_INFO "Set periph_clk's parent to pll2_pfd_400M!\n");
+ }
+}
+
+
+int __init mx6_clocks_init(unsigned long ckil, unsigned long osc,
+ unsigned long ckih1, unsigned long ckih2)
+{
+ __iomem void *base;
+ int i, reg;
+ u32 parent_rate, rate;
+ unsigned long ipg_clk_rate, max_arm_wait_clk;
+
+ external_low_reference = ckil;
+ external_high_reference = ckih1;
+ ckih2_reference = ckih2;
+ oscillator_reference = osc;
+
+ timer_base = ioremap(GPT_BASE_ADDR, SZ_4K);
+
+ apll_base = ioremap(ANATOP_BASE_ADDR, SZ_4K);
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+ clkdev_add(&lookups[i]);
+ clk_debug_register(lookups[i].clk);
+ }
+
+ /* Lower the ipg_perclk frequency to 22MHz.
+ * I2C needs a minimum of 12.8MHz as its source
+ * to acheive 400KHz speed. IPG_PERCLK sources
+ * I2C. 22MHz when divided by the I2C divider gives the
+ * freq closest to 400KHz.
+ */
+ clk_set_rate(&ipg_perclk, 22000000);
+
+ /* Timer needs to be initialized first as the
+ * the WAIT routines use GPT counter as
+ * a delay.
+ */
+ if (mx6q_revision() == IMX_CHIP_REVISION_1_0) {
+ gpt_clk[0].parent = &ipg_perclk;
+ gpt_clk[0].get_rate = NULL;
+ } else {
+ /* Here we use OSC 24M as GPT's clock source, no need to
+ enable gpt serial clock*/
+ gpt_clk[0].secondary = NULL;
+ }
+
+ mxc_timer_init(&gpt_clk[0], timer_base, MXC_INT_GPT);
+
+ clk_tree_init();
+
+ /*
+ * Lower the ipg_perclk frequency to 22MHz.
+ * I2C needs a minimum of 12.8MHz as its source
+ * to acheive 400KHz speed. IPG_PERCLK sources
+ * I2C. 22MHz when divided by the I2C divider gives the
+ * freq closest to 400KHz.
+ */
+ //clk_set_rate(&ipg_perclk, 22000000);
+
+#ifdef CONFIG_MX6_VPU_352M
+ if (cpu_is_mx6q()) {
+ clk_set_rate(&pll2_pfd_400M, 352000000);
+ clk_set_parent(&vpu_clk[0], &pll2_pfd_400M);
+ }
+#endif
+ /* keep correct count. */
+ clk_enable(&cpu_clk);
+ clk_enable(&periph_clk);
+ /* Disable un-necessary PFDs & PLLs */
+ if (pll2_pfd_400M.usecount == 0 && cpu_is_mx6q())
+ pll2_pfd_400M.disable(&pll2_pfd_400M);
+ pll2_pfd_352M.disable(&pll2_pfd_352M);
+ pll2_pfd_594M.disable(&pll2_pfd_594M);
+
+#if !defined(CONFIG_FEC_1588)
+ pll3_pfd_454M.disable(&pll3_pfd_454M);
+ pll3_pfd_508M.disable(&pll3_pfd_508M);
+ pll3_pfd_540M.disable(&pll3_pfd_540M);
+ pll3_pfd_720M.disable(&pll3_pfd_720M);
+
+ pll3_usb_otg_main_clk.disable(&pll3_usb_otg_main_clk);
+#endif
+ pll4_audio_main_clk.disable(&pll4_audio_main_clk);
+ pll5_video_main_clk.disable(&pll5_video_main_clk);
+ pll6_mlb150_main_clk.disable(&pll6_mlb150_main_clk);
+ pll7_usb_host_main_clk.disable(&pll7_usb_host_main_clk);
+ pll8_enet_main_clk.disable(&pll8_enet_main_clk);
+
+ sata_clk[0].disable(&sata_clk[0]);
+ pcie_clk[0].disable(&pcie_clk[0]);
+
+ /* Initialize Audio and Video PLLs to valid frequency. */
+ clk_set_rate(&pll4_audio_main_clk, 176000000);
+ clk_set_rate(&pll5_video_main_clk, 650000000);
+
+ clk_set_parent(&ipu1_di_clk[0], &pll5_video_main_clk);
+ clk_set_parent(&ipu1_di_clk[1], &pll5_video_main_clk);
+ clk_set_parent(&ipu2_di_clk[0], &pll5_video_main_clk);
+ clk_set_parent(&ipu2_di_clk[1], &pll5_video_main_clk);
+
+ clk_set_parent(&emi_clk, &pll2_pfd_400M);
+#ifdef CONFIG_MX6_VPU_352M
+ clk_set_rate(&emi_clk, 176000000);
+#else
+ clk_set_rate(&emi_clk, 198000000);
+#endif
+ /*
+ * on mx6dl, 2d core clock sources from 3d shader core clock,
+ * but 3d shader clock multiplexer of mx6dl is different from
+ * mx6q. For instance the equivalent of pll2_pfd_594M on mc6q
+ * is pll2_pfd_528M on mx6dl. Make a note here.
+ */
+ clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594M);
+ clk_set_rate(&gpu3d_shader_clk, 594000000);
+ if (cpu_is_mx6dl()) {
+ /*for mx6dl, change gpu3d core clk parant to 594_PFD */
+ clk_set_parent(&gpu3d_core_clk[0], &pll2_pfd_594M);
+ clk_set_rate(&gpu3d_core_clk[0], 594000000);
+
+ /*on mx6dl, 2d core clock sources from 3d shader core clock*/
+ clk_set_parent(&gpu2d_core_clk[0], &gpu3d_shader_clk);
+ /* on mx6dl gpu3d_axi_clk source from mmdc0 directly */
+ clk_set_parent(&gpu3d_axi_clk, &mmdc_ch0_axi_clk[0]);
+ /* on mx6dl gpu2d_axi_clk source from mmdc0 directly */
+ clk_set_parent(&gpu2d_axi_clk, &mmdc_ch0_axi_clk[0]);
+
+ clk_set_rate(&pll3_pfd_540M, 540000000);
+
+ clk_set_parent(&ipu1_clk, &pll3_pfd_540M);
+ /* pxp & epdc */
+ clk_set_parent(&ipu2_clk, &pll2_pfd_400M);
+ clk_set_rate(&ipu2_clk, 200000000);
+ clk_set_parent(&axi_clk, &pll3_pfd_540M);
+ } else if (cpu_is_mx6q()) {
+ clk_set_parent(&gpu3d_core_clk[0], &mmdc_ch0_axi_clk[0]);
+ clk_set_rate(&gpu3d_core_clk[0], 528000000);
+ clk_set_parent(&ipu2_clk, &mmdc_ch0_axi_clk[0]);
+ clk_set_parent(&ipu1_clk, &mmdc_ch0_axi_clk[0]);
+ clk_set_parent(&axi_clk, &periph_clk);
+ }
+
+ /* Need to keep PLL3_PFD_540M enabled until AXI is sourced from it. */
+ clk_enable(&axi_clk);
+
+ if (cpu_is_mx6q())
+ clk_set_parent(&gpu2d_core_clk[0], &pll3_usb_otg_main_clk);
+
+ clk_set_parent(&ldb_di0_clk, &pll2_pfd_352M);
+ clk_set_parent(&ldb_di1_clk, &pll2_pfd_352M);
+
+ /* PCLK camera - J5 */
+ clk_set_parent(&clko2_clk, &osc_clk);
+ clk_set_rate(&clko2_clk, 2400000);
+
+ clk_set_parent(&clko_clk, &pll4_audio_main_clk);
+ /*
+ * FIXME: asrc needs to use asrc_serial(spdif1) clock to do sample
+ * rate convertion and this clock frequency can not be too high, set
+ * it to the minimum value 7.5Mhz to make asrc work properly.
+ */
+ clk_set_parent(&asrc_clk[1], &pll3_sw_clk);
+ clk_set_rate(&asrc_clk[1], 7500000);
+
+ /* set the GPMI clock to default frequency : 20MHz */
+ clk_set_parent(&enfc_clk, &pll2_pfd_400M);
+ clk_set_rate(&enfc_clk, enfc_clk.round_rate(&enfc_clk, 20000000));
+
+ mx6_cpu_op_init();
+ cpu_op_tbl = get_cpu_op(&cpu_op_nr);
+
+ /* Gate off all possible clocks */
+ if (mxc_jtag_enabled) {
+ __raw_writel(3 << MXC_CCM_CCGRx_CG11_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR0);
+ } else {
+ __raw_writel(1 << MXC_CCM_CCGRx_CG11_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR0);
+ }
+ if (mx6q_revision() == IMX_CHIP_REVISION_1_0)
+ /* If GPT use ipg_perclk, we need to enable gpt serial clock */
+ __raw_writel(3 << MXC_CCM_CCGRx_CG10_OFFSET | 3 << MXC_CCM_CCGRx_CG11_OFFSET, MXC_CCM_CCGR1);
+ else
+ __raw_writel(3 << MXC_CCM_CCGRx_CG10_OFFSET, MXC_CCM_CCGR1);
+ __raw_writel(1 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG11_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG10_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2);
+ __raw_writel(1 << MXC_CCM_CCGRx_CG14_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG13_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG11_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG10_OFFSET, MXC_CCM_CCGR3);
+ __raw_writel(3 << MXC_CCM_CCGRx_CG7_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG6_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG4_OFFSET, MXC_CCM_CCGR4);
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR5);
+
+ __raw_writel(0, MXC_CCM_CCGR6);
+
+ /* S/PDIF */
+ clk_set_parent(&spdif0_clk[0], &pll3_pfd_454M);
+
+ /* MLB150 SYS Clock */
+ /*
+ * In Rigel validatioin, the MLB sys_clock isn't using the
+ * right frequency after boot.
+ * In arik, the register CBCMR controls gpu2d clock, not mlb clock,
+ * mlb is sourced from axi clock.
+ * But In rigel, the axi clock is lower than in mx6q, so mlb need to
+ * find a new clock root.
+ * The gpu2d clock is the root of mlb clock in rigel.
+ * Thus we need to add below code in mx6dl.
+ * */
+ if (cpu_is_mx6dl())
+ clk_set_parent(&mlb150_clk, &pll3_sw_clk);
+
+
+ if (cpu_is_mx6dl()) {
+ /* pxp & epdc */
+ clk_set_parent(&ipu2_clk, &pll2_pfd_400M);
+ clk_set_rate(&ipu2_clk, 200000000);
+ if (epdc_enabled)
+ clk_set_parent(&ipu2_di_clk[1], &pll5_video_main_clk);
+ else
+ clk_set_parent(&ipu2_di_clk[1], &pll3_pfd_540M);
+ }
+
+ lp_high_freq = 0;
+ lp_med_freq = 0;
+ lp_audio_freq = 0;
+
+ /* Get current ARM_PODF value */
+ rate = clk_get_rate(&cpu_clk);
+ parent_rate = clk_get_rate(&pll1_sw_clk);
+ cur_arm_podf = parent_rate / rate;
+
+ /* Calculate the ARM_PODF to be applied when the system
+ * enters WAIT state.
+ * The max ARM clk is decided by the ipg_clk and has to
+ * follow the ratio of ARM_CLK:IPG_CLK of 12:5.
+ */
+ ipg_clk_rate = clk_get_rate(&ipg_clk);
+ max_arm_wait_clk = (12 * ipg_clk_rate) / 5;
+ wait_mode_arm_podf = parent_rate / max_arm_wait_clk;
+
+ /* Turn OFF all unnecessary PHYs. */
+ if (cpu_is_mx6q()) {
+ /* Turn off SATA PHY. */
+ base = ioremap(MX6Q_SATA_BASE_ADDR, SZ_8K);
+ reg = __raw_readl(base + PORT_PHY_CTL);
+ __raw_writel(reg | PORT_PHY_CTL_PDDQ_LOC, base + PORT_PHY_CTL);
+ }
+
+ /* Turn off HDMI PHY. */
+ base = ioremap(MX6Q_HDMI_ARB_BASE_ADDR, SZ_128K);
+ reg = __raw_readb(base + HDMI_PHY_CONF0);
+ __raw_writeb(reg | HDMI_PHY_CONF0_GEN2_PDDQ_MASK, base + HDMI_PHY_CONF0);
+
+ reg = __raw_readb(base + HDMI_MC_PHYRSTZ);
+ __raw_writeb(reg | HDMI_MC_PHYRSTZ_DEASSERT, base + HDMI_MC_PHYRSTZ);
+
+ iounmap(base);
+
+ base = ioremap(MX6Q_IOMUXC_BASE_ADDR, SZ_4K);
+ /* Close PLL inside SATA PHY. */
+ reg = __raw_readl(base + 0x34);
+ __raw_writel(reg | (1 << 1), base + 0x34);
+
+ /* Close PCIE PHY. */
+ reg = __raw_readl(base + 0x04);
+ reg |= (1 << 18);
+ __raw_writel(reg, base + 0x04);
+ iounmap(base);
+
+ return 0;
+
+}
diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c
new file mode 100755
index 00000000..f70563d3
--- /dev/null
+++ b/arch/arm/mach-mx6/clock_mx6sl.c
@@ -0,0 +1,4182 @@
+/*
+ * Copyright (C) 2012-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/regulator/consumer.h>
+#include <asm/div64.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+#include <mach/mxc_dvfs.h>
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "regs-anadig.h"
+
+#ifdef CONFIG_CLK_DEBUG
+#define __INIT_CLK_DEBUG(n) .name = #n,
+#else
+#define __INIT_CLK_DEBUG(n)
+#endif
+
+extern u32 arm_max_freq;
+extern int mxc_jtag_enabled;
+extern struct regulator *cpu_regulator;
+extern struct cpu_op *(*get_cpu_op)(int *op);
+extern int lp_high_freq;
+extern int lp_med_freq;
+extern int wait_mode_arm_podf;
+extern int mx6q_revision(void);
+extern int cur_arm_podf;
+
+static void __iomem *apll_base;
+static void __iomem *timer_base;
+static struct clk pll1_sys_main_clk;
+static struct clk pll2_528_bus_main_clk;
+static struct clk pll2_pfd2_400M;
+static struct clk pll3_usb_otg_main_clk;
+static struct clk pll4_audio_main_clk;
+static struct clk pll5_video_main_clk;
+static struct clk pll6_enet_main_clk; /* Essentially same as PLL8 on MX6Q/DL */
+static struct clk pll7_usb_host_main_clk;
+static struct clk usdhc3_clk;
+static struct clk ipg_clk;
+static struct clk gpt_clk[];
+static struct clk ahb_clk;
+
+static struct cpu_op *cpu_op_tbl;
+static int cpu_op_nr;
+static bool pll1_enabled;
+static bool arm_needs_pll2_400;
+static bool audio_pll_bypass;
+
+DEFINE_SPINLOCK(mx6sl_clk_lock);
+#define SPIN_DELAY 1200000 /* in nanoseconds */
+
+#define AUDIO_VIDEO_MIN_CLK_FREQ 650000000
+#define AUDIO_VIDEO_MAX_CLK_FREQ 1300000000
+#define MAX_ARM_CLK_IN_WAIT 158000000
+#define V2_TCN 0x24
+#define V2_TSTAT 0x08
+#define V2_TSTAT_ROV (1 << 5)
+#define V2_TCTL_CLK_OSC_DIV8 (5 << 6)
+#define MXC_TCTL 0x00
+#define MXC_TPRER 0x04
+#define V2_TPRER_PRE24M_OFFSET 12
+#define V2_TPRER_PRE24M_MASK 0xF
+
+/* We need to check the exp status again after timer expiration,
+ * as there might be interrupt coming between the first time exp
+ * and the time reading, then the time reading may be several ms
+ * after the exp checking due to the irq handle, so we need to
+ * check it to make sure the exp return the right value after
+ * timer expiration. */
+#define WAIT(exp, timeout) \
+({ \
+ u32 gpt_rate; \
+ u32 gpt_ticks; \
+ u32 gpt_cnt; \
+ u32 reg; \
+ int result = 1; \
+ gpt_rate = clk_get_rate(&gpt_clk[0]); \
+ gpt_ticks = timeout / (1000000000 / gpt_rate); \
+ reg = __raw_readl(timer_base + V2_TSTAT);\
+ /* Clear the GPT roll over interrupt. */ \
+ if (reg & V2_TSTAT_ROV) { \
+ __raw_writel(V2_TSTAT_ROV, timer_base + V2_TSTAT); \
+ } \
+ gpt_cnt = __raw_readl(timer_base + V2_TCN); \
+ while (!(exp)) { \
+ if ((__raw_readl(timer_base + V2_TCN) - gpt_cnt) > gpt_ticks) { \
+ if (!exp) \
+ result = 0; \
+ break; \
+ } else { \
+ reg = __raw_readl(timer_base + V2_TSTAT);\
+ if (reg & V2_TSTAT_ROV) { \
+ u32 old_cnt = gpt_cnt; \
+ /* Timer has rolled over. \
+ * Calculate the new tick count. \
+ */ \
+ gpt_cnt = __raw_readl(timer_base + V2_TCN); \
+ gpt_ticks -= (0xFFFFFFFF - old_cnt + gpt_cnt); \
+ /* Clear the roll over interrupt. */ \
+ __raw_writel(V2_TSTAT_ROV, \
+ timer_base + V2_TSTAT); \
+ } \
+ } \
+ } \
+ result; \
+})
+
+/* 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 unsigned long anaclk_1_reference, anaclk_2_reference;
+
+static void __calc_pre_post_dividers(u32 max_podf, u32 div, u32 *pre, u32 *post)
+{
+ u32 min_pre, temp_pre, old_err, err;
+
+ /* Some of the podfs are 3 bits while others are 6 bits.
+ * Handle both cases here.
+ */
+ if (div >= 512 && (max_podf == 64)) {
+ /* For pre = 3bits and podf = 6 bits, max divider is 512. */
+ *pre = 8;
+ *post = 64;
+ } else if (div >= 64 && (max_podf == 8)) {
+ /* For pre = 3bits and podf = 3 bits, max divider is 64. */
+ *pre = 8;
+ *post = 8;
+ } else if (div >= 8) {
+ /* Find the minimum pre-divider for a max podf */
+ if (max_podf == 64)
+ min_pre = (div - 1) / (1 << 6) + 1;
+ else
+ min_pre = (div - 1) / (1 << 3) + 1;
+ old_err = 8;
+ /* Now loop through to find the max pre-divider. */
+ 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;
+ }
+}
+
+static int _clk_enable(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg |= MXC_CCM_CCGRx_CG_MASK << 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 &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+}
+
+static void _clk_disable_inwait(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ reg |= 1 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+}
+
+/*
+ * 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 0;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+ if (pll == &pll1_sys_main_clk)
+ return PLL1_SYS_BASE_ADDR;
+ else if (pll == &pll2_528_bus_main_clk)
+ return PLL2_528_BASE_ADDR;
+ else if (pll == &pll3_usb_otg_main_clk)
+ return PLL3_480_USB1_BASE_ADDR;
+ else if (pll == &pll4_audio_main_clk)
+ return PLL4_AUDIO_BASE_ADDR;
+ else if (pll == &pll5_video_main_clk)
+ return PLL5_VIDEO_BASE_ADDR;
+ else if (pll == &pll6_enet_main_clk)
+ /* Essentially same as PLL8 on MX6Q/DL */
+ return PLL8_ENET_BASE_ADDR;
+ else if (pll == &pll7_usb_host_main_clk)
+ return PLL7_480_USB2_BASE_ADDR;
+ else
+ BUG();
+ return NULL;
+}
+
+
+/*
+ * For the 6-to-1 muxed input clock
+ */
+static inline u32 _get_mux6(struct clk *parent, struct clk *m0, struct clk *m1,
+ struct clk *m2, struct clk *m3, struct clk *m4,
+ struct clk *m5)
+{
+ if (parent == m0)
+ return 0;
+ else if (parent == m1)
+ return 1;
+ else if (parent == m2)
+ return 2;
+ else if (parent == m3)
+ return 3;
+ else if (parent == m4)
+ return 4;
+ else if (parent == m5)
+ return 5;
+ else
+ BUG();
+
+ 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_anaclk_1_get_rate(struct clk *clk)
+{
+ return anaclk_1_reference;
+}
+
+static int _clk_anaclk_1_set_rate(struct clk *clk, unsigned long rate)
+{
+ anaclk_1_reference = rate;
+ return 0;
+}
+
+static unsigned long _clk_anaclk_2_get_rate(struct clk *clk)
+{
+ return anaclk_2_reference;
+}
+
+static int _clk_anaclk_2_set_rate(struct clk *clk, unsigned long rate)
+{
+ anaclk_2_reference = rate;
+ return 0;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+ __INIT_CLK_DEBUG(ckih_clk)
+ .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+ __INIT_CLK_DEBUG(ckih2_clk)
+ .get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+ __INIT_CLK_DEBUG(osc_clk)
+ .get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+ __INIT_CLK_DEBUG(ckil_clk)
+ .get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk anaclk_1 = {
+ __INIT_CLK_DEBUG(anaclk_1)
+ .get_rate = _clk_anaclk_1_get_rate,
+ .set_rate = _clk_anaclk_1_set_rate,
+};
+
+static struct clk anaclk_2 = {
+ __INIT_CLK_DEBUG(anaclk_2)
+ .get_rate = _clk_anaclk_2_get_rate,
+ .set_rate = _clk_anaclk_2_set_rate,
+};
+
+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 unsigned long pfd_get_rate(struct clk *clk)
+{
+ u32 frac;
+ u64 tmp;
+ tmp = (u64)clk_get_rate(clk->parent) * 18;
+
+ frac = (__raw_readl(clk->enable_reg) >> clk->enable_shift) &
+ ANADIG_PFD_FRAC_MASK;
+
+ do_div(tmp, frac);
+
+ return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 frac;
+ u64 tmp;
+ tmp = (u64)clk_get_rate(clk->parent) * 18;
+
+ /* 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;
+ /* clear clk frac bits */
+ __raw_writel(ANADIG_PFD_FRAC_MASK << clk->enable_shift,
+ (int)clk->enable_reg + 8);
+ /* set clk frac bits */
+ __raw_writel(frac << clk->enable_shift,
+ (int)clk->enable_reg + 4);
+
+ return 0;
+}
+
+static int _clk_pfd_enable(struct clk *clk)
+{
+ /* clear clk gate bit */
+ __raw_writel((1 << (clk->enable_shift + 7)),
+ (int)clk->enable_reg + 8);
+
+ udelay(3);
+ return 0;
+}
+
+static void _clk_pfd_disable(struct clk *clk)
+{
+ /* set clk gate bit */
+ __raw_writel((1 << (clk->enable_shift + 7)),
+ (int)clk->enable_reg + 4);
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+ unsigned int reg;
+ void __iomem *pllbase;
+
+ pllbase = _get_pll_base(clk);
+
+ reg = __raw_readl(pllbase);
+ if (clk != &pll4_audio_main_clk || !audio_pll_bypass)
+ reg &= ~ANADIG_PLL_POWER_DOWN;
+
+ /* The 480MHz PLLs have the opposite definition for power bit. */
+ if (clk == &pll3_usb_otg_main_clk || clk == &pll7_usb_host_main_clk)
+ reg |= ANADIG_PLL_POWER_DOWN;
+
+ __raw_writel(reg, pllbase);
+
+ /* It will power on pll3 */
+ if (clk == &pll3_usb_otg_main_clk)
+ __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_CLR);
+
+ /* Wait for PLL to lock */
+ if (clk != &pll4_audio_main_clk || !audio_pll_bypass) {
+ if (!WAIT((__raw_readl(pllbase) & ANADIG_PLL_LOCK),
+ SPIN_DELAY))
+ panic("pll enable failed\n");
+ }
+ /* Enable the PLL output now*/
+ reg = __raw_readl(pllbase);
+
+ /* If audio PLL is set to 24MHz, leave it in bypass mode. */
+ if (clk != &pll4_audio_main_clk || !audio_pll_bypass)
+ reg &= ~ANADIG_PLL_BYPASS;
+
+ reg |= ANADIG_PLL_ENABLE;
+
+ __raw_writel(reg, pllbase);
+
+ return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+ unsigned int reg;
+ void __iomem *pllbase;
+
+ if ((arm_needs_pll2_400) && (clk == &pll2_528_bus_main_clk))
+ return;
+
+
+ pllbase = _get_pll_base(clk);
+
+ reg = __raw_readl(pllbase);
+ reg |= ANADIG_PLL_BYPASS;
+ reg |= ANADIG_PLL_POWER_DOWN;
+
+ /* The 480MHz PLLs have the opposite definition for power bit. */
+ if (clk == &pll3_usb_otg_main_clk || clk == &pll7_usb_host_main_clk)
+ reg &= ~ANADIG_PLL_POWER_DOWN;
+
+ /* PLL1, PLL2, PLL3, PLL7 should not disable the ENABLE bit.
+ * The output of these PLLs maybe used even if they are bypassed.
+ */
+ if (clk == &pll4_audio_main_clk || clk == &pll5_video_main_clk ||
+ clk == &pll6_enet_main_clk)
+ reg &= ~ANADIG_PLL_ENABLE;
+
+ __raw_writel(reg, pllbase);
+
+ /*
+ * It will power off PLL3's power, it is the TO1.1 fix
+ * Please see TKT064178 for detail.
+ */
+ if (clk == &pll3_usb_otg_main_clk)
+ __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_SET);
+}
+
+static unsigned long _clk_pll1_main_get_rate(struct clk *clk)
+{
+ unsigned int div;
+ unsigned long val;
+
+ div = __raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_SYS_DIV_SELECT_MASK;
+ val = (clk_get_rate(clk->parent) * div) / 2;
+ return val;
+}
+
+static int _clk_pll1_main_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+
+ if (rate < AUDIO_VIDEO_MIN_CLK_FREQ || rate > AUDIO_VIDEO_MAX_CLK_FREQ)
+ return -EINVAL;
+
+ div = (rate * 2) / clk_get_rate(clk->parent);
+
+ /* Update div */
+ reg = __raw_readl(PLL1_SYS_BASE_ADDR) & ~ANADIG_PLL_SYS_DIV_SELECT_MASK;
+ reg |= div;
+ __raw_writel(reg, PLL1_SYS_BASE_ADDR);
+
+ /* Wait for PLL1 to lock */
+ if (!WAIT((__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_LOCK),
+ SPIN_DELAY))
+ panic("pll1 set rate failed\n");
+
+ return 0;
+}
+
+static int _clk_pll1_main_enable(struct clk *clk)
+{
+ pll1_enabled = true;
+ _clk_pll_enable(clk);
+ return 0;
+}
+
+static void _clk_pll1_main_disable(struct clk *clk)
+{
+ unsigned int reg;
+ void __iomem *pllbase;
+
+ pll1_enabled = false;
+ pllbase = _get_pll_base(clk);
+
+ /* Set the PLL is bypass mode only.
+ * We need to be able to set the ARM_PODF bit
+ * in WAIT mode. Setting the ARM_PODF bit
+ * requires PLL1 to be enabled.
+ */
+ reg = __raw_readl(pllbase);
+ reg |= (ANADIG_PLL_BYPASS | ANADIG_PLL_POWER_DOWN);
+ __raw_writel(reg, pllbase);
+}
+
+static struct clk pll1_sys_main_clk = {
+ __INIT_CLK_DEBUG(pll1_sys_main_clk)
+ .parent = &osc_clk,
+ .get_rate = _clk_pll1_main_get_rate,
+ .set_rate = _clk_pll1_main_set_rate,
+ .enable = _clk_pll1_main_enable,
+ .disable = _clk_pll1_main_disable,
+};
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (parent == &pll1_sys_main_clk) {
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* Set the step_clk parent to be lp_apm, to save power. */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL);
+ } else {
+ /* Set STEP_CLK to be the parent*/
+ if (parent == &osc_clk) {
+ /* Set STEP_CLK to be sourced from LPAPM. */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL);
+ __raw_writel(reg, MXC_CCM_CCSR);
+ } else {
+ /* Set STEP_CLK to be sourced from PLL2-PDF (400MHz). */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_STEP_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ }
+ 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)
+{
+ return clk_get_rate(clk->parent);
+}
+
+static struct clk pll1_sw_clk = {
+ __INIT_CLK_DEBUG(pll1_sw_clk)
+ .parent = &pll1_sys_main_clk,
+ .set_parent = _clk_pll1_sw_set_parent,
+ .get_rate = _clk_pll1_sw_get_rate,
+};
+
+static unsigned long _clk_pll2_main_get_rate(struct clk *clk)
+{
+ unsigned int div;
+ unsigned long val;
+
+ div = __raw_readl(PLL2_528_BASE_ADDR) & ANADIG_PLL_528_DIV_SELECT;
+
+ if (div == 1)
+ val = clk_get_rate(clk->parent) * 22;
+
+ else
+ val = clk_get_rate(clk->parent) * 20;
+
+ return val;
+}
+
+static int _clk_pll2_main_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+
+ if (rate == 528000000)
+ div = 1;
+ else if (rate == 480000000)
+ div = 0;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(PLL2_528_BASE_ADDR);
+ reg &= ~ANADIG_PLL_528_DIV_SELECT;
+ reg |= div;
+ __raw_writel(reg, PLL2_528_BASE_ADDR);
+
+ return 0;
+}
+
+static struct clk pll2_528_bus_main_clk = {
+ __INIT_CLK_DEBUG(pll2_528_bus_main_clk)
+ .parent = &osc_clk,
+ .get_rate = _clk_pll2_main_get_rate,
+ .set_rate = _clk_pll2_main_set_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+};
+
+static void _clk_pll2_pfd2_400M_disable(struct clk *clk)
+{
+ if (!arm_needs_pll2_400)
+ _clk_pfd_disable(clk);
+}
+
+static struct clk pll2_pfd2_400M = {
+ __INIT_CLK_DEBUG(pll2_pfd2_400M)
+ .parent = &pll2_528_bus_main_clk,
+ .enable_reg = (void *)PFD_528_BASE_ADDR,
+ .enable_shift = ANADIG_PFD2_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pll2_pfd2_400M_disable,
+ .get_rate = pfd_get_rate,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll2_pfd0_352M = {
+ __INIT_CLK_DEBUG(pll2_pfd0_352M)
+ .parent = &pll2_528_bus_main_clk,
+ .enable_reg = (void *)PFD_528_BASE_ADDR,
+ .enable_shift = ANADIG_PFD0_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll2_pfd1_594M = {
+ __INIT_CLK_DEBUG(pll2_pfd1_594M)
+ .parent = &pll2_528_bus_main_clk,
+ .enable_reg = (void *)PFD_528_BASE_ADDR,
+ .enable_shift = ANADIG_PFD1_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static unsigned long _clk_pll2_200M_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk pll2_200M = {
+ __INIT_CLK_DEBUG(pll2_200M)
+ .parent = &pll2_pfd2_400M,
+ .get_rate = _clk_pll2_200M_get_rate,
+};
+
+static unsigned long _clk_pll3_usb_otg_get_rate(struct clk *clk)
+{
+ unsigned int div;
+ unsigned long val;
+
+ div = __raw_readl(PLL3_480_USB1_BASE_ADDR)
+ & ANADIG_PLL_480_DIV_SELECT_MASK;
+
+ if (div == 1)
+ val = clk_get_rate(clk->parent) * 22;
+ else
+ val = clk_get_rate(clk->parent) * 20;
+ return val;
+}
+
+static int _clk_pll3_usb_otg_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+
+ if (rate == 528000000)
+ div = 1;
+ else if (rate == 480000000)
+ div = 0;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(PLL3_480_USB1_BASE_ADDR);
+ reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK;
+ reg |= div;
+ __raw_writel(reg, PLL3_480_USB1_BASE_ADDR);
+
+ return 0;
+}
+
+
+/* same as pll3_main_clk. These two clocks should always be the same */
+static struct clk pll3_usb_otg_main_clk = {
+ __INIT_CLK_DEBUG(pll3_usb_otg_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_pll3_usb_otg_set_rate,
+ .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* for USB OTG */
+static struct clk usb_phy1_clk = {
+ __INIT_CLK_DEBUG(usb_phy1_clk)
+ .parent = &pll3_usb_otg_main_clk,
+ .set_rate = _clk_pll3_usb_otg_set_rate,
+ .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* For HSIC port 1 */
+static struct clk usb_phy3_clk = {
+ __INIT_CLK_DEBUG(usb_phy3_clk)
+ .parent = &pll3_usb_otg_main_clk,
+ .set_rate = _clk_pll3_usb_otg_set_rate,
+ .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* For HSIC port 2 */
+static struct clk usb_phy4_clk = {
+ __INIT_CLK_DEBUG(usb_phy4_clk)
+ .parent = &pll3_usb_otg_main_clk,
+ .set_rate = _clk_pll3_usb_otg_set_rate,
+ .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+static struct clk pll3_pfd2_508M = {
+ __INIT_CLK_DEBUG(pll3_pfd2_508M)
+ .parent = &pll3_usb_otg_main_clk,
+ .enable_reg = (void *)PFD_480_BASE_ADDR,
+ .enable_shift = ANADIG_PFD2_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll3_pfd3_454M = {
+ __INIT_CLK_DEBUG(pll3_pfd3_454M)
+ .parent = &pll3_usb_otg_main_clk,
+ .enable_reg = (void *)PFD_480_BASE_ADDR,
+ .enable_shift = ANADIG_PFD3_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll3_pfd0_720M = {
+ __INIT_CLK_DEBUG(pll3_pfd0_720M)
+ .parent = &pll3_usb_otg_main_clk,
+ .enable_reg = (void *)PFD_480_BASE_ADDR,
+ .enable_shift = ANADIG_PFD0_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+};
+
+static struct clk pll3_pfd1_540M = {
+ __INIT_CLK_DEBUG(pll3_pfd1_540M)
+ .parent = &pll3_usb_otg_main_clk,
+ .enable_reg = (void *)PFD_480_BASE_ADDR,
+ .enable_shift = ANADIG_PFD1_FRAC_OFFSET,
+ .enable = _clk_pfd_enable,
+ .disable = _clk_pfd_disable,
+ .set_rate = pfd_set_rate,
+ .get_rate = pfd_get_rate,
+ .round_rate = pfd_round_rate,
+ .get_rate = pfd_get_rate,
+};
+
+static unsigned long _clk_pll3_sw_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent);
+}
+
+/* same as pll3_main_clk. These two clocks should always be the same */
+static struct clk pll3_sw_clk = {
+ __INIT_CLK_DEBUG(pll3_sw_clk)
+ .parent = &pll3_usb_otg_main_clk,
+ .get_rate = _clk_pll3_sw_get_rate,
+};
+
+static unsigned long _clk_pll3_120M_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 4;
+}
+
+static struct clk pll3_120M = {
+ __INIT_CLK_DEBUG(pll3_120M)
+ .parent = &pll3_sw_clk,
+ .get_rate = _clk_pll3_120M_get_rate,
+};
+
+static unsigned long _clk_pll3_80M_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 6;
+}
+
+static struct clk pll3_80M = {
+ __INIT_CLK_DEBUG(pll3_80M)
+ .parent = &pll3_sw_clk,
+ .get_rate = _clk_pll3_80M_get_rate,
+};
+
+static unsigned long _clk_pll3_60M_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 8;
+}
+
+static struct clk pll3_60M = {
+ __INIT_CLK_DEBUG(pll3_60M)
+ .parent = &pll3_sw_clk,
+ .get_rate = _clk_pll3_60M_get_rate,
+};
+
+static unsigned long _clk_audio_video_get_rate(struct clk *clk)
+{
+ unsigned int div, mfn, mfd;
+ unsigned long rate;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+ void __iomem *pllbase;
+ unsigned int test_div_sel, control3, post_div;
+
+ pllbase = _get_pll_base(clk);
+
+ if (__raw_readl(pllbase) & ANADIG_PLL_BYPASS)
+ return 24000000;
+
+ test_div_sel = (__raw_readl(pllbase)
+ & ANADIG_PLL_AV_TEST_DIV_SEL_MASK)
+ >> ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET;
+ /* post_div = 4 - test_div_sel; */
+ if (test_div_sel == 0)
+ post_div = 4;
+ else if (test_div_sel == 1)
+ post_div = 2;
+ else
+ post_div = 1;
+
+ /* PMU_REG_MISC2 in RM */
+ if (clk == &pll5_video_main_clk) {
+ control3 = (__raw_readl(ANA_MISC2_BASE_ADDR)
+ & ANADIG_ANA_MISC2_CONTROL3_MASK)
+ >> ANADIG_ANA_MISC2_CONTROL3_OFFSET;
+ if (control3 == 1)
+ post_div *= 2;
+ else if (control3 == 3)
+ post_div *= 4;
+ }
+
+ div = __raw_readl(pllbase) & ANADIG_PLL_SYS_DIV_SELECT_MASK;
+ mfn = __raw_readl(pllbase + PLL_NUM_DIV_OFFSET);
+ mfd = __raw_readl(pllbase + PLL_DENOM_DIV_OFFSET);
+
+ rate = (parent_rate * div) + ((parent_rate / mfd) * mfn);
+ rate = rate / post_div;
+
+ return rate;
+}
+
+static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+ unsigned int mfn, mfd = 1000000;
+ s64 temp64;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+ void __iomem *pllbase;
+ unsigned long min_clk_rate, pre_div_rate;
+ u32 test_div_sel = 2;
+ u32 control3 = 0;
+
+ pllbase = _get_pll_base(clk);
+
+ if (clk == &pll4_audio_main_clk && audio_pll_bypass) {
+ reg = __raw_readl(pllbase)
+ & ~ANADIG_PLL_SYS_DIV_SELECT_MASK
+ & ~ANADIG_PLL_AV_TEST_DIV_SEL_MASK;
+ __raw_writel(reg, pllbase);
+ return 0;
+ }
+
+ if (clk == &pll4_audio_main_clk)
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4;
+ else
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 16;
+
+ if ((rate < min_clk_rate) || (rate > AUDIO_VIDEO_MAX_CLK_FREQ))
+ return -EINVAL;
+
+ pre_div_rate = rate;
+ while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) {
+ pre_div_rate *= 2;
+ /*
+ * test_div_sel field values:
+ * 2 -> Divide by 1
+ * 1 -> Divide by 2
+ * 0 -> Divide by 4
+ *
+ * control3 field values:
+ * 0 -> Divide by 1
+ * 1 -> Divide by 2
+ * 3 -> Divide by 4
+ */
+ if (test_div_sel != 0)
+ test_div_sel--;
+ else {
+ control3++;
+ if (control3 == 2)
+ control3++;
+ }
+ }
+
+ div = pre_div_rate / parent_rate;
+ temp64 = (u64) (pre_div_rate - (div * parent_rate));
+ temp64 *= mfd;
+ do_div(temp64, parent_rate);
+ mfn = temp64;
+
+ reg = __raw_readl(pllbase)
+ & ~ANADIG_PLL_SYS_DIV_SELECT_MASK
+ & ~ANADIG_PLL_AV_TEST_DIV_SEL_MASK;
+ reg |= div |
+ (test_div_sel << ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET);
+ __raw_writel(reg, pllbase);
+ __raw_writel(mfn, pllbase + PLL_NUM_DIV_OFFSET);
+ __raw_writel(mfd, pllbase + PLL_DENOM_DIV_OFFSET);
+
+ reg = __raw_readl(ANA_MISC2_BASE_ADDR)
+ & ~ANADIG_ANA_MISC2_CONTROL3_MASK;
+ reg |= control3 << ANADIG_ANA_MISC2_CONTROL3_OFFSET;
+ __raw_writel(reg, ANA_MISC2_BASE_ADDR);
+
+ return 0;
+}
+
+static unsigned long _clk_audio_video_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ unsigned long min_clk_rate;
+ unsigned int div, post_div = 1;
+ unsigned int mfn, mfd = 1000000;
+ s64 temp64;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+ unsigned long pre_div_rate;
+ u32 test_div_sel = 2;
+ u32 control3 = 0;
+ unsigned long final_rate;
+
+ if (clk == &pll4_audio_main_clk && audio_pll_bypass)
+ return 24000000;
+
+ if (clk == &pll4_audio_main_clk)
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4;
+ else
+ min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 16;
+
+ if (rate < min_clk_rate)
+ return min_clk_rate;
+
+ if (rate > AUDIO_VIDEO_MAX_CLK_FREQ)
+ return AUDIO_VIDEO_MAX_CLK_FREQ;
+
+ pre_div_rate = rate;
+ while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) {
+ pre_div_rate *= 2;
+ post_div *= 2;
+ if (test_div_sel != 0)
+ test_div_sel--;
+ else {
+ control3++;
+ if (control3 == 2)
+ control3++;
+ }
+ }
+
+ div = pre_div_rate / parent_rate;
+ temp64 = (u64) (pre_div_rate - (div * parent_rate));
+ temp64 *= mfd;
+ do_div(temp64, parent_rate);
+ mfn = temp64;
+
+ final_rate = (parent_rate * div) + ((parent_rate / mfd) * mfn);
+ final_rate = final_rate / post_div;
+
+ return final_rate;
+}
+
+static int _clk_audio_video_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ int mux;
+ void __iomem *pllbase;
+
+ if (clk == &pll4_audio_main_clk)
+ pllbase = PLL4_AUDIO_BASE_ADDR;
+ else
+ pllbase = PLL5_VIDEO_BASE_ADDR;
+
+ reg = __raw_readl(pllbase) & ~ANADIG_PLL_BYPASS_CLK_SRC_MASK;
+ mux = _get_mux6(parent, &osc_clk, &anaclk_1, &anaclk_2,
+ NULL, NULL, NULL);
+ reg |= mux << ANADIG_PLL_BYPASS_CLK_SRC_OFFSET;
+ __raw_writel(reg, pllbase);
+
+ /* Set anaclk_x as input */
+ if (parent == &anaclk_1) {
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= (ANATOP_LVDS_CLK1_IBEN_MASK &
+ ~ANATOP_LVDS_CLK1_OBEN_MASK);
+ __raw_writel(reg, ANADIG_MISC1_REG);
+ } else if (parent == &anaclk_2) {
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= (ANATOP_LVDS_CLK2_IBEN_MASK &
+ ~ANATOP_LVDS_CLK2_OBEN_MASK);
+ __raw_writel(reg, ANADIG_MISC1_REG);
+ }
+
+ return 0;
+}
+
+static struct clk pll4_audio_main_clk = {
+ __INIT_CLK_DEBUG(pll4_audio_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_audio_video_set_rate,
+ .get_rate = _clk_audio_video_get_rate,
+ .round_rate = _clk_audio_video_round_rate,
+ .set_parent = _clk_audio_video_set_parent,
+};
+
+static struct clk pll5_video_main_clk = {
+ __INIT_CLK_DEBUG(pll5_video_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_audio_video_set_rate,
+ .get_rate = _clk_audio_video_get_rate,
+ .round_rate = _clk_audio_video_round_rate,
+ .set_parent = _clk_audio_video_set_parent,
+};
+
+static struct clk pll6_enet_main_clk = {
+ __INIT_CLK_DEBUG(pll6_enet_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+};
+
+static unsigned long _clk_pll7_usb_otg_get_rate(struct clk *clk)
+{
+ unsigned int div;
+ unsigned long val;
+
+ div = __raw_readl(PLL7_480_USB2_BASE_ADDR)
+ & ANADIG_PLL_480_DIV_SELECT_MASK;
+
+ if (div == 1)
+ val = clk_get_rate(clk->parent) * 22;
+ else
+ val = clk_get_rate(clk->parent) * 20;
+ return val;
+}
+
+static int _clk_pll7_usb_otg_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div;
+
+ if (rate == 528000000)
+ div = 1;
+ else if (rate == 480000000)
+ div = 0;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(PLL7_480_USB2_BASE_ADDR);
+ reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK;
+ reg |= div;
+ __raw_writel(reg, PLL7_480_USB2_BASE_ADDR);
+
+ return 0;
+}
+
+static struct clk pll7_usb_host_main_clk = {
+ __INIT_CLK_DEBUG(pll7_usb_host_main_clk)
+ .parent = &osc_clk,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_pll7_usb_otg_set_rate,
+ .get_rate = _clk_pll7_usb_otg_get_rate,
+
+};
+
+static unsigned long _clk_arm_get_rate(struct clk *clk)
+{
+ u32 cacrr, div;
+
+ cacrr = __raw_readl(MXC_CCM_CACRR);
+ div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+extern int high_cpu_freq;
+
+static int _clk_arm_set_rate(struct clk *clk, unsigned long rate)
+{
+ int i;
+ u32 div;
+ u32 parent_rate;
+ unsigned long ipg_clk_rate, max_arm_wait_clk;
+ unsigned long flags;
+
+ for (i = 0; i < cpu_op_nr; i++) {
+ if (rate == cpu_op_tbl[i].cpu_rate)
+ break;
+ }
+ if (i >= cpu_op_nr)
+ return -EINVAL;
+
+ if (clk_get_rate(&ahb_clk) == 24000000) {
+ printk(KERN_INFO "we should not be here!!!!! AHB is at 24MHz....cpu_rate requested = %ld\n", rate);
+ dump_stack();
+ BUG();
+ }
+ spin_lock_irqsave(&mx6sl_clk_lock, flags);
+
+ if (rate <= clk_get_rate(&pll2_pfd2_400M)) {
+ /* Source pll1_sw_clk from step_clk which is sourced from
+ * PLL2_PFD2_400M.
+ */
+ if (pll1_sw_clk.parent != &pll2_pfd2_400M) {
+ if (pll2_pfd2_400M.usecount == 0) {
+ /* Check if PLL2 needs to be enabled also. */
+ if (pll2_528_bus_main_clk.usecount == 0) {
+ pll2_528_bus_main_clk.enable(&pll2_528_bus_main_clk);
+ osc_clk.usecount++;
+ }
+ /* Ensure parent usecount is
+ * also incremented.
+ */
+ pll2_528_bus_main_clk.usecount++;
+ pll2_pfd2_400M.enable(&pll2_pfd2_400M);
+ }
+ arm_needs_pll2_400 = true;
+ pll2_pfd2_400M.usecount++;
+ pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd2_400M);
+ pll1_sw_clk.parent = &pll2_pfd2_400M;
+ }
+ } else {
+ /* Make sure PLL1 is enabled */
+ if (!pll1_enabled) {
+ pll1_sys_main_clk.enable(&pll1_sys_main_clk);
+ pll1_sys_main_clk.usecount = 1;
+ osc_clk.usecount++;
+ }
+ if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) {
+ if (pll1_sw_clk.parent == &pll1_sys_main_clk) {
+ /* Change the PLL1 rate. */
+ if (pll2_pfd2_400M.usecount != 0)
+ pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd2_400M);
+ else
+ pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk);
+ }
+ pll1_sys_main_clk.set_rate(&pll1_sys_main_clk, cpu_op_tbl[i].pll_rate);
+ }
+ pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk);
+ pll1_sw_clk.parent = &pll1_sys_main_clk;
+
+ if (arm_needs_pll2_400) {
+ pll2_pfd2_400M.usecount--;
+ if (pll2_pfd2_400M.usecount == 0) {
+ pll2_pfd2_400M.disable(&pll2_pfd2_400M);
+ /* Ensure parent usecount is
+ * also decremented.
+ */
+ pll2_528_bus_main_clk.usecount--;
+ if (pll2_528_bus_main_clk.usecount == 0) {
+ pll2_528_bus_main_clk.disable(&pll2_528_bus_main_clk);
+ osc_clk.usecount--;
+ }
+ }
+ }
+ arm_needs_pll2_400 = false;
+ }
+ parent_rate = clk_get_rate(clk->parent);
+ div = parent_rate / rate;
+ /* Calculate the ARM_PODF to be applied when the system
+ * enters WAIT state.
+ * The max ARM clk is decided by the ipg_clk and has to
+ * follow the ratio of ARM_CLK:IPG_CLK of 12:5.
+ * For ex, when IPG is at 66MHz, ARM_CLK cannot be greater
+ * than 158MHz. Pre-calculate the optimal divider now.
+ */
+ ipg_clk_rate = clk_get_rate(&ipg_clk);
+ max_arm_wait_clk = (12 * ipg_clk_rate) / 5;
+ wait_mode_arm_podf = parent_rate / max_arm_wait_clk;
+
+ if (div == 0)
+ div = 1;
+
+ if ((parent_rate / div) > rate)
+ div++;
+
+ if (div > 8) {
+ spin_unlock_irqrestore(&mx6sl_clk_lock, flags);
+ return -1;
+ }
+
+ cur_arm_podf = div;
+
+ __raw_writel(div - 1, MXC_CCM_CACRR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR))
+ ;
+
+ if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) {
+ pll1_sys_main_clk.disable(&pll1_sys_main_clk);
+ pll1_sys_main_clk.usecount = 0;
+ osc_clk.usecount--;
+ }
+
+ spin_unlock_irqrestore(&mx6sl_clk_lock, flags);
+
+ return 0;
+}
+
+static struct clk cpu_clk = {
+ __INIT_CLK_DEBUG(cpu_clk)
+ .parent = &pll1_sw_clk,
+ .set_rate = _clk_arm_set_rate,
+ .get_rate = _clk_arm_get_rate,
+};
+
+static unsigned long _clk_twd_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static int _clk_ipg_perclk_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+
+ if (parent == &osc_clk)
+ reg |= 0x1 << MXC_CCM_CSCMR1_PERCLK_CLK_SEL_OFFSET;
+ else
+ reg &= ~(0x1 << MXC_CCM_CSCMR1_PERCLK_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+static struct clk twd_clk = {
+ __INIT_CLK_DEBUG(twd_clk)
+ .parent = &cpu_clk,
+ .get_rate = _clk_twd_get_rate,
+};
+
+static int _clk_periph_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ int mux;
+
+ mux = _get_mux6(parent, &pll2_528_bus_main_clk, &pll2_pfd2_400M,
+ &pll2_pfd0_352M, &pll2_200M, &pll3_sw_clk, &osc_clk);
+
+ if (mux <= 3) {
+ /* Set the pre_periph_clk multiplexer */
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+ udelay(5);
+ /* Set the periph_clk_sel multiplexer. */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ } else {
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ /* Set the periph_clk2_podf divider to divide by 1. */
+ reg &= ~MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ /* Set the periph_clk2_sel mux. */
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK;
+ reg |= ((mux - 4) << MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR))
+ ;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ /* Set periph_clk_sel to select periph_clk. */
+ reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ }
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY), SPIN_DELAY))
+ panic("_clk_periph_set_parent failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_periph_get_rate(struct clk *clk)
+{
+ u32 div = 1;
+ u32 reg;
+ unsigned long val;
+
+ if ((clk->parent == &pll3_sw_clk) || (clk->parent == &osc_clk)) {
+ reg = __raw_readl(MXC_CCM_CBCDR)
+ & MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK;
+ div = (reg >> MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET) + 1;
+ }
+ val = clk_get_rate(clk->parent) / div;
+ return val;
+}
+
+static struct clk periph_clk = {
+ __INIT_CLK_DEBUG(periph_clk)
+ .parent = &pll2_528_bus_main_clk,
+ .set_parent = _clk_periph_set_parent,
+ .get_rate = _clk_periph_get_rate,
+};
+
+static unsigned long _clk_axi_get_rate(struct clk *clk)
+{
+ u32 div, reg;
+ unsigned long val;
+
+ reg = __raw_readl(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_AXI_PODF_MASK;
+ div = (reg >> MXC_CCM_CBCDR_AXI_PODF_OFFSET);
+
+ val = clk_get_rate(clk->parent) / (div + 1);
+ return val;
+}
+
+static int _clk_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AXI_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AXI_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_AXI_PODF_BUSY), SPIN_DELAY))
+ panic("pll _clk_axi_a_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum
+ * value for the clock.
+ * Also prevent a div of 0.
+ */
+
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+
+ return parent_rate / div;
+}
+
+static int _clk_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ int mux;
+
+ mux = _get_mux6(parent, &periph_clk, &pll2_pfd2_400M,
+ &pll3_pfd1_540M, NULL, NULL, NULL);
+
+ if (mux == 0) {
+ /* Set the AXI_SEL mux */
+ reg = __raw_readl(MXC_CCM_CBCDR) & ~MXC_CCM_CBCDR_AXI_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ } else {
+ /* Set the AXI_ALT_SEL mux. */
+ reg = __raw_readl(MXC_CCM_CBCDR)
+ & ~MXC_CCM_CBCDR_AXI_ALT_SEL_MASK;
+ reg |= ((mux - 1) << MXC_CCM_CBCDR_AXI_ALT_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ /* Set the AXI_SEL mux */
+ reg = __raw_readl(MXC_CCM_CBCDR) & ~MXC_CCM_CBCDR_AXI_SEL;
+ reg |= MXC_CCM_CBCDR_AXI_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ }
+ return 0;
+}
+
+static struct clk axi_clk = {
+ __INIT_CLK_DEBUG(axi_clk)
+ .parent = &periph_clk,
+ .set_parent = _clk_axi_set_parent,
+ .set_rate = _clk_axi_set_rate,
+ .get_rate = _clk_axi_get_rate,
+ .round_rate = _clk_axi_round_rate,
+};
+
+static unsigned long _clk_ahb_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+ MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+
+ if (((parent_rate / div) != rate) || (div > 8))
+ 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);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AHB_PODF_BUSY),
+ SPIN_DELAY))
+ panic("_clk_ahb_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static struct clk ahb_clk = {
+ __INIT_CLK_DEBUG(ahb_clk)
+ .parent = &periph_clk,
+ .get_rate = _clk_ahb_get_rate,
+ .set_rate = _clk_ahb_set_rate,
+ .round_rate = _clk_ahb_round_rate,
+};
+
+static unsigned long _clk_ipg_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+ MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+
+static struct clk ipg_clk = {
+ __INIT_CLK_DEBUG(ipg_clk)
+ .parent = &ahb_clk,
+ .get_rate = _clk_ipg_get_rate,
+};
+
+static struct clk tzasc2_clk = {
+ __INIT_CLK_DEBUG(tzasc2_clk)
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk mx6fast1_clk = {
+ __INIT_CLK_DEBUG(mx6fast1_clk)
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk mx6per1_clk = {
+ __INIT_CLK_DEBUG(mx6per1_clk)
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &mx6fast1_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static int _clk_mmdc_ch1_axi_set_parent(struct clk *clk,
+ struct clk *parent)
+{
+ u32 reg;
+ int mux;
+
+ mux = _get_mux6(parent, &pll2_528_bus_main_clk, &pll2_pfd2_400M,
+ &pll2_pfd0_352M, &pll2_200M, &pll3_sw_clk, NULL);
+
+ if (mux <= 3) {
+ /* Set the pre_periph2_clk_sel multiplexer */
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ /* Set the periph2_clk_sel multiplexer. */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ } else {
+ /* Select PLL3_SW_CLK from the periph2_clk2
+ multiplexer */
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_PERIPH2_CLK2_SEL;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ /* Set the periph2_clk_sel multiplexer. */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
+ reg |= MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ }
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY), SPIN_DELAY))
+ panic("_clk_mmdc_ch1_axi_set_parent failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_mmdc_ch1_axi_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK) >>
+ MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_mmdc_ch1_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_MMDC_CH1_PODF_BUSY), SPIN_DELAY))
+ panic("_clk_mmdc_ch1_axi_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_mmdc_ch1_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static struct clk mmdc_ch1_axi_clk[] = {
+ {
+ __INIT_CLK_DEBUG(mmdc_ch1_axi_clk)
+ .id = 0,
+ .parent = &pll2_pfd2_400M,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .secondary = &mmdc_ch1_axi_clk[1],
+ .set_parent = _clk_mmdc_ch1_axi_set_parent,
+ .get_rate = _clk_mmdc_ch1_axi_get_rate,
+ .set_rate = _clk_mmdc_ch1_axi_set_rate,
+ .round_rate = _clk_mmdc_ch1_axi_round_rate,
+ },
+ {
+ .id = 1,
+ __INIT_CLK_DEBUG(mmdc_ch1_ipg_clk)
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .secondary = &tzasc2_clk,
+ },
+};
+
+#if defined(CONFIG_SDMA_IRAM) || defined(CONFIG_SND_MXC_SOC_IRAM)
+static struct clk ocram_clk = {
+ __INIT_CLK_DEBUG(ocram_clk)
+ .id = 0,
+ .parent = &axi_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+#endif
+
+static unsigned long _clk_ipg_perclk_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ div = ((reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK) >>
+ MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipg_perclk_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 64))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ reg &= ~MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+
+static unsigned long _clk_ipg_perclk_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 64)
+ div = 64;
+
+ return parent_rate / div;
+}
+
+static struct clk ipg_perclk = {
+ __INIT_CLK_DEBUG(ipg_perclk)
+ .parent = &osc_clk,
+ .set_parent = _clk_ipg_perclk_set_parent,
+ .get_rate = _clk_ipg_perclk_get_rate,
+ .set_rate = _clk_ipg_perclk_set_rate,
+ .round_rate = _clk_ipg_perclk_round_rate,
+};
+
+static struct clk spba_clk = {
+ __INIT_CLK_DEBUG(spba_clk)
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static struct clk sdma_clk[] = {
+ {
+ __INIT_CLK_DEBUG(sdma_clk)
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &sdma_clk[1],
+ },
+ {
+ .parent = &mx6per1_clk,
+#ifdef CONFIG_SDMA_IRAM
+ .secondary = &ocram_clk,
+#else
+ .secondary = &mmdc_ch1_axi_clk[0],
+#endif
+ },
+};
+
+static unsigned long mx6_timer_rate(void)
+{
+ u32 parent_rate = clk_get_rate(&osc_clk);
+
+ u32 reg = __raw_readl(timer_base + MXC_TCTL);
+ u32 div;
+
+ if ((reg & V2_TCTL_CLK_OSC_DIV8) == V2_TCTL_CLK_OSC_DIV8) {
+ if (cpu_is_mx6q())
+ /* For MX6Q, only options are 24MHz or 24MHz/8*/
+ return parent_rate / 8;
+ else {
+ /* For MX6DLS and MX6Solo, the rate is based on the
+ * divider value set in prescalar register. */
+ div = __raw_readl(timer_base + MXC_TPRER);
+ div = (div >> V2_TPRER_PRE24M_OFFSET) &
+ V2_TPRER_PRE24M_MASK;
+ return parent_rate / (div + 1);
+ }
+ }
+ return 0;
+}
+
+static unsigned long _clk_gpt_get_rate(struct clk *clk)
+{
+ unsigned long rate;
+
+ if (mx6q_revision() == IMX_CHIP_REVISION_1_0)
+ return clk_get_rate(clk->parent);
+
+ rate = mx6_timer_rate();
+ if (!rate)
+ return clk_get_rate(clk->parent);
+
+ return rate;
+}
+
+static struct clk gpt_clk[] = {
+ {
+ __INIT_CLK_DEBUG(gpt_clk)
+ .parent = &osc_clk,
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .get_rate = _clk_gpt_get_rate,
+ },
+};
+
+static unsigned long _clk_iim_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent);
+}
+
+static struct clk iim_clk = {
+ __INIT_CLK_DEBUG(iim_clk)
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .disable = _clk_disable,
+ .get_rate = _clk_iim_get_rate,
+};
+
+static struct clk i2c_clk[] = {
+ {
+ __INIT_CLK_DEBUG(i2c_clk_0)
+ .id = 0,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(i2c_clk_1)
+ .id = 1,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(i2c_clk_2)
+ .id = 2,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static int _clk_ipu1_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CSCDR3)
+ & ~MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &osc_clk,
+ &pll2_pfd2_400M, &pll3_120M, &pll3_pfd1_540M, NULL, NULL);
+
+ reg |= (mux << MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR3);
+
+ return 0;
+}
+
+static unsigned long _clk_ipu1_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ div = ((reg & MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK) >>
+ MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ reg &= ~MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR3);
+
+ return 0;
+}
+
+static unsigned long _clk_ipu_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static struct clk ipu1_clk = {
+ __INIT_CLK_DEBUG(csi_clk)
+ .parent = &osc_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ipu1_set_parent,
+ .round_rate = _clk_ipu_round_rate,
+ .set_rate = _clk_ipu1_set_rate,
+ .get_rate = _clk_ipu1_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_ipu2_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CSCDR3)
+ & ~MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+ &pll2_pfd2_400M, &pll3_sw_clk, &pll3_pfd1_540M, NULL, NULL);
+
+ reg |= (mux << MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR3);
+
+ return 0;
+}
+
+static unsigned long _clk_ipu2_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ div = ((reg & MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK) >>
+ MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ reg &= ~MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR3);
+
+ return 0;
+}
+
+static struct clk ipu2_clk = {
+ __INIT_CLK_DEBUG(elcdif_axi_clk)
+ .parent = &pll2_pfd2_400M,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ipu2_set_parent,
+ .round_rate = _clk_ipu_round_rate,
+ .set_rate = _clk_ipu2_set_rate,
+ .get_rate = _clk_ipu2_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk usdhc_dep_clk = {
+ .parent = &mmdc_ch1_axi_clk[0],
+ .secondary = &mx6per1_clk,
+ };
+
+static unsigned long _clk_usdhc_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_usdhc1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC1_CLK_SEL;
+
+ if (parent == &pll2_pfd0_352M)
+ reg |= (MXC_CCM_CSCMR1_USDHC1_CLK_SEL);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_usdhc1_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USDHC1_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static struct clk usdhc1_clk = {
+ __INIT_CLK_DEBUG(usdhc1_clk)
+ .id = 0,
+ .parent = &pll2_pfd2_400M,
+ .secondary = &usdhc_dep_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_usdhc1_set_parent,
+ .round_rate = _clk_usdhc_round_rate,
+ .set_rate = _clk_usdhc1_set_rate,
+ .get_rate = _clk_usdhc1_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_usdhc2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC2_CLK_SEL;
+
+ if (parent == &pll2_pfd0_352M)
+ reg |= (MXC_CCM_CSCMR1_USDHC2_CLK_SEL);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_usdhc2_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USDHC2_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static struct clk usdhc2_clk = {
+ __INIT_CLK_DEBUG(usdhc2_clk)
+ .id = 1,
+ .parent = &pll2_pfd2_400M,
+ .secondary = &usdhc_dep_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_usdhc2_set_parent,
+ .round_rate = _clk_usdhc_round_rate,
+ .set_rate = _clk_usdhc2_set_rate,
+ .get_rate = _clk_usdhc2_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_usdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC3_CLK_SEL;
+
+ if (parent == &pll2_pfd0_352M)
+ reg |= (MXC_CCM_CSCMR1_USDHC3_CLK_SEL);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_usdhc3_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc3_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USDHC3_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+
+static struct clk usdhc3_clk = {
+ __INIT_CLK_DEBUG(usdhc3_clk)
+ .id = 2,
+ .parent = &pll2_pfd2_400M,
+ .secondary = &usdhc_dep_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_usdhc3_set_parent,
+ .round_rate = _clk_usdhc_round_rate,
+ .set_rate = _clk_usdhc3_set_rate,
+ .get_rate = _clk_usdhc3_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_usdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC4_CLK_SEL;
+
+ if (parent == &pll2_pfd0_352M)
+ reg |= (MXC_CCM_CSCMR1_USDHC4_CLK_SEL);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_usdhc4_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc4_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USDHC4_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+
+static struct clk usdhc4_clk = {
+ __INIT_CLK_DEBUG(usdhc4_clk)
+ .id = 3,
+ .parent = &pll2_pfd2_400M,
+ .secondary = &usdhc_dep_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_usdhc4_set_parent,
+ .round_rate = _clk_usdhc_round_rate,
+ .set_rate = _clk_usdhc4_set_rate,
+ .get_rate = _clk_usdhc4_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_ssi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static unsigned long _clk_ssi1_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+
+ prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK)
+ >> MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK)
+ >> MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~(MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK |
+ MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+static unsigned long _clk_extern_audio_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_extern_audio_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2) & ~MXC_CCM_CSCMR2_ESAI_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll4_audio_main_clk, &pll3_pfd2_508M,
+ &pll3_pfd3_454M, &pll3_sw_clk, NULL, NULL);
+ reg |= mux << MXC_CCM_CSCMR2_ESAI_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_extern_audio_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+
+ pred = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK)
+ >> MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK)
+ >> MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int _clk_extern_audio_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if (rate == 24000000 && clk->parent == &pll4_audio_main_clk) {
+ /* If the requested rate is 24MHz,
+ * set the PLL4 to bypass mode.
+ */
+ audio_pll_bypass = 1;
+ pre = post = 1;
+ } else {
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 64)
+ return -EINVAL;
+
+ audio_pll_bypass = 0;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+ }
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~(MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK|
+ MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+static struct clk extern_audio_clk = {
+ __INIT_CLK_DEBUG(extern_audio_clk)
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_rate = _clk_extern_audio_set_rate,
+ .get_rate = _clk_extern_audio_get_rate,
+ .set_parent = _clk_extern_audio_set_parent,
+ .round_rate = _clk_extern_audio_round_rate,
+};
+
+
+static int _clk_ssi1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1)
+ & ~MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll3_pfd2_508M, &pll3_pfd3_454M,
+ &pll4_audio_main_clk, NULL, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi1_clk[] = {
+ {
+ __INIT_CLK_DEBUG(ssi1_clk)
+ .parent = &pll3_pfd2_508M,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ssi1_set_parent,
+ .set_rate = _clk_ssi1_set_rate,
+ .round_rate = _clk_ssi_round_rate,
+ .get_rate = _clk_ssi1_get_rate,
+ .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#ifndef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &mmdc_ch1_axi_clk[0],
+#else
+ .secondary = &ocram_clk,
+#endif
+ },
+};
+
+static unsigned long _clk_ssi2_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+
+ prediv = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK)
+ >> MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK)
+ >> MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ reg &= ~(MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK |
+ MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ return 0;
+}
+
+
+static int _clk_ssi2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1)
+ & ~MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll3_pfd2_508M, &pll3_pfd3_454M,
+ &pll4_audio_main_clk, NULL, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi2_clk[] = {
+ {
+ __INIT_CLK_DEBUG(ssi2_clk)
+ .parent = &pll3_pfd2_508M,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ssi2_set_parent,
+ .set_rate = _clk_ssi2_set_rate,
+ .round_rate = _clk_ssi_round_rate,
+ .get_rate = _clk_ssi2_get_rate,
+ .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#ifndef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &mmdc_ch1_axi_clk[0],
+#else
+ .secondary = &ocram_clk,
+#endif
+ },
+};
+
+static unsigned long _clk_ssi3_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+
+ prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK)
+ >> MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK)
+ >> MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi3_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~(MXC_CCM_CS1CDR_SSI3_CLK_PODF_MASK|
+ MXC_CCM_CS1CDR_SSI3_CLK_PRED_MASK);
+ reg |= (post - 1) << MXC_CCM_CS1CDR_SSI3_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS1CDR_SSI3_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+
+static int _clk_ssi3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI3_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll3_pfd2_508M, &pll3_pfd3_454M,
+ &pll4_audio_main_clk, NULL, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi3_clk[] = {
+ {
+ __INIT_CLK_DEBUG(ssi3_clk)
+ .parent = &pll3_pfd2_508M,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ssi3_set_parent,
+ .set_rate = _clk_ssi3_set_rate,
+ .round_rate = _clk_ssi_round_rate,
+ .get_rate = _clk_ssi3_get_rate,
+ .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#ifndef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &mmdc_ch1_axi_clk[0],
+#else
+ .secondary = &ocram_clk,
+#endif
+ },
+};
+
+static unsigned long _clk_epdc_lcdif_pix_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ /* Round to closest divisor */
+ if ((parent_rate % rate) > (rate / 2))
+ div++;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 64)
+ div = 64;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static unsigned long _clk_pxp_epdc_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ /* Round to closest divisor */
+ if ((parent_rate % rate) > (rate / 2))
+ div++;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static unsigned long _clk_pxp_axi_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR);
+
+ div = ((reg & MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK) >>
+ MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_pxp_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR);
+ reg &= ~MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+ return 0;
+}
+
+static int _clk_pxp_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR)
+ & ~MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+ &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+ &pll2_pfd0_352M, &pll2_pfd2_400M, &pll3_pfd1_540M);
+ reg |= (mux << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+ /* Derive clock from divided pre-muxed pxp_axi clock.*/
+ mux = 0;
+ reg = __raw_readl(MXC_CCM_CHSCCDR)
+ & ~MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK;
+ __raw_writel(reg | (mux << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET),
+ MXC_CCM_CHSCCDR);
+
+ return 0;
+}
+
+static unsigned long _clk_epdc_axi_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR);
+
+ div = ((reg & MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK)
+ >> MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_epdc_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR);
+ reg &= ~MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+ return 0;
+}
+
+static int _clk_epdc_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CHSCCDR)
+ & ~MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+ &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+ &pll2_pfd0_352M, &pll2_pfd2_400M, &pll3_pfd1_540M);
+ reg |= (mux << MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+ /* Derive clock from divided pre-muxed ipu1_di0 clock.*/
+ mux = 0;
+ reg = __raw_readl(MXC_CCM_CHSCCDR)
+ & ~MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_MASK;
+ __raw_writel(reg | (mux << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET),
+ MXC_CCM_CHSCCDR);
+
+ return 0;
+}
+
+static struct clk pxp_axi_clk = {
+ __INIT_CLK_DEBUG(pxp_axi_clk)
+ .id = 0,
+ .parent = &pll5_video_main_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_pxp_axi_set_parent,
+ .set_rate = _clk_pxp_axi_set_rate,
+ .round_rate = _clk_pxp_epdc_axi_round_rate,
+ .get_rate = _clk_pxp_axi_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk epdc_axi_clk = {
+ __INIT_CLK_DEBUG(epdc_axi_clk)
+ .id = 0,
+ .parent = &pll5_video_main_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_epdc_axi_set_parent,
+ .set_rate = _clk_epdc_axi_set_rate,
+ .round_rate = _clk_pxp_epdc_axi_round_rate,
+ .get_rate = _clk_epdc_axi_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_lcdif_pix_get_rate(struct clk *clk)
+{
+ u32 reg, pre, post;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+
+ pre = ((reg & MXC_CCM_CSCDR2_IPU2_DI0_PODF_MASK) >>
+ MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET) + 1;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ post = ((reg & MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK) >>
+ MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (pre * post);
+}
+
+static int _clk_lcdif_pix_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 64))
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ reg &= ~MXC_CCM_CSCDR2_IPU2_DI0_PODF_MASK;
+ reg |= (pre - 1) << MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ /*
+ * fixup:
+ * Bits 22 and 21 of the divide value are inverted before
+ * going into the divider port.
+ */
+ post = (post - 1) ^ 0x6;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK;
+ reg |= post << MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static int _clk_lcdif_pix_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2)
+ & ~MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+ &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+ &pll2_pfd0_352M, &pll3_pfd0_720M, &pll3_pfd1_540M);
+ reg |= (mux << MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ /* Derive clock from divided pre-muxed lcdif_pix clock.*/
+ mux = 0;
+ reg = __raw_readl(MXC_CCM_CSCDR2)
+ & ~MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_MASK;
+ __raw_writel(reg | (mux << MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_OFFSET),
+ MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static unsigned long _clk_epdc_pix_get_rate(struct clk *clk)
+{
+ u32 reg, pre, post;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+
+ pre = ((reg & MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK) >>
+ MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET) + 1;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ post = ((reg & MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK) >>
+ MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET) + 1;
+
+
+ return clk_get_rate(clk->parent) / (pre * post);
+}
+
+static int _clk_epdc_pix_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+
+ if (((parent_rate / div) != rate) || (div > 64))
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ reg &= ~MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK;
+ reg |= (pre - 1) << MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK;
+ reg |= (post - 1) << MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static int _clk_epdc_pix_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2)
+ & ~MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+ &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+ &pll2_pfd0_352M, &pll2_pfd1_594M, &pll3_pfd1_540M);
+ reg |= (mux << MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static struct clk lcdif_pix_clk = {
+ __INIT_CLK_DEBUG(lcdif_pix_clk)
+ .id = 0,
+ .parent = &pll5_video_main_clk,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_lcdif_pix_set_parent,
+ .set_rate = _clk_lcdif_pix_set_rate,
+ .round_rate = _clk_epdc_lcdif_pix_round_rate,
+ .get_rate = _clk_lcdif_pix_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk epdc_pix_clk = {
+ __INIT_CLK_DEBUG(epdc_pix_clk)
+ .id = 0,
+ .parent = &pll3_pfd1_540M,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_epdc_pix_set_parent,
+ .set_rate = _clk_epdc_pix_set_rate,
+ .round_rate = _clk_epdc_lcdif_pix_round_rate,
+ .get_rate = _clk_epdc_pix_get_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+static unsigned long _clk_spdif_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_spdif0_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CDCDR)
+ & ~MXC_CCM_CDCDR_SPDIF0_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll4_audio_main_clk,
+ &pll3_pfd2_508M, &pll3_pfd3_454M,
+ &pll3_sw_clk, NULL, NULL);
+ reg |= mux << MXC_CCM_CDCDR_SPDIF0_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ return 0;
+}
+
+static unsigned long _clk_spdif0_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CDCDR);
+
+ pred = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK)
+ >> MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK)
+ >> MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int _clk_spdif0_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 64)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~(MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK|
+ MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ return 0;
+}
+
+static struct clk spdif0_clk[] = {
+ {
+ __INIT_CLK_DEBUG(spdif0_clk_0)
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &spdif0_clk[1],
+ .set_rate = _clk_spdif0_set_rate,
+ .get_rate = _clk_spdif0_get_rate,
+ .set_parent = _clk_spdif0_set_parent,
+ .round_rate = _clk_spdif_round_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ __INIT_CLK_DEBUG(spdif0_clk_1)
+ .id = 1,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ },
+};
+
+static int _clk_ecspi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2) & ~MXC_CCM_CSCDR2_ECSPI_CLK_SEL_MASK;
+
+ if (parent == &pll3_60M)
+ mux = 0;
+ else
+ mux = 1; /* osc */
+
+ reg |= mux << MXC_CCM_CSCDR2_ECSPI_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static int _clk_fec_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int reg, div = 1;
+
+ 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;
+ }
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg &= ~ANADIG_PLL_ENET_DIV_SELECT_MASK;
+ reg |= (div << ANADIG_PLL_ENET_DIV_SELECT_OFFSET);
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+
+ return 0;
+}
+
+static unsigned long _clk_fec_get_rate(struct clk *clk)
+{
+ unsigned int div;
+
+ div = (__raw_readl(PLL8_ENET_BASE_ADDR))
+ & ANADIG_PLL_ENET_DIV_SELECT_MASK;
+
+ switch (div) {
+ case 0:
+ div = 20;
+ break;
+ case 1:
+ div = 10;
+ break;
+ case 3:
+ div = 5;
+ break;
+ case 4:
+ div = 4;
+ break;
+ }
+
+ return 500000000 / div;
+}
+
+static int _clk_fec_enable(struct clk *clk)
+{
+ unsigned int reg;
+
+ /* Enable ENET ref clock */
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg &= ~ANADIG_PLL_BYPASS;
+ reg |= ANADIG_PLL_ENABLE;
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+
+ _clk_enable(clk);
+ return 0;
+}
+
+static void _clk_fec_disable(struct clk *clk)
+{
+ unsigned int reg;
+
+ _clk_disable(clk);
+
+ /* Enable ENET ref clock */
+ reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+ reg |= ANADIG_PLL_BYPASS;
+ reg &= ~ANADIG_PLL_ENABLE;
+ __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+}
+
+static struct clk fec_clk[] = {
+ {
+ __INIT_CLK_DEBUG(fec_clk)
+ .id = 0,
+ .parent = &pll6_enet_main_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_fec_enable,
+ .disable = _clk_fec_disable,
+ .set_rate = _clk_fec_set_rate,
+ .get_rate = _clk_fec_get_rate,
+ .secondary = &fec_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &mmdc_ch1_axi_clk[0],
+ .secondary = &mx6per1_clk,
+ },
+};
+
+static unsigned long _clk_fec_mdc_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent);
+}
+
+static struct clk fec_mdc_clk = {
+ __INIT_CLK_DEBUG(fec_mdc_clk)
+ .parent = &ipg_clk,
+ .get_rate = _clk_fec_mdc_get_rate,
+};
+
+static struct clk ecspi_clk[] = {
+ {
+ __INIT_CLK_DEBUG(ecspi0_clk)
+ .id = 0,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ecspi_set_parent,
+ },
+ {
+ __INIT_CLK_DEBUG(ecspi1_clk)
+ .id = 1,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ecspi_set_parent,
+ },
+ {
+ __INIT_CLK_DEBUG(ecspi2_clk)
+ .id = 2,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ecspi_set_parent,
+ },
+ {
+ __INIT_CLK_DEBUG(ecspi3_clk)
+ .id = 3,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ecspi_set_parent,
+ },
+ {
+ __INIT_CLK_DEBUG(ecspi4_clk)
+ .id = 4,
+ .parent = &pll3_60M,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_parent = _clk_ecspi_set_parent,
+ },
+};
+
+static unsigned long _clk_emi_slow_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_emi_slow_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1)
+ & ~MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK;
+
+ mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk,
+ &pll2_pfd2_400M, &pll3_pfd0_720M, NULL, NULL);
+ reg |= (mux << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET);
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_emi_slow_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ div = ((reg & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK) >>
+ MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_emi_slow_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk emi_slow_clk = {
+ __INIT_CLK_DEBUG(emi_slow_clk)
+ .id = 0,
+ .parent = &axi_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .set_rate = _clk_emi_slow_set_rate,
+ .get_rate = _clk_emi_slow_get_rate,
+ .round_rate = _clk_emi_slow_round_rate,
+ .set_parent = _clk_emi_slow_set_parent,
+};
+
+static unsigned long _clk_uart_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 64)
+ div = 64;
+
+ return parent_rate / div;
+}
+
+static int _clk_uart_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 64))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1) & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
+ reg |= ((div - 1) << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static unsigned long _clk_uart_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ unsigned long val;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1) & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
+ div = (reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
+ val = clk_get_rate(clk->parent) / div;
+
+ /* If the parent is OSC, there is an in-built divide by 6. */
+ if (clk->parent == &osc_clk)
+ val = val / 6;
+
+ return val;
+}
+
+static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1) & ~MXC_CCM_CSCDR1_UART_CLK_SEL_MASK;
+
+ if (parent == &osc_clk)
+ mux = 1;
+ else
+ mux = 0; /* osc */
+
+ reg |= mux << MXC_CCM_CSCDR1_UART_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static struct clk uart_clk[] = {
+ {
+ __INIT_CLK_DEBUG(uart_clk)
+ .id = 0,
+ .parent = &pll3_80M,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &uart_clk[1],
+ .set_rate = _clk_uart_set_rate,
+ .get_rate = _clk_uart_get_rate,
+ .round_rate = _clk_uart_round_rate,
+ .set_parent = _clk_uart_set_parent,
+ },
+ {
+ __INIT_CLK_DEBUG(uart_serial_clk)
+ .id = 1,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk aips_tz2_clk = {
+ __INIT_CLK_DEBUG(aips_tz2_clk)
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk aips_tz1_clk = {
+ __INIT_CLK_DEBUG(aips_tz1_clk)
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+/* Raster 2D and OpenVG GPU core share the same clock gate bits,
+ * so we abstract gpu2d_core_clk to handle clock gate enabling
+ * and disabling for both 2D core. These two 2D core have
+ * different multiplexer, so gpu2d_axi_clk and openvg_axi_clk
+ * are provided for them to control the multiplexer individually.
+*/
+static struct clk gpu2d_core_clk = {
+ __INIT_CLK_DEBUG(gpu2d_core_clk)
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_openvg_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_openvg_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CBCMR)
+ & ~MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll3_pfd1_540M,
+ &pll3_usb_otg_main_clk,
+ &pll2_528_bus_main_clk, &pll2_pfd2_400M, NULL, NULL);
+ reg |= (mux << MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static unsigned long _clk_openvg_axi_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ div = ((reg & MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK) >>
+ MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_openvg_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (div > 8)
+ div = 8;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk openvg_axi_clk = {
+ __INIT_CLK_DEBUG(openvg_axi_clk)
+ .parent = &pll2_528_bus_main_clk,
+ .set_parent = _clk_openvg_axi_set_parent,
+ .set_rate = _clk_openvg_axi_set_rate,
+ .get_rate = _clk_openvg_axi_get_rate,
+ .round_rate = _clk_openvg_axi_round_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_gpu2d_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_gpu2d_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CBCMR) &
+ ~MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &pll2_pfd2_400M, &pll3_usb_otg_main_clk,
+ &pll3_pfd1_540M, &pll2_528_bus_main_clk, NULL, NULL);
+ reg |= (mux << MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static unsigned long _clk_gpu2d_axi_get_rate(struct clk *clk)
+{
+ u32 reg, div = 1;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ div = ((reg & MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK) >>
+ MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_gpu2d_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg &= ~MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk gpu2d_axi_clk = {
+ __INIT_CLK_DEBUG(gpu2d_axi_clk)
+ .parent = &pll2_528_bus_main_clk,
+ .set_parent = _clk_gpu2d_axi_set_parent,
+ .set_rate = _clk_gpu2d_axi_set_rate,
+ .get_rate = _clk_gpu2d_axi_get_rate,
+ .round_rate = _clk_gpu2d_axi_round_rate,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+/* set the parent by the ipcg table */
+
+static struct clk pwm_clk[] = {
+ {
+ __INIT_CLK_DEBUG(pwm_clk_0)
+ .parent = &ipg_perclk,
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(pwm_clk_1)
+ .parent = &ipg_perclk,
+ .id = 1,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(pwm_clk_2)
+ .parent = &ipg_perclk,
+ .id = 2,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(pwm_clk_3)
+ .parent = &ipg_perclk,
+ .id = 3,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk usboh3_clk[] = {
+ {
+ __INIT_CLK_DEBUG(usboh3_clk)
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &usboh3_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &mmdc_ch1_axi_clk[0],
+ .secondary = &mx6per1_clk,
+ },
+};
+
+static int _clk_enable1(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_disable1(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(1 << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 sel, reg;
+
+ if (parent == &pll3_usb_otg_main_clk)
+ sel = 0;
+ else if (parent == &pll2_528_bus_main_clk)
+ sel = 1;
+ else if (parent == &pll1_sys_main_clk)
+ sel = 2;
+ else if (parent == &pll5_video_main_clk)
+ sel = 3;
+ else if (parent == &axi_clk)
+ sel = 5;
+ else if (parent == &pxp_axi_clk)
+ sel = 7;
+ else if (parent == &epdc_axi_clk)
+ sel = 8;
+ else if (parent == &lcdif_pix_clk)
+ sel = 9;
+ else if (parent == &epdc_pix_clk)
+ sel = 10;
+ else if (parent == &ahb_clk)
+ sel = 11;
+ else if (parent == &ipg_clk)
+ sel = 12;
+ else if (parent == &ipg_perclk)
+ sel = 13;
+ else if (parent == &ckil_clk)
+ sel = 14;
+ else if (parent == &pll4_audio_main_clk)
+ sel = 15;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKOL_SEL_MASK;
+ reg |= sel << MXC_CCM_CCOSR_CKOL_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static unsigned long _clk_clko_get_rate(struct clk *clk)
+{
+ u32 reg = __raw_readl(MXC_CCM_CCOSR);
+ u32 div = ((reg & MXC_CCM_CCOSR_CKOL_DIV_MASK) >>
+ MXC_CCM_CCOSR_CKOL_DIV_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKOL_DIV_MASK;
+ reg |= (div - 1) << MXC_CCM_CCOSR_CKOL_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static unsigned long _clk_clko_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (div > 8)
+ div = 8;
+ return parent_rate / div;
+}
+
+static int _clk_clko2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 sel, reg;
+
+ if (parent == &mmdc_ch1_axi_clk[0])
+ sel = 0;
+ else if (parent == &usdhc4_clk)
+ sel = 2;
+ else if (parent == &usdhc1_clk)
+ sel = 3;
+ else if (parent == &ecspi_clk[0])
+ sel = 6;
+ else if (parent == &usdhc3_clk)
+ sel = 8;
+ else if (parent == &ipu1_clk)
+ sel = 11;
+ else if (parent == &ipu2_clk)
+ sel = 12;
+
+ else if (parent == &osc_clk)
+ sel = 14;
+ else if (parent == &usdhc2_clk)
+ sel = 17;
+ else if (parent == &ssi1_clk[0])
+ sel = 18;
+ else if (parent == &ssi2_clk[0])
+ sel = 19;
+ else if (parent == &ssi3_clk[0])
+ sel = 20;
+ else if (parent == &uart_clk[0])
+ sel = 28;
+ else if (parent == &spdif0_clk[0])
+ sel = 29;
+ else if (parent == &spdif0_clk[1])
+ sel = 30;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKO2_SEL_MASK;
+ reg |= sel << MXC_CCM_CCOSR_CKO2_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static unsigned long _clk_clko2_get_rate(struct clk *clk)
+{
+ u32 reg = __raw_readl(MXC_CCM_CCOSR);
+ u32 div = ((reg & MXC_CCM_CCOSR_CKO2_DIV_MASK) >>
+ MXC_CCM_CCOSR_CKO2_DIV_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_clko2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKO2_DIV_MASK;
+ reg |= (div - 1) << MXC_CCM_CCOSR_CKO2_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static struct clk clko_clk = {
+ __INIT_CLK_DEBUG(clko_clk)
+ .parent = &pll2_528_bus_main_clk,
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCOSR,
+ .enable_shift = MXC_CCM_CCOSR_CKOL_EN_OFFSET,
+ .disable = _clk_disable1,
+ .set_parent = _clk_clko_set_parent,
+ .set_rate = _clk_clko_set_rate,
+ .get_rate = _clk_clko_get_rate,
+ .round_rate = _clk_clko_round_rate,
+};
+
+static struct clk clko2_clk = {
+ __INIT_CLK_DEBUG(clko2_clk)
+ .parent = &usdhc4_clk,
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCOSR,
+ .enable_shift = MXC_CCM_CCOSR_CKO2_EN_OFFSET,
+ .disable = _clk_disable1,
+ .set_parent = _clk_clko2_set_parent,
+ .set_rate = _clk_clko2_set_rate,
+ .get_rate = _clk_clko2_get_rate,
+ .round_rate = _clk_clko_round_rate,
+};
+
+static struct clk perfmon0_clk = {
+ __INIT_CLK_DEBUG(perfmon0_clk)
+ .parent = &mmdc_ch1_axi_clk[0],
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable1,
+};
+
+static struct clk perfmon1_clk = {
+ __INIT_CLK_DEBUG(perfmon1_clk)
+ .parent = &ipu1_clk,
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable1,
+};
+
+static struct clk perfmon2_clk = {
+ __INIT_CLK_DEBUG(perfmon2_clk)
+ .parent = &mmdc_ch1_axi_clk[0],
+ .enable = _clk_enable1,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .disable = _clk_disable1,
+};
+
+static struct clk dummy_clk = {
+ .id = 0,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ }
+
+static struct clk_lookup lookups[] = {
+ _REGISTER_CLOCK(NULL, "osc", osc_clk),
+ _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+ _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk),
+ _REGISTER_CLOCK(NULL, "ckil", ckil_clk),
+ _REGISTER_CLOCK(NULL, "pll1_main_clk", pll1_sys_main_clk),
+ _REGISTER_CLOCK(NULL, "pll1_sw_clk", pll1_sw_clk),
+ _REGISTER_CLOCK(NULL, "pll2", pll2_528_bus_main_clk),
+ _REGISTER_CLOCK(NULL, "pll2_pfd_400M", pll2_pfd2_400M),
+ _REGISTER_CLOCK(NULL, "pll2_pfd0_352M", pll2_pfd0_352M),
+ _REGISTER_CLOCK(NULL, "pll2_pfd1_594M", pll2_pfd1_594M),
+ _REGISTER_CLOCK(NULL, "pll2_200M", pll2_200M),
+ _REGISTER_CLOCK(NULL, "pll3_main_clk", pll3_usb_otg_main_clk),
+ _REGISTER_CLOCK(NULL, "pll3_pfd2_508M", pll3_pfd2_508M),
+ _REGISTER_CLOCK(NULL, "pll3_pfd3_454M", pll3_pfd3_454M),
+ _REGISTER_CLOCK(NULL, "pll3_pfd0_720M", pll3_pfd0_720M),
+ _REGISTER_CLOCK(NULL, "pll3_pfd_540M", pll3_pfd1_540M),
+ _REGISTER_CLOCK(NULL, "pll3_sw_clk", pll3_sw_clk),
+ _REGISTER_CLOCK(NULL, "pll3_120M", pll3_120M),
+ _REGISTER_CLOCK(NULL, "pll3_80M", pll3_80M),
+ _REGISTER_CLOCK(NULL, "pll3_60M", pll3_60M),
+ _REGISTER_CLOCK(NULL, "pll4", pll4_audio_main_clk),
+ _REGISTER_CLOCK(NULL, "pll5", pll5_video_main_clk),
+ _REGISTER_CLOCK(NULL, "pll6", pll6_enet_main_clk),
+ _REGISTER_CLOCK(NULL, "extern_audio_clk", extern_audio_clk),
+ _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk),
+ _REGISTER_CLOCK("smp_twd", NULL, twd_clk),
+ _REGISTER_CLOCK(NULL, "periph_clk", periph_clk),
+ _REGISTER_CLOCK(NULL, "axi_clk", axi_clk),
+ _REGISTER_CLOCK(NULL, "mmdc_ch0_axi", mmdc_ch1_axi_clk[0]),
+ _REGISTER_CLOCK(NULL, "ahb", ahb_clk),
+ _REGISTER_CLOCK(NULL, "ipg_clk", ipg_clk),
+ _REGISTER_CLOCK(NULL, "ipg_perclk", ipg_perclk),
+ _REGISTER_CLOCK(NULL, "spba", spba_clk),
+ _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk[0]),
+ _REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+ _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[0]),
+ _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk[1]),
+ _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2]),
+ _REGISTER_CLOCK(NULL, "csi_clk", ipu1_clk),
+ _REGISTER_CLOCK(NULL, "elcdif_axi", ipu2_clk),
+ _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, usdhc1_clk),
+ _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, usdhc2_clk),
+ _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, usdhc3_clk),
+ _REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, usdhc4_clk),
+ _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk[0]),
+ _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk[0]),
+ _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk[0]),
+ _REGISTER_CLOCK(NULL, "pxp_axi", pxp_axi_clk),
+ _REGISTER_CLOCK(NULL, "epdc_axi", epdc_axi_clk),
+ _REGISTER_CLOCK(NULL, "epdc_pix", epdc_pix_clk),
+ _REGISTER_CLOCK(NULL, "elcdif_pix", lcdif_pix_clk),
+ _REGISTER_CLOCK("mxc_spdif.0", NULL, spdif0_clk[0]),
+ _REGISTER_CLOCK("imx6q-ecspi.0", NULL, ecspi_clk[0]),
+ _REGISTER_CLOCK("imx6q-ecspi.1", NULL, ecspi_clk[1]),
+ _REGISTER_CLOCK("imx6q-ecspi.2", NULL, ecspi_clk[2]),
+ _REGISTER_CLOCK("imx6q-ecspi.3", NULL, ecspi_clk[3]),
+ _REGISTER_CLOCK("imx6q-ecspi.4", NULL, ecspi_clk[4]),
+ _REGISTER_CLOCK(NULL, "emi_slow_clk", emi_slow_clk),
+ _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0]),
+ _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[0]),
+ _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[0]),
+ _REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[0]),
+ _REGISTER_CLOCK(NULL, "gpt", gpt_clk[0]),
+ _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk[0]),
+ _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm_clk[1]),
+ _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm_clk[2]),
+ _REGISTER_CLOCK("mxc_pwm.3", NULL, pwm_clk[3]),
+ _REGISTER_CLOCK(NULL, "fec_clk", fec_clk[0]),
+ _REGISTER_CLOCK(NULL, "fec_mdc_clk", fec_mdc_clk),
+ _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk[0]),
+ _REGISTER_CLOCK(NULL, "usb_phy1_clk", usb_phy1_clk),
+ _REGISTER_CLOCK(NULL, "usb_phy3_clk", usb_phy3_clk),
+ _REGISTER_CLOCK(NULL, "usb_phy4_clk", usb_phy4_clk),
+ _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk),
+ _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk),
+ _REGISTER_CLOCK(NULL, "kpp", dummy_clk),
+ _REGISTER_CLOCK(NULL, NULL, aips_tz2_clk),
+ _REGISTER_CLOCK(NULL, NULL, aips_tz1_clk),
+ _REGISTER_CLOCK(NULL, "clko_clk", clko_clk),
+ _REGISTER_CLOCK(NULL, "clko2_clk", clko2_clk),
+ _REGISTER_CLOCK("mxs-perfmon.0", "perfmon", perfmon0_clk),
+ _REGISTER_CLOCK("mxs-perfmon.1", "perfmon", perfmon1_clk),
+ _REGISTER_CLOCK("mxs-perfmon.2", "perfmon", perfmon2_clk),
+ _REGISTER_CLOCK(NULL, "anaclk_1", anaclk_1),
+ _REGISTER_CLOCK(NULL, "anaclk_2", anaclk_2),
+ _REGISTER_CLOCK(NULL, "gpu2d_clk", gpu2d_core_clk),
+ _REGISTER_CLOCK(NULL, "gpu2d_axi_clk", gpu2d_axi_clk),
+ _REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
+ _REGISTER_CLOCK(NULL, "rng_clk", dummy_clk),
+ _REGISTER_CLOCK(NULL, "dcp_clk", dummy_clk),
+};
+
+static void clk_tree_init(void)
+
+{
+ unsigned int reg;
+
+ reg = __raw_readl(MMDC_MDMISC_OFFSET);
+ /*
+ * For lpddr2 board, current freq only support up to 400MHz,
+ * in this case, periph clk will set to 400MHz in uboot,
+ * so in clock init, we need to check whether the ddr clock
+ * is set to 400MHz, if yes, then we should set periph clk
+ * parent to pll2_pfd2_400M.
+ */
+ if ((reg & MMDC_MDMISC_DDR_TYPE_MASK) ==
+ (0x1 << MMDC_MDMISC_DDR_TYPE_OFFSET)) {
+ clk_set_parent(&periph_clk, &pll2_pfd2_400M);
+ }
+}
+
+
+int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc,
+ unsigned long ckih1, unsigned long ckih2)
+{
+ int i;
+ u32 parent_rate, rate;
+ unsigned long ipg_clk_rate, max_arm_wait_clk;
+
+ external_low_reference = ckil;
+ external_high_reference = ckih1;
+ ckih2_reference = ckih2;
+ oscillator_reference = osc;
+
+ timer_base = ioremap(GPT_BASE_ADDR, SZ_4K);
+ apll_base = ioremap(ANATOP_BASE_ADDR, SZ_4K);
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+ clkdev_add(&lookups[i]);
+ clk_debug_register(lookups[i].clk);
+ }
+
+ /* GPT will source from perclk, hence ipg_perclk
+ * should be from OSC24M */
+ clk_set_parent(&ipg_perclk, &osc_clk);
+
+
+ /*IPG_PERCLK sources I2C.
+ * I2C needs a minimum of 12.8MHz as its source
+ * to acheive 400KHz speed.
+ * Hence set ipg_perclk to 24MHz.
+ */
+
+ clk_set_rate(&ipg_perclk, 24000000);
+
+ gpt_clk[0].parent = &ipg_perclk;
+ gpt_clk[0].get_rate = NULL;
+
+ mxc_timer_init(&gpt_clk[0], timer_base, MXC_INT_GPT);
+
+ /* keep correct count. */
+ clk_enable(&cpu_clk);
+ clk_enable(&periph_clk);
+ clk_enable(&mmdc_ch1_axi_clk[0]);
+
+ clk_tree_init();
+
+ /* Set AHB to 132MHz. */
+ clk_set_rate(&ahb_clk, clk_round_rate(&ahb_clk, 132000000));
+
+ /* Disable un-necessary PFDs & PLLs */
+ pll2_pfd0_352M.disable(&pll2_pfd0_352M);
+ pll2_pfd1_594M.disable(&pll2_pfd1_594M);
+
+ pll3_pfd3_454M.disable(&pll3_pfd3_454M);
+ pll3_pfd2_508M.disable(&pll3_pfd2_508M);
+ pll3_pfd1_540M.disable(&pll3_pfd1_540M);
+ pll3_pfd0_720M.disable(&pll3_pfd0_720M);
+
+ pll3_usb_otg_main_clk.disable(&pll3_usb_otg_main_clk);
+ pll4_audio_main_clk.disable(&pll4_audio_main_clk);
+ pll5_video_main_clk.disable(&pll5_video_main_clk);
+ pll6_enet_main_clk.disable(&pll6_enet_main_clk);
+
+ /* Initialize Audio and Video PLLs to valid frequency (650MHz). */
+ clk_set_rate(&pll4_audio_main_clk, 650000000);
+ clk_set_rate(&pll5_video_main_clk, 650000000);
+
+ clk_set_parent(&clko_clk, &ipg_clk);
+
+ mx6_cpu_op_init();
+ cpu_op_tbl = get_cpu_op(&cpu_op_nr);
+
+ /* Gate off all possible clocks */
+ if (mxc_jtag_enabled) {
+ __raw_writel(3 << MXC_CCM_CCGRx_CG11_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR0);
+ } else {
+ __raw_writel(1 << MXC_CCM_CCGRx_CG11_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR0);
+ }
+ __raw_writel(3 << MXC_CCM_CCGRx_CG10_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG11_OFFSET, MXC_CCM_CCGR1);
+ __raw_writel(1 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG11_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG10_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2);
+ __raw_writel(1 << MXC_CCM_CCGRx_CG14_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG13_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG11_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG10_OFFSET, MXC_CCM_CCGR3);
+ __raw_writel(3 << MXC_CCM_CCGRx_CG7_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG6_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG4_OFFSET, MXC_CCM_CCGR4);
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR5);
+
+ __raw_writel(0, MXC_CCM_CCGR6);
+
+ /* Bypass MMDC_CH0 handshake */
+ __raw_writel(0x20000, MXC_CCM_CCDR);
+
+ /* S/PDIF */
+ clk_set_parent(&spdif0_clk[0], &pll3_pfd3_454M);
+
+ /* pxp & epdc axi */
+ clk_set_parent(&pxp_axi_clk, &pll2_pfd2_400M);
+ clk_set_rate(&pxp_axi_clk, 198000000);
+ clk_set_parent(&epdc_axi_clk, &pll2_pfd2_400M);
+ clk_set_rate(&epdc_axi_clk, 198000000);
+
+ /* epdc pix - PLL5 as parent */
+ clk_set_parent(&epdc_pix_clk, &pll5_video_main_clk);
+ /* lcdif pix - PLL5 as parent */
+ clk_set_parent(&lcdif_pix_clk, &pll5_video_main_clk);
+
+ clk_set_parent(&ssi2_clk[0], &pll4_audio_main_clk);
+
+ lp_high_freq = 0;
+ lp_med_freq = 0;
+
+ /* Get current ARM_PODF value */
+ rate = clk_get_rate(&cpu_clk);
+ parent_rate = clk_get_rate(&pll1_sw_clk);
+ cur_arm_podf = parent_rate / rate;
+
+ /* Calculate the ARM_PODF to be applied when the system
+ * enters WAIT state.
+ * The max ARM clk is decided by the ipg_clk and has to
+ * follow the ratio of ARM_CLK:IPG_CLK of 12:5.
+ */
+ ipg_clk_rate = clk_get_rate(&ipg_clk);
+ max_arm_wait_clk = (12 * ipg_clk_rate) / 5;
+ wait_mode_arm_podf = parent_rate / max_arm_wait_clk;
+
+#if 1
+ _clk_disable(&gpu2d_core_clk);
+#endif
+ return 0;
+
+}
diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c
new file mode 100644
index 00000000..86df0826
--- /dev/null
+++ b/arch/arm/mach-mx6/cpu.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2011-2013 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 <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/iram_alloc.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <mach/system.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+
+struct cpu_op *(*get_cpu_op)(int *op);
+bool enable_wait_mode = true;
+u32 enable_ldo_mode = LDO_MODE_DEFAULT;
+u32 arm_max_freq = CPU_AT_1_2GHz;
+bool mem_clk_on_in_wait;
+int chip_rev;
+unsigned long iram_tlb_base_addr;
+unsigned long iram_tlb_phys_addr;
+
+void __iomem *gpc_base;
+void __iomem *ccm_base;
+
+extern unsigned int num_cpu_idle_lock;
+
+static int cpu_silicon_rev = -1;
+#define MX6_USB_ANALOG_DIGPROG 0x260
+#define MX6SL_USB_ANALOG_DIGPROG 0x280
+
+unsigned long save_ttbr1(void)
+{
+ unsigned long lttbr1;
+ asm volatile(
+ ".align 4\n"
+ "mrc p15, 0, %0, c2, c0, 1\n"
+ : "=r" (lttbr1)
+ );
+ return lttbr1;
+}
+
+void restore_ttbr1(u32 ttbr1)
+{
+ asm volatile(
+ ".align 4\n"
+ "mcr p15, 0, %0, c2, c0, 1\n"
+ : : "r" (ttbr1)
+ );
+}
+
+static int mx6_get_srev(void)
+{
+ void __iomem *anatop = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ u32 rev;
+ if (cpu_is_mx6sl())
+ rev = __raw_readl(anatop + MX6SL_USB_ANALOG_DIGPROG);
+ else
+ rev = __raw_readl(anatop + MX6_USB_ANALOG_DIGPROG);
+
+ rev &= 0xff;
+
+ if (rev == 0)
+ return IMX_CHIP_REVISION_1_0;
+ else if (rev == 1)
+ return IMX_CHIP_REVISION_1_1;
+ else if (rev == 2)
+ return IMX_CHIP_REVISION_1_2;
+
+ return IMX_CHIP_REVISION_UNKNOWN;
+}
+
+/*
+ * Returns:
+ * the silicon revision of the cpu
+ */
+int mx6q_revision(void)
+{
+ if (!cpu_is_mx6q())
+ return -EINVAL;
+
+ if (cpu_silicon_rev == -1)
+ cpu_silicon_rev = mx6_get_srev();
+
+ return cpu_silicon_rev;
+}
+EXPORT_SYMBOL(mx6q_revision);
+
+/*
+ * Returns:
+ * the silicon revision of the cpu
+ */
+int mx6dl_revision(void)
+{
+ if (!cpu_is_mx6dl())
+ return -EINVAL;
+
+ if (cpu_silicon_rev == -1)
+ cpu_silicon_rev = mx6_get_srev();
+
+ return cpu_silicon_rev;
+}
+EXPORT_SYMBOL(mx6dl_revision);
+
+/*
+ * Returns:
+ * the silicon revision of the cpu
+ */
+int mx6sl_revision(void)
+{
+ if (!cpu_is_mx6sl())
+ return -EINVAL;
+
+ if (cpu_silicon_rev == -1)
+ cpu_silicon_rev = mx6_get_srev();
+
+ return cpu_silicon_rev;
+}
+EXPORT_SYMBOL(mx6sl_revision);
+
+static int __init post_cpu_init(void)
+{
+ unsigned int reg;
+ void __iomem *base;
+ u32 iram_size;
+
+ if (cpu_is_mx6q())
+ iram_size = MX6Q_IRAM_SIZE;
+ else
+ iram_size = MX6DL_MX6SL_IRAM_SIZE;
+
+ iram_init(MX6Q_IRAM_BASE_ADDR, iram_size);
+
+ base = ioremap(AIPS1_ON_BASE_ADDR, PAGE_SIZE);
+ __raw_writel(0x0, base + 0x40);
+ __raw_writel(0x0, base + 0x44);
+ __raw_writel(0x0, base + 0x48);
+ __raw_writel(0x0, base + 0x4C);
+ reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+ __raw_writel(reg, base + 0x50);
+ iounmap(base);
+
+ base = ioremap(AIPS2_ON_BASE_ADDR, PAGE_SIZE);
+ __raw_writel(0x0, base + 0x40);
+ __raw_writel(0x0, base + 0x44);
+ __raw_writel(0x0, base + 0x48);
+ __raw_writel(0x0, base + 0x4C);
+ reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+ __raw_writel(reg, base + 0x50);
+ iounmap(base);
+
+ /* Force IOMUXC irq to be pending for CCM LPM */
+ base = IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR);
+ reg = __raw_readl(base + 0x4);
+ reg |= 0x1000;
+ __raw_writel(reg, base + 0x4);
+
+ /* Allow SCU_CLK to be disabled when all cores are in WFI*/
+ base = IO_ADDRESS(SCU_BASE_ADDR);
+ reg = __raw_readl(base);
+ reg |= 0x20;
+ __raw_writel(reg, base);
+
+ /* Disable SRC warm reset to work aound system reboot issue */
+ base = IO_ADDRESS(SRC_BASE_ADDR);
+ reg = __raw_readl(base);
+ reg &= ~0x1;
+ __raw_writel(reg, base);
+
+ gpc_base = MX6_IO_ADDRESS(GPC_BASE_ADDR);
+ ccm_base = MX6_IO_ADDRESS(CCM_BASE_ADDR);
+
+ /* enable AXI cache for VDOA/VPU/IPU
+ * set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7
+ * clear OCRAM_CTL bits to disable pipeline control
+ */
+ reg = __raw_readl(IOMUXC_GPR3);
+ reg &= ~IOMUXC_GPR3_OCRAM_CTL_EN;
+ __raw_writel(reg, IOMUXC_GPR3);
+ reg = __raw_readl(IOMUXC_GPR4);
+ reg |= IOMUXC_GPR4_VDOA_CACHE_EN | IOMUXC_GPR4_VPU_CACHE_EN |
+ IOMUXC_GPR4_IPU_CACHE_EN;
+ __raw_writel(reg, IOMUXC_GPR4);
+ __raw_writel(IOMUXC_GPR6_IPU1_QOS, IOMUXC_GPR6);
+ __raw_writel(IOMUXC_GPR7_IPU2_QOS, IOMUXC_GPR7);
+
+ num_cpu_idle_lock = 0x0;
+ if (cpu_is_mx6dl())
+ num_cpu_idle_lock = 0xffff0000;
+
+#ifdef CONFIG_SMP
+ switch (setup_max_cpus) {
+ case 3:
+ num_cpu_idle_lock = 0xff000000;
+ break;
+ case 2:
+ num_cpu_idle_lock = 0xffff0000;
+ break;
+ case 1:
+ case 0:
+ num_cpu_idle_lock = 0xffffff00;
+ break;
+ }
+#endif
+ /*
+ * The option to keep ARM memory clocks enabled during WAIT
+ * is only available on MX6SL, MX6DQ TO1.2 (or later) and
+ * MX6DL TO1.1 (or later)
+ * So if the user specifies "mem_clk_on" on any other chip,
+ * ensure that it is disabled.
+ */
+ if (!cpu_is_mx6sl() && (mx6q_revision() < IMX_CHIP_REVISION_1_2) &&
+ (mx6dl_revision() < IMX_CHIP_REVISION_1_1))
+ mem_clk_on_in_wait = false;
+
+ if (cpu_is_mx6q())
+ chip_rev = mx6q_revision();
+ else if (cpu_is_mx6dl())
+ chip_rev = mx6dl_revision();
+ else
+ chip_rev = mx6sl_revision();
+
+ /* mx6sl doesn't have pcie. save power, disable PCIe PHY */
+ if (!cpu_is_mx6sl()) {
+ reg = __raw_readl(IOMUXC_GPR1);
+ reg = reg & (~IOMUXC_GPR1_PCIE_REF_CLK_EN);
+ reg |= IOMUXC_GPR1_TEST_POWERDOWN;
+ __raw_writel(reg, IOMUXC_GPR1);
+ }
+ if (cpu_is_mx6sl()) {
+ int i;
+ /*
+ * Allocate the bottom 16K of IRAM page tables that
+ * will be used when DDR is in self-refresh.
+ */
+ iram_tlb_phys_addr = MX6_IRAM_TLB_BASE_ADDR;
+ iram_tlb_base_addr = (unsigned long)__arm_ioremap(iram_tlb_phys_addr,
+ MX6_IRAM_TLB_SIZE, MT_MEMORY_NONCACHED);
+
+ /* Set all entries to 0. */
+ memset((void *)iram_tlb_base_addr, 0, MX6_IRAM_TLB_SIZE);
+
+ /* Make sure the IRAM virtual address has a mapping in the IRAM page table. */
+ i = ((IRAM_BASE_ADDR_VIRT >> 20) << 2 ) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (IRAM_BASE_ADDR & 0xFFF0000) | TT_ATTRIB_NON_CACHEABLE_1M;
+ /* Make sure the AIPS1 virtual address has a mapping in the IRAM page table. */
+ i = ((AIPS1_BASE_ADDR_VIRT >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (AIPS1_ARB_BASE_ADDR & 0xFFF00000) | TT_ATTRIB_NON_CACHEABLE_1M;
+ /* Make sure the AIPS2 virtual address has a mapping in the IRAM page table. */
+ i = ((AIPS2_BASE_ADDR_VIRT >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (AIPS2_ARB_BASE_ADDR & 0xFFF00000) | TT_ATTRIB_NON_CACHEABLE_1M;
+ /* Make sure the AIPS2 virtual address has a mapping in the IRAM page table. */
+ i = ((L2_BASE_ADDR_VIRT >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (L2_BASE_ADDR & 0xFFF0000) | TT_ATTRIB_NON_CACHEABLE_1M;
+
+ }
+ return 0;
+}
+postcore_initcall(post_cpu_init);
+
+static int __init enable_wait(char *p)
+{
+ if (memcmp(p, "on", 2) == 0) {
+ enable_wait_mode = true;
+ p += 2;
+ } else if (memcmp(p, "off", 3) == 0) {
+ enable_wait_mode = false;
+ p += 3;
+ }
+ return 0;
+}
+early_param("enable_wait_mode", enable_wait);
+
+static int __init arm_core_max(char *p)
+{
+ if (memcmp(p, "1200", 4) == 0) {
+ arm_max_freq = CPU_AT_1_2GHz;
+ p += 4;
+ } else if (memcmp(p, "1000", 4) == 0) {
+ arm_max_freq = CPU_AT_1GHz;
+ p += 4;
+ } else if (memcmp(p, "800", 3) == 0) {
+ arm_max_freq = CPU_AT_800MHz;
+ p += 3;
+ }
+ return 0;
+}
+
+early_param("arm_freq", arm_core_max);
+
+static int __init enable_ldo(char *p)
+{
+ if (memcmp(p, "on", 2) == 0) {
+ enable_ldo_mode = LDO_MODE_ENABLED;
+ p += 2;
+ } else if (memcmp(p, "off", 3) == 0) {
+ enable_ldo_mode = LDO_MODE_BYPASSED;
+ p += 3;
+ }
+ return 0;
+}
+early_param("ldo_active", enable_ldo);
+
+static int __init enable_mem_clk_in_wait(char *p)
+{
+ mem_clk_on_in_wait = true;
+
+ return 0;
+}
+
+early_param("mem_clk_on", enable_mem_clk_in_wait);
+
+
+
diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c
new file mode 100644
index 00000000..24dcc712
--- /dev/null
+++ b/arch/arm/mach-mx6/cpu_op-mx6.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2010-2013 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 <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+#include "cpu_op-mx6.h"
+
+#define OCOTP_SPEED_BIT_OFFSET (16)
+extern struct cpu_op *(*get_cpu_op)(int *op);
+extern struct dvfs_op *(*get_dvfs_core_op)(int *wp);
+extern void (*set_num_cpu_op)(int num);
+extern u32 arm_max_freq;
+static int num_cpu_op;
+
+/* working point(wp): 0 - 1.2GHz; 1 - 792MHz, 2 - 498MHz 3 - 396MHz */
+static struct cpu_op mx6q_cpu_op_1_2G[] = {
+ {
+ .pll_rate = 1200000000,
+ .cpu_rate = 1200000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1275000,
+ .soc_voltage = 1275000,
+ .cpu_voltage = 1275000,},
+ {
+ .pll_rate = 996000000,
+ .cpu_rate = 996000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1250000,
+ .soc_voltage = 1250000,
+ .cpu_voltage = 1250000,},
+ {
+ .pll_rate = 792000000,
+ .cpu_rate = 792000000,
+ .cpu_podf = 0,
+#ifdef CONFIG_MX6_VPU_352M
+ /*VPU 352Mhz need voltage 1.25V*/
+ .pu_voltage = 1250000,
+ .soc_voltage = 1250000,
+#else
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+#endif
+ .cpu_voltage = 1150000,},
+#ifdef CONFIG_MX6_VPU_352M
+ /*pll2_pfd_400M will be fix on 352M,to avoid modify other code
+ which assume ARM clock sourcing from pll2_pfd_400M, change cpu
+ freq from 396M to 352M.*/
+ {
+ .pll_rate = 352000000,
+ .cpu_rate = 352000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1250000,
+ .soc_voltage = 1250000,
+ .cpu_voltage = 950000,},
+#else
+ {
+ .pll_rate = 396000000,
+ .cpu_rate = 396000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 950000,},
+#endif
+};
+
+/* working point(wp): 0 - 1GHz; 1 - 792MHz, 2 - 498MHz 3 - 396MHz */
+static struct cpu_op mx6q_cpu_op_1G[] = {
+ {
+ .pll_rate = 996000000,
+ .cpu_rate = 996000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1250000,
+ .soc_voltage = 1250000,
+ .cpu_voltage = 1250000,},
+ {
+ .pll_rate = 792000000,
+ .cpu_rate = 792000000,
+ .cpu_podf = 0,
+#ifdef CONFIG_MX6_VPU_352M
+ /*VPU 352Mhz need voltage 1.25V*/
+ .pu_voltage = 1250000,
+ .soc_voltage = 1250000,
+#else
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+#endif
+ .cpu_voltage = 1150000,},
+#ifdef CONFIG_MX6_VPU_352M
+ /*pll2_pfd_400M will be fix on 352M,to avoid modify other code
+ which assume ARM clock sourcing from pll2_pfd_400M, change cpu
+ freq from 396M to 352M.*/
+ {
+ .pll_rate = 352000000,
+ .cpu_rate = 352000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1250000,
+ .soc_voltage = 1250000,
+ .cpu_voltage = 950000,},
+#else
+ {
+ .pll_rate = 396000000,
+ .cpu_rate = 396000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 950000,},
+#endif
+};
+
+static struct cpu_op mx6q_cpu_op[] = {
+ {
+ .pll_rate = 792000000,
+ .cpu_rate = 792000000,
+ .cpu_podf = 0,
+#ifdef CONFIG_MX6_VPU_352M
+ /*VPU 352Mhz need voltage 1.25V*/
+ .pu_voltage = 1250000,
+ .soc_voltage = 1250000,
+#else
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+#endif
+ .cpu_voltage = 1150000,},
+#ifdef CONFIG_MX6_VPU_352M
+ /*pll2_pfd_400M will be fix on 352M,to avoid modify other code
+ which assume ARM clock sourcing from pll2_pfd_400M, change cpu
+ freq from 396M to 352M.*/
+ {
+ .pll_rate = 352000000,
+ .cpu_rate = 352000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1250000,
+ .soc_voltage = 1250000,
+ .cpu_voltage = 950000,},
+#else
+ {
+ .pll_rate = 396000000,
+ .cpu_rate = 396000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 950000,},
+#endif
+};
+
+/* working point(wp): 0 - 1.2GHz; 1 - 800MHz, 2 - 400MHz, 3 - 200MHz */
+static struct cpu_op mx6dl_cpu_op_1_2G[] = {
+ {
+ .pll_rate = 1200000000,
+ .cpu_rate = 1200000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 1275000,},
+ {
+ .pll_rate = 792000000,
+ .cpu_rate = 792000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 1175000,},
+ {
+ .pll_rate = 396000000,
+ .cpu_rate = 396000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 1075000,},
+};
+/* working point(wp): 0 - 1GHz; 1 - 800MHz, 2 - 400MHz, 3 - 200MHz */
+static struct cpu_op mx6dl_cpu_op_1G[] = {
+ {
+ .pll_rate = 996000000,
+ .cpu_rate = 996000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 1250000,},
+ {
+ .pll_rate = 792000000,
+ .cpu_rate = 792000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 1175000,},
+ {
+ .pll_rate = 396000000,
+ .cpu_rate = 396000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 1075000,},
+};
+static struct cpu_op mx6dl_cpu_op[] = {
+ {
+ .pll_rate = 792000000,
+ .cpu_rate = 792000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 1175000,},
+ {
+ .pll_rate = 396000000,
+ .cpu_rate = 396000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1175000,
+ .soc_voltage = 1175000,
+ .cpu_voltage = 1075000,},
+};
+
+static struct cpu_op mx6sl_cpu_op_1G[] = {
+ {
+ .pll_rate = 996000000,
+ .cpu_rate = 996000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1200000,
+ .soc_voltage = 1200000,
+ .cpu_voltage = 1250000,},
+/* {
+ .pll_rate = 792000000,
+ .cpu_rate = 792000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1150000,
+ .soc_voltage = 1150000,
+ .cpu_voltage = 1150000,},*/
+ {
+ .pll_rate = 396000000,
+ .pll_lpm_rate = 792000000,
+ .cpu_rate = 396000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1150000,
+ .soc_voltage = 1150000,
+ .cpu_voltage = 950000,},
+};
+
+static struct cpu_op mx6sl_cpu_op[] = {
+ {
+ .pll_rate = 792000000,
+ .cpu_rate = 792000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1150000,
+ .soc_voltage = 1150000,
+ .cpu_voltage = 1150000,},
+ {
+ .pll_rate = 396000000,
+ .pll_lpm_rate = 792000000,
+ .cpu_rate = 396000000,
+ .cpu_podf = 0,
+ .pu_voltage = 1150000,
+ .soc_voltage = 1150000,
+ .cpu_voltage = 950000,},
+};
+
+static struct dvfs_op dvfs_core_setpoint_1_2G[] = {
+ {33, 14, 33, 10, 128, 0x10}, /* 1.2GHz*/
+ {30, 12, 33, 100, 200, 0x10}, /* 800MHz */
+ {28, 12, 33, 100, 200, 0x10}, /* 672MHz */
+ {26, 8, 33, 100, 200, 0x10}, /* 400MHz */
+ {20, 0, 33, 20, 10, 0x10} }; /* 200MHz*/
+
+static struct dvfs_op dvfs_core_setpoint_1G[] = {
+ {33, 14, 33, 10, 128, 0x10}, /* 1GHz*/
+ {30, 12, 33, 100, 200, 0x10}, /* 800MHz */
+ {28, 12, 33, 100, 200, 0x10}, /* 672MHz */
+ {26, 8, 33, 100, 200, 0x10}, /* 400MHz */
+ {20, 0, 33, 20, 10, 0x10} }; /* 200MHz*/
+
+static struct dvfs_op dvfs_core_setpoint[] = {
+ {33, 14, 33, 10, 128, 0x08}, /* 800MHz */
+ {26, 8, 33, 100, 200, 0x08}, /* 400MHz */
+ {20, 0, 33, 100, 10, 0x08} }; /* 200MHz*/
+
+static struct dvfs_op *mx6_get_dvfs_core_table(int *wp)
+{
+ if (arm_max_freq == CPU_AT_1_2GHz) {
+ *wp = ARRAY_SIZE(dvfs_core_setpoint_1_2G);
+ return dvfs_core_setpoint_1_2G;
+ } else if (arm_max_freq == CPU_AT_1GHz) {
+ *wp = ARRAY_SIZE(dvfs_core_setpoint_1G);
+ return dvfs_core_setpoint_1G;
+ } else {
+ *wp = ARRAY_SIZE(dvfs_core_setpoint);
+ return dvfs_core_setpoint;
+ }
+}
+
+struct cpu_op *mx6_get_cpu_op(int *op)
+{
+ if (cpu_is_mx6dl()) {
+ if (arm_max_freq == CPU_AT_1_2GHz) {
+ *op = num_cpu_op = ARRAY_SIZE(mx6dl_cpu_op_1_2G);
+ return mx6dl_cpu_op_1_2G;
+ } else if (arm_max_freq == CPU_AT_1GHz) {
+ *op = num_cpu_op = ARRAY_SIZE(mx6dl_cpu_op_1G);
+ return mx6dl_cpu_op_1G;
+ } else {
+ *op = num_cpu_op = ARRAY_SIZE(mx6dl_cpu_op);
+ return mx6dl_cpu_op;
+ }
+ } else if (cpu_is_mx6q()) {
+ if (arm_max_freq == CPU_AT_1_2GHz) {
+ *op = num_cpu_op = ARRAY_SIZE(mx6q_cpu_op_1_2G);
+ return mx6q_cpu_op_1_2G;
+ } else if (arm_max_freq == CPU_AT_1GHz) {
+ *op = num_cpu_op = ARRAY_SIZE(mx6q_cpu_op_1G);
+ return mx6q_cpu_op_1G;
+ } else {
+ *op = num_cpu_op = ARRAY_SIZE(mx6q_cpu_op);
+ return mx6q_cpu_op;
+ }
+ } else {
+ if (arm_max_freq == CPU_AT_1GHz) {
+ *op = num_cpu_op = ARRAY_SIZE(mx6sl_cpu_op_1G);
+ return mx6sl_cpu_op_1G;
+ } else {
+ *op = num_cpu_op = ARRAY_SIZE(mx6sl_cpu_op);
+ return mx6sl_cpu_op;
+ }
+ }
+}
+
+void mx6_set_num_cpu_op(int num)
+{
+ num_cpu_op = num;
+ return;
+}
+
+void mx6_cpu_op_init(void)
+{
+ unsigned int reg;
+ void __iomem *base;
+ if (!cpu_is_mx6sl()) {
+ /*read fuse bit to know the max cpu freq : offset 0x440
+ * bit[17:16]:SPEED_GRADING[1:0],for mx6dq/dl*/
+ base = IO_ADDRESS(OCOTP_BASE_ADDR);
+ reg = __raw_readl(base + 0x440);
+ reg &= (0x3 << OCOTP_SPEED_BIT_OFFSET);
+ reg >>= OCOTP_SPEED_BIT_OFFSET;
+ /*choose the little value to run lower max cpufreq*/
+ arm_max_freq = (reg > arm_max_freq) ? arm_max_freq : reg;
+ } else {
+ /*
+ * There is no SPEED_GRADING fuse bit on mx6sl,then do:
+ * If arm_max_freq set by default on CPU_AT_1_2GHz which mean
+ * there is no 'arm_freq' setting in cmdline from bootloader,
+ * force arm_max_freq to 1G. Else use 'arm_freq' setting.
+ */
+ if (arm_max_freq == CPU_AT_1_2GHz)
+ arm_max_freq = CPU_AT_1GHz;/*mx6sl max freq is 1Ghz*/
+ }
+ printk(KERN_INFO "arm_max_freq=%s\n", (arm_max_freq == CPU_AT_1_2GHz) ?
+ "1.2GHz" : ((arm_max_freq == CPU_AT_1GHz) ? "1GHz" : "800MHz"));
+ get_cpu_op = mx6_get_cpu_op;
+ set_num_cpu_op = mx6_set_num_cpu_op;
+
+ get_dvfs_core_op = mx6_get_dvfs_core_table;
+}
+
diff --git a/arch/arm/mach-mx6/cpu_op-mx6.h b/arch/arm/mach-mx6/cpu_op-mx6.h
new file mode 100644
index 00000000..310cbb37
--- /dev/null
+++ b/arch/arm/mach-mx6/cpu_op-mx6.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2010-2012 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
+ */
+/*The below value aligned with SPEED_GRADING bits in 0x440 fuse offset */
+#define CPU_AT_800MHz 0
+#define CPU_AT_1GHz 2
+#define CPU_AT_1_2GHz 3
+
+void mx6_cpu_op_init(void);
diff --git a/arch/arm/mach-mx6/cpu_regulator-mx6.c b/arch/arm/mach-mx6/cpu_regulator-mx6.c
new file mode 100644
index 00000000..1a67e9d5
--- /dev/null
+++ b/arch/arm/mach-mx6/cpu_regulator-mx6.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2012-2013 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 <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#if defined(CONFIG_CPU_FREQ)
+#include <linux/cpufreq.h>
+#endif
+#include <linux/io.h>
+#include <asm/cpu.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+#include <mach/system.h>
+#include "regs-anadig.h"
+#include "crm_regs.h"
+struct regulator *cpu_regulator;
+struct regulator *soc_regulator;
+struct regulator *pu_regulator;
+char *gp_reg_id;
+char *soc_reg_id;
+char *pu_reg_id;
+static struct clk *cpu_clk;
+static int cpu_op_nr;
+static struct cpu_op *cpu_op_tbl;
+extern struct cpu_op *(*get_cpu_op)(int *op);
+
+extern unsigned long loops_per_jiffy;
+extern u32 enable_ldo_mode;
+int external_pureg;
+
+static inline unsigned long mx6_cpu_jiffies(unsigned long old, u_int div,
+ u_int mult)
+{
+#if BITS_PER_LONG == 32
+
+ u64 result = ((u64) old) * ((u64) mult);
+ do_div(result, div);
+ return (unsigned long) result;
+
+#elif BITS_PER_LONG == 64
+
+ unsigned long result = old * ((u64) mult);
+ result /= div;
+ return result;
+
+#endif
+}
+
+void mx6_cpu_regulator_init(void)
+{
+ int cpu;
+ u32 curr_cpu = 0;
+ unsigned int reg;
+#ifndef CONFIG_SMP
+ unsigned long old_loops_per_jiffy;
+#endif
+ void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+ external_pureg = 0;
+ /*If internal ldo actived, use internal cpu_* regulator to replace the
+ *regulator ids from board file. If internal ldo bypassed, use the
+ *regulator ids which defined in board file and source from extern pmic
+ *power rails.
+ *If you want to use ldo bypass,you should do:
+ *1.set enable_ldo_mode=LDO_MODE_BYPASSED in your board file by default
+ * or set in commandline from u-boot
+ *2.set your extern pmic regulator name in your board file.
+ */
+ if (enable_ldo_mode != LDO_MODE_BYPASSED) {
+ gp_reg_id = "cpu_vddgp";
+ soc_reg_id = "cpu_vddsoc";
+ pu_reg_id = "cpu_vddgpu";
+ }
+ printk(KERN_INFO "cpu regulator mode:%s\n", (enable_ldo_mode ==
+ LDO_MODE_BYPASSED) ? "ldo_bypass" : "ldo_enable");
+ cpu_regulator = regulator_get(NULL, gp_reg_id);
+#if 0
+ if (IS_ERR(cpu_regulator))
+ printk(KERN_ERR "%s: failed to get cpu regulator\n", __func__);
+ else
+#endif
+ {
+ cpu_clk = clk_get(NULL, "cpu_clk");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_ERR "%s: failed to get cpu clock\n",
+ __func__);
+ } else {
+ curr_cpu = clk_get_rate(cpu_clk);
+ cpu_op_tbl = get_cpu_op(&cpu_op_nr);
+
+ soc_regulator = regulator_get(NULL, soc_reg_id);
+ if (IS_ERR(soc_regulator))
+ printk(KERN_ERR "%s: failed to get soc regulator\n",
+ __func__);
+ else
+ /* set soc to highest setpoint voltage. */
+ regulator_set_voltage(soc_regulator,
+ cpu_op_tbl[0].soc_voltage,
+ cpu_op_tbl[0].soc_voltage);
+
+ pu_regulator = regulator_get(NULL, pu_reg_id);
+ if (IS_ERR(pu_regulator))
+ printk(KERN_ERR "%s: failed to get pu regulator\n",
+ __func__);
+ else
+ /* set pu to higheset setpoint voltage. */
+ regulator_set_voltage(pu_regulator,
+ cpu_op_tbl[0].pu_voltage,
+ cpu_op_tbl[0].pu_voltage);
+ if (!IS_ERR(cpu_regulator)) {
+ /* set the core to higheset setpoint voltage. */
+ regulator_set_voltage(cpu_regulator,
+ cpu_op_tbl[0].cpu_voltage,
+ cpu_op_tbl[0].cpu_voltage);
+ }
+ if (enable_ldo_mode == LDO_MODE_BYPASSED) {
+ /* digital bypass VDDPU/VDDSOC/VDDARM */
+ reg = __raw_readl(ANADIG_REG_CORE);
+ reg &= ~BM_ANADIG_REG_CORE_REG0_TRG;
+ reg |= BF_ANADIG_REG_CORE_REG0_TRG(0x1f);
+ reg &= ~BM_ANADIG_REG_CORE_REG1_TRG;
+ reg |= BF_ANADIG_REG_CORE_REG1_TRG(0x1f);
+ reg &= ~BM_ANADIG_REG_CORE_REG2_TRG;
+ reg |= BF_ANADIG_REG_CORE_REG2_TRG(0x1f);
+ __raw_writel(reg, ANADIG_REG_CORE);
+ /* mask the ANATOP brown out irq in the GPC. */
+ reg = __raw_readl(gpc_base + 0x14);
+ reg |= 0x80000000;
+ __raw_writel(reg, gpc_base + 0x14);
+ }
+
+ clk_set_rate(cpu_clk, cpu_op_tbl[0].cpu_rate);
+
+ /* fix loops-per-jiffy */
+#ifdef CONFIG_SMP
+ for_each_online_cpu(cpu)
+ per_cpu(cpu_data, cpu).loops_per_jiffy =
+ mx6_cpu_jiffies(
+ per_cpu(cpu_data, cpu).loops_per_jiffy,
+ curr_cpu / 1000,
+ clk_get_rate(cpu_clk) / 1000);
+#else
+ old_loops_per_jiffy = loops_per_jiffy;
+
+ loops_per_jiffy =
+ mx6_cpu_jiffies(old_loops_per_jiffy,
+ curr_cpu/1000,
+ clk_get_rate(cpu_clk) / 1000);
+#endif
+#if defined(CONFIG_CPU_FREQ)
+ /* Fix CPU frequency for CPUFREQ. */
+ for (cpu = 0; cpu < num_online_cpus(); cpu++)
+ cpufreq_get(cpu);
+#endif
+ }
+ }
+ /*
+ * if use ldo bypass and VDDPU_IN is single supplied
+ * by external pmic, it means VDDPU_IN can be turned off
+ * if GPU/VPU driver not running.In this case we should set
+ * external_pureg which can be used in pu_enable/pu_disable of
+ * arch/arm/mach-mx6/mx6_anatop_regulator.c to
+ * enable or disable external VDDPU regulator from pmic. But for FSL
+ * reference boards, VDDSOC_IN connect with VDDPU_IN, so we didn't set
+ * pu_reg_id to the external pmic regulator supply name in the board
+ * file. In this case external_pureg should be 0 and can't turn off
+ * extern pmic regulator, but can turn off VDDPU by internal anatop
+ * power gate.
+ *
+ * if enable internal ldo , external_pureg will be 0, and
+ * VDDPU can be turned off by internal anatop anatop power gate.
+ *
+ */
+ if (!IS_ERR(pu_regulator) && strcmp(pu_reg_id, "cpu_vddgpu"))
+ external_pureg = 1;
+}
+
diff --git a/arch/arm/mach-mx6/crm_regs.h b/arch/arm/mach-mx6/crm_regs.h
new file mode 100644
index 00000000..0ae8e41e
--- /dev/null
+++ b/arch/arm/mach-mx6/crm_regs.h
@@ -0,0 +1,569 @@
+/*
+ * Copyright 2008-2013 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_MX6_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX6_CRM_REGS_H__
+
+/* IOMUXC */
+#define MXC_IOMUXC_BASE MX6_IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR)
+#define IOMUXC_GPR0 (MXC_IOMUXC_BASE + 0x00)
+#define IOMUXC_GPR1 (MXC_IOMUXC_BASE + 0x04)
+#define IOMUXC_GPR2 (MXC_IOMUXC_BASE + 0x08)
+#define IOMUXC_GPR3 (MXC_IOMUXC_BASE + 0x0C)
+#define IOMUXC_GPR4 (MXC_IOMUXC_BASE + 0x10)
+#define IOMUXC_GPR5 (MXC_IOMUXC_BASE + 0x14)
+#define IOMUXC_GPR6 (MXC_IOMUXC_BASE + 0x18)
+#define IOMUXC_GPR7 (MXC_IOMUXC_BASE + 0x1C)
+#define IOMUXC_GPR8 (MXC_IOMUXC_BASE + 0x20)
+#define IOMUXC_GPR9 (MXC_IOMUXC_BASE + 0x24)
+#define IOMUXC_GPR10 (MXC_IOMUXC_BASE + 0x28)
+#define IOMUXC_GPR11 (MXC_IOMUXC_BASE + 0x2C)
+#define IOMUXC_GPR12 (MXC_IOMUXC_BASE + 0x30)
+#define IOMUXC_GPR13 (MXC_IOMUXC_BASE + 0x34)
+
+/* GPR1: IOMUXC_GPR1_PCIE_REF_CLK_EN(IOMUXC_GPR1[16]) */
+#define IOMUXC_GPR1_PCIE_REF_CLK_EN (1 << 16)
+/* GPR1: IOMUXC_GPR1_TEST_POWERDOWN(IOMUXC_GPR1[18]) */
+#define IOMUXC_GPR1_TEST_POWERDOWN (1 << 18)
+
+/* GPR8: IOMUXC_GPR8_TX_DEEMPH_GEN1(IOMUXC_GPR8[5:0]) */
+#define IOMUXC_GPR8_TX_DEEMPH_GEN1 (0x3F << 0)
+/* GPR8: IOMUXC_GPR8_TX_DEEMPH_GEN2_3P5DB(IOMUXC_GPR8[11:6]) */
+#define IOMUXC_GPR8_TX_DEEMPH_GEN2_3P5DB (0x3F << 6)
+/* GPR8: IOMUXC_GPR8_TX_DEEMPH_GEN2_6DB(IOMUXC_GPR8[17:12]) */
+#define IOMUXC_GPR8_TX_DEEMPH_GEN2_6DB (0x3F << 12)
+/* GPR8: IOMUXC_GPR8_TX_SWING_FULL(IOMUXC_GPR8[24:18]) */
+#define IOMUXC_GPR8_TX_SWING_FULL (0x7F << 18)
+/* GPR8: IOMUXC_GPR8_TX_SWING_LOW(IOMUXC_GPR8[31:25]) */
+#define IOMUXC_GPR8_TX_SWING_LOW (0x7F << 25)
+
+/* GPR12: IOMUXC_GPR12_LOS_LEVEL(IOMUXC_GPR12[8:4]) */
+#define IOMUXC_GPR12_LOS_LEVEL (0x1F << 4)
+/* GPR12: IOMUXC_GPR12_APP_LTSSM_ENABLE(IOMUXC_GPR12[10]) */
+#define IOMUXC_GPR12_APP_LTSSM_ENABLE (1 << 10)
+/* GPR12: IOMUXC_GPR12_DEVICE_TYPE(IOMUXC_GPR12[15:12]) */
+#define IOMUXC_GPR12_DEVICE_TYPE (0xF << 12)
+
+#define IOMUXC_GPR3_OCRAM_CTL_EN (0xf << 21)
+#define IOMUXC_GPR4_VDOA_CACHE_EN (0xf << 28)
+#define IOMUXC_GPR4_VPU_CACHE_EN (0xcc)
+#define IOMUXC_GPR4_IPU_CACHE_EN (0x3)
+#define IOMUXC_GPR6_IPU1_QOS (0x007f007f)
+#define IOMUXC_GPR7_IPU2_QOS (0x007f007f)
+
+/* MMDC */
+#define MXC_MMDC_P0_BASE MX6_IO_ADDRESS(MMDC_P0_BASE_ADDR)
+#define MMDC_MDMISC_OFFSET (MXC_MMDC_P0_BASE + 0x18)
+#define MMDC_MDMISC_DDR_TYPE_MASK (0x3 << 3)
+#define MMDC_MDMISC_DDR_TYPE_OFFSET (3)
+
+/* PLLs */
+#define MXC_PLL_BASE MX6_IO_ADDRESS(ANATOP_BASE_ADDR)
+#define PLL1_SYS_BASE_ADDR (MXC_PLL_BASE + 0x0)
+#define PLL2_528_BASE_ADDR (MXC_PLL_BASE + 0x30)
+#define PLL3_480_USB1_BASE_ADDR (MXC_PLL_BASE + 0x10)
+#define PLL4_AUDIO_BASE_ADDR (MXC_PLL_BASE + 0x70)
+#define PLL5_VIDEO_BASE_ADDR (MXC_PLL_BASE + 0xA0)
+#define PLL6_MLB_BASE_ADDR (MXC_PLL_BASE + 0xD0)
+#define PLL7_480_USB2_BASE_ADDR (MXC_PLL_BASE + 0x20)
+#define PLL8_ENET_BASE_ADDR (MXC_PLL_BASE + 0xE0)
+#define PFD_480_BASE_ADDR (MXC_PLL_BASE + 0xF0)
+#define PFD_528_BASE_ADDR (MXC_PLL_BASE + 0x100)
+#define ANADIG_REG_CORE (MXC_PLL_BASE + 0x140)
+#define ANADIG_MISC1_REG (MXC_PLL_BASE + 0x160)
+#define ANADIG_MISC2_REG (MXC_PLL_BASE + 0x170)
+#define ANATOP_LVDS_CLK1_SRC_SATA 0xB
+#define ANATOP_LVDS_CLK1_OBEN_MASK 0x400
+#define ANATOP_LVDS_CLK1_IBEN_MASK 0x1000
+#define ANATOP_LVDS_CLK2_OBEN_MASK 0x800
+#define ANATOP_LVDS_CLK2_IBEN_MASK 0x2000
+#define ANA_MISC2_BASE_ADDR (MXC_PLL_BASE + 0x170)
+
+#define PLL_SETREG_OFFSET 0x4
+#define PLL_CLRREG_OFFSET 0x8
+#define PLL_TOGGLE_OFFSET 0x0C
+#define PLL_NUM_DIV_OFFSET 0x10
+#define PLL_DENOM_DIV_OFFSET 0x20
+#define PLL_528_SS_OFFSET 0x10
+#define PLL_528_NUM_DIV_OFFSET 0x20
+#define PLL_528_DENOM_DIV_OFFSET 0x30
+
+/* Common PLL register bit defines. */
+#define ANADIG_PLL_LOCK (1 << 31)
+#define ANADIG_PLL_BYPASS (1 << 16)
+#define ANADIG_PLL_BYPASS_CLK_SRC_MASK (0x3 << 14)
+#define ANADIG_PLL_BYPASS_CLK_SRC_OFFSET (14)
+#define ANADIG_PLL_ENABLE (1 << 13)
+#define ANADIG_PLL_POWER_DOWN (1 << 12)
+#define ANADIG_PLL_HOLD_RING_OFF (1 << 11)
+
+/* PLL1_SYS defines */
+#define ANADIG_PLL_SYS_DIV_SELECT_MASK (0x7F)
+#define ANADIG_PLL_SYS_DIV_SELECT_OFFSET (0)
+#define ANADIG_PLL_SYS_BYPASS_MASK (0x10000)
+#define ANADIG_PLL_SYS_BYPASS_OFFSET (16)
+
+/* PLL2_528 defines */
+#define ANADIG_PLL_528_DIV_SELECT (1)
+
+/* PLL3_480 defines. */
+#define ANADIG_PLL_480_EN_USB_CLKS (1 << 6)
+#define ANADIG_PLL_480_DIV_SELECT_MASK (0x3)
+#define ANADIG_PLL_480_DIV_SELECT_OFFSET (0)
+
+/* PLL4_AUDIO PLL5_VIDEO defines. */
+#define ANADIG_PLL_AV_DIV_SELECT_MASK (0x7F)
+#define ANADIG_PLL_AV_DIV_SELECT_OFFSET (0)
+#define ANADIG_PLL_AV_TEST_DIV_SEL_MASK (0x180000)
+#define ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET (19)
+
+/* PLL6_MLB defines. */
+#define ANADIG_PLL_MLB_LOCK (1 << 31)
+#define ANADIG_PLL_MLB_FLT_RES_CFG_MASK (0x7 << 26)
+#define ANADIG_PLL_MLB_FLT_RES_CFG_OFFSET (26)
+#define ANADIG_PLL_MLB_RX_CLK_DELAY_CFG_MASK (0x7 << 23)
+#define ANADIG_PLL_MLB_RX_CLK_DELAY_CFG_OFFSET (23)
+#define ANADIG_PLL_MLB_VDDD_DELAY_CFG_MASK (0x7 << 20)
+#define ANADIG_PLL_MLB_VDDD_DELAY_CFG_OFFSET (20)
+#define ANADIG_PLL_MLB_VDDA_DELAY_CFG_MASK (0x7 << 17)
+#define ANADIG_PLL_MLB_VDDA_DELAY_CFG_OFFSET (17)
+#define ANADIG_PLL_MLB_BYPASS (1 << 16)
+
+/* PLL8_ENET defines. */
+#define ANADIG_PLL_ENET_LOCK (1 << 31)
+#define ANADIG_PLL_ENET_EN_SATA (1 << 20)
+#define ANADIG_PLL_ENET_EN_PCIE (1 << 19)
+#define ANADIG_PLL_ENET_BYPASS (1 << 16)
+#define ANADIG_PLL_ENET_EN (1 << 13)
+#define ANADIG_PLL_ENET_POWER_DOWN (1 << 12)
+#define ANADIG_PLL_ENET_DIV_SELECT_MASK (0x3)
+#define ANADIG_PLL_ENET_DIV_SELECT_OFFSET (0)
+#define ANATOP_BYPASS_SRC_LVDS1 0x00004000
+
+/* PFD register defines. */
+#define ANADIG_PFD_FRAC_MASK 0x3F
+#define ANADIG_PFD3_CLKGATE (1 << 31)
+#define ANADIG_PFD3_STABLE (1 << 30)
+#define ANADIG_PFD3_FRAC_OFFSET 24
+#define ANADIG_PFD2_CLKGATE (1 << 23)
+#define ANADIG_PFD2_STABLE (1 << 22)
+#define ANADIG_PFD2_FRAC_OFFSET 16
+#define ANADIG_PFD1_CLKGATE (1 << 15)
+#define ANADIG_PFD1_STABLE (1 << 14)
+#define ANADIG_PFD1_FRAC_OFFSET 8
+#define ANADIG_PFD0_CLKGATE (1 << 7)
+#define ANADIG_PFD0_STABLE (1 << 6)
+#define ANADIG_PFD0_FRAC_OFFSET 0
+
+/* ANATOP Regulator/LDO defines */
+#define ANADIG_REG_RAMP_RATE_MASK 0x03
+#define ANADIG_REG_RAMP_RATE_OFFSET (0x3 << 27)
+#define ANADIG_REG_ADJUST_MASK 0xF
+#define ANADIG_REG_TARGET_MASK 0x1F
+#define ANADIG_REG2_SOC_ADJUST_OFFSET 23
+#define ANADIG_REG2_SOC_TARGET_OFFSET 18
+#define ANADIG_REG1_PU_ADJUST_OFFSET 14
+#define ANADIG_REG1_PU_TARGET_OFFSET 9
+#define ANADIG_REG0_CORE_ADJUST_OFFSET 5
+#define ANADIG_REG0_CORE_TARGET_OFFSET 0
+
+/* ANA MISC2 register defines */
+#define ANADIG_ANA_MISC2_REG1_BO_EN (1 << 13)
+#define ANADIG_ANA_MISC2_CONTROL3_MASK 0xC0000000
+#define ANADIG_ANA_MISC2_CONTROL3_OFFSET 30
+#define ANADIG_ANA_MISC2_REG0_STEP_TIME_MASK 0x03000000
+#define ANADIG_ANA_MISC2_REG1_STEP_TIME_MASK 0x0C000000
+#define ANADIG_ANA_MISC2_REG2_STEP_TIME_MASK 0x30000000
+
+#define MXC_CCM_BASE MX6_IO_ADDRESS(CCM_BASE_ADDR)
+/* CCM Register Offsets. */
+#define MXC_CCM_CDCR_OFFSET 0x4C
+#define MXC_CCM_CACRR_OFFSET 0x10
+#define MXC_CCM_CDHIPR_OFFSET 0x48
+
+/* Register addresses of CCM*/
+#define MXC_CCM_CCR (MXC_CCM_BASE + 0x00)
+#define MXC_CCM_CCDR (MXC_CCM_BASE + 0x04)
+#define MXC_CCM_CSR (MXC_CCM_BASE + 0x08)
+#define MXC_CCM_CCSR (MXC_CCM_BASE + 0x0c)
+#define MXC_CCM_CACRR (MXC_CCM_BASE + 0x10)
+#define MXC_CCM_CBCDR (MXC_CCM_BASE + 0x14)
+#define MXC_CCM_CBCMR (MXC_CCM_BASE + 0x18)
+#define MXC_CCM_CSCMR1 (MXC_CCM_BASE + 0x1c)
+#define MXC_CCM_CSCMR2 (MXC_CCM_BASE + 0x20)
+#define MXC_CCM_CSCDR1 (MXC_CCM_BASE + 0x24)
+#define MXC_CCM_CS1CDR (MXC_CCM_BASE + 0x28)
+#define MXC_CCM_CS2CDR (MXC_CCM_BASE + 0x2c)
+#define MXC_CCM_CDCDR (MXC_CCM_BASE + 0x30)
+#define MXC_CCM_CHSCCDR (MXC_CCM_BASE + 0x34)
+#define MXC_CCM_CSCDR2 (MXC_CCM_BASE + 0x38)
+#define MXC_CCM_CSCDR3 (MXC_CCM_BASE + 0x3c)
+#define MXC_CCM_CSCDR4 (MXC_CCM_BASE + 0x40)
+#define MXC_CCM_CWDR (MXC_CCM_BASE + 0x44)
+#define MXC_CCM_CDHIPR (MXC_CCM_BASE + 0x48)
+#define MXC_CCM_CDCR (MXC_CCM_BASE + 0x4c)
+#define MXC_CCM_CTOR (MXC_CCM_BASE + 0x50)
+#define MXC_CCM_CLPCR (MXC_CCM_BASE + 0x54)
+#define MXC_CCM_CISR (MXC_CCM_BASE + 0x58)
+#define MXC_CCM_CIMR (MXC_CCM_BASE + 0x5c)
+#define MXC_CCM_CCOSR (MXC_CCM_BASE + 0x60)
+#define MXC_CCM_CGPR (MXC_CCM_BASE + 0x64)
+#define MXC_CCM_CCGR0 (MXC_CCM_BASE + 0x68)
+#define MXC_CCM_CCGR1 (MXC_CCM_BASE + 0x6C)
+#define MXC_CCM_CCGR2 (MXC_CCM_BASE + 0x70)
+#define MXC_CCM_CCGR3 (MXC_CCM_BASE + 0x74)
+#define MXC_CCM_CCGR4 (MXC_CCM_BASE + 0x78)
+#define MXC_CCM_CCGR5 (MXC_CCM_BASE + 0x7C)
+#define MXC_CCM_CCGR6 (MXC_CCM_BASE + 0x80)
+#define MXC_CCM_CCGR7 (MXC_CCM_BASE + 0x84)
+#define MXC_CCM_CMEOR (MXC_CCM_BASE + 0x88)
+
+/* Define the bits in register CCR */
+#define MXC_CCM_CCR_RBC_EN (1 << 27)
+#define MXC_CCM_CCR_REG_BYPASS_CNT_MASK (0x3F << 21)
+#define MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET (21)
+#define MXC_CCM_CCR_WB_COUNT_MASK (0x7 << 16)
+#define MXC_CCM_CCR_WB_COUNT_OFFSET (16)
+#define MXC_CCM_CCR_COSC_EN (1 << 12)
+#define MXC_CCM_CCR_OSCNT_MASK (0xFF)
+#define MXC_CCM_CCR_OSCNT_OFFSET (0)
+
+/* Define the bits in register CCDR */
+#define MXC_CCM_CCDR_MMDC_CH1_HS_MASK (1 << 16)
+#define MXC_CCM_CCDR_MMDC_CH0_HS_MASK (1 << 17)
+
+/* Define the bits in register CSR */
+#define MXC_CCM_CSR_COSC_READY (1 << 5)
+#define MXC_CCM_CSR_REF_EN_B (1 << 0)
+
+/* Define the bits in register CCSR */
+#define MXC_CCM_CCSR_PDF_540M_AUTO_DIS (1 << 15)
+#define MXC_CCM_CCSR_PDF_720M_AUTO_DIS (1 << 14)
+#define MXC_CCM_CCSR_PDF_454M_AUTO_DIS (1 << 13)
+#define MXC_CCM_CCSR_PDF_508M_AUTO_DIS (1 << 12)
+#define MXC_CCM_CCSR_PDF_594M_AUTO_DIS (1 << 11)
+#define MXC_CCM_CCSR_PDF_352M_AUTO_DIS (1 << 10)
+#define MXC_CCM_CCSR_PDF_400M_AUTO_DIS (1 << 9)
+#define MXC_CCM_CCSR_STEP_SEL (1 << 8)
+#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2)
+#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_PERIPH_CLK2_PODF_MASK (0x7 << 27)
+#define MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET (27)
+#define MXC_CCM_CBCDR_PERIPH2_CLK_SEL (1 << 26)
+#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (1 << 25)
+#define MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK (0x7 << 19)
+#define MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET (19)
+#define MXC_CCM_CBCDR_AXI_PODF_MASK (0x7 << 16)
+#define MXC_CCM_CBCDR_AXI_PODF_OFFSET (16)
+#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10)
+#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10)
+#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8)
+#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8)
+#define MXC_CCM_CBCDR_AXI_ALT_SEL_MASK (1 << 7)
+#define MXC_CCM_CBCDR_AXI_ALT_SEL_OFFSET (7)
+#define MXC_CCM_CBCDR_AXI_SEL (1 << 6)
+#define MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK (0x7 << 3)
+#define MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET (3)
+#define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_MASK (0x7 << 0)
+#define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_OFFSET (0)
+
+/* Define the bits in register CBCMR */
+#define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK (0x7 << 29)
+#define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET (29)
+#define MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK (0x7 << 26)
+#define MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET (26)
+#define MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK (0x7 << 23)
+#define MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET (23)
+#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK (0x3 << 21)
+#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET (21)
+#define MXC_CCM_CBCMR_PERIPH2_CLK2_SEL (1 << 20)
+#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << 18)
+#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET (18)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 16)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (16)
+#define MXC_CCM_CBCMR_MLB_CLK_SEL_MASK (0x3 << 16)
+#define MXC_CCM_CBCMR_MLB_CLK_SEL_OFFSET (16)
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << 12)
+#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET (12)
+#define MXC_CCM_CBCMR_VDOAXI_CLK_SEL (1 << 11)
+#define MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL (1 << 10)
+#define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK (0x3 << 8)
+#define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET (8)
+#define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK (0x3 << 4)
+#define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET (4)
+#define MXC_CCM_CBCMR_GPU3D_AXI_CLK_SEL (1 << 1)
+#define MXC_CCM_CBCMR_GPU2D_AXI_CLK_SEL (1 << 0)
+
+/* Define the bits in register CSCMR1 */
+#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK (0x3 << 29)
+#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET (29)
+#define MXC_CCM_CSCMR1_ACLK_EMI_MASK (0x3 << 27)
+#define MXC_CCM_CSCMR1_ACLK_EMI_OFFSET (27)
+#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK (0x7 << 23)
+#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET (23)
+#define MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK (0x7 << 20)
+#define MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET (20)
+#define MXC_CCM_CSCMR1_USDHC4_CLK_SEL (1 << 19)
+#define MXC_CCM_CSCMR1_USDHC3_CLK_SEL (1 << 18)
+#define MXC_CCM_CSCMR1_USDHC2_CLK_SEL (1 << 17)
+#define MXC_CCM_CSCMR1_USDHC1_CLK_SEL (1 << 16)
+#define MXC_CCM_CSCMR1_SSI3_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 10)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (10)
+#define MXC_CCM_CSCMR1_PERCLK_CLK_SEL_MASK (0x1 << 6)
+#define MXC_CCM_CSCMR1_PERCLK_CLK_SEL_OFFSET (6)
+#define MXC_CCM_CSCMR1_PERCLK_PODF_MASK (0x3F)
+#define MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET (0)
+
+/* Define the bits in register CSCMR2 */
+#define MXC_CCM_CSCMR2_ESAI_CLK_SEL_MASK (0x3 << 19)
+#define MXC_CCM_CSCMR2_ESAI_CLK_SEL_OFFSET (19)
+#define MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV (1 << 11)
+#define MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV (1 << 10)
+#define MXC_CCM_CSCMR2_CAN_CLK_PODF_MASK (0x3F << 2)
+#define MXC_CCM_CSCMR2_CAN_CLK_PODF_OFFSET (2)
+
+/* Define the bits in register CSCDR1 */
+#define MXC_CCM_CSCDR1_VPU_AXI_PODF_MASK (0x7 << 25)
+#define MXC_CCM_CSCDR1_VPU_AXI_PODF_OFFSET (25)
+#define MXC_CCM_CSCDR1_USDHC4_PODF_MASK (0x7 << 22)
+#define MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET (22)
+#define MXC_CCM_CSCDR1_USDHC3_PODF_MASK (0x7 << 19)
+#define MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET (19)
+#define MXC_CCM_CSCDR1_USDHC2_PODF_MASK (0x7 << 16)
+#define MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET (16)
+#define MXC_CCM_CSCDR1_USDHC1_PODF_MASK (0x7 << 11)
+#define MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET (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_UART_CLK_SEL_MASK (0x1 << 6)
+#define MXC_CCM_CSCDR1_UART_CLK_SEL_OFFSET (6)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x3F)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0)
+
+/* Define the bits in register CS1CDR */
+#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK (0x7 << 25)
+#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET (25)
+#define MXC_CCM_CS1CDR_SSI3_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CS1CDR_SSI3_CLK_PRED_OFFSET (22)
+#define MXC_CCM_CS1CDR_SSI3_CLK_PODF_MASK (0x3F << 16)
+#define MXC_CCM_CS1CDR_SSI3_CLK_PODF_OFFSET (16)
+#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK (0x7 << 9)
+#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET (9)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0)
+
+/* Define the bits in register CS2CDR */
+#define MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK (0x3F << 21)
+#define MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET (21)
+#define MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK (0x7 << 18)
+#define MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET (18)
+#define MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK (0x3 << 16)
+#define MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET (16)
+#define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK (0x7 << 12)
+#define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET (12)
+#define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK (0x7 << 9)
+#define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET (9)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0)
+
+/* Define the bits in register CDCDR */
+#define MXC_CCM_CDCDR_HSI_TX_PODF_MASK (0x7 << 29)
+#define MXC_CCM_CDCDR_HSI_TX_PODF_OFFSET (29)
+#define MXC_CCM_CDCDR_HSI_TX_CLK_SEL (1 << 28)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x7 << 22)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (22)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_MASK (0x3 << 20)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_OFFSET (20)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 12)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (12)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x7 << 9)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_MASK (0x3 << 7)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_OFFSET (7)
+
+/* Define the bits in register CHSCCDR */
+#define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MASK (0x7 << 15)
+#define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_OFFSET (15)
+#define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK (0x7 << 12)
+#define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET (12)
+#define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_MASK (0x7 << 9)
+#define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET (9)
+#define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK (0x7 << 6)
+#define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET (6)
+#define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK (0x7 << 3)
+#define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET (3)
+#define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK (0x7)
+#define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET (0)
+
+/* Define the bits in register CSCDR2 */
+#define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK (0x3F << 19)
+#define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET (19)
+#define MXC_CCM_CSCDR2_ECSPI_CLK_SEL_MASK (0x1 << 18)
+#define MXC_CCM_CSCDR2_ECSPI_CLK_SEL_OFFSET (18)
+#define MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_MASK (0x7 << 15)
+#define MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_OFFSET (15)
+#define MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK (0x7 << 12)
+#define MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET (12)
+#define MXC_CCM_CSCDR2_IPU2_DI1_CLK_SEL_MASK (0x7 << 9)
+#define MXC_CCM_CSCDR2_IPU2_DI1_CLK_SEL_OFFSET (9)
+#define MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_MASK (0x7 << 6)
+#define MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_OFFSET (6)
+#define MXC_CCM_CSCDR2_IPU2_DI0_PODF_MASK (0x7 << 3)
+#define MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET (3)
+#define MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_MASK (0x7)
+#define MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_OFFSET (0)
+
+/* Define the bits in register CSCDR3 */
+#define MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK (0x7 << 16)
+#define MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET (16)
+#define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK (0x7 << 11)
+#define MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET (11)
+#define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK (0x3 << 9)
+#define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET (9)
+
+/* Define the bits in register CDHIPR */
+#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16)
+#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5)
+#define MXC_CCM_CDHIPR_MMDC_CH0_PODF_BUSY (1 << 4)
+#define MXC_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY (1 << 3)
+#define MXC_CCM_CDHIPR_MMDC_CH1_PODF_BUSY (1 << 2)
+#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 1)
+#define MXC_CCM_CDHIPR_AXI_PODF_BUSY (1)
+
+/* Define the bits in register CLPCR */
+#define MXC_CCM_CLPCR_MASK_L2CC_IDLE (1 << 27)
+#define MXC_CCM_CLPCR_MASK_SCU_IDLE (1 << 26)
+#define MXC_CCM_CLPCR_MASK_CORE3_WFI (1 << 25)
+#define MXC_CCM_CLPCR_MASK_CORE2_WFI (1 << 24)
+#define MXC_CCM_CLPCR_MASK_CORE1_WFI (1 << 23)
+#define MXC_CCM_CLPCR_MASK_CORE0_WFI (1 << 22)
+#define MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS (1 << 21)
+#define MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS (1 << 19)
+#define MXC_CCM_CLPCR_WB_CORE_AT_LPM (1 << 17)
+#define MXC_CCM_CLPCR_WB_PER_AT_LPM (1 << 16)
+#define MXC_CCM_CLPCR_COSC_PWRDOWN (1 << 11)
+#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9)
+#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9)
+#define MXC_CCM_CLPCR_VSTBY (1 << 8)
+#define MXC_CCM_CLPCR_DIS_REF_OSC (1 << 7)
+#define MXC_CCM_CLPCR_SBYOS (1 << 6)
+#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (1 << 5)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3)
+#define MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY (1 << 2)
+#define MXC_CCM_CLPCR_LPM_MASK (0x3)
+#define MXC_CCM_CLPCR_LPM_OFFSET (0)
+
+/* Define the bits in register CISR */
+#define MXC_CCM_CISR_ARM_PODF_LOADED (1 << 26)
+#define MXC_CCM_CISR_MMDC_CH0_PODF_LOADED (1 << 23)
+#define MXC_CCM_CISR_PERIPH_CLK_SEL_LOADED (1 << 22)
+#define MXC_CCM_CISR_MMDC_CH1_PODF_LOADED (1 << 21)
+#define MXC_CCM_CISR_AHB_PODF_LOADED (1 << 20)
+#define MXC_CCM_CISR_PERIPH2_CLK_SEL_LOADED (1 << 19)
+#define MXC_CCM_CISR_AXI_PODF_LOADED (1 << 17)
+#define MXC_CCM_CISR_COSC_READY (1 << 6)
+#define MXC_CCM_CISR_LRF_PLL (1)
+
+/* Define the bits in register CIMR */
+#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (1 << 26)
+#define MXC_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED (1 << 23)
+#define MXC_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED (1 << 22)
+#define MXC_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED (1 << 21)
+#define MXC_CCM_CIMR_MASK_AHB_PODF_LOADED (1 << 20)
+#define MXC_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED (1 << 22)
+#define MXC_CCM_CIMR_MASK_AXI_PODF_LOADED (1 << 17)
+#define MXC_CCM_CIMR_MASK_COSC_READY (1 << 6)
+#define MXC_CCM_CIMR_MASK_LRF_PLL (1)
+
+/* Define the bits in register CCOSR */
+#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (24)
+#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21)
+#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21)
+#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16)
+#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16)
+#define MXC_CCM_CCOSR_CKOL_MIRROR_CKO2_MASK (1 << 8)
+#define MXC_CCM_CCOSR_CKOL_EN_OFFSET 7
+#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7)
+#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4)
+#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4)
+#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF)
+#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0)
+
+/* Define the bits in registers CGPR */
+#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (1 << 4)
+#define MXC_CCM_CGPR_MMDC_EXT_CLK_DIS (1 << 2)
+#define MXC_CCM_CGPR_PMIC_DELAY_SCALER (1)
+#define MXC_CCM_CGPR_MEM_IPG_STOP_MASK (1 << 1)
+#define MXC_CCM_CGPR_WAIT_MODE_FIX (1 << 17)
+
+/* 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_CG7_MASK (0x3 << 14)
+#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
+
+#endif /* __ARCH_ARM_MACH_MX6_CRM_REGS_H__ */
diff --git a/arch/arm/mach-mx6/devices-imx6q.h b/arch/arm/mach-mx6/devices-imx6q.h
new file mode 100644
index 00000000..4525e29a
--- /dev/null
+++ b/arch/arm/mach-mx6/devices-imx6q.h
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011-2012 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 <mach/mx6.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_imx_uart_1irq_data imx6q_imx_uart_data[] __initconst;
+#define imx6q_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx6q_imx_uart_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx6sl_imx_uart_data[] __initconst;
+#define imx6sl_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx6sl_imx_uart_data[id], pdata)
+
+extern const struct imx_snvs_rtc_data imx6q_imx_snvs_rtc_data __initconst;
+#define imx6q_add_imx_snvs_rtc() \
+ imx_add_snvs_rtc(&imx6q_imx_snvs_rtc_data)
+
+extern const struct imx_caam_data imx6q_imx_caam_data __initconst;
+#define imx6q_add_imx_caam() \
+ imx_add_caam(&imx6q_imx_caam_data)
+
+extern const struct imx_anatop_thermal_imx_data
+imx6q_anatop_thermal_imx_data __initconst;
+#define imx6q_add_anatop_thermal_imx(id, pdata) \
+ imx_add_anatop_thermal_imx(&imx6q_anatop_thermal_imx_data, pdata)
+
+extern const struct imx_dma_res_data imx6q_dma_res_data __initconst;
+#define imx6q_add_dma() imx_add_dma(&imx6q_dma_res_data);
+
+#define imx6q_add_gpmi(platform_data) imx_add_gpmi(platform_data);
+
+extern const struct imx_fec_data imx6q_fec_data __initconst;
+#define imx6q_add_fec(pdata) \
+ imx_add_fec(&imx6q_fec_data, pdata)
+extern const struct imx_fec_data imx6sl_fec_data __initconst;
+#define imx6sl_add_fec(pdata) \
+ imx_add_fec(&imx6sl_fec_data, pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data
+imx6q_sdhci_usdhc_imx_data[] __initconst;
+#define imx6q_add_sdhci_usdhc_imx(id, pdata) \
+ imx_add_sdhci_esdhc_imx(&imx6q_sdhci_usdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx6q_ecspi_data[] __initconst;
+#define imx6q_add_ecspi(id, pdata) \
+ imx_add_spi_imx(&imx6q_ecspi_data[id], pdata)
+
+extern const struct imx_imx_i2c_data imx6q_imx_i2c_data[] __initconst;
+#define imx6q_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx6q_imx_i2c_data[id], pdata)
+
+extern const struct imx_fsl_usb2_udc_data imx6q_fsl_usb2_udc_data __initconst;
+#define imx6q_add_fsl_usb2_udc(pdata) \
+ imx_add_fsl_usb2_udc(&imx6q_fsl_usb2_udc_data, pdata)
+
+extern const struct imx_mxc_ehci_data imx6q_mxc_ehci_otg_data __initconst;
+#define imx6q_add_fsl_ehci_otg(pdata) \
+ imx_add_fsl_ehci(&imx6q_mxc_ehci_otg_data, pdata)
+
+extern const struct imx_mxc_ehci_data imx6q_mxc_ehci_hs_data[] __initconst;
+#define imx6q_add_fsl_ehci_hs(id, pdata) \
+ imx_add_fsl_ehci(&imx6q_mxc_ehci_hs_data[id - 1], pdata)
+
+extern const struct imx_mxc_ehci_data imx6sl_mxc_ehci_hs_data[] __initconst;
+#define imx6sl_add_fsl_ehci_hs(id, pdata) \
+ imx_add_fsl_ehci(&imx6sl_mxc_ehci_hs_data[id - 1], pdata)
+
+extern const struct imx_fsl_usb2_otg_data imx6q_fsl_usb2_otg_data __initconst;
+#define imx6q_add_fsl_usb2_otg(pdata) \
+ imx_add_fsl_usb2_otg(&imx6q_fsl_usb2_otg_data, pdata)
+
+extern const struct imx_fsl_usb2_wakeup_data imx6q_fsl_otg_wakeup_data __initconst;
+#define imx6q_add_fsl_usb2_otg_wakeup(pdata) \
+ imx_add_fsl_usb2_wakeup(&imx6q_fsl_otg_wakeup_data, pdata)
+
+extern const struct imx_fsl_usb2_wakeup_data imx6q_fsl_hs_wakeup_data[] __initconst;
+#define imx6q_add_fsl_usb2_hs_wakeup(id, pdata) \
+ imx_add_fsl_usb2_wakeup(&imx6q_fsl_hs_wakeup_data[id - 1], pdata)
+
+extern const struct imx_fsl_usb2_wakeup_data imx6sl_fsl_hs_wakeup_data[] __initconst;
+#define imx6sl_add_fsl_usb2_hs_wakeup(id, pdata) \
+ imx_add_fsl_usb2_wakeup(&imx6sl_fsl_hs_wakeup_data[id - 1], pdata)
+
+extern const struct imx_imx_esai_data imx6q_imx_esai_data[] __initconst;
+#define imx6q_add_imx_esai(id, pdata) \
+ imx_add_imx_esai(&imx6q_imx_esai_data[id], pdata)
+
+extern const struct imx_viv_gpu_data imx6_gpu_data __initconst;
+
+extern const struct imx_ahci_data imx6q_ahci_data __initconst;
+#define imx6q_add_ahci(id, pdata) \
+ imx_add_ahci(&imx6q_ahci_data, pdata)
+
+extern const struct imx_imx_ssi_data imx6_imx_ssi_data[] __initconst;
+#define imx6q_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx6_imx_ssi_data[id], pdata)
+
+extern const struct imx_ipuv3_data imx6q_ipuv3_data[] __initconst;
+#define imx6q_add_ipuv3(id, pdata) imx_add_ipuv3(id, &imx6q_ipuv3_data[id], pdata)
+#define imx6q_add_ipuv3fb(id, pdata) imx_add_ipuv3_fb(id, pdata)
+
+#define imx6q_add_lcdif(pdata) \
+ platform_device_register_resndata(NULL, "mxc_lcdif",\
+ 0, NULL, 0, pdata, sizeof(*pdata));
+
+extern const struct imx_ldb_data imx6q_ldb_data __initconst;
+#define imx6q_add_ldb(pdata) \
+ imx_add_ldb(&imx6q_ldb_data, pdata);
+
+#define imx6q_add_v4l2_output(id) \
+ platform_device_register_resndata(NULL, "mxc_v4l2_output",\
+ id, NULL, 0, NULL, 0);
+
+#define imx6q_add_v4l2_capture(id, pdata) \
+ platform_device_register_resndata(NULL, "mxc_v4l2_capture",\
+ id, NULL, 0, pdata, sizeof(*pdata));
+
+extern const struct imx_mxc_hdmi_data imx6q_mxc_hdmi_data __initconst;
+#define imx6q_add_mxc_hdmi(pdata) \
+ imx_add_mxc_hdmi(&imx6q_mxc_hdmi_data, pdata)
+
+extern const struct imx_mxc_hdmi_core_data imx6q_mxc_hdmi_core_data __initconst;
+#define imx6q_add_mxc_hdmi_core(pdata) \
+ imx_add_mxc_hdmi_core(&imx6q_mxc_hdmi_core_data, pdata)
+
+extern const struct imx_vpu_data imx6q_vpu_data __initconst;
+#define imx6q_add_vpu() imx_add_vpu(&imx6q_vpu_data)
+
+extern const struct imx_otp_data imx6q_otp_data __initconst;
+#define imx6q_add_otp() \
+ imx_add_otp(&imx6q_otp_data)
+
+extern const struct imx_viim_data imx6q_viim_data __initconst;
+#define imx6q_add_viim() \
+ imx_add_viim(&imx6q_viim_data)
+
+extern const struct imx_imx2_wdt_data imx6q_imx2_wdt_data[] __initconst;
+#define imx6q_add_imx2_wdt(id, pdata) \
+ imx_add_imx2_wdt(&imx6q_imx2_wdt_data[id])
+
+extern const struct imx_pm_imx_data imx6q_pm_imx_data __initconst;
+#define imx6q_add_pm_imx(id, pdata) \
+ imx_add_pm_imx(&imx6q_pm_imx_data, pdata)
+
+extern const struct imx_imx_asrc_data imx6q_imx_asrc_data[] __initconst;
+#define imx6q_add_asrc(pdata) \
+ imx_add_imx_asrc(imx6q_imx_asrc_data, pdata)
+
+extern const struct imx_dvfs_core_data imx6q_dvfs_core_data __initconst;
+#define imx6q_add_dvfs_core(pdata) \
+ imx_add_dvfs_core(&imx6q_dvfs_core_data, pdata)
+
+extern const struct imx_viv_gpu_data imx6_gc2000_data __initconst;
+extern const struct imx_viv_gpu_data imx6_gc320_data __initconst;
+extern const struct imx_viv_gpu_data imx6_gc355_data __initconst;
+
+extern const struct imx_mxc_pwm_data imx6q_mxc_pwm_data[] __initconst;
+#define imx6q_add_mxc_pwm(id) \
+ imx_add_mxc_pwm(&imx6q_mxc_pwm_data[id])
+
+#define imx6q_add_mxc_pwm_backlight(id, pdata) \
+ platform_device_register_resndata(NULL, "pwm-backlight",\
+ id, NULL, 0, pdata, sizeof(*pdata));
+
+extern const struct imx_spdif_data imx6q_imx_spdif_data __initconst;
+#define imx6q_add_spdif(pdata) imx_add_spdif(&imx6q_imx_spdif_data, pdata)
+
+extern const struct imx_spdif_dai_data imx6q_spdif_dai_data __initconst;
+#define imx6q_add_spdif_dai() imx_add_spdif_dai(&imx6q_spdif_dai_data)
+
+#define imx6q_add_spdif_audio_device(pdata) imx_add_spdif_audio_device()
+
+#define imx6q_add_hdmi_soc() imx_add_hdmi_soc()
+extern const struct imx_hdmi_soc_data imx6q_imx_hdmi_soc_dai_data __initconst;
+#define imx6q_add_hdmi_soc_dai() \
+ imx_add_hdmi_soc_dai(&imx6q_imx_hdmi_soc_dai_data)
+
+extern const struct imx_mipi_dsi_data imx6q_mipi_dsi_data __initconst;
+#define imx6q_add_mipi_dsi(pdata) \
+ imx_add_mipi_dsi(&imx6q_mipi_dsi_data, pdata)
+
+extern const struct imx_flexcan_data imx6q_flexcan_data[] __initconst;
+#define imx6q_add_flexcan(id, pdata) \
+ imx_add_flexcan(&imx6q_flexcan_data[id], pdata)
+#define imx6q_add_flexcan0(pdata) imx6q_add_flexcan(0, pdata)
+#define imx6q_add_flexcan1(pdata) imx6q_add_flexcan(1, pdata)
+
+extern const struct imx_mipi_csi2_data imx6q_mipi_csi2_data __initconst;
+#define imx6q_add_mipi_csi2(pdata) \
+ imx_add_mipi_csi2(&imx6q_mipi_csi2_data, pdata)
+
+extern const struct imx_perfmon_data imx6q_perfmon_data[] __initconst;
+#define imx6q_add_perfmon(id) \
+ imx_add_perfmon(&imx6q_perfmon_data[id])
+
+extern const struct imx_mxc_mlb_data imx6q_mxc_mlb150_data __initconst;
+#define imx6q_add_mlb150(pdata) \
+ imx_add_mlb(pdata)
+
+extern const struct imx_pxp_data imx6dl_pxp_data __initconst;
+#define imx6dl_add_imx_pxp() \
+ imx_add_imx_pxp(&imx6dl_pxp_data)
+
+#define imx6dl_add_imx_pxp_client() \
+ imx_add_imx_pxp_client()
+
+#define imx6sl_add_imx_pxp_v4l2() \
+ imx_add_imx_pxp_v4l2()
+
+extern const struct imx_fsl_csi_data imx6sl_csi_data __initconst;
+#define imx6sl_add_fsl_csi() \
+ imx_add_fsl_csi(&imx6sl_csi_data)
+
+extern const struct imx_epdc_data imx6dl_epdc_data __initconst;
+#define imx6dl_add_imx_epdc(pdata) \
+ imx_add_imx_epdc(&imx6dl_epdc_data, pdata)
+
+extern const struct imx_epdc_data imx6sl_spdc_data __initconst;
+#define imx6sl_add_imx_spdc(pdata) \
+ imx_add_imx_spdc(&imx6sl_spdc_data, pdata)
+
+extern const struct imx_elcdif_data imx6dl_elcdif_data __initconst;
+#define imx6dl_add_imx_elcdif(pdata) \
+ imx_add_imx_elcdif(&imx6dl_elcdif_data, pdata)
+extern const struct imx_vdoa_data imx6q_vdoa_data __initconst;
+#define imx6q_add_vdoa() imx_add_vdoa(&imx6q_vdoa_data)
+
+extern const struct imx_pcie_data imx6q_pcie_data __initconst;
+#define imx6q_add_pcie(pdata) imx_add_pcie(&imx6q_pcie_data, pdata)
+
+#define imx6q_add_busfreq(pdata) imx_add_busfreq(pdata)
+
+#define imx6q_add_ion(id, pdata, size) \
+ platform_device_register_resndata(NULL, "ion-mxc",\
+ id, NULL, 0, pdata, size);
+
+extern const struct imx_imx_keypad_data imx6sl_imx_keypad_data;
+#define imx6sl_add_imx_keypad(pdata) \
+ imx_add_imx_keypad(&imx6sl_imx_keypad_data, pdata)
+
+extern const struct imx_dcp_data imx6sl_dcp_data __initconst;
+#define imx6sl_add_dcp() \
+ imx_add_dcp(&imx6sl_dcp_data);
+
+extern const struct imx_rngb_data imx6sl_rngb_data __initconst;
+#define imx6sl_add_rngb() \
+ imx_add_rngb(&imx6sl_rngb_data);
+
+#define imx6_add_armpmu() imx_add_imx_armpmu()
diff --git a/arch/arm/mach-mx6/devices.c b/arch/arm/mach-mx6/devices.c
new file mode 100644
index 00000000..29becab0
--- /dev/null
+++ b/arch/arm/mach-mx6/devices.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011-2012 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/ipu.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/uio_driver.h>
+#include <linux/iram_alloc.h>
+#include <linux/fsl_devices.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+
+static struct mxc_gpio_port mxc_gpio_ports[] = {
+ {
+ .chip.label = "gpio-0",
+ .base = IO_ADDRESS(GPIO1_BASE_ADDR),
+ .irq = MXC_INT_GPIO1_INT15_0_NUM,
+ .irq_high = MXC_INT_GPIO1_INT31_16_NUM,
+ .virtual_irq_start = MXC_GPIO_IRQ_START
+ },
+ {
+ .chip.label = "gpio-1",
+ .base = IO_ADDRESS(GPIO2_BASE_ADDR),
+ .irq = MXC_INT_GPIO2_INT15_0_NUM,
+ .irq_high = MXC_INT_GPIO2_INT31_16_NUM,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1
+ },
+ {
+ .chip.label = "gpio-2",
+ .base = IO_ADDRESS(GPIO3_BASE_ADDR),
+ .irq = MXC_INT_GPIO3_INT15_0_NUM,
+ .irq_high = MXC_INT_GPIO3_INT31_16_NUM,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2
+ },
+ {
+ .chip.label = "gpio-3",
+ .base = IO_ADDRESS(GPIO4_BASE_ADDR),
+ .irq = MXC_INT_GPIO4_INT15_0_NUM,
+ .irq_high = MXC_INT_GPIO4_INT31_16_NUM,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
+ },
+ {
+ .chip.label = "gpio-4",
+ .base = IO_ADDRESS(GPIO5_BASE_ADDR),
+ .irq = MXC_INT_GPIO5_INT15_0_NUM,
+ .irq_high = MXC_INT_GPIO5_INT31_16_NUM,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4
+ },
+ {
+ .chip.label = "gpio-5",
+ .base = IO_ADDRESS(GPIO6_BASE_ADDR),
+ .irq = MXC_INT_GPIO6_INT15_0_NUM,
+ .irq_high = MXC_INT_GPIO6_INT31_16_NUM,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5
+ },
+ {
+ .chip.label = "gpio-6",
+ .base = IO_ADDRESS(GPIO7_BASE_ADDR),
+ .irq = MXC_INT_GPIO7_INT15_0_NUM,
+ .irq_high = MXC_INT_GPIO7_INT31_16_NUM,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6
+ },
+};
+
+int mx6q_register_gpios(void)
+{
+ /* 7 ports for Mx6 */
+ return mxc_gpio_init(mxc_gpio_ports, 7);
+}
diff --git a/arch/arm/mach-mx6/dummy_gpio.c b/arch/arm/mach-mx6/dummy_gpio.c
new file mode 100644
index 00000000..006397bc
--- /dev/null
+++ b/arch/arm/mach-mx6/dummy_gpio.c
@@ -0,0 +1,124 @@
+/*
+ * 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.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+
+void gpio_uart_active(int port, int no_irda) {}
+EXPORT_SYMBOL(gpio_uart_active);
+
+void gpio_uart_inactive(int port, int no_irda) {}
+EXPORT_SYMBOL(gpio_uart_inactive);
+
+void gpio_gps_active(void) {}
+EXPORT_SYMBOL(gpio_gps_active);
+
+void gpio_gps_inactive(void) {}
+EXPORT_SYMBOL(gpio_gps_inactive);
+
+void config_uartdma_event(int port) {}
+EXPORT_SYMBOL(config_uartdma_event);
+
+void gpio_spi_active(int cspi_mod) {}
+EXPORT_SYMBOL(gpio_spi_active);
+
+void gpio_spi_inactive(int cspi_mod) {}
+EXPORT_SYMBOL(gpio_spi_inactive);
+
+void gpio_owire_active(void) {}
+EXPORT_SYMBOL(gpio_owire_active);
+
+void gpio_owire_inactive(void) {}
+EXPORT_SYMBOL(gpio_owire_inactive);
+
+void gpio_i2c_active(int i2c_num) {}
+EXPORT_SYMBOL(gpio_i2c_active);
+
+void gpio_i2c_inactive(int i2c_num) {}
+EXPORT_SYMBOL(gpio_i2c_inactive);
+
+void gpio_i2c_hs_active(void) {}
+EXPORT_SYMBOL(gpio_i2c_hs_active);
+
+void gpio_i2c_hs_inactive(void) {}
+EXPORT_SYMBOL(gpio_i2c_hs_inactive);
+
+void gpio_pmic_active(void) {}
+EXPORT_SYMBOL(gpio_pmic_active);
+
+void gpio_activate_audio_ports(void) {}
+EXPORT_SYMBOL(gpio_activate_audio_ports);
+
+void gpio_sdhc_active(int module) {}
+EXPORT_SYMBOL(gpio_sdhc_active);
+
+void gpio_sdhc_inactive(int module) {}
+EXPORT_SYMBOL(gpio_sdhc_inactive);
+
+void gpio_sensor_select(int sensor) {}
+
+void gpio_sensor_active(unsigned int csi) {}
+EXPORT_SYMBOL(gpio_sensor_active);
+
+void gpio_sensor_inactive(unsigned int csi) {}
+EXPORT_SYMBOL(gpio_sensor_inactive);
+
+void gpio_ata_active(void) {}
+EXPORT_SYMBOL(gpio_ata_active);
+
+void gpio_ata_inactive(void) {}
+EXPORT_SYMBOL(gpio_ata_inactive);
+
+void gpio_nand_active(void) {}
+EXPORT_SYMBOL(gpio_nand_active);
+
+void gpio_nand_inactive(void) {}
+EXPORT_SYMBOL(gpio_nand_inactive);
+
+void gpio_keypad_active(void) {}
+EXPORT_SYMBOL(gpio_keypad_active);
+
+void gpio_keypad_inactive(void) {}
+EXPORT_SYMBOL(gpio_keypad_inactive);
+
+int gpio_usbotg_hs_active(void)
+{
+ return 0;
+}
+EXPORT_SYMBOL(gpio_usbotg_hs_active);
+
+void gpio_usbotg_hs_inactive(void) {}
+EXPORT_SYMBOL(gpio_usbotg_hs_inactive);
+
+void gpio_fec_active(void) {}
+EXPORT_SYMBOL(gpio_fec_active);
+
+void gpio_fec_inactive(void) {}
+EXPORT_SYMBOL(gpio_fec_inactive);
+
+void gpio_spdif_active(void) {}
+EXPORT_SYMBOL(gpio_spdif_active);
+
+void gpio_spdif_inactive(void) {}
+EXPORT_SYMBOL(gpio_spdif_inactive);
+
+void gpio_mlb_active(void) {}
+EXPORT_SYMBOL(gpio_mlb_active);
+
+void gpio_mlb_inactive(void) {}
+EXPORT_SYMBOL(gpio_mlb_inactive);
diff --git a/arch/arm/mach-mx6/etm.c b/arch/arm/mach-mx6/etm.c
new file mode 100644
index 00000000..8f328608
--- /dev/null
+++ b/arch/arm/mach-mx6/etm.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 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 <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/iram_alloc.h>
+#include <linux/delay.h>
+#include <linux/amba/bus.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/coresight.h>
+
+static struct __init amba_device mx6_etb_device = {
+ .dev = {
+ .init_name = "etb",
+ },
+ .res = {
+ .start = MX6Q_ETB_BASE_ADDR,
+ .end = MX6Q_ETB_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .periphid = 0x3bb907,
+};
+
+static struct __init amba_device mx6_etm_device[] = {
+ {
+ .dev = {
+ .init_name = "etm.0",
+ },
+ .res = {
+ .start = MX6Q_PTM0_BASE_ADDR,
+ .end = MX6Q_PTM0_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.1",
+ },
+ .res = {
+ .start = MX6Q_PTM1_BASE_ADDR,
+ .end = MX6Q_PTM1_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.2",
+ },
+ .res = {
+ .start = MX6Q_PTM2_BASE_ADDR,
+ .end = MX6Q_PTM2_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.3",
+ },
+ .res = {
+ .start = MX6Q_PTM3_BASE_ADDR,
+ .end = MX6Q_PTM3_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+};
+
+#define FUNNEL_CTL 0
+static int __init etm_init(void)
+{
+ int i;
+ __iomem void *base;
+ base = ioremap(0x02144000, SZ_4K);
+ /*Unlock Funnel*/
+ __raw_writel(UNLOCK_MAGIC, base + CSMR_LOCKACCESS);
+ /*Enable all funnel port*/
+ __raw_writel(__raw_readl(base + FUNNEL_CTL) | 0xFF,
+ base + FUNNEL_CTL);
+ /*Lock Funnel*/
+ __raw_writel(0, base + CSMR_LOCKACCESS);
+ iounmap(base);
+
+ amba_device_register(&mx6_etb_device, &iomem_resource);
+ for (i = 0; i < num_possible_cpus(); i++)
+ amba_device_register(mx6_etm_device + i, &iomem_resource);
+
+ return 0;
+}
+
+subsys_initcall(etm_init);
diff --git a/arch/arm/mach-mx6/headsmp.S b/arch/arm/mach-mx6/headsmp.S
new file mode 100644
index 00000000..9492d8dc
--- /dev/null
+++ b/arch/arm/mach-mx6/headsmp.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011-2012 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 <linux/linkage.h>
+#include <linux/init.h>
+
+ENTRY(v7_invalidate_l1)
+ mov r0, #0
+ mcr p15, 2, r0, c0, c0, 0
+ mrc p15, 1, r0, c0, c0, 0
+
+ ldr r1, =0x7fff
+ and r2, r1, r0, lsr #13
+
+ ldr r1, =0x3ff
+
+ and r3, r1, r0, lsr #3 @ NumWays - 1
+ add r2, r2, #1 @ NumSets
+
+ and r0, r0, #0x7
+ add r0, r0, #4 @ SetShift
+
+ clz r1, r3 @ WayShift
+ add r4, r3, #1 @ NumWays
+1: sub r2, r2, #1 @ NumSets--
+ mov r3, r4 @ Temp = NumWays
+2: subs r3, r3, #1 @ Temp--
+ mov r5, r3, lsl r1
+ mov r6, r2, lsl r0
+ orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+ mcr p15, 0, r5, c7, c6, 2
+ bgt 2b
+ cmp r2, #0
+ bgt 1b
+ dsb
+ isb
+ mov pc, lr
+ENDPROC(v7_invalidate_l1)
+
+ __CPUINIT
+ENTRY(mx6_secondary_startup)
+
+ /* Invalidate L1 I-cache first */
+ mov r1, #0x0
+ mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache
+ /* Invalidate L1 D-cache */
+ bl v7_invalidate_l1
+ /* Set ARM working mode */
+ msr cpsr_fsxc, #0xd3
+
+ mrc p15, 0, r0, c0, c0, 5
+ and r0, r0, #15
+ ldr r1, = 0x020d8020
+ add r1, r0, LSL#3
+
+ /*Clear SRC_GPR register */
+ mov r0, #0
+ str r0, [r1]
+ str r0, [r1, #0x4]
+
+ /* Jump to secondary_startup */
+ b secondary_startup
+
+ENDPROC(mx6_secondary_startup)
diff --git a/arch/arm/mach-mx6/irq.c b/arch/arm/mach-mx6/irq.c
new file mode 100644
index 00000000..d298d50b
--- /dev/null
+++ b/arch/arm/mach-mx6/irq.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2011-2013 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <asm/hardware/gic.h>
+#include <mach/hardware.h>
+#ifdef CONFIG_CPU_FREQ_GOV_INTERACTIVE
+#include <linux/cpufreq.h>
+#endif
+#ifdef CONFIG_PCI_MSI
+#include "msi.h"
+#endif
+
+int mx6q_register_gpios(void);
+unsigned int gpc_wake_irq[4];
+extern bool enable_wait_mode;
+#ifdef CONFIG_CPU_FREQ_GOV_INTERACTIVE
+extern int cpufreq_gov_irq_tuner_register(struct irq_tuner dbs_irq_tuner);
+#endif
+
+static int mx6_gic_irq_set_wake(struct irq_data *d, unsigned int enable)
+{
+ if ((d->irq < MXC_INT_START) || (d->irq > MXC_INT_END)) {
+ printk(KERN_ERR "Invalid irq number!\n");
+ return -EINVAL;
+ }
+
+ if (enable) {
+ gpc_wake_irq[d->irq / 32 - 1] |= 1 << (d->irq % 32);
+ printk(KERN_INFO "add wake up source irq %d\n", d->irq);
+ } else {
+ printk(KERN_INFO "remove wake up source irq %d\n", d->irq);
+ gpc_wake_irq[d->irq / 32 - 1] &= ~(1 << (d->irq % 32));
+ }
+ return 0;
+}
+#ifdef CONFIG_CPU_FREQ_GOV_INTERACTIVE
+static struct irq_tuner mxc_irq_tuner[] = {
+ {
+ .irq_number = 41, /* GPU 3D */
+ .up_threshold = 0,
+ .enable = 0,},
+ {
+ .irq_number = 42, /* GPU 2D */
+ .up_threshold = 40,
+ .enable = 0,},
+ {
+ .irq_number = 43, /* GPU VG */
+ .up_threshold = 0,
+ .enable = 0,},
+ {
+ .irq_number = 42, /* GPU 2D */
+ .up_threshold = 40,
+ .enable = 1,},
+ {
+ .irq_number = 43, /* GPU VG */
+ .up_threshold = 0,
+ .enable = 1,},
+ {
+ .irq_number = 54, /* uSDHC1 */
+ .up_threshold = 4,
+ .enable = 1,},
+ {
+ .irq_number = 55, /* uSDHC2 */
+ .up_threshold = 4,
+ .enable = 1,},
+ {
+ .irq_number = 56, /* uSDHC3 */
+ .up_threshold = 4,
+ .enable = 1,},
+ {
+ .irq_number = 57, /* uSDHC4 */
+ .up_threshold = 4,
+ .enable = 1,},
+ {
+ .irq_number = 71, /* SATA */
+ .up_threshold = 4,
+ .enable = 1,},
+ {
+ .irq_number = 75, /* OTG */
+ .up_threshold = 10,
+ .enable = 1,},
+ {
+ .irq_number = 150, /* ENET */
+ .up_threshold = 4,
+ .enable = 1,},
+ {
+ .irq_number = 0, /* END */
+ .up_threshold = 0,
+ .enable = 0,},
+};
+#endif
+void mx6_init_irq(void)
+{
+ void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+ struct irq_desc *desc;
+ unsigned int i;
+
+ /* start offset if private timer irq id, which is 29.
+ * ID table:
+ * Global timer, PPI -> ID27
+ * A legacy nFIQ, PPI -> ID28
+ * Private timer, PPI -> ID29
+ * Watchdog timers, PPI -> ID30
+ * A legacy nIRQ, PPI -> ID31
+ */
+ gic_init(0, 29, IO_ADDRESS(IC_DISTRIBUTOR_BASE_ADDR),
+ IO_ADDRESS(IC_INTERFACES_BASE_ADDR));
+
+ if (enable_wait_mode) {
+ /* Mask the always pending interrupts - HW bug. */
+ __raw_writel(0x00400000, gpc_base + 0x0c);
+ __raw_writel(0x20000000, gpc_base + 0x10);
+ }
+
+
+ for (i = MXC_INT_START; i <= MXC_INT_END; i++) {
+ desc = irq_to_desc(i);
+ desc->irq_data.chip->irq_set_wake = mx6_gic_irq_set_wake;
+ }
+ mx6q_register_gpios();
+#ifdef CONFIG_CPU_FREQ_GOV_INTERACTIVE
+ for (i = 0; i < ARRAY_SIZE(mxc_irq_tuner); i++)
+ cpufreq_gov_irq_tuner_register(mxc_irq_tuner[i]);
+#endif
+#ifdef CONFIG_PCI_MSI
+ imx_msi_init();
+#endif
+}
diff --git a/arch/arm/mach-mx6/localtimer.c b/arch/arm/mach-mx6/localtimer.c
new file mode 100644
index 00000000..2fac9fb2
--- /dev/null
+++ b/arch/arm/mach-mx6/localtimer.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011-2013 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 <linux/init.h>
+#include <linux/smp.h>
+#include <linux/clockchips.h>
+#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ evt->irq = IRQ_LOCALTIMER;
+ twd_timer_setup(evt);
+ return 0;
+}
diff --git a/arch/arm/mach-mx6/mm.c b/arch/arm/mach-mx6/mm.c
new file mode 100644
index 00000000..78e5712b
--- /dev/null
+++ b/arch/arm/mach-mx6/mm.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2011-2012 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.
+ */
+
+/*
+ * Create static mapping between physical to virtual memory.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+#include <mach/iomux-v3.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-v3.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "crm_regs.h"
+
+/*!
+ * This structure defines the MX6 memory map.
+ */
+static struct map_desc mx6_io_desc[] __initdata = {
+ {
+ .virtual = BOOT_ROM_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(BOOT_ROM_BASE_ADDR),
+ .length = ROMCP_SIZE,
+ .type = MT_DEVICE},
+ {
+ .virtual = AIPS1_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(AIPS1_ARB_BASE_ADDR),
+ .length = AIPS1_SIZE,
+ .type = MT_DEVICE},
+ {
+ .virtual = AIPS2_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(AIPS2_ARB_BASE_ADDR),
+ .length = AIPS2_SIZE,
+ .type = MT_DEVICE},
+ {
+ .virtual = ARM_PERIPHBASE_VIRT,
+ .pfn = __phys_to_pfn(ARM_PERIPHBASE),
+ .length = ARM_PERIPHBASE_SIZE,
+ .type = MT_DEVICE},
+ {
+ .virtual = IRAM_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(IRAM_BASE_ADDR),
+ .length = IRAM_VIRT_SIZE,
+ .type = MT_MEMORY_NONCACHED},
+};
+
+static void mx6_set_cpu_type(void)
+{
+ u32 cpu_type = readl(IO_ADDRESS(ANATOP_BASE_ADDR + 0x280));
+
+ cpu_type >>= 16;
+ if (cpu_type == 0x60) {
+ mxc_set_cpu_type(MXC_CPU_MX6SL);
+ imx_print_silicon_rev("i.MX6SoloLite", mx6sl_revision());
+ return;
+ }
+
+ cpu_type = readl(IO_ADDRESS(ANATOP_BASE_ADDR + 0x260));
+ cpu_type >>= 16;
+ if (cpu_type == 0x63) {
+ mxc_set_cpu_type(MXC_CPU_MX6Q);
+ imx_print_silicon_rev("i.MX6Q", mx6q_revision());
+ } else if (cpu_type == 0x61) {
+ mxc_set_cpu_type(MXC_CPU_MX6DL);
+ imx_print_silicon_rev("i.MX6DL/SOLO", mx6dl_revision());
+ } else
+ pr_err("Unknown CPU type: %x\n", cpu_type);
+}
+
+/*!
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory map for
+ * the IO modules.
+ */
+void __init mx6_map_io(void)
+{
+ iotable_init(mx6_io_desc, ARRAY_SIZE(mx6_io_desc));
+ mxc_iomux_v3_init(IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR));
+ mxc_arch_reset_init(IO_ADDRESS(MX6Q_WDOG1_BASE_ADDR));
+ mx6_set_cpu_type();
+ mxc_cpu_lp_set(WAIT_CLOCKED);
+}
+#ifdef CONFIG_CACHE_L2X0
+int mxc_init_l2x0(void)
+{
+ unsigned int val;
+
+ #define IOMUXC_GPR11_L2CACHE_AS_OCRAM 0x00000002
+
+ val = readl(IOMUXC_GPR11);
+ if (cpu_is_mx6sl() && (val & IOMUXC_GPR11_L2CACHE_AS_OCRAM)) {
+ /* L2 cache configured as OCRAM, reset it */
+ val &= ~IOMUXC_GPR11_L2CACHE_AS_OCRAM;
+ writel(val, IOMUXC_GPR11);
+ }
+
+ writel(0x132, IO_ADDRESS(L2_BASE_ADDR + L2X0_TAG_LATENCY_CTRL));
+ writel(0x132, IO_ADDRESS(L2_BASE_ADDR + L2X0_DATA_LATENCY_CTRL));
+
+ /*
+ * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0
+ * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL is r3p2
+ * But according to ARM PL310 errata: 752271
+ * ID: 752271: Double linefill feature can cause data corruption
+ * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2
+ * Workaround: The only workaround to this erratum is to disable the
+ * double linefill feature. This is the default behavior.
+ */
+ if (!cpu_is_mx6q()) {
+ val = readl(IO_ADDRESS(L2_BASE_ADDR + L2X0_PREFETCH_CTRL));
+ val |= 0x40800000;
+ writel(val, IO_ADDRESS(L2_BASE_ADDR + L2X0_PREFETCH_CTRL));
+ }
+
+ val = readl(IO_ADDRESS(L2_BASE_ADDR + L2X0_POWER_CTRL));
+ val |= L2X0_DYNAMIC_CLK_GATING_EN;
+ val |= L2X0_STNDBY_MODE_EN;
+ writel(val, IO_ADDRESS(L2_BASE_ADDR + L2X0_POWER_CTRL));
+
+ l2x0_init(IO_ADDRESS(L2_BASE_ADDR), 0x0, ~0x00000000);
+ return 0;
+}
+
+
+arch_initcall(mxc_init_l2x0);
+#endif
diff --git a/arch/arm/mach-mx6/msi.c b/arch/arm/mach-mx6/msi.c
new file mode 100644
index 00000000..096d1c24
--- /dev/null
+++ b/arch/arm/mach-mx6/msi.c
@@ -0,0 +1,151 @@
+/*
+ * arch/arm/mach-mx6/msi.c
+ *
+ * PCI MSI support for the imx processor
+ *
+ * Copyright (c) 2013 Boundary Devices.
+ * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <asm/bitops.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include "msi.h"
+
+
+#define IMX_NUM_MSI_IRQS 128
+static DECLARE_BITMAP(msi_irq_in_use, IMX_NUM_MSI_IRQS);
+
+static void imx_msi_handler(unsigned int irq, struct irq_desc *desc)
+{
+ int i, j;
+ unsigned int status;
+ struct irq_chip *chip = irq_get_chip(irq);
+ unsigned int base_irq = IRQ_IMX_MSI_0;
+
+ chained_irq_enter(chip, desc);
+ for (i = 0; i < 8; i++) {
+ status = imx_pcie_msi_pending(i);
+ while (status) {
+ j = __fls(status);
+ generic_handle_irq(base_irq + j);
+ status &= ~(1 << j);
+ }
+ base_irq += 32;
+ }
+ chained_irq_exit(chip, desc);
+}
+
+/*
+* Dynamic irq allocate and deallocation
+*/
+int create_irq(void)
+{
+ int irq, pos;
+
+ do {
+ pos = find_first_zero_bit(msi_irq_in_use, IMX_NUM_MSI_IRQS);
+ if ((unsigned int)pos >= IMX_NUM_MSI_IRQS)
+ return -ENOSPC;
+ /* test_and_set_bit operates on 32-bits at a time */
+ } while (test_and_set_bit(pos, msi_irq_in_use));
+
+ irq = IRQ_IMX_MSI_0 + pos;
+ dynamic_irq_init(irq);
+ return irq;
+}
+
+void destroy_irq(unsigned int irq)
+{
+ int pos = irq - IRQ_IMX_MSI_0;
+
+ dynamic_irq_cleanup(irq);
+ clear_bit(pos, msi_irq_in_use);
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+ destroy_irq(irq);
+}
+
+static void imx_msi_irq_ack(struct irq_data *d)
+{
+ return;
+}
+
+static void imx_msi_irq_enable(struct irq_data *d)
+{
+ imx_pcie_enable_irq(d->irq - IRQ_IMX_MSI_0, 1);
+ return unmask_msi_irq(d);
+}
+
+static void imx_msi_irq_disable(struct irq_data *d)
+{
+ imx_pcie_enable_irq(d->irq - IRQ_IMX_MSI_0, 0);
+ return mask_msi_irq(d);
+}
+
+static void imx_msi_irq_mask(struct irq_data *d)
+{
+ imx_pcie_mask_irq(d->irq - IRQ_IMX_MSI_0, 1);
+ return mask_msi_irq(d);
+}
+
+static void imx_msi_irq_unmask(struct irq_data *d)
+{
+ imx_pcie_mask_irq(d->irq - IRQ_IMX_MSI_0, 0);
+ return unmask_msi_irq(d);
+}
+
+static struct irq_chip imx_msi_chip = {
+ .name = "PCIe-MSI",
+ .irq_ack = imx_msi_irq_ack,
+ .irq_enable = imx_msi_irq_enable,
+ .irq_disable = imx_msi_irq_disable,
+ .irq_mask = imx_msi_irq_mask,
+ .irq_unmask = imx_msi_irq_unmask,
+};
+
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+ int irq = create_irq();
+ struct msi_msg msg;
+
+ if (irq < 0)
+ return irq;
+
+ irq_set_msi_desc(irq, desc);
+
+ msg.address_hi = 0x0;
+ msg.address_lo = MSI_MATCH_ADDR;
+ /* 16bits msg.data: set cpu type to the upper 8bits*/
+ msg.data = (mxc_cpu_type << 8) | ((irq - IRQ_IMX_MSI_0) & 0xFF);
+
+ write_msi_msg(irq, &msg);
+ irq_set_chip_and_handler(irq, &imx_msi_chip, handle_simple_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ pr_info("IMX-PCIe: MSI 0x%04x @%#x:%#x, irq = %d\n",
+ msg.data, msg.address_hi,
+ msg.address_lo, irq);
+ return 0;
+}
+
+void imx_msi_init(void)
+{
+ irq_set_chained_handler(MXC_INT_PCIE_0, imx_msi_handler);
+}
diff --git a/arch/arm/mach-mx6/msi.h b/arch/arm/mach-mx6/msi.h
new file mode 100644
index 00000000..ce0e4673
--- /dev/null
+++ b/arch/arm/mach-mx6/msi.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 Boundary Devices, Inc. All Rights Reserved.
+ * Copyright (C) 2013 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.
+ */
+
+extern void imx_pcie_enable_irq(unsigned pos, int set);
+void imx_pcie_mask_irq(unsigned pos, int set);
+unsigned imx_pcie_msi_pending(unsigned index);
+
+#define MSI_MATCH_ADDR 0x01FF8000
+
+void imx_msi_init(void);
diff --git a/arch/arm/mach-mx6/mx6_anatop_regulator.c b/arch/arm/mach-mx6/mx6_anatop_regulator.c
new file mode 100644
index 00000000..b26f86bf
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6_anatop_regulator.c
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) 2011-2013 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.
+ */
+
+/*
+ * mx6_anatop_regulator.c -- i.MX6 Driver for Anatop regulators
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+
+#include <mach/clock.h>
+#include <mach/system.h>
+
+#include "crm_regs.h"
+#include "regs-anadig.h"
+
+#define GPC_PGC_GPU_PGCR_OFFSET 0x260
+#define GPC_CNTR_OFFSET 0x0
+
+#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */
+#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* time base on 24M OSC */
+
+extern struct platform_device sgtl5000_vdda_reg_devices;
+extern struct platform_device sgtl5000_vddio_reg_devices;
+extern struct platform_device sgtl5000_vddd_reg_devices;
+extern void __iomem *gpc_base;
+/* we use the below flag to keep PU regulator state, because enable/disable
+of PU regulator share with the same register as voltage set of PU regulator.
+PU voltage set by cpufreq driver if the flag is set, and enable/disable by
+GPU/VPU driver*/
+static unsigned int pu_is_enabled;
+static unsigned int get_clk;
+static struct clk *gpu3d_clk, *gpu3d_shade_clk, *gpu2d_clk, *gpu2d_axi_clk;
+static struct clk *openvg_axi_clk, *vpu_clk;
+extern int external_pureg;
+extern struct regulator *pu_regulator;
+extern u32 enable_ldo_mode;
+
+
+static int get_voltage(struct anatop_regulator *sreg)
+{
+ int uv;
+ struct anatop_regulator_data *rdata = sreg->rdata;
+
+ if (sreg->rdata->control_reg) {
+ u32 val = (__raw_readl(rdata->control_reg) >>
+ rdata->vol_bit_shift) & rdata->vol_bit_mask;
+ uv = rdata->min_voltage + (val - rdata->min_bit_val) * 25000;
+ pr_debug("vddio = %d, val=%u\n", uv, val);
+ return uv;
+ } else {
+ pr_debug("Regulator not supported.\n");
+ return -ENOTSUPP;
+ }
+}
+
+static int set_voltage(struct anatop_regulator *sreg, int uv)
+{
+ u32 val, reg;
+ u32 delay, steps, old_val;
+
+ pr_debug("%s: uv %d, min %d, max %d\n", __func__,
+ uv, sreg->rdata->min_voltage, sreg->rdata->max_voltage);
+
+ if (uv < sreg->rdata->min_voltage || uv > sreg->rdata->max_voltage)
+ return -EINVAL;
+
+ if (sreg->rdata->control_reg) {
+ val = sreg->rdata->min_bit_val +
+ (uv - sreg->rdata->min_voltage) / 25000;
+
+ reg = (__raw_readl(sreg->rdata->control_reg) &
+ ~(sreg->rdata->vol_bit_mask <<
+ sreg->rdata->vol_bit_shift));
+ pr_debug("%s: calculated val %d\n", __func__, val);
+
+ old_val = (__raw_readl(sreg->rdata->control_reg) >>
+ sreg->rdata->vol_bit_shift) & sreg->rdata->vol_bit_mask;
+
+ __raw_writel((val << sreg->rdata->vol_bit_shift) | reg,
+ sreg->rdata->control_reg);
+
+ if (sreg->rdata->control_reg == (unsigned int)(MXC_PLL_BASE +
+ HW_ANADIG_REG_CORE)) {
+ /* calculate how many steps to ramp up */
+ steps = (val > old_val) ? val - old_val : 0;
+ if (steps) {
+ switch (sreg->rdata->vol_bit_shift) {
+ case BP_ANADIG_REG_CORE_REG0_TRG:
+ reg = (__raw_readl(MXC_PLL_BASE +
+ HW_ANADIG_ANA_MISC2) &
+ BM_ANADIG_ANA_MISC2_REG0_STEP_TIME) >>
+ BP_ANADIG_ANA_MISC2_REG0_STEP_TIME;
+ break;
+ case BP_ANADIG_REG_CORE_REG1_TRG:
+ reg = (__raw_readl(MXC_PLL_BASE +
+ HW_ANADIG_ANA_MISC2) &
+ BM_ANADIG_ANA_MISC2_REG1_STEP_TIME) >>
+ BP_ANADIG_ANA_MISC2_REG1_STEP_TIME;
+ break;
+ case BP_ANADIG_REG_CORE_REG2_TRG:
+ reg = (__raw_readl(MXC_PLL_BASE +
+ HW_ANADIG_ANA_MISC2) &
+ BM_ANADIG_ANA_MISC2_REG2_STEP_TIME) >>
+ BP_ANADIG_ANA_MISC2_REG2_STEP_TIME;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * the delay time for LDO ramp up time is
+ * based on the register setting, we need
+ * to calculate how many steps LDO need to
+ * ramp up, and how much delay needs. (us)
+ */
+ delay = steps * ((LDO_RAMP_UP_UNIT_IN_CYCLES <<
+ reg) / LDO_RAMP_UP_FREQ_IN_MHZ + 1);
+ udelay(delay);
+ pr_debug("%s: %s: delay %d, steps %d, uv %d\n",
+ __func__, sreg->rdata->name, delay,
+ steps, uv);
+ }
+ }
+
+ return 0;
+ } else {
+ pr_debug("Regulator not supported.\n");
+ return -ENOTSUPP;
+ }
+}
+
+static int pu_enable(struct anatop_regulator *sreg)
+{
+ unsigned int reg, vddsoc;
+ int ret = 0;
+ /*get PU related clk to finish PU regulator power up*/
+ if (!get_clk) {
+ if (!cpu_is_mx6sl()) {
+ gpu3d_clk = clk_get(NULL, "gpu3d_clk");
+ if (IS_ERR(gpu3d_clk))
+ printk(KERN_ERR "%s: failed to get gpu3d_clk!\n"
+ , __func__);
+ gpu3d_shade_clk = clk_get(NULL, "gpu3d_shader_clk");
+ if (IS_ERR(gpu3d_shade_clk))
+ printk(KERN_ERR "%s: failed to get shade_clk!\n"
+ , __func__);
+ if (IS_ERR(vpu_clk))
+ printk(KERN_ERR "%s: failed to get vpu_clk!\n",
+ __func__);
+ }
+ gpu2d_clk = clk_get(NULL, "gpu2d_clk");
+ if (IS_ERR(gpu2d_clk))
+ printk(KERN_ERR "%s: failed to get gpu2d_clk!\n",
+ __func__);
+ gpu2d_axi_clk = clk_get(NULL, "gpu2d_axi_clk");
+ if (IS_ERR(gpu2d_axi_clk))
+ printk(KERN_ERR "%s: failed to get gpu2d_axi_clk!\n",
+ __func__);
+ openvg_axi_clk = clk_get(NULL, "openvg_axi_clk");
+ if (IS_ERR(openvg_axi_clk))
+ printk(KERN_ERR "%s: failed to get openvg_axi_clk!\n",
+ __func__);
+ get_clk = 1;
+
+ }
+ if (external_pureg) {
+ /*enable extern PU regulator*/
+ ret = regulator_enable(pu_regulator);
+ if (ret < 0)
+ printk(KERN_ERR "%s: enable pu error!\n", __func__);
+ } else {
+ /*Track the voltage of VDDPU with VDDSOC if use internal PU
+ *regulator.
+ */
+ reg = __raw_readl(ANADIG_REG_CORE);
+ vddsoc = reg & (ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG2_SOC_TARGET_OFFSET);
+ reg &= ~(ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG1_PU_TARGET_OFFSET);
+ reg |= vddsoc >> (ANADIG_REG2_SOC_TARGET_OFFSET
+ -ANADIG_REG1_PU_TARGET_OFFSET);
+ __raw_writel(reg, ANADIG_REG_CORE);
+ }
+
+ /* Need to wait for the regulator to come back up */
+ /*
+ * Delay time is based on the number of 24MHz clock cycles
+ * programmed in the ANA_MISC2_BASE_ADDR for each
+ * 25mV step.
+ */
+ udelay(150);
+ /*enable gpu clock to powerup GPU right.*/
+ if (get_clk) {
+ if (!cpu_is_mx6sl()) {
+ clk_enable(gpu3d_clk);
+ clk_enable(gpu3d_shade_clk);
+ clk_enable(vpu_clk);
+ }
+ clk_enable(gpu2d_clk);
+ clk_enable(gpu2d_axi_clk);
+ clk_enable(openvg_axi_clk);
+ }
+ /* enable power up request */
+ reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ /* power up request */
+ reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+ __raw_writel(reg | 0x2, gpc_base + GPC_CNTR_OFFSET);
+ /* Wait for the power up bit to clear */
+ while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x2)
+ ;
+ /* Enable the Brown Out detection. */
+ reg = __raw_readl(ANA_MISC2_BASE_ADDR);
+ reg |= ANADIG_ANA_MISC2_REG1_BO_EN;
+ __raw_writel(reg, ANA_MISC2_BASE_ADDR);
+ if (enable_ldo_mode != LDO_MODE_BYPASSED) {
+ /* Unmask the ANATOP brown out interrupt in the GPC. */
+ reg = __raw_readl(gpc_base + 0x14);
+ reg &= ~0x80000000;
+ __raw_writel(reg, gpc_base + 0x14);
+ }
+ pu_is_enabled = 1;
+ if (get_clk) {
+ if (!cpu_is_mx6sl()) {
+ clk_disable(gpu3d_clk);
+ clk_disable(gpu3d_shade_clk);
+ clk_disable(vpu_clk);
+ }
+ clk_disable(gpu2d_clk);
+ clk_disable(gpu2d_axi_clk);
+ clk_disable(openvg_axi_clk);
+ }
+ return 0;
+}
+
+int pu_disable(struct anatop_regulator *sreg)
+{
+ unsigned int reg;
+ int ret = 0;
+
+ /* Disable the brown out detection since we are going to be
+ * disabling the LDO.
+ */
+ reg = __raw_readl(ANA_MISC2_BASE_ADDR);
+ reg &= ~ANADIG_ANA_MISC2_REG1_BO_EN;
+ __raw_writel(reg, ANA_MISC2_BASE_ADDR);
+
+ /* Power gate the PU LDO. */
+ /* Power gate the PU domain first. */
+ /* enable power down request */
+ reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ /* power down request */
+ reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_CNTR_OFFSET);
+ /* Wait for power down to complete. */
+ while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x1)
+ ;
+ if (enable_ldo_mode != LDO_MODE_BYPASSED) {
+ /* Mask the ANATOP brown out interrupt in the GPC. */
+ reg = __raw_readl(gpc_base + 0x14);
+ reg |= 0x80000000;
+ __raw_writel(reg, gpc_base + 0x14);
+ }
+
+ if (external_pureg) {
+ /*disable extern PU regulator*/
+ ret = regulator_disable(pu_regulator);
+ if (ret < 0)
+ printk(KERN_ERR "%s: disable pu error!\n", __func__);
+ } else {
+ /* PU power gating. */
+ reg = __raw_readl(ANADIG_REG_CORE);
+ reg &= ~(ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG1_PU_TARGET_OFFSET);
+ __raw_writel(reg, ANADIG_REG_CORE);
+ }
+ pu_is_enabled = 0;
+ /* Clear the BO interrupt in the ANATOP. */
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= 0x80000000;
+ __raw_writel(reg, ANADIG_MISC1_REG);
+ return 0;
+}
+EXPORT_SYMBOL(pu_disable);
+static int is_pu_enabled(struct anatop_regulator *sreg)
+{
+ return pu_is_enabled;
+}
+static int enable(struct anatop_regulator *sreg)
+{
+ return 0;
+}
+
+static int disable(struct anatop_regulator *sreg)
+{
+ return 0;
+}
+
+static int is_enabled(struct anatop_regulator *sreg)
+{
+ return 1;
+}
+static int vdd3p0_enable(struct anatop_regulator *sreg)
+{
+ __raw_writel(BM_ANADIG_REG_3P0_ENABLE_LINREG,
+ sreg->rdata->control_reg+4);
+ return 0;
+}
+
+static int vdd3p0_disable(struct anatop_regulator *sreg)
+{
+ __raw_writel(BM_ANADIG_REG_3P0_ENABLE_LINREG,
+ sreg->rdata->control_reg+8);
+ return 0;
+}
+
+static int vdd3p0_is_enabled(struct anatop_regulator *sreg)
+{
+ return !!(__raw_readl(sreg->rdata->control_reg) & BM_ANADIG_REG_3P0_ENABLE_LINREG);
+}
+
+static struct anatop_regulator_data vddpu_data = {
+ .name = "vddpu",
+ .set_voltage = set_voltage,
+ .get_voltage = get_voltage,
+ .enable = pu_enable,
+ .disable = pu_disable,
+ .is_enabled = is_pu_enabled,
+ .control_reg = (u32)(MXC_PLL_BASE + HW_ANADIG_REG_CORE),
+ .vol_bit_shift = 9,
+ .vol_bit_mask = 0x1F,
+ .min_bit_val = 1,
+ .min_voltage = 725000,
+ .max_voltage = 1300000,
+};
+
+static struct anatop_regulator_data vddcore_data = {
+ .name = "vddcore",
+ .set_voltage = set_voltage,
+ .get_voltage = get_voltage,
+ .enable = enable,
+ .disable = disable,
+ .is_enabled = is_enabled,
+ .control_reg = (u32)(MXC_PLL_BASE + HW_ANADIG_REG_CORE),
+ .vol_bit_shift = 0,
+ .vol_bit_mask = 0x1F,
+ .min_bit_val = 1,
+ .min_voltage = 725000,
+ .max_voltage = 1300000,
+};
+
+static struct anatop_regulator_data vddsoc_data = {
+ .name = "vddsoc",
+ .set_voltage = set_voltage,
+ .get_voltage = get_voltage,
+ .enable = enable,
+ .disable = disable,
+ .is_enabled = is_enabled,
+ .control_reg = (u32)(MXC_PLL_BASE + HW_ANADIG_REG_CORE),
+ .vol_bit_shift = 18,
+ .vol_bit_mask = 0x1F,
+ .min_bit_val = 1,
+ .min_voltage = 725000,
+ .max_voltage = 1300000,
+};
+
+static struct anatop_regulator_data vdd2p5_data = {
+ .name = "vdd2p5",
+ .set_voltage = set_voltage,
+ .get_voltage = get_voltage,
+ .enable = enable,
+ .disable = disable,
+ .is_enabled = is_enabled,
+ .control_reg = (u32)(MXC_PLL_BASE + HW_ANADIG_REG_2P5),
+ .vol_bit_shift = 8,
+ .vol_bit_mask = 0x1F,
+ .min_bit_val = 0,
+ .min_voltage = 2000000,
+ .max_voltage = 2775000,
+};
+
+static struct anatop_regulator_data vdd1p1_data = {
+ .name = "vdd1p1",
+ .set_voltage = set_voltage,
+ .get_voltage = get_voltage,
+ .enable = enable,
+ .disable = disable,
+ .is_enabled = is_enabled,
+ .control_reg = (u32)(MXC_PLL_BASE + HW_ANADIG_REG_1P1),
+ .vol_bit_shift = 8,
+ .vol_bit_mask = 0x1F,
+ .min_bit_val = 4,
+ .min_voltage = 800000,
+ .max_voltage = 1400000,
+};
+
+static struct anatop_regulator_data vdd3p0_data = {
+ .name = "vdd3p0",
+ .set_voltage = set_voltage,
+ .get_voltage = get_voltage,
+ .enable = vdd3p0_enable,
+ .disable = vdd3p0_disable,
+ .is_enabled = vdd3p0_is_enabled,
+ .control_reg = (u32)(MXC_PLL_BASE + HW_ANADIG_REG_3P0),
+ .vol_bit_shift = 8,
+ .vol_bit_mask = 0x1F,
+ .min_bit_val = 0,
+ .min_voltage = 2625000,
+ .max_voltage = 3400000,
+};
+
+/* CPU */
+static struct regulator_consumer_supply vddcore_consumers[] = {
+ {
+ .supply = "cpu_vddgp",
+ }
+};
+/* PU */
+static struct regulator_consumer_supply vddpu_consumers[] = {
+ {
+ .supply = "cpu_vddvpu",
+ },
+ {
+ .supply = "cpu_vddgpu",
+ }
+};
+/* SOC */
+static struct regulator_consumer_supply vddsoc_consumers[] = {
+ {
+ .supply = "cpu_vddsoc",
+ },
+};
+
+/* USB phy 3P0 */
+static struct regulator_consumer_supply vdd3p0_consumers[] = {
+ {
+ .supply = "cpu_vdd3p0",
+ },
+};
+
+static struct regulator_init_data vddpu_init = {
+ .constraints = {
+ .name = "vddpu",
+ .min_uV = 725000,
+ .max_uV = 1300000,
+ .valid_modes_mask = REGULATOR_MODE_FAST |
+ REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS |
+ REGULATOR_CHANGE_MODE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vddpu_consumers),
+ .consumer_supplies = vddpu_consumers,
+};
+
+static struct regulator_init_data vddcore_init = {
+ .constraints = {
+ .name = "vddcore",
+ .min_uV = 725000,
+ .max_uV = 1300000,
+ .valid_modes_mask = REGULATOR_MODE_FAST |
+ REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE,
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vddcore_consumers),
+ .consumer_supplies = &vddcore_consumers[0],
+};
+
+static struct regulator_init_data vddsoc_init = {
+ .constraints = {
+ .name = "vddsoc",
+ .min_uV = 725000,
+ .max_uV = 1300000,
+ .valid_modes_mask = REGULATOR_MODE_FAST |
+ REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE,
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vddsoc_consumers),
+ .consumer_supplies = &vddsoc_consumers[0],
+};
+
+static struct regulator_init_data vdd2p5_init = {
+ .constraints = {
+ .name = "vdd2p5",
+ .min_uV = 2000000,
+ .max_uV = 2775000,
+ .valid_modes_mask = REGULATOR_MODE_FAST |
+ REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE,
+ .always_on = 1,
+ },
+ .num_consumer_supplies = 0,
+ .consumer_supplies = NULL,
+};
+
+
+static struct regulator_init_data vdd1p1_init = {
+ .constraints = {
+ .name = "vdd1p1",
+ .min_uV = 800000,
+ .max_uV = 1400000,
+ .valid_modes_mask = REGULATOR_MODE_FAST |
+ REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE,
+ .input_uV = 5000000,
+ .always_on = 1,
+ },
+ .num_consumer_supplies = 0,
+ .consumer_supplies = NULL,
+};
+
+
+static struct regulator_init_data vdd3p0_init = {
+ .constraints = {
+ .name = "vdd3p0",
+ .min_uV = 2625000,
+ .max_uV = 3400000,
+ .valid_modes_mask = REGULATOR_MODE_FAST |
+ REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vdd3p0_consumers),
+ .consumer_supplies = &vdd3p0_consumers[0],
+};
+
+static struct anatop_regulator vddpu_reg = {
+ .rdata = &vddpu_data,
+};
+
+static struct anatop_regulator vddcore_reg = {
+ .rdata = &vddcore_data,
+};
+
+static struct anatop_regulator vddsoc_reg = {
+ .rdata = &vddsoc_data,
+};
+
+static struct anatop_regulator vdd2p5_reg = {
+ .rdata = &vdd2p5_data,
+};
+
+static struct anatop_regulator vdd1p1_reg = {
+ .rdata = &vdd1p1_data,
+};
+
+static struct anatop_regulator vdd3p0_reg = {
+ .rdata = &vdd3p0_data,
+};
+
+static int __init regulators_init(void)
+{
+ unsigned int reg;
+
+ anatop_register_regulator(&vddpu_reg, ANATOP_VDDPU, &vddpu_init);
+ anatop_register_regulator(&vddcore_reg, ANATOP_VDDCORE, &vddcore_init);
+ anatop_register_regulator(&vddsoc_reg, ANATOP_VDDSOC, &vddsoc_init);
+ anatop_register_regulator(&vdd2p5_reg, ANATOP_VDD2P5, &vdd2p5_init);
+ anatop_register_regulator(&vdd1p1_reg, ANATOP_VDD1P1, &vdd1p1_init);
+ anatop_register_regulator(&vdd3p0_reg, ANATOP_VDD3P0, &vdd3p0_init);
+
+ /* Set the REGx step time back to reset value,
+ * as ROM may modify it according to fuse setting,
+ * so we need to set it back, otherwise, the delay
+ * time in cpu freq change will be impacted, the reset
+ * value is 0'b00, 64 cycles of 24M clock.
+ */
+ reg = __raw_readl(ANADIG_MISC2_REG);
+ reg &= ~ANADIG_ANA_MISC2_REG0_STEP_TIME_MASK;
+ reg &= ~ANADIG_ANA_MISC2_REG1_STEP_TIME_MASK;
+ reg &= ~ANADIG_ANA_MISC2_REG2_STEP_TIME_MASK;
+ __raw_writel(reg, ANADIG_MISC2_REG);
+
+ /* clear flag in boot */
+ pu_is_enabled = 0;
+ get_clk = 0;
+ pu_disable(NULL);
+ return 0;
+}
+postcore_initcall(regulators_init);
diff --git a/arch/arm/mach-mx6/mx6_ddr_freq.S b/arch/arm/mach-mx6/mx6_ddr_freq.S
new file mode 100644
index 00000000..de20f0c3
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6_ddr_freq.S
@@ -0,0 +1,1010 @@
+/*
+ * Copyright (C) 2011-2013 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 <linux/linkage.h>
+#include <mach/hardware.h>
+
+ .macro switch_to_528MHz
+
+ /* DDR freq change to 528MHz */
+
+ /* check if periph_clk_sel is already set */
+ ldr r0, [r6, #0x14]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ beq set_ahb_podf_before_switch
+
+ /* Step 1: Change periph_clk to be sourced from pll3_clk. */
+ /* Ensure PLL3 is the source and set the divider to 1. */
+ ldr r0, [r6, #0x18]
+ bic r0, r0, #0x3000
+ str r0, [r6, #0x18]
+
+ ldr r0, [r6, #0x14]
+ bic r0, r0, #0x38000000
+ str r0, [r6, #0x14]
+
+ /* Set the AHB dividers before the switch. */
+ /* Don't change AXI clock divider. */
+ /* Set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4 (need to maintain GPT divider). */
+ ldr r0, [r6, #0x14]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #0xd00
+ orr r0, r0, #0x10000
+ str r0, [r6, #0x14]
+
+wait_div_update528:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne wait_div_update528
+
+ /* Now switch periph_clk to pll3_main_clk. */
+ ldr r0, [r6, #0x14]
+ orr r0, r0, #0x2000000
+ str r0, [r6, #0x14]
+
+periph_clk_switch3:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch3
+
+ b switch_pre_periph_clk_528
+
+set_ahb_podf_before_switch:
+ /* Set the AHB dividers before the switch. */
+ /* Especially if the AHB is at 24MHz, divider
+ * would be at divide by 1 and clock
+ * would be too fast when switching to PLL3.
+ */
+ /* Don't change AXI clock divider. */
+ /* Set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4 (need to maintain GPT divider). */
+ ldr r0, [r6, #0x14]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #0xd00
+ orr r0, r0, #0x10000
+ str r0, [r6, #0x14]
+
+wait_div_update528_1:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne wait_div_update528_1
+
+switch_pre_periph_clk_528:
+
+ /* Now switch pre_periph_clk to PLL2_528MHz. */
+ ldr r0, [r6, #0x18]
+ bic r0, r0, #0xC0000
+ str r0, [r6, #0x18]
+
+ /* Now switch periph_clk back. */
+ ldr r0, [r6, #0x14]
+ bic r0, r0, #0x2000000
+ str r0, [r6, #0x14]
+
+periph_clk_switch4:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch4
+
+ ldr r0, =ANATOP_BASE_ADDR
+ add r0, r0, #PERIPBASE_VIRT
+ ldr r1, [r0, #0x260]
+ mov r2, r1
+ /*Is mx6q?*/
+ and r1, r1, #0xff0000
+ cmp r1, #0x630000
+ bne skip_gpt_workaround1
+ /*Is mx6q TO1.0?*/
+ and r2, r2, #0xff
+ cmp r2, #0x0
+ bne skip_gpt_workaround1
+ /* Change the GPT divider so that its at 6MHz. */
+ ldr r0, [r6, #0x1C]
+ bic r0, r0, #0x3F
+ orr r0, r0, #0xA
+ str r0, [r6, #0x1C]
+skip_gpt_workaround1:
+ .endm
+
+ .macro switch_to_400MHz
+
+ /* check if periph_clk_sel is already set */
+ ldr r0, [r6, #0x14]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ beq set_ahb_podf_before_switch1
+
+ /* Step 1: Change periph_clk to be sourced from pll3_clk. */
+ /* Ensure PLL3 is the source and set the divider to 1. */
+ ldr r0, [r6, #0x18]
+ bic r0, r0, #0x3000
+ str r0, [r6, #0x18]
+
+ ldr r0, [r6, #0x14]
+ bic r0, r0, #0x38000000
+ str r0, [r6, #0x14]
+
+ /* Now switch periph_clk to pll3_main_clk. */
+ ldr r0, [r6, #0x14]
+ orr r0, r0, #0x2000000
+ str r0, [r6, #0x14]
+
+periph_clk_switch5:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch5
+
+ b switch_pre_periph_clk_400
+
+set_ahb_podf_before_switch1:
+ /* Set the AHB dividers before the switch. */
+ /* Especially if the AHB is at 24MHz, divider
+ * would be at divide by 1 and clock
+ * would be too fast when switching to PLL3.
+ */
+ /* Don't change AXI clock divider. */
+ /* Set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4 (need to maintain GPT divider). */
+ ldr r0, [r6, #0x14]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #0x900
+ orr r0, r0, #0x10000
+ str r0, [r6, #0x14]
+
+wait_div_update400_1:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne wait_div_update400_1
+
+switch_pre_periph_clk_400:
+
+ /* Now switch pre_periph_clk to PFD_400MHz. */
+ ldr r0, [r6, #0x18]
+ bic r0, r0, #0xC0000
+ orr r0, r0, #0x40000
+ str r0, [r6, #0x18]
+
+ /* Now switch periph_clk back. */
+ ldr r0, [r6, #0x14]
+ bic r0, r0, #0x2000000
+ str r0, [r6, #0x14]
+
+periph_clk_switch6:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch6
+
+ /* Change AHB divider so that we are at 400/3=133MHz. */
+ /* Don't change AXI clock divider. */
+ /* Set the MMDC_DIV=1, AXI_DIV=2, AHB_DIV=3 (need to maintain GPT divider). */
+ ldr r0, [r6, #0x14]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #0x900
+ orr r0, r0, #0x10000
+ str r0, [r6, #0x14]
+
+wait_div_update400_2:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne wait_div_update400_2
+
+ ldr r0, =ANATOP_BASE_ADDR
+ add r0, r0, #PERIPBASE_VIRT
+ ldr r1, [r0, #0x260]
+ mov r2, r1
+ /*Is mx6q?*/
+ and r1, r1, #0xff0000
+ cmp r1, #0x630000
+ bne skip_gpt_workaround2
+ /*Is mx6q TO1.0?*/
+ and r2, r2, #0xff
+ cmp r2, #0x0
+ bne skip_gpt_workaround2
+ /* Change the GPT divider so that its at 6MHz. */
+ ldr r0, [r6, #0x1C]
+ bic r0, r0, #0x3F
+ orr r0, r0, #0xA
+ str r0, [r6, #0x1C]
+skip_gpt_workaround2:
+ .endm
+
+ .macro switch_to_50MHz
+
+ /* Set DDR to 50MHz. */
+ /* check if periph_clk_sel is already set */
+ ldr r0, [r6, #0x14]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ beq switch_pre_periph_clk_50
+
+ /* Set the periph_clk to be sourced from PLL2_PFD_200M */
+ /* Step 1: Change periph_clk to be sourced from pll3_clk. */
+ /* Ensure PLL3 is the source and set the divider to 1. */
+ ldr r0, [r6, #0x18]
+ bic r0, r0, #0x3000
+ str r0, [r6, #0x18]
+
+ ldr r0, [r6, #0x14]
+ bic r0, r0, #0x38000000
+ str r0, [r6, #0x14]
+
+ /* Now switch periph_clk to pll3_main_clk. */
+ ldr r0, [r6, #0x14]
+ orr r0, r0, #0x2000000
+ str r0, [r6, #0x14]
+
+periph_clk_switch_50:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch_50
+
+switch_pre_periph_clk_50:
+
+ /* Now switch pre_periph_clk to PFD_200MHz. */
+ ldr r0, [r6, #0x18]
+ orr r0, r0, #0xC0000
+ str r0, [r6, #0x18]
+
+ /* Set the MMDC_DIV=4, AXI_DIV = 4, AHB_DIV=8 (need to maintain GPT divider). */
+ ldr r0, [r6, #0x14]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+
+ orr r0, r0, #0x180000
+ orr r0, r0, #0x30000
+
+ /* If changing AHB divider remember to change the IPGPER divider too below. */
+ orr r0, r0, #0x1d00
+ str r0, [r6, #0x14]
+
+wait_div_update_50:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne wait_div_update_50
+
+ /* Now switch periph_clk back. */
+ ldr r0, [r6, #0x14]
+ bic r0, r0, #0x2000000
+ str r0, [r6, #0x14]
+
+periph_clk_switch2:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch2
+
+ ldr r0, =ANATOP_BASE_ADDR
+ add r0, r0, #PERIPBASE_VIRT
+ ldr r1, [r0, #0x260]
+ mov r2, r1
+ /*Is mx6q?*/
+ and r1, r1, #0xff0000
+ cmp r1, #0x630000
+ bne skip_gpt_workaround3
+ /*Is mx6q TO1.0?*/
+ and r2, r2, #0xff
+ cmp r2, #0x0
+ bne skip_gpt_workaround3
+ /* Change the GPT divider so that its at 6MHz. */
+ ldr r0, [r6, #0x1C]
+ bic r0, r0, #0x3F
+ orr r0, r0, #0x1
+ str r0, [r6, #0x1C]
+skip_gpt_workaround3:
+
+ .endm
+
+ .macro switch_to_24MHz
+ /* Change the freq now */
+ /* Try setting DDR to 24MHz. */
+ /* Source it from the periph_clk2 */
+ /* Ensure the periph_clk2 is sourced from 24MHz
+ and the divider is 1. */
+ ldr r0, [r6, #0x18]
+ bic r0, r0, #0x3000
+ orr r0, r0, #0x1000
+ str r0, [r6, #0x18]
+
+ ldr r0, [r6, #0x14]
+ bic r0, r0, #0x38000000
+ str r0, [r6, #0x14]
+
+ /* Now switch periph_clk to 24MHz. */
+ ldr r0, [r6, #0x14]
+ orr r0, r0, #0x2000000
+ str r0, [r6, #0x14]
+
+periph_clk_switch1:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch1
+
+ /* Change all the dividers to 1. */
+ ldr r0, [r6, #0x14]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #0x100
+ str r0, [r6, #0x14]
+
+ /* Wait for the divider to change. */
+wait_div_update:
+ ldr r0, [r6, #0x48]
+ cmp r0, #0
+ bne wait_div_update
+
+ ldr r0, =ANATOP_BASE_ADDR
+ add r0, r0, #PERIPBASE_VIRT
+ ldr r1, [r0, #0x260]
+ mov r2, r1
+ /*Is mx6q?*/
+ and r1, r1, #0xff0000
+ cmp r1, #0x630000
+ bne skip_gpt_workaround4
+ /*Is mx6q TO1.0?*/
+ and r2, r2, #0xff
+ cmp r2, #0x0
+ bne skip_gpt_workaround4
+ /* Change the GPT divider so that its at 6MHz. */
+ ldr r0, [r6, #0x1C]
+ bic r0, r0, #0x3F
+ orr r0, r0, #0x1
+ str r0, [r6, #0x1C]
+skip_gpt_workaround4:
+
+ .endm
+
+/*
+ * mx6_ddr_freq_change
+ *
+ * Idle the processor (eg, wait for interrupt).
+ * Make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ */
+ENTRY(mx6_ddr_freq_change)
+
+ stmfd sp!, {r4,r5,r6, r7, r8, r9, r10, r11} @ Save registers
+
+ ldr r6, =CCM_BASE_ADDR
+ add r6, r6, #PERIPBASE_VIRT
+ ldr r5, =MMDC_P0_BASE_ADDR
+ add r5, r5, #PERIPBASE_VIRT
+ ldr r7, =MX6Q_IOMUXC_BASE_ADDR
+ add r7, r7, #PERIPBASE_VIRT
+
+ mov r4, r0 @save new freq requested
+ mov r8, r1 @save the ddr settings for the new rate
+ mov r9, r2 @save the mode DDR is currently in (DLL ON/OFF)
+ mov r11, r3 @save iomux offsets
+
+ddr_freq_change:
+ /* Make sure no TLB miss will occur when the DDR is in self refresh. */
+ /* Invalidate TLB single entry to ensure that the address is not
+ * already in the TLB.
+ */
+
+ adr r10, ddr_freq_change @Address in this function.
+
+ ldr r2, [r6] @ TLB will miss,
+ @CCM address will be loaded
+ ldr r2, [r5] @ TLB will miss,
+ @MMDC address will be loaded
+ ldr r2, [r7] @ TLB will miss,
+ @IOMUX will be loaded
+
+ ldr r2, [r8] @ Get the DDR settings.
+ ldr r2, [r10] @ TLB will miss
+ ldr r2, [r11] @Get the IOMUX settings
+
+ /* Make sure all the L1 & L2 buffers are drained, as
+ * we don't want any writes to the DDR when it is
+ * in self-refresh.
+ */
+ /* Make sure the L1 buffers are drained. */
+ dsb
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Make sure the L2 buffers are drained.
+ * Sync operation on L2 drains the buffers.
+ */
+ ldr r0, =L2_BASE_ADDR
+ add r0, r0, #PERIPBASE_VIRT
+ mov r1, #0x0
+ str r1, [r0, #0x730]
+#endif
+
+ /* The second dsb might be needed to keep cache sync (device write)
+ * ordering with the memory accesses before it.
+ */
+ dsb
+ isb
+
+ /* Disable automatic power saving. */
+ ldr r0, [r5, #0x404]
+ orr r0, r0, #0x01
+ str r0, [r5, #0x404]
+
+ /* Disable MMDC power down timer. */
+ /*MMDC0_MDPDC disable power down timer */
+ ldr r0, [r5, #0x4]
+ bic r0, r0, #0xff00
+ str r0, [r5, #0x4]
+
+/* Delay for a while */
+ ldr r1, =4
+delay1:
+ ldr r2, =0
+cont1:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont1
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay1
+
+ /* set CON_REG */
+ ldr r0, =0x8000
+ str r0, [r5, #0x1C]
+poll_conreq_set_1:
+ ldr r0, [r5, #0x1C]
+ and r0, r0, #0x4000
+ cmp r0, #0x4000
+ bne poll_conreq_set_1
+
+ /*setmem /32 0x021b001c = 0x00008010 //Precharge all on cs0 */
+ /*setmem /32 0x021b001c = 0x00008018 //Precharge all on cs1 */
+ ldr r0, =0x00008010
+ str r0, [r5, #0x1C]
+ ldr r0, =0x00008018
+ str r0, [r5, #0x1C]
+
+ /* if requested frequency is greater than 300MHz go to DLL on mode */
+ ldr r1, =300000000
+ cmp r4, r1
+ bge dll_on_mode
+
+dll_off_mode:
+
+ /* if DLL is currently on, turn it off
+ cmp r9, #1
+ beq continue_dll_off_1
+
+ /* setmem /32 0x021b001c = 0x00018031 //Rtt_NOM off + set dll off, cs 0 */
+ /* setmem /32 0x021b001c = 0x00018039 //Rtt_NOM off + set dll off, cs 1 */
+ ldr r0, =0x00018031
+ str r0, [r5, #0x1C]
+
+ ldr r0, =0x00018039
+ str r0, [r5, #0x1C]
+
+ ldr r1, =10
+delay1a:
+ ldr r2, =0
+cont1a:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont1a
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay1a
+
+continue_dll_off_1:
+
+ /* set DVFS - enter self refresh mode */
+ ldr r0, [r5, #0x404]
+ orr r0, r0, #0x200000
+ str r0, [r5, #0x404]
+
+ /* de-assert con_req */
+ mov r0, #0x0
+ str r0, [r5, #0x1C]
+
+poll_dvfs_set_1:
+ ldr r0, [r5, #0x404]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ bne poll_dvfs_set_1
+
+ ldr r1, =24000000
+ cmp r4, r1
+ beq switch_freq_24
+
+ switch_to_50MHz
+ b continue_dll_off_2
+
+switch_freq_24:
+ switch_to_24MHz
+
+continue_dll_off_2:
+
+ /* set SBS - block ddr accesses */
+ ldr r0, [r5, #0x410]
+ orr r0, r0, #0x100
+ str r0, [r5, #0x410]
+
+ /* clear DVFS - exit from self refresh mode */
+ ldr r0, [r5, #0x404]
+ bic r0, r0, #0x200000
+ str r0, [r5, #0x404]
+
+poll_dvfs_clear_1:
+ ldr r0, [r5, #0x404]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* if DLL was previously on, continue DLL off routine
+ cmp r9, #1
+ beq continue_dll_off_3
+
+ /* setmem /32 0x021b001c = 0x00018031 //Rtt_NOM off + set dll off, cs 0 */
+ /* setmem /32 0x021b001c = 0x00018039 //Rtt_NOM off + set dll off, cs 1 */
+ ldr r0, =0x00018031
+ str r0, [r5, #0x1C]
+
+ ldr r0, =0x00018039
+ str r0, [r5, #0x1C]
+
+ /* setmem /32 0x021b001c = 0x04208030 //write mode reg MR0: CL=6, wr=6 ,cs 0 */
+ /* setmem /32 0x021b001c = 0x04208038 //write mode reg MR0: CL=6, wr=6 ,cs 1 */
+ ldr r0, =0x08208030
+ str r0, [r5, #0x1C]
+
+ ldr r0, =0x08208038
+ str r0, [r5, #0x1C]
+
+ /* setmem /32 0x021b001c = 0x02088032 //write mode reg MR2 , CWL=6 ,cs0 */
+ /* setmem /32 0x021b001c = 0x0208803A //write mode reg MR2 , CWL=6 ,cs1 */
+ ldr r0, =0x00088032
+ str r0, [r5, #0x1C]
+
+ ldr r0, =0x0008803A
+ str r0, [r5, #0x1C]
+
+ /* double refresh ????
+ ldr r0, =0x00001800
+ str r0, [r5, #0x20]*/
+
+ /* delay for a while. */
+ ldr r1, =4
+delay_1:
+ ldr r2, =0
+cont_1:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont_1
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay_1
+
+ /* MMDC0_MDCFG0 see spread sheet for timings, CAS=6 */
+ ldr r0, [r5, #0x0C]
+ bic r0, r0, #0xf
+ orr r0, r0, #0x3
+ str r0, [r5, #0x0C]
+
+ /* MMDC0_MDCFG1 see spread sheet for timings, tCWL=6 */
+ ldr r0, [r5, #0x10]
+ bic r0, r0, #0x7
+ orr r0, r0, #0x4
+ str r0, [r5, #0x10]
+
+ /* Enable bank interleaving, Address mirror on, WALAT = 0x1, RALAT = 0x2, DDR2_EN = 0 */
+ /*setmem /32 0x021b0018 = 0x00091680 */
+ ldr r0, =0x00091680
+ str r0, [r5, #0x18]
+
+ /* enable dqs pull down in the IOMUX. */
+ /*
+ setmem /32 0x020e05a8 = 0x00003030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 - DSE=110
+ setmem /32 0x020e05b0 = 0x00003030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 - DSE=110
+ setmem /32 0x020e0524 = 0x00003030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2 - DSE=110
+ setmem /32 0x020e051c = 0x00003030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3 - DSE=110
+ setmem /32 0x020e0518 = 0x00003030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS4 - DSE=110
+ setmem /32 0x020e050c = 0x00003030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS5 - DSE=110
+ setmem /32 0x020e05b8 = 0x00003030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS6 - DSE=110
+ setmem /32 0x020e05c0 = 0x00003030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS7 - DSE=110
+ */
+ ldr r1, [r11] @size of array
+ add r11, r11, #8 @skip first eight bytes in array
+ ldr r2, =0x3028
+update_iomux:
+ ldr r0, [r11, #0x0] @ offset
+ ldr r3, [r7, r0]
+ bic r3, r3, r2 @ Clear the DSE, PUE and PKE bits
+ orr r3, r3, #0x3000 @ Enable the Pull downs and lower the drive strength.
+ orr r3, r3, #0x28
+ str r3, [r7, r0]
+ add r11, r11, #8
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt update_iomux
+
+ /* ODT disabled */
+ /* setmem /32 0x021b0818 = 0x0 // DDR_PHY_P0_MPODTCTRL */
+ /* setmem /32 0x021b4818 = 0x0 // DDR_PHY_P1_MPODTCTRL */
+ ldr r0, =0x0
+ ldr r2, =0x818
+ str r0, [r5, r2]
+ ldr r2, =0x4818
+ str r0, [r5, r2]
+
+ /* DQS gating disabled */
+ /* setmem /32 0x021b083c = 0x233f033f */
+ ldr r2, =0x83c
+ ldr r0, [r5, r2]
+ orr r0, r0, #0x20000000
+ str r0, [r5, r2]
+
+ ldr r2, =0x483c
+ ldr r0, [r5, r2]
+ orr r0, r0, #0x20000000
+ str r0, [r5, r2]
+
+ /* MMDC0_MAPSR adopt power down enable */
+ /* setmem /32 0x021b0404 = 0x00011006 */
+ ldr r0, [r5, #0x404]
+ bic r0, r0, #0x01
+ str r0, [r5, #0x404]
+
+ /* frc_msr + mu bypass*/
+ ldr r0, =0x00000060
+ str r0, [r5, #0x8b8]
+ ldr r2, =0x48b8
+ str r0, [r5, r2]
+ ldr r0, =0x00000460
+ str r0, [r5, #0x8b8]
+ ldr r2, =0x48b8
+ str r0, [r5, r2]
+ ldr r0, =0x00000c60
+ str r0, [r5, #0x8b8]
+ ldr r2, =0x48b8
+ str r0, [r5, r2]
+
+continue_dll_off_3:
+
+ /* clear SBS - unblock accesses to DDR */
+ ldr r0, [r5, #0x410]
+ bic r0, r0, #0x100
+ str r0, [r5, #0x410]
+
+ mov r0, #0x0
+ str r0, [r5, #0x1C]
+poll_conreq_clear_1:
+ ldr r0, [r5, #0x1C]
+ and r0, r0, #0x4000
+ cmp r0, #0x4000
+ beq poll_conreq_clear_1
+
+ b done
+
+dll_on_mode:
+ /* assert DVFS - enter self refresh mode */
+ ldr r0, [r5, #0x404]
+ orr r0, r0, #0x200000
+ str r0, [r5, #0x404]
+
+ /* de-assert CON_REQ */
+ mov r0, #0x0
+ str r0, [r5, #0x1C]
+
+ /* poll DVFS ack */
+poll_dvfs_set_2:
+ ldr r0, [r5, #0x404]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ bne poll_dvfs_set_2
+
+ ldr r1, =528000000
+ cmp r4, r1
+ beq switch_freq_528
+
+ switch_to_400MHz
+
+ b continue_dll_on
+
+switch_freq_528:
+ switch_to_528MHz
+
+continue_dll_on:
+
+ /* set SBS step-by-step mode */
+ ldr r0, [r5, #0x410]
+ orr r0, r0, #0x100
+ str r0, [r5, #0x410]
+
+ /* clear DVFS - exit self refresh mode */
+ ldr r0, [r5, #0x404]
+ bic r0, r0, #0x200000
+ str r0, [r5, #0x404]
+
+poll_dvfs_clear_2:
+ ldr r0, [r5, #0x404]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ beq poll_dvfs_clear_2
+
+ /* if DLL is currently off, turn it back on */
+ cmp r9, #0
+ beq update_calibration_only
+
+ ldr r0, =0xa5390003
+ str r0, [r5, #0x800]
+ ldr r2, =0x4800
+ str r0, [r5, r2]
+
+ /* enable DQS gating */
+ ldr r2, =0x83c
+ ldr r0, [r5, r2]
+ bic r0, r0, #0x20000000
+ str r0, [r5, r2]
+
+ ldr r2, =0x483c
+ ldr r0, [r5, r2]
+ bic r0, r0, #0x20000000
+ str r0, [r5, r2]
+
+ /* force measure */
+ ldr r0, =0x00000800
+ str r0, [r5, #0x8b8]
+ ldr r2, =0x48b8
+ str r0, [r5, r2]
+
+ /* delay for while */
+ ldr r1, =4
+delay5:
+ ldr r2, =0
+cont5:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont5
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay5
+ /* Disable dqs pull down in the IOMUX. */
+ /*
+ setmem /32 0x020e05a8 = 0x00000030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 - DSE=110
+ setmem /32 0x020e05b0 = 0x00000030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 - DSE=110
+ setmem /32 0x020e0524 = 0x00000030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2 - DSE=110
+ setmem /32 0x020e051c = 0x00000030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3 - DSE=110
+ setmem /32 0x020e0518 = 0x00000030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS4 - DSE=110
+ setmem /32 0x020e050c = 0x00000030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS5 - DSE=110
+ setmem /32 0x020e05b8 = 0x00000030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS6 - DSE=110
+ setmem /32 0x020e05c0 = 0x00000030 // IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS7 - DSE=110
+ */
+ ldr r1, [r11] @size of array
+ add r11, r11, #8 @skip first eight bytes in array
+update_iomux1:
+ ldr r0, [r11, #0x0] @ offset
+ ldr r3, [r11, #0x4]
+ str r3, [r7, r0] @Store the original IOMUX value read during boot
+ add r11, r11, #8
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt update_iomux1
+
+ /* config ESDCTL timings to 528MHz:
+ @// setmem /32 0x021b000c = 0x555A7975 @// MMDC0_MDCFG0 see spread sheet for timings
+ @//setmem /32 0x021b0010 = 0xFF538E64 @// MMDC0_MDCFG1 see spread sheet for timings
+ @//setmem /32 0x021b0014 = 0x01ff00db @// MMDC0_MDCFG2 - tRRD - 4ck; tWTR - 4ck; tRTP - 4ck; tDLLK - 512ck
+ @//setmem /32 0x021b0018 = 0x00081740 @// MMDC0_MDMISC, RALAT=0x5 (original value)
+ */
+ ldr r9, [r8] @size of array
+ add r8, r8, #8 @skip first eight bytes in array
+ ldr r0, [r8, #0x0] @ offset
+ ldr r3, [r8, #0x4] @ value
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ ldr r0, [r8, #0x0] @ offset
+ ldr r3, [r8, #0x4] @ value
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ /* update MISC register: WALAT, RALAT */
+ ldr r0, =0x00081740
+ str r0, [r5, #0x18]
+
+ /*configure ddr devices to dll on, odt
+ @//setmem /32 0x021b001c = 0x00428031
+ @//setmem /32 0x021b001c = 0x00428039
+ */
+ ldr r0, =0x00028031
+ str r0, [r5, #0x1C]
+
+ ldr r0, =0x00028039
+ str r0, [r5, #0x1C]
+
+ /* delay for while */
+ ldr r1, =4
+delay7:
+ ldr r2, =0
+cont7:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont7
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay7
+
+ /* reset dll
+ @// setmem /32 0x021b001c = 0x09208030
+ @// setmem /32 0x021b001c = 0x09208038
+ */
+ ldr r0, =0x09208030
+ str r0, [r5, #0x1C]
+
+ ldr r0, =0x09208038
+ str r0, [r5, #0x1C]
+
+ /* delay for while */
+ ldr r1, =100
+delay8:
+ ldr r2, =0
+cont8:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont8
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay8
+
+ /* tcwl=6:
+ @//setmem /32 0x021b001c = 0x04088032
+ @//setmem /32 0x021b001c = 0x0408803a
+ */
+ /* MR2 - CS0 */
+ ldr r0, [r8, #0x0] @ offset
+ ldr r3, [r8, #0x4] @ value
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ /*MR2 - CS1 */
+ ldr r0, [r8, #0x0] @ offset
+ ldr r3, [r8, #0x4] @ value
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ ldr r0, =0x00428031
+ str r0, [r5, #0x1C]
+
+ ldr r0, =0x00428039
+ str r0, [r5, #0x1C]
+
+ /* tcl=8
+ @// setmem /32 0x021b001c = 0x08408030
+ @// setmem /32 0x021b001c = 0x08408038
+ */
+ /* MR1 - CS0 */
+ ldr r0, [r8, #0x0] @ offset
+ ldr r3, [r8, #0x4] @ value
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ /*MR1 - CS1 */
+ ldr r0, [r8, #0x0] @ offset
+ ldr r3, [r8, #0x4] @ value
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ /* issue a zq command
+ @// setmem /32 0x021b001c = 0x04000040
+ @// setmem /32 0x021b001c = 0x04000048
+ */
+ ldr r0, =0x04008040
+ str r0, [r5, #0x1C]
+
+ ldr r0, =0x04008048
+ str r0, [r5, #0x1C]
+
+ /* ESDCTL ODT enable
+ @//setmem /32 0x021b0818 = 0x00022225 @// DDR_PHY_P0_MPODTCTRL
+ @//setmem /32 0x021b4818 = 0x00022225 @// DDR_PHY_P1_MPODTCTRL
+ */
+ ldr r0, [r8, #0x0] @ offset
+ ldr r3, [r8, #0x4] @ value
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ ldr r2, =0x4818
+ str r0, [r5, r2]
+
+ /* delay for while */
+ ldr r1, =40
+delay15:
+ ldr r2, =0
+cont15:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont15
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay15
+
+ /* MMDC0_MAPSR adopt power down enable */
+ /* setmem /32 0x021b0404 = 0x00011006 */
+ ldr r0, [r5, #0x404]
+ bic r0, r0, #0x01
+ str r0, [r5, #0x404]
+
+ /* Enable MMDC power down timer. */
+ ldr r0, [r5, #0x4]
+ orr r0, r0, #0x5500
+ str r0, [r5, #0x4]
+
+ b update_calibration
+
+update_calibration_only:
+ ldr r1, [r8] @ size of array
+ sub r1, r1, #7 @ first 7 entries are not related to calibration
+ add r8, r8, #64 @ Skip the first 7 entries that are needed only when DLL was OFF + count entry.
+ b update_calib
+
+update_calibration:
+ /* Write the new calibration values. */
+ mov r1, r9 @ size of array
+ sub r1, r1, #7 @ first 7 entries are not related to calibration
+
+update_calib:
+ ldr r0, [r8, #0x0] @ offset
+ ldr r3, [r8, #0x4] @ value
+ str r3, [r5, r0]
+ add r8, r8, #8
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt update_calib
+
+ /* Perform a force measurement. */
+ ldr r0, =0x800
+ str r0, [r5, #0x8B8]
+ ldr r2, =0x48B8
+ str r0, [r5, r2]
+
+ /* clear SBS - unblock DDR accesses */
+ ldr r0, [r5, #0x410]
+ bic r0, r0, #0x100
+ str r0, [r5, #0x410]
+
+ mov r0, #0x0
+ str r0, [r5, #0x1C]
+poll_conreq_clear_2:
+ ldr r0, [r5, #0x1C]
+ and r0, r0, #0x4000
+ cmp r0, #0x4000
+ beq poll_conreq_clear_2
+
+done:
+
+ /* Restore registers */
+
+ ldmfd sp!, {r4,r5,r6, r7, r8, r9, r10, r11}
+
+ mov pc, lr
+
+ .type mx6_do_ddr_freq_change, #object
+ENTRY(mx6_do_ddr_freq_change)
+ .word mx6_ddr_freq_change
+ .size mx6_ddr_freq_change, . - mx6_ddr_freq_change
diff --git a/arch/arm/mach-mx6/mx6_fec.c b/arch/arm/mach-mx6/mx6_fec.c
new file mode 100644
index 00000000..935ba264
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6_fec.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011-2012 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 <linux/fec.h>
+#include <linux/etherdevice.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include "devices-imx6q.h"
+
+#define HW_OCOTP_MACn(n) (0x00000620 + (n) * 0x10)
+
+static int fec_get_mac_addr(unsigned char *mac)
+{
+ unsigned int value;
+
+ value = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_MACn(0));
+ mac[5] = value & 0xff;
+ mac[4] = (value >> 8) & 0xff;
+ mac[3] = (value >> 16) & 0xff;
+ mac[2] = (value >> 24) & 0xff;
+ value = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_MACn(1));
+ mac[1] = value & 0xff;
+ mac[0] = (value >> 8) & 0xff;
+
+ return 0;
+}
+
+void __init imx6_init_fec(struct fec_platform_data fec_data)
+{
+ fec_get_mac_addr(fec_data.mac);
+ if (!is_valid_ether_addr(fec_data.mac))
+ random_ether_addr(fec_data.mac);
+
+ if (cpu_is_mx6sl())
+ imx6sl_add_fec(&fec_data);
+ else
+ imx6q_add_fec(&fec_data);
+}
diff --git a/arch/arm/mach-mx6/mx6_mmdc.c b/arch/arm/mach-mx6/mx6_mmdc.c
new file mode 100644
index 00000000..eca8d83c
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6_mmdc.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2011-2012 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
+ */
+
+/*!
+ * @file mx6_mmdc.c
+ *
+ * @brief MX6 MMDC specific file.
+ *
+ * @ingroup PM
+ */
+#include <asm/io.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/iram_alloc.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/cpumask.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/tlb.h>
+#include <asm/hardware/gic.h>
+#include "crm_regs.h"
+
+
+/* DDR settings */
+unsigned long (*iram_ddr_settings)[2];
+unsigned long (*normal_mmdc_settings)[2];
+unsigned long (*iram_iomux_settings)[2];
+void __iomem *mmdc_base;
+void __iomem *iomux_base;
+void __iomem *gic_dist_base;
+void __iomem *gic_cpu_base;
+
+void (*mx6_change_ddr_freq)(u32 freq, void *ddr_settings, bool dll_mode, void* iomux_offsets) = NULL;
+
+extern unsigned int ddr_low_rate;
+extern unsigned int ddr_med_rate;
+extern unsigned int ddr_normal_rate;
+extern int low_bus_freq_mode;
+extern int audio_bus_freq_mode;
+extern int mmdc_med_rate;
+extern void __iomem *ccm_base;
+extern void mx6_ddr_freq_change(u32 freq, void *ddr_settings, bool dll_mode, void *iomux_offsets);
+
+static void *ddr_freq_change_iram_base;
+static int ddr_settings_size;
+static int iomux_settings_size;
+static volatile unsigned int cpus_in_wfe;
+static volatile bool wait_for_ddr_freq_update;
+static int curr_ddr_rate;
+
+#define MIN_DLL_ON_FREQ 333000000
+#define MAX_DLL_OFF_FREQ 125000000
+
+unsigned long ddr3_dll_mx6q[][2] = {
+ {0x0c, 0x0},
+ {0x10, 0x0},
+ {0x1C, 0x04088032},
+ {0x1C, 0x0408803a},
+ {0x1C, 0x08408030},
+ {0x1C, 0x08408038},
+ {0x818, 0x0},
+};
+
+unsigned long ddr3_calibration[][2] = {
+ {0x83c, 0x0},
+ {0x840, 0x0},
+ {0x483c, 0x0},
+ {0x4840, 0x0},
+ {0x848, 0x0},
+ {0x4848, 0x0},
+ {0x850, 0x0},
+ {0x4850, 0x0},
+};
+
+unsigned long ddr3_dll_mx6dl[][2] = {
+ {0x0c, 0x0},
+ {0x10, 0x0},
+ {0x1C, 0x04008032},
+ {0x1C, 0x0400803a},
+ {0x1C, 0x07208030},
+ {0x1C, 0x07208038},
+ {0x818, 0x0},
+};
+
+unsigned long iomux_offsets_mx6q[][2] = {
+ {0x5A8, 0x0},
+ {0x5B0, 0x0},
+ {0x524, 0x0},
+ {0x51C, 0x0},
+ {0x518, 0x0},
+ {0x50C, 0x0},
+ {0x5B8, 0x0},
+ {0x5C0, 0x0},
+};
+
+unsigned long iomux_offsets_mx6dl[][2] = {
+ {0x4BC, 0x0},
+ {0x4C0, 0x0},
+ {0x4C4, 0x0},
+ {0x4C8, 0x0},
+ {0x4CC, 0x0},
+ {0x4D0, 0x0},
+ {0x4D4, 0x0},
+ {0x4D8, 0x0},
+};
+
+unsigned long ddr3_400[][2] = {
+ {0x83c, 0x42490249},
+ {0x840, 0x02470247},
+ {0x483c, 0x42570257},
+ {0x4840, 0x02400240},
+ {0x848, 0x4039363C},
+ {0x4848, 0x3A39333F},
+ {0x850, 0x38414441},
+ {0x4850, 0x472D4833}
+};
+
+unsigned long *irq_used;
+
+unsigned long irqs_used_mx6q[] = {
+ MXC_INT_INTERRUPT_139_NUM,
+ MX6Q_INT_PERFMON1,
+ MX6Q_INT_PERFMON2,
+ MX6Q_INT_PERFMON3,
+};
+
+unsigned long irqs_used_mx6dl[] = {
+ MXC_INT_INTERRUPT_139_NUM,
+ MX6Q_INT_PERFMON1,
+};
+
+int can_change_ddr_freq(void)
+{
+ return 1;
+}
+
+
+/* Each active core apart from the one changing the DDR frequency will execute
+ * this function. The rest of the cores have to remain in WFE state until the frequency
+ * is changed.
+ */
+irqreturn_t wait_in_wfe_irq(int irq, void *dev_id)
+{
+ u32 me = smp_processor_id();
+
+ *((char *)(&cpus_in_wfe) + (u8)me) = 0xff;
+
+ while (wait_for_ddr_freq_update)
+ wfe();
+
+ *((char *)(&cpus_in_wfe) + (u8)me) = 0;
+
+ return IRQ_HANDLED;
+}
+
+/* Change the DDR frequency. */
+int update_ddr_freq(int ddr_rate)
+{
+ int i, j;
+ unsigned int reg;
+ bool dll_off = false;
+ unsigned int online_cpus = 0;
+ int cpu = 0;
+ int me;
+
+ if (!can_change_ddr_freq())
+ return -1;
+
+ if (ddr_rate == curr_ddr_rate)
+ return 0;
+
+ printk(KERN_DEBUG"%s(%d) %s(%d)\n",__FILE__,__LINE__,__FUNCTION__,ddr_rate);
+
+ if (low_bus_freq_mode || audio_bus_freq_mode)
+ dll_off = true;
+
+ iram_ddr_settings[0][0] = ddr_settings_size;
+ iram_iomux_settings[0][0] = iomux_settings_size;
+ if (ddr_rate == ddr_med_rate && cpu_is_mx6q()) {
+ for (i = 0; i < ARRAY_SIZE(ddr3_dll_mx6q); i++) {
+ iram_ddr_settings[i + 1][0] =
+ normal_mmdc_settings[i][0];
+ iram_ddr_settings[i + 1][1] =
+ normal_mmdc_settings[i][1];
+ }
+ for (j = 0, i = ARRAY_SIZE(ddr3_dll_mx6q); i < iram_ddr_settings[0][0]; j++, i++) {
+ iram_ddr_settings[i + 1][0] =
+ ddr3_400[j][0];
+ iram_ddr_settings[i + 1][1] =
+ ddr3_400[j][1];
+ }
+ } else if (ddr_rate == ddr_normal_rate) {
+ for (i = 0; i < iram_ddr_settings[0][0]; i++) {
+ iram_ddr_settings[i + 1][0] =
+ normal_mmdc_settings[i][0];
+ iram_ddr_settings[i + 1][1] =
+ normal_mmdc_settings[i][1];
+ }
+ }
+
+ /* Ensure that all Cores are in WFE. */
+ local_irq_disable();
+
+ me = smp_processor_id();
+
+ *((char *)(&cpus_in_wfe) + (u8)me) = 0xff;
+ wait_for_ddr_freq_update = true;
+ for_each_online_cpu(cpu) {
+ *((char *)(&online_cpus) + (u8)cpu) = 0xff;
+ if (cpu != me) {
+ /* Set the interrupt to be pending in the GIC. */
+ reg = 1 << (irq_used[cpu] % 32);
+ writel_relaxed(reg, gic_dist_base + GIC_DIST_PENDING_SET + (irq_used[cpu] / 32) * 4);
+ }
+ }
+ while (cpus_in_wfe != online_cpus)
+ udelay(5);
+
+ /* Now we can change the DDR frequency. */
+ mx6_change_ddr_freq(ddr_rate, iram_ddr_settings, dll_off, iram_iomux_settings);
+
+ curr_ddr_rate = ddr_rate;
+
+ /* DDR frequency change is done . */
+ wait_for_ddr_freq_update = false;
+
+ /* Wake up all the cores. */
+ sev();
+
+ *((char *)(&cpus_in_wfe) + (u8)me) = 0;
+
+ local_irq_enable();
+
+ return 0;
+}
+
+int init_mmdc_settings(void)
+{
+ unsigned long iram_paddr;
+ int i, err, cpu;
+
+ mmdc_base = ioremap(MMDC_P0_BASE_ADDR, SZ_32K);
+ iomux_base = ioremap(MX6Q_IOMUXC_BASE_ADDR, SZ_16K);
+ gic_dist_base = ioremap(IC_DISTRIBUTOR_BASE_ADDR, SZ_16K);
+ gic_cpu_base = ioremap(IC_INTERFACES_BASE_ADDR, SZ_16K);
+
+ if (cpu_is_mx6q())
+ ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6q) + ARRAY_SIZE(ddr3_calibration);
+ if (cpu_is_mx6dl())
+ ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6dl) + ARRAY_SIZE(ddr3_calibration);
+
+ normal_mmdc_settings = kmalloc((ddr_settings_size * 8), GFP_KERNEL);
+ if (cpu_is_mx6q()) {
+ memcpy(normal_mmdc_settings, ddr3_dll_mx6q, sizeof(ddr3_dll_mx6q));
+ memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6q)), ddr3_calibration, sizeof(ddr3_calibration));
+ }
+ if (cpu_is_mx6dl()) {
+ memcpy(normal_mmdc_settings, ddr3_dll_mx6dl, sizeof(ddr3_dll_mx6dl));
+ memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6dl)), ddr3_calibration, sizeof(ddr3_calibration));
+ }
+
+ /* Store the original DDR settings at boot. */
+ for (i = 0; i < ddr_settings_size; i++) {
+ /*Writes via command mode register cannot be read back.
+ * Hence hardcode them in the initial static array.
+ * This may require modification on a per customer basis.
+ */
+ if (normal_mmdc_settings[i][0] != 0x1C)
+ normal_mmdc_settings[i][1] =
+ __raw_readl(mmdc_base
+ + normal_mmdc_settings[i][0]);
+ }
+
+ /* Store the size of the array in iRAM also,
+ * increase the size by 8 bytes.
+ */
+ iram_ddr_settings = iram_alloc((ddr_settings_size * 8) + 8, &iram_paddr);
+ if (iram_ddr_settings == NULL) {
+ printk(KERN_DEBUG
+ "%s: failed to allocate iRAM memory for ddr settings\n",
+ __func__);
+ return ENOMEM;
+ }
+
+ iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q);
+ /* Store the size of the iomux settings in iRAM also,
+ * increase the size by 8 bytes.
+ */
+ iram_iomux_settings = iram_alloc((iomux_settings_size * 8) + 8, &iram_paddr);
+ if (iram_iomux_settings == NULL) {
+ printk(KERN_DEBUG
+ "%s: failed to allocate iRAM memory for iomuxr settings\n",
+ __func__);
+ return ENOMEM;
+ }
+
+ /* Store the IOMUX settings at boot. */
+ if (cpu_is_mx6q()) {
+ for (i = 0; i < iomux_settings_size; i++) {
+ iomux_offsets_mx6q[i][1] =
+ __raw_readl(iomux_base
+ + iomux_offsets_mx6q[i][0]);
+ iram_iomux_settings[i+1][0] = iomux_offsets_mx6q[i][0];
+ iram_iomux_settings[i+1][1] = iomux_offsets_mx6q[i][1];
+ }
+ irq_used = irqs_used_mx6q;
+ }
+
+ if (cpu_is_mx6dl()) {
+ for (i = 0; i < iomux_settings_size; i++) {
+ iomux_offsets_mx6dl[i][1] =
+ __raw_readl(iomux_base
+ + iomux_offsets_mx6dl[i][0]);
+ iram_iomux_settings[i+1][0] = iomux_offsets_mx6dl[i][0];
+ iram_iomux_settings[i+1][1] = iomux_offsets_mx6dl[i][1];
+ }
+ irq_used = irqs_used_mx6dl;
+ }
+
+ /* Allocate IRAM for the DDR freq change code. */
+ iram_alloc(SZ_8K, &iram_paddr);
+ /* Need to remap the area here since we want the memory region
+ to be executable. */
+ ddr_freq_change_iram_base = __arm_ioremap(iram_paddr,
+ SZ_8K, MT_MEMORY_NONCACHED);
+ memcpy(ddr_freq_change_iram_base, mx6_ddr_freq_change, SZ_8K);
+ mx6_change_ddr_freq = (void *)ddr_freq_change_iram_base;
+
+ curr_ddr_rate = ddr_normal_rate;
+
+ for_each_online_cpu(cpu) {
+ /* Set up a reserved interrupt to get all the active cores into a WFE state
+ * before changing the DDR frequency.
+ */
+ err = request_irq(irq_used[cpu], wait_in_wfe_irq, IRQF_PERCPU, "mmdc_1",
+ NULL);
+ if (err) {
+ printk(KERN_ERR "MMDC: Unable to attach to %ld,err = %d\n", irq_used[cpu], err);
+ return err;
+ }
+ err = irq_set_affinity(irq_used[cpu], cpumask_of(cpu));
+ if (err) {
+ printk(KERN_ERR "MMDC: unable to set irq affinity irq=%ld,\n", irq_used[cpu]);
+ return err;
+ }
+ }
+ return 0;
+}
diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S
new file mode 100644
index 00000000..30388ead
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6_suspend.S
@@ -0,0 +1,1713 @@
+/*
+ * Copyright (C) 2010-2012 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 <linux/linkage.h>
+#include <mach/hardware.h>
+#include <asm/memory.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "src-reg.h"
+
+#define ARM_CTRL_DCACHE (1 << 2)
+#define ARM_CTRL_ICACHE (1 << 12)
+#define ARM_AUXCR_L2EN (1 << 1)
+#define TTRBIT_MASK 0xffffc000
+#define TABLE_INDEX_MASK 0xfff00000
+#define TABLE_ENTRY 0x00000c02
+#define CACHE_DISABLE_MASK 0xfffffffb
+#define MMDC_MAPSR_OFFSET 0x404
+#define MMDC_MAPSR_PSS (1 << 4)
+#define MMDC_MAPSR_PSD (1 << 0)
+/*
+ * The code size is limited to 5K, as we may need to store
+ * this code * along with the low power WFI and DDR freq
+ * change code within 8K of IRAM.
+ */
+#define IRAM_SUSPEND_SIZE MX6_SUSPEND_CODE_SIZE
+
+.extern iram_tlb_phys_addr
+.extern suspend_iram_base
+.extern suspend_iram_phys_addr
+
+/*************************************************************
+mx6_suspend:
+
+Suspend the processor (eg, wait for interrupt).
+Set the DDR into Self Refresh
+IRQs are already disabled.
+
+The following code contain both standby and
+dormant mode for MX6, decided by the parameter
+passed in r0:
+see define in include/linux/suspend.h
+1 -> cpu enter stop mode;
+3 -> cpu enter dormant mode.
+r1: iram_paddr
+r2: suspend_iram_base
+*************************************************************/
+ .macro mx6sl_standy_saving_set
+
+ /* Move periph_clk to OSC_CLK. */
+ ldr r1, =CCM_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Ensure the periph_clk2_sel to OSC clk. */
+ ldr r0, [r1, #0x18]
+ bic r0, r0, #0x3000
+ orr r0, r0, #0x1000
+ str r0, [r1, #0x18]
+
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x2000000
+ str r0, [r1, #0x14]
+
+periph_clk_switch:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch
+
+ /* Set the divider to divider by 8 */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x70000
+ orr r0, r0, #0x1c00
+ str r0, [r1, #0x14]
+
+ahb_podf:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne ahb_podf
+
+ /* Move DDR clk to PLL3 clock.
+ */
+ /* First set the divider to 2. */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x1
+ str r0, [r1, #0x14]
+
+ ldr r0, [r1, #0x18]
+ bic r0, r0, #0x100000
+ str r0, [r1, #0x18]
+
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x4000000
+ str r0, [r1, #0x14]
+
+ddr_switch:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne ddr_switch
+
+ /* Set DDR clock to divide by 8. */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x38
+ str r0, [r1, #0x14]
+
+mmdc_div:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne mmdc_div
+
+ /* Now Switch ARM to run from
+ * step_clk sourced from OSC.
+ */
+ ldr r0, [r1, #0xc]
+ bic r0, r1, #0x100
+ str r0, [r1, #0x0c]
+
+ /* Now switch PLL1_SW_CLK to step_clk. */
+ ldr r0, [r1, #0x0c]
+ orr r0, r0, #0x4
+ str r0, [r1, #0x0c]
+
+ ldr r1, =ANATOP_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Need to clock gate the 528 PFDs before
+ * powering down PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC/AHB
+ */
+ ldr r0, [r1, #0x100]
+ orr r0, r0, #0x800000
+ str r0, [r1, #0x100]
+
+ /* Now bypass PLL1 and PLL2. */
+ ldr r0, =0x10000
+ str r0, [r1, #0x4]
+ str r0, [r1, #0x34]
+
+ /* Now do all the analog savings. */
+
+ /* Disable 1p1 brown out. */
+ ldr r0, [r1, #0x110]
+ bic r0, r0, #0x2
+ str r0, [r1, #0x110]
+
+ /* Enable the weak 2P5 */
+ ldr r0, [r1, #0x130]
+ orr r0, r0, #0x40000
+ str r0, [r1, #0x130]
+
+ /*Disable main 2p5. */
+ ldr r0, [r1, #0x130]
+ bic r0, r0, #0x1
+ str r0, [r1, #0x130]
+
+
+ /* Set the OSC bias current to -37.5%
+ * to drop the power on VDDHIGH.
+ */
+ ldr r0, [r1, #0x150]
+ orr r0, r0, #0xC000
+ str r0, [r1, #0x150]
+ .endm
+
+ .macro mx6sl_standby_savings_restore
+
+ /* Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r1, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r1, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r1, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r1, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5:
+ ldr r6, [r1, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r1, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r1, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r1, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r1, #0x110]
+
+ /* Unbypass PLLs and
+ * wait for relock.
+ */
+ ldr r6, =(1 << 16)
+ str r6, [r1, #0x08]
+ str r6, [r1, #0x38]
+
+wait_for_pll_lock:
+ ldr r6, [r1, #0x0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock
+
+wait_for_pll2_lock:
+ ldr r6, [r1, #0x30]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll2_lock
+
+ /* Set PLL1_sw_clk back to PLL1. */
+ ldr r6, [r3, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r3, #0xc]
+
+ /* Need to enable the 528 PFDs after
+ * powering up PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC. Rest should have
+ * been managed by clock code.
+ */
+ ldr r6, [r1, #0x100]
+ bic r6, r6, #0x800000
+ str r6, [r1, #0x100]
+
+ /* Move periph_clk back
+ * to PLL2_PFD2_400.
+ */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x2000000
+ str r6, [r3, #0x14]
+
+periph_clk_switch1:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne periph_clk_switch1
+
+ /* Set the dividers to default value. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x70000
+ bic r6, r6, #0x1c00
+ orr r6, r6, #0x10800
+ str r6, [r3, #0x14]
+
+ahb_podf1:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne ahb_podf1
+
+ /* Move MMDC back to PLL2_PFD2_400 */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r3, #0x14]
+
+mmdc_loop2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_loop2
+
+ /* Set DDR clock to divide by 1. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x38
+ str r6, [r3, #0x14]
+
+mmdc_div1:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_div1
+
+ .endm
+
+ .macro mx6sl_standby_pg_savings_restore
+
+ /* Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r1, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r1, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r1, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r1, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5_1:
+ ldr r6, [r1, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5_1
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r1, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r1, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r1, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r1, #0x110]
+
+ /* Unbypass PLLs and
+ * wait for relock.
+ */
+ ldr r6, =(1 << 16)
+ str r6, [r1, #0x08]
+ str r6, [r1, #0x38]
+
+wait_for_pll_lock1:
+ ldr r6, [r1, #0x0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock1
+
+ /* Set PLL1_sw_clk back to PLL1. */
+ ldr r6, [r3, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r3, #0xc]
+
+ /* Need to enable the 528 PFDs after
+ * powering up PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC. Rest should have
+ * been managed by clock code.
+ */
+ ldr r6, [r1, #0x100]
+ bic r6, r6, #0x800000
+ str r6, [r1, #0x100]
+
+ /* Move DDR clock back to PLL2_PFD2_400 */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r3, #0x14]
+
+mmdc_loop3:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_loop3
+
+ /* Set DDR clock to divide by 1. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x38
+ str r6, [r3, #0x14]
+
+mmdc_div2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_div2
+
+ /* Move periph_clk back
+ * to PLL2_PFD2_400.
+ */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x2000000
+ str r6, [r3, #0x14]
+
+periph_clk_switch2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne periph_clk_switch2
+
+ /* Set the dividers to default value. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x70000
+ bic r6, r6, #0x1c00
+ orr r6, r6, #0x10800
+ str r6, [r3, #0x14]
+
+ahb_podf2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne ahb_podf2
+
+ .endm
+
+ .macro sl_ddr_io_save
+
+ ldr r4, [r1, #0x30c] /* DRAM_DQM0 */
+ ldr r5, [r1, #0x310] /* DRAM_DQM1 */
+ ldr r6, [r1, #0x314] /* DRAM_DQM2 */
+ ldr r7, [r1, #0x318] /* DRAM_DQM3 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x5c4] /* GPR_B0DS */
+ ldr r5, [r1, #0x5cc] /* GPR_B1DS */
+ ldr r6, [r1, #0x5d4] /* GPR_B2DS */
+ ldr r7, [r1, #0x5d8] /* GPR_B3DS */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x300] /* DRAM_CAS */
+ ldr r5, [r1, #0x31c] /* DRAM_RAS */
+ ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */
+ ldr r7, [r1, #0x5ac] /* GPR_ADDS*/
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */
+ ldr r5, [r1, #0x5c0] /* DDRMODE */
+ ldr r6, [r1, #0x33c] /* DRAM_SODT0*/
+ ldr r7, [r1, #0x340] /* DRAM_SODT1*/
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */
+ ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */
+ ldr r6, [r1, #0x320] /* DRAM_RESET */
+ stmfd r0!, {r4-r6}
+
+ .endm
+
+ .macro sl_ddr_io_restore
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x30c] /* DRAM_DQM0 */
+ str r5, [r1, #0x310] /* DRAM_DQM1 */
+ str r6, [r1, #0x314] /* DRAM_DQM2 */
+ str r7, [r1, #0x318] /* DRAM_DQM3 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x5c4] /* GPR_B0DS */
+ str r5, [r1, #0x5cc] /* GPR_B1DS */
+ str r6, [r1, #0x5d4] /* GPR_B2DS */
+ str r7, [r1, #0x5d8] /* GPR_B3DS */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x300] /* DRAM_CAS */
+ str r5, [r1, #0x31c] /* DRAM_RAS */
+ str r6, [r1, #0x338] /* DRAM_SDCLK_0 */
+ str r7, [r1, #0x5ac] /* GPR_ADDS*/
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x5b0] /* DDRMODE_CTL */
+ str r5, [r1, #0x5c0] /* DDRMODE */
+ str r6, [r1, #0x33c] /* DRAM_SODT0*/
+ str r7, [r1, #0x340] /* DRAM_SODT1*/
+
+ ldmea r0!, {r4-r6}
+ str r4, [r1, #0x330] /* DRAM_SDCKE0 */
+ str r5, [r1, #0x334] /* DRAM_SDCKE1 */
+ str r6, [r1, #0x320] /* DRAM_RESET */
+
+ .endm
+
+ .macro sl_ddr_io_set_lpm
+
+ mov r0, #0
+ str r0, [r1, #0x30c] /* DRAM_DQM0 */
+ str r0, [r1, #0x310] /* DRAM_DQM1 */
+ str r0, [r1, #0x314] /* DRAM_DQM2 */
+ str r0, [r1, #0x318] /* DRAM_DQM3 */
+
+ str r0, [r1, #0x5c4] /* GPR_B0DS */
+ str r0, [r1, #0x5cc] /* GPR_B1DS */
+ str r0, [r1, #0x5d4] /* GPR_B2DS */
+ str r0, [r1, #0x5d8] /* GPR_B3DS */
+
+ str r0, [r1, #0x300] /* DRAM_CAS */
+ str r0, [r1, #0x31c] /* DRAM_RAS */
+ str r0, [r1, #0x338] /* DRAM_SDCLK_0 */
+ str r0, [r1, #0x5ac] /* GPR_ADDS*/
+
+ str r0, [r1, #0x5b0] /* DDRMODE_CTL */
+ str r0, [r1, #0x5c0] /* DDRMODE */
+ str r0, [r1, #0x33c] /* DRAM_SODT0*/
+ str r0, [r1, #0x340] /* DRAM_SODT1*/
+
+ mov r0, #0x80000
+ str r0, [r1, #0x320] /* DRAM_RESET */
+ mov r0, #0x1000
+ str r0, [r1, #0x330] /* DRAM_SDCKE0 */
+ str r0, [r1, #0x334] /* DRAM_SDCKE1 */
+
+ .endm
+
+ .macro dl_ddr_io_save
+
+ ldr r4, [r1, #0x470] /* DRAM_DQM0 */
+ ldr r5, [r1, #0x474] /* DRAM_DQM1 */
+ ldr r6, [r1, #0x478] /* DRAM_DQM2 */
+ ldr r7, [r1, #0x47c] /* DRAM_DQM3 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x480] /* DRAM_DQM4 */
+ ldr r5, [r1, #0x484] /* DRAM_DQM5 */
+ ldr r6, [r1, #0x488] /* DRAM_DQM6 */
+ ldr r7, [r1, #0x48c] /* DRAM_DQM7 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x464] /* DRAM_CAS */
+ ldr r5, [r1, #0x490] /* DRAM_RAS */
+ ldr r6, [r1, #0x4ac] /* DRAM_SDCLK_0 */
+ ldr r7, [r1, #0x4b0] /* DRAM_SDCLK_1 */
+ stmfd r0!, {r4-r7}
+
+ ldr r5, [r1, #0x750] /* DDRMODE_CTL */
+ ldr r6, [r1, #0x760] /* DDRMODE */
+ stmfd r0!, {r5-r6}
+
+ ldr r4, [r1, #0x4bc] /* DRAM_SDQS0 */
+ ldr r5, [r1, #0x4c0] /* DRAM_SDQS1 */
+ ldr r6, [r1, #0x4c4] /* DRAM_SDQS2 */
+ ldr r7, [r1, #0x4c8] /* DRAM_SDQS3 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x4cc] /* DRAM_SDQS4 */
+ ldr r5, [r1, #0x4d0] /* DRAM_SDQS5 */
+ ldr r6, [r1, #0x4d4] /* DRAM_SDQS6 */
+ ldr r7, [r1, #0x4d8] /* DRAM_SDQS7 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x764] /* GPR_B0DS */
+ ldr r5, [r1, #0x770] /* GPR_B1DS */
+ ldr r6, [r1, #0x778] /* GPR_B2DS */
+ ldr r7, [r1, #0x77c] /* GPR_B3DS */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x780] /* GPR_B4DS */
+ ldr r5, [r1, #0x784] /* GPR_B5DS */
+ ldr r6, [r1, #0x78c] /* GPR_B6DS */
+ ldr r7, [r1, #0x748] /* GPR_B7DS */
+ stmfd r0!, {r4-r7}
+
+ ldr r5, [r1, #0x74c] /* GPR_ADDS*/
+ ldr r6, [r1, #0x4b4] /* DRAM_SODT0*/
+ ldr r7, [r1, #0x4b8] /* DRAM_SODT1*/
+ stmfd r0!, {r5-r7}
+
+ .endm
+
+ .macro dl_ddr_io_restore
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x470] /* DRAM_DQM0 */
+ str r5, [r1, #0x474] /* DRAM_DQM1 */
+ str r6, [r1, #0x478] /* DRAM_DQM2 */
+ str r7, [r1, #0x47c] /* DRAM_DQM3 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x480] /* DRAM_DQM4 */
+ str r5, [r1, #0x484] /* DRAM_DQM5 */
+ str r6, [r1, #0x488] /* DRAM_DQM6 */
+ str r7, [r1, #0x48c] /* DRAM_DQM7 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x464] /* DRAM_CAS */
+ str r5, [r1, #0x490] /* DRAM_RAS */
+ str r6, [r1, #0x4ac] /* DRAM_SDCLK_0 */
+ str r7, [r1, #0x4b0] /* DRAM_SDCLK_1 */
+
+ ldmea r0!, {r5-r6}
+ str r5, [r1, #0x750] /* DDRMODE_CTL */
+ str r6, [r1, #0x760] /* DDRMODE */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x4bc] /* DRAM_SDQS0 */
+ str r5, [r1, #0x4c0] /* DRAM_SDQS1 */
+ str r6, [r1, #0x4c4] /* DRAM_SDQS2 */
+ str r7, [r1, #0x4c8] /* DRAM_SDQS3 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x4cc] /* DRAM_SDQS4 */
+ str r5, [r1, #0x4d0] /* DRAM_SDQS5 */
+ str r6, [r1, #0x4d4] /* DRAM_SDQS6 */
+ str r7, [r1, #0x4d8] /* DRAM_SDQS7 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x764] /* GPR_B0DS */
+ str r5, [r1, #0x770] /* GPR_B1DS */
+ str r6, [r1, #0x778] /* GPR_B2DS */
+ str r7, [r1, #0x77c] /* GPR_B3DS */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x780] /* GPR_B4DS */
+ str r5, [r1, #0x784] /* GPR_B5DS */
+ str r6, [r1, #0x78c] /* GPR_B6DS */
+ str r7, [r1, #0x748] /* GPR_B7DS */
+
+ ldmea r0!, {r5-r7}
+ str r5, [r1, #0x74c] /* GPR_ADDS*/
+ str r6, [r1, #0x4b4] /* DRAM_SODT0*/
+ str r7, [r1, #0x4b8] /* DRAM_SODT1*/
+
+ .endm
+
+ .macro dl_ddr_io_set_lpm
+
+ mov r0, #0
+ str r0, [r1, #0x470] /* DRAM_DQM0 */
+ str r0, [r1, #0x474] /* DRAM_DQM1 */
+ str r0, [r1, #0x478] /* DRAM_DQM2 */
+ str r0, [r1, #0x47c] /* DRAM_DQM3 */
+
+ str r0, [r1, #0x480] /* DRAM_DQM4 */
+ str r0, [r1, #0x484] /* DRAM_DQM5 */
+ str r0, [r1, #0x488] /* DRAM_DQM6 */
+ str r0, [r1, #0x48c] /* DRAM_DQM7 */
+
+ str r0, [r1, #0x464] /* DRAM_CAS */
+ str r0, [r1, #0x490] /* DRAM_RAS */
+ str r0, [r1, #0x4ac] /* DRAM_SDCLK_0 */
+ str r0, [r1, #0x4b0] /* DRAM_SDCLK_1 */
+
+ str r0, [r1, #0x750] /* DDRMODE_CTL */
+ str r0, [r1, #0x760] /* DDRMODE */
+
+ str r0, [r1, #0x4bc] /* DRAM_SDQS0 */
+ str r0, [r1, #0x4c0] /* DRAM_SDQS1 */
+ str r0, [r1, #0x4c4] /* DRAM_SDQS2 */
+ str r0, [r1, #0x4c8] /* DRAM_SDQS3 */
+
+ str r0, [r1, #0x4cc] /* DRAM_SDQS4 */
+ str r0, [r1, #0x4d0] /* DRAM_SDQS5 */
+ str r0, [r1, #0x4d4] /* DRAM_SDQS6 */
+ str r0, [r1, #0x4d8] /* DRAM_SDQS7 */
+
+ str r0, [r1, #0x764] /* GPR_B0DS */
+ str r0, [r1, #0x770] /* GPR_B1DS */
+ str r0, [r1, #0x778] /* GPR_B2DS */
+ str r0, [r1, #0x77c] /* GPR_B3DS */
+
+ str r0, [r1, #0x780] /* GPR_B4DS */
+ str r0, [r1, #0x784] /* GPR_B5DS */
+ str r0, [r1, #0x78c] /* GPR_B6DS */
+ str r0, [r1, #0x748] /* GPR_B7DS */
+
+ str r0, [r1, #0x74c] /* GPR_ADDS*/
+ str r0, [r1, #0x4b4] /* DRAM_SODT0*/
+ str r0, [r1, #0x4b8] /* DRAM_SODT1*/
+
+ .endm
+
+ .macro dq_ddr_io_save
+
+ ldr r4, [r1, #0x5ac] /* DRAM_DQM0 */
+ ldr r5, [r1, #0x5b4] /* DRAM_DQM1 */
+ ldr r6, [r1, #0x528] /* DRAM_DQM2 */
+ ldr r7, [r1, #0x520] /* DRAM_DQM3 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x514] /* DRAM_DQM4 */
+ ldr r5, [r1, #0x510] /* DRAM_DQM5 */
+ ldr r6, [r1, #0x5bc] /* DRAM_DQM6 */
+ ldr r7, [r1, #0x5c4] /* DRAM_DQM7 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x56c] /* DRAM_CAS */
+ ldr r5, [r1, #0x578] /* DRAM_RAS */
+ ldr r6, [r1, #0x588] /* DRAM_SDCLK_0 */
+ ldr r7, [r1, #0x594] /* DRAM_SDCLK_1 */
+ stmfd r0!, {r4-r7}
+
+ ldr r5, [r1, #0x750] /* DDRMODE_CTL */
+ ldr r6, [r1, #0x774] /* DDRMODE */
+ stmfd r0!, {r5-r6}
+
+ ldr r4, [r1, #0x5a8] /* DRAM_SDQS0 */
+ ldr r5, [r1, #0x5b0] /* DRAM_SDQS1 */
+ ldr r6, [r1, #0x524] /* DRAM_SDQS2 */
+ ldr r7, [r1, #0x51c] /* DRAM_SDQS3 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x518] /* DRAM_SDQS4 */
+ ldr r5, [r1, #0x50c] /* DRAM_SDQS5 */
+ ldr r6, [r1, #0x5b8] /* DRAM_SDQS6 */
+ ldr r7, [r1, #0x5c0] /* DRAM_SDQS7 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x784] /* GPR_B0DS */
+ ldr r5, [r1, #0x788] /* GPR_B1DS */
+ ldr r6, [r1, #0x794] /* GPR_B2DS */
+ ldr r7, [r1, #0x79c] /* GPR_B3DS */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x7a0] /* GPR_B4DS */
+ ldr r5, [r1, #0x7a4] /* GPR_B5DS */
+ ldr r6, [r1, #0x7a8] /* GPR_B6DS */
+ ldr r7, [r1, #0x748] /* GPR_B7DS */
+ stmfd r0!, {r4-r7}
+
+ ldr r5, [r1, #0x74c] /* GPR_ADDS*/
+ ldr r6, [r1, #0x59c] /* DRAM_SODT0*/
+ ldr r7, [r1, #0x5a0] /* DRAM_SODT1*/
+ stmfd r0!, {r5-r7}
+
+ .endm
+
+ .macro dq_ddr_io_restore
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x5ac] /* DRAM_DQM0 */
+ str r5, [r1, #0x5b4] /* DRAM_DQM1 */
+ str r6, [r1, #0x528] /* DRAM_DQM2 */
+ str r7, [r1, #0x520] /* DRAM_DQM3 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x514] /* DRAM_DQM4 */
+ str r5, [r1, #0x510] /* DRAM_DQM5 */
+ str r6, [r1, #0x5bc] /* DRAM_DQM6 */
+ str r7, [r1, #0x5c4] /* DRAM_DQM7 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x56c] /* DRAM_CAS */
+ str r5, [r1, #0x578] /* DRAM_RAS */
+ str r6, [r1, #0x588] /* DRAM_SDCLK_0 */
+ str r7, [r1, #0x594] /* DRAM_SDCLK_1 */
+
+ ldmea r0!, {r5-r6}
+ str r5, [r1, #0x750] /* DDRMODE_CTL */
+ str r6, [r1, #0x774] /* DDRMODE */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x5a8] /* DRAM_SDQS0 */
+ str r5, [r1, #0x5b0] /* DRAM_SDQS1 */
+ str r6, [r1, #0x524] /* DRAM_SDQS2 */
+ str r7, [r1, #0x51c] /* DRAM_SDQS3 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x518] /* DRAM_SDQS4 */
+ str r5, [r1, #0x50c] /* DRAM_SDQS5 */
+ str r6, [r1, #0x5b8] /* DRAM_SDQS6 */
+ str r7, [r1, #0x5c0] /* DRAM_SDQS7 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x784] /* GPR_B0DS */
+ str r5, [r1, #0x788] /* GPR_B1DS */
+ str r6, [r1, #0x794] /* GPR_B2DS */
+ str r7, [r1, #0x79c] /* GPR_B3DS */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x7a0] /* GPR_B4DS */
+ str r5, [r1, #0x7a4] /* GPR_B5DS */
+ str r6, [r1, #0x7a8] /* GPR_B6DS */
+ str r7, [r1, #0x748] /* GPR_B7DS */
+
+ ldmea r0!, {r5-r7}
+ str r5, [r1, #0x74c] /* GPR_ADDS*/
+ str r6, [r1, #0x59c] /* DRAM_SODT0*/
+ str r7, [r1, #0x5a0] /* DRAM_SODT1*/
+
+ .endm
+
+ .macro dq_ddr_io_set_lpm
+
+ mov r0, #0
+ str r0, [r1, #0x5ac] /* DRAM_DQM0 */
+ str r0, [r1, #0x5b4] /* DRAM_DQM1 */
+ str r0, [r1, #0x528] /* DRAM_DQM2 */
+ str r0, [r1, #0x520] /* DRAM_DQM3 */
+
+ str r0, [r1, #0x514] /* DRAM_DQM4 */
+ str r0, [r1, #0x510] /* DRAM_DQM5 */
+ str r0, [r1, #0x5bc] /* DRAM_DQM6 */
+ str r0, [r1, #0x5c4] /* DRAM_DQM7 */
+
+ str r0, [r1, #0x56c] /* DRAM_CAS */
+ str r0, [r1, #0x578] /* DRAM_RAS */
+ str r0, [r1, #0x588] /* DRAM_SDCLK_0 */
+ str r0, [r1, #0x594] /* DRAM_SDCLK_1 */
+
+ str r0, [r1, #0x750] /* DDRMODE_CTL */
+ str r0, [r1, #0x774] /* DDRMODE */
+
+ str r0, [r1, #0x5a8] /* DRAM_SDQS0 */
+ str r0, [r1, #0x5b0] /* DRAM_SDQS1 */
+ str r0, [r1, #0x524] /* DRAM_SDQS2 */
+ str r0, [r1, #0x51c] /* DRAM_SDQS3 */
+
+ str r0, [r1, #0x518] /* DRAM_SDQS4 */
+ str r0, [r1, #0x50c] /* DRAM_SDQS5 */
+ str r0, [r1, #0x5b8] /* DRAM_SDQS6 */
+ str r0, [r1, #0x5c0] /* DRAM_SDQS7 */
+
+ str r0, [r1, #0x784] /* GPR_B0DS */
+ str r0, [r1, #0x788] /* GPR_B1DS */
+ str r0, [r1, #0x794] /* GPR_B2DS */
+ str r0, [r1, #0x79c] /* GPR_B3DS */
+
+ str r0, [r1, #0x7a0] /* GPR_B4DS */
+ str r0, [r1, #0x7a4] /* GPR_B5DS */
+ str r0, [r1, #0x7a8] /* GPR_B6DS */
+ str r0, [r1, #0x748] /* GPR_B7DS */
+
+ str r0, [r1, #0x74c] /* GPR_ADDS*/
+ str r0, [r1, #0x59c] /* DRAM_SODT0*/
+ str r0, [r1, #0x5a0] /* DRAM_SODT1*/
+
+ .endm
+
+/******************************************************************
+Invalidate l1 dcache, r0-r4, r6, r7 used
+******************************************************************/
+ .macro invalidate_l1_dcache
+
+ mov r0, #0
+ mcr p15, 2, r0, c0, c0, 0
+ mrc p15, 1, r0, c0, c0, 0
+
+ ldr r1, =0x7fff
+ and r2, r1, r0, lsr #13
+
+ ldr r1, =0x3ff
+
+ and r3, r1, r0, lsr #3 @ NumWays - 1
+ add r2, r2, #1 @ NumSets
+
+ and r0, r0, #0x7
+ add r0, r0, #4 @ SetShift
+
+ clz r1, r3 @ WayShift
+ add r4, r3, #1 @ NumWays
+1:
+ sub r2, r2, #1 @ NumSets--
+ mov r3, r4 @ Temp = NumWays
+2:
+ subs r3, r3, #1 @ Temp--
+ mov r7, r3, lsl r1
+ mov r6, r2, lsl r0
+ orr r7, r7, r6
+ mcr p15, 0, r7, c7, c6, 2
+ bgt 2b
+ cmp r2, #0
+ bgt 1b
+ dsb
+ isb
+
+ .endm
+
+/******************************************************************
+Flush and disable L1 dcache
+******************************************************************/
+ .macro flush_disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0-r12, lr}
+ ldr r0, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r0
+ pop {r0-r12, lr}
+
+ /*
+ * Clear the SCTLR.C bit to prevent further data cache
+ * allocation. Clearing SCTLR.C would make all the data accesses
+ * strongly ordered and would not hit the cache.
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #(1 << 2) @ Disable the C bit
+ mcr p15, 0, r0, c1, c0, 0
+ isb
+
+ /*
+ * Invalidate L1 data cache. Even though only invalidate is
+ * necessary exported flush API is used here. Doing clean
+ * on already clean cache would be almost NOP.
+ */
+ push {r0-r12, lr}
+ ldr r0, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r0
+ pop {r0-r12, lr}
+
+ /*
+ * Execute an ISB instruction to ensure that all of the
+ * CP15 register changes have been committed.
+ */
+ isb
+
+ /*
+ * Execute a barrier instruction to ensure that all cache,
+ * TLB and branch predictor maintenance operations issued
+ * by any CPU in the cluster have completed.
+ */
+ dsb
+ dmb
+
+ .endm
+
+/******************************************************************
+Clean L2 cache
+******************************************************************/
+ .macro clean_l2_cache
+ /* Clean L2 cache to write the dirty data into DRAM to make
+ sure the data alignment between DRAM and L2 cache.
+ */
+#ifdef CONFIG_CACHE_L2X0
+ /* Clean L2 cache here */
+ ldr r1, =L2_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ /* Make way to 0xFFFF 16 ways */
+ mov r0, #0x10000
+ sub r0, r0, #0x1
+ /* 0x7BC is L2X0_CLEAN_WAY */
+ mov r4, #0x700
+ orr r4, #0xBC
+ str r0, [r1, r4]
+3:
+ ldr r5, [r1, r4]
+ ands r5, r5, r0
+ bne 3b
+4:
+ mov r5, #0x0
+ /* 0x730 is L2X0_CACHE_SYNC */
+ mov r4, #0x700
+ orr r4, #0x30
+ str r5, [r1, r4]
+5:
+ ldr r5, [r1, r4]
+ ands r5, r5, #0x1
+ bne 5b
+#endif
+ .endm
+
+ .align 3
+ENTRY(mx6_suspend)
+ stmfd sp!, {r0-r12} @ Save registers
+/*************************************************************
+suspend mode entry
+*************************************************************/
+ mov r12, r3 /* Save CPU type to r12*/
+ mov r11, r0 /* Save the state in r11 */
+
+ cmp r12, #MXC_CPU_MX6SL
+ beq dormant
+
+ cmp r0, #0x1
+ bne dormant /* dormant mode */
+
+ /* Need to flush and disable L1 dcache*/
+ flush_disable_l1_dcache
+
+ /* Need to clean L2 dcache*/
+ clean_l2_cache
+
+ /* Disable L2 cache */
+#ifdef CONFIG_CACHE_L2X0
+ ldr r2, =L2_BASE_ADDR
+ add r2, r2, #PERIPBASE_VIRT
+ mov r4, #0x0
+ str r4, [r2, #L2X0_CTRL]
+#endif
+
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+
+ /* Invalidate L1 I-cache first */
+ mov r1, #0x0
+ mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache
+
+ /* Need to invalidate L1 dcache, as the power is dropped */
+ invalidate_l1_dcache
+
+ /* Enable L1 dcache first */
+ mrc p15, 0, r0, c1, c0, 0
+ orr r0, r0, #(1 << 2) @ Disable the C bit
+ mcr p15, 0, r0, c1, c0, 0
+
+ /* Enable L2 cache here */
+#ifdef CONFIG_CACHE_L2X0
+ ldr r2, =L2_BASE_ADDR
+ add r2, r2, #PERIPBASE_VIRT
+ mov r4, #0x1
+ str r4, [r2, #L2X0_CTRL]
+#endif
+
+/***********************************************************
+never run to here
+************************************************************/
+ b out /* exit standby */
+ /* Place the literal pool here so that
+ * literals are within 4KB range
+ */
+ .ltorg
+/************************************************************
+dormant entry, data save in stack, save sp in the src_gpr2
+************************************************************/
+dormant:
+ mov r3, r1
+ mov r0, r1
+ add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */
+ ldr r4, =SRC_BASE_ADDR
+ add r4, r4, #PERIPBASE_VIRT
+ str r0, [r4, #SRC_GPR2_OFFSET] /* set src_gpr2 */
+/************************************************************
+saved register and context as below:
+ ddr_iomux set
+ sp
+ spsr
+ lr
+ CPACR
+ TTBR0
+ TTBR1
+ TTBCR
+ DACR
+ PRRR
+ NMRR
+ ACTLR
+ Context ID
+ User r/w thread ID
+ Secure or NS VBAR
+ CPSR
+ SCTLR
+************************************************************/
+ /* save mmdc iomux setting, stack is from the tail of
+ iram_suspend base */
+
+ mov r0, r2 /* get suspend_iram_base */
+ add r0, r0, #IRAM_SUSPEND_SIZE /* 5K */
+
+ mov r4, r12 @ Store cpu type
+ stmfd r0!, {r4}
+ mov r4, r11 @ Store state entered
+ stmfd r0!, {r4}
+
+ ldr r1, =MX6Q_IOMUXC_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ cmp r12, #MXC_CPU_MX6Q
+ bne dl_io_save
+ dq_ddr_io_save
+ b ddr_io_save_done
+dl_io_save:
+ cmp r12, #MXC_CPU_MX6DL
+ bne sl_io_save
+ dl_ddr_io_save
+ b ddr_io_save_done
+sl_io_save:
+ sl_ddr_io_save
+
+ddr_io_save_done:
+#ifdef CONFIG_CACHE_L2X0
+ ldr r1, =L2_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ ldr r4, [r1, #L2X0_CTRL]
+ ldr r5, [r1, #L2X0_AUX_CTRL]
+ ldr r6, [r1, #L2X0_TAG_LATENCY_CTRL]
+ ldr r7, [r1, #L2X0_DATA_LATENCY_CTRL]
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #L2X0_PREFETCH_CTRL]
+ ldr r5, [r1, #L2X0_POWER_CTRL]
+ stmfd r0!, {r4-r5}
+#endif
+
+ mov r4, sp @ Store sp
+ mrs r5, spsr @ Store spsr
+ mov r6, lr @ Store lr
+ stmfd r0!, {r4-r6}
+
+ /* c1 and c2 registers */
+ mrc p15, 0, r4, c1, c0, 2 @ CPACR
+ mrc p15, 0, r5, c2, c0, 0 @ TTBR0
+ mrc p15, 0, r6, c2, c0, 1 @ TTBR1
+ mrc p15, 0, r7, c2, c0, 2 @ TTBCR
+ stmfd r0!, {r4-r7}
+
+ /* c3 and c10 registers */
+ mrc p15, 0, r4, c3, c0, 0 @ DACR
+ mrc p15, 0, r5, c10, c2, 0 @ PRRR
+ mrc p15, 0, r6, c10, c2, 1 @ NMRR
+ mrc p15, 0, r7, c1, c0, 1 @ ACTLR
+ stmfd r0!,{r4-r7}
+
+ /* c12, c13 and CPSR registers */
+ mrc p15, 0, r4, c13, c0, 1 @ Context ID
+ mrc p15, 0, r5, c13, c0, 2 @ User r/w thread ID
+ mrc p15, 0, r6, c12, c0, 0 @ Secure or NS VBAR
+ mrs r7, cpsr @ Store CPSR
+ stmfd r0!, {r4-r7}
+
+ /* c1 control register */
+ mrc p15, 0, r4, c1, c0, 0 @ SCTLR
+ stmfd r0!, {r4}
+
+ /* Need to flush and disable L1 dcache*/
+ flush_disable_l1_dcache
+
+ /* Need to clean L2 dcache*/
+ clean_l2_cache
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r6, [r6]
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r6, c2, c0, 1
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+/****************************************************************
+set ddr iomux to low power mode
+****************************************************************/
+ ldr r1, =MMDC_P0_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Put DDR explicitly into self-refresh. */
+ /* Disable Automatic power savings. */
+ ldr r0, [r1, #0x404]
+ orr r0, r0, #0x01
+ str r0, [r1, #0x404]
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r0, [r1, #0x404]
+ orr r0, r0, #0x200000
+ str r0, [r1, #0x404]
+
+poll_dvfs_set_1:
+ ldr r0, [r1, #0x404]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ bne poll_dvfs_set_1
+
+ /* set mmdc iomux to low power mode */
+ ldr r1, =MX6Q_IOMUXC_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ cmp r12, #MXC_CPU_MX6Q
+ bne dl_io_set_lpm
+ dq_ddr_io_set_lpm
+ b ddr_io_set_lpm_done
+dl_io_set_lpm:
+ cmp r12, #MXC_CPU_MX6DL
+ bne sl_io_set_lpm
+ dl_ddr_io_set_lpm
+ b ddr_io_set_lpm_done
+sl_io_set_lpm:
+ sl_ddr_io_set_lpm
+
+ddr_io_set_lpm_done:
+ /* Do Analog Power Optimizations
+ * for MX6SL in standby mode.
+ */
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_savings
+ cmp r11, #1
+ bne no_analog_savings
+
+ /* We are here because on
+ * MX6SL, we want to lower
+ * the power in Standby mode.
+ */
+ mx6sl_standy_saving_set
+
+no_analog_savings:
+
+/****************************************************************
+save resume pointer into SRC_GPR1
+****************************************************************/
+ ldr r0, =mx6_suspend
+ ldr r1, =resume
+ sub r1, r1, r0
+ add r3, r3, r1
+ ldr r1, =SRC_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ str r3, [r1, #SRC_GPR1_OFFSET]
+
+ /* Mask all GPC interrupts before
+ * enabling the RBC counters to
+ * avoid the counter starting too
+ * early if an interupt is already
+ * pending.
+ */
+ ldr r3, =GPC_BASE_ADDR
+ add r3, r3, #PERIPBASE_VIRT
+ ldr r4, [r3, #0x08]
+ ldr r5, [r3, #0x0c]
+ ldr r6, [r3, #0x10]
+ ldr r7, [r3, #0x14]
+
+ ldr r8, =0xffffffff
+ str r8, [r3, #0x08]
+ str r8, [r3, #0x0c]
+ str r8, [r3, #0x10]
+ str r8, [r3, #0x14]
+
+ /* Enable the RBC bypass counter here
+ * to hold off the interrupts.
+ * RBC counter = 32 (1ms)
+ * Minimum RBC delay should be
+ * 400us for the analog LDOs to
+ * power down.
+ */
+ ldr r1, =CCM_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ ldr r8, [r1, #0x0]
+ ldr r0, =0x7E00000
+ bic r8, r8, r0
+ ldr r0, =0x4000000
+ orr r8, r8, r0
+ str r8, [r1, #0x0]
+
+ /* Enable the counter. */
+ ldr r8, [r1, #0x0]
+ orr r8, r8, #0x8000000
+ str r8, [r1, #0x0]
+
+ /* Unmask all the GPC interrupts. */
+ str r4, [r3, #0x08]
+ str r5, [r3, #0x0c]
+ str r6, [r3, #0x10]
+ str r7, [r3, #0x14]
+
+
+ /* Now delay for a short while (3usec)
+ * ARM is at 1GHz at this point
+ * so a short loop should be enough.
+ * This delay is required to ensure that
+ * the RBC counter can start counting in case an
+ * interrupt is already pending or in case an interrupt
+ * arrives just as ARM is about to assert DSM_request.
+ */
+ ldr r4, =2000
+rbc_loop:
+ sub r4, r4, #0x1
+ cmp r4, #0x0
+ bne rbc_loop
+
+ /*if internal ldo(VDDARM) bypassed,analog bypass it for DSM(0x1e) and
+ *restore it when resume(0x1f).
+ */
+ ldr r1, =ANATOP_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ ldr r4, [r1, #0x140]
+ and r4, r4, #0x1f
+ cmp r4, #0x1f
+ bne ldo_check_done1
+ldo_analog_bypass:
+ ldr r4, [r1, #0x140]
+ bic r4, r4, #0x1f
+ orr r4, r4, #0x1e
+ str r4, [r1, #0x140]
+ldo_check_done1:
+/****************************************************************
+execute a wfi instruction to let SOC go into stop mode.
+****************************************************************/
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+
+/****************************************************************
+if go here, means there is a wakeup irq pending, we should resume
+system immediately.
+****************************************************************/
+ /*restore it with 0x1f if use ldo bypass mode.*/
+ ldr r1, =ANATOP_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ ldr r3, [r1, #0x140]
+ and r3, r3, #0x1f
+ cmp r3, #0x1e
+ bne ldo_check_done2
+ldo_bypass_restore:
+ ldr r3, [r1, #0x140]
+ orr r3, r3, #0x1f
+ str r3, [r1, #0x140]
+ldo_check_done2:
+ /*
+ * Get the address of IRAM stack
+ */
+ ldr r0, =SRC_BASE_ADDR
+ add r0, r0, #PERIPBASE_VIRT
+ ldr r0, [r0, #SRC_GPR2_OFFSET]
+
+ add r0, r0, #PERIPBASE_VIRT
+ ldmea r0!, {r12} @ get cpu type to make ddr io
+ @ offset right
+
+ ldmea r0!, {r11} @ standby or mem
+
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_restore
+
+ cmp r11, #0x1
+ bne no_analog_restore
+
+ ldr r3, =CCM_BASE_ADDR
+ add r3, r3, #PERIPBASE_VIRT
+
+ /* Restore the analog settings. */
+ mx6sl_standby_savings_restore
+
+no_analog_restore:
+ ldr r1, =MX6Q_IOMUXC_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ cmp r12, #MXC_CPU_MX6Q
+ bne dl_io_restore
+ dq_ddr_io_restore
+ b ddr_io_restore_done
+dl_io_restore:
+ cmp r12, #MXC_CPU_MX6DL
+ bne sl_io_restore
+ dl_ddr_io_restore
+ b ddr_io_restore_done
+sl_io_restore:
+ sl_ddr_io_restore
+ ldr r1, =MMDC_P0_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =0x83c
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+fifo_reset1_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne fifo_reset1_wait
+
+ /* reset FIFO a second time */
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+fifo_reset2_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne fifo_reset2_wait
+
+ddr_io_restore_done:
+ ldr r1, =MMDC_P0_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Ensure DDR exits self-refresh. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r1, #0x404]
+
+poll_dvfs_clear_1:
+ ldr r6, [r1, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r1, #0x404]
+
+ /* Add enough nops so that the
+ * prefetcher will not get instructions
+ * from DDR before its IO pads
+ * are restored.
+ */
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mrc p15, 0, r1, c1, c0, 0
+ orr r1, r1, #(1 << 2) @ Enable the C bit
+ mcr p15, 0, r1, c1, c0, 0
+
+ /* Restore TTBCR */
+ dsb
+ isb
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ b out /* exit standby */
+ .ltorg
+
+/****************************************************************
+when SOC exit stop mode, arm core restart from here, currently
+are running with MMU off.
+****************************************************************/
+resume:
+ /*restore it with 0x1f if use ldo bypass mode.*/
+ ldr r1, =ANATOP_BASE_ADDR
+ ldr r3, [r1, #0x140]
+ and r3, r3, #0x1f
+ cmp r3, #0x1e
+ bne ldo_check_done3
+ ldr r3, [r1, #0x140]
+ orr r3, r3, #0x1f
+ str r3, [r1, #0x140]
+ldo_check_done3:
+ /* Invalidate L1 I-cache first */
+ mov r1, #0x0
+ mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache
+ mcr p15, 0, r1, c7, c5, 0 @ invalidate Icache to PoU
+ mcr p15, 0, r1, c7, c5, 6 @ invalidate branch predictor
+ mov r1, #0x1800
+ mcr p15, 0, r1, c1, c0, 0 @ enable the Icache and branch prediction
+ isb @ as soon as possible
+
+ /* Need to invalidate L1 dcache */
+ invalidate_l1_dcache
+
+ ldr r0, =SRC_BASE_ADDR
+ str r1, [r0, #SRC_GPR1_OFFSET] /* clear SRC_GPR1 */
+ ldr r0, [r0, #SRC_GPR2_OFFSET]
+
+ ldmea r0!, {r12} @ get cpu type
+
+ ldmea r0!, {r11} @ standby or mem
+
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_restore1
+
+ cmp r11, #0x1
+ bne no_analog_restore1
+
+ ldr r1, =ANATOP_BASE_ADDR
+ ldr r3, =CCM_BASE_ADDR
+
+ /* Restore the analog settings. */
+ mx6sl_standby_pg_savings_restore
+
+no_analog_restore1:
+ /* Restore DDR IO */
+ ldr r1, =MX6Q_IOMUXC_BASE_ADDR
+
+ cmp r12, #MXC_CPU_MX6Q
+ bne dl_io_dsm_restore
+ dq_ddr_io_restore
+ b ddr_io_restore_dsm_done
+dl_io_dsm_restore:
+ cmp r12, #MXC_CPU_MX6DL
+ bne sl_io_dsm_restore
+ dl_ddr_io_restore
+ b ddr_io_restore_dsm_done
+sl_io_dsm_restore:
+ sl_ddr_io_restore
+ ldr r1, =MMDC_P0_BASE_ADDR
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =0x83c
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+dsm_fifo_reset1_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne dsm_fifo_reset1_wait
+
+ /* reset FIFO a second time */
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+dsm_fifo_reset2_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne dsm_fifo_reset2_wait
+
+ddr_io_restore_dsm_done:
+ ldr r1, =MMDC_P0_BASE_ADDR
+
+ /* Ensure DDR exits self-refresh. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r1, #0x404]
+
+poll_dvfs_clear_2:
+ ldr r6, [r1, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_2
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r1, #0x404]
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r2, =L2_BASE_ADDR
+ ldmea r0!, {r4-r7}
+ /* L2 will be enabled after L1 is enabled */
+ mov r4, #0x0
+ str r4, [r2, #L2X0_CTRL]
+ str r5, [r2, #L2X0_AUX_CTRL]
+ str r6, [r2, #L2X0_TAG_LATENCY_CTRL]
+ str r7, [r2, #L2X0_DATA_LATENCY_CTRL]
+
+ ldmea r0!, {r4-r5}
+ str r4, [r2, #L2X0_PREFETCH_CTRL]
+ str r5, [r2, #L2X0_POWER_CTRL]
+#endif
+
+ /* Restore cp15 registers and cpu type */
+ ldmea r0!, {r4-r6}
+ mov sp, r4 @ Restore sp
+ msr spsr_cxsf, r5 @ Restore spsr
+ mov lr, r6 @ Restore lr
+
+ /* c1 and c2 registers */
+ ldmea r0!, {r4-r7}
+ mcr p15, 0, r4, c1, c0, 2 @ CPACR
+ mcr p15, 0, r5, c2, c0, 0 @ TTBR0
+ mcr p15, 0, r6, c2, c0, 1 @ TTBR1
+ mcr p15, 0, r7, c2, c0, 2 @ TTBCR
+
+ /* c3 and c10 registers */
+ ldmea r0!,{r4-r7}
+ mcr p15, 0, r4, c3, c0, 0 @ DACR
+ mcr p15, 0, r5, c10, c2, 0 @ PRRR
+ mcr p15, 0, r6, c10, c2, 1 @ NMRR
+ mcr p15, 0, r7, c1, c0, 1 @ ACTLR
+
+ /* c12, c13 and CPSR registers */
+ ldmea r0!,{r4-r7}
+ mcr p15, 0, r4, c13, c0, 1 @ Context ID
+ mcr p15, 0, r5, c13, c0, 2 @ User r/w thread ID
+ mrc p15, 0, r6, c12, c0, 0 @ Secure or NS VBAR
+ msr cpsr, r7 @ store cpsr
+
+ /*
+ * Enabling MMU here. Page entry needs to be altered
+ * to create temporary 1:1 map and then resore the entry
+ * ones MMU is enabled
+ */
+ mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl
+ and r7, #0x7 @ Extract N (0:2) to decide
+ cmp r7, #0x0 @ TTBR0/TTBR1
+ beq use_ttbr0
+ttbr_error:
+ b ttbr_error @ Only N = 0 supported
+use_ttbr0:
+ mrc p15, 0, r2, c2, c0, 0 @ Read TTBR0
+ ldr r5, =TTRBIT_MASK
+ and r2, r5
+ mov r4, pc
+ ldr r5, =TABLE_INDEX_MASK
+ and r4, r5 @ r4 = 31 to 20 bits of pc
+ ldr r1, =TABLE_ENTRY
+ add r1, r1, r4 @ r1 has value of table entry
+ lsr r4, #18 @ Address of table entry
+ add r2, r4 @ r2 - location to be modified
+
+ /* Storing previous entry of location being modified */
+ ldr r4, [r2]
+ mov r9, r4
+ str r1, [r2]
+
+ /*
+ * Storing address of entry being modified
+ * It will be restored after enabling MMU
+ */
+ mov r10, r2
+
+ mov r1, #0
+ mcr p15, 0, r1, c7, c5, 4 @ Flush prefetch buffer
+ mcr p15, 0, r1, c8, c5, 0 @ Invalidate ITLB
+ mcr p15, 0, r1, c8, c6, 0 @ Invalidate DTLB
+
+ /*
+ * Restore control register but don't enable Data caches here.
+ * Caches will be enabled after restoring MMU table entry.
+ */
+ ldmea r0!, {r4}
+ mov r11, r4
+ ldr r2, =CACHE_DISABLE_MASK
+ and r4, r4, r2
+ mcr p15, 0, r4, c1, c0, 0
+ isb
+ dsb
+ ldr r1, =mmu_on_label
+ bx r1
+mmu_on_label:
+
+/************************************************************
+restore control register to enable cache
+************************************************************/
+ mov r0, r11
+ mcr p15, 0, r0, c1, c0, 0 @ with caches enabled.
+ dsb
+ isb
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Enable L2 cache here */
+ ldr r2, =L2_BASE_ADDR
+ add r2, r2, #PERIPBASE_VIRT
+ mov r4, #0x1
+ str r4, [r2, #L2X0_CTRL]
+#endif
+
+ mov r8, lr
+ push {r0-r3, r12}
+
+ /* Set up the per-CPU stacks */
+ bl cpu_init
+ pop {r0-r3, r12}
+
+ /*
+ * Restore the MMU table entry that was modified for
+ * enabling MMU.
+ */
+ ldr r4, =PAGE_OFFSET
+
+ cmp r12, #MXC_CPU_MX6SL
+ bne dq_dl_phy_offset
+ ldr r5, =MX6SL_PHYS_OFFSET
+ b get_phy_offset_done
+dq_dl_phy_offset:
+ ldr r5, =MX6_PHYS_OFFSET
+get_phy_offset_done:
+
+ sub r4, r4, r5
+ add r4, r4, r10
+ str r9, [r4]
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c1, 6 @ flush TLB and issue barriers
+ mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer
+ mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB
+ mcr p15, 0, r0, c8, c5, 0 @ Invalidate ITLB
+ mcr p15, 0, r0, c8, c6, 0 @ Invalidate DTLB
+ dsb
+ isb
+
+/***********************************************************
+return back to mx6_suspend_enter for dormant
+***********************************************************/
+ mov lr, r8
+ ldmfd sp!, {r0-r12}
+ mov pc, lr
+/************************************************
+return back to mx6_suspend_enter for suspend
+*************************************************/
+out:
+ ldmfd sp!, {r0-r12}
+ mov pc, lr
+
+ .type mx6_do_suspend, #object
+ENTRY(mx6_do_suspend)
+ .word mx6_suspend
+ .size mx6_suspend, . - mx6_suspend
diff --git a/arch/arm/mach-mx6/mx6_wfi.S b/arch/arm/mach-mx6/mx6_wfi.S
new file mode 100644
index 00000000..afe7b9a3
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6_wfi.S
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010-2012 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 <linux/linkage.h>
+#include <mach/hardware.h>
+
+/*
+ * mx6_wait
+ *
+ * Idle the processor (eg, wait for interrupt).
+ * Make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ */
+ENTRY(mx6_wait)
+
+ push {r4, r5, r6, r7, r8, r9}
+
+ mov r7, r2 /* Store the arm_podf to be used. */
+ mov r6, r3
+
+ ldr r2, =ANATOP_BASE_ADDR
+ add r2, r2, #PERIPBASE_VIRT
+
+ ldr r8, =CCM_BASE_ADDR
+ add r8, r8, #PERIPBASE_VIRT
+
+
+ /* get the flags variables into the cache */
+ ldr r3, [r0]
+
+ /* get CPU ID */
+ mrc p15,0,r5,c0,c0,5
+ and r5, r5, #0x3
+
+ mov r4,#0xff
+ strb r4,[r0,r5]
+
+ dsb
+
+ mvn r4, #0x0
+ ldr r3, [r0]
+ cmp r3, r4
+ bne DO_WFI
+
+ mov r4, #0x1
+ ldrex r3, [r1]
+ cmp r3, #0x0
+ strexeq r3, r4, [r1]
+ cmpeq r3, #0x0
+ bne DO_WFI
+
+ mov r3, #0xff
+
+ /* Check to see if we need to switch to 24MHz */
+ cmp r7, #0
+ bne use_podf
+ /* Switch ARM to PLL1 output. */
+ /* PLL1 should already be in bypass state. */
+ ldr r6, [r8, #0x0C]
+ bic r6, r6, #0x04
+ str r6, [r8, #0x0C]
+ b cont
+
+use_podf:
+ /* Change ARM_PODF to the max possible podf
+ * so that ARM_CLK to IPG_CLK is in 12:5 ratio.
+ */
+ str r7, [r8, #0x10]
+ /* Loop till podf is accepted. */
+podf_loop:
+ ldr r4, [r8, #0x48]
+ cmp r4, #0x0
+ bne podf_loop
+
+ /* dmb */
+
+cont:
+ str r3, [r1]
+
+ dsb
+
+ mvn r4, #0x0
+ ldr r3, [r0]
+ cmp r3, r4
+ beq DO_WFI
+
+ mov r3, #0x0
+ /* Switch to 24MHz or use ARM_PODF. */
+ cmp r7, #0x0
+ bne use_podf1
+ /* Set pll1_sw_clk to run from STEP_CLK. */
+ orr r6, r6, #0x04
+ str r6, [r8, #0x0C]
+ b DO_WFI
+use_podf1:
+ str r6, [r8, #0x10]
+
+ str r3, [r1]
+
+DO_WFI:
+ dsb
+
+ wfi
+
+ mov r4, #0x0
+ strb r4, [r0, r5]
+
+ dsb
+
+ ldr r3, [r1]
+ cmp r3, #0xff
+ bne DONE
+
+ mov r4, #0x0
+ cmp r7, #0x0
+ bne use_podf2
+ /* Set pll1_sw_clk to run from STEP_CLK. */
+ ldr r6, [r8, #0x0C]
+ orr r6, r6, #0x04
+ str r6, [r8, #0x0C]
+
+ b cont1
+
+use_podf2:
+ str r6, [r8, #0x10]
+
+cont1:
+ mov r3, #0x0
+ str r3, [r1]
+
+DONE:
+
+ pop {r4,r5, r6, r7, r8, r9}
+
+ /* Restore registers */
+ mov pc, lr
+
+ .type mx6_do_wait, #object
+ENTRY(mx6_do_wait)
+ .word mx6_wait
+ .size mx6_wait, . - mx6_wait
diff --git a/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c
new file mode 100644
index 00000000..671233f3
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2011-2012 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/pfuze.h>
+#include <linux/io.h>
+#include <mach/irqs.h>
+#include <mach/system.h>
+#include "crm_regs.h"
+#include "regs-anadig.h"
+#include "cpu_op-mx6.h"
+
+/*
+ * Convenience conversion.
+ * Here atm, maybe there is somewhere better for this.
+ */
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+#define PFUZE100_I2C_DEVICE_NAME "pfuze100"
+/* 7-bit I2C bus slave address */
+#define PFUZE100_I2C_ADDR (0x08)
+#define PFUZE100_DEVICEID (0x0)
+#define PFUZE100_REVID (0x3)
+#define PFUZE100_SW1AMODE (0x23)
+#define PFUZE100_SW1AVOL 32
+#define PFUZE100_SW1AVOL_VSEL_M (0x3f<<0)
+#define PFUZE100_SW1CVOL 46
+#define PFUZE100_SW1CVOL_VSEL_M (0x3f<<0)
+#define PFUZE100_SW1ACON 36
+#define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1ACON_SPEED_M (0x3<<6)
+#define PFUZE100_SW1CCON 49
+#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1CCON_SPEED_M (0x3<<6)
+
+extern u32 arm_max_freq;
+extern u32 enable_ldo_mode;
+
+static struct regulator_consumer_supply sw1a_consumers[] = {
+ {
+ .supply = "VDDCORE",
+ }
+};
+
+static struct regulator_consumer_supply sw1c_consumers[] = {
+ {
+ .supply = "VDDSOC",
+ }
+};
+
+static struct regulator_consumer_supply sw2_consumers[] = {
+ {
+ .supply = "P3V0_VDDHIGH_SW2",
+ }
+};
+
+static struct regulator_consumer_supply sw3_consumers[] = {
+ {
+ .supply = "P1V5_DDR_SW3",
+ }
+};
+
+static struct regulator_consumer_supply sw4_consumers[] = {
+ {
+ .supply = "P1V8_SW4",
+ }
+};
+
+static struct regulator_consumer_supply swbst_consumers[] = {
+ {
+ .supply = "P5V0_SWBST",
+ }
+};
+
+static struct regulator_consumer_supply vsnvs_consumers[] = {
+ {
+ .supply = "P3V0_STBY",
+ }
+};
+
+static struct regulator_consumer_supply vgen1_consumers[] = {
+ {
+ .supply = "P1V2_VGEN1",
+ }
+};
+
+static struct regulator_consumer_supply vgen2_consumers[] = {
+ {
+ .supply = "P1V5_VGEN2",
+ }
+};
+
+static struct regulator_consumer_supply vgen3_consumers[] = {
+ {
+ .supply = "P1V8_VGEN3",
+ }
+};
+
+static struct regulator_consumer_supply vgen4_consumers[] = {
+ {
+ .supply = "P1V8_VGEN4",
+ }
+};
+
+static struct regulator_consumer_supply vgen5_consumers[] = {
+ {
+ .supply = "P2V5_VGEN5",
+ }
+};
+
+static struct regulator_consumer_supply vgen6_consumers[] = {
+ {
+ .supply = "P2V8_VGEN6",
+ }
+};
+
+static struct regulator_init_data sw1a_init = {
+ .constraints = {
+ .name = "SW1A",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 650000,
+ .max_uV = 1437500,
+#else
+ .min_uV = 300000,
+ .max_uV = 1875000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .boot_on = 1,
+ .always_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 975000,/*0.9V+6%*/
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1a_consumers),
+ .consumer_supplies = sw1a_consumers,
+};
+
+static struct regulator_init_data sw1b_init = {
+ .constraints = {
+ .name = "SW1B",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw1c_init = {
+ .constraints = {
+ .name = "SW1C",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 975000,/*0.9V+6%*/
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers),
+ .consumer_supplies = sw1c_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+#if PFUZE100_SW2_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw2_consumers),
+ .consumer_supplies = sw2_consumers,
+};
+
+static struct regulator_init_data sw3a_init = {
+ .constraints = {
+ .name = "SW3A",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw3_consumers),
+ .consumer_supplies = sw3_consumers,
+};
+
+static struct regulator_init_data sw3b_init = {
+ .constraints = {
+ .name = "SW3B",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+#if PFUZE100_SW4_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw4_consumers),
+ .consumer_supplies = sw4_consumers,
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "SWBST",
+ .min_uV = 5000000,
+ .max_uV = 5150000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 0,
+ .boot_on = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(swbst_consumers),
+ .consumer_supplies = swbst_consumers,
+};
+
+static struct regulator_init_data vsnvs_init = {
+ .constraints = {
+ .name = "VSNVS",
+ .min_uV = 1200000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vsnvs_consumers),
+ .consumer_supplies = vsnvs_consumers,
+};
+
+static struct regulator_init_data vrefddr_init = {
+ .constraints = {
+ .name = "VREFDDR",
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "VGEN1",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 0,
+ .boot_on = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen1_consumers),
+ .consumer_supplies = vgen1_consumers,
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "VGEN2",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen2_consumers),
+ .consumer_supplies = vgen2_consumers,
+
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "VGEN3",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 0,
+ .boot_on = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen3_consumers),
+ .consumer_supplies = vgen3_consumers,
+};
+
+static struct regulator_init_data vgen4_init = {
+ .constraints = {
+ .name = "VGEN4",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen4_consumers),
+ .consumer_supplies = vgen4_consumers,
+};
+
+static struct regulator_init_data vgen5_init = {
+ .constraints = {
+ .name = "VGEN5",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen5_consumers),
+ .consumer_supplies = vgen5_consumers,
+};
+
+static struct regulator_init_data vgen6_init = {
+ .constraints = {
+ .name = "VGEN6",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen6_consumers),
+ .consumer_supplies = vgen6_consumers,
+};
+
+static int pfuze100_init(struct mc_pfuze *pfuze)
+{
+ int ret, i;
+ unsigned char value;
+
+ /*use default mode(ldo bypass) if no param from cmdline*/
+ if (enable_ldo_mode == LDO_MODE_DEFAULT)
+ enable_ldo_mode = LDO_MODE_ENABLED;
+
+ /*read Device ID*/
+ ret = pfuze_reg_read(pfuze, PFUZE100_DEVICEID, &value);
+ if (ret)
+ goto err;
+ if (value != 0x10) {
+ printk(KERN_ERR "wrong device id:%x!\n", value);
+ goto err;
+ }
+
+ /*read Revision ID*/
+ ret = pfuze_reg_read(pfuze, PFUZE100_REVID, &value);
+ if (ret)
+ goto err;
+ if (value == 0x10) {
+ printk(KERN_WARNING "PF100 1.0 chip found!\n");
+ /* workaround ER1 of pfuze1.0: set all buck regulators in PWM mode
+ * except SW1C(APS) in normal and PFM mode in standby.
+ */
+ for (i = 0; i < 7; i++) {
+ if (i == 2)/*SW1C*/
+ value = 0xc;/*normal:APS mode;standby:PFM mode*/
+ else
+ value = 0xd;/*normal:PWM mode;standby:PFM mode*/
+ ret = pfuze_reg_write(pfuze,
+ PFUZE100_SW1AMODE + (i * 7),
+ value);
+ if (ret)
+ goto err;
+ }
+
+ } else {
+ /*set all switches APS in normal and PFM mode in standby*/
+ for (i = 0; i < 7; i++) {
+ value = 0xc;
+ ret = pfuze_reg_write(pfuze,
+ PFUZE100_SW1AMODE + (i * 7),
+ value);
+ if (ret)
+ goto err;
+ }
+
+ }
+ /*use ldo active mode if use 1.2GHz,otherwise use ldo bypass mode*/
+ if (arm_max_freq == CPU_AT_1_2GHz) {
+ /*VDDARM_IN 1.425*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x2d);
+ if (ret)
+ goto err;
+ /*VDDSOC_IN 1.425V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x2d);
+ if (ret)
+ goto err;
+ enable_ldo_mode = LDO_MODE_ENABLED;
+ } else if (enable_ldo_mode == LDO_MODE_BYPASSED) {
+ /*decrease VDDARM_IN/VDDSOC_IN,since we will use ldo bypass mode*/
+ /*VDDARM_IN 1.3V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x28);
+ if (ret)
+ goto err;
+ /*VDDSOC_IN 1.3V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x28);
+ if (ret)
+ goto err;
+ /*set SW1AB/1C DVSPEED as 25mV step each 4us,quick than 16us before.*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON,
+ PFUZE100_SW1ACON_SPEED_M,
+ PFUZE100_SW1ACON_SPEED_VAL);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON,
+ PFUZE100_SW1CCON_SPEED_M,
+ PFUZE100_SW1CCON_SPEED_VAL);
+ if (ret)
+ goto err;
+ } else if (enable_ldo_mode != LDO_MODE_BYPASSED) {
+ /*Increase VDDARM_IN/VDDSOC_IN to 1.375V in ldo active mode*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x2b);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x2b);
+ if (ret)
+ goto err;
+ }
+ return 0;
+err:
+ printk(KERN_ERR "pfuze100 init error!\n");
+ return -1;
+}
+
+static struct pfuze_regulator_init_data mx6q_sabreauto_pfuze100_regulators[] = {
+ {.id = PFUZE100_SW1A, .init_data = &sw1a_init},
+ {.id = PFUZE100_SW1B, .init_data = &sw1b_init},
+ {.id = PFUZE100_SW1C, .init_data = &sw1c_init},
+ {.id = PFUZE100_SW2, .init_data = &sw2_init},
+ {.id = PFUZE100_SW3A, .init_data = &sw3a_init},
+ {.id = PFUZE100_SW3B, .init_data = &sw3b_init},
+ {.id = PFUZE100_SW4, .init_data = &sw4_init},
+ {.id = PFUZE100_SWBST, .init_data = &swbst_init},
+ {.id = PFUZE100_VSNVS, .init_data = &vsnvs_init},
+ {.id = PFUZE100_VREFDDR, .init_data = &vrefddr_init},
+ {.id = PFUZE100_VGEN1, .init_data = &vgen1_init},
+ {.id = PFUZE100_VGEN2, .init_data = &vgen2_init},
+ {.id = PFUZE100_VGEN3, .init_data = &vgen3_init},
+ {.id = PFUZE100_VGEN4, .init_data = &vgen4_init},
+ {.id = PFUZE100_VGEN5, .init_data = &vgen5_init},
+ {.id = PFUZE100_VGEN6, .init_data = &vgen6_init},
+};
+
+static struct pfuze_platform_data pfuze100_plat = {
+ .flags = PFUZE_USE_REGULATOR,
+ .num_regulators = ARRAY_SIZE(mx6q_sabreauto_pfuze100_regulators),
+ .regulators = mx6q_sabreauto_pfuze100_regulators,
+ .pfuze_init = pfuze100_init,
+
+};
+
+static struct i2c_board_info __initdata pfuze100_i2c_device = {
+ I2C_BOARD_INFO(PFUZE100_I2C_DEVICE_NAME, PFUZE100_I2C_ADDR),
+ .platform_data = &pfuze100_plat,
+};
+
+int __init mx6q_sabreauto_init_pfuze100(u32 int_gpio)
+{
+ pfuze100_i2c_device.irq = gpio_to_irq(int_gpio); /*update INT gpio */
+ return i2c_register_board_info(1, &pfuze100_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c
new file mode 100644
index 00000000..c18a0143
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2012 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/pfuze.h>
+#include <linux/io.h>
+#include <mach/irqs.h>
+#include <mach/system.h>
+#include "crm_regs.h"
+#include "regs-anadig.h"
+#include "cpu_op-mx6.h"
+
+/*
+ * Convenience conversion.
+ * Here atm, maybe there is somewhere better for this.
+ */
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+#define PFUZE100_I2C_DEVICE_NAME "pfuze100"
+/* 7-bit I2C bus slave address */
+#define PFUZE100_I2C_ADDR (0x08)
+#define PFUZE100_DEVICEID (0x0)
+#define PFUZE100_REVID (0x3)
+#define PFUZE100_SW1AMODE (0x23)
+#define PFUZE100_SW1AVOL 32
+#define PFUZE100_SW1AVOL_VSEL_M (0x3f<<0)
+#define PFUZE100_SW1CVOL 46
+#define PFUZE100_SW1CVOL_VSEL_M (0x3f<<0)
+#define PFUZE100_SW1ACON 36
+#define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1ACON_SPEED_M (0x3<<6)
+#define PFUZE100_SW1CCON 49
+#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1CCON_SPEED_M (0x3<<6)
+
+extern u32 arm_max_freq;
+extern u32 enable_ldo_mode;
+
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "VDDCORE",
+ }
+};
+static struct regulator_consumer_supply sw1c_consumers[] = {
+ {
+ .supply = "VDDSOC",
+ },
+};
+
+static struct regulator_consumer_supply sw2_consumers[] = {
+ {
+ .supply = "MICVDD",
+ .dev_name = "0-001a",
+ }
+};
+static struct regulator_consumer_supply sw4_consumers[] = {
+ {
+ .supply = "AUD_1V8",
+ }
+};
+static struct regulator_consumer_supply swbst_consumers[] = {
+ {
+ .supply = "SWBST_5V",
+ }
+};
+static struct regulator_consumer_supply vgen1_consumers[] = {
+ {
+ .supply = "VGEN1_1V5",
+ }
+};
+static struct regulator_consumer_supply vgen2_consumers[] = {
+ {
+ .supply = "VGEN2_1V5",
+ }
+};
+static struct regulator_consumer_supply vgen4_consumers[] = {
+ {
+ .supply = "DBVDD",
+ .dev_name = "0-001a",
+ },
+ {
+ .supply = "AVDD",
+ .dev_name = "0-001a",
+ },
+ {
+ .supply = "DCVDD",
+ .dev_name = "0-001a",
+ },
+ {
+ .supply = "CPVDD",
+ .dev_name = "0-001a",
+ },
+ {
+ .supply = "PLLVDD",
+ .dev_name = "0-001a",
+ }
+};
+static struct regulator_consumer_supply vgen5_consumers[] = {
+ {
+ .supply = "VGEN5_2V8",
+ }
+};
+static struct regulator_consumer_supply vgen6_consumers[] = {
+ {
+ .supply = "VGEN6_3V3",
+ }
+};
+
+static struct regulator_init_data sw1a_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1A",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 650000,
+ .max_uV = 1437500,
+#else
+ .min_uV = 300000,
+ .max_uV = 1875000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .boot_on = 1,
+ .always_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 975000,/*0.9V+6%*/
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw1b_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1B",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw1c_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1C",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 975000,/*0.9V+6%*/
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers),
+ .consumer_supplies = sw1c_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "PFUZE100_SW2",
+#if PFUZE100_SW2_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw2_consumers),
+ .consumer_supplies = sw2_consumers,
+};
+
+static struct regulator_init_data sw3a_init = {
+ .constraints = {
+ .name = "PFUZE100_SW3A",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw3b_init = {
+ .constraints = {
+ .name = "PFUZE100_SW3B",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "PFUZE100_SW4",
+#if PFUZE100_SW4_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw4_consumers),
+ .consumer_supplies = sw4_consumers,
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "PFUZE100_SWBST",
+ .min_uV = 5000000,
+ .max_uV = 5150000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(swbst_consumers),
+ .consumer_supplies = swbst_consumers,
+};
+
+static struct regulator_init_data vsnvs_init = {
+ .constraints = {
+ .name = "PFUZE100_VSNVS",
+ .min_uV = 1200000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vrefddr_init = {
+ .constraints = {
+ .name = "PFUZE100_VREFDDR",
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN1",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen1_consumers),
+ .consumer_supplies = vgen1_consumers,
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN2",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen2_consumers),
+ .consumer_supplies = vgen2_consumers,
+
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN3",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+};
+
+static struct regulator_init_data vgen4_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN4",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen4_consumers),
+ .consumer_supplies = vgen4_consumers,
+};
+
+static struct regulator_init_data vgen5_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN5",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen5_consumers),
+ .consumer_supplies = vgen5_consumers,
+};
+
+static struct regulator_init_data vgen6_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN6",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen6_consumers),
+ .consumer_supplies = vgen6_consumers,
+};
+
+static int pfuze100_init(struct mc_pfuze *pfuze)
+{
+ int ret, i;
+ unsigned char value;
+ /*use default mode(ldo bypass) if no param from cmdline*/
+ if (enable_ldo_mode == LDO_MODE_DEFAULT)
+ enable_ldo_mode = LDO_MODE_BYPASSED;
+ /*read Device ID*/
+ ret = pfuze_reg_read(pfuze, PFUZE100_DEVICEID, &value);
+ if (ret)
+ goto err;
+ if (value != 0x10) {
+ printk(KERN_ERR "wrong device id:%x!\n", value);
+ goto err;
+ }
+
+ /*read Revision ID*/
+ ret = pfuze_reg_read(pfuze, PFUZE100_REVID, &value);
+ if (ret)
+ goto err;
+ if (value == 0x10) {
+ printk(KERN_WARNING "PF100 1.0 chip found!\n");
+ /* workaround ER1 of pfuze1.0: set all buck regulators in PWM mode
+ * except SW1C(APS) in normal and PFM mode in standby.
+ */
+ for (i = 0; i < 7; i++) {
+ if (i == 2)/*SW1C*/
+ value = 0xc;/*normal:APS mode;standby:PFM mode*/
+ else
+ value = 0xd;/*normal:PWM mode;standby:PFM mode*/
+ ret = pfuze_reg_write(pfuze,
+ PFUZE100_SW1AMODE + (i * 7),
+ value);
+ if (ret)
+ goto err;
+ }
+
+ } else {
+ /*set all switches APS in normal and PFM mode in standby*/
+ for (i = 0; i < 7; i++) {
+ value = 0xc;
+ ret = pfuze_reg_write(pfuze,
+ PFUZE100_SW1AMODE + (i * 7),
+ value);
+ if (ret)
+ goto err;
+ }
+
+ }
+ /*use ldo active mode if use 1.2GHz,otherwise use ldo bypass mode*/
+ if (arm_max_freq == CPU_AT_1_2GHz) {
+ /*VDDARM_IN 1.425*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x2d);
+ if (ret)
+ goto err;
+ /*VDDSOC_IN 1.425V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x2d);
+ if (ret)
+ goto err;
+ enable_ldo_mode = LDO_MODE_ENABLED;
+ } else if (enable_ldo_mode == LDO_MODE_BYPASSED) {
+ /*decrease VDDARM_IN/VDDSOC_IN,since we will use ldo bypass mode*/
+ /*VDDARM_IN 1.3V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x28);
+ if (ret)
+ goto err;
+ /*VDDSOC_IN 1.3V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x28);
+ if (ret)
+ goto err;
+ /*set SW1AB/1C DVSPEED as 25mV step each 4us,quick than 16us before.*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON,
+ PFUZE100_SW1ACON_SPEED_M,
+ PFUZE100_SW1ACON_SPEED_VAL);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON,
+ PFUZE100_SW1CCON_SPEED_M,
+ PFUZE100_SW1CCON_SPEED_VAL);
+ if (ret)
+ goto err;
+ } else if (enable_ldo_mode != LDO_MODE_BYPASSED) {
+ /*Increase VDDARM_IN/VDDSOC_IN to 1.375V in ldo active mode*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x2b);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x2b);
+ if (ret)
+ goto err;
+ }
+ return 0;
+err:
+ printk(KERN_ERR "pfuze100 init error!\n");
+ return -1;
+}
+
+static struct pfuze_regulator_init_data mx6q_sabreauto_pfuze100_regulators[] = {
+ {.id = PFUZE100_SW1A, .init_data = &sw1a_init},
+ {.id = PFUZE100_SW1B, .init_data = &sw1b_init},
+ {.id = PFUZE100_SW1C, .init_data = &sw1c_init},
+ {.id = PFUZE100_SW2, .init_data = &sw2_init},
+ {.id = PFUZE100_SW3A, .init_data = &sw3a_init},
+ {.id = PFUZE100_SW3B, .init_data = &sw3b_init},
+ {.id = PFUZE100_SW4, .init_data = &sw4_init},
+ {.id = PFUZE100_SWBST, .init_data = &swbst_init},
+ {.id = PFUZE100_VSNVS, .init_data = &vsnvs_init},
+ {.id = PFUZE100_VREFDDR, .init_data = &vrefddr_init},
+ {.id = PFUZE100_VGEN1, .init_data = &vgen1_init},
+ {.id = PFUZE100_VGEN2, .init_data = &vgen2_init},
+ {.id = PFUZE100_VGEN3, .init_data = &vgen3_init},
+ {.id = PFUZE100_VGEN4, .init_data = &vgen4_init},
+ {.id = PFUZE100_VGEN5, .init_data = &vgen5_init},
+ {.id = PFUZE100_VGEN6, .init_data = &vgen6_init},
+};
+
+static struct pfuze_platform_data pfuze100_plat = {
+ .flags = PFUZE_USE_REGULATOR,
+ .num_regulators = ARRAY_SIZE(mx6q_sabreauto_pfuze100_regulators),
+ .regulators = mx6q_sabreauto_pfuze100_regulators,
+ .pfuze_init = pfuze100_init,
+};
+
+static struct i2c_board_info __initdata pfuze100_i2c_device = {
+ I2C_BOARD_INFO(PFUZE100_I2C_DEVICE_NAME, PFUZE100_I2C_ADDR),
+ .platform_data = &pfuze100_plat,
+};
+
+int __init mx6q_sabresd_init_pfuze100(u32 int_gpio)
+{
+ pfuze100_i2c_device.irq = gpio_to_irq(int_gpio); /*update INT gpio */
+ return i2c_register_board_info(1, &pfuze100_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c
new file mode 100644
index 00000000..7cebb8f2
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (C) 2012 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/pfuze.h>
+#include <mach/irqs.h>
+#include <mach/system.h>
+#include "cpu_op-mx6.h"
+
+/*
+ * Convenience conversion.
+ * Here atm, maybe there is somewhere better for this.
+ */
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+#define PFUZE100_I2C_DEVICE_NAME "pfuze100"
+/* 7-bit I2C bus slave address */
+#define PFUZE100_I2C_ADDR (0x08)
+#define PFUZE100_DEVICEID (0x0)
+#define PFUZE100_REVID (0x3)
+#define PFUZE100_SW1AMODE (0x23)
+#define PFUZE100_SW1ACON 36
+#define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1ACON_SPEED_M (0x3<<6)
+#define PFUZE100_SW1CCON 49
+#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1CCON_SPEED_M (0x3<<6)
+#define PFUZE100_SW1AVOL 32
+#define PFUZE100_SW1AVOL_VSEL_M (0x3f<<0)
+#define PFUZE100_SW1CVOL 46
+#define PFUZE100_SW1CVOL_VSEL_M (0x3f<<0)
+extern u32 enable_ldo_mode;
+extern u32 arm_max_freq;
+
+
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "VDDCORE",
+ }
+};
+static struct regulator_consumer_supply sw1c_consumers[] = {
+ {
+ .supply = "VDDSOC",
+ },
+};
+
+static struct regulator_consumer_supply sw2_consumers[] = {
+ {
+ .supply = "MICVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "DBVDD",
+ .dev_name = "1-001a",
+ }
+
+};
+static struct regulator_consumer_supply sw4_consumers[] = {
+ {
+ .supply = "AUD_1V8",
+ }
+};
+static struct regulator_consumer_supply swbst_consumers[] = {
+ {
+ .supply = "SWBST_5V",
+ }
+};
+static struct regulator_consumer_supply vgen1_consumers[] = {
+ {
+ .supply = "VGEN1_1V5",
+ }
+};
+static struct regulator_consumer_supply vgen2_consumers[] = {
+ {
+ .supply = "VGEN2_1V5",
+ }
+};
+static struct regulator_consumer_supply vgen4_consumers[] = {
+ {
+ .supply = "AVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "DCVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "CPVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "PLLVDD",
+ .dev_name = "1-001a",
+ }
+};
+static struct regulator_consumer_supply vgen5_consumers[] = {
+ {
+ .supply = "VGEN5_2V8",
+ }
+};
+static struct regulator_consumer_supply vgen6_consumers[] = {
+ {
+ .supply = "VGEN6_3V3",
+ }
+};
+
+static struct regulator_init_data sw1a_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1A",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 650000,
+ .max_uV = 1437500,
+#else
+ .min_uV = 300000,
+ .max_uV = 1875000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .boot_on = 1,
+ .always_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 975000,/*0.9V+6%*/
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw1b_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1B",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw1c_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1C",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 975000,/*0.9V+6%*/
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers),
+ .consumer_supplies = sw1c_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "PFUZE100_SW2",
+#if PFUZE100_SW2_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw2_consumers),
+ .consumer_supplies = sw2_consumers,
+};
+
+static struct regulator_init_data sw3a_init = {
+ .constraints = {
+ .name = "PFUZE100_SW3A",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw3b_init = {
+ .constraints = {
+ .name = "PFUZE100_SW3B",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "PFUZE100_SW4",
+#if PFUZE100_SW4_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw4_consumers),
+ .consumer_supplies = sw4_consumers,
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "PFUZE100_SWBST",
+ .min_uV = 5000000,
+ .max_uV = 5150000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(swbst_consumers),
+ .consumer_supplies = swbst_consumers,
+};
+
+static struct regulator_init_data vsnvs_init = {
+ .constraints = {
+ .name = "PFUZE100_VSNVS",
+ .min_uV = 1200000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vrefddr_init = {
+ .constraints = {
+ .name = "PFUZE100_VREFDDR",
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN1",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen1_consumers),
+ .consumer_supplies = vgen1_consumers,
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN2",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen2_consumers),
+ .consumer_supplies = vgen2_consumers,
+
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN3",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 0,
+ .boot_on = 0,
+ },
+};
+
+static struct regulator_init_data vgen4_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN4",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen4_consumers),
+ .consumer_supplies = vgen4_consumers,
+};
+
+static struct regulator_init_data vgen5_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN5",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen5_consumers),
+ .consumer_supplies = vgen5_consumers,
+};
+
+static struct regulator_init_data vgen6_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN6",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen6_consumers),
+ .consumer_supplies = vgen6_consumers,
+};
+
+static int pfuze100_init(struct mc_pfuze *pfuze)
+{
+ int ret, i;
+ unsigned char value;
+
+ /*use default mode(ldo bypass) if no param from cmdline*/
+ if (enable_ldo_mode == LDO_MODE_DEFAULT)
+ enable_ldo_mode = LDO_MODE_BYPASSED;
+ /*read Device ID*/
+ ret = pfuze_reg_read(pfuze, PFUZE100_DEVICEID, &value);
+ if (ret)
+ goto err;
+ if (value != 0x10) {
+ printk(KERN_ERR "wrong device id:%x!\n", value);
+ goto err;
+ }
+
+ /*read Revision ID*/
+ ret = pfuze_reg_read(pfuze, PFUZE100_REVID, &value);
+ if (ret)
+ goto err;
+ if (value == 0x10) {
+ printk(KERN_WARNING "PF100 1.0 chip found!\n");
+ /* workaround ER1 of pfuze1.0: set all buck regulators in PWM mode
+ * except SW1C(APS) in normal and PFM mode in standby.
+ */
+ for (i = 0; i < 7; i++) {
+ if (i == 2)/*SW1C*/
+ value = 0xc;/*normal:APS mode;standby:PFM mode*/
+ else
+ value = 0xd;/*normal:PWM mode;standby:PFM mode*/
+ ret = pfuze_reg_write(pfuze,
+ PFUZE100_SW1AMODE + (i * 7),
+ value);
+ if (ret)
+ goto err;
+ }
+
+ } else {
+ /*set all switches APS in normal and PFM mode in standby*/
+ for (i = 0; i < 7; i++) {
+ value = 0xc;
+ ret = pfuze_reg_write(pfuze,
+ PFUZE100_SW1AMODE + (i * 7),
+ value);
+ if (ret)
+ goto err;
+ }
+
+ }
+ /*use ldo active mode if use 1.2GHz,otherwise use ldo bypass mode*/
+ if (arm_max_freq == CPU_AT_1_2GHz) {
+ /*VDDARM_IN 1.47*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x2f);
+ if (ret)
+ goto err;
+ /*VDDSOC_IN 1.475V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x2f);
+ if (ret)
+ goto err;
+ enable_ldo_mode = LDO_MODE_ENABLED;
+ } else if (enable_ldo_mode == LDO_MODE_BYPASSED) {
+ /*decrease VDDARM_IN/VDDSOC_IN,since we will use dynamic ldo bypass
+ *mode or ldo bypass mode here.*/
+ /*VDDARM_IN 1.3V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x28);
+ if (ret)
+ goto err;
+ /*VDDSOC_IN 1.3V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x28);
+ if (ret)
+ goto err;
+ /*set SW1AB/SW1C DVSPEED as 25mV step each 4us,quick than 16us before.*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON,
+ PFUZE100_SW1ACON_SPEED_M,
+ PFUZE100_SW1ACON_SPEED_VAL);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON,
+ PFUZE100_SW1CCON_SPEED_M,
+ PFUZE100_SW1CCON_SPEED_VAL);
+ if (ret)
+ goto err;
+ } else if (enable_ldo_mode != LDO_MODE_BYPASSED) {
+ /*Increase VDDARM_IN/VDDSOC_IN to 1.375V in ldo active mode*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x2b);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x2b);
+ if (ret)
+ goto err;
+ }
+ return 0;
+err:
+ printk(KERN_ERR "pfuze100 init error!\n");
+ return -1;
+}
+
+static struct pfuze_regulator_init_data mx6q_sabreauto_pfuze100_regulators[] = {
+ {.id = PFUZE100_SW1A, .init_data = &sw1a_init},
+ {.id = PFUZE100_SW1B, .init_data = &sw1b_init},
+ {.id = PFUZE100_SW1C, .init_data = &sw1c_init},
+ {.id = PFUZE100_SW2, .init_data = &sw2_init},
+ {.id = PFUZE100_SW3A, .init_data = &sw3a_init},
+ {.id = PFUZE100_SW3B, .init_data = &sw3b_init},
+ {.id = PFUZE100_SW4, .init_data = &sw4_init},
+ {.id = PFUZE100_SWBST, .init_data = &swbst_init},
+ {.id = PFUZE100_VSNVS, .init_data = &vsnvs_init},
+ {.id = PFUZE100_VREFDDR, .init_data = &vrefddr_init},
+ {.id = PFUZE100_VGEN1, .init_data = &vgen1_init},
+ {.id = PFUZE100_VGEN2, .init_data = &vgen2_init},
+ {.id = PFUZE100_VGEN3, .init_data = &vgen3_init},
+ {.id = PFUZE100_VGEN4, .init_data = &vgen4_init},
+ {.id = PFUZE100_VGEN5, .init_data = &vgen5_init},
+ {.id = PFUZE100_VGEN6, .init_data = &vgen6_init},
+};
+
+static struct pfuze_platform_data pfuze100_plat = {
+ .flags = PFUZE_USE_REGULATOR,
+ .num_regulators = ARRAY_SIZE(mx6q_sabreauto_pfuze100_regulators),
+ .regulators = mx6q_sabreauto_pfuze100_regulators,
+ .pfuze_init = pfuze100_init,
+};
+
+static struct i2c_board_info __initdata pfuze100_i2c_device = {
+ I2C_BOARD_INFO(PFUZE100_I2C_DEVICE_NAME, PFUZE100_I2C_ADDR),
+ .platform_data = &pfuze100_plat,
+};
+
+int __init mx6sl_arm2_init_pfuze100(u32 int_gpio)
+{
+ if (int_gpio)
+ pfuze100_i2c_device.irq = gpio_to_irq(int_gpio); /*update INT gpio */
+ return i2c_register_board_info(0, &pfuze100_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx6/mx6sl_ddr.S b/arch/arm/mach-mx6/mx6sl_ddr.S
new file mode 100644
index 00000000..bac1e7c2
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6sl_ddr.S
@@ -0,0 +1,570 @@
+/*
+ * Copyright (C) 2012-2013 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 <linux/linkage.h>
+#include <mach/hardware.h>
+.extern iram_tlb_phys_addr
+.extern mx6sl_ddr_freq_base
+.extern mx6sl_ddr_freq_phys_addr
+
+ .macro mx6sl_switch_to_24MHz
+
+ /* Set MMDC clock to be sourced from PLL3. */
+ /* Ensure first periph2_clk2 is sourced from PLL3. */
+ /* Set the PERIPH2_CLK2_PODF to divide by 2. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x7
+ orr r6, r6, #0x1
+ str r6, [r2, #0x14]
+
+ /* Select PLL3 to source MMDC. */
+ ldr r6, [r2, #0x18]
+ bic r6, r6, #0x100000
+ str r6, [r2, #0x18]
+
+ /* Swtich periph2_clk_sel to run from PLL3. */
+ ldr r6, [r2, #0x14]
+ orr r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch1:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch1
+
+ /* Need to clock gate the 528 PFDs before
+ * powering down PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC
+ */
+ ldr r6, [r3, #0x100]
+ orr r6, r6, #0x800000
+ str r6, [r3, #0x100]
+
+ /* Set PLL2 to bypass state. We should be here
+ *only if MMDC is not sourced from PLL2.*/
+ ldr r6, [r3, #0x30]
+ orr r6, r6, #0x10000
+ str r6, [r3, #0x30]
+
+ ldr r6, [r3, #0x30]
+ orr r6, r6, #0x1000
+ str r6, [r3, #0x30]
+
+ /* Ensure pre_periph2_clk_mux is set to pll2 */
+ ldr r6, [r2, #0x18]
+ bic r6, r6, #0x600000
+ str r6, [r2, #0x18]
+
+ /* Set MMDC clock to be sourced from the bypassed PLL2. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch2:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch2
+
+ /* Now move MMDC back to periph2_clk2 source.
+ * after selecting PLL2 as the option.
+ */
+ /* Select PLL2 as the source. */
+ ldr r6, [r2, #0x18]
+ orr r6, r6, #0x100000
+ str r6, [r2, #0x18]
+
+ /* set periph2_clk2_podf to divide by 1. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x7
+ str r6, [r2, #0x14]
+
+ /* Now move periph2_clk to periph2_clk2 source */
+ ldr r6, [r2, #0x14]
+ orr r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch3:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch3
+
+ /* Now set the MMDC PODF back to 1.*/
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x38
+ str r6, [r2, #0x14]
+
+mmdc_podf0:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne mmdc_podf0
+
+ .endm
+
+ .macro ddr_switch_400MHz
+
+ /* Set MMDC divider first, in case PLL3 is at 480MHz. */
+ ldr r6, [r3, #0x10]
+ and r6, r6, #0x10000
+ cmp r6, #0x10000
+ beq pll3_in_bypass
+ /* Set MMDC divder to divide by 2. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x38
+ orr r6, r6, #0x8
+ str r6, [r2, #0x14]
+
+mmdc_podf:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne mmdc_podf
+
+pll3_in_bypass:
+
+ /* Check if we are switching between
+ * 400Mhz <-> 100MHz.If so, we should
+ * try to source MMDC from PLL2_200M.
+ */
+ cmp r1, #0
+ beq not_low_bus_freq
+
+ /* Ensure that MMDC is sourced from PLL2 mux first. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch4:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch4
+
+not_low_bus_freq:
+ /* Now ensure periph2_clk2_sel mux is set to PLL3 */
+ ldr r6, [r2, #0x18]
+ bic r6, r6, #0x100000
+ str r6, [r2, #0x18]
+
+ /* Now switch MMDC to PLL3. */
+ ldr r6, [r2, #0x14]
+ orr r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch5:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch5
+
+ /* Check if PLL2 is already unlocked.
+ * If so do nothing with PLL2.
+ */
+ cmp r1, #0
+ beq pll2_already_on
+
+ /* Now power up PLL2 and unbypass it. */
+ ldr r6, [r3, #0x30]
+ bic r6, r6, #0x1000
+ str r6, [r3, #0x30]
+
+ /* Make sure PLL2 has locked.*/
+wait_for_pll_lock:
+ ldr r6, [r3, #0x30]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock
+
+ ldr r6, [r3, #0x30]
+ bic r6, r6, #0x10000
+ str r6, [r3, #0x30]
+
+ /* Need to enable the 528 PFDs after
+ * powering up PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC. Rest should have
+ * been managed by clock code.
+ */
+ ldr r6, [r3, #0x100]
+ bic r6, r6, #0x800000
+ str r6, [r3, #0x100]
+
+pll2_already_on:
+ /* Now switch MMDC clk back to pll2_mux option. */
+ /* Ensure pre_periph2_clk2 is set to pll2_pfd_400M */
+ /* If switching to audio DDR freq, set the
+ * pre_periph2_clk2 to PLL2_PFD_200M
+ */
+ ldr r6, =400000000
+ cmp r6, r0
+ bne use_pll2_pfd_200M
+
+ ldr r6, [r2, #0x18]
+ bic r6, r6, #0x600000
+ orr r6, r6, #0x200000
+ str r6, [r2, #0x18]
+ ldr r6, =400000000
+ b cont2
+
+use_pll2_pfd_200M:
+ ldr r6, [r2, #0x18]
+ orr r6, r6, #0x600000
+ str r6, [r2, #0x18]
+ ldr r6, =200000000
+
+cont2:
+ ldr r4, [r2, #0x14]
+ bic r4, r4, #0x4000000
+ str r4, [r2, #0x14]
+
+periph2_clk_switch6:
+ ldr r4, [r2, #0x48]
+ cmp r4, #0
+ bne periph2_clk_switch6
+
+change_divider_only:
+ /* Calculate the MMDC divider
+ * based on the requested freq.
+ */
+ ldr r4, =0
+Loop2:
+ sub r6, r6, r0
+ cmp r6, r0
+ blt Div_Found
+ add r4, r4, #1
+ bgt Loop2
+
+ /* Shift divider into correct offset. */
+ lsl r4, r4, #3
+Div_Found:
+ /* Set the MMDC PODF. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x38
+ orr r6, r6, r4
+ str r6, [r2, #0x14]
+
+mmdc_podf1:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne mmdc_podf1
+
+ .endm
+
+ .macro mmdc_clk_lower_100MHz
+
+ /* Prior to reducing the DDR frequency (at 528/400 MHz),
+ read the Measure unit count bits (MU_UNIT_DEL_NUM) */
+ ldr r5, =0x8B8
+ ldr r6, [r8, r5]
+ /* Original MU unit count */
+ mov r6, r6, LSR #16
+ ldr r4, =0x3FF
+ and r6, r6, r4
+ /* Original MU unit count * 2 */
+ mov r7, r6, LSL #1
+ /* Bypass the automatic measure unit when below 100 MHz
+ by setting the Measure unit bypass enable bit (MU_BYP_EN) */
+ ldr r6, [r8, r5]
+ orr r6, r6, #0x400
+ str r6, [r8, r5]
+ /* Double the measure count value read in step 1 and program it in the
+ * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit
+ * Register for the reduced frequency operation below 100 MHz
+ */
+ ldr r6, [r8, r5]
+ ldr r4, =0x3FF
+ bic r6, r6, r4
+ orr r6, r6, r7
+ str r6, [r8, r5]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r8, r5]
+ orr r6, r6, #0x800
+ str r6, [r8, r5]
+ /* Wait for FRC_MSR to clear. */
+force_measure:
+ ldr r6, [r8, r5]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure
+
+ .endm
+
+ .macro mmdc_clk_above_100MHz
+
+ /* Make sure that the PHY measurement unit is NOT in bypass mode */
+ ldr r5, =0x8B8
+ ldr r6, [r8, r5]
+ bic r6, r6, #0x400
+ str r6, [r8, r5]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r8, r5]
+ orr r6, r6, #0x800
+ str r6, [r8, r5]
+ /* Wait for FRC_MSR to clear. */
+force_measure1:
+ ldr r6, [r8, r5]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure1
+ .endm
+
+ .align 3
+/*
+ * mx6sl_ddr_iram
+ *
+ * Idle the processor (eg, wait for interrupt).
+ * Make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ * r0 : DDR freq.
+ * r1: low_bus_freq_mode flag
+ */
+ENTRY(mx6sl_ddr_iram)
+
+ push {r4-r10}
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+mx6sl_ddr_freq_change:
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+
+ /* Disable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /*
+ * Sync L2 and then disable it.
+ */
+ dsb
+ ldr r4, =L2_BASE_ADDR
+ add r4, r4, #PERIPBASE_VIRT
+ ldr r6, =0x0
+ str r6, [r4, #0x730]
+ /* Disable L2. */
+ str r6, [r4, #0x100]
+
+ dsb
+ isb
+
+ ldr r3, =ANATOP_BASE_ADDR
+ add r3, r3, #PERIPBASE_VIRT
+ ldr r2, =CCM_BASE_ADDR
+ add r2, r2, #PERIPBASE_VIRT
+ ldr r8, =MMDC_P0_BASE_ADDR
+ add r8, r8, #PERIPBASE_VIRT
+
+ /* Disable Automatic power savings. */
+ ldr r6, [r8, #0x404]
+ orr r6, r6, #0x01
+ str r6, [r8, #0x404]
+
+ /* Disable MMDC power down timer. */
+ /*MMDC0_MDPDC disable power down timer */
+ ldr r6, [r8, #0x4]
+ bic r6, r6, #0xff00
+ str r6, [r8, #0x4]
+
+ /* Delay for a while */
+ ldr r10, =10
+delay1:
+ ldr r7, =0
+cont1:
+ ldr r6, [r8, r7]
+ add r7, r7, #4
+ cmp r7, #16
+ bne cont1
+ sub r10, r10, #1
+ cmp r10, #0
+ bgt delay1
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r6, [r8, #0x404]
+ orr r6, r6, #0x200000
+ str r6, [r8, #0x404]
+
+poll_dvfs_set_1:
+ ldr r6, [r8, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ bne poll_dvfs_set_1
+
+ /* set SBS step-by-step mode */
+ ldr r6, [r8, #0x410]
+ orr r6, r6, #0x100
+ str r6, [r8, #0x410]
+
+ ldr r10, =100000000
+ cmp r0, r10
+ bgt set_ddr_mu_above_100
+ mmdc_clk_lower_100MHz
+
+set_ddr_mu_above_100:
+ ldr r10, =24000000
+ cmp r0, r10
+ beq set_to_24MHz
+
+ ddr_switch_400MHz
+ ldr r10, =100000000
+ cmp r0, r10
+ blt done
+ mmdc_clk_above_100MHz
+ b done
+
+set_to_24MHz:
+ mx6sl_switch_to_24MHz
+
+done:
+ /* clear DVFS - exit from self refresh mode */
+ ldr r6, [r8, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r8, #0x404]
+
+poll_dvfs_clear_1:
+ ldr r6, [r8, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r8, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r8, #0x404]
+
+ ldr r10, =24000000
+ cmp r0, r10
+ beq skip_power_down
+
+ /* Enable MMDC power down timer. */
+ ldr r6, [r8, #0x4]
+ orr r6, r6, #0x5500
+ str r6, [r8, #0x4]
+
+skip_power_down:
+ /* clear SBS - unblock DDR accesses */
+ ldr r6, [r8, #0x410]
+ bic r6, r6, #0x100
+ str r6, [r8, #0x410]
+
+ /* Enable L2. */
+ ldr r1, =L2_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ ldr r6, =0x1
+ str r6, [r1, #0x100]
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ pop {r4-r10}
+
+ /* Restore registers */
+ mov pc, lr
diff --git a/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c
new file mode 100644
index 00000000..14bd33ff
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2012 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/pfuze.h>
+#include <mach/irqs.h>
+#include <mach/system.h>
+#include "cpu_op-mx6.h"
+
+/*
+ * Convenience conversion.
+ * Here atm, maybe there is somewhere better for this.
+ */
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+#define PFUZE100_I2C_DEVICE_NAME "pfuze100"
+/* 7-bit I2C bus slave address */
+#define PFUZE100_I2C_ADDR (0x08)
+#define PFUZE100_DEVICEID (0x0)
+#define PFUZE100_REVID (0x3)
+#define PFUZE100_SW1AMODE (0x23)
+#define PFUZE100_SW1ACON 36
+#define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1ACON_SPEED_M (0x3<<6)
+#define PFUZE100_SW1CCON 49
+#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1CCON_SPEED_M (0x3<<6)
+#define PFUZE100_SW1AVOL 32
+#define PFUZE100_SW1AVOL_VSEL_M (0x3f<<0)
+#define PFUZE100_SW1CVOL 46
+#define PFUZE100_SW1CVOL_VSEL_M (0x3f<<0)
+
+extern u32 enable_ldo_mode;
+extern u32 arm_max_freq;
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "VDDCORE",
+ }
+};
+static struct regulator_consumer_supply sw1c_consumers[] = {
+ {
+ .supply = "VDDSOC",
+ },
+};
+
+static struct regulator_consumer_supply sw2_consumers[] = {
+ {
+ .supply = "MICVDD",
+ .dev_name = "1-001a",
+ }
+};
+static struct regulator_consumer_supply sw4_consumers[] = {
+ {
+ .supply = "AUD_1V8",
+ }
+};
+static struct regulator_consumer_supply swbst_consumers[] = {
+ {
+ .supply = "SWBST_5V",
+ }
+};
+static struct regulator_consumer_supply vgen1_consumers[] = {
+ {
+ .supply = "VGEN1_1V5",
+ }
+};
+static struct regulator_consumer_supply vgen2_consumers[] = {
+ {
+ .supply = "VGEN2_1V5",
+ }
+};
+static struct regulator_consumer_supply vgen3_consumers[] = {
+ {
+ .supply = "AVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "DCVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "CPVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "PLLVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "DBVDD",
+ .dev_name = "1-001a",
+ }
+};
+static struct regulator_consumer_supply vgen4_consumers[] = {
+ {
+ .supply = "VGEN4_1V8",
+ }
+};
+static struct regulator_consumer_supply vgen5_consumers[] = {
+ {
+ .supply = "VGEN5_2V8",
+ }
+};
+static struct regulator_consumer_supply vgen6_consumers[] = {
+ {
+ .supply = "VGEN6_2V8",
+ }
+};
+
+static struct regulator_init_data sw1a_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1A",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 650000,
+ .max_uV = 1437500,
+#else
+ .min_uV = 300000,
+ .max_uV = 1875000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .boot_on = 1,
+ .always_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 975000,/*0.9V+6%*/
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw1b_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1B",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw1c_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1C",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 975000,/*0.9V+6%*/
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers),
+ .consumer_supplies = sw1c_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "PFUZE100_SW2",
+#if PFUZE100_SW2_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw2_consumers),
+ .consumer_supplies = sw2_consumers,
+};
+
+static struct regulator_init_data sw3a_init = {
+ .constraints = {
+ .name = "PFUZE100_SW3A",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw3b_init = {
+ .constraints = {
+ .name = "PFUZE100_SW3B",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "PFUZE100_SW4",
+#if PFUZE100_SW4_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw4_consumers),
+ .consumer_supplies = sw4_consumers,
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "PFUZE100_SWBST",
+ .min_uV = 5000000,
+ .max_uV = 5150000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(swbst_consumers),
+ .consumer_supplies = swbst_consumers,
+};
+
+static struct regulator_init_data vsnvs_init = {
+ .constraints = {
+ .name = "PFUZE100_VSNVS",
+ .min_uV = 1200000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vrefddr_init = {
+ .constraints = {
+ .name = "PFUZE100_VREFDDR",
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN1",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen1_consumers),
+ .consumer_supplies = vgen1_consumers,
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN2",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen2_consumers),
+ .consumer_supplies = vgen2_consumers,
+
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN3",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 0,
+ .boot_on = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen3_consumers),
+ .consumer_supplies = vgen3_consumers,
+};
+
+static struct regulator_init_data vgen4_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN4",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen4_consumers),
+ .consumer_supplies = vgen4_consumers,
+};
+
+static struct regulator_init_data vgen5_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN5",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen5_consumers),
+ .consumer_supplies = vgen5_consumers,
+};
+
+static struct regulator_init_data vgen6_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN6",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen6_consumers),
+ .consumer_supplies = vgen6_consumers,
+};
+
+static int pfuze100_init(struct mc_pfuze *pfuze)
+{
+ int ret, i;
+ unsigned char value;
+ /*use default mode(ldo bypass) if no param from cmdline*/
+ if (enable_ldo_mode == LDO_MODE_DEFAULT)
+ enable_ldo_mode = LDO_MODE_BYPASSED;
+ /*read Device ID*/
+ ret = pfuze_reg_read(pfuze, PFUZE100_DEVICEID, &value);
+ if (ret)
+ goto err;
+ if (value != 0x10) {
+ printk(KERN_ERR "wrong device id:%x!\n", value);
+ goto err;
+ }
+
+ /*read Revision ID*/
+ ret = pfuze_reg_read(pfuze, PFUZE100_REVID, &value);
+ if (ret)
+ goto err;
+ if (value == 0x10) {
+ printk(KERN_WARNING "PF100 1.0 chip found!\n");
+ /* workaround ER1 of pfuze1.0: set all buck regulators in PWM mode
+ * except SW1C(APS) in normal and PFM mode in standby.
+ */
+ for (i = 0; i < 7; i++) {
+ if (i == 2)/*SW1C*/
+ value = 0xc;/*normal:APS mode;standby:PFM mode*/
+ else
+ value = 0xd;/*normal:PWM mode;standby:PFM mode*/
+ ret = pfuze_reg_write(pfuze,
+ PFUZE100_SW1AMODE + (i * 7),
+ value);
+ if (ret)
+ goto err;
+ }
+
+ } else {
+ /*set all switches APS in normal and PFM mode in standby*/
+ for (i = 0; i < 7; i++) {
+ value = 0xc;
+ ret = pfuze_reg_write(pfuze,
+ PFUZE100_SW1AMODE + (i * 7),
+ value);
+ if (ret)
+ goto err;
+ }
+
+ }
+ /*use ldo active mode if use 1.2GHz,otherwise use ldo bypass mode*/
+ if (arm_max_freq == CPU_AT_1_2GHz) {
+ /*VDDARM_IN 1.47*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x2f);
+ if (ret)
+ goto err;
+ /*VDDSOC_IN 1.475V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x2f);
+ if (ret)
+ goto err;
+ enable_ldo_mode = LDO_MODE_ENABLED;
+ } else if (enable_ldo_mode == LDO_MODE_BYPASSED) {
+ /*decrease VDDARM_IN/VDDSOC_IN,since we will use dynamic ldo bypass
+ *mode or ldo bypass mode here.*/
+ /*VDDARM_IN 1.3V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x28);
+ if (ret)
+ goto err;
+ /*VDDSOC_IN 1.3V*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x28);
+ if (ret)
+ goto err;
+
+ /*set SW1AB/SW1CDVSPEED as 25mV step each 4us,quick than 16us before.*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON,
+ PFUZE100_SW1ACON_SPEED_M,
+ PFUZE100_SW1ACON_SPEED_VAL);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON,
+ PFUZE100_SW1CCON_SPEED_M,
+ PFUZE100_SW1CCON_SPEED_VAL);
+ if (ret)
+ goto err;
+ } else if (enable_ldo_mode != LDO_MODE_BYPASSED) {
+ /*Increase VDDARM_IN/VDDSOC_IN to 1.375V in ldo active mode*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL,
+ PFUZE100_SW1AVOL_VSEL_M,
+ 0x2b);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL,
+ PFUZE100_SW1CVOL_VSEL_M,
+ 0x2b);
+ if (ret)
+ goto err;
+ }
+ return 0;
+err:
+ printk(KERN_ERR "pfuze100 init error!\n");
+ return -1;
+}
+
+static struct pfuze_regulator_init_data mx6q_sabreauto_pfuze100_regulators[] = {
+ {.id = PFUZE100_SW1A, .init_data = &sw1a_init},
+ {.id = PFUZE100_SW1B, .init_data = &sw1b_init},
+ {.id = PFUZE100_SW1C, .init_data = &sw1c_init},
+ {.id = PFUZE100_SW2, .init_data = &sw2_init},
+ {.id = PFUZE100_SW3A, .init_data = &sw3a_init},
+ {.id = PFUZE100_SW3B, .init_data = &sw3b_init},
+ {.id = PFUZE100_SW4, .init_data = &sw4_init},
+ {.id = PFUZE100_SWBST, .init_data = &swbst_init},
+ {.id = PFUZE100_VSNVS, .init_data = &vsnvs_init},
+ {.id = PFUZE100_VREFDDR, .init_data = &vrefddr_init},
+ {.id = PFUZE100_VGEN1, .init_data = &vgen1_init},
+ {.id = PFUZE100_VGEN2, .init_data = &vgen2_init},
+ {.id = PFUZE100_VGEN3, .init_data = &vgen3_init},
+ {.id = PFUZE100_VGEN4, .init_data = &vgen4_init},
+ {.id = PFUZE100_VGEN5, .init_data = &vgen5_init},
+ {.id = PFUZE100_VGEN6, .init_data = &vgen6_init},
+};
+
+static struct pfuze_platform_data pfuze100_plat = {
+ .flags = PFUZE_USE_REGULATOR,
+ .num_regulators = ARRAY_SIZE(mx6q_sabreauto_pfuze100_regulators),
+ .regulators = mx6q_sabreauto_pfuze100_regulators,
+ .pfuze_init = pfuze100_init,
+};
+
+static struct i2c_board_info __initdata pfuze100_i2c_device = {
+ I2C_BOARD_INFO(PFUZE100_I2C_DEVICE_NAME, PFUZE100_I2C_ADDR),
+ .platform_data = &pfuze100_plat,
+};
+
+int __init mx6sl_evk_init_pfuze100(u32 int_gpio)
+{
+ if (int_gpio)
+ pfuze100_i2c_device.irq = gpio_to_irq(int_gpio); /*update INT gpio */
+ return i2c_register_board_info(0, &pfuze100_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx6/mx6sl_ntx_io.c b/arch/arm/mach-mx6/mx6sl_ntx_io.c
new file mode 100755
index 00000000..403509d1
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6sl_ntx_io.c
@@ -0,0 +1,2605 @@
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/iomux-mx6sl.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+
+#include <generated/autoconf.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/miscdevice.h>
+#include <linux/irq.h>
+#include <linux/freezer.h>
+
+#include <mach/common.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <mach/iomux-v3.h>
+
+
+#include <linux/mfd/ricoh619.h>
+#include <linux/rtc/rtc-ricoh619.h>
+#include <linux/power/ricoh619_battery.h>
+#include <linux/regulator/ricoh619-regulator.h>
+
+#define GDEBUG 0
+#include <linux/gallen_dbg.h>
+
+//#define GPIOFN_PWRKEY 1
+
+//#ifdef GPIOFN_PWRKEY//[
+ #include "../../../drivers/input/keyboard/gpiofn.h"
+//#endif //]GPIOFN_PWRKEY
+
+#include "../../../drivers/video/mxc/lk_tps65185.h"
+#include "../../../drivers/video/mxc/lk_fp9928.h"
+
+
+//#define _WIFI_ALWAYS_ON_ // wifi always on for startic
+
+#include "board-mx6sl_ntx.h"
+#include "ntx_hwconfig.h"
+
+#define DEVICE_NAME "ntx_io" // "pvi_io"
+#define DEVICE_MINJOR 190
+
+#define CM_PLATFORM 164
+#define CM_HWCONFIG 165
+#define CM_SET_HWCONFIG 166
+
+#define CM_SD_IN 117
+#define AC_IN 118
+#define CM_PWR_ON2 112
+#define CM_AUDIO_PWR 113
+#define CM_POWER_BTN 110
+#define CM_USB_Plug_IN 108
+#define CM_AC_CK 109
+#define CM_CHARGE_STATUS 204
+#define CM_nLED 101
+#define CM_nLED_CPU 102
+#define POWER_OFF_COMMAND 0xC0 // 192
+#define SYS_RESET_COMMAND 193 // Joseph 091223
+#define GET_LnBATT_CPU 0XC2 // 194
+#define GET_VBATT_TH 0XC3 // 195
+#define CM_SIGUSR1 104
+//kay 20081110 for detecting SD write protect
+#define CM_SD_PROTECT 120
+#define SYS_AUTO_POWER_ON 0xC4 // 196 Joseph 120620
+
+//20090216 for detecting controller
+#define CM_CONTROLLER 121
+
+//20090416 for detecting controller
+#define CM_USB_AC_STATUS 122
+#define CM_RTC_WAKEUP_FLAG 123
+#define CM_SYSTEM_RESET 124
+#define CM_USB_HOST_PWR 125
+#define CM_BLUETOOTH_PWR 126
+#define CM_TELLPID 99
+#define CM_LED_BLINK 127
+#define CM_TOUCH_LOCK 128
+#define CM_DEVICE_MODULE 129
+#define CM_BLUETOOTH_RESET 130
+#define CM_DEVICE_INFO 131
+
+//Joseph 091211 for 3G
+#define CM_3G_POWER 150
+#define CM_3G_RF_OFF 151
+#define CM_3G_RESET 152
+#define CM_3G_GET_WAKE_STATUS 153
+
+//Joseph 091209
+#define CM_ROTARY_STATUS 200
+#define CM_GET_KEY_STATUS 201
+#define CM_GET_WHEEL_KEY_STATUS 202
+#define CM_GET_KL25_STATUS 203
+#define CM_GET_KL25_ACTION 199
+#define POWER_KEEP_COMMAND 205
+#define CM_GET_BATTERY_STATUS 206
+#define CM_SET_ALARM_WAKEUP 207
+#define CM_WIFI_CTRL 208
+#define CM_ROTARY_ENABLE 209
+
+#define CM_GET_UP_VERSION 215
+
+// gallen 100621
+// Audio functions ...
+#define CM_AUDIO_GET_VOLUME 230
+#define CM_AUDIO_SET_VOLUME 240
+#define CM_FRONT_LIGHT_SET 241
+#define CM_FRONT_LIGHT_AVAILABLE 242
+#define CM_FRONT_LIGHT_DUTY 243
+#define CM_FRONT_LIGHT_FREQUENCY 244
+#define CM_FRONT_LIGHT_R_EN 245
+#define CM_FRONT_LIGHT_HT68F20_SETDUTY 246
+#define CM_FRONT_LIGHT_GETDUTY 247
+
+#define CM_GET_KEYS 107
+
+
+#ifdef GPIOFN_PWRKEY//[
+static void power_key_chk(unsigned long v);
+
+static int PWR_SW_func(int iGPIOVal)
+{
+ printk("[%s]\n",__FUNCTION__);
+ power_key_chk(0);
+}
+
+static GPIODATA gtNTX_PWR_GPIO_data = {
+ .pfnGPIO = PWR_SW_func,
+ .uGPIO = gMX6SL_PWR_SW,
+ .szName = "PWR_SW",
+ .tPADCtrl = MX50_PAD_CSPI_MISO__GPIO_4_10,
+ .uiIRQType = IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,
+ .iWakeup = 1,
+};
+
+#endif //]GPIOFN_PWRKEY
+
+
+unsigned short __EBRMAIN_PID__ = 0;
+
+unsigned char __USB_ADAPTOR__=0;
+EXPORT_SYMBOL(__USB_ADAPTOR__);
+
+static int Driver_Count = -1;
+unsigned char __TOUCH_LOCK__= 0;
+int gSleep_Mode_Suspend;
+
+extern volatile NTX_HWCONFIG *gptHWCFG;
+
+extern volatile int giISD_3V3_ON_Ctrl ;
+
+typedef enum __DEV_MODULE_NAME{
+ EB500=0,
+ EB600=1,
+ EB600E=2,
+ EB600EM=3,
+ COOKIE=4,
+}__dev_module_name;
+
+typedef enum __DEV_MODULE_CPU{
+ CPU_S3C2410=0,
+ CPU_S3C2440=1,
+ CPU_S3C2416=2,
+ CPU_CORETEX_A8=3,
+ CPU_COOKIE=4,
+}__dev_module_cpu;
+
+typedef enum __DEV_MODULE_CONTROLLER{
+ CONTROLLER_PVI=0,
+ CONTROLLER_EPSON=1,
+ CONTROLLER_SW=2,
+}__dev_module_controller;
+
+typedef enum __DEV_MODULE_WIFI{
+ WIFI_NONE=0,
+ WIFI_MARVELL=1,
+ WIFI_OTHER=2,
+}__dev_module_wifi;
+
+typedef enum __DEV_MODULE_BLUETOOTH{
+ BLUETOOTH_NONE=0,
+ BLUETOOTH_TI=1,
+ BLUETOOTH_CSR=2,
+}__devi_module_bluetooth;
+
+struct ebook_device_info {
+ char device_name;
+ char cpu;
+ char controller;
+ char wifi;
+ char bluetooth;
+};
+
+
+static volatile int giFL_ON=0;
+
+static unsigned short FL_table0[100]={
+0x0001,0x0006,0x0007,0x0009,0x000C,0x000D,0x000E,0x000F,0x0011,0x0012,
+0x0014,0x0015,0x0017,0x0018,0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,
+0x0022,0x0023,0x0025,0x0027,0x0028,0x002A,0x002B,0x002D,0x002E,0x0030,
+0x0031,0x0033,0x0035,0x0036,0x0038,0x0039,0x003B,0x003C,0x003E,0x0040,
+0x0041,0x0043,0x0044,0x0046,0x0047,0x0049,0x004A,0x0051,0x0057,0x005D,
+0x0063,0x006A,0x0070,0x0076,0x007C,0x0083,0x0089,0x008F,0x0095,0x009C,
+0x00A2,0x00A8,0x00AE,0x00B5,0x00B9,0x00BB,0x00C1,0x00C7,0x00CE,0x00D4,
+0x00DA,0x00E0,0x00E7,0x00ED,0x00F3,0x00F9,0x0100,0x0106,0x010C,0x0112,
+0x0118,0x011F,0x0125,0x012B,0x0131,0x0138,0x013E,0x0144,0x014A,0x0151,
+0x0157,0x015D,0x0163,0x016A,0x0170,0x0176,0x017C,0x0183,0x0189,0x018F
+};
+
+struct front_light_setting {
+ unsigned short fl_r_en;
+ unsigned short freq;
+ unsigned short duty;
+};
+
+static struct front_light_setting FL_table[][100]={
+{// TABLE1
+{0,20000,3}, {0,20000,5}, {0,20000,7}, {0,20000,9}, {0,20000,11},
+{0,20000,13}, {0,20000,15}, {0,20000,17}, {0,20000,19}, {0,20000,21},
+{0,20000,23}, {0,20000,25}, {0,20000,27}, {0,20000,30}, {0,20000,33},
+{0,20000,36}, {0,20000,39}, {0,20000,42}, {0,20000,46}, {0,20000,51},
+{0,20000,54}, {0,20000,59}, {0,20000,63}, {0,20000,68}, {0,20000,71},
+{0,20000,74}, {0,20000,87}, {0,20000,99}, {0,20000,112}, {0,20000,124},
+{0,20000,137}, {0,20000,149}, {0,20000,162}, {0,20000,174}, {0,20000,185},
+{0,20000,193}, {0,20000,206}, {0,20000,218}, {0,20000,231}, {0,20000,243},
+{0,20000,256}, {1,20000,45}, {1,20000,46}, {1,20000,47}, {1,20000,48},
+{1,20000,49}, {1,20000,50}, {1,20000,51}, {1,20000,53}, {1,20000,55},
+{1,20000,56}, {1,20000,58}, {1,20000,60}, {1,20000,63}, {1,20000,65},
+{1,20000,68}, {1,20000,70}, {1,20000,75}, {1,20000,78}, {1,20000,80},
+{1,20000,85}, {1,20000,88}, {1,20000,90}, {1,20000,95}, {1,20000,100},
+{1,20000,105}, {1,20000,110}, {1,20000,115}, {1,20000,120}, {1,20000,125},
+{1,20000,130}, {1,20000,135}, {1,20000,140}, {1,20000,145}, {1,20000,150},
+{1,20000,155}, {1,20000,160}, {1,20000,170}, {1,20000,180}, {1,20000,190},
+{1,20000,200}, {1,20000,210}, {1,20000,220}, {1,20000,230}, {1,20000,240},
+{1,20000,250}, {1,20000,260}, {1,20000,270}, {1,20000,280}, {1,20000,290},
+{1,20000,300}, {1,20000,310}, {1,20000,320}, {1,20000,330}, {1,20000,340},
+{1,20000,350}, {1,20000,360}, {1,20000,370}, {1,20000,380}, {1,20000,400}
+},
+{// TABLE2
+{0,20000, 3 }, {0,20000, 4 }, {0,20000, 5 }, {0,20000, 6 }, {0,20000, 7 }, // 1%
+{0,20000, 8 }, {0,20000, 8 }, {0,20000, 9 }, {0,20000, 9 }, {0,20000, 10 }, //
+{0,20000, 12 }, {0,20000, 16 }, {0,20000, 19 }, {0,20000, 22 }, {0,20000, 25 }, // 11%
+{0,20000, 30 }, {0,20000, 38 }, {0,20000, 45 }, {0,20000, 52 }, {0,20000, 60 }, //
+{0,20000, 75 }, {0,20000,100 }, {0,20000,125 }, {0,20000,145 }, {0,20000,160 }, // 21%
+{0,20000,160 }, {0,20000,160 }, {0,20000,160 }, {0,20000,160 }, {1,20000, 20 }, //
+{1,20000, 22 }, {1,20000, 24 }, {1,20000, 26 }, {1,20000, 28 }, {1,20000, 30 }, // 31%
+{1,20000, 32 }, {1,20000, 34 }, {1,20000, 36 }, {1,20000, 38 }, {1,20000, 40 }, //
+{1,20000, 42 }, {1,20000, 44 }, {1,20000, 46 }, {1,20000, 48 }, {1,20000, 50 }, // 41%
+{1,20000, 52 }, {1,20000, 54 }, {1,20000, 56 }, {1,20000, 58 }, {1,20000, 60 }, //
+{1,20000, 62 }, {1,20000, 65 }, {1,20000, 69 }, {1,20000, 74 }, {1,20000, 80 }, // 51%
+{1,20000, 84 }, {1,20000, 88 }, {1,20000, 92 }, {1,20000, 96 }, {1,20000,100 }, //
+{1,20000,106 }, {1,20000,112 }, {1,20000,118 }, {1,20000,124 }, {1,20000,130 }, // 61%
+{1,20000,136 }, {1,20000,142 }, {1,20000,148 }, {1,20000,154 }, {1,20000,160 }, //
+{1,20000,168 }, {1,20000,176 }, {1,20000,184 }, {1,20000,192 }, {1,20000,200 }, // 71%
+{1,20000,206 }, {1,20000,212 }, {1,20000,218 }, {1,20000,224 }, {1,20000,230 }, //
+{1,20000,238 }, {1,20000,246 }, {1,20000,254 }, {1,20000,262 }, {1,20000,270 }, // 81%
+{1,20000,278 }, {1,20000,286 }, {1,20000,294 }, {1,20000,302 }, {1,20000,310 }, //
+{1,20000,318 }, {1,20000,326 }, {1,20000,334 }, {1,20000,342 }, {1,20000,350 }, // 91%
+{1,20000,360 }, {1,20000,370 }, {1,20000,380 }, {1,20000,330 }, {1,20000,400 }
+},
+{// TABLE3
+{0,10000,6},{0,10000,28},{0,10000,44},{0,10000,62},{0,10000,87},
+{0,10000,100},{0,10000,112},{0,10000,128},{0,10000,147},{0,10000,153},
+{0,10000,165},{0,10000,172},{0,10000,181},{0,10000,194},{0,10000,215},
+{0,10000,225},{0,10000,247},{0,10000,265},{0,10000,287},{0,10000,490},
+{0,10000,500},{0,10000,515},{0,10000,537},{0,10000,553},{0,10000,587},
+{0,10000,618},{0,10000,681},{0,10000,737},{0,10000,799},{1,10000,6},
+{1,10000,12},{1,10000,19},{1,10000,25},{1,10000,28},{1,10000,37},
+{1,10000,44},{1,10000,53},{1,10000,56},{1,10000,62},{1,10000,69},
+{1,10000,75},{1,10000,81},{1,10000,87},{1,10000,94},{1,10000,100},
+{1,10000,103},{1,10000,109},{1,10000,116},{1,10000,122},{1,10000,128},
+{1,10000,134},{1,10000,137},{1,10000,144},{1,10000,150},{1,10000,165},
+{1,10000,178},{1,10000,187},{1,10000,197},{1,10000,206},{1,10000,215},
+{1,10000,225},{1,10000,237},{1,10000,250},{1,10000,262},{1,10000,275},
+{1,10000,287},{1,10000,300},{1,10000,312},{1,10000,325},{1,10000,337},
+{1,10000,350},{1,10000,365},{1,10000,381},{1,10000,393},{1,10000,409},
+{1,10000,425},{1,10000,440},{1,10000,456},{1,10000,471},{1,10000,484},
+{1,10000,496},{1,10000,509},{1,10000,524},{1,10000,540},{1,10000,553},
+{1,10000,568},{1,10000,584},{1,10000,599},{1,10000,615},{1,10000,631},
+{1,10000,646},{1,10000,659},{1,10000,677},{1,10000,696},{1,10000,712},
+{1,10000,731},{1,10000,746},{1,10000,765},{1,10000,784},{1,10000,799}
+},
+{// TABLE4
+{0,20000,2}, {0,20000,5}, {0,20000,8}, {0,20000,12}, {0,20000,16},
+{0,20000,22}, {0,20000,28}, {0,20000,36}, {0,20000,39}, {0,20000,45},
+{0,20000,52}, {0,20000,56}, {0,20000,61}, {0,20000,67}, {0,20000,75},
+{0,20000,81}, {0,20000,87}, {0,20000,94}, {0,20000,100}, {0,20000,106},
+{0,20000,112}, {0,20000,119}, {0,20000,131}, {0,20000,137}, {0,20000,144},
+{0,20000,156}, {0,20000,175}, {0,20000,188}, {0,20000,212}, {0,20000,231},
+{0,20000,237}, {0,20000,250}, {0,20000,256}, {0,20000,262}, {0,20000,268},
+{0,20000,275}, {0,20000,287}, {0,20000,293}, {0,20000,306}, {0,20000,331},
+{0,20000,337}, {0,20000,350}, {0,20000,368}, {1,20000,67}, {1,20000,69},
+{1,20000,72}, {1,20000,75}, {1,20000,81}, {1,20000,87}, {1,20000,94},
+{1,20000,100}, {1,20000,106}, {1,20000,112}, {1,20000,119}, {1,20000,125},
+{1,20000,131}, {1,20000,137}, {1,20000,144}, {1,20000,150}, {1,20000,156},
+{1,20000,162}, {1,20000,169}, {1,20000,175}, {1,20000,181}, {1,20000,185},
+{1,20000,188}, {1,20000,194}, {1,20000,200}, {1,20000,206}, {1,20000,212},
+{1,20000,219}, {1,20000,225}, {1,20000,231}, {1,20000,237}, {1,20000,244},
+{1,20000,250}, {1,20000,256}, {1,20000,262}, {1,20000,268}, {1,20000,275},
+{1,20000,281}, {1,20000,287}, {1,20000,293}, {1,20000,300}, {1,20000,306},
+{1,20000,312}, {1,20000,318}, {1,20000,325}, {1,20000,331}, {1,20000,337},
+{1,20000,343}, {1,20000,350}, {1,20000,356}, {1,20000,362}, {1,20000,368},
+{1,20000,375}, {1,20000,381}, {1,20000,387}, {1,20000,393}, {1,20000,400}
+},
+{// TABLE5
+{0,20000,39},{0,20000,41},{0,20000,42},{0,20000,45},{0,20000,47},
+{0,20000,48},{0,20000,50},{0,20000,53},{0,20000,56},{0,20000,59},
+{0,20000,62},{0,20000,64},{0,20000,67},{0,20000,70},{0,20000,73},
+{0,20000,75},{0,20000,81},{0,20000,87},{0,20000,94},{0,20000,100},
+{0,20000,106},{0,20000,112},{0,20000,119},{0,20000,125},{0,20000,131},
+{0,20000,137},{0,20000,144},{0,20000,150},{0,20000,156},{0,20000,162},
+{0,20000,168},{0,20000,175},{0,20000,181},{0,20000,185},{0,20000,194},
+{0,20000,200},{0,20000,206},{0,20000,212},{0,20000,219},{0,20000,225},
+{0,20000,231},{0,20000,237},{0,20000,244},{0,20000,250},{1,20000,67},
+{1,20000,70},{1,20000,73},{1,20000,75},{1,20000,81},{1,20000,87},
+{1,20000,94},{1,20000,100},{1,20000,106},{1,20000,112},{1,20000,119},
+{1,20000,125},{1,20000,131},{1,20000,137},{1,20000,144},{1,20000,150},
+{1,20000,156},{1,20000,162},{1,20000,169},{1,20000,175},{1,20000,181},
+{1,20000,188},{1,20000,194},{1,20000,200},{1,20000,206},{1,20000,212},
+{1,20000,219},{1,20000,225},{1,20000,231},{1,20000,237},{1,20000,244},
+{1,20000,250},{1,20000,256},{1,20000,262},{1,20000,268},{1,20000,275},
+{1,20000,281},{1,20000,287},{1,20000,293},{1,20000,300},{1,20000,306},
+{1,20000,312},{1,20000,318},{1,20000,325},{1,20000,331},{1,20000,337},
+{1,20000,343},{1,20000,350},{1,20000,356},{1,20000,362},{1,20000,368},
+{1,20000,375},{1,20000,381},{1,20000,387},{1,20000,393},{1,20000,400}
+},
+{// TABLE6
+{0,20000,39},{0,20000,42},{0,20000,45},{0,20000,47},{0,20000,50},
+{0,20000,53},{0,20000,59},{0,20000,62},{0,20000,64},{0,20000,67},
+{0,20000,70},{0,20000,73},{0,20000,75},{0,20000,81},{0,20000,87},
+{0,20000,94},{0,20000,100},{0,20000,106},{0,20000,112},{0,20000,119},
+{0,20000,125},{0,20000,131},{0,20000,137},{0,20000,144},{0,20000,150},
+{0,20000,156},{0,20000,162},{0,20000,168},{0,20000,175},{0,20000,181},
+{0,20000,185},{0,20000,194},{0,20000,200},{0,20000,206},{0,20000,212},
+{0,20000,219},{0,20000,225},{0,20000,231},{0,20000,237},{0,20000,244},
+{0,20000,250},{0,20000,260},{0,20000,270},{0,20000,280},{1,20000,55},
+{1,20000,58},{1,20000,63},{1,20000,68},{1,20000,75},{1,20000,81},
+{1,20000,87},{1,20000,94},{1,20000,100},{1,20000,106},{1,20000,112},
+{1,20000,119},{1,20000,125},{1,20000,131},{1,20000,137},{1,20000,144},
+{1,20000,150},{1,20000,156},{1,20000,162},{1,20000,169},{1,20000,175},
+{1,20000,181},{1,20000,188},{1,20000,194},{1,20000,200},{1,20000,206},
+{1,20000,212},{1,20000,219},{1,20000,225},{1,20000,231},{1,20000,237},
+{1,20000,244},{1,20000,250},{1,20000,256},{1,20000,262},{1,20000,268},
+{1,20000,275},{1,20000,281},{1,20000,287},{1,20000,293},{1,20000,300},
+{1,20000,306},{1,20000,312},{1,20000,318},{1,20000,325},{1,20000,331},
+{1,20000,337},{1,20000,343},{1,20000,350},{1,20000,356},{1,20000,362},
+{1,20000,368},{1,20000,375},{1,20000,381},{1,20000,387},{1,20000,400}
+},
+{ // TABLE7
+{0,20000,39}, {0,20000,41}, {0,20000,42}, {0,20000,45}, {0,20000,47},
+{0,20000,48}, {0,20000,50}, {0,20000,53}, {0,20000,56}, {0,20000,59},
+{0,20000,62}, {0,20000,64}, {0,20000,67}, {0,20000,70}, {0,20000,73},
+{0,20000,75}, {0,20000,81}, {0,20000,87}, {0,20000,94}, {0,20000,106},
+{0,20000,119}, {0,20000,131}, {0,20000,144}, {0,20000,156}, {0,20000,168},
+{0,20000,181}, {0,20000,194}, {0,20000,206}, {0,20000,219}, {0,20000,231},
+{0,20000,244}, {0,20000,255}, {0,20000,265}, {0,20000,275}, {0,20000,285},
+{0,20000,295}, {0,20000,305}, {0,20000,315}, {0,20000,325}, {0,20000,335},
+{0,20000,345}, {0,20000,355}, {0,20000,365}, {0,20000,375}, {1,20000,67},
+{1,20000,70}, {1,20000,73}, {1,20000,75}, {1,20000,81}, {1,20000,87},
+{1,20000,94}, {1,20000,100}, {1,20000,106}, {1,20000,112}, {1,20000,119},
+{1,20000,125}, {1,20000,131}, {1,20000,137}, {1,20000,144}, {1,20000,150},
+{1,20000,156}, {1,20000,162}, {1,20000,169}, {1,20000,175}, {1,20000,181},
+{1,20000,188}, {1,20000,194}, {1,20000,200}, {1,20000,206}, {1,20000,212},
+{1,20000,219}, {1,20000,225}, {1,20000,231}, {1,20000,237}, {1,20000,244},
+{1,20000,250}, {1,20000,256}, {1,20000,262}, {1,20000,268}, {1,20000,275},
+{1,20000,281}, {1,20000,287}, {1,20000,293}, {1,20000,300}, {1,20000,306},
+{1,20000,312}, {1,20000,318}, {1,20000,325}, {1,20000,331}, {1,20000,337},
+{1,20000,343}, {1,20000,350}, {1,20000,356}, {1,20000,362}, {1,20000,368},
+{1,20000,375}, {1,20000,381}, {1,20000,387}, {1,20000,393}, {1,20000,400}
+},
+{// TABLE8
+{0,20000,18},{0,20000,24},{0,20000,30},{0,20000,41},{0,20000,49},
+{0,20000,62},{0,20000,71},{0,20000,82},{0,20000,93},{0,20000,110},
+{0,20000,132},{0,20000,150},{0,20000,170},{0,20000,195},{0,20000,216},
+{0,20000,238},{0,20000,252},{0,20000,266},{0,20000,280},{1,20000,30},
+{1,20000,32},{1,20000,33},{1,20000,35},{1,20000,37},{1,20000,39},
+{1,20000,41},{1,20000,43},{1,20000,45},{1,20000,47},{1,20000,49},
+{1,20000,51},{1,20000,53},{1,20000,55},{1,20000,57},{1,20000,59},
+{1,20000,61},{1,20000,63},{1,20000,65},{1,20000,67},{1,20000,69},
+{1,20000,71},{1,20000,73},{1,20000,75},{1,20000,77},{1,20000,80},
+{1,20000,84},{1,20000,87},{1,20000,89},{1,20000,91},{1,20000,93},
+{1,20000,96},{1,20000,99},{1,20000,102},{1,20000,104},{1,20000,106},
+{1,20000,109},{1,20000,112},{1,20000,114},{1,20000,116},{1,20000,118},
+{1,20000,120},{1,20000,123},{1,20000,126},{1,20000,128},{1,20000,131},
+{1,20000,133},{1,20000,136},{1,20000,138},{1,20000,140},{1,20000,143},
+{1,20000,146},{1,20000,149},{1,20000,152},{1,20000,155},{1,20000,158},
+{1,20000,160},{1,20000,162},{1,20000,165},{1,20000,167},{1,20000,172},
+{1,20000,175},{1,20000,178},{1,20000,185},{1,20000,192},{1,20000,196},
+{1,20000,200},{1,20000,204},{1,20000,208},{1,20000,216},{1,20000,223},
+{1,20000,230},{1,20000,237},{1,20000,245},{1,20000,248},{1,20000,252},
+{1,20000,257},{1,20000,262},{1,20000,268},{1,20000,274},{1,20000,280},
+},
+{//TABLE9
+{0,20000,18}, {0,20000,21}, {0,20000,26}, {0,20000,38}, {0,20000,46},
+{0,20000,58}, {0,20000,67}, {0,20000,77}, {0,20000,90}, {0,20000,101},
+{0,20000,123}, {0,20000,140}, {0,20000,160}, {0,20000,190}, {0,20000,210},
+{0,20000,230}, {0,20000,245}, {0,20000,258}, {0,20000,270},{1,20000,24},
+{1,20000,26}, {1,20000,28}, {1,20000,30}, {1,20000,32}, {1,20000,34},
+{1,20000,36}, {1,20000,38}, {1,20000,40}, {1,20000,42}, {1,20000,44},
+{1,20000,46}, {1,20000,48}, {1,20000,50}, {1,20000,52}, {1,20000,54},
+{1,20000,56}, {1,20000,58}, {1,20000,60}, {1,20000,62}, {1,20000,64},
+{1,20000,66}, {1,20000,68}, {1,20000,70}, {1,20000,72}, {1,20000,74},
+{1,20000,76}, {1,20000,78}, {1,20000,80}, {1,20000,82}, {1,20000,84},
+{1,20000,86}, {1,20000,88}, {1,20000,90}, {1,20000,92}, {1,20000,94},
+{1,20000,96}, {1,20000,98}, {1,20000,100}, {1,20000,102}, {1,20000,104},
+{1,20000,106}, {1,20000,108}, {1,20000,110}, {1,20000,112}, {1,20000,114},
+{1,20000,116}, {1,20000,118}, {1,20000,120}, {1,20000,122}, {1,20000,124},
+{1,20000,126}, {1,20000,128}, {1,20000,130}, {1,20000,132}, {1,20000,134},
+{1,20000,136}, {1,20000,138}, {1,20000,142}, {1,20000,144}, {1,20000,148},
+{1,20000,152}, {1,20000,158}, {1,20000,161}, {1,20000,163}, {1,20000,166},
+{1,20000,169}, {1,20000,175}, {1,20000,180}, {1,20000,184}, {1,20000,187},
+{1,20000,192}, {1,20000,196}, {1,20000,199}, {1,20000,203}, {1,20000,207},
+{1,20000,211}, {1,20000,215}, {1,20000,219}, {1,20000,226}, {1,20000,230}
+}
+};
+
+struct delayed_work FL_off;
+
+static void FL_module_off(void);
+
+void FL_off_func(struct work_struct *work);
+int FL_suspend(void);
+
+//kay for LED thread
+//static unsigned char LED_conitnuous=0;
+static unsigned char LED_conitnuous=1;
+static int LED_Flash_Count;
+static int gKeepPowerAlive;
+int gMxcPowerKeyIrqTriggered, g_power_key_pressed;
+volatile int g_mxc_touch_triggered = 1; //gallen 100420
+int g_wakeup_by_alarm;
+int gWifiEnabled=0;
+static unsigned long g_usb_in_tick; // Joseph 101001
+static int g_ioctl_SD_status, g_ioctl_USB_status, g_ioctl_rotary_status,g_Cus_Ctrl_Led;
+int g_mmc_card_detect_changed; // Joseph 20110125
+static DEFINE_SPINLOCK(led_flash_lock);
+static DECLARE_WAIT_QUEUE_HEAD(LED_blink_WaitQueue);
+static DECLARE_WAIT_QUEUE_HEAD(LED_freeze_WaitQueue);
+static DECLARE_WAIT_QUEUE_HEAD(WheelKey_WaitQueue);
+////////////////////
+
+static unsigned int last_FL_duty = 0;
+static unsigned int current_FL_freq = 0xFFFF;
+
+
+static DECLARE_WAIT_QUEUE_HEAD(Reset_WaitQueue);
+
+extern int gIsCustomerUi;
+
+int ntx_charge_status (void);
+int mxc_usb_plug_getstatus (void);
+
+void led_green (int isOn)
+{
+
+ if(0x03!=gptHWCFG->m_val.bUIConfig) {
+ // do not check charging status in MP/RD mode
+ if(gMX6SL_ON_LED==gMX6SL_CHG_LED&&mxc_usb_plug_getstatus()) {
+ // skip control charge led while charging .
+ return ;
+ }
+ }
+
+
+ if (isOn)
+ gpio_direction_output (gMX6SL_ON_LED,0);
+ else {
+ switch(gptHWCFG->m_val.bPCB) {
+ case 33:
+ // E60Q2X .
+ gpio_direction_output (gMX6SL_ON_LED,1);
+ default :
+ gpio_direction_input (gMX6SL_ON_LED);
+ }
+ }
+}
+
+void led_blue (int isOn)
+{
+
+ switch(gptHWCFG->m_val.bLed) {
+ case 1:
+ if (isOn)
+ gpio_direction_output (gMX6SL_ACT_LED,0);
+ else
+ gpio_direction_input (gMX6SL_ACT_LED);
+ break;
+ }
+}
+
+void led_red (int isOn) {
+ switch(gptHWCFG->m_val.bLed) {
+ //case 0:// Type1 .
+ case 1:// RGB
+ case 2:// RG
+ case 3:// RGH
+ case 7:// WH
+ if (isOn) {
+ gpio_direction_output (gMX6SL_CHG_LED,0);
+ }
+ else {
+ gpio_direction_input (gMX6SL_CHG_LED);
+ }
+ break;
+ }
+}
+
+
+//kay 20090925
+//check WiFi ID
+static int check_hardware_wifi(void)
+{
+ return WIFI_NONE;
+}
+
+//check Bluetooth ID
+static int check_hardware_bt(void)
+{
+ return BLUETOOTH_NONE;
+}
+
+static int check_hardware_cpu(void)
+{
+ return CPU_S3C2440;
+}
+
+//static int check_hardeare_name(void)
+int check_hardware_name(void)
+{
+ static int pcb_id = -1;
+
+ if (0 >= pcb_id) {
+ switch(gptHWCFG->m_val.bPCB)
+ {
+ default:
+ pcb_id = gptHWCFG->m_val.bPCB;
+ break;
+ }
+ printk ("[%s-%d] PCBA ID is %d\n",__func__,__LINE__,pcb_id);
+ }
+
+ return pcb_id;
+}
+EXPORT_SYMBOL(check_hardware_name);
+
+static int check_hardware_controller(void)
+{
+ return CONTROLLER_EPSON;
+}
+
+static void collect_hardware_info(struct ebook_device_info *info)
+{
+ info->cpu = check_hardware_cpu();
+ info->device_name = check_hardware_name();
+ info->controller = check_hardware_controller();
+ info->wifi = check_hardware_wifi();
+ info->bluetooth = check_hardware_bt();
+}
+
+static int openDriver(struct inode *inode,struct file *filp)
+{
+ if(!Driver_Count)
+ Driver_Count++;
+ return 0;
+}
+static int releaseDriver(struct inode *inode,struct file *filp)
+{
+ if(Driver_Count)
+ Driver_Count--;
+ return 0;
+}
+static void bluetooth_reset(int i)
+{
+}
+
+static void bluetooth_pwr(int i)
+{
+}
+
+extern unsigned long g_kl25_result;
+extern unsigned long g_kl25_action;
+extern void ntx_wifi_power_ctrl (int isWifiEnable);
+
+extern u16 msp430_deviceid(void);
+extern void msp430_auto_power(int minutes);
+extern void msp430_power_off(void);
+extern void msp430_pm_restart(void);
+extern void msp430_powerkeep(int n);
+extern int msp430_battery(void);
+extern void msp430_fl_enable (int isEnable);
+
+int ricoh619_restart(void);
+int ricoh619_battery_2_msp430_adc(void);
+int ricoh619_charger_detect(void);
+int ricoh619_dcin_status(void);
+
+extern int ht68f20_write_reg(unsigned int reg, unsigned int value);
+extern unsigned int ht68f20_read_reg(unsigned int reg);
+extern void ht68f20_enable(int isEnable);
+
+extern int up_write_reg(unsigned int reg, unsigned int value);
+extern unsigned int up_read_reg(unsigned int reg);
+
+int g_power_key_debounce; // Joseph 20100921 for ESD
+
+static void fl_pwm_enable (int isEnable)
+{
+ static int s_pwm_enabled=1;
+ if(1==gptHWCFG->m_val.bFL_PWM)
+ {
+ if (s_pwm_enabled != isEnable) {
+ s_pwm_enabled = isEnable;
+ ht68f20_enable (isEnable);
+ if (isEnable) {
+ mxc_iomux_v3_setup_pad (MX6SL_PAD_I2C1_SCL__I2C1_SCL);
+ mxc_iomux_v3_setup_pad (MX6SL_PAD_I2C1_SDA__I2C1_SDA);
+ }
+ else {
+ mxc_iomux_v3_setup_pad (MX6SL_PAD_I2C1_SCL__GPIO_3_12);
+ mxc_iomux_v3_setup_pad (MX6SL_PAD_I2C1_SDA__GPIO_3_13);
+ }
+ }
+ }
+}
+
+unsigned long long hwconfig = 0x0000000011000001LL;
+EXPORT_SYMBOL(hwconfig);
+unsigned char platform_type[32];
+EXPORT_SYMBOL(platform_type);
+
+static int __init early_hw(char *p)
+{
+ hwconfig = simple_strtoull(p, NULL, 16);
+ printk("hwconfig: %16llX\n", hwconfig);
+ return 0;
+}
+early_param("hwconfig", early_hw);
+
+//to parse hardware configuration bits
+static int __init early_board(char *p)
+{
+ strncpy(platform_type, p, sizeof(platform_type));
+ printk("board: %s\n", platform_type);
+ return 0;
+}
+early_param("board", early_board);
+
+int power_key_status (void)
+{
+ return gpio_get_value (gMX6SL_PWR_SW)?0:1;
+}
+
+int fl_set_percentage(int iFL_Percentage)
+{
+ int iRet = 0;
+ int p=iFL_Percentage;
+
+
+ if(0==gptHWCFG->m_val.bFrontLight)
+ return -1;
+
+ if(1==gptHWCFG->m_val.bFL_PWM)
+ {
+ // HT68F20
+
+ if (p) {
+ fl_pwm_enable (1);
+ if(delayed_work_pending(&FL_off)){
+ cancel_delayed_work_sync(&FL_off);
+ printk("FL_off delayed work canceled");
+ }
+ printk ("\nset front light level : %d\n",p);
+ if(p>0 && p<=100)
+ {
+ // temporary table
+ // for first 70 levels, fl_r_en = 0
+ // duty = 27,34,41 .... 510
+ // for 71~100 levels, fl_r_en =1
+ // duty = 162, 174, 186, 198 ... 510
+ int fl_r_en;
+ int duty;
+ if(p<=70){
+ fl_r_en = 0;
+ duty = 20 + p*7;
+ }
+ else {
+ fl_r_en = 1;
+ duty = 150 + (p-70)*12;
+ }
+ if (last_FL_duty >= p)
+ gpio_direction_output (MX6SL_FL_R_EN, fl_r_en);
+
+ ht68f20_write_reg (0xA6, duty&0xFF); // Set PWM duty
+ ht68f20_write_reg (0xA7, duty>>8);
+ printk ("Set front light duty : %d\n",duty);
+
+ if (last_FL_duty < p)
+ gpio_direction_output (MX6SL_FL_R_EN, fl_r_en);
+ }
+ else{
+ printk("Wrong number! level range from 0 to 100\n");
+ }
+ if (0 == last_FL_duty){
+ ht68f20_write_reg (0xA3, 0x01); // enable front light pwm
+
+ msleep(100);
+ gpio_direction_output(MX6SL_FL_EN,giFL_ON);
+ }
+ }
+ else if(last_FL_duty != 0){
+ printk ("FL PWM off command\n");
+ ht68f20_write_reg(0xA3, 0);
+ schedule_delayed_work(&FL_off, 120);
+ }
+ last_FL_duty = p;
+
+ }
+ else
+ {
+ if (p) {
+ if(delayed_work_pending(&FL_off)){
+ cancel_delayed_work_sync(&FL_off);
+ printk("FL_off delayed work canceled");
+ }
+ printk ("\nset front light level : %d\n",p);
+ if(p>0 && p<=100)
+ {
+ if( gptHWCFG->m_val.bFrontLight == 3){ //TABLE0a
+ up_write_reg (0xA5, 0x0100);
+ up_write_reg (0xA4, 0x9000);
+ up_write_reg (0xA7, FL_table0[p-1]&0xFF00);
+ up_write_reg (0xA6, FL_table0[p-1]<<8);
+ printk("PWMCNT : 0x%04x\n", FL_table0[p-1]);
+ }
+ else if( gptHWCFG->m_val.bFrontLight == 1 || gptHWCFG->m_val.bFrontLight == 2 ){ //TABLE0, TABLE0+
+ if (0 == last_FL_duty){
+ up_write_reg (0xA5, 0x0100);
+ up_write_reg (0xA4, 0x9000);
+ }
+ if(p<=50){
+ gpio_direction_output(MX6SL_FL_R_EN,0);
+ up_write_reg (0xA7, FL_table0[2*(p-1)]&0xFF00);
+ up_write_reg (0xA6, FL_table0[2*(p-1)]<<8);
+ printk("PWMCNT : 0x%04x\n", FL_table0[2*(p-1)]);
+ }else{
+ gpio_direction_output(MX6SL_FL_R_EN,1);
+ up_write_reg (0xA7, FL_table0[p-1]&0xFF00);
+ up_write_reg (0xA6, FL_table0[p-1]<<8);
+ printk("PWMCNT : 0x%04x\n", FL_table0[p-1]);
+ }
+ }
+ else{
+ int t_no = gptHWCFG->m_val.bFrontLight-4; // mapping hwconfig to FL_table
+ int freq = 8000000/FL_table[t_no][p-1].freq;
+
+ if (30 == gptHWCFG->m_val.bPCB && p==5) { //E606E2
+ p=1;
+ }
+
+ if (last_FL_duty >= p)
+ gpio_direction_output (MX6SL_FL_R_EN, FL_table[t_no][p-1].fl_r_en);
+
+ if( freq != current_FL_freq){
+ printk ("Set front light Frequency : %d\n",FL_table[t_no][p-1].freq);
+ up_write_reg (0xA5, freq&0xFF00); // Set Frequency 8M/freq
+ up_write_reg (0xA4, freq<<8);
+ current_FL_freq = freq;
+ }
+ up_write_reg (0xA7, FL_table[t_no][p-1].duty&0xFF00); // Set PWM duty
+ up_write_reg (0xA6, FL_table[t_no][p-1].duty<<8);
+ printk ("Set front light duty : %d\n",FL_table[t_no][p-1].duty);
+
+ if (last_FL_duty < p)
+ gpio_direction_output (MX6SL_FL_R_EN, FL_table[t_no][p-1].fl_r_en);
+ }
+ }
+ else{
+ printk("Wrong number! level range from 0 to 100\n");
+ }
+ if (0 == last_FL_duty){
+ up_write_reg (0xA1, 0xFF00); // Disable front light auto off timer
+ up_write_reg (0xA2, 0xFF00);
+
+ up_write_reg (0xA3, 0x0100); // enable front light pwm
+
+ msleep(100);
+ gpio_direction_output(MX6SL_FL_EN,giFL_ON);
+ msp430_fl_enable (1);
+ }
+ }
+ else if(last_FL_duty != 0){
+ printk ("FL PWM off command\n");
+ up_write_reg(0xA3, 0);
+ schedule_delayed_work(&FL_off, 120);
+ }
+ last_FL_duty = p;
+ }
+ return iRet;
+}
+
+
+
+
+static void ntx_system_reset(const char *pszDomain)
+{
+ if(pszDomain) {
+ printk("%s() ---%s reset ---\n",__FUNCTION__,pszDomain);
+ }
+
+ if(0!=gptHWCFG->m_val.bFrontLight){
+ up_write_reg (0xA3, 0);
+ msleep (1200);
+
+ FL_module_off();
+ }
+
+ while (1) {
+ gKeepPowerAlive = 0;
+ if (1==gptHWCFG->m_val.bPMIC) {
+ // RC5T19 .
+ printk("%s() --- RC5T19 restarting system ---\n",__FUNCTION__);
+ ricoh619_restart ();
+ }
+ else {
+ printk("%s() --- MSP430 restarting system ---\n",__FUNCTION__);
+ msp430_pm_restart();
+ }
+ sleep_on_timeout(&Reset_WaitQueue, 14*HZ/10);
+ }
+}
+
+static void ntx_system_poweroff(const char *pszDomain)
+{
+ if(pszDomain) {
+ printk("%s() ---%s poweroff ---\n",__FUNCTION__,pszDomain);
+ }
+ if (!gKeepPowerAlive) {
+
+ if(0!=gptHWCFG->m_val.bFrontLight){
+
+ if(0==gptHWCFG->m_val.bFL_PWM) {
+ // FL is controlled by MSP430 .
+ up_write_reg (0xA3, 0);
+ }
+
+ msleep (1200);
+
+ FL_module_off();
+ }
+
+ LED_conitnuous = 0;
+ led_green(0);
+ while (1) {
+ printk("Kernel---Power Down ---\n");
+ if(1==gptHWCFG->m_val.bPMIC)
+ ricoh619_power_off();
+ else
+ msp430_power_off();
+ sleep_on_timeout(&Reset_WaitQueue, 14*HZ/10);
+ }
+ }
+ else {
+ printk("Kernel---in keep alive mode ---\n");
+ }
+}
+
+static int ioctlDriver(struct file *filp, unsigned int command, unsigned long arg)
+{
+ unsigned long i = 0, temp;
+ unsigned int p = arg;//*(unsigned int *)arg;
+ struct ebook_device_info info;
+
+ if(!Driver_Count){
+ printk("pvi_io : do not open\n");
+ return -1;
+ }
+
+ switch(command)
+ {
+ case POWER_OFF_COMMAND:
+ ntx_system_poweroff("POWER_OFF_COMMAND");
+ break;
+
+ case SYS_RESET_COMMAND:
+ ntx_system_reset("SYS_RESET_COMMAND");
+ break;
+
+ case SYS_AUTO_POWER_ON:
+ msp430_auto_power(p);
+ ntx_system_reset("SYS_AUTO_POWER_ON");
+ break;
+
+ case POWER_KEEP_COMMAND:
+ printk("Kernel---System Keep Alive --- %d\n",p);
+ gKeepPowerAlive=p;
+ if(1==gptHWCFG->m_val.bPMIC)
+ break;
+ if (gKeepPowerAlive) {
+ msp430_powerkeep(1);
+ wake_up_interruptible(&LED_freeze_WaitQueue);
+ }
+ else
+ msp430_powerkeep(0);
+ break;
+
+ case CM_GET_BATTERY_STATUS:
+ if(1==gptHWCFG->m_val.bPMIC) {
+ i = ricoh619_battery_2_msp430_adc();
+ }
+ else {
+ i = msp430_battery ();
+ }
+ if (0 == i)
+ i = 0x8000;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+
+ break;
+
+ case AC_IN:
+ if(1==gptHWCFG->m_val.bPMIC) {
+ i = ricoh619_charger_detect()?1:0;
+ }
+ else
+ i = gpio_get_value (gMX6SL_NTX_ACIN_PG)?0:1;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_SD_IN:
+ g_ioctl_SD_status = gpio_get_value (MX6SL_EXT_SD_CD);
+ i = (g_ioctl_SD_status)?0:1;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_USB_Plug_IN:
+ if(1==gptHWCFG->m_val.bPMIC) {
+ g_ioctl_USB_status = ricoh619_charger_detect()?0:1;
+ }
+ else {
+ if (!g_ioctl_USB_status && gpio_get_value (gMX6SL_NTX_ACIN_PG)) {
+ msleep(200); // sleep 200ms to avoid system halt when USB plug out.
+ }
+ g_ioctl_USB_status = gpio_get_value (gMX6SL_NTX_ACIN_PG);
+ }
+ i = (g_ioctl_USB_status)?0:1;
+ if (!g_Cus_Ctrl_Led) {
+ led_red(g_ioctl_USB_status?0:1);
+ }
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case GET_LnBATT_CPU:
+ break;
+ case GET_VBATT_TH:
+ break;
+ case CM_AC_CK:
+ break;
+ case CM_CHARGE_STATUS:
+ i = ntx_charge_status();
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+ case CM_PWR_ON2:
+ break;
+ case CM_AUDIO_PWR:
+ break;
+ case CM_nLED:
+ //printk("CM_nLED %d\n",p);
+ led_green(p?1:0);
+ break;
+
+ case CM_nLED_CPU:
+ break;
+
+ case CM_SD_PROTECT:
+ i = 0;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_CONTROLLER:
+ i = 2; // 2: Epson controller. for micro window
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_USB_AC_STATUS:
+ i = 0;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_RTC_WAKEUP_FLAG:
+ if (!g_wakeup_by_alarm) {
+ if(1!=gptHWCFG->m_val.bPMIC) {
+ int tmp = up_read_reg (0x60);
+ if (0x8000 & tmp) {
+ printk ("[%s-%d] =================> Micro P MSP430 alarm triggered <===================\n", __func__, __LINE__);
+ g_wakeup_by_alarm = 1;
+ }
+ }
+ }
+ i = g_wakeup_by_alarm; // Joseph 091221 for slide show test.
+ g_wakeup_by_alarm = 0;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_SYSTEM_RESET:
+ ntx_system_reset("CM_SYSTEM_RESET");
+ break;
+
+ case CM_USB_HOST_PWR:
+ break;
+
+ case CM_BLUETOOTH_PWR:
+ ntx_wifi_power_ctrl (p);
+ break;
+
+ case CM_TELLPID:
+ if(p!=0){
+ printk("PID %d\n",p);
+ __EBRMAIN_PID__= p;
+ }
+ break;
+
+ case CM_LED_BLINK:
+ if (2==p) {
+ spin_lock(&led_flash_lock);
+ LED_Flash_Count++;
+ spin_unlock(&led_flash_lock);
+ }
+ if (!LED_conitnuous)
+ wake_up_interruptible(&LED_freeze_WaitQueue);
+ LED_conitnuous = p;
+ break;
+
+ case CM_TOUCH_LOCK:
+ if(p==0)
+ {
+ __TOUCH_LOCK__ = 0;
+ }else{
+ __TOUCH_LOCK__ = 1;
+ }
+ break;
+
+ case CM_DEVICE_MODULE:
+ i = check_hardware_name();
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_BLUETOOTH_RESET:
+ break;
+
+ case CM_DEVICE_INFO:
+ collect_hardware_info(&info);
+ copy_to_user((void __user *)arg, &info, sizeof(info));
+ break;
+
+ case CM_ROTARY_STATUS:
+ break;
+
+ case CM_ROTARY_ENABLE:
+ break;
+
+ case CM_GET_KEYS:
+ i = 0;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+ case CM_POWER_BTN:
+ case CM_GET_KEY_STATUS:
+ if (g_power_key_pressed) {
+ g_power_key_pressed = 0;
+ i = 1;
+ }
+ else {
+ i = power_key_status ();
+
+ if (i) {
+ if (2 >= g_power_key_debounce) { // Joseph 20100921 for ESD
+ printk ("[%s-%d] power key bounce detected %d\n",__func__,__LINE__, g_power_key_debounce);
+ i=0;
+ }
+ else {
+ gMxcPowerKeyIrqTriggered = 0;
+ }
+ }
+ else if (gMxcPowerKeyIrqTriggered) { // POWER key interrupt triggered.
+ if (2 < g_power_key_debounce) {
+ i = 1;
+ }
+ else
+ printk ("[%s-%d] power key bounce detected %d\n",__func__,__LINE__,g_power_key_debounce);
+ gMxcPowerKeyIrqTriggered = 0;
+ }
+ }
+
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ g_mxc_touch_triggered = 0;
+ break;
+
+ case CM_GET_WHEEL_KEY_STATUS:
+ i=0;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_GET_KL25_STATUS:
+ i=g_kl25_result;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ g_kl25_result &= 0xFF;
+ break;
+
+ case CM_GET_KL25_ACTION:
+ i=g_kl25_action ;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ g_kl25_action = 0;
+ break;
+
+ case CM_3G_POWER:
+ break;
+
+ case CM_3G_RF_OFF:
+ break;
+
+ case CM_3G_RESET:
+ break;
+
+ case CM_WIFI_CTRL:
+ ntx_wifi_power_ctrl (p);
+ break;
+
+ case CM_3G_GET_WAKE_STATUS:
+ i = 0;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_SET_ALARM_WAKEUP:
+ break;
+
+ case CM_GET_UP_VERSION:
+ if(1==gptHWCFG->m_val.bMicroP) {
+ i = 0;
+ }
+ else
+ i = msp430_deviceid();
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ break;
+
+ case CM_AUDIO_GET_VOLUME:
+ break;
+
+ case CM_AUDIO_SET_VOLUME:
+ break;
+
+ case CM_FRONT_LIGHT_SET:
+ fl_set_percentage(p);
+ break;
+
+ case CM_FRONT_LIGHT_GETDUTY:
+ if(1==gptHWCFG->m_val.bFL_PWM)
+ {
+ int duty;
+ duty = ht68f20_read_reg(0xB0);
+ printk ("[%s-%d] Front light Duty : %d\%\n",__func__,__LINE__,duty);
+ }
+ break;
+
+ case CM_FRONT_LIGHT_HT68F20_SETDUTY:
+ if(0!=gptHWCFG->m_val.bFrontLight && 1==gptHWCFG->m_val.bFL_PWM)
+ {
+ fl_pwm_enable (1);
+ if (p) {
+ printk ("\nSet front light duty : %3d\n",p);
+ ht68f20_write_reg (0xA6, p&0xFF);
+ ht68f20_write_reg (0xA7, p>>8);
+ if (0 == last_FL_duty){
+ ht68f20_write_reg (0xA3, 0x01);
+
+ msleep(100);
+ gpio_direction_output(MX6SL_FL_EN,giFL_ON);
+ }
+ }
+ else {
+ printk ("turn off front light\n");
+ ht68f20_write_reg (0xA3, 0);
+
+ FL_module_off();
+ }
+ last_FL_duty = p;
+ }
+ break;
+
+ case CM_FRONT_LIGHT_AVAILABLE:
+ {
+ i = (unsigned long) (gptHWCFG->m_val.bFrontLight?1:0) ;
+ copy_to_user((void __user *)arg, &i, sizeof(unsigned long));
+ }
+ break;
+
+ case CM_FRONT_LIGHT_DUTY:
+ if(0!=gptHWCFG->m_val.bFrontLight)
+ {
+ if (p) {
+ printk ("\nSet front light PWMCNT : 0x%4X\n",p);
+ printk ("Current front light Frequency : (8MHz/0x%4X)\n",current_FL_freq);
+ up_write_reg (0xA7, p&0xFF00);
+ up_write_reg (0xA6, p<<8);
+ if (0 == last_FL_duty){
+ up_write_reg (0xA1, 0xFF00);
+ up_write_reg (0xA2, 0xFF00);
+// up_write_reg (0xA5, 0xFF00);
+// up_write_reg (0xA4, 0xFF00);
+ up_write_reg (0xA3, 0x0100);
+
+ msleep(100);
+ gpio_direction_output(MX6SL_FL_EN,giFL_ON);
+ }
+ }
+ else {
+ printk ("turn off front light\n");
+ up_write_reg (0xA3, 0);
+ FL_module_off();
+ }
+ last_FL_duty = p;
+ }
+ break;
+
+ case CM_FRONT_LIGHT_FREQUENCY:
+ if(0!=gptHWCFG->m_val.bFrontLight)
+ {
+ if (p) {
+ printk ("set front light Frequency : (8MHz/0x%4X)\n",p);
+// up_write_reg (0xA4, (p<<8));
+ up_write_reg (0xA5, p&0xFF00);
+ up_write_reg (0xA4, (p<<8));
+ current_FL_freq = p;
+ }
+ }
+ break;
+
+ case CM_FRONT_LIGHT_R_EN:
+ if(0!=gptHWCFG->m_val.bFrontLight)
+ {
+ printk ("set FL_R_EN : %d\n",p);
+ gpio_direction_output(MX6SL_FL_R_EN, p);
+ }
+ break;
+
+ case CM_PLATFORM:
+ copy_to_user((void __user *)arg, &platform_type, 32);
+ break;
+ case CM_HWCONFIG:
+ copy_to_user((void __user *)arg, &hwconfig, sizeof(unsigned long
+ long));
+ break;
+ case CM_SET_HWCONFIG:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ copy_from_user(&hwconfig, (void __user *)arg, sizeof(unsigned long
+ long));
+ break;
+
+#ifdef TOUCH_HOME_LED
+ case CM_HOME_LED_ONOFF:
+ if(0x03==gptHWCFG->m_val.bUIConfig){
+ extern void homeled_onoff(int iIsON);
+ switch(p){
+ case 0:
+ homeled_onoff(0);
+ break;
+
+ case 1:
+ homeled_onoff(1);
+ break;
+
+ default:
+ homeled_onoff(1);
+ break;
+ }
+ }
+ break;
+#endif //#ifdef TOUCH_HOME_LED
+
+ default:
+ printk("pvi_io : do not get the command [%d]\n", command);
+ return -1;
+ }
+ return 0;
+}
+
+static struct file_operations driverFops= {
+ .owner = THIS_MODULE,
+ .open = openDriver,
+ .unlocked_ioctl = ioctlDriver,
+ .release = releaseDriver,
+};
+static struct miscdevice driverDevice = {
+ .minor = DEVICE_MINJOR,
+ .name = DEVICE_NAME,
+ .fops = &driverFops,
+};
+
+/*
+void mxc_set_fl_duty (int duty)
+{
+ static unsigned int last_FL_duty = 0;
+ static unsigned int current_FL_freq = 0xFFFF;
+ int t_no = gptHWCFG->m_val.bFrontLight-4; // mapping hwconfig to FL_table
+
+ if(0==gptHWCFG->m_val.bFrontLight)
+ return;
+
+ if (duty) {
+ if(delayed_work_pending(&FL_off)){
+ cancel_delayed_work_sync(&FL_off);
+ printk("FL_off delayed work canceled");
+ }
+ printk ("\nset front light level : %d\n",duty);
+
+ int freq = 8000000/FL_table[t_no][duty-1].freq;
+
+ if (last_FL_duty >= duty)
+ gpio_direction_output (MX6SL_FL_R_EN, FL_table[t_no][duty-1].fl_r_en);
+ if (freq != current_FL_freq) {
+ up_write_reg (0xA5, freq&0xFF00); // Set Frequency 8M/freq
+ up_write_reg (0xA4, freq<<8);
+ current_FL_freq = freq;
+ }
+ up_write_reg (0xA7, FL_table[t_no][duty-1].duty&0xFF00); // Set PWM duty
+ up_write_reg (0xA6, FL_table[t_no][duty-1].duty<<8);
+ gpio_direction_output (MX6SL_FL_R_EN, FL_table[t_no][duty-1].fl_r_en);
+
+ if (0 == last_FL_duty){
+ up_write_reg (0xA1, 0xFF00);
+ up_write_reg (0xA2, 0xFF00);
+
+ up_write_reg (0xA3, 0x0100);
+
+ msleep(100);
+ gpio_direction_output(MX6SL_FL_EN,0);
+ }
+ }
+ else if (last_FL_duty) {
+ printk ("turn off front light\n");
+ printk ("FL PWM off command\n");
+ up_write_reg(0xA3, 0);
+ schedule_delayed_work(&FL_off, 120);
+ current_FL_freq = 0xFFFF;
+ }
+ last_FL_duty = duty;
+}
+*/
+
+// ================================= Simulate MC13892 Signaling LED Driver ================================
+static struct timer_list green_led_timer, blue_led_timer, red_led_timer;
+static unsigned char green_led_dc, blue_led_dc, red_led_dc, \
+ green_led_flag, blue_led_flag, red_led_flag;
+static int green_led_period,blue_led_period,red_led_period ;
+
+static void ntx_led_set_timer (struct timer_list *pTimer, unsigned char dc, int blink)
+{
+ int period;
+
+ if (0 == dc || 0==blink) {
+ del_timer_sync(pTimer);
+ return;
+ }
+
+
+ switch (blink) {
+ case 1:
+ period = 100 / 8; // 1/8 s
+ break;
+ case 2:
+ period = 100; // 1 s
+ break;
+ case 3:
+ period = 200; // 2 s
+ break;
+ default:
+ if(blink>10) {
+ period = blink/10;
+ break;
+ }
+ return ;
+ }
+
+ mod_timer(pTimer, jiffies + period);
+}
+
+static void green_led_blink_func (unsigned long v)
+{
+ green_led_flag ^= 1;
+ led_green(green_led_flag?0:1);
+ ntx_led_set_timer (&green_led_timer, green_led_dc, green_led_period);
+}
+
+static void blue_led_blink_func (unsigned long v)
+{
+ blue_led_flag ^= 1;
+ led_blue(blue_led_flag?0:1);
+ ntx_led_set_timer (&blue_led_timer, blue_led_dc, blue_led_period);
+}
+
+static void red_led_blink_func (unsigned long v)
+{
+ red_led_flag ^= 1;
+ led_red(red_led_flag?0:1);
+ ntx_led_set_timer (&red_led_timer, red_led_dc, red_led_period);
+}
+
+void ntx_led_blink (unsigned int channel, int period)
+{
+ //printk("%s,period=%d\n",__FUNCTION__,period);
+ g_Cus_Ctrl_Led = 1;
+ switch (channel) {
+ case 3:
+ red_led_period = period&3;
+ ntx_led_set_timer (&red_led_timer, red_led_dc, red_led_period);
+ if(0==period) {
+ led_red(0);
+ }
+ break;
+ case 4:
+ //green_led_period = period&3;
+ green_led_period = period;
+ ntx_led_set_timer (&green_led_timer, green_led_dc, green_led_period);
+ if(0==period) {
+ led_green(0);
+ }
+ break;
+ case 5:
+ blue_led_period = period&3;
+ ntx_led_set_timer (&blue_led_timer, blue_led_dc, blue_led_period);
+ if(0==period) {
+ led_blue(0);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void ntx_led_dc (unsigned int channel, unsigned char dc)
+{
+ LED_conitnuous = 0;
+ g_Cus_Ctrl_Led = 1;
+ switch (channel) {
+ case 3:
+ red_led_dc = dc;
+ red_led_flag = (dc)?0:1;
+ led_red(red_led_flag?0:1);
+ ntx_led_set_timer (&red_led_timer, red_led_dc, red_led_period);
+ break;
+ case 4:
+ green_led_dc = dc;
+ green_led_flag = (dc)?0:1;
+ led_green(green_led_flag?0:1);
+ ntx_led_set_timer (&green_led_timer, green_led_dc, green_led_period);
+ break;
+ case 5:
+ blue_led_dc = dc;
+ blue_led_flag = (dc)?0:1;
+ led_blue(blue_led_flag?0:1);
+ ntx_led_set_timer (&blue_led_timer, blue_led_dc, blue_led_period);
+ break;
+ default:
+ break;
+ }
+}
+
+void ntx_led_current (unsigned int channel, unsigned char value)
+{
+ g_Cus_Ctrl_Led = 1;
+ if (!value)
+ ntx_led_dc (channel, 0);
+}
+
+static void FL_module_off(void)
+{
+ if(giFL_ON) {
+ gpio_direction_output(MX6SL_FL_EN,0);
+ }
+ else {
+ gpio_direction_input(MX6SL_FL_EN);
+ }
+ gpio_direction_input(MX6SL_FL_R_EN);
+ fl_pwm_enable (0);
+ msp430_fl_enable (0);
+}
+
+void FL_off_func(struct work_struct *work)
+{
+ printk("[%s-%d]FL PWR off\n",__FUNCTION__,__LINE__);
+ FL_module_off();
+}
+
+int FL_suspend(void){
+ if(delayed_work_pending(&FL_off)){
+ return -1;
+ }
+ return 0;
+}
+
+static int sleep_thread(void)
+{
+int rc = 0;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if(signal_pending(current))
+ rc = -EINTR;
+ __set_current_state(TASK_RUNNING);
+ return rc;
+}
+
+static int LED_Thread(void *param)
+{
+ sigset_t thread_signal_mask;
+ siginitsetinv(&thread_signal_mask, sigmask(SIGKILL));
+ sigprocmask(SIG_SETMASK, &thread_signal_mask, NULL);
+
+ while(1){
+ if(freezing(current)){
+ printk("freeze 0 !!!!!!!!!!!!!!!!!!!!\n");
+ try_to_freeze();
+ }
+
+ if(LED_conitnuous == 0){
+ interruptible_sleep_on(&LED_freeze_WaitQueue);
+ if(freezing(current)){
+ printk("freeze 1!!!!!!!!!!!!!!!!!!!!\n");
+ try_to_freeze();
+ }
+ }
+ if (g_Cus_Ctrl_Led) {
+ LED_conitnuous = 0;
+ continue;
+ }
+ led_green(1);
+ while (gKeepPowerAlive) {
+ sleep_on_timeout(&Reset_WaitQueue,HZ*2);
+ msp430_powerkeep(1);
+ }
+ //start to blink LED;
+ if (2 == LED_conitnuous) {
+ spin_lock(&led_flash_lock);
+ LED_Flash_Count = 0;
+ LED_conitnuous = 0;
+ spin_unlock(&led_flash_lock);
+ sleep_on_timeout(&LED_blink_WaitQueue,HZ/10);
+ led_green(0);
+ sleep_on_timeout(&LED_blink_WaitQueue,HZ/10);
+ led_green(1);
+ sleep_on_timeout(&LED_blink_WaitQueue,HZ/10);
+ if (!green_led_dc)
+ led_green(0);
+ sleep_on_timeout(&LED_blink_WaitQueue,HZ/10);
+ }
+ else {
+ sleep_on_timeout(&LED_blink_WaitQueue,HZ/2);
+ if (!green_led_dc)
+ led_green(0);
+ sleep_on_timeout(&LED_blink_WaitQueue,HZ/2);
+ }
+ }
+ return 0;
+}
+
+static struct timer_list power_key_timer;
+
+extern void mxc_kpp_report_key(int isDown,__u16 wKeyCode);
+extern void gpiokeys_report_key(int isDown,__u16 wKeyCode);
+extern void mxc_kpp_report_power(int isDown);
+extern void gpiokeys_report_power(int isDown);
+extern void gpiokeys_report_event(unsigned int type, unsigned int code, int value);
+extern void mxc_kpp_report_event(unsigned int type, unsigned int code, int value);
+
+void ntx_report_key(int isDown,__u16 wKeyCode)
+{
+ if(NTXHWCFG_TST_FLAG(gptHWCFG->m_val.bPCB_Flags,0)) {
+ // no keymatrix .
+ gpiokeys_report_key(isDown, wKeyCode);
+ }else{
+ mxc_kpp_report_key(isDown, wKeyCode);
+ }
+}
+
+void ntx_report_event(unsigned int type, unsigned int code, int value)
+{
+ if(NTXHWCFG_TST_FLAG(gptHWCFG->m_val.bPCB_Flags,0)) {
+ // no keymatrix .
+ gpiokeys_report_event(type,code,value);
+ }else{
+ mxc_kpp_report_event(type,code,value);
+ }
+}
+
+void ntx_report_power(int isDown)
+{
+ ntx_report_key(isDown, KEY_POWER);
+}
+
+static void power_key_chk(unsigned long v)
+{
+ int iPwrKeyState=power_key_status();
+ if (iPwrKeyState) {
+ ++g_power_key_debounce;
+ if (2 == g_power_key_debounce) {
+ ntx_report_power(1);
+ }
+ mod_timer(&power_key_timer, jiffies + 1);
+ }
+ else {
+ ntx_report_power(0);
+ }
+
+#if 0 //[ debug code .
+ printk("%s():PwrKeyState=%d,debounce=%d,IsCustomUI=%d\n",__FUNCTION__,
+ iPwrKeyState,g_power_key_debounce,gIsCustomerUi);
+#endif //]
+}
+
+void power_key_int_function(void)
+{
+ gMxcPowerKeyIrqTriggered = 1;
+ g_power_key_debounce = 0;
+ mod_timer(&power_key_timer, jiffies + 1);
+}
+
+static irqreturn_t power_key_int(int irq, void *dev_id)
+{
+ //printk("%s !!\n",__FUNCTION__);
+ power_key_int_function();
+ return 0;
+}
+
+int ntx_charge_status (void)
+{
+ int iIsUSBPlugged = 0;
+
+ if (1==gptHWCFG->m_val.bPMIC) {
+ iIsUSBPlugged = ricoh619_dcin_status();
+ }
+ else {
+ iIsUSBPlugged = gpio_get_value (gMX6SL_NTX_ACIN_PG)?0:1;
+ }
+ if (!iIsUSBPlugged) {
+ return 0;
+ }
+ else {
+ return (1 | (gpio_get_value (gMX6SL_NTX_CHG)?0:2));
+ }
+}
+
+int mxc_usb_plug_getstatus (void)
+{
+ //if (gIsCustomerUi)
+ {
+ int usb_status = 0;
+#if 1
+ if (1==gptHWCFG->m_val.bPMIC) {
+ usb_status = ricoh619_dcin_status();
+ g_ioctl_USB_status = usb_status?0:1;
+ return usb_status;
+ }
+ else
+#endif
+ usb_status = gpio_get_value (gMX6SL_NTX_ACIN_PG);
+
+ DBG_MSG("%s(),USB status=%d\n",__FUNCTION__,g_ioctl_USB_status);
+ g_ioctl_USB_status = usb_status?0:1;
+ return g_ioctl_USB_status;
+ }
+ //else {
+ //return 0;
+ //}
+}
+
+/*!
+ * Key raw pins interrupt handler.
+ */
+static irqreturn_t gpio_key_row_int(int irq, void *dev_id)
+{
+// pr_info(KERN_INFO "key matrix pressed ...\n");
+ return 0;
+}
+
+// NTX_GPIO_KEYS
+#define NTX_GPIO_KEYS_MAX 5
+static int gi_ntx_gpio_buttons_total = 0;
+static struct gpio_keys_button ntx_gpio_buttons[NTX_GPIO_KEYS_MAX] = {
+ {0,},
+};
+static struct gpio_keys_platform_data ntx_gpio_key_data = {
+ .buttons=ntx_gpio_buttons,
+ .nbuttons=0,
+ .rep=0,
+};
+static struct platform_device ntx_gpio_key_device = {
+ .name = "mxckpd",
+ .id = -1,
+ .dev = {
+ .platform_data = &ntx_gpio_key_data,
+ },
+};
+
+static void mxc_pads_dse_setup(iomux_v3_cfg_t *pad_list, unsigned count,iomux_v3_cfg_t tDSE_PAD_VAL)
+{
+ iomux_v3_cfg_t *p = pad_list;
+ int i;
+ iomux_v3_cfg_t tDSE_PAD_MASK=(iomux_v3_cfg_t)0x38<<MUX_PAD_CTRL_SHIFT;
+ iomux_v3_cfg_t tDSE_PAD_Current;
+
+ tDSE_PAD_VAL <<= MUX_PAD_CTRL_SHIFT;
+ tDSE_PAD_VAL &= tDSE_PAD_MASK;
+
+ for(i=0;i<count;i++) {
+ mxc_iomux_v3_get_pad(p);
+
+ tDSE_PAD_Current = *p;
+
+ *p &= ~tDSE_PAD_MASK;
+ *p |= tDSE_PAD_VAL;
+
+ //printk("PAD set 0x%llx->0x%llx \n",tDSE_PAD_Current,*p);
+ mxc_iomux_v3_setup_pad(*p);
+ p++;
+ }
+}
+
+#define GPIO_BAT_LOW_INT IMX_GPIO_NR(3, 28) /* COL2 */
+static irqreturn_t bat_low_int(int irq, void *dev_id)
+{
+ printk ("[%s-%d] triggered!!\n", __func__, __LINE__);
+ return 0;
+}
+
+
+static int gpio_initials(void)
+{
+ int irq, ret;
+ int error;
+
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_KEY_COL2__GPIO_3_28);
+ gpio_request (GPIO_BAT_LOW_INT, "MX6SL_BAT_LOW");
+ gpio_direction_input(GPIO_BAT_LOW_INT);
+#if 0
+ irq = gpio_to_irq(GPIO_BAT_LOW_INT);
+ ret = request_irq(irq, bat_low_int, IRQF_TRIGGER_FALLING, "bat_low", 0);
+ if (ret)
+ pr_info("register on-off key interrupt failed\n");
+ else
+ enable_irq_wake(irq);
+#endif
+#ifndef CONFIG_ANDROID//[
+ if(0==gptHWCFG->m_val.bUIStyle) {
+ // Ebrmain .
+
+ power_key_timer.function = power_key_chk;
+ init_timer(&power_key_timer);
+ /* OFF_CHK */
+ #ifdef GPIOFN_PWRKEY//[
+ gpiofn_register(&gtNTX_PWR_GPIO_data);
+ #else //][!GPIOFN_PWRKEY
+
+ gpio_direction_input(gMX6SL_PWR_SW);
+ {
+ /* Set power key as wakeup resource */
+ irq = gpio_to_irq(gMX6SL_PWR_SW);
+ ret = request_irq(irq, power_key_int, IRQF_TRIGGER_FALLING, "power_key", 0);
+ if (ret)
+ pr_info("register on-off key interrupt failed\n");
+ else
+ enable_irq_wake(irq);
+ }
+ }
+ #endif //]GPIOFN_PWRKEY
+#endif//]CONFIG_ANDROID
+
+
+ gpio_direction_output(gMX6SL_IR_TOUCH_RST, 0);
+ msleep(20);
+ gpio_direction_input(gMX6SL_IR_TOUCH_RST);
+
+ // MX6SL_FL_EN
+ if( 0 != gptHWCFG->m_val.bFrontLight ){
+ if(NTXHWCFG_TST_FLAG(gptHWCFG->m_val.bFrontLight_Flags,2)){
+ // FL_EN invert .
+ //printk("FL_EN inverted !\n",__FUNCTION__);
+ giFL_ON=1;
+ }
+ if( 0 == NTXHWCFG_TST_FLAG(gptHWCFG->m_val.bFrontLight_Flags,0)){
+ FL_module_off();
+ }
+ INIT_DELAYED_WORK(&FL_off, FL_off_func);
+ }
+
+#ifdef _WIFI_ALWAYS_ON_
+ set_irq_type(gpio_to_irq(gMX6SL_WIFI_INT), IRQF_TRIGGER_FALLING);
+#endif
+
+ if(40==gptHWCFG->m_val.bPCB||49==gptHWCFG->m_val.bPCB) {
+ // E60Q5X / E60QDX for EMI .
+ printk("EMMC DSE set to 48 ohm \n");
+ mxc_pads_dse_setup(mx6sl_brd_ntx_sd4_pads,
+ ARRAY_SIZE(mx6sl_brd_ntx_sd4_pads),(iomux_v3_cfg_t)PAD_CTL_DSE_48ohm);
+ }
+
+ // initial test point for ESD , Joseph 20100504
+ return 0;
+}
+
+#include <mach/hardware.h>
+#define SSI1_IO_BASE_ADDR IO_ADDRESS(SSI1_BASE_ADDR)
+#define SSI2_IO_BASE_ADDR IO_ADDRESS(SSI2_BASE_ADDR)
+#define SSI1_SCR ((SSI1_IO_BASE_ADDR) + 0x10)
+#define SSI2_SCR ((SSI2_IO_BASE_ADDR) + 0x10)
+
+#include <mach/arc_otg.h>
+#include "crm_regs.h"
+extern void __iomem *apll_base;
+unsigned long gUart_ucr1;
+
+static iomux_v3_cfg_t ntx_suspend_enter_pads[] = {
+ // I2C1,I2C2
+ MX6SL_PAD_I2C2_SCL__GPIO_3_14,
+ MX6SL_PAD_I2C2_SDA__GPIO_3_15,
+ MX6SL_PAD_I2C1_SCL__GPIO_3_12,
+ MX6SL_PAD_I2C1_SDA__GPIO_3_13,
+ // SD2
+ MX6SL_PAD_SD2_CLK__GPIO_5_5,
+ MX6SL_PAD_SD2_CMD__GPIO_5_4,
+ MX6SL_PAD_SD2_DAT0__GPIO_5_1,
+ MX6SL_PAD_SD2_DAT1__GPIO_4_30,
+ MX6SL_PAD_SD2_DAT2__GPIO_5_3,
+ MX6SL_PAD_SD2_DAT3__GPIO_4_28,
+ // SD3
+ MX6SL_PAD_SD3_CLK__GPIO_5_18,
+ MX6SL_PAD_SD3_CMD__GPIO_5_21,
+ MX6SL_PAD_SD3_DAT0__GPIO_5_19,
+ MX6SL_PAD_SD3_DAT1__GPIO_5_20,
+ MX6SL_PAD_SD3_DAT2__GPIO_5_16,
+ MX6SL_PAD_SD3_DAT3__GPIO_5_17,
+ // SD4
+ MX6SL_PAD_FEC_TX_CLK__GPIO_4_21,
+ MX6SL_PAD_FEC_MDIO__GPIO_4_20,
+ MX6SL_PAD_FEC_RX_ER__GPIO_4_19,
+ MX6SL_PAD_FEC_CRS_DV__GPIO_4_25,
+ MX6SL_PAD_FEC_RXD1__GPIO_4_18,
+ MX6SL_PAD_FEC_TXD0__GPIO_4_24,
+ MX6SL_PAD_FEC_MDC__GPIO_4_23,
+ MX6SL_PAD_FEC_RXD0__GPIO_4_17,
+ MX6SL_PAD_FEC_TX_EN__GPIO_4_22,
+ MX6SL_PAD_FEC_TXD1__GPIO_4_16,
+ MX6SL_PAD_FEC_REF_CLK__GPIO_4_26,
+
+ // TEST ONLY
+ MX6SL_PAD_ECSPI1_MISO__GPIO_4_10,
+ MX6SL_PAD_ECSPI1_MOSI__GPIO_4_9,
+ MX6SL_PAD_ECSPI1_SCLK__GPIO_4_8,
+ MX6SL_PAD_ECSPI1_SS0__GPIO_4_11,
+
+ MX6SL_PAD_ECSPI2_MISO__GPIO_4_14,
+ MX6SL_PAD_ECSPI2_MOSI__GPIO_4_13,
+ MX6SL_PAD_ECSPI2_SCLK__GPIO_4_12,
+ MX6SL_PAD_ECSPI2_SS0__GPIO_4_15,
+
+ MX6SL_PAD_EPDC_BDR0__GPIO_2_5,
+ MX6SL_PAD_EPDC_BDR1__GPIO_2_6,
+ MX6SL_PAD_EPDC_D0__GPIO_1_7,
+ MX6SL_PAD_EPDC_D1__GPIO_1_8,
+ MX6SL_PAD_EPDC_D10__GPIO_1_17,
+ MX6SL_PAD_EPDC_D11__GPIO_1_18,
+ MX6SL_PAD_EPDC_D12__GPIO_1_19,
+ MX6SL_PAD_EPDC_D13__GPIO_1_20,
+ MX6SL_PAD_EPDC_D14__GPIO_1_21,
+ MX6SL_PAD_EPDC_D15__GPIO_1_22,
+ MX6SL_PAD_EPDC_D2__GPIO_1_9,
+ MX6SL_PAD_EPDC_D3__GPIO_1_10,
+ MX6SL_PAD_EPDC_D4__GPIO_1_11,
+ MX6SL_PAD_EPDC_D5__GPIO_1_12,
+ MX6SL_PAD_EPDC_D6__GPIO_1_13,
+ MX6SL_PAD_EPDC_D7__GPIO_1_14,
+ MX6SL_PAD_EPDC_D8__GPIO_1_15,
+ MX6SL_PAD_EPDC_D9__GPIO_1_16,
+ MX6SL_PAD_EPDC_GDCLK__GPIO_1_31,
+ MX6SL_PAD_EPDC_GDOE__GPIO_2_0,
+ MX6SL_PAD_EPDC_GDRL__GPIO_2_1,
+ MX6SL_PAD_EPDC_GDSP__GPIO_2_2,
+// MX6SL_PAD_EPDC_PWRCOM__GPIO_2_11,
+ MX6SL_PAD_EPDC_PWRCTRL0__GPIO_2_7,
+ MX6SL_PAD_EPDC_PWRCTRL1__GPIO_2_8,
+ MX6SL_PAD_EPDC_PWRCTRL2__GPIO_2_9,
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10,
+ MX6SL_PAD_EPDC_PWRINT__GPIO_2_12,
+ MX6SL_PAD_EPDC_PWRSTAT__GPIO_2_13,
+ MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14,
+ MX6SL_PAD_EPDC_SDCE0__GPIO_1_27,
+ MX6SL_PAD_EPDC_SDCE1__GPIO_1_28,
+ MX6SL_PAD_EPDC_SDCE2__GPIO_1_29,
+ MX6SL_PAD_EPDC_SDCE3__GPIO_1_30,
+ MX6SL_PAD_EPDC_SDCLK__GPIO_1_23,
+ MX6SL_PAD_EPDC_SDLE__GPIO_1_24,
+ MX6SL_PAD_EPDC_SDOE__GPIO_1_25,
+ MX6SL_PAD_EPDC_SDSHR__GPIO_1_26,
+ MX6SL_PAD_EPDC_VCOM0__GPIO_2_3,
+ MX6SL_PAD_EPDC_VCOM1__GPIO_2_4,
+
+/*
+ffffff80
+000077ff
+0000f000
+53ffff00
+003f003a
+*/
+ MX6SL_PAD_HSIC_DAT__GPIO_3_19,
+ MX6SL_PAD_HSIC_STROBE__GPIO_3_20,
+ MX6SL_PAD_KEY_COL0__GPIO_3_24,
+ MX6SL_PAD_KEY_COL1__GPIO_3_26,
+ MX6SL_PAD_KEY_COL2__GPIO_3_28,
+ MX6SL_PAD_KEY_COL3__GPIO_3_30,
+ MX6SL_PAD_KEY_COL4__GPIO_4_0,
+ MX6SL_PAD_KEY_COL5__GPIO_4_2,
+ MX6SL_PAD_KEY_COL6__GPIO_4_4,
+ MX6SL_PAD_KEY_COL7__GPIO_4_6,
+ MX6SL_PAD_KEY_ROW0__GPIO_3_25,
+ MX6SL_PAD_KEY_ROW1__GPIO_3_27,
+ MX6SL_PAD_KEY_ROW2__GPIO_3_29,
+ MX6SL_PAD_KEY_ROW3__GPIO_3_31,
+ MX6SL_PAD_KEY_ROW4__GPIO_4_1,
+ MX6SL_PAD_KEY_ROW5__GPIO_4_3,
+ MX6SL_PAD_KEY_ROW6__GPIO_4_5,
+ MX6SL_PAD_KEY_ROW7__GPIO_4_7,
+/*
+ffffff80
+000077ff
+ff18f000
+57ffffff
+003f003a
+*/
+ MX6SL_PAD_LCD_CLK__GPIO_2_15,
+ MX6SL_PAD_LCD_DAT0__GPIO_2_20,
+ MX6SL_PAD_LCD_DAT1__GPIO_2_21,
+ MX6SL_PAD_LCD_DAT10__GPIO_2_30,
+ MX6SL_PAD_LCD_DAT11__GPIO_2_31,
+ MX6SL_PAD_LCD_DAT12__GPIO_3_0,
+ MX6SL_PAD_LCD_DAT13__GPIO_3_1,
+ MX6SL_PAD_LCD_DAT14__GPIO_3_2,
+ MX6SL_PAD_LCD_DAT15__GPIO_3_3,
+ MX6SL_PAD_LCD_DAT16__GPIO_3_4,
+ MX6SL_PAD_LCD_DAT17__GPIO_3_5,
+ MX6SL_PAD_LCD_DAT18__GPIO_3_6,
+ MX6SL_PAD_LCD_DAT19__GPIO_3_7,
+ MX6SL_PAD_LCD_DAT2__GPIO_2_22,
+ MX6SL_PAD_LCD_DAT20__GPIO_3_8,
+ MX6SL_PAD_LCD_DAT21__GPIO_3_9,
+ MX6SL_PAD_LCD_DAT22__GPIO_3_10,
+ MX6SL_PAD_LCD_DAT23__GPIO_3_11,
+ MX6SL_PAD_LCD_DAT3__GPIO_2_23,
+ MX6SL_PAD_LCD_DAT4__GPIO_2_24,
+ MX6SL_PAD_LCD_DAT5__GPIO_2_25,
+ MX6SL_PAD_LCD_DAT6__GPIO_2_26,
+ MX6SL_PAD_LCD_DAT7__GPIO_2_27,
+ MX6SL_PAD_LCD_DAT8__GPIO_2_28,
+ MX6SL_PAD_LCD_DAT9__GPIO_2_29,
+ MX6SL_PAD_LCD_ENABLE__GPIO_2_16,
+ MX6SL_PAD_LCD_HSYNC__GPIO_2_17,
+ MX6SL_PAD_LCD_RESET__GPIO_2_19,
+ MX6SL_PAD_LCD_VSYNC__GPIO_2_18,
+ MX6SL_PAD_PWM1__GPIO_3_23,
+ MX6SL_PAD_REF_CLK_24M__GPIO_3_21,
+ MX6SL_PAD_REF_CLK_32K__GPIO_3_22,
+ MX6SL_PAD_SD1_CLK__GPIO_5_15,
+ MX6SL_PAD_SD1_CMD__GPIO_5_14,
+ MX6SL_PAD_SD1_DAT0__GPIO_5_11,
+ MX6SL_PAD_SD1_DAT1__GPIO_5_8,
+ MX6SL_PAD_SD1_DAT2__GPIO_5_13,
+ MX6SL_PAD_SD1_DAT3__GPIO_5_6,
+ MX6SL_PAD_SD1_DAT4__GPIO_5_12,
+ MX6SL_PAD_SD1_DAT5__GPIO_5_9,
+ MX6SL_PAD_SD1_DAT6__GPIO_5_7,
+ MX6SL_PAD_SD1_DAT7__GPIO_5_10,
+ MX6SL_PAD_SD2_DAT4__GPIO_5_2,
+ MX6SL_PAD_SD2_DAT5__GPIO_4_31,
+// MX6SL_PAD_SD2_DAT6__GPIO_4_29,
+ MX6SL_PAD_SD2_DAT7__GPIO_5_0,
+ MX6SL_PAD_SD2_RST__GPIO_4_27,
+// MX6SL_PAD_UART1_RXD__GPIO_3_16,
+// MX6SL_PAD_UART1_TXD__GPIO_3_17,
+ MX6SL_PAD_WDOG_B__GPIO_3_18,
+/*
+0xffffff80
+0xfffff7ff
+0xfffcffff
+0xdfffffff
+0x003fffff
+
+ 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0
+2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
+3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+4 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+5 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+
+*/
+
+};
+
+#define dump_pad_iomux_val(_pad_name,_iomux_v3cfg,pin_func_str,desc_str) \
+ {\
+ iomux_v3_cfg_t tDSE_PAD_Current;\
+ tDSE_PAD_Current=_iomux_v3cfg;\
+ mxc_iomux_v3_get_pad(&tDSE_PAD_Current);\
+ printk("%s(%d):%s %s(%s)= 0x%llx \n",__func__,__LINE__,\
+ desc_str,#_pad_name,pin_func_str,tDSE_PAD_Current);\
+ printk("\tpadctrl=0x%x\n",(tDSE_PAD_Current>>MUX_PAD_CTRL_SHIFT)&0x43ffff);\
+ printk("\tmode=0x%x\n",(tDSE_PAD_Current>>MUX_MODE_SHIFT)&0x1f);\
+ printk("\tinput=0x%x\n",(tDSE_PAD_Current>>MUX_SEL_INPUT_SHIFT)&0xf);\
+ }
+
+static unsigned int ntx_gpio_dir[5],ntx_gpio_insuspend_dir[5];
+static iomux_v3_cfg_t local_suspend_enter_pads[ARRAY_SIZE(ntx_suspend_enter_pads)];
+static iomux_v3_cfg_t ntx_suspend_exit_pads[ARRAY_SIZE(ntx_suspend_enter_pads)];
+
+extern int fl_level; // If FL is on, value is 0-100. If FL is off, value is 0;
+extern int fl_current; // Unit is 1uA. If FL is off, value is 0;
+extern int slp_state; // 0:Suspend, 1:Hibernate
+extern int idle_current; // Unit is 1uA.
+extern int sus_current; // Unit is 1uA.
+extern int hiber_current; // Unit is 1uA.
+extern bool bat_alert_req_flg; // 0:Normal, 1:Re-synchronize request from system
+void ricoh_suspend_state_sync(void)
+{
+ const int fl_currentA[] = {
+ 620 , 720 , 830 , 990 , 1120 , 1300 , 1460 , 1590 , 1750 , 2020 , // 01 ~ 10
+ 2330 , 2610 , 2900 , 3260 , 3570 , 3900 , 4100 , 4300 , 4510 , 6230 , // 11 ~ 20
+ 6640 , 6840 , 7270 , 7690 , 8100 , 8520 , 8930 , 9350 , 9810 , 10180, // 21 ~ 30
+ 10610, 11010, 11430, 11860, 12310, 12700, 13160, 13560, 13960, 14370, // 31 ~ 40
+ 14730, 15130, 15530, 15930, 16530, 17330, 17920, 18300, 18720, 19120, // 41 ~ 50
+ 19720, 20320, 20930, 21320, 21720, 22330, 22940, 23340, 23760, 24170, // 51 ~ 60
+ 24570, 25180, 25780, 26180, 26790, 27190, 27820, 28220, 28630, 29260, // 61 ~ 70
+ 29860, 30500, 31090, 31700, 32310, 32740, 33140, 33760, 34200, 35230, // 71 ~ 80
+ 35850, 36460, 37910, 39370, 40200, 41050, 41890, 42700, 44400, 45880, // 81 ~ 90
+ 47360, 48860, 50560, 51160, 52000, 53070, 54150, 55440, 56710, 58000, // 91 ~ 100
+ };
+ fl_level = last_FL_duty; // If FL is on, value is 0-100. If FL is off, value is 0;
+ if (last_FL_duty)
+ fl_current = fl_currentA[last_FL_duty-1]; // Unit is 1uA. If FL is off, value is 0;
+ else
+ fl_current = 0;
+ slp_state = gSleep_Mode_Suspend?1:0; // 0:Suspend, 1:Hibernate
+ idle_current = 1000; // Unit is 1uA.
+ sus_current = 1900; // Unit is 1uA.
+ hiber_current = 889; // Unit is 1uA.
+ bat_alert_req_flg = 0; // 0:Normal, 1:Re-synchronize request from system
+}
+
+//#define DUMP_PADS 1
+extern int mxc_epdc_fb_ep1v8_output(int iIsOutput);
+
+void ntx_gpio_suspend (void)
+{
+ g_wakeup_by_alarm = 0;
+
+
+ led_blue(0);
+ led_green(0);
+
+ gpiofn_suspend();
+ if (gSleep_Mode_Suspend) {
+
+ ntx_gpio_insuspend_dir[0]=0xffffff80;
+ ntx_gpio_insuspend_dir[1]=0xfffff7ff;
+ ntx_gpio_insuspend_dir[2]=0xfffcffff;
+ ntx_gpio_insuspend_dir[3]=0xdfffffff;
+ ntx_gpio_insuspend_dir[4]=0x003fffff;
+
+
+ if(7==gptHWCFG->m_val.bDisplayCtrl) {
+ tps65185_ONOFF(0);
+ }
+ else if(8==gptHWCFG->m_val.bDisplayCtrl) {
+ fp9928_ONOFF(0);
+ }
+ //mxc_epdc_fb_ep1v8_output(0);
+ //gpio_direction_output (GPIO_EP_3V3_ON, 0);
+ //gpio_direction_output (MX6SL_EP_PWRALL, 0);
+
+
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C1_SCL__GPIO_3_12);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C1_SDA__GPIO_3_13);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C2_SCL__GPIO_3_14);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C2_SDA__GPIO_3_15);
+
+ if(3==gptHWCFG->m_val.bTouchType || 4==gptHWCFG->m_val.bTouchType) {
+ if(0x03!=gptHWCFG->m_val.bUIConfig) {
+ // turn off ir touch power.
+ gpio_direction_output (gMX6SL_IR_TOUCH_INT, 0);
+
+ gpio_direction_output (gMX6SL_IR_TOUCH_RST, 0);
+ gpio_direction_output (GPIO_IR_3V3_ON, 0);
+ }
+ }
+
+ }
+
+ gUart_ucr1 = __raw_readl(ioremap(MX6SL_UART1_BASE_ADDR, SZ_4K)+0x80);
+ __raw_writel(0, ioremap(MX6SL_UART1_BASE_ADDR, SZ_4K)+0x80);
+
+ if (gSleep_Mode_Suspend) {
+ iomux_v3_cfg_t *p = local_suspend_enter_pads;
+ int i;
+ void __iomem *base;
+ unsigned long dwDisableBit ;
+
+ /* Set PADCTRL to 0 for all IOMUX. */
+ for (i = 0; i < ARRAY_SIZE(ntx_suspend_enter_pads); i++) {
+ *p = ntx_suspend_exit_pads[i] = ntx_suspend_enter_pads[i];
+
+ if(1==gptHWCFG->m_val.bPMIC) {
+ // pads for Ricoh PMIC .
+ // I2C3_SCL,I2C3_SDA,CHG,BAT_LOW_INT,PMU_INT
+ if( ((*p)==(MX6SL_PAD_REF_CLK_24M__GPIO_3_21)) ||
+ ((*p)==(MX6SL_PAD_REF_CLK_32K__GPIO_3_22)) ||
+ ((*p)==(MX6SL_PAD_SD1_CLK__GPIO_5_15)) ||
+ ((*p)==(MX6SL_PAD_KEY_COL2__GPIO_3_28)) ||
+ ((*p)==(MX6SL_PAD_SD1_DAT0__GPIO_5_11)) )
+ {
+ continue ;
+ }
+ }
+
+ if( (*p) == (MX6SL_PAD_SD3_CLK__GPIO_5_18) ||
+ (*p) == (MX6SL_PAD_SD3_CMD__GPIO_5_21) ||
+ (*p) == (MX6SL_PAD_SD3_DAT0__GPIO_5_19) ||
+ (*p) == (MX6SL_PAD_SD3_DAT1__GPIO_5_20) ||
+ (*p) == (MX6SL_PAD_SD3_DAT2__GPIO_5_16) ||
+ (*p) == (MX6SL_PAD_SD3_DAT3__GPIO_5_17) )
+ {
+ *p &= ~MUX_PAD_CTRL_MASK;
+ /* Enable the Pull down and the keeper
+ * Set the drive strength to 0.
+ */
+ *p |= ((u64)0x3000 << MUX_PAD_CTRL_SHIFT);
+ }
+ else if((*p) == (MX6SL_PAD_FEC_MDIO__GPIO_4_20 )||
+ (*p) == (MX6SL_PAD_FEC_TX_CLK__GPIO_4_21)||
+ (*p) == (MX6SL_PAD_FEC_RX_ER__GPIO_4_19 )||
+ (*p) == (MX6SL_PAD_FEC_CRS_DV__GPIO_4_25)||
+ (*p) == (MX6SL_PAD_FEC_RXD1__GPIO_4_18 )||
+ (*p) == (MX6SL_PAD_FEC_TXD0__GPIO_4_24 )||
+ (*p) == (MX6SL_PAD_FEC_MDC__GPIO_4_23 )||
+ (*p) == (MX6SL_PAD_FEC_RXD0__GPIO_4_17 )||
+ (*p) == (MX6SL_PAD_FEC_TX_EN__GPIO_4_22 )||
+ (*p) == (MX6SL_PAD_FEC_TXD1__GPIO_4_16 )||
+ (*p) == (MX6SL_PAD_FEC_REF_CLK__GPIO_4_26))
+ {
+ // EMMC PADS
+#if 1
+ if( 2==gptHWCFG->m_val.bIFlash )
+#else
+ if (37==gptHWCFG->m_val.bPCB /* E60QBX */||
+/* >=E60Q30A10 */((36==gptHWCFG->m_val.bPCB) && gptHWCFG->m_val.bPCB_REV>=0x10) ||
+ 40==gptHWCFG->m_val.bPCB /* E60Q5X */ )
+#endif
+ {
+ *p &= ~MUX_PAD_CTRL_MASK;
+ /* Enable the Pull down and the keeper
+ * Set the drive strength to 0.
+ */
+ *p |= ((u64)0x3000 << MUX_PAD_CTRL_SHIFT);
+ }
+ }
+ else if((*p) == (MX6SL_PAD_KEY_ROW5__GPIO_4_3) &&
+ (((36==gptHWCFG->m_val.bPCB) && gptHWCFG->m_val.bPCB_REV>=0x10) ||
+ (40==gptHWCFG->m_val.bPCB)||(47==gptHWCFG->m_val.bPCB)||(49==gptHWCFG->m_val.bPCB)))
+ {
+ // E60Q3X revA10 , E60Q5X , ED0Q0X , E60QDX
+ // GPIO 4_3 for EP_3V3_ON .
+ }
+ else if((*p) == (MX6SL_PAD_KEY_ROW3__GPIO_3_31) && (giISD_3V3_ON_Ctrl!=-1) )
+ {
+ //only >=E60Q30A10 can turn off ISD_3V3
+
+ gpio_direction_output (GPIO_ISD_3V3_ON, giISD_3V3_ON_Ctrl?0:1);
+ }
+ else if( (*p) == (MX6SL_PAD_KEY_ROW4__GPIO_4_1) ||
+ (*p) == (MX6SL_PAD_KEY_ROW5__GPIO_4_3) ||
+ (*p) == (MX6SL_PAD_EPDC_SDCE2__GPIO_1_29) ) {
+ // pull down
+ *p &= ~MUX_PAD_CTRL_MASK;
+ *p |= ((u64)0x30b0 << MUX_PAD_CTRL_SHIFT);
+ }
+/* else if(
+ (*p) == MX6SL_PAD_EPDC_BDR0__GPIO_2_5 ||
+ (*p) == MX6SL_PAD_EPDC_BDR1__GPIO_2_6 ||
+ (*p) == MX6SL_PAD_EPDC_D0__GPIO_1_7 ||
+ (*p) == MX6SL_PAD_EPDC_D1__GPIO_1_8 ||
+ (*p) == MX6SL_PAD_EPDC_D10__GPIO_1_17 ||
+ (*p) == MX6SL_PAD_EPDC_D11__GPIO_1_18 ||
+ (*p) == MX6SL_PAD_EPDC_D12__GPIO_1_19 ||
+ (*p) == MX6SL_PAD_EPDC_D13__GPIO_1_20 ||
+ (*p) == MX6SL_PAD_EPDC_D14__GPIO_1_21 ||
+ (*p) == MX6SL_PAD_EPDC_D15__GPIO_1_22 ||
+ (*p) == MX6SL_PAD_EPDC_D2__GPIO_1_9 ||
+ (*p) == MX6SL_PAD_EPDC_D3__GPIO_1_10 ||
+ (*p) == MX6SL_PAD_EPDC_D4__GPIO_1_11 ||
+ (*p) == MX6SL_PAD_EPDC_D5__GPIO_1_12 ||
+ (*p) == MX6SL_PAD_EPDC_D6__GPIO_1_13 ||
+ (*p) == MX6SL_PAD_EPDC_D7__GPIO_1_14 ||
+ (*p) == MX6SL_PAD_EPDC_D8__GPIO_1_15 ||
+ (*p) == MX6SL_PAD_EPDC_D9__GPIO_1_16 ||
+ (*p) == MX6SL_PAD_EPDC_GDCLK__GPIO_1_31 ||
+ (*p) == MX6SL_PAD_EPDC_GDOE__GPIO_2_0 ||
+ (*p) == MX6SL_PAD_EPDC_GDRL__GPIO_2_1 ||
+ (*p) == MX6SL_PAD_EPDC_GDSP__GPIO_2_2 ||
+ (*p) == MX6SL_PAD_EPDC_PWRCOM__GPIO_2_11 ||
+ (*p) == MX6SL_PAD_EPDC_PWRCTRL0__GPIO_2_7 ||
+ (*p) == MX6SL_PAD_EPDC_PWRCTRL1__GPIO_2_8 ||
+ (*p) == MX6SL_PAD_EPDC_PWRCTRL2__GPIO_2_9 ||
+ (*p) == MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10 ||
+ (*p) == MX6SL_PAD_EPDC_PWRINT__GPIO_2_12 ||
+ (*p) == MX6SL_PAD_EPDC_PWRSTAT__GPIO_2_13 ||
+ (*p) == MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14 ||
+ (*p) == MX6SL_PAD_EPDC_SDCE0__GPIO_1_27 ||
+ (*p) == MX6SL_PAD_EPDC_SDCE1__GPIO_1_28 ||
+ (*p) == MX6SL_PAD_EPDC_SDCE2__GPIO_1_29 ||
+ (*p) == MX6SL_PAD_EPDC_SDCE3__GPIO_1_30 ||
+ (*p) == MX6SL_PAD_EPDC_SDCLK__GPIO_1_23 ||
+ (*p) == MX6SL_PAD_EPDC_SDLE__GPIO_1_24 ||
+ (*p) == MX6SL_PAD_EPDC_SDOE__GPIO_1_25 ||
+ (*p) == MX6SL_PAD_EPDC_SDSHR__GPIO_1_26 ||
+ (*p) == MX6SL_PAD_EPDC_VCOM0__GPIO_2_3 ||
+ (*p) == MX6SL_PAD_EPDC_VCOM1__GPIO_2_4
+ ) {
+ *p &= ~MUX_PAD_CTRL_MASK;
+ *p |= ((u64)0x3000 << MUX_PAD_CTRL_SHIFT);
+ }
+*/
+ else if ( (*p) == MX6SL_PAD_SD2_DAT6__GPIO_4_29 ||
+ (*p) == MX6SL_PAD_SD1_DAT6__GPIO_5_7 ||
+ ((1==gptHWCFG->m_val.bLed)&&((*p)==MX6SL_PAD_SD1_DAT2__GPIO_5_13)) )
+ {
+ // pull up
+ if((*p) == MX6SL_PAD_SD1_DAT6__GPIO_5_7&&(36==gptHWCFG->m_val.bPCB || 40==gptHWCFG->m_val.bPCB
+ || 49==gptHWCFG->m_val.bPCB))
+ {
+ // E60Q3X/E60Q5X/E60QDX
+ // skip set pad of GP5_7 for Green LED .
+ }
+ else {
+ *p &= ~MUX_PAD_CTRL_MASK;
+ *p |= ((u64)0x0001b0b1 << MUX_PAD_CTRL_SHIFT);
+ }
+ }
+ else if( (*p) == MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10) {
+
+ if(0==giFL_ON) {
+ // open drain
+ *p &= ~MUX_PAD_CTRL_MASK;
+ *p |= ((u64)0x000108b0 << MUX_PAD_CTRL_SHIFT);
+ }
+ }
+ else {
+ if((36==gptHWCFG->m_val.bPCB||40==gptHWCFG->m_val.bPCB||49==gptHWCFG->m_val.bPCB) &&
+ ((*p) == (MX6SL_PAD_SD1_DAT7__GPIO_5_10 )) )
+ {
+ // E60Q3X ,E60Q5X, E60QDX
+ // skip setting home led to floating state .
+ }
+ else {
+ // floating
+ *p &= ~MUX_PAD_CTRL_MASK;
+ *p |= ((u64)0x000110b0 << MUX_PAD_CTRL_SHIFT);
+ }
+ }
+ p++;
+ }
+
+ // Direction control .
+ mxc_iomux_v3_get_multiple_pads(ntx_suspend_exit_pads,
+ ARRAY_SIZE(ntx_suspend_exit_pads));
+
+#ifdef DUMP_PADS//[
+ dump_pad_iomux_val(MX6SL_PAD_REF_CLK_24M,MX6SL_PAD_REF_CLK_24M__GPIO_3_21,
+ "I2C3_SCL","before hibernation");
+ dump_pad_iomux_val(MX6SL_PAD_REF_CLK_32K,MX6SL_PAD_REF_CLK_32K__GPIO_3_22,
+ "I2C3_SDA","before hibernation");
+#endif//] DUMP_PADS
+ mxc_iomux_v3_setup_multiple_pads(local_suspend_enter_pads,
+ ARRAY_SIZE(local_suspend_enter_pads));
+
+#ifdef DUMP_PADS//[
+ dump_pad_iomux_val(MX6SL_PAD_REF_CLK_24M,MX6SL_PAD_REF_CLK_24M__GPIO_3_21,
+ "I2C3_SCL","in hibernation");
+ dump_pad_iomux_val(MX6SL_PAD_REF_CLK_32K,MX6SL_PAD_REF_CLK_32K__GPIO_3_22,
+ "I2C3_SDA","in hibernation");
+#endif//]DUMP_PADS
+
+ if(giFL_ON) {
+ // set as output .
+ dwDisableBit = (unsigned long)(1<<10);
+ ntx_gpio_insuspend_dir[1] &= ~dwDisableBit; //GP2_10
+ }
+
+ if( (36==gptHWCFG->m_val.bPCB && gptHWCFG->m_val.bPCB_REV>=0x10) ||
+ 40==gptHWCFG->m_val.bPCB || 49==gptHWCFG->m_val.bPCB)
+ {
+ // >=E60Q30A1 , E60Q5X , E60QDX
+ dwDisableBit = (unsigned long)(1<<3);
+ ntx_gpio_insuspend_dir[3] &= ~dwDisableBit; //GP4_3 for EP_3V3_ON output
+ dwDisableBit = (unsigned long)(1<<7);
+ ntx_gpio_insuspend_dir[4] &= ~dwDisableBit; //GP5_7 for POWER_LED output
+ dwDisableBit = (unsigned long)(1<<10);
+ ntx_gpio_insuspend_dir[4] &= ~dwDisableBit; //GP5_10 for HOME_LED output
+ }
+ else if(47==gptHWCFG->m_val.bPCB)
+ {
+ // ED0Q0X .
+ dwDisableBit = (unsigned long)(1<<3);
+ ntx_gpio_insuspend_dir[3] &= ~dwDisableBit; //GP4_3 for EP_3V3/1V8_ON output
+ dwDisableBit = (unsigned long)(1<<7);
+ ntx_gpio_insuspend_dir[4] &= ~dwDisableBit; //GP5_7 for (green)ACTION_LED output
+ }
+
+ if(-1!=giISD_3V3_ON_Ctrl) {
+ dwDisableBit = (unsigned long)(1<<31);
+ ntx_gpio_insuspend_dir[2] &= ~dwDisableBit; //GP3_31 for ISD_3V3_ON output
+ }
+
+
+ base = IO_ADDRESS(GPIO1_BASE_ADDR);
+ ntx_gpio_dir[0] = __raw_readl(base+4);
+ __raw_writel( ntx_gpio_dir[0]&(~ntx_gpio_insuspend_dir[0]), base+4);
+
+ base = IO_ADDRESS(GPIO2_BASE_ADDR);
+ ntx_gpio_dir[1] = __raw_readl(base+4);
+ __raw_writel( ntx_gpio_dir[1]&(~ntx_gpio_insuspend_dir[1]), base+4);
+
+ base = IO_ADDRESS(GPIO3_BASE_ADDR);
+ ntx_gpio_dir[2] = __raw_readl(base+4);
+ __raw_writel( ntx_gpio_dir[2]&(~ntx_gpio_insuspend_dir[2]), base+4);
+
+ base = IO_ADDRESS(GPIO4_BASE_ADDR);
+ ntx_gpio_dir[3] = __raw_readl(base+4);
+ __raw_writel( ntx_gpio_dir[3]&(~ntx_gpio_insuspend_dir[3]), base+4);
+
+ base = IO_ADDRESS(GPIO5_BASE_ADDR);
+ ntx_gpio_dir[4] = __raw_readl(base+4);
+ __raw_writel( ntx_gpio_dir[4]&(~ntx_gpio_insuspend_dir[4]), base+4);
+ }
+}
+
+void ntx_gpio_resume (void)
+{
+ if (gSleep_Mode_Suspend) {
+ void __iomem *base;
+
+ base = IO_ADDRESS(GPIO1_BASE_ADDR);
+ __raw_writel( ntx_gpio_dir[0], base+4);
+
+ base = IO_ADDRESS(GPIO2_BASE_ADDR);
+ __raw_writel( ntx_gpio_dir[1], base+4);
+
+ base = IO_ADDRESS(GPIO3_BASE_ADDR);
+ __raw_writel( ntx_gpio_dir[2], base+4);
+
+ base = IO_ADDRESS(GPIO4_BASE_ADDR);
+ __raw_writel( ntx_gpio_dir[3], base+4);
+
+ base = IO_ADDRESS(GPIO5_BASE_ADDR);
+ __raw_writel( ntx_gpio_dir[4], base+4);
+
+ mxc_iomux_v3_setup_multiple_pads(ntx_suspend_exit_pads,
+ ARRAY_SIZE(ntx_suspend_exit_pads));
+
+#ifdef DUMP_PADS//[
+ dump_pad_iomux_val(MX6SL_PAD_REF_CLK_24M,MX6SL_PAD_REF_CLK_24M__GPIO_3_21,
+ "I2C3_SCL","exit hibernation");
+ dump_pad_iomux_val(MX6SL_PAD_REF_CLK_32K,MX6SL_PAD_REF_CLK_32K__GPIO_3_22,
+ "I2C3_SDA","exit hibernation");
+#endif//] DUMP_PADS
+
+ }
+ __raw_writel(gUart_ucr1, ioremap(MX6SL_UART1_BASE_ADDR, SZ_4K)+0x80);
+ if (gSleep_Mode_Suspend) {
+
+ if(-1!=giISD_3V3_ON_Ctrl) {
+ gpio_direction_output (GPIO_ISD_3V3_ON,giISD_3V3_ON_Ctrl?1:0);
+ }
+
+ if(1==gptHWCFG->m_val.bLed) {
+ // Blue Led .
+ // ON_LED#
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_SD1_DAT2__GPIO_5_13_PULLHIGH);
+ }
+
+
+ if((3==gptHWCFG->m_val.bTouchType || 4==gptHWCFG->m_val.bTouchType) && 0x03==gptHWCFG->m_val.bUIConfig) {
+ // IR Touch Type & MP/RD Mode for IR tool .
+ // reset ir touch
+ gpio_direction_output (gMX6SL_IR_TOUCH_RST, 0);
+ mdelay (20);
+ gpio_direction_output (gMX6SL_IR_TOUCH_RST, 1);
+ }
+ else {
+ // turn on ir touch power.
+ gpio_direction_output (GPIO_IR_3V3_ON, 1);
+ if (37 != gptHWCFG->m_val.bPCB) {
+ // E60QB0 .
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C1_SCL__I2C1_SCL);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C1_SDA__I2C1_SDA);
+ }
+ gpio_direction_input (gMX6SL_IR_TOUCH_INT);
+ mdelay (20);
+ gpio_direction_output (gMX6SL_IR_TOUCH_RST, 1);
+ }
+
+ gpio_free(IMX_GPIO_NR(3, 14));
+ gpio_free(IMX_GPIO_NR(3, 15));
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C2_SCL__I2C2_SCL);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C2_SDA__I2C2_SDA);
+
+ //mxc_epdc_fb_ep1v8_output(1);
+ //gpio_direction_output (GPIO_EP_3V3_ON, 1);
+ //mdelay (5);
+ if(7==gptHWCFG->m_val.bDisplayCtrl) {
+ tps65185_ONOFF(1);
+ }
+ else if(8==gptHWCFG->m_val.bDisplayCtrl) {
+ fp9928_ONOFF(1);
+ }
+ //gpio_direction_output (MX6SL_EP_PWRALL, 1);
+ }
+
+ gpiofn_resume();
+
+ if(36==gptHWCFG->m_val.bPCB || 40==gptHWCFG->m_val.bPCB || 49==gptHWCFG->m_val.bPCB) {
+ // E60Q3X/E60Q5X
+ if(mxc_usb_plug_getstatus()) {
+ led_red(1);
+ }
+ else {
+ led_red(0);
+ }
+ }
+
+#ifdef CONFIG_ANDROID //[
+#else //][!CONFIG_ANDROID
+ g_power_key_pressed = power_key_status(); // POWER key
+ if(0==gptHWCFG->m_val.bUIStyle) {
+ // Ebrmain .
+ if (g_power_key_pressed)
+ mod_timer(&power_key_timer, jiffies + 1);
+ }
+
+ if (LED_conitnuous)
+ wake_up_interruptible(&LED_freeze_WaitQueue);
+ else {
+ ntx_led_blink (3, red_led_period);
+ ntx_led_blink (4, green_led_period);
+ ntx_led_blink (5, blue_led_period);
+ }
+#endif //]CONFIG_ANDROID
+}
+
+
+#include <linux/regulator/consumer.h>
+void ntx_gpio_touch_reset (void)
+{
+ struct regulator *reg_TP3V3 = NULL;
+
+ printk ("[%s-%d] reset touch.\n",__func__,__LINE__);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C1_SCL__GPIO_3_12);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C1_SDA__GPIO_3_13);
+
+ gpio_request(IMX_GPIO_NR(3, 12),"i2c1_scl");
+ gpio_request(IMX_GPIO_NR(3, 13),"i2c1_sda");
+ gpio_direction_output (IMX_GPIO_NR(3, 12), 0);
+ gpio_direction_output (IMX_GPIO_NR(3, 13), 0);
+ // turn off ir touch power.
+ gpio_direction_output (gMX6SL_IR_TOUCH_INT, 0);
+ gpio_direction_output(gMX6SL_IR_TOUCH_RST, 0);
+ if (1==gptHWCFG->m_val.bPMIC) {
+ reg_TP3V3 = regulator_get(NULL,"vdd_ir_3v3");
+ if (IS_ERR(reg_TP3V3))
+ printk ("[%s-%d] regulator_get vdd_ir_3v3 returned NULL!!\n",__func__,__LINE__);
+ else {
+ regulator_force_disable (reg_TP3V3);
+ }
+ }
+ else
+ gpio_direction_output (GPIO_IR_3V3_ON, 0);
+ msleep (200);
+ // turn on ir touch power.
+ if (1==gptHWCFG->m_val.bPMIC) {
+ if (IS_ERR(reg_TP3V3))
+ printk ("[%s-%d] regulator_get vdd_ir_3v3 returned NULL!!\n",__func__,__LINE__);
+ else {
+ regulator_enable (reg_TP3V3);
+ regulator_put (reg_TP3V3);
+ }
+ }
+ else
+ gpio_direction_output (GPIO_IR_3V3_ON, 1);
+ gpio_free(IMX_GPIO_NR(3, 12));
+ gpio_free(IMX_GPIO_NR(3, 13));
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C1_SCL__I2C1_SCL);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_I2C1_SDA__I2C1_SDA);
+ gpio_direction_input (gMX6SL_IR_TOUCH_INT);
+ mdelay (20);
+ gpio_direction_output (gMX6SL_IR_TOUCH_RST, 1);
+}
+
+void ntx_msp430_i2c_force_release (void)
+{
+ int retryCnt=20;
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_REF_CLK_24M__GPIO_3_21);
+ gpio_request(MX6SL_I2C3_SDA, "i2c3_sda");
+ gpio_direction_input (MX6SL_I2C3_SDA);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_REF_CLK_32K__GPIO_3_22);
+ gpio_request(MX6SL_I2C3_SCL, "i2c3_scl");
+ gpio_direction_output (MX6SL_I2C3_SCL, 1);
+ // send clock out until i2c SDA released.
+ while (retryCnt-- && !gpio_get_value (MX6SL_I2C3_SDA)) {
+ gpio_set_value (MX6SL_I2C3_SCL,1);
+ udelay (5);
+ gpio_set_value (MX6SL_I2C3_SCL,0);
+ schedule_timeout (1);
+// udelay (5);
+ }
+ // simulate i2c stop signal
+ gpio_direction_output (MX6SL_I2C3_SDA,0);
+ gpio_free(MX6SL_I2C3_SCL);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_REF_CLK_24M__I2C3_SCL);
+ udelay (2);
+ gpio_free(MX6SL_I2C3_SDA);
+ mxc_iomux_v3_setup_pad(MX6SL_PAD_REF_CLK_32K__I2C3_SDA);
+}
+
+
+void ntx_machine_restart(char mode, const char *cmd)
+{
+ if (cmd && ('\0' != *cmd)) {
+ printk("%s mode=%c,cmd=%s\n",__FUNCTION__,mode,cmd);
+ arm_machine_restart (mode, cmd);
+ }
+ else {
+ printk ("[%s-%d] do hardware reset...\n",__func__,__LINE__);
+ ntx_system_reset(0);
+ }
+}
+
+void ntx_machine_poweroff(void)
+{
+ ntx_system_poweroff(__FUNCTION__);
+}
+
+static int __init initDriver(void)
+{
+ int ret;
+
+ ret = misc_register(&driverDevice);
+ if (ret < 0) {
+ printk("pvi_io: can't get major number\n");
+ return ret;
+ }
+
+ gpio_initials();
+
+ //start a kernel thread;
+ ret = kernel_thread(LED_Thread,NULL,CLONE_KERNEL);
+ if(ret < 0){
+ printk("LED thread creat error\n");
+ }
+
+ ////////////////////////
+ green_led_timer.function = green_led_blink_func;
+ init_timer(&green_led_timer);
+ blue_led_timer.function = blue_led_blink_func;
+ init_timer(&blue_led_timer);
+ red_led_timer.function = red_led_blink_func;
+ init_timer(&red_led_timer);
+
+ pm_power_off = ntx_machine_poweroff;
+ arm_pm_restart = ntx_machine_restart;
+
+ return 0;
+}
+static void __exit exitDriver(void) {
+ misc_deregister(&driverDevice);
+}
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Joe");
+MODULE_VERSION("2007-9-20");
+MODULE_DESCRIPTION ("PVI_IO driver");
+module_init(initDriver);
+module_exit(exitDriver);
diff --git a/arch/arm/mach-mx6/mx6sl_ntx_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_ntx_pmic_pfuze100.c
new file mode 100755
index 00000000..88f2c9c7
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6sl_ntx_pmic_pfuze100.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2012 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/pfuze.h>
+#include <mach/irqs.h>
+
+/*
+ * Convenience conversion.
+ * Here atm, maybe there is somewhere better for this.
+ */
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+#define PFUZE100_I2C_DEVICE_NAME "pfuze100"
+/* 7-bit I2C bus slave address */
+#define PFUZE100_I2C_ADDR (0x08)
+ /*SWBST*/
+#define PFUZE100_SW1ASTANDBY 33
+#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x19) /* 925mv */
+#define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0)
+#define PFUZE100_SW1BSTANDBY 40
+#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x19) /* 925mv */
+#define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0)
+#define PFUZE100_SW1CSTANDBY 47
+#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x19) /* 925mv */
+#define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0)
+#define PFUZE100_SW2STANDBY 54
+#define PFUZE100_SW2STANDBY_STBY_VAL 0x0
+#define PFUZE100_SW2STANDBY_STBY_M (0x3f<<0)
+#define PFUZE100_SW3ASTANDBY 61
+#define PFUZE100_SW3ASTANDBY_STBY_VAL 0x0
+#define PFUZE100_SW3ASTANDBY_STBY_M (0x3f<<0)
+#define PFUZE100_SW3BSTANDBY 68
+#define PFUZE100_SW3BSTANDBY_STBY_VAL 0x0
+#define PFUZE100_SW3BSTANDBY_STBY_M (0x3f<<0)
+#define PFUZE100_SW4STANDBY 75
+#define PFUZE100_SW4STANDBY_STBY_VAL 0
+#define PFUZE100_SW4STANDBY_STBY_M (0x3f<<0)
+#define PFUZE100_SWBSTCON1 102
+#define PFUZE100_SWBSTCON1_SWBSTMOD_VAL (0x1<<2)
+#define PFUZE100_SWBSTCON1_SWBSTMOD_M (0x3<<2)
+#define PFUZE100_SW1ACON 36
+#define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1ACON_SPEED_M (0x3<<6)
+#define PFUZE100_SW1CCON 49
+#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */
+#define PFUZE100_SW1CCON_SPEED_M (0x3<<6)
+
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "VDDCORE",
+ }
+};
+static struct regulator_consumer_supply sw1c_consumers[] = {
+ {
+ .supply = "VDDSOC",
+ },
+};
+#endif
+
+static struct regulator_consumer_supply sw2_consumers[] = {
+ {
+ .supply = "MICVDD",
+ .dev_name = "1-001a",
+ }
+};
+static struct regulator_consumer_supply sw4_consumers[] = {
+ {
+ .supply = "AUD_1V8",
+ }
+};
+static struct regulator_consumer_supply swbst_consumers[] = {
+ {
+ .supply = "SWBST_5V",
+ }
+};
+static struct regulator_consumer_supply vgen1_consumers[] = {
+ {
+ .supply = "VGEN1_1V5",
+ }
+};
+static struct regulator_consumer_supply vgen2_consumers[] = {
+ {
+ .supply = "VGEN2_1V5",
+ }
+};
+static struct regulator_consumer_supply vgen3_consumers[] = {
+ {
+ .supply = "AVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "DCVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "CPVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "PLLVDD",
+ .dev_name = "1-001a",
+ },
+ {
+ .supply = "DBVDD",
+ .dev_name = "1-001a",
+ }
+};
+static struct regulator_consumer_supply vgen4_consumers[] = {
+ {
+ .supply = "VGEN4_1V8",
+ }
+};
+static struct regulator_consumer_supply vgen5_consumers[] = {
+ {
+ .supply = "VGEN5_2V8",
+ }
+};
+static struct regulator_consumer_supply vgen6_consumers[] = {
+ {
+ .supply = "VGEN6_2V8",
+ }
+};
+
+static struct regulator_init_data sw1a_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1A",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 650000,
+ .max_uV = 1437500,
+#else
+ .min_uV = 300000,
+ .max_uV = 1875000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .boot_on = 1,
+ .always_on = 1,
+ },
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+#ifndef CONFIG_MACH_MX6SL_NTX
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+#endif
+#endif
+};
+
+static struct regulator_init_data sw1b_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1B",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw1c_init = {
+ .constraints = {
+ .name = "PFUZE100_SW1C",
+ .min_uV = 300000,
+ .max_uV = 1875000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+#ifdef CONFIG_MX6_INTER_LDO_BYPASS
+#ifndef CONFIG_MACH_MX6SL_NTX
+ .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers),
+ .consumer_supplies = sw1c_consumers,
+#endif
+#endif
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "PFUZE100_SW2",
+#if PFUZE100_SW2_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw2_consumers),
+ .consumer_supplies = sw2_consumers,
+};
+
+static struct regulator_init_data sw3a_init = {
+ .constraints = {
+ .name = "PFUZE100_SW3A",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw3b_init = {
+ .constraints = {
+ .name = "PFUZE100_SW3B",
+#if PFUZE100_SW3_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "PFUZE100_SW4",
+#if PFUZE100_SW4_VOL6
+ .min_uV = 800000,
+ .max_uV = 3950000,
+#else
+ .min_uV = 400000,
+ .max_uV = 1975000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw4_consumers),
+ .consumer_supplies = sw4_consumers,
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "PFUZE100_SWBST",
+ .min_uV = 5000000,
+ .max_uV = 5150000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(swbst_consumers),
+ .consumer_supplies = swbst_consumers,
+};
+
+static struct regulator_init_data vsnvs_init = {
+ .constraints = {
+ .name = "PFUZE100_VSNVS",
+ .min_uV = 1200000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vrefddr_init = {
+ .constraints = {
+ .name = "PFUZE100_VREFDDR",
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN1",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen1_consumers),
+ .consumer_supplies = vgen1_consumers,
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN2",
+#ifdef PFUZE100_FIRST_VERSION
+ .min_uV = 1200000,
+ .max_uV = 1550000,
+#else
+ .min_uV = 800000,
+ .max_uV = 1550000,
+#endif
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen2_consumers),
+ .consumer_supplies = vgen2_consumers,
+
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN3",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 0,
+ .boot_on = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen3_consumers),
+ .consumer_supplies = vgen3_consumers,
+};
+
+static struct regulator_init_data vgen4_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN4",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen4_consumers),
+ .consumer_supplies = vgen4_consumers,
+};
+
+static struct regulator_init_data vgen5_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN5",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen5_consumers),
+ .consumer_supplies = vgen5_consumers,
+};
+
+static struct regulator_init_data vgen6_init = {
+ .constraints = {
+ .name = "PFUZE100_VGEN6",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = 0,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen6_consumers),
+ .consumer_supplies = vgen6_consumers,
+};
+
+static int pfuze100_init(struct mc_pfuze *pfuze)
+{
+ int ret;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ASTANDBY,
+ PFUZE100_SW1ASTANDBY_STBY_M,
+ PFUZE100_SW1ASTANDBY_STBY_VAL);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CSTANDBY,
+ PFUZE100_SW1CSTANDBY_STBY_M,
+ PFUZE100_SW1CSTANDBY_STBY_VAL);
+ if (ret)
+ goto err;
+ /*set SW1AB/SW1CDVSPEED as 25mV step each 4us,quick than 16us before.*/
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON,
+ PFUZE100_SW1ACON_SPEED_M,
+ PFUZE100_SW1ACON_SPEED_VAL);
+ if (ret)
+ goto err;
+ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON,
+ PFUZE100_SW1CCON_SPEED_M,
+ PFUZE100_SW1CCON_SPEED_VAL);
+ if (ret)
+ goto err;
+ return 0;
+err:
+ printk(KERN_ERR "pfuze100 init error!\n");
+ return -1;
+}
+
+static struct pfuze_regulator_init_data mx6q_sabreauto_pfuze100_regulators[] = {
+ {.id = PFUZE100_SW1A, .init_data = &sw1a_init},
+// {.id = PFUZE100_SW1B, .init_data = &sw1b_init},
+ {.id = PFUZE100_SW1C, .init_data = &sw1c_init},
+#if 0
+ {.id = PFUZE100_SW2, .init_data = &sw2_init},
+ {.id = PFUZE100_SW3A, .init_data = &sw3a_init},
+ {.id = PFUZE100_SW3B, .init_data = &sw3b_init},
+ {.id = PFUZE100_SW4, .init_data = &sw4_init},
+ {.id = PFUZE100_SWBST, .init_data = &swbst_init},
+ {.id = PFUZE100_VSNVS, .init_data = &vsnvs_init},
+ {.id = PFUZE100_VREFDDR, .init_data = &vrefddr_init},
+ {.id = PFUZE100_VGEN1, .init_data = &vgen1_init},
+ {.id = PFUZE100_VGEN2, .init_data = &vgen2_init},
+ {.id = PFUZE100_VGEN3, .init_data = &vgen3_init},
+ {.id = PFUZE100_VGEN4, .init_data = &vgen4_init},
+ {.id = PFUZE100_VGEN5, .init_data = &vgen5_init},
+ {.id = PFUZE100_VGEN6, .init_data = &vgen6_init},
+#endif
+};
+
+static struct pfuze_platform_data pfuze100_plat = {
+ .flags = PFUZE_USE_REGULATOR,
+ .num_regulators = ARRAY_SIZE(mx6q_sabreauto_pfuze100_regulators),
+ .regulators = mx6q_sabreauto_pfuze100_regulators,
+ .pfuze_init = pfuze100_init,
+};
+
+static struct i2c_board_info __initdata pfuze100_i2c_device = {
+ I2C_BOARD_INFO(PFUZE100_I2C_DEVICE_NAME, PFUZE100_I2C_ADDR),
+ .irq=0,
+ .platform_data = &pfuze100_plat,
+};
+
+int __init mx6sl_ntx_init_pfuze100(u32 int_gpio)
+{
+ if (int_gpio)
+ pfuze100_i2c_device.irq = gpio_to_irq(int_gpio); /*update INT gpio */
+ return i2c_register_board_info(0, &pfuze100_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx6/mx6sl_wfi.S b/arch/arm/mach-mx6/mx6sl_wfi.S
new file mode 100644
index 00000000..c51fcc77
--- /dev/null
+++ b/arch/arm/mach-mx6/mx6sl_wfi.S
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) 2012-2013 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 <linux/linkage.h>
+#include <mach/hardware.h>
+/*
+ * The code size is limited to 1.5K
+ * as we may need to store this code
+ * along with the suspend and DDR freq change
+ * code within 8K of IRAM.
+ */
+
+#define IRAM_WAIT_SIZE MX6SL_WFI_IRAM_CODE_SIZE
+
+.extern iram_tlb_phys_addr
+.extern mx6sl_wfi_iram_base
+.extern mx6sl_wfi_iram_phys_addr
+
+ .macro sl_ddr_io_save
+
+ ldr r4, [r1, #0x30c] /* DRAM_DQM0 */
+ ldr r5, [r1, #0x310] /* DRAM_DQM1 */
+ ldr r6, [r1, #0x314] /* DRAM_DQM2 */
+ ldr r7, [r1, #0x318] /* DRAM_DQM3 */
+ stmfd r9!, {r4-r7}
+
+ ldr r4, [r1, #0x5c4] /* GPR_B0DS */
+ ldr r5, [r1, #0x5cc] /* GPR_B1DS */
+ ldr r6, [r1, #0x5d4] /* GPR_B2DS */
+ ldr r7, [r1, #0x5d8] /* GPR_B3DS */
+ stmfd r9!, {r4-r7}
+
+ ldr r4, [r1, #0x300] /* DRAM_CAS */
+ ldr r5, [r1, #0x31c] /* DRAM_RAS */
+ ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */
+ ldr r7, [r1, #0x5ac] /* GPR_ADDS*/
+ stmfd r9!, {r4-r7}
+
+ ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */
+ ldr r5, [r1, #0x5c0] /* DDRMODE */
+ ldr r6, [r1, #0x33c] /* DRAM_SODT0*/
+ ldr r7, [r1, #0x340] /* DRAM_SODT1*/
+ stmfd r9!, {r4-r7}
+
+ ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */
+ ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */
+ ldr r6, [r1, #0x320] /* DRAM_RESET */
+ stmfd r9!, {r4-r6}
+
+ .endm
+
+ .macro sl_ddr_io_restore
+
+ /* r9 points to IRAM stack.
+ * r1 points to IOMUX base address.
+ * r8 points to MMDC base address.
+ */
+ ldmea r9!, {r4-r7}
+ str r4, [r1, #0x30c] /* DRAM_DQM0 */
+ str r5, [r1, #0x310] /* DRAM_DQM1 */
+ str r6, [r1, #0x314] /* DRAM_DQM2 */
+ str r7, [r1, #0x318] /* DRAM_DQM3 */
+
+ ldmea r9!, {r4-r7}
+ str r4, [r1, #0x5c4] /* GPR_B0DS */
+ str r5, [r1, #0x5cc] /* GPR_B1DS */
+ str r6, [r1, #0x5d4] /* GPR_B2DS */
+ str r7, [r1, #0x5d8] /* GPR_B3DS */
+
+ ldmea r9!, {r4-r7}
+ str r4, [r1, #0x300] /* DRAM_CAS */
+ str r5, [r1, #0x31c] /* DRAM_RAS */
+ str r6, [r1, #0x338] /* DRAM_SDCLK_0 */
+ str r7, [r1, #0x5ac] /* GPR_ADDS*/
+
+ ldmea r9!, {r4-r7}
+ str r4, [r1, #0x5b0] /* DDRMODE_CTL */
+ str r5, [r1, #0x5c0] /* DDRMODE */
+ str r6, [r1, #0x33c] /* DRAM_SODT0*/
+ str r7, [r1, #0x340] /* DRAM_SODT1*/
+
+ ldmea r9!, {r4-r6}
+ str r4, [r1, #0x330] /* DRAM_SDCKE0 */
+ str r5, [r1, #0x334] /* DRAM_SDCKE1 */
+ str r6, [r1, #0x320] /* DRAM_RESET */
+
+ /* Need to reset the FIFO to avoid MMDC lockup
+ * caused because of floating/changing the
+ * configuration of many DDR IO pads.
+ */
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =0x83c
+ ldr r6, [r8, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r8, r7]
+fifo_reset1_wait:
+ ldr r6, [r8, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne fifo_reset1_wait
+
+ /* reset FIFO a second time */
+ ldr r6, [r8, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r8, r7]
+fifo_reset2_wait:
+ ldr r6, [r8, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne fifo_reset2_wait
+
+ .endm
+
+ .macro sl_ddr_io_set_lpm
+
+ mov r4, #0
+ str r4, [r1, #0x30c] /* DRAM_DQM0 */
+ str r4, [r1, #0x310] /* DRAM_DQM1 */
+ str r4, [r1, #0x314] /* DRAM_DQM2 */
+ str r4, [r1, #0x318] /* DRAM_DQM3 */
+
+ str r4, [r1, #0x5c4] /* GPR_B0DS */
+ str r4, [r1, #0x5cc] /* GPR_B1DS */
+ str r4, [r1, #0x5d4] /* GPR_B2DS */
+ str r4, [r1, #0x5d8] /* GPR_B3DS */
+
+ str r4, [r1, #0x300] /* DRAM_CAS */
+ str r4, [r1, #0x31c] /* DRAM_RAS */
+ str r4, [r1, #0x338] /* DRAM_SDCLK_0 */
+ str r4, [r1, #0x5ac] /* GPR_ADDS*/
+
+ str r4, [r1, #0x5b0] /* DDRMODE_CTL */
+ str r4, [r1, #0x5c0] /* DDRMODE */
+ str r4, [r1, #0x33c] /* DRAM_SODT0*/
+ str r4, [r1, #0x340] /* DRAM_SODT1*/
+
+ mov r4, #0x80000
+ str r4, [r1, #0x320] /* DRAM_RESET */
+ mov r4, #0x1000
+ str r4, [r1, #0x330] /* DRAM_SDCKE0 */
+ str r4, [r1, #0x334] /* DRAM_SDCKE1 */
+
+ .endm
+
+ .align 3
+/*
+ * mx6sl_wait
+ *
+ * Idle the processor (eg, wait for interrupt).
+ * Make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ * r0 : arm_podf before WFI is entered
+ * r1: WFI IRAMcode base address.
+ */
+ENTRY(mx6sl_wait)
+
+ push {r4-r12}
+
+mx6sl_lpm_wfi:
+ mov r11, r2
+
+ /* Get the IRAM data storage address. */
+ mov r10, r1
+ mov r9, r1 /* get suspend_iram_base */
+ add r9, r9, #IRAM_WAIT_SIZE /* 1.5K */
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Disable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+
+ /*
+ * Sync L2 and then disable it.
+ */
+ dsb
+ ldr r1, =L2_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ ldr r6, =0x0
+ str r6, [r1, #0x730]
+ /* Disable L2. */
+ str r6, [r1, #0x100]
+ dsb
+ isb
+
+ ldr r1, =MX6Q_IOMUXC_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Save the DDR IO state. */
+ sl_ddr_io_save
+
+ ldr r3, =ANATOP_BASE_ADDR
+ add r3, r3, #PERIPBASE_VIRT
+ ldr r2, =CCM_BASE_ADDR
+ add r2, r2, #PERIPBASE_VIRT
+ ldr r8, =MMDC_P0_BASE_ADDR
+ add r8, r8, #PERIPBASE_VIRT
+
+ /* Disable Automatic power savings. */
+ ldr r6, [r8, #0x404]
+ orr r6, r6, #0x01
+ str r6, [r8, #0x404]
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r6, [r8, #0x404]
+ orr r6, r6, #0x200000
+ str r6, [r8, #0x404]
+
+poll_dvfs_set_1:
+ ldr r6, [r8, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ bne poll_dvfs_set_1
+
+ /* set SBS step-by-step mode */
+ ldr r6, [r8, #0x410]
+ orr r6, r6, #0x100
+ str r6, [r8, #0x410]
+
+ cmp r11, #1
+ beq audio_mode
+
+ /* Now set DDR rate to 1MHz. */
+ /* DDR is from bypassed PLL2 on periph2_clk2 path.
+ * Set the periph2_clk2_podf to divide by 8.
+ */
+ ldr r6, [r2, #0x14]
+ orr r6, r6, #0x07
+ str r6, [r2, #0x14]
+
+ /* Now set MMDC PODF to divide by 3. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x38
+ orr r6, r6, #0x10
+ str r6, [r2, #0x14]
+ b mmdc_podf
+
+audio_mode:
+ /* MMDC is from PLL2_200M.
+ * Set the mmdc_podf to div by 8.
+ */
+ ldr r6, [r2, #0x14]
+ orr r6, r6, #0x38
+ str r6, [r2, #0x14]
+
+ /* Loop till podf is accepted. */
+mmdc_podf:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0x0
+ bne mmdc_podf
+
+ /* Set the DDR IO in LPM state. */
+ sl_ddr_io_set_lpm
+
+ cmp r11, #1
+ beq do_audio_arm_clk
+
+ /* Check if none of the PLLs are
+ * locked, except PLL1 which will get
+ * bypassed below.
+ * We should not be here if PLL2 is not
+ * bypassed.
+ */
+ ldr r7, =1
+ /* USB1 PLL3 */
+ ldr r6, [r3, #0x10]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* USB2 PLL7 */
+ ldr r6, [r3, #0x20]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* Audio PLL4 */
+ ldr r6, [r3, #0x70]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* Video PLL5 */
+ ldr r6, [r3, #0xA0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* ENET PLL8 */
+ ldr r6, [r3, #0xE0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ b cont
+
+no_analog_saving:
+ ldr r7, =0
+
+cont:
+ /*Set the AHB to 3MHz. AXI to 3MHz. */
+ ldr r9, [r2, #0x14]
+ mov r6, r9
+ orr r6, r6, #0x1c00
+ orr r6, r6, #0x70000
+ str r6, [r2, #0x14]
+
+ /* Loop till podf is accepted. */
+ahb_podf:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0x0
+ bne podf_loop
+
+ /* Now set ARM to 24MHz. */
+ /* Move ARM to be sourced from STEP_CLK
+ * after setting STEP_CLK to 24MHz.
+ */
+ ldr r6, [r2, #0xc]
+ bic r6, r6, #0x100
+ str r6, [r2, #0x0c]
+ /* Now PLL1_SW_CLK to step_clk. */
+ ldr r6, [r2, #0x0c]
+ orr r6, r6, #0x4
+ str r6, [r2, #0x0c]
+
+ /* Bypass PLL1 and power it down. */
+ ldr r6, =(1 << 16)
+ orr r6, r6, #0x1000
+ str r6, [r3, #0x04]
+
+ /* Set the ARM PODF to divide by 8. */
+ /* IPG is at 1.5MHz here, we need ARM to
+ * run at the 12:5 ratio (WAIT mode issue).
+ */
+ ldr r6, =0x7
+ str r6, [r2, #0x10]
+
+ /* Loop till podf is accepted. */
+podf_loop:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0x0
+ bne podf_loop
+
+ /* Check if we can save some
+ * in the Analog section.
+ */
+ cmp r7, #0x1
+ bne do_wfi
+
+ /* Disable 1p1 brown out. */
+ ldr r6, [r3, #0x110]
+ bic r6, r6, #0x2
+ str r6, [r3, #0x110]
+
+ /* Enable the weak 2P5 */
+ ldr r6, [r3, #0x130]
+ orr r6, r6, #0x40000
+ str r6, [r3, #0x130]
+
+ /*Disable main 2p5. */
+ ldr r6, [r3, #0x130]
+ bic r6, r6, #0x1
+ str r6, [r3, #0x130]
+
+ /* Set the OSC bias current to -37.5%
+ * to drop the power on VDDHIGH.
+ */
+ ldr r6, [r3, #0x150]
+ orr r6, r6, #0xC000
+ str r6, [r3, #0x150]
+
+ /* Enable low power bandgap */
+ ldr r6, [r3, #0x260]
+ orr r6, r6, #0x20
+ str r6, [r3, #0x260]
+
+ /* turn off the bias current
+ * from the regular bandgap.
+ */
+ ldr r6, [r3, #0x260]
+ orr r6, r6, #0x80
+ str r6, [r3, #0x260]
+
+ /* Clear the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ * Per RM, should be cleared when
+ * band gap is powered down.
+ */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0x8
+ str r6, [r3, #0x150]
+
+ /*Power down the regular bandgap. */
+ ldr r6, [r3, #0x150]
+ orr r6, r6, #0x1
+ str r6, [r3, #0x150]
+
+ b do_wfi
+
+do_audio_arm_clk:
+ /*
+ * ARM is from PLL2_PFD2_400M here.
+ * Switch ARM to bypassed PLL1.
+ */
+ ldr r6, [r2, #0xC]
+ bic r6, r6, #0x4
+ str r6, [r2, #0xC]
+
+ /*
+ * Set the ARM_PODF to divide by 2
+ * as IPG is at 4MHz, we cannot run
+ * ARM_CLK above 9.6MHz when
+ * system enters WAIT mode.
+ */
+ ldr r6, =0x2
+ str r6, [r2, #0x10]
+
+ /* Loop till podf is accepted. */
+podf_loop_audio:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0x0
+ bne podf_loop_audio
+
+do_wfi:
+ /* Now do WFI. */
+ wfi
+
+ /* Set original ARM PODF back. */
+ str r0, [r2, #0x10]
+
+ /* Loop till podf is accepted. */
+podf_loop1:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0x0
+ bne podf_loop1
+
+ cmp r11, #1
+ beq audio_arm_clk_restore
+
+ /*
+ * Check if powered down
+ * analog components.
+ */
+ cmp r7, #0x1
+ bne skip_analog_restore
+
+ /* Power up the regular bandgap. */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0x1
+ str r6, [r3, #0x150]
+
+ /* turn on the bias current
+ * from the regular bandgap.
+ */
+ ldr r6, [r3, #0x260]
+ bic r6, r6, #0x80
+ str r6, [r3, #0x260]
+
+ /* Disable the low power bandgap */
+ ldr r6, [r3, #0x260]
+ bic r6, r6, #0x20
+ str r6, [r3, #0x260]
+
+ /*
+ * Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r3, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r3, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r3, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5:
+ ldr r6, [r3, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r3, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r3, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r3, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r3, #0x110]
+
+skip_analog_restore:
+
+ /* Power up PLL1 and un-bypass it. */
+ ldr r6, =(1 << 12)
+ str r6, [r3, #0x08]
+
+ /* Wait for PLL1 to relock. */
+wait_for_pll_lock:
+ ldr r6, [r3, #0x0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock
+
+ ldr r6, =(1 << 16)
+ str r6, [r3, #0x08]
+
+ /* Set PLL1_sw_clk back to PLL1. */
+ ldr r6, [r2, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r2, #0xc]
+
+ /* Restore AHB/AXI back. */
+ str r9, [r2, #0x14]
+
+ /* Loop till podf is accepted. */
+ahb_podf1:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0x0
+ bne podf_loop1
+
+ b wfi_restore
+
+audio_arm_clk_restore:
+ /* Move ARM back to PLL2_PFD2_400M */
+ ldr r6, [r2, #0xC]
+ orr r6, r6, #0x4
+ str r6, [r2, #0xC]
+
+wfi_restore:
+ mov r9, r10 /* get suspend_iram_base */
+ add r9, r9, #IRAM_WAIT_SIZE /* 4K */
+
+ /* Restore the DDR IO before exiting self-refresh. */
+ sl_ddr_io_restore
+
+ cmp r11, #1
+ beq mmdc_audio_restore
+
+ /* Set MMDC back to 24MHz. */
+ /* Set periph2_clk2_podf to divide by 1. */
+ /* Now set MMDC PODF to divide by 1. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x3f
+ str r6, [r2, #0x14]
+
+ b mmdc_podf1
+
+mmdc_audio_restore:
+ /* Set MMDC back to 100MHz. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x38
+ orr r6, r6, #0x8
+ str r6, [r2, $0x14]
+
+mmdc_podf1:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0x0
+ bne mmdc_podf1
+
+ /* clear DVFS - exit from self refresh mode */
+ ldr r6, [r8, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r8, #0x404]
+
+poll_dvfs_clear_1:
+ ldr r6, [r8, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r8, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r8, #0x404]
+
+ /* clear SBS - unblock DDR accesses */
+ ldr r6, [r8, #0x410]
+ bic r6, r6, #0x100
+ str r6, [r8, #0x410]
+
+ /* Enable L2. */
+ ldr r1, =L2_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ ldr r6, =0x1
+ str r6, [r1, #0x100]
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+
+ dsb
+ isb
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+
+ /* Add these nops so that the
+ * prefetcher will not try to get
+ * any instructions from DDR.
+ * The prefetch depth is about 23
+ * on A9, so adding 25 nops.
+ */
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ pop {r4-r12}
+
+ /* Restore registers */
+ mov pc, lr
+
+ .type mx6sl_do_wait, #object
+ENTRY(mx6sl_do_wait)
+ .word mx6sl_wait
+ .size mx6sl_wait, . - mx6sl_wait
+
diff --git a/arch/arm/mach-mx6/ntx_hwconfig.h b/arch/arm/mach-mx6/ntx_hwconfig.h
new file mode 100755
index 00000000..cba4f94e
--- /dev/null
+++ b/arch/arm/mach-mx6/ntx_hwconfig.h
@@ -0,0 +1,267 @@
+#ifndef __ntx_hwconfig_h//[
+#define __ntx_hwconfig_h
+
+
+#ifdef __cplusplus //[
+extern "C" {
+#endif //] __cplusplus
+
+
+#define SYSHWCONFIG_SEEKSIZE (1024*512)
+
+
+typedef struct tagNTXHWCFG_HDR {
+ char cMagicNameA[10];// should be "HW CONFIG "
+ char cVersionNameA[5];// should be "vx.x"
+ unsigned char bHWConfigSize;// v0.1=19 .
+} NTXHWCFG_HDR ;
+
+typedef struct tagNTXHWCFG_VAL {
+ unsigned char bPCB;//
+ unsigned char bKeyPad;// key pad type .
+ unsigned char bAudioCodec;//
+ unsigned char bAudioAmp;//
+ unsigned char bWifi;//
+ unsigned char bBT;//
+ unsigned char bMobile;//
+ unsigned char bTouchCtrl;//touch controller .
+ unsigned char bTouchType;//touch type .
+ unsigned char bDisplayCtrl;//
+ unsigned char bDisplayPanel;//
+ unsigned char bRSensor;//
+ unsigned char bMicroP;//
+ unsigned char bCustomer;//
+ unsigned char bBattery;//
+ unsigned char bLed;//
+ unsigned char bRamSize;// ram size
+ unsigned char bIFlash; // internal flash type .
+ unsigned char bExternalMem;// external sd type .
+ unsigned char bRootFsType;// root fs type .
+ unsigned char bSysPartType;// system partition type .
+ unsigned char bProgressXHiByte; // Progress bar position while boot ,X
+ unsigned char bProgressXLoByte; // ,X
+ unsigned char bProgressYHiByte; // ,Y
+ unsigned char bProgressYLoByte; // ,Y
+ unsigned char bProgressCnts; // Cnt .
+ unsigned char bContentType; // Book content type .
+ unsigned char bCPU; //main cpu type .
+ unsigned char bUIStyle; // UI style .
+ unsigned char bRamType; // Ram Type .
+ unsigned char bUIConfig; // UI config .
+ unsigned char bDisplayResolution;// Display resolution .
+ unsigned char bFrontLight;// Front Light .
+ unsigned char bCPUFreq;// CPU frequency .
+ unsigned char bHallSensor;// Hall Sensor Controller .
+ unsigned char bDisplayBusWidth;// Display BUS width/bits .
+ unsigned char bFrontLight_Flags;// Front Light Flags .
+ unsigned char bPCB_Flags;// PCB Flags .
+ unsigned char bFrontLight_LED_Driver;// Front Light LED driver .
+ unsigned char bVCOM_10mV_HiByte;// VCOM mV High byte .
+ unsigned char bVCOM_10mV_LoByte;// VCOM mV Low byte .
+ unsigned char bPCB_REV;// PCB revision .
+ unsigned char bPCB_LVL;// PCB develop level .
+ unsigned char bHOME_LED_PWM;// HOME LED PWM source .
+ unsigned char bPMIC;// System PMIC .
+ unsigned char bFL_PWM;// FrontLight PWM source
+ unsigned char bRTC;// System RTC source
+ unsigned char bBootOpt;// Boot option
+ unsigned char bTouch2Ctrl;//touch controller .
+ unsigned char bTouch2Type;//touch type .
+ unsigned char bGPS;//GPS module .
+ unsigned char bFM;//FM module .
+} NTXHWCFG_VAL ;
+
+typedef struct tagNTX_HWCONFG{
+ NTXHWCFG_HDR m_hdr;
+ NTXHWCFG_VAL m_val;
+ unsigned char m_bReserveA[110-sizeof(NTXHWCFG_HDR)-sizeof(NTXHWCFG_VAL)];
+} NTX_HWCONFIG;
+
+// Filed types ...
+#define FIELD_TYPE_IDXSTR 0
+#define FIELD_TYPE_BYTE 1
+#define FIELD_TYPE_FLAGS 2
+
+// Filed Flags ...
+#define FIELD_FLAGS_HW 0x0000
+#define FIELD_FLAGS_SW 0x0001
+
+
+typedef struct tagHwConfigField{
+ char *szVersion;
+ char *szFieldName ;
+ int iFieldValueCnt;
+ char **szFieldValueA ;
+ unsigned short wFieldType;
+ unsigned short wFieldFlags;
+} HwConfigField ;
+
+
+extern const char * gszPCBA[];
+extern const char * gszKeyPadA[];
+extern const char * gszAudioCodecA[];//
+extern const char * gszAudioAmpA[];//
+extern const char * gszWifiA[];//
+extern const char * gszBTA[];//
+extern const char * gszMobileA[];//
+extern const char * gszTouchCtrlA[];//touch controller .
+extern const char * gszTouchTypeA[];//
+extern const char * gszDisplayCtrlA[];
+extern const char * gszDisplayPanelA[];
+extern const char * gszRSensorA[];//
+extern const char * gszMicroPA[];//
+extern const char * gszCustomerA[];//
+extern const char * gszBatteryA[];//
+extern const char * gszLedA[];//
+extern const char * gszRamSizeA[];// ram size
+extern const char * gszIFlashA[]; // internal flash type .
+extern const char * gszExternalMemA[];// external sd type .
+extern const char * gszRootFsTypeA[];// root fs type .
+extern const char * gszSysPartTypeA[];// system partition type .
+extern const char * gszCPUA[];// cpu type .
+extern const char * gszUIStyleA[];// UI Style (netronix UI/customer UI) .
+extern const char * gszRAMTypeA[];// Ram Type .
+extern const char * gszUIConfigA[];// UI Config .
+extern const char * gszDisplayResolutionA[];// Display Resolution .
+extern const char * gszFrontLightA[];// Front Light .
+extern const char * gszCPUFreqA[];// CPU frequency .
+extern const char * gszHallSensorA[];// Hall Sensor .
+extern const char * gszDisplayBusWidthA[];// Display BUS width .
+extern const char * gszFrontLightLEDrvA[];//Front Light LED driver IC .
+extern const char * gszPCB_LVLA[];//PCB develop level .
+extern const char * gszHOME_LED_PWMA[];// HOME LED PWM source .
+extern const char * gszPMICA[];// System PMIC .
+extern const char * gszFL_PWMA[];// FrontLight PWM source
+extern const char * gszRTCA[];// System RTC source .
+extern const char * gszFMA[];// System RTC source .
+extern const char * gszGPSA[];// System RTC source .
+
+
+// the return value of hw config apis . >=0 is success ,others is fail .
+#define HWCFG_RET_SUCCESS (0)
+#define HWCFG_RET_PTRERR (-1) // parameter include error pointer
+#define HWCFG_RET_HDRNOTMATCH (-2) // hwconfig header magic not match .
+#define HWCFG_RET_CFGVERTOOOLD (-3) // hwconfig tool version newer than config struct value (you should update the config file)...
+#define HWCFG_RET_CFGVERTOONEW (-4) // hwconfig tool version older than config struct value (you should update the config tool)...
+#define HWCFG_RET_CFGVERNOTMATCH (-5) // hwconfig tool version and config struct version not match ...
+#define HWCFG_RET_CFGVERFMTERR (-6) // config version format error (must be vX.X) ...
+#define HWCFG_RET_NOTHISFIELDIDX (-7) // field index error .
+#define HWCFG_RET_NOTHISFIELDNAME (-8) // field name error .
+#define HWCFG_RET_FILEOPENFAIL (-9) // file open fail .
+#define HWCFG_RET_FILEWRITEFAIL (-10) // file open fail .
+#define HWCFG_RET_FIELDTYPEERROR (-11) // field type error .
+#define HWCFG_RET_FIELDTRDONLY (-12) // field read only .
+#define HWCFG_RET_CFGVALFLAGIDXERROR (-13) // index of config's flags not avalible .
+#define HWCFG_RET_CFGVALFLAGNAMEERROR (-14) // flag name of config not avalible .
+#define HWCFG_RET_FIELDIDXOUTRANGE (-15) // field index out of range .
+
+
+// ntx hardward config field index list ...
+#define HWCFG_FLDIDX_PCB 0
+#define HWCFG_FLDIDX_KeyPad 1
+#define HWCFG_FLDIDX_AudioCodec 2
+#define HWCFG_FLDIDX_AudioAmp 3
+#define HWCFG_FLDIDX_Wifi 4
+#define HWCFG_FLDIDX_BT 5
+#define HWCFG_FLDIDX_Mobile 6
+#define HWCFG_FLDIDX_TouchCtrl 7
+#define HWCFG_FLDIDX_TouchType 8
+#define HWCFG_FLDIDX_DisplayCtrl 9
+#define HWCFG_FLDIDX_DisplayPanel 10
+#define HWCFG_FLDIDX_RSensor 11
+#define HWCFG_FLDIDX_MicroP 12
+#define HWCFG_FLDIDX_Customer 13
+#define HWCFG_FLDIDX_Battery 14
+#define HWCFG_FLDIDX_Led 15
+#define HWCFG_FLDIDX_RamSize 16
+#define HWCFG_FLDIDX_IFlash 17
+#define HWCFG_FLDIDX_ExternalMem 18
+#define HWCFG_FLDIDX_RootFsType 19 // v0.2
+#define HWCFG_FLDIDX_SysPartType 20 // v0.3
+
+#define HWCFG_FLDIDX_ProgressXHiByte 21 // v0.4
+#define HWCFG_FLDIDX_ProgressXLoByte 22 // v0.4
+#define HWCFG_FLDIDX_ProgressYHiByte 23 // v0.4
+#define HWCFG_FLDIDX_ProgressYLoByte 24 // v0.4
+#define HWCFG_FLDIDX_ProgressCnts 25 // v0.4
+
+#define HWCFG_FLDIDX_ContentType 26 // v0.5
+#define HWCFG_FLDIDX_CPU 27 // v0.6
+#define HWCFG_FLDIDX_UISTYLE 28 // v0.7
+
+#define HWCFG_FLDIDX_RAMTYPE 29 // v0.8
+#define HWCFG_FLDIDX_UICONFIG 30 // v0.9
+#define HWCFG_FLDIDX_DISPLAYRESOLUTION 31 // v1.0
+#define HWCFG_FLDIDX_FRONTLIGHT 32 // v1.1
+#define HWCFG_FLDIDX_CPUFREQ 33 // v1.2
+#define HWCFG_FLDIDX_HALLSENSOR 34 // v1.3
+#define HWCFG_FLDIDX_DisplayBusWidth 35 // v1.4
+#define HWCFG_FLDIDX_FrontLight_Flags 36 // v1.5
+#define HWCFG_FLDIDX_PCB_Flags 37 // v1.6
+#define HWCFG_FLDIDX_FrontLight_LEDrv 38 // v1.7
+#define HWCFG_FLDIDX_VCOM_10mV_HiByte 39 // v1.8
+#define HWCFG_FLDIDX_VCOM_10mV_LoByte 40 // v1.8
+#define HWCFG_FLDIDX_PCB_REV 41 // v1.9
+#define HWCFG_FLDIDX_PCB_LVL 42 // v2.0
+#define HWCFG_FLDIDX_HOME_PWM 43 // v2.1
+#define HWCFG_FLDIDX_PMIC 44 // v2.1
+#define HWCFG_FLDIDX_FL_PWM 45// v2.1
+#define HWCFG_FLDIDX_RTC 46// v2.1
+#define HWCFG_FLDIDX_BOOTOPT 47// v2.2
+#define HWCFG_FLDIDX_Touch2Ctrl 48 // v2.3
+#define HWCFG_FLDIDX_Touch2Type 49 // v2.3
+#define HWCFG_FLDIDX_GPS 50 // v2.4
+#define HWCFG_FLDIDX_FM 51 // v2.4
+
+
+
+
+NTX_HWCONFIG *NtxHwCfg_Load(const char *szFileName,int iIsSeek);
+NTX_HWCONFIG *NtxHwCfg_LoadEx(const char *szFileName,unsigned long dwIsSeek);
+int NtxHwCfg_Save(const char *szFileName,int iIsSeek);
+NTX_HWCONFIG *NtxHwCfg_Get(void);
+
+
+int NtxHwCfg_GetTotalFlds(void);//¨ú±o¦@¦³´X­ÓÄæ¦ì.
+int NtxHwCfg_GetFldVal(int iFldIdx,HwConfigField *O_ptHwCfgFld);//¨ú±o¤v©w¸qªºÄæ¦ì­È.
+unsigned char NtxHwCfg_FldStrVal2Val(int iFldIdx,char *szFldStrVal);//Äæ¦ìªº¦r¦ê­ÈÂà´«¬°Äæ¦ì.
+const char *NtxHwCfg_FldVal2StrVal(int iFldIdx,unsigned char bFldVal);//Äæ¦ìªº­ÈÂà´«¬°¦r¦ê­È.
+int NtxHwCfg_FldName2Idx(const char *szFldName);
+int NtxHwCfg_is_HW_Fld(int iFldIdx);
+int NtxHwCfg_is_SW_Fld(int iFldIdx);
+
+int NtxHwCfg_ChkCfgHeaderEx2(NTX_HWCONFIG *pHdr,int iIsIgnoreVersion,const char *pcCompareHdrVersionA);
+int NtxHwCfg_ChkCfgHeaderEx(NTX_HWCONFIG *pHdr,int iIsIgnoreVersion);
+int NtxHwCfg_ChkCfgHeader(NTX_HWCONFIG *pHdr);//Àˬd²ÕºAªíÀY,ª©¥».
+int NtxHwCfg_CfgUpgrade(NTX_HWCONFIG *pHdr);//®æ¦¡¤É¯Å¦Ü¤u¨ã¤@­Pªºª©¥».
+
+int NtxHwCfg_GetCfgTotalFlds(NTX_HWCONFIG *pHdr);//¨ú±o²ÕºAÁ`¦@¦³´X­ÓÄæ¦ì.
+
+int NtxHwCfg_GetCfgFldVal(NTX_HWCONFIG *pHdr,int iFieldIdx);
+const char *NtxHwCfg_GetCfgFldStrVal(NTX_HWCONFIG *pHdr,int iFieldIdx);
+int NtxHwCfg_GetCfgFldFlagVal(NTX_HWCONFIG *pHdr,int iFieldIdx,int iFlagsIdx);
+int NtxHwCfg_GetCfgFldFlagValByName(NTX_HWCONFIG *pHdr,int iFieldIdx,const char *pszFlagName);
+
+int NtxHwCfg_SetCfgFldVal(NTX_HWCONFIG *pHdr,int iFieldIdx,int iFieldVal);
+int NtxHwCfg_SetCfgFldStrVal(NTX_HWCONFIG *pHdr,int iFieldIdx,const char *pszFieldStrVal);
+int NtxHwCfg_SetCfgFldStrValEx(NTX_HWCONFIG *pHdr,int iFieldIdx,const char *pszFieldStrVal,int iHW_WR_Protect);
+int NtxHwCfg_SetCfgFldFlagValByName(NTX_HWCONFIG *pHdr,int iFieldIdx,const char *pszFlagName,int iIsTurnON,int iHW_WR_Protect);
+
+int NtxHwCfg_SetCfgFldValDefs(NTX_HWCONFIG *I_pHdr,int I_iFieldIdx,
+ const char **I_pszFieldValDefs,int I_iTotalVals);
+
+int NtxHwCfg_CompareHdrFldVersion(NTX_HWCONFIG *pHdr,int iFieldIdx);
+
+// get field value name in hardware config struct ...
+#define NTXHWCFG_GET_FLDCFGNAME(pHdr,_fld) gsz##_fld##A[pHdr->m_val.b##_fld]
+// get print format by field in hardware config struct ...
+#define NTXHWCFG_GET_FLDCFGPRTFMT(pHdr,_fld) "%s : %s",#_fld,NTXHWCFG_GET_FLDCFGNAME(pHdr,_fld)
+
+#define NTXHWCFG_TST_FLAG(_flags,_bit_n) ((_flags)&(0x01<<(_bit_n)))?1:0
+
+#ifdef __cplusplus //[
+}
+#endif //] __cplusplus
+
+#endif //] __ntx_hwconfig_h
+
diff --git a/arch/arm/mach-mx6/pcie.c b/arch/arm/mach-mx6/pcie.c
new file mode 100644
index 00000000..fa37e07c
--- /dev/null
+++ b/arch/arm/mach-mx6/pcie.c
@@ -0,0 +1,1161 @@
+/*
+ * arch/arm/mach-mx6/pcie.c
+ *
+ * PCIe host controller driver for IMX6 SOCs
+ *
+ * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Bits taken from arch/arm/mach-dove/pcie.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+
+#include <mach/pcie.h>
+
+#include <asm/sizes.h>
+#include <asm/signal.h>
+
+#include "crm_regs.h"
+#ifdef CONFIG_PCI_MSI
+#include "msi.h"
+#endif
+
+/* Register Definitions */
+#define PRT_LOG_R_BaseAddress 0x700
+
+/* Register DB_R0 */
+/* Debug Register 0 */
+#define DB_R0 (PRT_LOG_R_BaseAddress + 0x28)
+#define DB_R0_RegisterSize 32
+#define DB_R0_RegisterResetValue 0x0
+#define DB_R0_RegisterResetMask 0xFFFFFFFF
+/* End of Register Definition for DB_R0 */
+
+/* Register DB_R1 */
+/* Debug Register 1 */
+#define DB_R1 (PRT_LOG_R_BaseAddress + 0x2c)
+#define DB_R1_RegisterSize 32
+#define DB_R1_RegisterResetValue 0x0
+#define DB_R1_RegisterResetMask 0xFFFFFFFF
+/* End of Register Definition for DB_R1 */
+
+#define ATU_R_BaseAddress 0x900
+#define ATU_VIEWPORT_R (ATU_R_BaseAddress + 0x0)
+#define ATU_REGION_CTRL1_R (ATU_R_BaseAddress + 0x4)
+#define ATU_REGION_CTRL2_R (ATU_R_BaseAddress + 0x8)
+#define ATU_REGION_LOWBASE_R (ATU_R_BaseAddress + 0xC)
+#define ATU_REGION_UPBASE_R (ATU_R_BaseAddress + 0x10)
+#define ATU_REGION_LIMIT_ADDR_R (ATU_R_BaseAddress + 0x14)
+#define ATU_REGION_LOW_TRGT_ADDR_R (ATU_R_BaseAddress + 0x18)
+#define ATU_REGION_UP_TRGT_ADDR_R (ATU_R_BaseAddress + 0x1C)
+
+/* Registers of PHY */
+/* Register PHY_STS_R */
+/* PHY Status Register */
+#define PHY_STS_R (PRT_LOG_R_BaseAddress + 0x110)
+
+/* Register PHY_CTRL_R */
+/* PHY Control Register */
+#define PHY_CTRL_R (PRT_LOG_R_BaseAddress + 0x114)
+
+#define SSP_CR_SUP_DIG_MPLL_OVRD_IN_LO 0x0011
+/* FIELD: RES_ACK_IN_OVRD [15:15]
+// FIELD: RES_ACK_IN [14:14]
+// FIELD: RES_REQ_IN_OVRD [13:13]
+// FIELD: RES_REQ_IN [12:12]
+// FIELD: RTUNE_REQ_OVRD [11:11]
+// FIELD: RTUNE_REQ [10:10]
+// FIELD: MPLL_MULTIPLIER_OVRD [9:9]
+// FIELD: MPLL_MULTIPLIER [8:2]
+// FIELD: MPLL_EN_OVRD [1:1]
+// FIELD: MPLL_EN [0:0]
+*/
+
+#define SSP_CR_SUP_DIG_ATEOVRD 0x0010
+/* FIELD: ateovrd_en [2:2]
+// FIELD: ref_usb2_en [1:1]
+// FIELD: ref_clkdiv2 [0:0]
+*/
+
+#define SSP_CR_LANE0_DIG_RX_OVRD_IN_LO 0x1005
+/* FIELD: RX_LOS_EN_OVRD [13:13]
+// FIELD: RX_LOS_EN [12:12]
+// FIELD: RX_TERM_EN_OVRD [11:11]
+// FIELD: RX_TERM_EN [10:10]
+// FIELD: RX_BIT_SHIFT_OVRD [9:9]
+// FIELD: RX_BIT_SHIFT [8:8]
+// FIELD: RX_ALIGN_EN_OVRD [7:7]
+// FIELD: RX_ALIGN_EN [6:6]
+// FIELD: RX_DATA_EN_OVRD [5:5]
+// FIELD: RX_DATA_EN [4:4]
+// FIELD: RX_PLL_EN_OVRD [3:3]
+// FIELD: RX_PLL_EN [2:2]
+// FIELD: RX_INVERT_OVRD [1:1]
+// FIELD: RX_INVERT [0:0]
+*/
+
+#define SSP_CR_LANE0_DIG_RX_ASIC_OUT 0x100D
+/* FIELD: LOS [2:2]
+// FIELD: PLL_STATE [1:1]
+// FIELD: VALID [0:0]
+*/
+
+/* control bus bit definition */
+#define PCIE_CR_CTL_DATA_LOC 0
+#define PCIE_CR_CTL_CAP_ADR_LOC 16
+#define PCIE_CR_CTL_CAP_DAT_LOC 17
+#define PCIE_CR_CTL_WR_LOC 18
+#define PCIE_CR_CTL_RD_LOC 19
+#define PCIE_CR_STAT_DATA_LOC 0
+#define PCIE_CR_STAT_ACK_LOC 16
+
+#define PCIE_CAP_STRUC_BaseAddress 0x70
+
+/* Register LNK_CAP */
+/* PCIE Link cap */
+#define LNK_CAP (PCIE_CAP_STRUC_BaseAddress + 0xc)
+#define LNK_CAP_RegisterSize 32
+#define LNK_CAP_RegisterResetValue 0x011cc12
+#define LNK_CAP_RegisterResetMask 0xffffffff
+
+#ifdef CONFIG_PCI_MSI
+#define PCIE_RC_MSI_CAP 0x50
+
+#define PCIE_PL_MSICA 0x820
+#define PCIE_PL_MSICUA 0x824
+#define PCIE_PL_MSIC_INT 0x828
+
+#define MSIC_INT_EN 0x0
+#define MSIC_INT_MASK 0x4
+#define MSIC_INT_STATUS 0x8
+#endif
+
+/* End of Register Definitions */
+
+#define PCIE_DBI_BASE_ADDR (PCIE_ARB_END_ADDR - SZ_16K + 1)
+
+#define PCIE_CONF_BUS(b) (((b) & 0xFF) << 16)
+#define PCIE_CONF_DEV(d) (((d) & 0x1F) << 11)
+#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8)
+#define PCIE_CONF_REG(r) ((r) & ~0x3)
+
+/*
+ * The default values of the RC's reserved ddr memory
+ * used to verify EP mode.
+ * BTW, here is the layout of the 1G ddr on SD boards
+ * 0x1000_0000 ~ 0x4FFF_FFFF
+ */
+static u32 rc_ddr_test_region = 0x40000000;
+static u32 rc_ddr_test_region_size = (SZ_16M - SZ_16K);
+
+#ifdef EP_SELF_IO_TEST
+static void *rc_ddr_test_reg1, *rc_ddr_test_reg2;
+static void __iomem *pcie_arb_base_addr;
+static struct timeval tv1, tv2, tv3;
+static u32 tv_count1, tv_count2;
+#endif
+static void __iomem *base;
+static void __iomem *dbi_base;
+
+enum {
+ MemRdWr = 0,
+ MemRdLk = 1,
+ IORdWr = 2,
+ CfgRdWr0 = 4,
+ CfgRdWr1 = 5
+};
+
+struct imx_pcie_port {
+ u8 index;
+ u8 root_bus_nr;
+ void __iomem *base;
+ void __iomem *dbi_base;
+ spinlock_t conf_lock;
+
+ char io_space_name[16];
+ char mem_space_name[16];
+
+ struct resource res[2];
+};
+
+static struct imx_pcie_port imx_pcie_port[1];
+static int num_pcie_ports;
+
+static int pcie_phy_cr_read(int addr, int *data);
+static int pcie_phy_cr_write(int addr, int data);
+static void change_field(int *in, int start, int end, int val);
+
+/* IMX PCIE GPR configure routines */
+static inline void imx_pcie_clrset(u32 mask, u32 val, void __iomem *addr)
+{
+ writel(((readl(addr) & ~mask) | (val & mask)), addr);
+}
+
+static struct imx_pcie_port *bus_to_port(int bus)
+{
+ int i;
+
+ for (i = num_pcie_ports - 1; i >= 0; i--) {
+ int rbus = imx_pcie_port[i].root_bus_nr;
+ if (rbus != -1 && rbus == bus)
+ break;
+ }
+
+ return i >= 0 ? imx_pcie_port + i : NULL;
+}
+
+static int __init imx_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+ struct imx_pcie_port *pp;
+
+ if (nr >= num_pcie_ports)
+ return 0;
+
+ pp = &imx_pcie_port[nr];
+ pp->root_bus_nr = sys->busnr;
+
+ /*
+ * IORESOURCE_IO
+ */
+ snprintf(pp->io_space_name, sizeof(pp->io_space_name),
+ "PCIe %d I/O", pp->index);
+ pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
+ pp->res[0].name = pp->io_space_name;
+ if (pp->index == 0) {
+ pp->res[0].start = PCIE_ARB_BASE_ADDR + SZ_16M - SZ_2M;
+ pp->res[0].end = pp->res[0].start + SZ_1M - 1;
+ }
+ pp->res[0].flags = IORESOURCE_IO;
+ if (request_resource(&ioport_resource, &pp->res[0]))
+ panic("Request PCIe IO resource failed\n");
+ sys->resource[0] = &pp->res[0];
+
+ /*
+ * IORESOURCE_MEM
+ */
+ snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
+ "PCIe %d MEM", pp->index);
+ pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
+ pp->res[1].name = pp->mem_space_name;
+ if (pp->index == 0) {
+ pp->res[1].start = PCIE_ARB_BASE_ADDR;
+ pp->res[1].end = pp->res[1].start + SZ_16M - SZ_2M - 1;
+ }
+ pp->res[1].flags = IORESOURCE_MEM;
+ if (request_resource(&iomem_resource, &pp->res[1]))
+ panic("Request PCIe Memory resource failed\n");
+ sys->resource[1] = &pp->res[1];
+
+ sys->resource[2] = NULL;
+
+ return 1;
+}
+
+static int imx_pcie_link_up(void __iomem *dbi_base)
+{
+ /* Check the pcie link up or link down */
+ int iterations = 200;
+ u32 rc, ltssm, rx_valid, temp;
+
+ do {
+ /* link is debug bit 36 debug 1 start in bit 32 */
+ rc = readl(dbi_base + DB_R1) & (0x1 << (36 - 32)) ;
+ iterations--;
+ usleep_range(2000, 3000);
+
+ /* From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
+ * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
+ * If (MAC/LTSSM.state == Recovery.RcvrLock)
+ * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition
+ * to gen2 is stuck
+ */
+ pcie_phy_cr_read(SSP_CR_LANE0_DIG_RX_ASIC_OUT, &rx_valid);
+ ltssm = readl(dbi_base + DB_R0) & 0x3F;
+ if ((ltssm == 0x0D) && ((rx_valid & 0x01) == 0)) {
+ pr_info("Transition to gen2 is stuck, reset PHY!\n");
+ pcie_phy_cr_read(SSP_CR_LANE0_DIG_RX_OVRD_IN_LO, &temp);
+ change_field(&temp, 3, 3, 0x1);
+ change_field(&temp, 5, 5, 0x1);
+ pcie_phy_cr_write(SSP_CR_LANE0_DIG_RX_OVRD_IN_LO,
+ 0x0028);
+ usleep_range(2000, 3000);
+ pcie_phy_cr_read(SSP_CR_LANE0_DIG_RX_OVRD_IN_LO, &temp);
+ change_field(&temp, 3, 3, 0x0);
+ change_field(&temp, 5, 5, 0x0);
+ pcie_phy_cr_write(SSP_CR_LANE0_DIG_RX_OVRD_IN_LO,
+ 0x0000);
+ }
+
+ if (iterations == 0)
+ pr_info("link up failed, DB_R0:0x%08x, DB_R1:0x%08x!\n"
+ , readl(dbi_base + DB_R0)
+ , readl(dbi_base + DB_R1));
+ } while (!rc && iterations);
+
+ if (!rc)
+ return 0;
+ return 1;
+}
+
+static void imx_pcie_regions_setup(struct device *dev, void __iomem *dbi_base)
+{
+ struct imx_pcie_platform_data *pdata = dev->platform_data;
+#ifdef CONFIG_PCI_MSI
+ unsigned int i;
+ void __iomem *p = dbi_base + PCIE_PL_MSIC_INT;
+#endif
+
+ /*
+ * i.MX6 defines 16MB in the AXI address map for PCIe.
+ *
+ * That address space excepted the pcie registers is
+ * split and defined into different regions by iATU,
+ * with sizes and offsets as follows:
+ *
+ * RC:
+ * 0x0100_0000 --- 0x01DF_FFFF 14MB IORESOURCE_MEM
+ * 0x01E0_0000 --- 0x01EF_FFFF 1MB IORESOURCE_IO
+ * 0x01F0_0000 --- 0x01FF_FFFF 1MB Cfg + MSI + Registers
+ *
+ * EP (default value):
+ * 0x0100_0000 --- 0x01FF_C000 16MB - 16KB IORESOURCE_MEM
+ */
+
+ /* CMD reg:I/O space, MEM space, and Bus Master Enable */
+ writel(readl(dbi_base + PCI_COMMAND)
+ | PCI_COMMAND_IO
+ | PCI_COMMAND_MEMORY
+ | PCI_COMMAND_MASTER,
+ dbi_base + PCI_COMMAND);
+
+ if (pdata->type_ep) {
+ /*
+ * configure the class_rev(emaluate one memory ram ep device),
+ * bar0 and bar1 of ep
+ */
+ writel(0xdeadbeaf, dbi_base + PCI_VENDOR_ID);
+ writel(readl(dbi_base + PCI_CLASS_REVISION)
+ | (PCI_CLASS_MEMORY_RAM << 16),
+ dbi_base + PCI_CLASS_REVISION);
+ writel(0xdeadbeaf, dbi_base + PCI_SUBSYSTEM_VENDOR_ID);
+
+ /* 32bit none-prefetchable 8M bytes memory on bar0 */
+ writel(0x0, dbi_base + PCI_BASE_ADDRESS_0);
+ writel(SZ_8M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_0);
+
+ /* None used bar1 */
+ writel(0x0, dbi_base + PCI_BASE_ADDRESS_1);
+ writel(0, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_1);
+
+ /* 4K bytes IO on bar2 */
+ writel(0x1, dbi_base + PCI_BASE_ADDRESS_2);
+ writel(SZ_4K - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_2);
+
+ /*
+ * 32bit prefetchable 1M bytes memory on bar3
+ * FIXME BAR MASK3 is not changable, the size
+ * is fixed to 256 bytes.
+ */
+ writel(0x8, dbi_base + PCI_BASE_ADDRESS_3);
+ writel(SZ_1M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_3);
+
+ /*
+ * 64bit prefetchable 1M bytes memory on bar4-5.
+ * FIXME BAR4,5 are not enabled yet
+ */
+ writel(0xc, dbi_base + PCI_BASE_ADDRESS_4);
+ writel(SZ_1M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_4);
+ writel(0, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_5);
+
+ /*
+ * region0 outbound used to access RC's reserved ddr memory
+ */
+ writel(0, dbi_base + ATU_VIEWPORT_R);
+ writel(PCIE_ARB_BASE_ADDR, dbi_base + ATU_REGION_LOWBASE_R);
+ writel(0, dbi_base + ATU_REGION_UPBASE_R);
+ writel(PCIE_ARB_BASE_ADDR + rc_ddr_test_region_size,
+ dbi_base + ATU_REGION_LIMIT_ADDR_R);
+
+ writel(rc_ddr_test_region,
+ dbi_base + ATU_REGION_LOW_TRGT_ADDR_R);
+ writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R);
+ writel(MemRdWr, dbi_base + ATU_REGION_CTRL1_R);
+ writel((1<<31), dbi_base + ATU_REGION_CTRL2_R);
+ } else {
+ /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */
+ writel(readl(dbi_base + PCI_CLASS_REVISION)
+ | (PCI_CLASS_BRIDGE_PCI << 16),
+ dbi_base + PCI_CLASS_REVISION);
+
+ /*
+ * region0 outbound used to access target cfg
+ */
+ writel(0, dbi_base + ATU_VIEWPORT_R);
+ writel(PCIE_ARB_END_ADDR - SZ_1M + 1,
+ dbi_base + ATU_REGION_LOWBASE_R);
+ writel(PCIE_ARB_END_ADDR - SZ_64K,
+ dbi_base + ATU_REGION_LIMIT_ADDR_R);
+ writel(0, dbi_base + ATU_REGION_UPBASE_R);
+
+ writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R);
+ writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R);
+ writel(CfgRdWr0, dbi_base + ATU_REGION_CTRL1_R);
+ writel((1<<31), dbi_base + ATU_REGION_CTRL2_R);
+ }
+
+#ifdef CONFIG_PCI_MSI
+ writel(MSI_MATCH_ADDR, dbi_base + PCIE_PL_MSICA);
+ writel(0, dbi_base + PCIE_PL_MSICUA);
+ for (i = 0; i < 8 ; i++) {
+ writel(0, p + MSIC_INT_EN);
+ writel(0xFFFFFFFF, p + MSIC_INT_MASK);
+ writel(0xFFFFFFFF, p + MSIC_INT_STATUS);
+ p += 12;
+ }
+#endif
+}
+
+#ifdef CONFIG_PCI_MSI
+void imx_pcie_mask_irq(unsigned int pos, int set)
+{
+ unsigned int mask = 1 << (pos & 0x1F);
+ unsigned int val, newval;
+ void __iomem *p;
+
+ p = dbi_base + PCIE_PL_MSIC_INT + MSIC_INT_MASK + ((pos >> 5) * 12);
+
+ if (pos >= (8 * 32))
+ return;
+ val = readl(p);
+ if (set)
+ newval = val | mask;
+ else
+ newval = val & ~mask;
+ if (val != newval)
+ writel(newval, p);
+}
+
+void imx_pcie_enable_irq(unsigned int pos, int set)
+{
+ unsigned int mask = 1 << (pos & 0x1F);
+ unsigned int val, newval;
+ void __iomem *p;
+
+ p = dbi_base + PCIE_PL_MSIC_INT + MSIC_INT_EN + ((pos >> 5) * 12);
+
+ /* RC: MSI CAP enable */
+ if (set) {
+ val = readl(dbi_base + PCIE_RC_MSI_CAP);
+ val |= (PCI_MSI_FLAGS_ENABLE << 16);
+ writel(val, dbi_base + PCIE_RC_MSI_CAP);
+ }
+
+ if (pos >= (8 * 32))
+ return;
+ val = readl(p);
+ if (set)
+ newval = val | mask;
+ else
+ newval = val & ~mask;
+ if (val != newval)
+ writel(newval, p);
+ if (set && (val != newval))
+ imx_pcie_mask_irq(pos, 0); /* unmask when enabled */
+ }
+
+unsigned int imx_pcie_msi_pending(unsigned int index)
+{
+ unsigned int val, mask;
+ void __iomem *p = dbi_base + PCIE_PL_MSIC_INT + (index * 12);
+
+ if (index >= 8)
+ return 0;
+ val = readl(p + MSIC_INT_STATUS);
+ mask = readl(p + MSIC_INT_MASK);
+ val &= ~mask;
+ writel(val, p + MSIC_INT_STATUS);
+ return val;
+}
+#endif
+
+static int imx_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+ int size, u32 *val)
+{
+ struct imx_pcie_port *pp = bus_to_port(bus->number);
+ u32 va_address;
+
+ /* Added to change transaction TYPE */
+ if (bus->number < 2) {
+ writel(0, dbi_base + ATU_VIEWPORT_R);
+ writel(CfgRdWr0, dbi_base + ATU_REGION_CTRL1_R);
+ } else {
+ writel(0, dbi_base + ATU_VIEWPORT_R);
+ writel(CfgRdWr1, dbi_base + ATU_REGION_CTRL1_R);
+ }
+
+ if (pp) {
+ if (devfn != 0) {
+ *val = 0xFFFFFFFF;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ va_address = (u32)dbi_base + (where & ~0x3);
+ } else {
+ writel(0, dbi_base + ATU_VIEWPORT_R);
+
+ writel((((PCIE_CONF_BUS(bus->number)
+ + PCIE_CONF_DEV(PCI_SLOT(devfn))
+ + PCIE_CONF_FUNC(PCI_FUNC(devfn)))) << 8),
+ dbi_base + ATU_REGION_LOW_TRGT_ADDR_R);
+ va_address = (u32)base + PCIE_CONF_REG(where);
+ }
+
+ *val = readl(va_address);
+
+ if (size == 1)
+ *val = (*val >> (8 * (where & 3))) & 0xFF;
+ else if (size == 2)
+ *val = (*val >> (8 * (where & 3))) & 0xFFFF;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int imx_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+ int where, int size, u32 val)
+{
+ struct imx_pcie_port *pp = bus_to_port(bus->number);
+ u32 va_address = 0, mask = 0, tmp = 0;
+ int ret = PCIBIOS_SUCCESSFUL;
+
+ /* Added to change transaction TYPE */
+ if (bus->number < 2) {
+ writel(0, dbi_base + ATU_VIEWPORT_R);
+ writel(CfgRdWr0, dbi_base + ATU_REGION_CTRL1_R);
+ } else {
+ writel(0, dbi_base + ATU_VIEWPORT_R);
+ writel(CfgRdWr1, dbi_base + ATU_REGION_CTRL1_R);
+ }
+
+ if (pp) {
+ if (devfn != 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ va_address = (u32)dbi_base + (where & ~0x3);
+ } else {
+ writel(0, dbi_base + ATU_VIEWPORT_R);
+
+ writel((((PCIE_CONF_BUS(bus->number)
+ + PCIE_CONF_DEV(PCI_SLOT(devfn))
+ + PCIE_CONF_FUNC(PCI_FUNC(devfn)))) << 8),
+ dbi_base + ATU_REGION_LOW_TRGT_ADDR_R);
+ va_address = (u32)base + PCIE_CONF_REG(where);
+ }
+
+ if (size == 4) {
+ writel(val, va_address);
+ goto exit;
+ }
+
+ if (size == 2)
+ mask = ~(0xFFFF << ((where & 0x3) * 8));
+ else if (size == 1)
+ mask = ~(0xFF << ((where & 0x3) * 8));
+ else
+ ret = PCIBIOS_BAD_REGISTER_NUMBER;
+
+ tmp = readl(va_address) & mask;
+ tmp |= val << ((where & 0x3) * 8);
+ writel(tmp, va_address);
+exit:
+ return ret;
+}
+
+static struct pci_ops imx_pcie_ops = {
+ .read = imx_pcie_rd_conf,
+ .write = imx_pcie_wr_conf,
+};
+
+static struct pci_bus __init *
+imx_pcie_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ struct pci_bus *bus;
+
+ if (nr < num_pcie_ports) {
+ bus = pci_scan_bus(sys->busnr, &imx_pcie_ops, sys);
+ } else {
+ bus = NULL;
+ BUG();
+ }
+
+ return bus;
+}
+
+static int __init imx_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ switch (pin) {
+ case 1: return MXC_INT_PCIE_3;
+ case 2: return MXC_INT_PCIE_2;
+ case 3: return MXC_INT_PCIE_1;
+ case 4: return MXC_INT_PCIE_0;
+ default: return -1;
+ }
+}
+
+static struct hw_pci imx_pci __initdata = {
+ .nr_controllers = 1,
+ .swizzle = pci_std_swizzle,
+ .setup = imx_pcie_setup,
+ .scan = imx_pcie_scan_bus,
+ .map_irq = imx_pcie_map_irq,
+};
+
+/* PHY CR bus acess routines */
+static int pcie_phy_cr_ack_polling(int max_iterations, int exp_val)
+{
+ u32 temp_rd_data, wait_counter = 0;
+
+ do {
+ temp_rd_data = readl(dbi_base + PHY_STS_R);
+ temp_rd_data = (temp_rd_data >> PCIE_CR_STAT_ACK_LOC) & 0x1;
+ wait_counter++;
+ } while ((wait_counter < max_iterations) && (temp_rd_data != exp_val));
+
+ if (temp_rd_data != exp_val)
+ return 0 ;
+ return 1 ;
+}
+
+static int pcie_phy_cr_cap_addr(int addr)
+{
+ u32 temp_wr_data;
+
+ /* write addr */
+ temp_wr_data = addr << PCIE_CR_CTL_DATA_LOC ;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* capture addr */
+ temp_wr_data |= (0x1 << PCIE_CR_CTL_CAP_ADR_LOC);
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* wait for ack */
+ if (!pcie_phy_cr_ack_polling(100, 1))
+ return 0;
+
+ /* deassert cap addr */
+ temp_wr_data = addr << PCIE_CR_CTL_DATA_LOC;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* wait for ack de-assetion */
+ if (!pcie_phy_cr_ack_polling(100, 0))
+ return 0 ;
+
+ return 1 ;
+}
+
+static int pcie_phy_cr_read(int addr , int *data)
+{
+ u32 temp_rd_data, temp_wr_data;
+
+ /* write addr */
+ /* cap addr */
+ if (!pcie_phy_cr_cap_addr(addr))
+ return 0;
+
+ /* assert rd signal */
+ temp_wr_data = 0x1 << PCIE_CR_CTL_RD_LOC;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* wait for ack */
+ if (!pcie_phy_cr_ack_polling(100, 1))
+ return 0;
+
+ /* after got ack return data */
+ temp_rd_data = readl(dbi_base + PHY_STS_R);
+ *data = (temp_rd_data & (0xFFFF << PCIE_CR_STAT_DATA_LOC)) ;
+
+ /* deassert rd signal */
+ temp_wr_data = 0x0;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* wait for ack de-assetion */
+ if (!pcie_phy_cr_ack_polling(100, 0))
+ return 0 ;
+
+ return 1 ;
+
+}
+
+static int pcie_phy_cr_write(int addr, int data)
+{
+ u32 temp_wr_data;
+
+ /* write addr */
+ /* cap addr */
+ if (!pcie_phy_cr_cap_addr(addr))
+ return 0 ;
+
+ temp_wr_data = data << PCIE_CR_CTL_DATA_LOC;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* capture data */
+ temp_wr_data |= (0x1 << PCIE_CR_CTL_CAP_DAT_LOC);
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* wait for ack */
+ if (!pcie_phy_cr_ack_polling(100, 1))
+ return 0 ;
+
+ /* deassert cap data */
+ temp_wr_data = data << PCIE_CR_CTL_DATA_LOC;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* wait for ack de-assetion */
+ if (!pcie_phy_cr_ack_polling(100, 0))
+ return 0;
+
+ /* assert wr signal */
+ temp_wr_data = 0x1 << PCIE_CR_CTL_WR_LOC;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* wait for ack */
+ if (!pcie_phy_cr_ack_polling(100, 1))
+ return 0;
+
+ /* deassert wr signal */
+ temp_wr_data = data << PCIE_CR_CTL_DATA_LOC;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ /* wait for ack de-assetion */
+ if (!pcie_phy_cr_ack_polling(100, 0))
+ return 0;
+
+ temp_wr_data = 0x0 ;
+ writel(temp_wr_data, dbi_base + PHY_CTRL_R);
+
+ return 1 ;
+}
+
+static void change_field(int *in, int start, int end, int val)
+{
+ int mask;
+
+ mask = ((0xFFFFFFFF << start) ^ (0xFFFFFFFF << (end + 1))) & 0xFFFFFFFF;
+ *in = (*in & ~mask) | (val << start);
+}
+
+static void imx_pcie_enable_controller(struct device *dev)
+{
+ struct clk *pcie_clk;
+ struct imx_pcie_platform_data *pdata = dev->platform_data;
+
+ /* Enable PCIE power */
+ gpio_request(pdata->pcie_pwr_en, "PCIE POWER_EN");
+
+ /* activate PCIE_PWR_EN */
+ gpio_direction_output(pdata->pcie_pwr_en, 1);
+
+ imx_pcie_clrset(IOMUXC_GPR1_TEST_POWERDOWN, 0 << 18, IOMUXC_GPR1);
+
+
+ /* enable the clks */
+ if (pdata->type_ep) {
+ pcie_clk = clk_get(NULL, "pcie_ep_clk");
+ if (IS_ERR(pcie_clk))
+ pr_err("no pcie_ep clock.\n");
+
+ if (clk_enable(pcie_clk)) {
+ pr_err("can't enable pcie_ep clock.\n");
+ clk_put(pcie_clk);
+ }
+ } else {
+ pcie_clk = clk_get(NULL, "pcie_clk");
+ if (IS_ERR(pcie_clk))
+ pr_err("no pcie clock.\n");
+
+ if (clk_enable(pcie_clk)) {
+ pr_err("can't enable pcie clock.\n");
+ clk_put(pcie_clk);
+ }
+ }
+ imx_pcie_clrset(IOMUXC_GPR1_PCIE_REF_CLK_EN, 1 << 16, IOMUXC_GPR1);
+}
+
+static void card_reset(struct device *dev)
+{
+ struct imx_pcie_platform_data *pdata = dev->platform_data;
+
+ /* PCIE RESET */
+ gpio_request(pdata->pcie_rst, "PCIE RESET");
+
+ /* activate PERST_B */
+ gpio_direction_output(pdata->pcie_rst, 0);
+
+ /* Add one reset to the pcie external device */
+ msleep(100);
+
+ /* deactive PERST_B */
+ gpio_direction_output(pdata->pcie_rst, 1);
+}
+
+static void __init add_pcie_port(void __iomem *base, void __iomem *dbi_base,
+ struct imx_pcie_platform_data *pdata)
+{
+ struct clk *pcie_clk;
+
+ if (imx_pcie_link_up(dbi_base)) {
+ struct imx_pcie_port *pp = &imx_pcie_port[num_pcie_ports++];
+
+ pr_info("IMX PCIe port: link up.\n");
+
+ pp->index = 0;
+ pp->root_bus_nr = -1;
+ pp->base = base;
+ pp->dbi_base = dbi_base;
+ spin_lock_init(&pp->conf_lock);
+ memset(pp->res, 0, sizeof(pp->res));
+ } else {
+ pr_info("IMX PCIe port: link down!\n");
+
+ /* Release the clocks, and disable the power */
+ pcie_clk = clk_get(NULL, "pcie_clk");
+ if (IS_ERR(pcie_clk))
+ pr_err("no pcie clock.\n");
+
+ clk_disable(pcie_clk);
+ clk_put(pcie_clk);
+
+ imx_pcie_clrset(IOMUXC_GPR1_PCIE_REF_CLK_EN, 0 << 16,
+ IOMUXC_GPR1);
+
+ /* Disable PCIE power */
+ gpio_request(pdata->pcie_pwr_en, "PCIE POWER_EN");
+
+ /* activate PCIE_PWR_EN */
+ gpio_direction_output(pdata->pcie_pwr_en, 0);
+
+ imx_pcie_clrset(IOMUXC_GPR1_TEST_POWERDOWN, 1 << 18,
+ IOMUXC_GPR1);
+ }
+}
+
+/* Added for PCI abort handling */
+static int imx6q_pcie_abort_handler(unsigned long addr,
+ unsigned int fsr, struct pt_regs *regs)
+{
+ /*
+ * If it was an imprecise abort, then we need to correct the
+ * return address to be _after_ the instruction.
+ */
+ if (fsr & (1 << 10))
+ regs->ARM_pc += 4;
+ return 0;
+}
+
+#ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS
+static ssize_t imx_pcie_rc_memw_info(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return sprintf(buf, "imx-pcie-rc-memw-info start 0x%08x, size 0x%08x\n",
+ rc_ddr_test_region, rc_ddr_test_region_size);
+}
+
+static ssize_t
+imx_pcie_rc_memw_start(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 memw_start;
+
+ sscanf(buf, "%x\n", &memw_start);
+
+ if (memw_start < 0x10000000) {
+ dev_err(dev, "Invalid memory start address.\n");
+ dev_info(dev, "For example: echo 0x41000000 > /sys/...");
+ return -1;
+ }
+
+ if (rc_ddr_test_region != memw_start) {
+ rc_ddr_test_region = memw_start;
+ /* Re-setup the iATU */
+ imx_pcie_regions_setup(dev, dbi_base);
+ }
+
+ return count;
+}
+
+static ssize_t
+imx_pcie_rc_memw_size(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 memw_size;
+
+ sscanf(buf, "%x\n", &memw_size);
+
+ if ((memw_size > (SZ_16M - SZ_16K)) || (memw_size < SZ_64K)) {
+ dev_err(dev, "Invalid, should be [SZ_64K,SZ_16M - SZ_16KB].\n");
+ dev_info(dev, "For example: echo 0x800000 > /sys/...");
+ return -1;
+ }
+
+ if (rc_ddr_test_region_size != memw_size) {
+ rc_ddr_test_region_size = memw_size;
+ /* Re-setup the iATU */
+ imx_pcie_regions_setup(dev, dbi_base);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(rc_memw_info, S_IRUGO, imx_pcie_rc_memw_info, NULL);
+static DEVICE_ATTR(rc_memw_start_set, S_IWUGO, NULL, imx_pcie_rc_memw_start);
+static DEVICE_ATTR(rc_memw_size_set, S_IWUGO, NULL, imx_pcie_rc_memw_size);
+
+static struct attribute *imx_pcie_attrs[] = {
+ /*
+ * The start address, and the limitation (64KB ~ (16MB - 16KB))
+ * of the ddr mem window reserved by RC, and used for EP to access.
+ * BTW, these attrs are only configured at EP side.
+ */
+ &dev_attr_rc_memw_info.attr,
+ &dev_attr_rc_memw_start_set.attr,
+ &dev_attr_rc_memw_size_set.attr,
+ NULL
+};
+
+static struct attribute_group imx_pcie_attrgroup = {
+ .attrs = imx_pcie_attrs,
+};
+#endif
+
+static int __devinit imx_pcie_pltfm_probe(struct platform_device *pdev)
+{
+#ifdef EP_SELF_IO_TEST
+ int i;
+#endif
+ int ret = 0;
+ struct resource *mem;
+ struct device *dev = &pdev->dev;
+ struct imx_pcie_platform_data *pdata = dev->platform_data;
+
+ pr_info("iMX6 PCIe %s mode %s entering.\n",
+ pdata->type_ep ? "PCIe EP" : "PCIe RC", __func__);
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(dev, "no mmio space\n");
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS
+ /* add attributes for device */
+ ret = sysfs_create_group(&pdev->dev.kobj, &imx_pcie_attrgroup);
+ if (ret)
+ return -EINVAL;
+#endif
+
+ /* Added for PCI abort handling */
+ hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
+ "imprecise external abort");
+
+ base = ioremap_nocache(PCIE_ARB_END_ADDR - SZ_1M + 1, SZ_1M - SZ_16K);
+ if (!base) {
+ pr_err("error with ioremap in function %s\n", __func__);
+ ret = PTR_ERR(base);
+#ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS
+ sysfs_remove_group(&pdev->dev.kobj, &imx_pcie_attrgroup);
+#endif
+ return ret;
+ }
+
+ dbi_base = devm_ioremap(dev, mem->start, resource_size(mem));
+ if (!dbi_base) {
+ dev_err(dev, "can't map %pR\n", mem);
+ ret = PTR_ERR(dbi_base);
+ goto err_base;
+ }
+
+ /* FIXME the field name should be aligned to RM */
+ imx_pcie_clrset(IOMUXC_GPR12_APP_LTSSM_ENABLE, 0 << 10, IOMUXC_GPR12);
+
+ /* configure constant input signal to the pcie ctrl and phy */
+ if (pdata->type_ep & 1)
+ /* EP */
+ imx_pcie_clrset(IOMUXC_GPR12_DEVICE_TYPE,
+ PCI_EXP_TYPE_ENDPOINT << 12, IOMUXC_GPR12);
+ else
+ /* RC */
+ imx_pcie_clrset(IOMUXC_GPR12_DEVICE_TYPE,
+ PCI_EXP_TYPE_ROOT_PORT << 12, IOMUXC_GPR12);
+ imx_pcie_clrset(IOMUXC_GPR12_LOS_LEVEL, 9 << 4, IOMUXC_GPR12);
+
+ imx_pcie_clrset(IOMUXC_GPR8_TX_DEEMPH_GEN1, 0 << 0, IOMUXC_GPR8);
+ imx_pcie_clrset(IOMUXC_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6, IOMUXC_GPR8);
+ imx_pcie_clrset(IOMUXC_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12, IOMUXC_GPR8);
+ imx_pcie_clrset(IOMUXC_GPR8_TX_SWING_FULL, 127 << 18, IOMUXC_GPR8);
+ imx_pcie_clrset(IOMUXC_GPR8_TX_SWING_LOW, 127 << 25, IOMUXC_GPR8);
+
+ /* Enable the pwr, clks and so on */
+ imx_pcie_enable_controller(dev);
+ if (!(pdata->type_ep)) {
+ /*Only RC: togle the external card's reset */
+ card_reset(dev) ;
+
+ imx_pcie_regions_setup(dev, dbi_base);
+ }
+
+ pr_info("PCIE: %s start link up.\n", __func__);
+ /* start link up */
+ imx_pcie_clrset(IOMUXC_GPR12_APP_LTSSM_ENABLE, 1 << 10, IOMUXC_GPR12);
+
+ if (pdata->type_ep) {
+#ifdef EP_SELF_IO_TEST
+ /* Prepare the test regions and data */
+ rc_ddr_test_reg1 = kzalloc(rc_ddr_test_region_size, GFP_KERNEL);
+ if (!rc_ddr_test_reg1)
+ pr_err("PCIe EP: can't alloc the test region1.\n");
+
+ rc_ddr_test_reg2 = kzalloc(rc_ddr_test_region_size, GFP_KERNEL);
+ if (!rc_ddr_test_reg2) {
+ kfree(rc_ddr_test_reg1);
+ pr_err("PCIe EP: can't alloc the test region2.\n");
+ }
+
+ pcie_arb_base_addr = ioremap_cached(PCIE_ARB_BASE_ADDR,
+ rc_ddr_test_region_size);
+
+ if (!pcie_arb_base_addr) {
+ pr_err("error with ioremap in function %s\n", __func__);
+ ret = PTR_ERR(pcie_arb_base_addr);
+ kfree(rc_ddr_test_reg2);
+ kfree(rc_ddr_test_reg1);
+ goto err_base;
+ }
+
+ for (i = 0; i < rc_ddr_test_region_size; i = i + 4) {
+ writel(0xE6600D00 + i, rc_ddr_test_reg1 + i);
+ writel(0xDEADBEAF, rc_ddr_test_reg2 + i);
+ }
+#endif
+
+ pr_info("PCIe EP: waiting for link up...\n");
+ /* link is debug bit 36 debug 1 start in bit 32 */
+ do {
+ usleep_range(10, 20);
+ } while ((readl(dbi_base + DB_R1) & 0x10) == 0);
+ /* Make sure that the PCIe link is up */
+ if (imx_pcie_link_up(dbi_base)) {
+ pr_info("PCIe EP: link up.\n");
+ } else {
+ pr_info("PCIe EP: ERROR link is down, exit!\n");
+#ifdef EP_SELF_IO_TEST
+ kfree(rc_ddr_test_reg2);
+ kfree(rc_ddr_test_reg1);
+ iounmap(pcie_arb_base_addr);
+#endif
+ goto err_link_down;
+ }
+
+ imx_pcie_regions_setup(dev, dbi_base);
+#ifdef EP_SELF_IO_TEST
+ /* PCIe EP start the data transfer after link up */
+ pr_info("PCIe EP: Starting data transfer...\n");
+ do_gettimeofday(&tv1);
+
+ memcpy((unsigned long *)pcie_arb_base_addr,
+ (unsigned long *)rc_ddr_test_reg1, 0xFFC000);
+
+ do_gettimeofday(&tv2);
+
+ memcpy((unsigned long *)rc_ddr_test_reg2,
+ (unsigned long *)pcie_arb_base_addr, 0xFFC000);
+
+ do_gettimeofday(&tv3);
+
+ if (memcmp(rc_ddr_test_reg2, rc_ddr_test_reg1, 0xFFC000) != 0) {
+ pr_info("PCIe EP: Data transfer is failed.\n");
+ } else {
+ tv_count1 = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC
+ + tv2.tv_usec - tv1.tv_usec;
+ tv_count2 = (tv3.tv_sec - tv2.tv_sec) * USEC_PER_SEC
+ + tv3.tv_usec - tv2.tv_usec;
+
+ pr_info("PCIe EP: Data transfer is successful."
+ "tv_count1 %dus, tv_count2 %dus.\n",
+ tv_count1, tv_count2);
+ pr_info("PCIe EP: Data write speed is %ldMB/s.\n",
+ ((((0xFFC000/1024) * MSEC_PER_SEC)))
+ /(tv_count1));
+ pr_info("PCIe EP: Data read speed is %ldMB/s.\n",
+ ((((0xFFC000/1024) * MSEC_PER_SEC)))
+ /(tv_count2));
+ }
+#endif
+
+ } else {
+ /* add the pcie port */
+ add_pcie_port(base, dbi_base, pdata);
+
+ pci_common_init(&imx_pci);
+ }
+ return 0;
+
+err_link_down:
+ iounmap(dbi_base);
+
+err_base:
+ iounmap(base);
+
+ return ret;
+}
+
+static struct platform_driver imx_pcie_pltfm_driver = {
+ .driver = {
+ .name = "imx-pcie",
+ .owner = THIS_MODULE,
+ },
+ .probe = imx_pcie_pltfm_probe,
+};
+
+/*****************************************************************************\
+ * *
+ * Driver init/exit *
+ * *
+\*****************************************************************************/
+
+static int __init imx_pcie_drv_init(void)
+{
+ return platform_driver_register(&imx_pcie_pltfm_driver);
+}
+
+static void __exit imx_pcie_drv_exit(void)
+{
+ platform_driver_unregister(&imx_pcie_pltfm_driver);
+}
+
+module_init(imx_pcie_drv_init);
+module_exit(imx_pcie_drv_exit);
+
+MODULE_DESCRIPTION("i.MX PCIE platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-mx6/plat_hotplug.c b/arch/arm/mach-mx6/plat_hotplug.c
new file mode 100644
index 00000000..20a33329
--- /dev/null
+++ b/arch/arm/mach-mx6/plat_hotplug.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011-2012 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 <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <linux/io.h>
+#include "src-reg.h"
+#include <linux/sched.h>
+#include <asm/cacheflush.h>
+
+extern unsigned int num_cpu_idle_lock;
+void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
+
+int platform_cpu_kill(unsigned int cpu)
+{
+ unsigned int val;
+
+ val = jiffies;
+ /* wait secondary cpu to die, timeout is 50ms */
+ while (__raw_readl(src_base + SRC_GPR1_OFFSET + (8 * cpu) + 4) == 0) {
+ if (time_after(jiffies, (unsigned long)(val + HZ / 20))) {
+ printk(KERN_WARNING "cpu %d: cpu could not die\n", cpu);
+ break;
+ }
+ }
+
+ /*
+ * we're ready for shutdown now, so do it
+ */
+ val = __raw_readl(src_base + SRC_SCR_OFFSET);
+ val &= ~(1 << (BP_SRC_SCR_CORES_DBG_RST + cpu));
+ val |= (1 << (BP_SRC_SCR_CORE0_RST + cpu));
+ __raw_writel(val, src_base + SRC_SCR_OFFSET);
+
+ val = jiffies;
+ /* wait secondary cpu reset done, timeout is 10ms */
+ while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
+ (1 << (BP_SRC_SCR_CORE0_RST + cpu))) != 0) {
+ if (time_after(jiffies, (unsigned long)(val + HZ / 100))) {
+ printk(KERN_WARNING "cpu %d: cpu reset fail\n", cpu);
+ break;
+ }
+ }
+
+ __raw_writel(0x0, src_base + SRC_GPR1_OFFSET + (8 * cpu) + 4);
+ return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+ unsigned int v;
+ if (cpu == 0) {
+ printk(KERN_ERR "CPU0 can't be disabled!\n");
+ return;
+ }
+ flush_cache_all();
+ asm volatile(
+ " mcr p15, 0, %1, c7, c5, 0\n" /* Invalidate I cache */
+ " mcr p15, 0, %1, c7, c10, 4\n" /* DSB */
+ /*
+ * Turn off coherency
+ */
+ " mrc p15, 0, %0, c1, c0, 1\n" /* Disable SMP in ACTLR */
+ " bic %0, %0, %3\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ " mrc p15, 0, %0, c1, c0, 0\n" /* Disable D cache in SCTLR */
+ " bic %0, %0, %2\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ : "=&r" (v)
+ : "r" (0), "Ir" (CR_C), "Ir" (0x40)
+ : "cc");
+ /* Tell cpu0 to kill this core, as this core's cache is
+ already disabled, and we want to set a flag to tell cpu0
+ to kill this core, so I write the flag to this core's SRC
+ parameter register, after cpu0 kill this core, it will
+ clear this register. */
+
+ __raw_writel(0x1, src_base + SRC_GPR1_OFFSET + (8 * cpu) + 4);
+
+ for (;;) {
+ /*
+ * Execute WFI
+ */
+ asm(".word 0xe320f003\n"
+ :
+ :
+ : "memory", "cc");
+ printk(KERN_ERR "cpu %d wake up from wfi !!!\n", cpu);
+ }
+ asm volatile(
+ " mrc p15, 0, %0, c1, c0, 0\n" /* Enable D cache in SCTLR */
+ " orr %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ " mrc p15, 0, %0, c1, c0, 1\n" /* Enable SMP in ACTLR */
+ " orr %0, %0, %2\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (CR_C), "Ir" (0x40)
+ : "cc");
+ __raw_writel(0x0, src_base + SRC_GPR1_OFFSET + (8 * cpu) + 4);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+ /*
+ * we don't allow CPU 0 to be shutdown (it is still too special
+ * e.g. clock tick interrupts)
+ */
+ *((char *)(&num_cpu_idle_lock) + (u8)cpu) = 0xff;
+ return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-mx6/platsmp.c b/arch/arm/mach-mx6/platsmp.c
new file mode 100644
index 00000000..a21f0231
--- /dev/null
+++ b/arch/arm/mach-mx6/platsmp.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2011-2012 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 <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/mach-types.h>
+#include <asm/localtimer.h>
+#include <asm/smp_scu.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/mx6.h>
+#include <mach/smp.h>
+#include "src-reg.h"
+
+static DEFINE_SPINLOCK(boot_lock);
+
+static void __iomem *scu_base_addr(void)
+{
+ return IO_ADDRESS(SCU_BASE_ADDR);
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+ trace_hardirqs_off();
+
+ spin_lock(&boot_lock);
+ /*
+ * if any interrupts are already enabled for the primary
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+ gic_secondary_init(0);
+
+ /*
+ * Synchronise with the boot thread.
+ */
+
+ spin_unlock(&boot_lock);
+
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned long boot_entry;
+ void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
+ unsigned int val;
+
+ /*
+ * set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ spin_lock(&boot_lock);
+
+ /* set entry point for cpu1-cpu3*/
+ boot_entry = virt_to_phys(mx6_secondary_startup);
+
+ writel(boot_entry, src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu);
+ writel(0, src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu + 4);
+
+ smp_wmb();
+ dsb();
+ flush_cache_all();
+
+ /* reset cpu<n> */
+ val = readl(src_base + SRC_SCR_OFFSET);
+ val |= 1 << (BP_SRC_SCR_CORE0_RST + cpu);
+ val |= 1 << (BP_SRC_SCR_CORES_DBG_RST + cpu);
+ writel(val, src_base + SRC_SCR_OFFSET);
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ spin_unlock(&boot_lock);
+
+ return 0;
+
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+ void __iomem *scu_base = scu_base_addr();
+ unsigned int i, ncores;
+
+ ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+
+ /* sanity check */
+ if (ncores == 0) {
+ pr_err("mx6: strange CM count of 0? Default to 1\n");
+ ncores = 1;
+ }
+ if (ncores > NR_CPUS) {
+ pr_warning("mx6: no. of cores (%d) greater than configured "
+ "maximum of %d - clipping\n",
+ ncores, NR_CPUS);
+ ncores = NR_CPUS;
+ }
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ set_smp_cross_call(gic_raise_softirq);
+}
+static void __init wakeup_secondary(void)
+{
+
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+ int i;
+ void __iomem *scu_base = scu_base_addr();
+
+ /*
+ * Initialise the present map, which describes the set of CPUs
+ * actually populated at the present time.
+ */
+ for (i = 0; i < max_cpus; i++)
+ set_cpu_present(i, true);
+
+ /*
+ * Initialise the SCU and wake up the secondary core using
+ * wakeup_secondary().
+ */
+ scu_enable(scu_base);
+ wakeup_secondary();
+}
diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c
new file mode 100644
index 00000000..a6b4c748
--- /dev/null
+++ b/arch/arm/mach-mx6/pm.c
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2011-2013 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 <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/proc_fs.h>
+#include <linux/iram_alloc.h>
+#include <linux/fsl_devices.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/tlb.h>
+#include <asm/delay.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+#include <mach/imx-pm.h>
+#include <mach/arc_otg.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#ifdef CONFIG_ARCH_MX6Q
+#include <mach/iomux-mx6q.h>
+#endif
+#include "crm_regs.h"
+#include "src-reg.h"
+#include "regs-anadig.h"
+
+#define SCU_CTRL_OFFSET 0x00
+#define GPC_IMR1_OFFSET 0x08
+#define GPC_IMR2_OFFSET 0x0c
+#define GPC_IMR3_OFFSET 0x10
+#define GPC_IMR4_OFFSET 0x14
+#define GPC_ISR1_OFFSET 0x18
+#define GPC_ISR2_OFFSET 0x1c
+#define GPC_ISR3_OFFSET 0x20
+#define GPC_ISR4_OFFSET 0x24
+#define GPC_CNTR_OFFSET 0x0
+#define GPC_PGC_DISP_PGCR_OFFSET 0x240
+#define GPC_PGC_DISP_PUPSCR_OFFSET 0x244
+#define GPC_PGC_DISP_PDNSCR_OFFSET 0x248
+#define GPC_PGC_DISP_SR_OFFSET 0x24c
+#define GPC_PGC_GPU_PGCR_OFFSET 0x260
+#define GPC_PGC_CPU_PDN_OFFSET 0x2a0
+#define GPC_PGC_CPU_PUPSCR_OFFSET 0x2a4
+#define GPC_PGC_CPU_PDNSCR_OFFSET 0x2a8
+#define UART_UCR3_OFFSET 0x88
+#define UART_USR1_OFFSET 0x94
+#define UART_UCR3_AWAKEN (1 << 4)
+#define UART_USR1_AWAKE (1 << 4)
+#define LOCAL_TWD_LOAD_OFFSET 0x0
+#define LOCAL_TWD_COUNT_OFFSET 0x4
+#define LOCAL_TWD_CONTROL_OFFSET 0x8
+#define LOCAL_TWD_INT_OFFSET 0xc
+#define ANATOP_REG_1P1_OFFSET 0x110
+#define ANATOP_REG_2P5_OFFSET 0x130
+#define ANATOP_REG_CORE_OFFSET 0x140
+#define VDD3P0_VOLTAGE 3200000
+
+static struct clk *cpu_clk;
+static struct clk *axi_clk;
+static struct clk *periph_clk;
+static struct clk *pll3_usb_otg_main_clk;
+static struct regulator *vdd3p0_regulator;
+
+static struct pm_platform_data *pm_data;
+
+
+#if defined(CONFIG_CPU_FREQ)
+extern int set_cpu_freq(int wp);
+#endif
+extern void mx6_suspend(suspend_state_t state);
+extern void mx6_init_irq(void);
+extern unsigned int gpc_wake_irq[4];
+extern bool enable_wait_mode;
+extern unsigned long save_ttbr1(void);
+extern void restore_ttbr1(u32 ttbr1);
+extern int pu_disable(struct anatop_regulator *sreg);
+
+static struct device *pm_dev;
+struct clk *gpc_dvfs_clk;
+static void __iomem *scu_base;
+static void __iomem *gpc_base;
+static void __iomem *src_base;
+static void __iomem *local_twd_base;
+static void __iomem *gic_dist_base;
+static void __iomem *gic_cpu_base;
+static void __iomem *anatop_base;
+
+static void (*suspend_in_iram)(suspend_state_t state,
+ unsigned long iram_paddr, unsigned long suspend_iram_base, unsigned int cpu_type) = NULL;
+static unsigned long cpaddr;
+
+static u32 ccm_ccr, ccm_clpcr, scu_ctrl;
+static u32 gpc_imr[4], gpc_cpu_pup, gpc_cpu_pdn, gpc_cpu, gpc_ctr, gpc_disp;
+static u32 anatop[3], ccgr1, ccgr2, ccgr3, ccgr6;
+static u32 ccm_analog_pfd528;
+static u32 ccm_analog_pll3_480;
+static u32 ccm_anadig_ana_misc2;
+static bool usb_vbus_wakeup_enabled;
+
+void *suspend_iram_base;
+unsigned long suspend_iram_phys_addr;
+
+/*
+ * The USB VBUS wakeup should be disabled to avoid vbus wake system
+ * up due to vbus comparator is closed at weak 2p5 mode.
+ */
+static void usb_power_down_handler(void)
+{
+ u32 temp;
+ bool usb_oh3_clk_already_on;
+ if ((__raw_readl(anatop_base + HW_ANADIG_ANA_MISC0)
+ & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) != 0) {
+ usb_vbus_wakeup_enabled = false;
+ return;
+ }
+ /* enable usb oh3 clock if needed*/
+ temp = __raw_readl(MXC_CCM_CCGR6);
+ usb_oh3_clk_already_on = \
+ ((temp & (MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG0_OFFSET)) \
+ == (MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG0_OFFSET));
+ if (!usb_oh3_clk_already_on) {
+ temp |= MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG0_OFFSET;
+ __raw_writel(temp, MXC_CCM_CCGR6);
+ }
+ /* disable vbus wakeup */
+ usb_vbus_wakeup_enabled = !!(USB_OTG_CTRL & UCTRL_WKUP_VBUS_EN);
+ if (usb_vbus_wakeup_enabled) {
+ USB_OTG_CTRL &= ~UCTRL_WKUP_VBUS_EN;
+ }
+ /* disable usb oh3 clock */
+ if (!usb_oh3_clk_already_on) {
+ temp = __raw_readl(MXC_CCM_CCGR6);
+ temp &= ~(MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG0_OFFSET);
+ __raw_writel(temp, MXC_CCM_CCGR6);
+ }
+}
+
+static void usb_power_up_handler(void)
+{
+ /* enable vbus wakeup at runtime if needed */
+ if (usb_vbus_wakeup_enabled) {
+ u32 temp;
+ bool usb_oh3_clk_already_on;
+ /* enable usb oh3 clock if needed*/
+ temp = __raw_readl(MXC_CCM_CCGR6);
+ usb_oh3_clk_already_on = \
+ ((temp & (MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG0_OFFSET)) \
+ == (MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG0_OFFSET));
+ if (!usb_oh3_clk_already_on) {
+ temp |= MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG0_OFFSET;
+ __raw_writel(temp, MXC_CCM_CCGR6);
+ }
+
+ /* restore usb wakeup enable setting */
+ USB_OTG_CTRL |= UCTRL_WKUP_VBUS_EN;
+
+ /* disable usb oh3 clock */
+ if (!usb_oh3_clk_already_on) {
+ temp = __raw_readl(MXC_CCM_CCGR6);
+ temp &= ~(MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG0_OFFSET);
+ __raw_writel(temp, MXC_CCM_CCGR6);
+ }
+ }
+}
+
+
+static void disp_power_down(void)
+{
+ if (cpu_is_mx6sl() && (mx6sl_revision() >= IMX_CHIP_REVISION_1_2)) {
+
+ __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET);
+ __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET);
+
+ __raw_writel(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+ __raw_writel(0x10, gpc_base + GPC_CNTR_OFFSET);
+
+ /* Disable EPDC/LCDIF pix clock, and EPDC/LCDIF/PXP axi clock */
+ __raw_writel(ccgr3 &
+ ~MXC_CCM_CCGRx_CG5_MASK &
+ ~MXC_CCM_CCGRx_CG4_MASK &
+ ~MXC_CCM_CCGRx_CG3_MASK &
+ ~MXC_CCM_CCGRx_CG2_MASK &
+ ~MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3);
+
+ }
+}
+
+static void disp_power_up(void)
+{
+ if (cpu_is_mx6sl() && (mx6sl_revision() >= IMX_CHIP_REVISION_1_2)) {
+ /*
+ * Need to enable EPDC/LCDIF pix clock, and
+ * EPDC/LCDIF/PXP axi clock before power up.
+ */
+ __raw_writel(ccgr3 |
+ MXC_CCM_CCGRx_CG5_MASK |
+ MXC_CCM_CCGRx_CG4_MASK |
+ MXC_CCM_CCGRx_CG3_MASK |
+ MXC_CCM_CCGRx_CG2_MASK |
+ MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3);
+
+ __raw_writel(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+ __raw_writel(0x20, gpc_base + GPC_CNTR_OFFSET);
+ __raw_writel(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET);
+ }
+}
+
+static void mx6_suspend_store(void)
+{
+ /* save some settings before suspend */
+ ccm_ccr = __raw_readl(MXC_CCM_CCR);
+ ccm_clpcr = __raw_readl(MXC_CCM_CLPCR);
+ ccm_analog_pfd528 = __raw_readl(PFD_528_BASE_ADDR);
+ ccm_analog_pll3_480 = __raw_readl(PLL3_480_USB1_BASE_ADDR);
+ ccm_anadig_ana_misc2 = __raw_readl(MXC_PLL_BASE + HW_ANADIG_ANA_MISC2);
+ ccgr1 = __raw_readl(MXC_CCM_CCGR1);
+ ccgr2 = __raw_readl(MXC_CCM_CCGR2);
+ ccgr3 = __raw_readl(MXC_CCM_CCGR3);
+ ccgr6 = __raw_readl(MXC_CCM_CCGR6);
+ scu_ctrl = __raw_readl(scu_base + SCU_CTRL_OFFSET);
+ gpc_imr[0] = __raw_readl(gpc_base + GPC_IMR1_OFFSET);
+ gpc_imr[1] = __raw_readl(gpc_base + GPC_IMR2_OFFSET);
+ gpc_imr[2] = __raw_readl(gpc_base + GPC_IMR3_OFFSET);
+ gpc_imr[3] = __raw_readl(gpc_base + GPC_IMR4_OFFSET);
+ gpc_cpu_pup = __raw_readl(gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
+ gpc_cpu_pdn = __raw_readl(gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
+ gpc_cpu = __raw_readl(gpc_base + GPC_PGC_CPU_PDN_OFFSET);
+ gpc_ctr = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+ if (cpu_is_mx6sl())
+ gpc_disp = __raw_readl(gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+ anatop[0] = __raw_readl(anatop_base + ANATOP_REG_2P5_OFFSET);
+ anatop[1] = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
+ anatop[2] = __raw_readl(anatop_base + ANATOP_REG_1P1_OFFSET);
+}
+
+static void mx6_suspend_restore(void)
+{
+ /* restore settings after suspend */
+ __raw_writel(anatop[0], anatop_base + ANATOP_REG_2P5_OFFSET);
+ __raw_writel(anatop[1], anatop_base + ANATOP_REG_CORE_OFFSET);
+ __raw_writel(anatop[2], anatop_base + ANATOP_REG_1P1_OFFSET);
+ /* Per spec, the count needs to be zeroed and reconfigured on exit from
+ * low power mode
+ */
+ __raw_writel(ccm_ccr & ~MXC_CCM_CCR_REG_BYPASS_CNT_MASK &
+ ~MXC_CCM_CCR_WB_COUNT_MASK, MXC_CCM_CCR);
+ udelay(50);
+ __raw_writel(ccm_ccr, MXC_CCM_CCR);
+ __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+ __raw_writel(scu_ctrl, scu_base + SCU_CTRL_OFFSET);
+ __raw_writel(gpc_imr[0], gpc_base + GPC_IMR1_OFFSET);
+ __raw_writel(gpc_imr[1], gpc_base + GPC_IMR2_OFFSET);
+ __raw_writel(gpc_imr[2], gpc_base + GPC_IMR3_OFFSET);
+ __raw_writel(gpc_imr[3], gpc_base + GPC_IMR4_OFFSET);
+ __raw_writel(gpc_cpu_pup, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
+ __raw_writel(gpc_cpu_pdn, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
+ __raw_writel(gpc_cpu, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
+ if (cpu_is_mx6sl())
+ __raw_writel(gpc_disp, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+ __raw_writel(ccgr1, MXC_CCM_CCGR1);
+ __raw_writel(ccgr2, MXC_CCM_CCGR2);
+ __raw_writel(ccgr3, MXC_CCM_CCGR3);
+ __raw_writel(ccgr6, MXC_CCM_CCGR6);
+ __raw_writel(ccm_analog_pfd528, PFD_528_BASE_ADDR);
+ __raw_writel(ccm_analog_pll3_480, PLL3_480_USB1_BASE_ADDR);
+ __raw_writel(ccm_anadig_ana_misc2, MXC_PLL_BASE + HW_ANADIG_ANA_MISC2);
+}
+
+static int mx6_suspend_enter(suspend_state_t state)
+{
+ unsigned int wake_irq_isr[4];
+ unsigned int cpu_type;
+ struct gic_dist_state gds;
+ struct gic_cpu_state gcs;
+ bool arm_pg = false;
+
+ if (cpu_is_mx6q())
+ cpu_type = MXC_CPU_MX6Q;
+ else if (cpu_is_mx6dl())
+ cpu_type = MXC_CPU_MX6DL;
+ else
+ cpu_type = MXC_CPU_MX6SL;
+
+ wake_irq_isr[0] = __raw_readl(gpc_base +
+ GPC_ISR1_OFFSET) & gpc_wake_irq[0];
+ wake_irq_isr[1] = __raw_readl(gpc_base +
+ GPC_ISR2_OFFSET) & gpc_wake_irq[1];
+ wake_irq_isr[2] = __raw_readl(gpc_base +
+ GPC_ISR3_OFFSET) & gpc_wake_irq[2];
+ wake_irq_isr[3] = __raw_readl(gpc_base +
+ GPC_ISR4_OFFSET) & gpc_wake_irq[3];
+ if (wake_irq_isr[0] | wake_irq_isr[1] |
+ wake_irq_isr[2] | wake_irq_isr[3]) {
+ printk(KERN_INFO "There are wakeup irq pending,system resume!\n");
+ printk(KERN_INFO "wake_irq_isr[0-3]: 0x%x, 0x%x, 0x%x, 0x%x\n",
+ wake_irq_isr[0], wake_irq_isr[1],
+ wake_irq_isr[2], wake_irq_isr[3]);
+ return 0;
+ }
+ mx6_suspend_store();
+
+ /*
+ * i.MX6dl TO1.0/i.MX6dq TO1.1/1.0 TKT094231: can't support
+ * ARM_POWER_OFF mode.
+ */
+ if (state == PM_SUSPEND_MEM &&
+ ((mx6dl_revision() == IMX_CHIP_REVISION_1_0) ||
+ (cpu_is_mx6q() && mx6q_revision() <= IMX_CHIP_REVISION_1_1))) {
+ state = PM_SUSPEND_STANDBY;
+ }
+
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ disp_power_down();
+ usb_power_down_handler();
+#ifndef CONFIG_MXC_GPU_VIV
+ pu_disable(NULL);
+#endif
+ mxc_cpu_lp_set(ARM_POWER_OFF);
+ arm_pg = true;
+ break;
+ case PM_SUSPEND_STANDBY:
+ if (cpu_is_mx6sl()) {
+ disp_power_down();
+ usb_power_down_handler();
+#ifndef CONFIG_MXC_GPU_VIV
+ pu_disable(NULL);
+#endif
+ mxc_cpu_lp_set(STOP_XTAL_ON);
+ arm_pg = true;
+ } else
+ mxc_cpu_lp_set(STOP_POWER_OFF);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * L2 can exit by 'reset' or Inband beacon (from remote EP)
+ * toggling phy_powerdown has same effect as 'inband beacon'
+ * So, toggle bit18 of GPR1, to fix errata
+ * "PCIe PCIe does not support L2 Power Down"
+ */
+ __raw_writel(__raw_readl(IOMUXC_GPR1) | (1 << 18), IOMUXC_GPR1);
+
+ if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) {
+ u32 ttbr1;
+
+ flush_cache_all();
+
+ if (arm_pg) {
+ /* preserve gic state */
+ save_gic_dist_state(0, &gds);
+ save_gic_cpu_state(0, &gcs);
+ }
+
+ if (pm_data && pm_data->suspend_enter)
+ pm_data->suspend_enter();
+
+ ttbr1 = save_ttbr1();
+ suspend_in_iram(state, (unsigned long)suspend_iram_phys_addr,
+ (unsigned long)suspend_iram_base, cpu_type);
+ restore_ttbr1(ttbr1);
+
+ if (pm_data && pm_data->suspend_exit)
+ pm_data->suspend_exit();
+
+ /* Reset the RBC counter. */
+ /* All interrupts should be masked before the
+ * RBC counter is reset.
+ */
+ /* Mask all interrupts. These will be unmasked by
+ * the mx6_suspend_restore routine below.
+ */
+ __raw_writel(0xffffffff, gpc_base + 0x08);
+ __raw_writel(0xffffffff, gpc_base + 0x0c);
+ __raw_writel(0xffffffff, gpc_base + 0x10);
+ __raw_writel(0xffffffff, gpc_base + 0x14);
+
+ /* Clear the RBC counter and RBC_EN bit. */
+ /* Disable the REG_BYPASS_COUNTER. */
+ __raw_writel(__raw_readl(MXC_CCM_CCR) &
+ ~MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR);
+ /* Make sure we clear REG_BYPASS_COUNT*/
+ __raw_writel(__raw_readl(MXC_CCM_CCR) &
+ (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR);
+ /* Need to wait for a minimum of 2 CLKILS (32KHz) for the
+ * counter to clear and reset.
+ */
+ udelay(80);
+
+ if (arm_pg) {
+ /* restore gic registers */
+ restore_gic_dist_state(0, &gds);
+ restore_gic_cpu_state(0, &gcs);
+ }
+ if (state == PM_SUSPEND_MEM || (cpu_is_mx6sl())) {
+ usb_power_up_handler();
+ disp_power_up();
+ }
+
+ mx6_suspend_restore();
+
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ anatop_base + HW_ANADIG_ANA_MISC0_CLR);
+
+ } else {
+ cpu_do_idle();
+ }
+
+ /*
+ * L2 can exit by 'reset' or Inband beacon (from remote EP)
+ * toggling phy_powerdown has same effect as 'inband beacon'
+ * So, toggle bit18 of GPR1, to fix errata
+ * "PCIe PCIe does not support L2 Power Down"
+ */
+ __raw_writel(__raw_readl(IOMUXC_GPR1) & (~(1 << 18)), IOMUXC_GPR1);
+
+ return 0;
+}
+
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int mx6_suspend_prepare(void)
+{
+ int ret;
+ ret = regulator_disable(vdd3p0_regulator);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to disable 3p0 regulator Err: %d\n",
+ __func__, ret);
+ }
+ return 0;
+}
+
+/*
+ * Called before devices are re-setup.
+ */
+static void mx6_suspend_finish(void)
+{
+ int ret;
+ ret = regulator_enable(vdd3p0_regulator);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to enable 3p0 regulator Err: %d\n",
+ __func__, ret);
+ }
+}
+
+static int mx6_suspend_begin(suspend_state_t state)
+{
+ return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+
+static int mx6_pm_valid(suspend_state_t state)
+{
+ return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+struct platform_suspend_ops mx6_suspend_ops = {
+ .valid = mx6_pm_valid,
+ .begin = mx6_suspend_begin,
+ .prepare = mx6_suspend_prepare,
+ .enter = mx6_suspend_enter,
+ .finish = mx6_suspend_finish,
+};
+
+static int __devinit mx6_pm_probe(struct platform_device *pdev)
+{
+ pm_dev = &pdev->dev;
+ pm_data = pdev->dev.platform_data;
+
+ return 0;
+}
+
+static struct platform_driver mx6_pm_driver = {
+ .driver = {
+ .name = "imx_pm",
+ },
+ .probe = mx6_pm_probe,
+};
+
+static int __init pm_init(void)
+{
+ int ret = 0;
+ scu_base = IO_ADDRESS(SCU_BASE_ADDR);
+ gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+ src_base = IO_ADDRESS(SRC_BASE_ADDR);
+ gic_dist_base = IO_ADDRESS(IC_DISTRIBUTOR_BASE_ADDR);
+ gic_cpu_base = IO_ADDRESS(IC_INTERFACES_BASE_ADDR);
+ local_twd_base = IO_ADDRESS(LOCAL_TWD_ADDR);
+ anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR);
+
+ pr_info("Static Power Management for Freescale i.MX6\n");
+
+ pr_info("wait mode is %s for i.MX6\n", enable_wait_mode ?
+ "enabled" : "disabled");
+
+ if (platform_driver_register(&mx6_pm_driver) != 0) {
+ printk(KERN_ERR "mx6_pm_driver register failed\n");
+ return -ENODEV;
+ }
+
+ suspend_set_ops(&mx6_suspend_ops);
+ /* Use preallocated IRAM memory. */
+ suspend_iram_phys_addr = MX6_SUSPEND_IRAM_CODE;
+
+ /* Dont ioremap the address, we have fixed the IRAM address at IRAM_BASE_ADDR_VIRT */
+ suspend_iram_base = IRAM_BASE_ADDR_VIRT + (suspend_iram_phys_addr - IRAM_BASE_ADDR);
+
+ pr_info("cpaddr = %x suspend_iram_base=%x\n",
+ (unsigned int)cpaddr, (unsigned int)suspend_iram_base);
+
+ /*
+ * Need to run the suspend code from IRAM as the DDR needs
+ * to be put into low power mode manually.
+ */
+ memcpy((void *)suspend_iram_base, mx6_suspend, MX6_SUSPEND_CODE_SIZE);
+
+ suspend_in_iram = (void *)suspend_iram_base;
+
+ cpu_clk = clk_get(NULL, "cpu_clk");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__);
+ return PTR_ERR(cpu_clk);
+ }
+ axi_clk = clk_get(NULL, "axi_clk");
+ if (IS_ERR(axi_clk)) {
+ printk(KERN_DEBUG "%s: failed to get axi_clk\n", __func__);
+ return PTR_ERR(axi_clk);
+ }
+ periph_clk = clk_get(NULL, "periph_clk");
+ if (IS_ERR(periph_clk)) {
+ printk(KERN_DEBUG "%s: failed to get periph_clk\n", __func__);
+ return PTR_ERR(periph_clk);
+ }
+ pll3_usb_otg_main_clk = clk_get(NULL, "pll3_main_clk");
+ if (IS_ERR(pll3_usb_otg_main_clk)) {
+ printk(KERN_DEBUG "%s: failed to get pll3_main_clk\n", __func__);
+ return PTR_ERR(pll3_usb_otg_main_clk);
+ }
+
+ vdd3p0_regulator = regulator_get(NULL, "cpu_vdd3p0");
+ if (IS_ERR(vdd3p0_regulator)) {
+ printk(KERN_ERR "%s: failed to get 3p0 regulator Err: %d\n",
+ __func__, ret);
+ return PTR_ERR(vdd3p0_regulator);
+ }
+ ret = regulator_set_voltage(vdd3p0_regulator, VDD3P0_VOLTAGE,
+ VDD3P0_VOLTAGE);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to set 3p0 regulator voltage Err: %d\n",
+ __func__, ret);
+ }
+ ret = regulator_enable(vdd3p0_regulator);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to enable 3p0 regulator Err: %d\n",
+ __func__, ret);
+ }
+
+ printk(KERN_INFO "PM driver module loaded\n");
+
+ return 0;
+}
+
+static void __exit pm_cleanup(void)
+{
+ /* Unregister the device structure */
+ platform_driver_unregister(&mx6_pm_driver);
+ regulator_put(vdd3p0_regulator);
+}
+
+module_init(pm_init);
+module_exit(pm_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("PM driver");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/mach-mx6/regs-anadig.h b/arch/arm/mach-mx6/regs-anadig.h
new file mode 100644
index 00000000..b1d16456
--- /dev/null
+++ b/arch/arm/mach-mx6/regs-anadig.h
@@ -0,0 +1,1011 @@
+/*
+ * Copyright (C) 2011-2013 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.
+ */
+
+/*
+ * Freescale ANADIG Register Definitions
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.30
+ * Template revision: 1.3
+ */
+
+#ifndef __ARCH_ARM___ANADIG_H
+#define __ARCH_ARM___ANADIG_H
+
+
+#define HW_ANADIG_PLL_SYS (0x00000000)
+#define HW_ANADIG_PLL_SYS_SET (0x00000004)
+#define HW_ANADIG_PLL_SYS_CLR (0x00000008)
+#define HW_ANADIG_PLL_SYS_TOG (0x0000000c)
+
+#define BM_ANADIG_PLL_SYS_LOCK 0x80000000
+#define BP_ANADIG_PLL_SYS_RSVD0 20
+#define BM_ANADIG_PLL_SYS_RSVD0 0x7FF00000
+#define BF_ANADIG_PLL_SYS_RSVD0(v) \
+ (((v) << 20) & BM_ANADIG_PLL_SYS_RSVD0)
+#define BM_ANADIG_PLL_SYS_PLL_SEL 0x00080000
+#define BM_ANADIG_PLL_SYS_LVDS_24MHZ_SEL 0x00040000
+#define BM_ANADIG_PLL_SYS_LVDS_SEL 0x00020000
+#define BM_ANADIG_PLL_SYS_BYPASS 0x00010000
+#define BP_ANADIG_PLL_SYS_BYPASS_CLK_SRC 14
+#define BM_ANADIG_PLL_SYS_BYPASS_CLK_SRC 0x0000C000
+#define BF_ANADIG_PLL_SYS_BYPASS_CLK_SRC(v) \
+ (((v) << 14) & BM_ANADIG_PLL_SYS_BYPASS_CLK_SRC)
+#define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__OSC_24M 0x0
+#define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__ANACLK_1 0x1
+#define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__ANACLK_2 0x2
+#define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__XOR 0x3
+#define BM_ANADIG_PLL_SYS_ENABLE 0x00002000
+#define BM_ANADIG_PLL_SYS_POWERDOWN 0x00001000
+#define BM_ANADIG_PLL_SYS_HOLD_RING_OFF 0x00000800
+#define BM_ANADIG_PLL_SYS_DOUBLE_CP 0x00000400
+#define BM_ANADIG_PLL_SYS_HALF_CP 0x00000200
+#define BM_ANADIG_PLL_SYS_DOUBLE_LF 0x00000100
+#define BM_ANADIG_PLL_SYS_HALF_LF 0x00000080
+#define BP_ANADIG_PLL_SYS_DIV_SELECT 0
+#define BM_ANADIG_PLL_SYS_DIV_SELECT 0x0000007F
+#define BF_ANADIG_PLL_SYS_DIV_SELECT(v) \
+ (((v) << 0) & BM_ANADIG_PLL_SYS_DIV_SELECT)
+
+#define HW_ANADIG_USB1_PLL_480_CTRL (0x00000010)
+#define HW_ANADIG_USB1_PLL_480_CTRL_SET (0x00000014)
+#define HW_ANADIG_USB1_PLL_480_CTRL_CLR (0x00000018)
+#define HW_ANADIG_USB1_PLL_480_CTRL_TOG (0x0000001c)
+
+#define BM_ANADIG_USB1_PLL_480_CTRL_LOCK 0x80000000
+#define BP_ANADIG_USB1_PLL_480_CTRL_RSVD1 17
+#define BM_ANADIG_USB1_PLL_480_CTRL_RSVD1 0x7FFE0000
+#define BF_ANADIG_USB1_PLL_480_CTRL_RSVD1(v) \
+ (((v) << 17) & BM_ANADIG_USB1_PLL_480_CTRL_RSVD1)
+#define BM_ANADIG_USB1_PLL_480_CTRL_BYPASS 0x00010000
+#define BP_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC 14
+#define BM_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC 0x0000C000
+#define BF_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC(v) \
+ (((v) << 14) & BM_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC)
+#define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__OSC_24M 0x0
+#define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_1 0x1
+#define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_2 0x2
+#define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__XOR 0x3
+#define BM_ANADIG_USB1_PLL_480_CTRL_ENABLE 0x00002000
+#define BM_ANADIG_USB1_PLL_480_CTRL_POWER 0x00001000
+#define BM_ANADIG_USB1_PLL_480_CTRL_HOLD_RING_OFF 0x00000800
+#define BM_ANADIG_USB1_PLL_480_CTRL_DOUBLE_CP 0x00000400
+#define BM_ANADIG_USB1_PLL_480_CTRL_HALF_CP 0x00000200
+#define BM_ANADIG_USB1_PLL_480_CTRL_DOUBLE_LF 0x00000100
+#define BM_ANADIG_USB1_PLL_480_CTRL_HALF_LF 0x00000080
+#define BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS 0x00000040
+#define BM_ANADIG_USB1_PLL_480_CTRL_RSVD0 0x00000020
+#define BP_ANADIG_USB1_PLL_480_CTRL_CONTROL0 2
+#define BM_ANADIG_USB1_PLL_480_CTRL_CONTROL0 0x0000001C
+#define BF_ANADIG_USB1_PLL_480_CTRL_CONTROL0(v) \
+ (((v) << 2) & BM_ANADIG_USB1_PLL_480_CTRL_CONTROL0)
+#define BP_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT 0
+#define BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT 0x00000003
+#define BF_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT(v) \
+ (((v) << 0) & BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT)
+
+#define HW_ANADIG_USB2_PLL_480_CTRL (0x00000020)
+#define HW_ANADIG_USB2_PLL_480_CTRL_SET (0x00000024)
+#define HW_ANADIG_USB2_PLL_480_CTRL_CLR (0x00000028)
+#define HW_ANADIG_USB2_PLL_480_CTRL_TOG (0x0000002c)
+
+#define BM_ANADIG_USB2_PLL_480_CTRL_LOCK 0x80000000
+#define BP_ANADIG_USB2_PLL_480_CTRL_RSVD1 17
+#define BM_ANADIG_USB2_PLL_480_CTRL_RSVD1 0x7FFE0000
+#define BF_ANADIG_USB2_PLL_480_CTRL_RSVD1(v) \
+ (((v) << 17) & BM_ANADIG_USB2_PLL_480_CTRL_RSVD1)
+#define BM_ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000
+#define BP_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC 14
+#define BM_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC 0x0000C000
+#define BF_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC(v) \
+ (((v) << 14) & BM_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC)
+#define BV_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC__OSC_24M 0x0
+#define BV_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_1 0x1
+#define BV_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_2 0x2
+#define BV_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC__XOR 0x3
+#define BM_ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000
+#define BM_ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000
+#define BM_ANADIG_USB2_PLL_480_CTRL_HOLD_RING_OFF 0x00000800
+#define BM_ANADIG_USB2_PLL_480_CTRL_DOUBLE_CP 0x00000400
+#define BM_ANADIG_USB2_PLL_480_CTRL_HALF_CP 0x00000200
+#define BM_ANADIG_USB2_PLL_480_CTRL_DOUBLE_LF 0x00000100
+#define BM_ANADIG_USB2_PLL_480_CTRL_HALF_LF 0x00000080
+#define BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040
+#define BM_ANADIG_USB2_PLL_480_CTRL_RSVD0 0x00000020
+#define BP_ANADIG_USB2_PLL_480_CTRL_CONTROL0 2
+#define BM_ANADIG_USB2_PLL_480_CTRL_CONTROL0 0x0000001C
+#define BF_ANADIG_USB2_PLL_480_CTRL_CONTROL0(v) \
+ (((v) << 2) & BM_ANADIG_USB2_PLL_480_CTRL_CONTROL0)
+#define BP_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT 0
+#define BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT 0x00000003
+#define BF_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT(v) \
+ (((v) << 0) & BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT)
+
+#define HW_ANADIG_PLL_528 (0x00000030)
+#define HW_ANADIG_PLL_528_SET (0x00000034)
+#define HW_ANADIG_PLL_528_CLR (0x00000038)
+#define HW_ANADIG_PLL_528_TOG (0x0000003c)
+
+#define BM_ANADIG_PLL_528_LOCK 0x80000000
+#define BP_ANADIG_PLL_528_RSVD1 19
+#define BM_ANADIG_PLL_528_RSVD1 0x7FF80000
+#define BF_ANADIG_PLL_528_RSVD1(v) \
+ (((v) << 19) & BM_ANADIG_PLL_528_RSVD1)
+#define BM_ANADIG_PLL_528_PFD_OFFSET_EN 0x00040000
+#define BM_ANADIG_PLL_528_DITHER_ENABLE 0x00020000
+#define BM_ANADIG_PLL_528_BYPASS 0x00010000
+#define BP_ANADIG_PLL_528_BYPASS_CLK_SRC 14
+#define BM_ANADIG_PLL_528_BYPASS_CLK_SRC 0x0000C000
+#define BF_ANADIG_PLL_528_BYPASS_CLK_SRC(v) \
+ (((v) << 14) & BM_ANADIG_PLL_528_BYPASS_CLK_SRC)
+#define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__OSC_24M 0x0
+#define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__ANACLK_1 0x1
+#define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__ANACLK_2 0x2
+#define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__XOR 0x3
+#define BM_ANADIG_PLL_528_ENABLE 0x00002000
+#define BM_ANADIG_PLL_528_POWERDOWN 0x00001000
+#define BM_ANADIG_PLL_528_HOLD_RING_OFF 0x00000800
+#define BM_ANADIG_PLL_528_DOUBLE_CP 0x00000400
+#define BM_ANADIG_PLL_528_HALF_CP 0x00000200
+#define BM_ANADIG_PLL_528_DOUBLE_LF 0x00000100
+#define BM_ANADIG_PLL_528_HALF_LF 0x00000080
+#define BP_ANADIG_PLL_528_RSVD0 1
+#define BM_ANADIG_PLL_528_RSVD0 0x0000007E
+#define BF_ANADIG_PLL_528_RSVD0(v) \
+ (((v) << 1) & BM_ANADIG_PLL_528_RSVD0)
+#define BM_ANADIG_PLL_528_DIV_SELECT 0x00000001
+
+#define HW_ANADIG_PLL_528_SS (0x00000040)
+
+#define BP_ANADIG_PLL_528_SS_STOP 16
+#define BM_ANADIG_PLL_528_SS_STOP 0xFFFF0000
+#define BF_ANADIG_PLL_528_SS_STOP(v) \
+ (((v) << 16) & BM_ANADIG_PLL_528_SS_STOP)
+#define BM_ANADIG_PLL_528_SS_ENABLE 0x00008000
+#define BP_ANADIG_PLL_528_SS_STEP 0
+#define BM_ANADIG_PLL_528_SS_STEP 0x00007FFF
+#define BF_ANADIG_PLL_528_SS_STEP(v) \
+ (((v) << 0) & BM_ANADIG_PLL_528_SS_STEP)
+
+#define HW_ANADIG_PLL_528_NUM (0x00000050)
+
+#define BP_ANADIG_PLL_528_NUM_RSVD0 30
+#define BM_ANADIG_PLL_528_NUM_RSVD0 0xC0000000
+#define BF_ANADIG_PLL_528_NUM_RSVD0(v) \
+ (((v) << 30) & BM_ANADIG_PLL_528_NUM_RSVD0)
+#define BP_ANADIG_PLL_528_NUM_A 0
+#define BM_ANADIG_PLL_528_NUM_A 0x3FFFFFFF
+#define BF_ANADIG_PLL_528_NUM_A(v) \
+ (((v) << 0) & BM_ANADIG_PLL_528_NUM_A)
+
+#define HW_ANADIG_PLL_528_DENOM (0x00000060)
+
+#define BP_ANADIG_PLL_528_DENOM_RSVD0 30
+#define BM_ANADIG_PLL_528_DENOM_RSVD0 0xC0000000
+#define BF_ANADIG_PLL_528_DENOM_RSVD0(v) \
+ (((v) << 30) & BM_ANADIG_PLL_528_DENOM_RSVD0)
+#define BP_ANADIG_PLL_528_DENOM_B 0
+#define BM_ANADIG_PLL_528_DENOM_B 0x3FFFFFFF
+#define BF_ANADIG_PLL_528_DENOM_B(v) \
+ (((v) << 0) & BM_ANADIG_PLL_528_DENOM_B)
+
+#define HW_ANADIG_PLL_AUDIO (0x00000070)
+#define HW_ANADIG_PLL_AUDIO_SET (0x00000074)
+#define HW_ANADIG_PLL_AUDIO_CLR (0x00000078)
+#define HW_ANADIG_PLL_AUDIO_TOG (0x0000007c)
+
+#define BM_ANADIG_PLL_AUDIO_LOCK 0x80000000
+#define BP_ANADIG_PLL_AUDIO_RSVD0 22
+#define BM_ANADIG_PLL_AUDIO_RSVD0 0x7FC00000
+#define BF_ANADIG_PLL_AUDIO_RSVD0(v) \
+ (((v) << 22) & BM_ANADIG_PLL_AUDIO_RSVD0)
+#define BM_ANADIG_PLL_AUDIO_SSC_EN 0x00200000
+#define BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT 19
+#define BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT 0x00180000
+#define BF_ANADIG_PLL_AUDIO_TEST_DIV_SELECT(v) \
+ (((v) << 19) & BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT)
+#define BM_ANADIG_PLL_AUDIO_PFD_OFFSET_EN 0x00040000
+#define BM_ANADIG_PLL_AUDIO_DITHER_ENABLE 0x00020000
+#define BM_ANADIG_PLL_AUDIO_BYPASS 0x00010000
+#define BP_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC 14
+#define BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC 0x0000C000
+#define BF_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC(v) \
+ (((v) << 14) & BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC)
+#define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__OSC_24M 0x0
+#define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__ANACLK_1 0x1
+#define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__ANACLK_2 0x2
+#define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__XOR 0x3
+#define BM_ANADIG_PLL_AUDIO_ENABLE 0x00002000
+#define BM_ANADIG_PLL_AUDIO_POWERDOWN 0x00001000
+#define BM_ANADIG_PLL_AUDIO_HOLD_RING_OFF 0x00000800
+#define BM_ANADIG_PLL_AUDIO_DOUBLE_CP 0x00000400
+#define BM_ANADIG_PLL_AUDIO_HALF_CP 0x00000200
+#define BM_ANADIG_PLL_AUDIO_DOUBLE_LF 0x00000100
+#define BM_ANADIG_PLL_AUDIO_HALF_LF 0x00000080
+#define BP_ANADIG_PLL_AUDIO_DIV_SELECT 0
+#define BM_ANADIG_PLL_AUDIO_DIV_SELECT 0x0000007F
+#define BF_ANADIG_PLL_AUDIO_DIV_SELECT(v) \
+ (((v) << 0) & BM_ANADIG_PLL_AUDIO_DIV_SELECT)
+
+#define HW_ANADIG_PLL_AUDIO_NUM (0x00000080)
+
+#define BP_ANADIG_PLL_AUDIO_NUM_RSVD0 30
+#define BM_ANADIG_PLL_AUDIO_NUM_RSVD0 0xC0000000
+#define BF_ANADIG_PLL_AUDIO_NUM_RSVD0(v) \
+ (((v) << 30) & BM_ANADIG_PLL_AUDIO_NUM_RSVD0)
+#define BP_ANADIG_PLL_AUDIO_NUM_A 0
+#define BM_ANADIG_PLL_AUDIO_NUM_A 0x3FFFFFFF
+#define BF_ANADIG_PLL_AUDIO_NUM_A(v) \
+ (((v) << 0) & BM_ANADIG_PLL_AUDIO_NUM_A)
+
+#define HW_ANADIG_PLL_AUDIO_DENOM (0x00000090)
+
+#define BP_ANADIG_PLL_AUDIO_DENOM_RSVD0 30
+#define BM_ANADIG_PLL_AUDIO_DENOM_RSVD0 0xC0000000
+#define BF_ANADIG_PLL_AUDIO_DENOM_RSVD0(v) \
+ (((v) << 30) & BM_ANADIG_PLL_AUDIO_DENOM_RSVD0)
+#define BP_ANADIG_PLL_AUDIO_DENOM_B 0
+#define BM_ANADIG_PLL_AUDIO_DENOM_B 0x3FFFFFFF
+#define BF_ANADIG_PLL_AUDIO_DENOM_B(v) \
+ (((v) << 0) & BM_ANADIG_PLL_AUDIO_DENOM_B)
+
+#define HW_ANADIG_PLL_VIDEO (0x000000a0)
+#define HW_ANADIG_PLL_VIDEO_SET (0x000000a4)
+#define HW_ANADIG_PLL_VIDEO_CLR (0x000000a8)
+#define HW_ANADIG_PLL_VIDEO_TOG (0x000000ac)
+
+#define BM_ANADIG_PLL_VIDEO_LOCK 0x80000000
+#define BP_ANADIG_PLL_VIDEO_RSVD0 22
+#define BM_ANADIG_PLL_VIDEO_RSVD0 0x7FC00000
+#define BF_ANADIG_PLL_VIDEO_RSVD0(v) \
+ (((v) << 22) & BM_ANADIG_PLL_VIDEO_RSVD0)
+#define BM_ANADIG_PLL_VIDEO_SSC_EN 0x00200000
+#define BP_ANADIG_PLL_VIDEO_TEST_DIV_SELECT 19
+#define BM_ANADIG_PLL_VIDEO_TEST_DIV_SELECT 0x00180000
+#define BF_ANADIG_PLL_VIDEO_TEST_DIV_SELECT(v) \
+ (((v) << 19) & BM_ANADIG_PLL_VIDEO_TEST_DIV_SELECT)
+#define BM_ANADIG_PLL_VIDEO_PFD_OFFSET_EN 0x00040000
+#define BM_ANADIG_PLL_VIDEO_DITHER_ENABLE 0x00020000
+#define BM_ANADIG_PLL_VIDEO_BYPASS 0x00010000
+#define BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC 14
+#define BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC 0x0000C000
+#define BF_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC(v) \
+ (((v) << 14) & BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC)
+#define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__OSC_24M 0x0
+#define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__ANACLK_1 0x1
+#define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__ANACLK_2 0x2
+#define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__XOR 0x3
+#define BM_ANADIG_PLL_VIDEO_ENABLE 0x00002000
+#define BM_ANADIG_PLL_VIDEO_POWERDOWN 0x00001000
+#define BM_ANADIG_PLL_VIDEO_HOLD_RING_OFF 0x00000800
+#define BM_ANADIG_PLL_VIDEO_DOUBLE_CP 0x00000400
+#define BM_ANADIG_PLL_VIDEO_HALF_CP 0x00000200
+#define BM_ANADIG_PLL_VIDEO_DOUBLE_LF 0x00000100
+#define BM_ANADIG_PLL_VIDEO_HALF_LF 0x00000080
+#define BP_ANADIG_PLL_VIDEO_DIV_SELECT 0
+#define BM_ANADIG_PLL_VIDEO_DIV_SELECT 0x0000007F
+#define BF_ANADIG_PLL_VIDEO_DIV_SELECT(v) \
+ (((v) << 0) & BM_ANADIG_PLL_VIDEO_DIV_SELECT)
+
+#define HW_ANADIG_PLL_VIDEO_NUM (0x000000b0)
+
+#define BP_ANADIG_PLL_VIDEO_NUM_RSVD0 30
+#define BM_ANADIG_PLL_VIDEO_NUM_RSVD0 0xC0000000
+#define BF_ANADIG_PLL_VIDEO_NUM_RSVD0(v) \
+ (((v) << 30) & BM_ANADIG_PLL_VIDEO_NUM_RSVD0)
+#define BP_ANADIG_PLL_VIDEO_NUM_A 0
+#define BM_ANADIG_PLL_VIDEO_NUM_A 0x3FFFFFFF
+#define BF_ANADIG_PLL_VIDEO_NUM_A(v) \
+ (((v) << 0) & BM_ANADIG_PLL_VIDEO_NUM_A)
+
+#define HW_ANADIG_PLL_VIDEO_DENOM (0x000000c0)
+
+#define BP_ANADIG_PLL_VIDEO_DENOM_RSVD0 30
+#define BM_ANADIG_PLL_VIDEO_DENOM_RSVD0 0xC0000000
+#define BF_ANADIG_PLL_VIDEO_DENOM_RSVD0(v) \
+ (((v) << 30) & BM_ANADIG_PLL_VIDEO_DENOM_RSVD0)
+#define BP_ANADIG_PLL_VIDEO_DENOM_B 0
+#define BM_ANADIG_PLL_VIDEO_DENOM_B 0x3FFFFFFF
+#define BF_ANADIG_PLL_VIDEO_DENOM_B(v) \
+ (((v) << 0) & BM_ANADIG_PLL_VIDEO_DENOM_B)
+
+#define HW_ANADIG_PLL_MLB (0x000000d0)
+#define HW_ANADIG_PLL_MLB_SET (0x000000d4)
+#define HW_ANADIG_PLL_MLB_CLR (0x000000d8)
+#define HW_ANADIG_PLL_MLB_TOG (0x000000dc)
+
+#define BM_ANADIG_PLL_MLB_LOCK 0x80000000
+#define BP_ANADIG_PLL_MLB_RSVD2 29
+#define BM_ANADIG_PLL_MLB_RSVD2 0x60000000
+#define BF_ANADIG_PLL_MLB_RSVD2(v) \
+ (((v) << 29) & BM_ANADIG_PLL_MLB_RSVD2)
+#define BP_ANADIG_PLL_MLB_MLB_FLT_RES_SEL 26
+#define BM_ANADIG_PLL_MLB_MLB_FLT_RES_SEL 0x1C000000
+#define BF_ANADIG_PLL_MLB_MLB_FLT_RES_SEL(v) \
+ (((v) << 26) & BM_ANADIG_PLL_MLB_MLB_FLT_RES_SEL)
+#define BP_ANADIG_PLL_MLB_RX_CLK_DELAY_CFG 23
+#define BM_ANADIG_PLL_MLB_RX_CLK_DELAY_CFG 0x03800000
+#define BF_ANADIG_PLL_MLB_RX_CLK_DELAY_CFG(v) \
+ (((v) << 23) & BM_ANADIG_PLL_MLB_RX_CLK_DELAY_CFG)
+#define BP_ANADIG_PLL_MLB_VDDD_DELAY_CFG 20
+#define BM_ANADIG_PLL_MLB_VDDD_DELAY_CFG 0x00700000
+#define BF_ANADIG_PLL_MLB_VDDD_DELAY_CFG(v) \
+ (((v) << 20) & BM_ANADIG_PLL_MLB_VDDD_DELAY_CFG)
+#define BP_ANADIG_PLL_MLB_VDDA_DELAY_CFG 17
+#define BM_ANADIG_PLL_MLB_VDDA_DELAY_CFG 0x000E0000
+#define BF_ANADIG_PLL_MLB_VDDA_DELAY_CFG(v) \
+ (((v) << 17) & BM_ANADIG_PLL_MLB_VDDA_DELAY_CFG)
+#define BM_ANADIG_PLL_MLB_BYPASS 0x00010000
+#define BP_ANADIG_PLL_MLB_RSVD1 14
+#define BM_ANADIG_PLL_MLB_RSVD1 0x0000C000
+#define BF_ANADIG_PLL_MLB_RSVD1(v) \
+ (((v) << 14) & BM_ANADIG_PLL_MLB_RSVD1)
+#define BP_ANADIG_PLL_MLB_PHASE_SEL 12
+#define BM_ANADIG_PLL_MLB_PHASE_SEL 0x00003000
+#define BF_ANADIG_PLL_MLB_PHASE_SEL(v) \
+ (((v) << 12) & BM_ANADIG_PLL_MLB_PHASE_SEL)
+#define BM_ANADIG_PLL_MLB_HOLD_RING_OFF 0x00000800
+#define BM_ANADIG_PLL_MLB_DOUBLE_CP 0x00000400
+#define BM_ANADIG_PLL_MLB_HALF_CP 0x00000200
+#define BP_ANADIG_PLL_MLB_RSVD0 0
+#define BM_ANADIG_PLL_MLB_RSVD0 0x000001FF
+#define BF_ANADIG_PLL_MLB_RSVD0(v) \
+ (((v) << 0) & BM_ANADIG_PLL_MLB_RSVD0)
+
+#define HW_ANADIG_PLL_ENET (0x000000e0)
+#define HW_ANADIG_PLL_ENET_SET (0x000000e4)
+#define HW_ANADIG_PLL_ENET_CLR (0x000000e8)
+#define HW_ANADIG_PLL_ENET_TOG (0x000000ec)
+
+#define BM_ANADIG_PLL_ENET_LOCK 0x80000000
+#define BP_ANADIG_PLL_ENET_RSVD1 21
+#define BM_ANADIG_PLL_ENET_RSVD1 0x7FE00000
+#define BF_ANADIG_PLL_ENET_RSVD1(v) \
+ (((v) << 21) & BM_ANADIG_PLL_ENET_RSVD1)
+#define BM_ANADIG_PLL_ENET_ENABLE_SATA 0x00100000
+#define BM_ANADIG_PLL_ENET_ENABLE_PCIE 0x00080000
+#define BM_ANADIG_PLL_ENET_PFD_OFFSET_EN 0x00040000
+#define BM_ANADIG_PLL_ENET_DITHER_ENABLE 0x00020000
+#define BM_ANADIG_PLL_ENET_BYPASS 0x00010000
+#define BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC 14
+#define BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC 0x0000C000
+#define BF_ANADIG_PLL_ENET_BYPASS_CLK_SRC(v) \
+ (((v) << 14) & BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC)
+#define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__OSC_24M 0x0
+#define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__ANACLK_1 0x1
+#define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__ANACLK_2 0x2
+#define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__XOR 0x3
+#define BM_ANADIG_PLL_ENET_ENABLE 0x00002000
+#define BM_ANADIG_PLL_ENET_POWERDOWN 0x00001000
+#define BM_ANADIG_PLL_ENET_HOLD_RING_OFF 0x00000800
+#define BM_ANADIG_PLL_ENET_DOUBLE_CP 0x00000400
+#define BM_ANADIG_PLL_ENET_HALF_CP 0x00000200
+#define BM_ANADIG_PLL_ENET_DOUBLE_LF 0x00000100
+#define BM_ANADIG_PLL_ENET_HALF_LF 0x00000080
+#define BP_ANADIG_PLL_ENET_RSVD0 2
+#define BM_ANADIG_PLL_ENET_RSVD0 0x0000007C
+#define BF_ANADIG_PLL_ENET_RSVD0(v) \
+ (((v) << 2) & BM_ANADIG_PLL_ENET_RSVD0)
+#define BP_ANADIG_PLL_ENET_DIV_SELECT 0
+#define BM_ANADIG_PLL_ENET_DIV_SELECT 0x00000003
+#define BF_ANADIG_PLL_ENET_DIV_SELECT(v) \
+ (((v) << 0) & BM_ANADIG_PLL_ENET_DIV_SELECT)
+
+#define HW_ANADIG_PFD_480 (0x000000f0)
+#define HW_ANADIG_PFD_480_SET (0x000000f4)
+#define HW_ANADIG_PFD_480_CLR (0x000000f8)
+#define HW_ANADIG_PFD_480_TOG (0x000000fc)
+
+#define BM_ANADIG_PFD_480_PFD3_CLKGATE 0x80000000
+#define BM_ANADIG_PFD_480_PFD3_STABLE 0x40000000
+#define BP_ANADIG_PFD_480_PFD3_FRAC 24
+#define BM_ANADIG_PFD_480_PFD3_FRAC 0x3F000000
+#define BF_ANADIG_PFD_480_PFD3_FRAC(v) \
+ (((v) << 24) & BM_ANADIG_PFD_480_PFD3_FRAC)
+#define BM_ANADIG_PFD_480_PFD2_CLKGATE 0x00800000
+#define BM_ANADIG_PFD_480_PFD2_STABLE 0x00400000
+#define BP_ANADIG_PFD_480_PFD2_FRAC 16
+#define BM_ANADIG_PFD_480_PFD2_FRAC 0x003F0000
+#define BF_ANADIG_PFD_480_PFD2_FRAC(v) \
+ (((v) << 16) & BM_ANADIG_PFD_480_PFD2_FRAC)
+#define BM_ANADIG_PFD_480_PFD1_CLKGATE 0x00008000
+#define BM_ANADIG_PFD_480_PFD1_STABLE 0x00004000
+#define BP_ANADIG_PFD_480_PFD1_FRAC 8
+#define BM_ANADIG_PFD_480_PFD1_FRAC 0x00003F00
+#define BF_ANADIG_PFD_480_PFD1_FRAC(v) \
+ (((v) << 8) & BM_ANADIG_PFD_480_PFD1_FRAC)
+#define BM_ANADIG_PFD_480_PFD0_CLKGATE 0x00000080
+#define BM_ANADIG_PFD_480_PFD0_STABLE 0x00000040
+#define BP_ANADIG_PFD_480_PFD0_FRAC 0
+#define BM_ANADIG_PFD_480_PFD0_FRAC 0x0000003F
+#define BF_ANADIG_PFD_480_PFD0_FRAC(v) \
+ (((v) << 0) & BM_ANADIG_PFD_480_PFD0_FRAC)
+
+#define HW_ANADIG_PFD_528 (0x00000100)
+#define HW_ANADIG_PFD_528_SET (0x00000104)
+#define HW_ANADIG_PFD_528_CLR (0x00000108)
+#define HW_ANADIG_PFD_528_TOG (0x0000010c)
+
+#define BM_ANADIG_PFD_528_PFD3_CLKGATE 0x80000000
+#define BM_ANADIG_PFD_528_PFD3_STABLE 0x40000000
+#define BP_ANADIG_PFD_528_PFD3_FRAC 24
+#define BM_ANADIG_PFD_528_PFD3_FRAC 0x3F000000
+#define BF_ANADIG_PFD_528_PFD3_FRAC(v) \
+ (((v) << 24) & BM_ANADIG_PFD_528_PFD3_FRAC)
+#define BM_ANADIG_PFD_528_PFD2_CLKGATE 0x00800000
+#define BM_ANADIG_PFD_528_PFD2_STABLE 0x00400000
+#define BP_ANADIG_PFD_528_PFD2_FRAC 16
+#define BM_ANADIG_PFD_528_PFD2_FRAC 0x003F0000
+#define BF_ANADIG_PFD_528_PFD2_FRAC(v) \
+ (((v) << 16) & BM_ANADIG_PFD_528_PFD2_FRAC)
+#define BM_ANADIG_PFD_528_PFD1_CLKGATE 0x00008000
+#define BM_ANADIG_PFD_528_PFD1_STABLE 0x00004000
+#define BP_ANADIG_PFD_528_PFD1_FRAC 8
+#define BM_ANADIG_PFD_528_PFD1_FRAC 0x00003F00
+#define BF_ANADIG_PFD_528_PFD1_FRAC(v) \
+ (((v) << 8) & BM_ANADIG_PFD_528_PFD1_FRAC)
+#define BM_ANADIG_PFD_528_PFD0_CLKGATE 0x00000080
+#define BM_ANADIG_PFD_528_PFD0_STABLE 0x00000040
+#define BP_ANADIG_PFD_528_PFD0_FRAC 0
+#define BM_ANADIG_PFD_528_PFD0_FRAC 0x0000003F
+#define BF_ANADIG_PFD_528_PFD0_FRAC(v) \
+ (((v) << 0) & BM_ANADIG_PFD_528_PFD0_FRAC)
+
+#define HW_ANADIG_REG_1P1 (0x00000110)
+#define HW_ANADIG_REG_1P1_SET (0x00000114)
+#define HW_ANADIG_REG_1P1_CLR (0x00000118)
+#define HW_ANADIG_REG_1P1_TOG (0x0000011c)
+
+#define BP_ANADIG_REG_1P1_RSVD2 18
+#define BM_ANADIG_REG_1P1_RSVD2 0xFFFC0000
+#define BF_ANADIG_REG_1P1_RSVD2(v) \
+ (((v) << 18) & BM_ANADIG_REG_1P1_RSVD2)
+#define BM_ANADIG_REG_1P1_OK_VDD1P1 0x00020000
+#define BM_ANADIG_REG_1P1_BO_VDD1P1 0x00010000
+#define BP_ANADIG_REG_1P1_RSVD1 13
+#define BM_ANADIG_REG_1P1_RSVD1 0x0000E000
+#define BF_ANADIG_REG_1P1_RSVD1(v) \
+ (((v) << 13) & BM_ANADIG_REG_1P1_RSVD1)
+#define BP_ANADIG_REG_1P1_OUTPUT_TRG 8
+#define BM_ANADIG_REG_1P1_OUTPUT_TRG 0x00001F00
+#define BF_ANADIG_REG_1P1_OUTPUT_TRG(v) \
+ (((v) << 8) & BM_ANADIG_REG_1P1_OUTPUT_TRG)
+#define BM_ANADIG_REG_1P1_RSVD0 0x00000080
+#define BP_ANADIG_REG_1P1_BO_OFFSET 4
+#define BM_ANADIG_REG_1P1_BO_OFFSET 0x00000070
+#define BF_ANADIG_REG_1P1_BO_OFFSET(v) \
+ (((v) << 4) & BM_ANADIG_REG_1P1_BO_OFFSET)
+#define BM_ANADIG_REG_1P1_ENABLE_PULLDOWN 0x00000008
+#define BM_ANADIG_REG_1P1_ENABLE_ILIMIT 0x00000004
+#define BM_ANADIG_REG_1P1_ENABLE_BO 0x00000002
+#define BM_ANADIG_REG_1P1_ENABLE_LINREG 0x00000001
+
+#define HW_ANADIG_REG_3P0 (0x00000120)
+#define HW_ANADIG_REG_3P0_SET (0x00000124)
+#define HW_ANADIG_REG_3P0_CLR (0x00000128)
+#define HW_ANADIG_REG_3P0_TOG (0x0000012c)
+
+#define BP_ANADIG_REG_3P0_RSVD2 18
+#define BM_ANADIG_REG_3P0_RSVD2 0xFFFC0000
+#define BF_ANADIG_REG_3P0_RSVD2(v) \
+ (((v) << 18) & BM_ANADIG_REG_3P0_RSVD2)
+#define BM_ANADIG_REG_3P0_OK_VDD3P0 0x00020000
+#define BM_ANADIG_REG_3P0_BO_VDD3P0 0x00010000
+#define BP_ANADIG_REG_3P0_RSVD1 13
+#define BM_ANADIG_REG_3P0_RSVD1 0x0000E000
+#define BF_ANADIG_REG_3P0_RSVD1(v) \
+ (((v) << 13) & BM_ANADIG_REG_3P0_RSVD1)
+#define BP_ANADIG_REG_3P0_OUTPUT_TRG 8
+#define BM_ANADIG_REG_3P0_OUTPUT_TRG 0x00001F00
+#define BF_ANADIG_REG_3P0_OUTPUT_TRG(v) \
+ (((v) << 8) & BM_ANADIG_REG_3P0_OUTPUT_TRG)
+#define BM_ANADIG_REG_3P0_VBUS_SEL 0x00000080
+#define BP_ANADIG_REG_3P0_BO_OFFSET 4
+#define BM_ANADIG_REG_3P0_BO_OFFSET 0x00000070
+#define BF_ANADIG_REG_3P0_BO_OFFSET(v) \
+ (((v) << 4) & BM_ANADIG_REG_3P0_BO_OFFSET)
+#define BM_ANADIG_REG_3P0_RSVD0 0x00000008
+#define BM_ANADIG_REG_3P0_ENABLE_ILIMIT 0x00000004
+#define BM_ANADIG_REG_3P0_ENABLE_BO 0x00000002
+#define BM_ANADIG_REG_3P0_ENABLE_LINREG 0x00000001
+
+#define HW_ANADIG_REG_2P5 (0x00000130)
+#define HW_ANADIG_REG_2P5_SET (0x00000134)
+#define HW_ANADIG_REG_2P5_CLR (0x00000138)
+#define HW_ANADIG_REG_2P5_TOG (0x0000013c)
+
+#define BP_ANADIG_REG_2P5_RSVD2 19
+#define BM_ANADIG_REG_2P5_RSVD2 0xFFF80000
+#define BF_ANADIG_REG_2P5_RSVD2(v) \
+ (((v) << 19) & BM_ANADIG_REG_2P5_RSVD2)
+#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x00040000
+#define BM_ANADIG_REG_2P5_OK_VDD2P5 0x00020000
+#define BM_ANADIG_REG_2P5_BO_VDD2P5 0x00010000
+#define BP_ANADIG_REG_2P5_RSVD1 13
+#define BM_ANADIG_REG_2P5_RSVD1 0x0000E000
+#define BF_ANADIG_REG_2P5_RSVD1(v) \
+ (((v) << 13) & BM_ANADIG_REG_2P5_RSVD1)
+#define BP_ANADIG_REG_2P5_OUTPUT_TRG 8
+#define BM_ANADIG_REG_2P5_OUTPUT_TRG 0x00001F00
+#define BF_ANADIG_REG_2P5_OUTPUT_TRG(v) \
+ (((v) << 8) & BM_ANADIG_REG_2P5_OUTPUT_TRG)
+#define BM_ANADIG_REG_2P5_RSVD0 0x00000080
+#define BP_ANADIG_REG_2P5_BO_OFFSET 4
+#define BM_ANADIG_REG_2P5_BO_OFFSET 0x00000070
+#define BF_ANADIG_REG_2P5_BO_OFFSET(v) \
+ (((v) << 4) & BM_ANADIG_REG_2P5_BO_OFFSET)
+#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN 0x00000008
+#define BM_ANADIG_REG_2P5_ENABLE_ILIMIT 0x00000004
+#define BM_ANADIG_REG_2P5_ENABLE_BO 0x00000002
+#define BM_ANADIG_REG_2P5_ENABLE_LINREG 0x00000001
+
+#define HW_ANADIG_REG_CORE (0x00000140)
+#define HW_ANADIG_REG_CORE_SET (0x00000144)
+#define HW_ANADIG_REG_CORE_CLR (0x00000148)
+#define HW_ANADIG_REG_CORE_TOG (0x0000014c)
+
+#define BM_ANADIG_REG_CORE_REF_SHIFT 0x80000000
+#define BM_ANADIG_REG_CORE_RSVD0 0x40000000
+#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000
+#define BP_ANADIG_REG_CORE_RAMP_RATE 27
+#define BM_ANADIG_REG_CORE_RAMP_RATE 0x18000000
+#define BF_ANADIG_REG_CORE_RAMP_RATE(v) \
+ (((v) << 27) & BM_ANADIG_REG_CORE_RAMP_RATE)
+#define BP_ANADIG_REG_CORE_REG2_ADJ 23
+#define BM_ANADIG_REG_CORE_REG2_ADJ 0x07800000
+#define BF_ANADIG_REG_CORE_REG2_ADJ(v) \
+ (((v) << 23) & BM_ANADIG_REG_CORE_REG2_ADJ)
+#define BP_ANADIG_REG_CORE_REG2_TRG 18
+#define BM_ANADIG_REG_CORE_REG2_TRG 0x007C0000
+#define BF_ANADIG_REG_CORE_REG2_TRG(v) \
+ (((v) << 18) & BM_ANADIG_REG_CORE_REG2_TRG)
+#define BP_ANADIG_REG_CORE_REG1_ADJ 14
+#define BM_ANADIG_REG_CORE_REG1_ADJ 0x0003C000
+#define BF_ANADIG_REG_CORE_REG1_ADJ(v) \
+ (((v) << 14) & BM_ANADIG_REG_CORE_REG1_ADJ)
+#define BP_ANADIG_REG_CORE_REG1_TRG 9
+#define BM_ANADIG_REG_CORE_REG1_TRG 0x00003E00
+#define BF_ANADIG_REG_CORE_REG1_TRG(v) \
+ (((v) << 9) & BM_ANADIG_REG_CORE_REG1_TRG)
+#define BP_ANADIG_REG_CORE_REG0_ADJ 5
+#define BM_ANADIG_REG_CORE_REG0_ADJ 0x000001E0
+#define BF_ANADIG_REG_CORE_REG0_ADJ(v) \
+ (((v) << 5) & BM_ANADIG_REG_CORE_REG0_ADJ)
+#define BP_ANADIG_REG_CORE_REG0_TRG 0
+#define BM_ANADIG_REG_CORE_REG0_TRG 0x0000001F
+#define BF_ANADIG_REG_CORE_REG0_TRG(v) \
+ (((v) << 0) & BM_ANADIG_REG_CORE_REG0_TRG)
+
+#define HW_ANADIG_ANA_MISC0 (0x00000150)
+#define HW_ANADIG_ANA_MISC0_SET (0x00000154)
+#define HW_ANADIG_ANA_MISC0_CLR (0x00000158)
+#define HW_ANADIG_ANA_MISC0_TOG (0x0000015c)
+
+#define BP_ANADIG_ANA_MISC0_RSVD2 29
+#define BM_ANADIG_ANA_MISC0_RSVD2 0xE0000000
+#define BF_ANADIG_ANA_MISC0_RSVD2(v) \
+ (((v) << 29) & BM_ANADIG_ANA_MISC0_RSVD2)
+#define BP_ANADIG_ANA_MISC0_CLKGATE_DELAY 26
+#define BM_ANADIG_ANA_MISC0_CLKGATE_DELAY 0x1C000000
+#define BF_ANADIG_ANA_MISC0_CLKGATE_DELAY(v) \
+ (((v) << 26) & BM_ANADIG_ANA_MISC0_CLKGATE_DELAY)
+#define BM_ANADIG_ANA_MISC0_CLKGATE_CTRL 0x02000000
+#define BP_ANADIG_ANA_MISC0_ANAMUX 21
+#define BM_ANADIG_ANA_MISC0_ANAMUX 0x01E00000
+#define BF_ANADIG_ANA_MISC0_ANAMUX(v) \
+ (((v) << 21) & BM_ANADIG_ANA_MISC0_ANAMUX)
+#define BM_ANADIG_ANA_MISC0_ANAMUX_EN 0x00100000
+#define BP_ANADIG_ANA_MISC0_WBCP_VPW_THRESH 18
+#define BM_ANADIG_ANA_MISC0_WBCP_VPW_THRESH 0x000C0000
+#define BF_ANADIG_ANA_MISC0_WBCP_VPW_THRESH(v) \
+ (((v) << 18) & BM_ANADIG_ANA_MISC0_WBCP_VPW_THRESH)
+#define BM_ANADIG_ANA_MISC0_OSC_XTALOK_EN 0x00020000
+#define BM_ANADIG_ANA_MISC0_OSC_XTALOK 0x00010000
+#define BP_ANADIG_ANA_MISC0_OSC_I 14
+#define BM_ANADIG_ANA_MISC0_OSC_I 0x0000C000
+#define BF_ANADIG_ANA_MISC0_OSC_I(v) \
+ (((v) << 14) & BM_ANADIG_ANA_MISC0_OSC_I)
+#define BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN 0x00002000
+#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG \
+ (cpu_is_mx6sl() ? 0x00000800 : 0x00001000)
+#define BP_ANADIG_ANA_MISC0_RSVD0 10
+#define BM_ANADIG_ANA_MISC0_RSVD0 0x00000C00
+#define BF_ANADIG_ANA_MISC0_RSVD0(v) \
+ (((v) << 10) & BM_ANADIG_ANA_MISC0_RSVD0)
+#define BP_ANADIG_ANA_MISC0_REFTOP_BIAS_TST 8
+#define BM_ANADIG_ANA_MISC0_REFTOP_BIAS_TST 0x00000300
+#define BF_ANADIG_ANA_MISC0_REFTOP_BIAS_TST(v) \
+ (((v) << 8) & BM_ANADIG_ANA_MISC0_REFTOP_BIAS_TST)
+#define BM_ANADIG_ANA_MISC0_REFTOP_VBGUP 0x00000080
+#define BP_ANADIG_ANA_MISC0_REFTOP_VBGADJ 4
+#define BM_ANADIG_ANA_MISC0_REFTOP_VBGADJ 0x00000070
+#define BF_ANADIG_ANA_MISC0_REFTOP_VBGADJ(v) \
+ (((v) << 4) & BM_ANADIG_ANA_MISC0_REFTOP_VBGADJ)
+#define BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF 0x00000008
+#define BM_ANADIG_ANA_MISC0_REFTOP_LOWPOWER 0x00000004
+#define BM_ANADIG_ANA_MISC0_REFTOP_PWDVBGUP 0x00000002
+#define BM_ANADIG_ANA_MISC0_REFTOP_PWD 0x00000001
+
+#define HW_ANADIG_ANA_MISC1 (0x00000160)
+#define HW_ANADIG_ANA_MISC1_SET (0x00000164)
+#define HW_ANADIG_ANA_MISC1_CLR (0x00000168)
+#define HW_ANADIG_ANA_MISC1_TOG (0x0000016c)
+
+#define BM_ANADIG_ANA_MISC1_IRQ_DIG_BO 0x80000000
+#define BM_ANADIG_ANA_MISC1_IRQ_ANA_BO 0x40000000
+#define BM_ANADIG_ANA_MISC1_IRQ_TEMPSENSE_BO 0x20000000
+#define BP_ANADIG_ANA_MISC1_RSVD0 14
+#define BM_ANADIG_ANA_MISC1_RSVD0 0x1FFFC000
+#define BF_ANADIG_ANA_MISC1_RSVD0(v) \
+ (((v) << 14) & BM_ANADIG_ANA_MISC1_RSVD0)
+#define BM_ANADIG_ANA_MISC1_LVDSCLK2_IBEN 0x00002000
+#define BM_ANADIG_ANA_MISC1_LVDSCLK1_IBEN 0x00001000
+#define BM_ANADIG_ANA_MISC1_LVDSCLK2_OBEN 0x00000800
+#define BM_ANADIG_ANA_MISC1_LVDSCLK1_OBEN 0x00000400
+#define BP_ANADIG_ANA_MISC1_LVDS2_CLK_SEL 5
+#define BM_ANADIG_ANA_MISC1_LVDS2_CLK_SEL 0x000003E0
+#define BF_ANADIG_ANA_MISC1_LVDS2_CLK_SEL(v) \
+ (((v) << 5) & BM_ANADIG_ANA_MISC1_LVDS2_CLK_SEL)
+#define BP_ANADIG_ANA_MISC1_LVDS1_CLK_SEL 0
+#define BM_ANADIG_ANA_MISC1_LVDS1_CLK_SEL 0x0000001F
+#define BF_ANADIG_ANA_MISC1_LVDS1_CLK_SEL(v) \
+ (((v) << 0) & BM_ANADIG_ANA_MISC1_LVDS1_CLK_SEL)
+
+#define HW_ANADIG_ANA_MISC2 (0x00000170)
+#define HW_ANADIG_ANA_MISC2_SET (0x00000174)
+#define HW_ANADIG_ANA_MISC2_CLR (0x00000178)
+#define HW_ANADIG_ANA_MISC2_TOG (0x0000017c)
+
+#define BP_ANADIG_ANA_MISC2_CONTROL3 30
+#define BM_ANADIG_ANA_MISC2_CONTROL3 0xC0000000
+#define BF_ANADIG_ANA_MISC2_CONTROL3(v) \
+ (((v) << 30) & BM_ANADIG_ANA_MISC2_CONTROL3)
+#define BP_ANADIG_ANA_MISC2_REG2_STEP_TIME 28
+#define BM_ANADIG_ANA_MISC2_REG2_STEP_TIME 0x30000000
+#define BF_ANADIG_ANA_MISC2_REG2_STEP_TIME(v) \
+ (((v) << 28) & BM_ANADIG_ANA_MISC2_REG2_STEP_TIME)
+#define BP_ANADIG_ANA_MISC2_REG1_STEP_TIME 26
+#define BM_ANADIG_ANA_MISC2_REG1_STEP_TIME 0x0C000000
+#define BF_ANADIG_ANA_MISC2_REG1_STEP_TIME(v) \
+ (((v) << 26) & BM_ANADIG_ANA_MISC2_REG1_STEP_TIME)
+#define BP_ANADIG_ANA_MISC2_REG0_STEP_TIME 24
+#define BM_ANADIG_ANA_MISC2_REG0_STEP_TIME 0x03000000
+#define BF_ANADIG_ANA_MISC2_REG0_STEP_TIME(v) \
+ (((v) << 24) & BM_ANADIG_ANA_MISC2_REG0_STEP_TIME)
+#define BM_ANADIG_ANA_MISC2_CONTROL2 0x00800000
+#define BM_ANADIG_ANA_MISC2_REG2_OK 0x00400000
+#define BM_ANADIG_ANA_MISC2_REG2_ENABLE_BO 0x00200000
+#define BM_ANADIG_ANA_MISC2_RSVD2 0x00100000
+#define BM_ANADIG_ANA_MISC2_REG2_BO_STATUS 0x00080000
+#define BP_ANADIG_ANA_MISC2_REG2_BO_OFFSET 16
+#define BM_ANADIG_ANA_MISC2_REG2_BO_OFFSET 0x00070000
+#define BF_ANADIG_ANA_MISC2_REG2_BO_OFFSET(v) \
+ (((v) << 16) & BM_ANADIG_ANA_MISC2_REG2_BO_OFFSET)
+#define BM_ANADIG_ANA_MISC2_CONTROL1 0x00008000
+#define BM_ANADIG_ANA_MISC2_REG1_OK 0x00004000
+#define BM_ANADIG_ANA_MISC2_REG1_ENABLE_BO 0x00002000
+#define BM_ANADIG_ANA_MISC2_RSVD1 0x00001000
+#define BM_ANADIG_ANA_MISC2_REG1_BO_STATUS 0x00000800
+#define BP_ANADIG_ANA_MISC2_REG1_BO_OFFSET 8
+#define BM_ANADIG_ANA_MISC2_REG1_BO_OFFSET 0x00000700
+#define BF_ANADIG_ANA_MISC2_REG1_BO_OFFSET(v) \
+ (((v) << 8) & BM_ANADIG_ANA_MISC2_REG1_BO_OFFSET)
+#define BM_ANADIG_ANA_MISC2_CONTROL0 0x00000080
+#define BM_ANADIG_ANA_MISC2_REG0_OK 0x00000040
+#define BM_ANADIG_ANA_MISC2_REG0_ENABLE_BO 0x00000020
+#define BM_ANADIG_ANA_MISC2_RSVD0 0x00000010
+#define BM_ANADIG_ANA_MISC2_REG0_BO_STATUS 0x00000008
+#define BP_ANADIG_ANA_MISC2_REG0_BO_OFFSET 0
+#define BM_ANADIG_ANA_MISC2_REG0_BO_OFFSET 0x00000007
+#define BF_ANADIG_ANA_MISC2_REG0_BO_OFFSET(v) \
+ (((v) << 0) & BM_ANADIG_ANA_MISC2_REG0_BO_OFFSET)
+
+#define HW_ANADIG_TEMPSENSE0 (0x00000180)
+#define HW_ANADIG_TEMPSENSE0_SET (0x00000184)
+#define HW_ANADIG_TEMPSENSE0_CLR (0x00000188)
+#define HW_ANADIG_TEMPSENSE0_TOG (0x0000018c)
+
+#define BP_ANADIG_TEMPSENSE0_ALARM_VALUE 20
+#define BM_ANADIG_TEMPSENSE0_ALARM_VALUE 0xFFF00000
+#define BF_ANADIG_TEMPSENSE0_ALARM_VALUE(v) \
+ (((v) << 20) & BM_ANADIG_TEMPSENSE0_ALARM_VALUE)
+#define BP_ANADIG_TEMPSENSE0_TEMP_VALUE 8
+#define BM_ANADIG_TEMPSENSE0_TEMP_VALUE 0x000FFF00
+#define BF_ANADIG_TEMPSENSE0_TEMP_VALUE(v) \
+ (((v) << 8) & BM_ANADIG_TEMPSENSE0_TEMP_VALUE)
+#define BM_ANADIG_TEMPSENSE0_RSVD0 0x00000080
+#define BM_ANADIG_TEMPSENSE0_TEST 0x00000040
+#define BP_ANADIG_TEMPSENSE0_VBGADJ 3
+#define BM_ANADIG_TEMPSENSE0_VBGADJ 0x00000038
+#define BF_ANADIG_TEMPSENSE0_VBGADJ(v) \
+ (((v) << 3) & BM_ANADIG_TEMPSENSE0_VBGADJ)
+#define BM_ANADIG_TEMPSENSE0_FINISHED 0x00000004
+#define BM_ANADIG_TEMPSENSE0_MEASURE_TEMP 0x00000002
+#define BM_ANADIG_TEMPSENSE0_POWER_DOWN 0x00000001
+
+#define HW_ANADIG_TEMPSENSE1 (0x00000190)
+#define HW_ANADIG_TEMPSENSE1_SET (0x00000194)
+#define HW_ANADIG_TEMPSENSE1_CLR (0x00000198)
+#define HW_ANADIG_TEMPSENSE1_TOG (0x0000019c)
+
+#define BP_ANADIG_TEMPSENSE1_RSVD0 16
+#define BM_ANADIG_TEMPSENSE1_RSVD0 0xFFFF0000
+#define BF_ANADIG_TEMPSENSE1_RSVD0(v) \
+ (((v) << 16) & BM_ANADIG_TEMPSENSE1_RSVD0)
+#define BP_ANADIG_TEMPSENSE1_MEASURE_FREQ 0
+#define BM_ANADIG_TEMPSENSE1_MEASURE_FREQ 0x0000FFFF
+#define BF_ANADIG_TEMPSENSE1_MEASURE_FREQ(v) \
+ (((v) << 0) & BM_ANADIG_TEMPSENSE1_MEASURE_FREQ)
+
+#define HW_ANADIG_USB1_VBUS_DETECT (0x000001a0)
+#define HW_ANADIG_USB1_VBUS_DETECT_SET (0x000001a4)
+#define HW_ANADIG_USB1_VBUS_DETECT_CLR (0x000001a8)
+#define HW_ANADIG_USB1_VBUS_DETECT_TOG (0x000001ac)
+
+#define BM_ANADIG_USB1_VBUS_DETECT_EN_CHARGER_RESISTOR 0x80000000
+#define BP_ANADIG_USB1_VBUS_DETECT_RSVD2 28
+#define BM_ANADIG_USB1_VBUS_DETECT_RSVD2 0x70000000
+#define BF_ANADIG_USB1_VBUS_DETECT_RSVD2(v) \
+ (((v) << 28) & BM_ANADIG_USB1_VBUS_DETECT_RSVD2)
+#define BM_ANADIG_USB1_VBUS_DETECT_CHARGE_VBUS 0x08000000
+#define BM_ANADIG_USB1_VBUS_DETECT_DISCHARGE_VBUS 0x04000000
+#define BP_ANADIG_USB1_VBUS_DETECT_RSVD1 21
+#define BM_ANADIG_USB1_VBUS_DETECT_RSVD1 0x03E00000
+#define BF_ANADIG_USB1_VBUS_DETECT_RSVD1(v) \
+ (((v) << 21) & BM_ANADIG_USB1_VBUS_DETECT_RSVD1)
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_PWRUP_CMPS 0x00100000
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_5VDETECT 0x00080000
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_TO_B 0x00040000
+#define BP_ANADIG_USB1_VBUS_DETECT_RSVD0 8
+#define BM_ANADIG_USB1_VBUS_DETECT_RSVD0 0x0003FF00
+#define BF_ANADIG_USB1_VBUS_DETECT_RSVD0(v) \
+ (((v) << 8) & BM_ANADIG_USB1_VBUS_DETECT_RSVD0)
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_OVERRIDE 0x00000080
+#define BM_ANADIG_USB1_VBUS_DETECT_AVALID_OVERRIDE 0x00000040
+#define BM_ANADIG_USB1_VBUS_DETECT_BVALID_OVERRIDE 0x00000020
+#define BM_ANADIG_USB1_VBUS_DETECT_SESSEND_OVERRIDE 0x00000010
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUS_OVERRIDE_EN 0x00000008
+#define BP_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH 0
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH 0x00000007
+#define BF_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH(v) \
+ (((v) << 0) & BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH)
+
+#define HW_ANADIG_USB1_CHRG_DETECT (0x000001b0)
+#define HW_ANADIG_USB1_CHRG_DETECT_SET (0x000001b4)
+#define HW_ANADIG_USB1_CHRG_DETECT_CLR (0x000001b8)
+#define HW_ANADIG_USB1_CHRG_DETECT_TOG (0x000001bc)
+
+#define BP_ANADIG_USB1_CHRG_DETECT_RSVD2 24
+#define BM_ANADIG_USB1_CHRG_DETECT_RSVD2 0xFF000000
+#define BF_ANADIG_USB1_CHRG_DETECT_RSVD2(v) \
+ (((v) << 24) & BM_ANADIG_USB1_CHRG_DETECT_RSVD2)
+#define BM_ANADIG_USB1_CHRG_DETECT_BGR_BIAS 0x00800000
+#define BP_ANADIG_USB1_CHRG_DETECT_RSVD1 21
+#define BM_ANADIG_USB1_CHRG_DETECT_RSVD1 0x00600000
+#define BF_ANADIG_USB1_CHRG_DETECT_RSVD1(v) \
+ (((v) << 21) & BM_ANADIG_USB1_CHRG_DETECT_RSVD1)
+#define BM_ANADIG_USB1_CHRG_DETECT_EN_B 0x00100000
+#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B 0x00080000
+#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT 0x00040000
+#define BP_ANADIG_USB1_CHRG_DETECT_RSVD0 1
+#define BM_ANADIG_USB1_CHRG_DETECT_RSVD0 0x0003FFFE
+#define BF_ANADIG_USB1_CHRG_DETECT_RSVD0(v) \
+ (((v) << 1) & BM_ANADIG_USB1_CHRG_DETECT_RSVD0)
+#define BM_ANADIG_USB1_CHRG_DETECT_FORCE_DETECT 0x00000001
+
+#define HW_ANADIG_USB1_VBUS_DET_STAT (0x000001c0)
+#define HW_ANADIG_USB1_VBUS_DET_STAT_SET (0x000001c4)
+#define HW_ANADIG_USB1_VBUS_DET_STAT_CLR (0x000001c8)
+#define HW_ANADIG_USB1_VBUS_DET_STAT_TOG (0x000001cc)
+
+#define BP_ANADIG_USB1_VBUS_DET_STAT_RSVD0 4
+#define BM_ANADIG_USB1_VBUS_DET_STAT_RSVD0 0xFFFFFFF0
+#define BF_ANADIG_USB1_VBUS_DET_STAT_RSVD0(v) \
+ (((v) << 4) & BM_ANADIG_USB1_VBUS_DET_STAT_RSVD0)
+#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID 0x00000008
+#define BM_ANADIG_USB1_VBUS_DET_STAT_AVALID 0x00000004
+#define BM_ANADIG_USB1_VBUS_DET_STAT_BVALID 0x00000002
+#define BM_ANADIG_USB1_VBUS_DET_STAT_SESSEND 0x00000001
+
+#define HW_ANADIG_USB1_CHRG_DET_STAT (0x000001d0)
+#define HW_ANADIG_USB1_CHRG_DET_STAT_SET (0x000001d4)
+#define HW_ANADIG_USB1_CHRG_DET_STAT_CLR (0x000001d8)
+#define HW_ANADIG_USB1_CHRG_DET_STAT_TOG (0x000001dc)
+
+#define BP_ANADIG_USB1_CHRG_DET_STAT_RSVD0 4
+#define BM_ANADIG_USB1_CHRG_DET_STAT_RSVD0 0xFFFFFFF0
+#define BF_ANADIG_USB1_CHRG_DET_STAT_RSVD0(v) \
+ (((v) << 4) & BM_ANADIG_USB1_CHRG_DET_STAT_RSVD0)
+#define BM_ANADIG_USB1_CHRG_DET_STAT_DP_STATE 0x00000008
+#define BM_ANADIG_USB1_CHRG_DET_STAT_DM_STATE 0x00000004
+#define BM_ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED 0x00000002
+#define BM_ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT 0x00000001
+
+#define HW_ANADIG_USB1_LOOPBACK (0x000001e0)
+#define HW_ANADIG_USB1_LOOPBACK_SET (0x000001e4)
+#define HW_ANADIG_USB1_LOOPBACK_CLR (0x000001e8)
+#define HW_ANADIG_USB1_LOOPBACK_TOG (0x000001ec)
+
+#define BP_ANADIG_USB1_LOOPBACK_RSVD0 9
+#define BM_ANADIG_USB1_LOOPBACK_RSVD0 0xFFFFFE00
+#define BF_ANADIG_USB1_LOOPBACK_RSVD0(v) \
+ (((v) << 9) & BM_ANADIG_USB1_LOOPBACK_RSVD0)
+#define BM_ANADIG_USB1_LOOPBACK_UTMO_DIG_TST1 0x00000100
+#define BM_ANADIG_USB1_LOOPBACK_UTMO_DIG_TST0 0x00000080
+#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_HIZ 0x00000040
+#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN 0x00000020
+#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_LS_MODE 0x00000010
+#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_HS_MODE 0x00000008
+#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 0x00000004
+#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST0 0x00000002
+#define BM_ANADIG_USB1_LOOPBACK_UTMI_TESTSTART 0x00000001
+
+#define HW_ANADIG_USB1_MISC (0x000001f0)
+#define HW_ANADIG_USB1_MISC_SET (0x000001f4)
+#define HW_ANADIG_USB1_MISC_CLR (0x000001f8)
+#define HW_ANADIG_USB1_MISC_TOG (0x000001fc)
+
+#define BM_ANADIG_USB1_MISC_RSVD1 0x80000000
+#define BM_ANADIG_USB1_MISC_EN_CLK_UTMI 0x40000000
+#define BM_ANADIG_USB1_MISC_RX_VPIN_FS 0x20000000
+#define BM_ANADIG_USB1_MISC_RX_VMIN_FS 0x10000000
+#define BM_ANADIG_USB1_MISC_RX_RXD_FS 0x08000000
+#define BM_ANADIG_USB1_MISC_RX_SQUELCH 0x04000000
+#define BM_ANADIG_USB1_MISC_RX_DISCON_DET 0x02000000
+#define BM_ANADIG_USB1_MISC_RX_HS_DATA 0x01000000
+#define BP_ANADIG_USB1_MISC_RSVD0 2
+#define BM_ANADIG_USB1_MISC_RSVD0 0x00FFFFFC
+#define BF_ANADIG_USB1_MISC_RSVD0(v) \
+ (((v) << 2) & BM_ANADIG_USB1_MISC_RSVD0)
+#define BM_ANADIG_USB1_MISC_EN_DEGLITCH 0x00000002
+#define BM_ANADIG_USB1_MISC_HS_USE_EXTERNAL_R 0x00000001
+
+#define HW_ANADIG_USB2_VBUS_DETECT (0x00000200)
+#define HW_ANADIG_USB2_VBUS_DETECT_SET (0x00000204)
+#define HW_ANADIG_USB2_VBUS_DETECT_CLR (0x00000208)
+#define HW_ANADIG_USB2_VBUS_DETECT_TOG (0x0000020c)
+
+#define BM_ANADIG_USB2_VBUS_DETECT_EN_CHARGER_RESISTOR 0x80000000
+#define BP_ANADIG_USB2_VBUS_DETECT_RSVD2 28
+#define BM_ANADIG_USB2_VBUS_DETECT_RSVD2 0x70000000
+#define BF_ANADIG_USB2_VBUS_DETECT_RSVD2(v) \
+ (((v) << 28) & BM_ANADIG_USB2_VBUS_DETECT_RSVD2)
+#define BM_ANADIG_USB2_VBUS_DETECT_CHARGE_VBUS 0x08000000
+#define BM_ANADIG_USB2_VBUS_DETECT_DISCHARGE_VBUS 0x04000000
+#define BP_ANADIG_USB2_VBUS_DETECT_RSVD1 21
+#define BM_ANADIG_USB2_VBUS_DETECT_RSVD1 0x03E00000
+#define BF_ANADIG_USB2_VBUS_DETECT_RSVD1(v) \
+ (((v) << 21) & BM_ANADIG_USB2_VBUS_DETECT_RSVD1)
+#define BM_ANADIG_USB2_VBUS_DETECT_VBUSVALID_PWRUP_CMPS 0x00100000
+#define BM_ANADIG_USB2_VBUS_DETECT_VBUSVALID_5VDETECT 0x00080000
+#define BM_ANADIG_USB2_VBUS_DETECT_VBUSVALID_TO_B 0x00040000
+#define BP_ANADIG_USB2_VBUS_DETECT_RSVD0 3
+#define BM_ANADIG_USB2_VBUS_DETECT_RSVD0 0x0003FFF8
+#define BF_ANADIG_USB2_VBUS_DETECT_RSVD0(v) \
+ (((v) << 3) & BM_ANADIG_USB2_VBUS_DETECT_RSVD0)
+#define BP_ANADIG_USB2_VBUS_DETECT_VBUSVALID_THRESH 0
+#define BM_ANADIG_USB2_VBUS_DETECT_VBUSVALID_THRESH 0x00000007
+#define BF_ANADIG_USB2_VBUS_DETECT_VBUSVALID_THRESH(v) \
+ (((v) << 0) & BM_ANADIG_USB2_VBUS_DETECT_VBUSVALID_THRESH)
+
+#define HW_ANADIG_USB2_CHRG_DETECT (0x00000210)
+#define HW_ANADIG_USB2_CHRG_DETECT_SET (0x00000214)
+#define HW_ANADIG_USB2_CHRG_DETECT_CLR (0x00000218)
+#define HW_ANADIG_USB2_CHRG_DETECT_TOG (0x0000021c)
+
+#define BP_ANADIG_USB2_CHRG_DETECT_RSVD2 24
+#define BM_ANADIG_USB2_CHRG_DETECT_RSVD2 0xFF000000
+#define BF_ANADIG_USB2_CHRG_DETECT_RSVD2(v) \
+ (((v) << 24) & BM_ANADIG_USB2_CHRG_DETECT_RSVD2)
+#define BM_ANADIG_USB2_CHRG_DETECT_BGR_BIAS 0x00800000
+#define BP_ANADIG_USB2_CHRG_DETECT_RSVD1 21
+#define BM_ANADIG_USB2_CHRG_DETECT_RSVD1 0x00600000
+#define BF_ANADIG_USB2_CHRG_DETECT_RSVD1(v) \
+ (((v) << 21) & BM_ANADIG_USB2_CHRG_DETECT_RSVD1)
+#define BM_ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000
+#define BM_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000
+#define BM_ANADIG_USB2_CHRG_DETECT_CHK_CONTACT 0x00040000
+#define BP_ANADIG_USB2_CHRG_DETECT_RSVD0 1
+#define BM_ANADIG_USB2_CHRG_DETECT_RSVD0 0x0003FFFE
+#define BF_ANADIG_USB2_CHRG_DETECT_RSVD0(v) \
+ (((v) << 1) & BM_ANADIG_USB2_CHRG_DETECT_RSVD0)
+#define BM_ANADIG_USB2_CHRG_DETECT_FORCE_DETECT 0x00000001
+
+#define HW_ANADIG_USB2_VBUS_DET_STAT (0x00000220)
+#define HW_ANADIG_USB2_VBUS_DET_STAT_SET (0x00000224)
+#define HW_ANADIG_USB2_VBUS_DET_STAT_CLR (0x00000228)
+#define HW_ANADIG_USB2_VBUS_DET_STAT_TOG (0x0000022c)
+
+#define BP_ANADIG_USB2_VBUS_DET_STAT_RSVD0 4
+#define BM_ANADIG_USB2_VBUS_DET_STAT_RSVD0 0xFFFFFFF0
+#define BF_ANADIG_USB2_VBUS_DET_STAT_RSVD0(v) \
+ (((v) << 4) & BM_ANADIG_USB2_VBUS_DET_STAT_RSVD0)
+#define BM_ANADIG_USB2_VBUS_DET_STAT_VBUS_VALID 0x00000008
+#define BM_ANADIG_USB2_VBUS_DET_STAT_AVALID 0x00000004
+#define BM_ANADIG_USB2_VBUS_DET_STAT_BVALID 0x00000002
+#define BM_ANADIG_USB2_VBUS_DET_STAT_SESSEND 0x00000001
+
+#define HW_ANADIG_USB2_CHRG_DET_STAT (0x00000230)
+#define HW_ANADIG_USB2_CHRG_DET_STAT_SET (0x00000234)
+#define HW_ANADIG_USB2_CHRG_DET_STAT_CLR (0x00000238)
+#define HW_ANADIG_USB2_CHRG_DET_STAT_TOG (0x0000023c)
+
+#define BP_ANADIG_USB2_CHRG_DET_STAT_RSVD0 4
+#define BM_ANADIG_USB2_CHRG_DET_STAT_RSVD0 0xFFFFFFF0
+#define BF_ANADIG_USB2_CHRG_DET_STAT_RSVD0(v) \
+ (((v) << 4) & BM_ANADIG_USB2_CHRG_DET_STAT_RSVD0)
+#define BM_ANADIG_USB2_CHRG_DET_STAT_DP_STATE 0x00000008
+#define BM_ANADIG_USB2_CHRG_DET_STAT_DM_STATE 0x00000004
+#define BM_ANADIG_USB2_CHRG_DET_STAT_CHRG_DETECTED 0x00000002
+#define BM_ANADIG_USB2_CHRG_DET_STAT_PLUG_CONTACT 0x00000001
+
+#define HW_ANADIG_USB2_LOOPBACK (0x00000240)
+#define HW_ANADIG_USB2_LOOPBACK_SET (0x00000244)
+#define HW_ANADIG_USB2_LOOPBACK_CLR (0x00000248)
+#define HW_ANADIG_USB2_LOOPBACK_TOG (0x0000024c)
+
+#define BP_ANADIG_USB2_LOOPBACK_RSVD0 9
+#define BM_ANADIG_USB2_LOOPBACK_RSVD0 0xFFFFFE00
+#define BF_ANADIG_USB2_LOOPBACK_RSVD0(v) \
+ (((v) << 9) & BM_ANADIG_USB2_LOOPBACK_RSVD0)
+#define BM_ANADIG_USB2_LOOPBACK_UTMO_DIG_TST1 0x00000100
+#define BM_ANADIG_USB2_LOOPBACK_UTMO_DIG_TST0 0x00000080
+#define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_HIZ 0x00000040
+#define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN 0x00000020
+#define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_LS_MODE 0x00000010
+#define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_HS_MODE 0x00000008
+#define BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 0x00000004
+#define BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST0 0x00000002
+#define BM_ANADIG_USB2_LOOPBACK_UTMI_TESTSTART 0x00000001
+
+#define HW_ANADIG_USB2_MISC (0x00000250)
+#define HW_ANADIG_USB2_MISC_SET (0x00000254)
+#define HW_ANADIG_USB2_MISC_CLR (0x00000258)
+#define HW_ANADIG_USB2_MISC_TOG (0x0000025c)
+
+#define BM_ANADIG_USB2_MISC_RSVD1 0x80000000
+#define BM_ANADIG_USB2_MISC_EN_CLK_UTMI 0x40000000
+#define BM_ANADIG_USB2_MISC_RX_VPIN_FS 0x20000000
+#define BM_ANADIG_USB2_MISC_RX_VMIN_FS 0x10000000
+#define BM_ANADIG_USB2_MISC_RX_RXD_FS 0x08000000
+#define BM_ANADIG_USB2_MISC_RX_SQUELCH 0x04000000
+#define BM_ANADIG_USB2_MISC_RX_DISCON_DET 0x02000000
+#define BM_ANADIG_USB2_MISC_RX_HS_DATA 0x01000000
+#define BP_ANADIG_USB2_MISC_RSVD0 2
+#define BM_ANADIG_USB2_MISC_RSVD0 0x00FFFFFC
+#define BF_ANADIG_USB2_MISC_RSVD0(v) \
+ (((v) << 2) & BM_ANADIG_USB2_MISC_RSVD0)
+#define BM_ANADIG_USB2_MISC_EN_DEGLITCH 0x00000002
+#define BM_ANADIG_USB2_MISC_HS_USE_EXTERNAL_R 0x00000001
+
+#define HW_ANADIG_DIGPROG (0x00000260)
+
+#define BP_ANADIG_DIGPROG_RSVD 24
+#define BM_ANADIG_DIGPROG_RSVD 0xFF000000
+#define BF_ANADIG_DIGPROG_RSVD(v) \
+ (((v) << 24) & BM_ANADIG_DIGPROG_RSVD)
+#define BP_ANADIG_DIGPROG_MAJOR 8
+#define BM_ANADIG_DIGPROG_MAJOR 0x00FFFF00
+#define BF_ANADIG_DIGPROG_MAJOR(v) \
+ (((v) << 8) & BM_ANADIG_DIGPROG_MAJOR)
+#define BP_ANADIG_DIGPROG_MINOR 0
+#define BM_ANADIG_DIGPROG_MINOR 0x000000FF
+#define BF_ANADIG_DIGPROG_MINOR(v) \
+ (((v) << 0) & BM_ANADIG_DIGPROG_MINOR)
+#endif /* __ARCH_ARM___ANADIG_H */
diff --git a/arch/arm/mach-mx6/serial.h b/arch/arm/mach-mx6/serial.h
new file mode 100644
index 00000000..c510b59b
--- /dev/null
+++ b/arch/arm/mach-mx6/serial.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_MX51_SERIAL_H__
+#define __ARCH_ARM_MACH_MX51_SERIAL_H__
+
+/* UART 1 configuration */
+/*!
+ * This specifies the threshold at which the CTS pin is deasserted by the
+ * RXFIFO. Set this value in Decimal to anything from 0 to 32 for
+ * hardware-driven hardware flow control. Read the HW spec while specifying
+ * this value. When using interrupt-driven software controlled hardware
+ * flow control set this option to -1.
+ */
+#define UART1_UCR4_CTSTL 16
+/*!
+ * Specify the size of the DMA receive buffer. The minimum buffer size is 512
+ * bytes. The buffer size should be a multiple of 256.
+ */
+#define UART1_DMA_RXBUFSIZE 1024
+/*!
+ * Specify the MXC UART's Receive Trigger Level. This controls the threshold at
+ * which a maskable interrupt is generated by the RxFIFO. Set this value in
+ * Decimal to anything from 0 to 32. Read the HW spec while specifying this
+ * value.
+ */
+#define UART1_UFCR_RXTL 16
+/*!
+ * Specify the MXC UART's Transmit Trigger Level. This controls the threshold at
+ * which a maskable interrupt is generated by the TxFIFO. Set this value in
+ * Decimal to anything from 0 to 32. Read the HW spec while specifying this
+ * value.
+ */
+#define UART1_UFCR_TXTL 16
+#define UART1_DMA_ENABLE 0
+/* UART 2 configuration */
+#define UART2_UCR4_CTSTL -1
+#define UART2_DMA_ENABLE 1
+#define UART2_DMA_RXBUFSIZE 512
+#define UART2_UFCR_RXTL 16
+#define UART2_UFCR_TXTL 16
+/* UART 3 configuration */
+#define UART3_UCR4_CTSTL 16
+#define UART3_DMA_ENABLE 0
+#define UART3_DMA_RXBUFSIZE 1024
+#define UART3_UFCR_RXTL 16
+#define UART3_UFCR_TXTL 16
+/* UART 4 configuration */
+#define UART4_UCR4_CTSTL -1
+#define UART4_DMA_ENABLE 0
+#define UART4_DMA_RXBUFSIZE 512
+#define UART4_UFCR_RXTL 16
+#define UART4_UFCR_TXTL 16
+/* UART 5 configuration */
+#define UART5_UCR4_CTSTL -1
+#define UART5_DMA_ENABLE 0
+#define UART5_DMA_RXBUFSIZE 512
+#define UART5_UFCR_RXTL 16
+#define UART5_UFCR_TXTL 16
+
+#endif /* __ARCH_ARM_MACH_MX51_SERIAL_H__ */
diff --git a/arch/arm/mach-mx6/src-reg.h b/arch/arm/mach-mx6/src-reg.h
new file mode 100644
index 00000000..dc13e431
--- /dev/null
+++ b/arch/arm/mach-mx6/src-reg.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+
+ * 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.
+ */
+
+/*
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.30
+ * Template revision: 1.3
+ */
+#ifndef _SRC_REGISTER_HEADER_
+#define _SRC_REGISTER_HEADER_
+
+#define SRC_SCR_OFFSET 0x000
+#define SRC_SBMR_OFFSET 0x004
+#define SRC_SRSR_OFFSET 0x008
+#define SRC_SAIAR_OFFSET 0x00c
+#define SRC_SAIRAR_OFFSET 0x010
+#define SRC_SISR_OFFSET 0x014
+#define SRC_SIMR_OFFSET 0x018
+#define SRC_SBMR2_OFFSET 0x01c
+#define SRC_GPR1_OFFSET 0x020
+#define SRC_GPR2_OFFSET 0x024
+#define SRC_GPR3_OFFSET 0x028
+#define SRC_GPR4_OFFSET 0x02c
+#define SRC_GPR5_OFFSET 0x030
+#define SRC_GPR6_OFFSET 0x034
+#define SRC_GPR7_OFFSET 0x038
+#define SRC_GPR8_OFFSET 0x03c
+#define SRC_GPR9_OFFSET 0x040
+#define SRC_GPR10_OFFSET 0x044
+
+#define BP_SRC_SCR_CORE0_RST 13
+#define BP_SRC_SCR_CORES_DBG_RST 21
+#define BP_SRC_SCR_CORE1_ENABLE 22
+
+#endif
diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c
new file mode 100644
index 00000000..a195094b
--- /dev/null
+++ b/arch/arm/mach-mx6/system.c
@@ -0,0 +1,682 @@
+/*
+ * Copyright (C) 2011-2013 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 <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/clockchips.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <asm/proc-fns.h>
+#include <asm/system.h>
+#include <asm/hardware/gic.h>
+#include "crm_regs.h"
+#include "regs-anadig.h"
+
+#include "ntx_hwconfig.h"
+
+
+#define SCU_CTRL 0x00
+#define SCU_CONFIG 0x04
+#define SCU_CPU_STATUS 0x08
+#define SCU_INVALIDATE 0x0c
+#define SCU_FPGA_REVISION 0x10
+#define GPC_CNTR_OFFSET 0x0
+#define GPC_PGC_GPU_PGCR_OFFSET 0x260
+#define GPC_PGC_CPU_PDN_OFFSET 0x2a0
+#define GPC_PGC_CPU_PUPSCR_OFFSET 0x2a4
+#define GPC_PGC_CPU_PDNSCR_OFFSET 0x2a8
+
+#define MODULE_CLKGATE (1 << 30)
+#define MODULE_SFTRST (1 << 31)
+
+extern unsigned int gpc_wake_irq[4];
+
+static void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+extern struct clk *mmdc_ch0_axi;
+
+volatile unsigned int num_cpu_idle;
+volatile unsigned int num_cpu_idle_lock = 0x0;
+int wait_mode_arm_podf;
+int cur_arm_podf;
+bool enet_is_active;
+void arch_idle_with_workaround(int cpu);
+
+extern void *mx6sl_wfi_iram_base;
+extern void (*mx6sl_wfi_iram)(int arm_podf, unsigned long wfi_iram_addr, \
+ int audio_mode);
+extern void mx6_wait(void *num_cpu_idle_lock, void *num_cpu_idle, \
+ int wait_arm_podf, int cur_arm_podf);
+extern unsigned long save_ttbr1(void);
+extern void restore_ttbr1(u32 ttbr1);
+
+extern bool enable_wait_mode;
+extern int low_bus_freq_mode;
+extern int audio_bus_freq_mode;
+extern bool mem_clk_on_in_wait;
+extern int chip_rev;
+
+extern volatile NTX_HWCONFIG *gptHWCFG;
+
+void gpc_set_wakeup(unsigned int irq[4])
+{
+ /* Mask all wake up source */
+ __raw_writel(~irq[0], gpc_base + 0x8);
+ __raw_writel(~irq[1], gpc_base + 0xc);
+ __raw_writel(~irq[2], gpc_base + 0x10);
+ __raw_writel(~irq[3], gpc_base + 0x14);
+
+ return;
+}
+
+void gpc_mask_single_irq(int irq, bool enable)
+{
+ void __iomem *reg;
+ u32 val;
+
+ reg = gpc_base + 0x8 + (irq / 32 - 1) * 4;
+ val = __raw_readl(reg);
+ if (enable)
+ val |= 1 << (irq % 32);
+ else
+ val &= ~(1 << (irq % 32));
+ __raw_writel(val, reg);
+
+ return;
+}
+
+/* set cpu low power mode before WFI instruction */
+void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+{
+
+ int stop_mode = 0;
+ void __iomem *anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR);
+ u32 ccm_clpcr, anatop_val;
+
+ ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
+ /*
+ * CCM state machine has restriction that, everytime enable
+ * LPM mode, we need to make sure last wakeup from LPM mode
+ * is a dsm_wakeup_signal, which means the wakeup source
+ * must be seen by GPC, then CCM will clean its state machine
+ * and re-sample necessary signal to decide whether it can
+ * enter LPM mode. Here we force irq #32 to be always pending,
+ * unmask it before we enable LPM mode and mask it after LPM
+ * is enabled, this flow will make sure CCM state machine in
+ * reliable state before we enter LPM mode.
+ */
+ gpc_mask_single_irq(MXC_INT_GPR, false);
+
+ switch (mode) {
+ case WAIT_CLOCKED:
+ break;
+ case WAIT_UNCLOCKED:
+ ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+ break;
+ case WAIT_UNCLOCKED_POWER_OFF:
+ case STOP_POWER_OFF:
+ case ARM_POWER_OFF:
+ if (mode == WAIT_UNCLOCKED_POWER_OFF) {
+ ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+ ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ stop_mode = 0;
+ } else if (mode == STOP_POWER_OFF) {
+ ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+ ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
+ ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ stop_mode = 1;
+ } else {
+ ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+ ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
+ ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ stop_mode = 2;
+ }
+ break;
+ case STOP_XTAL_ON:
+ ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+ ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ stop_mode = 3;
+
+ break;
+ default:
+ printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
+ gpc_mask_single_irq(MXC_INT_GPR, true);
+ return;
+ }
+
+ if (stop_mode > 0) {
+ gpc_set_wakeup(gpc_wake_irq);
+ /* Power down and power up sequence */
+ /* The PUPSCR counter counts in terms of CLKIL (32KHz) cycles.
+ * The PUPSCR should include the time it takes for the ARM LDO to
+ * ramp up.
+ */
+ __raw_writel(0xf0f, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
+ /* The PDNSCR is a counter that counts in IPG_CLK cycles. This counter
+ * can be set to minimum values to power down faster.
+ */
+ __raw_writel(0x101, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
+ if (stop_mode >= 2) {
+ /* dormant mode, need to power off the arm core */
+ __raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
+#if 0
+ if (cpu_is_mx6q() || cpu_is_mx6dl() && (4!=gptHWCFG->m_val.bRamType) )
+#else
+ if( cpu_is_mx6q() || cpu_is_mx6dl() )
+#endif
+ {
+ /* If stop_mode_config is clear, then 2P5 will be off,
+ need to enable weak 2P5, as DDR IO need 2P5 as
+ pre-driver */
+ if ((__raw_readl(anatop_base + HW_ANADIG_ANA_MISC0)
+ & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) {
+ /* Enable weak 2P5 linear regulator */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_REG_2P5);
+ anatop_val |= BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_REG_2P5);
+ }
+ if (mx6q_revision() != IMX_CHIP_REVISION_1_0) {
+ /* Enable fet_odrive */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_REG_CORE);
+ anatop_val |= BM_ANADIG_REG_CORE_FET_ODRIVE;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_REG_CORE);
+ }
+ } else {
+ if (stop_mode == 2) {
+#if 1
+ /* Disable VDDHIGH_IN to VDDSNVS_IN
+ * power path, only used when VDDSNVS_IN
+ * is powered by dedicated
+ * power rail */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_ANA_MISC0);
+ anatop_val |= BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_ANA_MISC0);
+#endif
+ /* Need to enable pull down if 2P5 is disabled */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_REG_2P5);
+
+#if 1 //[
+ if ( /* <= E60Q2XA14 */
+ (33==gptHWCFG->m_val.bPCB && gptHWCFG->m_val.bPCB_REV<=0x14 ) ||
+ /* <= E60Q30BXX */
+ (36==gptHWCFG->m_val.bPCB && gptHWCFG->m_val.bPCB_LVL==1 ) ||
+ /* <= E60QBXA00 */
+ (37==gptHWCFG->m_val.bPCB && gptHWCFG->m_val.bPCB_REV<=0 ) )
+ {
+ //printk("%s<=E60Q2XA14|<=E60Q3XA00\n",__FUNCTION__);
+ /* Enable weak 2P5 linear regulator */
+ anatop_val |= BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG|
+ BM_ANADIG_REG_2P5_ENABLE_ILIMIT;
+ }
+ else
+ {
+ anatop_val |= (BM_ANADIG_REG_2P5_ENABLE_ILIMIT|
+ BM_ANADIG_REG_2P5_ENABLE_PULLDOWN);
+ }
+#endif //]
+
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_REG_2P5);
+
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_REG_1P1);
+ anatop_val |= BM_ANADIG_REG_1P1_ENABLE_ILIMIT;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_REG_1P1);
+ }
+ }
+ if (stop_mode != 3) {
+ /* Make sure we clear WB_COUNT
+ * and re-config it.
+ */
+ __raw_writel(__raw_readl(MXC_CCM_CCR) &
+ (~MXC_CCM_CCR_WB_COUNT_MASK),
+ MXC_CCM_CCR);
+ /* Reconfigure WB, need to set WB counter
+ * to 0x7 to make sure it work normally */
+ __raw_writel(__raw_readl(MXC_CCM_CCR) |
+ (0x7 << MXC_CCM_CCR_WB_COUNT_OFFSET),
+ MXC_CCM_CCR);
+
+ /* Set WB_PER enable */
+ ccm_clpcr |= MXC_CCM_CLPCR_WB_PER_AT_LPM;
+ }
+ }
+ if (cpu_is_mx6sl() ||
+ (mx6q_revision() > IMX_CHIP_REVISION_1_1) ||
+ (mx6dl_revision() > IMX_CHIP_REVISION_1_0)) {
+ u32 reg;
+ /* We need to allow the memories to be clock gated
+ * in STOP mode, else the power consumption will
+ * be very high.
+ */
+ reg = __raw_readl(MXC_CCM_CGPR);
+ reg |= MXC_CCM_CGPR_MEM_IPG_STOP_MASK;
+ if (!cpu_is_mx6sl() && stop_mode >= 2) {
+ /*
+ * For MX6QTO1.2 or later and MX6DLTO1.1 or later,
+ * ensure that the CCM_CGPR bit 17 is cleared before
+ * dormant mode is entered.
+ */
+ reg &= ~MXC_CCM_CGPR_WAIT_MODE_FIX;
+ }
+ __raw_writel(reg, MXC_CCM_CGPR);
+ }
+ }
+ __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+ gpc_mask_single_irq(MXC_INT_GPR, true);
+}
+
+extern int tick_broadcast_oneshot_active(void);
+
+void ca9_do_idle(void)
+{
+ do {
+ cpu_do_idle();
+ } while (__raw_readl(gic_cpu_base_addr + GIC_CPU_HIGHPRI) == 1023);
+}
+
+void arch_idle_single_core(void)
+{
+ u32 reg;
+
+ if (cpu_is_mx6dl() && chip_rev > IMX_CHIP_REVISION_1_0) {
+ /*
+ * MX6DLS TO1.1 has the HW fix for the WAIT mode issue.
+ * Ensure that the CGPR bit 17 is set to enable the fix.
+ */
+ reg = __raw_readl(MXC_CCM_CGPR);
+ reg |= MXC_CCM_CGPR_WAIT_MODE_FIX;
+ __raw_writel(reg, MXC_CCM_CGPR);
+
+ ca9_do_idle();
+ } else {
+ if (low_bus_freq_mode || audio_bus_freq_mode) {
+ int ddr_usecount = 0;
+ if ((mmdc_ch0_axi != NULL))
+ ddr_usecount = clk_get_usecount(mmdc_ch0_axi);
+
+ if (cpu_is_mx6sl() && (ddr_usecount == 1) &&
+ (low_bus_freq_mode || audio_bus_freq_mode)) {
+ /* In this mode PLL2 i already in bypass,
+ * ARM is sourced from PLL1. The code in IRAM
+ * will set ARM to be sourced from STEP_CLK
+ * at 24MHz. It will also set DDR to 1MHz to
+ * reduce power.
+ */
+ u32 org_arm_podf = __raw_readl(MXC_CCM_CACRR);
+ u32 ttbr1;
+
+ outer_sync();
+ /* Need to run WFI code from IRAM so that
+ * we can lower DDR freq.
+ */
+ ttbr1 = save_ttbr1();
+ mx6sl_wfi_iram(org_arm_podf,
+ (unsigned long)mx6sl_wfi_iram_base,
+ audio_bus_freq_mode);
+ restore_ttbr1(ttbr1);
+ } else {
+ /* Need to set ARM to run at 24MHz since IPG
+ * is at 12MHz. This is valid for audio mode on
+ * MX6SL, and all low power modes on MX6DLS.
+ */
+ if (cpu_is_mx6sl() && low_bus_freq_mode) {
+ /* ARM is from PLL1, need to switch to
+ * STEP_CLK sourced from 24MHz.
+ */
+ /* Swtich STEP_CLK to 24MHz. */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_STEP_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* Set PLL1_SW_CLK to be from
+ *STEP_CLK.
+ */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ } else {
+ /* PLL1_SW_CLK is sourced from
+ * PLL2_PFD2_400MHz at this point.
+ * Move it to bypassed PLL1.
+ */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ }
+ ca9_do_idle();
+
+ if (cpu_is_mx6sl() && low_bus_freq_mode) {
+ /* Set PLL1_SW_CLK to be from PLL1 */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ } else {
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ }
+ }
+ } else {
+ /*
+ * Implement the 12:5 ARM:IPG_CLK ratio
+ * workaround for the WAIT mode issue.
+ * We can directly use the divider to drop the ARM
+ * core freq in a single core environment.
+ * Set the ARM_PODF to get the max freq possible
+ * to avoid the WAIT mode issue when IPG is at 66MHz.
+ */
+ __raw_writel(wait_mode_arm_podf, MXC_CCM_CACRR);
+ while (__raw_readl(MXC_CCM_CDHIPR))
+ ;
+ ca9_do_idle();
+
+ __raw_writel(cur_arm_podf - 1, MXC_CCM_CACRR);
+ }
+ }
+}
+
+void arch_idle_with_workaround(int cpu)
+{
+ u32 podf = wait_mode_arm_podf;
+
+ *((char *)(&num_cpu_idle_lock) + (char)cpu) = 0x0;
+
+ if (low_bus_freq_mode || audio_bus_freq_mode)
+ /* In case when IPG is at 12MHz, we need to ensure that
+ * ARM is at 24MHz, as the max freq ARM can run at is
+ *~28.8MHz.
+ */
+ podf = 0;
+
+ mx6_wait((void *)&num_cpu_idle_lock,
+ (void *)&num_cpu_idle,
+ podf, cur_arm_podf - 1);
+
+}
+
+void arch_idle_multi_core(int cpu)
+{
+ u32 reg;
+
+ /* iMX6Q and iMX6DL */
+ if ((cpu_is_mx6q() && chip_rev >= IMX_CHIP_REVISION_1_2) ||
+ (cpu_is_mx6dl() && chip_rev >= IMX_CHIP_REVISION_1_1)) {
+ /*
+ * This code should only be executed on MX6QTO1.2 or later
+ * and MX6DL TO1.1 or later.
+ * These chips have the HW fix for the WAIT mode issue.
+ * Ensure that the CGPR bit 17 is set to enable the fix.
+ */
+
+ reg = __raw_readl(MXC_CCM_CGPR);
+ reg |= MXC_CCM_CGPR_WAIT_MODE_FIX;
+ __raw_writel(reg, MXC_CCM_CGPR);
+
+ ca9_do_idle();
+ } else
+ arch_idle_with_workaround(cpu);
+}
+
+void arch_idle(void)
+{
+ int cpu = smp_processor_id();
+
+ if (enable_wait_mode) {
+#ifdef CONFIG_LOCAL_TIMERS
+ if (!tick_broadcast_oneshot_active()
+ || !tick_oneshot_mode_active())
+ return;
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+#endif
+ if (enet_is_active)
+ /* Don't allow the chip to enter WAIT mode if enet is active
+ * and the GPIO workaround for ENET interrupts is not used,
+ * since all ENET interrupts donot wake up the SOC.
+ */
+ mxc_cpu_lp_set(WAIT_CLOCKED);
+ else
+ mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+ if (mem_clk_on_in_wait) {
+ u32 reg;
+ /*
+ * MX6SL, MX6Q (TO1.2 or later) and
+ * MX6DL (TO1.1 or later) have a bit in
+ * CCM_CGPR that when cleared keeps the
+ * clocks to memories ON when ARM is in WFI.
+ * This mode can be used when IPG clock is
+ * very low (12MHz) and the ARM:IPG ratio
+ * perhaps cannot be maintained.
+ */
+ reg = __raw_readl(MXC_CCM_CGPR);
+ reg &= ~MXC_CCM_CGPR_MEM_IPG_STOP_MASK;
+ __raw_writel(reg, MXC_CCM_CGPR);
+
+ ca9_do_idle();
+ } else if (num_possible_cpus() == 1)
+ /* iMX6SL or iMX6DLS */
+ arch_idle_single_core();
+ else
+ arch_idle_multi_core(cpu);
+#ifdef CONFIG_LOCAL_TIMERS
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+#endif
+ } else {
+ mxc_cpu_lp_set(WAIT_CLOCKED);
+ ca9_do_idle();
+ }
+}
+
+static int __mxs_reset_block(void __iomem *hwreg, int just_enable)
+{
+ u32 c;
+ int timeout;
+
+ /* the process of software reset of IP block is done
+ in several steps:
+
+ - clear SFTRST and wait for block is enabled;
+ - clear clock gating (CLKGATE bit);
+ - set the SFTRST again and wait for block is in reset;
+ - clear SFTRST and wait for reset completion.
+ */
+ c = __raw_readl(hwreg);
+ c &= ~MODULE_SFTRST; /* clear SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & MODULE_SFTRST) == 0)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when enabling\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~MODULE_CLKGATE; /* clear CLKGATE */
+ __raw_writel(c, hwreg);
+
+ if (!just_enable) {
+ c = __raw_readl(hwreg);
+ c |= MODULE_SFTRST; /* now again set SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* poll until CLKGATE set */
+ if (__raw_readl(hwreg) & MODULE_CLKGATE)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when resetting\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~MODULE_SFTRST; /* clear SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & MODULE_SFTRST) == 0)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when enabling "
+ "after reset\n", __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~MODULE_CLKGATE; /* clear CLKGATE */
+ __raw_writel(c, hwreg);
+ }
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & MODULE_CLKGATE) == 0)
+ break;
+
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when unclockgating\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ return 0;
+}
+
+static int _mxs_reset_block(void __iomem *hwreg, int just_enable)
+{
+ int try = 10;
+ int r;
+
+ while (try--) {
+ r = __mxs_reset_block(hwreg, just_enable);
+ if (!r)
+ break;
+ pr_debug("%s: try %d failed\n", __func__, 10 - try);
+ }
+ return r;
+}
+
+
+#define BOOT_MODE_SERIAL_ROM (0x00000030)
+#define PERSIST_WATCHDOG_RESET_BOOT (0x10000000)
+/*BOOT_CFG1[7..4] = 0x3 Boot from Serial ROM (I2C/SPI)*/
+
+#ifdef CONFIG_MXC_REBOOT_MFGMODE
+void do_switch_mfgmode(void)
+{
+ u32 reg;
+
+ /*
+ * During reset, if GPR10[28] is 1, ROM will copy GPR9[25:0]
+ * to SBMR1, which will determine what is the boot device.
+ * Here SERIAL_ROM mode is selected
+ */
+ reg = __raw_readl(SRC_BASE_ADDR + SRC_GPR9);
+ reg |= BOOT_MODE_SERIAL_ROM;
+ __raw_writel(reg, SRC_BASE_ADDR + SRC_GPR9);
+
+ reg = __raw_readl(SRC_BASE_ADDR + SRC_GPR10);
+ reg |= PERSIST_WATCHDOG_RESET_BOOT;
+ __raw_writel(reg, SRC_BASE_ADDR + SRC_GPR10);
+
+}
+
+void mxc_clear_mfgmode(void)
+{
+ u32 reg;
+ reg = __raw_readl(SRC_BASE_ADDR + SRC_GPR9);
+
+ reg &= ~BOOT_MODE_SERIAL_ROM;
+ __raw_writel(reg, SRC_BASE_ADDR + SRC_GPR9);
+
+ reg = __raw_readl(SRC_BASE_ADDR + SRC_GPR10);
+ reg &= ~PERSIST_WATCHDOG_RESET_BOOT;
+ __raw_writel(reg, SRC_BASE_ADDR + SRC_GPR10);
+}
+#endif
+
+#ifdef CONFIG_MXC_REBOOT_ANDROID_CMD
+/* This function will set a bit on SNVS_LPGPR[7-8] bits to enter
+ * special boot mode. These bits will not clear by watchdog reset, so
+ * it can be checked by bootloader to choose enter different mode.*/
+
+#define ANDROID_RECOVERY_BOOT (1 << 7)
+#define ANDROID_FASTBOOT_BOOT (1 << 8)
+
+void do_switch_recovery(void)
+{
+ u32 reg;
+
+ reg = __raw_readl(MX6Q_SNVS_BASE_ADDR + SNVS_LPGPR);
+ reg |= ANDROID_RECOVERY_BOOT;
+ __raw_writel(reg, MX6Q_SNVS_BASE_ADDR + SNVS_LPGPR);
+}
+
+void do_switch_fastboot(void)
+{
+ u32 reg;
+
+ reg = __raw_readl(MX6Q_SNVS_BASE_ADDR + SNVS_LPGPR);
+ reg |= ANDROID_FASTBOOT_BOOT;
+ __raw_writel(reg, MX6Q_SNVS_BASE_ADDR + SNVS_LPGPR);
+}
+#endif
+
+int mxs_reset_block(void __iomem *hwreg)
+{
+ return _mxs_reset_block(hwreg, false);
+}
+EXPORT_SYMBOL(mxs_reset_block);
diff --git a/arch/arm/mach-mx6/usb.h b/arch/arm/mach-mx6/usb.h
new file mode 100644
index 00000000..819e45e5
--- /dev/null
+++ b/arch/arm/mach-mx6/usb.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011-2012 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 <mach/common.h>
+
+extern int usbotg_init(struct platform_device *pdev);
+extern void usbotg_uninit(struct fsl_usb2_platform_data *pdata);
+extern struct platform_device *host_pdev_register(struct resource *res,
+ int n_res, struct fsl_usb2_platform_data *config);
+
+extern int fsl_usb_host_init(struct platform_device *pdev);
+extern void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata);
+extern int gpio_usbotg_utmi_active(void);
+extern void gpio_usbotg_utmi_inactive(void);
+extern bool usb_icbug_swfix_need(void);
+extern void __init mx6_usb_h2_init(void);
+extern void __init mx6_usb_h3_init(void);
+
+typedef void (*driver_vbus_func)(bool);
+extern void mx6_set_host3_vbus_func(driver_vbus_func);
+extern void mx6_set_host2_vbus_func(driver_vbus_func);
+extern void mx6_set_host1_vbus_func(driver_vbus_func);
+extern void mx6_set_otghost_vbus_func(driver_vbus_func);
+extern void mx6_get_otghost_vbus_func(driver_vbus_func *driver_vbus);
+extern void mx6_get_host1_vbus_func(driver_vbus_func *driver_vbus);
+extern struct platform_device anatop_thermal_device;
+extern struct platform_device mxc_usbdr_otg_device;
+extern struct platform_device mxc_usbdr_udc_device;
+extern struct platform_device mxc_usbdr_host_device;
+extern struct platform_device mxc_usbdr_wakeup_device;
+extern struct platform_device mxc_usbh1_device;
+extern struct platform_device mxc_usbh1_wakeup_device;
+
+/*
+ * Used to set pdata->operating_mode before registering the platform_device.
+ * If OTG is configured, the controller operates in OTG mode,
+ * otherwise it's either host or device.
+ */
+#ifdef CONFIG_USB_OTG
+#define DR_UDC_MODE FSL_USB2_DR_OTG
+#define DR_HOST_MODE FSL_USB2_DR_OTG
+#else
+#define DR_UDC_MODE FSL_USB2_DR_DEVICE
+#define DR_HOST_MODE FSL_USB2_DR_HOST
+#endif
+
+extern void __iomem *imx_otg_base;
+#define imx_fsl_usb2_wakeup_data_entry_single(soc, _id, hs) \
+ { \
+ .id = _id, \
+ .irq_phy = soc ## _INT_USB_PHY ## _id, \
+ .irq_core = soc ## _INT_USB_ ## hs, \
+ }
+#define imx_mxc_ehci_data_entry_single(soc, _id, hs) \
+ { \
+ .id = _id, \
+ .iobase = soc ## _USB_ ## hs ## _BASE_ADDR, \
+ .irq = soc ## _INT_USB_ ## hs, \
+ }
+#define imx_fsl_usb2_otg_data_entry_single(soc) \
+ { \
+ .iobase = soc ## _USB_OTG_BASE_ADDR, \
+ .irq = soc ## _INT_USB_OTG, \
+ }
+#define imx_fsl_usb2_udc_data_entry_single(soc) \
+ { \
+ .iobase = soc ## _USB_OTG_BASE_ADDR, \
+ .irq = soc ## _INT_USB_OTG, \
+ }
+
diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c
new file mode 100644
index 00000000..cba9c541
--- /dev/null
+++ b/arch/arm/mach-mx6/usb_dr.c
@@ -0,0 +1,795 @@
+/*
+ * Copyright (C) 2012 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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <mach/arc_otg.h>
+#include <mach/hardware.h>
+#include "devices-imx6q.h"
+#include "regs-anadig.h"
+#include "usb.h"
+
+DEFINE_MUTEX(otg_wakeup_enable_mutex);
+static int usbotg_init_ext(struct platform_device *pdev);
+static void usbotg_uninit_ext(struct platform_device *pdev);
+static void usbotg_clock_gate(bool on);
+static void _dr_discharge_line(bool enable);
+extern bool usb_icbug_swfix_need(void);
+static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, \
+ bool enable);
+static u32 wakeup_irq_enable_src; /* only useful at otg mode */
+static u32 low_power_enable_src; /* only useful at otg mode */
+
+/* The usb_phy1_clk do not have enable/disable function at clock.c
+ * and PLL output for usb1's phy should be always enabled.
+ * usb_phy1_clk only stands for usb uses pll3 as its parent.
+ */
+static struct clk *usb_phy1_clk;
+static struct clk *usb_oh3_clk;
+static u8 otg_used;
+
+static void usbotg_wakeup_event_clear(void);
+extern int clk_get_usecount(struct clk *clk);
+/* Beginning of Common operation for DR port */
+
+/*
+ * platform data structs
+ * - Which one to use is determined by CONFIG options in usb.h
+ * - operating_mode plugged at run time
+ */
+static struct fsl_usb2_platform_data dr_utmi_config = {
+ .name = "DR",
+ .init = usbotg_init_ext,
+ .exit = usbotg_uninit_ext,
+ .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
+ .power_budget = 500, /* 500 mA max power */
+ .usb_clock_for_pm = usbotg_clock_gate,
+ .transceiver = "utmi",
+ .phy_regs = USB_PHY0_BASE_ADDR,
+ .dr_discharge_line = _dr_discharge_line,
+ .lowpower = true, /* Default driver low power is true */
+};
+
+/* Platform data for wakeup operation */
+static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = {
+ .name = "DR wakeup",
+ .usb_clock_for_pm = usbotg_clock_gate,
+ .usb_wakeup_exhandle = usbotg_wakeup_event_clear,
+};
+
+static void usbotg_internal_phy_clock_gate(bool on)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+ if (on) {
+ __raw_writel(BM_USBPHY_CTRL_CLKGATE, phy_reg + HW_USBPHY_CTRL_CLR);
+ } else {
+ __raw_writel(BM_USBPHY_CTRL_CLKGATE, phy_reg + HW_USBPHY_CTRL_SET);
+ }
+}
+
+static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
+{
+ u32 tmp;
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+ void __iomem *phy_ctrl;
+
+ /* Stop then Reset */
+ UOG_USBCMD &= ~UCMD_RUN_STOP;
+ while (UOG_USBCMD & UCMD_RUN_STOP)
+ ;
+
+ UOG_USBCMD |= UCMD_RESET;
+ while ((UOG_USBCMD) & (UCMD_RESET))
+ ;
+
+ /*
+ * If the controller reset does not put the PHY be out of
+ * low power mode, do it manually.
+ */
+ if (UOG_PORTSC1 & PORTSC_PHCD) {
+ UOG_PORTSC1 &= ~PORTSC_PHCD;
+ mdelay(1);
+ }
+
+ /* Reset USBPHY module */
+ phy_ctrl = phy_reg + HW_USBPHY_CTRL;
+ tmp = __raw_readl(phy_ctrl);
+ tmp |= BM_USBPHY_CTRL_SFTRST;
+ __raw_writel(tmp, phy_ctrl);
+ udelay(10);
+
+ /* Remove CLKGATE and SFTRST */
+ tmp = __raw_readl(phy_ctrl);
+ tmp &= ~(BM_USBPHY_CTRL_CLKGATE | BM_USBPHY_CTRL_SFTRST);
+ __raw_writel(tmp, phy_ctrl);
+ udelay(10);
+
+ /* Power up the PHY */
+ __raw_writel(0, phy_reg + HW_USBPHY_PWD);
+ if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
+ (pdata->operating_mode == FSL_USB2_DR_OTG)) {
+ /* enable FS/LS device */
+ __raw_writel(BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3
+ , phy_reg + HW_USBPHY_CTRL_SET);
+ }
+
+ if (!usb_icbug_swfix_need())
+ __raw_writel((1 << 17), phy_reg + HW_USBPHY_IP_SET);
+ if (cpu_is_mx6sl())
+ __raw_writel((1 << 18), phy_reg + HW_USBPHY_IP_SET);
+ return 0;
+}
+/* Notes: configure USB clock*/
+static int usbotg_init_ext(struct platform_device *pdev)
+{
+ struct clk *usb_clk;
+ u32 ret;
+
+ /* at mx6q: this clock is AHB clock for usb core */
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ usb_oh3_clk = usb_clk;
+
+ usb_clk = clk_get(NULL, "usb_phy1_clk");
+ clk_enable(usb_clk);
+ usb_phy1_clk = usb_clk;
+
+ ret = usbotg_init(pdev);
+ if (ret) {
+ clk_disable(usb_oh3_clk);
+ clk_put(usb_oh3_clk);
+ clk_disable(usb_phy1_clk);
+ clk_put(usb_phy1_clk);
+ printk(KERN_ERR "otg init fails......\n");
+ return ret;
+ }
+ if (!otg_used) {
+ wakeup_irq_enable_src = 0;
+ low_power_enable_src = 0;
+ usb_phy_enable(pdev->dev.platform_data);
+ enter_phy_lowpower_suspend(pdev->dev.platform_data, false);
+ /*after the phy reset,can not read the readingvalue for id/vbus at
+ * the register of otgsc ,cannot read at once ,need delay 3 ms
+ */
+ mdelay(3);
+ }
+ otg_used++;
+
+#if 0
+ printk("%s(%d):usb_oh3_clk:%d, usb_phy_clk1_ref_count:%d\n",
+ __FUNCTION__,__LINE__,clk_get_usecount(usb_oh3_clk),
+ clk_get_usecount(usb_phy1_clk));
+#endif
+
+ return ret;
+}
+
+static void usbotg_uninit_ext(struct platform_device *pdev)
+{
+ otg_used--;
+ if (!otg_used) {
+ //clk_disable(usb_phy1_clk);
+ clk_put(usb_phy1_clk);
+ clk_put(usb_oh3_clk);
+ }
+#if 0
+ printk("%s(%d):otg_used=%d,usb_oh3_clk:%d, usb_phy_clk1_ref_count:%d\n",
+ __FUNCTION__,__LINE__,otg_used,clk_get_usecount(usb_oh3_clk),
+ clk_get_usecount(usb_phy1_clk));
+#endif
+}
+
+static void usbotg_clock_gate(bool on)
+{
+ pr_debug("%s: on is %d\n", __func__, on);
+ if (on) {
+ clk_enable(usb_oh3_clk);
+ clk_enable(usb_phy1_clk);
+ } else {
+ clk_disable(usb_phy1_clk);
+ clk_disable(usb_oh3_clk);
+ }
+ //printk("usb_oh3_clk:%d, usb_phy_clk1_ref_count:%d\n", clk_get_usecount(usb_oh3_clk), clk_get_usecount(usb_phy1_clk));
+}
+
+static void dr_platform_phy_power_on(void)
+{
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
+}
+
+static void _dr_discharge_line(bool enable)
+{
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+
+ pr_debug("DR: %s enable is %d\n", __func__, enable);
+ if (enable) {
+ __raw_writel(BM_USBPHY_DEBUG_CLKGATE, phy_reg + HW_USBPHY_DEBUG_CLR);
+ __raw_writel(BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1
+ |BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN,
+ anatop_base_addr + HW_ANADIG_USB1_LOOPBACK);
+ } else {
+ __raw_writel(0x0,
+ anatop_base_addr + HW_ANADIG_USB1_LOOPBACK);
+ __raw_writel(BM_USBPHY_DEBUG_CLKGATE, phy_reg + HW_USBPHY_DEBUG_SET);
+ }
+}
+
+/* Below two macros are used at otg mode to indicate usb mode*/
+#define ENABLED_BY_HOST (0x1 << 0)
+#define ENABLED_BY_DEVICE (0x1 << 1)
+static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+ u32 tmp;
+ pr_debug("DR: %s begins, enable is %d\n", __func__, enable);
+
+ if (enable) {
+ UOG_PORTSC1 |= PORTSC_PHCD;
+ tmp = (BM_USBPHY_PWD_TXPWDFS
+ | BM_USBPHY_PWD_TXPWDIBIAS
+ | BM_USBPHY_PWD_TXPWDV2I
+ | BM_USBPHY_PWD_RXPWDENV
+ | BM_USBPHY_PWD_RXPWD1PT1
+ | BM_USBPHY_PWD_RXPWDDIFF
+ | BM_USBPHY_PWD_RXPWDRX);
+ __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET);
+ usbotg_internal_phy_clock_gate(false);
+
+ } else {
+ if (UOG_PORTSC1 & PORTSC_PHCD)
+ UOG_PORTSC1 &= ~PORTSC_PHCD;
+
+ /* Wait PHY clock stable */
+ mdelay(1);
+
+ usbotg_internal_phy_clock_gate(true);
+
+ udelay(2);
+
+ tmp = (BM_USBPHY_PWD_TXPWDFS
+ | BM_USBPHY_PWD_TXPWDIBIAS
+ | BM_USBPHY_PWD_TXPWDV2I
+ | BM_USBPHY_PWD_RXPWDENV
+ | BM_USBPHY_PWD_RXPWD1PT1
+ | BM_USBPHY_PWD_RXPWDDIFF
+ | BM_USBPHY_PWD_RXPWDRX);
+ __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR);
+ /*
+ * The PHY works at 32Khz clock when it is at low power mode,
+ * it needs 10 clocks from 32Khz to normal work state, so
+ * 500us is the safe value for PHY enters stable status
+ * according to IC engineer.
+ *
+ * Besides, the digital value needs 1ms debounce time to
+ * wait the value to be stable. We have expected the
+ * value from OTGSC is correct after calling this API.
+ *
+ * So delay 2ms is a save value.
+ */
+ mdelay(2);
+
+ }
+ pr_debug("DR: %s ends, enable is %d\n", __func__, enable);
+}
+
+static void __phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable, int source)
+{
+ if (enable) {
+ low_power_enable_src |= source;
+#ifdef CONFIG_USB_OTG
+ if (low_power_enable_src == (ENABLED_BY_HOST | ENABLED_BY_DEVICE)) {
+ pr_debug("phy lowpower enabled\n");
+ enter_phy_lowpower_suspend(pdata, enable);
+ }
+#else
+ enter_phy_lowpower_suspend(pdata, enable);
+#endif
+ } else {
+ pr_debug("phy lowpower disable\n");
+ enter_phy_lowpower_suspend(pdata, enable);
+ low_power_enable_src &= ~source;
+ }
+}
+
+static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+
+ pr_debug("%s, enable is %d\n", __func__, enable);
+ if (enable) {
+ __raw_writel(BM_USBPHY_CTRL_ENDPDMCHG_WKUP
+ | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS
+ | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD
+ | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE
+ | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE
+ | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_SET);
+ USB_OTG_CTRL |= UCTRL_OWIE;
+ } else {
+ __raw_writel(BM_USBPHY_CTRL_ENDPDMCHG_WKUP
+ | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS
+ | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD
+ | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE
+ | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE
+ | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_CLR);
+ USB_OTG_CTRL &= ~UCTRL_OWIE;
+ /* The interrupt must be disabled for at least 3 clock
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata, bool on, int source)
+ {
+ /* otg host and device share the OWIE bit, only when host and device
+ * all enable the wakeup irq, we can enable the OWIE bit
+ */
+ if (on) {
+#ifdef CONFIG_USB_OTG
+ wakeup_irq_enable_src |= source;
+ if (wakeup_irq_enable_src == (ENABLED_BY_HOST | ENABLED_BY_DEVICE)) {
+ otg_wake_up_enable(pdata, on);
+ }
+#else
+ otg_wake_up_enable(pdata, on);
+#endif
+ } else {
+ otg_wake_up_enable(pdata, on);
+ wakeup_irq_enable_src &= ~source;
+ /* The interrupt must be disabled for at least 3 clock
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+/* The wakeup operation for DR port, it will clear the wakeup irq status
+ * and re-enable the wakeup
+ */
+static void usbotg_wakeup_event_clear(void)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+ int wakeup_req = USB_OTG_CTRL & UCTRL_OWIR;
+
+ printk(KERN_INFO "\n %s: wakeup_req=%d, USB_OTG_CTRL=%08x, UOG_OTGSC=%08x, UOG_USBSTS=%08x, UOG_PORTSC1=%08x, USBPHY_CTRL=%08x\n",
+ __func__, wakeup_req?1:0, USB_OTG_CTRL, UOG_OTGSC, UOG_USBSTS, UOG_PORTSC1, __raw_readl(phy_reg + HW_USBPHY_CTRL));
+
+ if (wakeup_req != 0) {
+ printk(KERN_INFO "Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC);
+ /* Disable OWIE to clear OWIR, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ __raw_writel(BM_USBPHY_CTRL_ENDPDMCHG_WKUP, phy_reg + HW_USBPHY_CTRL_CLR);
+ UOG_OTGSC |= 0x007f0000;
+
+ USB_OTG_CTRL &= ~UCTRL_OWIE;
+ udelay(100);
+ __raw_writel(BM_USBPHY_CTRL_ENDPDMCHG_WKUP, phy_reg + HW_USBPHY_CTRL_SET);
+ USB_OTG_CTRL |= UCTRL_OWIE;
+ }
+ else {
+ /* spurious USB wakeup but WIR does not set, let's software use the
+ * bit UCTRL_WKUP_SW as an indication of software OWIR
+ */
+ USB_OTG_CTRL &= ~UCTRL_OWIE;
+ udelay(100);
+ USB_OTG_CTRL |= UCTRL_OWIE;
+ USB_OTG_CTRL |= UCTRL_WKUP_SW;
+ }
+}
+
+/* End of Common operation for DR port */
+
+#ifdef CONFIG_USB_EHCI_ARC_OTG
+/* Beginning of host related operation for DR port */
+static void fsl_platform_otg_set_usb_phy_dis(
+ struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ u32 usb_phy_ctrl_dcdt = 0;
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ usb_phy_ctrl_dcdt = __raw_readl(
+ MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_CTRL) &
+ BM_USBPHY_CTRL_ENHOSTDISCONDETECT;
+ if (enable) {
+ if (usb_phy_ctrl_dcdt == 0) {
+ __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS,
+ anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_CLR);
+
+ __raw_writel(BM_USBPHY_PWD_RXPWDENV,
+ MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_PWD_SET);
+
+ udelay(300);
+
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ MX6_IO_ADDRESS(pdata->phy_regs)
+ + HW_USBPHY_CTRL_SET);
+
+ UOG_USBSTS |= (1 << 7);
+
+ while ((UOG_USBSTS & (1 << 7)) == 0)
+ ;
+
+ udelay(2);
+
+ __raw_writel(BM_USBPHY_PWD_RXPWDENV,
+ MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_PWD_CLR);
+
+ __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS,
+ anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_SET);
+
+ }
+ } else {
+ if (usb_phy_ctrl_dcdt
+ == BM_USBPHY_CTRL_ENHOSTDISCONDETECT)
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ MX6_IO_ADDRESS(pdata->phy_regs)
+ + HW_USBPHY_CTRL_CLR);
+ }
+}
+
+static void _host_platform_rh_suspend_swfix(struct fsl_usb2_platform_data *pdata)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+ u32 tmp;
+ u32 index = 0;
+
+ /* before we set and then clear PWD bit,
+ * we must wait LS to be suspend */
+ if ((UOG_PORTSC1 & (3 << 26)) != (1 << 26)) {
+ while (((UOG_PORTSC1 & PORTSC_LS_MASK) != PORTSC_LS_J_STATE) &&
+ (index < 1000)) {
+ index++;
+ udelay(4);
+ }
+ } else {
+ while (((UOG_PORTSC1 & PORTSC_LS_MASK) != PORTSC_LS_K_STATE) &&
+ (index < 1000)) {
+ index++;
+ udelay(4);
+ }
+ }
+
+ if (index >= 1000)
+ printk(KERN_INFO "%s big error\n", __func__);
+
+ tmp = (BM_USBPHY_PWD_TXPWDFS
+ | BM_USBPHY_PWD_TXPWDIBIAS
+ | BM_USBPHY_PWD_TXPWDV2I
+ | BM_USBPHY_PWD_RXPWDENV
+ | BM_USBPHY_PWD_RXPWD1PT1
+ | BM_USBPHY_PWD_RXPWDDIFF
+ | BM_USBPHY_PWD_RXPWDRX);
+ __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET);
+
+ __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR);
+
+ fsl_platform_otg_set_usb_phy_dis(pdata, 0);
+}
+
+static void _host_platform_rh_resume_swfix(struct fsl_usb2_platform_data *pdata)
+{
+ u32 index = 0;
+
+ if ((UOG_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH)
+ return ;
+ while ((UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME)
+ && (index < 1000)) {
+ udelay(500);
+ index++;
+ }
+ if (index >= 1000)
+ printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n",
+ __func__, __LINE__);
+ /* We should add some delay to wait for the device switch to
+ * High-Speed 45ohm termination resistors mode. */
+ udelay(500);
+ fsl_platform_otg_set_usb_phy_dis(pdata, 1);
+}
+static void _host_platform_rh_suspend(struct fsl_usb2_platform_data *pdata)
+{
+ /*for mx6sl ,we do not need any sw fix*/
+ if (cpu_is_mx6sl())
+ return ;
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ MX6_IO_ADDRESS(pdata->phy_regs)
+ + HW_USBPHY_CTRL_CLR);
+}
+
+static void _host_platform_rh_resume(struct fsl_usb2_platform_data *pdata)
+{
+ u32 index = 0;
+
+ /*for mx6sl ,we do not need any sw fix*/
+ if (cpu_is_mx6sl())
+ return ;
+ if ((UOG_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH)
+ return ;
+ while ((UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME)
+ && (index < 1000)) {
+ udelay(500);
+ index++;
+ }
+ if (index >= 1000)
+ printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n",
+ __func__, __LINE__);
+ /* We should add some delay to wait for the device switch to
+ * High-Speed 45ohm termination resistors mode. */
+ udelay(500);
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ MX6_IO_ADDRESS(pdata->phy_regs)
+ + HW_USBPHY_CTRL_SET);
+}
+
+static void _host_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ __phy_lowpower_suspend(pdata, enable, ENABLED_BY_HOST);
+}
+
+static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ void __iomem *phy_reg __maybe_unused = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+ mutex_lock(&otg_wakeup_enable_mutex);
+ __wakeup_irq_enable(pdata, enable, ENABLED_BY_HOST);
+#ifdef CONFIG_USB_OTG
+ if (enable) {
+ pr_debug("host wakeup enable\n");
+ USB_OTG_CTRL |= UCTRL_WKUP_ID_EN;
+ __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP, phy_reg + HW_USBPHY_CTRL_SET);
+ } else {
+ pr_debug("host wakeup disable\n");
+ __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP, phy_reg + HW_USBPHY_CTRL_CLR);
+ USB_OTG_CTRL &= ~UCTRL_WKUP_ID_EN;
+ /* The interrupt must be disabled for at least 3 clock
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+ pr_debug("the otgsc is 0x%x, usbsts is 0x%x, portsc is 0x%x, otgctrl: 0x%x\n", UOG_OTGSC, UOG_USBSTS, UOG_PORTSC1, USB_OTG_CTRL);
+#endif
+ mutex_unlock(&otg_wakeup_enable_mutex);
+}
+
+static enum usb_wakeup_event _is_host_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ u32 wakeup_req = USB_OTG_CTRL & UCTRL_OWIR;
+ u32 otgsc = UOG_OTGSC;
+
+ if (wakeup_req) {
+ pr_debug("the otgsc is 0x%x, usbsts is 0x%x, portsc is 0x%x, wakeup_irq is 0x%x\n", UOG_OTGSC, UOG_USBSTS, UOG_PORTSC1, wakeup_req);
+ }
+ else {
+ // no hardware OWIR, let check if there is software OWIR
+ if (USB_OTG_CTRL & UCTRL_WKUP_SW) {
+ wakeup_req = UCTRL_WKUP_SW;
+ }
+ }
+ /* if ID change sts, it is a host wakeup event */
+ if (otgsc & OTGSC_IS_USB_ID) {
+ pr_debug("otg host ID wakeup\n");
+ USB_OTG_CTRL &= (~UCTRL_WKUP_SW);
+ return WAKEUP_EVENT_ID;
+ }
+ if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) {
+ pr_debug("otg host Remote wakeup\n");
+ USB_OTG_CTRL &= (~UCTRL_WKUP_SW);
+ return WAKEUP_EVENT_DPDM;
+ }
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _host_phy_lowpower_suspend(pdata, false);
+ _host_wakeup_enable(pdata, false);
+}
+/* End of host related operation for DR port */
+#endif /* CONFIG_USB_EHCI_ARC_OTG */
+
+
+#ifdef CONFIG_USB_GADGET_ARC
+/* Beginning of device related operation for DR port */
+static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ __phy_lowpower_suspend(pdata, enable, ENABLED_BY_DEVICE);
+}
+
+static void _device_wakeup_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR);
+ mutex_lock(&otg_wakeup_enable_mutex);
+ __wakeup_irq_enable(pdata, enable, ENABLED_BY_DEVICE);
+ /* if udc is not used by any gadget, we can not enable the vbus wakeup */
+ if (!pdata->port_enables) {
+ USB_OTG_CTRL &= ~UCTRL_WKUP_VBUS_EN;
+ mutex_unlock(&otg_wakeup_enable_mutex);
+ return;
+ }
+ if (enable) {
+ pr_debug("device wakeup enable\n");
+ USB_OTG_CTRL |= UCTRL_WKUP_VBUS_EN;
+ __raw_writel(BM_USBPHY_CTRL_ENVBUSCHG_WKUP, phy_reg + HW_USBPHY_CTRL_SET);
+ } else {
+ pr_debug("device wakeup disable\n");
+ __raw_writel(BM_USBPHY_CTRL_ENVBUSCHG_WKUP, phy_reg + HW_USBPHY_CTRL_CLR);
+ USB_OTG_CTRL &= ~UCTRL_WKUP_VBUS_EN;
+ }
+ mutex_unlock(&otg_wakeup_enable_mutex);
+}
+
+static enum usb_wakeup_event _is_device_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ int wakeup_req = (USB_OTG_CTRL & UCTRL_OWIR);
+ pr_debug("%s\n", __func__);
+
+ if (!wakeup_req) {
+ // no hardware OWIR, let check if there is software OWIR
+ if (USB_OTG_CTRL & UCTRL_WKUP_SW) {
+ wakeup_req = UCTRL_WKUP_SW;
+ }
+ }
+
+ /* if ID=1, it is a device wakeup event */
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && (UOG_USBSTS & USBSTS_URI)) {
+ printk(KERN_INFO "otg udc wakeup, host sends reset signal\n");
+ USB_OTG_CTRL &= (~UCTRL_WKUP_SW);
+ return WAKEUP_EVENT_DPDM;
+ }
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && \
+ ((UOG_USBSTS & USBSTS_PCI) || (UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME))) {
+ /*
+ * When the line state from J to K, the Port Change Detect bit
+ * in the USBSTS register is also set to '1'.
+ */
+ printk(KERN_INFO "otg udc wakeup, host sends resume signal\n");
+ USB_OTG_CTRL &= (~UCTRL_WKUP_SW);
+ return WAKEUP_EVENT_DPDM;
+ }
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && (UOG_OTGSC & OTGSC_STS_A_VBUS_VALID) /*\
+ && (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)*/) {
+ printk(KERN_INFO "otg udc vbus rising wakeup\n");
+ USB_OTG_CTRL &= (~UCTRL_WKUP_SW);
+ return WAKEUP_EVENT_VBUS;
+ }
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && !(UOG_OTGSC & OTGSC_STS_A_VBUS_VALID)) {
+ printk(KERN_INFO "otg udc vbus falling wakeup\n");
+ USB_OTG_CTRL &= (~UCTRL_WKUP_SW);
+ return WAKEUP_EVENT_VBUS;
+ }
+
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _device_phy_lowpower_suspend(pdata, false);
+ _device_wakeup_enable(pdata, false);
+}
+
+/* end of device related operation for DR port */
+#endif /* CONFIG_USB_GADGET_ARC */
+
+static struct platform_device *pdev[3], *pdev_wakeup;
+static driver_vbus_func mx6_set_usb_otg_vbus;
+static int devnum;
+static int __init mx6_usb_dr_init(void)
+{
+ int i = 0;
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ struct imx_fsl_usb2_wakeup_data __maybe_unused imx6q_fsl_otg_wakeup_data =
+ imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 0, OTG);
+ struct imx_mxc_ehci_data __maybe_unused imx6q_mxc_ehci_otg_data =
+ imx_mxc_ehci_data_entry_single(MX6Q, 0, OTG);
+ struct imx_fsl_usb2_udc_data __maybe_unused imx6q_fsl_usb2_udc_data =
+ imx_fsl_usb2_udc_data_entry_single(MX6Q);
+ struct imx_fsl_usb2_otg_data __maybe_unused imx6q_fsl_usb2_otg_data =
+ imx_fsl_usb2_otg_data_entry_single(MX6Q);
+
+ /* Some phy and power's special controls for otg
+ * 1. The external charger detector needs to be disabled
+ * or the signal at DP will be poor
+ * 2. The EN_USB_CLKS is always enabled.
+ * The PLL's power is controlled by usb and others who
+ * use pll3 too.
+ */
+ __raw_writel(BM_ANADIG_USB1_CHRG_DETECT_EN_B \
+ | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B, \
+ anatop_base_addr + HW_ANADIG_USB1_CHRG_DETECT);
+ __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS,
+ anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_SET);
+ mx6_get_otghost_vbus_func(&mx6_set_usb_otg_vbus);
+ dr_utmi_config.platform_driver_vbus = mx6_set_usb_otg_vbus;
+#ifdef CONFIG_USB_OTG
+ /* wake_up_enable is useless, just for usb_register_remote_wakeup execution*/
+ dr_utmi_config.wake_up_enable = _device_wakeup_enable;
+ dr_utmi_config.operating_mode = FSL_USB2_DR_OTG;
+ dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
+ pdev[i] = imx6q_add_fsl_usb2_otg(&dr_utmi_config);
+ dr_wakeup_config.usb_pdata[i] = pdev[i]->dev.platform_data;
+ i++;
+#endif
+#ifdef CONFIG_USB_GADGET_ARC
+ dr_utmi_config.operating_mode = DR_UDC_MODE;
+ dr_utmi_config.wake_up_enable = _device_wakeup_enable;
+ dr_utmi_config.platform_rh_suspend = NULL;
+ dr_utmi_config.platform_rh_resume = NULL;
+ dr_utmi_config.platform_set_disconnect_det = NULL;
+ dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend;
+ dr_utmi_config.is_wakeup_event = _is_device_wakeup;
+ dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
+ dr_utmi_config.wakeup_handler = device_wakeup_handler;
+ dr_utmi_config.charger_base_addr = anatop_base_addr;
+ dr_utmi_config.platform_phy_power_on = dr_platform_phy_power_on;
+ pdev[i] = imx6q_add_fsl_usb2_udc(&dr_utmi_config);
+ dr_wakeup_config.usb_pdata[i] = pdev[i]->dev.platform_data;
+ i++;
+#endif
+#ifdef CONFIG_USB_EHCI_ARC_OTG
+ dr_utmi_config.operating_mode = DR_HOST_MODE;
+ dr_utmi_config.wake_up_enable = _host_wakeup_enable;
+ if (usb_icbug_swfix_need()) {
+ dr_utmi_config.platform_rh_suspend = _host_platform_rh_suspend_swfix;
+ dr_utmi_config.platform_rh_resume = _host_platform_rh_resume_swfix;
+ } else {
+ dr_utmi_config.platform_rh_suspend = _host_platform_rh_suspend;
+ dr_utmi_config.platform_rh_resume = _host_platform_rh_resume;
+ }
+ dr_utmi_config.platform_set_disconnect_det = fsl_platform_otg_set_usb_phy_dis;
+ dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend;
+ dr_utmi_config.is_wakeup_event = _is_host_wakeup;
+ dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
+ dr_utmi_config.wakeup_handler = host_wakeup_handler;
+ dr_utmi_config.platform_phy_power_on = dr_platform_phy_power_on;
+ pdev[i] = imx6q_add_fsl_ehci_otg(&dr_utmi_config);
+ dr_wakeup_config.usb_pdata[i] = pdev[i]->dev.platform_data;
+ i++;
+#endif
+ devnum = i;
+ /* register wakeup device */
+ pdev_wakeup = imx6q_add_fsl_usb2_otg_wakeup(&dr_wakeup_config);
+ for (i = 0; i < devnum; i++) {
+ platform_device_add(pdev[i]);
+ ((struct fsl_usb2_platform_data *)(pdev[i]->dev.platform_data))->wakeup_pdata =
+ (struct fsl_usb2_wakeup_platform_data *)(pdev_wakeup->dev.platform_data);
+ }
+ return 0;
+}
+module_init(mx6_usb_dr_init);
+
+static void __exit mx6_usb_dr_exit(void)
+{
+ int i;
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+
+ for (i = 0; i < devnum; i++)
+ platform_device_del(pdev[devnum-i-1]);
+ platform_device_unregister(pdev_wakeup);
+ otg_used = 0;
+ __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS,
+ anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_CLR);
+ return ;
+}
+module_exit(mx6_usb_dr_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/mach-mx6/usb_h1.c b/arch/arm/mach-mx6/usb_h1.c
new file mode 100644
index 00000000..cfbced8f
--- /dev/null
+++ b/arch/arm/mach-mx6/usb_h1.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2011-2012 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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/arc_otg.h>
+#include <mach/hardware.h>
+#include "devices-imx6q.h"
+#include "regs-anadig.h"
+#include "usb.h"
+
+static struct clk *usb_oh3_clk;
+extern int clk_get_usecount(struct clk *clk);
+static struct fsl_usb2_platform_data usbh1_config;
+
+static void fsl_platform_h1_set_usb_phy_dis(
+ struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ u32 usb_phy_ctrl_dcdt = 0;
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ usb_phy_ctrl_dcdt = __raw_readl(
+ MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_CTRL) &
+ BM_USBPHY_CTRL_ENHOSTDISCONDETECT;
+ if (enable) {
+ if (usb_phy_ctrl_dcdt == 0) {
+ __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
+ anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR);
+
+ __raw_writel(BM_USBPHY_PWD_RXPWDENV,
+ MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_PWD_SET);
+
+ udelay(300);
+
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ MX6_IO_ADDRESS(pdata->phy_regs)
+ + HW_USBPHY_CTRL_SET);
+
+ UH1_USBSTS |= (1 << 7);
+
+ while ((UH1_USBSTS & (1 << 7)) == 0)
+ ;
+
+ udelay(2);
+
+ __raw_writel(BM_USBPHY_PWD_RXPWDENV,
+ MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_PWD_CLR);
+
+ __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
+ anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET);
+
+ }
+ } else {
+ if (usb_phy_ctrl_dcdt
+ == BM_USBPHY_CTRL_ENHOSTDISCONDETECT)
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ MX6_IO_ADDRESS(pdata->phy_regs)
+ + HW_USBPHY_CTRL_CLR);
+ }
+}
+
+static void usbh1_internal_phy_clock_gate(bool on)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
+ if (on) {
+ __raw_writel(BM_USBPHY_CTRL_CLKGATE, phy_reg + HW_USBPHY_CTRL_CLR);
+ } else {
+ __raw_writel(BM_USBPHY_CTRL_CLKGATE, phy_reg + HW_USBPHY_CTRL_SET);
+ }
+}
+
+static void usbh1_platform_phy_power_on(void)
+{
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
+}
+
+static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
+{
+ u32 tmp;
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
+ void __iomem *phy_ctrl;
+
+ /* Stop then Reset */
+ UH1_USBCMD &= ~UCMD_RUN_STOP;
+ while (UH1_USBCMD & UCMD_RUN_STOP)
+ ;
+
+ UH1_USBCMD |= UCMD_RESET;
+ while ((UH1_USBCMD) & (UCMD_RESET))
+ ;
+ /*
+ * If the controller reset does not put the PHY be out of
+ * low power mode, do it manually.
+ */
+ if (UH1_PORTSC1 & PORTSC_PHCD) {
+ UH1_PORTSC1 &= ~PORTSC_PHCD;
+ mdelay(1);
+ }
+
+ /* Reset USBPHY module */
+ phy_ctrl = phy_reg + HW_USBPHY_CTRL;
+ tmp = __raw_readl(phy_ctrl);
+ tmp |= BM_USBPHY_CTRL_SFTRST;
+ __raw_writel(tmp, phy_ctrl);
+ udelay(10);
+
+ /* Remove CLKGATE and SFTRST */
+ tmp = __raw_readl(phy_ctrl);
+ tmp &= ~(BM_USBPHY_CTRL_CLKGATE | BM_USBPHY_CTRL_SFTRST);
+ __raw_writel(tmp, phy_ctrl);
+ udelay(10);
+
+ /* Power up the PHY */
+ __raw_writel(0, phy_reg + HW_USBPHY_PWD);
+ /* enable FS/LS device */
+ tmp = __raw_readl(phy_reg + HW_USBPHY_CTRL);
+ tmp |= (BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3);
+ __raw_writel(tmp, phy_reg + HW_USBPHY_CTRL);
+
+ if (!usb_icbug_swfix_need())
+ __raw_writel((1 << 17), phy_reg + HW_USBPHY_IP_SET);
+ if (cpu_is_mx6sl())
+ __raw_writel((1 << 18), phy_reg + HW_USBPHY_IP_SET);
+ return 0;
+}
+static int fsl_usb_host_init_ext(struct platform_device *pdev)
+{
+ int ret;
+ struct clk *usb_clk;
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ usb_oh3_clk = usb_clk;
+
+ ret = fsl_usb_host_init(pdev);
+ if (ret) {
+ printk(KERN_ERR "host1 init fails......\n");
+ clk_disable(usb_oh3_clk);
+ clk_put(usb_oh3_clk);
+ return ret;
+ }
+ usbh1_internal_phy_clock_gate(true);
+ usb_phy_enable(pdev->dev.platform_data);
+
+ return 0;
+}
+
+static void fsl_usb_host_uninit_ext(struct platform_device *pdev)
+{
+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+ fsl_usb_host_uninit(pdata);
+
+ clk_put(usb_oh3_clk);
+
+}
+
+static void usbh1_clock_gate(bool on)
+{
+ pr_debug("%s: on is %d\n", __func__, on);
+ if (on) {
+ clk_enable(usb_oh3_clk);
+ } else {
+ clk_disable(usb_oh3_clk);
+ }
+}
+
+static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
+
+ pr_debug("host1, %s, enable is %d\n", __func__, enable);
+ if (enable) {
+ __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP | BM_USBPHY_CTRL_ENVBUSCHG_WKUP
+ | BM_USBPHY_CTRL_ENDPDMCHG_WKUP
+ | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS
+ | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD
+ | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE
+ | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE
+ | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_SET);
+ USB_H1_CTRL |= (UCTRL_OWIE);
+ } else {
+ __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP | BM_USBPHY_CTRL_ENVBUSCHG_WKUP
+ | BM_USBPHY_CTRL_ENDPDMCHG_WKUP
+ | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS
+ | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD
+ | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE
+ | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE
+ | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_CLR);
+ USB_H1_CTRL &= ~(UCTRL_OWIE);
+ /* The interrupt must be disabled for at least 3
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+static void usbh1_platform_rh_suspend_swfix(struct fsl_usb2_platform_data *pdata)
+{
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
+ u32 tmp;
+ u32 index = 0;
+
+ /* before we set and then clear PWD bit,
+ * we must wait LS to be J */
+ if ((UH1_PORTSC1 & (3 << 26)) != (1 << 26)) {
+ while (((UH1_PORTSC1 & PORTSC_LS_MASK) != PORTSC_LS_J_STATE) &&
+ (index < 1000)) {
+ index++;
+ udelay(4);
+ }
+ } else {
+ while (((UH1_PORTSC1 & PORTSC_LS_MASK) != PORTSC_LS_K_STATE) &&
+ (index < 1000)) {
+ index++;
+ udelay(4);
+ }
+ }
+
+ if (index >= 1000)
+ printk(KERN_INFO "%s big error\n", __func__);
+
+ tmp = (BM_USBPHY_PWD_TXPWDFS
+ | BM_USBPHY_PWD_TXPWDIBIAS
+ | BM_USBPHY_PWD_TXPWDV2I
+ | BM_USBPHY_PWD_RXPWDENV
+ | BM_USBPHY_PWD_RXPWD1PT1
+ | BM_USBPHY_PWD_RXPWDDIFF
+ | BM_USBPHY_PWD_RXPWDRX);
+ __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET);
+
+ __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR);
+
+ fsl_platform_h1_set_usb_phy_dis(pdata, 0);
+}
+
+static void usbh1_platform_rh_resume_swfix(struct fsl_usb2_platform_data *pdata)
+{
+ u32 index = 0;
+
+ if ((UH1_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH)
+ return ;
+ while ((UH1_PORTSC1 & PORTSC_PORT_FORCE_RESUME)
+ && (index < 1000)) {
+ udelay(500);
+ index++;
+ }
+ if (index >= 1000)
+ printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n",
+ __func__, __LINE__);
+ /* We should add some delay to wait for the device switch to
+ * High-Speed 45ohm termination resistors mode. */
+ udelay(500);
+ fsl_platform_h1_set_usb_phy_dis(pdata, 1);
+}
+
+static void usbh1_platform_rh_suspend(struct fsl_usb2_platform_data *pdata)
+{
+ /*for mx6sl ,we do not need any sw fix*/
+ if (cpu_is_mx6sl())
+ return ;
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ MX6_IO_ADDRESS(pdata->phy_regs)
+ + HW_USBPHY_CTRL_CLR);
+}
+
+static void usbh1_platform_rh_resume(struct fsl_usb2_platform_data *pdata)
+{
+ u32 index = 0;
+
+ /*for mx6sl ,we do not need any sw fix*/
+ if (cpu_is_mx6sl())
+ return ;
+ if ((UH1_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH)
+ return ;
+ while ((UH1_PORTSC1 & PORTSC_PORT_FORCE_RESUME)
+ && (index < 1000)) {
+ udelay(500);
+ index++;
+ }
+ if (index >= 1000)
+ printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n",
+ __func__, __LINE__);
+ /* We should add some delay to wait for the device switch to
+ * High-Speed 45ohm termination resistors mode. */
+ udelay(500);
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ MX6_IO_ADDRESS(pdata->phy_regs)
+ + HW_USBPHY_CTRL_SET);
+}
+
+static void _phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ u32 tmp;
+ void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
+ pr_debug("host1, %s, enable is %d\n", __func__, enable);
+ if (enable) {
+ UH1_PORTSC1 |= PORTSC_PHCD;
+
+ pr_debug("%s, Poweroff UTMI \n", __func__);
+
+ tmp = (BM_USBPHY_PWD_TXPWDFS
+ | BM_USBPHY_PWD_TXPWDIBIAS
+ | BM_USBPHY_PWD_TXPWDV2I
+ | BM_USBPHY_PWD_RXPWDENV
+ | BM_USBPHY_PWD_RXPWD1PT1
+ | BM_USBPHY_PWD_RXPWDDIFF
+ | BM_USBPHY_PWD_RXPWDRX);
+ __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET);
+
+ usbh1_internal_phy_clock_gate(false);
+ } else {
+ if (UH1_PORTSC1 & PORTSC_PHCD)
+ UH1_PORTSC1 &= ~PORTSC_PHCD;
+
+ /* Wait PHY clock stable */
+ mdelay(1);
+
+ usbh1_internal_phy_clock_gate(true);
+
+ udelay(2);
+
+ tmp = (BM_USBPHY_PWD_TXPWDFS
+ | BM_USBPHY_PWD_TXPWDIBIAS
+ | BM_USBPHY_PWD_TXPWDV2I
+ | BM_USBPHY_PWD_RXPWDENV
+ | BM_USBPHY_PWD_RXPWD1PT1
+ | BM_USBPHY_PWD_RXPWDDIFF
+ | BM_USBPHY_PWD_RXPWDRX);
+ __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR);
+ /*
+ * The PHY works at 32Khz clock when it is at low power mode,
+ * it needs 10 clocks from 32Khz to normal work state, so
+ * 500us is the safe value for PHY enters stable status
+ * according to IC engineer.
+ */
+ udelay(500);
+ }
+}
+
+static enum usb_wakeup_event _is_usbh1_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ u32 wakeup_req = USB_H1_CTRL & UCTRL_OWIR;
+
+ if (wakeup_req)
+ return WAKEUP_EVENT_DPDM;
+ pr_err("host1, %s, invalid wake up\n", __func__);
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void h1_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _wake_up_enable(pdata, false);
+ _phy_lowpower_suspend(pdata, false);
+}
+
+static void usbh1_wakeup_event_clear(void)
+{
+ int wakeup_req = USB_H1_CTRL & UCTRL_OWIR;
+
+ if (wakeup_req != 0) {
+ printk(KERN_INFO "Unknown wakeup.(H1 OTGSC 0x%x)\n", UH1_OTGSC);
+ /* Disable OWIE to clear OWIR, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ USB_H1_CTRL &= ~UCTRL_OWIE;
+ udelay(100);
+ USB_H1_CTRL |= UCTRL_OWIE;
+ }
+}
+
+static struct fsl_usb2_platform_data usbh1_config = {
+ .name = "Host 1",
+ .init = fsl_usb_host_init_ext,
+ .exit = fsl_usb_host_uninit_ext,
+ .operating_mode = FSL_USB2_MPH_HOST,
+ .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
+ .power_budget = 500, /* 500 mA max power */
+ .wake_up_enable = _wake_up_enable,
+ .usb_clock_for_pm = usbh1_clock_gate,
+ .platform_set_disconnect_det = fsl_platform_h1_set_usb_phy_dis,
+ .phy_lowpower_suspend = _phy_lowpower_suspend,
+ .is_wakeup_event = _is_usbh1_wakeup,
+ .wakeup_handler = h1_wakeup_handler,
+ .platform_phy_power_on = usbh1_platform_phy_power_on,
+ .transceiver = "utmi",
+ .phy_regs = USB_PHY1_BASE_ADDR,
+};
+static struct fsl_usb2_wakeup_platform_data usbh1_wakeup_config = {
+ .name = "USBH1 wakeup",
+ .usb_clock_for_pm = usbh1_clock_gate,
+ .usb_pdata = {&usbh1_config, NULL, NULL},
+ .usb_wakeup_exhandle = usbh1_wakeup_event_clear,
+};
+
+static struct platform_device *pdev, *pdev_wakeup;
+static driver_vbus_func mx6_set_usb_host1_vbus;
+
+static int __init mx6_usb_h1_init(void)
+{
+ static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ struct imx_fsl_usb2_wakeup_data imx6q_fsl_hs_wakeup_data[] = {
+ imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 1, HS1)};
+ struct imx_fsl_usb2_wakeup_data imx6sl_fsl_hs_wakeup_data[] = {
+ imx_fsl_usb2_wakeup_data_entry_single(MX6SL, 1, HS1)};
+ struct imx_mxc_ehci_data imx6q_mxc_ehci_hs_data[] = {
+ imx_mxc_ehci_data_entry_single(MX6Q, 1, HS1)};
+ struct imx_mxc_ehci_data imx6sl_mxc_ehci_hs_data[] = {
+ imx_mxc_ehci_data_entry_single(MX6SL, 1, HS1)};
+
+ mx6_get_host1_vbus_func(&mx6_set_usb_host1_vbus);
+ if (mx6_set_usb_host1_vbus)
+ mx6_set_usb_host1_vbus(true);
+
+ /* Some phy and power's special controls for host1
+ * 1. The external charger detector needs to be disabled
+ * or the signal at DP will be poor
+ * 2. The PLL's power and output to usb for host 1
+ * is totally controlled by IC, so the Software only needs
+ * to enable them at initializtion.
+ */
+ __raw_writel(BM_ANADIG_USB2_CHRG_DETECT_EN_B \
+ | BM_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, \
+ anatop_base_addr + HW_ANADIG_USB2_CHRG_DETECT);
+ __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_BYPASS,
+ anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR);
+ __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_ENABLE \
+ | BM_ANADIG_USB2_PLL_480_CTRL_POWER \
+ | BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, \
+ anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET);
+
+ usbh1_config.wakeup_pdata = &usbh1_wakeup_config;
+ if (usb_icbug_swfix_need()) {
+ usbh1_config.platform_rh_suspend = usbh1_platform_rh_suspend_swfix;
+ usbh1_config.platform_rh_resume = usbh1_platform_rh_resume_swfix;
+ } else {
+ usbh1_config.platform_rh_suspend = usbh1_platform_rh_suspend;
+ usbh1_config.platform_rh_resume = usbh1_platform_rh_resume;
+ }
+ if (cpu_is_mx6sl())
+ pdev = imx6sl_add_fsl_ehci_hs(1, &usbh1_config);
+ else
+ pdev = imx6q_add_fsl_ehci_hs(1, &usbh1_config);
+ usbh1_wakeup_config.usb_pdata[0] = pdev->dev.platform_data;
+ if (cpu_is_mx6sl())
+ pdev_wakeup = imx6sl_add_fsl_usb2_hs_wakeup(1, &usbh1_wakeup_config);
+ else
+ pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(1, &usbh1_wakeup_config);
+ platform_device_add(pdev);
+ ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata =
+ (struct fsl_usb2_wakeup_platform_data *)(pdev_wakeup->dev.platform_data);
+ return 0;
+}
+module_init(mx6_usb_h1_init);
+
+static void __exit mx6_usb_h1_exit(void)
+{
+ static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+
+ platform_device_unregister(pdev);
+ platform_device_unregister(pdev_wakeup);
+ __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_BYPASS,
+ anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET);
+ __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_ENABLE \
+ | BM_ANADIG_USB2_PLL_480_CTRL_POWER \
+ | BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, \
+ anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR);
+ if (mx6_set_usb_host1_vbus)
+ mx6_set_usb_host1_vbus(false);
+
+ return ;
+}
+module_exit(mx6_usb_h1_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-mx6/usb_h2.c b/arch/arm/mach-mx6/usb_h2.c
new file mode 100644
index 00000000..2577abd4
--- /dev/null
+++ b/arch/arm/mach-mx6/usb_h2.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2011-2012 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.
+ *
+ * High Speed Inter Chip code for i.MX6, this file is for HSIC port 1
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/arc_otg.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx6q.h>
+#include <mach/iomux-mx6dl.h>
+#include <mach/iomux-mx6sl.h>
+#include "devices-imx6q.h"
+#include "regs-anadig.h"
+#include "usb.h"
+
+static struct clk *usb_oh3_clk;
+static struct clk *usb_phy3_clk;
+
+extern int clk_get_usecount(struct clk *clk);
+static struct fsl_usb2_platform_data usbh2_config;
+
+static void usbh2_internal_phy_clock_gate(bool on)
+{
+ if (on) {
+ /* must turn on the 480M clock, otherwise
+ * there will be a 10ms delay before host
+ * controller send out resume signal*/
+ USB_H2_CTRL |= UCTRL_UTMI_ON_CLOCK;
+ USB_UH2_HSIC_CTRL |= HSIC_CLK_ON;
+ } else {
+ USB_UH2_HSIC_CTRL &= ~HSIC_CLK_ON;
+ /* can't turn off this clock, otherwise
+ * there will be a 10ms delay before host
+ * controller send out resume signal*/
+ /*USB_H2_CTRL &= ~UCTRL_UTMI_ON_CLOCK*/;
+ }
+}
+
+static int fsl_usb_host_init_ext(struct platform_device *pdev)
+{
+ int ret;
+ struct clk *usb_clk;
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ usb_oh3_clk = usb_clk;
+
+ usb_clk = clk_get(NULL, "usb_phy3_clk");
+ clk_enable(usb_clk);
+ usb_phy3_clk = usb_clk;
+
+ ret = fsl_usb_host_init(pdev);
+ if (ret) {
+ printk(KERN_ERR "host1 init fails......\n");
+ return ret;
+ }
+ usbh2_internal_phy_clock_gate(true);
+ /* Host2 HSIC enable */
+ USB_UH2_HSIC_CTRL |= HSIC_EN;
+
+ return 0;
+}
+
+static void fsl_usb_host_uninit_ext(struct platform_device *pdev)
+{
+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+ fsl_usb_host_uninit(pdata);
+
+ clk_put(usb_phy3_clk);
+
+ clk_put(usb_oh3_clk);
+
+}
+
+static void usbh2_clock_gate(bool on)
+{
+ pr_debug("%s: on is %d\n", __func__, on);
+ if (on) {
+ clk_enable(usb_oh3_clk);
+ clk_enable(usb_phy3_clk);
+ usbh2_internal_phy_clock_gate(true);
+ } else {
+ usbh2_internal_phy_clock_gate(false);
+ clk_disable(usb_phy3_clk);
+ clk_disable(usb_oh3_clk);
+ }
+}
+
+void mx6_set_host2_vbus_func(driver_vbus_func driver_vbus)
+{
+ usbh2_config.platform_driver_vbus = driver_vbus;
+}
+
+static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ pr_debug("host2, %s, enable is %d\n", __func__, enable);
+ /* for HSIC, no disconnect nor connect
+ * we need to disable the WKDS, WKCN */
+ UH2_PORTSC1 &= ~(PORTSC_WKDC | PORTSC_WKCN);
+
+ if (enable) {
+ USB_H2_CTRL |= (UCTRL_OWIE);
+ } else {
+ USB_H2_CTRL &= ~(UCTRL_OWIE);
+ /* The interrupt must be disabled for at least 3
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+static void _phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ pr_debug("host2, %s, enable is %d\n", __func__, enable);
+ if (enable)
+ UH2_PORTSC1 |= PORTSC_PHCD;
+ else
+ UH2_PORTSC1 &= ~PORTSC_PHCD;
+
+}
+
+static enum usb_wakeup_event _is_usbh2_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ u32 wakeup_req = USB_H2_CTRL & UCTRL_OWIR;
+
+ if (wakeup_req)
+ return WAKEUP_EVENT_DPDM;
+ pr_err("host2, %s, invalid wake up\n", __func__);
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void h2_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _wake_up_enable(pdata, false);
+ _phy_lowpower_suspend(pdata, false);
+}
+
+static void usbh2_wakeup_event_clear(void)
+{
+ u32 wakeup_req = USB_H2_CTRL & UCTRL_OWIR;
+ pr_debug("%s\n", __func__);
+
+ if (wakeup_req != 0) {
+ /* Disable H2 wakeup enable to clear H2 wakeup request, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ USB_H2_CTRL &= ~UCTRL_OWIE;
+ udelay(100);
+ USB_H2_CTRL |= UCTRL_OWIE;
+ }
+}
+
+static void hsic_start(void)
+{
+ pr_debug("%s\n", __func__);
+ /* strobe 47K pull up */
+ if (cpu_is_mx6q())
+ mxc_iomux_v3_setup_pad(
+ MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE_START);
+ else if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_pad(
+ MX6DL_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE_START);
+ else if (cpu_is_mx6sl())
+ mxc_iomux_v3_setup_pad(
+ MX6SL_PAD_HSIC_STROBE__USB_H_STROBE_START);
+}
+
+static void hsic_device_connected(void)
+{
+ pr_debug("%s\n", __func__);
+ if (!(USB_UH2_HSIC_CTRL & HSIC_DEV_CONN))
+ USB_UH2_HSIC_CTRL |= HSIC_DEV_CONN;
+}
+
+static struct fsl_usb2_platform_data usbh2_config = {
+ .name = "Host 2",
+ .init = fsl_usb_host_init_ext,
+ .exit = fsl_usb_host_uninit_ext,
+ .operating_mode = FSL_USB2_MPH_HOST,
+ .phy_mode = FSL_USB2_PHY_HSIC,
+ .power_budget = 500, /* 500 mA max power */
+ .wake_up_enable = _wake_up_enable,
+ .usb_clock_for_pm = usbh2_clock_gate,
+ .phy_lowpower_suspend = _phy_lowpower_suspend,
+ .is_wakeup_event = _is_usbh2_wakeup,
+ .wakeup_handler = h2_wakeup_handler,
+ .transceiver = "hsic_xcvr",
+ .hsic_post_ops = hsic_start,
+ .hsic_device_connected = hsic_device_connected,
+};
+
+static struct fsl_usb2_wakeup_platform_data usbh2_wakeup_config = {
+ .name = "usbh2 wakeup",
+ .usb_clock_for_pm = usbh2_clock_gate,
+ .usb_pdata = {&usbh2_config, NULL, NULL},
+ .usb_wakeup_exhandle = usbh2_wakeup_event_clear,
+};
+
+void __init mx6_usb_h2_init(void)
+{
+ struct platform_device *pdev, *pdev_wakeup;
+ static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ usbh2_config.wakeup_pdata = &usbh2_wakeup_config;
+ if (cpu_is_mx6sl())
+ pdev = imx6sl_add_fsl_ehci_hs(2, &usbh2_config);
+ else
+ pdev = imx6q_add_fsl_ehci_hs(2, &usbh2_config);
+
+ usbh2_wakeup_config.usb_pdata[0] = pdev->dev.platform_data;
+ if (cpu_is_mx6sl())
+ pdev_wakeup = imx6sl_add_fsl_usb2_hs_wakeup(2, &usbh2_wakeup_config);
+ else
+ pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(2, &usbh2_wakeup_config);
+ platform_device_add(pdev);
+ ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata =
+ pdev_wakeup->dev.platform_data;
+ /* Some phy and power's special controls for host2
+ * 1. Its 480M is from OTG's 480M
+ * 2. EN_USB_CLKS should always be opened
+ */
+ __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS,
+ anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_SET);
+ /* must change the clkgate delay to 2 or 3 to avoid
+ * 24M OSCI clock not stable issue */
+ __raw_writel(BF_ANADIG_ANA_MISC0_CLKGATE_DELAY(3),
+ anatop_base_addr + HW_ANADIG_ANA_MISC0);
+}
diff --git a/arch/arm/mach-mx6/usb_h3.c b/arch/arm/mach-mx6/usb_h3.c
new file mode 100644
index 00000000..a057269c
--- /dev/null
+++ b/arch/arm/mach-mx6/usb_h3.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2011-2012 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.
+ *
+ * High Speed Inter Chip code for i.MX6, this file is for HSIC port 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/arc_otg.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx6q.h>
+#include <mach/iomux-mx6dl.h>
+#include "devices-imx6q.h"
+#include "regs-anadig.h"
+#include "usb.h"
+
+static struct clk *usb_oh3_clk;
+static struct clk *usb_phy4_clk;
+
+extern int clk_get_usecount(struct clk *clk);
+static struct fsl_usb2_platform_data usbh3_config;
+
+static void usbh3_internal_phy_clock_gate(bool on)
+{
+ if (on) {
+ /* must turn on the 480M clock, otherwise
+ * there will be a 10ms delay before host
+ * controller send out resume signal*/
+ USB_H3_CTRL |= UCTRL_UTMI_ON_CLOCK;
+ USB_UH3_HSIC_CTRL |= HSIC_CLK_ON;
+ } else {
+ USB_UH3_HSIC_CTRL &= ~HSIC_CLK_ON;
+ /* can't turn off this clock, otherwise
+ * there will be a 10ms delay before host
+ * controller send out resume signal*/
+ /*USB_H3_CTRL &= ~UCTRL_UTMI_ON_CLOCK;*/
+ }
+}
+
+static int fsl_usb_host_init_ext(struct platform_device *pdev)
+{
+ int ret;
+ struct clk *usb_clk;
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ usb_oh3_clk = usb_clk;
+
+ usb_clk = clk_get(NULL, "usb_phy4_clk");
+ clk_enable(usb_clk);
+ usb_phy4_clk = usb_clk;
+
+ ret = fsl_usb_host_init(pdev);
+ if (ret) {
+ printk(KERN_ERR "host1 init fails......\n");
+ return ret;
+ }
+ usbh3_internal_phy_clock_gate(true);
+
+ /* Host3 HSIC enable */
+ USB_UH3_HSIC_CTRL |= HSIC_EN;
+
+ return 0;
+}
+
+static void fsl_usb_host_uninit_ext(struct platform_device *pdev)
+{
+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+ fsl_usb_host_uninit(pdata);
+
+ clk_put(usb_phy4_clk);
+
+ clk_put(usb_oh3_clk);
+
+}
+
+static void usbh3_clock_gate(bool on)
+{
+ pr_debug("%s: on is %d\n", __func__, on);
+ if (on) {
+ clk_enable(usb_oh3_clk);
+ clk_enable(usb_phy4_clk);
+ usbh3_internal_phy_clock_gate(true);
+ } else {
+ usbh3_internal_phy_clock_gate(false);
+ clk_disable(usb_phy4_clk);
+ clk_disable(usb_oh3_clk);
+ }
+}
+
+void mx6_set_host3_vbus_func(driver_vbus_func driver_vbus)
+{
+ usbh3_config.platform_driver_vbus = driver_vbus;
+}
+
+static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ pr_debug("host3, %s, enable is %d\n", __func__, enable);
+ /* for HSIC, no disconnect nor connect
+ * we need to disable the WKDS, WKCN */
+ UH3_PORTSC1 &= ~(PORTSC_WKDC | PORTSC_WKCN);
+
+ if (enable) {
+ USB_H3_CTRL |= (UCTRL_OWIE);
+ } else {
+ USB_H3_CTRL &= ~(UCTRL_OWIE);
+ /* The interrupt must be disabled for at least 3
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+static void _phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ pr_debug("host3, %s, enable is %d\n", __func__, enable);
+ if (enable)
+ UH3_PORTSC1 |= PORTSC_PHCD;
+ else
+ UH3_PORTSC1 &= ~PORTSC_PHCD;
+
+}
+
+static enum usb_wakeup_event _is_usbh3_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ u32 wakeup_req = USB_H3_CTRL & UCTRL_OWIR;
+
+ if (wakeup_req)
+ return WAKEUP_EVENT_DPDM;
+ pr_err("host3, %s, invalid wake up\n", __func__);
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void usbh3_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _wake_up_enable(pdata, false);
+ _phy_lowpower_suspend(pdata, false);
+}
+
+static void usbh3_wakeup_event_clear(void)
+{
+ u32 wakeup_req = USB_H3_CTRL & UCTRL_OWIR;
+ pr_debug("%s\n", __func__);
+
+ if (wakeup_req != 0) {
+ /* Disable H3 wakeup enable to clear H3 wakeup request, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ USB_H3_CTRL &= ~UCTRL_OWIE;
+ udelay(100);
+ USB_H3_CTRL |= UCTRL_OWIE;
+ }
+}
+
+static void hsic_start(void)
+{
+ pr_debug("%s", __func__);
+ /* strobe 47K pull up */
+ if (cpu_is_mx6q())
+ mxc_iomux_v3_setup_pad(
+ MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE_START);
+ else if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_pad(
+ MX6DL_PAD_RGMII_RXC__USBOH3_H3_STROBE_START);
+}
+
+static void hsic_device_connected(void)
+{
+ pr_debug("%s\n", __func__);
+ if (!(USB_UH3_HSIC_CTRL & HSIC_DEV_CONN))
+ USB_UH3_HSIC_CTRL |= HSIC_DEV_CONN;
+}
+
+static struct fsl_usb2_platform_data usbh3_config = {
+ .name = "Host 3",
+ .init = fsl_usb_host_init_ext,
+ .exit = fsl_usb_host_uninit_ext,
+ .operating_mode = FSL_USB2_MPH_HOST,
+ .phy_mode = FSL_USB2_PHY_HSIC,
+ .power_budget = 500, /* 500 mA max power */
+ .wake_up_enable = _wake_up_enable,
+ .usb_clock_for_pm = usbh3_clock_gate,
+ .phy_lowpower_suspend = _phy_lowpower_suspend,
+ .is_wakeup_event = _is_usbh3_wakeup,
+ .wakeup_handler = usbh3_wakeup_handler,
+ .transceiver = "hsic_xcvr",
+ .hsic_post_ops = hsic_start,
+ .hsic_device_connected = hsic_device_connected,
+};
+
+static struct fsl_usb2_wakeup_platform_data usbh3_wakeup_config = {
+ .name = "usbh3 wakeup",
+ .usb_clock_for_pm = usbh3_clock_gate,
+ .usb_pdata = {&usbh3_config, NULL, NULL},
+ .usb_wakeup_exhandle = usbh3_wakeup_event_clear,
+};
+
+void __init mx6_usb_h3_init(void)
+{
+ struct platform_device *pdev, *pdev_wakeup;
+ static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ usbh3_config.wakeup_pdata = &usbh3_wakeup_config;
+ pdev = imx6q_add_fsl_ehci_hs(3, &usbh3_config);
+ usbh3_wakeup_config.usb_pdata[0] = pdev->dev.platform_data;
+ pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(3, &usbh3_wakeup_config);
+ platform_device_add(pdev);
+ ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata =
+ pdev_wakeup->dev.platform_data;
+
+ /* Some phy and power's special controls for host3
+ * 1. Its 480M is from OTG's 480M
+ * 2. EN_USB_CLKS should always be opened
+ */
+ __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS,
+ anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_SET);
+ /* must change the clkgate delay to 2 or 3 to avoid
+ * 24M OSCI clock not stable issue */
+ __raw_writel(BF_ANADIG_ANA_MISC0_CLKGATE_DELAY(3),
+ anatop_base_addr + HW_ANADIG_ANA_MISC0);
+}