162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2018-2021 SiFive, Inc.
462306a36Sopenharmony_ci * Copyright (C) 2018-2019 Wesley Terpstra
562306a36Sopenharmony_ci * Copyright (C) 2018-2019 Paul Walmsley
662306a36Sopenharmony_ci * Copyright (C) 2020-2021 Zong Li
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * The FU540 PRCI implements clock and reset control for the SiFive
962306a36Sopenharmony_ci * FU540-C000 chip.  This driver assumes that it has sole control
1062306a36Sopenharmony_ci * over all PRCI resources.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * This driver is based on the PRCI driver written by Wesley Terpstra:
1362306a36Sopenharmony_ci * https://github.com/riscv/riscv-linux/commit/999529edf517ed75b56659d456d221b2ee56bb60
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * References:
1662306a36Sopenharmony_ci * - SiFive FU540-C000 manual v1p0, Chapter 7 "Clocking and Reset"
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#ifndef __SIFIVE_CLK_FU540_PRCI_H
2062306a36Sopenharmony_ci#define __SIFIVE_CLK_FU540_PRCI_H
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/module.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <dt-bindings/clock/sifive-fu540-prci.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "sifive-prci.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/* PRCI integration data for each WRPLL instance */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic struct __prci_wrpll_data sifive_fu540_prci_corepll_data = {
3262306a36Sopenharmony_ci	.cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
3362306a36Sopenharmony_ci	.cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
3462306a36Sopenharmony_ci	.enable_bypass = sifive_prci_coreclksel_use_hfclk,
3562306a36Sopenharmony_ci	.disable_bypass = sifive_prci_coreclksel_use_corepll,
3662306a36Sopenharmony_ci};
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic struct __prci_wrpll_data sifive_fu540_prci_ddrpll_data = {
3962306a36Sopenharmony_ci	.cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
4062306a36Sopenharmony_ci	.cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic struct __prci_wrpll_data sifive_fu540_prci_gemgxlpll_data = {
4462306a36Sopenharmony_ci	.cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
4562306a36Sopenharmony_ci	.cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/* Linux clock framework integration */
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
5162306a36Sopenharmony_ci	.set_rate = sifive_prci_wrpll_set_rate,
5262306a36Sopenharmony_ci	.round_rate = sifive_prci_wrpll_round_rate,
5362306a36Sopenharmony_ci	.recalc_rate = sifive_prci_wrpll_recalc_rate,
5462306a36Sopenharmony_ci	.enable = sifive_prci_clock_enable,
5562306a36Sopenharmony_ci	.disable = sifive_prci_clock_disable,
5662306a36Sopenharmony_ci	.is_enabled = sifive_clk_is_enabled,
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
6062306a36Sopenharmony_ci	.recalc_rate = sifive_prci_wrpll_recalc_rate,
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic const struct clk_ops sifive_fu540_prci_tlclksel_clk_ops = {
6462306a36Sopenharmony_ci	.recalc_rate = sifive_prci_tlclksel_recalc_rate,
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/* List of clock controls provided by the PRCI */
6862306a36Sopenharmony_cistatic struct __prci_clock __prci_init_clocks_fu540[] = {
6962306a36Sopenharmony_ci	[FU540_PRCI_CLK_COREPLL] = {
7062306a36Sopenharmony_ci		.name = "corepll",
7162306a36Sopenharmony_ci		.parent_name = "hfclk",
7262306a36Sopenharmony_ci		.ops = &sifive_fu540_prci_wrpll_clk_ops,
7362306a36Sopenharmony_ci		.pwd = &sifive_fu540_prci_corepll_data,
7462306a36Sopenharmony_ci	},
7562306a36Sopenharmony_ci	[FU540_PRCI_CLK_DDRPLL] = {
7662306a36Sopenharmony_ci		.name = "ddrpll",
7762306a36Sopenharmony_ci		.parent_name = "hfclk",
7862306a36Sopenharmony_ci		.ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
7962306a36Sopenharmony_ci		.pwd = &sifive_fu540_prci_ddrpll_data,
8062306a36Sopenharmony_ci	},
8162306a36Sopenharmony_ci	[FU540_PRCI_CLK_GEMGXLPLL] = {
8262306a36Sopenharmony_ci		.name = "gemgxlpll",
8362306a36Sopenharmony_ci		.parent_name = "hfclk",
8462306a36Sopenharmony_ci		.ops = &sifive_fu540_prci_wrpll_clk_ops,
8562306a36Sopenharmony_ci		.pwd = &sifive_fu540_prci_gemgxlpll_data,
8662306a36Sopenharmony_ci	},
8762306a36Sopenharmony_ci	[FU540_PRCI_CLK_TLCLK] = {
8862306a36Sopenharmony_ci		.name = "tlclk",
8962306a36Sopenharmony_ci		.parent_name = "corepll",
9062306a36Sopenharmony_ci		.ops = &sifive_fu540_prci_tlclksel_clk_ops,
9162306a36Sopenharmony_ci	},
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic const struct prci_clk_desc prci_clk_fu540 = {
9562306a36Sopenharmony_ci	.clks = __prci_init_clocks_fu540,
9662306a36Sopenharmony_ci	.num_clks = ARRAY_SIZE(__prci_init_clocks_fu540),
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci#endif /* __SIFIVE_CLK_FU540_PRCI_H */
100