···11+Qualcomm RPM Clock Controller Binding22+------------------------------------------------33+The RPM is a dedicated hardware engine for managing the shared44+SoC resources in order to keep the lowest power profile. It55+communicates with other hardware subsystems via shared memory66+and accepts clock requests, aggregates the requests and turns77+the clocks on/off or scales them on demand.88+99+Required properties :1010+- compatible : shall contain only one of the following. The generic1111+ compatible "qcom,rpmcc" should be also included.1212+1313+ "qcom,rpmcc-msm8916", "qcom,rpmcc"1414+ "qcom,rpmcc-apq8064", "qcom,rpmcc"1515+1616+- #clock-cells : shall contain 11717+1818+Example:1919+ smd {2020+ compatible = "qcom,smd";2121+2222+ rpm {2323+ interrupts = <0 168 1>;2424+ qcom,ipc = <&apcs 8 0>;2525+ qcom,smd-edge = <15>;2626+2727+ rpm_requests {2828+ compatible = "qcom,rpm-msm8916";2929+ qcom,smd-channels = "rpm_requests";3030+3131+ rpmcc: clock-controller {3232+ compatible = "qcom,rpmcc-msm8916", "qcom,rpmcc";3333+ #clock-cells = <1>;3434+ };3535+ };3636+ };3737+ };
+29
drivers/clk/qcom/Kconfig
···22 bool33 select PM_GENERIC_DOMAINS if PM4455+config QCOM_RPMCC66+ bool77+58config COMMON_CLK_QCOM69 tristate "Support for Qualcomm's clock controllers"710 depends on OF811 depends on ARCH_QCOM || COMPILE_TEST912 select REGMAP_MMIO1013 select RESET_CONTROLLER1414+1515+config QCOM_CLK_RPM1616+ tristate "RPM based Clock Controller"1717+ depends on COMMON_CLK_QCOM && MFD_QCOM_RPM1818+ select QCOM_RPMCC1919+ help2020+ The RPM (Resource Power Manager) is a dedicated hardware engine for2121+ managing the shared SoC resources in order to keep the lowest power2222+ profile. It communicates with other hardware subsystems via shared2323+ memory and accepts clock requests, aggregates the requests and turns2424+ the clocks on/off or scales them on demand.2525+ Say Y if you want to support the clocks exposed by the RPM on2626+ platforms such as apq8064, msm8660, msm8960 etc.2727+2828+config QCOM_CLK_SMD_RPM2929+ tristate "RPM over SMD based Clock Controller"3030+ depends on COMMON_CLK_QCOM && QCOM_SMD_RPM3131+ select QCOM_RPMCC3232+ help3333+ The RPM (Resource Power Manager) is a dedicated hardware engine for3434+ managing the shared SoC resources in order to keep the lowest power3535+ profile. It communicates with other hardware subsystems via shared3636+ memory and accepts clock requests, aggregates the requests and turns3737+ the clocks on/off or scales them on demand.3838+ Say Y if you want to support the clocks exposed by the RPM on3939+ platforms such as apq8016, apq8084, msm8974 etc.11401241config APQ_GCC_80841342 tristate "APQ8084 Global Clock Controller"
···11+/*22+ * Copyright (c) 2016, Linaro Limited33+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.44+ *55+ * This software is licensed under the terms of the GNU General Public66+ * License version 2, as published by the Free Software Foundation, and77+ * may be copied, distributed, and modified under those terms.88+ *99+ * This program is distributed in the hope that it will be useful,1010+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1111+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212+ * GNU General Public License for more details.1313+ */1414+1515+#include <linux/clk-provider.h>1616+#include <linux/err.h>1717+#include <linux/export.h>1818+#include <linux/init.h>1919+#include <linux/kernel.h>2020+#include <linux/module.h>2121+#include <linux/mutex.h>2222+#include <linux/mfd/qcom_rpm.h>2323+#include <linux/of.h>2424+#include <linux/of_device.h>2525+#include <linux/platform_device.h>2626+2727+#include <dt-bindings/mfd/qcom-rpm.h>2828+#include <dt-bindings/clock/qcom,rpmcc.h>2929+3030+#define QCOM_RPM_MISC_CLK_TYPE 0x306b6c633131+#define QCOM_RPM_SCALING_ENABLE_ID 0x23232+3333+#define DEFINE_CLK_RPM(_platform, _name, _active, r_id) \3434+ static struct clk_rpm _platform##_##_active; \3535+ static struct clk_rpm _platform##_##_name = { \3636+ .rpm_clk_id = (r_id), \3737+ .peer = &_platform##_##_active, \3838+ .rate = INT_MAX, \3939+ .hw.init = &(struct clk_init_data){ \4040+ .ops = &clk_rpm_ops, \4141+ .name = #_name, \4242+ .parent_names = (const char *[]){ "pxo_board" }, \4343+ .num_parents = 1, \4444+ }, \4545+ }; \4646+ static struct clk_rpm _platform##_##_active = { \4747+ .rpm_clk_id = (r_id), \4848+ .peer = &_platform##_##_name, \4949+ .active_only = true, \5050+ .rate = INT_MAX, \5151+ .hw.init = &(struct clk_init_data){ \5252+ .ops = &clk_rpm_ops, \5353+ .name = #_active, \5454+ .parent_names = (const char *[]){ "pxo_board" }, \5555+ .num_parents = 1, \5656+ }, \5757+ }5858+5959+#define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r) \6060+ static struct clk_rpm _platform##_##_active; \6161+ static struct clk_rpm _platform##_##_name = { \6262+ .rpm_clk_id = (r_id), \6363+ .active_only = true, \6464+ .peer = &_platform##_##_active, \6565+ .rate = (r), \6666+ .branch = true, \6767+ .hw.init = &(struct clk_init_data){ \6868+ .ops = &clk_rpm_branch_ops, \6969+ .name = #_name, \7070+ .parent_names = (const char *[]){ "pxo_board" }, \7171+ .num_parents = 1, \7272+ }, \7373+ }; \7474+ static struct clk_rpm _platform##_##_active = { \7575+ .rpm_clk_id = (r_id), \7676+ .peer = &_platform##_##_name, \7777+ .rate = (r), \7878+ .branch = true, \7979+ .hw.init = &(struct clk_init_data){ \8080+ .ops = &clk_rpm_branch_ops, \8181+ .name = #_active, \8282+ .parent_names = (const char *[]){ "pxo_board" }, \8383+ .num_parents = 1, \8484+ }, \8585+ }8686+8787+#define DEFINE_CLK_RPM_CXO_BRANCH(_platform, _name, _active, r_id, r) \8888+ static struct clk_rpm _platform##_##_active; \8989+ static struct clk_rpm _platform##_##_name = { \9090+ .rpm_clk_id = (r_id), \9191+ .peer = &_platform##_##_active, \9292+ .rate = (r), \9393+ .branch = true, \9494+ .hw.init = &(struct clk_init_data){ \9595+ .ops = &clk_rpm_branch_ops, \9696+ .name = #_name, \9797+ .parent_names = (const char *[]){ "cxo_board" }, \9898+ .num_parents = 1, \9999+ }, \100100+ }; \101101+ static struct clk_rpm _platform##_##_active = { \102102+ .rpm_clk_id = (r_id), \103103+ .active_only = true, \104104+ .peer = &_platform##_##_name, \105105+ .rate = (r), \106106+ .branch = true, \107107+ .hw.init = &(struct clk_init_data){ \108108+ .ops = &clk_rpm_branch_ops, \109109+ .name = #_active, \110110+ .parent_names = (const char *[]){ "cxo_board" }, \111111+ .num_parents = 1, \112112+ }, \113113+ }114114+115115+#define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)116116+117117+struct clk_rpm {118118+ const int rpm_clk_id;119119+ const bool active_only;120120+ unsigned long rate;121121+ bool enabled;122122+ bool branch;123123+ struct clk_rpm *peer;124124+ struct clk_hw hw;125125+ struct qcom_rpm *rpm;126126+};127127+128128+struct rpm_cc {129129+ struct qcom_rpm *rpm;130130+ struct clk_hw_onecell_data data;131131+ struct clk_hw *hws[];132132+};133133+134134+struct rpm_clk_desc {135135+ struct clk_rpm **clks;136136+ size_t num_clks;137137+};138138+139139+static DEFINE_MUTEX(rpm_clk_lock);140140+141141+static int clk_rpm_handoff(struct clk_rpm *r)142142+{143143+ int ret;144144+ u32 value = INT_MAX;145145+146146+ ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,147147+ r->rpm_clk_id, &value, 1);148148+ if (ret)149149+ return ret;150150+ ret = qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE,151151+ r->rpm_clk_id, &value, 1);152152+ if (ret)153153+ return ret;154154+155155+ return 0;156156+}157157+158158+static int clk_rpm_set_rate_active(struct clk_rpm *r, unsigned long rate)159159+{160160+ u32 value = DIV_ROUND_UP(rate, 1000); /* to kHz */161161+162162+ return qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,163163+ r->rpm_clk_id, &value, 1);164164+}165165+166166+static int clk_rpm_set_rate_sleep(struct clk_rpm *r, unsigned long rate)167167+{168168+ u32 value = DIV_ROUND_UP(rate, 1000); /* to kHz */169169+170170+ return qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE,171171+ r->rpm_clk_id, &value, 1);172172+}173173+174174+static void to_active_sleep(struct clk_rpm *r, unsigned long rate,175175+ unsigned long *active, unsigned long *sleep)176176+{177177+ *active = rate;178178+179179+ /*180180+ * Active-only clocks don't care what the rate is during sleep. So,181181+ * they vote for zero.182182+ */183183+ if (r->active_only)184184+ *sleep = 0;185185+ else186186+ *sleep = *active;187187+}188188+189189+static int clk_rpm_prepare(struct clk_hw *hw)190190+{191191+ struct clk_rpm *r = to_clk_rpm(hw);192192+ struct clk_rpm *peer = r->peer;193193+ unsigned long this_rate = 0, this_sleep_rate = 0;194194+ unsigned long peer_rate = 0, peer_sleep_rate = 0;195195+ unsigned long active_rate, sleep_rate;196196+ int ret = 0;197197+198198+ mutex_lock(&rpm_clk_lock);199199+200200+ /* Don't send requests to the RPM if the rate has not been set. */201201+ if (!r->rate)202202+ goto out;203203+204204+ to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate);205205+206206+ /* Take peer clock's rate into account only if it's enabled. */207207+ if (peer->enabled)208208+ to_active_sleep(peer, peer->rate,209209+ &peer_rate, &peer_sleep_rate);210210+211211+ active_rate = max(this_rate, peer_rate);212212+213213+ if (r->branch)214214+ active_rate = !!active_rate;215215+216216+ ret = clk_rpm_set_rate_active(r, active_rate);217217+ if (ret)218218+ goto out;219219+220220+ sleep_rate = max(this_sleep_rate, peer_sleep_rate);221221+ if (r->branch)222222+ sleep_rate = !!sleep_rate;223223+224224+ ret = clk_rpm_set_rate_sleep(r, sleep_rate);225225+ if (ret)226226+ /* Undo the active set vote and restore it */227227+ ret = clk_rpm_set_rate_active(r, peer_rate);228228+229229+out:230230+ if (!ret)231231+ r->enabled = true;232232+233233+ mutex_unlock(&rpm_clk_lock);234234+235235+ return ret;236236+}237237+238238+static void clk_rpm_unprepare(struct clk_hw *hw)239239+{240240+ struct clk_rpm *r = to_clk_rpm(hw);241241+ struct clk_rpm *peer = r->peer;242242+ unsigned long peer_rate = 0, peer_sleep_rate = 0;243243+ unsigned long active_rate, sleep_rate;244244+ int ret;245245+246246+ mutex_lock(&rpm_clk_lock);247247+248248+ if (!r->rate)249249+ goto out;250250+251251+ /* Take peer clock's rate into account only if it's enabled. */252252+ if (peer->enabled)253253+ to_active_sleep(peer, peer->rate, &peer_rate,254254+ &peer_sleep_rate);255255+256256+ active_rate = r->branch ? !!peer_rate : peer_rate;257257+ ret = clk_rpm_set_rate_active(r, active_rate);258258+ if (ret)259259+ goto out;260260+261261+ sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate;262262+ ret = clk_rpm_set_rate_sleep(r, sleep_rate);263263+ if (ret)264264+ goto out;265265+266266+ r->enabled = false;267267+268268+out:269269+ mutex_unlock(&rpm_clk_lock);270270+}271271+272272+static int clk_rpm_set_rate(struct clk_hw *hw,273273+ unsigned long rate, unsigned long parent_rate)274274+{275275+ struct clk_rpm *r = to_clk_rpm(hw);276276+ struct clk_rpm *peer = r->peer;277277+ unsigned long active_rate, sleep_rate;278278+ unsigned long this_rate = 0, this_sleep_rate = 0;279279+ unsigned long peer_rate = 0, peer_sleep_rate = 0;280280+ int ret = 0;281281+282282+ mutex_lock(&rpm_clk_lock);283283+284284+ if (!r->enabled)285285+ goto out;286286+287287+ to_active_sleep(r, rate, &this_rate, &this_sleep_rate);288288+289289+ /* Take peer clock's rate into account only if it's enabled. */290290+ if (peer->enabled)291291+ to_active_sleep(peer, peer->rate,292292+ &peer_rate, &peer_sleep_rate);293293+294294+ active_rate = max(this_rate, peer_rate);295295+ ret = clk_rpm_set_rate_active(r, active_rate);296296+ if (ret)297297+ goto out;298298+299299+ sleep_rate = max(this_sleep_rate, peer_sleep_rate);300300+ ret = clk_rpm_set_rate_sleep(r, sleep_rate);301301+ if (ret)302302+ goto out;303303+304304+ r->rate = rate;305305+306306+out:307307+ mutex_unlock(&rpm_clk_lock);308308+309309+ return ret;310310+}311311+312312+static long clk_rpm_round_rate(struct clk_hw *hw, unsigned long rate,313313+ unsigned long *parent_rate)314314+{315315+ /*316316+ * RPM handles rate rounding and we don't have a way to317317+ * know what the rate will be, so just return whatever318318+ * rate is requested.319319+ */320320+ return rate;321321+}322322+323323+static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,324324+ unsigned long parent_rate)325325+{326326+ struct clk_rpm *r = to_clk_rpm(hw);327327+328328+ /*329329+ * RPM handles rate rounding and we don't have a way to330330+ * know what the rate will be, so just return whatever331331+ * rate was set.332332+ */333333+ return r->rate;334334+}335335+336336+static const struct clk_ops clk_rpm_ops = {337337+ .prepare = clk_rpm_prepare,338338+ .unprepare = clk_rpm_unprepare,339339+ .set_rate = clk_rpm_set_rate,340340+ .round_rate = clk_rpm_round_rate,341341+ .recalc_rate = clk_rpm_recalc_rate,342342+};343343+344344+static const struct clk_ops clk_rpm_branch_ops = {345345+ .prepare = clk_rpm_prepare,346346+ .unprepare = clk_rpm_unprepare,347347+ .round_rate = clk_rpm_round_rate,348348+ .recalc_rate = clk_rpm_recalc_rate,349349+};350350+351351+/* apq8064 */352352+DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);353353+DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);354354+DEFINE_CLK_RPM(apq8064, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);355355+DEFINE_CLK_RPM(apq8064, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);356356+DEFINE_CLK_RPM(apq8064, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK);357357+DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);358358+DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);359359+DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);360360+DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);361361+362362+static struct clk_rpm *apq8064_clks[] = {363363+ [RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,364364+ [RPM_APPS_FABRIC_A_CLK] = &apq8064_afab_a_clk,365365+ [RPM_CFPB_CLK] = &apq8064_cfpb_clk,366366+ [RPM_CFPB_A_CLK] = &apq8064_cfpb_a_clk,367367+ [RPM_DAYTONA_FABRIC_CLK] = &apq8064_daytona_clk,368368+ [RPM_DAYTONA_FABRIC_A_CLK] = &apq8064_daytona_a_clk,369369+ [RPM_EBI1_CLK] = &apq8064_ebi1_clk,370370+ [RPM_EBI1_A_CLK] = &apq8064_ebi1_a_clk,371371+ [RPM_MM_FABRIC_CLK] = &apq8064_mmfab_clk,372372+ [RPM_MM_FABRIC_A_CLK] = &apq8064_mmfab_a_clk,373373+ [RPM_MMFPB_CLK] = &apq8064_mmfpb_clk,374374+ [RPM_MMFPB_A_CLK] = &apq8064_mmfpb_a_clk,375375+ [RPM_SYS_FABRIC_CLK] = &apq8064_sfab_clk,376376+ [RPM_SYS_FABRIC_A_CLK] = &apq8064_sfab_a_clk,377377+ [RPM_SFPB_CLK] = &apq8064_sfpb_clk,378378+ [RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,379379+ [RPM_QDSS_CLK] = &apq8064_qdss_clk,380380+ [RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,381381+};382382+383383+static const struct rpm_clk_desc rpm_clk_apq8064 = {384384+ .clks = apq8064_clks,385385+ .num_clks = ARRAY_SIZE(apq8064_clks),386386+};387387+388388+static const struct of_device_id rpm_clk_match_table[] = {389389+ { .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 },390390+ { }391391+};392392+MODULE_DEVICE_TABLE(of, rpm_clk_match_table);393393+394394+static int rpm_clk_probe(struct platform_device *pdev)395395+{396396+ struct clk_hw **hws;397397+ struct rpm_cc *rcc;398398+ struct clk_hw_onecell_data *data;399399+ int ret;400400+ size_t num_clks, i;401401+ struct qcom_rpm *rpm;402402+ struct clk_rpm **rpm_clks;403403+ const struct rpm_clk_desc *desc;404404+405405+ rpm = dev_get_drvdata(pdev->dev.parent);406406+ if (!rpm) {407407+ dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");408408+ return -ENODEV;409409+ }410410+411411+ desc = of_device_get_match_data(&pdev->dev);412412+ if (!desc)413413+ return -EINVAL;414414+415415+ rpm_clks = desc->clks;416416+ num_clks = desc->num_clks;417417+418418+ rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc) + sizeof(*hws) * num_clks,419419+ GFP_KERNEL);420420+ if (!rcc)421421+ return -ENOMEM;422422+423423+ hws = rcc->hws;424424+ data = &rcc->data;425425+ data->num = num_clks;426426+427427+ for (i = 0; i < num_clks; i++) {428428+ if (!rpm_clks[i])429429+ continue;430430+431431+ rpm_clks[i]->rpm = rpm;432432+433433+ ret = clk_rpm_handoff(rpm_clks[i]);434434+ if (ret)435435+ goto err;436436+ }437437+438438+ for (i = 0; i < num_clks; i++) {439439+ if (!rpm_clks[i]) {440440+ data->hws[i] = ERR_PTR(-ENOENT);441441+ continue;442442+ }443443+444444+ ret = devm_clk_hw_register(&pdev->dev, &rpm_clks[i]->hw);445445+ if (ret)446446+ goto err;447447+ }448448+449449+ ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,450450+ data);451451+ if (ret)452452+ goto err;453453+454454+ return 0;455455+err:456456+ dev_err(&pdev->dev, "Error registering RPM Clock driver (%d)\n", ret);457457+ return ret;458458+}459459+460460+static int rpm_clk_remove(struct platform_device *pdev)461461+{462462+ of_clk_del_provider(pdev->dev.of_node);463463+ return 0;464464+}465465+466466+static struct platform_driver rpm_clk_driver = {467467+ .driver = {468468+ .name = "qcom-clk-rpm",469469+ .of_match_table = rpm_clk_match_table,470470+ },471471+ .probe = rpm_clk_probe,472472+ .remove = rpm_clk_remove,473473+};474474+475475+static int __init rpm_clk_init(void)476476+{477477+ return platform_driver_register(&rpm_clk_driver);478478+}479479+core_initcall(rpm_clk_init);480480+481481+static void __exit rpm_clk_exit(void)482482+{483483+ platform_driver_unregister(&rpm_clk_driver);484484+}485485+module_exit(rpm_clk_exit);486486+487487+MODULE_DESCRIPTION("Qualcomm RPM Clock Controller Driver");488488+MODULE_LICENSE("GPL v2");489489+MODULE_ALIAS("platform:qcom-clk-rpm");
+570
drivers/clk/qcom/clk-smd-rpm.c
···11+/*22+ * Copyright (c) 2016, Linaro Limited33+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.44+ *55+ * This software is licensed under the terms of the GNU General Public66+ * License version 2, as published by the Free Software Foundation, and77+ * may be copied, distributed, and modified under those terms.88+ *99+ * This program is distributed in the hope that it will be useful,1010+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1111+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212+ * GNU General Public License for more details.1313+ */1414+1515+#include <linux/clk-provider.h>1616+#include <linux/err.h>1717+#include <linux/export.h>1818+#include <linux/init.h>1919+#include <linux/kernel.h>2020+#include <linux/module.h>2121+#include <linux/mutex.h>2222+#include <linux/of.h>2323+#include <linux/of_device.h>2424+#include <linux/platform_device.h>2525+#include <linux/soc/qcom/smd-rpm.h>2626+2727+#include <dt-bindings/clock/qcom,rpmcc.h>2828+#include <dt-bindings/mfd/qcom-rpm.h>2929+3030+#define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e6577733131+#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x626363703232+#define QCOM_RPM_SMD_KEY_RATE 0x007a484b3333+#define QCOM_RPM_SMD_KEY_ENABLE 0x62616e453434+#define QCOM_RPM_SMD_KEY_STATE 0x544154533535+#define QCOM_RPM_SCALING_ENABLE_ID 0x23636+3737+#define __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, stat_id, \3838+ key) \3939+ static struct clk_smd_rpm _platform##_##_active; \4040+ static struct clk_smd_rpm _platform##_##_name = { \4141+ .rpm_res_type = (type), \4242+ .rpm_clk_id = (r_id), \4343+ .rpm_status_id = (stat_id), \4444+ .rpm_key = (key), \4545+ .peer = &_platform##_##_active, \4646+ .rate = INT_MAX, \4747+ .hw.init = &(struct clk_init_data){ \4848+ .ops = &clk_smd_rpm_ops, \4949+ .name = #_name, \5050+ .parent_names = (const char *[]){ "xo_board" }, \5151+ .num_parents = 1, \5252+ }, \5353+ }; \5454+ static struct clk_smd_rpm _platform##_##_active = { \5555+ .rpm_res_type = (type), \5656+ .rpm_clk_id = (r_id), \5757+ .rpm_status_id = (stat_id), \5858+ .active_only = true, \5959+ .rpm_key = (key), \6060+ .peer = &_platform##_##_name, \6161+ .rate = INT_MAX, \6262+ .hw.init = &(struct clk_init_data){ \6363+ .ops = &clk_smd_rpm_ops, \6464+ .name = #_active, \6565+ .parent_names = (const char *[]){ "xo_board" }, \6666+ .num_parents = 1, \6767+ }, \6868+ }6969+7070+#define __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id, \7171+ stat_id, r, key) \7272+ static struct clk_smd_rpm _platform##_##_active; \7373+ static struct clk_smd_rpm _platform##_##_name = { \7474+ .rpm_res_type = (type), \7575+ .rpm_clk_id = (r_id), \7676+ .rpm_status_id = (stat_id), \7777+ .rpm_key = (key), \7878+ .branch = true, \7979+ .peer = &_platform##_##_active, \8080+ .rate = (r), \8181+ .hw.init = &(struct clk_init_data){ \8282+ .ops = &clk_smd_rpm_branch_ops, \8383+ .name = #_name, \8484+ .parent_names = (const char *[]){ "xo_board" }, \8585+ .num_parents = 1, \8686+ }, \8787+ }; \8888+ static struct clk_smd_rpm _platform##_##_active = { \8989+ .rpm_res_type = (type), \9090+ .rpm_clk_id = (r_id), \9191+ .rpm_status_id = (stat_id), \9292+ .active_only = true, \9393+ .rpm_key = (key), \9494+ .branch = true, \9595+ .peer = &_platform##_##_name, \9696+ .rate = (r), \9797+ .hw.init = &(struct clk_init_data){ \9898+ .ops = &clk_smd_rpm_branch_ops, \9999+ .name = #_active, \100100+ .parent_names = (const char *[]){ "xo_board" }, \101101+ .num_parents = 1, \102102+ }, \103103+ }104104+105105+#define DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id) \106106+ __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, \107107+ 0, QCOM_RPM_SMD_KEY_RATE)108108+109109+#define DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id, r) \110110+ __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, \111111+ r_id, 0, r, QCOM_RPM_SMD_KEY_ENABLE)112112+113113+#define DEFINE_CLK_SMD_RPM_QDSS(_platform, _name, _active, type, r_id) \114114+ __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, \115115+ 0, QCOM_RPM_SMD_KEY_STATE)116116+117117+#define DEFINE_CLK_SMD_RPM_XO_BUFFER(_platform, _name, _active, r_id) \118118+ __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, \119119+ QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000, \120120+ QCOM_RPM_KEY_SOFTWARE_ENABLE)121121+122122+#define DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(_platform, _name, _active, r_id) \123123+ __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, \124124+ QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000, \125125+ QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY)126126+127127+#define to_clk_smd_rpm(_hw) container_of(_hw, struct clk_smd_rpm, hw)128128+129129+struct clk_smd_rpm {130130+ const int rpm_res_type;131131+ const int rpm_key;132132+ const int rpm_clk_id;133133+ const int rpm_status_id;134134+ const bool active_only;135135+ bool enabled;136136+ bool branch;137137+ struct clk_smd_rpm *peer;138138+ struct clk_hw hw;139139+ unsigned long rate;140140+ struct qcom_smd_rpm *rpm;141141+};142142+143143+struct clk_smd_rpm_req {144144+ __le32 key;145145+ __le32 nbytes;146146+ __le32 value;147147+};148148+149149+struct rpm_cc {150150+ struct qcom_rpm *rpm;151151+ struct clk_hw_onecell_data data;152152+ struct clk_hw *hws[];153153+};154154+155155+struct rpm_smd_clk_desc {156156+ struct clk_smd_rpm **clks;157157+ size_t num_clks;158158+};159159+160160+static DEFINE_MUTEX(rpm_smd_clk_lock);161161+162162+static int clk_smd_rpm_handoff(struct clk_smd_rpm *r)163163+{164164+ int ret;165165+ struct clk_smd_rpm_req req = {166166+ .key = cpu_to_le32(r->rpm_key),167167+ .nbytes = cpu_to_le32(sizeof(u32)),168168+ .value = cpu_to_le32(INT_MAX),169169+ };170170+171171+ ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,172172+ r->rpm_res_type, r->rpm_clk_id, &req,173173+ sizeof(req));174174+ if (ret)175175+ return ret;176176+ ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,177177+ r->rpm_res_type, r->rpm_clk_id, &req,178178+ sizeof(req));179179+ if (ret)180180+ return ret;181181+182182+ return 0;183183+}184184+185185+static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r,186186+ unsigned long rate)187187+{188188+ struct clk_smd_rpm_req req = {189189+ .key = cpu_to_le32(r->rpm_key),190190+ .nbytes = cpu_to_le32(sizeof(u32)),191191+ .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */192192+ };193193+194194+ return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,195195+ r->rpm_res_type, r->rpm_clk_id, &req,196196+ sizeof(req));197197+}198198+199199+static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r,200200+ unsigned long rate)201201+{202202+ struct clk_smd_rpm_req req = {203203+ .key = cpu_to_le32(r->rpm_key),204204+ .nbytes = cpu_to_le32(sizeof(u32)),205205+ .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */206206+ };207207+208208+ return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,209209+ r->rpm_res_type, r->rpm_clk_id, &req,210210+ sizeof(req));211211+}212212+213213+static void to_active_sleep(struct clk_smd_rpm *r, unsigned long rate,214214+ unsigned long *active, unsigned long *sleep)215215+{216216+ *active = rate;217217+218218+ /*219219+ * Active-only clocks don't care what the rate is during sleep. So,220220+ * they vote for zero.221221+ */222222+ if (r->active_only)223223+ *sleep = 0;224224+ else225225+ *sleep = *active;226226+}227227+228228+static int clk_smd_rpm_prepare(struct clk_hw *hw)229229+{230230+ struct clk_smd_rpm *r = to_clk_smd_rpm(hw);231231+ struct clk_smd_rpm *peer = r->peer;232232+ unsigned long this_rate = 0, this_sleep_rate = 0;233233+ unsigned long peer_rate = 0, peer_sleep_rate = 0;234234+ unsigned long active_rate, sleep_rate;235235+ int ret = 0;236236+237237+ mutex_lock(&rpm_smd_clk_lock);238238+239239+ /* Don't send requests to the RPM if the rate has not been set. */240240+ if (!r->rate)241241+ goto out;242242+243243+ to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate);244244+245245+ /* Take peer clock's rate into account only if it's enabled. */246246+ if (peer->enabled)247247+ to_active_sleep(peer, peer->rate,248248+ &peer_rate, &peer_sleep_rate);249249+250250+ active_rate = max(this_rate, peer_rate);251251+252252+ if (r->branch)253253+ active_rate = !!active_rate;254254+255255+ ret = clk_smd_rpm_set_rate_active(r, active_rate);256256+ if (ret)257257+ goto out;258258+259259+ sleep_rate = max(this_sleep_rate, peer_sleep_rate);260260+ if (r->branch)261261+ sleep_rate = !!sleep_rate;262262+263263+ ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);264264+ if (ret)265265+ /* Undo the active set vote and restore it */266266+ ret = clk_smd_rpm_set_rate_active(r, peer_rate);267267+268268+out:269269+ if (!ret)270270+ r->enabled = true;271271+272272+ mutex_unlock(&rpm_smd_clk_lock);273273+274274+ return ret;275275+}276276+277277+static void clk_smd_rpm_unprepare(struct clk_hw *hw)278278+{279279+ struct clk_smd_rpm *r = to_clk_smd_rpm(hw);280280+ struct clk_smd_rpm *peer = r->peer;281281+ unsigned long peer_rate = 0, peer_sleep_rate = 0;282282+ unsigned long active_rate, sleep_rate;283283+ int ret;284284+285285+ mutex_lock(&rpm_smd_clk_lock);286286+287287+ if (!r->rate)288288+ goto out;289289+290290+ /* Take peer clock's rate into account only if it's enabled. */291291+ if (peer->enabled)292292+ to_active_sleep(peer, peer->rate, &peer_rate,293293+ &peer_sleep_rate);294294+295295+ active_rate = r->branch ? !!peer_rate : peer_rate;296296+ ret = clk_smd_rpm_set_rate_active(r, active_rate);297297+ if (ret)298298+ goto out;299299+300300+ sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate;301301+ ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);302302+ if (ret)303303+ goto out;304304+305305+ r->enabled = false;306306+307307+out:308308+ mutex_unlock(&rpm_smd_clk_lock);309309+}310310+311311+static int clk_smd_rpm_set_rate(struct clk_hw *hw, unsigned long rate,312312+ unsigned long parent_rate)313313+{314314+ struct clk_smd_rpm *r = to_clk_smd_rpm(hw);315315+ struct clk_smd_rpm *peer = r->peer;316316+ unsigned long active_rate, sleep_rate;317317+ unsigned long this_rate = 0, this_sleep_rate = 0;318318+ unsigned long peer_rate = 0, peer_sleep_rate = 0;319319+ int ret = 0;320320+321321+ mutex_lock(&rpm_smd_clk_lock);322322+323323+ if (!r->enabled)324324+ goto out;325325+326326+ to_active_sleep(r, rate, &this_rate, &this_sleep_rate);327327+328328+ /* Take peer clock's rate into account only if it's enabled. */329329+ if (peer->enabled)330330+ to_active_sleep(peer, peer->rate,331331+ &peer_rate, &peer_sleep_rate);332332+333333+ active_rate = max(this_rate, peer_rate);334334+ ret = clk_smd_rpm_set_rate_active(r, active_rate);335335+ if (ret)336336+ goto out;337337+338338+ sleep_rate = max(this_sleep_rate, peer_sleep_rate);339339+ ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);340340+ if (ret)341341+ goto out;342342+343343+ r->rate = rate;344344+345345+out:346346+ mutex_unlock(&rpm_smd_clk_lock);347347+348348+ return ret;349349+}350350+351351+static long clk_smd_rpm_round_rate(struct clk_hw *hw, unsigned long rate,352352+ unsigned long *parent_rate)353353+{354354+ /*355355+ * RPM handles rate rounding and we don't have a way to356356+ * know what the rate will be, so just return whatever357357+ * rate is requested.358358+ */359359+ return rate;360360+}361361+362362+static unsigned long clk_smd_rpm_recalc_rate(struct clk_hw *hw,363363+ unsigned long parent_rate)364364+{365365+ struct clk_smd_rpm *r = to_clk_smd_rpm(hw);366366+367367+ /*368368+ * RPM handles rate rounding and we don't have a way to369369+ * know what the rate will be, so just return whatever370370+ * rate was set.371371+ */372372+ return r->rate;373373+}374374+375375+static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm)376376+{377377+ int ret;378378+ struct clk_smd_rpm_req req = {379379+ .key = cpu_to_le32(QCOM_RPM_SMD_KEY_ENABLE),380380+ .nbytes = cpu_to_le32(sizeof(u32)),381381+ .value = cpu_to_le32(1),382382+ };383383+384384+ ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_SLEEP_STATE,385385+ QCOM_SMD_RPM_MISC_CLK,386386+ QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));387387+ if (ret) {388388+ pr_err("RPM clock scaling (sleep set) not enabled!\n");389389+ return ret;390390+ }391391+392392+ ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_ACTIVE_STATE,393393+ QCOM_SMD_RPM_MISC_CLK,394394+ QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));395395+ if (ret) {396396+ pr_err("RPM clock scaling (active set) not enabled!\n");397397+ return ret;398398+ }399399+400400+ pr_debug("%s: RPM clock scaling is enabled\n", __func__);401401+ return 0;402402+}403403+404404+static const struct clk_ops clk_smd_rpm_ops = {405405+ .prepare = clk_smd_rpm_prepare,406406+ .unprepare = clk_smd_rpm_unprepare,407407+ .set_rate = clk_smd_rpm_set_rate,408408+ .round_rate = clk_smd_rpm_round_rate,409409+ .recalc_rate = clk_smd_rpm_recalc_rate,410410+};411411+412412+static const struct clk_ops clk_smd_rpm_branch_ops = {413413+ .prepare = clk_smd_rpm_prepare,414414+ .unprepare = clk_smd_rpm_unprepare,415415+ .round_rate = clk_smd_rpm_round_rate,416416+ .recalc_rate = clk_smd_rpm_recalc_rate,417417+};418418+419419+/* msm8916 */420420+DEFINE_CLK_SMD_RPM(msm8916, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);421421+DEFINE_CLK_SMD_RPM(msm8916, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);422422+DEFINE_CLK_SMD_RPM(msm8916, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);423423+DEFINE_CLK_SMD_RPM_QDSS(msm8916, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1);424424+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk1, bb_clk1_a, 1);425425+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk2, bb_clk2_a, 2);426426+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk1, rf_clk1_a, 4);427427+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk2, rf_clk2_a, 5);428428+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk1_pin, bb_clk1_a_pin, 1);429429+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk2_pin, bb_clk2_a_pin, 2);430430+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk1_pin, rf_clk1_a_pin, 4);431431+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk2_pin, rf_clk2_a_pin, 5);432432+433433+static struct clk_smd_rpm *msm8916_clks[] = {434434+ [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,435435+ [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,436436+ [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,437437+ [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk,438438+ [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,439439+ [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,440440+ [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk,441441+ [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk,442442+ [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1,443443+ [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a,444444+ [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2,445445+ [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a,446446+ [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1,447447+ [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a,448448+ [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,449449+ [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,450450+ [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,451451+ [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,452452+ [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,453453+ [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,454454+ [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,455455+ [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,456456+ [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,457457+ [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,458458+};459459+460460+static const struct rpm_smd_clk_desc rpm_clk_msm8916 = {461461+ .clks = msm8916_clks,462462+ .num_clks = ARRAY_SIZE(msm8916_clks),463463+};464464+465465+static const struct of_device_id rpm_smd_clk_match_table[] = {466466+ { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },467467+ { }468468+};469469+MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);470470+471471+static int rpm_smd_clk_probe(struct platform_device *pdev)472472+{473473+ struct clk_hw **hws;474474+ struct rpm_cc *rcc;475475+ struct clk_hw_onecell_data *data;476476+ int ret;477477+ size_t num_clks, i;478478+ struct qcom_smd_rpm *rpm;479479+ struct clk_smd_rpm **rpm_smd_clks;480480+ const struct rpm_smd_clk_desc *desc;481481+482482+ rpm = dev_get_drvdata(pdev->dev.parent);483483+ if (!rpm) {484484+ dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");485485+ return -ENODEV;486486+ }487487+488488+ desc = of_device_get_match_data(&pdev->dev);489489+ if (!desc)490490+ return -EINVAL;491491+492492+ rpm_smd_clks = desc->clks;493493+ num_clks = desc->num_clks;494494+495495+ rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc) + sizeof(*hws) * num_clks,496496+ GFP_KERNEL);497497+ if (!rcc)498498+ return -ENOMEM;499499+500500+ hws = rcc->hws;501501+ data = &rcc->data;502502+ data->num = num_clks;503503+504504+ for (i = 0; i < num_clks; i++) {505505+ if (!rpm_smd_clks[i])506506+ continue;507507+508508+ rpm_smd_clks[i]->rpm = rpm;509509+510510+ ret = clk_smd_rpm_handoff(rpm_smd_clks[i]);511511+ if (ret)512512+ goto err;513513+ }514514+515515+ ret = clk_smd_rpm_enable_scaling(rpm);516516+ if (ret)517517+ goto err;518518+519519+ for (i = 0; i < num_clks; i++) {520520+ if (!rpm_smd_clks[i]) {521521+ data->hws[i] = ERR_PTR(-ENOENT);522522+ continue;523523+ }524524+525525+ ret = devm_clk_hw_register(&pdev->dev, &rpm_smd_clks[i]->hw);526526+ if (ret)527527+ goto err;528528+ }529529+530530+ ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,531531+ data);532532+ if (ret)533533+ goto err;534534+535535+ return 0;536536+err:537537+ dev_err(&pdev->dev, "Error registering SMD clock driver (%d)\n", ret);538538+ return ret;539539+}540540+541541+static int rpm_smd_clk_remove(struct platform_device *pdev)542542+{543543+ of_clk_del_provider(pdev->dev.of_node);544544+ return 0;545545+}546546+547547+static struct platform_driver rpm_smd_clk_driver = {548548+ .driver = {549549+ .name = "qcom-clk-smd-rpm",550550+ .of_match_table = rpm_smd_clk_match_table,551551+ },552552+ .probe = rpm_smd_clk_probe,553553+ .remove = rpm_smd_clk_remove,554554+};555555+556556+static int __init rpm_smd_clk_init(void)557557+{558558+ return platform_driver_register(&rpm_smd_clk_driver);559559+}560560+core_initcall(rpm_smd_clk_init);561561+562562+static void __exit rpm_smd_clk_exit(void)563563+{564564+ platform_driver_unregister(&rpm_smd_clk_driver);565565+}566566+module_exit(rpm_smd_clk_exit);567567+568568+MODULE_DESCRIPTION("Qualcomm RPM over SMD Clock Controller Driver");569569+MODULE_LICENSE("GPL v2");570570+MODULE_ALIAS("platform:qcom-clk-smd-rpm");
+5-8
drivers/clk/qcom/common.c
···174174 const char *name, unsigned long rate)175175{176176 bool add_factor = true;177177- struct device_node *node;178177179179- /* The RPM clock driver will add the factor clock if present */180180- if (IS_ENABLED(CONFIG_QCOM_RPMCC)) {181181- node = of_find_compatible_node(NULL, NULL, "qcom,rpmcc");182182- if (of_device_is_available(node))183183- add_factor = false;184184- of_node_put(node);185185- }178178+ /*179179+ * TODO: The RPM clock driver currently does not support the xo clock.180180+ * When xo is added to the RPM clock driver, we should change this181181+ * function to skip registration of xo factor clocks.182182+ */186183187184 return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor);188185}
+69
include/dt-bindings/clock/qcom,rpmcc.h
···11+/*22+ * Copyright 2015 Linaro Limited33+ *44+ * This software is licensed under the terms of the GNU General Public55+ * License version 2, as published by the Free Software Foundation, and66+ * may be copied, distributed, and modified under those terms.77+ *88+ * This program is distributed in the hope that it will be useful,99+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1010+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1111+ * GNU General Public License for more details.1212+ */1313+1414+#ifndef _DT_BINDINGS_CLK_MSM_RPMCC_H1515+#define _DT_BINDINGS_CLK_MSM_RPMCC_H1616+1717+/* apq8064 */1818+#define RPM_PXO_CLK 01919+#define RPM_PXO_A_CLK 12020+#define RPM_CXO_CLK 22121+#define RPM_CXO_A_CLK 32222+#define RPM_APPS_FABRIC_CLK 42323+#define RPM_APPS_FABRIC_A_CLK 52424+#define RPM_CFPB_CLK 62525+#define RPM_CFPB_A_CLK 72626+#define RPM_QDSS_CLK 82727+#define RPM_QDSS_A_CLK 92828+#define RPM_DAYTONA_FABRIC_CLK 102929+#define RPM_DAYTONA_FABRIC_A_CLK 113030+#define RPM_EBI1_CLK 123131+#define RPM_EBI1_A_CLK 133232+#define RPM_MM_FABRIC_CLK 143333+#define RPM_MM_FABRIC_A_CLK 153434+#define RPM_MMFPB_CLK 163535+#define RPM_MMFPB_A_CLK 173636+#define RPM_SYS_FABRIC_CLK 183737+#define RPM_SYS_FABRIC_A_CLK 193838+#define RPM_SFPB_CLK 203939+#define RPM_SFPB_A_CLK 214040+4141+/* msm8916 */4242+#define RPM_SMD_XO_CLK_SRC 04343+#define RPM_SMD_XO_A_CLK_SRC 14444+#define RPM_SMD_PCNOC_CLK 24545+#define RPM_SMD_PCNOC_A_CLK 34646+#define RPM_SMD_SNOC_CLK 44747+#define RPM_SMD_SNOC_A_CLK 54848+#define RPM_SMD_BIMC_CLK 64949+#define RPM_SMD_BIMC_A_CLK 75050+#define RPM_SMD_QDSS_CLK 85151+#define RPM_SMD_QDSS_A_CLK 95252+#define RPM_SMD_BB_CLK1 105353+#define RPM_SMD_BB_CLK1_A 115454+#define RPM_SMD_BB_CLK2 125555+#define RPM_SMD_BB_CLK2_A 135656+#define RPM_SMD_RF_CLK1 145757+#define RPM_SMD_RF_CLK1_A 155858+#define RPM_SMD_RF_CLK2 165959+#define RPM_SMD_RF_CLK2_A 176060+#define RPM_SMD_BB_CLK1_PIN 186161+#define RPM_SMD_BB_CLK1_A_PIN 196262+#define RPM_SMD_BB_CLK2_PIN 206363+#define RPM_SMD_BB_CLK2_A_PIN 216464+#define RPM_SMD_RF_CLK1_PIN 226565+#define RPM_SMD_RF_CLK1_A_PIN 236666+#define RPM_SMD_RF_CLK2_PIN 246767+#define RPM_SMD_RF_CLK2_A_PIN 256868+6969+#endif