aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2011-11-01 21:46:55 -0400
committerArnd Bergmann <arnd@arndb.de>2011-11-01 21:46:55 -0400
commitabc3f126ac736280c68db6472eb0040ddf6e1b1f (patch)
tree4e3333cde6da6c49dcd81920410bf5a33055f03a /arch/arm/mach-imx
parentb8df0ea26ac17c9a073f235c7fdfbdd1851b59ea (diff)
parent8bcb97659656042f3132b2814b19709856aa1335 (diff)
Merge branch 'imx/imx6q' into next/soc
Conflicts: Documentation/devicetree/bindings/arm/fsl.txt arch/arm/Kconfig arch/arm/Kconfig.debug arch/arm/plat-mxc/include/mach/common.h
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/Kconfig30
-rw-r--r--arch/arm/mach-imx/Makefile11
-rw-r--r--arch/arm/mach-imx/Makefile.boot4
-rw-r--r--arch/arm/mach-imx/clock-imx6q.c2012
-rw-r--r--arch/arm/mach-imx/gpc.c113
-rw-r--r--arch/arm/mach-imx/head-v7.S99
-rw-r--r--arch/arm/mach-imx/hotplug.c44
-rw-r--r--arch/arm/mach-imx/lluart.c32
-rw-r--r--arch/arm/mach-imx/localtimer.c35
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c84
-rw-r--r--arch/arm/mach-imx/mmdc.c72
-rw-r--r--arch/arm/mach-imx/platsmp.c85
-rw-r--r--arch/arm/mach-imx/pm-imx6q.c70
-rw-r--r--arch/arm/mach-imx/src.c49
14 files changed, 2739 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index b4e1bf8757c..b1f782f07f1 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1,5 +1,15 @@
1config IMX_HAVE_DMA_V1 1config IMX_HAVE_DMA_V1
2 bool 2 bool
3
4config HAVE_IMX_GPC
5 bool
6
7config HAVE_IMX_MMDC
8 bool
9
10config HAVE_IMX_SRC
11 bool
12
3# 13#
4# ARCH_MX31 and ARCH_MX35 are left for compatibility 14# ARCH_MX31 and ARCH_MX35 are left for compatibility
5# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2. 15# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2.
@@ -64,6 +74,7 @@ config SOC_IMX31
64 select ARCH_MXC_AUDMUX_V2 74 select ARCH_MXC_AUDMUX_V2
65 select ARCH_MX31 75 select ARCH_MX31
66 select MXC_AVIC 76 select MXC_AVIC
77 select SMP_ON_UP if SMP
67 78
68config SOC_IMX35 79config SOC_IMX35
69 bool 80 bool
@@ -73,6 +84,7 @@ config SOC_IMX35
73 select HAVE_EPIT 84 select HAVE_EPIT
74 select ARCH_MX35 85 select ARCH_MX35
75 select MXC_AVIC 86 select MXC_AVIC
87 select SMP_ON_UP if SMP
76 88
77 89
78if ARCH_IMX_V4_V5 90if ARCH_IMX_V4_V5
@@ -341,7 +353,7 @@ config MACH_IMX27IPCAM
341 353
342endif 354endif
343 355
344if ARCH_MX3 356if ARCH_IMX_V6_V7
345 357
346comment "MX31 platforms:" 358comment "MX31 platforms:"
347 359
@@ -591,4 +603,20 @@ config MACH_VPR200
591 Include support for VPR200 platform. This includes specific 603 Include support for VPR200 platform. This includes specific
592 configurations for the board and its peripherals. 604 configurations for the board and its peripherals.
593 605
606comment "i.MX6 family:"
607
608config SOC_IMX6Q
609 bool "i.MX6 Quad support"
610 select ARM_GIC
611 select CACHE_L2X0
612 select CPU_V7
613 select HAVE_ARM_SCU
614 select HAVE_IMX_GPC
615 select HAVE_IMX_MMDC
616 select HAVE_IMX_SRC
617 select USE_OF
618
619 help
620 This enables support for Freescale i.MX6 Quad processor.
621
594endif 622endif
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 116d4b2d281..aba73214c2a 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -60,3 +60,14 @@ obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o
60obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o 60obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o
61obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o 61obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
62obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o 62obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
63
64obj-$(CONFIG_DEBUG_LL) += lluart.o
65obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
66obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
67obj-$(CONFIG_HAVE_IMX_SRC) += src.o
68obj-$(CONFIG_CPU_V7) += head-v7.o
69AFLAGS_head-v7.o :=-Wa,-march=armv7-a
70obj-$(CONFIG_SMP) += platsmp.o
71obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
72obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
73obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o
diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot
index ebee18b3884..136cfc6f2f8 100644
--- a/arch/arm/mach-imx/Makefile.boot
+++ b/arch/arm/mach-imx/Makefile.boot
@@ -17,3 +17,7 @@ initrd_phys-$(CONFIG_MACH_MX27) := 0xA0800000
17zreladdr-$(CONFIG_ARCH_MX3) := 0x80008000 17zreladdr-$(CONFIG_ARCH_MX3) := 0x80008000
18params_phys-$(CONFIG_ARCH_MX3) := 0x80000100 18params_phys-$(CONFIG_ARCH_MX3) := 0x80000100
19initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000 19initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000
20
21zreladdr-$(CONFIG_SOC_IMX6Q) += 0x10008000
22params_phys-$(CONFIG_SOC_IMX6Q) := 0x10000100
23initrd_phys-$(CONFIG_SOC_IMX6Q) := 0x10800000
diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
new file mode 100644
index 00000000000..e0b926dfece
--- /dev/null
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -0,0 +1,2012 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/types.h>
15#include <linux/clk.h>
16#include <linux/clkdev.h>
17#include <linux/io.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20#include <linux/of_irq.h>
21#include <asm/div64.h>
22#include <asm/mach/map.h>
23#include <mach/clock.h>
24#include <mach/common.h>
25#include <mach/hardware.h>
26
27#define PLL_BASE IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
28#define PLL1_SYS (PLL_BASE + 0x000)
29#define PLL2_BUS (PLL_BASE + 0x030)
30#define PLL3_USB_OTG (PLL_BASE + 0x010)
31#define PLL4_AUDIO (PLL_BASE + 0x070)
32#define PLL5_VIDEO (PLL_BASE + 0x0a0)
33#define PLL6_MLB (PLL_BASE + 0x0d0)
34#define PLL7_USB_HOST (PLL_BASE + 0x020)
35#define PLL8_ENET (PLL_BASE + 0x0e0)
36#define PFD_480 (PLL_BASE + 0x0f0)
37#define PFD_528 (PLL_BASE + 0x100)
38#define PLL_NUM_OFFSET 0x010
39#define PLL_DENOM_OFFSET 0x020
40
41#define PFD0 7
42#define PFD1 15
43#define PFD2 23
44#define PFD3 31
45#define PFD_FRAC_MASK 0x3f
46
47#define BM_PLL_BYPASS (0x1 << 16)
48#define BM_PLL_ENABLE (0x1 << 13)
49#define BM_PLL_POWER_DOWN (0x1 << 12)
50#define BM_PLL_LOCK (0x1 << 31)
51#define BP_PLL_SYS_DIV_SELECT 0
52#define BM_PLL_SYS_DIV_SELECT (0x7f << 0)
53#define BP_PLL_BUS_DIV_SELECT 0
54#define BM_PLL_BUS_DIV_SELECT (0x1 << 0)
55#define BP_PLL_USB_DIV_SELECT 0
56#define BM_PLL_USB_DIV_SELECT (0x3 << 0)
57#define BP_PLL_AV_DIV_SELECT 0
58#define BM_PLL_AV_DIV_SELECT (0x7f << 0)
59#define BP_PLL_ENET_DIV_SELECT 0
60#define BM_PLL_ENET_DIV_SELECT (0x3 << 0)
61#define BM_PLL_ENET_EN_PCIE (0x1 << 19)
62#define BM_PLL_ENET_EN_SATA (0x1 << 20)
63
64#define CCM_BASE IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
65#define CCR (CCM_BASE + 0x00)
66#define CCDR (CCM_BASE + 0x04)
67#define CSR (CCM_BASE + 0x08)
68#define CCSR (CCM_BASE + 0x0c)
69#define CACRR (CCM_BASE + 0x10)
70#define CBCDR (CCM_BASE + 0x14)
71#define CBCMR (CCM_BASE + 0x18)
72#define CSCMR1 (CCM_BASE + 0x1c)
73#define CSCMR2 (CCM_BASE + 0x20)
74#define CSCDR1 (CCM_BASE + 0x24)
75#define CS1CDR (CCM_BASE + 0x28)
76#define CS2CDR (CCM_BASE + 0x2c)
77#define CDCDR (CCM_BASE + 0x30)
78#define CHSCCDR (CCM_BASE + 0x34)
79#define CSCDR2 (CCM_BASE + 0x38)
80#define CSCDR3 (CCM_BASE + 0x3c)
81#define CSCDR4 (CCM_BASE + 0x40)
82#define CWDR (CCM_BASE + 0x44)
83#define CDHIPR (CCM_BASE + 0x48)
84#define CDCR (CCM_BASE + 0x4c)
85#define CTOR (CCM_BASE + 0x50)
86#define CLPCR (CCM_BASE + 0x54)
87#define CISR (CCM_BASE + 0x58)
88#define CIMR (CCM_BASE + 0x5c)
89#define CCOSR (CCM_BASE + 0x60)
90#define CGPR (CCM_BASE + 0x64)
91#define CCGR0 (CCM_BASE + 0x68)
92#define CCGR1 (CCM_BASE + 0x6c)
93#define CCGR2 (CCM_BASE + 0x70)
94#define CCGR3 (CCM_BASE + 0x74)
95#define CCGR4 (CCM_BASE + 0x78)
96#define CCGR5 (CCM_BASE + 0x7c)
97#define CCGR6 (CCM_BASE + 0x80)
98#define CCGR7 (CCM_BASE + 0x84)
99#define CMEOR (CCM_BASE + 0x88)
100
101#define CG0 0
102#define CG1 2
103#define CG2 4
104#define CG3 6
105#define CG4 8
106#define CG5 10
107#define CG6 12
108#define CG7 14
109#define CG8 16
110#define CG9 18
111#define CG10 20
112#define CG11 22
113#define CG12 24
114#define CG13 26
115#define CG14 28
116#define CG15 30
117
118#define BM_CCSR_PLL1_SW_SEL (0x1 << 2)
119#define BM_CCSR_STEP_SEL (0x1 << 8)
120
121#define BP_CACRR_ARM_PODF 0
122#define BM_CACRR_ARM_PODF (0x7 << 0)
123
124#define BP_CBCDR_PERIPH2_CLK2_PODF 0
125#define BM_CBCDR_PERIPH2_CLK2_PODF (0x7 << 0)
126#define BP_CBCDR_MMDC_CH1_AXI_PODF 3
127#define BM_CBCDR_MMDC_CH1_AXI_PODF (0x7 << 3)
128#define BP_CBCDR_AXI_SEL 6
129#define BM_CBCDR_AXI_SEL (0x3 << 6)
130#define BP_CBCDR_IPG_PODF 8
131#define BM_CBCDR_IPG_PODF (0x3 << 8)
132#define BP_CBCDR_AHB_PODF 10
133#define BM_CBCDR_AHB_PODF (0x7 << 10)
134#define BP_CBCDR_AXI_PODF 16
135#define BM_CBCDR_AXI_PODF (0x7 << 16)
136#define BP_CBCDR_MMDC_CH0_AXI_PODF 19
137#define BM_CBCDR_MMDC_CH0_AXI_PODF (0x7 << 19)
138#define BP_CBCDR_PERIPH_CLK_SEL 25
139#define BM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
140#define BP_CBCDR_PERIPH2_CLK_SEL 26
141#define BM_CBCDR_PERIPH2_CLK_SEL (0x1 << 26)
142#define BP_CBCDR_PERIPH_CLK2_PODF 27
143#define BM_CBCDR_PERIPH_CLK2_PODF (0x7 << 27)
144
145#define BP_CBCMR_GPU2D_AXI_SEL 0
146#define BM_CBCMR_GPU2D_AXI_SEL (0x1 << 0)
147#define BP_CBCMR_GPU3D_AXI_SEL 1
148#define BM_CBCMR_GPU3D_AXI_SEL (0x1 << 1)
149#define BP_CBCMR_GPU3D_CORE_SEL 4
150#define BM_CBCMR_GPU3D_CORE_SEL (0x3 << 4)
151#define BP_CBCMR_GPU3D_SHADER_SEL 8
152#define BM_CBCMR_GPU3D_SHADER_SEL (0x3 << 8)
153#define BP_CBCMR_PCIE_AXI_SEL 10
154#define BM_CBCMR_PCIE_AXI_SEL (0x1 << 10)
155#define BP_CBCMR_VDO_AXI_SEL 11
156#define BM_CBCMR_VDO_AXI_SEL (0x1 << 11)
157#define BP_CBCMR_PERIPH_CLK2_SEL 12
158#define BM_CBCMR_PERIPH_CLK2_SEL (0x3 << 12)
159#define BP_CBCMR_VPU_AXI_SEL 14
160#define BM_CBCMR_VPU_AXI_SEL (0x3 << 14)
161#define BP_CBCMR_GPU2D_CORE_SEL 16
162#define BM_CBCMR_GPU2D_CORE_SEL (0x3 << 16)
163#define BP_CBCMR_PRE_PERIPH_CLK_SEL 18
164#define BM_CBCMR_PRE_PERIPH_CLK_SEL (0x3 << 18)
165#define BP_CBCMR_PERIPH2_CLK2_SEL 20
166#define BM_CBCMR_PERIPH2_CLK2_SEL (0x1 << 20)
167#define BP_CBCMR_PRE_PERIPH2_CLK_SEL 21
168#define BM_CBCMR_PRE_PERIPH2_CLK_SEL (0x3 << 21)
169#define BP_CBCMR_GPU2D_CORE_PODF 23
170#define BM_CBCMR_GPU2D_CORE_PODF (0x7 << 23)
171#define BP_CBCMR_GPU3D_CORE_PODF 26
172#define BM_CBCMR_GPU3D_CORE_PODF (0x7 << 26)
173#define BP_CBCMR_GPU3D_SHADER_PODF 29
174#define BM_CBCMR_GPU3D_SHADER_PODF (0x7 << 29)
175
176#define BP_CSCMR1_PERCLK_PODF 0
177#define BM_CSCMR1_PERCLK_PODF (0x3f << 0)
178#define BP_CSCMR1_SSI1_SEL 10
179#define BM_CSCMR1_SSI1_SEL (0x3 << 10)
180#define BP_CSCMR1_SSI2_SEL 12
181#define BM_CSCMR1_SSI2_SEL (0x3 << 12)
182#define BP_CSCMR1_SSI3_SEL 14
183#define BM_CSCMR1_SSI3_SEL (0x3 << 14)
184#define BP_CSCMR1_USDHC1_SEL 16
185#define BM_CSCMR1_USDHC1_SEL (0x1 << 16)
186#define BP_CSCMR1_USDHC2_SEL 17
187#define BM_CSCMR1_USDHC2_SEL (0x1 << 17)
188#define BP_CSCMR1_USDHC3_SEL 18
189#define BM_CSCMR1_USDHC3_SEL (0x1 << 18)
190#define BP_CSCMR1_USDHC4_SEL 19
191#define BM_CSCMR1_USDHC4_SEL (0x1 << 19)
192#define BP_CSCMR1_EMI_PODF 20
193#define BM_CSCMR1_EMI_PODF (0x7 << 20)
194#define BP_CSCMR1_EMI_SLOW_PODF 23
195#define BM_CSCMR1_EMI_SLOW_PODF (0x7 << 23)
196#define BP_CSCMR1_EMI_SEL 27
197#define BM_CSCMR1_EMI_SEL (0x3 << 27)
198#define BP_CSCMR1_EMI_SLOW_SEL 29
199#define BM_CSCMR1_EMI_SLOW_SEL (0x3 << 29)
200
201#define BP_CSCMR2_CAN_PODF 2
202#define BM_CSCMR2_CAN_PODF (0x3f << 2)
203#define BM_CSCMR2_LDB_DI0_IPU_DIV (0x1 << 10)
204#define BM_CSCMR2_LDB_DI1_IPU_DIV (0x1 << 11)
205#define BP_CSCMR2_ESAI_SEL 19
206#define BM_CSCMR2_ESAI_SEL (0x3 << 19)
207
208#define BP_CSCDR1_UART_PODF 0
209#define BM_CSCDR1_UART_PODF (0x3f << 0)
210#define BP_CSCDR1_USDHC1_PODF 11
211#define BM_CSCDR1_USDHC1_PODF (0x7 << 11)
212#define BP_CSCDR1_USDHC2_PODF 16
213#define BM_CSCDR1_USDHC2_PODF (0x7 << 16)
214#define BP_CSCDR1_USDHC3_PODF 19
215#define BM_CSCDR1_USDHC3_PODF (0x7 << 19)
216#define BP_CSCDR1_USDHC4_PODF 22
217#define BM_CSCDR1_USDHC4_PODF (0x7 << 22)
218#define BP_CSCDR1_VPU_AXI_PODF 25
219#define BM_CSCDR1_VPU_AXI_PODF (0x7 << 25)
220
221#define BP_CS1CDR_SSI1_PODF 0
222#define BM_CS1CDR_SSI1_PODF (0x3f << 0)
223#define BP_CS1CDR_SSI1_PRED 6
224#define BM_CS1CDR_SSI1_PRED (0x7 << 6)
225#define BP_CS1CDR_ESAI_PRED 9
226#define BM_CS1CDR_ESAI_PRED (0x7 << 9)
227#define BP_CS1CDR_SSI3_PODF 16
228#define BM_CS1CDR_SSI3_PODF (0x3f << 16)
229#define BP_CS1CDR_SSI3_PRED 22
230#define BM_CS1CDR_SSI3_PRED (0x7 << 22)
231#define BP_CS1CDR_ESAI_PODF 25
232#define BM_CS1CDR_ESAI_PODF (0x7 << 25)
233
234#define BP_CS2CDR_SSI2_PODF 0
235#define BM_CS2CDR_SSI2_PODF (0x3f << 0)
236#define BP_CS2CDR_SSI2_PRED 6
237#define BM_CS2CDR_SSI2_PRED (0x7 << 6)
238#define BP_CS2CDR_LDB_DI0_SEL 9
239#define BM_CS2CDR_LDB_DI0_SEL (0x7 << 9)
240#define BP_CS2CDR_LDB_DI1_SEL 12
241#define BM_CS2CDR_LDB_DI1_SEL (0x7 << 12)
242#define BP_CS2CDR_ENFC_SEL 16
243#define BM_CS2CDR_ENFC_SEL (0x3 << 16)
244#define BP_CS2CDR_ENFC_PRED 18
245#define BM_CS2CDR_ENFC_PRED (0x7 << 18)
246#define BP_CS2CDR_ENFC_PODF 21
247#define BM_CS2CDR_ENFC_PODF (0x3f << 21)
248
249#define BP_CDCDR_ASRC_SERIAL_SEL 7
250#define BM_CDCDR_ASRC_SERIAL_SEL (0x3 << 7)
251#define BP_CDCDR_ASRC_SERIAL_PODF 9
252#define BM_CDCDR_ASRC_SERIAL_PODF (0x7 << 9)
253#define BP_CDCDR_ASRC_SERIAL_PRED 12
254#define BM_CDCDR_ASRC_SERIAL_PRED (0x7 << 12)
255#define BP_CDCDR_SPDIF_SEL 20
256#define BM_CDCDR_SPDIF_SEL (0x3 << 20)
257#define BP_CDCDR_SPDIF_PODF 22
258#define BM_CDCDR_SPDIF_PODF (0x7 << 22)
259#define BP_CDCDR_SPDIF_PRED 25
260#define BM_CDCDR_SPDIF_PRED (0x7 << 25)
261#define BP_CDCDR_HSI_TX_PODF 29
262#define BM_CDCDR_HSI_TX_PODF (0x7 << 29)
263#define BP_CDCDR_HSI_TX_SEL 28
264#define BM_CDCDR_HSI_TX_SEL (0x1 << 28)
265
266#define BP_CHSCCDR_IPU1_DI0_SEL 0
267#define BM_CHSCCDR_IPU1_DI0_SEL (0x7 << 0)
268#define BP_CHSCCDR_IPU1_DI0_PRE_PODF 3
269#define BM_CHSCCDR_IPU1_DI0_PRE_PODF (0x7 << 3)
270#define BP_CHSCCDR_IPU1_DI0_PRE_SEL 6
271#define BM_CHSCCDR_IPU1_DI0_PRE_SEL (0x7 << 6)
272#define BP_CHSCCDR_IPU1_DI1_SEL 9
273#define BM_CHSCCDR_IPU1_DI1_SEL (0x7 << 9)
274#define BP_CHSCCDR_IPU1_DI1_PRE_PODF 12
275#define BM_CHSCCDR_IPU1_DI1_PRE_PODF (0x7 << 12)
276#define BP_CHSCCDR_IPU1_DI1_PRE_SEL 15
277#define BM_CHSCCDR_IPU1_DI1_PRE_SEL (0x7 << 15)
278
279#define BP_CSCDR2_IPU2_DI0_SEL 0
280#define BM_CSCDR2_IPU2_DI0_SEL (0x7)
281#define BP_CSCDR2_IPU2_DI0_PRE_PODF 3
282#define BM_CSCDR2_IPU2_DI0_PRE_PODF (0x7 << 3)
283#define BP_CSCDR2_IPU2_DI0_PRE_SEL 6
284#define BM_CSCDR2_IPU2_DI0_PRE_SEL (0x7 << 6)
285#define BP_CSCDR2_IPU2_DI1_SEL 9
286#define BM_CSCDR2_IPU2_DI1_SEL (0x7 << 9)
287#define BP_CSCDR2_IPU2_DI1_PRE_PODF 12
288#define BM_CSCDR2_IPU2_DI1_PRE_PODF (0x7 << 12)
289#define BP_CSCDR2_IPU2_DI1_PRE_SEL 15
290#define BM_CSCDR2_IPU2_DI1_PRE_SEL (0x7 << 15)
291#define BP_CSCDR2_ECSPI_CLK_PODF 19
292#define BM_CSCDR2_ECSPI_CLK_PODF (0x3f << 19)
293
294#define BP_CSCDR3_IPU1_HSP_SEL 9
295#define BM_CSCDR3_IPU1_HSP_SEL (0x3 << 9)
296#define BP_CSCDR3_IPU1_HSP_PODF 11
297#define BM_CSCDR3_IPU1_HSP_PODF (0x7 << 11)
298#define BP_CSCDR3_IPU2_HSP_SEL 14
299#define BM_CSCDR3_IPU2_HSP_SEL (0x3 << 14)
300#define BP_CSCDR3_IPU2_HSP_PODF 16
301#define BM_CSCDR3_IPU2_HSP_PODF (0x7 << 16)
302
303#define BM_CDHIPR_AXI_PODF_BUSY (0x1 << 0)
304#define BM_CDHIPR_AHB_PODF_BUSY (0x1 << 1)
305#define BM_CDHIPR_MMDC_CH1_PODF_BUSY (0x1 << 2)
306#define BM_CDHIPR_PERIPH2_SEL_BUSY (0x1 << 3)
307#define BM_CDHIPR_MMDC_CH0_PODF_BUSY (0x1 << 4)
308#define BM_CDHIPR_PERIPH_SEL_BUSY (0x1 << 5)
309#define BM_CDHIPR_ARM_PODF_BUSY (0x1 << 16)
310
311#define BP_CLPCR_LPM 0
312#define BM_CLPCR_LPM (0x3 << 0)
313#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
314#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
315#define BM_CLPCR_SBYOS (0x1 << 6)
316#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
317#define BM_CLPCR_VSTBY (0x1 << 8)
318#define BP_CLPCR_STBY_COUNT 9
319#define BM_CLPCR_STBY_COUNT (0x3 << 9)
320#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
321#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
322#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
323#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
324#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
325#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
326#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
327#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
328#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
329#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
330#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
331
332#define FREQ_480M 480000000
333#define FREQ_528M 528000000
334#define FREQ_594M 594000000
335#define FREQ_650M 650000000
336#define FREQ_1300M 1300000000
337
338static struct clk pll1_sys;
339static struct clk pll2_bus;
340static struct clk pll3_usb_otg;
341static struct clk pll4_audio;
342static struct clk pll5_video;
343static struct clk pll6_mlb;
344static struct clk pll7_usb_host;
345static struct clk pll8_enet;
346static struct clk apbh_dma_clk;
347static struct clk arm_clk;
348static struct clk ipg_clk;
349static struct clk ahb_clk;
350static struct clk axi_clk;
351static struct clk mmdc_ch0_axi_clk;
352static struct clk mmdc_ch1_axi_clk;
353static struct clk periph_clk;
354static struct clk periph_pre_clk;
355static struct clk periph_clk2_clk;
356static struct clk periph2_clk;
357static struct clk periph2_pre_clk;
358static struct clk periph2_clk2_clk;
359static struct clk gpu2d_core_clk;
360static struct clk gpu3d_core_clk;
361static struct clk gpu3d_shader_clk;
362static struct clk ipg_perclk;
363static struct clk emi_clk;
364static struct clk emi_slow_clk;
365static struct clk can1_clk;
366static struct clk uart_clk;
367static struct clk usdhc1_clk;
368static struct clk usdhc2_clk;
369static struct clk usdhc3_clk;
370static struct clk usdhc4_clk;
371static struct clk vpu_clk;
372static struct clk hsi_tx_clk;
373static struct clk ipu1_di0_pre_clk;
374static struct clk ipu1_di1_pre_clk;
375static struct clk ipu2_di0_pre_clk;
376static struct clk ipu2_di1_pre_clk;
377static struct clk ipu1_clk;
378static struct clk ipu2_clk;
379static struct clk ssi1_clk;
380static struct clk ssi3_clk;
381static struct clk esai_clk;
382static struct clk ssi2_clk;
383static struct clk spdif_clk;
384static struct clk asrc_serial_clk;
385static struct clk gpu2d_axi_clk;
386static struct clk gpu3d_axi_clk;
387static struct clk pcie_clk;
388static struct clk vdo_axi_clk;
389static struct clk ldb_di0_clk;
390static struct clk ldb_di1_clk;
391static struct clk ipu1_di0_clk;
392static struct clk ipu1_di1_clk;
393static struct clk ipu2_di0_clk;
394static struct clk ipu2_di1_clk;
395static struct clk enfc_clk;
396static struct clk dummy_clk = {};
397
398static unsigned long external_high_reference;
399static unsigned long external_low_reference;
400static unsigned long oscillator_reference;
401
402static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
403{
404 return oscillator_reference;
405}
406
407static unsigned long get_high_reference_clock_rate(struct clk *clk)
408{
409 return external_high_reference;
410}
411
412static unsigned long get_low_reference_clock_rate(struct clk *clk)
413{
414 return external_low_reference;
415}
416
417static struct clk ckil_clk = {
418 .get_rate = get_low_reference_clock_rate,
419};
420
421static struct clk ckih_clk = {
422 .get_rate = get_high_reference_clock_rate,
423};
424
425static struct clk osc_clk = {
426 .get_rate = get_oscillator_reference_clock_rate,
427};
428
429static inline void __iomem *pll_get_reg_addr(struct clk *pll)
430{
431 if (pll == &pll1_sys)
432 return PLL1_SYS;
433 else if (pll == &pll2_bus)
434 return PLL2_BUS;
435 else if (pll == &pll3_usb_otg)
436 return PLL3_USB_OTG;
437 else if (pll == &pll4_audio)
438 return PLL4_AUDIO;
439 else if (pll == &pll5_video)
440 return PLL5_VIDEO;
441 else if (pll == &pll6_mlb)
442 return PLL6_MLB;
443 else if (pll == &pll7_usb_host)
444 return PLL7_USB_HOST;
445 else if (pll == &pll8_enet)
446 return PLL8_ENET;
447 else
448 BUG();
449
450 return NULL;
451}
452
453static int pll_enable(struct clk *clk)
454{
455 int timeout = 0x100000;
456 void __iomem *reg;
457 u32 val;
458
459 reg = pll_get_reg_addr(clk);
460 val = readl_relaxed(reg);
461 val &= ~BM_PLL_BYPASS;
462 val &= ~BM_PLL_POWER_DOWN;
463 /* 480MHz PLLs have the opposite definition for power bit */
464 if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
465 val |= BM_PLL_POWER_DOWN;
466 writel_relaxed(val, reg);
467
468 /* Wait for PLL to lock */
469 while (!(readl_relaxed(reg) & BM_PLL_LOCK) && --timeout)
470 cpu_relax();
471
472 if (unlikely(!timeout))
473 return -EBUSY;
474
475 /* Enable the PLL output now */
476 val = readl_relaxed(reg);
477 val |= BM_PLL_ENABLE;
478 writel_relaxed(val, reg);
479
480 return 0;
481}
482
483static void pll_disable(struct clk *clk)
484{
485 void __iomem *reg;
486 u32 val;
487
488 reg = pll_get_reg_addr(clk);
489 val = readl_relaxed(reg);
490 val &= ~BM_PLL_ENABLE;
491 val |= BM_PLL_BYPASS;
492 val |= BM_PLL_POWER_DOWN;
493 if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
494 val &= ~BM_PLL_POWER_DOWN;
495 writel_relaxed(val, reg);
496}
497
498static unsigned long pll1_sys_get_rate(struct clk *clk)
499{
500 u32 div = (readl_relaxed(PLL1_SYS) & BM_PLL_SYS_DIV_SELECT) >>
501 BP_PLL_SYS_DIV_SELECT;
502
503 return clk_get_rate(clk->parent) * div / 2;
504}
505
506static int pll1_sys_set_rate(struct clk *clk, unsigned long rate)
507{
508 u32 val, div;
509
510 if (rate < FREQ_650M || rate > FREQ_1300M)
511 return -EINVAL;
512
513 div = rate * 2 / clk_get_rate(clk->parent);
514 val = readl_relaxed(PLL1_SYS);
515 val &= ~BM_PLL_SYS_DIV_SELECT;
516 val |= div << BP_PLL_SYS_DIV_SELECT;
517 writel_relaxed(val, PLL1_SYS);
518
519 return 0;
520}
521
522static unsigned long pll8_enet_get_rate(struct clk *clk)
523{
524 u32 div = (readl_relaxed(PLL8_ENET) & BM_PLL_ENET_DIV_SELECT) >>
525 BP_PLL_ENET_DIV_SELECT;
526
527 switch (div) {
528 case 0:
529 return 25000000;
530 case 1:
531 return 50000000;
532 case 2:
533 return 100000000;
534 case 3:
535 return 125000000;
536 }
537
538 return 0;
539}
540
541static int pll8_enet_set_rate(struct clk *clk, unsigned long rate)
542{
543 u32 val, div;
544
545 switch (rate) {
546 case 25000000:
547 div = 0;
548 break;
549 case 50000000:
550 div = 1;
551 break;
552 case 100000000:
553 div = 2;
554 break;
555 case 125000000:
556 div = 3;
557 break;
558 default:
559 return -EINVAL;
560 }
561
562 val = readl_relaxed(PLL8_ENET);
563 val &= ~BM_PLL_ENET_DIV_SELECT;
564 val |= div << BP_PLL_ENET_DIV_SELECT;
565 writel_relaxed(val, PLL8_ENET);
566
567 return 0;
568}
569
570static unsigned long pll_av_get_rate(struct clk *clk)
571{
572 void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
573 unsigned long parent_rate = clk_get_rate(clk->parent);
574 u32 mfn = readl_relaxed(reg + PLL_NUM_OFFSET);
575 u32 mfd = readl_relaxed(reg + PLL_DENOM_OFFSET);
576 u32 div = (readl_relaxed(reg) & BM_PLL_AV_DIV_SELECT) >>
577 BP_PLL_AV_DIV_SELECT;
578
579 return (parent_rate * div) + ((parent_rate / mfd) * mfn);
580}
581
582static int pll_av_set_rate(struct clk *clk, unsigned long rate)
583{
584 void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
585 unsigned int parent_rate = clk_get_rate(clk->parent);
586 u32 val, div;
587 u32 mfn, mfd = 1000000;
588 s64 temp64;
589
590 if (rate < FREQ_650M || rate > FREQ_1300M)
591 return -EINVAL;
592
593 div = rate / parent_rate;
594 temp64 = (u64) (rate - div * parent_rate);
595 temp64 *= mfd;
596 do_div(temp64, parent_rate);
597 mfn = temp64;
598
599 val = readl_relaxed(reg);
600 val &= ~BM_PLL_AV_DIV_SELECT;
601 val |= div << BP_PLL_AV_DIV_SELECT;
602 writel_relaxed(val, reg);
603 writel_relaxed(mfn, reg + PLL_NUM_OFFSET);
604 writel_relaxed(mfd, reg + PLL_DENOM_OFFSET);
605
606 return 0;
607}
608
609static void __iomem *pll_get_div_reg_bit(struct clk *clk, u32 *bp, u32 *bm)
610{
611 void __iomem *reg;
612
613 if (clk == &pll2_bus) {
614 reg = PLL2_BUS;
615 *bp = BP_PLL_BUS_DIV_SELECT;
616 *bm = BM_PLL_BUS_DIV_SELECT;
617 } else if (clk == &pll3_usb_otg) {
618 reg = PLL3_USB_OTG;
619 *bp = BP_PLL_USB_DIV_SELECT;
620 *bm = BM_PLL_USB_DIV_SELECT;
621 } else if (clk == &pll7_usb_host) {
622 reg = PLL7_USB_HOST;
623 *bp = BP_PLL_USB_DIV_SELECT;
624 *bm = BM_PLL_USB_DIV_SELECT;
625 } else {
626 BUG();
627 }
628
629 return reg;
630}
631
632static unsigned long pll_get_rate(struct clk *clk)
633{
634 void __iomem *reg;
635 u32 div, bp, bm;
636
637 reg = pll_get_div_reg_bit(clk, &bp, &bm);
638 div = (readl_relaxed(reg) & bm) >> bp;
639
640 return (div == 1) ? clk_get_rate(clk->parent) * 22 :
641 clk_get_rate(clk->parent) * 20;
642}
643
644static int pll_set_rate(struct clk *clk, unsigned long rate)
645{
646 void __iomem *reg;
647 u32 val, div, bp, bm;
648
649 if (rate == FREQ_528M)
650 div = 1;
651 else if (rate == FREQ_480M)
652 div = 0;
653 else
654 return -EINVAL;
655
656 reg = pll_get_div_reg_bit(clk, &bp, &bm);
657 val = readl_relaxed(reg);
658 val &= ~bm;
659 val |= div << bp;
660 writel_relaxed(val, reg);
661
662 return 0;
663}
664
665#define pll2_bus_get_rate pll_get_rate
666#define pll2_bus_set_rate pll_set_rate
667#define pll3_usb_otg_get_rate pll_get_rate
668#define pll3_usb_otg_set_rate pll_set_rate
669#define pll7_usb_host_get_rate pll_get_rate
670#define pll7_usb_host_set_rate pll_set_rate
671#define pll4_audio_get_rate pll_av_get_rate
672#define pll4_audio_set_rate pll_av_set_rate
673#define pll5_video_get_rate pll_av_get_rate
674#define pll5_video_set_rate pll_av_set_rate
675#define pll6_mlb_get_rate NULL
676#define pll6_mlb_set_rate NULL
677
678#define DEF_PLL(name) \
679 static struct clk name = { \
680 .enable = pll_enable, \
681 .disable = pll_disable, \
682 .get_rate = name##_get_rate, \
683 .set_rate = name##_set_rate, \
684 .parent = &osc_clk, \
685 }
686
687DEF_PLL(pll1_sys);
688DEF_PLL(pll2_bus);
689DEF_PLL(pll3_usb_otg);
690DEF_PLL(pll4_audio);
691DEF_PLL(pll5_video);
692DEF_PLL(pll6_mlb);
693DEF_PLL(pll7_usb_host);
694DEF_PLL(pll8_enet);
695
696static unsigned long pfd_get_rate(struct clk *clk)
697{
698 u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
699 u32 frac, bp_frac;
700
701 if (apbh_dma_clk.usecount == 0)
702 apbh_dma_clk.enable(&apbh_dma_clk);
703
704 bp_frac = clk->enable_shift - 7;
705 frac = readl_relaxed(clk->enable_reg) >> bp_frac & PFD_FRAC_MASK;
706 do_div(tmp, frac);
707
708 return tmp;
709}
710
711static int pfd_set_rate(struct clk *clk, unsigned long rate)
712{
713 u32 val, frac, bp_frac;
714 u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
715
716 if (apbh_dma_clk.usecount == 0)
717 apbh_dma_clk.enable(&apbh_dma_clk);
718
719 /*
720 * Round up the divider so that we don't set a rate
721 * higher than what is requested
722 */
723 tmp += rate / 2;
724 do_div(tmp, rate);
725 frac = tmp;
726 frac = (frac < 12) ? 12 : frac;
727 frac = (frac > 35) ? 35 : frac;
728
729 /*
730 * The frac field always starts from 7 bits lower
731 * position of enable bit
732 */
733 bp_frac = clk->enable_shift - 7;
734 val = readl_relaxed(clk->enable_reg);
735 val &= ~(PFD_FRAC_MASK << bp_frac);
736 val |= frac << bp_frac;
737 writel_relaxed(val, clk->enable_reg);
738
739 tmp = (u64) clk_get_rate(clk->parent) * 18;
740 do_div(tmp, frac);
741
742 if (apbh_dma_clk.usecount == 0)
743 apbh_dma_clk.disable(&apbh_dma_clk);
744
745 return 0;
746}
747
748static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
749{
750 u32 frac;
751 u64 tmp;
752
753 tmp = (u64) clk_get_rate(clk->parent) * 18;
754 tmp += rate / 2;
755 do_div(tmp, rate);
756 frac = tmp;
757 frac = (frac < 12) ? 12 : frac;
758 frac = (frac > 35) ? 35 : frac;
759 tmp = (u64) clk_get_rate(clk->parent) * 18;
760 do_div(tmp, frac);
761
762 return tmp;
763}
764
765static int pfd_enable(struct clk *clk)
766{
767 u32 val;
768
769 if (apbh_dma_clk.usecount == 0)
770 apbh_dma_clk.enable(&apbh_dma_clk);
771
772 val = readl_relaxed(clk->enable_reg);
773 val &= ~(1 << clk->enable_shift);
774 writel_relaxed(val, clk->enable_reg);
775
776 if (apbh_dma_clk.usecount == 0)
777 apbh_dma_clk.disable(&apbh_dma_clk);
778
779 return 0;
780}
781
782static void pfd_disable(struct clk *clk)
783{
784 u32 val;
785
786 if (apbh_dma_clk.usecount == 0)
787 apbh_dma_clk.enable(&apbh_dma_clk);
788
789 val = readl_relaxed(clk->enable_reg);
790 val |= 1 << clk->enable_shift;
791 writel_relaxed(val, clk->enable_reg);
792
793 if (apbh_dma_clk.usecount == 0)
794 apbh_dma_clk.disable(&apbh_dma_clk);
795}
796
797#define DEF_PFD(name, er, es, p) \
798 static struct clk name = { \
799 .enable_reg = er, \
800 .enable_shift = es, \
801 .enable = pfd_enable, \
802 .disable = pfd_disable, \
803 .get_rate = pfd_get_rate, \
804 .set_rate = pfd_set_rate, \
805 .round_rate = pfd_round_rate, \
806 .parent = p, \
807 }
808
809DEF_PFD(pll2_pfd_352m, PFD_528, PFD0, &pll2_bus);
810DEF_PFD(pll2_pfd_594m, PFD_528, PFD1, &pll2_bus);
811DEF_PFD(pll2_pfd_400m, PFD_528, PFD2, &pll2_bus);
812DEF_PFD(pll3_pfd_720m, PFD_480, PFD0, &pll3_usb_otg);
813DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg);
814DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
815DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
816
817static unsigned long pll2_200m_get_rate(struct clk *clk)
818{
819 return clk_get_rate(clk->parent) / 2;
820}
821
822static struct clk pll2_200m = {
823 .parent = &pll2_pfd_400m,
824 .get_rate = pll2_200m_get_rate,
825};
826
827static unsigned long pll3_120m_get_rate(struct clk *clk)
828{
829 return clk_get_rate(clk->parent) / 4;
830}
831
832static struct clk pll3_120m = {
833 .parent = &pll3_usb_otg,
834 .get_rate = pll3_120m_get_rate,
835};
836
837static unsigned long pll3_80m_get_rate(struct clk *clk)
838{
839 return clk_get_rate(clk->parent) / 6;
840}
841
842static struct clk pll3_80m = {
843 .parent = &pll3_usb_otg,
844 .get_rate = pll3_80m_get_rate,
845};
846
847static unsigned long pll3_60m_get_rate(struct clk *clk)
848{
849 return clk_get_rate(clk->parent) / 8;
850}
851
852static struct clk pll3_60m = {
853 .parent = &pll3_usb_otg,
854 .get_rate = pll3_60m_get_rate,
855};
856
857static int pll1_sw_clk_set_parent(struct clk *clk, struct clk *parent)
858{
859 u32 val = readl_relaxed(CCSR);
860
861 if (parent == &pll1_sys) {
862 val &= ~BM_CCSR_PLL1_SW_SEL;
863 val &= ~BM_CCSR_STEP_SEL;
864 } else if (parent == &osc_clk) {
865 val |= BM_CCSR_PLL1_SW_SEL;
866 val &= ~BM_CCSR_STEP_SEL;
867 } else if (parent == &pll2_pfd_400m) {
868 val |= BM_CCSR_PLL1_SW_SEL;
869 val |= BM_CCSR_STEP_SEL;
870 } else {
871 return -EINVAL;
872 }
873
874 writel_relaxed(val, CCSR);
875
876 return 0;
877}
878
879static struct clk pll1_sw_clk = {
880 .parent = &pll1_sys,
881 .set_parent = pll1_sw_clk_set_parent,
882};
883
884static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
885{
886 u32 min_pred, temp_pred, old_err, err;
887
888 if (div >= 512) {
889 *pred = 8;
890 *podf = 64;
891 } else if (div >= 8) {
892 min_pred = (div - 1) / 64 + 1;
893 old_err = 8;
894 for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
895 err = div % temp_pred;
896 if (err == 0) {
897 *pred = temp_pred;
898 break;
899 }
900 err = temp_pred - err;
901 if (err < old_err) {
902 old_err = err;
903 *pred = temp_pred;
904 }
905 }
906 *podf = (div + *pred - 1) / *pred;
907 } else if (div < 8) {
908 *pred = div;
909 *podf = 1;
910 }
911}
912
913static int _clk_enable(struct clk *clk)
914{
915 u32 reg;
916 reg = readl_relaxed(clk->enable_reg);
917 reg |= 0x3 << clk->enable_shift;
918 writel_relaxed(reg, clk->enable_reg);
919
920 return 0;
921}
922
923static void _clk_disable(struct clk *clk)
924{
925 u32 reg;
926 reg = readl_relaxed(clk->enable_reg);
927 reg &= ~(0x3 << clk->enable_shift);
928 writel_relaxed(reg, clk->enable_reg);
929}
930
931struct divider {
932 struct clk *clk;
933 void __iomem *reg;
934 u32 bp_pred;
935 u32 bm_pred;
936 u32 bp_podf;
937 u32 bm_podf;
938};
939
940#define DEF_CLK_DIV1(d, c, r, b) \
941 static struct divider d = { \
942 .clk = c, \
943 .reg = r, \
944 .bp_podf = BP_##r##_##b##_PODF, \
945 .bm_podf = BM_##r##_##b##_PODF, \
946 }
947
948DEF_CLK_DIV1(arm_div, &arm_clk, CACRR, ARM);
949DEF_CLK_DIV1(ipg_div, &ipg_clk, CBCDR, IPG);
950DEF_CLK_DIV1(ahb_div, &ahb_clk, CBCDR, AHB);
951DEF_CLK_DIV1(axi_div, &axi_clk, CBCDR, AXI);
952DEF_CLK_DIV1(mmdc_ch0_axi_div, &mmdc_ch0_axi_clk, CBCDR, MMDC_CH0_AXI);
953DEF_CLK_DIV1(mmdc_ch1_axi_div, &mmdc_ch1_axi_clk, CBCDR, MMDC_CH1_AXI);
954DEF_CLK_DIV1(periph_clk2_div, &periph_clk2_clk, CBCDR, PERIPH_CLK2);
955DEF_CLK_DIV1(periph2_clk2_div, &periph2_clk2_clk, CBCDR, PERIPH2_CLK2);
956DEF_CLK_DIV1(gpu2d_core_div, &gpu2d_core_clk, CBCMR, GPU2D_CORE);
957DEF_CLK_DIV1(gpu3d_core_div, &gpu3d_core_clk, CBCMR, GPU3D_CORE);
958DEF_CLK_DIV1(gpu3d_shader_div, &gpu3d_shader_clk, CBCMR, GPU3D_SHADER);
959DEF_CLK_DIV1(ipg_perclk_div, &ipg_perclk, CSCMR1, PERCLK);
960DEF_CLK_DIV1(emi_div, &emi_clk, CSCMR1, EMI);
961DEF_CLK_DIV1(emi_slow_div, &emi_slow_clk, CSCMR1, EMI_SLOW);
962DEF_CLK_DIV1(can_div, &can1_clk, CSCMR2, CAN);
963DEF_CLK_DIV1(uart_div, &uart_clk, CSCDR1, UART);
964DEF_CLK_DIV1(usdhc1_div, &usdhc1_clk, CSCDR1, USDHC1);
965DEF_CLK_DIV1(usdhc2_div, &usdhc2_clk, CSCDR1, USDHC2);
966DEF_CLK_DIV1(usdhc3_div, &usdhc3_clk, CSCDR1, USDHC3);
967DEF_CLK_DIV1(usdhc4_div, &usdhc4_clk, CSCDR1, USDHC4);
968DEF_CLK_DIV1(vpu_div, &vpu_clk, CSCDR1, VPU_AXI);
969DEF_CLK_DIV1(hsi_tx_div, &hsi_tx_clk, CDCDR, HSI_TX);
970DEF_CLK_DIV1(ipu1_di0_pre_div, &ipu1_di0_pre_clk, CHSCCDR, IPU1_DI0_PRE);
971DEF_CLK_DIV1(ipu1_di1_pre_div, &ipu1_di1_pre_clk, CHSCCDR, IPU1_DI1_PRE);
972DEF_CLK_DIV1(ipu2_di0_pre_div, &ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE);
973DEF_CLK_DIV1(ipu2_di1_pre_div, &ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE);
974DEF_CLK_DIV1(ipu1_div, &ipu1_clk, CSCDR3, IPU1_HSP);
975DEF_CLK_DIV1(ipu2_div, &ipu2_clk, CSCDR3, IPU2_HSP);
976
977#define DEF_CLK_DIV2(d, c, r, b) \
978 static struct divider d = { \
979 .clk = c, \
980 .reg = r, \
981 .bp_pred = BP_##r##_##b##_PRED, \
982 .bm_pred = BM_##r##_##b##_PRED, \
983 .bp_podf = BP_##r##_##b##_PODF, \
984 .bm_podf = BM_##r##_##b##_PODF, \
985 }
986
987DEF_CLK_DIV2(ssi1_div, &ssi1_clk, CS1CDR, SSI1);
988DEF_CLK_DIV2(ssi3_div, &ssi3_clk, CS1CDR, SSI3);
989DEF_CLK_DIV2(esai_div, &esai_clk, CS1CDR, ESAI);
990DEF_CLK_DIV2(ssi2_div, &ssi2_clk, CS2CDR, SSI2);
991DEF_CLK_DIV2(enfc_div, &enfc_clk, CS2CDR, ENFC);
992DEF_CLK_DIV2(spdif_div, &spdif_clk, CDCDR, SPDIF);
993DEF_CLK_DIV2(asrc_serial_div, &asrc_serial_clk, CDCDR, ASRC_SERIAL);
994
995static struct divider *dividers[] = {
996 &arm_div,
997 &ipg_div,
998 &ahb_div,
999 &axi_div,
1000 &mmdc_ch0_axi_div,
1001 &mmdc_ch1_axi_div,
1002 &periph_clk2_div,
1003 &periph2_clk2_div,
1004 &gpu2d_core_div,
1005 &gpu3d_core_div,
1006 &gpu3d_shader_div,
1007 &ipg_perclk_div,
1008 &emi_div,
1009 &emi_slow_div,
1010 &can_div,
1011 &uart_div,
1012 &usdhc1_div,
1013 &usdhc2_div,
1014 &usdhc3_div,
1015 &usdhc4_div,
1016 &vpu_div,
1017 &hsi_tx_div,
1018 &ipu1_di0_pre_div,
1019 &ipu1_di1_pre_div,
1020 &ipu2_di0_pre_div,
1021 &ipu2_di1_pre_div,
1022 &ipu1_div,
1023 &ipu2_div,
1024 &ssi1_div,
1025 &ssi3_div,
1026 &esai_div,
1027 &ssi2_div,
1028 &enfc_div,
1029 &spdif_div,
1030 &asrc_serial_div,
1031};
1032
1033static unsigned long ldb_di_clk_get_rate(struct clk *clk)
1034{
1035 u32 val = readl_relaxed(CSCMR2);
1036
1037 val &= (clk == &ldb_di0_clk) ? BM_CSCMR2_LDB_DI0_IPU_DIV :
1038 BM_CSCMR2_LDB_DI1_IPU_DIV;
1039 if (val)
1040 return clk_get_rate(clk->parent) / 7;
1041 else
1042 return clk_get_rate(clk->parent) * 2 / 7;
1043}
1044
1045static int ldb_di_clk_set_rate(struct clk *clk, unsigned long rate)
1046{
1047 unsigned long parent_rate = clk_get_rate(clk->parent);
1048 u32 val = readl_relaxed(CSCMR2);
1049
1050 if (rate * 7 <= parent_rate + parent_rate / 20)
1051 val |= BM_CSCMR2_LDB_DI0_IPU_DIV;
1052 else
1053 val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV;
1054
1055 writel_relaxed(val, CSCMR2);
1056
1057 return 0;
1058}
1059
1060static unsigned long ldb_di_clk_round_rate(struct clk *clk, unsigned long rate)
1061{
1062 unsigned long parent_rate = clk_get_rate(clk->parent);
1063
1064 if (rate * 7 <= parent_rate + parent_rate / 20)
1065 return parent_rate / 7;
1066 else
1067 return 2 * parent_rate / 7;
1068}
1069
1070static unsigned long _clk_get_rate(struct clk *clk)
1071{
1072 struct divider *d;
1073 u32 val, pred, podf;
1074 int i, num;
1075
1076 if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
1077 return ldb_di_clk_get_rate(clk);
1078
1079 num = ARRAY_SIZE(dividers);
1080 for (i = 0; i < num; i++)
1081 if (dividers[i]->clk == clk) {
1082 d = dividers[i];
1083 break;
1084 }
1085 if (i == num)
1086 return clk_get_rate(clk->parent);
1087
1088 val = readl_relaxed(d->reg);
1089 pred = ((val & d->bm_pred) >> d->bp_pred) + 1;
1090 podf = ((val & d->bm_podf) >> d->bp_podf) + 1;
1091
1092 return clk_get_rate(clk->parent) / (pred * podf);
1093}
1094
1095static int clk_busy_wait(struct clk *clk)
1096{
1097 int timeout = 0x100000;
1098 u32 bm;
1099
1100 if (clk == &axi_clk)
1101 bm = BM_CDHIPR_AXI_PODF_BUSY;
1102 else if (clk == &ahb_clk)
1103 bm = BM_CDHIPR_AHB_PODF_BUSY;
1104 else if (clk == &mmdc_ch0_axi_clk)
1105 bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY;
1106 else if (clk == &periph_clk)
1107 bm = BM_CDHIPR_PERIPH_SEL_BUSY;
1108 else if (clk == &arm_clk)
1109 bm = BM_CDHIPR_ARM_PODF_BUSY;
1110 else
1111 return -EINVAL;
1112
1113 while ((readl_relaxed(CDHIPR) & bm) && --timeout)
1114 cpu_relax();
1115
1116 if (unlikely(!timeout))
1117 return -EBUSY;
1118
1119 return 0;
1120}
1121
1122static int _clk_set_rate(struct clk *clk, unsigned long rate)
1123{
1124 unsigned long parent_rate = clk_get_rate(clk->parent);
1125 struct divider *d;
1126 u32 val, div, max_div, pred = 0, podf;
1127 int i, num;
1128
1129 if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
1130 return ldb_di_clk_set_rate(clk, rate);
1131
1132 num = ARRAY_SIZE(dividers);
1133 for (i = 0; i < num; i++)
1134 if (dividers[i]->clk == clk) {
1135 d = dividers[i];
1136 break;
1137 }
1138 if (i == num)
1139 return -EINVAL;
1140
1141 max_div = ((d->bm_pred >> d->bp_pred) + 1) *
1142 ((d->bm_pred >> d->bp_pred) + 1);
1143
1144 div = parent_rate / rate;
1145 if (div == 0)
1146 div++;
1147
1148 if ((parent_rate / div != rate) || div > max_div)
1149 return -EINVAL;
1150
1151 if (d->bm_pred) {
1152 calc_pred_podf_dividers(div, &pred, &podf);
1153 } else {
1154 pred = 1;
1155 podf = div;
1156 }
1157
1158 val = readl_relaxed(d->reg);
1159 val &= ~(d->bm_pred | d->bm_podf);
1160 val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf;
1161 writel_relaxed(val, d->reg);
1162
1163 if (clk == &axi_clk || clk == &ahb_clk ||
1164 clk == &mmdc_ch0_axi_clk || clk == &arm_clk)
1165 return clk_busy_wait(clk);
1166
1167 return 0;
1168}
1169
1170static unsigned long _clk_round_rate(struct clk *clk, unsigned long rate)
1171{
1172 unsigned long parent_rate = clk_get_rate(clk->parent);
1173 u32 div = parent_rate / rate;
1174 u32 div_max, pred = 0, podf;
1175 struct divider *d;
1176 int i, num;
1177
1178 if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
1179 return ldb_di_clk_round_rate(clk, rate);
1180
1181 num = ARRAY_SIZE(dividers);
1182 for (i = 0; i < num; i++)
1183 if (dividers[i]->clk == clk) {
1184 d = dividers[i];
1185 break;
1186 }
1187 if (i == num)
1188 return -EINVAL;
1189
1190 if (div == 0 || parent_rate % rate)
1191 div++;
1192
1193 if (d->bm_pred) {
1194 calc_pred_podf_dividers(div, &pred, &podf);
1195 div = pred * podf;
1196 } else {
1197 div_max = (d->bm_podf >> d->bp_podf) + 1;
1198 if (div > div_max)
1199 div = div_max;
1200 }
1201
1202 return parent_rate / div;
1203}
1204
1205struct multiplexer {
1206 struct clk *clk;
1207 void __iomem *reg;
1208 u32 bp;
1209 u32 bm;
1210 int pnum;
1211 struct clk *parents[];
1212};
1213
1214static struct multiplexer axi_mux = {
1215 .clk = &axi_clk,
1216 .reg = CBCDR,
1217 .bp = BP_CBCDR_AXI_SEL,
1218 .bm = BM_CBCDR_AXI_SEL,
1219 .parents = {
1220 &periph_clk,
1221 &pll2_pfd_400m,
1222 &pll3_pfd_540m,
1223 NULL
1224 },
1225};
1226
1227static struct multiplexer periph_mux = {
1228 .clk = &periph_clk,
1229 .reg = CBCDR,
1230 .bp = BP_CBCDR_PERIPH_CLK_SEL,
1231 .bm = BM_CBCDR_PERIPH_CLK_SEL,
1232 .parents = {
1233 &periph_pre_clk,
1234 &periph_clk2_clk,
1235 NULL
1236 },
1237};
1238
1239static struct multiplexer periph_pre_mux = {
1240 .clk = &periph_pre_clk,
1241 .reg = CBCMR,
1242 .bp = BP_CBCMR_PRE_PERIPH_CLK_SEL,
1243 .bm = BM_CBCMR_PRE_PERIPH_CLK_SEL,
1244 .parents = {
1245 &pll2_bus,
1246 &pll2_pfd_400m,
1247 &pll2_pfd_352m,
1248 &pll2_200m,
1249 NULL
1250 },
1251};
1252
1253static struct multiplexer periph_clk2_mux = {
1254 .clk = &periph_clk2_clk,
1255 .reg = CBCMR,
1256 .bp = BP_CBCMR_PERIPH_CLK2_SEL,
1257 .bm = BM_CBCMR_PERIPH_CLK2_SEL,
1258 .parents = {
1259 &pll3_usb_otg,
1260 &osc_clk,
1261 NULL
1262 },
1263};
1264
1265static struct multiplexer periph2_mux = {
1266 .clk = &periph2_clk,
1267 .reg = CBCDR,
1268 .bp = BP_CBCDR_PERIPH2_CLK_SEL,
1269 .bm = BM_CBCDR_PERIPH2_CLK_SEL,
1270 .parents = {
1271 &periph2_pre_clk,
1272 &periph2_clk2_clk,
1273 NULL
1274 },
1275};
1276
1277static struct multiplexer periph2_pre_mux = {
1278 .clk = &periph2_pre_clk,
1279 .reg = CBCMR,
1280 .bp = BP_CBCMR_PRE_PERIPH2_CLK_SEL,
1281 .bm = BM_CBCMR_PRE_PERIPH2_CLK_SEL,
1282 .parents = {
1283 &pll2_bus,
1284 &pll2_pfd_400m,
1285 &pll2_pfd_352m,
1286 &pll2_200m,
1287 NULL
1288 },
1289};
1290
1291static struct multiplexer periph2_clk2_mux = {
1292 .clk = &periph2_clk2_clk,
1293 .reg = CBCMR,
1294 .bp = BP_CBCMR_PERIPH2_CLK2_SEL,
1295 .bm = BM_CBCMR_PERIPH2_CLK2_SEL,
1296 .parents = {
1297 &pll3_usb_otg,
1298 &osc_clk,
1299 NULL
1300 },
1301};
1302
1303static struct multiplexer gpu2d_axi_mux = {
1304 .clk = &gpu2d_axi_clk,
1305 .reg = CBCMR,
1306 .bp = BP_CBCMR_GPU2D_AXI_SEL,
1307 .bm = BM_CBCMR_GPU2D_AXI_SEL,
1308 .parents = {
1309 &axi_clk,
1310 &ahb_clk,
1311 NULL
1312 },
1313};
1314
1315static struct multiplexer gpu3d_axi_mux = {
1316 .clk = &gpu3d_axi_clk,
1317 .reg = CBCMR,
1318 .bp = BP_CBCMR_GPU3D_AXI_SEL,
1319 .bm = BM_CBCMR_GPU3D_AXI_SEL,
1320 .parents = {
1321 &axi_clk,
1322 &ahb_clk,
1323 NULL
1324 },
1325};
1326
1327static struct multiplexer gpu3d_core_mux = {
1328 .clk = &gpu3d_core_clk,
1329 .reg = CBCMR,
1330 .bp = BP_CBCMR_GPU3D_CORE_SEL,
1331 .bm = BM_CBCMR_GPU3D_CORE_SEL,
1332 .parents = {
1333 &mmdc_ch0_axi_clk,
1334 &pll3_usb_otg,
1335 &pll2_pfd_594m,
1336 &pll2_pfd_400m,
1337 NULL
1338 },
1339};
1340
1341static struct multiplexer gpu3d_shader_mux = {
1342 .clk = &gpu3d_shader_clk,
1343 .reg = CBCMR,
1344 .bp = BP_CBCMR_GPU3D_SHADER_SEL,
1345 .bm = BM_CBCMR_GPU3D_SHADER_SEL,
1346 .parents = {
1347 &mmdc_ch0_axi_clk,
1348 &pll3_usb_otg,
1349 &pll2_pfd_594m,
1350 &pll3_pfd_720m,
1351 NULL
1352 },
1353};
1354
1355static struct multiplexer pcie_axi_mux = {
1356 .clk = &pcie_clk,
1357 .reg = CBCMR,
1358 .bp = BP_CBCMR_PCIE_AXI_SEL,
1359 .bm = BM_CBCMR_PCIE_AXI_SEL,
1360 .parents = {
1361 &axi_clk,
1362 &ahb_clk,
1363 NULL
1364 },
1365};
1366
1367static struct multiplexer vdo_axi_mux = {
1368 .clk = &vdo_axi_clk,
1369 .reg = CBCMR,
1370 .bp = BP_CBCMR_VDO_AXI_SEL,
1371 .bm = BM_CBCMR_VDO_AXI_SEL,
1372 .parents = {
1373 &axi_clk,
1374 &ahb_clk,
1375 NULL
1376 },
1377};
1378
1379static struct multiplexer vpu_axi_mux = {
1380 .clk = &vpu_clk,
1381 .reg = CBCMR,
1382 .bp = BP_CBCMR_VPU_AXI_SEL,
1383 .bm = BM_CBCMR_VPU_AXI_SEL,
1384 .parents = {
1385 &axi_clk,
1386 &pll2_pfd_400m,
1387 &pll2_pfd_352m,
1388 NULL
1389 },
1390};
1391
1392static struct multiplexer gpu2d_core_mux = {
1393 .clk = &gpu2d_core_clk,
1394 .reg = CBCMR,
1395 .bp = BP_CBCMR_GPU2D_CORE_SEL,
1396 .bm = BM_CBCMR_GPU2D_CORE_SEL,
1397 .parents = {
1398 &axi_clk,
1399 &pll3_usb_otg,
1400 &pll2_pfd_352m,
1401 &pll2_pfd_400m,
1402 NULL
1403 },
1404};
1405
1406#define DEF_SSI_MUX(id) \
1407 static struct multiplexer ssi##id##_mux = { \
1408 .clk = &ssi##id##_clk, \
1409 .reg = CSCMR1, \
1410 .bp = BP_CSCMR1_SSI##id##_SEL, \
1411 .bm = BM_CSCMR1_SSI##id##_SEL, \
1412 .parents = { \
1413 &pll3_pfd_508m, \
1414 &pll3_pfd_454m, \
1415 &pll4_audio, \
1416 NULL \
1417 }, \
1418 }
1419
1420DEF_SSI_MUX(1);
1421DEF_SSI_MUX(2);
1422DEF_SSI_MUX(3);
1423
1424#define DEF_USDHC_MUX(id) \
1425 static struct multiplexer usdhc##id##_mux = { \
1426 .clk = &usdhc##id##_clk, \
1427 .reg = CSCMR1, \
1428 .bp = BP_CSCMR1_USDHC##id##_SEL, \
1429 .bm = BM_CSCMR1_USDHC##id##_SEL, \
1430 .parents = { \
1431 &pll2_pfd_400m, \
1432 &pll2_pfd_352m, \
1433 NULL \
1434 }, \
1435 }
1436
1437DEF_USDHC_MUX(1);
1438DEF_USDHC_MUX(2);
1439DEF_USDHC_MUX(3);
1440DEF_USDHC_MUX(4);
1441
1442static struct multiplexer emi_mux = {
1443 .clk = &emi_clk,
1444 .reg = CSCMR1,
1445 .bp = BP_CSCMR1_EMI_SEL,
1446 .bm = BM_CSCMR1_EMI_SEL,
1447 .parents = {
1448 &axi_clk,
1449 &pll3_usb_otg,
1450 &pll2_pfd_400m,
1451 &pll2_pfd_352m,
1452 NULL
1453 },
1454};
1455
1456static struct multiplexer emi_slow_mux = {
1457 .clk = &emi_slow_clk,
1458 .reg = CSCMR1,
1459 .bp = BP_CSCMR1_EMI_SLOW_SEL,
1460 .bm = BM_CSCMR1_EMI_SLOW_SEL,
1461 .parents = {
1462 &axi_clk,
1463 &pll3_usb_otg,
1464 &pll2_pfd_400m,
1465 &pll2_pfd_352m,
1466 NULL
1467 },
1468};
1469
1470static struct multiplexer esai_mux = {
1471 .clk = &esai_clk,
1472 .reg = CSCMR2,
1473 .bp = BP_CSCMR2_ESAI_SEL,
1474 .bm = BM_CSCMR2_ESAI_SEL,
1475 .parents = {
1476 &pll4_audio,
1477 &pll3_pfd_508m,
1478 &pll3_pfd_454m,
1479 &pll3_usb_otg,
1480 NULL
1481 },
1482};
1483
1484#define DEF_LDB_DI_MUX(id) \
1485 static struct multiplexer ldb_di##id##_mux = { \
1486 .clk = &ldb_di##id##_clk, \
1487 .reg = CS2CDR, \
1488 .bp = BP_CS2CDR_LDB_DI##id##_SEL, \
1489 .bm = BM_CS2CDR_LDB_DI##id##_SEL, \
1490 .parents = { \
1491 &pll5_video, \
1492 &pll2_pfd_352m, \
1493 &pll2_pfd_400m, \
1494 &pll3_pfd_540m, \
1495 &pll3_usb_otg, \
1496 NULL \
1497 }, \
1498 }
1499
1500DEF_LDB_DI_MUX(0);
1501DEF_LDB_DI_MUX(1);
1502
1503static struct multiplexer enfc_mux = {
1504 .clk = &enfc_clk,
1505 .reg = CS2CDR,
1506 .bp = BP_CS2CDR_ENFC_SEL,
1507 .bm = BM_CS2CDR_ENFC_SEL,
1508 .parents = {
1509 &pll2_pfd_352m,
1510 &pll2_bus,
1511 &pll3_usb_otg,
1512 &pll2_pfd_400m,
1513 NULL
1514 },
1515};
1516
1517static struct multiplexer spdif_mux = {
1518 .clk = &spdif_clk,
1519 .reg = CDCDR,
1520 .bp = BP_CDCDR_SPDIF_SEL,
1521 .bm = BM_CDCDR_SPDIF_SEL,
1522 .parents = {
1523 &pll4_audio,
1524 &pll3_pfd_508m,
1525 &pll3_pfd_454m,
1526 &pll3_usb_otg,
1527 NULL
1528 },
1529};
1530
1531static struct multiplexer asrc_serial_mux = {
1532 .clk = &asrc_serial_clk,
1533 .reg = CDCDR,
1534 .bp = BP_CDCDR_ASRC_SERIAL_SEL,
1535 .bm = BM_CDCDR_ASRC_SERIAL_SEL,
1536 .parents = {
1537 &pll4_audio,
1538 &pll3_pfd_508m,
1539 &pll3_pfd_454m,
1540 &pll3_usb_otg,
1541 NULL
1542 },
1543};
1544
1545static struct multiplexer hsi_tx_mux = {
1546 .clk = &hsi_tx_clk,
1547 .reg = CDCDR,
1548 .bp = BP_CDCDR_HSI_TX_SEL,
1549 .bm = BM_CDCDR_HSI_TX_SEL,
1550 .parents = {
1551 &pll3_120m,
1552 &pll2_pfd_400m,
1553 NULL
1554 },
1555};
1556
1557#define DEF_IPU_DI_PRE_MUX(r, i, d) \
1558 static struct multiplexer ipu##i##_di##d##_pre_mux = { \
1559 .clk = &ipu##i##_di##d##_pre_clk, \
1560 .reg = r, \
1561 .bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL, \
1562 .bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL, \
1563 .parents = { \
1564 &mmdc_ch0_axi_clk, \
1565 &pll3_usb_otg, \
1566 &pll5_video, \
1567 &pll2_pfd_352m, \
1568 &pll2_pfd_400m, \
1569 &pll3_pfd_540m, \
1570 NULL \
1571 }, \
1572 }
1573
1574DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 0);
1575DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 1);
1576DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 0);
1577DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 1);
1578
1579#define DEF_IPU_DI_MUX(r, i, d) \
1580 static struct multiplexer ipu##i##_di##d##_mux = { \
1581 .clk = &ipu##i##_di##d##_clk, \
1582 .reg = r, \
1583 .bp = BP_##r##_IPU##i##_DI##d##_SEL, \
1584 .bm = BM_##r##_IPU##i##_DI##d##_SEL, \
1585 .parents = { \
1586 &ipu##i##_di##d##_pre_clk, \
1587 &dummy_clk, \
1588 &dummy_clk, \
1589 &ldb_di0_clk, \
1590 &ldb_di1_clk, \
1591 NULL \
1592 }, \
1593 }
1594
1595DEF_IPU_DI_MUX(CHSCCDR, 1, 0);
1596DEF_IPU_DI_MUX(CHSCCDR, 1, 1);
1597DEF_IPU_DI_MUX(CSCDR2, 2, 0);
1598DEF_IPU_DI_MUX(CSCDR2, 2, 1);
1599
1600#define DEF_IPU_MUX(id) \
1601 static struct multiplexer ipu##id##_mux = { \
1602 .clk = &ipu##id##_clk, \
1603 .reg = CSCDR3, \
1604 .bp = BP_CSCDR3_IPU##id##_HSP_SEL, \
1605 .bm = BM_CSCDR3_IPU##id##_HSP_SEL, \
1606 .parents = { \
1607 &mmdc_ch0_axi_clk, \
1608 &pll2_pfd_400m, \
1609 &pll3_120m, \
1610 &pll3_pfd_540m, \
1611 NULL \
1612 }, \
1613 }
1614
1615DEF_IPU_MUX(1);
1616DEF_IPU_MUX(2);
1617
1618static struct multiplexer *multiplexers[] = {
1619 &axi_mux,
1620 &periph_mux,
1621 &periph_pre_mux,
1622 &periph_clk2_mux,
1623 &periph2_mux,
1624 &periph2_pre_mux,
1625 &periph2_clk2_mux,
1626 &gpu2d_axi_mux,
1627 &gpu3d_axi_mux,
1628 &gpu3d_core_mux,
1629 &gpu3d_shader_mux,
1630 &pcie_axi_mux,
1631 &vdo_axi_mux,
1632 &vpu_axi_mux,
1633 &gpu2d_core_mux,
1634 &ssi1_mux,
1635 &ssi2_mux,
1636 &ssi3_mux,
1637 &usdhc1_mux,
1638 &usdhc2_mux,
1639 &usdhc3_mux,
1640 &usdhc4_mux,
1641 &emi_mux,
1642 &emi_slow_mux,
1643 &esai_mux,
1644 &ldb_di0_mux,
1645 &ldb_di1_mux,
1646 &enfc_mux,
1647 &spdif_mux,
1648 &asrc_serial_mux,
1649 &hsi_tx_mux,
1650 &ipu1_di0_pre_mux,
1651 &ipu1_di0_mux,
1652 &ipu1_di1_pre_mux,
1653 &ipu1_di1_mux,
1654 &ipu2_di0_pre_mux,
1655 &ipu2_di0_mux,
1656 &ipu2_di1_pre_mux,
1657 &ipu2_di1_mux,
1658 &ipu1_mux,
1659 &ipu2_mux,
1660};
1661
1662static int _clk_set_parent(struct clk *clk, struct clk *parent)
1663{
1664 struct multiplexer *m;
1665 int i, num;
1666 u32 val;
1667
1668 num = ARRAY_SIZE(multiplexers);
1669 for (i = 0; i < num; i++)
1670 if (multiplexers[i]->clk == clk) {
1671 m = multiplexers[i];
1672 break;
1673 }
1674 if (i == num)
1675 return -EINVAL;
1676
1677 i = 0;
1678 while (m->parents[i]) {
1679 if (parent == m->parents[i])
1680 break;
1681 i++;
1682 }
1683 if (!m->parents[i])
1684 return -EINVAL;
1685
1686 val = readl_relaxed(m->reg);
1687 val &= ~m->bm;
1688 val |= i << m->bp;
1689 writel_relaxed(val, m->reg);
1690
1691 if (clk == &periph_clk)
1692 return clk_busy_wait(clk);
1693
1694 return 0;
1695}
1696
1697#define DEF_NG_CLK(name, p) \
1698 static struct clk name = { \
1699 .get_rate = _clk_get_rate, \
1700 .set_rate = _clk_set_rate, \
1701 .round_rate = _clk_round_rate, \
1702 .set_parent = _clk_set_parent, \
1703 .parent = p, \
1704 }
1705
1706DEF_NG_CLK(periph_clk2_clk, &osc_clk);
1707DEF_NG_CLK(periph_pre_clk, &pll2_bus);
1708DEF_NG_CLK(periph_clk, &periph_pre_clk);
1709DEF_NG_CLK(periph2_clk2_clk, &osc_clk);
1710DEF_NG_CLK(periph2_pre_clk, &pll2_bus);
1711DEF_NG_CLK(periph2_clk, &periph2_pre_clk);
1712DEF_NG_CLK(axi_clk, &periph_clk);
1713DEF_NG_CLK(emi_clk, &axi_clk);
1714DEF_NG_CLK(arm_clk, &pll1_sw_clk);
1715DEF_NG_CLK(ahb_clk, &periph_clk);
1716DEF_NG_CLK(ipg_clk, &ahb_clk);
1717DEF_NG_CLK(ipg_perclk, &ipg_clk);
1718DEF_NG_CLK(ipu1_di0_pre_clk, &pll3_pfd_540m);
1719DEF_NG_CLK(ipu1_di1_pre_clk, &pll3_pfd_540m);
1720DEF_NG_CLK(ipu2_di0_pre_clk, &pll3_pfd_540m);
1721DEF_NG_CLK(ipu2_di1_pre_clk, &pll3_pfd_540m);
1722DEF_NG_CLK(asrc_serial_clk, &pll3_usb_otg);
1723
1724#define DEF_CLK(name, er, es, p, s) \
1725 static struct clk name = { \
1726 .enable_reg = er, \
1727 .enable_shift = es, \
1728 .enable = _clk_enable, \
1729 .disable = _clk_disable, \
1730 .get_rate = _clk_get_rate, \
1731 .set_rate = _clk_set_rate, \
1732 .round_rate = _clk_round_rate, \
1733 .set_parent = _clk_set_parent, \
1734 .parent = p, \
1735 .secondary = s, \
1736 }
1737
1738DEF_CLK(aips_tz1_clk, CCGR0, CG0, &ahb_clk, NULL);
1739DEF_CLK(aips_tz2_clk, CCGR0, CG1, &ahb_clk, NULL);
1740DEF_CLK(apbh_dma_clk, CCGR0, CG2, &ahb_clk, NULL);
1741DEF_CLK(asrc_clk, CCGR0, CG3, &pll4_audio, NULL);
1742DEF_CLK(can1_serial_clk, CCGR0, CG8, &pll3_usb_otg, NULL);
1743DEF_CLK(can1_clk, CCGR0, CG7, &pll3_usb_otg, &can1_serial_clk);
1744DEF_CLK(can2_serial_clk, CCGR0, CG10, &pll3_usb_otg, NULL);
1745DEF_CLK(can2_clk, CCGR0, CG9, &pll3_usb_otg, &can2_serial_clk);
1746DEF_CLK(ecspi1_clk, CCGR1, CG0, &pll3_60m, NULL);
1747DEF_CLK(ecspi2_clk, CCGR1, CG1, &pll3_60m, NULL);
1748DEF_CLK(ecspi3_clk, CCGR1, CG2, &pll3_60m, NULL);
1749DEF_CLK(ecspi4_clk, CCGR1, CG3, &pll3_60m, NULL);
1750DEF_CLK(ecspi5_clk, CCGR1, CG4, &pll3_60m, NULL);
1751DEF_CLK(enet_clk, CCGR1, CG5, &ipg_clk, NULL);
1752DEF_CLK(esai_clk, CCGR1, CG8, &pll3_usb_otg, NULL);
1753DEF_CLK(gpt_serial_clk, CCGR1, CG11, &ipg_perclk, NULL);
1754DEF_CLK(gpt_clk, CCGR1, CG10, &ipg_perclk, &gpt_serial_clk);
1755DEF_CLK(gpu2d_core_clk, CCGR1, CG12, &pll2_pfd_352m, &gpu2d_axi_clk);
1756DEF_CLK(gpu3d_core_clk, CCGR1, CG13, &pll2_pfd_594m, &gpu3d_axi_clk);
1757DEF_CLK(gpu3d_shader_clk, CCGR1, CG13, &pll3_pfd_720m, &gpu3d_axi_clk);
1758DEF_CLK(hdmi_iahb_clk, CCGR2, CG0, &ahb_clk, NULL);
1759DEF_CLK(hdmi_isfr_clk, CCGR2, CG2, &pll3_pfd_540m, &hdmi_iahb_clk);
1760DEF_CLK(i2c1_clk, CCGR2, CG3, &ipg_perclk, NULL);
1761DEF_CLK(i2c2_clk, CCGR2, CG4, &ipg_perclk, NULL);
1762DEF_CLK(i2c3_clk, CCGR2, CG5, &ipg_perclk, NULL);
1763DEF_CLK(iim_clk, CCGR2, CG6, &ipg_clk, NULL);
1764DEF_CLK(enfc_clk, CCGR2, CG7, &pll2_pfd_352m, NULL);
1765DEF_CLK(ipu1_clk, CCGR3, CG0, &mmdc_ch0_axi_clk, NULL);
1766DEF_CLK(ipu1_di0_clk, CCGR3, CG1, &ipu1_di0_pre_clk, NULL);
1767DEF_CLK(ipu1_di1_clk, CCGR3, CG2, &ipu1_di1_pre_clk, NULL);
1768DEF_CLK(ipu2_clk, CCGR3, CG3, &mmdc_ch0_axi_clk, NULL);
1769DEF_CLK(ipu2_di0_clk, CCGR3, CG4, &ipu2_di0_pre_clk, NULL);
1770DEF_CLK(ipu2_di1_clk, CCGR3, CG5, &ipu2_di1_pre_clk, NULL);
1771DEF_CLK(ldb_di0_clk, CCGR3, CG6, &pll3_pfd_540m, NULL);
1772DEF_CLK(ldb_di1_clk, CCGR3, CG7, &pll3_pfd_540m, NULL);
1773DEF_CLK(hsi_tx_clk, CCGR3, CG8, &pll2_pfd_400m, NULL);
1774DEF_CLK(mlb_clk, CCGR3, CG9, &pll6_mlb, NULL);
1775DEF_CLK(mmdc_ch0_ipg_clk, CCGR3, CG12, &ipg_clk, NULL);
1776DEF_CLK(mmdc_ch0_axi_clk, CCGR3, CG10, &periph_clk, &mmdc_ch0_ipg_clk);
1777DEF_CLK(mmdc_ch1_ipg_clk, CCGR3, CG13, &ipg_clk, NULL);
1778DEF_CLK(mmdc_ch1_axi_clk, CCGR3, CG11, &periph2_clk, &mmdc_ch1_ipg_clk);
1779DEF_CLK(openvg_axi_clk, CCGR3, CG13, &axi_clk, NULL);
1780DEF_CLK(pwm1_clk, CCGR4, CG8, &ipg_perclk, NULL);
1781DEF_CLK(pwm2_clk, CCGR4, CG9, &ipg_perclk, NULL);
1782DEF_CLK(pwm3_clk, CCGR4, CG10, &ipg_perclk, NULL);
1783DEF_CLK(pwm4_clk, CCGR4, CG11, &ipg_perclk, NULL);
1784DEF_CLK(gpmi_bch_apb_clk, CCGR4, CG12, &usdhc3_clk, NULL);
1785DEF_CLK(gpmi_bch_clk, CCGR4, CG13, &usdhc4_clk, &gpmi_bch_apb_clk);
1786DEF_CLK(gpmi_apb_clk, CCGR4, CG15, &usdhc3_clk, &gpmi_bch_clk);
1787DEF_CLK(gpmi_io_clk, CCGR4, CG14, &enfc_clk, &gpmi_apb_clk);
1788DEF_CLK(sdma_clk, CCGR5, CG3, &ahb_clk, NULL);
1789DEF_CLK(spba_clk, CCGR5, CG6, &ipg_clk, NULL);
1790DEF_CLK(spdif_clk, CCGR5, CG7, &pll3_usb_otg, &spba_clk);
1791DEF_CLK(ssi1_clk, CCGR5, CG9, &pll3_pfd_508m, NULL);
1792DEF_CLK(ssi2_clk, CCGR5, CG10, &pll3_pfd_508m, NULL);
1793DEF_CLK(ssi3_clk, CCGR5, CG11, &pll3_pfd_508m, NULL);
1794DEF_CLK(uart_serial_clk, CCGR5, CG13, &pll3_usb_otg, NULL);
1795DEF_CLK(uart_clk, CCGR5, CG12, &pll3_80m, &uart_serial_clk);
1796DEF_CLK(usboh3_clk, CCGR6, CG0, &ipg_clk, NULL);
1797DEF_CLK(usdhc1_clk, CCGR6, CG1, &pll2_pfd_400m, NULL);
1798DEF_CLK(usdhc2_clk, CCGR6, CG2, &pll2_pfd_400m, NULL);
1799DEF_CLK(usdhc3_clk, CCGR6, CG3, &pll2_pfd_400m, NULL);
1800DEF_CLK(usdhc4_clk, CCGR6, CG4, &pll2_pfd_400m, NULL);
1801DEF_CLK(emi_slow_clk, CCGR6, CG5, &axi_clk, NULL);
1802DEF_CLK(vdo_axi_clk, CCGR6, CG6, &axi_clk, NULL);
1803DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, NULL);
1804
1805static int pcie_clk_enable(struct clk *clk)
1806{
1807 u32 val;
1808
1809 val = readl_relaxed(PLL8_ENET);
1810 val |= BM_PLL_ENET_EN_PCIE;
1811 writel_relaxed(val, PLL8_ENET);
1812
1813 return _clk_enable(clk);
1814}
1815
1816static void pcie_clk_disable(struct clk *clk)
1817{
1818 u32 val;
1819
1820 _clk_disable(clk);
1821
1822 val = readl_relaxed(PLL8_ENET);
1823 val &= BM_PLL_ENET_EN_PCIE;
1824 writel_relaxed(val, PLL8_ENET);
1825}
1826
1827static struct clk pcie_clk = {
1828 .enable_reg = CCGR4,
1829 .enable_shift = CG0,
1830 .enable = pcie_clk_enable,
1831 .disable = pcie_clk_disable,
1832 .set_parent = _clk_set_parent,
1833 .parent = &axi_clk,
1834 .secondary = &pll8_enet,
1835};
1836
1837static int sata_clk_enable(struct clk *clk)
1838{
1839 u32 val;
1840
1841 val = readl_relaxed(PLL8_ENET);
1842 val |= BM_PLL_ENET_EN_SATA;
1843 writel_relaxed(val, PLL8_ENET);
1844
1845 return _clk_enable(clk);
1846}
1847
1848static void sata_clk_disable(struct clk *clk)
1849{
1850 u32 val;
1851
1852 _clk_disable(clk);
1853
1854 val = readl_relaxed(PLL8_ENET);
1855 val &= BM_PLL_ENET_EN_SATA;
1856 writel_relaxed(val, PLL8_ENET);
1857}
1858
1859static struct clk sata_clk = {
1860 .enable_reg = CCGR5,
1861 .enable_shift = CG2,
1862 .enable = sata_clk_enable,
1863 .disable = sata_clk_disable,
1864 .parent = &ipg_clk,
1865 .secondary = &pll8_enet,
1866};
1867
1868#define _REGISTER_CLOCK(d, n, c) \
1869 { \
1870 .dev_id = d, \
1871 .con_id = n, \
1872 .clk = &c, \
1873 }
1874
1875static struct clk_lookup lookups[] = {
1876 _REGISTER_CLOCK("2020000.uart", NULL, uart_clk),
1877 _REGISTER_CLOCK("21e8000.uart", NULL, uart_clk),
1878 _REGISTER_CLOCK("21ec000.uart", NULL, uart_clk),
1879 _REGISTER_CLOCK("21f0000.uart", NULL, uart_clk),
1880 _REGISTER_CLOCK("21f4000.uart", NULL, uart_clk),
1881 _REGISTER_CLOCK("2188000.enet", NULL, enet_clk),
1882 _REGISTER_CLOCK("2190000.usdhc", NULL, usdhc1_clk),
1883 _REGISTER_CLOCK("2194000.usdhc", NULL, usdhc2_clk),
1884 _REGISTER_CLOCK("2198000.usdhc", NULL, usdhc3_clk),
1885 _REGISTER_CLOCK("219c000.usdhc", NULL, usdhc4_clk),
1886 _REGISTER_CLOCK("21a0000.i2c", NULL, i2c1_clk),
1887 _REGISTER_CLOCK("21a4000.i2c", NULL, i2c2_clk),
1888 _REGISTER_CLOCK("21a8000.i2c", NULL, i2c3_clk),
1889 _REGISTER_CLOCK("2008000.ecspi", NULL, ecspi1_clk),
1890 _REGISTER_CLOCK("200c000.ecspi", NULL, ecspi2_clk),
1891 _REGISTER_CLOCK("2010000.ecspi", NULL, ecspi3_clk),
1892 _REGISTER_CLOCK("2014000.ecspi", NULL, ecspi4_clk),
1893 _REGISTER_CLOCK("2018000.ecspi", NULL, ecspi5_clk),
1894 _REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
1895 _REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
1896 _REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
1897 _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
1898 _REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
1899 _REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
1900 _REGISTER_CLOCK(NULL, "aips_tz2_clk", aips_tz2_clk),
1901 _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk),
1902 _REGISTER_CLOCK(NULL, "can2_clk", can2_clk),
1903 _REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_isfr_clk),
1904 _REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
1905 _REGISTER_CLOCK(NULL, "mlb_clk", mlb_clk),
1906 _REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
1907 _REGISTER_CLOCK(NULL, "pwm1_clk", pwm1_clk),
1908 _REGISTER_CLOCK(NULL, "pwm2_clk", pwm2_clk),
1909 _REGISTER_CLOCK(NULL, "pwm3_clk", pwm3_clk),
1910 _REGISTER_CLOCK(NULL, "pwm4_clk", pwm4_clk),
1911 _REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
1912 _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
1913 _REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
1914};
1915
1916int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
1917{
1918 u32 val = readl_relaxed(CLPCR);
1919
1920 val &= ~BM_CLPCR_LPM;
1921 switch (mode) {
1922 case WAIT_CLOCKED:
1923 break;
1924 case WAIT_UNCLOCKED:
1925 val |= 0x1 << BP_CLPCR_LPM;
1926 break;
1927 case STOP_POWER_ON:
1928 val |= 0x2 << BP_CLPCR_LPM;
1929 break;
1930 case WAIT_UNCLOCKED_POWER_OFF:
1931 val |= 0x1 << BP_CLPCR_LPM;
1932 val &= ~BM_CLPCR_VSTBY;
1933 val &= ~BM_CLPCR_SBYOS;
1934 val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
1935 break;
1936 case STOP_POWER_OFF:
1937 val |= 0x2 << BP_CLPCR_LPM;
1938 val |= 0x3 << BP_CLPCR_STBY_COUNT;
1939 val |= BM_CLPCR_VSTBY;
1940 val |= BM_CLPCR_SBYOS;
1941 val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
1942 break;
1943 default:
1944 return -EINVAL;
1945 }
1946 writel_relaxed(val, CLPCR);
1947
1948 return 0;
1949}
1950
1951static struct map_desc imx6q_clock_desc[] = {
1952 imx_map_entry(MX6Q, CCM, MT_DEVICE),
1953 imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
1954};
1955
1956int __init mx6q_clocks_init(void)
1957{
1958 struct device_node *np;
1959 void __iomem *base;
1960 int i, irq;
1961
1962 iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
1963
1964 /* retrieve the freqency of fixed clocks from device tree */
1965 for_each_compatible_node(np, NULL, "fixed-clock") {
1966 u32 rate;
1967 if (of_property_read_u32(np, "clock-frequency", &rate))
1968 continue;
1969
1970 if (of_device_is_compatible(np, "fsl,imx-ckil"))
1971 external_low_reference = rate;
1972 else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
1973 external_high_reference = rate;
1974 else if (of_device_is_compatible(np, "fsl,imx-osc"))
1975 oscillator_reference = rate;
1976 }
1977
1978 for (i = 0; i < ARRAY_SIZE(lookups); i++)
1979 clkdev_add(&lookups[i]);
1980
1981 /* only keep necessary clocks on */
1982 writel_relaxed(0x3 << CG0 | 0x3 << CG1 | 0x3 << CG2, CCGR0);
1983 writel_relaxed(0x3 << CG8 | 0x3 << CG9 | 0x3 << CG10, CCGR2);
1984 writel_relaxed(0x3 << CG10 | 0x3 << CG12, CCGR3);
1985 writel_relaxed(0x3 << CG4 | 0x3 << CG6 | 0x3 << CG7, CCGR4);
1986 writel_relaxed(0x3 << CG0, CCGR5);
1987 writel_relaxed(0, CCGR6);
1988 writel_relaxed(0, CCGR7);
1989
1990 clk_enable(&uart_clk);
1991 clk_enable(&mmdc_ch0_axi_clk);
1992
1993 clk_set_rate(&pll4_audio, FREQ_650M);
1994 clk_set_rate(&pll5_video, FREQ_650M);
1995 clk_set_parent(&ipu1_di0_clk, &ipu1_di0_pre_clk);
1996 clk_set_parent(&ipu1_di0_pre_clk, &pll5_video);
1997 clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594m);
1998 clk_set_rate(&gpu3d_shader_clk, FREQ_594M);
1999 clk_set_parent(&gpu3d_core_clk, &mmdc_ch0_axi_clk);
2000 clk_set_rate(&gpu3d_core_clk, FREQ_528M);
2001 clk_set_parent(&asrc_serial_clk, &pll3_usb_otg);
2002 clk_set_rate(&asrc_serial_clk, 1500000);
2003 clk_set_rate(&enfc_clk, 11000000);
2004
2005 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
2006 base = of_iomap(np, 0);
2007 WARN_ON(!base);
2008 irq = irq_of_parse_and_map(np, 0);
2009 mxc_timer_init(&gpt_clk, base, irq);
2010
2011 return 0;
2012}
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
new file mode 100644
index 00000000000..e1537f9e45b
--- /dev/null
+++ b/arch/arm/mach-imx/gpc.c
@@ -0,0 +1,113 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/io.h>
14#include <linux/irq.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <linux/of_irq.h>
18#include <asm/hardware/gic.h>
19
20#define GPC_IMR1 0x008
21#define GPC_PGC_CPU_PDN 0x2a0
22
23#define IMR_NUM 4
24
25static void __iomem *gpc_base;
26static u32 gpc_wake_irqs[IMR_NUM];
27static u32 gpc_saved_imrs[IMR_NUM];
28
29void imx_gpc_pre_suspend(void)
30{
31 void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
32 int i;
33
34 /* Tell GPC to power off ARM core when suspend */
35 writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
36
37 for (i = 0; i < IMR_NUM; i++) {
38 gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
39 writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
40 }
41}
42
43void imx_gpc_post_resume(void)
44{
45 void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
46 int i;
47
48 /* Keep ARM core powered on for other low-power modes */
49 writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
50
51 for (i = 0; i < IMR_NUM; i++)
52 writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
53}
54
55static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
56{
57 unsigned int idx = d->irq / 32 - 1;
58 u32 mask;
59
60 /* Sanity check for SPI irq */
61 if (d->irq < 32)
62 return -EINVAL;
63
64 mask = 1 << d->irq % 32;
65 gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
66 gpc_wake_irqs[idx] & ~mask;
67
68 return 0;
69}
70
71static void imx_gpc_irq_unmask(struct irq_data *d)
72{
73 void __iomem *reg;
74 u32 val;
75
76 /* Sanity check for SPI irq */
77 if (d->irq < 32)
78 return;
79
80 reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
81 val = readl_relaxed(reg);
82 val &= ~(1 << d->irq % 32);
83 writel_relaxed(val, reg);
84}
85
86static void imx_gpc_irq_mask(struct irq_data *d)
87{
88 void __iomem *reg;
89 u32 val;
90
91 /* Sanity check for SPI irq */
92 if (d->irq < 32)
93 return;
94
95 reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
96 val = readl_relaxed(reg);
97 val |= 1 << (d->irq % 32);
98 writel_relaxed(val, reg);
99}
100
101void __init imx_gpc_init(void)
102{
103 struct device_node *np;
104
105 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
106 gpc_base = of_iomap(np, 0);
107 WARN_ON(!gpc_base);
108
109 /* Register GPC as the secondary interrupt controller behind GIC */
110 gic_arch_extn.irq_mask = imx_gpc_irq_mask;
111 gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
112 gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
113}
diff --git a/arch/arm/mach-imx/head-v7.S b/arch/arm/mach-imx/head-v7.S
new file mode 100644
index 00000000000..6229efbc70c
--- /dev/null
+++ b/arch/arm/mach-imx/head-v7.S
@@ -0,0 +1,99 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/linkage.h>
14#include <linux/init.h>
15#include <asm/asm-offsets.h>
16#include <asm/hardware/cache-l2x0.h>
17
18 .section ".text.head", "ax"
19 __CPUINIT
20
21/*
22 * The secondary kernel init calls v7_flush_dcache_all before it enables
23 * the L1; however, the L1 comes out of reset in an undefined state, so
24 * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
25 * of cache lines with uninitialized data and uninitialized tags to get
26 * written out to memory, which does really unpleasant things to the main
27 * processor. We fix this by performing an invalidate, rather than a
28 * clean + invalidate, before jumping into the kernel.
29 *
30 * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
31 * to be called for both secondary cores startup and primary core resume
32 * procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S.
33 */
34ENTRY(v7_invalidate_l1)
35 mov r0, #0
36 mcr p15, 2, r0, c0, c0, 0
37 mrc p15, 1, r0, c0, c0, 0
38
39 ldr r1, =0x7fff
40 and r2, r1, r0, lsr #13
41
42 ldr r1, =0x3ff
43
44 and r3, r1, r0, lsr #3 @ NumWays - 1
45 add r2, r2, #1 @ NumSets
46
47 and r0, r0, #0x7
48 add r0, r0, #4 @ SetShift
49
50 clz r1, r3 @ WayShift
51 add r4, r3, #1 @ NumWays
521: sub r2, r2, #1 @ NumSets--
53 mov r3, r4 @ Temp = NumWays
542: subs r3, r3, #1 @ Temp--
55 mov r5, r3, lsl r1
56 mov r6, r2, lsl r0
57 orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
58 mcr p15, 0, r5, c7, c6, 2
59 bgt 2b
60 cmp r2, #0
61 bgt 1b
62 dsb
63 isb
64 mov pc, lr
65ENDPROC(v7_invalidate_l1)
66
67#ifdef CONFIG_SMP
68ENTRY(v7_secondary_startup)
69 bl v7_invalidate_l1
70 b secondary_startup
71ENDPROC(v7_secondary_startup)
72#endif
73
74/*
75 * The following code is located into the .data section. This is to
76 * allow phys_l2x0_saved_regs to be accessed with a relative load
77 * as we are running on physical address here.
78 */
79 .data
80 .align
81
82 .macro pl310_resume
83 ldr r2, phys_l2x0_saved_regs
84 ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0
85 ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value
86 str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl
87 mov r1, #0x1
88 str r1, [r0, #L2X0_CTRL] @ re-enable L2
89 .endm
90
91ENTRY(v7_cpu_resume)
92 bl v7_invalidate_l1
93 pl310_resume
94 b cpu_resume
95ENDPROC(v7_cpu_resume)
96
97 .globl phys_l2x0_saved_regs
98phys_l2x0_saved_regs:
99 .long 0
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
new file mode 100644
index 00000000000..89493abd497
--- /dev/null
+++ b/arch/arm/mach-imx/hotplug.c
@@ -0,0 +1,44 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/errno.h>
14#include <asm/cacheflush.h>
15#include <mach/common.h>
16
17int platform_cpu_kill(unsigned int cpu)
18{
19 return 1;
20}
21
22/*
23 * platform-specific code to shutdown a CPU
24 *
25 * Called with IRQs disabled
26 */
27void platform_cpu_die(unsigned int cpu)
28{
29 flush_cache_all();
30 imx_enable_cpu(cpu, false);
31 cpu_do_idle();
32
33 /* We should never return from idle */
34 panic("cpu %d unexpectedly exit from shutdown\n", cpu);
35}
36
37int platform_cpu_disable(unsigned int cpu)
38{
39 /*
40 * we don't allow CPU 0 to be shutdown (it is still too special
41 * e.g. clock tick interrupts)
42 */
43 return cpu == 0 ? -EPERM : 0;
44}
diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c
new file mode 100644
index 00000000000..d4ab6f29a76
--- /dev/null
+++ b/arch/arm/mach-imx/lluart.c
@@ -0,0 +1,32 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <asm/page.h>
15#include <asm/sizes.h>
16#include <asm/mach/map.h>
17#include <mach/hardware.h>
18
19static struct map_desc imx_lluart_desc = {
20#ifdef CONFIG_DEBUG_IMX6Q_UART
21 .virtual = MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
22 .pfn = __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
23 .length = MX6Q_UART4_SIZE,
24 .type = MT_DEVICE,
25#endif
26};
27
28void __init imx_lluart_map_io(void)
29{
30 if (imx_lluart_desc.virtual)
31 iotable_init(&imx_lluart_desc, 1);
32}
diff --git a/arch/arm/mach-imx/localtimer.c b/arch/arm/mach-imx/localtimer.c
new file mode 100644
index 00000000000..3a163515d41
--- /dev/null
+++ b/arch/arm/mach-imx/localtimer.c
@@ -0,0 +1,35 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/clockchips.h>
15#include <linux/of_address.h>
16#include <linux/of_irq.h>
17#include <asm/smp_twd.h>
18
19/*
20 * Setup the local clock events for a CPU.
21 */
22int __cpuinit local_timer_setup(struct clock_event_device *evt)
23{
24 struct device_node *np;
25
26 np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
27 if (!twd_base) {
28 twd_base = of_iomap(np, 0);
29 WARN_ON(!twd_base);
30 }
31 evt->irq = irq_of_parse_and_map(np, 0);
32 twd_timer_setup(evt);
33
34 return 0;
35}
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
new file mode 100644
index 00000000000..8bf5fa34948
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -0,0 +1,84 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/irq.h>
15#include <linux/irqdomain.h>
16#include <linux/of.h>
17#include <linux/of_irq.h>
18#include <linux/of_platform.h>
19#include <asm/hardware/cache-l2x0.h>
20#include <asm/hardware/gic.h>
21#include <asm/mach/arch.h>
22#include <asm/mach/time.h>
23#include <mach/common.h>
24#include <mach/hardware.h>
25
26static void __init imx6q_init_machine(void)
27{
28 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
29
30 imx6q_pm_init();
31}
32
33static void __init imx6q_map_io(void)
34{
35 imx_lluart_map_io();
36 imx_scu_map_io();
37}
38
39static void __init imx6q_gpio_add_irq_domain(struct device_node *np,
40 struct device_node *interrupt_parent)
41{
42 static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS -
43 32 * 7; /* imx6q gets 7 gpio ports */
44
45 irq_domain_add_simple(np, gpio_irq_base);
46 gpio_irq_base += 32;
47}
48
49static const struct of_device_id imx6q_irq_match[] __initconst = {
50 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
51 { .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
52 { /* sentinel */ }
53};
54
55static void __init imx6q_init_irq(void)
56{
57 l2x0_of_init(0, ~0UL);
58 imx_src_init();
59 imx_gpc_init();
60 of_irq_init(imx6q_irq_match);
61}
62
63static void __init imx6q_timer_init(void)
64{
65 mx6q_clocks_init();
66}
67
68static struct sys_timer imx6q_timer = {
69 .init = imx6q_timer_init,
70};
71
72static const char *imx6q_dt_compat[] __initdata = {
73 "fsl,imx6q-sabreauto",
74 NULL,
75};
76
77DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
78 .map_io = imx6q_map_io,
79 .init_irq = imx6q_init_irq,
80 .handle_irq = imx6q_handle_irq,
81 .timer = &imx6q_timer,
82 .init_machine = imx6q_init_machine,
83 .dt_compat = imx6q_dt_compat,
84MACHINE_END
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
new file mode 100644
index 00000000000..c461e98496c
--- /dev/null
+++ b/arch/arm/mach-imx/mmdc.c
@@ -0,0 +1,72 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_address.h>
18#include <linux/of_device.h>
19
20#define MMDC_MAPSR 0x404
21#define BP_MMDC_MAPSR_PSD 0
22#define BP_MMDC_MAPSR_PSS 4
23
24static int __devinit imx_mmdc_probe(struct platform_device *pdev)
25{
26 struct device_node *np = pdev->dev.of_node;
27 void __iomem *mmdc_base, *reg;
28 u32 val;
29 int timeout = 0x400;
30
31 mmdc_base = of_iomap(np, 0);
32 WARN_ON(!mmdc_base);
33
34 reg = mmdc_base + MMDC_MAPSR;
35
36 /* Enable automatic power saving */
37 val = readl_relaxed(reg);
38 val &= ~(1 << BP_MMDC_MAPSR_PSD);
39 writel_relaxed(val, reg);
40
41 /* Ensure it's successfully enabled */
42 while (!(readl_relaxed(reg) & 1 << BP_MMDC_MAPSR_PSS) && --timeout)
43 cpu_relax();
44
45 if (unlikely(!timeout)) {
46 pr_warn("%s: failed to enable automatic power saving\n",
47 __func__);
48 return -EBUSY;
49 }
50
51 return 0;
52}
53
54static struct of_device_id imx_mmdc_dt_ids[] = {
55 { .compatible = "fsl,imx6q-mmdc", },
56 { /* sentinel */ }
57};
58
59static struct platform_driver imx_mmdc_driver = {
60 .driver = {
61 .name = "imx-mmdc",
62 .owner = THIS_MODULE,
63 .of_match_table = imx_mmdc_dt_ids,
64 },
65 .probe = imx_mmdc_probe,
66};
67
68static int __init imx_mmdc_init(void)
69{
70 return platform_driver_register(&imx_mmdc_driver);
71}
72postcore_initcall(imx_mmdc_init);
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
new file mode 100644
index 00000000000..ab98c6fec9e
--- /dev/null
+++ b/arch/arm/mach-imx/platsmp.c
@@ -0,0 +1,85 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/smp.h>
15#include <asm/page.h>
16#include <asm/smp_scu.h>
17#include <asm/hardware/gic.h>
18#include <asm/mach/map.h>
19#include <mach/common.h>
20#include <mach/hardware.h>
21
22static void __iomem *scu_base;
23
24static struct map_desc scu_io_desc __initdata = {
25 /* .virtual and .pfn are run-time assigned */
26 .length = SZ_4K,
27 .type = MT_DEVICE,
28};
29
30void __init imx_scu_map_io(void)
31{
32 unsigned long base;
33
34 /* Get SCU base */
35 asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
36
37 scu_io_desc.virtual = IMX_IO_P2V(base);
38 scu_io_desc.pfn = __phys_to_pfn(base);
39 iotable_init(&scu_io_desc, 1);
40
41 scu_base = IMX_IO_ADDRESS(base);
42}
43
44void __cpuinit platform_secondary_init(unsigned int cpu)
45{
46 /*
47 * if any interrupts are already enabled for the primary
48 * core (e.g. timer irq), then they will not have been enabled
49 * for us: do so
50 */
51 gic_secondary_init(0);
52}
53
54int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
55{
56 imx_set_cpu_jump(cpu, v7_secondary_startup);
57 imx_enable_cpu(cpu, true);
58 return 0;
59}
60
61/*
62 * Initialise the CPU possible map early - this describes the CPUs
63 * which may be present or become present in the system.
64 */
65void __init smp_init_cpus(void)
66{
67 int i, ncores;
68
69 ncores = scu_get_core_count(scu_base);
70
71 for (i = 0; i < ncores; i++)
72 set_cpu_possible(i, true);
73
74 set_smp_cross_call(gic_raise_softirq);
75}
76
77void imx_smp_prepare(void)
78{
79 scu_enable(scu_base);
80}
81
82void __init platform_smp_prepare_cpus(unsigned int max_cpus)
83{
84 imx_smp_prepare();
85}
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
new file mode 100644
index 00000000000..f20f191d7cc
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -0,0 +1,70 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/of.h>
16#include <linux/suspend.h>
17#include <asm/cacheflush.h>
18#include <asm/proc-fns.h>
19#include <asm/suspend.h>
20#include <asm/hardware/cache-l2x0.h>
21#include <mach/common.h>
22#include <mach/hardware.h>
23
24extern unsigned long phys_l2x0_saved_regs;
25
26static int imx6q_suspend_finish(unsigned long val)
27{
28 cpu_do_idle();
29 return 0;
30}
31
32static int imx6q_pm_enter(suspend_state_t state)
33{
34 switch (state) {
35 case PM_SUSPEND_MEM:
36 imx6q_set_lpm(STOP_POWER_OFF);
37 imx_gpc_pre_suspend();
38 imx_set_cpu_jump(0, v7_cpu_resume);
39 /* Zzz ... */
40 cpu_suspend(0, imx6q_suspend_finish);
41 imx_smp_prepare();
42 imx_gpc_post_resume();
43 break;
44 default:
45 return -EINVAL;
46 }
47
48 return 0;
49}
50
51static const struct platform_suspend_ops imx6q_pm_ops = {
52 .enter = imx6q_pm_enter,
53 .valid = suspend_valid_only_mem,
54};
55
56void __init imx6q_pm_init(void)
57{
58 /*
59 * The l2x0 core code provides an infrastucture to save and restore
60 * l2x0 registers across suspend/resume cycle. But because imx6q
61 * retains L2 content during suspend and needs to resume L2 before
62 * MMU is enabled, it can only utilize register saving support and
63 * have to take care of restoring on its own. So we save physical
64 * address of the data structure used by l2x0 core to save registers,
65 * and later restore the necessary ones in imx6q resume entry.
66 */
67 phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
68
69 suspend_set_ops(&imx6q_pm_ops);
70}
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
new file mode 100644
index 00000000000..36cacbd0dcc
--- /dev/null
+++ b/arch/arm/mach-imx/src.c
@@ -0,0 +1,49 @@
1/*
2 * Copyright 2011 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <asm/unified.h>
18
19#define SRC_SCR 0x000
20#define SRC_GPR1 0x020
21#define BP_SRC_SCR_CORE1_RST 14
22#define BP_SRC_SCR_CORE1_ENABLE 22
23
24static void __iomem *src_base;
25
26void imx_enable_cpu(int cpu, bool enable)
27{
28 u32 mask, val;
29
30 mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
31 val = readl_relaxed(src_base + SRC_SCR);
32 val = enable ? val | mask : val & ~mask;
33 writel_relaxed(val, src_base + SRC_SCR);
34}
35
36void imx_set_cpu_jump(int cpu, void *jump_addr)
37{
38 writel_relaxed(BSYM(virt_to_phys(jump_addr)),
39 src_base + SRC_GPR1 + cpu * 8);
40}
41
42void __init imx_src_init(void)
43{
44 struct device_node *np;
45
46 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
47 src_base = of_iomap(np, 0);
48 WARN_ON(!src_base);
49}