Re: [PATCH V7 1/2] clk: qcom: Add spmi_pmic clock divider support

2017-12-06 Thread Stephen Boyd
On 11/21, Tirupathi Reddy wrote:
> Clkdiv module provides a clock output on the PMIC with CXO as
> the source. This clock can be routed through PMIC GPIOs. Add
> a device driver to configure this clkdiv module.
> 
> Signed-off-by: Stephen Boyd 
> Signed-off-by: Tirupathi Reddy 
> ---

Applied to clk-next

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH V7 1/2] clk: qcom: Add spmi_pmic clock divider support

2017-12-06 Thread Stephen Boyd
On 11/21, Tirupathi Reddy wrote:
> Clkdiv module provides a clock output on the PMIC with CXO as
> the source. This clock can be routed through PMIC GPIOs. Add
> a device driver to configure this clkdiv module.
> 
> Signed-off-by: Stephen Boyd 
> Signed-off-by: Tirupathi Reddy 
> ---

Applied to clk-next

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH V7 1/2] clk: qcom: Add spmi_pmic clock divider support

2017-11-21 Thread Tirupathi Reddy
Clkdiv module provides a clock output on the PMIC with CXO as
the source. This clock can be routed through PMIC GPIOs. Add
a device driver to configure this clkdiv module.

Signed-off-by: Stephen Boyd 
Signed-off-by: Tirupathi Reddy 
---
 drivers/clk/qcom/Kconfig |   9 ++
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-spmi-pmic-div.c | 302 +++
 3 files changed, 312 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-spmi-pmic-div.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 9f6c278..20b5d6f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -196,3 +196,12 @@ config MSM_MMCC_8996
  Support for the multimedia clock controller on msm8996 devices.
  Say Y if you want to support multimedia devices such as display,
  graphics, video encode/decode, camera, etc.
+
+config SPMI_PMIC_CLKDIV
+   tristate "SPMI PMIC clkdiv Support"
+   depends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST
+   help
+ This driver supports the clkdiv functionality on the Qualcomm
+ Technologies, Inc. SPMI PMIC. It configures the frequency of
+ clkdiv outputs of the PMIC. These clocks are typically wired
+ through alternate functions on GPIO pins.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 26410d3..602af38 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
+obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/clk-spmi-pmic-div.c 
b/drivers/clk/qcom/clk-spmi-pmic-div.c
new file mode 100644
index 000..8672ab8
--- /dev/null
+++ b/drivers/clk/qcom/clk-spmi-pmic-div.c
@@ -0,0 +1,302 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define REG_DIV_CTL1   0x43
+#define DIV_CTL1_DIV_FACTOR_MASK   GENMASK(2, 0)
+
+#define REG_EN_CTL 0x46
+#define REG_EN_MASKBIT(7)
+
+struct clkdiv {
+   struct regmap   *regmap;
+   u16 base;
+   spinlock_t  lock;
+
+   struct clk_hw   hw;
+   unsigned intcxo_period_ns;
+};
+
+static inline struct clkdiv *to_clkdiv(struct clk_hw *hw)
+{
+   return container_of(hw, struct clkdiv, hw);
+}
+
+static inline unsigned int div_factor_to_div(unsigned int div_factor)
+{
+   if (!div_factor)
+   div_factor = 1;
+
+   return 1 << (div_factor - 1);
+}
+
+static inline unsigned int div_to_div_factor(unsigned int div)
+{
+   return min(ilog2(div) + 1, 7);
+}
+
+static bool is_spmi_pmic_clkdiv_enabled(struct clkdiv *clkdiv)
+{
+   unsigned int val = 0;
+
+   regmap_read(clkdiv->regmap, clkdiv->base + REG_EN_CTL, );
+
+   return val & REG_EN_MASK;
+}
+
+static int
+__spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv, bool enable,
+   unsigned int div_factor)
+{
+   int ret;
+   unsigned int ns = clkdiv->cxo_period_ns;
+   unsigned int div = div_factor_to_div(div_factor);
+
+   ret = regmap_update_bits(clkdiv->regmap, clkdiv->base + REG_EN_CTL,
+REG_EN_MASK, enable ? REG_EN_MASK : 0);
+   if (ret)
+   return ret;
+
+   if (enable)
+   ndelay((2 + 3 * div) * ns);
+   else
+   ndelay(3 * div * ns);
+
+   return 0;
+}
+
+static int spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv, bool 
enable)
+{
+   unsigned int div_factor;
+
+   regmap_read(clkdiv->regmap, clkdiv->base + REG_DIV_CTL1, _factor);
+   div_factor &= DIV_CTL1_DIV_FACTOR_MASK;
+
+   return __spmi_pmic_clkdiv_set_enable_state(clkdiv, enable, div_factor);
+}
+
+static int clk_spmi_pmic_div_enable(struct clk_hw *hw)
+{
+   struct clkdiv *clkdiv = to_clkdiv(hw);
+   unsigned long flags;
+   int ret;
+
+   spin_lock_irqsave(>lock, flags);
+   ret = spmi_pmic_clkdiv_set_enable_state(clkdiv, true);
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
+static void 

[PATCH V7 1/2] clk: qcom: Add spmi_pmic clock divider support

2017-11-21 Thread Tirupathi Reddy
Clkdiv module provides a clock output on the PMIC with CXO as
the source. This clock can be routed through PMIC GPIOs. Add
a device driver to configure this clkdiv module.

Signed-off-by: Stephen Boyd 
Signed-off-by: Tirupathi Reddy 
---
 drivers/clk/qcom/Kconfig |   9 ++
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-spmi-pmic-div.c | 302 +++
 3 files changed, 312 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-spmi-pmic-div.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 9f6c278..20b5d6f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -196,3 +196,12 @@ config MSM_MMCC_8996
  Support for the multimedia clock controller on msm8996 devices.
  Say Y if you want to support multimedia devices such as display,
  graphics, video encode/decode, camera, etc.
+
+config SPMI_PMIC_CLKDIV
+   tristate "SPMI PMIC clkdiv Support"
+   depends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST
+   help
+ This driver supports the clkdiv functionality on the Qualcomm
+ Technologies, Inc. SPMI PMIC. It configures the frequency of
+ clkdiv outputs of the PMIC. These clocks are typically wired
+ through alternate functions on GPIO pins.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 26410d3..602af38 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
+obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/clk-spmi-pmic-div.c 
b/drivers/clk/qcom/clk-spmi-pmic-div.c
new file mode 100644
index 000..8672ab8
--- /dev/null
+++ b/drivers/clk/qcom/clk-spmi-pmic-div.c
@@ -0,0 +1,302 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define REG_DIV_CTL1   0x43
+#define DIV_CTL1_DIV_FACTOR_MASK   GENMASK(2, 0)
+
+#define REG_EN_CTL 0x46
+#define REG_EN_MASKBIT(7)
+
+struct clkdiv {
+   struct regmap   *regmap;
+   u16 base;
+   spinlock_t  lock;
+
+   struct clk_hw   hw;
+   unsigned intcxo_period_ns;
+};
+
+static inline struct clkdiv *to_clkdiv(struct clk_hw *hw)
+{
+   return container_of(hw, struct clkdiv, hw);
+}
+
+static inline unsigned int div_factor_to_div(unsigned int div_factor)
+{
+   if (!div_factor)
+   div_factor = 1;
+
+   return 1 << (div_factor - 1);
+}
+
+static inline unsigned int div_to_div_factor(unsigned int div)
+{
+   return min(ilog2(div) + 1, 7);
+}
+
+static bool is_spmi_pmic_clkdiv_enabled(struct clkdiv *clkdiv)
+{
+   unsigned int val = 0;
+
+   regmap_read(clkdiv->regmap, clkdiv->base + REG_EN_CTL, );
+
+   return val & REG_EN_MASK;
+}
+
+static int
+__spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv, bool enable,
+   unsigned int div_factor)
+{
+   int ret;
+   unsigned int ns = clkdiv->cxo_period_ns;
+   unsigned int div = div_factor_to_div(div_factor);
+
+   ret = regmap_update_bits(clkdiv->regmap, clkdiv->base + REG_EN_CTL,
+REG_EN_MASK, enable ? REG_EN_MASK : 0);
+   if (ret)
+   return ret;
+
+   if (enable)
+   ndelay((2 + 3 * div) * ns);
+   else
+   ndelay(3 * div * ns);
+
+   return 0;
+}
+
+static int spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv, bool 
enable)
+{
+   unsigned int div_factor;
+
+   regmap_read(clkdiv->regmap, clkdiv->base + REG_DIV_CTL1, _factor);
+   div_factor &= DIV_CTL1_DIV_FACTOR_MASK;
+
+   return __spmi_pmic_clkdiv_set_enable_state(clkdiv, enable, div_factor);
+}
+
+static int clk_spmi_pmic_div_enable(struct clk_hw *hw)
+{
+   struct clkdiv *clkdiv = to_clkdiv(hw);
+   unsigned long flags;
+   int ret;
+
+   spin_lock_irqsave(>lock, flags);
+   ret = spmi_pmic_clkdiv_set_enable_state(clkdiv, true);
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
+static void clk_spmi_pmic_div_disable(struct clk_hw *hw)
+{
+