clk: msm: osm: model LMh RCG to ensure OSM clock runs at 200 MHz

The OSM clock is sourced from the LMh RCG. Model this RCG so
that it can be configured properly to provide the OSM a 200 MHz
clock source.

Change-Id: Ib799e8c082977ac226d6bd31ffad8ca63597c0fc
CRs-Fixed: 1007896
Signed-off-by: Osvaldo Banuelos <osvaldob@codeaurora.org>
This commit is contained in:
Osvaldo Banuelos 2016-04-25 11:03:50 -07:00 committed by Kyle Yan
parent 6374e0bf13
commit 5b613ab9a1
4 changed files with 70 additions and 5 deletions

View file

@ -14,13 +14,14 @@ Properties:
- reg
Usage: required
Value type: <prop-encoded-array>
Definition: Addresses and sizes for the memory of the OSM controller
and cluster PLL management.
Definition: Addresses and sizes for the memory of the OSM controller,
cluster PLL management, and APCS common register regions.
- reg-names
Usage: required
Value type: <stringlist>
Definition: Address names. Must be "osm", "pwrcl_pll", and "perfcl_pll."
Definition: Address names. Must be "osm", "pwrcl_pll", "perfcl_pll",
and "apcs_common".
Must be specified in the same order as the corresponding
addresses are specified in the reg property.
@ -284,8 +285,10 @@ Example:
compatible = "qcom,cpu-clock-osm";
reg = <0x179C0000 0x4000>,
<0x17916000 0x1000>,
<0x17816000 0x1000>;
reg-names = "osm", "pwrcl_pll", "perfcl_pll";
<0x17816000 0x1000>,
<0x179D1000 0x1000>;
reg-names = "osm", "pwrcl_pll", "perfcl_pll",
"apcs_common";
vdd-pwrcl-supply = <&apc0_pwrcl_vreg>;
vdd-perfcl-supply = <&apc1_perfcl_vreg>;

View file

@ -39,6 +39,7 @@
#include <soc/qcom/clock-local2.h>
#include <soc/qcom/clock-alpha-pll.h>
#include <dt-bindings/clock/msm-clocks-hwio-cobalt.h>
#include <dt-bindings/clock/msm-clocks-cobalt.h>
#include "clock.h"
@ -193,6 +194,23 @@ enum clk_osm_trace_packet_id {
#define PERIODIC_TRACE_MAX_US 20000000
#define PERIODIC_TRACE_DEFAULT_US 1000
static void __iomem *virt_base;
#define lmh_lite_clk_src_source_val 1
#define FIXDIV(div) (div ? (2 * (div) - 1) : (0))
#define F(f, s, div, m, n) \
{ \
.freq_hz = (f), \
.src_clk = &s.c, \
.m_val = (m), \
.n_val = ~((n)-(m)) * !!(n), \
.d_val = ~(n),\
.div_src_val = BVAL(4, 0, (int)FIXDIV(div)) \
| BVAL(10, 8, s##_source_val), \
}
static u32 seq_instr[] = {
0xc2005000, 0x2c9e3b21, 0xc0ab2cdc, 0xc2882525, 0x359dc491,
0x700a500b, 0x70005001, 0x390938c8, 0xcb44c833, 0xce56cd54,
@ -243,6 +261,7 @@ static u32 seq_br_instr[] = {
DEFINE_EXT_CLK(xo_ao, NULL);
DEFINE_EXT_CLK(sys_apcsaux_clk_gcc, NULL);
DEFINE_EXT_CLK(lmh_lite_clk_src, NULL);
struct osm_entry {
u16 virtual_corner;
@ -428,6 +447,24 @@ static struct clk_ops clk_ops_cpu_osm = {
static struct regulator *vdd_pwrcl;
static struct regulator *vdd_perfcl;
static struct clk_freq_tbl ftbl_osm_clk_src[] = {
F( 200000000, lmh_lite_clk_src, 1.5, 0, 0),
F_END
};
static struct rcg_clk osm_clk_src = {
.cmd_rcgr_reg = APCS_COMMON_LMH_CMD_RCGR,
.set_rate = set_rate_hid,
.freq_tbl = ftbl_osm_clk_src,
.current_freq = &rcg_dummy_freq,
.base = &virt_base,
.c = {
.dbg_name = "osm_clk_src",
.ops = &clk_ops_rcg,
CLK_INIT(osm_clk_src.c),
},
};
static struct clk_osm pwrcl_clk = {
.cluster_num = 0,
.cpu_reg_mask = 0x3,
@ -455,6 +492,7 @@ static struct clk_lookup cpu_clocks_osm[] = {
CLK_LIST(perfcl_clk),
CLK_LIST(sys_apcsaux_clk_gcc),
CLK_LIST(xo_ao),
CLK_LIST(osm_clk_src),
};
static void clk_osm_print_osm_table(struct clk_osm *c)
@ -813,6 +851,18 @@ static int clk_osm_resources_init(struct platform_device *pdev)
}
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apcs_common");
if (!res) {
dev_err(&pdev->dev, "Failed to get apcs common base\n");
return -EINVAL;
}
virt_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!virt_base) {
dev_err(&pdev->dev, "Failed to map apcs common registers\n");
return -ENOMEM;
}
vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl");
if (IS_ERR(vdd_pwrcl)) {
rc = PTR_ERR(vdd_pwrcl);
@ -2113,6 +2163,7 @@ exit:
}
static unsigned long init_rate = 300000000;
static unsigned long osm_clk_init_rate = 200000000;
static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
{
@ -2288,6 +2339,14 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
return rc;
}
rc = clk_set_rate(&osm_clk_src.c, osm_clk_init_rate);
if (rc) {
dev_err(&pdev->dev, "Unable to set init rate on osm_clk, rc=%d\n",
rc);
clk_disable_unprepare(&sys_apcsaux_clk_gcc.c);
return rc;
}
/* Enable OSM */
WARN(clk_prepare_enable(&pwrcl_clk.c),
"Failed to enable power cluster clock\n");

View file

@ -475,6 +475,7 @@
#define clk_perfcl_clk 0x58869997
#define clk_sys_apcsaux_clk_gcc 0xf905e862
#define clk_xo_ao 0x428c856d
#define clk_osm_clk_src 0xaabe68c3
/* Audio External Clocks */
#define clk_audio_ap_clk 0x9b5727cb

View file

@ -55,6 +55,8 @@
#define AGGR2_NOC_ID 0x2
#define MMSSNOC_AXI_CLK_ID 0x0
#define APCS_COMMON_LMH_CMD_RCGR 0x0012C
#define GCC_APCS_GPLL_ENA_VOTE 0x52000
#define GCC_APCS_CLOCK_BRANCH_ENA_VOTE 0x52004
#define GCC_APCS_CLOCK_BRANCH_ENA_VOTE_1 0x5200C