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