forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/drivers/clk/ingenic/jz4780-cgu.c
....@@ -1,71 +1,69 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Ingenic JZ4780 SoC CGU driver
34 *
45 * Copyright (c) 2013-2015 Imagination Technologies
56 * Author: Paul Burton <paul.burton@mips.com>
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License as
9
- * published by the Free Software Foundation; either version 2 of
10
- * the License, or (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
7
+ * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
168 */
179
1810 #include <linux/clk-provider.h>
1911 #include <linux/delay.h>
12
+#include <linux/io.h>
13
+#include <linux/iopoll.h>
2014 #include <linux/of.h>
15
+
2116 #include <dt-bindings/clock/jz4780-cgu.h>
17
+
2218 #include "cgu.h"
19
+#include "pm.h"
2320
2421 /* CGU register offsets */
2522 #define CGU_REG_CLOCKCONTROL 0x00
26
-#define CGU_REG_PLLCONTROL 0x0c
27
-#define CGU_REG_APLL 0x10
28
-#define CGU_REG_MPLL 0x14
29
-#define CGU_REG_EPLL 0x18
30
-#define CGU_REG_VPLL 0x1c
31
-#define CGU_REG_CLKGR0 0x20
32
-#define CGU_REG_OPCR 0x24
33
-#define CGU_REG_CLKGR1 0x28
34
-#define CGU_REG_DDRCDR 0x2c
35
-#define CGU_REG_VPUCDR 0x30
36
-#define CGU_REG_USBPCR 0x3c
37
-#define CGU_REG_USBRDT 0x40
38
-#define CGU_REG_USBVBFIL 0x44
39
-#define CGU_REG_USBPCR1 0x48
40
-#define CGU_REG_LP0CDR 0x54
41
-#define CGU_REG_I2SCDR 0x60
42
-#define CGU_REG_LP1CDR 0x64
43
-#define CGU_REG_MSC0CDR 0x68
44
-#define CGU_REG_UHCCDR 0x6c
45
-#define CGU_REG_SSICDR 0x74
46
-#define CGU_REG_CIMCDR 0x7c
47
-#define CGU_REG_PCMCDR 0x84
48
-#define CGU_REG_GPUCDR 0x88
49
-#define CGU_REG_HDMICDR 0x8c
50
-#define CGU_REG_MSC1CDR 0xa4
51
-#define CGU_REG_MSC2CDR 0xa8
52
-#define CGU_REG_BCHCDR 0xac
53
-#define CGU_REG_CLOCKSTATUS 0xd4
23
+#define CGU_REG_LCR 0x04
24
+#define CGU_REG_APLL 0x10
25
+#define CGU_REG_MPLL 0x14
26
+#define CGU_REG_EPLL 0x18
27
+#define CGU_REG_VPLL 0x1c
28
+#define CGU_REG_CLKGR0 0x20
29
+#define CGU_REG_OPCR 0x24
30
+#define CGU_REG_CLKGR1 0x28
31
+#define CGU_REG_DDRCDR 0x2c
32
+#define CGU_REG_VPUCDR 0x30
33
+#define CGU_REG_USBPCR 0x3c
34
+#define CGU_REG_USBRDT 0x40
35
+#define CGU_REG_USBVBFIL 0x44
36
+#define CGU_REG_USBPCR1 0x48
37
+#define CGU_REG_LP0CDR 0x54
38
+#define CGU_REG_I2SCDR 0x60
39
+#define CGU_REG_LP1CDR 0x64
40
+#define CGU_REG_MSC0CDR 0x68
41
+#define CGU_REG_UHCCDR 0x6c
42
+#define CGU_REG_SSICDR 0x74
43
+#define CGU_REG_CIMCDR 0x7c
44
+#define CGU_REG_PCMCDR 0x84
45
+#define CGU_REG_GPUCDR 0x88
46
+#define CGU_REG_HDMICDR 0x8c
47
+#define CGU_REG_MSC1CDR 0xa4
48
+#define CGU_REG_MSC2CDR 0xa8
49
+#define CGU_REG_BCHCDR 0xac
50
+#define CGU_REG_CLOCKSTATUS 0xd4
5451
5552 /* bits within the OPCR register */
56
-#define OPCR_SPENDN0 (1 << 7)
57
-#define OPCR_SPENDN1 (1 << 6)
53
+#define OPCR_SPENDN0 BIT(7)
54
+#define OPCR_SPENDN1 BIT(6)
5855
5956 /* bits within the USBPCR register */
60
-#define USBPCR_USB_MODE BIT(31)
57
+#define USBPCR_USB_MODE BIT(31)
6158 #define USBPCR_IDPULLUP_MASK (0x3 << 28)
62
-#define USBPCR_COMMONONN BIT(25)
63
-#define USBPCR_VBUSVLDEXT BIT(24)
59
+#define USBPCR_COMMONONN BIT(25)
60
+#define USBPCR_VBUSVLDEXT BIT(24)
6461 #define USBPCR_VBUSVLDEXTSEL BIT(23)
65
-#define USBPCR_POR BIT(22)
66
-#define USBPCR_OTG_DISABLE BIT(20)
62
+#define USBPCR_POR BIT(22)
63
+#define USBPCR_SIDDQ BIT(21)
64
+#define USBPCR_OTG_DISABLE BIT(20)
6765 #define USBPCR_COMPDISTUNE_MASK (0x7 << 17)
68
-#define USBPCR_OTGTUNE_MASK (0x7 << 14)
66
+#define USBPCR_OTGTUNE_MASK (0x7 << 14)
6967 #define USBPCR_SQRXTUNE_MASK (0x7 << 11)
7068 #define USBPCR_TXFSLSTUNE_MASK (0xf << 7)
7169 #define USBPCR_TXPREEMPHTUNE BIT(6)
....@@ -82,46 +80,27 @@
8280 #define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)
8381 #define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)
8482 #define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)
85
-#define USBPCR1_USB_SEL BIT(28)
86
-#define USBPCR1_WORD_IF0 BIT(19)
87
-#define USBPCR1_WORD_IF1 BIT(18)
83
+#define USBPCR1_USB_SEL BIT(28)
84
+#define USBPCR1_WORD_IF0 BIT(19)
85
+#define USBPCR1_WORD_IF1 BIT(18)
8886
8987 /* bits within the USBRDT register */
90
-#define USBRDT_VBFIL_LD_EN BIT(25)
91
-#define USBRDT_USBRDT_MASK 0x7fffff
88
+#define USBRDT_VBFIL_LD_EN BIT(25)
89
+#define USBRDT_USBRDT_MASK 0x7fffff
9290
9391 /* bits within the USBVBFIL register */
9492 #define USBVBFIL_IDDIGFIL_SHIFT 16
9593 #define USBVBFIL_IDDIGFIL_MASK (0xffff << USBVBFIL_IDDIGFIL_SHIFT)
9694 #define USBVBFIL_USBVBFIL_MASK (0xffff)
9795
96
+/* bits within the LCR register */
97
+#define LCR_PD_SCPU BIT(31)
98
+#define LCR_SCPUS BIT(27)
99
+
100
+/* bits within the CLKGR1 register */
101
+#define CLKGR1_CORE1 BIT(15)
102
+
98103 static struct ingenic_cgu *cgu;
99
-
100
-static u8 jz4780_otg_phy_get_parent(struct clk_hw *hw)
101
-{
102
- /* we only use CLKCORE, revisit if that ever changes */
103
- return 0;
104
-}
105
-
106
-static int jz4780_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
107
-{
108
- unsigned long flags;
109
- u32 usbpcr1;
110
-
111
- if (idx > 0)
112
- return -EINVAL;
113
-
114
- spin_lock_irqsave(&cgu->lock, flags);
115
-
116
- usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
117
- usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
118
- /* we only use CLKCORE */
119
- usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
120
- writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
121
-
122
- spin_unlock_irqrestore(&cgu->lock, flags);
123
- return 0;
124
-}
125104
126105 static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw,
127106 unsigned long parent_rate)
....@@ -146,7 +125,6 @@
146125 return 19200000;
147126 }
148127
149
- BUG();
150128 return parent_rate;
151129 }
152130
....@@ -203,13 +181,79 @@
203181 return 0;
204182 }
205183
206
-static const struct clk_ops jz4780_otg_phy_ops = {
207
- .get_parent = jz4780_otg_phy_get_parent,
208
- .set_parent = jz4780_otg_phy_set_parent,
184
+static int jz4780_otg_phy_enable(struct clk_hw *hw)
185
+{
186
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
187
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
209188
189
+ writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
190
+ writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
191
+ return 0;
192
+}
193
+
194
+static void jz4780_otg_phy_disable(struct clk_hw *hw)
195
+{
196
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
197
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
198
+
199
+ writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
200
+ writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
201
+}
202
+
203
+static int jz4780_otg_phy_is_enabled(struct clk_hw *hw)
204
+{
205
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
206
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
207
+
208
+ return (readl(reg_opcr) & OPCR_SPENDN0) &&
209
+ !(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
210
+ !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
211
+}
212
+
213
+static const struct clk_ops jz4780_otg_phy_ops = {
210214 .recalc_rate = jz4780_otg_phy_recalc_rate,
211215 .round_rate = jz4780_otg_phy_round_rate,
212216 .set_rate = jz4780_otg_phy_set_rate,
217
+
218
+ .enable = jz4780_otg_phy_enable,
219
+ .disable = jz4780_otg_phy_disable,
220
+ .is_enabled = jz4780_otg_phy_is_enabled,
221
+};
222
+
223
+static int jz4780_core1_enable(struct clk_hw *hw)
224
+{
225
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
226
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
227
+ const unsigned int timeout = 5000;
228
+ unsigned long flags;
229
+ int retval;
230
+ u32 lcr, clkgr1;
231
+
232
+ spin_lock_irqsave(&cgu->lock, flags);
233
+
234
+ lcr = readl(cgu->base + CGU_REG_LCR);
235
+ lcr &= ~LCR_PD_SCPU;
236
+ writel(lcr, cgu->base + CGU_REG_LCR);
237
+
238
+ clkgr1 = readl(cgu->base + CGU_REG_CLKGR1);
239
+ clkgr1 &= ~CLKGR1_CORE1;
240
+ writel(clkgr1, cgu->base + CGU_REG_CLKGR1);
241
+
242
+ spin_unlock_irqrestore(&cgu->lock, flags);
243
+
244
+ /* wait for the CPU to be powered up */
245
+ retval = readl_poll_timeout(cgu->base + CGU_REG_LCR, lcr,
246
+ !(lcr & LCR_SCPUS), 10, timeout);
247
+ if (retval == -ETIMEDOUT) {
248
+ pr_err("%s: Wait for power up core1 timeout\n", __func__);
249
+ return retval;
250
+ }
251
+
252
+ return 0;
253
+}
254
+
255
+static const struct clk_ops jz4780_core1_ops = {
256
+ .enable = jz4780_core1_enable,
213257 };
214258
215259 static const s8 pll_od_encoding[16] = {
....@@ -228,6 +272,7 @@
228272
229273 #define DEF_PLL(name) { \
230274 .reg = CGU_REG_ ## name, \
275
+ .rate_multiplier = 1, \
231276 .m_shift = 19, \
232277 .m_bits = 13, \
233278 .m_offset = 1, \
....@@ -239,6 +284,7 @@
239284 .od_max = 16, \
240285 .od_encoding = pll_od_encoding, \
241286 .stable_bit = 6, \
287
+ .bypass_reg = CGU_REG_ ## name, \
242288 .bypass_bit = 1, \
243289 .enable_bit = 0, \
244290 }
....@@ -475,6 +521,18 @@
475521 .gate = { CGU_REG_CLKGR0, 1 },
476522 },
477523
524
+ [JZ4780_CLK_EXCLK_DIV512] = {
525
+ "exclk_div512", CGU_CLK_FIXDIV,
526
+ .parents = { JZ4780_CLK_EXCLK },
527
+ .fixdiv = { 512 },
528
+ },
529
+
530
+ [JZ4780_CLK_RTC] = {
531
+ "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
532
+ .parents = { JZ4780_CLK_EXCLK_DIV512, JZ4780_CLK_RTCLK },
533
+ .mux = { CGU_REG_OPCR, 2, 1},
534
+ },
535
+
478536 /* Gate-only clocks */
479537
480538 [JZ4780_CLK_NEMC] = {
....@@ -706,9 +764,9 @@
706764 },
707765
708766 [JZ4780_CLK_CORE1] = {
709
- "core1", CGU_CLK_GATE,
767
+ "core1", CGU_CLK_CUSTOM,
710768 .parents = { JZ4780_CLK_CPU, -1, -1, -1 },
711
- .gate = { CGU_REG_CLKGR1, 15 },
769
+ .custom = { &jz4780_core1_ops },
712770 },
713771
714772 };
....@@ -729,5 +787,7 @@
729787 pr_err("%s: failed to register CGU Clocks\n", __func__);
730788 return;
731789 }
790
+
791
+ ingenic_cgu_register_syscore_ops(cgu);
732792 }
733
-CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
793
+CLK_OF_DECLARE_DRIVER(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);