^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Lin Huang <hl@rock-chips.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/arm-smccc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/rockchip/rockchip_sip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <soc/rockchip/rockchip_sip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <soc/rockchip/scpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <uapi/drm/drm_mode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #ifdef CONFIG_ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/psci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MHZ (1000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct rockchip_ddrclk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) void __iomem *reg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int mux_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int mux_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int mux_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int div_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int div_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int ddr_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define to_rockchip_ddrclk_hw(hw) container_of(hw, struct rockchip_ddrclk, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct share_params_ddrclk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u32 lcdc_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct rockchip_ddrclk_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) void __iomem *params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int (*dmcfreq_wait_complete)(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static struct rockchip_ddrclk_data ddr_data = {NULL, NULL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) void rockchip_set_ddrclk_params(void __iomem *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ddr_data.params = params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) EXPORT_SYMBOL(rockchip_set_ddrclk_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) void rockchip_set_ddrclk_dmcfreq_wait_complete(int (*func)(void))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ddr_data.dmcfreq_wait_complete = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) EXPORT_SYMBOL(rockchip_set_ddrclk_dmcfreq_wait_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static int rockchip_ddrclk_sip_set_rate(struct clk_hw *hw, unsigned long drate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned long prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, drate, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 0, 0, 0, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (res.a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) rockchip_ddrclk_sip_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 0, 0, 0, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return res.a0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static long rockchip_ddrclk_sip_round_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned long *prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, rate, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) 0, 0, 0, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return res.a0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) val = readl(ddrclk->reg_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ddrclk->mux_offset) >> ddrclk->mux_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) val &= GENMASK(ddrclk->mux_width - 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static const struct clk_ops rockchip_ddrclk_sip_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .recalc_rate = rockchip_ddrclk_sip_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .set_rate = rockchip_ddrclk_sip_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .round_rate = rockchip_ddrclk_sip_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .get_parent = rockchip_ddrclk_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static u32 ddr_clk_cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int rockchip_ddrclk_scpi_set_rate(struct clk_hw *hw, unsigned long drate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) unsigned long prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u32 lcdc_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct share_params_ddrclk *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) p = (struct share_params_ddrclk *)ddr_data.params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) lcdc_type = p->lcdc_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ret = scpi_ddr_set_clk_rate(drate / MHZ, lcdc_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ddr_clk_cached = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ddr_clk_cached = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static unsigned long rockchip_ddrclk_scpi_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (ddr_clk_cached)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return (MHZ * ddr_clk_cached);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return (MHZ * scpi_ddr_get_clk_rate());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static long rockchip_ddrclk_scpi_round_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned long *prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) rate = rate / MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) rate = (rate / 12) * 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return (rate * MHZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static const struct clk_ops rockchip_ddrclk_scpi_ops __maybe_unused = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .recalc_rate = rockchip_ddrclk_scpi_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .set_rate = rockchip_ddrclk_scpi_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .round_rate = rockchip_ddrclk_scpi_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .get_parent = rockchip_ddrclk_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) unsigned long drate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned long prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct share_params_ddrclk *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) p = (struct share_params_ddrclk *)ddr_data.params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) p->hz = drate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) res = sip_smc_dram(SHARE_PAGE_TYPE_DDR, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if ((int)res.a1 == SIP_RET_SET_RATE_TIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (ddr_data.dmcfreq_wait_complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ddr_data.dmcfreq_wait_complete();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return res.a0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static unsigned long rockchip_ddrclk_sip_recalc_rate_v2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) (struct clk_hw *hw, unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) res = sip_smc_dram(SHARE_PAGE_TYPE_DDR, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (!res.a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return res.a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static long rockchip_ddrclk_sip_round_rate_v2(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) unsigned long *prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct share_params_ddrclk *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) p = (struct share_params_ddrclk *)ddr_data.params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) p->hz = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) res = sip_smc_dram(SHARE_PAGE_TYPE_DDR, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!res.a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return res.a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static const struct clk_ops rockchip_ddrclk_sip_ops_v2 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .recalc_rate = rockchip_ddrclk_sip_recalc_rate_v2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .set_rate = rockchip_ddrclk_sip_set_rate_v2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .round_rate = rockchip_ddrclk_sip_round_rate_v2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .get_parent = rockchip_ddrclk_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) const char *const *parent_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u8 num_parents, int mux_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int mux_shift, int mux_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int div_shift, int div_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int ddr_flag, void __iomem *reg_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct rockchip_ddrclk *ddrclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #ifdef CONFIG_ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (!psci_smp_available())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ddrclk = kzalloc(sizeof(*ddrclk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!ddrclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) init.parent_names = parent_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) init.num_parents = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) init.flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) init.flags |= CLK_SET_RATE_NO_REPARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) switch (ddr_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) #ifdef CONFIG_ROCKCHIP_DDRCLK_SIP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case ROCKCHIP_DDRCLK_SIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) init.ops = &rockchip_ddrclk_sip_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #ifdef CONFIG_ROCKCHIP_DDRCLK_SCPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case ROCKCHIP_DDRCLK_SCPI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) init.ops = &rockchip_ddrclk_scpi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #ifdef CONFIG_ROCKCHIP_DDRCLK_SIP_V2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) case ROCKCHIP_DDRCLK_SIP_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) init.ops = &rockchip_ddrclk_sip_ops_v2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) kfree(ddrclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ddrclk->reg_base = reg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ddrclk->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ddrclk->mux_offset = mux_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ddrclk->mux_shift = mux_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ddrclk->mux_width = mux_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ddrclk->div_shift = div_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ddrclk->div_width = div_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ddrclk->ddr_flag = ddr_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) clk = clk_register(NULL, &ddrclk->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) kfree(ddrclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) EXPORT_SYMBOL_GPL(rockchip_clk_register_ddrclk);