diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 14:34:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 14:34:35 -0400 |
commit | 4aa705b18bf17c4ff33ff7bbcd3f0c596443fa81 (patch) | |
tree | 3b166bff290d123ccaa88598ad2d45be67f5b358 /drivers/clk/imx | |
parent | c11d716218910c3aa2bac1bb641e6086ad649555 (diff) | |
parent | 2879e43f09122f8b3ef5456e3d7e48716b086e60 (diff) |
Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform support updates from Kevin Hilman:
"Our SoC branch usually contains expanded support for new SoCs and
other core platform code. Some highlights from this round:
- sunxi: SMP support for A23 SoC
- socpga: big-endian support
- pxa: conversion to common clock framework
- bcm: SMP support for BCM63138
- imx: support new I.MX7D SoC
- zte: basic support for ZX296702 SoC"
* tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (134 commits)
ARM: zx: Add basic defconfig support for ZX296702
ARM: dts: zx: add an initial zx296702 dts and doc
clk: zx: add clock support to zx296702
dt-bindings: Add #defines for ZTE ZX296702 clocks
ARM: socfpga: fix build error due to secondary_startup
MAINTAINERS: ARM64: EXYNOS: Extend entry for ARM64 DTS
ARM: ep93xx: simone: support for SPI-based MMC/SD cards
MAINTAINERS: update Shawn's email to use kernel.org one
ARM: socfpga: support suspend to ram
ARM: socfpga: add CPU_METHOD_OF_DECLARE for Arria 10
ARM: socfpga: use CPU_METHOD_OF_DECLARE for socfpga_cyclone5
ARM: EXYNOS: register power domain driver from core_initcall
ARM: EXYNOS: use PS_HOLD based poweroff for all supported SoCs
ARM: SAMSUNG: Constify platform_device_id
ARM: EXYNOS: Constify irq_domain_ops
ARM: EXYNOS: add coupled cpuidle support for Exynos3250
ARM: EXYNOS: add exynos_get_boot_addr() helper
ARM: EXYNOS: add exynos_set_boot_addr() helper
ARM: EXYNOS: make exynos_core_restart() less verbose
ARM: EXYNOS: fix exynos_boot_secondary() return value on timeout
...
Diffstat (limited to 'drivers/clk/imx')
25 files changed, 6682 insertions, 0 deletions
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile new file mode 100644 index 000000000000..75fae169ce8f --- /dev/null +++ b/drivers/clk/imx/Makefile | |||
@@ -0,0 +1,26 @@ | |||
1 | |||
2 | obj-y += \ | ||
3 | clk.o \ | ||
4 | clk-busy.o \ | ||
5 | clk-cpu.o \ | ||
6 | clk-fixup-div.o \ | ||
7 | clk-fixup-mux.o \ | ||
8 | clk-gate-exclusive.o \ | ||
9 | clk-gate2.o \ | ||
10 | clk-pllv1.o \ | ||
11 | clk-pllv2.o \ | ||
12 | clk-pllv3.o \ | ||
13 | clk-pfd.o | ||
14 | |||
15 | obj-$(CONFIG_SOC_IMX1) += clk-imx1.o | ||
16 | obj-$(CONFIG_SOC_IMX21) += clk-imx21.o | ||
17 | obj-$(CONFIG_SOC_IMX25) += clk-imx25.o | ||
18 | obj-$(CONFIG_SOC_IMX27) += clk-imx27.o | ||
19 | obj-$(CONFIG_SOC_IMX31) += clk-imx31.o | ||
20 | obj-$(CONFIG_SOC_IMX35) += clk-imx35.o | ||
21 | obj-$(CONFIG_SOC_IMX5) += clk-imx51-imx53.o | ||
22 | obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o | ||
23 | obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o | ||
24 | obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o | ||
25 | obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o | ||
26 | obj-$(CONFIG_SOC_VF610) += clk-vf610.o | ||
diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c new file mode 100644 index 000000000000..4bb1bc419b79 --- /dev/null +++ b/drivers/clk/imx/clk-busy.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2012 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/clk.h> | ||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/jiffies.h> | ||
18 | #include <linux/err.h> | ||
19 | #include "clk.h" | ||
20 | |||
21 | static int clk_busy_wait(void __iomem *reg, u8 shift) | ||
22 | { | ||
23 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | ||
24 | |||
25 | while (readl_relaxed(reg) & (1 << shift)) | ||
26 | if (time_after(jiffies, timeout)) | ||
27 | return -ETIMEDOUT; | ||
28 | |||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | struct clk_busy_divider { | ||
33 | struct clk_divider div; | ||
34 | const struct clk_ops *div_ops; | ||
35 | void __iomem *reg; | ||
36 | u8 shift; | ||
37 | }; | ||
38 | |||
39 | static inline struct clk_busy_divider *to_clk_busy_divider(struct clk_hw *hw) | ||
40 | { | ||
41 | struct clk_divider *div = container_of(hw, struct clk_divider, hw); | ||
42 | |||
43 | return container_of(div, struct clk_busy_divider, div); | ||
44 | } | ||
45 | |||
46 | static unsigned long clk_busy_divider_recalc_rate(struct clk_hw *hw, | ||
47 | unsigned long parent_rate) | ||
48 | { | ||
49 | struct clk_busy_divider *busy = to_clk_busy_divider(hw); | ||
50 | |||
51 | return busy->div_ops->recalc_rate(&busy->div.hw, parent_rate); | ||
52 | } | ||
53 | |||
54 | static long clk_busy_divider_round_rate(struct clk_hw *hw, unsigned long rate, | ||
55 | unsigned long *prate) | ||
56 | { | ||
57 | struct clk_busy_divider *busy = to_clk_busy_divider(hw); | ||
58 | |||
59 | return busy->div_ops->round_rate(&busy->div.hw, rate, prate); | ||
60 | } | ||
61 | |||
62 | static int clk_busy_divider_set_rate(struct clk_hw *hw, unsigned long rate, | ||
63 | unsigned long parent_rate) | ||
64 | { | ||
65 | struct clk_busy_divider *busy = to_clk_busy_divider(hw); | ||
66 | int ret; | ||
67 | |||
68 | ret = busy->div_ops->set_rate(&busy->div.hw, rate, parent_rate); | ||
69 | if (!ret) | ||
70 | ret = clk_busy_wait(busy->reg, busy->shift); | ||
71 | |||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | static struct clk_ops clk_busy_divider_ops = { | ||
76 | .recalc_rate = clk_busy_divider_recalc_rate, | ||
77 | .round_rate = clk_busy_divider_round_rate, | ||
78 | .set_rate = clk_busy_divider_set_rate, | ||
79 | }; | ||
80 | |||
81 | struct clk *imx_clk_busy_divider(const char *name, const char *parent_name, | ||
82 | void __iomem *reg, u8 shift, u8 width, | ||
83 | void __iomem *busy_reg, u8 busy_shift) | ||
84 | { | ||
85 | struct clk_busy_divider *busy; | ||
86 | struct clk *clk; | ||
87 | struct clk_init_data init; | ||
88 | |||
89 | busy = kzalloc(sizeof(*busy), GFP_KERNEL); | ||
90 | if (!busy) | ||
91 | return ERR_PTR(-ENOMEM); | ||
92 | |||
93 | busy->reg = busy_reg; | ||
94 | busy->shift = busy_shift; | ||
95 | |||
96 | busy->div.reg = reg; | ||
97 | busy->div.shift = shift; | ||
98 | busy->div.width = width; | ||
99 | busy->div.lock = &imx_ccm_lock; | ||
100 | busy->div_ops = &clk_divider_ops; | ||
101 | |||
102 | init.name = name; | ||
103 | init.ops = &clk_busy_divider_ops; | ||
104 | init.flags = CLK_SET_RATE_PARENT; | ||
105 | init.parent_names = &parent_name; | ||
106 | init.num_parents = 1; | ||
107 | |||
108 | busy->div.hw.init = &init; | ||
109 | |||
110 | clk = clk_register(NULL, &busy->div.hw); | ||
111 | if (IS_ERR(clk)) | ||
112 | kfree(busy); | ||
113 | |||
114 | return clk; | ||
115 | } | ||
116 | |||
117 | struct clk_busy_mux { | ||
118 | struct clk_mux mux; | ||
119 | const struct clk_ops *mux_ops; | ||
120 | void __iomem *reg; | ||
121 | u8 shift; | ||
122 | }; | ||
123 | |||
124 | static inline struct clk_busy_mux *to_clk_busy_mux(struct clk_hw *hw) | ||
125 | { | ||
126 | struct clk_mux *mux = container_of(hw, struct clk_mux, hw); | ||
127 | |||
128 | return container_of(mux, struct clk_busy_mux, mux); | ||
129 | } | ||
130 | |||
131 | static u8 clk_busy_mux_get_parent(struct clk_hw *hw) | ||
132 | { | ||
133 | struct clk_busy_mux *busy = to_clk_busy_mux(hw); | ||
134 | |||
135 | return busy->mux_ops->get_parent(&busy->mux.hw); | ||
136 | } | ||
137 | |||
138 | static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index) | ||
139 | { | ||
140 | struct clk_busy_mux *busy = to_clk_busy_mux(hw); | ||
141 | int ret; | ||
142 | |||
143 | ret = busy->mux_ops->set_parent(&busy->mux.hw, index); | ||
144 | if (!ret) | ||
145 | ret = clk_busy_wait(busy->reg, busy->shift); | ||
146 | |||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static struct clk_ops clk_busy_mux_ops = { | ||
151 | .get_parent = clk_busy_mux_get_parent, | ||
152 | .set_parent = clk_busy_mux_set_parent, | ||
153 | }; | ||
154 | |||
155 | struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift, | ||
156 | u8 width, void __iomem *busy_reg, u8 busy_shift, | ||
157 | const char **parent_names, int num_parents) | ||
158 | { | ||
159 | struct clk_busy_mux *busy; | ||
160 | struct clk *clk; | ||
161 | struct clk_init_data init; | ||
162 | |||
163 | busy = kzalloc(sizeof(*busy), GFP_KERNEL); | ||
164 | if (!busy) | ||
165 | return ERR_PTR(-ENOMEM); | ||
166 | |||
167 | busy->reg = busy_reg; | ||
168 | busy->shift = busy_shift; | ||
169 | |||
170 | busy->mux.reg = reg; | ||
171 | busy->mux.shift = shift; | ||
172 | busy->mux.mask = BIT(width) - 1; | ||
173 | busy->mux.lock = &imx_ccm_lock; | ||
174 | busy->mux_ops = &clk_mux_ops; | ||
175 | |||
176 | init.name = name; | ||
177 | init.ops = &clk_busy_mux_ops; | ||
178 | init.flags = 0; | ||
179 | init.parent_names = parent_names; | ||
180 | init.num_parents = num_parents; | ||
181 | |||
182 | busy->mux.hw.init = &init; | ||
183 | |||
184 | clk = clk_register(NULL, &busy->mux.hw); | ||
185 | if (IS_ERR(clk)) | ||
186 | kfree(busy); | ||
187 | |||
188 | return clk; | ||
189 | } | ||
diff --git a/drivers/clk/imx/clk-cpu.c b/drivers/clk/imx/clk-cpu.c new file mode 100644 index 000000000000..9d46eac87f45 --- /dev/null +++ b/drivers/clk/imx/clk-cpu.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include "clk.h" | ||
16 | |||
17 | struct clk_cpu { | ||
18 | struct clk_hw hw; | ||
19 | struct clk *div; | ||
20 | struct clk *mux; | ||
21 | struct clk *pll; | ||
22 | struct clk *step; | ||
23 | }; | ||
24 | |||
25 | static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw) | ||
26 | { | ||
27 | return container_of(hw, struct clk_cpu, hw); | ||
28 | } | ||
29 | |||
30 | static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw, | ||
31 | unsigned long parent_rate) | ||
32 | { | ||
33 | struct clk_cpu *cpu = to_clk_cpu(hw); | ||
34 | |||
35 | return clk_get_rate(cpu->div); | ||
36 | } | ||
37 | |||
38 | static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate, | ||
39 | unsigned long *prate) | ||
40 | { | ||
41 | struct clk_cpu *cpu = to_clk_cpu(hw); | ||
42 | |||
43 | return clk_round_rate(cpu->pll, rate); | ||
44 | } | ||
45 | |||
46 | static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate, | ||
47 | unsigned long parent_rate) | ||
48 | { | ||
49 | struct clk_cpu *cpu = to_clk_cpu(hw); | ||
50 | int ret; | ||
51 | |||
52 | /* switch to PLL bypass clock */ | ||
53 | ret = clk_set_parent(cpu->mux, cpu->step); | ||
54 | if (ret) | ||
55 | return ret; | ||
56 | |||
57 | /* reprogram PLL */ | ||
58 | ret = clk_set_rate(cpu->pll, rate); | ||
59 | if (ret) { | ||
60 | clk_set_parent(cpu->mux, cpu->pll); | ||
61 | return ret; | ||
62 | } | ||
63 | /* switch back to PLL clock */ | ||
64 | clk_set_parent(cpu->mux, cpu->pll); | ||
65 | |||
66 | /* Ensure the divider is what we expect */ | ||
67 | clk_set_rate(cpu->div, rate); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static const struct clk_ops clk_cpu_ops = { | ||
73 | .recalc_rate = clk_cpu_recalc_rate, | ||
74 | .round_rate = clk_cpu_round_rate, | ||
75 | .set_rate = clk_cpu_set_rate, | ||
76 | }; | ||
77 | |||
78 | struct clk *imx_clk_cpu(const char *name, const char *parent_name, | ||
79 | struct clk *div, struct clk *mux, struct clk *pll, | ||
80 | struct clk *step) | ||
81 | { | ||
82 | struct clk_cpu *cpu; | ||
83 | struct clk *clk; | ||
84 | struct clk_init_data init; | ||
85 | |||
86 | cpu = kzalloc(sizeof(*cpu), GFP_KERNEL); | ||
87 | if (!cpu) | ||
88 | return ERR_PTR(-ENOMEM); | ||
89 | |||
90 | cpu->div = div; | ||
91 | cpu->mux = mux; | ||
92 | cpu->pll = pll; | ||
93 | cpu->step = step; | ||
94 | |||
95 | init.name = name; | ||
96 | init.ops = &clk_cpu_ops; | ||
97 | init.flags = 0; | ||
98 | init.parent_names = &parent_name; | ||
99 | init.num_parents = 1; | ||
100 | |||
101 | cpu->hw.init = &init; | ||
102 | |||
103 | clk = clk_register(NULL, &cpu->hw); | ||
104 | if (IS_ERR(clk)) | ||
105 | kfree(cpu); | ||
106 | |||
107 | return clk; | ||
108 | } | ||
diff --git a/drivers/clk/imx/clk-fixup-div.c b/drivers/clk/imx/clk-fixup-div.c new file mode 100644 index 000000000000..21db020b1f2d --- /dev/null +++ b/drivers/clk/imx/clk-fixup-div.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include "clk.h" | ||
17 | |||
18 | #define to_clk_div(_hw) container_of(_hw, struct clk_divider, hw) | ||
19 | #define div_mask(d) ((1 << (d->width)) - 1) | ||
20 | |||
21 | /** | ||
22 | * struct clk_fixup_div - imx integer fixup divider clock | ||
23 | * @divider: the parent class | ||
24 | * @ops: pointer to clk_ops of parent class | ||
25 | * @fixup: a hook to fixup the write value | ||
26 | * | ||
27 | * The imx fixup divider clock is a subclass of basic clk_divider | ||
28 | * with an addtional fixup hook. | ||
29 | */ | ||
30 | struct clk_fixup_div { | ||
31 | struct clk_divider divider; | ||
32 | const struct clk_ops *ops; | ||
33 | void (*fixup)(u32 *val); | ||
34 | }; | ||
35 | |||
36 | static inline struct clk_fixup_div *to_clk_fixup_div(struct clk_hw *hw) | ||
37 | { | ||
38 | struct clk_divider *divider = to_clk_div(hw); | ||
39 | |||
40 | return container_of(divider, struct clk_fixup_div, divider); | ||
41 | } | ||
42 | |||
43 | static unsigned long clk_fixup_div_recalc_rate(struct clk_hw *hw, | ||
44 | unsigned long parent_rate) | ||
45 | { | ||
46 | struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); | ||
47 | |||
48 | return fixup_div->ops->recalc_rate(&fixup_div->divider.hw, parent_rate); | ||
49 | } | ||
50 | |||
51 | static long clk_fixup_div_round_rate(struct clk_hw *hw, unsigned long rate, | ||
52 | unsigned long *prate) | ||
53 | { | ||
54 | struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); | ||
55 | |||
56 | return fixup_div->ops->round_rate(&fixup_div->divider.hw, rate, prate); | ||
57 | } | ||
58 | |||
59 | static int clk_fixup_div_set_rate(struct clk_hw *hw, unsigned long rate, | ||
60 | unsigned long parent_rate) | ||
61 | { | ||
62 | struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); | ||
63 | struct clk_divider *div = to_clk_div(hw); | ||
64 | unsigned int divider, value; | ||
65 | unsigned long flags = 0; | ||
66 | u32 val; | ||
67 | |||
68 | divider = parent_rate / rate; | ||
69 | |||
70 | /* Zero based divider */ | ||
71 | value = divider - 1; | ||
72 | |||
73 | if (value > div_mask(div)) | ||
74 | value = div_mask(div); | ||
75 | |||
76 | spin_lock_irqsave(div->lock, flags); | ||
77 | |||
78 | val = readl(div->reg); | ||
79 | val &= ~(div_mask(div) << div->shift); | ||
80 | val |= value << div->shift; | ||
81 | fixup_div->fixup(&val); | ||
82 | writel(val, div->reg); | ||
83 | |||
84 | spin_unlock_irqrestore(div->lock, flags); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static const struct clk_ops clk_fixup_div_ops = { | ||
90 | .recalc_rate = clk_fixup_div_recalc_rate, | ||
91 | .round_rate = clk_fixup_div_round_rate, | ||
92 | .set_rate = clk_fixup_div_set_rate, | ||
93 | }; | ||
94 | |||
95 | struct clk *imx_clk_fixup_divider(const char *name, const char *parent, | ||
96 | void __iomem *reg, u8 shift, u8 width, | ||
97 | void (*fixup)(u32 *val)) | ||
98 | { | ||
99 | struct clk_fixup_div *fixup_div; | ||
100 | struct clk *clk; | ||
101 | struct clk_init_data init; | ||
102 | |||
103 | if (!fixup) | ||
104 | return ERR_PTR(-EINVAL); | ||
105 | |||
106 | fixup_div = kzalloc(sizeof(*fixup_div), GFP_KERNEL); | ||
107 | if (!fixup_div) | ||
108 | return ERR_PTR(-ENOMEM); | ||
109 | |||
110 | init.name = name; | ||
111 | init.ops = &clk_fixup_div_ops; | ||
112 | init.flags = CLK_SET_RATE_PARENT; | ||
113 | init.parent_names = parent ? &parent : NULL; | ||
114 | init.num_parents = parent ? 1 : 0; | ||
115 | |||
116 | fixup_div->divider.reg = reg; | ||
117 | fixup_div->divider.shift = shift; | ||
118 | fixup_div->divider.width = width; | ||
119 | fixup_div->divider.lock = &imx_ccm_lock; | ||
120 | fixup_div->divider.hw.init = &init; | ||
121 | fixup_div->ops = &clk_divider_ops; | ||
122 | fixup_div->fixup = fixup; | ||
123 | |||
124 | clk = clk_register(NULL, &fixup_div->divider.hw); | ||
125 | if (IS_ERR(clk)) | ||
126 | kfree(fixup_div); | ||
127 | |||
128 | return clk; | ||
129 | } | ||
diff --git a/drivers/clk/imx/clk-fixup-mux.c b/drivers/clk/imx/clk-fixup-mux.c new file mode 100644 index 000000000000..0d40b35c557c --- /dev/null +++ b/drivers/clk/imx/clk-fixup-mux.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include "clk.h" | ||
17 | |||
18 | #define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) | ||
19 | |||
20 | /** | ||
21 | * struct clk_fixup_mux - imx integer fixup multiplexer clock | ||
22 | * @mux: the parent class | ||
23 | * @ops: pointer to clk_ops of parent class | ||
24 | * @fixup: a hook to fixup the write value | ||
25 | * | ||
26 | * The imx fixup multiplexer clock is a subclass of basic clk_mux | ||
27 | * with an addtional fixup hook. | ||
28 | */ | ||
29 | struct clk_fixup_mux { | ||
30 | struct clk_mux mux; | ||
31 | const struct clk_ops *ops; | ||
32 | void (*fixup)(u32 *val); | ||
33 | }; | ||
34 | |||
35 | static inline struct clk_fixup_mux *to_clk_fixup_mux(struct clk_hw *hw) | ||
36 | { | ||
37 | struct clk_mux *mux = to_clk_mux(hw); | ||
38 | |||
39 | return container_of(mux, struct clk_fixup_mux, mux); | ||
40 | } | ||
41 | |||
42 | static u8 clk_fixup_mux_get_parent(struct clk_hw *hw) | ||
43 | { | ||
44 | struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw); | ||
45 | |||
46 | return fixup_mux->ops->get_parent(&fixup_mux->mux.hw); | ||
47 | } | ||
48 | |||
49 | static int clk_fixup_mux_set_parent(struct clk_hw *hw, u8 index) | ||
50 | { | ||
51 | struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw); | ||
52 | struct clk_mux *mux = to_clk_mux(hw); | ||
53 | unsigned long flags = 0; | ||
54 | u32 val; | ||
55 | |||
56 | spin_lock_irqsave(mux->lock, flags); | ||
57 | |||
58 | val = readl(mux->reg); | ||
59 | val &= ~(mux->mask << mux->shift); | ||
60 | val |= index << mux->shift; | ||
61 | fixup_mux->fixup(&val); | ||
62 | writel(val, mux->reg); | ||
63 | |||
64 | spin_unlock_irqrestore(mux->lock, flags); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static const struct clk_ops clk_fixup_mux_ops = { | ||
70 | .get_parent = clk_fixup_mux_get_parent, | ||
71 | .set_parent = clk_fixup_mux_set_parent, | ||
72 | }; | ||
73 | |||
74 | struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg, | ||
75 | u8 shift, u8 width, const char **parents, | ||
76 | int num_parents, void (*fixup)(u32 *val)) | ||
77 | { | ||
78 | struct clk_fixup_mux *fixup_mux; | ||
79 | struct clk *clk; | ||
80 | struct clk_init_data init; | ||
81 | |||
82 | if (!fixup) | ||
83 | return ERR_PTR(-EINVAL); | ||
84 | |||
85 | fixup_mux = kzalloc(sizeof(*fixup_mux), GFP_KERNEL); | ||
86 | if (!fixup_mux) | ||
87 | return ERR_PTR(-ENOMEM); | ||
88 | |||
89 | init.name = name; | ||
90 | init.ops = &clk_fixup_mux_ops; | ||
91 | init.parent_names = parents; | ||
92 | init.num_parents = num_parents; | ||
93 | init.flags = 0; | ||
94 | |||
95 | fixup_mux->mux.reg = reg; | ||
96 | fixup_mux->mux.shift = shift; | ||
97 | fixup_mux->mux.mask = BIT(width) - 1; | ||
98 | fixup_mux->mux.lock = &imx_ccm_lock; | ||
99 | fixup_mux->mux.hw.init = &init; | ||
100 | fixup_mux->ops = &clk_mux_ops; | ||
101 | fixup_mux->fixup = fixup; | ||
102 | |||
103 | clk = clk_register(NULL, &fixup_mux->mux.hw); | ||
104 | if (IS_ERR(clk)) | ||
105 | kfree(fixup_mux); | ||
106 | |||
107 | return clk; | ||
108 | } | ||
diff --git a/drivers/clk/imx/clk-gate-exclusive.c b/drivers/clk/imx/clk-gate-exclusive.c new file mode 100644 index 000000000000..c12f5f2e04dc --- /dev/null +++ b/drivers/clk/imx/clk-gate-exclusive.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright 2014 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/clk-provider.h> | ||
10 | #include <linux/err.h> | ||
11 | #include <linux/io.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include "clk.h" | ||
14 | |||
15 | /** | ||
16 | * struct clk_gate_exclusive - i.MX specific gate clock which is mutually | ||
17 | * exclusive with other gate clocks | ||
18 | * | ||
19 | * @gate: the parent class | ||
20 | * @exclusive_mask: mask of gate bits which are mutually exclusive to this | ||
21 | * gate clock | ||
22 | * | ||
23 | * The imx exclusive gate clock is a subclass of basic clk_gate | ||
24 | * with an addtional mask to indicate which other gate bits in the same | ||
25 | * register is mutually exclusive to this gate clock. | ||
26 | */ | ||
27 | struct clk_gate_exclusive { | ||
28 | struct clk_gate gate; | ||
29 | u32 exclusive_mask; | ||
30 | }; | ||
31 | |||
32 | static int clk_gate_exclusive_enable(struct clk_hw *hw) | ||
33 | { | ||
34 | struct clk_gate *gate = container_of(hw, struct clk_gate, hw); | ||
35 | struct clk_gate_exclusive *exgate = container_of(gate, | ||
36 | struct clk_gate_exclusive, gate); | ||
37 | u32 val = readl(gate->reg); | ||
38 | |||
39 | if (val & exgate->exclusive_mask) | ||
40 | return -EBUSY; | ||
41 | |||
42 | return clk_gate_ops.enable(hw); | ||
43 | } | ||
44 | |||
45 | static void clk_gate_exclusive_disable(struct clk_hw *hw) | ||
46 | { | ||
47 | clk_gate_ops.disable(hw); | ||
48 | } | ||
49 | |||
50 | static int clk_gate_exclusive_is_enabled(struct clk_hw *hw) | ||
51 | { | ||
52 | return clk_gate_ops.is_enabled(hw); | ||
53 | } | ||
54 | |||
55 | static const struct clk_ops clk_gate_exclusive_ops = { | ||
56 | .enable = clk_gate_exclusive_enable, | ||
57 | .disable = clk_gate_exclusive_disable, | ||
58 | .is_enabled = clk_gate_exclusive_is_enabled, | ||
59 | }; | ||
60 | |||
61 | struct clk *imx_clk_gate_exclusive(const char *name, const char *parent, | ||
62 | void __iomem *reg, u8 shift, u32 exclusive_mask) | ||
63 | { | ||
64 | struct clk_gate_exclusive *exgate; | ||
65 | struct clk_gate *gate; | ||
66 | struct clk *clk; | ||
67 | struct clk_init_data init; | ||
68 | |||
69 | if (exclusive_mask == 0) | ||
70 | return ERR_PTR(-EINVAL); | ||
71 | |||
72 | exgate = kzalloc(sizeof(*exgate), GFP_KERNEL); | ||
73 | if (!exgate) | ||
74 | return ERR_PTR(-ENOMEM); | ||
75 | gate = &exgate->gate; | ||
76 | |||
77 | init.name = name; | ||
78 | init.ops = &clk_gate_exclusive_ops; | ||
79 | init.flags = CLK_SET_RATE_PARENT; | ||
80 | init.parent_names = parent ? &parent : NULL; | ||
81 | init.num_parents = parent ? 1 : 0; | ||
82 | |||
83 | gate->reg = reg; | ||
84 | gate->bit_idx = shift; | ||
85 | gate->lock = &imx_ccm_lock; | ||
86 | gate->hw.init = &init; | ||
87 | exgate->exclusive_mask = exclusive_mask; | ||
88 | |||
89 | clk = clk_register(NULL, &gate->hw); | ||
90 | if (IS_ERR(clk)) | ||
91 | kfree(exgate); | ||
92 | |||
93 | return clk; | ||
94 | } | ||
diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c new file mode 100644 index 000000000000..8935bff99fe7 --- /dev/null +++ b/drivers/clk/imx/clk-gate2.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com> | ||
3 | * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * Gated clock implementation | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/string.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | /** | ||
21 | * DOC: basic gatable clock which can gate and ungate it's ouput | ||
22 | * | ||
23 | * Traits of this clock: | ||
24 | * prepare - clk_(un)prepare only ensures parent is (un)prepared | ||
25 | * enable - clk_enable and clk_disable are functional & control gating | ||
26 | * rate - inherits rate from parent. No clk_set_rate support | ||
27 | * parent - fixed parent. No clk_set_parent support | ||
28 | */ | ||
29 | |||
30 | struct clk_gate2 { | ||
31 | struct clk_hw hw; | ||
32 | void __iomem *reg; | ||
33 | u8 bit_idx; | ||
34 | u8 flags; | ||
35 | spinlock_t *lock; | ||
36 | unsigned int *share_count; | ||
37 | }; | ||
38 | |||
39 | #define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw) | ||
40 | |||
41 | static int clk_gate2_enable(struct clk_hw *hw) | ||
42 | { | ||
43 | struct clk_gate2 *gate = to_clk_gate2(hw); | ||
44 | u32 reg; | ||
45 | unsigned long flags = 0; | ||
46 | |||
47 | spin_lock_irqsave(gate->lock, flags); | ||
48 | |||
49 | if (gate->share_count && (*gate->share_count)++ > 0) | ||
50 | goto out; | ||
51 | |||
52 | reg = readl(gate->reg); | ||
53 | reg |= 3 << gate->bit_idx; | ||
54 | writel(reg, gate->reg); | ||
55 | |||
56 | out: | ||
57 | spin_unlock_irqrestore(gate->lock, flags); | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static void clk_gate2_disable(struct clk_hw *hw) | ||
63 | { | ||
64 | struct clk_gate2 *gate = to_clk_gate2(hw); | ||
65 | u32 reg; | ||
66 | unsigned long flags = 0; | ||
67 | |||
68 | spin_lock_irqsave(gate->lock, flags); | ||
69 | |||
70 | if (gate->share_count) { | ||
71 | if (WARN_ON(*gate->share_count == 0)) | ||
72 | goto out; | ||
73 | else if (--(*gate->share_count) > 0) | ||
74 | goto out; | ||
75 | } | ||
76 | |||
77 | reg = readl(gate->reg); | ||
78 | reg &= ~(3 << gate->bit_idx); | ||
79 | writel(reg, gate->reg); | ||
80 | |||
81 | out: | ||
82 | spin_unlock_irqrestore(gate->lock, flags); | ||
83 | } | ||
84 | |||
85 | static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx) | ||
86 | { | ||
87 | u32 val = readl(reg); | ||
88 | |||
89 | if (((val >> bit_idx) & 1) == 1) | ||
90 | return 1; | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int clk_gate2_is_enabled(struct clk_hw *hw) | ||
96 | { | ||
97 | struct clk_gate2 *gate = to_clk_gate2(hw); | ||
98 | |||
99 | return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); | ||
100 | } | ||
101 | |||
102 | static void clk_gate2_disable_unused(struct clk_hw *hw) | ||
103 | { | ||
104 | struct clk_gate2 *gate = to_clk_gate2(hw); | ||
105 | unsigned long flags = 0; | ||
106 | u32 reg; | ||
107 | |||
108 | spin_lock_irqsave(gate->lock, flags); | ||
109 | |||
110 | if (!gate->share_count || *gate->share_count == 0) { | ||
111 | reg = readl(gate->reg); | ||
112 | reg &= ~(3 << gate->bit_idx); | ||
113 | writel(reg, gate->reg); | ||
114 | } | ||
115 | |||
116 | spin_unlock_irqrestore(gate->lock, flags); | ||
117 | } | ||
118 | |||
119 | static struct clk_ops clk_gate2_ops = { | ||
120 | .enable = clk_gate2_enable, | ||
121 | .disable = clk_gate2_disable, | ||
122 | .disable_unused = clk_gate2_disable_unused, | ||
123 | .is_enabled = clk_gate2_is_enabled, | ||
124 | }; | ||
125 | |||
126 | struct clk *clk_register_gate2(struct device *dev, const char *name, | ||
127 | const char *parent_name, unsigned long flags, | ||
128 | void __iomem *reg, u8 bit_idx, | ||
129 | u8 clk_gate2_flags, spinlock_t *lock, | ||
130 | unsigned int *share_count) | ||
131 | { | ||
132 | struct clk_gate2 *gate; | ||
133 | struct clk *clk; | ||
134 | struct clk_init_data init; | ||
135 | |||
136 | gate = kzalloc(sizeof(struct clk_gate2), GFP_KERNEL); | ||
137 | if (!gate) | ||
138 | return ERR_PTR(-ENOMEM); | ||
139 | |||
140 | /* struct clk_gate2 assignments */ | ||
141 | gate->reg = reg; | ||
142 | gate->bit_idx = bit_idx; | ||
143 | gate->flags = clk_gate2_flags; | ||
144 | gate->lock = lock; | ||
145 | gate->share_count = share_count; | ||
146 | |||
147 | init.name = name; | ||
148 | init.ops = &clk_gate2_ops; | ||
149 | init.flags = flags; | ||
150 | init.parent_names = parent_name ? &parent_name : NULL; | ||
151 | init.num_parents = parent_name ? 1 : 0; | ||
152 | |||
153 | gate->hw.init = &init; | ||
154 | |||
155 | clk = clk_register(dev, &gate->hw); | ||
156 | if (IS_ERR(clk)) | ||
157 | kfree(gate); | ||
158 | |||
159 | return clk; | ||
160 | } | ||
diff --git a/drivers/clk/imx/clk-imx1.c b/drivers/clk/imx/clk-imx1.c new file mode 100644 index 000000000000..c2647fa19f28 --- /dev/null +++ b/drivers/clk/imx/clk-imx1.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along | ||
14 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clkdev.h> | ||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/of_address.h> | ||
25 | #include <dt-bindings/clock/imx1-clock.h> | ||
26 | #include <soc/imx/timer.h> | ||
27 | #include <asm/irq.h> | ||
28 | |||
29 | #include "clk.h" | ||
30 | |||
31 | #define MX1_CCM_BASE_ADDR 0x0021b000 | ||
32 | #define MX1_TIM1_BASE_ADDR 0x00220000 | ||
33 | #define MX1_TIM1_INT (NR_IRQS_LEGACY + 59) | ||
34 | |||
35 | static const char *prem_sel_clks[] = { "clk32_premult", "clk16m", }; | ||
36 | static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m", | ||
37 | "prem", "fclk", }; | ||
38 | |||
39 | static struct clk *clk[IMX1_CLK_MAX]; | ||
40 | static struct clk_onecell_data clk_data; | ||
41 | |||
42 | static void __iomem *ccm __initdata; | ||
43 | #define CCM_CSCR (ccm + 0x0000) | ||
44 | #define CCM_MPCTL0 (ccm + 0x0004) | ||
45 | #define CCM_SPCTL0 (ccm + 0x000c) | ||
46 | #define CCM_PCDR (ccm + 0x0020) | ||
47 | #define SCM_GCCR (ccm + 0x0810) | ||
48 | |||
49 | static void __init _mx1_clocks_init(unsigned long fref) | ||
50 | { | ||
51 | clk[IMX1_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
52 | clk[IMX1_CLK_CLK32] = imx_obtain_fixed_clock("clk32", fref); | ||
53 | clk[IMX1_CLK_CLK16M_EXT] = imx_clk_fixed("clk16m_ext", 16000000); | ||
54 | clk[IMX1_CLK_CLK16M] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17); | ||
55 | clk[IMX1_CLK_CLK32_PREMULT] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1); | ||
56 | clk[IMX1_CLK_PREM] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks)); | ||
57 | clk[IMX1_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX1, "mpll", "clk32_premult", CCM_MPCTL0); | ||
58 | clk[IMX1_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0); | ||
59 | clk[IMX1_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX1, "spll", "prem", CCM_SPCTL0); | ||
60 | clk[IMX1_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); | ||
61 | clk[IMX1_CLK_MCU] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1); | ||
62 | clk[IMX1_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1); | ||
63 | clk[IMX1_CLK_HCLK] = imx_clk_divider("hclk", "spll_gate", CCM_CSCR, 10, 4); | ||
64 | clk[IMX1_CLK_CLK48M] = imx_clk_divider("clk48m", "spll_gate", CCM_CSCR, 26, 3); | ||
65 | clk[IMX1_CLK_PER1] = imx_clk_divider("per1", "spll_gate", CCM_PCDR, 0, 4); | ||
66 | clk[IMX1_CLK_PER2] = imx_clk_divider("per2", "spll_gate", CCM_PCDR, 4, 4); | ||
67 | clk[IMX1_CLK_PER3] = imx_clk_divider("per3", "spll_gate", CCM_PCDR, 16, 7); | ||
68 | clk[IMX1_CLK_CLKO] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); | ||
69 | clk[IMX1_CLK_UART3_GATE] = imx_clk_gate("uart3_gate", "hclk", SCM_GCCR, 6); | ||
70 | clk[IMX1_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate", "hclk", SCM_GCCR, 5); | ||
71 | clk[IMX1_CLK_BROM_GATE] = imx_clk_gate("brom_gate", "hclk", SCM_GCCR, 4); | ||
72 | clk[IMX1_CLK_DMA_GATE] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 3); | ||
73 | clk[IMX1_CLK_CSI_GATE] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2); | ||
74 | clk[IMX1_CLK_MMA_GATE] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1); | ||
75 | clk[IMX1_CLK_USBD_GATE] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0); | ||
76 | |||
77 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
78 | } | ||
79 | |||
80 | int __init mx1_clocks_init(unsigned long fref) | ||
81 | { | ||
82 | ccm = ioremap(MX1_CCM_BASE_ADDR, SZ_4K); | ||
83 | BUG_ON(!ccm); | ||
84 | |||
85 | _mx1_clocks_init(fref); | ||
86 | |||
87 | clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx-gpt.0"); | ||
88 | clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx-gpt.0"); | ||
89 | clk_register_clkdev(clk[IMX1_CLK_DMA_GATE], "ahb", "imx1-dma"); | ||
90 | clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-dma"); | ||
91 | clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.0"); | ||
92 | clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-uart.0"); | ||
93 | clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.1"); | ||
94 | clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-uart.1"); | ||
95 | clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.2"); | ||
96 | clk_register_clkdev(clk[IMX1_CLK_UART3_GATE], "ipg", "imx1-uart.2"); | ||
97 | clk_register_clkdev(clk[IMX1_CLK_HCLK], NULL, "imx1-i2c.0"); | ||
98 | clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-cspi.0"); | ||
99 | clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-cspi.0"); | ||
100 | clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-cspi.1"); | ||
101 | clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-cspi.1"); | ||
102 | clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-fb.0"); | ||
103 | clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-fb.0"); | ||
104 | clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ahb", "imx1-fb.0"); | ||
105 | |||
106 | mxc_timer_init(MX1_TIM1_BASE_ADDR, MX1_TIM1_INT, GPT_TYPE_IMX1); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void __init mx1_clocks_init_dt(struct device_node *np) | ||
112 | { | ||
113 | ccm = of_iomap(np, 0); | ||
114 | BUG_ON(!ccm); | ||
115 | |||
116 | _mx1_clocks_init(32768); | ||
117 | |||
118 | clk_data.clks = clk; | ||
119 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
120 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
121 | } | ||
122 | CLK_OF_DECLARE(imx1_ccm, "fsl,imx1-ccm", mx1_clocks_init_dt); | ||
diff --git a/drivers/clk/imx/clk-imx21.c b/drivers/clk/imx/clk-imx21.c new file mode 100644 index 000000000000..dba987e3b89f --- /dev/null +++ b/drivers/clk/imx/clk-imx21.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * Copyright 2008 Juergen Beisert, kernel@pengutronix.de | ||
4 | * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/clkdev.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <dt-bindings/clock/imx21-clock.h> | ||
18 | #include <soc/imx/timer.h> | ||
19 | #include <asm/irq.h> | ||
20 | |||
21 | #include "clk.h" | ||
22 | |||
23 | #define MX21_CCM_BASE_ADDR 0x10027000 | ||
24 | #define MX21_GPT1_BASE_ADDR 0x10003000 | ||
25 | #define MX21_INT_GPT1 (NR_IRQS_LEGACY + 26) | ||
26 | |||
27 | static void __iomem *ccm __initdata; | ||
28 | |||
29 | /* Register offsets */ | ||
30 | #define CCM_CSCR (ccm + 0x00) | ||
31 | #define CCM_MPCTL0 (ccm + 0x04) | ||
32 | #define CCM_SPCTL0 (ccm + 0x0c) | ||
33 | #define CCM_PCDR0 (ccm + 0x18) | ||
34 | #define CCM_PCDR1 (ccm + 0x1c) | ||
35 | #define CCM_PCCR0 (ccm + 0x20) | ||
36 | #define CCM_PCCR1 (ccm + 0x24) | ||
37 | |||
38 | static const char *mpll_osc_sel_clks[] = { "ckih_gate", "ckih_div1p5", }; | ||
39 | static const char *mpll_sel_clks[] = { "fpm_gate", "mpll_osc_sel", }; | ||
40 | static const char *spll_sel_clks[] = { "fpm_gate", "mpll_osc_sel", }; | ||
41 | static const char *ssi_sel_clks[] = { "spll_gate", "mpll_gate", }; | ||
42 | |||
43 | static struct clk *clk[IMX21_CLK_MAX]; | ||
44 | static struct clk_onecell_data clk_data; | ||
45 | |||
46 | static void __init _mx21_clocks_init(unsigned long lref, unsigned long href) | ||
47 | { | ||
48 | BUG_ON(!ccm); | ||
49 | |||
50 | clk[IMX21_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
51 | clk[IMX21_CLK_CKIL] = imx_obtain_fixed_clock("ckil", lref); | ||
52 | clk[IMX21_CLK_CKIH] = imx_obtain_fixed_clock("ckih", href); | ||
53 | clk[IMX21_CLK_FPM] = imx_clk_fixed_factor("fpm", "ckil", 512, 1); | ||
54 | clk[IMX21_CLK_CKIH_DIV1P5] = imx_clk_fixed_factor("ckih_div1p5", "ckih_gate", 2, 3); | ||
55 | |||
56 | clk[IMX21_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0); | ||
57 | clk[IMX21_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); | ||
58 | clk[IMX21_CLK_FPM_GATE] = imx_clk_gate("fpm_gate", "fpm", CCM_CSCR, 2); | ||
59 | clk[IMX21_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3); | ||
60 | clk[IMX21_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks)); | ||
61 | clk[IMX21_CLK_IPG] = imx_clk_divider("ipg", "hclk", CCM_CSCR, 9, 1); | ||
62 | clk[IMX21_CLK_HCLK] = imx_clk_divider("hclk", "fclk", CCM_CSCR, 10, 4); | ||
63 | clk[IMX21_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks)); | ||
64 | clk[IMX21_CLK_SPLL_SEL] = imx_clk_mux("spll_sel", CCM_CSCR, 17, 1, spll_sel_clks, ARRAY_SIZE(spll_sel_clks)); | ||
65 | clk[IMX21_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", CCM_CSCR, 19, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks)); | ||
66 | clk[IMX21_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", CCM_CSCR, 20, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks)); | ||
67 | clk[IMX21_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 26, 3); | ||
68 | clk[IMX21_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 29, 3); | ||
69 | |||
70 | clk[IMX21_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX21, "mpll", "mpll_sel", CCM_MPCTL0); | ||
71 | |||
72 | clk[IMX21_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX21, "spll", "spll_sel", CCM_SPCTL0); | ||
73 | |||
74 | clk[IMX21_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "fclk", CCM_PCDR0, 12, 4); | ||
75 | clk[IMX21_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6); | ||
76 | clk[IMX21_CLK_SSI2_DIV] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6); | ||
77 | |||
78 | clk[IMX21_CLK_PER1] = imx_clk_divider("per1", "mpll_gate", CCM_PCDR1, 0, 6); | ||
79 | clk[IMX21_CLK_PER2] = imx_clk_divider("per2", "mpll_gate", CCM_PCDR1, 8, 6); | ||
80 | clk[IMX21_CLK_PER3] = imx_clk_divider("per3", "mpll_gate", CCM_PCDR1, 16, 6); | ||
81 | clk[IMX21_CLK_PER4] = imx_clk_divider("per4", "mpll_gate", CCM_PCDR1, 24, 6); | ||
82 | |||
83 | clk[IMX21_CLK_UART1_IPG_GATE] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR0, 0); | ||
84 | clk[IMX21_CLK_UART2_IPG_GATE] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR0, 1); | ||
85 | clk[IMX21_CLK_UART3_IPG_GATE] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR0, 2); | ||
86 | clk[IMX21_CLK_UART4_IPG_GATE] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR0, 3); | ||
87 | clk[IMX21_CLK_CSPI1_IPG_GATE] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 4); | ||
88 | clk[IMX21_CLK_CSPI2_IPG_GATE] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 5); | ||
89 | clk[IMX21_CLK_SSI1_GATE] = imx_clk_gate("ssi1_gate", "ipg", CCM_PCCR0, 6); | ||
90 | clk[IMX21_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate", "ipg", CCM_PCCR0, 7); | ||
91 | clk[IMX21_CLK_SDHC1_IPG_GATE] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 9); | ||
92 | clk[IMX21_CLK_SDHC2_IPG_GATE] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 10); | ||
93 | clk[IMX21_CLK_GPIO_GATE] = imx_clk_gate("gpio_gate", "ipg", CCM_PCCR0, 11); | ||
94 | clk[IMX21_CLK_I2C_GATE] = imx_clk_gate("i2c_gate", "ipg", CCM_PCCR0, 12); | ||
95 | clk[IMX21_CLK_DMA_GATE] = imx_clk_gate("dma_gate", "ipg", CCM_PCCR0, 13); | ||
96 | clk[IMX21_CLK_USB_GATE] = imx_clk_gate("usb_gate", "usb_div", CCM_PCCR0, 14); | ||
97 | clk[IMX21_CLK_EMMA_GATE] = imx_clk_gate("emma_gate", "ipg", CCM_PCCR0, 15); | ||
98 | clk[IMX21_CLK_SSI2_BAUD_GATE] = imx_clk_gate("ssi2_baud_gate", "ipg", CCM_PCCR0, 16); | ||
99 | clk[IMX21_CLK_SSI1_BAUD_GATE] = imx_clk_gate("ssi1_baud_gate", "ipg", CCM_PCCR0, 17); | ||
100 | clk[IMX21_CLK_LCDC_IPG_GATE] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 18); | ||
101 | clk[IMX21_CLK_NFC_GATE] = imx_clk_gate("nfc_gate", "nfc_div", CCM_PCCR0, 19); | ||
102 | clk[IMX21_CLK_SLCDC_HCLK_GATE] = imx_clk_gate("slcdc_hclk_gate", "hclk", CCM_PCCR0, 21); | ||
103 | clk[IMX21_CLK_PER4_GATE] = imx_clk_gate("per4_gate", "per4", CCM_PCCR0, 22); | ||
104 | clk[IMX21_CLK_BMI_GATE] = imx_clk_gate("bmi_gate", "hclk", CCM_PCCR0, 23); | ||
105 | clk[IMX21_CLK_USB_HCLK_GATE] = imx_clk_gate("usb_hclk_gate", "hclk", CCM_PCCR0, 24); | ||
106 | clk[IMX21_CLK_SLCDC_GATE] = imx_clk_gate("slcdc_gate", "hclk", CCM_PCCR0, 25); | ||
107 | clk[IMX21_CLK_LCDC_HCLK_GATE] = imx_clk_gate("lcdc_hclk_gate", "hclk", CCM_PCCR0, 26); | ||
108 | clk[IMX21_CLK_EMMA_HCLK_GATE] = imx_clk_gate("emma_hclk_gate", "hclk", CCM_PCCR0, 27); | ||
109 | clk[IMX21_CLK_BROM_GATE] = imx_clk_gate("brom_gate", "hclk", CCM_PCCR0, 28); | ||
110 | clk[IMX21_CLK_DMA_HCLK_GATE] = imx_clk_gate("dma_hclk_gate", "hclk", CCM_PCCR0, 30); | ||
111 | clk[IMX21_CLK_CSI_HCLK_GATE] = imx_clk_gate("csi_hclk_gate", "hclk", CCM_PCCR0, 31); | ||
112 | |||
113 | clk[IMX21_CLK_CSPI3_IPG_GATE] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR1, 23); | ||
114 | clk[IMX21_CLK_WDOG_GATE] = imx_clk_gate("wdog_gate", "ipg", CCM_PCCR1, 24); | ||
115 | clk[IMX21_CLK_GPT1_IPG_GATE] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR1, 25); | ||
116 | clk[IMX21_CLK_GPT2_IPG_GATE] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR1, 26); | ||
117 | clk[IMX21_CLK_GPT3_IPG_GATE] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR1, 27); | ||
118 | clk[IMX21_CLK_PWM_IPG_GATE] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR1, 28); | ||
119 | clk[IMX21_CLK_RTC_GATE] = imx_clk_gate("rtc_gate", "ipg", CCM_PCCR1, 29); | ||
120 | clk[IMX21_CLK_KPP_GATE] = imx_clk_gate("kpp_gate", "ipg", CCM_PCCR1, 30); | ||
121 | clk[IMX21_CLK_OWIRE_GATE] = imx_clk_gate("owire_gate", "ipg", CCM_PCCR1, 31); | ||
122 | |||
123 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
124 | } | ||
125 | |||
126 | int __init mx21_clocks_init(unsigned long lref, unsigned long href) | ||
127 | { | ||
128 | ccm = ioremap(MX21_CCM_BASE_ADDR, SZ_2K); | ||
129 | |||
130 | _mx21_clocks_init(lref, href); | ||
131 | |||
132 | clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.0"); | ||
133 | clk_register_clkdev(clk[IMX21_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0"); | ||
134 | clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.1"); | ||
135 | clk_register_clkdev(clk[IMX21_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1"); | ||
136 | clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.2"); | ||
137 | clk_register_clkdev(clk[IMX21_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2"); | ||
138 | clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.3"); | ||
139 | clk_register_clkdev(clk[IMX21_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3"); | ||
140 | clk_register_clkdev(clk[IMX21_CLK_GPT1_IPG_GATE], "ipg", "imx-gpt.0"); | ||
141 | clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx-gpt.0"); | ||
142 | clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.0"); | ||
143 | clk_register_clkdev(clk[IMX21_CLK_CSPI1_IPG_GATE], "ipg", "imx21-cspi.0"); | ||
144 | clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.1"); | ||
145 | clk_register_clkdev(clk[IMX21_CLK_CSPI2_IPG_GATE], "ipg", "imx21-cspi.1"); | ||
146 | clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.2"); | ||
147 | clk_register_clkdev(clk[IMX21_CLK_CSPI3_IPG_GATE], "ipg", "imx21-cspi.2"); | ||
148 | clk_register_clkdev(clk[IMX21_CLK_PER3], "per", "imx21-fb.0"); | ||
149 | clk_register_clkdev(clk[IMX21_CLK_LCDC_IPG_GATE], "ipg", "imx21-fb.0"); | ||
150 | clk_register_clkdev(clk[IMX21_CLK_LCDC_HCLK_GATE], "ahb", "imx21-fb.0"); | ||
151 | clk_register_clkdev(clk[IMX21_CLK_USB_GATE], "per", "imx21-hcd.0"); | ||
152 | clk_register_clkdev(clk[IMX21_CLK_USB_HCLK_GATE], "ahb", "imx21-hcd.0"); | ||
153 | clk_register_clkdev(clk[IMX21_CLK_NFC_GATE], NULL, "imx21-nand.0"); | ||
154 | clk_register_clkdev(clk[IMX21_CLK_DMA_HCLK_GATE], "ahb", "imx21-dma"); | ||
155 | clk_register_clkdev(clk[IMX21_CLK_DMA_GATE], "ipg", "imx21-dma"); | ||
156 | clk_register_clkdev(clk[IMX21_CLK_WDOG_GATE], NULL, "imx2-wdt.0"); | ||
157 | clk_register_clkdev(clk[IMX21_CLK_I2C_GATE], NULL, "imx21-i2c.0"); | ||
158 | clk_register_clkdev(clk[IMX21_CLK_OWIRE_GATE], NULL, "mxc_w1.0"); | ||
159 | |||
160 | mxc_timer_init(MX21_GPT1_BASE_ADDR, MX21_INT_GPT1, GPT_TYPE_IMX21); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static void __init mx21_clocks_init_dt(struct device_node *np) | ||
166 | { | ||
167 | ccm = of_iomap(np, 0); | ||
168 | |||
169 | _mx21_clocks_init(32768, 26000000); | ||
170 | |||
171 | clk_data.clks = clk; | ||
172 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
173 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
174 | } | ||
175 | CLK_OF_DECLARE(imx27_ccm, "fsl,imx21-ccm", mx21_clocks_init_dt); | ||
diff --git a/drivers/clk/imx/clk-imx25.c b/drivers/clk/imx/clk-imx25.c new file mode 100644 index 000000000000..ec1a4c1dacf1 --- /dev/null +++ b/drivers/clk/imx/clk-imx25.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 by Sascha Hauer, Pengutronix | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||
16 | * MA 02110-1301, USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/clkdev.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/of_address.h> | ||
28 | #include <linux/of_irq.h> | ||
29 | |||
30 | #include "clk.h" | ||
31 | |||
32 | #define CCM_MPCTL 0x00 | ||
33 | #define CCM_UPCTL 0x04 | ||
34 | #define CCM_CCTL 0x08 | ||
35 | #define CCM_CGCR0 0x0C | ||
36 | #define CCM_CGCR1 0x10 | ||
37 | #define CCM_CGCR2 0x14 | ||
38 | #define CCM_PCDR0 0x18 | ||
39 | #define CCM_PCDR1 0x1C | ||
40 | #define CCM_PCDR2 0x20 | ||
41 | #define CCM_PCDR3 0x24 | ||
42 | #define CCM_RCSR 0x28 | ||
43 | #define CCM_CRDR 0x2C | ||
44 | #define CCM_DCVR0 0x30 | ||
45 | #define CCM_DCVR1 0x34 | ||
46 | #define CCM_DCVR2 0x38 | ||
47 | #define CCM_DCVR3 0x3c | ||
48 | #define CCM_LTR0 0x40 | ||
49 | #define CCM_LTR1 0x44 | ||
50 | #define CCM_LTR2 0x48 | ||
51 | #define CCM_LTR3 0x4c | ||
52 | #define CCM_MCR 0x64 | ||
53 | |||
54 | #define ccm(x) (ccm_base + (x)) | ||
55 | |||
56 | static struct clk_onecell_data clk_data; | ||
57 | |||
58 | static const char *cpu_sel_clks[] = { "mpll", "mpll_cpu_3_4", }; | ||
59 | static const char *per_sel_clks[] = { "ahb", "upll", }; | ||
60 | static const char *cko_sel_clks[] = { "dummy", "osc", "cpu", "ahb", | ||
61 | "ipg", "dummy", "dummy", "dummy", | ||
62 | "dummy", "dummy", "per0", "per2", | ||
63 | "per13", "per14", "usbotg_ahb", "dummy",}; | ||
64 | |||
65 | enum mx25_clks { | ||
66 | dummy, osc, mpll, upll, mpll_cpu_3_4, cpu_sel, cpu, ahb, usb_div, ipg, | ||
67 | per0_sel, per1_sel, per2_sel, per3_sel, per4_sel, per5_sel, per6_sel, | ||
68 | per7_sel, per8_sel, per9_sel, per10_sel, per11_sel, per12_sel, | ||
69 | per13_sel, per14_sel, per15_sel, per0, per1, per2, per3, per4, per5, | ||
70 | per6, per7, per8, per9, per10, per11, per12, per13, per14, per15, | ||
71 | csi_ipg_per, epit_ipg_per, esai_ipg_per, esdhc1_ipg_per, esdhc2_ipg_per, | ||
72 | gpt_ipg_per, i2c_ipg_per, lcdc_ipg_per, nfc_ipg_per, owire_ipg_per, | ||
73 | pwm_ipg_per, sim1_ipg_per, sim2_ipg_per, ssi1_ipg_per, ssi2_ipg_per, | ||
74 | uart_ipg_per, ata_ahb, reserved1, csi_ahb, emi_ahb, esai_ahb, esdhc1_ahb, | ||
75 | esdhc2_ahb, fec_ahb, lcdc_ahb, rtic_ahb, sdma_ahb, slcdc_ahb, usbotg_ahb, | ||
76 | reserved2, reserved3, reserved4, reserved5, can1_ipg, can2_ipg, csi_ipg, | ||
77 | cspi1_ipg, cspi2_ipg, cspi3_ipg, dryice_ipg, ect_ipg, epit1_ipg, epit2_ipg, | ||
78 | reserved6, esdhc1_ipg, esdhc2_ipg, fec_ipg, reserved7, reserved8, reserved9, | ||
79 | gpt1_ipg, gpt2_ipg, gpt3_ipg, gpt4_ipg, reserved10, reserved11, reserved12, | ||
80 | iim_ipg, reserved13, reserved14, kpp_ipg, lcdc_ipg, reserved15, pwm1_ipg, | ||
81 | pwm2_ipg, pwm3_ipg, pwm4_ipg, rngb_ipg, reserved16, scc_ipg, sdma_ipg, | ||
82 | sim1_ipg, sim2_ipg, slcdc_ipg, spba_ipg, ssi1_ipg, ssi2_ipg, tsc_ipg, | ||
83 | uart1_ipg, uart2_ipg, uart3_ipg, uart4_ipg, uart5_ipg, reserved17, | ||
84 | wdt_ipg, cko_div, cko_sel, cko, clk_max | ||
85 | }; | ||
86 | |||
87 | static struct clk *clk[clk_max]; | ||
88 | |||
89 | static int __init __mx25_clocks_init(unsigned long osc_rate, | ||
90 | void __iomem *ccm_base) | ||
91 | { | ||
92 | BUG_ON(!ccm_base); | ||
93 | |||
94 | clk[dummy] = imx_clk_fixed("dummy", 0); | ||
95 | clk[osc] = imx_clk_fixed("osc", osc_rate); | ||
96 | clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "mpll", "osc", ccm(CCM_MPCTL)); | ||
97 | clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "upll", "osc", ccm(CCM_UPCTL)); | ||
98 | clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4); | ||
99 | clk[cpu_sel] = imx_clk_mux("cpu_sel", ccm(CCM_CCTL), 14, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks)); | ||
100 | clk[cpu] = imx_clk_divider("cpu", "cpu_sel", ccm(CCM_CCTL), 30, 2); | ||
101 | clk[ahb] = imx_clk_divider("ahb", "cpu", ccm(CCM_CCTL), 28, 2); | ||
102 | clk[usb_div] = imx_clk_divider("usb_div", "upll", ccm(CCM_CCTL), 16, 6); | ||
103 | clk[ipg] = imx_clk_fixed_factor("ipg", "ahb", 1, 2); | ||
104 | clk[per0_sel] = imx_clk_mux("per0_sel", ccm(CCM_MCR), 0, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
105 | clk[per1_sel] = imx_clk_mux("per1_sel", ccm(CCM_MCR), 1, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
106 | clk[per2_sel] = imx_clk_mux("per2_sel", ccm(CCM_MCR), 2, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
107 | clk[per3_sel] = imx_clk_mux("per3_sel", ccm(CCM_MCR), 3, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
108 | clk[per4_sel] = imx_clk_mux("per4_sel", ccm(CCM_MCR), 4, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
109 | clk[per5_sel] = imx_clk_mux("per5_sel", ccm(CCM_MCR), 5, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
110 | clk[per6_sel] = imx_clk_mux("per6_sel", ccm(CCM_MCR), 6, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
111 | clk[per7_sel] = imx_clk_mux("per7_sel", ccm(CCM_MCR), 7, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
112 | clk[per8_sel] = imx_clk_mux("per8_sel", ccm(CCM_MCR), 8, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
113 | clk[per9_sel] = imx_clk_mux("per9_sel", ccm(CCM_MCR), 9, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
114 | clk[per10_sel] = imx_clk_mux("per10_sel", ccm(CCM_MCR), 10, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
115 | clk[per11_sel] = imx_clk_mux("per11_sel", ccm(CCM_MCR), 11, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
116 | clk[per12_sel] = imx_clk_mux("per12_sel", ccm(CCM_MCR), 12, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
117 | clk[per13_sel] = imx_clk_mux("per13_sel", ccm(CCM_MCR), 13, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
118 | clk[per14_sel] = imx_clk_mux("per14_sel", ccm(CCM_MCR), 14, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
119 | clk[per15_sel] = imx_clk_mux("per15_sel", ccm(CCM_MCR), 15, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); | ||
120 | clk[cko_div] = imx_clk_divider("cko_div", "cko_sel", ccm(CCM_MCR), 24, 6); | ||
121 | clk[cko_sel] = imx_clk_mux("cko_sel", ccm(CCM_MCR), 20, 4, cko_sel_clks, ARRAY_SIZE(cko_sel_clks)); | ||
122 | clk[cko] = imx_clk_gate("cko", "cko_div", ccm(CCM_MCR), 30); | ||
123 | clk[per0] = imx_clk_divider("per0", "per0_sel", ccm(CCM_PCDR0), 0, 6); | ||
124 | clk[per1] = imx_clk_divider("per1", "per1_sel", ccm(CCM_PCDR0), 8, 6); | ||
125 | clk[per2] = imx_clk_divider("per2", "per2_sel", ccm(CCM_PCDR0), 16, 6); | ||
126 | clk[per3] = imx_clk_divider("per3", "per3_sel", ccm(CCM_PCDR0), 24, 6); | ||
127 | clk[per4] = imx_clk_divider("per4", "per4_sel", ccm(CCM_PCDR1), 0, 6); | ||
128 | clk[per5] = imx_clk_divider("per5", "per5_sel", ccm(CCM_PCDR1), 8, 6); | ||
129 | clk[per6] = imx_clk_divider("per6", "per6_sel", ccm(CCM_PCDR1), 16, 6); | ||
130 | clk[per7] = imx_clk_divider("per7", "per7_sel", ccm(CCM_PCDR1), 24, 6); | ||
131 | clk[per8] = imx_clk_divider("per8", "per8_sel", ccm(CCM_PCDR2), 0, 6); | ||
132 | clk[per9] = imx_clk_divider("per9", "per9_sel", ccm(CCM_PCDR2), 8, 6); | ||
133 | clk[per10] = imx_clk_divider("per10", "per10_sel", ccm(CCM_PCDR2), 16, 6); | ||
134 | clk[per11] = imx_clk_divider("per11", "per11_sel", ccm(CCM_PCDR2), 24, 6); | ||
135 | clk[per12] = imx_clk_divider("per12", "per12_sel", ccm(CCM_PCDR3), 0, 6); | ||
136 | clk[per13] = imx_clk_divider("per13", "per13_sel", ccm(CCM_PCDR3), 8, 6); | ||
137 | clk[per14] = imx_clk_divider("per14", "per14_sel", ccm(CCM_PCDR3), 16, 6); | ||
138 | clk[per15] = imx_clk_divider("per15", "per15_sel", ccm(CCM_PCDR3), 24, 6); | ||
139 | clk[csi_ipg_per] = imx_clk_gate("csi_ipg_per", "per0", ccm(CCM_CGCR0), 0); | ||
140 | clk[epit_ipg_per] = imx_clk_gate("epit_ipg_per", "per1", ccm(CCM_CGCR0), 1); | ||
141 | clk[esai_ipg_per] = imx_clk_gate("esai_ipg_per", "per2", ccm(CCM_CGCR0), 2); | ||
142 | clk[esdhc1_ipg_per] = imx_clk_gate("esdhc1_ipg_per", "per3", ccm(CCM_CGCR0), 3); | ||
143 | clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0), 4); | ||
144 | clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0), 5); | ||
145 | clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0), 6); | ||
146 | clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0), 7); | ||
147 | clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0), 8); | ||
148 | clk[owire_ipg_per] = imx_clk_gate("owire_ipg_per", "per9", ccm(CCM_CGCR0), 9); | ||
149 | clk[pwm_ipg_per] = imx_clk_gate("pwm_ipg_per", "per10", ccm(CCM_CGCR0), 10); | ||
150 | clk[sim1_ipg_per] = imx_clk_gate("sim1_ipg_per", "per11", ccm(CCM_CGCR0), 11); | ||
151 | clk[sim2_ipg_per] = imx_clk_gate("sim2_ipg_per", "per12", ccm(CCM_CGCR0), 12); | ||
152 | clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13); | ||
153 | clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14); | ||
154 | clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15); | ||
155 | clk[ata_ahb] = imx_clk_gate("ata_ahb", "ahb", ccm(CCM_CGCR0), 16); | ||
156 | /* CCM_CGCR0(17): reserved */ | ||
157 | clk[csi_ahb] = imx_clk_gate("csi_ahb", "ahb", ccm(CCM_CGCR0), 18); | ||
158 | clk[emi_ahb] = imx_clk_gate("emi_ahb", "ahb", ccm(CCM_CGCR0), 19); | ||
159 | clk[esai_ahb] = imx_clk_gate("esai_ahb", "ahb", ccm(CCM_CGCR0), 20); | ||
160 | clk[esdhc1_ahb] = imx_clk_gate("esdhc1_ahb", "ahb", ccm(CCM_CGCR0), 21); | ||
161 | clk[esdhc2_ahb] = imx_clk_gate("esdhc2_ahb", "ahb", ccm(CCM_CGCR0), 22); | ||
162 | clk[fec_ahb] = imx_clk_gate("fec_ahb", "ahb", ccm(CCM_CGCR0), 23); | ||
163 | clk[lcdc_ahb] = imx_clk_gate("lcdc_ahb", "ahb", ccm(CCM_CGCR0), 24); | ||
164 | clk[rtic_ahb] = imx_clk_gate("rtic_ahb", "ahb", ccm(CCM_CGCR0), 25); | ||
165 | clk[sdma_ahb] = imx_clk_gate("sdma_ahb", "ahb", ccm(CCM_CGCR0), 26); | ||
166 | clk[slcdc_ahb] = imx_clk_gate("slcdc_ahb", "ahb", ccm(CCM_CGCR0), 27); | ||
167 | clk[usbotg_ahb] = imx_clk_gate("usbotg_ahb", "ahb", ccm(CCM_CGCR0), 28); | ||
168 | /* CCM_CGCR0(29-31): reserved */ | ||
169 | /* CCM_CGCR1(0): reserved in datasheet, used as audmux in FSL kernel */ | ||
170 | clk[can1_ipg] = imx_clk_gate("can1_ipg", "ipg", ccm(CCM_CGCR1), 2); | ||
171 | clk[can2_ipg] = imx_clk_gate("can2_ipg", "ipg", ccm(CCM_CGCR1), 3); | ||
172 | clk[csi_ipg] = imx_clk_gate("csi_ipg", "ipg", ccm(CCM_CGCR1), 4); | ||
173 | clk[cspi1_ipg] = imx_clk_gate("cspi1_ipg", "ipg", ccm(CCM_CGCR1), 5); | ||
174 | clk[cspi2_ipg] = imx_clk_gate("cspi2_ipg", "ipg", ccm(CCM_CGCR1), 6); | ||
175 | clk[cspi3_ipg] = imx_clk_gate("cspi3_ipg", "ipg", ccm(CCM_CGCR1), 7); | ||
176 | clk[dryice_ipg] = imx_clk_gate("dryice_ipg", "ipg", ccm(CCM_CGCR1), 8); | ||
177 | clk[ect_ipg] = imx_clk_gate("ect_ipg", "ipg", ccm(CCM_CGCR1), 9); | ||
178 | clk[epit1_ipg] = imx_clk_gate("epit1_ipg", "ipg", ccm(CCM_CGCR1), 10); | ||
179 | clk[epit2_ipg] = imx_clk_gate("epit2_ipg", "ipg", ccm(CCM_CGCR1), 11); | ||
180 | /* CCM_CGCR1(12): reserved in datasheet, used as esai in FSL kernel */ | ||
181 | clk[esdhc1_ipg] = imx_clk_gate("esdhc1_ipg", "ipg", ccm(CCM_CGCR1), 13); | ||
182 | clk[esdhc2_ipg] = imx_clk_gate("esdhc2_ipg", "ipg", ccm(CCM_CGCR1), 14); | ||
183 | clk[fec_ipg] = imx_clk_gate("fec_ipg", "ipg", ccm(CCM_CGCR1), 15); | ||
184 | /* CCM_CGCR1(16): reserved in datasheet, used as gpio1 in FSL kernel */ | ||
185 | /* CCM_CGCR1(17): reserved in datasheet, used as gpio2 in FSL kernel */ | ||
186 | /* CCM_CGCR1(18): reserved in datasheet, used as gpio3 in FSL kernel */ | ||
187 | clk[gpt1_ipg] = imx_clk_gate("gpt1_ipg", "ipg", ccm(CCM_CGCR1), 19); | ||
188 | clk[gpt2_ipg] = imx_clk_gate("gpt2_ipg", "ipg", ccm(CCM_CGCR1), 20); | ||
189 | clk[gpt3_ipg] = imx_clk_gate("gpt3_ipg", "ipg", ccm(CCM_CGCR1), 21); | ||
190 | clk[gpt4_ipg] = imx_clk_gate("gpt4_ipg", "ipg", ccm(CCM_CGCR1), 22); | ||
191 | /* CCM_CGCR1(23): reserved in datasheet, used as i2c1 in FSL kernel */ | ||
192 | /* CCM_CGCR1(24): reserved in datasheet, used as i2c2 in FSL kernel */ | ||
193 | /* CCM_CGCR1(25): reserved in datasheet, used as i2c3 in FSL kernel */ | ||
194 | clk[iim_ipg] = imx_clk_gate("iim_ipg", "ipg", ccm(CCM_CGCR1), 26); | ||
195 | /* CCM_CGCR1(27): reserved in datasheet, used as iomuxc in FSL kernel */ | ||
196 | /* CCM_CGCR1(28): reserved in datasheet, used as kpp in FSL kernel */ | ||
197 | clk[kpp_ipg] = imx_clk_gate("kpp_ipg", "ipg", ccm(CCM_CGCR1), 28); | ||
198 | clk[lcdc_ipg] = imx_clk_gate("lcdc_ipg", "ipg", ccm(CCM_CGCR1), 29); | ||
199 | /* CCM_CGCR1(30): reserved in datasheet, used as owire in FSL kernel */ | ||
200 | clk[pwm1_ipg] = imx_clk_gate("pwm1_ipg", "ipg", ccm(CCM_CGCR1), 31); | ||
201 | clk[pwm2_ipg] = imx_clk_gate("pwm2_ipg", "ipg", ccm(CCM_CGCR2), 0); | ||
202 | clk[pwm3_ipg] = imx_clk_gate("pwm3_ipg", "ipg", ccm(CCM_CGCR2), 1); | ||
203 | clk[pwm4_ipg] = imx_clk_gate("pwm4_ipg", "ipg", ccm(CCM_CGCR2), 2); | ||
204 | clk[rngb_ipg] = imx_clk_gate("rngb_ipg", "ipg", ccm(CCM_CGCR2), 3); | ||
205 | /* CCM_CGCR2(4): reserved in datasheet, used as rtic in FSL kernel */ | ||
206 | clk[scc_ipg] = imx_clk_gate("scc_ipg", "ipg", ccm(CCM_CGCR2), 5); | ||
207 | clk[sdma_ipg] = imx_clk_gate("sdma_ipg", "ipg", ccm(CCM_CGCR2), 6); | ||
208 | clk[sim1_ipg] = imx_clk_gate("sim1_ipg", "ipg", ccm(CCM_CGCR2), 7); | ||
209 | clk[sim2_ipg] = imx_clk_gate("sim2_ipg", "ipg", ccm(CCM_CGCR2), 8); | ||
210 | clk[slcdc_ipg] = imx_clk_gate("slcdc_ipg", "ipg", ccm(CCM_CGCR2), 9); | ||
211 | clk[spba_ipg] = imx_clk_gate("spba_ipg", "ipg", ccm(CCM_CGCR2), 10); | ||
212 | clk[ssi1_ipg] = imx_clk_gate("ssi1_ipg", "ipg", ccm(CCM_CGCR2), 11); | ||
213 | clk[ssi2_ipg] = imx_clk_gate("ssi2_ipg", "ipg", ccm(CCM_CGCR2), 12); | ||
214 | clk[tsc_ipg] = imx_clk_gate("tsc_ipg", "ipg", ccm(CCM_CGCR2), 13); | ||
215 | clk[uart1_ipg] = imx_clk_gate("uart1_ipg", "ipg", ccm(CCM_CGCR2), 14); | ||
216 | clk[uart2_ipg] = imx_clk_gate("uart2_ipg", "ipg", ccm(CCM_CGCR2), 15); | ||
217 | clk[uart3_ipg] = imx_clk_gate("uart3_ipg", "ipg", ccm(CCM_CGCR2), 16); | ||
218 | clk[uart4_ipg] = imx_clk_gate("uart4_ipg", "ipg", ccm(CCM_CGCR2), 17); | ||
219 | clk[uart5_ipg] = imx_clk_gate("uart5_ipg", "ipg", ccm(CCM_CGCR2), 18); | ||
220 | /* CCM_CGCR2(19): reserved in datasheet, but used as wdt in FSL kernel */ | ||
221 | clk[wdt_ipg] = imx_clk_gate("wdt_ipg", "ipg", ccm(CCM_CGCR2), 19); | ||
222 | |||
223 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
224 | |||
225 | clk_prepare_enable(clk[emi_ahb]); | ||
226 | |||
227 | /* Clock source for gpt must be derived from AHB */ | ||
228 | clk_set_parent(clk[per5_sel], clk[ahb]); | ||
229 | |||
230 | /* | ||
231 | * Let's initially set up CLKO parent as ipg, since this configuration | ||
232 | * is used on some imx25 board designs to clock the audio codec. | ||
233 | */ | ||
234 | clk_set_parent(clk[cko_sel], clk[ipg]); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static void __init mx25_clocks_init_dt(struct device_node *np) | ||
240 | { | ||
241 | struct device_node *refnp; | ||
242 | unsigned long osc_rate = 24000000; | ||
243 | void __iomem *ccm; | ||
244 | |||
245 | /* retrieve the freqency of fixed clocks from device tree */ | ||
246 | for_each_compatible_node(refnp, NULL, "fixed-clock") { | ||
247 | u32 rate; | ||
248 | if (of_property_read_u32(refnp, "clock-frequency", &rate)) | ||
249 | continue; | ||
250 | |||
251 | if (of_device_is_compatible(refnp, "fsl,imx-osc")) | ||
252 | osc_rate = rate; | ||
253 | } | ||
254 | |||
255 | ccm = of_iomap(np, 0); | ||
256 | __mx25_clocks_init(osc_rate, ccm); | ||
257 | |||
258 | clk_data.clks = clk; | ||
259 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
260 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
261 | } | ||
262 | CLK_OF_DECLARE(imx25_ccm, "fsl,imx25-ccm", mx25_clocks_init_dt); | ||
diff --git a/drivers/clk/imx/clk-imx27.c b/drivers/clk/imx/clk-imx27.c new file mode 100644 index 000000000000..d9d50d54ef2a --- /dev/null +++ b/drivers/clk/imx/clk-imx27.c | |||
@@ -0,0 +1,263 @@ | |||
1 | #include <linux/clk.h> | ||
2 | #include <linux/clk-provider.h> | ||
3 | #include <linux/clkdev.h> | ||
4 | #include <linux/err.h> | ||
5 | #include <linux/of.h> | ||
6 | #include <linux/of_address.h> | ||
7 | #include <dt-bindings/clock/imx27-clock.h> | ||
8 | #include <soc/imx/revision.h> | ||
9 | #include <soc/imx/timer.h> | ||
10 | #include <asm/irq.h> | ||
11 | |||
12 | #include "clk.h" | ||
13 | |||
14 | #define MX27_CCM_BASE_ADDR 0x10027000 | ||
15 | #define MX27_GPT1_BASE_ADDR 0x10003000 | ||
16 | #define MX27_INT_GPT1 (NR_IRQS_LEGACY + 26) | ||
17 | |||
18 | static void __iomem *ccm __initdata; | ||
19 | |||
20 | /* Register offsets */ | ||
21 | #define CCM_CSCR (ccm + 0x00) | ||
22 | #define CCM_MPCTL0 (ccm + 0x04) | ||
23 | #define CCM_MPCTL1 (ccm + 0x08) | ||
24 | #define CCM_SPCTL0 (ccm + 0x0c) | ||
25 | #define CCM_SPCTL1 (ccm + 0x10) | ||
26 | #define CCM_PCDR0 (ccm + 0x18) | ||
27 | #define CCM_PCDR1 (ccm + 0x1c) | ||
28 | #define CCM_PCCR0 (ccm + 0x20) | ||
29 | #define CCM_PCCR1 (ccm + 0x24) | ||
30 | #define CCM_CCSR (ccm + 0x28) | ||
31 | |||
32 | static const char *vpu_sel_clks[] = { "spll", "mpll_main2", }; | ||
33 | static const char *cpu_sel_clks[] = { "mpll_main2", "mpll", }; | ||
34 | static const char *mpll_sel_clks[] = { "fpm", "mpll_osc_sel", }; | ||
35 | static const char *mpll_osc_sel_clks[] = { "ckih_gate", "ckih_div1p5", }; | ||
36 | static const char *clko_sel_clks[] = { | ||
37 | "ckil", "fpm", "ckih_gate", "ckih_gate", | ||
38 | "ckih_gate", "mpll", "spll", "cpu_div", | ||
39 | "ahb", "ipg", "per1_div", "per2_div", | ||
40 | "per3_div", "per4_div", "ssi1_div", "ssi2_div", | ||
41 | "nfc_div", "mshc_div", "vpu_div", "60m", | ||
42 | "32k", "usb_div", "dptc", | ||
43 | }; | ||
44 | |||
45 | static const char *ssi_sel_clks[] = { "spll_gate", "mpll", }; | ||
46 | |||
47 | static struct clk *clk[IMX27_CLK_MAX]; | ||
48 | static struct clk_onecell_data clk_data; | ||
49 | |||
50 | static void __init _mx27_clocks_init(unsigned long fref) | ||
51 | { | ||
52 | BUG_ON(!ccm); | ||
53 | |||
54 | clk[IMX27_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
55 | clk[IMX27_CLK_CKIH] = imx_clk_fixed("ckih", fref); | ||
56 | clk[IMX27_CLK_CKIL] = imx_clk_fixed("ckil", 32768); | ||
57 | clk[IMX27_CLK_FPM] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1); | ||
58 | clk[IMX27_CLK_CKIH_DIV1P5] = imx_clk_fixed_factor("ckih_div1p5", "ckih_gate", 2, 3); | ||
59 | clk[IMX27_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3); | ||
60 | clk[IMX27_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks)); | ||
61 | clk[IMX27_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks)); | ||
62 | clk[IMX27_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX27, "mpll", "mpll_sel", CCM_MPCTL0); | ||
63 | clk[IMX27_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX27, "spll", "ckih_gate", CCM_SPCTL0); | ||
64 | clk[IMX27_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); | ||
65 | clk[IMX27_CLK_MPLL_MAIN2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3); | ||
66 | |||
67 | if (mx27_revision() >= IMX_CHIP_REVISION_2_0) { | ||
68 | clk[IMX27_CLK_AHB] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 8, 2); | ||
69 | clk[IMX27_CLK_IPG] = imx_clk_fixed_factor("ipg", "ahb", 1, 2); | ||
70 | } else { | ||
71 | clk[IMX27_CLK_AHB] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 9, 4); | ||
72 | clk[IMX27_CLK_IPG] = imx_clk_divider("ipg", "ahb", CCM_CSCR, 8, 1); | ||
73 | } | ||
74 | |||
75 | clk[IMX27_CLK_MSHC_DIV] = imx_clk_divider("mshc_div", "ahb", CCM_PCDR0, 0, 6); | ||
76 | clk[IMX27_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4); | ||
77 | clk[IMX27_CLK_PER1_DIV] = imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6); | ||
78 | clk[IMX27_CLK_PER2_DIV] = imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6); | ||
79 | clk[IMX27_CLK_PER3_DIV] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6); | ||
80 | clk[IMX27_CLK_PER4_DIV] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6); | ||
81 | clk[IMX27_CLK_VPU_SEL] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks)); | ||
82 | clk[IMX27_CLK_VPU_DIV] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6); | ||
83 | clk[IMX27_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 28, 3); | ||
84 | clk[IMX27_CLK_CPU_SEL] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks)); | ||
85 | clk[IMX27_CLK_CLKO_SEL] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); | ||
86 | |||
87 | if (mx27_revision() >= IMX_CHIP_REVISION_2_0) | ||
88 | clk[IMX27_CLK_CPU_DIV] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 12, 2); | ||
89 | else | ||
90 | clk[IMX27_CLK_CPU_DIV] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 13, 3); | ||
91 | |||
92 | clk[IMX27_CLK_CLKO_DIV] = imx_clk_divider("clko_div", "clko_sel", CCM_PCDR0, 22, 3); | ||
93 | clk[IMX27_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks)); | ||
94 | clk[IMX27_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks)); | ||
95 | clk[IMX27_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6); | ||
96 | clk[IMX27_CLK_SSI2_DIV] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6); | ||
97 | clk[IMX27_CLK_CLKO_EN] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0); | ||
98 | clk[IMX27_CLK_SSI2_IPG_GATE] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0); | ||
99 | clk[IMX27_CLK_SSI1_IPG_GATE] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1); | ||
100 | clk[IMX27_CLK_SLCDC_IPG_GATE] = imx_clk_gate("slcdc_ipg_gate", "ipg", CCM_PCCR0, 2); | ||
101 | clk[IMX27_CLK_SDHC3_IPG_GATE] = imx_clk_gate("sdhc3_ipg_gate", "ipg", CCM_PCCR0, 3); | ||
102 | clk[IMX27_CLK_SDHC2_IPG_GATE] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 4); | ||
103 | clk[IMX27_CLK_SDHC1_IPG_GATE] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5); | ||
104 | clk[IMX27_CLK_SCC_IPG_GATE] = imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6); | ||
105 | clk[IMX27_CLK_SAHARA_IPG_GATE] = imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7); | ||
106 | clk[IMX27_CLK_RTIC_IPG_GATE] = imx_clk_gate("rtic_ipg_gate", "ipg", CCM_PCCR0, 8); | ||
107 | clk[IMX27_CLK_RTC_IPG_GATE] = imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9); | ||
108 | clk[IMX27_CLK_PWM_IPG_GATE] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11); | ||
109 | clk[IMX27_CLK_OWIRE_IPG_GATE] = imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12); | ||
110 | clk[IMX27_CLK_MSHC_IPG_GATE] = imx_clk_gate("mshc_ipg_gate", "ipg", CCM_PCCR0, 13); | ||
111 | clk[IMX27_CLK_LCDC_IPG_GATE] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14); | ||
112 | clk[IMX27_CLK_KPP_IPG_GATE] = imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15); | ||
113 | clk[IMX27_CLK_IIM_IPG_GATE] = imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16); | ||
114 | clk[IMX27_CLK_I2C2_IPG_GATE] = imx_clk_gate("i2c2_ipg_gate", "ipg", CCM_PCCR0, 17); | ||
115 | clk[IMX27_CLK_I2C1_IPG_GATE] = imx_clk_gate("i2c1_ipg_gate", "ipg", CCM_PCCR0, 18); | ||
116 | clk[IMX27_CLK_GPT6_IPG_GATE] = imx_clk_gate("gpt6_ipg_gate", "ipg", CCM_PCCR0, 19); | ||
117 | clk[IMX27_CLK_GPT5_IPG_GATE] = imx_clk_gate("gpt5_ipg_gate", "ipg", CCM_PCCR0, 20); | ||
118 | clk[IMX27_CLK_GPT4_IPG_GATE] = imx_clk_gate("gpt4_ipg_gate", "ipg", CCM_PCCR0, 21); | ||
119 | clk[IMX27_CLK_GPT3_IPG_GATE] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR0, 22); | ||
120 | clk[IMX27_CLK_GPT2_IPG_GATE] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR0, 23); | ||
121 | clk[IMX27_CLK_GPT1_IPG_GATE] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR0, 24); | ||
122 | clk[IMX27_CLK_GPIO_IPG_GATE] = imx_clk_gate("gpio_ipg_gate", "ipg", CCM_PCCR0, 25); | ||
123 | clk[IMX27_CLK_FEC_IPG_GATE] = imx_clk_gate("fec_ipg_gate", "ipg", CCM_PCCR0, 26); | ||
124 | clk[IMX27_CLK_EMMA_IPG_GATE] = imx_clk_gate("emma_ipg_gate", "ipg", CCM_PCCR0, 27); | ||
125 | clk[IMX27_CLK_DMA_IPG_GATE] = imx_clk_gate("dma_ipg_gate", "ipg", CCM_PCCR0, 28); | ||
126 | clk[IMX27_CLK_CSPI3_IPG_GATE] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29); | ||
127 | clk[IMX27_CLK_CSPI2_IPG_GATE] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30); | ||
128 | clk[IMX27_CLK_CSPI1_IPG_GATE] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31); | ||
129 | clk[IMX27_CLK_MSHC_BAUD_GATE] = imx_clk_gate("mshc_baud_gate", "mshc_div", CCM_PCCR1, 2); | ||
130 | clk[IMX27_CLK_NFC_BAUD_GATE] = imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1, 3); | ||
131 | clk[IMX27_CLK_SSI2_BAUD_GATE] = imx_clk_gate("ssi2_baud_gate", "ssi2_div", CCM_PCCR1, 4); | ||
132 | clk[IMX27_CLK_SSI1_BAUD_GATE] = imx_clk_gate("ssi1_baud_gate", "ssi1_div", CCM_PCCR1, 5); | ||
133 | clk[IMX27_CLK_VPU_BAUD_GATE] = imx_clk_gate("vpu_baud_gate", "vpu_div", CCM_PCCR1, 6); | ||
134 | clk[IMX27_CLK_PER4_GATE] = imx_clk_gate("per4_gate", "per4_div", CCM_PCCR1, 7); | ||
135 | clk[IMX27_CLK_PER3_GATE] = imx_clk_gate("per3_gate", "per3_div", CCM_PCCR1, 8); | ||
136 | clk[IMX27_CLK_PER2_GATE] = imx_clk_gate("per2_gate", "per2_div", CCM_PCCR1, 9); | ||
137 | clk[IMX27_CLK_PER1_GATE] = imx_clk_gate("per1_gate", "per1_div", CCM_PCCR1, 10); | ||
138 | clk[IMX27_CLK_USB_AHB_GATE] = imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11); | ||
139 | clk[IMX27_CLK_SLCDC_AHB_GATE] = imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12); | ||
140 | clk[IMX27_CLK_SAHARA_AHB_GATE] = imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13); | ||
141 | clk[IMX27_CLK_RTIC_AHB_GATE] = imx_clk_gate("rtic_ahb_gate", "ahb", CCM_PCCR1, 14); | ||
142 | clk[IMX27_CLK_LCDC_AHB_GATE] = imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15); | ||
143 | clk[IMX27_CLK_VPU_AHB_GATE] = imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16); | ||
144 | clk[IMX27_CLK_FEC_AHB_GATE] = imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17); | ||
145 | clk[IMX27_CLK_EMMA_AHB_GATE] = imx_clk_gate("emma_ahb_gate", "ahb", CCM_PCCR1, 18); | ||
146 | clk[IMX27_CLK_EMI_AHB_GATE] = imx_clk_gate("emi_ahb_gate", "ahb", CCM_PCCR1, 19); | ||
147 | clk[IMX27_CLK_DMA_AHB_GATE] = imx_clk_gate("dma_ahb_gate", "ahb", CCM_PCCR1, 20); | ||
148 | clk[IMX27_CLK_CSI_AHB_GATE] = imx_clk_gate("csi_ahb_gate", "ahb", CCM_PCCR1, 21); | ||
149 | clk[IMX27_CLK_BROM_AHB_GATE] = imx_clk_gate("brom_ahb_gate", "ahb", CCM_PCCR1, 22); | ||
150 | clk[IMX27_CLK_ATA_AHB_GATE] = imx_clk_gate("ata_ahb_gate", "ahb", CCM_PCCR1, 23); | ||
151 | clk[IMX27_CLK_WDOG_IPG_GATE] = imx_clk_gate("wdog_ipg_gate", "ipg", CCM_PCCR1, 24); | ||
152 | clk[IMX27_CLK_USB_IPG_GATE] = imx_clk_gate("usb_ipg_gate", "ipg", CCM_PCCR1, 25); | ||
153 | clk[IMX27_CLK_UART6_IPG_GATE] = imx_clk_gate("uart6_ipg_gate", "ipg", CCM_PCCR1, 26); | ||
154 | clk[IMX27_CLK_UART5_IPG_GATE] = imx_clk_gate("uart5_ipg_gate", "ipg", CCM_PCCR1, 27); | ||
155 | clk[IMX27_CLK_UART4_IPG_GATE] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR1, 28); | ||
156 | clk[IMX27_CLK_UART3_IPG_GATE] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29); | ||
157 | clk[IMX27_CLK_UART2_IPG_GATE] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30); | ||
158 | clk[IMX27_CLK_UART1_IPG_GATE] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31); | ||
159 | |||
160 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
161 | |||
162 | clk_register_clkdev(clk[IMX27_CLK_CPU_DIV], NULL, "cpu0"); | ||
163 | |||
164 | clk_prepare_enable(clk[IMX27_CLK_EMI_AHB_GATE]); | ||
165 | |||
166 | imx_print_silicon_rev("i.MX27", mx27_revision()); | ||
167 | } | ||
168 | |||
169 | int __init mx27_clocks_init(unsigned long fref) | ||
170 | { | ||
171 | ccm = ioremap(MX27_CCM_BASE_ADDR, SZ_4K); | ||
172 | |||
173 | _mx27_clocks_init(fref); | ||
174 | |||
175 | clk_register_clkdev(clk[IMX27_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0"); | ||
176 | clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.0"); | ||
177 | clk_register_clkdev(clk[IMX27_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1"); | ||
178 | clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.1"); | ||
179 | clk_register_clkdev(clk[IMX27_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2"); | ||
180 | clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.2"); | ||
181 | clk_register_clkdev(clk[IMX27_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3"); | ||
182 | clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.3"); | ||
183 | clk_register_clkdev(clk[IMX27_CLK_UART5_IPG_GATE], "ipg", "imx21-uart.4"); | ||
184 | clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.4"); | ||
185 | clk_register_clkdev(clk[IMX27_CLK_UART6_IPG_GATE], "ipg", "imx21-uart.5"); | ||
186 | clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.5"); | ||
187 | clk_register_clkdev(clk[IMX27_CLK_GPT1_IPG_GATE], "ipg", "imx-gpt.0"); | ||
188 | clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx-gpt.0"); | ||
189 | clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.0"); | ||
190 | clk_register_clkdev(clk[IMX27_CLK_SDHC1_IPG_GATE], "ipg", "imx21-mmc.0"); | ||
191 | clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.1"); | ||
192 | clk_register_clkdev(clk[IMX27_CLK_SDHC2_IPG_GATE], "ipg", "imx21-mmc.1"); | ||
193 | clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.2"); | ||
194 | clk_register_clkdev(clk[IMX27_CLK_SDHC2_IPG_GATE], "ipg", "imx21-mmc.2"); | ||
195 | clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.0"); | ||
196 | clk_register_clkdev(clk[IMX27_CLK_CSPI1_IPG_GATE], "ipg", "imx27-cspi.0"); | ||
197 | clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.1"); | ||
198 | clk_register_clkdev(clk[IMX27_CLK_CSPI2_IPG_GATE], "ipg", "imx27-cspi.1"); | ||
199 | clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.2"); | ||
200 | clk_register_clkdev(clk[IMX27_CLK_CSPI3_IPG_GATE], "ipg", "imx27-cspi.2"); | ||
201 | clk_register_clkdev(clk[IMX27_CLK_PER3_GATE], "per", "imx21-fb.0"); | ||
202 | clk_register_clkdev(clk[IMX27_CLK_LCDC_IPG_GATE], "ipg", "imx21-fb.0"); | ||
203 | clk_register_clkdev(clk[IMX27_CLK_LCDC_AHB_GATE], "ahb", "imx21-fb.0"); | ||
204 | clk_register_clkdev(clk[IMX27_CLK_CSI_AHB_GATE], "ahb", "imx27-camera.0"); | ||
205 | clk_register_clkdev(clk[IMX27_CLK_PER4_GATE], "per", "imx27-camera.0"); | ||
206 | clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "imx-udc-mx27"); | ||
207 | clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "imx-udc-mx27"); | ||
208 | clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "imx-udc-mx27"); | ||
209 | clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.0"); | ||
210 | clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.0"); | ||
211 | clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.0"); | ||
212 | clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.1"); | ||
213 | clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.1"); | ||
214 | clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.1"); | ||
215 | clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.2"); | ||
216 | clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.2"); | ||
217 | clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.2"); | ||
218 | clk_register_clkdev(clk[IMX27_CLK_SSI1_IPG_GATE], NULL, "imx-ssi.0"); | ||
219 | clk_register_clkdev(clk[IMX27_CLK_SSI2_IPG_GATE], NULL, "imx-ssi.1"); | ||
220 | clk_register_clkdev(clk[IMX27_CLK_NFC_BAUD_GATE], NULL, "imx27-nand.0"); | ||
221 | clk_register_clkdev(clk[IMX27_CLK_VPU_BAUD_GATE], "per", "coda-imx27.0"); | ||
222 | clk_register_clkdev(clk[IMX27_CLK_VPU_AHB_GATE], "ahb", "coda-imx27.0"); | ||
223 | clk_register_clkdev(clk[IMX27_CLK_DMA_AHB_GATE], "ahb", "imx27-dma"); | ||
224 | clk_register_clkdev(clk[IMX27_CLK_DMA_IPG_GATE], "ipg", "imx27-dma"); | ||
225 | clk_register_clkdev(clk[IMX27_CLK_FEC_IPG_GATE], "ipg", "imx27-fec.0"); | ||
226 | clk_register_clkdev(clk[IMX27_CLK_FEC_AHB_GATE], "ahb", "imx27-fec.0"); | ||
227 | clk_register_clkdev(clk[IMX27_CLK_WDOG_IPG_GATE], NULL, "imx2-wdt.0"); | ||
228 | clk_register_clkdev(clk[IMX27_CLK_I2C1_IPG_GATE], NULL, "imx21-i2c.0"); | ||
229 | clk_register_clkdev(clk[IMX27_CLK_I2C2_IPG_GATE], NULL, "imx21-i2c.1"); | ||
230 | clk_register_clkdev(clk[IMX27_CLK_OWIRE_IPG_GATE], NULL, "mxc_w1.0"); | ||
231 | clk_register_clkdev(clk[IMX27_CLK_KPP_IPG_GATE], NULL, "imx-keypad"); | ||
232 | clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "emma-ahb", "imx27-camera.0"); | ||
233 | clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "emma-ipg", "imx27-camera.0"); | ||
234 | clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "ahb", "m2m-emmaprp.0"); | ||
235 | clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "ipg", "m2m-emmaprp.0"); | ||
236 | |||
237 | mxc_timer_init(MX27_GPT1_BASE_ADDR, MX27_INT_GPT1, GPT_TYPE_IMX21); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static void __init mx27_clocks_init_dt(struct device_node *np) | ||
243 | { | ||
244 | struct device_node *refnp; | ||
245 | u32 fref = 26000000; /* default */ | ||
246 | |||
247 | for_each_compatible_node(refnp, NULL, "fixed-clock") { | ||
248 | if (!of_device_is_compatible(refnp, "fsl,imx-osc26m")) | ||
249 | continue; | ||
250 | |||
251 | if (!of_property_read_u32(refnp, "clock-frequency", &fref)) | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | ccm = of_iomap(np, 0); | ||
256 | |||
257 | _mx27_clocks_init(fref); | ||
258 | |||
259 | clk_data.clks = clk; | ||
260 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
261 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
262 | } | ||
263 | CLK_OF_DECLARE(imx27_ccm, "fsl,imx27-ccm", mx27_clocks_init_dt); | ||
diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c new file mode 100644 index 000000000000..fe66c40b7be2 --- /dev/null +++ b/drivers/clk/imx/clk-imx31.c | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Sascha Hauer <kernel@pengutronix.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/clkdev.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <soc/imx/revision.h> | ||
25 | #include <soc/imx/timer.h> | ||
26 | #include <asm/irq.h> | ||
27 | |||
28 | #include "clk.h" | ||
29 | |||
30 | #define MX31_CCM_BASE_ADDR 0x53f80000 | ||
31 | #define MX31_GPT1_BASE_ADDR 0x53f90000 | ||
32 | #define MX31_INT_GPT (NR_IRQS_LEGACY + 29) | ||
33 | |||
34 | #define MXC_CCM_CCMR 0x00 | ||
35 | #define MXC_CCM_PDR0 0x04 | ||
36 | #define MXC_CCM_PDR1 0x08 | ||
37 | #define MXC_CCM_MPCTL 0x10 | ||
38 | #define MXC_CCM_UPCTL 0x14 | ||
39 | #define MXC_CCM_SRPCTL 0x18 | ||
40 | #define MXC_CCM_CGR0 0x20 | ||
41 | #define MXC_CCM_CGR1 0x24 | ||
42 | #define MXC_CCM_CGR2 0x28 | ||
43 | #define MXC_CCM_PMCR0 0x5c | ||
44 | |||
45 | static const char *mcu_main_sel[] = { "spll", "mpll", }; | ||
46 | static const char *per_sel[] = { "per_div", "ipg", }; | ||
47 | static const char *csi_sel[] = { "upll", "spll", }; | ||
48 | static const char *fir_sel[] = { "mcu_main", "upll", "spll" }; | ||
49 | |||
50 | enum mx31_clks { | ||
51 | dummy, ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg, | ||
52 | per_div, per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre, | ||
53 | fir_div_post, sdhc1_gate, sdhc2_gate, gpt_gate, epit1_gate, epit2_gate, | ||
54 | iim_gate, ata_gate, sdma_gate, cspi3_gate, rng_gate, uart1_gate, | ||
55 | uart2_gate, ssi1_gate, i2c1_gate, i2c2_gate, i2c3_gate, hantro_gate, | ||
56 | mstick1_gate, mstick2_gate, csi_gate, rtc_gate, wdog_gate, pwm_gate, | ||
57 | sim_gate, ect_gate, usb_gate, kpp_gate, ipu_gate, uart3_gate, | ||
58 | uart4_gate, uart5_gate, owire_gate, ssi2_gate, cspi1_gate, cspi2_gate, | ||
59 | gacc_gate, emi_gate, rtic_gate, firi_gate, clk_max | ||
60 | }; | ||
61 | |||
62 | static struct clk *clk[clk_max]; | ||
63 | static struct clk_onecell_data clk_data; | ||
64 | |||
65 | int __init mx31_clocks_init(unsigned long fref) | ||
66 | { | ||
67 | void __iomem *base; | ||
68 | struct device_node *np; | ||
69 | |||
70 | base = ioremap(MX31_CCM_BASE_ADDR, SZ_4K); | ||
71 | BUG_ON(!base); | ||
72 | |||
73 | clk[dummy] = imx_clk_fixed("dummy", 0); | ||
74 | clk[ckih] = imx_clk_fixed("ckih", fref); | ||
75 | clk[ckil] = imx_clk_fixed("ckil", 32768); | ||
76 | clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "mpll", "ckih", base + MXC_CCM_MPCTL); | ||
77 | clk[spll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "spll", "ckih", base + MXC_CCM_SRPCTL); | ||
78 | clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "upll", "ckih", base + MXC_CCM_UPCTL); | ||
79 | clk[mcu_main] = imx_clk_mux("mcu_main", base + MXC_CCM_PMCR0, 31, 1, mcu_main_sel, ARRAY_SIZE(mcu_main_sel)); | ||
80 | clk[hsp] = imx_clk_divider("hsp", "mcu_main", base + MXC_CCM_PDR0, 11, 3); | ||
81 | clk[ahb] = imx_clk_divider("ahb", "mcu_main", base + MXC_CCM_PDR0, 3, 3); | ||
82 | clk[nfc] = imx_clk_divider("nfc", "ahb", base + MXC_CCM_PDR0, 8, 3); | ||
83 | clk[ipg] = imx_clk_divider("ipg", "ahb", base + MXC_CCM_PDR0, 6, 2); | ||
84 | clk[per_div] = imx_clk_divider("per_div", "upll", base + MXC_CCM_PDR0, 16, 5); | ||
85 | clk[per] = imx_clk_mux("per", base + MXC_CCM_CCMR, 24, 1, per_sel, ARRAY_SIZE(per_sel)); | ||
86 | clk[csi] = imx_clk_mux("csi_sel", base + MXC_CCM_CCMR, 25, 1, csi_sel, ARRAY_SIZE(csi_sel)); | ||
87 | clk[fir] = imx_clk_mux("fir_sel", base + MXC_CCM_CCMR, 11, 2, fir_sel, ARRAY_SIZE(fir_sel)); | ||
88 | clk[csi_div] = imx_clk_divider("csi_div", "csi_sel", base + MXC_CCM_PDR0, 23, 9); | ||
89 | clk[usb_div_pre] = imx_clk_divider("usb_div_pre", "upll", base + MXC_CCM_PDR1, 30, 2); | ||
90 | clk[usb_div_post] = imx_clk_divider("usb_div_post", "usb_div_pre", base + MXC_CCM_PDR1, 27, 3); | ||
91 | clk[fir_div_pre] = imx_clk_divider("fir_div_pre", "fir_sel", base + MXC_CCM_PDR1, 24, 3); | ||
92 | clk[fir_div_post] = imx_clk_divider("fir_div_post", "fir_div_pre", base + MXC_CCM_PDR1, 23, 6); | ||
93 | clk[sdhc1_gate] = imx_clk_gate2("sdhc1_gate", "per", base + MXC_CCM_CGR0, 0); | ||
94 | clk[sdhc2_gate] = imx_clk_gate2("sdhc2_gate", "per", base + MXC_CCM_CGR0, 2); | ||
95 | clk[gpt_gate] = imx_clk_gate2("gpt_gate", "per", base + MXC_CCM_CGR0, 4); | ||
96 | clk[epit1_gate] = imx_clk_gate2("epit1_gate", "per", base + MXC_CCM_CGR0, 6); | ||
97 | clk[epit2_gate] = imx_clk_gate2("epit2_gate", "per", base + MXC_CCM_CGR0, 8); | ||
98 | clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", base + MXC_CCM_CGR0, 10); | ||
99 | clk[ata_gate] = imx_clk_gate2("ata_gate", "ipg", base + MXC_CCM_CGR0, 12); | ||
100 | clk[sdma_gate] = imx_clk_gate2("sdma_gate", "ahb", base + MXC_CCM_CGR0, 14); | ||
101 | clk[cspi3_gate] = imx_clk_gate2("cspi3_gate", "ipg", base + MXC_CCM_CGR0, 16); | ||
102 | clk[rng_gate] = imx_clk_gate2("rng_gate", "ipg", base + MXC_CCM_CGR0, 18); | ||
103 | clk[uart1_gate] = imx_clk_gate2("uart1_gate", "per", base + MXC_CCM_CGR0, 20); | ||
104 | clk[uart2_gate] = imx_clk_gate2("uart2_gate", "per", base + MXC_CCM_CGR0, 22); | ||
105 | clk[ssi1_gate] = imx_clk_gate2("ssi1_gate", "spll", base + MXC_CCM_CGR0, 24); | ||
106 | clk[i2c1_gate] = imx_clk_gate2("i2c1_gate", "per", base + MXC_CCM_CGR0, 26); | ||
107 | clk[i2c2_gate] = imx_clk_gate2("i2c2_gate", "per", base + MXC_CCM_CGR0, 28); | ||
108 | clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per", base + MXC_CCM_CGR0, 30); | ||
109 | clk[hantro_gate] = imx_clk_gate2("hantro_gate", "per", base + MXC_CCM_CGR1, 0); | ||
110 | clk[mstick1_gate] = imx_clk_gate2("mstick1_gate", "per", base + MXC_CCM_CGR1, 2); | ||
111 | clk[mstick2_gate] = imx_clk_gate2("mstick2_gate", "per", base + MXC_CCM_CGR1, 4); | ||
112 | clk[csi_gate] = imx_clk_gate2("csi_gate", "csi_div", base + MXC_CCM_CGR1, 6); | ||
113 | clk[rtc_gate] = imx_clk_gate2("rtc_gate", "ipg", base + MXC_CCM_CGR1, 8); | ||
114 | clk[wdog_gate] = imx_clk_gate2("wdog_gate", "ipg", base + MXC_CCM_CGR1, 10); | ||
115 | clk[pwm_gate] = imx_clk_gate2("pwm_gate", "per", base + MXC_CCM_CGR1, 12); | ||
116 | clk[sim_gate] = imx_clk_gate2("sim_gate", "per", base + MXC_CCM_CGR1, 14); | ||
117 | clk[ect_gate] = imx_clk_gate2("ect_gate", "per", base + MXC_CCM_CGR1, 16); | ||
118 | clk[usb_gate] = imx_clk_gate2("usb_gate", "ahb", base + MXC_CCM_CGR1, 18); | ||
119 | clk[kpp_gate] = imx_clk_gate2("kpp_gate", "ipg", base + MXC_CCM_CGR1, 20); | ||
120 | clk[ipu_gate] = imx_clk_gate2("ipu_gate", "hsp", base + MXC_CCM_CGR1, 22); | ||
121 | clk[uart3_gate] = imx_clk_gate2("uart3_gate", "per", base + MXC_CCM_CGR1, 24); | ||
122 | clk[uart4_gate] = imx_clk_gate2("uart4_gate", "per", base + MXC_CCM_CGR1, 26); | ||
123 | clk[uart5_gate] = imx_clk_gate2("uart5_gate", "per", base + MXC_CCM_CGR1, 28); | ||
124 | clk[owire_gate] = imx_clk_gate2("owire_gate", "per", base + MXC_CCM_CGR1, 30); | ||
125 | clk[ssi2_gate] = imx_clk_gate2("ssi2_gate", "spll", base + MXC_CCM_CGR2, 0); | ||
126 | clk[cspi1_gate] = imx_clk_gate2("cspi1_gate", "ipg", base + MXC_CCM_CGR2, 2); | ||
127 | clk[cspi2_gate] = imx_clk_gate2("cspi2_gate", "ipg", base + MXC_CCM_CGR2, 4); | ||
128 | clk[gacc_gate] = imx_clk_gate2("gacc_gate", "per", base + MXC_CCM_CGR2, 6); | ||
129 | clk[emi_gate] = imx_clk_gate2("emi_gate", "ahb", base + MXC_CCM_CGR2, 8); | ||
130 | clk[rtic_gate] = imx_clk_gate2("rtic_gate", "ahb", base + MXC_CCM_CGR2, 10); | ||
131 | clk[firi_gate] = imx_clk_gate2("firi_gate", "upll", base+MXC_CCM_CGR2, 12); | ||
132 | |||
133 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
134 | |||
135 | np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm"); | ||
136 | |||
137 | if (np) { | ||
138 | clk_data.clks = clk; | ||
139 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
140 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
141 | } | ||
142 | |||
143 | clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0"); | ||
144 | clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0"); | ||
145 | clk_register_clkdev(clk[cspi1_gate], NULL, "imx31-cspi.0"); | ||
146 | clk_register_clkdev(clk[cspi2_gate], NULL, "imx31-cspi.1"); | ||
147 | clk_register_clkdev(clk[cspi3_gate], NULL, "imx31-cspi.2"); | ||
148 | clk_register_clkdev(clk[pwm_gate], "pwm", NULL); | ||
149 | clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0"); | ||
150 | clk_register_clkdev(clk[rtc_gate], NULL, "imx21-rtc"); | ||
151 | clk_register_clkdev(clk[epit1_gate], "epit", NULL); | ||
152 | clk_register_clkdev(clk[epit2_gate], "epit", NULL); | ||
153 | clk_register_clkdev(clk[nfc], NULL, "imx27-nand.0"); | ||
154 | clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core"); | ||
155 | clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); | ||
156 | clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad"); | ||
157 | clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.0"); | ||
158 | clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.0"); | ||
159 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0"); | ||
160 | clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.1"); | ||
161 | clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.1"); | ||
162 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.1"); | ||
163 | clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2"); | ||
164 | clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2"); | ||
165 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); | ||
166 | clk_register_clkdev(clk[usb_div_post], "per", "imx-udc-mx27"); | ||
167 | clk_register_clkdev(clk[usb_gate], "ahb", "imx-udc-mx27"); | ||
168 | clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27"); | ||
169 | clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); | ||
170 | /* i.mx31 has the i.mx21 type uart */ | ||
171 | clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); | ||
172 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0"); | ||
173 | clk_register_clkdev(clk[uart2_gate], "per", "imx21-uart.1"); | ||
174 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.1"); | ||
175 | clk_register_clkdev(clk[uart3_gate], "per", "imx21-uart.2"); | ||
176 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.2"); | ||
177 | clk_register_clkdev(clk[uart4_gate], "per", "imx21-uart.3"); | ||
178 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.3"); | ||
179 | clk_register_clkdev(clk[uart5_gate], "per", "imx21-uart.4"); | ||
180 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.4"); | ||
181 | clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0"); | ||
182 | clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1"); | ||
183 | clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2"); | ||
184 | clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0"); | ||
185 | clk_register_clkdev(clk[sdhc1_gate], NULL, "imx31-mmc.0"); | ||
186 | clk_register_clkdev(clk[sdhc2_gate], NULL, "imx31-mmc.1"); | ||
187 | clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0"); | ||
188 | clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1"); | ||
189 | clk_register_clkdev(clk[firi_gate], "firi", NULL); | ||
190 | clk_register_clkdev(clk[ata_gate], NULL, "pata_imx"); | ||
191 | clk_register_clkdev(clk[rtic_gate], "rtic", NULL); | ||
192 | clk_register_clkdev(clk[rng_gate], NULL, "mxc_rnga"); | ||
193 | clk_register_clkdev(clk[sdma_gate], NULL, "imx31-sdma"); | ||
194 | clk_register_clkdev(clk[iim_gate], "iim", NULL); | ||
195 | |||
196 | clk_set_parent(clk[csi], clk[upll]); | ||
197 | clk_prepare_enable(clk[emi_gate]); | ||
198 | clk_prepare_enable(clk[iim_gate]); | ||
199 | mx31_revision(); | ||
200 | clk_disable_unprepare(clk[iim_gate]); | ||
201 | |||
202 | mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT, GPT_TYPE_IMX31); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | int __init mx31_clocks_init_dt(void) | ||
208 | { | ||
209 | struct device_node *np; | ||
210 | u32 fref = 26000000; /* default */ | ||
211 | |||
212 | for_each_compatible_node(np, NULL, "fixed-clock") { | ||
213 | if (!of_device_is_compatible(np, "fsl,imx-osc26m")) | ||
214 | continue; | ||
215 | |||
216 | if (!of_property_read_u32(np, "clock-frequency", &fref)) | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | return mx31_clocks_init(fref); | ||
221 | } | ||
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c new file mode 100644 index 000000000000..69138ba3dec7 --- /dev/null +++ b/drivers/clk/imx/clk-imx35.c | |||
@@ -0,0 +1,310 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | */ | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/clk.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <soc/imx/revision.h> | ||
17 | #include <soc/imx/timer.h> | ||
18 | #include <asm/irq.h> | ||
19 | |||
20 | #include "clk.h" | ||
21 | |||
22 | #define MX35_CCM_BASE_ADDR 0x53f80000 | ||
23 | #define MX35_GPT1_BASE_ADDR 0x53f90000 | ||
24 | #define MX35_INT_GPT (NR_IRQS_LEGACY + 29) | ||
25 | |||
26 | #define MXC_CCM_PDR0 0x04 | ||
27 | #define MX35_CCM_PDR2 0x0c | ||
28 | #define MX35_CCM_PDR3 0x10 | ||
29 | #define MX35_CCM_PDR4 0x14 | ||
30 | #define MX35_CCM_MPCTL 0x1c | ||
31 | #define MX35_CCM_PPCTL 0x20 | ||
32 | #define MX35_CCM_CGR0 0x2c | ||
33 | #define MX35_CCM_CGR1 0x30 | ||
34 | #define MX35_CCM_CGR2 0x34 | ||
35 | #define MX35_CCM_CGR3 0x38 | ||
36 | |||
37 | struct arm_ahb_div { | ||
38 | unsigned char arm, ahb, sel; | ||
39 | }; | ||
40 | |||
41 | static struct arm_ahb_div clk_consumer[] = { | ||
42 | { .arm = 1, .ahb = 4, .sel = 0}, | ||
43 | { .arm = 1, .ahb = 3, .sel = 1}, | ||
44 | { .arm = 2, .ahb = 2, .sel = 0}, | ||
45 | { .arm = 0, .ahb = 0, .sel = 0}, | ||
46 | { .arm = 0, .ahb = 0, .sel = 0}, | ||
47 | { .arm = 0, .ahb = 0, .sel = 0}, | ||
48 | { .arm = 4, .ahb = 1, .sel = 0}, | ||
49 | { .arm = 1, .ahb = 5, .sel = 0}, | ||
50 | { .arm = 1, .ahb = 8, .sel = 0}, | ||
51 | { .arm = 1, .ahb = 6, .sel = 1}, | ||
52 | { .arm = 2, .ahb = 4, .sel = 0}, | ||
53 | { .arm = 0, .ahb = 0, .sel = 0}, | ||
54 | { .arm = 0, .ahb = 0, .sel = 0}, | ||
55 | { .arm = 0, .ahb = 0, .sel = 0}, | ||
56 | { .arm = 4, .ahb = 2, .sel = 0}, | ||
57 | { .arm = 0, .ahb = 0, .sel = 0}, | ||
58 | }; | ||
59 | |||
60 | static char hsp_div_532[] = { 4, 8, 3, 0 }; | ||
61 | static char hsp_div_400[] = { 3, 6, 3, 0 }; | ||
62 | |||
63 | static struct clk_onecell_data clk_data; | ||
64 | |||
65 | static const char *std_sel[] = {"ppll", "arm"}; | ||
66 | static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"}; | ||
67 | |||
68 | enum mx35_clks { | ||
69 | ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg, | ||
70 | arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel, | ||
71 | esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre, | ||
72 | spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre, | ||
73 | ssi2_div_post, usb_sel, usb_div, nfc_div, asrc_gate, pata_gate, | ||
74 | audmux_gate, can1_gate, can2_gate, cspi1_gate, cspi2_gate, ect_gate, | ||
75 | edio_gate, emi_gate, epit1_gate, epit2_gate, esai_gate, esdhc1_gate, | ||
76 | esdhc2_gate, esdhc3_gate, fec_gate, gpio1_gate, gpio2_gate, gpio3_gate, | ||
77 | gpt_gate, i2c1_gate, i2c2_gate, i2c3_gate, iomuxc_gate, ipu_gate, | ||
78 | kpp_gate, mlb_gate, mshc_gate, owire_gate, pwm_gate, rngc_gate, | ||
79 | rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate, | ||
80 | ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate, | ||
81 | wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate, | ||
82 | gpu2d_gate, clk_max | ||
83 | }; | ||
84 | |||
85 | static struct clk *clk[clk_max]; | ||
86 | |||
87 | int __init mx35_clocks_init(void) | ||
88 | { | ||
89 | void __iomem *base; | ||
90 | u32 pdr0, consumer_sel, hsp_sel; | ||
91 | struct arm_ahb_div *aad; | ||
92 | unsigned char *hsp_div; | ||
93 | |||
94 | base = ioremap(MX35_CCM_BASE_ADDR, SZ_4K); | ||
95 | BUG_ON(!base); | ||
96 | |||
97 | pdr0 = __raw_readl(base + MXC_CCM_PDR0); | ||
98 | consumer_sel = (pdr0 >> 16) & 0xf; | ||
99 | aad = &clk_consumer[consumer_sel]; | ||
100 | if (!aad->arm) { | ||
101 | pr_err("i.MX35 clk: illegal consumer mux selection 0x%x\n", consumer_sel); | ||
102 | /* | ||
103 | * We are basically stuck. Continue with a default entry and hope we | ||
104 | * get far enough to actually show the above message | ||
105 | */ | ||
106 | aad = &clk_consumer[0]; | ||
107 | } | ||
108 | |||
109 | clk[ckih] = imx_clk_fixed("ckih", 24000000); | ||
110 | clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "mpll", "ckih", base + MX35_CCM_MPCTL); | ||
111 | clk[ppll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "ppll", "ckih", base + MX35_CCM_PPCTL); | ||
112 | |||
113 | clk[mpll] = imx_clk_fixed_factor("mpll_075", "mpll", 3, 4); | ||
114 | |||
115 | if (aad->sel) | ||
116 | clk[arm] = imx_clk_fixed_factor("arm", "mpll_075", 1, aad->arm); | ||
117 | else | ||
118 | clk[arm] = imx_clk_fixed_factor("arm", "mpll", 1, aad->arm); | ||
119 | |||
120 | if (clk_get_rate(clk[arm]) > 400000000) | ||
121 | hsp_div = hsp_div_532; | ||
122 | else | ||
123 | hsp_div = hsp_div_400; | ||
124 | |||
125 | hsp_sel = (pdr0 >> 20) & 0x3; | ||
126 | if (!hsp_div[hsp_sel]) { | ||
127 | pr_err("i.MX35 clk: illegal hsp clk selection 0x%x\n", hsp_sel); | ||
128 | hsp_sel = 0; | ||
129 | } | ||
130 | |||
131 | clk[hsp] = imx_clk_fixed_factor("hsp", "arm", 1, hsp_div[hsp_sel]); | ||
132 | |||
133 | clk[ahb] = imx_clk_fixed_factor("ahb", "arm", 1, aad->ahb); | ||
134 | clk[ipg] = imx_clk_fixed_factor("ipg", "ahb", 1, 2); | ||
135 | |||
136 | clk[arm_per_div] = imx_clk_divider("arm_per_div", "arm", base + MX35_CCM_PDR4, 16, 6); | ||
137 | clk[ahb_per_div] = imx_clk_divider("ahb_per_div", "ahb", base + MXC_CCM_PDR0, 12, 3); | ||
138 | clk[ipg_per] = imx_clk_mux("ipg_per", base + MXC_CCM_PDR0, 26, 1, ipg_per_sel, ARRAY_SIZE(ipg_per_sel)); | ||
139 | |||
140 | clk[uart_sel] = imx_clk_mux("uart_sel", base + MX35_CCM_PDR3, 14, 1, std_sel, ARRAY_SIZE(std_sel)); | ||
141 | clk[uart_div] = imx_clk_divider("uart_div", "uart_sel", base + MX35_CCM_PDR4, 10, 6); | ||
142 | |||
143 | clk[esdhc_sel] = imx_clk_mux("esdhc_sel", base + MX35_CCM_PDR4, 9, 1, std_sel, ARRAY_SIZE(std_sel)); | ||
144 | clk[esdhc1_div] = imx_clk_divider("esdhc1_div", "esdhc_sel", base + MX35_CCM_PDR3, 0, 6); | ||
145 | clk[esdhc2_div] = imx_clk_divider("esdhc2_div", "esdhc_sel", base + MX35_CCM_PDR3, 8, 6); | ||
146 | clk[esdhc3_div] = imx_clk_divider("esdhc3_div", "esdhc_sel", base + MX35_CCM_PDR3, 16, 6); | ||
147 | |||
148 | clk[spdif_sel] = imx_clk_mux("spdif_sel", base + MX35_CCM_PDR3, 22, 1, std_sel, ARRAY_SIZE(std_sel)); | ||
149 | clk[spdif_div_pre] = imx_clk_divider("spdif_div_pre", "spdif_sel", base + MX35_CCM_PDR3, 29, 3); /* divide by 1 not allowed */ | ||
150 | clk[spdif_div_post] = imx_clk_divider("spdif_div_post", "spdif_div_pre", base + MX35_CCM_PDR3, 23, 6); | ||
151 | |||
152 | clk[ssi_sel] = imx_clk_mux("ssi_sel", base + MX35_CCM_PDR2, 6, 1, std_sel, ARRAY_SIZE(std_sel)); | ||
153 | clk[ssi1_div_pre] = imx_clk_divider("ssi1_div_pre", "ssi_sel", base + MX35_CCM_PDR2, 24, 3); | ||
154 | clk[ssi1_div_post] = imx_clk_divider("ssi1_div_post", "ssi1_div_pre", base + MX35_CCM_PDR2, 0, 6); | ||
155 | clk[ssi2_div_pre] = imx_clk_divider("ssi2_div_pre", "ssi_sel", base + MX35_CCM_PDR2, 27, 3); | ||
156 | clk[ssi2_div_post] = imx_clk_divider("ssi2_div_post", "ssi2_div_pre", base + MX35_CCM_PDR2, 8, 6); | ||
157 | |||
158 | clk[usb_sel] = imx_clk_mux("usb_sel", base + MX35_CCM_PDR4, 9, 1, std_sel, ARRAY_SIZE(std_sel)); | ||
159 | clk[usb_div] = imx_clk_divider("usb_div", "usb_sel", base + MX35_CCM_PDR4, 22, 6); | ||
160 | |||
161 | clk[nfc_div] = imx_clk_divider("nfc_div", "ahb", base + MX35_CCM_PDR4, 28, 4); | ||
162 | |||
163 | clk[csi_sel] = imx_clk_mux("csi_sel", base + MX35_CCM_PDR2, 7, 1, std_sel, ARRAY_SIZE(std_sel)); | ||
164 | clk[csi_div] = imx_clk_divider("csi_div", "csi_sel", base + MX35_CCM_PDR2, 16, 6); | ||
165 | |||
166 | clk[asrc_gate] = imx_clk_gate2("asrc_gate", "ipg", base + MX35_CCM_CGR0, 0); | ||
167 | clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", base + MX35_CCM_CGR0, 2); | ||
168 | clk[audmux_gate] = imx_clk_gate2("audmux_gate", "ipg", base + MX35_CCM_CGR0, 4); | ||
169 | clk[can1_gate] = imx_clk_gate2("can1_gate", "ipg", base + MX35_CCM_CGR0, 6); | ||
170 | clk[can2_gate] = imx_clk_gate2("can2_gate", "ipg", base + MX35_CCM_CGR0, 8); | ||
171 | clk[cspi1_gate] = imx_clk_gate2("cspi1_gate", "ipg", base + MX35_CCM_CGR0, 10); | ||
172 | clk[cspi2_gate] = imx_clk_gate2("cspi2_gate", "ipg", base + MX35_CCM_CGR0, 12); | ||
173 | clk[ect_gate] = imx_clk_gate2("ect_gate", "ipg", base + MX35_CCM_CGR0, 14); | ||
174 | clk[edio_gate] = imx_clk_gate2("edio_gate", "ipg", base + MX35_CCM_CGR0, 16); | ||
175 | clk[emi_gate] = imx_clk_gate2("emi_gate", "ipg", base + MX35_CCM_CGR0, 18); | ||
176 | clk[epit1_gate] = imx_clk_gate2("epit1_gate", "ipg", base + MX35_CCM_CGR0, 20); | ||
177 | clk[epit2_gate] = imx_clk_gate2("epit2_gate", "ipg", base + MX35_CCM_CGR0, 22); | ||
178 | clk[esai_gate] = imx_clk_gate2("esai_gate", "ipg", base + MX35_CCM_CGR0, 24); | ||
179 | clk[esdhc1_gate] = imx_clk_gate2("esdhc1_gate", "esdhc1_div", base + MX35_CCM_CGR0, 26); | ||
180 | clk[esdhc2_gate] = imx_clk_gate2("esdhc2_gate", "esdhc2_div", base + MX35_CCM_CGR0, 28); | ||
181 | clk[esdhc3_gate] = imx_clk_gate2("esdhc3_gate", "esdhc3_div", base + MX35_CCM_CGR0, 30); | ||
182 | |||
183 | clk[fec_gate] = imx_clk_gate2("fec_gate", "ipg", base + MX35_CCM_CGR1, 0); | ||
184 | clk[gpio1_gate] = imx_clk_gate2("gpio1_gate", "ipg", base + MX35_CCM_CGR1, 2); | ||
185 | clk[gpio2_gate] = imx_clk_gate2("gpio2_gate", "ipg", base + MX35_CCM_CGR1, 4); | ||
186 | clk[gpio3_gate] = imx_clk_gate2("gpio3_gate", "ipg", base + MX35_CCM_CGR1, 6); | ||
187 | clk[gpt_gate] = imx_clk_gate2("gpt_gate", "ipg", base + MX35_CCM_CGR1, 8); | ||
188 | clk[i2c1_gate] = imx_clk_gate2("i2c1_gate", "ipg_per", base + MX35_CCM_CGR1, 10); | ||
189 | clk[i2c2_gate] = imx_clk_gate2("i2c2_gate", "ipg_per", base + MX35_CCM_CGR1, 12); | ||
190 | clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "ipg_per", base + MX35_CCM_CGR1, 14); | ||
191 | clk[iomuxc_gate] = imx_clk_gate2("iomuxc_gate", "ipg", base + MX35_CCM_CGR1, 16); | ||
192 | clk[ipu_gate] = imx_clk_gate2("ipu_gate", "hsp", base + MX35_CCM_CGR1, 18); | ||
193 | clk[kpp_gate] = imx_clk_gate2("kpp_gate", "ipg", base + MX35_CCM_CGR1, 20); | ||
194 | clk[mlb_gate] = imx_clk_gate2("mlb_gate", "ahb", base + MX35_CCM_CGR1, 22); | ||
195 | clk[mshc_gate] = imx_clk_gate2("mshc_gate", "dummy", base + MX35_CCM_CGR1, 24); | ||
196 | clk[owire_gate] = imx_clk_gate2("owire_gate", "ipg_per", base + MX35_CCM_CGR1, 26); | ||
197 | clk[pwm_gate] = imx_clk_gate2("pwm_gate", "ipg_per", base + MX35_CCM_CGR1, 28); | ||
198 | clk[rngc_gate] = imx_clk_gate2("rngc_gate", "ipg", base + MX35_CCM_CGR1, 30); | ||
199 | |||
200 | clk[rtc_gate] = imx_clk_gate2("rtc_gate", "ipg", base + MX35_CCM_CGR2, 0); | ||
201 | clk[rtic_gate] = imx_clk_gate2("rtic_gate", "ahb", base + MX35_CCM_CGR2, 2); | ||
202 | clk[scc_gate] = imx_clk_gate2("scc_gate", "ipg", base + MX35_CCM_CGR2, 4); | ||
203 | clk[sdma_gate] = imx_clk_gate2("sdma_gate", "ahb", base + MX35_CCM_CGR2, 6); | ||
204 | clk[spba_gate] = imx_clk_gate2("spba_gate", "ipg", base + MX35_CCM_CGR2, 8); | ||
205 | clk[spdif_gate] = imx_clk_gate2("spdif_gate", "spdif_div_post", base + MX35_CCM_CGR2, 10); | ||
206 | clk[ssi1_gate] = imx_clk_gate2("ssi1_gate", "ssi1_div_post", base + MX35_CCM_CGR2, 12); | ||
207 | clk[ssi2_gate] = imx_clk_gate2("ssi2_gate", "ssi2_div_post", base + MX35_CCM_CGR2, 14); | ||
208 | clk[uart1_gate] = imx_clk_gate2("uart1_gate", "uart_div", base + MX35_CCM_CGR2, 16); | ||
209 | clk[uart2_gate] = imx_clk_gate2("uart2_gate", "uart_div", base + MX35_CCM_CGR2, 18); | ||
210 | clk[uart3_gate] = imx_clk_gate2("uart3_gate", "uart_div", base + MX35_CCM_CGR2, 20); | ||
211 | clk[usbotg_gate] = imx_clk_gate2("usbotg_gate", "ahb", base + MX35_CCM_CGR2, 22); | ||
212 | clk[wdog_gate] = imx_clk_gate2("wdog_gate", "ipg", base + MX35_CCM_CGR2, 24); | ||
213 | clk[max_gate] = imx_clk_gate2("max_gate", "dummy", base + MX35_CCM_CGR2, 26); | ||
214 | clk[admux_gate] = imx_clk_gate2("admux_gate", "ipg", base + MX35_CCM_CGR2, 30); | ||
215 | |||
216 | clk[csi_gate] = imx_clk_gate2("csi_gate", "csi_div", base + MX35_CCM_CGR3, 0); | ||
217 | clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", base + MX35_CCM_CGR3, 2); | ||
218 | clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "ahb", base + MX35_CCM_CGR3, 4); | ||
219 | |||
220 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
221 | |||
222 | clk_register_clkdev(clk[pata_gate], NULL, "pata_imx"); | ||
223 | clk_register_clkdev(clk[can1_gate], NULL, "flexcan.0"); | ||
224 | clk_register_clkdev(clk[can2_gate], NULL, "flexcan.1"); | ||
225 | clk_register_clkdev(clk[cspi1_gate], "per", "imx35-cspi.0"); | ||
226 | clk_register_clkdev(clk[cspi1_gate], "ipg", "imx35-cspi.0"); | ||
227 | clk_register_clkdev(clk[cspi2_gate], "per", "imx35-cspi.1"); | ||
228 | clk_register_clkdev(clk[cspi2_gate], "ipg", "imx35-cspi.1"); | ||
229 | clk_register_clkdev(clk[epit1_gate], NULL, "imx-epit.0"); | ||
230 | clk_register_clkdev(clk[epit2_gate], NULL, "imx-epit.1"); | ||
231 | clk_register_clkdev(clk[esdhc1_gate], "per", "sdhci-esdhc-imx35.0"); | ||
232 | clk_register_clkdev(clk[ipg], "ipg", "sdhci-esdhc-imx35.0"); | ||
233 | clk_register_clkdev(clk[ahb], "ahb", "sdhci-esdhc-imx35.0"); | ||
234 | clk_register_clkdev(clk[esdhc2_gate], "per", "sdhci-esdhc-imx35.1"); | ||
235 | clk_register_clkdev(clk[ipg], "ipg", "sdhci-esdhc-imx35.1"); | ||
236 | clk_register_clkdev(clk[ahb], "ahb", "sdhci-esdhc-imx35.1"); | ||
237 | clk_register_clkdev(clk[esdhc3_gate], "per", "sdhci-esdhc-imx35.2"); | ||
238 | clk_register_clkdev(clk[ipg], "ipg", "sdhci-esdhc-imx35.2"); | ||
239 | clk_register_clkdev(clk[ahb], "ahb", "sdhci-esdhc-imx35.2"); | ||
240 | /* i.mx35 has the i.mx27 type fec */ | ||
241 | clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0"); | ||
242 | clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0"); | ||
243 | clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0"); | ||
244 | clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0"); | ||
245 | clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1"); | ||
246 | clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2"); | ||
247 | clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core"); | ||
248 | clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); | ||
249 | clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad"); | ||
250 | clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1"); | ||
251 | clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma"); | ||
252 | clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0"); | ||
253 | clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1"); | ||
254 | /* i.mx35 has the i.mx21 type uart */ | ||
255 | clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); | ||
256 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0"); | ||
257 | clk_register_clkdev(clk[uart2_gate], "per", "imx21-uart.1"); | ||
258 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.1"); | ||
259 | clk_register_clkdev(clk[uart3_gate], "per", "imx21-uart.2"); | ||
260 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.2"); | ||
261 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0"); | ||
262 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0"); | ||
263 | clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.0"); | ||
264 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.1"); | ||
265 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.1"); | ||
266 | clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.1"); | ||
267 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2"); | ||
268 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); | ||
269 | clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.2"); | ||
270 | clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27"); | ||
271 | clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27"); | ||
272 | clk_register_clkdev(clk[usbotg_gate], "ahb", "imx-udc-mx27"); | ||
273 | clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0"); | ||
274 | clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0"); | ||
275 | clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); | ||
276 | clk_register_clkdev(clk[admux_gate], "audmux", NULL); | ||
277 | |||
278 | clk_prepare_enable(clk[spba_gate]); | ||
279 | clk_prepare_enable(clk[gpio1_gate]); | ||
280 | clk_prepare_enable(clk[gpio2_gate]); | ||
281 | clk_prepare_enable(clk[gpio3_gate]); | ||
282 | clk_prepare_enable(clk[iim_gate]); | ||
283 | clk_prepare_enable(clk[emi_gate]); | ||
284 | clk_prepare_enable(clk[max_gate]); | ||
285 | clk_prepare_enable(clk[iomuxc_gate]); | ||
286 | |||
287 | /* | ||
288 | * SCC is needed to boot via mmc after a watchdog reset. The clock code | ||
289 | * before conversion to common clk also enabled UART1 (which isn't | ||
290 | * handled here and not needed for mmc) and IIM (which is enabled | ||
291 | * unconditionally above). | ||
292 | */ | ||
293 | clk_prepare_enable(clk[scc_gate]); | ||
294 | |||
295 | imx_print_silicon_rev("i.MX35", mx35_revision()); | ||
296 | |||
297 | mxc_timer_init(MX35_GPT1_BASE_ADDR, MX35_INT_GPT, GPT_TYPE_IMX31); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static void __init mx35_clocks_init_dt(struct device_node *ccm_node) | ||
303 | { | ||
304 | clk_data.clks = clk; | ||
305 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
306 | of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data); | ||
307 | |||
308 | mx35_clocks_init(); | ||
309 | } | ||
310 | CLK_OF_DECLARE(imx35, "fsl,imx35-ccm", mx35_clocks_init_dt); | ||
diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c new file mode 100644 index 000000000000..a7e4f394be0d --- /dev/null +++ b/drivers/clk/imx/clk-imx51-imx53.c | |||
@@ -0,0 +1,570 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | */ | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/clk.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/of_irq.h> | ||
19 | #include <soc/imx/revision.h> | ||
20 | #include <dt-bindings/clock/imx5-clock.h> | ||
21 | |||
22 | #include "clk.h" | ||
23 | |||
24 | #define MX51_DPLL1_BASE 0x83f80000 | ||
25 | #define MX51_DPLL2_BASE 0x83f84000 | ||
26 | #define MX51_DPLL3_BASE 0x83f88000 | ||
27 | |||
28 | #define MX53_DPLL1_BASE 0x63f80000 | ||
29 | #define MX53_DPLL2_BASE 0x63f84000 | ||
30 | #define MX53_DPLL3_BASE 0x63f88000 | ||
31 | #define MX53_DPLL4_BASE 0x63f8c000 | ||
32 | |||
33 | #define MXC_CCM_CCR (ccm_base + 0x00) | ||
34 | #define MXC_CCM_CCDR (ccm_base + 0x04) | ||
35 | #define MXC_CCM_CSR (ccm_base + 0x08) | ||
36 | #define MXC_CCM_CCSR (ccm_base + 0x0c) | ||
37 | #define MXC_CCM_CACRR (ccm_base + 0x10) | ||
38 | #define MXC_CCM_CBCDR (ccm_base + 0x14) | ||
39 | #define MXC_CCM_CBCMR (ccm_base + 0x18) | ||
40 | #define MXC_CCM_CSCMR1 (ccm_base + 0x1c) | ||
41 | #define MXC_CCM_CSCMR2 (ccm_base + 0x20) | ||
42 | #define MXC_CCM_CSCDR1 (ccm_base + 0x24) | ||
43 | #define MXC_CCM_CS1CDR (ccm_base + 0x28) | ||
44 | #define MXC_CCM_CS2CDR (ccm_base + 0x2c) | ||
45 | #define MXC_CCM_CDCDR (ccm_base + 0x30) | ||
46 | #define MXC_CCM_CHSCDR (ccm_base + 0x34) | ||
47 | #define MXC_CCM_CSCDR2 (ccm_base + 0x38) | ||
48 | #define MXC_CCM_CSCDR3 (ccm_base + 0x3c) | ||
49 | #define MXC_CCM_CSCDR4 (ccm_base + 0x40) | ||
50 | #define MXC_CCM_CWDR (ccm_base + 0x44) | ||
51 | #define MXC_CCM_CDHIPR (ccm_base + 0x48) | ||
52 | #define MXC_CCM_CDCR (ccm_base + 0x4c) | ||
53 | #define MXC_CCM_CTOR (ccm_base + 0x50) | ||
54 | #define MXC_CCM_CLPCR (ccm_base + 0x54) | ||
55 | #define MXC_CCM_CISR (ccm_base + 0x58) | ||
56 | #define MXC_CCM_CIMR (ccm_base + 0x5c) | ||
57 | #define MXC_CCM_CCOSR (ccm_base + 0x60) | ||
58 | #define MXC_CCM_CGPR (ccm_base + 0x64) | ||
59 | #define MXC_CCM_CCGR0 (ccm_base + 0x68) | ||
60 | #define MXC_CCM_CCGR1 (ccm_base + 0x6c) | ||
61 | #define MXC_CCM_CCGR2 (ccm_base + 0x70) | ||
62 | #define MXC_CCM_CCGR3 (ccm_base + 0x74) | ||
63 | #define MXC_CCM_CCGR4 (ccm_base + 0x78) | ||
64 | #define MXC_CCM_CCGR5 (ccm_base + 0x7c) | ||
65 | #define MXC_CCM_CCGR6 (ccm_base + 0x80) | ||
66 | #define MXC_CCM_CCGR7 (ccm_base + 0x84) | ||
67 | |||
68 | /* Low-power Audio Playback Mode clock */ | ||
69 | static const char *lp_apm_sel[] = { "osc", }; | ||
70 | |||
71 | /* This is used multiple times */ | ||
72 | static const char *standard_pll_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "lp_apm", }; | ||
73 | static const char *periph_apm_sel[] = { "pll1_sw", "pll3_sw", "lp_apm", }; | ||
74 | static const char *main_bus_sel[] = { "pll2_sw", "periph_apm", }; | ||
75 | static const char *per_lp_apm_sel[] = { "main_bus", "lp_apm", }; | ||
76 | static const char *per_root_sel[] = { "per_podf", "ipg", }; | ||
77 | static const char *esdhc_c_sel[] = { "esdhc_a_podf", "esdhc_b_podf", }; | ||
78 | static const char *esdhc_d_sel[] = { "esdhc_a_podf", "esdhc_b_podf", }; | ||
79 | static const char *ssi_apm_sels[] = { "ckih1", "lp_amp", "ckih2", }; | ||
80 | static const char *ssi_clk_sels[] = { "pll1_sw", "pll2_sw", "pll3_sw", "ssi_apm", }; | ||
81 | static const char *ssi3_clk_sels[] = { "ssi1_root_gate", "ssi2_root_gate", }; | ||
82 | static const char *ssi_ext1_com_sels[] = { "ssi_ext1_podf", "ssi1_root_gate", }; | ||
83 | static const char *ssi_ext2_com_sels[] = { "ssi_ext2_podf", "ssi2_root_gate", }; | ||
84 | static const char *emi_slow_sel[] = { "main_bus", "ahb", }; | ||
85 | static const char *usb_phy_sel_str[] = { "osc", "usb_phy_podf", }; | ||
86 | static const char *mx51_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "tve_di", }; | ||
87 | static const char *mx53_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "di_pll4_podf", "dummy", "ldb_di0_gate", }; | ||
88 | static const char *mx53_ldb_di0_sel[] = { "pll3_sw", "pll4_sw", }; | ||
89 | static const char *mx51_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", }; | ||
90 | static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", "ldb_di1_gate", }; | ||
91 | static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", }; | ||
92 | static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", }; | ||
93 | static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", }; | ||
94 | static const char *mx51_tve_sel[] = { "tve_pred", "tve_ext_sel", }; | ||
95 | static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", }; | ||
96 | static const char *gpu3d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" }; | ||
97 | static const char *gpu2d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" }; | ||
98 | static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", }; | ||
99 | static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", }; | ||
100 | static const char *mx53_cko1_sel[] = { | ||
101 | "cpu_podf", "pll1_sw", "pll2_sw", "pll3_sw", | ||
102 | "emi_slow_podf", "pll4_sw", "nfc_podf", "dummy", | ||
103 | "di_pred", "dummy", "dummy", "ahb", | ||
104 | "ipg", "per_root", "ckil", "dummy",}; | ||
105 | static const char *mx53_cko2_sel[] = { | ||
106 | "dummy"/* dptc_core */, "dummy"/* dptc_perich */, | ||
107 | "dummy", "esdhc_a_podf", | ||
108 | "usboh3_podf", "dummy"/* wrck_clk_root */, | ||
109 | "ecspi_podf", "dummy"/* pll1_ref_clk */, | ||
110 | "esdhc_b_podf", "dummy"/* ddr_clk_root */, | ||
111 | "dummy"/* arm_axi_clk_root */, "dummy"/* usb_phy_out */, | ||
112 | "vpu_sel", "ipu_sel", | ||
113 | "osc", "ckih1", | ||
114 | "dummy", "esdhc_c_sel", | ||
115 | "ssi1_root_podf", "ssi2_root_podf", | ||
116 | "dummy", "dummy", | ||
117 | "dummy"/* lpsr_clk_root */, "dummy"/* pgc_clk_root */, | ||
118 | "dummy"/* tve_out */, "usb_phy_sel", | ||
119 | "tve_sel", "lp_apm", | ||
120 | "uart_root", "dummy"/* spdif0_clk_root */, | ||
121 | "dummy", "dummy", }; | ||
122 | static const char *mx51_spdif_xtal_sel[] = { "osc", "ckih", "ckih2", }; | ||
123 | static const char *mx53_spdif_xtal_sel[] = { "osc", "ckih", "ckih2", "pll4_sw", }; | ||
124 | static const char *spdif_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "spdif_xtal_sel", }; | ||
125 | static const char *spdif0_com_sel[] = { "spdif0_podf", "ssi1_root_gate", }; | ||
126 | static const char *mx51_spdif1_com_sel[] = { "spdif1_podf", "ssi2_root_gate", }; | ||
127 | static const char *step_sels[] = { "lp_apm", }; | ||
128 | static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" }; | ||
129 | |||
130 | static struct clk *clk[IMX5_CLK_END]; | ||
131 | static struct clk_onecell_data clk_data; | ||
132 | |||
133 | static void __init mx5_clocks_common_init(void __iomem *ccm_base) | ||
134 | { | ||
135 | clk[IMX5_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
136 | clk[IMX5_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0); | ||
137 | clk[IMX5_CLK_OSC] = imx_obtain_fixed_clock("osc", 0); | ||
138 | clk[IMX5_CLK_CKIH1] = imx_obtain_fixed_clock("ckih1", 0); | ||
139 | clk[IMX5_CLK_CKIH2] = imx_obtain_fixed_clock("ckih2", 0); | ||
140 | |||
141 | clk[IMX5_CLK_PERIPH_APM] = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2, | ||
142 | periph_apm_sel, ARRAY_SIZE(periph_apm_sel)); | ||
143 | clk[IMX5_CLK_MAIN_BUS] = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1, | ||
144 | main_bus_sel, ARRAY_SIZE(main_bus_sel)); | ||
145 | clk[IMX5_CLK_PER_LP_APM] = imx_clk_mux("per_lp_apm", MXC_CCM_CBCMR, 1, 1, | ||
146 | per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel)); | ||
147 | clk[IMX5_CLK_PER_PRED1] = imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2); | ||
148 | clk[IMX5_CLK_PER_PRED2] = imx_clk_divider("per_pred2", "per_pred1", MXC_CCM_CBCDR, 3, 3); | ||
149 | clk[IMX5_CLK_PER_PODF] = imx_clk_divider("per_podf", "per_pred2", MXC_CCM_CBCDR, 0, 3); | ||
150 | clk[IMX5_CLK_PER_ROOT] = imx_clk_mux("per_root", MXC_CCM_CBCMR, 0, 1, | ||
151 | per_root_sel, ARRAY_SIZE(per_root_sel)); | ||
152 | clk[IMX5_CLK_AHB] = imx_clk_divider("ahb", "main_bus", MXC_CCM_CBCDR, 10, 3); | ||
153 | clk[IMX5_CLK_AHB_MAX] = imx_clk_gate2("ahb_max", "ahb", MXC_CCM_CCGR0, 28); | ||
154 | clk[IMX5_CLK_AIPS_TZ1] = imx_clk_gate2("aips_tz1", "ahb", MXC_CCM_CCGR0, 24); | ||
155 | clk[IMX5_CLK_AIPS_TZ2] = imx_clk_gate2("aips_tz2", "ahb", MXC_CCM_CCGR0, 26); | ||
156 | clk[IMX5_CLK_TMAX1] = imx_clk_gate2("tmax1", "ahb", MXC_CCM_CCGR1, 0); | ||
157 | clk[IMX5_CLK_TMAX2] = imx_clk_gate2("tmax2", "ahb", MXC_CCM_CCGR1, 2); | ||
158 | clk[IMX5_CLK_TMAX3] = imx_clk_gate2("tmax3", "ahb", MXC_CCM_CCGR1, 4); | ||
159 | clk[IMX5_CLK_SPBA] = imx_clk_gate2("spba", "ipg", MXC_CCM_CCGR5, 0); | ||
160 | clk[IMX5_CLK_IPG] = imx_clk_divider("ipg", "ahb", MXC_CCM_CBCDR, 8, 2); | ||
161 | clk[IMX5_CLK_AXI_A] = imx_clk_divider("axi_a", "main_bus", MXC_CCM_CBCDR, 16, 3); | ||
162 | clk[IMX5_CLK_AXI_B] = imx_clk_divider("axi_b", "main_bus", MXC_CCM_CBCDR, 19, 3); | ||
163 | clk[IMX5_CLK_UART_SEL] = imx_clk_mux("uart_sel", MXC_CCM_CSCMR1, 24, 2, | ||
164 | standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); | ||
165 | clk[IMX5_CLK_UART_PRED] = imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3); | ||
166 | clk[IMX5_CLK_UART_ROOT] = imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3); | ||
167 | |||
168 | clk[IMX5_CLK_ESDHC_A_SEL] = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2, | ||
169 | standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); | ||
170 | clk[IMX5_CLK_ESDHC_B_SEL] = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2, | ||
171 | standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); | ||
172 | clk[IMX5_CLK_ESDHC_A_PRED] = imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3); | ||
173 | clk[IMX5_CLK_ESDHC_A_PODF] = imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3); | ||
174 | clk[IMX5_CLK_ESDHC_B_PRED] = imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3); | ||
175 | clk[IMX5_CLK_ESDHC_B_PODF] = imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3); | ||
176 | clk[IMX5_CLK_ESDHC_C_SEL] = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel)); | ||
177 | clk[IMX5_CLK_ESDHC_D_SEL] = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel)); | ||
178 | |||
179 | clk[IMX5_CLK_EMI_SEL] = imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1, | ||
180 | emi_slow_sel, ARRAY_SIZE(emi_slow_sel)); | ||
181 | clk[IMX5_CLK_EMI_SLOW_PODF] = imx_clk_divider("emi_slow_podf", "emi_sel", MXC_CCM_CBCDR, 22, 3); | ||
182 | clk[IMX5_CLK_NFC_PODF] = imx_clk_divider("nfc_podf", "emi_slow_podf", MXC_CCM_CBCDR, 13, 3); | ||
183 | clk[IMX5_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", MXC_CCM_CSCMR1, 4, 2, | ||
184 | standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); | ||
185 | clk[IMX5_CLK_ECSPI_PRED] = imx_clk_divider("ecspi_pred", "ecspi_sel", MXC_CCM_CSCDR2, 25, 3); | ||
186 | clk[IMX5_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_pred", MXC_CCM_CSCDR2, 19, 6); | ||
187 | clk[IMX5_CLK_USBOH3_SEL] = imx_clk_mux("usboh3_sel", MXC_CCM_CSCMR1, 22, 2, | ||
188 | standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); | ||
189 | clk[IMX5_CLK_USBOH3_PRED] = imx_clk_divider("usboh3_pred", "usboh3_sel", MXC_CCM_CSCDR1, 8, 3); | ||
190 | clk[IMX5_CLK_USBOH3_PODF] = imx_clk_divider("usboh3_podf", "usboh3_pred", MXC_CCM_CSCDR1, 6, 2); | ||
191 | clk[IMX5_CLK_USB_PHY_PRED] = imx_clk_divider("usb_phy_pred", "pll3_sw", MXC_CCM_CDCDR, 3, 3); | ||
192 | clk[IMX5_CLK_USB_PHY_PODF] = imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3); | ||
193 | clk[IMX5_CLK_USB_PHY_SEL] = imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1, | ||
194 | usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str)); | ||
195 | clk[IMX5_CLK_STEP_SEL] = imx_clk_mux("step_sel", MXC_CCM_CCSR, 7, 2, step_sels, ARRAY_SIZE(step_sels)); | ||
196 | clk[IMX5_CLK_CPU_PODF_SEL] = imx_clk_mux("cpu_podf_sel", MXC_CCM_CCSR, 2, 1, cpu_podf_sels, ARRAY_SIZE(cpu_podf_sels)); | ||
197 | clk[IMX5_CLK_CPU_PODF] = imx_clk_divider("cpu_podf", "cpu_podf_sel", MXC_CCM_CACRR, 0, 3); | ||
198 | clk[IMX5_CLK_DI_PRED] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3); | ||
199 | clk[IMX5_CLK_IIM_GATE] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30); | ||
200 | clk[IMX5_CLK_UART1_IPG_GATE] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6); | ||
201 | clk[IMX5_CLK_UART1_PER_GATE] = imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8); | ||
202 | clk[IMX5_CLK_UART2_IPG_GATE] = imx_clk_gate2("uart2_ipg_gate", "ipg", MXC_CCM_CCGR1, 10); | ||
203 | clk[IMX5_CLK_UART2_PER_GATE] = imx_clk_gate2("uart2_per_gate", "uart_root", MXC_CCM_CCGR1, 12); | ||
204 | clk[IMX5_CLK_UART3_IPG_GATE] = imx_clk_gate2("uart3_ipg_gate", "ipg", MXC_CCM_CCGR1, 14); | ||
205 | clk[IMX5_CLK_UART3_PER_GATE] = imx_clk_gate2("uart3_per_gate", "uart_root", MXC_CCM_CCGR1, 16); | ||
206 | clk[IMX5_CLK_I2C1_GATE] = imx_clk_gate2("i2c1_gate", "per_root", MXC_CCM_CCGR1, 18); | ||
207 | clk[IMX5_CLK_I2C2_GATE] = imx_clk_gate2("i2c2_gate", "per_root", MXC_CCM_CCGR1, 20); | ||
208 | clk[IMX5_CLK_PWM1_IPG_GATE] = imx_clk_gate2("pwm1_ipg_gate", "ipg", MXC_CCM_CCGR2, 10); | ||
209 | clk[IMX5_CLK_PWM1_HF_GATE] = imx_clk_gate2("pwm1_hf_gate", "per_root", MXC_CCM_CCGR2, 12); | ||
210 | clk[IMX5_CLK_PWM2_IPG_GATE] = imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14); | ||
211 | clk[IMX5_CLK_PWM2_HF_GATE] = imx_clk_gate2("pwm2_hf_gate", "per_root", MXC_CCM_CCGR2, 16); | ||
212 | clk[IMX5_CLK_GPT_IPG_GATE] = imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 18); | ||
213 | clk[IMX5_CLK_GPT_HF_GATE] = imx_clk_gate2("gpt_hf_gate", "per_root", MXC_CCM_CCGR2, 20); | ||
214 | clk[IMX5_CLK_FEC_GATE] = imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24); | ||
215 | clk[IMX5_CLK_USBOH3_GATE] = imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26); | ||
216 | clk[IMX5_CLK_USBOH3_PER_GATE] = imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28); | ||
217 | clk[IMX5_CLK_ESDHC1_IPG_GATE] = imx_clk_gate2("esdhc1_ipg_gate", "ipg", MXC_CCM_CCGR3, 0); | ||
218 | clk[IMX5_CLK_ESDHC2_IPG_GATE] = imx_clk_gate2("esdhc2_ipg_gate", "ipg", MXC_CCM_CCGR3, 4); | ||
219 | clk[IMX5_CLK_ESDHC3_IPG_GATE] = imx_clk_gate2("esdhc3_ipg_gate", "ipg", MXC_CCM_CCGR3, 8); | ||
220 | clk[IMX5_CLK_ESDHC4_IPG_GATE] = imx_clk_gate2("esdhc4_ipg_gate", "ipg", MXC_CCM_CCGR3, 12); | ||
221 | clk[IMX5_CLK_SSI1_IPG_GATE] = imx_clk_gate2("ssi1_ipg_gate", "ipg", MXC_CCM_CCGR3, 16); | ||
222 | clk[IMX5_CLK_SSI2_IPG_GATE] = imx_clk_gate2("ssi2_ipg_gate", "ipg", MXC_CCM_CCGR3, 20); | ||
223 | clk[IMX5_CLK_SSI3_IPG_GATE] = imx_clk_gate2("ssi3_ipg_gate", "ipg", MXC_CCM_CCGR3, 24); | ||
224 | clk[IMX5_CLK_ECSPI1_IPG_GATE] = imx_clk_gate2("ecspi1_ipg_gate", "ipg", MXC_CCM_CCGR4, 18); | ||
225 | clk[IMX5_CLK_ECSPI1_PER_GATE] = imx_clk_gate2("ecspi1_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 20); | ||
226 | clk[IMX5_CLK_ECSPI2_IPG_GATE] = imx_clk_gate2("ecspi2_ipg_gate", "ipg", MXC_CCM_CCGR4, 22); | ||
227 | clk[IMX5_CLK_ECSPI2_PER_GATE] = imx_clk_gate2("ecspi2_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 24); | ||
228 | clk[IMX5_CLK_CSPI_IPG_GATE] = imx_clk_gate2("cspi_ipg_gate", "ipg", MXC_CCM_CCGR4, 26); | ||
229 | clk[IMX5_CLK_SDMA_GATE] = imx_clk_gate2("sdma_gate", "ipg", MXC_CCM_CCGR4, 30); | ||
230 | clk[IMX5_CLK_EMI_FAST_GATE] = imx_clk_gate2("emi_fast_gate", "dummy", MXC_CCM_CCGR5, 14); | ||
231 | clk[IMX5_CLK_EMI_SLOW_GATE] = imx_clk_gate2("emi_slow_gate", "emi_slow_podf", MXC_CCM_CCGR5, 16); | ||
232 | clk[IMX5_CLK_IPU_SEL] = imx_clk_mux("ipu_sel", MXC_CCM_CBCMR, 6, 2, ipu_sel, ARRAY_SIZE(ipu_sel)); | ||
233 | clk[IMX5_CLK_IPU_GATE] = imx_clk_gate2("ipu_gate", "ipu_sel", MXC_CCM_CCGR5, 10); | ||
234 | clk[IMX5_CLK_NFC_GATE] = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20); | ||
235 | clk[IMX5_CLK_IPU_DI0_GATE] = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10); | ||
236 | clk[IMX5_CLK_IPU_DI1_GATE] = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12); | ||
237 | clk[IMX5_CLK_GPU3D_SEL] = imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel)); | ||
238 | clk[IMX5_CLK_GPU2D_SEL] = imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel)); | ||
239 | clk[IMX5_CLK_GPU3D_GATE] = imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2); | ||
240 | clk[IMX5_CLK_GARB_GATE] = imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4); | ||
241 | clk[IMX5_CLK_GPU2D_GATE] = imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14); | ||
242 | clk[IMX5_CLK_VPU_SEL] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel)); | ||
243 | clk[IMX5_CLK_VPU_GATE] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6); | ||
244 | clk[IMX5_CLK_VPU_REFERENCE_GATE] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8); | ||
245 | clk[IMX5_CLK_UART4_IPG_GATE] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8); | ||
246 | clk[IMX5_CLK_UART4_PER_GATE] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10); | ||
247 | clk[IMX5_CLK_UART5_IPG_GATE] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12); | ||
248 | clk[IMX5_CLK_UART5_PER_GATE] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14); | ||
249 | clk[IMX5_CLK_GPC_DVFS] = imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24); | ||
250 | |||
251 | clk[IMX5_CLK_SSI_APM] = imx_clk_mux("ssi_apm", MXC_CCM_CSCMR1, 8, 2, ssi_apm_sels, ARRAY_SIZE(ssi_apm_sels)); | ||
252 | clk[IMX5_CLK_SSI1_ROOT_SEL] = imx_clk_mux("ssi1_root_sel", MXC_CCM_CSCMR1, 14, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels)); | ||
253 | clk[IMX5_CLK_SSI2_ROOT_SEL] = imx_clk_mux("ssi2_root_sel", MXC_CCM_CSCMR1, 12, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels)); | ||
254 | clk[IMX5_CLK_SSI3_ROOT_SEL] = imx_clk_mux("ssi3_root_sel", MXC_CCM_CSCMR1, 11, 1, ssi3_clk_sels, ARRAY_SIZE(ssi3_clk_sels)); | ||
255 | clk[IMX5_CLK_SSI_EXT1_SEL] = imx_clk_mux("ssi_ext1_sel", MXC_CCM_CSCMR1, 28, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels)); | ||
256 | clk[IMX5_CLK_SSI_EXT2_SEL] = imx_clk_mux("ssi_ext2_sel", MXC_CCM_CSCMR1, 30, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels)); | ||
257 | clk[IMX5_CLK_SSI_EXT1_COM_SEL] = imx_clk_mux("ssi_ext1_com_sel", MXC_CCM_CSCMR1, 0, 1, ssi_ext1_com_sels, ARRAY_SIZE(ssi_ext1_com_sels)); | ||
258 | clk[IMX5_CLK_SSI_EXT2_COM_SEL] = imx_clk_mux("ssi_ext2_com_sel", MXC_CCM_CSCMR1, 1, 1, ssi_ext2_com_sels, ARRAY_SIZE(ssi_ext2_com_sels)); | ||
259 | clk[IMX5_CLK_SSI1_ROOT_PRED] = imx_clk_divider("ssi1_root_pred", "ssi1_root_sel", MXC_CCM_CS1CDR, 6, 3); | ||
260 | clk[IMX5_CLK_SSI1_ROOT_PODF] = imx_clk_divider("ssi1_root_podf", "ssi1_root_pred", MXC_CCM_CS1CDR, 0, 6); | ||
261 | clk[IMX5_CLK_SSI2_ROOT_PRED] = imx_clk_divider("ssi2_root_pred", "ssi2_root_sel", MXC_CCM_CS2CDR, 6, 3); | ||
262 | clk[IMX5_CLK_SSI2_ROOT_PODF] = imx_clk_divider("ssi2_root_podf", "ssi2_root_pred", MXC_CCM_CS2CDR, 0, 6); | ||
263 | clk[IMX5_CLK_SSI_EXT1_PRED] = imx_clk_divider("ssi_ext1_pred", "ssi_ext1_sel", MXC_CCM_CS1CDR, 22, 3); | ||
264 | clk[IMX5_CLK_SSI_EXT1_PODF] = imx_clk_divider("ssi_ext1_podf", "ssi_ext1_pred", MXC_CCM_CS1CDR, 16, 6); | ||
265 | clk[IMX5_CLK_SSI_EXT2_PRED] = imx_clk_divider("ssi_ext2_pred", "ssi_ext2_sel", MXC_CCM_CS2CDR, 22, 3); | ||
266 | clk[IMX5_CLK_SSI_EXT2_PODF] = imx_clk_divider("ssi_ext2_podf", "ssi_ext2_pred", MXC_CCM_CS2CDR, 16, 6); | ||
267 | clk[IMX5_CLK_SSI1_ROOT_GATE] = imx_clk_gate2("ssi1_root_gate", "ssi1_root_podf", MXC_CCM_CCGR3, 18); | ||
268 | clk[IMX5_CLK_SSI2_ROOT_GATE] = imx_clk_gate2("ssi2_root_gate", "ssi2_root_podf", MXC_CCM_CCGR3, 22); | ||
269 | clk[IMX5_CLK_SSI3_ROOT_GATE] = imx_clk_gate2("ssi3_root_gate", "ssi3_root_sel", MXC_CCM_CCGR3, 26); | ||
270 | clk[IMX5_CLK_SSI_EXT1_GATE] = imx_clk_gate2("ssi_ext1_gate", "ssi_ext1_com_sel", MXC_CCM_CCGR3, 28); | ||
271 | clk[IMX5_CLK_SSI_EXT2_GATE] = imx_clk_gate2("ssi_ext2_gate", "ssi_ext2_com_sel", MXC_CCM_CCGR3, 30); | ||
272 | clk[IMX5_CLK_EPIT1_IPG_GATE] = imx_clk_gate2("epit1_ipg_gate", "ipg", MXC_CCM_CCGR2, 2); | ||
273 | clk[IMX5_CLK_EPIT1_HF_GATE] = imx_clk_gate2("epit1_hf_gate", "per_root", MXC_CCM_CCGR2, 4); | ||
274 | clk[IMX5_CLK_EPIT2_IPG_GATE] = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6); | ||
275 | clk[IMX5_CLK_EPIT2_HF_GATE] = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8); | ||
276 | clk[IMX5_CLK_OWIRE_GATE] = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22); | ||
277 | clk[IMX5_CLK_SRTC_GATE] = imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28); | ||
278 | clk[IMX5_CLK_PATA_GATE] = imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0); | ||
279 | clk[IMX5_CLK_SPDIF0_SEL] = imx_clk_mux("spdif0_sel", MXC_CCM_CSCMR2, 0, 2, spdif_sel, ARRAY_SIZE(spdif_sel)); | ||
280 | clk[IMX5_CLK_SPDIF0_PRED] = imx_clk_divider("spdif0_pred", "spdif0_sel", MXC_CCM_CDCDR, 25, 3); | ||
281 | clk[IMX5_CLK_SPDIF0_PODF] = imx_clk_divider("spdif0_podf", "spdif0_pred", MXC_CCM_CDCDR, 19, 6); | ||
282 | clk[IMX5_CLK_SPDIF0_COM_SEL] = imx_clk_mux_flags("spdif0_com_sel", MXC_CCM_CSCMR2, 4, 1, | ||
283 | spdif0_com_sel, ARRAY_SIZE(spdif0_com_sel), CLK_SET_RATE_PARENT); | ||
284 | clk[IMX5_CLK_SPDIF0_GATE] = imx_clk_gate2("spdif0_gate", "spdif0_com_sel", MXC_CCM_CCGR5, 26); | ||
285 | clk[IMX5_CLK_SPDIF_IPG_GATE] = imx_clk_gate2("spdif_ipg_gate", "ipg", MXC_CCM_CCGR5, 30); | ||
286 | clk[IMX5_CLK_SAHARA_IPG_GATE] = imx_clk_gate2("sahara_ipg_gate", "ipg", MXC_CCM_CCGR4, 14); | ||
287 | clk[IMX5_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "usb_phy1_gate", 1, 1); | ||
288 | |||
289 | clk_register_clkdev(clk[IMX5_CLK_CPU_PODF], NULL, "cpu0"); | ||
290 | clk_register_clkdev(clk[IMX5_CLK_GPC_DVFS], "gpc_dvfs", NULL); | ||
291 | |||
292 | /* Set SDHC parents to be PLL2 */ | ||
293 | clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]); | ||
294 | clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]); | ||
295 | |||
296 | /* move usb phy clk to 24MHz */ | ||
297 | clk_set_parent(clk[IMX5_CLK_USB_PHY_SEL], clk[IMX5_CLK_OSC]); | ||
298 | |||
299 | clk_prepare_enable(clk[IMX5_CLK_GPC_DVFS]); | ||
300 | clk_prepare_enable(clk[IMX5_CLK_AHB_MAX]); /* esdhc3 */ | ||
301 | clk_prepare_enable(clk[IMX5_CLK_AIPS_TZ1]); | ||
302 | clk_prepare_enable(clk[IMX5_CLK_AIPS_TZ2]); /* fec */ | ||
303 | clk_prepare_enable(clk[IMX5_CLK_SPBA]); | ||
304 | clk_prepare_enable(clk[IMX5_CLK_EMI_FAST_GATE]); /* fec */ | ||
305 | clk_prepare_enable(clk[IMX5_CLK_EMI_SLOW_GATE]); /* eim */ | ||
306 | clk_prepare_enable(clk[IMX5_CLK_MIPI_HSC1_GATE]); | ||
307 | clk_prepare_enable(clk[IMX5_CLK_MIPI_HSC2_GATE]); | ||
308 | clk_prepare_enable(clk[IMX5_CLK_MIPI_ESC_GATE]); | ||
309 | clk_prepare_enable(clk[IMX5_CLK_MIPI_HSP_GATE]); | ||
310 | clk_prepare_enable(clk[IMX5_CLK_TMAX1]); | ||
311 | clk_prepare_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */ | ||
312 | clk_prepare_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */ | ||
313 | } | ||
314 | |||
315 | static void __init mx50_clocks_init(struct device_node *np) | ||
316 | { | ||
317 | void __iomem *ccm_base; | ||
318 | void __iomem *pll_base; | ||
319 | unsigned long r; | ||
320 | |||
321 | pll_base = ioremap(MX53_DPLL1_BASE, SZ_16K); | ||
322 | WARN_ON(!pll_base); | ||
323 | clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", pll_base); | ||
324 | |||
325 | pll_base = ioremap(MX53_DPLL2_BASE, SZ_16K); | ||
326 | WARN_ON(!pll_base); | ||
327 | clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", pll_base); | ||
328 | |||
329 | pll_base = ioremap(MX53_DPLL3_BASE, SZ_16K); | ||
330 | WARN_ON(!pll_base); | ||
331 | clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", pll_base); | ||
332 | |||
333 | ccm_base = of_iomap(np, 0); | ||
334 | WARN_ON(!ccm_base); | ||
335 | |||
336 | mx5_clocks_common_init(ccm_base); | ||
337 | |||
338 | clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1, | ||
339 | lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); | ||
340 | clk[IMX5_CLK_ESDHC1_PER_GATE] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); | ||
341 | clk[IMX5_CLK_ESDHC2_PER_GATE] = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6); | ||
342 | clk[IMX5_CLK_ESDHC3_PER_GATE] = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10); | ||
343 | clk[IMX5_CLK_ESDHC4_PER_GATE] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14); | ||
344 | clk[IMX5_CLK_USB_PHY1_GATE] = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10); | ||
345 | clk[IMX5_CLK_USB_PHY2_GATE] = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12); | ||
346 | clk[IMX5_CLK_I2C3_GATE] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22); | ||
347 | |||
348 | clk[IMX5_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4, | ||
349 | mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel)); | ||
350 | clk[IMX5_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3); | ||
351 | clk[IMX5_CLK_CKO1] = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7); | ||
352 | |||
353 | clk[IMX5_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5, | ||
354 | mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel)); | ||
355 | clk[IMX5_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3); | ||
356 | clk[IMX5_CLK_CKO2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24); | ||
357 | |||
358 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
359 | |||
360 | clk_data.clks = clk; | ||
361 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
362 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
363 | |||
364 | /* set SDHC root clock to 200MHZ*/ | ||
365 | clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000); | ||
366 | clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000); | ||
367 | |||
368 | clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]); | ||
369 | imx_print_silicon_rev("i.MX50", IMX_CHIP_REVISION_1_1); | ||
370 | clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]); | ||
371 | |||
372 | r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000); | ||
373 | clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r); | ||
374 | } | ||
375 | CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init); | ||
376 | |||
377 | static void __init mx51_clocks_init(struct device_node *np) | ||
378 | { | ||
379 | void __iomem *ccm_base; | ||
380 | void __iomem *pll_base; | ||
381 | u32 val; | ||
382 | |||
383 | pll_base = ioremap(MX51_DPLL1_BASE, SZ_16K); | ||
384 | WARN_ON(!pll_base); | ||
385 | clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", pll_base); | ||
386 | |||
387 | pll_base = ioremap(MX51_DPLL2_BASE, SZ_16K); | ||
388 | WARN_ON(!pll_base); | ||
389 | clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", pll_base); | ||
390 | |||
391 | pll_base = ioremap(MX51_DPLL3_BASE, SZ_16K); | ||
392 | WARN_ON(!pll_base); | ||
393 | clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", pll_base); | ||
394 | |||
395 | ccm_base = of_iomap(np, 0); | ||
396 | WARN_ON(!ccm_base); | ||
397 | |||
398 | mx5_clocks_common_init(ccm_base); | ||
399 | |||
400 | clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1, | ||
401 | lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); | ||
402 | clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, | ||
403 | mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel)); | ||
404 | clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, | ||
405 | mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel)); | ||
406 | clk[IMX5_CLK_TVE_EXT_SEL] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, | ||
407 | mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT); | ||
408 | clk[IMX5_CLK_TVE_SEL] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, | ||
409 | mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel)); | ||
410 | clk[IMX5_CLK_TVE_GATE] = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30); | ||
411 | clk[IMX5_CLK_TVE_PRED] = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3); | ||
412 | clk[IMX5_CLK_ESDHC1_PER_GATE] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); | ||
413 | clk[IMX5_CLK_ESDHC2_PER_GATE] = imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6); | ||
414 | clk[IMX5_CLK_ESDHC3_PER_GATE] = imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10); | ||
415 | clk[IMX5_CLK_ESDHC4_PER_GATE] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14); | ||
416 | clk[IMX5_CLK_USB_PHY_GATE] = imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0); | ||
417 | clk[IMX5_CLK_HSI2C_GATE] = imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22); | ||
418 | clk[IMX5_CLK_MIPI_HSC1_GATE] = imx_clk_gate2("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6); | ||
419 | clk[IMX5_CLK_MIPI_HSC2_GATE] = imx_clk_gate2("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8); | ||
420 | clk[IMX5_CLK_MIPI_ESC_GATE] = imx_clk_gate2("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10); | ||
421 | clk[IMX5_CLK_MIPI_HSP_GATE] = imx_clk_gate2("mipi_hsp_gate", "ipg", MXC_CCM_CCGR4, 12); | ||
422 | clk[IMX5_CLK_SPDIF_XTAL_SEL] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2, | ||
423 | mx51_spdif_xtal_sel, ARRAY_SIZE(mx51_spdif_xtal_sel)); | ||
424 | clk[IMX5_CLK_SPDIF1_SEL] = imx_clk_mux("spdif1_sel", MXC_CCM_CSCMR2, 2, 2, | ||
425 | spdif_sel, ARRAY_SIZE(spdif_sel)); | ||
426 | clk[IMX5_CLK_SPDIF1_PRED] = imx_clk_divider("spdif1_pred", "spdif1_sel", MXC_CCM_CDCDR, 16, 3); | ||
427 | clk[IMX5_CLK_SPDIF1_PODF] = imx_clk_divider("spdif1_podf", "spdif1_pred", MXC_CCM_CDCDR, 9, 6); | ||
428 | clk[IMX5_CLK_SPDIF1_COM_SEL] = imx_clk_mux("spdif1_com_sel", MXC_CCM_CSCMR2, 5, 1, | ||
429 | mx51_spdif1_com_sel, ARRAY_SIZE(mx51_spdif1_com_sel)); | ||
430 | clk[IMX5_CLK_SPDIF1_GATE] = imx_clk_gate2("spdif1_gate", "spdif1_com_sel", MXC_CCM_CCGR5, 28); | ||
431 | |||
432 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
433 | |||
434 | clk_data.clks = clk; | ||
435 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
436 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
437 | |||
438 | /* set the usboh3 parent to pll2_sw */ | ||
439 | clk_set_parent(clk[IMX5_CLK_USBOH3_SEL], clk[IMX5_CLK_PLL2_SW]); | ||
440 | |||
441 | /* set SDHC root clock to 166.25MHZ*/ | ||
442 | clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 166250000); | ||
443 | clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 166250000); | ||
444 | |||
445 | clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]); | ||
446 | imx_print_silicon_rev("i.MX51", mx51_revision()); | ||
447 | clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]); | ||
448 | |||
449 | /* | ||
450 | * Reference Manual says: Functionality of CCDR[18] and CLPCR[23] is no | ||
451 | * longer supported. Set to one for better power saving. | ||
452 | * | ||
453 | * The effect of not setting these bits is that MIPI clocks can't be | ||
454 | * enabled without the IPU clock being enabled aswell. | ||
455 | */ | ||
456 | val = readl(MXC_CCM_CCDR); | ||
457 | val |= 1 << 18; | ||
458 | writel(val, MXC_CCM_CCDR); | ||
459 | |||
460 | val = readl(MXC_CCM_CLPCR); | ||
461 | val |= 1 << 23; | ||
462 | writel(val, MXC_CCM_CLPCR); | ||
463 | } | ||
464 | CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init); | ||
465 | |||
466 | static void __init mx53_clocks_init(struct device_node *np) | ||
467 | { | ||
468 | void __iomem *ccm_base; | ||
469 | void __iomem *pll_base; | ||
470 | unsigned long r; | ||
471 | |||
472 | pll_base = ioremap(MX53_DPLL1_BASE, SZ_16K); | ||
473 | WARN_ON(!pll_base); | ||
474 | clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", pll_base); | ||
475 | |||
476 | pll_base = ioremap(MX53_DPLL2_BASE, SZ_16K); | ||
477 | WARN_ON(!pll_base); | ||
478 | clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", pll_base); | ||
479 | |||
480 | pll_base = ioremap(MX53_DPLL3_BASE, SZ_16K); | ||
481 | WARN_ON(!pll_base); | ||
482 | clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", pll_base); | ||
483 | |||
484 | pll_base = ioremap(MX53_DPLL4_BASE, SZ_16K); | ||
485 | WARN_ON(!pll_base); | ||
486 | clk[IMX5_CLK_PLL4_SW] = imx_clk_pllv2("pll4_sw", "osc", pll_base); | ||
487 | |||
488 | ccm_base = of_iomap(np, 0); | ||
489 | WARN_ON(!ccm_base); | ||
490 | |||
491 | mx5_clocks_common_init(ccm_base); | ||
492 | |||
493 | clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1, | ||
494 | lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); | ||
495 | clk[IMX5_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); | ||
496 | clk[IMX5_CLK_LDB_DI1_DIV] = imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0); | ||
497 | clk[IMX5_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1, | ||
498 | mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT); | ||
499 | clk[IMX5_CLK_DI_PLL4_PODF] = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3); | ||
500 | clk[IMX5_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); | ||
501 | clk[IMX5_CLK_LDB_DI0_DIV] = imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0); | ||
502 | clk[IMX5_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1, | ||
503 | mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT); | ||
504 | clk[IMX5_CLK_LDB_DI0_GATE] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28); | ||
505 | clk[IMX5_CLK_LDB_DI1_GATE] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30); | ||
506 | clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, | ||
507 | mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel)); | ||
508 | clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, | ||
509 | mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel)); | ||
510 | clk[IMX5_CLK_TVE_EXT_SEL] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, | ||
511 | mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT); | ||
512 | clk[IMX5_CLK_TVE_GATE] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30); | ||
513 | clk[IMX5_CLK_TVE_PRED] = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3); | ||
514 | clk[IMX5_CLK_ESDHC1_PER_GATE] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); | ||
515 | clk[IMX5_CLK_ESDHC2_PER_GATE] = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6); | ||
516 | clk[IMX5_CLK_ESDHC3_PER_GATE] = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10); | ||
517 | clk[IMX5_CLK_ESDHC4_PER_GATE] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14); | ||
518 | clk[IMX5_CLK_USB_PHY1_GATE] = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10); | ||
519 | clk[IMX5_CLK_USB_PHY2_GATE] = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12); | ||
520 | clk[IMX5_CLK_CAN_SEL] = imx_clk_mux("can_sel", MXC_CCM_CSCMR2, 6, 2, | ||
521 | mx53_can_sel, ARRAY_SIZE(mx53_can_sel)); | ||
522 | clk[IMX5_CLK_CAN1_SERIAL_GATE] = imx_clk_gate2("can1_serial_gate", "can_sel", MXC_CCM_CCGR6, 22); | ||
523 | clk[IMX5_CLK_CAN1_IPG_GATE] = imx_clk_gate2("can1_ipg_gate", "ipg", MXC_CCM_CCGR6, 20); | ||
524 | clk[IMX5_CLK_OCRAM] = imx_clk_gate2("ocram", "ahb", MXC_CCM_CCGR6, 2); | ||
525 | clk[IMX5_CLK_CAN2_SERIAL_GATE] = imx_clk_gate2("can2_serial_gate", "can_sel", MXC_CCM_CCGR4, 8); | ||
526 | clk[IMX5_CLK_CAN2_IPG_GATE] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6); | ||
527 | clk[IMX5_CLK_I2C3_GATE] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22); | ||
528 | clk[IMX5_CLK_SATA_GATE] = imx_clk_gate2("sata_gate", "ipg", MXC_CCM_CCGR4, 2); | ||
529 | |||
530 | clk[IMX5_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4, | ||
531 | mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel)); | ||
532 | clk[IMX5_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3); | ||
533 | clk[IMX5_CLK_CKO1] = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7); | ||
534 | |||
535 | clk[IMX5_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5, | ||
536 | mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel)); | ||
537 | clk[IMX5_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3); | ||
538 | clk[IMX5_CLK_CKO2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24); | ||
539 | clk[IMX5_CLK_SPDIF_XTAL_SEL] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2, | ||
540 | mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel)); | ||
541 | clk[IMX5_CLK_ARM] = imx_clk_cpu("arm", "cpu_podf", | ||
542 | clk[IMX5_CLK_CPU_PODF], | ||
543 | clk[IMX5_CLK_CPU_PODF_SEL], | ||
544 | clk[IMX5_CLK_PLL1_SW], | ||
545 | clk[IMX5_CLK_STEP_SEL]); | ||
546 | |||
547 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
548 | |||
549 | clk_data.clks = clk; | ||
550 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
551 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
552 | |||
553 | /* set SDHC root clock to 200MHZ*/ | ||
554 | clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000); | ||
555 | clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000); | ||
556 | |||
557 | /* move can bus clk to 24MHz */ | ||
558 | clk_set_parent(clk[IMX5_CLK_CAN_SEL], clk[IMX5_CLK_LP_APM]); | ||
559 | |||
560 | /* make sure step clock is running from 24MHz */ | ||
561 | clk_set_parent(clk[IMX5_CLK_STEP_SEL], clk[IMX5_CLK_LP_APM]); | ||
562 | |||
563 | clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]); | ||
564 | imx_print_silicon_rev("i.MX53", mx53_revision()); | ||
565 | clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]); | ||
566 | |||
567 | r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000); | ||
568 | clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r); | ||
569 | } | ||
570 | CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init); | ||
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c new file mode 100644 index 000000000000..d046f8e43de8 --- /dev/null +++ b/drivers/clk/imx/clk-imx6q.c | |||
@@ -0,0 +1,538 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2013 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/err.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/of_irq.h> | ||
22 | #include <soc/imx/revision.h> | ||
23 | #include <dt-bindings/clock/imx6qdl-clock.h> | ||
24 | |||
25 | #include "clk.h" | ||
26 | |||
27 | static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; | ||
28 | static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; | ||
29 | static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; | ||
30 | static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", }; | ||
31 | static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", }; | ||
32 | static const char *periph_sels[] = { "periph_pre", "periph_clk2", }; | ||
33 | static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", }; | ||
34 | static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", }; | ||
35 | static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", }; | ||
36 | static const char *gpu_axi_sels[] = { "axi", "ahb", }; | ||
37 | static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", }; | ||
38 | static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", }; | ||
39 | static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll3_pfd0_720m", }; | ||
40 | static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; | ||
41 | static const char *ldb_di_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", }; | ||
42 | static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", }; | ||
43 | static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; | ||
44 | static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; | ||
45 | static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; | ||
46 | static const char *ipu2_di1_sels[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; | ||
47 | static const char *hsi_tx_sels[] = { "pll3_120m", "pll2_pfd2_396m", }; | ||
48 | static const char *pcie_axi_sels[] = { "axi", "ahb", }; | ||
49 | static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", }; | ||
50 | static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; | ||
51 | static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", }; | ||
52 | static const char *eim_sels[] = { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", }; | ||
53 | static const char *eim_slow_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", }; | ||
54 | static const char *vdo_axi_sels[] = { "axi", "ahb", }; | ||
55 | static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", }; | ||
56 | static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div", | ||
57 | "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0", | ||
58 | "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio_div", }; | ||
59 | static const char *cko2_sels[] = { | ||
60 | "mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1", | ||
61 | "gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi", | ||
62 | "usdhc3", "dummy", "arm", "ipu1", | ||
63 | "ipu2", "vdo_axi", "osc", "gpu2d_core", | ||
64 | "gpu3d_core", "usdhc2", "ssi1", "ssi2", | ||
65 | "ssi3", "gpu3d_shader", "vpu_axi", "can_root", | ||
66 | "ldb_di0", "ldb_di1", "esai_extal", "eim_slow", | ||
67 | "uart_serial", "spdif", "asrc", "hsi_tx", | ||
68 | }; | ||
69 | static const char *cko_sels[] = { "cko1", "cko2", }; | ||
70 | static const char *lvds_sels[] = { | ||
71 | "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", | ||
72 | "pll4_audio", "pll5_video", "pll8_mlb", "enet_ref", | ||
73 | "pcie_ref_125m", "sata_ref_100m", | ||
74 | }; | ||
75 | static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", "lvds2_in", "dummy", }; | ||
76 | static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", }; | ||
77 | static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", }; | ||
78 | static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", }; | ||
79 | static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", }; | ||
80 | static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", }; | ||
81 | static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; | ||
82 | static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; | ||
83 | |||
84 | static struct clk *clk[IMX6QDL_CLK_END]; | ||
85 | static struct clk_onecell_data clk_data; | ||
86 | |||
87 | static unsigned int const clks_init_on[] __initconst = { | ||
88 | IMX6QDL_CLK_MMDC_CH0_AXI, | ||
89 | IMX6QDL_CLK_ROM, | ||
90 | IMX6QDL_CLK_ARM, | ||
91 | }; | ||
92 | |||
93 | static struct clk_div_table clk_enet_ref_table[] = { | ||
94 | { .val = 0, .div = 20, }, | ||
95 | { .val = 1, .div = 10, }, | ||
96 | { .val = 2, .div = 5, }, | ||
97 | { .val = 3, .div = 4, }, | ||
98 | { /* sentinel */ } | ||
99 | }; | ||
100 | |||
101 | static struct clk_div_table post_div_table[] = { | ||
102 | { .val = 2, .div = 1, }, | ||
103 | { .val = 1, .div = 2, }, | ||
104 | { .val = 0, .div = 4, }, | ||
105 | { /* sentinel */ } | ||
106 | }; | ||
107 | |||
108 | static struct clk_div_table video_div_table[] = { | ||
109 | { .val = 0, .div = 1, }, | ||
110 | { .val = 1, .div = 2, }, | ||
111 | { .val = 2, .div = 1, }, | ||
112 | { .val = 3, .div = 4, }, | ||
113 | { /* sentinel */ } | ||
114 | }; | ||
115 | |||
116 | static unsigned int share_count_esai; | ||
117 | static unsigned int share_count_asrc; | ||
118 | static unsigned int share_count_ssi1; | ||
119 | static unsigned int share_count_ssi2; | ||
120 | static unsigned int share_count_ssi3; | ||
121 | static unsigned int share_count_mipi_core_cfg; | ||
122 | |||
123 | static inline int clk_on_imx6q(void) | ||
124 | { | ||
125 | return of_machine_is_compatible("fsl,imx6q"); | ||
126 | } | ||
127 | |||
128 | static inline int clk_on_imx6dl(void) | ||
129 | { | ||
130 | return of_machine_is_compatible("fsl,imx6dl"); | ||
131 | } | ||
132 | |||
133 | static void __init imx6q_clocks_init(struct device_node *ccm_node) | ||
134 | { | ||
135 | struct device_node *np; | ||
136 | void __iomem *base; | ||
137 | int i; | ||
138 | int ret; | ||
139 | |||
140 | clk[IMX6QDL_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
141 | clk[IMX6QDL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0); | ||
142 | clk[IMX6QDL_CLK_CKIH] = imx_obtain_fixed_clock("ckih1", 0); | ||
143 | clk[IMX6QDL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0); | ||
144 | /* Clock source from external clock via CLK1/2 PADs */ | ||
145 | clk[IMX6QDL_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0); | ||
146 | clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0); | ||
147 | |||
148 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); | ||
149 | base = of_iomap(np, 0); | ||
150 | WARN_ON(!base); | ||
151 | |||
152 | /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */ | ||
153 | if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) { | ||
154 | post_div_table[1].div = 1; | ||
155 | post_div_table[2].div = 1; | ||
156 | video_div_table[1].div = 1; | ||
157 | video_div_table[3].div = 1; | ||
158 | } | ||
159 | |||
160 | clk[IMX6QDL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
161 | clk[IMX6QDL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
162 | clk[IMX6QDL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
163 | clk[IMX6QDL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
164 | clk[IMX6QDL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
165 | clk[IMX6QDL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
166 | clk[IMX6QDL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
167 | |||
168 | /* type name parent_name base div_mask */ | ||
169 | clk[IMX6QDL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f); | ||
170 | clk[IMX6QDL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1); | ||
171 | clk[IMX6QDL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3); | ||
172 | clk[IMX6QDL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f); | ||
173 | clk[IMX6QDL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f); | ||
174 | clk[IMX6QDL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3); | ||
175 | clk[IMX6QDL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3); | ||
176 | |||
177 | clk[IMX6QDL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); | ||
178 | clk[IMX6QDL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); | ||
179 | clk[IMX6QDL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT); | ||
180 | clk[IMX6QDL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT); | ||
181 | clk[IMX6QDL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT); | ||
182 | clk[IMX6QDL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT); | ||
183 | clk[IMX6QDL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT); | ||
184 | |||
185 | /* Do not bypass PLLs initially */ | ||
186 | clk_set_parent(clk[IMX6QDL_PLL1_BYPASS], clk[IMX6QDL_CLK_PLL1]); | ||
187 | clk_set_parent(clk[IMX6QDL_PLL2_BYPASS], clk[IMX6QDL_CLK_PLL2]); | ||
188 | clk_set_parent(clk[IMX6QDL_PLL3_BYPASS], clk[IMX6QDL_CLK_PLL3]); | ||
189 | clk_set_parent(clk[IMX6QDL_PLL4_BYPASS], clk[IMX6QDL_CLK_PLL4]); | ||
190 | clk_set_parent(clk[IMX6QDL_PLL5_BYPASS], clk[IMX6QDL_CLK_PLL5]); | ||
191 | clk_set_parent(clk[IMX6QDL_PLL6_BYPASS], clk[IMX6QDL_CLK_PLL6]); | ||
192 | clk_set_parent(clk[IMX6QDL_PLL7_BYPASS], clk[IMX6QDL_CLK_PLL7]); | ||
193 | |||
194 | clk[IMX6QDL_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", base + 0x00, 13); | ||
195 | clk[IMX6QDL_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13); | ||
196 | clk[IMX6QDL_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13); | ||
197 | clk[IMX6QDL_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13); | ||
198 | clk[IMX6QDL_CLK_PLL5_VIDEO] = imx_clk_gate("pll5_video", "pll5_bypass", base + 0xa0, 13); | ||
199 | clk[IMX6QDL_CLK_PLL6_ENET] = imx_clk_gate("pll6_enet", "pll6_bypass", base + 0xe0, 13); | ||
200 | clk[IMX6QDL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13); | ||
201 | |||
202 | /* | ||
203 | * Bit 20 is the reserved and read-only bit, we do this only for: | ||
204 | * - Do nothing for usbphy clk_enable/disable | ||
205 | * - Keep refcount when do usbphy clk_enable/disable, in that case, | ||
206 | * the clk framework may need to enable/disable usbphy's parent | ||
207 | */ | ||
208 | clk[IMX6QDL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20); | ||
209 | clk[IMX6QDL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20); | ||
210 | |||
211 | /* | ||
212 | * usbphy*_gate needs to be on after system boots up, and software | ||
213 | * never needs to control it anymore. | ||
214 | */ | ||
215 | clk[IMX6QDL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6); | ||
216 | clk[IMX6QDL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6); | ||
217 | |||
218 | clk[IMX6QDL_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5); | ||
219 | clk[IMX6QDL_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4); | ||
220 | |||
221 | clk[IMX6QDL_CLK_SATA_REF_100M] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20); | ||
222 | clk[IMX6QDL_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19); | ||
223 | |||
224 | clk[IMX6QDL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0, | ||
225 | base + 0xe0, 0, 2, 0, clk_enet_ref_table, | ||
226 | &imx_ccm_lock); | ||
227 | |||
228 | clk[IMX6QDL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); | ||
229 | clk[IMX6QDL_CLK_LVDS2_SEL] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); | ||
230 | |||
231 | /* | ||
232 | * lvds1_gate and lvds2_gate are pseudo-gates. Both can be | ||
233 | * independently configured as clock inputs or outputs. We treat | ||
234 | * the "output_enable" bit as a gate, even though it's really just | ||
235 | * enabling clock output. | ||
236 | */ | ||
237 | clk[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate_exclusive("lvds1_gate", "lvds1_sel", base + 0x160, 10, BIT(12)); | ||
238 | clk[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate_exclusive("lvds2_gate", "lvds2_sel", base + 0x160, 11, BIT(13)); | ||
239 | |||
240 | clk[IMX6QDL_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10)); | ||
241 | clk[IMX6QDL_CLK_LVDS2_IN] = imx_clk_gate_exclusive("lvds2_in", "anaclk2", base + 0x160, 13, BIT(11)); | ||
242 | |||
243 | /* name parent_name reg idx */ | ||
244 | clk[IMX6QDL_CLK_PLL2_PFD0_352M] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0); | ||
245 | clk[IMX6QDL_CLK_PLL2_PFD1_594M] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1); | ||
246 | clk[IMX6QDL_CLK_PLL2_PFD2_396M] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2); | ||
247 | clk[IMX6QDL_CLK_PLL3_PFD0_720M] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0); | ||
248 | clk[IMX6QDL_CLK_PLL3_PFD1_540M] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1); | ||
249 | clk[IMX6QDL_CLK_PLL3_PFD2_508M] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2); | ||
250 | clk[IMX6QDL_CLK_PLL3_PFD3_454M] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3); | ||
251 | |||
252 | /* name parent_name mult div */ | ||
253 | clk[IMX6QDL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2); | ||
254 | clk[IMX6QDL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); | ||
255 | clk[IMX6QDL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); | ||
256 | clk[IMX6QDL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); | ||
257 | clk[IMX6QDL_CLK_TWD] = imx_clk_fixed_factor("twd", "arm", 1, 2); | ||
258 | clk[IMX6QDL_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); | ||
259 | clk[IMX6QDL_CLK_VIDEO_27M] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20); | ||
260 | if (clk_on_imx6dl()) { | ||
261 | clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_fixed_factor("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1); | ||
262 | clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1); | ||
263 | } | ||
264 | |||
265 | clk[IMX6QDL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); | ||
266 | clk[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock); | ||
267 | clk[IMX6QDL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); | ||
268 | clk[IMX6QDL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); | ||
269 | |||
270 | np = ccm_node; | ||
271 | base = of_iomap(np, 0); | ||
272 | WARN_ON(!base); | ||
273 | |||
274 | /* name reg shift width parent_names num_parents */ | ||
275 | clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); | ||
276 | clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); | ||
277 | clk[IMX6QDL_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels)); | ||
278 | clk[IMX6QDL_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels)); | ||
279 | clk[IMX6QDL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); | ||
280 | clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); | ||
281 | clk[IMX6QDL_CLK_AXI_SEL] = imx_clk_mux("axi_sel", base + 0x14, 6, 2, axi_sels, ARRAY_SIZE(axi_sels)); | ||
282 | clk[IMX6QDL_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
283 | clk[IMX6QDL_CLK_ASRC_SEL] = imx_clk_mux("asrc_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
284 | clk[IMX6QDL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
285 | if (clk_on_imx6q()) { | ||
286 | clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_mux("gpu2d_axi", base + 0x18, 0, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels)); | ||
287 | clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_mux("gpu3d_axi", base + 0x18, 1, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels)); | ||
288 | } | ||
289 | clk[IMX6QDL_CLK_GPU2D_CORE_SEL] = imx_clk_mux("gpu2d_core_sel", base + 0x18, 16, 2, gpu2d_core_sels, ARRAY_SIZE(gpu2d_core_sels)); | ||
290 | clk[IMX6QDL_CLK_GPU3D_CORE_SEL] = imx_clk_mux("gpu3d_core_sel", base + 0x18, 4, 2, gpu3d_core_sels, ARRAY_SIZE(gpu3d_core_sels)); | ||
291 | clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels)); | ||
292 | clk[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); | ||
293 | clk[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); | ||
294 | clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); | ||
295 | clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); | ||
296 | clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); | ||
297 | clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); | ||
298 | clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); | ||
299 | clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); | ||
300 | clk[IMX6QDL_CLK_IPU1_DI0_SEL] = imx_clk_mux_flags("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT); | ||
301 | clk[IMX6QDL_CLK_IPU1_DI1_SEL] = imx_clk_mux_flags("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT); | ||
302 | clk[IMX6QDL_CLK_IPU2_DI0_SEL] = imx_clk_mux_flags("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT); | ||
303 | clk[IMX6QDL_CLK_IPU2_DI1_SEL] = imx_clk_mux_flags("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT); | ||
304 | clk[IMX6QDL_CLK_HSI_TX_SEL] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels)); | ||
305 | clk[IMX6QDL_CLK_PCIE_AXI_SEL] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels)); | ||
306 | clk[IMX6QDL_CLK_SSI1_SEL] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); | ||
307 | clk[IMX6QDL_CLK_SSI2_SEL] = imx_clk_fixup_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); | ||
308 | clk[IMX6QDL_CLK_SSI3_SEL] = imx_clk_fixup_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); | ||
309 | clk[IMX6QDL_CLK_USDHC1_SEL] = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); | ||
310 | clk[IMX6QDL_CLK_USDHC2_SEL] = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); | ||
311 | clk[IMX6QDL_CLK_USDHC3_SEL] = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); | ||
312 | clk[IMX6QDL_CLK_USDHC4_SEL] = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); | ||
313 | clk[IMX6QDL_CLK_ENFC_SEL] = imx_clk_mux("enfc_sel", base + 0x2c, 16, 2, enfc_sels, ARRAY_SIZE(enfc_sels)); | ||
314 | clk[IMX6QDL_CLK_EIM_SEL] = imx_clk_fixup_mux("eim_sel", base + 0x1c, 27, 2, eim_sels, ARRAY_SIZE(eim_sels), imx_cscmr1_fixup); | ||
315 | clk[IMX6QDL_CLK_EIM_SLOW_SEL] = imx_clk_fixup_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels), imx_cscmr1_fixup); | ||
316 | clk[IMX6QDL_CLK_VDO_AXI_SEL] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels)); | ||
317 | clk[IMX6QDL_CLK_VPU_AXI_SEL] = imx_clk_mux("vpu_axi_sel", base + 0x18, 14, 2, vpu_axi_sels, ARRAY_SIZE(vpu_axi_sels)); | ||
318 | clk[IMX6QDL_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels)); | ||
319 | clk[IMX6QDL_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels)); | ||
320 | clk[IMX6QDL_CLK_CKO] = imx_clk_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels)); | ||
321 | |||
322 | /* name reg shift width busy: reg, shift parent_names num_parents */ | ||
323 | clk[IMX6QDL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); | ||
324 | clk[IMX6QDL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels)); | ||
325 | |||
326 | /* name parent_name reg shift width */ | ||
327 | clk[IMX6QDL_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3); | ||
328 | clk[IMX6QDL_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3); | ||
329 | clk[IMX6QDL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); | ||
330 | clk[IMX6QDL_CLK_IPG_PER] = imx_clk_fixup_divider("ipg_per", "ipg", base + 0x1c, 0, 6, imx_cscmr1_fixup); | ||
331 | clk[IMX6QDL_CLK_ESAI_PRED] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3); | ||
332 | clk[IMX6QDL_CLK_ESAI_PODF] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3); | ||
333 | clk[IMX6QDL_CLK_ASRC_PRED] = imx_clk_divider("asrc_pred", "asrc_sel", base + 0x30, 12, 3); | ||
334 | clk[IMX6QDL_CLK_ASRC_PODF] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3); | ||
335 | clk[IMX6QDL_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3); | ||
336 | clk[IMX6QDL_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3); | ||
337 | clk[IMX6QDL_CLK_CAN_ROOT] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6); | ||
338 | clk[IMX6QDL_CLK_ECSPI_ROOT] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6); | ||
339 | clk[IMX6QDL_CLK_GPU2D_CORE_PODF] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3); | ||
340 | clk[IMX6QDL_CLK_GPU3D_CORE_PODF] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3); | ||
341 | clk[IMX6QDL_CLK_GPU3D_SHADER] = imx_clk_divider("gpu3d_shader", "gpu3d_shader_sel", base + 0x18, 29, 3); | ||
342 | clk[IMX6QDL_CLK_IPU1_PODF] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3); | ||
343 | clk[IMX6QDL_CLK_IPU2_PODF] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3); | ||
344 | clk[IMX6QDL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); | ||
345 | clk[IMX6QDL_CLK_LDB_DI0_PODF] = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0); | ||
346 | clk[IMX6QDL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); | ||
347 | clk[IMX6QDL_CLK_LDB_DI1_PODF] = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0); | ||
348 | clk[IMX6QDL_CLK_IPU1_DI0_PRE] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3); | ||
349 | clk[IMX6QDL_CLK_IPU1_DI1_PRE] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3); | ||
350 | clk[IMX6QDL_CLK_IPU2_DI0_PRE] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3); | ||
351 | clk[IMX6QDL_CLK_IPU2_DI1_PRE] = imx_clk_divider("ipu2_di1_pre", "ipu2_di1_pre_sel", base + 0x38, 12, 3); | ||
352 | clk[IMX6QDL_CLK_HSI_TX_PODF] = imx_clk_divider("hsi_tx_podf", "hsi_tx_sel", base + 0x30, 29, 3); | ||
353 | clk[IMX6QDL_CLK_SSI1_PRED] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3); | ||
354 | clk[IMX6QDL_CLK_SSI1_PODF] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6); | ||
355 | clk[IMX6QDL_CLK_SSI2_PRED] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3); | ||
356 | clk[IMX6QDL_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6); | ||
357 | clk[IMX6QDL_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3); | ||
358 | clk[IMX6QDL_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6); | ||
359 | clk[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_divider("uart_serial_podf", "pll3_80m", base + 0x24, 0, 6); | ||
360 | clk[IMX6QDL_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3); | ||
361 | clk[IMX6QDL_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3); | ||
362 | clk[IMX6QDL_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3); | ||
363 | clk[IMX6QDL_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); | ||
364 | clk[IMX6QDL_CLK_ENFC_PRED] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3); | ||
365 | clk[IMX6QDL_CLK_ENFC_PODF] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6); | ||
366 | clk[IMX6QDL_CLK_EIM_PODF] = imx_clk_fixup_divider("eim_podf", "eim_sel", base + 0x1c, 20, 3, imx_cscmr1_fixup); | ||
367 | clk[IMX6QDL_CLK_EIM_SLOW_PODF] = imx_clk_fixup_divider("eim_slow_podf", "eim_slow_sel", base + 0x1c, 23, 3, imx_cscmr1_fixup); | ||
368 | clk[IMX6QDL_CLK_VPU_AXI_PODF] = imx_clk_divider("vpu_axi_podf", "vpu_axi_sel", base + 0x24, 25, 3); | ||
369 | clk[IMX6QDL_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3); | ||
370 | clk[IMX6QDL_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3); | ||
371 | |||
372 | /* name parent_name reg shift width busy: reg, shift */ | ||
373 | clk[IMX6QDL_CLK_AXI] = imx_clk_busy_divider("axi", "axi_sel", base + 0x14, 16, 3, base + 0x48, 0); | ||
374 | clk[IMX6QDL_CLK_MMDC_CH0_AXI_PODF] = imx_clk_busy_divider("mmdc_ch0_axi_podf", "periph", base + 0x14, 19, 3, base + 0x48, 4); | ||
375 | clk[IMX6QDL_CLK_MMDC_CH1_AXI_PODF] = imx_clk_busy_divider("mmdc_ch1_axi_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2); | ||
376 | clk[IMX6QDL_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16); | ||
377 | clk[IMX6QDL_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1); | ||
378 | |||
379 | /* name parent_name reg shift */ | ||
380 | clk[IMX6QDL_CLK_APBH_DMA] = imx_clk_gate2("apbh_dma", "usdhc3", base + 0x68, 4); | ||
381 | clk[IMX6QDL_CLK_ASRC] = imx_clk_gate2_shared("asrc", "asrc_podf", base + 0x68, 6, &share_count_asrc); | ||
382 | clk[IMX6QDL_CLK_ASRC_IPG] = imx_clk_gate2_shared("asrc_ipg", "ahb", base + 0x68, 6, &share_count_asrc); | ||
383 | clk[IMX6QDL_CLK_ASRC_MEM] = imx_clk_gate2_shared("asrc_mem", "ahb", base + 0x68, 6, &share_count_asrc); | ||
384 | clk[IMX6QDL_CLK_CAN1_IPG] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14); | ||
385 | clk[IMX6QDL_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_root", base + 0x68, 16); | ||
386 | clk[IMX6QDL_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18); | ||
387 | clk[IMX6QDL_CLK_CAN2_SERIAL] = imx_clk_gate2("can2_serial", "can_root", base + 0x68, 20); | ||
388 | clk[IMX6QDL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0); | ||
389 | clk[IMX6QDL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2); | ||
390 | clk[IMX6QDL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4); | ||
391 | clk[IMX6QDL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6); | ||
392 | if (clk_on_imx6dl()) | ||
393 | clk[IMX6DL_CLK_I2C4] = imx_clk_gate2("i2c4", "ipg_per", base + 0x6c, 8); | ||
394 | else | ||
395 | clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8); | ||
396 | clk[IMX6QDL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10); | ||
397 | clk[IMX6QDL_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x6c, 16, &share_count_esai); | ||
398 | clk[IMX6QDL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x6c, 16, &share_count_esai); | ||
399 | clk[IMX6QDL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai); | ||
400 | clk[IMX6QDL_CLK_GPT_IPG] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20); | ||
401 | clk[IMX6QDL_CLK_GPT_IPG_PER] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22); | ||
402 | if (clk_on_imx6dl()) | ||
403 | /* | ||
404 | * The multiplexer and divider of imx6q clock gpu3d_shader get | ||
405 | * redefined/reused as gpu2d_core_sel and gpu2d_core_podf on imx6dl. | ||
406 | */ | ||
407 | clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu3d_shader", base + 0x6c, 24); | ||
408 | else | ||
409 | clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24); | ||
410 | clk[IMX6QDL_CLK_GPU3D_CORE] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26); | ||
411 | clk[IMX6QDL_CLK_HDMI_IAHB] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0); | ||
412 | clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "video_27m", base + 0x70, 4); | ||
413 | clk[IMX6QDL_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6); | ||
414 | clk[IMX6QDL_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8); | ||
415 | clk[IMX6QDL_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10); | ||
416 | clk[IMX6QDL_CLK_IIM] = imx_clk_gate2("iim", "ipg", base + 0x70, 12); | ||
417 | clk[IMX6QDL_CLK_ENFC] = imx_clk_gate2("enfc", "enfc_podf", base + 0x70, 14); | ||
418 | clk[IMX6QDL_CLK_VDOA] = imx_clk_gate2("vdoa", "vdo_axi", base + 0x70, 26); | ||
419 | clk[IMX6QDL_CLK_IPU1] = imx_clk_gate2("ipu1", "ipu1_podf", base + 0x74, 0); | ||
420 | clk[IMX6QDL_CLK_IPU1_DI0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", base + 0x74, 2); | ||
421 | clk[IMX6QDL_CLK_IPU1_DI1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", base + 0x74, 4); | ||
422 | clk[IMX6QDL_CLK_IPU2] = imx_clk_gate2("ipu2", "ipu2_podf", base + 0x74, 6); | ||
423 | clk[IMX6QDL_CLK_IPU2_DI0] = imx_clk_gate2("ipu2_di0", "ipu2_di0_sel", base + 0x74, 8); | ||
424 | clk[IMX6QDL_CLK_LDB_DI0] = imx_clk_gate2("ldb_di0", "ldb_di0_podf", base + 0x74, 12); | ||
425 | clk[IMX6QDL_CLK_LDB_DI1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", base + 0x74, 14); | ||
426 | clk[IMX6QDL_CLK_IPU2_DI1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", base + 0x74, 10); | ||
427 | clk[IMX6QDL_CLK_HSI_TX] = imx_clk_gate2_shared("hsi_tx", "hsi_tx_podf", base + 0x74, 16, &share_count_mipi_core_cfg); | ||
428 | clk[IMX6QDL_CLK_MIPI_CORE_CFG] = imx_clk_gate2_shared("mipi_core_cfg", "video_27m", base + 0x74, 16, &share_count_mipi_core_cfg); | ||
429 | clk[IMX6QDL_CLK_MIPI_IPG] = imx_clk_gate2_shared("mipi_ipg", "ipg", base + 0x74, 16, &share_count_mipi_core_cfg); | ||
430 | if (clk_on_imx6dl()) | ||
431 | /* | ||
432 | * The multiplexer and divider of the imx6q clock gpu2d get | ||
433 | * redefined/reused as mlb_sys_sel and mlb_sys_clk_podf on imx6dl. | ||
434 | */ | ||
435 | clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb", "gpu2d_core_podf", base + 0x74, 18); | ||
436 | else | ||
437 | clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb", "axi", base + 0x74, 18); | ||
438 | clk[IMX6QDL_CLK_MMDC_CH0_AXI] = imx_clk_gate2("mmdc_ch0_axi", "mmdc_ch0_axi_podf", base + 0x74, 20); | ||
439 | clk[IMX6QDL_CLK_MMDC_CH1_AXI] = imx_clk_gate2("mmdc_ch1_axi", "mmdc_ch1_axi_podf", base + 0x74, 22); | ||
440 | clk[IMX6QDL_CLK_OCRAM] = imx_clk_gate2("ocram", "ahb", base + 0x74, 28); | ||
441 | clk[IMX6QDL_CLK_OPENVG_AXI] = imx_clk_gate2("openvg_axi", "axi", base + 0x74, 30); | ||
442 | clk[IMX6QDL_CLK_PCIE_AXI] = imx_clk_gate2("pcie_axi", "pcie_axi_sel", base + 0x78, 0); | ||
443 | clk[IMX6QDL_CLK_PER1_BCH] = imx_clk_gate2("per1_bch", "usdhc3", base + 0x78, 12); | ||
444 | clk[IMX6QDL_CLK_PWM1] = imx_clk_gate2("pwm1", "ipg_per", base + 0x78, 16); | ||
445 | clk[IMX6QDL_CLK_PWM2] = imx_clk_gate2("pwm2", "ipg_per", base + 0x78, 18); | ||
446 | clk[IMX6QDL_CLK_PWM3] = imx_clk_gate2("pwm3", "ipg_per", base + 0x78, 20); | ||
447 | clk[IMX6QDL_CLK_PWM4] = imx_clk_gate2("pwm4", "ipg_per", base + 0x78, 22); | ||
448 | clk[IMX6QDL_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb", "usdhc3", base + 0x78, 24); | ||
449 | clk[IMX6QDL_CLK_GPMI_BCH] = imx_clk_gate2("gpmi_bch", "usdhc4", base + 0x78, 26); | ||
450 | clk[IMX6QDL_CLK_GPMI_IO] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28); | ||
451 | clk[IMX6QDL_CLK_GPMI_APB] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); | ||
452 | clk[IMX6QDL_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); | ||
453 | clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4); | ||
454 | clk[IMX6QDL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); | ||
455 | clk[IMX6QDL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); | ||
456 | clk[IMX6QDL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14); | ||
457 | clk[IMX6QDL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1); | ||
458 | clk[IMX6QDL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2); | ||
459 | clk[IMX6QDL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3); | ||
460 | clk[IMX6QDL_CLK_SSI1] = imx_clk_gate2_shared("ssi1", "ssi1_podf", base + 0x7c, 18, &share_count_ssi1); | ||
461 | clk[IMX6QDL_CLK_SSI2] = imx_clk_gate2_shared("ssi2", "ssi2_podf", base + 0x7c, 20, &share_count_ssi2); | ||
462 | clk[IMX6QDL_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3); | ||
463 | clk[IMX6QDL_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24); | ||
464 | clk[IMX6QDL_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_serial_podf", base + 0x7c, 26); | ||
465 | clk[IMX6QDL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); | ||
466 | clk[IMX6QDL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2); | ||
467 | clk[IMX6QDL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); | ||
468 | clk[IMX6QDL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); | ||
469 | clk[IMX6QDL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); | ||
470 | clk[IMX6QDL_CLK_EIM_SLOW] = imx_clk_gate2("eim_slow", "eim_slow_podf", base + 0x80, 10); | ||
471 | clk[IMX6QDL_CLK_VDO_AXI] = imx_clk_gate2("vdo_axi", "vdo_axi_sel", base + 0x80, 12); | ||
472 | clk[IMX6QDL_CLK_VPU_AXI] = imx_clk_gate2("vpu_axi", "vpu_axi_podf", base + 0x80, 14); | ||
473 | clk[IMX6QDL_CLK_CKO1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7); | ||
474 | clk[IMX6QDL_CLK_CKO2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24); | ||
475 | |||
476 | /* | ||
477 | * The gpt_3m clock is not available on i.MX6Q TO1.0. Let's point it | ||
478 | * to clock gpt_ipg_per to ease the gpt driver code. | ||
479 | */ | ||
480 | if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) | ||
481 | clk[IMX6QDL_CLK_GPT_3M] = clk[IMX6QDL_CLK_GPT_IPG_PER]; | ||
482 | |||
483 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
484 | |||
485 | clk_data.clks = clk; | ||
486 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
487 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
488 | |||
489 | clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL); | ||
490 | |||
491 | if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) || | ||
492 | clk_on_imx6dl()) { | ||
493 | clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); | ||
494 | clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); | ||
495 | } | ||
496 | |||
497 | clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); | ||
498 | clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); | ||
499 | clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); | ||
500 | clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); | ||
501 | clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_SEL], clk[IMX6QDL_CLK_IPU1_DI0_PRE]); | ||
502 | clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_SEL], clk[IMX6QDL_CLK_IPU1_DI1_PRE]); | ||
503 | clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_SEL], clk[IMX6QDL_CLK_IPU2_DI0_PRE]); | ||
504 | clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_SEL], clk[IMX6QDL_CLK_IPU2_DI1_PRE]); | ||
505 | |||
506 | /* | ||
507 | * The gpmi needs 100MHz frequency in the EDO/Sync mode, | ||
508 | * We can not get the 100MHz from the pll2_pfd0_352m. | ||
509 | * So choose pll2_pfd2_396m as enfc_sel's parent. | ||
510 | */ | ||
511 | clk_set_parent(clk[IMX6QDL_CLK_ENFC_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]); | ||
512 | |||
513 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | ||
514 | clk_prepare_enable(clk[clks_init_on[i]]); | ||
515 | |||
516 | if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { | ||
517 | clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]); | ||
518 | clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]); | ||
519 | } | ||
520 | |||
521 | /* | ||
522 | * Let's initially set up CLKO with OSC24M, since this configuration | ||
523 | * is widely used by imx6q board designs to clock audio codec. | ||
524 | */ | ||
525 | ret = clk_set_parent(clk[IMX6QDL_CLK_CKO2_SEL], clk[IMX6QDL_CLK_OSC]); | ||
526 | if (!ret) | ||
527 | ret = clk_set_parent(clk[IMX6QDL_CLK_CKO], clk[IMX6QDL_CLK_CKO2]); | ||
528 | if (ret) | ||
529 | pr_warn("failed to set up CLKO: %d\n", ret); | ||
530 | |||
531 | /* Audio-related clocks configuration */ | ||
532 | clk_set_parent(clk[IMX6QDL_CLK_SPDIF_SEL], clk[IMX6QDL_CLK_PLL3_PFD3_454M]); | ||
533 | |||
534 | /* All existing boards with PCIe use LVDS1 */ | ||
535 | if (IS_ENABLED(CONFIG_PCI_IMX6)) | ||
536 | clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]); | ||
537 | } | ||
538 | CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init); | ||
diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c new file mode 100644 index 000000000000..a0d4cf26cfa9 --- /dev/null +++ b/drivers/clk/imx/clk-imx6sl.c | |||
@@ -0,0 +1,443 @@ | |||
1 | /* | ||
2 | * Copyright 2013-2014 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/clk.h> | ||
11 | #include <linux/clkdev.h> | ||
12 | #include <linux/err.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/of_address.h> | ||
15 | #include <linux/of_irq.h> | ||
16 | #include <dt-bindings/clock/imx6sl-clock.h> | ||
17 | |||
18 | #include "clk.h" | ||
19 | |||
20 | #define CCSR 0xc | ||
21 | #define BM_CCSR_PLL1_SW_CLK_SEL (1 << 2) | ||
22 | #define CACRR 0x10 | ||
23 | #define CDHIPR 0x48 | ||
24 | #define BM_CDHIPR_ARM_PODF_BUSY (1 << 16) | ||
25 | #define ARM_WAIT_DIV_396M 2 | ||
26 | #define ARM_WAIT_DIV_792M 4 | ||
27 | #define ARM_WAIT_DIV_996M 6 | ||
28 | |||
29 | #define PLL_ARM 0x0 | ||
30 | #define BM_PLL_ARM_DIV_SELECT (0x7f << 0) | ||
31 | #define BM_PLL_ARM_POWERDOWN (1 << 12) | ||
32 | #define BM_PLL_ARM_ENABLE (1 << 13) | ||
33 | #define BM_PLL_ARM_LOCK (1 << 31) | ||
34 | #define PLL_ARM_DIV_792M 66 | ||
35 | |||
36 | static const char *step_sels[] = { "osc", "pll2_pfd2", }; | ||
37 | static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; | ||
38 | static const char *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", }; | ||
39 | static const char *ocram_sels[] = { "periph", "ocram_alt_sels", }; | ||
40 | static const char *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", }; | ||
41 | static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", }; | ||
42 | static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", }; | ||
43 | static const char *periph_sels[] = { "pre_periph_sel", "periph_clk2_podf", }; | ||
44 | static const char *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2_podf", }; | ||
45 | static const char *csi_sels[] = { "osc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", }; | ||
46 | static const char *lcdif_axi_sels[] = { "pll2_bus", "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", }; | ||
47 | static const char *usdhc_sels[] = { "pll2_pfd2", "pll2_pfd0", }; | ||
48 | static const char *ssi_sels[] = { "pll3_pfd2", "pll3_pfd3", "pll4_audio_div", "dummy", }; | ||
49 | static const char *perclk_sels[] = { "ipg", "osc", }; | ||
50 | static const char *pxp_axi_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd3", }; | ||
51 | static const char *epdc_axi_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd2", }; | ||
52 | static const char *gpu2d_ovg_sels[] = { "pll3_pfd1", "pll3_usb_otg", "pll2_bus", "pll2_pfd2", }; | ||
53 | static const char *gpu2d_sels[] = { "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", "pll2_bus", }; | ||
54 | static const char *lcdif_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll3_pfd0", "pll3_pfd1", }; | ||
55 | static const char *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", }; | ||
56 | static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", }; | ||
57 | static const char *ecspi_sels[] = { "pll3_60m", "osc", }; | ||
58 | static const char *uart_sels[] = { "pll3_80m", "osc", }; | ||
59 | static const char *lvds_sels[] = { | ||
60 | "pll1_sys", "pll2_bus", "pll2_pfd0", "pll2_pfd1", "pll2_pfd2", "dummy", "pll4_audio", "pll5_video", | ||
61 | "dummy", "enet_ref", "dummy", "dummy", "pll3_usb_otg", "pll7_usb_host", "pll3_pfd0", "pll3_pfd1", | ||
62 | "pll3_pfd2", "pll3_pfd3", "osc", "dummy", "dummy", "dummy", "dummy", "dummy", | ||
63 | "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", | ||
64 | }; | ||
65 | static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", }; | ||
66 | static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", }; | ||
67 | static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", }; | ||
68 | static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", }; | ||
69 | static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", }; | ||
70 | static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", }; | ||
71 | static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; | ||
72 | static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; | ||
73 | |||
74 | static struct clk_div_table clk_enet_ref_table[] = { | ||
75 | { .val = 0, .div = 20, }, | ||
76 | { .val = 1, .div = 10, }, | ||
77 | { .val = 2, .div = 5, }, | ||
78 | { .val = 3, .div = 4, }, | ||
79 | { } | ||
80 | }; | ||
81 | |||
82 | static struct clk_div_table post_div_table[] = { | ||
83 | { .val = 2, .div = 1, }, | ||
84 | { .val = 1, .div = 2, }, | ||
85 | { .val = 0, .div = 4, }, | ||
86 | { } | ||
87 | }; | ||
88 | |||
89 | static struct clk_div_table video_div_table[] = { | ||
90 | { .val = 0, .div = 1, }, | ||
91 | { .val = 1, .div = 2, }, | ||
92 | { .val = 2, .div = 1, }, | ||
93 | { .val = 3, .div = 4, }, | ||
94 | { } | ||
95 | }; | ||
96 | |||
97 | static unsigned int share_count_ssi1; | ||
98 | static unsigned int share_count_ssi2; | ||
99 | static unsigned int share_count_ssi3; | ||
100 | |||
101 | static struct clk *clks[IMX6SL_CLK_END]; | ||
102 | static struct clk_onecell_data clk_data; | ||
103 | static void __iomem *ccm_base; | ||
104 | static void __iomem *anatop_base; | ||
105 | |||
106 | static const u32 clks_init_on[] __initconst = { | ||
107 | IMX6SL_CLK_IPG, IMX6SL_CLK_ARM, IMX6SL_CLK_MMDC_ROOT, | ||
108 | }; | ||
109 | |||
110 | /* | ||
111 | * ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken | ||
112 | * during WAIT mode entry process could cause cache memory | ||
113 | * corruption. | ||
114 | * | ||
115 | * Software workaround: | ||
116 | * To prevent this issue from occurring, software should ensure that the | ||
117 | * ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before | ||
118 | * entering WAIT mode. | ||
119 | * | ||
120 | * This function will set the ARM clk to max value within the 12:5 limit. | ||
121 | * As IPG clock is fixed at 66MHz(so ARM freq must not exceed 158.4MHz), | ||
122 | * ARM freq are one of below setpoints: 396MHz, 792MHz and 996MHz, since | ||
123 | * the clk APIs can NOT be called in idle thread(may cause kernel schedule | ||
124 | * as there is sleep function in PLL wait function), so here we just slow | ||
125 | * down ARM to below freq according to previous freq: | ||
126 | * | ||
127 | * run mode wait mode | ||
128 | * 396MHz -> 132MHz; | ||
129 | * 792MHz -> 158.4MHz; | ||
130 | * 996MHz -> 142.3MHz; | ||
131 | */ | ||
132 | static int imx6sl_get_arm_divider_for_wait(void) | ||
133 | { | ||
134 | if (readl_relaxed(ccm_base + CCSR) & BM_CCSR_PLL1_SW_CLK_SEL) { | ||
135 | return ARM_WAIT_DIV_396M; | ||
136 | } else { | ||
137 | if ((readl_relaxed(anatop_base + PLL_ARM) & | ||
138 | BM_PLL_ARM_DIV_SELECT) == PLL_ARM_DIV_792M) | ||
139 | return ARM_WAIT_DIV_792M; | ||
140 | else | ||
141 | return ARM_WAIT_DIV_996M; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | static void imx6sl_enable_pll_arm(bool enable) | ||
146 | { | ||
147 | static u32 saved_pll_arm; | ||
148 | u32 val; | ||
149 | |||
150 | if (enable) { | ||
151 | saved_pll_arm = val = readl_relaxed(anatop_base + PLL_ARM); | ||
152 | val |= BM_PLL_ARM_ENABLE; | ||
153 | val &= ~BM_PLL_ARM_POWERDOWN; | ||
154 | writel_relaxed(val, anatop_base + PLL_ARM); | ||
155 | while (!(__raw_readl(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK)) | ||
156 | ; | ||
157 | } else { | ||
158 | writel_relaxed(saved_pll_arm, anatop_base + PLL_ARM); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | void imx6sl_set_wait_clk(bool enter) | ||
163 | { | ||
164 | static unsigned long saved_arm_div; | ||
165 | int arm_div_for_wait = imx6sl_get_arm_divider_for_wait(); | ||
166 | |||
167 | /* | ||
168 | * According to hardware design, arm podf change need | ||
169 | * PLL1 clock enabled. | ||
170 | */ | ||
171 | if (arm_div_for_wait == ARM_WAIT_DIV_396M) | ||
172 | imx6sl_enable_pll_arm(true); | ||
173 | |||
174 | if (enter) { | ||
175 | saved_arm_div = readl_relaxed(ccm_base + CACRR); | ||
176 | writel_relaxed(arm_div_for_wait, ccm_base + CACRR); | ||
177 | } else { | ||
178 | writel_relaxed(saved_arm_div, ccm_base + CACRR); | ||
179 | } | ||
180 | while (__raw_readl(ccm_base + CDHIPR) & BM_CDHIPR_ARM_PODF_BUSY) | ||
181 | ; | ||
182 | |||
183 | if (arm_div_for_wait == ARM_WAIT_DIV_396M) | ||
184 | imx6sl_enable_pll_arm(false); | ||
185 | } | ||
186 | |||
187 | static void __init imx6sl_clocks_init(struct device_node *ccm_node) | ||
188 | { | ||
189 | struct device_node *np; | ||
190 | void __iomem *base; | ||
191 | int i; | ||
192 | int ret; | ||
193 | |||
194 | clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
195 | clks[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0); | ||
196 | clks[IMX6SL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0); | ||
197 | /* Clock source from external clock via CLK1 PAD */ | ||
198 | clks[IMX6SL_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0); | ||
199 | |||
200 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop"); | ||
201 | base = of_iomap(np, 0); | ||
202 | WARN_ON(!base); | ||
203 | anatop_base = base; | ||
204 | |||
205 | clks[IMX6SL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
206 | clks[IMX6SL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
207 | clks[IMX6SL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
208 | clks[IMX6SL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
209 | clks[IMX6SL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
210 | clks[IMX6SL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
211 | clks[IMX6SL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
212 | |||
213 | /* type name parent_name base div_mask */ | ||
214 | clks[IMX6SL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f); | ||
215 | clks[IMX6SL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1); | ||
216 | clks[IMX6SL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3); | ||
217 | clks[IMX6SL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f); | ||
218 | clks[IMX6SL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f); | ||
219 | clks[IMX6SL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3); | ||
220 | clks[IMX6SL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3); | ||
221 | |||
222 | clks[IMX6SL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); | ||
223 | clks[IMX6SL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); | ||
224 | clks[IMX6SL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT); | ||
225 | clks[IMX6SL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT); | ||
226 | clks[IMX6SL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT); | ||
227 | clks[IMX6SL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT); | ||
228 | clks[IMX6SL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT); | ||
229 | |||
230 | /* Do not bypass PLLs initially */ | ||
231 | clk_set_parent(clks[IMX6SL_PLL1_BYPASS], clks[IMX6SL_CLK_PLL1]); | ||
232 | clk_set_parent(clks[IMX6SL_PLL2_BYPASS], clks[IMX6SL_CLK_PLL2]); | ||
233 | clk_set_parent(clks[IMX6SL_PLL3_BYPASS], clks[IMX6SL_CLK_PLL3]); | ||
234 | clk_set_parent(clks[IMX6SL_PLL4_BYPASS], clks[IMX6SL_CLK_PLL4]); | ||
235 | clk_set_parent(clks[IMX6SL_PLL5_BYPASS], clks[IMX6SL_CLK_PLL5]); | ||
236 | clk_set_parent(clks[IMX6SL_PLL6_BYPASS], clks[IMX6SL_CLK_PLL6]); | ||
237 | clk_set_parent(clks[IMX6SL_PLL7_BYPASS], clks[IMX6SL_CLK_PLL7]); | ||
238 | |||
239 | clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", base + 0x00, 13); | ||
240 | clks[IMX6SL_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13); | ||
241 | clks[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13); | ||
242 | clks[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13); | ||
243 | clks[IMX6SL_CLK_PLL5_VIDEO] = imx_clk_gate("pll5_video", "pll5_bypass", base + 0xa0, 13); | ||
244 | clks[IMX6SL_CLK_PLL6_ENET] = imx_clk_gate("pll6_enet", "pll6_bypass", base + 0xe0, 13); | ||
245 | clks[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13); | ||
246 | |||
247 | clks[IMX6SL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); | ||
248 | clks[IMX6SL_CLK_LVDS1_OUT] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x160, 10, BIT(12)); | ||
249 | clks[IMX6SL_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10)); | ||
250 | |||
251 | /* | ||
252 | * usbphy1 and usbphy2 are implemented as dummy gates using reserve | ||
253 | * bit 20. They are used by phy driver to keep the refcount of | ||
254 | * parent PLL correct. usbphy1_gate and usbphy2_gate only needs to be | ||
255 | * turned on during boot, and software will not need to control it | ||
256 | * anymore after that. | ||
257 | */ | ||
258 | clks[IMX6SL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20); | ||
259 | clks[IMX6SL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20); | ||
260 | clks[IMX6SL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6); | ||
261 | clks[IMX6SL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6); | ||
262 | |||
263 | /* dev name parent_name flags reg shift width div: flags, div_table lock */ | ||
264 | clks[IMX6SL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); | ||
265 | clks[IMX6SL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock); | ||
266 | clks[IMX6SL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); | ||
267 | clks[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); | ||
268 | clks[IMX6SL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0, base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock); | ||
269 | |||
270 | /* name parent_name reg idx */ | ||
271 | clks[IMX6SL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0", "pll2_bus", base + 0x100, 0); | ||
272 | clks[IMX6SL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_bus", base + 0x100, 1); | ||
273 | clks[IMX6SL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_bus", base + 0x100, 2); | ||
274 | clks[IMX6SL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0", "pll3_usb_otg", base + 0xf0, 0); | ||
275 | clks[IMX6SL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_usb_otg", base + 0xf0, 1); | ||
276 | clks[IMX6SL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", base + 0xf0, 2); | ||
277 | clks[IMX6SL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", base + 0xf0, 3); | ||
278 | |||
279 | /* name parent_name mult div */ | ||
280 | clks[IMX6SL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2", 1, 2); | ||
281 | clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); | ||
282 | clks[IMX6SL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); | ||
283 | clks[IMX6SL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); | ||
284 | |||
285 | np = ccm_node; | ||
286 | base = of_iomap(np, 0); | ||
287 | WARN_ON(!base); | ||
288 | ccm_base = base; | ||
289 | |||
290 | /* name reg shift width parent_names num_parents */ | ||
291 | clks[IMX6SL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); | ||
292 | clks[IMX6SL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); | ||
293 | clks[IMX6SL_CLK_OCRAM_ALT_SEL] = imx_clk_mux("ocram_alt_sel", base + 0x14, 7, 1, ocram_alt_sels, ARRAY_SIZE(ocram_alt_sels)); | ||
294 | clks[IMX6SL_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 1, ocram_sels, ARRAY_SIZE(ocram_sels)); | ||
295 | clks[IMX6SL_CLK_PRE_PERIPH2_SEL] = imx_clk_mux("pre_periph2_sel", base + 0x18, 21, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); | ||
296 | clks[IMX6SL_CLK_PRE_PERIPH_SEL] = imx_clk_mux("pre_periph_sel", base + 0x18, 18, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); | ||
297 | clks[IMX6SL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); | ||
298 | clks[IMX6SL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); | ||
299 | clks[IMX6SL_CLK_CSI_SEL] = imx_clk_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels)); | ||
300 | clks[IMX6SL_CLK_LCDIF_AXI_SEL] = imx_clk_mux("lcdif_axi_sel", base + 0x3c, 14, 2, lcdif_axi_sels, ARRAY_SIZE(lcdif_axi_sels)); | ||
301 | clks[IMX6SL_CLK_USDHC1_SEL] = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); | ||
302 | clks[IMX6SL_CLK_USDHC2_SEL] = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); | ||
303 | clks[IMX6SL_CLK_USDHC3_SEL] = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); | ||
304 | clks[IMX6SL_CLK_USDHC4_SEL] = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); | ||
305 | clks[IMX6SL_CLK_SSI1_SEL] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); | ||
306 | clks[IMX6SL_CLK_SSI2_SEL] = imx_clk_fixup_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); | ||
307 | clks[IMX6SL_CLK_SSI3_SEL] = imx_clk_fixup_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); | ||
308 | clks[IMX6SL_CLK_PERCLK_SEL] = imx_clk_fixup_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels), imx_cscmr1_fixup); | ||
309 | clks[IMX6SL_CLK_PXP_AXI_SEL] = imx_clk_mux("pxp_axi_sel", base + 0x34, 6, 3, pxp_axi_sels, ARRAY_SIZE(pxp_axi_sels)); | ||
310 | clks[IMX6SL_CLK_EPDC_AXI_SEL] = imx_clk_mux("epdc_axi_sel", base + 0x34, 15, 3, epdc_axi_sels, ARRAY_SIZE(epdc_axi_sels)); | ||
311 | clks[IMX6SL_CLK_GPU2D_OVG_SEL] = imx_clk_mux("gpu2d_ovg_sel", base + 0x18, 4, 2, gpu2d_ovg_sels, ARRAY_SIZE(gpu2d_ovg_sels)); | ||
312 | clks[IMX6SL_CLK_GPU2D_SEL] = imx_clk_mux("gpu2d_sel", base + 0x18, 8, 2, gpu2d_sels, ARRAY_SIZE(gpu2d_sels)); | ||
313 | clks[IMX6SL_CLK_LCDIF_PIX_SEL] = imx_clk_mux("lcdif_pix_sel", base + 0x38, 6, 3, lcdif_pix_sels, ARRAY_SIZE(lcdif_pix_sels)); | ||
314 | clks[IMX6SL_CLK_EPDC_PIX_SEL] = imx_clk_mux("epdc_pix_sel", base + 0x38, 15, 3, epdc_pix_sels, ARRAY_SIZE(epdc_pix_sels)); | ||
315 | clks[IMX6SL_CLK_SPDIF0_SEL] = imx_clk_mux("spdif0_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
316 | clks[IMX6SL_CLK_SPDIF1_SEL] = imx_clk_mux("spdif1_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
317 | clks[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
318 | clks[IMX6SL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); | ||
319 | clks[IMX6SL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels)); | ||
320 | |||
321 | /* name reg shift width busy: reg, shift parent_names num_parents */ | ||
322 | clks[IMX6SL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); | ||
323 | clks[IMX6SL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels)); | ||
324 | |||
325 | /* name parent_name reg shift width */ | ||
326 | clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3); | ||
327 | clks[IMX6SL_CLK_PERIPH_CLK2_PODF] = imx_clk_divider("periph_clk2_podf", "periph_clk2_sel", base + 0x14, 27, 3); | ||
328 | clks[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_divider("periph2_clk2_podf", "periph2_clk2_sel", base + 0x14, 0, 3); | ||
329 | clks[IMX6SL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); | ||
330 | clks[IMX6SL_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3); | ||
331 | clks[IMX6SL_CLK_LCDIF_AXI_PODF] = imx_clk_divider("lcdif_axi_podf", "lcdif_axi_sel", base + 0x3c, 16, 3); | ||
332 | clks[IMX6SL_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3); | ||
333 | clks[IMX6SL_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3); | ||
334 | clks[IMX6SL_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3); | ||
335 | clks[IMX6SL_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); | ||
336 | clks[IMX6SL_CLK_SSI1_PRED] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3); | ||
337 | clks[IMX6SL_CLK_SSI1_PODF] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6); | ||
338 | clks[IMX6SL_CLK_SSI2_PRED] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3); | ||
339 | clks[IMX6SL_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6); | ||
340 | clks[IMX6SL_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3); | ||
341 | clks[IMX6SL_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6); | ||
342 | clks[IMX6SL_CLK_PERCLK] = imx_clk_fixup_divider("perclk", "perclk_sel", base + 0x1c, 0, 6, imx_cscmr1_fixup); | ||
343 | clks[IMX6SL_CLK_PXP_AXI_PODF] = imx_clk_divider("pxp_axi_podf", "pxp_axi_sel", base + 0x34, 3, 3); | ||
344 | clks[IMX6SL_CLK_EPDC_AXI_PODF] = imx_clk_divider("epdc_axi_podf", "epdc_axi_sel", base + 0x34, 12, 3); | ||
345 | clks[IMX6SL_CLK_GPU2D_OVG_PODF] = imx_clk_divider("gpu2d_ovg_podf", "gpu2d_ovg_sel", base + 0x18, 26, 3); | ||
346 | clks[IMX6SL_CLK_GPU2D_PODF] = imx_clk_divider("gpu2d_podf", "gpu2d_sel", base + 0x18, 29, 3); | ||
347 | clks[IMX6SL_CLK_LCDIF_PIX_PRED] = imx_clk_divider("lcdif_pix_pred", "lcdif_pix_sel", base + 0x38, 3, 3); | ||
348 | clks[IMX6SL_CLK_EPDC_PIX_PRED] = imx_clk_divider("epdc_pix_pred", "epdc_pix_sel", base + 0x38, 12, 3); | ||
349 | clks[IMX6SL_CLK_LCDIF_PIX_PODF] = imx_clk_fixup_divider("lcdif_pix_podf", "lcdif_pix_pred", base + 0x1c, 20, 3, imx_cscmr1_fixup); | ||
350 | clks[IMX6SL_CLK_EPDC_PIX_PODF] = imx_clk_divider("epdc_pix_podf", "epdc_pix_pred", base + 0x18, 23, 3); | ||
351 | clks[IMX6SL_CLK_SPDIF0_PRED] = imx_clk_divider("spdif0_pred", "spdif0_sel", base + 0x30, 25, 3); | ||
352 | clks[IMX6SL_CLK_SPDIF0_PODF] = imx_clk_divider("spdif0_podf", "spdif0_pred", base + 0x30, 22, 3); | ||
353 | clks[IMX6SL_CLK_SPDIF1_PRED] = imx_clk_divider("spdif1_pred", "spdif1_sel", base + 0x30, 12, 3); | ||
354 | clks[IMX6SL_CLK_SPDIF1_PODF] = imx_clk_divider("spdif1_podf", "spdif1_pred", base + 0x30, 9, 3); | ||
355 | clks[IMX6SL_CLK_EXTERN_AUDIO_PRED] = imx_clk_divider("extern_audio_pred", "extern_audio_sel", base + 0x28, 9, 3); | ||
356 | clks[IMX6SL_CLK_EXTERN_AUDIO_PODF] = imx_clk_divider("extern_audio_podf", "extern_audio_pred", base + 0x28, 25, 3); | ||
357 | clks[IMX6SL_CLK_ECSPI_ROOT] = imx_clk_divider("ecspi_root", "ecspi_sel", base + 0x38, 19, 6); | ||
358 | clks[IMX6SL_CLK_UART_ROOT] = imx_clk_divider("uart_root", "uart_sel", base + 0x24, 0, 6); | ||
359 | |||
360 | /* name parent_name reg shift width busy: reg, shift */ | ||
361 | clks[IMX6SL_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1); | ||
362 | clks[IMX6SL_CLK_MMDC_ROOT] = imx_clk_busy_divider("mmdc", "periph2", base + 0x14, 3, 3, base + 0x48, 2); | ||
363 | clks[IMX6SL_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16); | ||
364 | |||
365 | /* name parent_name reg shift */ | ||
366 | clks[IMX6SL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0); | ||
367 | clks[IMX6SL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2); | ||
368 | clks[IMX6SL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4); | ||
369 | clks[IMX6SL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6); | ||
370 | clks[IMX6SL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10); | ||
371 | clks[IMX6SL_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12); | ||
372 | clks[IMX6SL_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14); | ||
373 | clks[IMX6SL_CLK_EXTERN_AUDIO] = imx_clk_gate2("extern_audio", "extern_audio_podf", base + 0x6c, 16); | ||
374 | clks[IMX6SL_CLK_GPT] = imx_clk_gate2("gpt", "perclk", base + 0x6c, 20); | ||
375 | clks[IMX6SL_CLK_GPT_SERIAL] = imx_clk_gate2("gpt_serial", "perclk", base + 0x6c, 22); | ||
376 | clks[IMX6SL_CLK_GPU2D_OVG] = imx_clk_gate2("gpu2d_ovg", "gpu2d_ovg_podf", base + 0x6c, 26); | ||
377 | clks[IMX6SL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6); | ||
378 | clks[IMX6SL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8); | ||
379 | clks[IMX6SL_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10); | ||
380 | clks[IMX6SL_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12); | ||
381 | clks[IMX6SL_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x74, 0); | ||
382 | clks[IMX6SL_CLK_PXP_AXI] = imx_clk_gate2("pxp_axi", "pxp_axi_podf", base + 0x74, 2); | ||
383 | clks[IMX6SL_CLK_EPDC_AXI] = imx_clk_gate2("epdc_axi", "epdc_axi_podf", base + 0x74, 4); | ||
384 | clks[IMX6SL_CLK_LCDIF_AXI] = imx_clk_gate2("lcdif_axi", "lcdif_axi_podf", base + 0x74, 6); | ||
385 | clks[IMX6SL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_pix_podf", base + 0x74, 8); | ||
386 | clks[IMX6SL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_pix_podf", base + 0x74, 10); | ||
387 | clks[IMX6SL_CLK_OCRAM] = imx_clk_gate2("ocram", "ocram_podf", base + 0x74, 28); | ||
388 | clks[IMX6SL_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16); | ||
389 | clks[IMX6SL_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18); | ||
390 | clks[IMX6SL_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20); | ||
391 | clks[IMX6SL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22); | ||
392 | clks[IMX6SL_CLK_SDMA] = imx_clk_gate2("sdma", "ipg", base + 0x7c, 6); | ||
393 | clks[IMX6SL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); | ||
394 | clks[IMX6SL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif0_podf", base + 0x7c, 14); | ||
395 | clks[IMX6SL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1); | ||
396 | clks[IMX6SL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2); | ||
397 | clks[IMX6SL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3); | ||
398 | clks[IMX6SL_CLK_SSI1] = imx_clk_gate2_shared("ssi1", "ssi1_podf", base + 0x7c, 18, &share_count_ssi1); | ||
399 | clks[IMX6SL_CLK_SSI2] = imx_clk_gate2_shared("ssi2", "ssi2_podf", base + 0x7c, 20, &share_count_ssi2); | ||
400 | clks[IMX6SL_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3); | ||
401 | clks[IMX6SL_CLK_UART] = imx_clk_gate2("uart", "ipg", base + 0x7c, 24); | ||
402 | clks[IMX6SL_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_root", base + 0x7c, 26); | ||
403 | clks[IMX6SL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); | ||
404 | clks[IMX6SL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2); | ||
405 | clks[IMX6SL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); | ||
406 | clks[IMX6SL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); | ||
407 | clks[IMX6SL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); | ||
408 | |||
409 | imx_check_clocks(clks, ARRAY_SIZE(clks)); | ||
410 | |||
411 | clk_data.clks = clks; | ||
412 | clk_data.clk_num = ARRAY_SIZE(clks); | ||
413 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
414 | |||
415 | /* Ensure the AHB clk is at 132MHz. */ | ||
416 | ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000); | ||
417 | if (ret) | ||
418 | pr_warn("%s: failed to set AHB clock rate %d!\n", | ||
419 | __func__, ret); | ||
420 | |||
421 | /* | ||
422 | * Make sure those always on clocks are enabled to maintain the correct | ||
423 | * usecount and enabling/disabling of parent PLLs. | ||
424 | */ | ||
425 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | ||
426 | clk_prepare_enable(clks[clks_init_on[i]]); | ||
427 | |||
428 | if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { | ||
429 | clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]); | ||
430 | clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]); | ||
431 | } | ||
432 | |||
433 | /* Audio-related clocks configuration */ | ||
434 | clk_set_parent(clks[IMX6SL_CLK_SPDIF0_SEL], clks[IMX6SL_CLK_PLL3_PFD3]); | ||
435 | |||
436 | /* set PLL5 video as lcdif pix parent clock */ | ||
437 | clk_set_parent(clks[IMX6SL_CLK_LCDIF_PIX_SEL], | ||
438 | clks[IMX6SL_CLK_PLL5_VIDEO_DIV]); | ||
439 | |||
440 | clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL], | ||
441 | clks[IMX6SL_CLK_PLL2_PFD2]); | ||
442 | } | ||
443 | CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init); | ||
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c new file mode 100644 index 000000000000..5b95c2c2bf52 --- /dev/null +++ b/drivers/clk/imx/clk-imx6sx.c | |||
@@ -0,0 +1,561 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <dt-bindings/clock/imx6sx-clock.h> | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/clkdev.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/init.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 <linux/types.h> | ||
22 | |||
23 | #include "clk.h" | ||
24 | |||
25 | #define CCDR 0x4 | ||
26 | #define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16) | ||
27 | |||
28 | static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; | ||
29 | static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; | ||
30 | static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; | ||
31 | static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", }; | ||
32 | static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", }; | ||
33 | static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", }; | ||
34 | static const char *periph_sels[] = { "periph_pre", "periph_clk2", }; | ||
35 | static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", }; | ||
36 | static const char *ocram_sels[] = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", }; | ||
37 | static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", }; | ||
38 | static const char *gpu_axi_sels[] = { "pll2_pfd2_396m", "pll3_pfd0_720m", "pll3_pfd1_540m", "pll2_bus", }; | ||
39 | static const char *gpu_core_sels[] = { "pll3_pfd1_540m", "pll3_pfd0_720m", "pll2_bus", "pll2_pfd2_396m", }; | ||
40 | static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", }; | ||
41 | static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", }; | ||
42 | static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", }; | ||
43 | static const char *ldb_di1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", }; | ||
44 | static const char *pcie_axi_sels[] = { "axi", "ahb", }; | ||
45 | static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll5_video_div", "pll4_audio_div", }; | ||
46 | static const char *qspi1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", }; | ||
47 | static const char *perclk_sels[] = { "ipg", "osc", }; | ||
48 | static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; | ||
49 | static const char *vid_sels[] = { "pll3_pfd1_540m", "pll3_usb_otg", "pll3_pfd3_454m", "pll4_audio_div", "pll5_video_div", }; | ||
50 | static const char *can_sels[] = { "pll3_60m", "osc", "pll3_80m", "dummy", }; | ||
51 | static const char *uart_sels[] = { "pll3_80m", "osc", }; | ||
52 | static const char *qspi2_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd3_454m", "dummy", "dummy", "dummy", }; | ||
53 | static const char *enet_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", }; | ||
54 | static const char *enet_sels[] = { "enet_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; | ||
55 | static const char *m4_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "osc", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd3_454m", }; | ||
56 | static const char *m4_sels[] = { "m4_pre_sel", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; | ||
57 | static const char *eim_slow_sels[] = { "ocram", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", }; | ||
58 | static const char *ecspi_sels[] = { "pll3_60m", "osc", }; | ||
59 | static const char *lcdif1_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", }; | ||
60 | static const char *lcdif1_sels[] = { "lcdif1_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; | ||
61 | static const char *lcdif2_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd3_594m", "pll3_pfd1_540m", }; | ||
62 | static const char *lcdif2_sels[] = { "lcdif2_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; | ||
63 | static const char *display_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll3_usb_otg", "pll3_pfd1_540m", }; | ||
64 | static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; | ||
65 | static const char *cko1_sels[] = { | ||
66 | "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div", | ||
67 | "dummy", "ocram", "dummy", "pxp_axi", "epdc_axi", "lcdif_pix", | ||
68 | "epdc_pix", "ahb", "ipg", "perclk", "ckil", "pll4_audio_div", | ||
69 | }; | ||
70 | static const char *cko2_sels[] = { | ||
71 | "dummy", "mmdc_p0_fast", "usdhc4", "usdhc1", "dummy", "wrck", | ||
72 | "ecspi_root", "dummy", "usdhc3", "pcie", "arm", "csi_core", | ||
73 | "lcdif_axi", "dummy", "osc", "dummy", "gpu2d_ovg_core", | ||
74 | "usdhc2", "ssi1", "ssi2", "ssi3", "gpu2d_core", "dummy", | ||
75 | "dummy", "dummy", "dummy", "esai_extal", "eim_slow", "uart_serial", | ||
76 | "spdif", "asrc", "dummy", | ||
77 | }; | ||
78 | static const char *cko_sels[] = { "cko1", "cko2", }; | ||
79 | static const char *lvds_sels[] = { | ||
80 | "arm", "pll1_sys", "dummy", "dummy", "dummy", "dummy", "dummy", "pll5_video_div", | ||
81 | "dummy", "dummy", "pcie_ref_125m", "dummy", "usbphy1", "usbphy2", | ||
82 | }; | ||
83 | static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", }; | ||
84 | static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", }; | ||
85 | static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", }; | ||
86 | static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", }; | ||
87 | static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", }; | ||
88 | static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", }; | ||
89 | static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; | ||
90 | static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; | ||
91 | |||
92 | static struct clk *clks[IMX6SX_CLK_CLK_END]; | ||
93 | static struct clk_onecell_data clk_data; | ||
94 | |||
95 | static int const clks_init_on[] __initconst = { | ||
96 | IMX6SX_CLK_AIPS_TZ1, IMX6SX_CLK_AIPS_TZ2, IMX6SX_CLK_AIPS_TZ3, | ||
97 | IMX6SX_CLK_IPMUX1, IMX6SX_CLK_IPMUX2, IMX6SX_CLK_IPMUX3, | ||
98 | IMX6SX_CLK_WAKEUP, IMX6SX_CLK_MMDC_P0_FAST, IMX6SX_CLK_MMDC_P0_IPG, | ||
99 | IMX6SX_CLK_ROM, IMX6SX_CLK_ARM, IMX6SX_CLK_IPG, IMX6SX_CLK_OCRAM, | ||
100 | IMX6SX_CLK_PER2_MAIN, IMX6SX_CLK_PERCLK, IMX6SX_CLK_M4, | ||
101 | IMX6SX_CLK_QSPI1, IMX6SX_CLK_QSPI2, IMX6SX_CLK_UART_IPG, | ||
102 | IMX6SX_CLK_UART_SERIAL, IMX6SX_CLK_I2C3, IMX6SX_CLK_ECSPI5, | ||
103 | IMX6SX_CLK_CAN1_IPG, IMX6SX_CLK_CAN1_SERIAL, IMX6SX_CLK_CAN2_IPG, | ||
104 | IMX6SX_CLK_CAN2_SERIAL, IMX6SX_CLK_CANFD, IMX6SX_CLK_EPIT1, | ||
105 | IMX6SX_CLK_EPIT2, | ||
106 | }; | ||
107 | |||
108 | static struct clk_div_table clk_enet_ref_table[] = { | ||
109 | { .val = 0, .div = 20, }, | ||
110 | { .val = 1, .div = 10, }, | ||
111 | { .val = 2, .div = 5, }, | ||
112 | { .val = 3, .div = 4, }, | ||
113 | { } | ||
114 | }; | ||
115 | |||
116 | static struct clk_div_table post_div_table[] = { | ||
117 | { .val = 2, .div = 1, }, | ||
118 | { .val = 1, .div = 2, }, | ||
119 | { .val = 0, .div = 4, }, | ||
120 | { } | ||
121 | }; | ||
122 | |||
123 | static struct clk_div_table video_div_table[] = { | ||
124 | { .val = 0, .div = 1, }, | ||
125 | { .val = 1, .div = 2, }, | ||
126 | { .val = 2, .div = 1, }, | ||
127 | { .val = 3, .div = 4, }, | ||
128 | { } | ||
129 | }; | ||
130 | |||
131 | static u32 share_count_asrc; | ||
132 | static u32 share_count_audio; | ||
133 | static u32 share_count_esai; | ||
134 | static u32 share_count_ssi1; | ||
135 | static u32 share_count_ssi2; | ||
136 | static u32 share_count_ssi3; | ||
137 | |||
138 | static void __init imx6sx_clocks_init(struct device_node *ccm_node) | ||
139 | { | ||
140 | struct device_node *np; | ||
141 | void __iomem *base; | ||
142 | int i; | ||
143 | |||
144 | clks[IMX6SX_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
145 | |||
146 | clks[IMX6SX_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil"); | ||
147 | clks[IMX6SX_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc"); | ||
148 | |||
149 | /* ipp_di clock is external input */ | ||
150 | clks[IMX6SX_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0"); | ||
151 | clks[IMX6SX_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1"); | ||
152 | |||
153 | /* Clock source from external clock via CLK1 PAD */ | ||
154 | clks[IMX6SX_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0); | ||
155 | |||
156 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-anatop"); | ||
157 | base = of_iomap(np, 0); | ||
158 | WARN_ON(!base); | ||
159 | |||
160 | clks[IMX6SX_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
161 | clks[IMX6SX_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
162 | clks[IMX6SX_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
163 | clks[IMX6SX_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
164 | clks[IMX6SX_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
165 | clks[IMX6SX_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
166 | clks[IMX6SX_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
167 | |||
168 | /* type name parent_name base div_mask */ | ||
169 | clks[IMX6SX_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f); | ||
170 | clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1); | ||
171 | clks[IMX6SX_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3); | ||
172 | clks[IMX6SX_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f); | ||
173 | clks[IMX6SX_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f); | ||
174 | clks[IMX6SX_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3); | ||
175 | clks[IMX6SX_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3); | ||
176 | |||
177 | clks[IMX6SX_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); | ||
178 | clks[IMX6SX_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); | ||
179 | clks[IMX6SX_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT); | ||
180 | clks[IMX6SX_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT); | ||
181 | clks[IMX6SX_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT); | ||
182 | clks[IMX6SX_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT); | ||
183 | clks[IMX6SX_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT); | ||
184 | |||
185 | /* Do not bypass PLLs initially */ | ||
186 | clk_set_parent(clks[IMX6SX_PLL1_BYPASS], clks[IMX6SX_CLK_PLL1]); | ||
187 | clk_set_parent(clks[IMX6SX_PLL2_BYPASS], clks[IMX6SX_CLK_PLL2]); | ||
188 | clk_set_parent(clks[IMX6SX_PLL3_BYPASS], clks[IMX6SX_CLK_PLL3]); | ||
189 | clk_set_parent(clks[IMX6SX_PLL4_BYPASS], clks[IMX6SX_CLK_PLL4]); | ||
190 | clk_set_parent(clks[IMX6SX_PLL5_BYPASS], clks[IMX6SX_CLK_PLL5]); | ||
191 | clk_set_parent(clks[IMX6SX_PLL6_BYPASS], clks[IMX6SX_CLK_PLL6]); | ||
192 | clk_set_parent(clks[IMX6SX_PLL7_BYPASS], clks[IMX6SX_CLK_PLL7]); | ||
193 | |||
194 | clks[IMX6SX_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", base + 0x00, 13); | ||
195 | clks[IMX6SX_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13); | ||
196 | clks[IMX6SX_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13); | ||
197 | clks[IMX6SX_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13); | ||
198 | clks[IMX6SX_CLK_PLL5_VIDEO] = imx_clk_gate("pll5_video", "pll5_bypass", base + 0xa0, 13); | ||
199 | clks[IMX6SX_CLK_PLL6_ENET] = imx_clk_gate("pll6_enet", "pll6_bypass", base + 0xe0, 13); | ||
200 | clks[IMX6SX_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13); | ||
201 | |||
202 | /* | ||
203 | * Bit 20 is the reserved and read-only bit, we do this only for: | ||
204 | * - Do nothing for usbphy clk_enable/disable | ||
205 | * - Keep refcount when do usbphy clk_enable/disable, in that case, | ||
206 | * the clk framework may need to enable/disable usbphy's parent | ||
207 | */ | ||
208 | clks[IMX6SX_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20); | ||
209 | clks[IMX6SX_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20); | ||
210 | |||
211 | /* | ||
212 | * usbphy*_gate needs to be on after system boots up, and software | ||
213 | * never needs to control it anymore. | ||
214 | */ | ||
215 | clks[IMX6SX_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6); | ||
216 | clks[IMX6SX_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6); | ||
217 | |||
218 | /* FIXME 100MHz is used for pcie ref for all imx6 pcie, excepted imx6q */ | ||
219 | clks[IMX6SX_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 5); | ||
220 | clks[IMX6SX_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19); | ||
221 | |||
222 | clks[IMX6SX_CLK_LVDS1_OUT] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x160, 10, BIT(12)); | ||
223 | clks[IMX6SX_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10)); | ||
224 | |||
225 | clks[IMX6SX_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0, | ||
226 | base + 0xe0, 0, 2, 0, clk_enet_ref_table, | ||
227 | &imx_ccm_lock); | ||
228 | clks[IMX6SX_CLK_ENET2_REF] = clk_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0, | ||
229 | base + 0xe0, 2, 2, 0, clk_enet_ref_table, | ||
230 | &imx_ccm_lock); | ||
231 | clks[IMX6SX_CLK_ENET2_REF_125M] = imx_clk_gate("enet2_ref_125m", "enet2_ref", base + 0xe0, 20); | ||
232 | |||
233 | clks[IMX6SX_CLK_ENET_PTP_REF] = imx_clk_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20); | ||
234 | clks[IMX6SX_CLK_ENET_PTP] = imx_clk_gate("enet_ptp_25m", "enet_ptp_ref", base + 0xe0, 21); | ||
235 | |||
236 | /* name parent_name reg idx */ | ||
237 | clks[IMX6SX_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0); | ||
238 | clks[IMX6SX_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1); | ||
239 | clks[IMX6SX_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2); | ||
240 | clks[IMX6SX_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus", base + 0x100, 3); | ||
241 | clks[IMX6SX_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0); | ||
242 | clks[IMX6SX_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1); | ||
243 | clks[IMX6SX_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2); | ||
244 | clks[IMX6SX_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3); | ||
245 | |||
246 | /* name parent_name mult div */ | ||
247 | clks[IMX6SX_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2); | ||
248 | clks[IMX6SX_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); | ||
249 | clks[IMX6SX_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); | ||
250 | clks[IMX6SX_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); | ||
251 | clks[IMX6SX_CLK_TWD] = imx_clk_fixed_factor("twd", "arm", 1, 2); | ||
252 | clks[IMX6SX_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); | ||
253 | |||
254 | clks[IMX6SX_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", | ||
255 | CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); | ||
256 | clks[IMX6SX_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", | ||
257 | CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock); | ||
258 | clks[IMX6SX_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", | ||
259 | CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); | ||
260 | clks[IMX6SX_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", | ||
261 | CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); | ||
262 | |||
263 | /* name reg shift width parent_names num_parents */ | ||
264 | clks[IMX6SX_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); | ||
265 | |||
266 | np = ccm_node; | ||
267 | base = of_iomap(np, 0); | ||
268 | WARN_ON(!base); | ||
269 | |||
270 | /* name reg shift width parent_names num_parents */ | ||
271 | clks[IMX6SX_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); | ||
272 | clks[IMX6SX_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); | ||
273 | clks[IMX6SX_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 2, ocram_sels, ARRAY_SIZE(ocram_sels)); | ||
274 | clks[IMX6SX_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels)); | ||
275 | clks[IMX6SX_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels)); | ||
276 | clks[IMX6SX_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); | ||
277 | clks[IMX6SX_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); | ||
278 | clks[IMX6SX_CLK_PCIE_AXI_SEL] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels)); | ||
279 | clks[IMX6SX_CLK_GPU_AXI_SEL] = imx_clk_mux("gpu_axi_sel", base + 0x18, 8, 2, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels)); | ||
280 | clks[IMX6SX_CLK_GPU_CORE_SEL] = imx_clk_mux("gpu_core_sel", base + 0x18, 4, 2, gpu_core_sels, ARRAY_SIZE(gpu_core_sels)); | ||
281 | clks[IMX6SX_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels)); | ||
282 | clks[IMX6SX_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); | ||
283 | clks[IMX6SX_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); | ||
284 | clks[IMX6SX_CLK_USDHC3_SEL] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); | ||
285 | clks[IMX6SX_CLK_USDHC4_SEL] = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); | ||
286 | clks[IMX6SX_CLK_SSI3_SEL] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); | ||
287 | clks[IMX6SX_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); | ||
288 | clks[IMX6SX_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); | ||
289 | clks[IMX6SX_CLK_QSPI1_SEL] = imx_clk_mux_flags("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT); | ||
290 | clks[IMX6SX_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels)); | ||
291 | clks[IMX6SX_CLK_VID_SEL] = imx_clk_mux("vid_sel", base + 0x20, 21, 3, vid_sels, ARRAY_SIZE(vid_sels)); | ||
292 | clks[IMX6SX_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
293 | clks[IMX6SX_CLK_CAN_SEL] = imx_clk_mux("can_sel", base + 0x20, 8, 2, can_sels, ARRAY_SIZE(can_sels)); | ||
294 | clks[IMX6SX_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels)); | ||
295 | clks[IMX6SX_CLK_QSPI2_SEL] = imx_clk_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT); | ||
296 | clks[IMX6SX_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
297 | clks[IMX6SX_CLK_AUDIO_SEL] = imx_clk_mux("audio_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels)); | ||
298 | clks[IMX6SX_CLK_ENET_PRE_SEL] = imx_clk_mux("enet_pre_sel", base + 0x34, 15, 3, enet_pre_sels, ARRAY_SIZE(enet_pre_sels)); | ||
299 | clks[IMX6SX_CLK_ENET_SEL] = imx_clk_mux("enet_sel", base + 0x34, 9, 3, enet_sels, ARRAY_SIZE(enet_sels)); | ||
300 | clks[IMX6SX_CLK_M4_PRE_SEL] = imx_clk_mux("m4_pre_sel", base + 0x34, 6, 3, m4_pre_sels, ARRAY_SIZE(m4_pre_sels)); | ||
301 | clks[IMX6SX_CLK_M4_SEL] = imx_clk_mux("m4_sel", base + 0x34, 0, 3, m4_sels, ARRAY_SIZE(m4_sels)); | ||
302 | clks[IMX6SX_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); | ||
303 | clks[IMX6SX_CLK_LCDIF2_PRE_SEL] = imx_clk_mux("lcdif2_pre_sel", base + 0x38, 6, 3, lcdif2_pre_sels, ARRAY_SIZE(lcdif2_pre_sels)); | ||
304 | clks[IMX6SX_CLK_LCDIF2_SEL] = imx_clk_mux("lcdif2_sel", base + 0x38, 0, 3, lcdif2_sels, ARRAY_SIZE(lcdif2_sels)); | ||
305 | clks[IMX6SX_CLK_DISPLAY_SEL] = imx_clk_mux("display_sel", base + 0x3c, 14, 2, display_sels, ARRAY_SIZE(display_sels)); | ||
306 | clks[IMX6SX_CLK_CSI_SEL] = imx_clk_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels)); | ||
307 | clks[IMX6SX_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels)); | ||
308 | clks[IMX6SX_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels)); | ||
309 | clks[IMX6SX_CLK_CKO] = imx_clk_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels)); | ||
310 | |||
311 | clks[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT); | ||
312 | clks[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT); | ||
313 | clks[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels), CLK_SET_RATE_PARENT); | ||
314 | clks[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels), CLK_SET_RATE_PARENT); | ||
315 | clks[IMX6SX_CLK_LCDIF1_PRE_SEL] = imx_clk_mux_flags("lcdif1_pre_sel", base + 0x38, 15, 3, lcdif1_pre_sels, ARRAY_SIZE(lcdif1_pre_sels), CLK_SET_RATE_PARENT); | ||
316 | clks[IMX6SX_CLK_LCDIF1_SEL] = imx_clk_mux_flags("lcdif1_sel", base + 0x38, 9, 3, lcdif1_sels, ARRAY_SIZE(lcdif1_sels), CLK_SET_RATE_PARENT); | ||
317 | |||
318 | /* name parent_name reg shift width */ | ||
319 | clks[IMX6SX_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3); | ||
320 | clks[IMX6SX_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3); | ||
321 | clks[IMX6SX_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); | ||
322 | clks[IMX6SX_CLK_GPU_CORE_PODF] = imx_clk_divider("gpu_core_podf", "gpu_core_sel", base + 0x18, 29, 3); | ||
323 | clks[IMX6SX_CLK_GPU_AXI_PODF] = imx_clk_divider("gpu_axi_podf", "gpu_axi_sel", base + 0x18, 26, 3); | ||
324 | clks[IMX6SX_CLK_LCDIF1_PODF] = imx_clk_divider("lcdif1_podf", "lcdif1_pred", base + 0x18, 23, 3); | ||
325 | clks[IMX6SX_CLK_QSPI1_PODF] = imx_clk_divider("qspi1_podf", "qspi1_sel", base + 0x1c, 26, 3); | ||
326 | clks[IMX6SX_CLK_EIM_SLOW_PODF] = imx_clk_divider("eim_slow_podf", "eim_slow_sel", base + 0x1c, 23, 3); | ||
327 | clks[IMX6SX_CLK_LCDIF2_PODF] = imx_clk_divider("lcdif2_podf", "lcdif2_pred", base + 0x1c, 20, 3); | ||
328 | clks[IMX6SX_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6); | ||
329 | clks[IMX6SX_CLK_VID_PODF] = imx_clk_divider("vid_podf", "vid_sel", base + 0x20, 24, 2); | ||
330 | clks[IMX6SX_CLK_CAN_PODF] = imx_clk_divider("can_podf", "can_sel", base + 0x20, 2, 6); | ||
331 | clks[IMX6SX_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); | ||
332 | clks[IMX6SX_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3); | ||
333 | clks[IMX6SX_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3); | ||
334 | clks[IMX6SX_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3); | ||
335 | clks[IMX6SX_CLK_UART_PODF] = imx_clk_divider("uart_podf", "uart_sel", base + 0x24, 0, 6); | ||
336 | clks[IMX6SX_CLK_ESAI_PRED] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3); | ||
337 | clks[IMX6SX_CLK_ESAI_PODF] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3); | ||
338 | clks[IMX6SX_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3); | ||
339 | clks[IMX6SX_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6); | ||
340 | clks[IMX6SX_CLK_SSI1_PRED] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3); | ||
341 | clks[IMX6SX_CLK_SSI1_PODF] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6); | ||
342 | clks[IMX6SX_CLK_QSPI2_PRED] = imx_clk_divider("qspi2_pred", "qspi2_sel", base + 0x2c, 18, 3); | ||
343 | clks[IMX6SX_CLK_QSPI2_PODF] = imx_clk_divider("qspi2_podf", "qspi2_pred", base + 0x2c, 21, 6); | ||
344 | clks[IMX6SX_CLK_SSI2_PRED] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3); | ||
345 | clks[IMX6SX_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6); | ||
346 | clks[IMX6SX_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3); | ||
347 | clks[IMX6SX_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3); | ||
348 | clks[IMX6SX_CLK_AUDIO_PRED] = imx_clk_divider("audio_pred", "audio_sel", base + 0x30, 12, 3); | ||
349 | clks[IMX6SX_CLK_AUDIO_PODF] = imx_clk_divider("audio_podf", "audio_pred", base + 0x30, 9, 3); | ||
350 | clks[IMX6SX_CLK_ENET_PODF] = imx_clk_divider("enet_podf", "enet_pre_sel", base + 0x34, 12, 3); | ||
351 | clks[IMX6SX_CLK_M4_PODF] = imx_clk_divider("m4_podf", "m4_sel", base + 0x34, 3, 3); | ||
352 | clks[IMX6SX_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel", base + 0x38, 19, 6); | ||
353 | clks[IMX6SX_CLK_LCDIF1_PRED] = imx_clk_divider("lcdif1_pred", "lcdif1_pre_sel", base + 0x38, 12, 3); | ||
354 | clks[IMX6SX_CLK_LCDIF2_PRED] = imx_clk_divider("lcdif2_pred", "lcdif2_pre_sel", base + 0x38, 3, 3); | ||
355 | clks[IMX6SX_CLK_DISPLAY_PODF] = imx_clk_divider("display_podf", "display_sel", base + 0x3c, 16, 3); | ||
356 | clks[IMX6SX_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3); | ||
357 | clks[IMX6SX_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3); | ||
358 | clks[IMX6SX_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3); | ||
359 | |||
360 | clks[IMX6SX_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); | ||
361 | clks[IMX6SX_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7); | ||
362 | clks[IMX6SX_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); | ||
363 | clks[IMX6SX_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7); | ||
364 | |||
365 | /* name reg shift width busy: reg, shift parent_names num_parents */ | ||
366 | clks[IMX6SX_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); | ||
367 | clks[IMX6SX_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels)); | ||
368 | /* name parent_name reg shift width busy: reg, shift */ | ||
369 | clks[IMX6SX_CLK_OCRAM_PODF] = imx_clk_busy_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3, base + 0x48, 0); | ||
370 | clks[IMX6SX_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1); | ||
371 | clks[IMX6SX_CLK_MMDC_PODF] = imx_clk_busy_divider("mmdc_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2); | ||
372 | clks[IMX6SX_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16); | ||
373 | |||
374 | /* name parent_name reg shift */ | ||
375 | /* CCGR0 */ | ||
376 | clks[IMX6SX_CLK_AIPS_TZ1] = imx_clk_gate2("aips_tz1", "ahb", base + 0x68, 0); | ||
377 | clks[IMX6SX_CLK_AIPS_TZ2] = imx_clk_gate2("aips_tz2", "ahb", base + 0x68, 2); | ||
378 | clks[IMX6SX_CLK_APBH_DMA] = imx_clk_gate2("apbh_dma", "usdhc3", base + 0x68, 4); | ||
379 | clks[IMX6SX_CLK_ASRC_MEM] = imx_clk_gate2_shared("asrc_mem", "ahb", base + 0x68, 6, &share_count_asrc); | ||
380 | clks[IMX6SX_CLK_ASRC_IPG] = imx_clk_gate2_shared("asrc_ipg", "ahb", base + 0x68, 6, &share_count_asrc); | ||
381 | clks[IMX6SX_CLK_CAAM_MEM] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8); | ||
382 | clks[IMX6SX_CLK_CAAM_ACLK] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10); | ||
383 | clks[IMX6SX_CLK_CAAM_IPG] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12); | ||
384 | clks[IMX6SX_CLK_CAN1_IPG] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14); | ||
385 | clks[IMX6SX_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_podf", base + 0x68, 16); | ||
386 | clks[IMX6SX_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18); | ||
387 | clks[IMX6SX_CLK_CAN2_SERIAL] = imx_clk_gate2("can2_serial", "can_podf", base + 0x68, 20); | ||
388 | clks[IMX6SX_CLK_DCIC1] = imx_clk_gate2("dcic1", "display_podf", base + 0x68, 24); | ||
389 | clks[IMX6SX_CLK_DCIC2] = imx_clk_gate2("dcic2", "display_podf", base + 0x68, 26); | ||
390 | clks[IMX6SX_CLK_AIPS_TZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30); | ||
391 | |||
392 | /* CCGR1 */ | ||
393 | clks[IMX6SX_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_podf", base + 0x6c, 0); | ||
394 | clks[IMX6SX_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_podf", base + 0x6c, 2); | ||
395 | clks[IMX6SX_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_podf", base + 0x6c, 4); | ||
396 | clks[IMX6SX_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_podf", base + 0x6c, 6); | ||
397 | clks[IMX6SX_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_podf", base + 0x6c, 8); | ||
398 | clks[IMX6SX_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12); | ||
399 | clks[IMX6SX_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14); | ||
400 | clks[IMX6SX_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x6c, 16, &share_count_esai); | ||
401 | clks[IMX6SX_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x6c, 16, &share_count_esai); | ||
402 | clks[IMX6SX_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai); | ||
403 | clks[IMX6SX_CLK_WAKEUP] = imx_clk_gate2("wakeup", "ipg", base + 0x6c, 18); | ||
404 | clks[IMX6SX_CLK_GPT_BUS] = imx_clk_gate2("gpt_bus", "perclk", base + 0x6c, 20); | ||
405 | clks[IMX6SX_CLK_GPT_SERIAL] = imx_clk_gate2("gpt_serial", "perclk", base + 0x6c, 22); | ||
406 | clks[IMX6SX_CLK_GPU] = imx_clk_gate2("gpu", "gpu_core_podf", base + 0x6c, 26); | ||
407 | clks[IMX6SX_CLK_CANFD] = imx_clk_gate2("canfd", "can_podf", base + 0x6c, 30); | ||
408 | |||
409 | /* CCGR2 */ | ||
410 | clks[IMX6SX_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x70, 2); | ||
411 | clks[IMX6SX_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6); | ||
412 | clks[IMX6SX_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8); | ||
413 | clks[IMX6SX_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10); | ||
414 | clks[IMX6SX_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12); | ||
415 | clks[IMX6SX_CLK_IOMUXC] = imx_clk_gate2("iomuxc", "lcdif1_podf", base + 0x70, 14); | ||
416 | clks[IMX6SX_CLK_IPMUX1] = imx_clk_gate2("ipmux1", "ahb", base + 0x70, 16); | ||
417 | clks[IMX6SX_CLK_IPMUX2] = imx_clk_gate2("ipmux2", "ahb", base + 0x70, 18); | ||
418 | clks[IMX6SX_CLK_IPMUX3] = imx_clk_gate2("ipmux3", "ahb", base + 0x70, 20); | ||
419 | clks[IMX6SX_CLK_TZASC1] = imx_clk_gate2("tzasc1", "mmdc_podf", base + 0x70, 22); | ||
420 | clks[IMX6SX_CLK_LCDIF_APB] = imx_clk_gate2("lcdif_apb", "display_podf", base + 0x70, 28); | ||
421 | clks[IMX6SX_CLK_PXP_AXI] = imx_clk_gate2("pxp_axi", "display_podf", base + 0x70, 30); | ||
422 | |||
423 | /* CCGR3 */ | ||
424 | clks[IMX6SX_CLK_M4] = imx_clk_gate2("m4", "m4_podf", base + 0x74, 2); | ||
425 | clks[IMX6SX_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x74, 4); | ||
426 | clks[IMX6SX_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "enet_sel", base + 0x74, 4); | ||
427 | clks[IMX6SX_CLK_DISPLAY_AXI] = imx_clk_gate2("display_axi", "display_podf", base + 0x74, 6); | ||
428 | clks[IMX6SX_CLK_LCDIF2_PIX] = imx_clk_gate2("lcdif2_pix", "lcdif2_sel", base + 0x74, 8); | ||
429 | clks[IMX6SX_CLK_LCDIF1_PIX] = imx_clk_gate2("lcdif1_pix", "lcdif1_sel", base + 0x74, 10); | ||
430 | clks[IMX6SX_CLK_LDB_DI0] = imx_clk_gate2("ldb_di0", "ldb_di0_div_sel", base + 0x74, 12); | ||
431 | clks[IMX6SX_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_podf", base + 0x74, 14); | ||
432 | clks[IMX6SX_CLK_MLB] = imx_clk_gate2("mlb", "ahb", base + 0x74, 18); | ||
433 | clks[IMX6SX_CLK_MMDC_P0_FAST] = imx_clk_gate2("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20); | ||
434 | clks[IMX6SX_CLK_MMDC_P0_IPG] = imx_clk_gate2("mmdc_p0_ipg", "ipg", base + 0x74, 24); | ||
435 | clks[IMX6SX_CLK_OCRAM] = imx_clk_gate2("ocram", "ocram_podf", base + 0x74, 28); | ||
436 | |||
437 | /* CCGR4 */ | ||
438 | clks[IMX6SX_CLK_PCIE_AXI] = imx_clk_gate2("pcie_axi", "display_podf", base + 0x78, 0); | ||
439 | clks[IMX6SX_CLK_QSPI2] = imx_clk_gate2("qspi2", "qspi2_podf", base + 0x78, 10); | ||
440 | clks[IMX6SX_CLK_PER1_BCH] = imx_clk_gate2("per1_bch", "usdhc3", base + 0x78, 12); | ||
441 | clks[IMX6SX_CLK_PER2_MAIN] = imx_clk_gate2("per2_main", "ahb", base + 0x78, 14); | ||
442 | clks[IMX6SX_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16); | ||
443 | clks[IMX6SX_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18); | ||
444 | clks[IMX6SX_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20); | ||
445 | clks[IMX6SX_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22); | ||
446 | clks[IMX6SX_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb", "usdhc3", base + 0x78, 24); | ||
447 | clks[IMX6SX_CLK_GPMI_BCH] = imx_clk_gate2("gpmi_bch", "usdhc4", base + 0x78, 26); | ||
448 | clks[IMX6SX_CLK_GPMI_IO] = imx_clk_gate2("gpmi_io", "qspi2_podf", base + 0x78, 28); | ||
449 | clks[IMX6SX_CLK_GPMI_APB] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); | ||
450 | |||
451 | /* CCGR5 */ | ||
452 | clks[IMX6SX_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); | ||
453 | clks[IMX6SX_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); | ||
454 | clks[IMX6SX_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); | ||
455 | clks[IMX6SX_CLK_AUDIO] = imx_clk_gate2_shared("audio", "audio_podf", base + 0x7c, 14, &share_count_audio); | ||
456 | clks[IMX6SX_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_audio); | ||
457 | clks[IMX6SX_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1); | ||
458 | clks[IMX6SX_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2); | ||
459 | clks[IMX6SX_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3); | ||
460 | clks[IMX6SX_CLK_SSI1] = imx_clk_gate2_shared("ssi1", "ssi1_podf", base + 0x7c, 18, &share_count_ssi1); | ||
461 | clks[IMX6SX_CLK_SSI2] = imx_clk_gate2_shared("ssi2", "ssi2_podf", base + 0x7c, 20, &share_count_ssi2); | ||
462 | clks[IMX6SX_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3); | ||
463 | clks[IMX6SX_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24); | ||
464 | clks[IMX6SX_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_podf", base + 0x7c, 26); | ||
465 | clks[IMX6SX_CLK_SAI1_IPG] = imx_clk_gate2("sai1_ipg", "ipg", base + 0x7c, 28); | ||
466 | clks[IMX6SX_CLK_SAI2_IPG] = imx_clk_gate2("sai2_ipg", "ipg", base + 0x7c, 30); | ||
467 | clks[IMX6SX_CLK_SAI1] = imx_clk_gate2("sai1", "ssi1_podf", base + 0x7c, 28); | ||
468 | clks[IMX6SX_CLK_SAI2] = imx_clk_gate2("sai2", "ssi2_podf", base + 0x7c, 30); | ||
469 | |||
470 | /* CCGR6 */ | ||
471 | clks[IMX6SX_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); | ||
472 | clks[IMX6SX_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2); | ||
473 | clks[IMX6SX_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); | ||
474 | clks[IMX6SX_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); | ||
475 | clks[IMX6SX_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); | ||
476 | clks[IMX6SX_CLK_EIM_SLOW] = imx_clk_gate2("eim_slow", "eim_slow_podf", base + 0x80, 10); | ||
477 | clks[IMX6SX_CLK_PWM8] = imx_clk_gate2("pwm8", "perclk", base + 0x80, 16); | ||
478 | clks[IMX6SX_CLK_VADC] = imx_clk_gate2("vadc", "vid_podf", base + 0x80, 20); | ||
479 | clks[IMX6SX_CLK_GIS] = imx_clk_gate2("gis", "display_podf", base + 0x80, 22); | ||
480 | clks[IMX6SX_CLK_I2C4] = imx_clk_gate2("i2c4", "perclk", base + 0x80, 24); | ||
481 | clks[IMX6SX_CLK_PWM5] = imx_clk_gate2("pwm5", "perclk", base + 0x80, 26); | ||
482 | clks[IMX6SX_CLK_PWM6] = imx_clk_gate2("pwm6", "perclk", base + 0x80, 28); | ||
483 | clks[IMX6SX_CLK_PWM7] = imx_clk_gate2("pwm7", "perclk", base + 0x80, 30); | ||
484 | |||
485 | clks[IMX6SX_CLK_CKO1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7); | ||
486 | clks[IMX6SX_CLK_CKO2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24); | ||
487 | |||
488 | /* mask handshake of mmdc */ | ||
489 | writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR); | ||
490 | |||
491 | imx_check_clocks(clks, ARRAY_SIZE(clks)); | ||
492 | |||
493 | clk_data.clks = clks; | ||
494 | clk_data.clk_num = ARRAY_SIZE(clks); | ||
495 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
496 | |||
497 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | ||
498 | clk_prepare_enable(clks[clks_init_on[i]]); | ||
499 | |||
500 | if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { | ||
501 | clk_prepare_enable(clks[IMX6SX_CLK_USBPHY1_GATE]); | ||
502 | clk_prepare_enable(clks[IMX6SX_CLK_USBPHY2_GATE]); | ||
503 | } | ||
504 | |||
505 | /* Set the default 132MHz for EIM module */ | ||
506 | clk_set_parent(clks[IMX6SX_CLK_EIM_SLOW_SEL], clks[IMX6SX_CLK_PLL2_PFD2]); | ||
507 | clk_set_rate(clks[IMX6SX_CLK_EIM_SLOW], 132000000); | ||
508 | |||
509 | /* set parent clock for LCDIF1 pixel clock */ | ||
510 | clk_set_parent(clks[IMX6SX_CLK_LCDIF1_PRE_SEL], clks[IMX6SX_CLK_PLL5_VIDEO_DIV]); | ||
511 | clk_set_parent(clks[IMX6SX_CLK_LCDIF1_SEL], clks[IMX6SX_CLK_LCDIF1_PODF]); | ||
512 | |||
513 | /* Set the parent clks of PCIe lvds1 and pcie_axi to be pcie ref, axi */ | ||
514 | if (clk_set_parent(clks[IMX6SX_CLK_LVDS1_SEL], clks[IMX6SX_CLK_PCIE_REF_125M])) | ||
515 | pr_err("Failed to set pcie bus parent clk.\n"); | ||
516 | if (clk_set_parent(clks[IMX6SX_CLK_PCIE_AXI_SEL], clks[IMX6SX_CLK_AXI])) | ||
517 | pr_err("Failed to set pcie parent clk.\n"); | ||
518 | |||
519 | /* | ||
520 | * Init enet system AHB clock, set to 200MHz | ||
521 | * pll2_pfd2_396m-> ENET_PODF-> ENET_AHB | ||
522 | */ | ||
523 | clk_set_parent(clks[IMX6SX_CLK_ENET_PRE_SEL], clks[IMX6SX_CLK_PLL2_PFD2]); | ||
524 | clk_set_parent(clks[IMX6SX_CLK_ENET_SEL], clks[IMX6SX_CLK_ENET_PODF]); | ||
525 | clk_set_rate(clks[IMX6SX_CLK_ENET_PODF], 200000000); | ||
526 | clk_set_rate(clks[IMX6SX_CLK_ENET_REF], 125000000); | ||
527 | clk_set_rate(clks[IMX6SX_CLK_ENET2_REF], 125000000); | ||
528 | |||
529 | /* Audio clocks */ | ||
530 | clk_set_rate(clks[IMX6SX_CLK_PLL4_AUDIO_DIV], 393216000); | ||
531 | |||
532 | clk_set_parent(clks[IMX6SX_CLK_SPDIF_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); | ||
533 | clk_set_rate(clks[IMX6SX_CLK_SPDIF_PODF], 98304000); | ||
534 | |||
535 | clk_set_parent(clks[IMX6SX_CLK_AUDIO_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]); | ||
536 | clk_set_rate(clks[IMX6SX_CLK_AUDIO_PODF], 24000000); | ||
537 | |||
538 | clk_set_parent(clks[IMX6SX_CLK_SSI1_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); | ||
539 | clk_set_parent(clks[IMX6SX_CLK_SSI2_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); | ||
540 | clk_set_parent(clks[IMX6SX_CLK_SSI3_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); | ||
541 | clk_set_rate(clks[IMX6SX_CLK_SSI1_PODF], 24576000); | ||
542 | clk_set_rate(clks[IMX6SX_CLK_SSI2_PODF], 24576000); | ||
543 | clk_set_rate(clks[IMX6SX_CLK_SSI3_PODF], 24576000); | ||
544 | |||
545 | clk_set_parent(clks[IMX6SX_CLK_ESAI_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); | ||
546 | clk_set_rate(clks[IMX6SX_CLK_ESAI_PODF], 24576000); | ||
547 | |||
548 | /* Set parent clock for vadc */ | ||
549 | clk_set_parent(clks[IMX6SX_CLK_VID_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]); | ||
550 | |||
551 | /* default parent of can_sel clock is invalid, manually set it here */ | ||
552 | clk_set_parent(clks[IMX6SX_CLK_CAN_SEL], clks[IMX6SX_CLK_PLL3_60M]); | ||
553 | |||
554 | /* Update gpu clock from default 528M to 720M */ | ||
555 | clk_set_parent(clks[IMX6SX_CLK_GPU_CORE_SEL], clks[IMX6SX_CLK_PLL3_PFD0]); | ||
556 | clk_set_parent(clks[IMX6SX_CLK_GPU_AXI_SEL], clks[IMX6SX_CLK_PLL3_PFD0]); | ||
557 | |||
558 | clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]); | ||
559 | clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]); | ||
560 | } | ||
561 | CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init); | ||
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c new file mode 100644 index 000000000000..71f3a94b472c --- /dev/null +++ b/drivers/clk/imx/clk-imx7d.c | |||
@@ -0,0 +1,860 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <dt-bindings/clock/imx7d-clock.h> | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/clkdev.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/init.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 <linux/types.h> | ||
22 | |||
23 | #include "clk.h" | ||
24 | |||
25 | static struct clk *clks[IMX7D_CLK_END]; | ||
26 | static const char *arm_a7_sel[] = { "osc", "pll_arm_main_clk", | ||
27 | "pll_enet_500m_clk", "pll_dram_main_clk", | ||
28 | "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_audio_main_clk", | ||
29 | "pll_usb_main_clk", }; | ||
30 | |||
31 | static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
32 | "pll_enet_250m_clk", "pll_sys_pfd2_270m_clk", | ||
33 | "pll_dram_533m_clk", "pll_audio_main_clk", "pll_video_main_clk", | ||
34 | "pll_usb_main_clk", }; | ||
35 | |||
36 | static const char *arm_m0_sel[] = { "osc", "pll_sys_main_120m_clk", | ||
37 | "pll_enet_125m_clk", "pll_sys_pfd2_135m_clk", | ||
38 | "pll_dram_533m_clk", "pll_audio_main_clk", "pll_video_main_clk", | ||
39 | "pll_usb_main_clk", }; | ||
40 | |||
41 | static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk", | ||
42 | "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk", | ||
43 | "pll_audio_main_clk", "pll_video_main_clk", "pll_sys_pfd7_clk", }; | ||
44 | |||
45 | static const char *disp_axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk", | ||
46 | "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd6_clk", | ||
47 | "pll_sys_pfd7_clk", "pll_audio_main_clk", "pll_video_main_clk", }; | ||
48 | |||
49 | static const char *enet_axi_sel[] = { "osc", "pll_sys_pfd2_270m_clk", | ||
50 | "pll_dram_533m_clk", "pll_enet_250m_clk", | ||
51 | "pll_sys_main_240m_clk", "pll_audio_main_clk", "pll_video_main_clk", | ||
52 | "pll_sys_pfd4_clk", }; | ||
53 | |||
54 | static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk", | ||
55 | "pll_dram_533m_clk", "pll_sys_main_240m_clk", | ||
56 | "pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk", | ||
57 | "pll_audio_main_clk", }; | ||
58 | |||
59 | static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
60 | "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", | ||
61 | "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_main_clk", | ||
62 | "pll_video_main_clk", }; | ||
63 | |||
64 | static const char *dram_phym_sel[] = { "pll_dram_main_clk", | ||
65 | "dram_phym_alt_clk", }; | ||
66 | |||
67 | static const char *dram_sel[] = { "pll_dram_main_clk", | ||
68 | "dram_alt_clk", }; | ||
69 | |||
70 | static const char *dram_phym_alt_sel[] = { "osc", "pll_dram_533m_clk", | ||
71 | "pll_sys_main_clk", "pll_enet_500m_clk", | ||
72 | "pll_usb_main_clk", "pll_sys_pfd7_clk", "pll_audio_main_clk", | ||
73 | "pll_video_main_clk", }; | ||
74 | |||
75 | static const char *dram_alt_sel[] = { "osc", "pll_dram_533m_clk", | ||
76 | "pll_sys_main_clk", "pll_enet_500m_clk", | ||
77 | "pll_enet_250m_clk", "pll_sys_pfd0_392m_clk", | ||
78 | "pll_audio_main_clk", "pll_sys_pfd2_270m_clk", }; | ||
79 | |||
80 | static const char *usb_hsic_sel[] = { "osc", "pll_sys_main_clk", | ||
81 | "pll_usb_main_clk", "pll_sys_pfd3_clk", "pll_sys_pfd4_clk", | ||
82 | "pll_sys_pfd5_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; | ||
83 | |||
84 | static const char *pcie_ctrl_sel[] = { "osc", "pll_enet_250m_clk", | ||
85 | "pll_sys_main_240m_clk", "pll_sys_pfd2_270m_clk", | ||
86 | "pll_dram_533m_clk", "pll_enet_500m_clk", | ||
87 | "pll_sys_pfd1_332m_clk", "pll_sys_pfd6_clk", }; | ||
88 | |||
89 | static const char *pcie_phy_sel[] = { "osc", "pll_enet_100m_clk", | ||
90 | "pll_enet_500m_clk", "ext_clk_1", "ext_clk_2", "ext_clk_3", | ||
91 | "ext_clk_4", "pll_sys_pfd0_392m_clk", }; | ||
92 | |||
93 | static const char *epdc_pixel_sel[] = { "osc", "pll_sys_pfd1_332m_clk", | ||
94 | "pll_dram_533m_clk", "pll_sys_main_clk", "pll_sys_pfd5_clk", | ||
95 | "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_main_clk", }; | ||
96 | |||
97 | static const char *lcdif_pixel_sel[] = { "osc", "pll_sys_pfd5_clk", | ||
98 | "pll_dram_533m_clk", "ext_clk_3", "pll_sys_pfd4_clk", | ||
99 | "pll_sys_pfd2_270m_clk", "pll_video_main_clk", | ||
100 | "pll_usb_main_clk", }; | ||
101 | |||
102 | static const char *mipi_dsi_sel[] = { "osc", "pll_sys_pfd5_clk", | ||
103 | "pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk", | ||
104 | "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_main_clk", }; | ||
105 | |||
106 | static const char *mipi_csi_sel[] = { "osc", "pll_sys_pfd4_clk", | ||
107 | "pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk", | ||
108 | "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_main_clk", }; | ||
109 | |||
110 | static const char *mipi_dphy_sel[] = { "osc", "pll_sys_main_120m_clk", | ||
111 | "pll_dram_533m_clk", "pll_sys_pfd5_clk", "ref_1m_clk", "ext_clk_2", | ||
112 | "pll_video_main_clk", "ext_clk_3", }; | ||
113 | |||
114 | static const char *sai1_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
115 | "pll_audio_main_clk", "pll_dram_533m_clk", "pll_video_main_clk", | ||
116 | "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", }; | ||
117 | |||
118 | static const char *sai2_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
119 | "pll_audio_main_clk", "pll_dram_533m_clk", "pll_video_main_clk", | ||
120 | "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", }; | ||
121 | |||
122 | static const char *sai3_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
123 | "pll_audio_main_clk", "pll_dram_533m_clk", "pll_video_main_clk", | ||
124 | "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_3", }; | ||
125 | |||
126 | static const char *spdif_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
127 | "pll_audio_main_clk", "pll_dram_533m_clk", "pll_video_main_clk", | ||
128 | "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_3_clk", }; | ||
129 | |||
130 | static const char *enet1_ref_sel[] = { "osc", "pll_enet_125m_clk", | ||
131 | "pll_enet_50m_clk", "pll_enet_25m_clk", | ||
132 | "pll_sys_main_120m_clk", "pll_audio_main_clk", "pll_video_main_clk", | ||
133 | "ext_clk_4", }; | ||
134 | |||
135 | static const char *enet1_time_sel[] = { "osc", "pll_enet_100m_clk", | ||
136 | "pll_audio_main_clk", "ext_clk_1", "ext_clk_2", "ext_clk_3", | ||
137 | "ext_clk_4", "pll_video_main_clk", }; | ||
138 | |||
139 | static const char *enet2_ref_sel[] = { "osc", "pll_enet_125m_clk", | ||
140 | "pll_enet_50m_clk", "pll_enet_25m_clk", | ||
141 | "pll_sys_main_120m_clk", "pll_audio_main_clk", "pll_video_main_clk", | ||
142 | "ext_clk_4", }; | ||
143 | |||
144 | static const char *enet2_time_sel[] = { "osc", "pll_enet_100m_clk", | ||
145 | "pll_audio_main_clk", "ext_clk_1", "ext_clk_2", "ext_clk_3", | ||
146 | "ext_clk_4", "pll_video_main_clk", }; | ||
147 | |||
148 | static const char *enet_phy_ref_sel[] = { "osc", "pll_enet_25m_clk", | ||
149 | "pll_enet_50m_clk", "pll_enet_125m_clk", | ||
150 | "pll_dram_533m_clk", "pll_audio_main_clk", "pll_video_main_clk", | ||
151 | "pll_sys_pfd3_clk", }; | ||
152 | |||
153 | static const char *eim_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
154 | "pll_sys_main_120m_clk", "pll_dram_533m_clk", | ||
155 | "pll_sys_pfd2_270m_clk", "pll_sys_pfd3_clk", "pll_enet_125m_clk", | ||
156 | "pll_usb_main_clk", }; | ||
157 | |||
158 | static const char *nand_sel[] = { "osc", "pll_sys_main_clk", | ||
159 | "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd3_clk", | ||
160 | "pll_enet_500m_clk", "pll_enet_250m_clk", | ||
161 | "pll_video_main_clk", }; | ||
162 | |||
163 | static const char *qspi_sel[] = { "osc", "pll_sys_pfd4_clk", | ||
164 | "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd3_clk", | ||
165 | "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; | ||
166 | |||
167 | static const char *usdhc1_sel[] = { "osc", "pll_sys_pfd0_392m_clk", | ||
168 | "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", | ||
169 | "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; | ||
170 | |||
171 | static const char *usdhc2_sel[] = { "osc", "pll_sys_pfd0_392m_clk", | ||
172 | "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", | ||
173 | "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; | ||
174 | |||
175 | static const char *usdhc3_sel[] = { "osc", "pll_sys_pfd0_392m_clk", | ||
176 | "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", | ||
177 | "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; | ||
178 | |||
179 | static const char *can1_sel[] = { "osc", "pll_sys_main_120m_clk", | ||
180 | "pll_dram_533m_clk", "pll_sys_main_clk", | ||
181 | "pll_enet_40m_clk", "pll_usb_main_clk", "ext_clk_1", | ||
182 | "ext_clk_4", }; | ||
183 | |||
184 | static const char *can2_sel[] = { "osc", "pll_sys_main_120m_clk", | ||
185 | "pll_dram_533m_clk", "pll_sys_main_clk", | ||
186 | "pll_enet_40m_clk", "pll_usb_main_clk", "ext_clk_1", | ||
187 | "ext_clk_3", }; | ||
188 | |||
189 | static const char *i2c1_sel[] = { "osc", "pll_sys_main_120m_clk", | ||
190 | "pll_enet_50m_clk", "pll_dram_533m_clk", | ||
191 | "pll_audio_main_clk", "pll_video_main_clk", "pll_usb_main_clk", | ||
192 | "pll_sys_pfd2_135m_clk", }; | ||
193 | |||
194 | static const char *i2c2_sel[] = { "osc", "pll_sys_main_120m_clk", | ||
195 | "pll_enet_50m_clk", "pll_dram_533m_clk", | ||
196 | "pll_audio_main_clk", "pll_video_main_clk", "pll_usb_main_clk", | ||
197 | "pll_sys_pfd2_135m_clk", }; | ||
198 | |||
199 | static const char *i2c3_sel[] = { "osc", "pll_sys_main_120m_clk", | ||
200 | "pll_enet_50m_clk", "pll_dram_533m_clk", | ||
201 | "pll_audio_main_clk", "pll_video_main_clk", "pll_usb_main_clk", | ||
202 | "pll_sys_pfd2_135m_clk", }; | ||
203 | |||
204 | static const char *i2c4_sel[] = { "osc", "pll_sys_main_120m_clk", | ||
205 | "pll_enet_50m_clk", "pll_dram_533m_clk", | ||
206 | "pll_audio_main_clk", "pll_video_main_clk", "pll_usb_main_clk", | ||
207 | "pll_sys_pfd2_135m_clk", }; | ||
208 | |||
209 | static const char *uart1_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
210 | "pll_enet_40m_clk", "pll_enet_100m_clk", | ||
211 | "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", | ||
212 | "pll_usb_main_clk", }; | ||
213 | |||
214 | static const char *uart2_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
215 | "pll_enet_40m_clk", "pll_enet_100m_clk", | ||
216 | "pll_sys_main_clk", "ext_clk_2", "ext_clk_3", | ||
217 | "pll_usb_main_clk", }; | ||
218 | |||
219 | static const char *uart3_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
220 | "pll_enet_40m_clk", "pll_enet_100m_clk", | ||
221 | "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", | ||
222 | "pll_usb_main_clk", }; | ||
223 | |||
224 | static const char *uart4_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
225 | "pll_enet_40m_clk", "pll_enet_100m_clk", | ||
226 | "pll_sys_main_clk", "ext_clk_2", "ext_clk_3", | ||
227 | "pll_usb_main_clk", }; | ||
228 | |||
229 | static const char *uart5_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
230 | "pll_enet_40m_clk", "pll_enet_100m_clk", | ||
231 | "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", | ||
232 | "pll_usb_main_clk", }; | ||
233 | |||
234 | static const char *uart6_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
235 | "pll_enet_40m_clk", "pll_enet_100m_clk", | ||
236 | "pll_sys_main_clk", "ext_clk_2", "ext_clk_3", | ||
237 | "pll_usb_main_clk", }; | ||
238 | |||
239 | static const char *uart7_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
240 | "pll_enet_40m_clk", "pll_enet_100m_clk", | ||
241 | "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", | ||
242 | "pll_usb_main_clk", }; | ||
243 | |||
244 | static const char *ecspi1_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
245 | "pll_enet_40m_clk", "pll_sys_main_120m_clk", | ||
246 | "pll_sys_main_clk", "pll_sys_pfd4_clk", "pll_enet_250m_clk", | ||
247 | "pll_usb_main_clk", }; | ||
248 | |||
249 | static const char *ecspi2_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
250 | "pll_enet_40m_clk", "pll_sys_main_120m_clk", | ||
251 | "pll_sys_main_clk", "pll_sys_pfd4_clk", "pll_enet_250m_clk", | ||
252 | "pll_usb_main_clk", }; | ||
253 | |||
254 | static const char *ecspi3_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
255 | "pll_enet_40m_clk", "pll_sys_main_120m_clk", | ||
256 | "pll_sys_main_clk", "pll_sys_pfd4_clk", "pll_enet_250m_clk", | ||
257 | "pll_usb_main_clk", }; | ||
258 | |||
259 | static const char *ecspi4_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
260 | "pll_enet_40m_clk", "pll_sys_main_120m_clk", | ||
261 | "pll_sys_main_clk", "pll_sys_pfd4_clk", "pll_enet_250m_clk", | ||
262 | "pll_usb_main_clk", }; | ||
263 | |||
264 | static const char *pwm1_sel[] = { "osc", "pll_enet_100m_clk", | ||
265 | "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", | ||
266 | "ext_clk_1", "ref_1m_clk", "pll_video_main_clk", }; | ||
267 | |||
268 | static const char *pwm2_sel[] = { "osc", "pll_enet_100m_clk", | ||
269 | "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", | ||
270 | "ext_clk_1", "ref_1m_clk", "pll_video_main_clk", }; | ||
271 | |||
272 | static const char *pwm3_sel[] = { "osc", "pll_enet_100m_clk", | ||
273 | "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", | ||
274 | "ext_clk_2", "ref_1m_clk", "pll_video_main_clk", }; | ||
275 | |||
276 | static const char *pwm4_sel[] = { "osc", "pll_enet_100m_clk", | ||
277 | "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", | ||
278 | "ext_clk_2", "ref_1m_clk", "pll_video_main_clk", }; | ||
279 | |||
280 | static const char *flextimer1_sel[] = { "osc", "pll_enet_100m_clk", | ||
281 | "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", | ||
282 | "ext_clk_3", "ref_1m_clk", "pll_video_main_clk", }; | ||
283 | |||
284 | static const char *flextimer2_sel[] = { "osc", "pll_enet_100m_clk", | ||
285 | "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", | ||
286 | "ext_clk_3", "ref_1m_clk", "pll_video_main_clk", }; | ||
287 | |||
288 | static const char *sim1_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
289 | "pll_sys_main_120m_clk", "pll_dram_533m_clk", | ||
290 | "pll_usb_main_clk", "pll_audio_main_clk", "pll_enet_125m_clk", | ||
291 | "pll_sys_pfd7_clk", }; | ||
292 | |||
293 | static const char *sim2_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
294 | "pll_sys_main_120m_clk", "pll_dram_533m_clk", | ||
295 | "pll_usb_main_clk", "pll_video_main_clk", "pll_enet_125m_clk", | ||
296 | "pll_sys_pfd7_clk", }; | ||
297 | |||
298 | static const char *gpt1_sel[] = { "osc", "pll_enet_100m_clk", | ||
299 | "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk", | ||
300 | "ref_1m_clk", "pll_audio_main_clk", "ext_clk_1", }; | ||
301 | |||
302 | static const char *gpt2_sel[] = { "osc", "pll_enet_100m_clk", | ||
303 | "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk", | ||
304 | "ref_1m_clk", "pll_audio_main_clk", "ext_clk_2", }; | ||
305 | |||
306 | static const char *gpt3_sel[] = { "osc", "pll_enet_100m_clk", | ||
307 | "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk", | ||
308 | "ref_1m_clk", "pll_audio_main_clk", "ext_clk_3", }; | ||
309 | |||
310 | static const char *gpt4_sel[] = { "osc", "pll_enet_100m_clk", | ||
311 | "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk", | ||
312 | "ref_1m_clk", "pll_audio_main_clk", "ext_clk_4", }; | ||
313 | |||
314 | static const char *trace_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
315 | "pll_sys_main_120m_clk", "pll_dram_533m_clk", | ||
316 | "pll_enet_125m_clk", "pll_usb_main_clk", "ext_clk_2", | ||
317 | "ext_clk_3", }; | ||
318 | |||
319 | static const char *wdog_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
320 | "pll_sys_main_120m_clk", "pll_dram_533m_clk", | ||
321 | "pll_enet_125m_clk", "pll_usb_main_clk", "ref_1m_clk", | ||
322 | "pll_sys_pfd1_166m_clk", }; | ||
323 | |||
324 | static const char *csi_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
325 | "pll_sys_main_120m_clk", "pll_dram_533m_clk", | ||
326 | "pll_enet_125m_clk", "pll_audio_main_clk", "pll_video_main_clk", | ||
327 | "pll_usb_main_clk", }; | ||
328 | |||
329 | static const char *audio_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | ||
330 | "pll_sys_main_120m_clk", "pll_dram_533m_clk", | ||
331 | "pll_enet_125m_clk", "pll_audio_main_clk", "pll_video_main_clk", | ||
332 | "pll_usb_main_clk", }; | ||
333 | |||
334 | static const char *wrclk_sel[] = { "osc", "pll_enet_40m_clk", | ||
335 | "pll_dram_533m_clk", "pll_usb_main_clk", | ||
336 | "pll_sys_main_240m_clk", "pll_sys_pfd2_270m_clk", | ||
337 | "pll_enet_500m_clk", "pll_sys_pfd7_clk", }; | ||
338 | |||
339 | static const char *clko1_sel[] = { "osc", "pll_sys_main_clk", | ||
340 | "pll_sys_main_240m_clk", "pll_sys_pfd0_196m_clk", "pll_sys_pfd3_clk", | ||
341 | "pll_enet_500m_clk", "pll_dram_533m_clk", "ref_1m_clk", }; | ||
342 | |||
343 | static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk", | ||
344 | "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk", | ||
345 | "pll_audio_main_clk", "pll_video_main_clk", "osc_32k_clk", }; | ||
346 | |||
347 | static const char *lvds1_sel[] = { "pll_arm_main_clk", | ||
348 | "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk", | ||
349 | "pll_sys_pfd2_270m_clk", "pll_sys_pfd3_clk", "pll_sys_pfd4_clk", | ||
350 | "pll_sys_pfd5_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", | ||
351 | "pll_audio_main_clk", "pll_video_main_clk", "pll_enet_500m_clk", | ||
352 | "pll_enet_250m_clk", "pll_enet_125m_clk", "pll_enet_100m_clk", | ||
353 | "pll_enet_50m_clk", "pll_enet_40m_clk", "pll_enet_25m_clk", | ||
354 | "pll_dram_main_clk", }; | ||
355 | |||
356 | static const char *pll_bypass_src_sel[] = { "osc", "dummy", }; | ||
357 | static const char *pll_arm_bypass_sel[] = { "pll_arm_main", "pll_arm_main_src", }; | ||
358 | static const char *pll_dram_bypass_sel[] = { "pll_dram_main", "pll_dram_main_src", }; | ||
359 | static const char *pll_sys_bypass_sel[] = { "pll_sys_main", "pll_sys_main_src", }; | ||
360 | static const char *pll_enet_bypass_sel[] = { "pll_enet_main", "pll_enet_main_src", }; | ||
361 | static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", }; | ||
362 | static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", }; | ||
363 | |||
364 | static struct clk_onecell_data clk_data; | ||
365 | |||
366 | static void __init imx7d_clocks_init(struct device_node *ccm_node) | ||
367 | { | ||
368 | struct device_node *np; | ||
369 | void __iomem *base; | ||
370 | int i; | ||
371 | |||
372 | clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
373 | clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc"); | ||
374 | |||
375 | np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop"); | ||
376 | base = of_iomap(np, 0); | ||
377 | WARN_ON(!base); | ||
378 | |||
379 | clks[IMX7D_PLL_ARM_MAIN_SRC] = imx_clk_mux("pll_arm_main_src", base + 0x60, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); | ||
380 | clks[IMX7D_PLL_DRAM_MAIN_SRC] = imx_clk_mux("pll_dram_main_src", base + 0x70, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); | ||
381 | clks[IMX7D_PLL_SYS_MAIN_SRC] = imx_clk_mux("pll_sys_main_src", base + 0xb0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); | ||
382 | clks[IMX7D_PLL_ENET_MAIN_SRC] = imx_clk_mux("pll_enet_main_src", base + 0xe0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); | ||
383 | clks[IMX7D_PLL_AUDIO_MAIN_SRC] = imx_clk_mux("pll_audio_main_src", base + 0xf0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); | ||
384 | clks[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); | ||
385 | |||
386 | clks[IMX7D_PLL_ARM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "pll_arm_main_src", base + 0x60, 0x7f); | ||
387 | clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_dram_main", "pll_dram_main_src", base + 0x70, 0x7f); | ||
388 | clks[IMX7D_PLL_SYS_MAIN] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "pll_sys_main_src", base + 0xb0, 0x1); | ||
389 | clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "pll_enet_main_src", base + 0xe0, 0x0); | ||
390 | clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "pll_audio_main_src", base + 0xf0, 0x7f); | ||
391 | clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "pll_video_main_src", base + 0x130, 0x7f); | ||
392 | |||
393 | clks[IMX7D_PLL_ARM_MAIN_BYPASS] = imx_clk_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT); | ||
394 | clks[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT); | ||
395 | clks[IMX7D_PLL_SYS_MAIN_BYPASS] = imx_clk_mux_flags("pll_sys_main_bypass", base + 0xb0, 16, 1, pll_sys_bypass_sel, ARRAY_SIZE(pll_sys_bypass_sel), CLK_SET_RATE_PARENT); | ||
396 | clks[IMX7D_PLL_ENET_MAIN_BYPASS] = imx_clk_mux_flags("pll_enet_main_bypass", base + 0xe0, 16, 1, pll_enet_bypass_sel, ARRAY_SIZE(pll_enet_bypass_sel), CLK_SET_RATE_PARENT); | ||
397 | clks[IMX7D_PLL_AUDIO_MAIN_BYPASS] = imx_clk_mux_flags("pll_audio_main_bypass", base + 0xf0, 16, 1, pll_audio_bypass_sel, ARRAY_SIZE(pll_audio_bypass_sel), CLK_SET_RATE_PARENT); | ||
398 | clks[IMX7D_PLL_VIDEO_MAIN_BYPASS] = imx_clk_mux_flags("pll_video_main_bypass", base + 0x130, 16, 1, pll_video_bypass_sel, ARRAY_SIZE(pll_video_bypass_sel), CLK_SET_RATE_PARENT); | ||
399 | |||
400 | clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]); | ||
401 | clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]); | ||
402 | clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]); | ||
403 | clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], clks[IMX7D_PLL_ENET_MAIN]); | ||
404 | clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], clks[IMX7D_PLL_AUDIO_MAIN]); | ||
405 | clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], clks[IMX7D_PLL_VIDEO_MAIN]); | ||
406 | |||
407 | clks[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_gate("pll_arm_main_clk", "pll_arm_main_bypass", base + 0x60, 13); | ||
408 | clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", "pll_dram_main_bypass", base + 0x70, 13); | ||
409 | clks[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_gate("pll_sys_main_clk", "pll_sys_main_bypass", base + 0xb0, 13); | ||
410 | clks[IMX7D_PLL_AUDIO_MAIN_CLK] = imx_clk_gate("pll_audio_main_clk", "pll_audio_main_bypass", base + 0xf0, 13); | ||
411 | clks[IMX7D_PLL_VIDEO_MAIN_CLK] = imx_clk_gate("pll_video_main_clk", "pll_video_main_bypass", base + 0x130, 13); | ||
412 | |||
413 | clks[IMX7D_PLL_SYS_PFD0_392M_CLK] = imx_clk_pfd("pll_sys_pfd0_392m_clk", "pll_sys_main_clk", base + 0xc0, 0); | ||
414 | clks[IMX7D_PLL_SYS_PFD1_332M_CLK] = imx_clk_pfd("pll_sys_pfd1_332m_clk", "pll_sys_main_clk", base + 0xc0, 1); | ||
415 | clks[IMX7D_PLL_SYS_PFD2_270M_CLK] = imx_clk_pfd("pll_sys_pfd2_270m_clk", "pll_sys_main_clk", base + 0xc0, 2); | ||
416 | |||
417 | clks[IMX7D_PLL_SYS_PFD3_CLK] = imx_clk_pfd("pll_sys_pfd3_clk", "pll_sys_main_clk", base + 0xc0, 3); | ||
418 | clks[IMX7D_PLL_SYS_PFD4_CLK] = imx_clk_pfd("pll_sys_pfd4_clk", "pll_sys_main_clk", base + 0xd0, 0); | ||
419 | clks[IMX7D_PLL_SYS_PFD5_CLK] = imx_clk_pfd("pll_sys_pfd5_clk", "pll_sys_main_clk", base + 0xd0, 1); | ||
420 | clks[IMX7D_PLL_SYS_PFD6_CLK] = imx_clk_pfd("pll_sys_pfd6_clk", "pll_sys_main_clk", base + 0xd0, 2); | ||
421 | clks[IMX7D_PLL_SYS_PFD7_CLK] = imx_clk_pfd("pll_sys_pfd7_clk", "pll_sys_main_clk", base + 0xd0, 3); | ||
422 | |||
423 | clks[IMX7D_PLL_SYS_MAIN_480M] = imx_clk_fixed_factor("pll_sys_main_480m", "pll_sys_main_clk", 1, 1); | ||
424 | clks[IMX7D_PLL_SYS_MAIN_240M] = imx_clk_fixed_factor("pll_sys_main_240m", "pll_sys_main_clk", 1, 2); | ||
425 | clks[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_fixed_factor("pll_sys_main_120m", "pll_sys_main_clk", 1, 4); | ||
426 | clks[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_fixed_factor("pll_dram_533m", "pll_dram_main_clk", 1, 2); | ||
427 | |||
428 | clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4); | ||
429 | clks[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5); | ||
430 | clks[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6); | ||
431 | clks[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12); | ||
432 | |||
433 | clks[IMX7D_PLL_SYS_PFD0_196M] = imx_clk_fixed_factor("pll_sys_pfd0_196m", "pll_sys_pfd0_392m_clk", 1, 2); | ||
434 | clks[IMX7D_PLL_SYS_PFD1_166M] = imx_clk_fixed_factor("pll_sys_pfd1_166m", "pll_sys_pfd1_332m_clk", 1, 2); | ||
435 | clks[IMX7D_PLL_SYS_PFD2_135M] = imx_clk_fixed_factor("pll_sys_pfd2_135m", "pll_sys_pfd2_270m_clk", 1, 2); | ||
436 | |||
437 | clks[IMX7D_PLL_SYS_PFD0_196M_CLK] = imx_clk_gate_dis("pll_sys_pfd0_196m_clk", "pll_sys_pfd0_196m", base + 0xb0, 26); | ||
438 | clks[IMX7D_PLL_SYS_PFD1_166M_CLK] = imx_clk_gate_dis("pll_sys_pfd1_166m_clk", "pll_sys_pfd1_166m", base + 0xb0, 27); | ||
439 | clks[IMX7D_PLL_SYS_PFD2_135M_CLK] = imx_clk_gate_dis("pll_sys_pfd2_135m_clk", "pll_sys_pfd2_135m", base + 0xb0, 28); | ||
440 | |||
441 | clks[IMX7D_PLL_ENET_MAIN_CLK] = imx_clk_fixed_factor("pll_enet_main_clk", "pll_enet_main_bypass", 1, 1); | ||
442 | clks[IMX7D_PLL_ENET_MAIN_500M] = imx_clk_fixed_factor("pll_enet_500m", "pll_enet_main_clk", 1, 2); | ||
443 | clks[IMX7D_PLL_ENET_MAIN_250M] = imx_clk_fixed_factor("pll_enet_250m", "pll_enet_main_clk", 1, 4); | ||
444 | clks[IMX7D_PLL_ENET_MAIN_125M] = imx_clk_fixed_factor("pll_enet_125m", "pll_enet_main_clk", 1, 8); | ||
445 | clks[IMX7D_PLL_ENET_MAIN_100M] = imx_clk_fixed_factor("pll_enet_100m", "pll_enet_main_clk", 1, 10); | ||
446 | clks[IMX7D_PLL_ENET_MAIN_50M] = imx_clk_fixed_factor("pll_enet_50m", "pll_enet_main_clk", 1, 20); | ||
447 | clks[IMX7D_PLL_ENET_MAIN_40M] = imx_clk_fixed_factor("pll_enet_40m", "pll_enet_main_clk", 1, 25); | ||
448 | clks[IMX7D_PLL_ENET_MAIN_25M] = imx_clk_fixed_factor("pll_enet_25m", "pll_enet_main_clk", 1, 40); | ||
449 | |||
450 | clks[IMX7D_PLL_ENET_MAIN_500M_CLK] = imx_clk_gate("pll_enet_500m_clk", "pll_enet_500m", base + 0xe0, 12); | ||
451 | clks[IMX7D_PLL_ENET_MAIN_250M_CLK] = imx_clk_gate("pll_enet_250m_clk", "pll_enet_250m", base + 0xe0, 11); | ||
452 | clks[IMX7D_PLL_ENET_MAIN_125M_CLK] = imx_clk_gate("pll_enet_125m_clk", "pll_enet_125m", base + 0xe0, 10); | ||
453 | clks[IMX7D_PLL_ENET_MAIN_100M_CLK] = imx_clk_gate("pll_enet_100m_clk", "pll_enet_100m", base + 0xe0, 9); | ||
454 | clks[IMX7D_PLL_ENET_MAIN_50M_CLK] = imx_clk_gate("pll_enet_50m_clk", "pll_enet_50m", base + 0xe0, 8); | ||
455 | clks[IMX7D_PLL_ENET_MAIN_40M_CLK] = imx_clk_gate("pll_enet_40m_clk", "pll_enet_40m", base + 0xe0, 7); | ||
456 | clks[IMX7D_PLL_ENET_MAIN_25M_CLK] = imx_clk_gate("pll_enet_25m_clk", "pll_enet_25m", base + 0xe0, 6); | ||
457 | |||
458 | clks[IMX7D_LVDS1_OUT_SEL] = imx_clk_mux("lvds1_sel", base + 0x170, 0, 5, lvds1_sel, ARRAY_SIZE(lvds1_sel)); | ||
459 | clks[IMX7D_LVDS1_OUT_CLK] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x170, 5, BIT(6)); | ||
460 | |||
461 | np = ccm_node; | ||
462 | base = of_iomap(np, 0); | ||
463 | WARN_ON(!base); | ||
464 | |||
465 | clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel)); | ||
466 | clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel)); | ||
467 | clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel)); | ||
468 | clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel)); | ||
469 | clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel)); | ||
470 | clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel)); | ||
471 | clks[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_mux("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel)); | ||
472 | clks[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_mux("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel)); | ||
473 | clks[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_mux("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel)); | ||
474 | clks[IMX7D_DRAM_ROOT_SRC] = imx_clk_mux("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel)); | ||
475 | clks[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_mux("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel)); | ||
476 | clks[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_mux("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel)); | ||
477 | clks[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_mux("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel)); | ||
478 | clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel)); | ||
479 | clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel)); | ||
480 | clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel)); | ||
481 | clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel)); | ||
482 | clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux("mipi_dsi_src", base + 0xa380, 24, 3, mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel)); | ||
483 | clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel)); | ||
484 | clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel)); | ||
485 | clks[IMX7D_SAI1_ROOT_SRC] = imx_clk_mux("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel)); | ||
486 | clks[IMX7D_SAI2_ROOT_SRC] = imx_clk_mux("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel)); | ||
487 | clks[IMX7D_SAI3_ROOT_SRC] = imx_clk_mux("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel)); | ||
488 | clks[IMX7D_SPDIF_ROOT_SRC] = imx_clk_mux("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel)); | ||
489 | clks[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_mux("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel)); | ||
490 | clks[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_mux("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel)); | ||
491 | clks[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_mux("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel)); | ||
492 | clks[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_mux("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel)); | ||
493 | clks[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_mux("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel)); | ||
494 | clks[IMX7D_EIM_ROOT_SRC] = imx_clk_mux("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel)); | ||
495 | clks[IMX7D_NAND_ROOT_SRC] = imx_clk_mux("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel)); | ||
496 | clks[IMX7D_QSPI_ROOT_SRC] = imx_clk_mux("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel)); | ||
497 | clks[IMX7D_USDHC1_ROOT_SRC] = imx_clk_mux("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel)); | ||
498 | clks[IMX7D_USDHC2_ROOT_SRC] = imx_clk_mux("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel)); | ||
499 | clks[IMX7D_USDHC3_ROOT_SRC] = imx_clk_mux("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel)); | ||
500 | clks[IMX7D_CAN1_ROOT_SRC] = imx_clk_mux("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel)); | ||
501 | clks[IMX7D_CAN2_ROOT_SRC] = imx_clk_mux("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel)); | ||
502 | clks[IMX7D_I2C1_ROOT_SRC] = imx_clk_mux("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel)); | ||
503 | clks[IMX7D_I2C2_ROOT_SRC] = imx_clk_mux("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel)); | ||
504 | clks[IMX7D_I2C3_ROOT_SRC] = imx_clk_mux("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel)); | ||
505 | clks[IMX7D_I2C4_ROOT_SRC] = imx_clk_mux("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel)); | ||
506 | clks[IMX7D_UART1_ROOT_SRC] = imx_clk_mux("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel)); | ||
507 | clks[IMX7D_UART2_ROOT_SRC] = imx_clk_mux("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel)); | ||
508 | clks[IMX7D_UART3_ROOT_SRC] = imx_clk_mux("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel)); | ||
509 | clks[IMX7D_UART4_ROOT_SRC] = imx_clk_mux("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel)); | ||
510 | clks[IMX7D_UART5_ROOT_SRC] = imx_clk_mux("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel)); | ||
511 | clks[IMX7D_UART6_ROOT_SRC] = imx_clk_mux("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel)); | ||
512 | clks[IMX7D_UART7_ROOT_SRC] = imx_clk_mux("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel)); | ||
513 | clks[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_mux("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel)); | ||
514 | clks[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_mux("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel)); | ||
515 | clks[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_mux("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel)); | ||
516 | clks[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_mux("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel)); | ||
517 | clks[IMX7D_PWM1_ROOT_SRC] = imx_clk_mux("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel)); | ||
518 | clks[IMX7D_PWM2_ROOT_SRC] = imx_clk_mux("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel)); | ||
519 | clks[IMX7D_PWM3_ROOT_SRC] = imx_clk_mux("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel)); | ||
520 | clks[IMX7D_PWM4_ROOT_SRC] = imx_clk_mux("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel)); | ||
521 | clks[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_mux("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel)); | ||
522 | clks[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_mux("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel)); | ||
523 | clks[IMX7D_SIM1_ROOT_SRC] = imx_clk_mux("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel)); | ||
524 | clks[IMX7D_SIM2_ROOT_SRC] = imx_clk_mux("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel)); | ||
525 | clks[IMX7D_GPT1_ROOT_SRC] = imx_clk_mux("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel)); | ||
526 | clks[IMX7D_GPT2_ROOT_SRC] = imx_clk_mux("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel)); | ||
527 | clks[IMX7D_GPT3_ROOT_SRC] = imx_clk_mux("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel)); | ||
528 | clks[IMX7D_GPT4_ROOT_SRC] = imx_clk_mux("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel)); | ||
529 | clks[IMX7D_TRACE_ROOT_SRC] = imx_clk_mux("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel)); | ||
530 | clks[IMX7D_WDOG_ROOT_SRC] = imx_clk_mux("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel)); | ||
531 | clks[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_mux("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel)); | ||
532 | clks[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_mux("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel)); | ||
533 | clks[IMX7D_WRCLK_ROOT_SRC] = imx_clk_mux("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel)); | ||
534 | clks[IMX7D_CLKO1_ROOT_SRC] = imx_clk_mux("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel)); | ||
535 | clks[IMX7D_CLKO2_ROOT_SRC] = imx_clk_mux("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel)); | ||
536 | |||
537 | clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate("arm_a7_cg", "arm_a7_src", base + 0x8000, 28); | ||
538 | clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); | ||
539 | clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate("arm_m0_cg", "arm_m0_src", base + 0x8100, 28); | ||
540 | clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate("axi_cg", "axi_src", base + 0x8800, 28); | ||
541 | clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate("disp_axi_cg", "disp_axi_src", base + 0x8880, 28); | ||
542 | clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate("enet_axi_cg", "enet_axi_src", base + 0x8900, 28); | ||
543 | clks[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_gate("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28); | ||
544 | clks[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_gate("ahb_cg", "ahb_src", base + 0x9000, 28); | ||
545 | clks[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_gate("dram_phym_cg", "dram_phym_src", base + 0x9800, 28); | ||
546 | clks[IMX7D_DRAM_ROOT_CG] = imx_clk_gate("dram_cg", "dram_src", base + 0x9880, 28); | ||
547 | clks[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_gate("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28); | ||
548 | clks[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_gate("dram_alt_cg", "dram_alt_src", base + 0xa080, 28); | ||
549 | clks[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_gate("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28); | ||
550 | clks[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_gate("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28); | ||
551 | clks[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_gate("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28); | ||
552 | clks[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_gate("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28); | ||
553 | clks[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_gate("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28); | ||
554 | clks[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_gate("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28); | ||
555 | clks[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_gate("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28); | ||
556 | clks[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_gate("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28); | ||
557 | clks[IMX7D_SAI1_ROOT_CG] = imx_clk_gate("sai1_cg", "sai1_src", base + 0xa500, 28); | ||
558 | clks[IMX7D_SAI2_ROOT_CG] = imx_clk_gate("sai2_cg", "sai2_src", base + 0xa580, 28); | ||
559 | clks[IMX7D_SAI3_ROOT_CG] = imx_clk_gate("sai3_cg", "sai3_src", base + 0xa600, 28); | ||
560 | clks[IMX7D_SPDIF_ROOT_CG] = imx_clk_gate("spdif_cg", "spdif_src", base + 0xa680, 28); | ||
561 | clks[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_gate("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28); | ||
562 | clks[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_gate("enet1_time_cg", "enet1_time_src", base + 0xa780, 28); | ||
563 | clks[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_gate("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28); | ||
564 | clks[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_gate("enet2_time_cg", "enet2_time_src", base + 0xa880, 28); | ||
565 | clks[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_gate("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28); | ||
566 | clks[IMX7D_EIM_ROOT_CG] = imx_clk_gate("eim_cg", "eim_src", base + 0xa980, 28); | ||
567 | clks[IMX7D_NAND_ROOT_CG] = imx_clk_gate("nand_cg", "nand_src", base + 0xaa00, 28); | ||
568 | clks[IMX7D_QSPI_ROOT_CG] = imx_clk_gate("qspi_cg", "qspi_src", base + 0xaa80, 28); | ||
569 | clks[IMX7D_USDHC1_ROOT_CG] = imx_clk_gate("usdhc1_cg", "usdhc1_src", base + 0xab00, 28); | ||
570 | clks[IMX7D_USDHC2_ROOT_CG] = imx_clk_gate("usdhc2_cg", "usdhc2_src", base + 0xab80, 28); | ||
571 | clks[IMX7D_USDHC3_ROOT_CG] = imx_clk_gate("usdhc3_cg", "usdhc3_src", base + 0xac00, 28); | ||
572 | clks[IMX7D_CAN1_ROOT_CG] = imx_clk_gate("can1_cg", "can1_src", base + 0xac80, 28); | ||
573 | clks[IMX7D_CAN2_ROOT_CG] = imx_clk_gate("can2_cg", "can2_src", base + 0xad00, 28); | ||
574 | clks[IMX7D_I2C1_ROOT_CG] = imx_clk_gate("i2c1_cg", "i2c1_src", base + 0xad80, 28); | ||
575 | clks[IMX7D_I2C2_ROOT_CG] = imx_clk_gate("i2c2_cg", "i2c2_src", base + 0xae00, 28); | ||
576 | clks[IMX7D_I2C3_ROOT_CG] = imx_clk_gate("i2c3_cg", "i2c3_src", base + 0xae80, 28); | ||
577 | clks[IMX7D_I2C4_ROOT_CG] = imx_clk_gate("i2c4_cg", "i2c4_src", base + 0xaf00, 28); | ||
578 | clks[IMX7D_UART1_ROOT_CG] = imx_clk_gate("uart1_cg", "uart1_src", base + 0xaf80, 28); | ||
579 | clks[IMX7D_UART2_ROOT_CG] = imx_clk_gate("uart2_cg", "uart2_src", base + 0xb000, 28); | ||
580 | clks[IMX7D_UART3_ROOT_CG] = imx_clk_gate("uart3_cg", "uart3_src", base + 0xb080, 28); | ||
581 | clks[IMX7D_UART4_ROOT_CG] = imx_clk_gate("uart4_cg", "uart4_src", base + 0xb100, 28); | ||
582 | clks[IMX7D_UART5_ROOT_CG] = imx_clk_gate("uart5_cg", "uart5_src", base + 0xb180, 28); | ||
583 | clks[IMX7D_UART6_ROOT_CG] = imx_clk_gate("uart6_cg", "uart6_src", base + 0xb200, 28); | ||
584 | clks[IMX7D_UART7_ROOT_CG] = imx_clk_gate("uart7_cg", "uart7_src", base + 0xb280, 28); | ||
585 | clks[IMX7D_ECSPI1_ROOT_CG] = imx_clk_gate("ecspi1_cg", "ecspi1_src", base + 0xb300, 28); | ||
586 | clks[IMX7D_ECSPI2_ROOT_CG] = imx_clk_gate("ecspi2_cg", "ecspi2_src", base + 0xb380, 28); | ||
587 | clks[IMX7D_ECSPI3_ROOT_CG] = imx_clk_gate("ecspi3_cg", "ecspi3_src", base + 0xb400, 28); | ||
588 | clks[IMX7D_ECSPI4_ROOT_CG] = imx_clk_gate("ecspi4_cg", "ecspi4_src", base + 0xb480, 28); | ||
589 | clks[IMX7D_PWM1_ROOT_CG] = imx_clk_gate("pwm1_cg", "pwm1_src", base + 0xb500, 28); | ||
590 | clks[IMX7D_PWM2_ROOT_CG] = imx_clk_gate("pwm2_cg", "pwm2_src", base + 0xb580, 28); | ||
591 | clks[IMX7D_PWM3_ROOT_CG] = imx_clk_gate("pwm3_cg", "pwm3_src", base + 0xb600, 28); | ||
592 | clks[IMX7D_PWM4_ROOT_CG] = imx_clk_gate("pwm4_cg", "pwm4_src", base + 0xb680, 28); | ||
593 | clks[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_gate("flextimer1_cg", "flextimer1_src", base + 0xb700, 28); | ||
594 | clks[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_gate("flextimer2_cg", "flextimer2_src", base + 0xb780, 28); | ||
595 | clks[IMX7D_SIM1_ROOT_CG] = imx_clk_gate("sim1_cg", "sim1_src", base + 0xb800, 28); | ||
596 | clks[IMX7D_SIM2_ROOT_CG] = imx_clk_gate("sim2_cg", "sim2_src", base + 0xb880, 28); | ||
597 | clks[IMX7D_GPT1_ROOT_CG] = imx_clk_gate("gpt1_cg", "gpt1_src", base + 0xb900, 28); | ||
598 | clks[IMX7D_GPT2_ROOT_CG] = imx_clk_gate("gpt2_cg", "gpt2_src", base + 0xb980, 28); | ||
599 | clks[IMX7D_GPT3_ROOT_CG] = imx_clk_gate("gpt3_cg", "gpt3_src", base + 0xbA00, 28); | ||
600 | clks[IMX7D_GPT4_ROOT_CG] = imx_clk_gate("gpt4_cg", "gpt4_src", base + 0xbA80, 28); | ||
601 | clks[IMX7D_TRACE_ROOT_CG] = imx_clk_gate("trace_cg", "trace_src", base + 0xbb00, 28); | ||
602 | clks[IMX7D_WDOG_ROOT_CG] = imx_clk_gate("wdog_cg", "wdog_src", base + 0xbb80, 28); | ||
603 | clks[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_gate("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28); | ||
604 | clks[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_gate("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28); | ||
605 | clks[IMX7D_WRCLK_ROOT_CG] = imx_clk_gate("wrclk_cg", "wrclk_src", base + 0xbd00, 28); | ||
606 | clks[IMX7D_CLKO1_ROOT_CG] = imx_clk_gate("clko1_cg", "clko1_src", base + 0xbd80, 28); | ||
607 | clks[IMX7D_CLKO2_ROOT_CG] = imx_clk_gate("clko2_cg", "clko2_src", base + 0xbe00, 28); | ||
608 | |||
609 | clks[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_divider("axi_pre_div", "axi_cg", base + 0x8800, 16, 3); | ||
610 | clks[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_divider("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3); | ||
611 | clks[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_divider("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3); | ||
612 | clks[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_divider("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3); | ||
613 | clks[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_divider("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3); | ||
614 | clks[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_divider("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3); | ||
615 | clks[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_divider("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3); | ||
616 | clks[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_divider("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3); | ||
617 | clks[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_divider("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3); | ||
618 | clks[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_divider("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3); | ||
619 | clks[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_divider("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3); | ||
620 | clks[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_divider("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3); | ||
621 | clks[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_divider("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3); | ||
622 | clks[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_divider("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3); | ||
623 | clks[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_divider("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3); | ||
624 | clks[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_divider("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3); | ||
625 | clks[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_divider("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3); | ||
626 | clks[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_divider("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3); | ||
627 | clks[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_divider("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3); | ||
628 | clks[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_divider("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3); | ||
629 | clks[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_divider("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3); | ||
630 | clks[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_divider("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3); | ||
631 | clks[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_divider("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3); | ||
632 | clks[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_divider("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3); | ||
633 | clks[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_divider("eim_pre_div", "eim_cg", base + 0xa980, 16, 3); | ||
634 | clks[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_divider("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3); | ||
635 | clks[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_divider("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3); | ||
636 | clks[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_divider("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3); | ||
637 | clks[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_divider("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3); | ||
638 | clks[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_divider("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3); | ||
639 | clks[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_divider("can1_pre_div", "can1_cg", base + 0xac80, 16, 3); | ||
640 | clks[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_divider("can2_pre_div", "can2_cg", base + 0xad00, 16, 3); | ||
641 | clks[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_divider("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3); | ||
642 | clks[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_divider("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3); | ||
643 | clks[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_divider("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3); | ||
644 | clks[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_divider("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3); | ||
645 | clks[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_divider("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3); | ||
646 | clks[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_divider("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3); | ||
647 | clks[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_divider("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3); | ||
648 | clks[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_divider("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3); | ||
649 | clks[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_divider("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3); | ||
650 | clks[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_divider("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3); | ||
651 | clks[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_divider("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3); | ||
652 | clks[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_divider("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3); | ||
653 | clks[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_divider("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3); | ||
654 | clks[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_divider("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3); | ||
655 | clks[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_divider("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3); | ||
656 | clks[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_divider("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3); | ||
657 | clks[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_divider("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3); | ||
658 | clks[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_divider("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3); | ||
659 | clks[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_divider("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3); | ||
660 | clks[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_divider("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3); | ||
661 | clks[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_divider("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3); | ||
662 | clks[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_divider("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3); | ||
663 | clks[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_divider("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3); | ||
664 | clks[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_divider("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3); | ||
665 | clks[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_divider("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3); | ||
666 | clks[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_divider("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3); | ||
667 | clks[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_divider("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3); | ||
668 | clks[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_divider("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3); | ||
669 | clks[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_divider("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3); | ||
670 | clks[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_divider("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3); | ||
671 | clks[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_divider("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3); | ||
672 | clks[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_divider("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3); | ||
673 | clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3); | ||
674 | clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3); | ||
675 | |||
676 | clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3); | ||
677 | clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); | ||
678 | clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3); | ||
679 | clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6); | ||
680 | clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6); | ||
681 | clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6); | ||
682 | clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6); | ||
683 | clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6); | ||
684 | clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider("dram_post_div", "dram_cg", base + 0x9880, 0, 3); | ||
685 | clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3); | ||
686 | clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3); | ||
687 | clks[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_divider("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6); | ||
688 | clks[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_divider("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6); | ||
689 | clks[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_divider("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6); | ||
690 | clks[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_divider("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6); | ||
691 | clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6); | ||
692 | clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6); | ||
693 | clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6); | ||
694 | clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider("mipi_dphy_post_div", "mipi_csi_dphy_div", base + 0xa480, 0, 6); | ||
695 | clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6); | ||
696 | clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6); | ||
697 | clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6); | ||
698 | clks[IMX7D_SPDIF_ROOT_DIV] = imx_clk_divider("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6); | ||
699 | clks[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_divider("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6); | ||
700 | clks[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_divider("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6); | ||
701 | clks[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_divider("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6); | ||
702 | clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6); | ||
703 | clks[IMX7D_ENET_PHY_REF_ROOT_DIV] = imx_clk_divider("enet_phy_ref_post_div", "enet_phy_ref_pre_div", base + 0xa900, 0, 6); | ||
704 | clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6); | ||
705 | clks[IMX7D_NAND_ROOT_DIV] = imx_clk_divider("nand_post_div", "nand_pre_div", base + 0xaa00, 0, 6); | ||
706 | clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6); | ||
707 | clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6); | ||
708 | clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6); | ||
709 | clks[IMX7D_USDHC3_ROOT_DIV] = imx_clk_divider("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6); | ||
710 | clks[IMX7D_CAN1_ROOT_DIV] = imx_clk_divider("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6); | ||
711 | clks[IMX7D_CAN2_ROOT_DIV] = imx_clk_divider("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6); | ||
712 | clks[IMX7D_I2C1_ROOT_DIV] = imx_clk_divider("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6); | ||
713 | clks[IMX7D_I2C2_ROOT_DIV] = imx_clk_divider("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6); | ||
714 | clks[IMX7D_I2C3_ROOT_DIV] = imx_clk_divider("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6); | ||
715 | clks[IMX7D_I2C4_ROOT_DIV] = imx_clk_divider("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6); | ||
716 | clks[IMX7D_UART1_ROOT_DIV] = imx_clk_divider("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6); | ||
717 | clks[IMX7D_UART2_ROOT_DIV] = imx_clk_divider("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6); | ||
718 | clks[IMX7D_UART3_ROOT_DIV] = imx_clk_divider("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6); | ||
719 | clks[IMX7D_UART4_ROOT_DIV] = imx_clk_divider("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6); | ||
720 | clks[IMX7D_UART5_ROOT_DIV] = imx_clk_divider("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6); | ||
721 | clks[IMX7D_UART6_ROOT_DIV] = imx_clk_divider("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6); | ||
722 | clks[IMX7D_UART7_ROOT_DIV] = imx_clk_divider("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6); | ||
723 | clks[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_divider("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6); | ||
724 | clks[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_divider("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6); | ||
725 | clks[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_divider("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6); | ||
726 | clks[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_divider("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6); | ||
727 | clks[IMX7D_PWM1_ROOT_DIV] = imx_clk_divider("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6); | ||
728 | clks[IMX7D_PWM2_ROOT_DIV] = imx_clk_divider("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6); | ||
729 | clks[IMX7D_PWM3_ROOT_DIV] = imx_clk_divider("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6); | ||
730 | clks[IMX7D_PWM4_ROOT_DIV] = imx_clk_divider("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6); | ||
731 | clks[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_divider("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6); | ||
732 | clks[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_divider("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6); | ||
733 | clks[IMX7D_SIM1_ROOT_DIV] = imx_clk_divider("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6); | ||
734 | clks[IMX7D_SIM2_ROOT_DIV] = imx_clk_divider("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6); | ||
735 | clks[IMX7D_GPT1_ROOT_DIV] = imx_clk_divider("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6); | ||
736 | clks[IMX7D_GPT2_ROOT_DIV] = imx_clk_divider("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6); | ||
737 | clks[IMX7D_GPT3_ROOT_DIV] = imx_clk_divider("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6); | ||
738 | clks[IMX7D_GPT4_ROOT_DIV] = imx_clk_divider("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6); | ||
739 | clks[IMX7D_TRACE_ROOT_DIV] = imx_clk_divider("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6); | ||
740 | clks[IMX7D_WDOG_ROOT_DIV] = imx_clk_divider("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6); | ||
741 | clks[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_divider("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6); | ||
742 | clks[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_divider("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6); | ||
743 | clks[IMX7D_WRCLK_ROOT_DIV] = imx_clk_divider("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6); | ||
744 | clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6); | ||
745 | clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6); | ||
746 | |||
747 | clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0); | ||
748 | clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate2("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0); | ||
749 | clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate2("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0); | ||
750 | clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate2("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); | ||
751 | clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate2("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); | ||
752 | clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate2("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); | ||
753 | clks[IMX7D_OCRAM_CLK] = imx_clk_gate2("ocram_clk", "axi_post_div", base + 0x4110, 0); | ||
754 | clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate2("ocram_s_clk", "ahb_post_div", base + 0x4120, 0); | ||
755 | clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate2("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0); | ||
756 | clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate2("ahb_root_clk", "ahb_post_div", base + 0x4200, 0); | ||
757 | clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate2("dram_root_clk", "dram_post_div", base + 0x4130, 0); | ||
758 | clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate2("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0); | ||
759 | clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate2("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0); | ||
760 | clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate2("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0); | ||
761 | clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate2("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0); | ||
762 | clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate2("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0); | ||
763 | clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate2("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0); | ||
764 | clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate2("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0); | ||
765 | clks[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_gate2("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0); | ||
766 | clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate2("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0); | ||
767 | clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate2("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0); | ||
768 | clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate2("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0); | ||
769 | clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate2("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0); | ||
770 | clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate2("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0); | ||
771 | clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate2("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0); | ||
772 | clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate2("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0); | ||
773 | clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate2("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x44e0, 0); | ||
774 | clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate2("enet1_time_root_clk", "enet1_time_post_div", base + 0x44f0, 0); | ||
775 | clks[IMX7D_ENET2_REF_ROOT_CLK] = imx_clk_gate2("enet2_ref_root_clk", "enet2_ref_post_div", base + 0x4500, 0); | ||
776 | clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate2("enet2_time_root_clk", "enet2_time_post_div", base + 0x4510, 0); | ||
777 | clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate2("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0); | ||
778 | clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate2("eim_root_clk", "eim_post_div", base + 0x4160, 0); | ||
779 | clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate2("nand_root_clk", "nand_post_div", base + 0x4140, 0); | ||
780 | clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate2("qspi_root_clk", "qspi_post_div", base + 0x4150, 0); | ||
781 | clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate2("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0); | ||
782 | clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate2("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0); | ||
783 | clks[IMX7D_USDHC3_ROOT_CLK] = imx_clk_gate2("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0); | ||
784 | clks[IMX7D_CAN1_ROOT_CLK] = imx_clk_gate2("can1_root_clk", "can1_post_div", base + 0x4740, 0); | ||
785 | clks[IMX7D_CAN2_ROOT_CLK] = imx_clk_gate2("can2_root_clk", "can2_post_div", base + 0x4750, 0); | ||
786 | clks[IMX7D_I2C1_ROOT_CLK] = imx_clk_gate2("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0); | ||
787 | clks[IMX7D_I2C2_ROOT_CLK] = imx_clk_gate2("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0); | ||
788 | clks[IMX7D_I2C3_ROOT_CLK] = imx_clk_gate2("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0); | ||
789 | clks[IMX7D_I2C4_ROOT_CLK] = imx_clk_gate2("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0); | ||
790 | clks[IMX7D_UART1_ROOT_CLK] = imx_clk_gate2("uart1_root_clk", "uart1_post_div", base + 0x4940, 0); | ||
791 | clks[IMX7D_UART2_ROOT_CLK] = imx_clk_gate2("uart2_root_clk", "uart2_post_div", base + 0x4950, 0); | ||
792 | clks[IMX7D_UART3_ROOT_CLK] = imx_clk_gate2("uart3_root_clk", "uart3_post_div", base + 0x4960, 0); | ||
793 | clks[IMX7D_UART4_ROOT_CLK] = imx_clk_gate2("uart4_root_clk", "uart4_post_div", base + 0x4970, 0); | ||
794 | clks[IMX7D_UART5_ROOT_CLK] = imx_clk_gate2("uart5_root_clk", "uart5_post_div", base + 0x4980, 0); | ||
795 | clks[IMX7D_UART6_ROOT_CLK] = imx_clk_gate2("uart6_root_clk", "uart6_post_div", base + 0x4990, 0); | ||
796 | clks[IMX7D_UART7_ROOT_CLK] = imx_clk_gate2("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0); | ||
797 | clks[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_gate2("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0); | ||
798 | clks[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_gate2("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0); | ||
799 | clks[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_gate2("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0); | ||
800 | clks[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_gate2("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0); | ||
801 | clks[IMX7D_PWM1_ROOT_CLK] = imx_clk_gate2("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0); | ||
802 | clks[IMX7D_PWM2_ROOT_CLK] = imx_clk_gate2("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0); | ||
803 | clks[IMX7D_PWM3_ROOT_CLK] = imx_clk_gate2("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0); | ||
804 | clks[IMX7D_PWM4_ROOT_CLK] = imx_clk_gate2("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0); | ||
805 | clks[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_gate2("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0); | ||
806 | clks[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_gate2("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0); | ||
807 | clks[IMX7D_SIM1_ROOT_CLK] = imx_clk_gate2("sim1_root_clk", "sim1_post_div", base + 0x4900, 0); | ||
808 | clks[IMX7D_SIM2_ROOT_CLK] = imx_clk_gate2("sim2_root_clk", "sim2_post_div", base + 0x4910, 0); | ||
809 | clks[IMX7D_GPT1_ROOT_CLK] = imx_clk_gate2("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0); | ||
810 | clks[IMX7D_GPT2_ROOT_CLK] = imx_clk_gate2("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0); | ||
811 | clks[IMX7D_GPT3_ROOT_CLK] = imx_clk_gate2("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0); | ||
812 | clks[IMX7D_GPT4_ROOT_CLK] = imx_clk_gate2("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0); | ||
813 | clks[IMX7D_TRACE_ROOT_CLK] = imx_clk_gate2("trace_root_clk", "trace_post_div", base + 0x4300, 0); | ||
814 | clks[IMX7D_WDOG1_ROOT_CLK] = imx_clk_gate2("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0); | ||
815 | clks[IMX7D_WDOG2_ROOT_CLK] = imx_clk_gate2("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0); | ||
816 | clks[IMX7D_WDOG3_ROOT_CLK] = imx_clk_gate2("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0); | ||
817 | clks[IMX7D_WDOG4_ROOT_CLK] = imx_clk_gate2("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0); | ||
818 | clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate2("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0); | ||
819 | clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate2("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0); | ||
820 | clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate2("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0); | ||
821 | |||
822 | clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); | ||
823 | |||
824 | for (i = 0; i < ARRAY_SIZE(clks); i++) | ||
825 | if (IS_ERR(clks[i])) | ||
826 | pr_err("i.MX7D clk %d: register failed with %ld\n", | ||
827 | i, PTR_ERR(clks[i])); | ||
828 | |||
829 | clk_data.clks = clks; | ||
830 | clk_data.clk_num = ARRAY_SIZE(clks); | ||
831 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
832 | |||
833 | /* TO BE FIXED LATER | ||
834 | * Enable all clock to bring up imx7, otherwise system will be halt and block | ||
835 | * the other part upstream Because imx7d clock design changed, clock framework | ||
836 | * need do a little modify. | ||
837 | * Dong Aisheng is working on this. After that, this part need be changed. | ||
838 | */ | ||
839 | for (i = 0; i < IMX7D_CLK_END; i++) | ||
840 | clk_prepare_enable(clks[i]); | ||
841 | |||
842 | /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */ | ||
843 | clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); | ||
844 | |||
845 | /* | ||
846 | * init enet clock source: | ||
847 | * AXI clock source is 250MHz | ||
848 | * Phy refrence clock is 25MHz | ||
849 | * 1588 time clock source is 100MHz | ||
850 | */ | ||
851 | clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]); | ||
852 | clk_set_parent(clks[IMX7D_ENET_PHY_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_25M_CLK]); | ||
853 | clk_set_parent(clks[IMX7D_ENET1_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]); | ||
854 | clk_set_parent(clks[IMX7D_ENET2_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]); | ||
855 | |||
856 | /* set uart module clock's parent clock source that must be great then 80MHz */ | ||
857 | clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); | ||
858 | |||
859 | } | ||
860 | CLK_OF_DECLARE(imx7d, "fsl,imx7d-ccm", imx7d_clocks_init); | ||
diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c new file mode 100644 index 000000000000..0b0f6f66ec56 --- /dev/null +++ b/drivers/clk/imx/clk-pfd.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2012 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/clk.h> | ||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/err.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | /** | ||
21 | * struct clk_pfd - IMX PFD clock | ||
22 | * @clk_hw: clock source | ||
23 | * @reg: PFD register address | ||
24 | * @idx: the index of PFD encoded in the register | ||
25 | * | ||
26 | * PFD clock found on i.MX6 series. Each register for PFD has 4 clk_pfd | ||
27 | * data encoded, and member idx is used to specify the one. And each | ||
28 | * register has SET, CLR and TOG registers at offset 0x4 0x8 and 0xc. | ||
29 | */ | ||
30 | struct clk_pfd { | ||
31 | struct clk_hw hw; | ||
32 | void __iomem *reg; | ||
33 | u8 idx; | ||
34 | }; | ||
35 | |||
36 | #define to_clk_pfd(_hw) container_of(_hw, struct clk_pfd, hw) | ||
37 | |||
38 | #define SET 0x4 | ||
39 | #define CLR 0x8 | ||
40 | #define OTG 0xc | ||
41 | |||
42 | static int clk_pfd_enable(struct clk_hw *hw) | ||
43 | { | ||
44 | struct clk_pfd *pfd = to_clk_pfd(hw); | ||
45 | |||
46 | writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static void clk_pfd_disable(struct clk_hw *hw) | ||
52 | { | ||
53 | struct clk_pfd *pfd = to_clk_pfd(hw); | ||
54 | |||
55 | writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET); | ||
56 | } | ||
57 | |||
58 | static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw, | ||
59 | unsigned long parent_rate) | ||
60 | { | ||
61 | struct clk_pfd *pfd = to_clk_pfd(hw); | ||
62 | u64 tmp = parent_rate; | ||
63 | u8 frac = (readl_relaxed(pfd->reg) >> (pfd->idx * 8)) & 0x3f; | ||
64 | |||
65 | tmp *= 18; | ||
66 | do_div(tmp, frac); | ||
67 | |||
68 | return tmp; | ||
69 | } | ||
70 | |||
71 | static long clk_pfd_round_rate(struct clk_hw *hw, unsigned long rate, | ||
72 | unsigned long *prate) | ||
73 | { | ||
74 | u64 tmp = *prate; | ||
75 | u8 frac; | ||
76 | |||
77 | tmp = tmp * 18 + rate / 2; | ||
78 | do_div(tmp, rate); | ||
79 | frac = tmp; | ||
80 | if (frac < 12) | ||
81 | frac = 12; | ||
82 | else if (frac > 35) | ||
83 | frac = 35; | ||
84 | tmp = *prate; | ||
85 | tmp *= 18; | ||
86 | do_div(tmp, frac); | ||
87 | |||
88 | return tmp; | ||
89 | } | ||
90 | |||
91 | static int clk_pfd_set_rate(struct clk_hw *hw, unsigned long rate, | ||
92 | unsigned long parent_rate) | ||
93 | { | ||
94 | struct clk_pfd *pfd = to_clk_pfd(hw); | ||
95 | u64 tmp = parent_rate; | ||
96 | u8 frac; | ||
97 | |||
98 | tmp = tmp * 18 + rate / 2; | ||
99 | do_div(tmp, rate); | ||
100 | frac = tmp; | ||
101 | if (frac < 12) | ||
102 | frac = 12; | ||
103 | else if (frac > 35) | ||
104 | frac = 35; | ||
105 | |||
106 | writel_relaxed(0x3f << (pfd->idx * 8), pfd->reg + CLR); | ||
107 | writel_relaxed(frac << (pfd->idx * 8), pfd->reg + SET); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int clk_pfd_is_enabled(struct clk_hw *hw) | ||
113 | { | ||
114 | struct clk_pfd *pfd = to_clk_pfd(hw); | ||
115 | |||
116 | if (readl_relaxed(pfd->reg) & (1 << ((pfd->idx + 1) * 8 - 1))) | ||
117 | return 0; | ||
118 | |||
119 | return 1; | ||
120 | } | ||
121 | |||
122 | static const struct clk_ops clk_pfd_ops = { | ||
123 | .enable = clk_pfd_enable, | ||
124 | .disable = clk_pfd_disable, | ||
125 | .recalc_rate = clk_pfd_recalc_rate, | ||
126 | .round_rate = clk_pfd_round_rate, | ||
127 | .set_rate = clk_pfd_set_rate, | ||
128 | .is_enabled = clk_pfd_is_enabled, | ||
129 | }; | ||
130 | |||
131 | struct clk *imx_clk_pfd(const char *name, const char *parent_name, | ||
132 | void __iomem *reg, u8 idx) | ||
133 | { | ||
134 | struct clk_pfd *pfd; | ||
135 | struct clk *clk; | ||
136 | struct clk_init_data init; | ||
137 | |||
138 | pfd = kzalloc(sizeof(*pfd), GFP_KERNEL); | ||
139 | if (!pfd) | ||
140 | return ERR_PTR(-ENOMEM); | ||
141 | |||
142 | pfd->reg = reg; | ||
143 | pfd->idx = idx; | ||
144 | |||
145 | init.name = name; | ||
146 | init.ops = &clk_pfd_ops; | ||
147 | init.flags = 0; | ||
148 | init.parent_names = &parent_name; | ||
149 | init.num_parents = 1; | ||
150 | |||
151 | pfd->hw.init = &init; | ||
152 | |||
153 | clk = clk_register(NULL, &pfd->hw); | ||
154 | if (IS_ERR(clk)) | ||
155 | kfree(pfd); | ||
156 | |||
157 | return clk; | ||
158 | } | ||
diff --git a/drivers/clk/imx/clk-pllv1.c b/drivers/clk/imx/clk-pllv1.c new file mode 100644 index 000000000000..c34ad8a611dd --- /dev/null +++ b/drivers/clk/imx/clk-pllv1.c | |||
@@ -0,0 +1,141 @@ | |||
1 | #include <linux/clk.h> | ||
2 | #include <linux/clk-provider.h> | ||
3 | #include <linux/io.h> | ||
4 | #include <linux/slab.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/err.h> | ||
7 | |||
8 | #include "clk.h" | ||
9 | |||
10 | /** | ||
11 | * pll v1 | ||
12 | * | ||
13 | * @clk_hw clock source | ||
14 | * @parent the parent clock name | ||
15 | * @base base address of pll registers | ||
16 | * | ||
17 | * PLL clock version 1, found on i.MX1/21/25/27/31/35 | ||
18 | */ | ||
19 | |||
20 | #define MFN_BITS (10) | ||
21 | #define MFN_SIGN (BIT(MFN_BITS - 1)) | ||
22 | #define MFN_MASK (MFN_SIGN - 1) | ||
23 | |||
24 | struct clk_pllv1 { | ||
25 | struct clk_hw hw; | ||
26 | void __iomem *base; | ||
27 | enum imx_pllv1_type type; | ||
28 | }; | ||
29 | |||
30 | #define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk)) | ||
31 | |||
32 | static inline bool is_imx1_pllv1(struct clk_pllv1 *pll) | ||
33 | { | ||
34 | return pll->type == IMX_PLLV1_IMX1; | ||
35 | } | ||
36 | |||
37 | static inline bool is_imx21_pllv1(struct clk_pllv1 *pll) | ||
38 | { | ||
39 | return pll->type == IMX_PLLV1_IMX21; | ||
40 | } | ||
41 | |||
42 | static inline bool is_imx27_pllv1(struct clk_pllv1 *pll) | ||
43 | { | ||
44 | return pll->type == IMX_PLLV1_IMX27; | ||
45 | } | ||
46 | |||
47 | static inline bool mfn_is_negative(struct clk_pllv1 *pll, unsigned int mfn) | ||
48 | { | ||
49 | return !is_imx1_pllv1(pll) && !is_imx21_pllv1(pll) && (mfn & MFN_SIGN); | ||
50 | } | ||
51 | |||
52 | static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw, | ||
53 | unsigned long parent_rate) | ||
54 | { | ||
55 | struct clk_pllv1 *pll = to_clk_pllv1(hw); | ||
56 | long long ll; | ||
57 | int mfn_abs; | ||
58 | unsigned int mfi, mfn, mfd, pd; | ||
59 | u32 reg; | ||
60 | unsigned long rate; | ||
61 | |||
62 | reg = readl(pll->base); | ||
63 | |||
64 | /* | ||
65 | * Get the resulting clock rate from a PLL register value and the input | ||
66 | * frequency. PLLs with this register layout can be found on i.MX1, | ||
67 | * i.MX21, i.MX27 and i,MX31 | ||
68 | * | ||
69 | * mfi + mfn / (mfd + 1) | ||
70 | * f = 2 * f_ref * -------------------- | ||
71 | * pd + 1 | ||
72 | */ | ||
73 | |||
74 | mfi = (reg >> 10) & 0xf; | ||
75 | mfn = reg & 0x3ff; | ||
76 | mfd = (reg >> 16) & 0x3ff; | ||
77 | pd = (reg >> 26) & 0xf; | ||
78 | |||
79 | mfi = mfi <= 5 ? 5 : mfi; | ||
80 | |||
81 | mfn_abs = mfn; | ||
82 | |||
83 | /* | ||
84 | * On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit | ||
85 | * 2's complements number. | ||
86 | * On i.MX27 the bit 9 is the sign bit. | ||
87 | */ | ||
88 | if (mfn_is_negative(pll, mfn)) { | ||
89 | if (is_imx27_pllv1(pll)) | ||
90 | mfn_abs = mfn & MFN_MASK; | ||
91 | else | ||
92 | mfn_abs = BIT(MFN_BITS) - mfn; | ||
93 | } | ||
94 | |||
95 | rate = parent_rate * 2; | ||
96 | rate /= pd + 1; | ||
97 | |||
98 | ll = (unsigned long long)rate * mfn_abs; | ||
99 | |||
100 | do_div(ll, mfd + 1); | ||
101 | |||
102 | if (mfn_is_negative(pll, mfn)) | ||
103 | ll = -ll; | ||
104 | |||
105 | ll = (rate * mfi) + ll; | ||
106 | |||
107 | return ll; | ||
108 | } | ||
109 | |||
110 | static struct clk_ops clk_pllv1_ops = { | ||
111 | .recalc_rate = clk_pllv1_recalc_rate, | ||
112 | }; | ||
113 | |||
114 | struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name, | ||
115 | const char *parent, void __iomem *base) | ||
116 | { | ||
117 | struct clk_pllv1 *pll; | ||
118 | struct clk *clk; | ||
119 | struct clk_init_data init; | ||
120 | |||
121 | pll = kmalloc(sizeof(*pll), GFP_KERNEL); | ||
122 | if (!pll) | ||
123 | return ERR_PTR(-ENOMEM); | ||
124 | |||
125 | pll->base = base; | ||
126 | pll->type = type; | ||
127 | |||
128 | init.name = name; | ||
129 | init.ops = &clk_pllv1_ops; | ||
130 | init.flags = 0; | ||
131 | init.parent_names = &parent; | ||
132 | init.num_parents = 1; | ||
133 | |||
134 | pll->hw.init = &init; | ||
135 | |||
136 | clk = clk_register(NULL, &pll->hw); | ||
137 | if (IS_ERR(clk)) | ||
138 | kfree(pll); | ||
139 | |||
140 | return clk; | ||
141 | } | ||
diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c new file mode 100644 index 000000000000..20889d59b44d --- /dev/null +++ b/drivers/clk/imx/clk-pllv2.c | |||
@@ -0,0 +1,266 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/clk.h> | ||
3 | #include <linux/io.h> | ||
4 | #include <linux/errno.h> | ||
5 | #include <linux/delay.h> | ||
6 | #include <linux/slab.h> | ||
7 | #include <linux/err.h> | ||
8 | |||
9 | #include <asm/div64.h> | ||
10 | |||
11 | #include "clk.h" | ||
12 | |||
13 | #define to_clk_pllv2(clk) (container_of(clk, struct clk_pllv2, clk)) | ||
14 | |||
15 | /* PLL Register Offsets */ | ||
16 | #define MXC_PLL_DP_CTL 0x00 | ||
17 | #define MXC_PLL_DP_CONFIG 0x04 | ||
18 | #define MXC_PLL_DP_OP 0x08 | ||
19 | #define MXC_PLL_DP_MFD 0x0C | ||
20 | #define MXC_PLL_DP_MFN 0x10 | ||
21 | #define MXC_PLL_DP_MFNMINUS 0x14 | ||
22 | #define MXC_PLL_DP_MFNPLUS 0x18 | ||
23 | #define MXC_PLL_DP_HFS_OP 0x1C | ||
24 | #define MXC_PLL_DP_HFS_MFD 0x20 | ||
25 | #define MXC_PLL_DP_HFS_MFN 0x24 | ||
26 | #define MXC_PLL_DP_MFN_TOGC 0x28 | ||
27 | #define MXC_PLL_DP_DESTAT 0x2c | ||
28 | |||
29 | /* PLL Register Bit definitions */ | ||
30 | #define MXC_PLL_DP_CTL_MUL_CTRL 0x2000 | ||
31 | #define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000 | ||
32 | #define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12 | ||
33 | #define MXC_PLL_DP_CTL_ADE 0x800 | ||
34 | #define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400 | ||
35 | #define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8) | ||
36 | #define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8 | ||
37 | #define MXC_PLL_DP_CTL_HFSM 0x80 | ||
38 | #define MXC_PLL_DP_CTL_PRE 0x40 | ||
39 | #define MXC_PLL_DP_CTL_UPEN 0x20 | ||
40 | #define MXC_PLL_DP_CTL_RST 0x10 | ||
41 | #define MXC_PLL_DP_CTL_RCP 0x8 | ||
42 | #define MXC_PLL_DP_CTL_PLM 0x4 | ||
43 | #define MXC_PLL_DP_CTL_BRM0 0x2 | ||
44 | #define MXC_PLL_DP_CTL_LRF 0x1 | ||
45 | |||
46 | #define MXC_PLL_DP_CONFIG_BIST 0x8 | ||
47 | #define MXC_PLL_DP_CONFIG_SJC_CE 0x4 | ||
48 | #define MXC_PLL_DP_CONFIG_AREN 0x2 | ||
49 | #define MXC_PLL_DP_CONFIG_LDREQ 0x1 | ||
50 | |||
51 | #define MXC_PLL_DP_OP_MFI_OFFSET 4 | ||
52 | #define MXC_PLL_DP_OP_MFI_MASK (0xF << 4) | ||
53 | #define MXC_PLL_DP_OP_PDF_OFFSET 0 | ||
54 | #define MXC_PLL_DP_OP_PDF_MASK 0xF | ||
55 | |||
56 | #define MXC_PLL_DP_MFD_OFFSET 0 | ||
57 | #define MXC_PLL_DP_MFD_MASK 0x07FFFFFF | ||
58 | |||
59 | #define MXC_PLL_DP_MFN_OFFSET 0x0 | ||
60 | #define MXC_PLL_DP_MFN_MASK 0x07FFFFFF | ||
61 | |||
62 | #define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17) | ||
63 | #define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16) | ||
64 | #define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0 | ||
65 | #define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF | ||
66 | |||
67 | #define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31) | ||
68 | #define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF | ||
69 | |||
70 | #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ | ||
71 | |||
72 | struct clk_pllv2 { | ||
73 | struct clk_hw hw; | ||
74 | void __iomem *base; | ||
75 | }; | ||
76 | |||
77 | static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate, | ||
78 | u32 dp_ctl, u32 dp_op, u32 dp_mfd, u32 dp_mfn) | ||
79 | { | ||
80 | long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; | ||
81 | unsigned long dbl; | ||
82 | s64 temp; | ||
83 | |||
84 | dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; | ||
85 | |||
86 | pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; | ||
87 | mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; | ||
88 | mfi = (mfi <= 5) ? 5 : mfi; | ||
89 | mfd = dp_mfd & MXC_PLL_DP_MFD_MASK; | ||
90 | mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK; | ||
91 | /* Sign extend to 32-bits */ | ||
92 | if (mfn >= 0x04000000) { | ||
93 | mfn |= 0xFC000000; | ||
94 | mfn_abs = -mfn; | ||
95 | } | ||
96 | |||
97 | ref_clk = 2 * parent_rate; | ||
98 | if (dbl != 0) | ||
99 | ref_clk *= 2; | ||
100 | |||
101 | ref_clk /= (pdf + 1); | ||
102 | temp = (u64) ref_clk * mfn_abs; | ||
103 | do_div(temp, mfd + 1); | ||
104 | if (mfn < 0) | ||
105 | temp = -temp; | ||
106 | temp = (ref_clk * mfi) + temp; | ||
107 | |||
108 | return temp; | ||
109 | } | ||
110 | |||
111 | static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, | ||
112 | unsigned long parent_rate) | ||
113 | { | ||
114 | u32 dp_op, dp_mfd, dp_mfn, dp_ctl; | ||
115 | void __iomem *pllbase; | ||
116 | struct clk_pllv2 *pll = to_clk_pllv2(hw); | ||
117 | |||
118 | pllbase = pll->base; | ||
119 | |||
120 | dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); | ||
121 | dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); | ||
122 | dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); | ||
123 | dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); | ||
124 | |||
125 | return __clk_pllv2_recalc_rate(parent_rate, dp_ctl, dp_op, dp_mfd, dp_mfn); | ||
126 | } | ||
127 | |||
128 | static int __clk_pllv2_set_rate(unsigned long rate, unsigned long parent_rate, | ||
129 | u32 *dp_op, u32 *dp_mfd, u32 *dp_mfn) | ||
130 | { | ||
131 | u32 reg; | ||
132 | long mfi, pdf, mfn, mfd = 999999; | ||
133 | s64 temp64; | ||
134 | unsigned long quad_parent_rate; | ||
135 | |||
136 | quad_parent_rate = 4 * parent_rate; | ||
137 | pdf = mfi = -1; | ||
138 | while (++pdf < 16 && mfi < 5) | ||
139 | mfi = rate * (pdf+1) / quad_parent_rate; | ||
140 | if (mfi > 15) | ||
141 | return -EINVAL; | ||
142 | pdf--; | ||
143 | |||
144 | temp64 = rate * (pdf + 1) - quad_parent_rate * mfi; | ||
145 | do_div(temp64, quad_parent_rate / 1000000); | ||
146 | mfn = (long)temp64; | ||
147 | |||
148 | reg = mfi << 4 | pdf; | ||
149 | |||
150 | *dp_op = reg; | ||
151 | *dp_mfd = mfd; | ||
152 | *dp_mfn = mfn; | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, | ||
158 | unsigned long parent_rate) | ||
159 | { | ||
160 | struct clk_pllv2 *pll = to_clk_pllv2(hw); | ||
161 | void __iomem *pllbase; | ||
162 | u32 dp_ctl, dp_op, dp_mfd, dp_mfn; | ||
163 | int ret; | ||
164 | |||
165 | pllbase = pll->base; | ||
166 | |||
167 | |||
168 | ret = __clk_pllv2_set_rate(rate, parent_rate, &dp_op, &dp_mfd, &dp_mfn); | ||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); | ||
173 | /* use dpdck0_2 */ | ||
174 | __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); | ||
175 | |||
176 | __raw_writel(dp_op, pllbase + MXC_PLL_DP_OP); | ||
177 | __raw_writel(dp_mfd, pllbase + MXC_PLL_DP_MFD); | ||
178 | __raw_writel(dp_mfn, pllbase + MXC_PLL_DP_MFN); | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate, | ||
184 | unsigned long *prate) | ||
185 | { | ||
186 | u32 dp_op, dp_mfd, dp_mfn; | ||
187 | |||
188 | __clk_pllv2_set_rate(rate, *prate, &dp_op, &dp_mfd, &dp_mfn); | ||
189 | return __clk_pllv2_recalc_rate(*prate, MXC_PLL_DP_CTL_DPDCK0_2_EN, | ||
190 | dp_op, dp_mfd, dp_mfn); | ||
191 | } | ||
192 | |||
193 | static int clk_pllv2_prepare(struct clk_hw *hw) | ||
194 | { | ||
195 | struct clk_pllv2 *pll = to_clk_pllv2(hw); | ||
196 | u32 reg; | ||
197 | void __iomem *pllbase; | ||
198 | int i = 0; | ||
199 | |||
200 | pllbase = pll->base; | ||
201 | reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN; | ||
202 | __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); | ||
203 | |||
204 | /* Wait for lock */ | ||
205 | do { | ||
206 | reg = __raw_readl(pllbase + MXC_PLL_DP_CTL); | ||
207 | if (reg & MXC_PLL_DP_CTL_LRF) | ||
208 | break; | ||
209 | |||
210 | udelay(1); | ||
211 | } while (++i < MAX_DPLL_WAIT_TRIES); | ||
212 | |||
213 | if (i == MAX_DPLL_WAIT_TRIES) { | ||
214 | pr_err("MX5: pll locking failed\n"); | ||
215 | return -EINVAL; | ||
216 | } | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static void clk_pllv2_unprepare(struct clk_hw *hw) | ||
222 | { | ||
223 | struct clk_pllv2 *pll = to_clk_pllv2(hw); | ||
224 | u32 reg; | ||
225 | void __iomem *pllbase; | ||
226 | |||
227 | pllbase = pll->base; | ||
228 | reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN; | ||
229 | __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); | ||
230 | } | ||
231 | |||
232 | static struct clk_ops clk_pllv2_ops = { | ||
233 | .prepare = clk_pllv2_prepare, | ||
234 | .unprepare = clk_pllv2_unprepare, | ||
235 | .recalc_rate = clk_pllv2_recalc_rate, | ||
236 | .round_rate = clk_pllv2_round_rate, | ||
237 | .set_rate = clk_pllv2_set_rate, | ||
238 | }; | ||
239 | |||
240 | struct clk *imx_clk_pllv2(const char *name, const char *parent, | ||
241 | void __iomem *base) | ||
242 | { | ||
243 | struct clk_pllv2 *pll; | ||
244 | struct clk *clk; | ||
245 | struct clk_init_data init; | ||
246 | |||
247 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
248 | if (!pll) | ||
249 | return ERR_PTR(-ENOMEM); | ||
250 | |||
251 | pll->base = base; | ||
252 | |||
253 | init.name = name; | ||
254 | init.ops = &clk_pllv2_ops; | ||
255 | init.flags = 0; | ||
256 | init.parent_names = &parent; | ||
257 | init.num_parents = 1; | ||
258 | |||
259 | pll->hw.init = &init; | ||
260 | |||
261 | clk = clk_register(NULL, &pll->hw); | ||
262 | if (IS_ERR(clk)) | ||
263 | kfree(pll); | ||
264 | |||
265 | return clk; | ||
266 | } | ||
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c new file mode 100644 index 000000000000..f0d15fb9d783 --- /dev/null +++ b/drivers/clk/imx/clk-pllv3.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2012 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/clk.h> | ||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/jiffies.h> | ||
19 | #include <linux/err.h> | ||
20 | #include "clk.h" | ||
21 | |||
22 | #define PLL_NUM_OFFSET 0x10 | ||
23 | #define PLL_DENOM_OFFSET 0x20 | ||
24 | |||
25 | #define BM_PLL_POWER (0x1 << 12) | ||
26 | #define BM_PLL_LOCK (0x1 << 31) | ||
27 | #define IMX7_ENET_PLL_POWER (0x1 << 5) | ||
28 | |||
29 | /** | ||
30 | * struct clk_pllv3 - IMX PLL clock version 3 | ||
31 | * @clk_hw: clock source | ||
32 | * @base: base address of PLL registers | ||
33 | * @powerup_set: set POWER bit to power up the PLL | ||
34 | * @powerdown: pll powerdown offset bit | ||
35 | * @div_mask: mask of divider bits | ||
36 | * @div_shift: shift of divider bits | ||
37 | * | ||
38 | * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 | ||
39 | * is actually a multiplier, and always sits at bit 0. | ||
40 | */ | ||
41 | struct clk_pllv3 { | ||
42 | struct clk_hw hw; | ||
43 | void __iomem *base; | ||
44 | bool powerup_set; | ||
45 | u32 powerdown; | ||
46 | u32 div_mask; | ||
47 | u32 div_shift; | ||
48 | }; | ||
49 | |||
50 | #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) | ||
51 | |||
52 | static int clk_pllv3_wait_lock(struct clk_pllv3 *pll) | ||
53 | { | ||
54 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | ||
55 | u32 val = readl_relaxed(pll->base) & pll->powerdown; | ||
56 | |||
57 | /* No need to wait for lock when pll is not powered up */ | ||
58 | if ((pll->powerup_set && !val) || (!pll->powerup_set && val)) | ||
59 | return 0; | ||
60 | |||
61 | /* Wait for PLL to lock */ | ||
62 | do { | ||
63 | if (readl_relaxed(pll->base) & BM_PLL_LOCK) | ||
64 | break; | ||
65 | if (time_after(jiffies, timeout)) | ||
66 | break; | ||
67 | usleep_range(50, 500); | ||
68 | } while (1); | ||
69 | |||
70 | return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT; | ||
71 | } | ||
72 | |||
73 | static int clk_pllv3_prepare(struct clk_hw *hw) | ||
74 | { | ||
75 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | ||
76 | u32 val; | ||
77 | |||
78 | val = readl_relaxed(pll->base); | ||
79 | if (pll->powerup_set) | ||
80 | val |= BM_PLL_POWER; | ||
81 | else | ||
82 | val &= ~BM_PLL_POWER; | ||
83 | writel_relaxed(val, pll->base); | ||
84 | |||
85 | return clk_pllv3_wait_lock(pll); | ||
86 | } | ||
87 | |||
88 | static void clk_pllv3_unprepare(struct clk_hw *hw) | ||
89 | { | ||
90 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | ||
91 | u32 val; | ||
92 | |||
93 | val = readl_relaxed(pll->base); | ||
94 | if (pll->powerup_set) | ||
95 | val &= ~BM_PLL_POWER; | ||
96 | else | ||
97 | val |= BM_PLL_POWER; | ||
98 | writel_relaxed(val, pll->base); | ||
99 | } | ||
100 | |||
101 | static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, | ||
102 | unsigned long parent_rate) | ||
103 | { | ||
104 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | ||
105 | u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask; | ||
106 | |||
107 | return (div == 1) ? parent_rate * 22 : parent_rate * 20; | ||
108 | } | ||
109 | |||
110 | static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate, | ||
111 | unsigned long *prate) | ||
112 | { | ||
113 | unsigned long parent_rate = *prate; | ||
114 | |||
115 | return (rate >= parent_rate * 22) ? parent_rate * 22 : | ||
116 | parent_rate * 20; | ||
117 | } | ||
118 | |||
119 | static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate, | ||
120 | unsigned long parent_rate) | ||
121 | { | ||
122 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | ||
123 | u32 val, div; | ||
124 | |||
125 | if (rate == parent_rate * 22) | ||
126 | div = 1; | ||
127 | else if (rate == parent_rate * 20) | ||
128 | div = 0; | ||
129 | else | ||
130 | return -EINVAL; | ||
131 | |||
132 | val = readl_relaxed(pll->base); | ||
133 | val &= ~(pll->div_mask << pll->div_shift); | ||
134 | val |= (div << pll->div_shift); | ||
135 | writel_relaxed(val, pll->base); | ||
136 | |||
137 | return clk_pllv3_wait_lock(pll); | ||
138 | } | ||
139 | |||
140 | static const struct clk_ops clk_pllv3_ops = { | ||
141 | .prepare = clk_pllv3_prepare, | ||
142 | .unprepare = clk_pllv3_unprepare, | ||
143 | .recalc_rate = clk_pllv3_recalc_rate, | ||
144 | .round_rate = clk_pllv3_round_rate, | ||
145 | .set_rate = clk_pllv3_set_rate, | ||
146 | }; | ||
147 | |||
148 | static unsigned long clk_pllv3_sys_recalc_rate(struct clk_hw *hw, | ||
149 | unsigned long parent_rate) | ||
150 | { | ||
151 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | ||
152 | u32 div = readl_relaxed(pll->base) & pll->div_mask; | ||
153 | |||
154 | return parent_rate * div / 2; | ||
155 | } | ||
156 | |||
157 | static long clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long rate, | ||
158 | unsigned long *prate) | ||
159 | { | ||
160 | unsigned long parent_rate = *prate; | ||
161 | unsigned long min_rate = parent_rate * 54 / 2; | ||
162 | unsigned long max_rate = parent_rate * 108 / 2; | ||
163 | u32 div; | ||
164 | |||
165 | if (rate > max_rate) | ||
166 | rate = max_rate; | ||
167 | else if (rate < min_rate) | ||
168 | rate = min_rate; | ||
169 | div = rate * 2 / parent_rate; | ||
170 | |||
171 | return parent_rate * div / 2; | ||
172 | } | ||
173 | |||
174 | static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate, | ||
175 | unsigned long parent_rate) | ||
176 | { | ||
177 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | ||
178 | unsigned long min_rate = parent_rate * 54 / 2; | ||
179 | unsigned long max_rate = parent_rate * 108 / 2; | ||
180 | u32 val, div; | ||
181 | |||
182 | if (rate < min_rate || rate > max_rate) | ||
183 | return -EINVAL; | ||
184 | |||
185 | div = rate * 2 / parent_rate; | ||
186 | val = readl_relaxed(pll->base); | ||
187 | val &= ~pll->div_mask; | ||
188 | val |= div; | ||
189 | writel_relaxed(val, pll->base); | ||
190 | |||
191 | return clk_pllv3_wait_lock(pll); | ||
192 | } | ||
193 | |||
194 | static const struct clk_ops clk_pllv3_sys_ops = { | ||
195 | .prepare = clk_pllv3_prepare, | ||
196 | .unprepare = clk_pllv3_unprepare, | ||
197 | .recalc_rate = clk_pllv3_sys_recalc_rate, | ||
198 | .round_rate = clk_pllv3_sys_round_rate, | ||
199 | .set_rate = clk_pllv3_sys_set_rate, | ||
200 | }; | ||
201 | |||
202 | static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw, | ||
203 | unsigned long parent_rate) | ||
204 | { | ||
205 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | ||
206 | u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET); | ||
207 | u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET); | ||
208 | u32 div = readl_relaxed(pll->base) & pll->div_mask; | ||
209 | |||
210 | return (parent_rate * div) + ((parent_rate / mfd) * mfn); | ||
211 | } | ||
212 | |||
213 | static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, | ||
214 | unsigned long *prate) | ||
215 | { | ||
216 | unsigned long parent_rate = *prate; | ||
217 | unsigned long min_rate = parent_rate * 27; | ||
218 | unsigned long max_rate = parent_rate * 54; | ||
219 | u32 div; | ||
220 | u32 mfn, mfd = 1000000; | ||
221 | u64 temp64; | ||
222 | |||
223 | if (rate > max_rate) | ||
224 | rate = max_rate; | ||
225 | else if (rate < min_rate) | ||
226 | rate = min_rate; | ||
227 | |||
228 | div = rate / parent_rate; | ||
229 | temp64 = (u64) (rate - div * parent_rate); | ||
230 | temp64 *= mfd; | ||
231 | do_div(temp64, parent_rate); | ||
232 | mfn = temp64; | ||
233 | |||
234 | return parent_rate * div + parent_rate / mfd * mfn; | ||
235 | } | ||
236 | |||
237 | static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, | ||
238 | unsigned long parent_rate) | ||
239 | { | ||
240 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | ||
241 | unsigned long min_rate = parent_rate * 27; | ||
242 | unsigned long max_rate = parent_rate * 54; | ||
243 | u32 val, div; | ||
244 | u32 mfn, mfd = 1000000; | ||
245 | u64 temp64; | ||
246 | |||
247 | if (rate < min_rate || rate > max_rate) | ||
248 | return -EINVAL; | ||
249 | |||
250 | div = rate / parent_rate; | ||
251 | temp64 = (u64) (rate - div * parent_rate); | ||
252 | temp64 *= mfd; | ||
253 | do_div(temp64, parent_rate); | ||
254 | mfn = temp64; | ||
255 | |||
256 | val = readl_relaxed(pll->base); | ||
257 | val &= ~pll->div_mask; | ||
258 | val |= div; | ||
259 | writel_relaxed(val, pll->base); | ||
260 | writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); | ||
261 | writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); | ||
262 | |||
263 | return clk_pllv3_wait_lock(pll); | ||
264 | } | ||
265 | |||
266 | static const struct clk_ops clk_pllv3_av_ops = { | ||
267 | .prepare = clk_pllv3_prepare, | ||
268 | .unprepare = clk_pllv3_unprepare, | ||
269 | .recalc_rate = clk_pllv3_av_recalc_rate, | ||
270 | .round_rate = clk_pllv3_av_round_rate, | ||
271 | .set_rate = clk_pllv3_av_set_rate, | ||
272 | }; | ||
273 | |||
274 | static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw, | ||
275 | unsigned long parent_rate) | ||
276 | { | ||
277 | return 500000000; | ||
278 | } | ||
279 | |||
280 | static const struct clk_ops clk_pllv3_enet_ops = { | ||
281 | .prepare = clk_pllv3_prepare, | ||
282 | .unprepare = clk_pllv3_unprepare, | ||
283 | .recalc_rate = clk_pllv3_enet_recalc_rate, | ||
284 | }; | ||
285 | |||
286 | struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, | ||
287 | const char *parent_name, void __iomem *base, | ||
288 | u32 div_mask) | ||
289 | { | ||
290 | struct clk_pllv3 *pll; | ||
291 | const struct clk_ops *ops; | ||
292 | struct clk *clk; | ||
293 | struct clk_init_data init; | ||
294 | |||
295 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
296 | if (!pll) | ||
297 | return ERR_PTR(-ENOMEM); | ||
298 | |||
299 | pll->powerdown = BM_PLL_POWER; | ||
300 | |||
301 | switch (type) { | ||
302 | case IMX_PLLV3_SYS: | ||
303 | ops = &clk_pllv3_sys_ops; | ||
304 | break; | ||
305 | case IMX_PLLV3_USB_VF610: | ||
306 | pll->div_shift = 1; | ||
307 | case IMX_PLLV3_USB: | ||
308 | ops = &clk_pllv3_ops; | ||
309 | pll->powerup_set = true; | ||
310 | break; | ||
311 | case IMX_PLLV3_AV: | ||
312 | ops = &clk_pllv3_av_ops; | ||
313 | break; | ||
314 | case IMX_PLLV3_ENET_IMX7: | ||
315 | pll->powerdown = IMX7_ENET_PLL_POWER; | ||
316 | case IMX_PLLV3_ENET: | ||
317 | ops = &clk_pllv3_enet_ops; | ||
318 | break; | ||
319 | default: | ||
320 | ops = &clk_pllv3_ops; | ||
321 | } | ||
322 | pll->base = base; | ||
323 | pll->div_mask = div_mask; | ||
324 | |||
325 | init.name = name; | ||
326 | init.ops = ops; | ||
327 | init.flags = 0; | ||
328 | init.parent_names = &parent_name; | ||
329 | init.num_parents = 1; | ||
330 | |||
331 | pll->hw.init = &init; | ||
332 | |||
333 | clk = clk_register(NULL, &pll->hw); | ||
334 | if (IS_ERR(clk)) | ||
335 | kfree(pll); | ||
336 | |||
337 | return clk; | ||
338 | } | ||
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c new file mode 100644 index 000000000000..bff45ead7389 --- /dev/null +++ b/drivers/clk/imx/clk-vf610.c | |||
@@ -0,0 +1,416 @@ | |||
1 | /* | ||
2 | * Copyright 2012-2013 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/of_address.h> | ||
12 | #include <linux/clk.h> | ||
13 | #include <dt-bindings/clock/vf610-clock.h> | ||
14 | |||
15 | #include "clk.h" | ||
16 | |||
17 | #define CCM_CCR (ccm_base + 0x00) | ||
18 | #define CCM_CSR (ccm_base + 0x04) | ||
19 | #define CCM_CCSR (ccm_base + 0x08) | ||
20 | #define CCM_CACRR (ccm_base + 0x0c) | ||
21 | #define CCM_CSCMR1 (ccm_base + 0x10) | ||
22 | #define CCM_CSCDR1 (ccm_base + 0x14) | ||
23 | #define CCM_CSCDR2 (ccm_base + 0x18) | ||
24 | #define CCM_CSCDR3 (ccm_base + 0x1c) | ||
25 | #define CCM_CSCMR2 (ccm_base + 0x20) | ||
26 | #define CCM_CSCDR4 (ccm_base + 0x24) | ||
27 | #define CCM_CLPCR (ccm_base + 0x2c) | ||
28 | #define CCM_CISR (ccm_base + 0x30) | ||
29 | #define CCM_CIMR (ccm_base + 0x34) | ||
30 | #define CCM_CGPR (ccm_base + 0x3c) | ||
31 | #define CCM_CCGR0 (ccm_base + 0x40) | ||
32 | #define CCM_CCGR1 (ccm_base + 0x44) | ||
33 | #define CCM_CCGR2 (ccm_base + 0x48) | ||
34 | #define CCM_CCGR3 (ccm_base + 0x4c) | ||
35 | #define CCM_CCGR4 (ccm_base + 0x50) | ||
36 | #define CCM_CCGR5 (ccm_base + 0x54) | ||
37 | #define CCM_CCGR6 (ccm_base + 0x58) | ||
38 | #define CCM_CCGR7 (ccm_base + 0x5c) | ||
39 | #define CCM_CCGR8 (ccm_base + 0x60) | ||
40 | #define CCM_CCGR9 (ccm_base + 0x64) | ||
41 | #define CCM_CCGR10 (ccm_base + 0x68) | ||
42 | #define CCM_CCGR11 (ccm_base + 0x6c) | ||
43 | #define CCM_CMEOR0 (ccm_base + 0x70) | ||
44 | #define CCM_CMEOR1 (ccm_base + 0x74) | ||
45 | #define CCM_CMEOR2 (ccm_base + 0x78) | ||
46 | #define CCM_CMEOR3 (ccm_base + 0x7c) | ||
47 | #define CCM_CMEOR4 (ccm_base + 0x80) | ||
48 | #define CCM_CMEOR5 (ccm_base + 0x84) | ||
49 | #define CCM_CPPDSR (ccm_base + 0x88) | ||
50 | #define CCM_CCOWR (ccm_base + 0x8c) | ||
51 | #define CCM_CCPGR0 (ccm_base + 0x90) | ||
52 | #define CCM_CCPGR1 (ccm_base + 0x94) | ||
53 | #define CCM_CCPGR2 (ccm_base + 0x98) | ||
54 | #define CCM_CCPGR3 (ccm_base + 0x9c) | ||
55 | |||
56 | #define CCM_CCGRx_CGn(n) ((n) * 2) | ||
57 | |||
58 | #define PFD_PLL1_BASE (anatop_base + 0x2b0) | ||
59 | #define PFD_PLL2_BASE (anatop_base + 0x100) | ||
60 | #define PFD_PLL3_BASE (anatop_base + 0xf0) | ||
61 | #define PLL1_CTRL (anatop_base + 0x270) | ||
62 | #define PLL2_CTRL (anatop_base + 0x30) | ||
63 | #define PLL3_CTRL (anatop_base + 0x10) | ||
64 | #define PLL4_CTRL (anatop_base + 0x70) | ||
65 | #define PLL5_CTRL (anatop_base + 0xe0) | ||
66 | #define PLL6_CTRL (anatop_base + 0xa0) | ||
67 | #define PLL7_CTRL (anatop_base + 0x20) | ||
68 | #define ANA_MISC1 (anatop_base + 0x160) | ||
69 | |||
70 | static void __iomem *anatop_base; | ||
71 | static void __iomem *ccm_base; | ||
72 | |||
73 | /* sources for multiplexer clocks, this is used multiple times */ | ||
74 | static const char *fast_sels[] = { "firc", "fxosc", }; | ||
75 | static const char *slow_sels[] = { "sirc_32k", "sxosc", }; | ||
76 | static const char *pll1_sels[] = { "pll1_sys", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", }; | ||
77 | static const char *pll2_sels[] = { "pll2_bus", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", }; | ||
78 | static const char *pll_bypass_src_sels[] = { "fast_clk_sel", "lvds1_in", }; | ||
79 | static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", }; | ||
80 | static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", }; | ||
81 | static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", }; | ||
82 | static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", }; | ||
83 | static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", }; | ||
84 | static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; | ||
85 | static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; | ||
86 | static const char *sys_sels[] = { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_bus", "pll1_pfd_sel", "pll3_usb_otg", }; | ||
87 | static const char *ddr_sels[] = { "pll2_pfd2", "sys_sel", }; | ||
88 | static const char *rmii_sels[] = { "enet_ext", "audio_ext", "enet_50m", "enet_25m", }; | ||
89 | static const char *enet_ts_sels[] = { "enet_ext", "fxosc", "audio_ext", "usb", "enet_ts", "enet_25m", "enet_50m", }; | ||
90 | static const char *esai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_audio_div", }; | ||
91 | static const char *sai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_audio_div", }; | ||
92 | static const char *nfc_sels[] = { "platform_bus", "pll1_pfd1", "pll3_pfd1", "pll3_pfd3", }; | ||
93 | static const char *qspi_sels[] = { "pll3_usb_otg", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", }; | ||
94 | static const char *esdhc_sels[] = { "pll3_usb_otg", "pll3_pfd3", "pll1_pfd3", "platform_bus", }; | ||
95 | static const char *dcu_sels[] = { "pll1_pfd2", "pll3_usb_otg", }; | ||
96 | static const char *gpu_sels[] = { "pll2_pfd2", "pll3_pfd2", }; | ||
97 | static const char *vadc_sels[] = { "pll6_video_div", "pll3_usb_otg_div", "pll3_usb_otg", }; | ||
98 | /* FTM counter clock source, not module clock */ | ||
99 | static const char *ftm_ext_sels[] = {"sirc_128k", "sxosc", "fxosc_half", "audio_ext", }; | ||
100 | static const char *ftm_fix_sels[] = { "sxosc", "ipg_bus", }; | ||
101 | |||
102 | |||
103 | static struct clk_div_table pll4_audio_div_table[] = { | ||
104 | { .val = 0, .div = 1 }, | ||
105 | { .val = 1, .div = 2 }, | ||
106 | { .val = 2, .div = 6 }, | ||
107 | { .val = 3, .div = 8 }, | ||
108 | { .val = 4, .div = 10 }, | ||
109 | { .val = 5, .div = 12 }, | ||
110 | { .val = 6, .div = 14 }, | ||
111 | { .val = 7, .div = 16 }, | ||
112 | { } | ||
113 | }; | ||
114 | |||
115 | static struct clk *clk[VF610_CLK_END]; | ||
116 | static struct clk_onecell_data clk_data; | ||
117 | |||
118 | static unsigned int const clks_init_on[] __initconst = { | ||
119 | VF610_CLK_SYS_BUS, | ||
120 | VF610_CLK_DDR_SEL, | ||
121 | VF610_CLK_DAP, | ||
122 | }; | ||
123 | |||
124 | static struct clk * __init vf610_get_fixed_clock( | ||
125 | struct device_node *ccm_node, const char *name) | ||
126 | { | ||
127 | struct clk *clk = of_clk_get_by_name(ccm_node, name); | ||
128 | |||
129 | /* Backward compatibility if device tree is missing clks assignments */ | ||
130 | if (IS_ERR(clk)) | ||
131 | clk = imx_obtain_fixed_clock(name, 0); | ||
132 | return clk; | ||
133 | }; | ||
134 | |||
135 | static void __init vf610_clocks_init(struct device_node *ccm_node) | ||
136 | { | ||
137 | struct device_node *np; | ||
138 | int i; | ||
139 | |||
140 | clk[VF610_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | ||
141 | clk[VF610_CLK_SIRC_128K] = imx_clk_fixed("sirc_128k", 128000); | ||
142 | clk[VF610_CLK_SIRC_32K] = imx_clk_fixed("sirc_32k", 32000); | ||
143 | clk[VF610_CLK_FIRC] = imx_clk_fixed("firc", 24000000); | ||
144 | |||
145 | clk[VF610_CLK_SXOSC] = vf610_get_fixed_clock(ccm_node, "sxosc"); | ||
146 | clk[VF610_CLK_FXOSC] = vf610_get_fixed_clock(ccm_node, "fxosc"); | ||
147 | clk[VF610_CLK_AUDIO_EXT] = vf610_get_fixed_clock(ccm_node, "audio_ext"); | ||
148 | clk[VF610_CLK_ENET_EXT] = vf610_get_fixed_clock(ccm_node, "enet_ext"); | ||
149 | |||
150 | /* Clock source from external clock via LVDs PAD */ | ||
151 | clk[VF610_CLK_ANACLK1] = vf610_get_fixed_clock(ccm_node, "anaclk1"); | ||
152 | |||
153 | clk[VF610_CLK_FXOSC_HALF] = imx_clk_fixed_factor("fxosc_half", "fxosc", 1, 2); | ||
154 | |||
155 | np = of_find_compatible_node(NULL, NULL, "fsl,vf610-anatop"); | ||
156 | anatop_base = of_iomap(np, 0); | ||
157 | BUG_ON(!anatop_base); | ||
158 | |||
159 | np = ccm_node; | ||
160 | ccm_base = of_iomap(np, 0); | ||
161 | BUG_ON(!ccm_base); | ||
162 | |||
163 | clk[VF610_CLK_SLOW_CLK_SEL] = imx_clk_mux("slow_clk_sel", CCM_CCSR, 4, 1, slow_sels, ARRAY_SIZE(slow_sels)); | ||
164 | clk[VF610_CLK_FASK_CLK_SEL] = imx_clk_mux("fast_clk_sel", CCM_CCSR, 5, 1, fast_sels, ARRAY_SIZE(fast_sels)); | ||
165 | |||
166 | clk[VF610_CLK_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", PLL1_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
167 | clk[VF610_CLK_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", PLL2_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
168 | clk[VF610_CLK_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", PLL3_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
169 | clk[VF610_CLK_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", PLL4_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
170 | clk[VF610_CLK_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", PLL5_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
171 | clk[VF610_CLK_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", PLL6_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
172 | clk[VF610_CLK_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", PLL7_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); | ||
173 | |||
174 | clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1); | ||
175 | clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1); | ||
176 | clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2); | ||
177 | clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f); | ||
178 | clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3); | ||
179 | clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f); | ||
180 | clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2); | ||
181 | |||
182 | clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); | ||
183 | clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); | ||
184 | clk[VF610_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", PLL3_CTRL, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT); | ||
185 | clk[VF610_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", PLL4_CTRL, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT); | ||
186 | clk[VF610_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", PLL5_CTRL, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT); | ||
187 | clk[VF610_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", PLL6_CTRL, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT); | ||
188 | clk[VF610_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", PLL7_CTRL, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT); | ||
189 | |||
190 | /* Do not bypass PLLs initially */ | ||
191 | clk_set_parent(clk[VF610_PLL1_BYPASS], clk[VF610_CLK_PLL1]); | ||
192 | clk_set_parent(clk[VF610_PLL2_BYPASS], clk[VF610_CLK_PLL2]); | ||
193 | clk_set_parent(clk[VF610_PLL3_BYPASS], clk[VF610_CLK_PLL3]); | ||
194 | clk_set_parent(clk[VF610_PLL4_BYPASS], clk[VF610_CLK_PLL4]); | ||
195 | clk_set_parent(clk[VF610_PLL5_BYPASS], clk[VF610_CLK_PLL5]); | ||
196 | clk_set_parent(clk[VF610_PLL6_BYPASS], clk[VF610_CLK_PLL6]); | ||
197 | clk_set_parent(clk[VF610_PLL7_BYPASS], clk[VF610_CLK_PLL7]); | ||
198 | |||
199 | clk[VF610_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", PLL1_CTRL, 13); | ||
200 | clk[VF610_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", PLL2_CTRL, 13); | ||
201 | clk[VF610_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", PLL3_CTRL, 13); | ||
202 | clk[VF610_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", PLL4_CTRL, 13); | ||
203 | clk[VF610_CLK_PLL5_ENET] = imx_clk_gate("pll5_enet", "pll5_bypass", PLL5_CTRL, 13); | ||
204 | clk[VF610_CLK_PLL6_VIDEO] = imx_clk_gate("pll6_video", "pll6_bypass", PLL6_CTRL, 13); | ||
205 | clk[VF610_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", PLL7_CTRL, 13); | ||
206 | |||
207 | clk[VF610_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", "anaclk1", ANA_MISC1, 12, BIT(10)); | ||
208 | |||
209 | clk[VF610_CLK_PLL1_PFD1] = imx_clk_pfd("pll1_pfd1", "pll1_sys", PFD_PLL1_BASE, 0); | ||
210 | clk[VF610_CLK_PLL1_PFD2] = imx_clk_pfd("pll1_pfd2", "pll1_sys", PFD_PLL1_BASE, 1); | ||
211 | clk[VF610_CLK_PLL1_PFD3] = imx_clk_pfd("pll1_pfd3", "pll1_sys", PFD_PLL1_BASE, 2); | ||
212 | clk[VF610_CLK_PLL1_PFD4] = imx_clk_pfd("pll1_pfd4", "pll1_sys", PFD_PLL1_BASE, 3); | ||
213 | |||
214 | clk[VF610_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_bus", PFD_PLL2_BASE, 0); | ||
215 | clk[VF610_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_bus", PFD_PLL2_BASE, 1); | ||
216 | clk[VF610_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3", "pll2_bus", PFD_PLL2_BASE, 2); | ||
217 | clk[VF610_CLK_PLL2_PFD4] = imx_clk_pfd("pll2_pfd4", "pll2_bus", PFD_PLL2_BASE, 3); | ||
218 | |||
219 | clk[VF610_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_usb_otg", PFD_PLL3_BASE, 0); | ||
220 | clk[VF610_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", PFD_PLL3_BASE, 1); | ||
221 | clk[VF610_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", PFD_PLL3_BASE, 2); | ||
222 | clk[VF610_CLK_PLL3_PFD4] = imx_clk_pfd("pll3_pfd4", "pll3_usb_otg", PFD_PLL3_BASE, 3); | ||
223 | |||
224 | clk[VF610_CLK_PLL1_PFD_SEL] = imx_clk_mux("pll1_pfd_sel", CCM_CCSR, 16, 3, pll1_sels, 5); | ||
225 | clk[VF610_CLK_PLL2_PFD_SEL] = imx_clk_mux("pll2_pfd_sel", CCM_CCSR, 19, 3, pll2_sels, 5); | ||
226 | clk[VF610_CLK_SYS_SEL] = imx_clk_mux("sys_sel", CCM_CCSR, 0, 3, sys_sels, ARRAY_SIZE(sys_sels)); | ||
227 | clk[VF610_CLK_DDR_SEL] = imx_clk_mux("ddr_sel", CCM_CCSR, 6, 1, ddr_sels, ARRAY_SIZE(ddr_sels)); | ||
228 | clk[VF610_CLK_SYS_BUS] = imx_clk_divider("sys_bus", "sys_sel", CCM_CACRR, 0, 3); | ||
229 | clk[VF610_CLK_PLATFORM_BUS] = imx_clk_divider("platform_bus", "sys_bus", CCM_CACRR, 3, 3); | ||
230 | clk[VF610_CLK_IPG_BUS] = imx_clk_divider("ipg_bus", "platform_bus", CCM_CACRR, 11, 2); | ||
231 | |||
232 | clk[VF610_CLK_PLL3_MAIN_DIV] = imx_clk_divider("pll3_usb_otg_div", "pll3_usb_otg", CCM_CACRR, 20, 1); | ||
233 | clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, 0, pll4_audio_div_table, &imx_ccm_lock); | ||
234 | clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1); | ||
235 | |||
236 | clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6); | ||
237 | clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6); | ||
238 | |||
239 | clk[VF610_CLK_USBC0] = imx_clk_gate2("usbc0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(4)); | ||
240 | clk[VF610_CLK_USBC1] = imx_clk_gate2("usbc1", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(4)); | ||
241 | |||
242 | clk[VF610_CLK_QSPI0_SEL] = imx_clk_mux("qspi0_sel", CCM_CSCMR1, 22, 2, qspi_sels, 4); | ||
243 | clk[VF610_CLK_QSPI0_EN] = imx_clk_gate("qspi0_en", "qspi0_sel", CCM_CSCDR3, 4); | ||
244 | clk[VF610_CLK_QSPI0_X4_DIV] = imx_clk_divider("qspi0_x4", "qspi0_en", CCM_CSCDR3, 0, 2); | ||
245 | clk[VF610_CLK_QSPI0_X2_DIV] = imx_clk_divider("qspi0_x2", "qspi0_x4", CCM_CSCDR3, 2, 1); | ||
246 | clk[VF610_CLK_QSPI0_X1_DIV] = imx_clk_divider("qspi0_x1", "qspi0_x2", CCM_CSCDR3, 3, 1); | ||
247 | clk[VF610_CLK_QSPI0] = imx_clk_gate2("qspi0", "qspi0_x1", CCM_CCGR2, CCM_CCGRx_CGn(4)); | ||
248 | |||
249 | clk[VF610_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel", CCM_CSCMR1, 24, 2, qspi_sels, 4); | ||
250 | clk[VF610_CLK_QSPI1_EN] = imx_clk_gate("qspi1_en", "qspi1_sel", CCM_CSCDR3, 12); | ||
251 | clk[VF610_CLK_QSPI1_X4_DIV] = imx_clk_divider("qspi1_x4", "qspi1_en", CCM_CSCDR3, 8, 2); | ||
252 | clk[VF610_CLK_QSPI1_X2_DIV] = imx_clk_divider("qspi1_x2", "qspi1_x4", CCM_CSCDR3, 10, 1); | ||
253 | clk[VF610_CLK_QSPI1_X1_DIV] = imx_clk_divider("qspi1_x1", "qspi1_x2", CCM_CSCDR3, 11, 1); | ||
254 | clk[VF610_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_x1", CCM_CCGR8, CCM_CCGRx_CGn(4)); | ||
255 | |||
256 | clk[VF610_CLK_ENET_50M] = imx_clk_fixed_factor("enet_50m", "pll5_enet", 1, 10); | ||
257 | clk[VF610_CLK_ENET_25M] = imx_clk_fixed_factor("enet_25m", "pll5_enet", 1, 20); | ||
258 | clk[VF610_CLK_ENET_SEL] = imx_clk_mux("enet_sel", CCM_CSCMR2, 4, 2, rmii_sels, 4); | ||
259 | clk[VF610_CLK_ENET_TS_SEL] = imx_clk_mux("enet_ts_sel", CCM_CSCMR2, 0, 3, enet_ts_sels, 7); | ||
260 | clk[VF610_CLK_ENET] = imx_clk_gate("enet", "enet_sel", CCM_CSCDR1, 24); | ||
261 | clk[VF610_CLK_ENET_TS] = imx_clk_gate("enet_ts", "enet_ts_sel", CCM_CSCDR1, 23); | ||
262 | clk[VF610_CLK_ENET0] = imx_clk_gate2("enet0", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(0)); | ||
263 | clk[VF610_CLK_ENET1] = imx_clk_gate2("enet1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(1)); | ||
264 | |||
265 | clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(7)); | ||
266 | |||
267 | clk[VF610_CLK_UART0] = imx_clk_gate2("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7)); | ||
268 | clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8)); | ||
269 | clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9)); | ||
270 | clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10)); | ||
271 | clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9)); | ||
272 | clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10)); | ||
273 | |||
274 | clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6)); | ||
275 | clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7)); | ||
276 | clk[VF610_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(6)); | ||
277 | clk[VF610_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(7)); | ||
278 | |||
279 | clk[VF610_CLK_DSPI0] = imx_clk_gate2("dspi0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(12)); | ||
280 | clk[VF610_CLK_DSPI1] = imx_clk_gate2("dspi1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(13)); | ||
281 | clk[VF610_CLK_DSPI2] = imx_clk_gate2("dspi2", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(12)); | ||
282 | clk[VF610_CLK_DSPI3] = imx_clk_gate2("dspi3", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(13)); | ||
283 | |||
284 | clk[VF610_CLK_WDT] = imx_clk_gate2("wdt", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(14)); | ||
285 | |||
286 | clk[VF610_CLK_ESDHC0_SEL] = imx_clk_mux("esdhc0_sel", CCM_CSCMR1, 16, 2, esdhc_sels, 4); | ||
287 | clk[VF610_CLK_ESDHC0_EN] = imx_clk_gate("esdhc0_en", "esdhc0_sel", CCM_CSCDR2, 28); | ||
288 | clk[VF610_CLK_ESDHC0_DIV] = imx_clk_divider("esdhc0_div", "esdhc0_en", CCM_CSCDR2, 16, 4); | ||
289 | clk[VF610_CLK_ESDHC0] = imx_clk_gate2("eshc0", "esdhc0_div", CCM_CCGR7, CCM_CCGRx_CGn(1)); | ||
290 | |||
291 | clk[VF610_CLK_ESDHC1_SEL] = imx_clk_mux("esdhc1_sel", CCM_CSCMR1, 18, 2, esdhc_sels, 4); | ||
292 | clk[VF610_CLK_ESDHC1_EN] = imx_clk_gate("esdhc1_en", "esdhc1_sel", CCM_CSCDR2, 29); | ||
293 | clk[VF610_CLK_ESDHC1_DIV] = imx_clk_divider("esdhc1_div", "esdhc1_en", CCM_CSCDR2, 20, 4); | ||
294 | clk[VF610_CLK_ESDHC1] = imx_clk_gate2("eshc1", "esdhc1_div", CCM_CCGR7, CCM_CCGRx_CGn(2)); | ||
295 | |||
296 | /* | ||
297 | * ftm_ext_clk and ftm_fix_clk are FTM timer counter's | ||
298 | * selectable clock sources, both use a common enable bit | ||
299 | * in CCM_CSCDR1, selecting "dummy" clock as parent of | ||
300 | * "ftm0_ext_fix" make it serve only for enable/disable. | ||
301 | */ | ||
302 | clk[VF610_CLK_FTM0_EXT_SEL] = imx_clk_mux("ftm0_ext_sel", CCM_CSCMR2, 6, 2, ftm_ext_sels, 4); | ||
303 | clk[VF610_CLK_FTM0_FIX_SEL] = imx_clk_mux("ftm0_fix_sel", CCM_CSCMR2, 14, 1, ftm_fix_sels, 2); | ||
304 | clk[VF610_CLK_FTM0_EXT_FIX_EN] = imx_clk_gate("ftm0_ext_fix_en", "dummy", CCM_CSCDR1, 25); | ||
305 | clk[VF610_CLK_FTM1_EXT_SEL] = imx_clk_mux("ftm1_ext_sel", CCM_CSCMR2, 8, 2, ftm_ext_sels, 4); | ||
306 | clk[VF610_CLK_FTM1_FIX_SEL] = imx_clk_mux("ftm1_fix_sel", CCM_CSCMR2, 15, 1, ftm_fix_sels, 2); | ||
307 | clk[VF610_CLK_FTM1_EXT_FIX_EN] = imx_clk_gate("ftm1_ext_fix_en", "dummy", CCM_CSCDR1, 26); | ||
308 | clk[VF610_CLK_FTM2_EXT_SEL] = imx_clk_mux("ftm2_ext_sel", CCM_CSCMR2, 10, 2, ftm_ext_sels, 4); | ||
309 | clk[VF610_CLK_FTM2_FIX_SEL] = imx_clk_mux("ftm2_fix_sel", CCM_CSCMR2, 16, 1, ftm_fix_sels, 2); | ||
310 | clk[VF610_CLK_FTM2_EXT_FIX_EN] = imx_clk_gate("ftm2_ext_fix_en", "dummy", CCM_CSCDR1, 27); | ||
311 | clk[VF610_CLK_FTM3_EXT_SEL] = imx_clk_mux("ftm3_ext_sel", CCM_CSCMR2, 12, 2, ftm_ext_sels, 4); | ||
312 | clk[VF610_CLK_FTM3_FIX_SEL] = imx_clk_mux("ftm3_fix_sel", CCM_CSCMR2, 17, 1, ftm_fix_sels, 2); | ||
313 | clk[VF610_CLK_FTM3_EXT_FIX_EN] = imx_clk_gate("ftm3_ext_fix_en", "dummy", CCM_CSCDR1, 28); | ||
314 | |||
315 | /* ftm(n)_clk are FTM module operation clock */ | ||
316 | clk[VF610_CLK_FTM0] = imx_clk_gate2("ftm0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(8)); | ||
317 | clk[VF610_CLK_FTM1] = imx_clk_gate2("ftm1", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(9)); | ||
318 | clk[VF610_CLK_FTM2] = imx_clk_gate2("ftm2", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(8)); | ||
319 | clk[VF610_CLK_FTM3] = imx_clk_gate2("ftm3", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(9)); | ||
320 | |||
321 | clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2); | ||
322 | clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19); | ||
323 | clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3); | ||
324 | clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "dcu0_div", CCM_CCGR3, CCM_CCGRx_CGn(8)); | ||
325 | clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2); | ||
326 | clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23); | ||
327 | clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3); | ||
328 | clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8)); | ||
329 | |||
330 | clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4); | ||
331 | clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30); | ||
332 | clk[VF610_CLK_ESAI_DIV] = imx_clk_divider("esai_div", "esai_en", CCM_CSCDR2, 24, 4); | ||
333 | clk[VF610_CLK_ESAI] = imx_clk_gate2("esai", "esai_div", CCM_CCGR4, CCM_CCGRx_CGn(2)); | ||
334 | |||
335 | clk[VF610_CLK_SAI0_SEL] = imx_clk_mux("sai0_sel", CCM_CSCMR1, 0, 2, sai_sels, 4); | ||
336 | clk[VF610_CLK_SAI0_EN] = imx_clk_gate("sai0_en", "sai0_sel", CCM_CSCDR1, 16); | ||
337 | clk[VF610_CLK_SAI0_DIV] = imx_clk_divider("sai0_div", "sai0_en", CCM_CSCDR1, 0, 4); | ||
338 | clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "sai0_div", CCM_CCGR0, CCM_CCGRx_CGn(15)); | ||
339 | |||
340 | clk[VF610_CLK_SAI1_SEL] = imx_clk_mux("sai1_sel", CCM_CSCMR1, 2, 2, sai_sels, 4); | ||
341 | clk[VF610_CLK_SAI1_EN] = imx_clk_gate("sai1_en", "sai1_sel", CCM_CSCDR1, 17); | ||
342 | clk[VF610_CLK_SAI1_DIV] = imx_clk_divider("sai1_div", "sai1_en", CCM_CSCDR1, 4, 4); | ||
343 | clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "sai1_div", CCM_CCGR1, CCM_CCGRx_CGn(0)); | ||
344 | |||
345 | clk[VF610_CLK_SAI2_SEL] = imx_clk_mux("sai2_sel", CCM_CSCMR1, 4, 2, sai_sels, 4); | ||
346 | clk[VF610_CLK_SAI2_EN] = imx_clk_gate("sai2_en", "sai2_sel", CCM_CSCDR1, 18); | ||
347 | clk[VF610_CLK_SAI2_DIV] = imx_clk_divider("sai2_div", "sai2_en", CCM_CSCDR1, 8, 4); | ||
348 | clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "sai2_div", CCM_CCGR1, CCM_CCGRx_CGn(1)); | ||
349 | |||
350 | clk[VF610_CLK_SAI3_SEL] = imx_clk_mux("sai3_sel", CCM_CSCMR1, 6, 2, sai_sels, 4); | ||
351 | clk[VF610_CLK_SAI3_EN] = imx_clk_gate("sai3_en", "sai3_sel", CCM_CSCDR1, 19); | ||
352 | clk[VF610_CLK_SAI3_DIV] = imx_clk_divider("sai3_div", "sai3_en", CCM_CSCDR1, 12, 4); | ||
353 | clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "sai3_div", CCM_CCGR1, CCM_CCGRx_CGn(2)); | ||
354 | |||
355 | clk[VF610_CLK_NFC_SEL] = imx_clk_mux("nfc_sel", CCM_CSCMR1, 12, 2, nfc_sels, 4); | ||
356 | clk[VF610_CLK_NFC_EN] = imx_clk_gate("nfc_en", "nfc_sel", CCM_CSCDR2, 9); | ||
357 | clk[VF610_CLK_NFC_PRE_DIV] = imx_clk_divider("nfc_pre_div", "nfc_en", CCM_CSCDR3, 13, 3); | ||
358 | clk[VF610_CLK_NFC_FRAC_DIV] = imx_clk_divider("nfc_frac_div", "nfc_pre_div", CCM_CSCDR2, 4, 4); | ||
359 | clk[VF610_CLK_NFC] = imx_clk_gate2("nfc", "nfc_frac_div", CCM_CCGR10, CCM_CCGRx_CGn(0)); | ||
360 | |||
361 | clk[VF610_CLK_GPU_SEL] = imx_clk_mux("gpu_sel", CCM_CSCMR1, 14, 1, gpu_sels, 2); | ||
362 | clk[VF610_CLK_GPU_EN] = imx_clk_gate("gpu_en", "gpu_sel", CCM_CSCDR2, 10); | ||
363 | clk[VF610_CLK_GPU2D] = imx_clk_gate2("gpu", "gpu_en", CCM_CCGR8, CCM_CCGRx_CGn(15)); | ||
364 | |||
365 | clk[VF610_CLK_VADC_SEL] = imx_clk_mux("vadc_sel", CCM_CSCMR1, 8, 2, vadc_sels, 3); | ||
366 | clk[VF610_CLK_VADC_EN] = imx_clk_gate("vadc_en", "vadc_sel", CCM_CSCDR1, 22); | ||
367 | clk[VF610_CLK_VADC_DIV] = imx_clk_divider("vadc_div", "vadc_en", CCM_CSCDR1, 20, 2); | ||
368 | clk[VF610_CLK_VADC_DIV_HALF] = imx_clk_fixed_factor("vadc_div_half", "vadc_div", 1, 2); | ||
369 | clk[VF610_CLK_VADC] = imx_clk_gate2("vadc", "vadc_div", CCM_CCGR8, CCM_CCGRx_CGn(7)); | ||
370 | |||
371 | clk[VF610_CLK_ADC0] = imx_clk_gate2("adc0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(11)); | ||
372 | clk[VF610_CLK_ADC1] = imx_clk_gate2("adc1", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(11)); | ||
373 | clk[VF610_CLK_DAC0] = imx_clk_gate2("dac0", "ipg_bus", CCM_CCGR8, CCM_CCGRx_CGn(12)); | ||
374 | clk[VF610_CLK_DAC1] = imx_clk_gate2("dac1", "ipg_bus", CCM_CCGR8, CCM_CCGRx_CGn(13)); | ||
375 | |||
376 | clk[VF610_CLK_ASRC] = imx_clk_gate2("asrc", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(1)); | ||
377 | |||
378 | clk[VF610_CLK_FLEXCAN0_EN] = imx_clk_gate("flexcan0_en", "ipg_bus", CCM_CSCDR2, 11); | ||
379 | clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "flexcan0_en", CCM_CCGR0, CCM_CCGRx_CGn(0)); | ||
380 | clk[VF610_CLK_FLEXCAN1_EN] = imx_clk_gate("flexcan1_en", "ipg_bus", CCM_CSCDR2, 12); | ||
381 | clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "flexcan1_en", CCM_CCGR9, CCM_CCGRx_CGn(4)); | ||
382 | |||
383 | clk[VF610_CLK_DMAMUX0] = imx_clk_gate2("dmamux0", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(4)); | ||
384 | clk[VF610_CLK_DMAMUX1] = imx_clk_gate2("dmamux1", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(5)); | ||
385 | clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1)); | ||
386 | clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2)); | ||
387 | |||
388 | clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7)); | ||
389 | clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", CCM_CCSR, 24); | ||
390 | |||
391 | imx_check_clocks(clk, ARRAY_SIZE(clk)); | ||
392 | |||
393 | clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]); | ||
394 | clk_set_rate(clk[VF610_CLK_QSPI0_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_SEL]) / 2); | ||
395 | clk_set_rate(clk[VF610_CLK_QSPI0_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X4_DIV]) / 2); | ||
396 | clk_set_rate(clk[VF610_CLK_QSPI0_X1_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X2_DIV]) / 2); | ||
397 | |||
398 | clk_set_parent(clk[VF610_CLK_QSPI1_SEL], clk[VF610_CLK_PLL1_PFD4]); | ||
399 | clk_set_rate(clk[VF610_CLK_QSPI1_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_SEL]) / 2); | ||
400 | clk_set_rate(clk[VF610_CLK_QSPI1_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_X4_DIV]) / 2); | ||
401 | clk_set_rate(clk[VF610_CLK_QSPI1_X1_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_X2_DIV]) / 2); | ||
402 | |||
403 | clk_set_parent(clk[VF610_CLK_SAI0_SEL], clk[VF610_CLK_AUDIO_EXT]); | ||
404 | clk_set_parent(clk[VF610_CLK_SAI1_SEL], clk[VF610_CLK_AUDIO_EXT]); | ||
405 | clk_set_parent(clk[VF610_CLK_SAI2_SEL], clk[VF610_CLK_AUDIO_EXT]); | ||
406 | clk_set_parent(clk[VF610_CLK_SAI3_SEL], clk[VF610_CLK_AUDIO_EXT]); | ||
407 | |||
408 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | ||
409 | clk_prepare_enable(clk[clks_init_on[i]]); | ||
410 | |||
411 | /* Add the clocks to provider list */ | ||
412 | clk_data.clks = clk; | ||
413 | clk_data.clk_num = ARRAY_SIZE(clk); | ||
414 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
415 | } | ||
416 | CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init); | ||
diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c new file mode 100644 index 000000000000..df12b5307175 --- /dev/null +++ b/drivers/clk/imx/clk.c | |||
@@ -0,0 +1,75 @@ | |||
1 | #include <linux/clk.h> | ||
2 | #include <linux/err.h> | ||
3 | #include <linux/of.h> | ||
4 | #include <linux/slab.h> | ||
5 | #include <linux/spinlock.h> | ||
6 | #include "clk.h" | ||
7 | |||
8 | DEFINE_SPINLOCK(imx_ccm_lock); | ||
9 | |||
10 | void __init imx_check_clocks(struct clk *clks[], unsigned int count) | ||
11 | { | ||
12 | unsigned i; | ||
13 | |||
14 | for (i = 0; i < count; i++) | ||
15 | if (IS_ERR(clks[i])) | ||
16 | pr_err("i.MX clk %u: register failed with %ld\n", | ||
17 | i, PTR_ERR(clks[i])); | ||
18 | } | ||
19 | |||
20 | static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name) | ||
21 | { | ||
22 | struct of_phandle_args phandle; | ||
23 | struct clk *clk = ERR_PTR(-ENODEV); | ||
24 | char *path; | ||
25 | |||
26 | path = kasprintf(GFP_KERNEL, "/clocks/%s", name); | ||
27 | if (!path) | ||
28 | return ERR_PTR(-ENOMEM); | ||
29 | |||
30 | phandle.np = of_find_node_by_path(path); | ||
31 | kfree(path); | ||
32 | |||
33 | if (phandle.np) { | ||
34 | clk = of_clk_get_from_provider(&phandle); | ||
35 | of_node_put(phandle.np); | ||
36 | } | ||
37 | return clk; | ||
38 | } | ||
39 | |||
40 | struct clk * __init imx_obtain_fixed_clock( | ||
41 | const char *name, unsigned long rate) | ||
42 | { | ||
43 | struct clk *clk; | ||
44 | |||
45 | clk = imx_obtain_fixed_clock_from_dt(name); | ||
46 | if (IS_ERR(clk)) | ||
47 | clk = imx_clk_fixed(name, rate); | ||
48 | return clk; | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * This fixups the register CCM_CSCMR1 write value. | ||
53 | * The write/read/divider values of the aclk_podf field | ||
54 | * of that register have the relationship described by | ||
55 | * the following table: | ||
56 | * | ||
57 | * write value read value divider | ||
58 | * 3b'000 3b'110 7 | ||
59 | * 3b'001 3b'111 8 | ||
60 | * 3b'010 3b'100 5 | ||
61 | * 3b'011 3b'101 6 | ||
62 | * 3b'100 3b'010 3 | ||
63 | * 3b'101 3b'011 4 | ||
64 | * 3b'110 3b'000 1 | ||
65 | * 3b'111 3b'001 2(default) | ||
66 | * | ||
67 | * That's why we do the xor operation below. | ||
68 | */ | ||
69 | #define CSCMR1_FIXUP 0x00600000 | ||
70 | |||
71 | void imx_cscmr1_fixup(u32 *val) | ||
72 | { | ||
73 | *val ^= CSCMR1_FIXUP; | ||
74 | return; | ||
75 | } | ||
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h new file mode 100644 index 000000000000..1049b0c7d818 --- /dev/null +++ b/drivers/clk/imx/clk.h | |||
@@ -0,0 +1,149 @@ | |||
1 | #ifndef __MACH_IMX_CLK_H | ||
2 | #define __MACH_IMX_CLK_H | ||
3 | |||
4 | #include <linux/spinlock.h> | ||
5 | #include <linux/clk-provider.h> | ||
6 | |||
7 | extern spinlock_t imx_ccm_lock; | ||
8 | |||
9 | void imx_check_clocks(struct clk *clks[], unsigned int count); | ||
10 | |||
11 | extern void imx_cscmr1_fixup(u32 *val); | ||
12 | |||
13 | enum imx_pllv1_type { | ||
14 | IMX_PLLV1_IMX1, | ||
15 | IMX_PLLV1_IMX21, | ||
16 | IMX_PLLV1_IMX25, | ||
17 | IMX_PLLV1_IMX27, | ||
18 | IMX_PLLV1_IMX31, | ||
19 | IMX_PLLV1_IMX35, | ||
20 | }; | ||
21 | |||
22 | struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name, | ||
23 | const char *parent, void __iomem *base); | ||
24 | |||
25 | struct clk *imx_clk_pllv2(const char *name, const char *parent, | ||
26 | void __iomem *base); | ||
27 | |||
28 | enum imx_pllv3_type { | ||
29 | IMX_PLLV3_GENERIC, | ||
30 | IMX_PLLV3_SYS, | ||
31 | IMX_PLLV3_USB, | ||
32 | IMX_PLLV3_USB_VF610, | ||
33 | IMX_PLLV3_AV, | ||
34 | IMX_PLLV3_ENET, | ||
35 | IMX_PLLV3_ENET_IMX7, | ||
36 | }; | ||
37 | |||
38 | struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, | ||
39 | const char *parent_name, void __iomem *base, u32 div_mask); | ||
40 | |||
41 | struct clk *clk_register_gate2(struct device *dev, const char *name, | ||
42 | const char *parent_name, unsigned long flags, | ||
43 | void __iomem *reg, u8 bit_idx, | ||
44 | u8 clk_gate_flags, spinlock_t *lock, | ||
45 | unsigned int *share_count); | ||
46 | |||
47 | struct clk * imx_obtain_fixed_clock( | ||
48 | const char *name, unsigned long rate); | ||
49 | |||
50 | struct clk *imx_clk_gate_exclusive(const char *name, const char *parent, | ||
51 | void __iomem *reg, u8 shift, u32 exclusive_mask); | ||
52 | |||
53 | static inline struct clk *imx_clk_gate2(const char *name, const char *parent, | ||
54 | void __iomem *reg, u8 shift) | ||
55 | { | ||
56 | return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, | ||
57 | shift, 0, &imx_ccm_lock, NULL); | ||
58 | } | ||
59 | |||
60 | static inline struct clk *imx_clk_gate2_shared(const char *name, | ||
61 | const char *parent, void __iomem *reg, u8 shift, | ||
62 | unsigned int *share_count) | ||
63 | { | ||
64 | return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, | ||
65 | shift, 0, &imx_ccm_lock, share_count); | ||
66 | } | ||
67 | |||
68 | struct clk *imx_clk_pfd(const char *name, const char *parent_name, | ||
69 | void __iomem *reg, u8 idx); | ||
70 | |||
71 | struct clk *imx_clk_busy_divider(const char *name, const char *parent_name, | ||
72 | void __iomem *reg, u8 shift, u8 width, | ||
73 | void __iomem *busy_reg, u8 busy_shift); | ||
74 | |||
75 | struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift, | ||
76 | u8 width, void __iomem *busy_reg, u8 busy_shift, | ||
77 | const char **parent_names, int num_parents); | ||
78 | |||
79 | struct clk *imx_clk_fixup_divider(const char *name, const char *parent, | ||
80 | void __iomem *reg, u8 shift, u8 width, | ||
81 | void (*fixup)(u32 *val)); | ||
82 | |||
83 | struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg, | ||
84 | u8 shift, u8 width, const char **parents, | ||
85 | int num_parents, void (*fixup)(u32 *val)); | ||
86 | |||
87 | static inline struct clk *imx_clk_fixed(const char *name, int rate) | ||
88 | { | ||
89 | return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); | ||
90 | } | ||
91 | |||
92 | static inline struct clk *imx_clk_divider(const char *name, const char *parent, | ||
93 | void __iomem *reg, u8 shift, u8 width) | ||
94 | { | ||
95 | return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT, | ||
96 | reg, shift, width, 0, &imx_ccm_lock); | ||
97 | } | ||
98 | |||
99 | static inline struct clk *imx_clk_divider_flags(const char *name, | ||
100 | const char *parent, void __iomem *reg, u8 shift, u8 width, | ||
101 | unsigned long flags) | ||
102 | { | ||
103 | return clk_register_divider(NULL, name, parent, flags, | ||
104 | reg, shift, width, 0, &imx_ccm_lock); | ||
105 | } | ||
106 | |||
107 | static inline struct clk *imx_clk_gate(const char *name, const char *parent, | ||
108 | void __iomem *reg, u8 shift) | ||
109 | { | ||
110 | return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg, | ||
111 | shift, 0, &imx_ccm_lock); | ||
112 | } | ||
113 | |||
114 | static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent, | ||
115 | void __iomem *reg, u8 shift) | ||
116 | { | ||
117 | return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg, | ||
118 | shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock); | ||
119 | } | ||
120 | |||
121 | static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, | ||
122 | u8 shift, u8 width, const char **parents, int num_parents) | ||
123 | { | ||
124 | return clk_register_mux(NULL, name, parents, num_parents, | ||
125 | CLK_SET_RATE_NO_REPARENT, reg, shift, | ||
126 | width, 0, &imx_ccm_lock); | ||
127 | } | ||
128 | |||
129 | static inline struct clk *imx_clk_mux_flags(const char *name, | ||
130 | void __iomem *reg, u8 shift, u8 width, const char **parents, | ||
131 | int num_parents, unsigned long flags) | ||
132 | { | ||
133 | return clk_register_mux(NULL, name, parents, num_parents, | ||
134 | flags | CLK_SET_RATE_NO_REPARENT, reg, shift, width, 0, | ||
135 | &imx_ccm_lock); | ||
136 | } | ||
137 | |||
138 | static inline struct clk *imx_clk_fixed_factor(const char *name, | ||
139 | const char *parent, unsigned int mult, unsigned int div) | ||
140 | { | ||
141 | return clk_register_fixed_factor(NULL, name, parent, | ||
142 | CLK_SET_RATE_PARENT, mult, div); | ||
143 | } | ||
144 | |||
145 | struct clk *imx_clk_cpu(const char *name, const char *parent_name, | ||
146 | struct clk *div, struct clk *mux, struct clk *pll, | ||
147 | struct clk *step); | ||
148 | |||
149 | #endif | ||