1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Toshiba Visconti PLL controller |
4 | * |
5 | * Copyright (c) 2021 TOSHIBA CORPORATION |
6 | * Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation |
7 | * |
8 | * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> |
9 | */ |
10 | |
11 | #include <linux/clk-provider.h> |
12 | #include <linux/of_address.h> |
13 | #include <linux/slab.h> |
14 | |
15 | #include <dt-bindings/clock/toshiba,tmpv770x.h> |
16 | |
17 | #include "pll.h" |
18 | |
19 | static DEFINE_SPINLOCK(tmpv770x_pll_lock); |
20 | |
21 | static const struct visconti_pll_rate_table pipll0_rates[] __initconst = { |
22 | VISCONTI_PLL_RATE(840000000, 0x1, 0x0, 0x1, 0x54, 0x000000, 0x2, 0x1), |
23 | VISCONTI_PLL_RATE(780000000, 0x1, 0x0, 0x1, 0x4e, 0x000000, 0x2, 0x1), |
24 | VISCONTI_PLL_RATE(600000000, 0x1, 0x0, 0x1, 0x3c, 0x000000, 0x2, 0x1), |
25 | { /* sentinel */ }, |
26 | }; |
27 | |
28 | static const struct visconti_pll_rate_table piddrcpll_rates[] __initconst = { |
29 | VISCONTI_PLL_RATE(780000000, 0x1, 0x0, 0x1, 0x4e, 0x000000, 0x2, 0x1), |
30 | VISCONTI_PLL_RATE(760000000, 0x1, 0x0, 0x1, 0x4c, 0x000000, 0x2, 0x1), |
31 | { /* sentinel */ }, |
32 | }; |
33 | |
34 | static const struct visconti_pll_rate_table pivoifpll_rates[] __initconst = { |
35 | VISCONTI_PLL_RATE(165000000, 0x1, 0x0, 0x1, 0x42, 0x000000, 0x4, 0x2), |
36 | VISCONTI_PLL_RATE(148500000, 0x1, 0x1, 0x1, 0x3b, 0x666666, 0x4, 0x2), |
37 | VISCONTI_PLL_RATE(96000000, 0x1, 0x0, 0x1, 0x30, 0x000000, 0x5, 0x2), |
38 | VISCONTI_PLL_RATE(74250000, 0x1, 0x1, 0x1, 0x3b, 0x666666, 0x4, 0x4), |
39 | VISCONTI_PLL_RATE(54000000, 0x1, 0x0, 0x1, 0x36, 0x000000, 0x5, 0x4), |
40 | VISCONTI_PLL_RATE(48000000, 0x1, 0x0, 0x1, 0x30, 0x000000, 0x5, 0x4), |
41 | VISCONTI_PLL_RATE(35750000, 0x1, 0x1, 0x1, 0x32, 0x0ccccc, 0x7, 0x4), |
42 | { /* sentinel */ }, |
43 | }; |
44 | |
45 | static const struct visconti_pll_rate_table piimgerpll_rates[] __initconst = { |
46 | VISCONTI_PLL_RATE(165000000, 0x1, 0x0, 0x1, 0x42, 0x000000, 0x4, 0x2), |
47 | VISCONTI_PLL_RATE(96000000, 0x1, 0x0, 0x1, 0x30, 0x000000, 0x5, 0x2), |
48 | VISCONTI_PLL_RATE(54000000, 0x1, 0x0, 0x1, 0x36, 0x000000, 0x5, 0x4), |
49 | VISCONTI_PLL_RATE(48000000, 0x1, 0x0, 0x1, 0x30, 0x000000, 0x5, 0x4), |
50 | { /* sentinel */ }, |
51 | }; |
52 | |
53 | static const struct visconti_pll_info pll_info[] __initconst = { |
54 | { TMPV770X_PLL_PIPLL0, "pipll0" , "osc2-clk" , 0x0, pipll0_rates }, |
55 | { TMPV770X_PLL_PIDDRCPLL, "piddrcpll" , "osc2-clk" , 0x500, piddrcpll_rates }, |
56 | { TMPV770X_PLL_PIVOIFPLL, "pivoifpll" , "osc2-clk" , 0x600, pivoifpll_rates }, |
57 | { TMPV770X_PLL_PIIMGERPLL, "piimgerpll" , "osc2-clk" , 0x700, piimgerpll_rates }, |
58 | }; |
59 | |
60 | static void __init tmpv770x_setup_plls(struct device_node *np) |
61 | { |
62 | struct visconti_pll_provider *ctx; |
63 | void __iomem *reg_base; |
64 | |
65 | reg_base = of_iomap(node: np, index: 0); |
66 | if (!reg_base) |
67 | return; |
68 | |
69 | ctx = visconti_init_pll(np, base: reg_base, TMPV770X_NR_PLL); |
70 | if (IS_ERR(ptr: ctx)) { |
71 | iounmap(addr: reg_base); |
72 | return; |
73 | } |
74 | |
75 | ctx->clk_data.hws[TMPV770X_PLL_PIPLL1] = |
76 | clk_hw_register_fixed_rate(NULL, "pipll1" , NULL, 0, 600000000); |
77 | ctx->clk_data.hws[TMPV770X_PLL_PIDNNPLL] = |
78 | clk_hw_register_fixed_rate(NULL, "pidnnpll" , NULL, 0, 500000000); |
79 | ctx->clk_data.hws[TMPV770X_PLL_PIETHERPLL] = |
80 | clk_hw_register_fixed_rate(NULL, "pietherpll" , NULL, 0, 500000000); |
81 | |
82 | visconti_register_plls(ctx, list: pll_info, ARRAY_SIZE(pll_info), lock: &tmpv770x_pll_lock); |
83 | } |
84 | |
85 | CLK_OF_DECLARE(tmpv770x_plls, "toshiba,tmpv7708-pipllct" , tmpv770x_setup_plls); |
86 | |