1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Copyright (C) 2018-2021 SiFive, Inc. |
4 | * Copyright (C) 2018-2019 Wesley Terpstra |
5 | * Copyright (C) 2018-2019 Paul Walmsley |
6 | * Copyright (C) 2020-2021 Zong Li |
7 | * |
8 | * The FU540 PRCI implements clock and reset control for the SiFive |
9 | * FU540-C000 chip. This driver assumes that it has sole control |
10 | * over all PRCI resources. |
11 | * |
12 | * This driver is based on the PRCI driver written by Wesley Terpstra: |
13 | * https://github.com/riscv/riscv-linux/commit/999529edf517ed75b56659d456d221b2ee56bb60 |
14 | * |
15 | * References: |
16 | * - SiFive FU540-C000 manual v1p0, Chapter 7 "Clocking and Reset" |
17 | */ |
18 | |
19 | #ifndef __SIFIVE_CLK_FU540_PRCI_H |
20 | #define __SIFIVE_CLK_FU540_PRCI_H |
21 | |
22 | |
23 | #include <linux/module.h> |
24 | |
25 | #include <dt-bindings/clock/sifive-fu540-prci.h> |
26 | |
27 | #include "sifive-prci.h" |
28 | |
29 | /* PRCI integration data for each WRPLL instance */ |
30 | |
31 | static struct __prci_wrpll_data sifive_fu540_prci_corepll_data = { |
32 | .cfg0_offs = PRCI_COREPLLCFG0_OFFSET, |
33 | .cfg1_offs = PRCI_COREPLLCFG1_OFFSET, |
34 | .enable_bypass = sifive_prci_coreclksel_use_hfclk, |
35 | .disable_bypass = sifive_prci_coreclksel_use_corepll, |
36 | }; |
37 | |
38 | static struct __prci_wrpll_data sifive_fu540_prci_ddrpll_data = { |
39 | .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET, |
40 | .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET, |
41 | }; |
42 | |
43 | static struct __prci_wrpll_data sifive_fu540_prci_gemgxlpll_data = { |
44 | .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET, |
45 | .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET, |
46 | }; |
47 | |
48 | /* Linux clock framework integration */ |
49 | |
50 | static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = { |
51 | .set_rate = sifive_prci_wrpll_set_rate, |
52 | .round_rate = sifive_prci_wrpll_round_rate, |
53 | .recalc_rate = sifive_prci_wrpll_recalc_rate, |
54 | .enable = sifive_prci_clock_enable, |
55 | .disable = sifive_prci_clock_disable, |
56 | .is_enabled = sifive_clk_is_enabled, |
57 | }; |
58 | |
59 | static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = { |
60 | .recalc_rate = sifive_prci_wrpll_recalc_rate, |
61 | }; |
62 | |
63 | static const struct clk_ops sifive_fu540_prci_tlclksel_clk_ops = { |
64 | .recalc_rate = sifive_prci_tlclksel_recalc_rate, |
65 | }; |
66 | |
67 | /* List of clock controls provided by the PRCI */ |
68 | static struct __prci_clock __prci_init_clocks_fu540[] = { |
69 | [FU540_PRCI_CLK_COREPLL] = { |
70 | .name = "corepll" , |
71 | .parent_name = "hfclk" , |
72 | .ops = &sifive_fu540_prci_wrpll_clk_ops, |
73 | .pwd = &sifive_fu540_prci_corepll_data, |
74 | }, |
75 | [FU540_PRCI_CLK_DDRPLL] = { |
76 | .name = "ddrpll" , |
77 | .parent_name = "hfclk" , |
78 | .ops = &sifive_fu540_prci_wrpll_ro_clk_ops, |
79 | .pwd = &sifive_fu540_prci_ddrpll_data, |
80 | }, |
81 | [FU540_PRCI_CLK_GEMGXLPLL] = { |
82 | .name = "gemgxlpll" , |
83 | .parent_name = "hfclk" , |
84 | .ops = &sifive_fu540_prci_wrpll_clk_ops, |
85 | .pwd = &sifive_fu540_prci_gemgxlpll_data, |
86 | }, |
87 | [FU540_PRCI_CLK_TLCLK] = { |
88 | .name = "tlclk" , |
89 | .parent_name = "corepll" , |
90 | .ops = &sifive_fu540_prci_tlclksel_clk_ops, |
91 | }, |
92 | }; |
93 | |
94 | static const struct prci_clk_desc prci_clk_fu540 = { |
95 | .clks = __prci_init_clocks_fu540, |
96 | .num_clks = ARRAY_SIZE(__prci_init_clocks_fu540), |
97 | }; |
98 | |
99 | #endif /* __SIFIVE_CLK_FU540_PRCI_H */ |
100 | |