1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2018-2021 SiFive, Inc. 4 * Wesley Terpstra 5 * Paul Walmsley 6 * Zong Li 7 * Pragnesh Patel 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19#include <dt-bindings/clock/sifive-fu740-prci.h> 20#include "sifive-prci.h" 21#include <asm/io.h> 22 23int sifive_prci_fu740_pcieauxclk_enable(struct __prci_clock *pc, bool enable) 24{ 25 struct __prci_wrpll_data *pwd = pc->pwd; 26 struct __prci_data *pd = pc->pd; 27 u32 v; 28 29 if (pwd->cfg1_offs != PRCI_PCIEAUXCFG1_OFFSET) 30 return -EINVAL; 31 32 v = readl(pd->va + pwd->cfg1_offs); 33 v = enable ? (v | PRCI_PCIEAUXCFG1_MASK) : (v & ~PRCI_PCIEAUXCFG1_MASK); 34 writel(v, pd->va + pwd->cfg1_offs); 35 36 return 0; 37} 38 39/* PRCI integration data for each WRPLL instance */ 40static struct __prci_wrpll_data __prci_corepll_data = { 41 .cfg0_offs = PRCI_COREPLLCFG0_OFFSET, 42 .cfg1_offs = PRCI_COREPLLCFG1_OFFSET, 43 .enable_bypass = sifive_prci_coreclksel_use_hfclk, 44 .disable_bypass = sifive_prci_coreclksel_use_final_corepll, 45}; 46 47static struct __prci_wrpll_data __prci_ddrpll_data = { 48 .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET, 49 .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET, 50 .release_reset = sifive_prci_ddr_release_reset, 51}; 52 53static struct __prci_wrpll_data __prci_gemgxlpll_data = { 54 .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET, 55 .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET, 56 .release_reset = sifive_prci_ethernet_release_reset, 57}; 58 59static struct __prci_wrpll_data __prci_dvfscorepll_data = { 60 .cfg0_offs = PRCI_DVFSCOREPLLCFG0_OFFSET, 61 .cfg1_offs = PRCI_DVFSCOREPLLCFG1_OFFSET, 62 .enable_bypass = sifive_prci_corepllsel_use_corepll, 63 .disable_bypass = sifive_prci_corepllsel_use_dvfscorepll, 64}; 65 66static struct __prci_wrpll_data __prci_hfpclkpll_data = { 67 .cfg0_offs = PRCI_HFPCLKPLLCFG0_OFFSET, 68 .cfg1_offs = PRCI_HFPCLKPLLCFG1_OFFSET, 69 .enable_bypass = sifive_prci_hfpclkpllsel_use_hfclk, 70 .disable_bypass = sifive_prci_hfpclkpllsel_use_hfpclkpll, 71}; 72 73static struct __prci_wrpll_data __prci_cltxpll_data = { 74 .cfg0_offs = PRCI_CLTXPLLCFG0_OFFSET, 75 .cfg1_offs = PRCI_CLTXPLLCFG1_OFFSET, 76 .release_reset = sifive_prci_cltx_release_reset, 77}; 78 79static struct __prci_wrpll_data __prci_pcieaux_data = { 80 .cfg1_offs = PRCI_PCIEAUXCFG1_OFFSET, 81}; 82 83/* Linux clock framework integration */ 84 85static const struct __prci_clock_ops sifive_fu740_prci_wrpll_clk_ops = { 86 .set_rate = sifive_prci_wrpll_set_rate, 87 .round_rate = sifive_prci_wrpll_round_rate, 88 .recalc_rate = sifive_prci_wrpll_recalc_rate, 89 .enable_clk = sifive_prci_clock_enable, 90}; 91 92static const struct __prci_clock_ops sifive_fu740_prci_tlclksel_clk_ops = { 93 .recalc_rate = sifive_prci_tlclksel_recalc_rate, 94}; 95 96static const struct __prci_clock_ops sifive_fu740_prci_hfpclkplldiv_clk_ops = { 97 .recalc_rate = sifive_prci_hfpclkplldiv_recalc_rate, 98}; 99 100static const struct __prci_clock_ops sifive_fu740_prci_pcieaux_clk_ops = { 101 .enable_clk = sifive_prci_fu740_pcieauxclk_enable, 102}; 103 104/* List of clock controls provided by the PRCI */ 105struct __prci_clock __prci_init_clocks_fu740[] = { 106 [FU740_PRCI_CLK_COREPLL] = { 107 .name = "corepll", 108 .parent_name = "hfclk", 109 .ops = &sifive_fu740_prci_wrpll_clk_ops, 110 .pwd = &__prci_corepll_data, 111 }, 112 [FU740_PRCI_CLK_DDRPLL] = { 113 .name = "ddrpll", 114 .parent_name = "hfclk", 115 .ops = &sifive_fu740_prci_wrpll_clk_ops, 116 .pwd = &__prci_ddrpll_data, 117 }, 118 [FU740_PRCI_CLK_GEMGXLPLL] = { 119 .name = "gemgxlpll", 120 .parent_name = "hfclk", 121 .ops = &sifive_fu740_prci_wrpll_clk_ops, 122 .pwd = &__prci_gemgxlpll_data, 123 }, 124 [FU740_PRCI_CLK_DVFSCOREPLL] = { 125 .name = "dvfscorepll", 126 .parent_name = "hfclk", 127 .ops = &sifive_fu740_prci_wrpll_clk_ops, 128 .pwd = &__prci_dvfscorepll_data, 129 }, 130 [FU740_PRCI_CLK_HFPCLKPLL] = { 131 .name = "hfpclkpll", 132 .parent_name = "hfclk", 133 .ops = &sifive_fu740_prci_wrpll_clk_ops, 134 .pwd = &__prci_hfpclkpll_data, 135 }, 136 [FU740_PRCI_CLK_CLTXPLL] = { 137 .name = "cltxpll", 138 .parent_name = "hfclk", 139 .ops = &sifive_fu740_prci_wrpll_clk_ops, 140 .pwd = &__prci_cltxpll_data, 141 }, 142 [FU740_PRCI_CLK_TLCLK] = { 143 .name = "tlclk", 144 .parent_name = "corepll", 145 .ops = &sifive_fu740_prci_tlclksel_clk_ops, 146 }, 147 [FU740_PRCI_CLK_PCLK] = { 148 .name = "pclk", 149 .parent_name = "hfpclkpll", 150 .ops = &sifive_fu740_prci_hfpclkplldiv_clk_ops, 151 }, 152 [FU740_PRCI_CLK_PCIE_AUX] { 153 .name = "pcieaux", 154 .parent_name = "", 155 .ops = &sifive_fu740_prci_pcieaux_clk_ops, 156 .pwd = &__prci_pcieaux_data, 157 } 158}; 159