2019-04-30 13:51:00 -07:00
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright ( C ) 2018 - 2019 SiFive , Inc .
2020-12-09 17:49:12 +08:00
* Copyright ( C ) 2018 - 2019 Wesley Terpstra
* Copyright ( C ) 2018 - 2019 Paul Walmsley
* Copyright ( C ) 2020 Zong Li
2019-04-30 13:51:00 -07:00
*
* The FU540 PRCI implements clock and reset control for the SiFive
* FU540 - C000 chip . This driver assumes that it has sole control
* over all PRCI resources .
*
* This driver is based on the PRCI driver written by Wesley Terpstra :
* https : //github.com/riscv/riscv-linux/commit/999529edf517ed75b56659d456d221b2ee56bb60
*
* References :
* - SiFive FU540 - C000 manual v1p0 , Chapter 7 " Clocking and Reset "
*/
# include <linux/module.h>
2020-12-09 17:49:12 +08:00
# include <dt-bindings/clock/sifive-fu540-prci.h>
2019-04-30 13:51:00 -07:00
2020-12-09 17:49:12 +08:00
# include "fu540-prci.h"
# include "sifive-prci.h"
2019-04-30 13:51:00 -07:00
2020-12-09 17:49:12 +08:00
/* PRCI integration data for each WRPLL instance */
2019-04-30 13:51:00 -07:00
2020-12-09 17:49:12 +08:00
static struct __prci_wrpll_data __prci_corepll_data = {
. cfg0_offs = PRCI_COREPLLCFG0_OFFSET ,
2020-12-09 17:49:16 +08:00
. cfg1_offs = PRCI_COREPLLCFG1_OFFSET ,
2020-12-09 17:49:12 +08:00
. enable_bypass = sifive_prci_coreclksel_use_hfclk ,
. disable_bypass = sifive_prci_coreclksel_use_corepll ,
2019-04-30 13:51:00 -07:00
} ;
2020-12-09 17:49:12 +08:00
static struct __prci_wrpll_data __prci_ddrpll_data = {
. cfg0_offs = PRCI_DDRPLLCFG0_OFFSET ,
2020-12-09 17:49:16 +08:00
. cfg1_offs = PRCI_DDRPLLCFG1_OFFSET ,
2019-04-30 13:51:00 -07:00
} ;
2020-12-09 17:49:12 +08:00
static struct __prci_wrpll_data __prci_gemgxlpll_data = {
. cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET ,
2020-12-09 17:49:16 +08:00
. cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET ,
2019-04-30 13:51:00 -07:00
} ;
2020-12-09 17:49:12 +08:00
/* Linux clock framework integration */
2019-04-30 13:51:00 -07:00
static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
2020-12-09 17:49:12 +08:00
. set_rate = sifive_prci_wrpll_set_rate ,
. round_rate = sifive_prci_wrpll_round_rate ,
. recalc_rate = sifive_prci_wrpll_recalc_rate ,
2020-12-09 17:49:16 +08:00
. enable = sifive_prci_clock_enable ,
. disable = sifive_prci_clock_disable ,
. is_enabled = sifive_clk_is_enabled ,
2019-04-30 13:51:00 -07:00
} ;
static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
2020-12-09 17:49:12 +08:00
. recalc_rate = sifive_prci_wrpll_recalc_rate ,
2019-04-30 13:51:00 -07:00
} ;
static const struct clk_ops sifive_fu540_prci_tlclksel_clk_ops = {
2020-12-09 17:49:12 +08:00
. recalc_rate = sifive_prci_tlclksel_recalc_rate ,
2019-04-30 13:51:00 -07:00
} ;
2020-12-09 17:49:12 +08:00
/* List of clock controls provided by the PRCI */
struct __prci_clock __prci_init_clocks_fu540 [ ] = {
2019-04-30 13:51:00 -07:00
[ PRCI_CLK_COREPLL ] = {
. name = " corepll " ,
. parent_name = " hfclk " ,
. ops = & sifive_fu540_prci_wrpll_clk_ops ,
. pwd = & __prci_corepll_data ,
} ,
[ PRCI_CLK_DDRPLL ] = {
. name = " ddrpll " ,
. parent_name = " hfclk " ,
. ops = & sifive_fu540_prci_wrpll_ro_clk_ops ,
. pwd = & __prci_ddrpll_data ,
} ,
[ PRCI_CLK_GEMGXLPLL ] = {
. name = " gemgxlpll " ,
. parent_name = " hfclk " ,
. ops = & sifive_fu540_prci_wrpll_clk_ops ,
. pwd = & __prci_gemgxlpll_data ,
} ,
[ PRCI_CLK_TLCLK ] = {
. name = " tlclk " ,
. parent_name = " corepll " ,
. ops = & sifive_fu540_prci_tlclksel_clk_ops ,
} ,
} ;