hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/clk/samsung/clk-exynos4.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
34 * Copyright (c) 2013 Linaro Ltd.
45 * Author: Thomas Abraham <thomas.ab@samsung.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 *
107 * Common Clock Framework support for all Exynos4 SoCs.
118 */
....@@ -14,9 +11,9 @@
1411 #include <linux/slab.h>
1512 #include <linux/clk.h>
1613 #include <linux/clk-provider.h>
14
+#include <linux/io.h>
1715 #include <linux/of.h>
1816 #include <linux/of_address.h>
19
-#include <linux/syscore_ops.h>
2017
2118 #include "clk.h"
2219 #include "clk-cpu.h"
....@@ -123,10 +120,6 @@
123120 #define CLKOUT_CMU_CPU 0x14a00
124121 #define PWR_CTRL1 0x15020
125122 #define E4X12_PWR_CTRL2 0x15024
126
-#define E4X12_DIV_ISP0 0x18300
127
-#define E4X12_DIV_ISP1 0x18304
128
-#define E4X12_GATE_ISP0 0x18800
129
-#define E4X12_GATE_ISP1 0x18804
130123
131124 /* Below definitions are used for PWR_CTRL settings */
132125 #define PWR_CTRL1_CORE2_DOWN_RATIO(x) (((x) & 0x7) << 28)
....@@ -158,14 +151,6 @@
158151 static enum exynos4_soc exynos4_soc;
159152
160153 /*
161
- * Support for CMU save/restore across system suspends
162
- */
163
-#ifdef CONFIG_PM_SLEEP
164
-static struct samsung_clk_reg_dump *exynos4_save_common;
165
-static struct samsung_clk_reg_dump *exynos4_save_soc;
166
-static struct samsung_clk_reg_dump *exynos4_save_pll;
167
-
168
-/*
169154 * list of controller registers to be saved and restored during a
170155 * suspend/resume cycle.
171156 */
....@@ -192,7 +177,7 @@
192177 E4X12_PWR_CTRL2,
193178 };
194179
195
-static const unsigned long exynos4_clk_pll_regs[] __initconst = {
180
+static const unsigned long exynos4_clk_regs[] __initconst = {
196181 EPLL_LOCK,
197182 VPLL_LOCK,
198183 EPLL_CON0,
....@@ -201,9 +186,6 @@
201186 VPLL_CON0,
202187 VPLL_CON1,
203188 VPLL_CON2,
204
-};
205
-
206
-static const unsigned long exynos4_clk_regs[] __initconst = {
207189 SRC_LEFTBUS,
208190 DIV_LEFTBUS,
209191 GATE_IP_LEFTBUS,
....@@ -276,6 +258,8 @@
276258 };
277259
278260 static const struct samsung_clk_reg_dump src_mask_suspend[] = {
261
+ { .offset = VPLL_CON0, .value = 0x80600302, },
262
+ { .offset = EPLL_CON0, .value = 0x806F0302, },
279263 { .offset = SRC_MASK_TOP, .value = 0x00000001, },
280264 { .offset = SRC_MASK_CAM, .value = 0x11111111, },
281265 { .offset = SRC_MASK_TV, .value = 0x00000111, },
....@@ -290,123 +274,6 @@
290274 static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = {
291275 { .offset = E4210_SRC_MASK_LCD1, .value = 0x00001111, },
292276 };
293
-
294
-#define PLL_ENABLED (1 << 31)
295
-#define PLL_LOCKED (1 << 29)
296
-
297
-static void exynos4_clk_enable_pll(u32 reg)
298
-{
299
- u32 pll_con = readl(reg_base + reg);
300
- pll_con |= PLL_ENABLED;
301
- writel(pll_con, reg_base + reg);
302
-
303
- while (!(pll_con & PLL_LOCKED)) {
304
- cpu_relax();
305
- pll_con = readl(reg_base + reg);
306
- }
307
-}
308
-
309
-static void exynos4_clk_wait_for_pll(u32 reg)
310
-{
311
- u32 pll_con;
312
-
313
- pll_con = readl(reg_base + reg);
314
- if (!(pll_con & PLL_ENABLED))
315
- return;
316
-
317
- while (!(pll_con & PLL_LOCKED)) {
318
- cpu_relax();
319
- pll_con = readl(reg_base + reg);
320
- }
321
-}
322
-
323
-static int exynos4_clk_suspend(void)
324
-{
325
- samsung_clk_save(reg_base, exynos4_save_common,
326
- ARRAY_SIZE(exynos4_clk_regs));
327
- samsung_clk_save(reg_base, exynos4_save_pll,
328
- ARRAY_SIZE(exynos4_clk_pll_regs));
329
-
330
- exynos4_clk_enable_pll(EPLL_CON0);
331
- exynos4_clk_enable_pll(VPLL_CON0);
332
-
333
- if (exynos4_soc == EXYNOS4210) {
334
- samsung_clk_save(reg_base, exynos4_save_soc,
335
- ARRAY_SIZE(exynos4210_clk_save));
336
- samsung_clk_restore(reg_base, src_mask_suspend_e4210,
337
- ARRAY_SIZE(src_mask_suspend_e4210));
338
- } else {
339
- samsung_clk_save(reg_base, exynos4_save_soc,
340
- ARRAY_SIZE(exynos4x12_clk_save));
341
- }
342
-
343
- samsung_clk_restore(reg_base, src_mask_suspend,
344
- ARRAY_SIZE(src_mask_suspend));
345
-
346
- return 0;
347
-}
348
-
349
-static void exynos4_clk_resume(void)
350
-{
351
- samsung_clk_restore(reg_base, exynos4_save_pll,
352
- ARRAY_SIZE(exynos4_clk_pll_regs));
353
-
354
- exynos4_clk_wait_for_pll(EPLL_CON0);
355
- exynos4_clk_wait_for_pll(VPLL_CON0);
356
-
357
- samsung_clk_restore(reg_base, exynos4_save_common,
358
- ARRAY_SIZE(exynos4_clk_regs));
359
-
360
- if (exynos4_soc == EXYNOS4210)
361
- samsung_clk_restore(reg_base, exynos4_save_soc,
362
- ARRAY_SIZE(exynos4210_clk_save));
363
- else
364
- samsung_clk_restore(reg_base, exynos4_save_soc,
365
- ARRAY_SIZE(exynos4x12_clk_save));
366
-}
367
-
368
-static struct syscore_ops exynos4_clk_syscore_ops = {
369
- .suspend = exynos4_clk_suspend,
370
- .resume = exynos4_clk_resume,
371
-};
372
-
373
-static void __init exynos4_clk_sleep_init(void)
374
-{
375
- exynos4_save_common = samsung_clk_alloc_reg_dump(exynos4_clk_regs,
376
- ARRAY_SIZE(exynos4_clk_regs));
377
- if (!exynos4_save_common)
378
- goto err_warn;
379
-
380
- if (exynos4_soc == EXYNOS4210)
381
- exynos4_save_soc = samsung_clk_alloc_reg_dump(
382
- exynos4210_clk_save,
383
- ARRAY_SIZE(exynos4210_clk_save));
384
- else
385
- exynos4_save_soc = samsung_clk_alloc_reg_dump(
386
- exynos4x12_clk_save,
387
- ARRAY_SIZE(exynos4x12_clk_save));
388
- if (!exynos4_save_soc)
389
- goto err_common;
390
-
391
- exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs,
392
- ARRAY_SIZE(exynos4_clk_pll_regs));
393
- if (!exynos4_save_pll)
394
- goto err_soc;
395
-
396
- register_syscore_ops(&exynos4_clk_syscore_ops);
397
- return;
398
-
399
-err_soc:
400
- kfree(exynos4_save_soc);
401
-err_common:
402
- kfree(exynos4_save_common);
403
-err_warn:
404
- pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
405
- __func__);
406
-}
407
-#else
408
-static void __init exynos4_clk_sleep_init(void) {}
409
-#endif
410277
411278 /* list of all parent clock list */
412279 PNAME(mout_apll_p) = { "fin_pll", "fout_apll", };
....@@ -841,18 +708,6 @@
841708 DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3),
842709 };
843710
844
-static struct samsung_div_clock exynos4x12_isp_div_clks[] = {
845
- DIV_F(CLK_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3,
846
- CLK_GET_RATE_NOCACHE, 0),
847
- DIV_F(CLK_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3,
848
- CLK_GET_RATE_NOCACHE, 0),
849
- DIV(0, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
850
- DIV_F(CLK_DIV_MCUISP0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1,
851
- 4, 3, CLK_GET_RATE_NOCACHE, 0),
852
- DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
853
- 8, 3, CLK_GET_RATE_NOCACHE, 0),
854
-};
855
-
856711 /* list of gate clocks supported in all exynos4 soc's */
857712 static const struct samsung_gate_clock exynos4_gate_clks[] __initconst = {
858713 GATE(CLK_PPMULEFT, "ppmuleft", "aclk200", GATE_IP_LEFTBUS, 1, 0, 0),
....@@ -1103,6 +958,7 @@
1103958
1104959 /* list of gate clocks supported in exynos4x12 soc */
1105960 static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = {
961
+ GATE(CLK_ASYNC_G3D, "async_g3d", "aclk200", GATE_IP_LEFTBUS, 6, 0, 0),
1106962 GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
1107963 GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
1108964 GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
....@@ -1148,61 +1004,6 @@
11481004 GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0),
11491005 GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0,
11501006 0),
1151
-};
1152
-
1153
-static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = {
1154
- GATE(CLK_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0,
1155
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1156
- GATE(CLK_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1,
1157
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1158
- GATE(CLK_FIMC_FD, "fd", "aclk200", E4X12_GATE_ISP0, 2,
1159
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1160
- GATE(CLK_FIMC_LITE0, "lite0", "aclk200", E4X12_GATE_ISP0, 3,
1161
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1162
- GATE(CLK_FIMC_LITE1, "lite1", "aclk200", E4X12_GATE_ISP0, 4,
1163
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1164
- GATE(CLK_MCUISP, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5,
1165
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1166
- GATE(CLK_GICISP, "gicisp", "aclk200", E4X12_GATE_ISP0, 7,
1167
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1168
- GATE(CLK_SMMU_ISP, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8,
1169
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1170
- GATE(CLK_SMMU_DRC, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9,
1171
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1172
- GATE(CLK_SMMU_FD, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10,
1173
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1174
- GATE(CLK_SMMU_LITE0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
1175
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1176
- GATE(CLK_SMMU_LITE1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
1177
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1178
- GATE(CLK_PPMUISPMX, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
1179
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1180
- GATE(CLK_PPMUISPX, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
1181
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1182
- GATE(CLK_MCUCTL_ISP, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
1183
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1184
- GATE(CLK_MPWM_ISP, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
1185
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1186
- GATE(CLK_I2C0_ISP, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
1187
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1188
- GATE(CLK_I2C1_ISP, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
1189
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1190
- GATE(CLK_MTCADC_ISP, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
1191
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1192
- GATE(CLK_PWM_ISP, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28,
1193
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1194
- GATE(CLK_WDT_ISP, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30,
1195
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1196
- GATE(CLK_UART_ISP, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
1197
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1198
- GATE(CLK_ASYNCAXIM, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
1199
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1200
- GATE(CLK_SMMU_ISPCX, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
1201
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1202
- GATE(CLK_SPI0_ISP, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
1203
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1204
- GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
1205
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
12061007 };
12071008
12081009 /*
....@@ -1432,6 +1233,8 @@
14321233 enum exynos4_soc soc)
14331234 {
14341235 struct samsung_clk_provider *ctx;
1236
+ struct clk_hw **hws;
1237
+
14351238 exynos4_soc = soc;
14361239
14371240 reg_base = of_iomap(np, 0);
....@@ -1439,6 +1242,7 @@
14391242 panic("%s: failed to map registers\n", __func__);
14401243
14411244 ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
1245
+ hws = ctx->clk_data.hws;
14421246
14431247 samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks,
14441248 ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
....@@ -1501,12 +1305,10 @@
15011305 exynos4210_fixed_factor_clks,
15021306 ARRAY_SIZE(exynos4210_fixed_factor_clks));
15031307 exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
1504
- mout_core_p4210[0], mout_core_p4210[1], 0x14200,
1308
+ hws[CLK_MOUT_APLL], hws[CLK_SCLK_MPLL], 0x14200,
15051309 e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d),
15061310 CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
15071311 } else {
1508
- struct resource res;
1509
-
15101312 samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
15111313 ARRAY_SIZE(exynos4x12_mux_clks));
15121314 samsung_clk_register_div(ctx, exynos4x12_div_clks,
....@@ -1517,23 +1319,25 @@
15171319 exynos4x12_fixed_factor_clks,
15181320 ARRAY_SIZE(exynos4x12_fixed_factor_clks));
15191321
1520
- of_address_to_resource(np, 0, &res);
1521
- if (resource_size(&res) > 0x18000) {
1522
- samsung_clk_register_div(ctx, exynos4x12_isp_div_clks,
1523
- ARRAY_SIZE(exynos4x12_isp_div_clks));
1524
- samsung_clk_register_gate(ctx, exynos4x12_isp_gate_clks,
1525
- ARRAY_SIZE(exynos4x12_isp_gate_clks));
1526
- }
1527
-
15281322 exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
1529
- mout_core_p4x12[0], mout_core_p4x12[1], 0x14200,
1323
+ hws[CLK_MOUT_APLL], hws[CLK_MOUT_MPLL_USER_C], 0x14200,
15301324 e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d),
15311325 CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
15321326 }
15331327
15341328 if (soc == EXYNOS4X12)
15351329 exynos4x12_core_down_clock();
1536
- exynos4_clk_sleep_init();
1330
+
1331
+ samsung_clk_extended_sleep_init(reg_base,
1332
+ exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
1333
+ src_mask_suspend, ARRAY_SIZE(src_mask_suspend));
1334
+ if (exynos4_soc == EXYNOS4210)
1335
+ samsung_clk_extended_sleep_init(reg_base,
1336
+ exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save),
1337
+ src_mask_suspend_e4210, ARRAY_SIZE(src_mask_suspend_e4210));
1338
+ else
1339
+ samsung_clk_sleep_init(reg_base, exynos4x12_clk_save,
1340
+ ARRAY_SIZE(exynos4x12_clk_save));
15371341
15381342 samsung_clk_of_add_provider(np, ctx);
15391343