clk: qcom: Add a regmap type clock struct
authorStephen Boyd <sboyd@codeaurora.org>
Wed, 15 Jan 2014 18:47:23 +0000 (10:47 -0800)
committerMike Turquette <mturquette@linaro.org>
Thu, 16 Jan 2014 20:00:58 +0000 (12:00 -0800)
Add a clock type that associates a regmap pointer and some
enable/disable bits with a clk_hw struct. This will be the struct
that a hw specific implementation wraps if it wants to use the
regmap helper functions.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/qcom/Kconfig [new file with mode: 0644]
drivers/clk/qcom/Makefile [new file with mode: 0644]
drivers/clk/qcom/clk-regmap.c [new file with mode: 0644]
drivers/clk/qcom/clk-regmap.h [new file with mode: 0644]

index 407cffb04895250f0176e5740d95f3d1f7823870..7641965d208d62cab3aea35a6af460b8e3ea1c2a 100644 (file)
@@ -107,6 +107,8 @@ config COMMON_CLK_KEYSTONE
           Supports clock drivers for Keystone based SOCs. These SOCs have local
          a power sleep control module that gate the clock to the IPs and PLLs.
 
+source "drivers/clk/qcom/Kconfig"
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
index fcaa5b8d4e623e81a6d559ae3d197767641cbf2c..972da894baa1c949f534016855b4dadda12ae76c 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)    += socfpga/
 obj-$(CONFIG_PLAT_SPEAR)       += spear/
 obj-$(CONFIG_ARCH_U300)                += clk-u300.o
 obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
+obj-$(CONFIG_COMMON_CLK_QCOM)  += qcom/
 obj-$(CONFIG_PLAT_ORION)       += mvebu/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)         += mmp/
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
new file mode 100644 (file)
index 0000000..73a8c8f
--- /dev/null
@@ -0,0 +1,5 @@
+config COMMON_CLK_QCOM
+       tristate "Support for Qualcomm's clock controllers"
+       depends on OF
+       select REGMAP_MMIO
+
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
new file mode 100644 (file)
index 0000000..f9faa8f
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
+
+clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-regmap.o
diff --git a/drivers/clk/qcom/clk-regmap.c b/drivers/clk/qcom/clk-regmap.c
new file mode 100644 (file)
index 0000000..a58ba39
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/export.h>
+
+#include "clk-regmap.h"
+
+/**
+ * clk_is_enabled_regmap - standard is_enabled() for regmap users
+ *
+ * @hw: clk to operate on
+ *
+ * Clocks that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their struct clk_regmap and then use
+ * this as their is_enabled operation, saving some code.
+ */
+int clk_is_enabled_regmap(struct clk_hw *hw)
+{
+       struct clk_regmap *rclk = to_clk_regmap(hw);
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(rclk->regmap, rclk->enable_reg, &val);
+       if (ret != 0)
+               return ret;
+
+       if (rclk->enable_is_inverted)
+               return (val & rclk->enable_mask) == 0;
+       else
+               return (val & rclk->enable_mask) != 0;
+}
+EXPORT_SYMBOL_GPL(clk_is_enabled_regmap);
+
+/**
+ * clk_enable_regmap - standard enable() for regmap users
+ *
+ * @hw: clk to operate on
+ *
+ * Clocks that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their struct clk_regmap and then use
+ * this as their enable() operation, saving some code.
+ */
+int clk_enable_regmap(struct clk_hw *hw)
+{
+       struct clk_regmap *rclk = to_clk_regmap(hw);
+       unsigned int val;
+
+       if (rclk->enable_is_inverted)
+               val = 0;
+       else
+               val = rclk->enable_mask;
+
+       return regmap_update_bits(rclk->regmap, rclk->enable_reg,
+                                 rclk->enable_mask, val);
+}
+EXPORT_SYMBOL_GPL(clk_enable_regmap);
+
+/**
+ * clk_disable_regmap - standard disable() for regmap users
+ *
+ * @hw: clk to operate on
+ *
+ * Clocks that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their struct clk_regmap and then use
+ * this as their disable() operation, saving some code.
+ */
+void clk_disable_regmap(struct clk_hw *hw)
+{
+       struct clk_regmap *rclk = to_clk_regmap(hw);
+       unsigned int val;
+
+       if (rclk->enable_is_inverted)
+               val = rclk->enable_mask;
+       else
+               val = 0;
+
+       regmap_update_bits(rclk->regmap, rclk->enable_reg, rclk->enable_mask,
+                          val);
+}
+EXPORT_SYMBOL_GPL(clk_disable_regmap);
+
+/**
+ * devm_clk_register_regmap - register a clk_regmap clock
+ *
+ * @rclk: clk to operate on
+ *
+ * Clocks that use regmap for their register I/O should register their
+ * clk_regmap struct via this function so that the regmap is initialized
+ * and so that the clock is registered with the common clock framework.
+ */
+struct clk *devm_clk_register_regmap(struct device *dev,
+                                    struct clk_regmap *rclk)
+{
+       if (dev && dev_get_regmap(dev, NULL))
+               rclk->regmap = dev_get_regmap(dev, NULL);
+       else if (dev && dev->parent)
+               rclk->regmap = dev_get_regmap(dev->parent, NULL);
+
+       return devm_clk_register(dev, &rclk->hw);
+}
+EXPORT_SYMBOL_GPL(devm_clk_register_regmap);
diff --git a/drivers/clk/qcom/clk-regmap.h b/drivers/clk/qcom/clk-regmap.h
new file mode 100644 (file)
index 0000000..491a63d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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_REGMAP_H__
+#define __QCOM_CLK_REGMAP_H__
+
+#include <linux/clk-provider.h>
+
+struct regmap;
+
+/**
+ * struct clk_regmap - regmap supporting clock
+ * @hw:                handle between common and hardware-specific interfaces
+ * @regmap:    regmap to use for regmap helpers and/or by providers
+ * @enable_reg: register when using regmap enable/disable ops
+ * @enable_mask: mask when using regmap enable/disable ops
+ * @enable_is_inverted: flag to indicate set enable_mask bits to disable
+ *                      when using clock_enable_regmap and friends APIs.
+ */
+struct clk_regmap {
+       struct clk_hw hw;
+       struct regmap *regmap;
+       unsigned int enable_reg;
+       unsigned int enable_mask;
+       bool enable_is_inverted;
+};
+#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
+
+int clk_is_enabled_regmap(struct clk_hw *hw);
+int clk_enable_regmap(struct clk_hw *hw);
+void clk_disable_regmap(struct clk_hw *hw);
+struct clk *
+devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk);
+
+#endif