static void *variable_rate_alpha_pll_dt_parser(struct device *dev, struct device_node *np) { struct alpha_pll_clk *pll; pll = alpha_pll_dt_parser(dev, np); if (IS_ERR(pll)) return pll; /* Optional Property */ of_property_read_u32(np, "qcom,output-enable", &pll->enable_config); pll->c.ops = &clk_ops_alpha_pll; return msmclk_generic_clk_init(dev, np, &pll->c); }
static void *ext_clk_dt_parser(struct device *dev, struct device_node *np) { struct ext_clk *ext; const char *str; int rc; ext = devm_kzalloc(dev, sizeof(*ext), GFP_KERNEL); if (!ext) { dev_err(dev, "memory allocation failure\n"); return ERR_PTR(-ENOMEM); } ext->dev = dev; rc = of_property_read_string(np, "qcom,clock-names", &str); if (!rc) ext->clk_id = (void *)str; ext->c.ops = &clk_ops_ext; return msmclk_generic_clk_init(dev, np, &ext->c); }
static void *fixed_rate_alpha_pll_dt_parser(struct device *dev, struct device_node *np) { struct alpha_pll_clk *pll; int rc; u32 val; pll = alpha_pll_dt_parser(dev, np); if (IS_ERR(pll)) return pll; rc = of_property_read_u32(np, "qcom,pll-config-rate", &val); if (rc) { dt_err(np, "missing qcom,pll-config-rate\n"); return ERR_PTR(-EINVAL); } pll->c.rate = val; rc = of_property_read_u32(np, "qcom,output-enable", &pll->enable_config); if (rc) { dt_err(np, "missing qcom,output-enable\n"); return ERR_PTR(-EINVAL); } /* Optional Property */ rc = of_property_read_u32(np, "qcom,fsm-en-bit", &val); if (!rc) { rc = of_property_read_u32(np, "qcom,fsm-en-offset", &pll->fsm_reg_offset); if (rc) { dt_err(np, "missing qcom,fsm-en-offset\n"); return ERR_PTR(-EINVAL); } pll->fsm_en_mask = BIT(val); } pll->c.ops = &clk_ops_fixed_alpha_pll; return msmclk_generic_clk_init(dev, np, &pll->c); }
static void *votable_pll_clk_dt_parser(struct device *dev, struct device_node *np) { struct pll_vote_clk *v, *peer; struct clk *c; u32 val, rc; phandle p; struct msmclk_data *drv; v = devm_kzalloc(dev, sizeof(*v), GFP_KERNEL); if (!v) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } drv = msmclk_parse_phandle(dev, np->parent->phandle); if (IS_ERR_OR_NULL(drv)) return ERR_CAST(drv); v->base = &drv->base; rc = of_property_read_u32(np, "qcom,en-offset", (u32 *)&v->en_reg); if (rc) { dt_err(np, "missing qcom,en-offset dt property\n"); return ERR_PTR(-EINVAL); } rc = of_property_read_u32(np, "qcom,en-bit", &val); if (rc) { dt_err(np, "missing qcom,en-bit dt property\n"); return ERR_PTR(-EINVAL); } v->en_mask = BIT(val); rc = of_property_read_u32(np, "qcom,status-offset", (u32 *)&v->status_reg); if (rc) { dt_err(np, "missing qcom,status-offset dt property\n"); return ERR_PTR(-EINVAL); } rc = of_property_read_u32(np, "qcom,status-bit", &val); if (rc) { dt_err(np, "missing qcom,status-bit dt property\n"); return ERR_PTR(-EINVAL); } v->status_mask = BIT(val); rc = of_property_read_u32(np, "qcom,pll-config-rate", &val); if (rc) { dt_err(np, "missing qcom,pll-config-rate dt property\n"); return ERR_PTR(-EINVAL); } v->c.rate = val; if (of_device_is_compatible(np, "qcom,active-only-pll")) v->soft_vote_mask = PLL_SOFT_VOTE_ACPU; else if (of_device_is_compatible(np, "qcom,sleep-active-pll")) v->soft_vote_mask = PLL_SOFT_VOTE_PRIMARY; if (of_device_is_compatible(np, "qcom,votable-pll")) { v->c.ops = &clk_ops_pll_vote; return msmclk_generic_clk_init(dev, np, &v->c); } rc = of_property_read_phandle_index(np, "qcom,peer", 0, &p); if (rc) { dt_err(np, "missing qcom,peer dt property\n"); return ERR_PTR(-EINVAL); } c = msmclk_lookup_phandle(dev, p); if (!IS_ERR_OR_NULL(c)) { v->soft_vote = devm_kzalloc(dev, sizeof(*v->soft_vote), GFP_KERNEL); if (!v->soft_vote) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } peer = to_pll_vote_clk(c); peer->soft_vote = v->soft_vote; } v->c.ops = &clk_ops_pll_acpu_vote; return msmclk_generic_clk_init(dev, np, &v->c); }
int enable_rpm_scaling(void) { int rc, value = 0x1; static int is_inited; struct msm_rpm_kvp kvp = { .key = RPM_SMD_KEY_ENABLE, .data = (void *)&value, .length = sizeof(value), }; if (is_inited) return 0; rc = msm_rpm_send_message_noirq(MSM_RPM_CTX_SLEEP_SET, RPM_MISC_CLK_TYPE, RPM_SCALING_ENABLE_ID, &kvp, 1); if (rc < 0) { if (rc != -EPROBE_DEFER) WARN(1, "RPM clock scaling (sleep set) did not enable!\n"); return rc; } rc = msm_rpm_send_message_noirq(MSM_RPM_CTX_ACTIVE_SET, RPM_MISC_CLK_TYPE, RPM_SCALING_ENABLE_ID, &kvp, 1); if (rc < 0) { if (rc != -EPROBE_DEFER) WARN(1, "RPM clock scaling (active set) did not enable!\n"); return rc; } is_inited++; return 0; } struct clk_ops clk_ops_rpm = { .prepare = rpm_clk_prepare, .unprepare = rpm_clk_unprepare, .set_rate = rpm_clk_set_rate, .get_rate = rpm_clk_get_rate, .is_enabled = rpm_clk_is_enabled, .round_rate = rpm_clk_round_rate, .is_local = rpm_clk_is_local, .handoff = rpm_clk_handoff, }; struct clk_ops clk_ops_rpm_branch = { .prepare = rpm_clk_prepare, .unprepare = rpm_clk_unprepare, .is_local = rpm_clk_is_local, .handoff = rpm_clk_handoff, }; static struct rpm_clk *rpm_clk_dt_parser_common(struct device *dev, struct device_node *np) { struct rpm_clk *rpm, *peer; struct clk *c; int rc = 0; phandle p; const char *str; rpm = devm_kzalloc(dev, sizeof(*rpm), GFP_KERNEL); if (!rpm) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } rc = of_property_read_phandle_index(np, "qcom,rpm-peer", 0, &p); if (rc) { dt_err(np, "missing qcom,rpm-peer dt property\n"); return ERR_PTR(rc); } /* Rely on whoever's called last to setup the circular ref */ c = msmclk_lookup_phandle(dev, p); if (!IS_ERR(c)) { peer = to_rpm_clk(c); peer->peer = rpm; rpm->peer = peer; } rpm->rpmrs_data = &clk_rpmrs_data_smd; rpm->active_only = of_device_is_compatible(np, "qcom,rpm-a-clk") || of_device_is_compatible(np, "qcom,rpm-branch-a-clk"); rc = of_property_read_string(np, "qcom,res-type", &str); if (rc) { dt_err(np, "missing qcom,res-type dt property\n"); return ERR_PTR(rc); } sscanf(str, "%4c", (char *) &rpm->rpm_res_type); rc = of_property_read_u32(np, "qcom,res-id", &rpm->rpm_clk_id); if (rc) { dt_err(np, "missing qcom,res-id dt property\n"); return ERR_PTR(rc); } rc = of_property_read_string(np, "qcom,key", &str); if (rc) { dt_err(np, "missing qcom,key dt property\n"); return ERR_PTR(rc); } sscanf(str, "%4c", (char *) &rpm->rpm_key); return rpm; } static void *rpm_clk_dt_parser(struct device *dev, struct device_node *np) { struct rpm_clk *rpm; rpm = rpm_clk_dt_parser_common(dev, np); if (IS_ERR(rpm)) return rpm; rpm->c.ops = &clk_ops_rpm; return msmclk_generic_clk_init(dev, np, &rpm->c); } static void *rpm_branch_clk_dt_parser(struct device *dev, struct device_node *np) { struct rpm_clk *rpm; u32 rate; int rc; rpm = rpm_clk_dt_parser_common(dev, np); if (IS_ERR(rpm)) return rpm; rpm->c.ops = &clk_ops_rpm_branch; rpm->branch = true; rc = of_property_read_u32(np, "qcom,rcg-init-rate", &rate); if (!rc) rpm->c.rate = rate; return msmclk_generic_clk_init(dev, np, &rpm->c); } MSMCLK_PARSER(rpm_clk_dt_parser, "qcom,rpm-clk", 0); MSMCLK_PARSER(rpm_clk_dt_parser, "qcom,rpm-a-clk", 1); MSMCLK_PARSER(rpm_branch_clk_dt_parser, "qcom,rpm-branch-clk", 0); MSMCLK_PARSER(rpm_branch_clk_dt_parser, "qcom,rpm-branch-a-clk", 1);