ipq806x: Add support for IPQ806x chip family
[openwrt/svn-archive/archive.git] / target / linux / ipq806x / patches / 0078-clk-qcom-Consolidate-common-probe-code.patch
diff --git a/target/linux/ipq806x/patches/0078-clk-qcom-Consolidate-common-probe-code.patch b/target/linux/ipq806x/patches/0078-clk-qcom-Consolidate-common-probe-code.patch
new file mode 100644 (file)
index 0000000..c801ed5
--- /dev/null
@@ -0,0 +1,755 @@
+From d79cb0c583772f38a9367af106d61bcf8bfa08e4 Mon Sep 17 00:00:00 2001
+From: Stephen Boyd <sboyd@codeaurora.org>
+Date: Fri, 21 Mar 2014 17:59:37 -0700
+Subject: [PATCH 078/182] clk: qcom: Consolidate common probe code
+
+Most of the probe code is the same between all the different
+clock controllers. Consolidate the code into a common.c file.
+This makes changes to the common probe parts easier and reduces
+chances for bugs.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Kumar Gala <galak@codeaurora.org>
+---
+ drivers/clk/qcom/Makefile       |    1 +
+ drivers/clk/qcom/common.c       |   99 +++++++++++++++++++++++++++++++++++++++
+ drivers/clk/qcom/common.h       |   34 ++++++++++++++
+ drivers/clk/qcom/gcc-msm8660.c  |   87 +++++-----------------------------
+ drivers/clk/qcom/gcc-msm8960.c  |   77 +++++-------------------------
+ drivers/clk/qcom/gcc-msm8974.c  |   77 +++++-------------------------
+ drivers/clk/qcom/mmcc-msm8960.c |   78 +++++-------------------------
+ drivers/clk/qcom/mmcc-msm8974.c |   80 +++++++------------------------
+ 8 files changed, 196 insertions(+), 337 deletions(-)
+ create mode 100644 drivers/clk/qcom/common.c
+ create mode 100644 drivers/clk/qcom/common.h
+
+diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
+index f60db2e..689e05b 100644
+--- a/drivers/clk/qcom/Makefile
++++ b/drivers/clk/qcom/Makefile
+@@ -1,5 +1,6 @@
+ obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
++clk-qcom-y += common.o
+ clk-qcom-y += clk-regmap.o
+ clk-qcom-y += clk-pll.o
+ clk-qcom-y += clk-rcg.o
+diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
+new file mode 100644
+index 0000000..86b45fb
+--- /dev/null
++++ b/drivers/clk/qcom/common.c
+@@ -0,0 +1,99 @@
++/*
++ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/export.h>
++#include <linux/regmap.h>
++#include <linux/platform_device.h>
++#include <linux/clk-provider.h>
++#include <linux/reset-controller.h>
++
++#include "common.h"
++#include "clk-regmap.h"
++#include "reset.h"
++
++struct qcom_cc {
++      struct qcom_reset_controller reset;
++      struct clk_onecell_data data;
++      struct clk *clks[];
++};
++
++int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
++{
++      void __iomem *base;
++      struct resource *res;
++      int i, ret;
++      struct device *dev = &pdev->dev;
++      struct clk *clk;
++      struct clk_onecell_data *data;
++      struct clk **clks;
++      struct regmap *regmap;
++      struct qcom_reset_controller *reset;
++      struct qcom_cc *cc;
++      size_t num_clks = desc->num_clks;
++      struct clk_regmap **rclks = desc->clks;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      base = devm_ioremap_resource(dev, res);
++      if (IS_ERR(base))
++              return PTR_ERR(base);
++
++      regmap = devm_regmap_init_mmio(dev, base, desc->config);
++      if (IS_ERR(regmap))
++              return PTR_ERR(regmap);
++
++      cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
++                        GFP_KERNEL);
++      if (!cc)
++              return -ENOMEM;
++
++      clks = cc->clks;
++      data = &cc->data;
++      data->clks = clks;
++      data->clk_num = num_clks;
++
++      for (i = 0; i < num_clks; i++) {
++              if (!rclks[i])
++                      continue;
++              clk = devm_clk_register_regmap(dev, rclks[i]);
++              if (IS_ERR(clk))
++                      return PTR_ERR(clk);
++              clks[i] = clk;
++      }
++
++      ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
++      if (ret)
++              return ret;
++
++      reset = &cc->reset;
++      reset->rcdev.of_node = dev->of_node;
++      reset->rcdev.ops = &qcom_reset_ops;
++      reset->rcdev.owner = dev->driver->owner;
++      reset->rcdev.nr_resets = desc->num_resets;
++      reset->regmap = regmap;
++      reset->reset_map = desc->resets;
++      platform_set_drvdata(pdev, &reset->rcdev);
++
++      ret = reset_controller_register(&reset->rcdev);
++      if (ret)
++              of_clk_del_provider(dev->of_node);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(qcom_cc_probe);
++
++void qcom_cc_remove(struct platform_device *pdev)
++{
++      of_clk_del_provider(pdev->dev.of_node);
++      reset_controller_unregister(platform_get_drvdata(pdev));
++}
++EXPORT_SYMBOL_GPL(qcom_cc_remove);
+diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
+new file mode 100644
+index 0000000..2c3cfc8
+--- /dev/null
++++ b/drivers/clk/qcom/common.h
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++#ifndef __QCOM_CLK_COMMON_H__
++#define __QCOM_CLK_COMMON_H__
++
++struct platform_device;
++struct regmap_config;
++struct clk_regmap;
++struct qcom_reset_map;
++
++struct qcom_cc_desc {
++      const struct regmap_config *config;
++      struct clk_regmap **clks;
++      size_t num_clks;
++      const struct qcom_reset_map *resets;
++      size_t num_resets;
++};
++
++extern int qcom_cc_probe(struct platform_device *pdev,
++                       const struct qcom_cc_desc *desc);
++
++extern void qcom_cc_remove(struct platform_device *pdev);
++
++#endif
+diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c
+index bc0b7f1..44bc6fa 100644
+--- a/drivers/clk/qcom/gcc-msm8660.c
++++ b/drivers/clk/qcom/gcc-msm8660.c
+@@ -25,6 +25,7 @@
+ #include <dt-bindings/clock/qcom,gcc-msm8660.h>
+ #include <dt-bindings/reset/qcom,gcc-msm8660.h>
++#include "common.h"
+ #include "clk-regmap.h"
+ #include "clk-pll.h"
+ #include "clk-rcg.h"
+@@ -2701,94 +2702,28 @@ static const struct regmap_config gcc_msm8660_regmap_config = {
+       .fast_io        = true,
+ };
++static const struct qcom_cc_desc gcc_msm8660_desc = {
++      .config = &gcc_msm8660_regmap_config,
++      .clks = gcc_msm8660_clks,
++      .num_clks = ARRAY_SIZE(gcc_msm8660_clks),
++      .resets = gcc_msm8660_resets,
++      .num_resets = ARRAY_SIZE(gcc_msm8660_resets),
++};
++
+ static const struct of_device_id gcc_msm8660_match_table[] = {
+       { .compatible = "qcom,gcc-msm8660" },
+       { }
+ };
+ MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table);
+-struct qcom_cc {
+-      struct qcom_reset_controller reset;
+-      struct clk_onecell_data data;
+-      struct clk *clks[];
+-};
+-
+ static int gcc_msm8660_probe(struct platform_device *pdev)
+ {
+-      void __iomem *base;
+-      struct resource *res;
+-      int i, ret;
+-      struct device *dev = &pdev->dev;
+-      struct clk *clk;
+-      struct clk_onecell_data *data;
+-      struct clk **clks;
+-      struct regmap *regmap;
+-      size_t num_clks;
+-      struct qcom_reset_controller *reset;
+-      struct qcom_cc *cc;
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      base = devm_ioremap_resource(dev, res);
+-      if (IS_ERR(base))
+-              return PTR_ERR(base);
+-
+-      regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8660_regmap_config);
+-      if (IS_ERR(regmap))
+-              return PTR_ERR(regmap);
+-
+-      num_clks = ARRAY_SIZE(gcc_msm8660_clks);
+-      cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+-                        GFP_KERNEL);
+-      if (!cc)
+-              return -ENOMEM;
+-
+-      clks = cc->clks;
+-      data = &cc->data;
+-      data->clks = clks;
+-      data->clk_num = num_clks;
+-
+-      /* Temporary until RPM clocks supported */
+-      clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
+-      if (IS_ERR(clk))
+-              return PTR_ERR(clk);
+-
+-      clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000);
+-      if (IS_ERR(clk))
+-              return PTR_ERR(clk);
+-
+-      for (i = 0; i < num_clks; i++) {
+-              if (!gcc_msm8660_clks[i])
+-                      continue;
+-              clk = devm_clk_register_regmap(dev, gcc_msm8660_clks[i]);
+-              if (IS_ERR(clk))
+-                      return PTR_ERR(clk);
+-              clks[i] = clk;
+-      }
+-
+-      ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+-      if (ret)
+-              return ret;
+-
+-      reset = &cc->reset;
+-      reset->rcdev.of_node = dev->of_node;
+-      reset->rcdev.ops = &qcom_reset_ops,
+-      reset->rcdev.owner = THIS_MODULE,
+-      reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8660_resets),
+-      reset->regmap = regmap;
+-      reset->reset_map = gcc_msm8660_resets,
+-      platform_set_drvdata(pdev, &reset->rcdev);
+-
+-      ret = reset_controller_register(&reset->rcdev);
+-      if (ret)
+-              of_clk_del_provider(dev->of_node);
+-
+-      return ret;
++      return qcom_cc_probe(pdev, &gcc_msm8660_desc);
+ }
+ static int gcc_msm8660_remove(struct platform_device *pdev)
+ {
+-      of_clk_del_provider(pdev->dev.of_node);
+-      reset_controller_unregister(platform_get_drvdata(pdev));
++      qcom_cc_remove(pdev);
+       return 0;
+ }
+diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
+index fd446ab..633b019 100644
+--- a/drivers/clk/qcom/gcc-msm8960.c
++++ b/drivers/clk/qcom/gcc-msm8960.c
+@@ -25,6 +25,7 @@
+ #include <dt-bindings/clock/qcom,gcc-msm8960.h>
+ #include <dt-bindings/reset/qcom,gcc-msm8960.h>
++#include "common.h"
+ #include "clk-regmap.h"
+ #include "clk-pll.h"
+ #include "clk-rcg.h"
+@@ -2875,51 +2876,24 @@ static const struct regmap_config gcc_msm8960_regmap_config = {
+       .fast_io        = true,
+ };
++static const struct qcom_cc_desc gcc_msm8960_desc = {
++      .config = &gcc_msm8960_regmap_config,
++      .clks = gcc_msm8960_clks,
++      .num_clks = ARRAY_SIZE(gcc_msm8960_clks),
++      .resets = gcc_msm8960_resets,
++      .num_resets = ARRAY_SIZE(gcc_msm8960_resets),
++};
++
+ static const struct of_device_id gcc_msm8960_match_table[] = {
+       { .compatible = "qcom,gcc-msm8960" },
+       { }
+ };
+ MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table);
+-struct qcom_cc {
+-      struct qcom_reset_controller reset;
+-      struct clk_onecell_data data;
+-      struct clk *clks[];
+-};
+-
+ static int gcc_msm8960_probe(struct platform_device *pdev)
+ {
+-      void __iomem *base;
+-      struct resource *res;
+-      int i, ret;
+-      struct device *dev = &pdev->dev;
+       struct clk *clk;
+-      struct clk_onecell_data *data;
+-      struct clk **clks;
+-      struct regmap *regmap;
+-      size_t num_clks;
+-      struct qcom_reset_controller *reset;
+-      struct qcom_cc *cc;
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      base = devm_ioremap_resource(dev, res);
+-      if (IS_ERR(base))
+-              return PTR_ERR(base);
+-
+-      regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8960_regmap_config);
+-      if (IS_ERR(regmap))
+-              return PTR_ERR(regmap);
+-
+-      num_clks = ARRAY_SIZE(gcc_msm8960_clks);
+-      cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+-                        GFP_KERNEL);
+-      if (!cc)
+-              return -ENOMEM;
+-
+-      clks = cc->clks;
+-      data = &cc->data;
+-      data->clks = clks;
+-      data->clk_num = num_clks;
++      struct device *dev = &pdev->dev;
+       /* Temporary until RPM clocks supported */
+       clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
+@@ -2930,39 +2904,12 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+-      for (i = 0; i < num_clks; i++) {
+-              if (!gcc_msm8960_clks[i])
+-                      continue;
+-              clk = devm_clk_register_regmap(dev, gcc_msm8960_clks[i]);
+-              if (IS_ERR(clk))
+-                      return PTR_ERR(clk);
+-              clks[i] = clk;
+-      }
+-
+-      ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+-      if (ret)
+-              return ret;
+-
+-      reset = &cc->reset;
+-      reset->rcdev.of_node = dev->of_node;
+-      reset->rcdev.ops = &qcom_reset_ops,
+-      reset->rcdev.owner = THIS_MODULE,
+-      reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8960_resets),
+-      reset->regmap = regmap;
+-      reset->reset_map = gcc_msm8960_resets,
+-      platform_set_drvdata(pdev, &reset->rcdev);
+-
+-      ret = reset_controller_register(&reset->rcdev);
+-      if (ret)
+-              of_clk_del_provider(dev->of_node);
+-
+-      return ret;
++      return qcom_cc_probe(pdev, &gcc_msm8960_desc);
+ }
+ static int gcc_msm8960_remove(struct platform_device *pdev)
+ {
+-      of_clk_del_provider(pdev->dev.of_node);
+-      reset_controller_unregister(platform_get_drvdata(pdev));
++      qcom_cc_remove(pdev);
+       return 0;
+ }
+diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
+index 51d457e..0d1edc1 100644
+--- a/drivers/clk/qcom/gcc-msm8974.c
++++ b/drivers/clk/qcom/gcc-msm8974.c
+@@ -25,6 +25,7 @@
+ #include <dt-bindings/clock/qcom,gcc-msm8974.h>
+ #include <dt-bindings/reset/qcom,gcc-msm8974.h>
++#include "common.h"
+ #include "clk-regmap.h"
+ #include "clk-pll.h"
+ #include "clk-rcg.h"
+@@ -2574,51 +2575,24 @@ static const struct regmap_config gcc_msm8974_regmap_config = {
+       .fast_io        = true,
+ };
++static const struct qcom_cc_desc gcc_msm8974_desc = {
++      .config = &gcc_msm8974_regmap_config,
++      .clks = gcc_msm8974_clocks,
++      .num_clks = ARRAY_SIZE(gcc_msm8974_clocks),
++      .resets = gcc_msm8974_resets,
++      .num_resets = ARRAY_SIZE(gcc_msm8974_resets),
++};
++
+ static const struct of_device_id gcc_msm8974_match_table[] = {
+       { .compatible = "qcom,gcc-msm8974" },
+       { }
+ };
+ MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table);
+-struct qcom_cc {
+-      struct qcom_reset_controller reset;
+-      struct clk_onecell_data data;
+-      struct clk *clks[];
+-};
+-
+ static int gcc_msm8974_probe(struct platform_device *pdev)
+ {
+-      void __iomem *base;
+-      struct resource *res;
+-      int i, ret;
+-      struct device *dev = &pdev->dev;
+       struct clk *clk;
+-      struct clk_onecell_data *data;
+-      struct clk **clks;
+-      struct regmap *regmap;
+-      size_t num_clks;
+-      struct qcom_reset_controller *reset;
+-      struct qcom_cc *cc;
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      base = devm_ioremap_resource(dev, res);
+-      if (IS_ERR(base))
+-              return PTR_ERR(base);
+-
+-      regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8974_regmap_config);
+-      if (IS_ERR(regmap))
+-              return PTR_ERR(regmap);
+-
+-      num_clks = ARRAY_SIZE(gcc_msm8974_clocks);
+-      cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+-                        GFP_KERNEL);
+-      if (!cc)
+-              return -ENOMEM;
+-
+-      clks = cc->clks;
+-      data = &cc->data;
+-      data->clks = clks;
+-      data->clk_num = num_clks;
++      struct device *dev = &pdev->dev;
+       /* Temporary until RPM clocks supported */
+       clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
+@@ -2631,39 +2605,12 @@ static int gcc_msm8974_probe(struct platform_device *pdev)
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+-      for (i = 0; i < num_clks; i++) {
+-              if (!gcc_msm8974_clocks[i])
+-                      continue;
+-              clk = devm_clk_register_regmap(dev, gcc_msm8974_clocks[i]);
+-              if (IS_ERR(clk))
+-                      return PTR_ERR(clk);
+-              clks[i] = clk;
+-      }
+-
+-      ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+-      if (ret)
+-              return ret;
+-
+-      reset = &cc->reset;
+-      reset->rcdev.of_node = dev->of_node;
+-      reset->rcdev.ops = &qcom_reset_ops,
+-      reset->rcdev.owner = THIS_MODULE,
+-      reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8974_resets),
+-      reset->regmap = regmap;
+-      reset->reset_map = gcc_msm8974_resets,
+-      platform_set_drvdata(pdev, &reset->rcdev);
+-
+-      ret = reset_controller_register(&reset->rcdev);
+-      if (ret)
+-              of_clk_del_provider(dev->of_node);
+-
+-      return ret;
++      return qcom_cc_probe(pdev, &gcc_msm8974_desc);
+ }
+ static int gcc_msm8974_remove(struct platform_device *pdev)
+ {
+-      of_clk_del_provider(pdev->dev.of_node);
+-      reset_controller_unregister(platform_get_drvdata(pdev));
++      qcom_cc_remove(pdev);
+       return 0;
+ }
+diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
+index f9b59c7..12f3c0b 100644
+--- a/drivers/clk/qcom/mmcc-msm8960.c
++++ b/drivers/clk/qcom/mmcc-msm8960.c
+@@ -26,6 +26,7 @@
+ #include <dt-bindings/clock/qcom,mmcc-msm8960.h>
+ #include <dt-bindings/reset/qcom,mmcc-msm8960.h>
++#include "common.h"
+ #include "clk-regmap.h"
+ #include "clk-pll.h"
+ #include "clk-rcg.h"
+@@ -2222,85 +2223,28 @@ static const struct regmap_config mmcc_msm8960_regmap_config = {
+       .fast_io        = true,
+ };
++static const struct qcom_cc_desc mmcc_msm8960_desc = {
++      .config = &mmcc_msm8960_regmap_config,
++      .clks = mmcc_msm8960_clks,
++      .num_clks = ARRAY_SIZE(mmcc_msm8960_clks),
++      .resets = mmcc_msm8960_resets,
++      .num_resets = ARRAY_SIZE(mmcc_msm8960_resets),
++};
++
+ static const struct of_device_id mmcc_msm8960_match_table[] = {
+       { .compatible = "qcom,mmcc-msm8960" },
+       { }
+ };
+ MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table);
+-struct qcom_cc {
+-      struct qcom_reset_controller reset;
+-      struct clk_onecell_data data;
+-      struct clk *clks[];
+-};
+-
+ static int mmcc_msm8960_probe(struct platform_device *pdev)
+ {
+-      void __iomem *base;
+-      struct resource *res;
+-      int i, ret;
+-      struct device *dev = &pdev->dev;
+-      struct clk *clk;
+-      struct clk_onecell_data *data;
+-      struct clk **clks;
+-      struct regmap *regmap;
+-      size_t num_clks;
+-      struct qcom_reset_controller *reset;
+-      struct qcom_cc *cc;
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      base = devm_ioremap_resource(dev, res);
+-      if (IS_ERR(base))
+-              return PTR_ERR(base);
+-
+-      regmap = devm_regmap_init_mmio(dev, base, &mmcc_msm8960_regmap_config);
+-      if (IS_ERR(regmap))
+-              return PTR_ERR(regmap);
+-
+-      num_clks = ARRAY_SIZE(mmcc_msm8960_clks);
+-      cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+-                        GFP_KERNEL);
+-      if (!cc)
+-              return -ENOMEM;
+-
+-      clks = cc->clks;
+-      data = &cc->data;
+-      data->clks = clks;
+-      data->clk_num = num_clks;
+-
+-      for (i = 0; i < num_clks; i++) {
+-              if (!mmcc_msm8960_clks[i])
+-                      continue;
+-              clk = devm_clk_register_regmap(dev, mmcc_msm8960_clks[i]);
+-              if (IS_ERR(clk))
+-                      return PTR_ERR(clk);
+-              clks[i] = clk;
+-      }
+-
+-      ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+-      if (ret)
+-              return ret;
+-
+-      reset = &cc->reset;
+-      reset->rcdev.of_node = dev->of_node;
+-      reset->rcdev.ops = &qcom_reset_ops,
+-      reset->rcdev.owner = THIS_MODULE,
+-      reset->rcdev.nr_resets = ARRAY_SIZE(mmcc_msm8960_resets),
+-      reset->regmap = regmap;
+-      reset->reset_map = mmcc_msm8960_resets,
+-      platform_set_drvdata(pdev, &reset->rcdev);
+-
+-      ret = reset_controller_register(&reset->rcdev);
+-      if (ret)
+-              of_clk_del_provider(dev->of_node);
+-
+-      return ret;
++      return qcom_cc_probe(pdev, &mmcc_msm8960_desc);
+ }
+ static int mmcc_msm8960_remove(struct platform_device *pdev)
+ {
+-      of_clk_del_provider(pdev->dev.of_node);
+-      reset_controller_unregister(platform_get_drvdata(pdev));
++      qcom_cc_remove(pdev);
+       return 0;
+ }
+diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
+index c957745..60b7c24 100644
+--- a/drivers/clk/qcom/mmcc-msm8974.c
++++ b/drivers/clk/qcom/mmcc-msm8974.c
+@@ -25,6 +25,7 @@
+ #include <dt-bindings/clock/qcom,mmcc-msm8974.h>
+ #include <dt-bindings/reset/qcom,mmcc-msm8974.h>
++#include "common.h"
+ #include "clk-regmap.h"
+ #include "clk-pll.h"
+ #include "clk-rcg.h"
+@@ -2524,88 +2525,39 @@ static const struct regmap_config mmcc_msm8974_regmap_config = {
+       .fast_io        = true,
+ };
++static const struct qcom_cc_desc mmcc_msm8974_desc = {
++      .config = &mmcc_msm8974_regmap_config,
++      .clks = mmcc_msm8974_clocks,
++      .num_clks = ARRAY_SIZE(mmcc_msm8974_clocks),
++      .resets = mmcc_msm8974_resets,
++      .num_resets = ARRAY_SIZE(mmcc_msm8974_resets),
++};
++
+ static const struct of_device_id mmcc_msm8974_match_table[] = {
+       { .compatible = "qcom,mmcc-msm8974" },
+       { }
+ };
+ MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table);
+-struct qcom_cc {
+-      struct qcom_reset_controller reset;
+-      struct clk_onecell_data data;
+-      struct clk *clks[];
+-};
+-
+ static int mmcc_msm8974_probe(struct platform_device *pdev)
+ {
+-      void __iomem *base;
+-      struct resource *res;
+-      int i, ret;
+-      struct device *dev = &pdev->dev;
+-      struct clk *clk;
+-      struct clk_onecell_data *data;
+-      struct clk **clks;
++      int ret;
+       struct regmap *regmap;
+-      size_t num_clks;
+-      struct qcom_reset_controller *reset;
+-      struct qcom_cc *cc;
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      base = devm_ioremap_resource(dev, res);
+-      if (IS_ERR(base))
+-              return PTR_ERR(base);
+-
+-      regmap = devm_regmap_init_mmio(dev, base, &mmcc_msm8974_regmap_config);
+-      if (IS_ERR(regmap))
+-              return PTR_ERR(regmap);
+-
+-      num_clks = ARRAY_SIZE(mmcc_msm8974_clocks);
+-      cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+-                        GFP_KERNEL);
+-      if (!cc)
+-              return -ENOMEM;
+-
+-      clks = cc->clks;
+-      data = &cc->data;
+-      data->clks = clks;
+-      data->clk_num = num_clks;
+-
+-      clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
+-      clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
+-      for (i = 0; i < num_clks; i++) {
+-              if (!mmcc_msm8974_clocks[i])
+-                      continue;
+-              clk = devm_clk_register_regmap(dev, mmcc_msm8974_clocks[i]);
+-              if (IS_ERR(clk))
+-                      return PTR_ERR(clk);
+-              clks[i] = clk;
+-      }
+-
+-      ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
++      ret = qcom_cc_probe(pdev, &mmcc_msm8974_desc);
+       if (ret)
+               return ret;
+-      reset = &cc->reset;
+-      reset->rcdev.of_node = dev->of_node;
+-      reset->rcdev.ops = &qcom_reset_ops,
+-      reset->rcdev.owner = THIS_MODULE,
+-      reset->rcdev.nr_resets = ARRAY_SIZE(mmcc_msm8974_resets),
+-      reset->regmap = regmap;
+-      reset->reset_map = mmcc_msm8974_resets,
+-      platform_set_drvdata(pdev, &reset->rcdev);
+-
+-      ret = reset_controller_register(&reset->rcdev);
+-      if (ret)
+-              of_clk_del_provider(dev->of_node);
++      regmap = dev_get_regmap(&pdev->dev, NULL);
++      clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
++      clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
+-      return ret;
++      return 0;
+ }
+ static int mmcc_msm8974_remove(struct platform_device *pdev)
+ {
+-      of_clk_del_provider(pdev->dev.of_node);
+-      reset_controller_unregister(platform_get_drvdata(pdev));
++      qcom_cc_remove(pdev);
+       return 0;
+ }
+-- 
+1.7.10.4
+