^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.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/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define CLK_SEL_EXTERNAL_32K 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define CLK_SEL_INTERNAL_PVTM 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define wr_msk_bit(v, off, msk) ((v) << (off) | (msk << (16 + (off))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct rockchip_clock_pvtm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct rockchip_clock_pvtm_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) u32 con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u32 sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u32 sel_con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u32 sel_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) u32 sel_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u32 sel_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u32 div_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u32 div_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u32 (*get_value)(struct rockchip_clock_pvtm *pvtm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned int time_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int (*init_freq)(struct rockchip_clock_pvtm *pvtm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int (*sel_enable)(struct rockchip_clock_pvtm *pvtm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct rockchip_clock_pvtm {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) const struct rockchip_clock_pvtm_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct regmap *grf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct clk *pvtm_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static unsigned long xin32k_pvtm_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return 32768;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static const struct clk_ops xin32k_pvtm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .recalc_rate = xin32k_pvtm_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static void rockchip_clock_pvtm_delay(unsigned int delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int ms = delay / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int us = delay % 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (ms > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (ms < 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) us += ms * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) msleep(ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (us >= 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) usleep_range(us, us + 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) udelay(us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int rockchip_clock_sel_internal_pvtm(struct rockchip_clock_pvtm *pvtm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ret = regmap_write(pvtm->grf, pvtm->info->sel_con,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) wr_msk_bit(pvtm->info->sel_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pvtm->info->sel_shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pvtm->info->sel_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) pr_err("%s: fail to write register\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* get pmu pvtm value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static u32 rockchip_clock_pvtm_get_value(struct rockchip_clock_pvtm *pvtm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u32 time_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) const struct rockchip_clock_pvtm_info *info = pvtm->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u32 val = 0, sta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u32 clk_cnt, check_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* 24m clk ,24cnt=1us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) clk_cnt = time_us * 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) regmap_write(pvtm->grf, info->con + 0x4, clk_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) regmap_write(pvtm->grf, info->con, wr_msk_bit(3, 0, 0x3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) rockchip_clock_pvtm_delay(time_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) check_cnt = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) while (check_cnt--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) regmap_read(pvtm->grf, info->sta, &sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (sta & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) udelay(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (check_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) regmap_read(pvtm->grf, info->sta + 0x4, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pr_err("%s: wait pvtm_done timeout!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) regmap_write(pvtm->grf, info->con, wr_msk_bit(0, 0, 0x3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int rockchip_clock_pvtm_init_freq(struct rockchip_clock_pvtm *pvtm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u32 pvtm_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u32 div, time_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) time_us = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pvtm_cnt = pvtm->info->get_value(pvtm, time_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) pr_debug("get pvtm_cnt = %d\n", pvtm_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* set pvtm_div to get rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) div = DIV_ROUND_UP(1000 * pvtm_cnt, pvtm->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (div > pvtm->info->div_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pr_err("pvtm_div out of bounary! set max instead\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) div = pvtm->info->div_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pr_debug("set div %d, rate %luKHZ\n", div, pvtm->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ret = regmap_write(pvtm->grf, pvtm->info->con,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) wr_msk_bit(div, pvtm->info->div_shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) pvtm->info->div_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* pmu pvtm oscilator enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ret = regmap_write(pvtm->grf, pvtm->info->con,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) wr_msk_bit(1, 1, 0x1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ret = pvtm->info->sel_enable(pvtm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) pr_err("%s: fail to write register\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return ret;
^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 int clock_pvtm_regitstor(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct rockchip_clock_pvtm *pvtm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct clk_init_data init = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct clk_hw *clk_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* Init the xin32k_pvtm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) pvtm->info->init_freq(pvtm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) init.parent_names = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) init.num_parents = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) init.name = "xin32k_pvtm";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) init.ops = &xin32k_pvtm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) clk_hw = devm_kzalloc(dev, sizeof(*clk_hw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (!clk_hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) clk_hw->init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* optional override of the clockname */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) of_property_read_string_index(dev->of_node, "clock-output-names",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 0, &init.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) pvtm->clk = devm_clk_register(dev, clk_hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (IS_ERR(pvtm->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return PTR_ERR(pvtm->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) pvtm->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static const struct rockchip_clock_pvtm_info rk3368_pvtm_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .con = 0x180,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .sta = 0x190,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .sel_con = 0x100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .sel_shift = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .sel_value = CLK_SEL_INTERNAL_PVTM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .sel_mask = 0x1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .div_shift = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .div_mask = 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .sel_enable = rockchip_clock_sel_internal_pvtm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .get_value = rockchip_clock_pvtm_get_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .init_freq = rockchip_clock_pvtm_init_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static const struct of_device_id rockchip_clock_pvtm_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .compatible = "rockchip,rk3368-pvtm-clock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .data = (void *)&rk3368_pvtm_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) MODULE_DEVICE_TABLE(of, rockchip_clock_pvtm_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int rockchip_clock_pvtm_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct rockchip_clock_pvtm *pvtm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u32 rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) pvtm = devm_kzalloc(dev, sizeof(*pvtm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!pvtm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) match = of_match_node(rockchip_clock_pvtm_match, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (!match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) pvtm->info = (const struct rockchip_clock_pvtm_info *)match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (!pvtm->info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (!dev->parent || !dev->parent->of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) pvtm->grf = syscon_node_to_regmap(dev->parent->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (IS_ERR(pvtm->grf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return PTR_ERR(pvtm->grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!of_property_read_u32(np, "pvtm-rate", &rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) pvtm->rate = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) pvtm->rate = 32768;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) pvtm->pvtm_clk = devm_clk_get(&pdev->dev, "pvtm_pmu_clk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (IS_ERR(pvtm->pvtm_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) error = PTR_ERR(pvtm->pvtm_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (error != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) "failed to get pvtm core clock: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) goto out_probe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) error = clk_prepare_enable(pvtm->pvtm_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) dev_err(&pdev->dev, "failed to enable the clock: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) goto out_probe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) platform_set_drvdata(pdev, pvtm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) error = clock_pvtm_regitstor(&pdev->dev, pvtm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dev_err(&pdev->dev, "failed to registor clock: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) goto out_clk_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) out_clk_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) clk_disable_unprepare(pvtm->pvtm_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) out_probe:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int rockchip_clock_pvtm_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct rockchip_clock_pvtm *pvtm = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) of_clk_del_provider(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) clk_disable_unprepare(pvtm->pvtm_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static struct platform_driver rockchip_clock_pvtm_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .name = "rockchip-clcok-pvtm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .of_match_table = rockchip_clock_pvtm_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .probe = rockchip_clock_pvtm_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .remove = rockchip_clock_pvtm_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) module_platform_driver(rockchip_clock_pvtm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) MODULE_DESCRIPTION("Rockchip Clock Pvtm Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) MODULE_LICENSE("GPL v2");