From 7c9231090ed0768fb44c9bf3fd22bc9469f11e38 Mon Sep 17 00:00:00 2001 From: dkl Date: Fri, 30 Jan 2015 14:57:59 +0800 Subject: [PATCH] pvtm: rk3368: add pvtm_pmu clk support (output 32k) Support pvtm_pmu output 32k clk. By default, 32k use xin32k, and pvtm_pmu 32k clk is disabled. Signed-off-by: dkl --- arch/arm/mach-rockchip/pvtm.c | 118 ++++++++++++++++++++++--- arch/arm64/boot/dts/rk3368-clocks.dtsi | 9 +- arch/arm64/boot/dts/rk3368.dtsi | 4 +- 3 files changed, 117 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-rockchip/pvtm.c b/arch/arm/mach-rockchip/pvtm.c index d8aa8f77f223..e6c5ca2fe772 100644 --- a/arch/arm/mach-rockchip/pvtm.c +++ b/arch/arm/mach-rockchip/pvtm.c @@ -43,6 +43,11 @@ #define RK3368_PVTM_STATUS1 (0x810) #define RK3368_PVTM_STATUS2 (0x814) +#define RK3368_PMUPVTM_CON0 (0x180) +#define RK3368_PMUPVTM_CON1 (0x184) +#define RK3368_PMUPVTM_STATUS0 (0x190) +#define RK3368_PMUPVTM_STATUS1 (0x194) + #define grf_readl(offset) readl_relaxed(RK_GRF_VIRT+offset) #define grf_writel(val, offset) writel_relaxed(val, RK_GRF_VIRT+offset) @@ -56,22 +61,30 @@ struct rockchip_pvtm { static struct rockchip_pvtm pvtm; static struct regmap *grf_regmap; +static struct regmap *pmugrf_regmap; static DEFINE_MUTEX(pvtm_mutex); -/* 0 core, 1 gpu */ +/* 0 core, 1 gpu, 2 pmu */ static u32 rk3368_pvtm_get_value(u32 ch , u32 time_us) { u32 val = 0, clk_cnt, check_cnt, pvtm_done_bit; u32 sta = 0; - if (ch > 1) + if (ch > 2) return 0; /* 24m clk ,24cnt=1us */ clk_cnt = time_us*24; - regmap_write(grf_regmap, RK3368_PVTM_CON0+(ch+1)*4, clk_cnt); - regmap_write(grf_regmap, RK3368_PVTM_CON0, wr_msk_bit(3, ch*8, 0x3)); + if (ch == 2) { + regmap_write(pmugrf_regmap, RK3368_PMUPVTM_CON1, clk_cnt); + regmap_write(pmugrf_regmap, RK3368_PMUPVTM_CON0, + wr_msk_bit(3, 0, 0x3)); + } else { + regmap_write(grf_regmap, RK3368_PVTM_CON0+(ch+1)*4, clk_cnt); + regmap_write(grf_regmap, RK3368_PVTM_CON0, + wr_msk_bit(3, ch*8, 0x3)); + } if (time_us >= 1000) mdelay(time_us / 1000); @@ -83,18 +96,42 @@ static u32 rk3368_pvtm_get_value(u32 ch , u32 time_us) pvtm_done_bit = 1; check_cnt = 100; - while (!((regmap_read(grf_regmap, RK3368_PVTM_STATUS0, &sta) == 0) && - (sta & (1 << pvtm_done_bit)))) { - udelay(4); - check_cnt--; - if (!check_cnt) - break; + if (ch == 2) { + while (check_cnt--) { + regmap_read(pmugrf_regmap, RK3368_PMUPVTM_STATUS0, + &sta); + if (sta & 0x1) + break; + udelay(4); + } + + } else { + while (check_cnt--) { + regmap_read(grf_regmap, RK3368_PVTM_STATUS0, &sta); + if (sta & (1 << pvtm_done_bit)) + break; + udelay(4); + } } if (check_cnt) - regmap_read(grf_regmap, RK3368_PVTM_STATUS0+(ch+1)*4, &val); + if (ch == 2) + regmap_read(pmugrf_regmap, RK3368_PMUPVTM_STATUS1, + &val); + else + regmap_read(grf_regmap, RK3368_PVTM_STATUS0+(ch+1)*4, + &val); + else { + pr_err("%s: wait pvtm_done timeout!\n", __func__); + val = 0; + } - regmap_write(grf_regmap, RK3368_PVTM_CON0, wr_msk_bit(0, ch*8, 0x3)); + if (ch == 2) + regmap_write(pmugrf_regmap, RK3368_PMUPVTM_CON0, + wr_msk_bit(0, 0, 0x3)); + else + regmap_write(grf_regmap, RK3368_PVTM_CON0, + wr_msk_bit(0, ch*8, 0x3)); return val; } @@ -200,9 +237,48 @@ u32 pvtm_get_value(u32 ch, u32 time_us) return val; } +static int __init rk3368_pmupvtm_clk_init(void) +{ + u32 pvtm_cnt = 0, div, val, time_us; + unsigned long rate = 32;/* KHZ */ + int ret = 0; + + pr_info("%s\n", __func__); + + time_us = 1000; + pvtm_cnt = pvtm_get_value(2, time_us); + pr_debug("get pvtm_cnt = %d\n", pvtm_cnt); + + /* set pvtm_div to get rate */ + div = DIV_ROUND_UP(1000*pvtm_cnt, time_us*rate); + val = DIV_ROUND_UP(div-1, 4); + + if (val > 0x3f) { + pr_err("need pvtm_div out of bounary! set max instead\n"); + val = 0x3f; + } + + pr_debug("will set div %d, val %d, rate %luKHZ\n", div, val, rate); + ret = regmap_write(pmugrf_regmap, RK3368_PMUPVTM_CON0, + wr_msk_bit(val, 2, 0x3f)); + if (ret != 0) + goto out; + + /* pvtm oscilator enable */ + ret = regmap_write(pmugrf_regmap, RK3368_PMUPVTM_CON0, + wr_msk_bit(1, 1, 0x1)); +out: + if (ret != 0) + pr_err("%s: fail to write register\n", __func__); + + return ret; +} + static int __init pvtm_init(void) { struct device_node *np; + int ret; + u32 clk_out; np = of_find_node_by_name(NULL, "pvtm"); if (!IS_ERR_OR_NULL(np)) { @@ -212,11 +288,29 @@ static int __init pvtm_init(void) pr_err("pvtm: dts couldn't find grf regmap\n"); return PTR_ERR(grf_regmap); } + pmugrf_regmap = syscon_regmap_lookup_by_phandle(np, + "rockchip,pmugrf"); + if (IS_ERR(pmugrf_regmap)) { + pr_err("pvtm: dts couldn't find pmugrf regmap\n"); + return PTR_ERR(pmugrf_regmap); + } + if (of_device_is_compatible(np, "rockchip,rk3368-pvtm")) { ch_clk[0] = clk_get(NULL, "clk_pvtm_core"); ch_clk[1] = clk_get(NULL, "clk_pvtm_gpu"); + ch_clk[2] = clk_get(NULL, "clk_pvtm_pmu"); pvtm.get_value = rk3368_pvtm_get_value; + ret = of_property_read_u32(np, "rockchip,pvtm-clk-out", + &clk_out); + if (!ret && clk_out) { + ret = rk3368_pmupvtm_clk_init(); + if (ret != 0) { + pr_err("rk3368_pmupvtm_clk_init failed\n"); + return ret; + } + } } + return 0; } diff --git a/arch/arm64/boot/dts/rk3368-clocks.dtsi b/arch/arm64/boot/dts/rk3368-clocks.dtsi index 40103bbf8c58..0e8fc0a7b615 100644 --- a/arch/arm64/boot/dts/rk3368-clocks.dtsi +++ b/arch/arm64/boot/dts/rk3368-clocks.dtsi @@ -46,6 +46,13 @@ #clock-cells = <0>; }; + pvtm_clkout: pvtm_clkout { + compatible = "rockchip,rk-fixed-clock"; + clock-output-names = "pvtm_clkout"; + clock-frequency = <32000>; + #clock-cells = <0>; + }; + dummy: dummy { compatible = "rockchip,rk-fixed-clock"; clock-output-names = "dummy"; @@ -2717,7 +2724,7 @@ compatible = "rockchip,rk3188-mux-con"; reg = <0x0 0xff738100 0x0 0x4>; rockchip,bits = <6 1>; - clocks = <&xin32k>, <&clk_gates7 3>; + clocks = <&xin32k>, <&pvtm_clkout>; clock-output-names = "clk_32k_mux"; #clock-cells = <0>; #clock-init-cells = <1>; diff --git a/arch/arm64/boot/dts/rk3368.dtsi b/arch/arm64/boot/dts/rk3368.dtsi index c36f9c16461e..080b88737bd2 100755 --- a/arch/arm64/boot/dts/rk3368.dtsi +++ b/arch/arm64/boot/dts/rk3368.dtsi @@ -523,7 +523,7 @@ <&i2s_pll &clk_gpll>, <&spdif_8ch_pll &clk_gpll>, <&i2s_2ch_pll &clk_gpll>, <&usbphy_480m &usbotg_480m_out>, <&clk_uart_pll &clk_gpll>, <&aclk_gpu &clk_cpll>, - <&clk_cs &clk_gpll>; + <&clk_cs &clk_gpll>, <&clk_32k_mux &xin32k>; rockchip,clocks-init-rate = <&clk_gpll 576000000>, <&clk_core_b 792000000>, <&clk_core_l 600000000>, <&clk_cpll 400000000>, @@ -906,6 +906,8 @@ pvtm { compatible = "rockchip,rk3368-pvtm"; rockchip,grf = <&grf>; + rockchip,pmugrf = <&pmugrf>; + rockchip,pvtm-clk-out = <0>; }; cpufreq { -- 2.34.1