Skip to contentSkip to conversation

Add clk driver to register s2mps11 clocks

PATCH Superseded Yadwinder Singh Brar 4 participants 13 messages Jul 7, 2013 – Aug 8, 2013

Subsystems (4)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover Add clk driver to register s2mps11 clocks

This series adds support to register three(AP/CP/BT) buffered 32.768 KHz outputs of mfd-s2mps11 with common clock framework and removes clocks from regulators list.

Yadwinder Singh Brar (3):
clk: s2mps11: Add support for s2mps11
mfd: sec: Add clock cell for s2mps11
mfd: s2mps11: Remove clocks from regulators list

 Documentation/devicetree/bindings/mfd/s2mps11.txt |   20 ++
 drivers/clk/Kconfig                               |    6 +
 drivers/clk/Makefile                              |    1 +
 drivers/clk/clk-s2mps11.c                         |  273 +++++++++++++++++++++
 drivers/mfd/sec-core.c                            |    4 +-
 include/linux/mfd/samsung/s2mps11.h               |    6 +-
 6 files changed, 304 insertions(+), 6 deletions(-)
 create mode 100644 drivers/clk/clk-s2mps11.c
#1 lore raw

PATCH 1/3 clk: s2mps11: Add support for s2mps11

This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz outputs of mfd-s2mps11 with common clock framework.

---
 drivers/clk/Kconfig       |    6 +
 drivers/clk/Makefile      |    1 +
 drivers/clk/clk-s2mps11.c |  273 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 280 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-s2mps11.c
drivers/clk/Kconfig +6 -0
index 0357ac4..3fdf10e 100644
@@ -65,6 +65,12 @@ config COMMON_CLK_SI5351
 	  This driver supports Silicon Labs 5351A/B/C programmable clock
 	  generators.
 
+config COMMON_CLK_S2MPS11
+	tristate "Clock driver for S2MPS11 MFD"
+	depends on MFD_SEC_CORE
+	---help---
+	  This driver supports S2MPS11 crystal oscillator clock.
+
 config CLK_TWL6040
 	tristate "External McPDM functional clock from twl6040"
 	depends on TWL6040_CORE
drivers/clk/Makefile +1 -0
index 137d3e7..5fd642d 100644
@@ -38,4 +38,5 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
+obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
 obj-$(CONFIG_CLK_TWL6040)	+= clk-twl6040.o
drivers/clk/clk-s2mps11.c new file +273 -0

273 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#2 lore raw

Re: [PATCH 1/3] clk: s2mps11: Add support for s2mps11

Gentle ping ...

Any review comments?

Quoted 320 lines · Yadwinder Singh Brar

This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz outputs of mfd-s2mps11 with common clock framework.

---
 drivers/clk/Kconfig       |    6 +
 drivers/clk/Makefile      |    1 +
 drivers/clk/clk-s2mps11.c |  273 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 280 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-s2mps11.c
drivers/clk/Kconfig +6 -0
index 0357ac4..3fdf10e 100644
@@ -65,6 +65,12 @@ config COMMON_CLK_SI5351
          This driver supports Silicon Labs 5351A/B/C programmable clock
          generators.
 
+config COMMON_CLK_S2MPS11
+       tristate "Clock driver for S2MPS11 MFD"
+       depends on MFD_SEC_CORE
+       ---help---
+         This driver supports S2MPS11 crystal oscillator clock.
+
 config CLK_TWL6040
        tristate "External McPDM functional clock from twl6040"
        depends on TWL6040_CORE
drivers/clk/Makefile +1 -0
index 137d3e7..5fd642d 100644
@@ -38,4 +38,5 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
+obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
 obj-$(CONFIG_CLK_TWL6040)      += clk-twl6040.o
drivers/clk/clk-s2mps11.c new file +273 -1
new file mode 100644
index 0000000..7be41e6
@@ -0,0 +1,273 @@
+/*
+ * clk-s2mps11.c - Clock driver for S2MPS11.
+ *
+ * Copyright (C) 2013 Samsung Electornics
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/regmap.h>
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/core.h>
+
+#define s2mps11_name(a) (a->hw.init->name)
+
+static struct clk **clk_table;
+static struct clk_onecell_data clk_data;
+
+enum {
+       S2MPS11_CLK_AP = 0,
+       S2MPS11_CLK_CP,
+       S2MPS11_CLK_BT,
+       S2MPS11_CLKS_NUM,
+};
+
+struct s2mps11_clk {
+       struct sec_pmic_dev *iodev;
+       struct clk_hw hw;
+       struct clk *clk;
+       struct clk_lookup *lookup;
+       u32 mask;
+       bool enabled;
+};
+
+static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
+{
+       return container_of(hw, struct s2mps11_clk, hw);
+}
+
+static int s2mps11_clk_prepare(struct clk_hw *hw)
+{
+       struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+       int ret;
+
+       ret = regmap_update_bits(s2mps11->iodev->regmap,
+                               S2MPS11_REG_RTC_CTRL,
+                                s2mps11->mask, s2mps11->mask);
+       if (!ret)
+               s2mps11->enabled = true;
+
+       return ret;
+}
+
+static void s2mps11_clk_unprepare(struct clk_hw *hw)
+{
+       struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+       int ret;
+
+       ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
+                          s2mps11->mask, ~s2mps11->mask);
+
+       if (!ret)
+               s2mps11->enabled = false;
+}
+
+static int s2mps11_clk_is_enabled(struct clk_hw *hw)
+{
+       struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+
+       return s2mps11->enabled;
+}
+
+static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+       if (s2mps11->enabled)
+               return 32768;
+       else
+               return 0;
+}
+
+static struct clk_ops s2mps11_clk_ops = {
+       .prepare        = s2mps11_clk_prepare,
+       .unprepare      = s2mps11_clk_unprepare,
+       .is_enabled     = s2mps11_clk_is_enabled,
+       .recalc_rate    = s2mps11_clk_recalc_rate,
+};
+
+static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
+       [S2MPS11_CLK_AP] = {
+               .name = "s2mps11_ap",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [S2MPS11_CLK_CP] = {
+               .name = "s2mps11_cp",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [S2MPS11_CLK_BT] = {
+               .name = "s2mps11_bt",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+};
+
+static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev)
+{
+       struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct device_node *clk_np;
+       int i;
+
+       if (!iodev->dev->of_node)
+               return NULL;
+
+       clk_np = of_find_node_by_name(iodev->dev->of_node, "clocks");
+       if (!clk_np) {
+               dev_err(&pdev->dev, "could not find clock sub-node\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) *
+                                S2MPS11_CLKS_NUM, GFP_KERNEL);
+       if (!clk_table)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < S2MPS11_CLKS_NUM; i++)
+               of_property_read_string_index(clk_np, "clock-output-names", i,
+                               &s2mps11_clks_init[i].name);
+
+       return clk_np;
+}
+
+static int s2mps11_clk_probe(struct platform_device *pdev)
+{
+       struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
+       struct device_node *clk_np = NULL;
+       int i, ret = 0;
+       u32 val;
+
+       s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
+                                       S2MPS11_CLKS_NUM, GFP_KERNEL);
+       if (!s2mps11_clks)
+               return -ENOMEM;
+
+       s2mps11_clk = s2mps11_clks;
+
+       clk_np = s2mps11_clk_parse_dt(pdev);
+       if (IS_ERR(clk_np))
+               return PTR_ERR(clk_np);
+
+       for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
+               s2mps11_clk->iodev = iodev;
+               s2mps11_clk->hw.init = &s2mps11_clks_init[i];
+               s2mps11_clk->mask = 1 << i;
+
+               ret = regmap_read(s2mps11_clk->iodev->regmap,
+                                 S2MPS11_REG_RTC_CTRL, &val);
+               if (ret < 0)
+                       goto err_reg;
+
+               s2mps11_clk->enabled = val & s2mps11_clk->mask;
+
+               s2mps11_clk->clk = devm_clk_register(&pdev->dev,
+                                                       &s2mps11_clk->hw);
+               if (IS_ERR(s2mps11_clk->clk)) {
+                       dev_err(&pdev->dev, "Fail to register : %s\n",
+                                               s2mps11_name(s2mps11_clk));
+                       ret = PTR_ERR(s2mps11_clk->clk);
+                       goto err_reg;
+               }
+
+               s2mps11_clk->lookup = devm_kzalloc(&pdev->dev,
+                                       sizeof(struct clk_lookup), GFP_KERNEL);
+               if (!s2mps11_clk->lookup) {
+                       ret = -ENOMEM;
+                       goto err_lup;
+               }
+
+               s2mps11_clk->lookup->con_id = s2mps11_name(s2mps11_clk);
+               s2mps11_clk->lookup->clk = s2mps11_clk->clk;
+
+               clkdev_add(s2mps11_clk->lookup);
+       }
+
+       if (clk_table) {
+               for (i = 0; i < S2MPS11_CLKS_NUM; i++)
+                       clk_table[i] = s2mps11_clks[i].clk;
+
+               clk_data.clks = clk_table;
+               clk_data.clk_num = S2MPS11_CLKS_NUM;
+               of_clk_add_provider(clk_np, of_clk_src_onecell_get, &clk_data);
+       }
+
+       platform_set_drvdata(pdev, s2mps11_clks);
+
+       return ret;
+err_lup:
+       devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
+err_reg:
+       while (s2mps11_clk > s2mps11_clks) {
+               if (s2mps11_clk->lookup) {
+                       clkdev_drop(s2mps11_clk->lookup);
+                       devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
+               }
+               s2mps11_clk--;
+       }
+
+       return ret;
+}
+
+static int s2mps11_clk_remove(struct platform_device *pdev)
+{
+       struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < S2MPS11_CLKS_NUM; i++)
+               clkdev_drop(s2mps11_clks[i].lookup);
+
+       return 0;
+}
+
+static const struct platform_device_id s2mps11_clk_id[] = {
+       { "s2mps11-clk", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
+
+static struct platform_driver s2mps11_clk_driver = {
+       .driver = {
+               .name  = "s2mps11-clk",
+               .owner = THIS_MODULE,
+       },
+       .probe = s2mps11_clk_probe,
+       .remove = s2mps11_clk_remove,
+       .id_table = s2mps11_clk_id,
+};
+
+static int __init s2mps11_clk_init(void)
+{
+       return platform_driver_register(&s2mps11_clk_driver);
+}
+subsys_initcall(s2mps11_clk_init);
+
+static void __init s2mps11_clk_cleanup(void)
+{
+       platform_driver_unregister(&s2mps11_clk_driver);
+}
+module_exit(s2mps11_clk_cleanup);
+
+MODULE_DESCRIPTION("S2MPS11 Clock Driver");
+MODULE_AUTHOR("Yadwinder Singh Brar <[email protected]>");
+MODULE_LICENSE("GPL");
--

1.7.0.4

#3 lore raw

Re: [PATCH 1/3] clk: s2mps11: Add support for s2mps11

In reply to Yadwinder Singh Brar

Quoting Yadwinder Singh Brar (2013-07-07 04:44:20)

Quoted 4 lines

This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz outputs of mfd-s2mps11 with common clock framework.

Yadwinder,

Looks good to me with the exception of a binding description document. Can you provide one and squash it into this commit?

Thanks,
Mike

Quoted 315 lines
---
 drivers/clk/Kconfig       |    6 +
 drivers/clk/Makefile      |    1 +
 drivers/clk/clk-s2mps11.c |  273 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 280 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-s2mps11.c
drivers/clk/Kconfig +6 -0
index 0357ac4..3fdf10e 100644
@@ -65,6 +65,12 @@ config COMMON_CLK_SI5351
          This driver supports Silicon Labs 5351A/B/C programmable clock
          generators.
 
+config COMMON_CLK_S2MPS11
+       tristate "Clock driver for S2MPS11 MFD"
+       depends on MFD_SEC_CORE
+       ---help---
+         This driver supports S2MPS11 crystal oscillator clock.
+
 config CLK_TWL6040
        tristate "External McPDM functional clock from twl6040"
        depends on TWL6040_CORE
drivers/clk/Makefile +1 -0
index 137d3e7..5fd642d 100644
@@ -38,4 +38,5 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
+obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
 obj-$(CONFIG_CLK_TWL6040)      += clk-twl6040.o
drivers/clk/clk-s2mps11.c new file +273 -0
new file mode 100644
index 0000000..7be41e6
@@ -0,0 +1,273 @@
+/*
+ * clk-s2mps11.c - Clock driver for S2MPS11.
+ *
+ * Copyright (C) 2013 Samsung Electornics
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/regmap.h>
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/core.h>
+
+#define s2mps11_name(a) (a->hw.init->name)
+
+static struct clk **clk_table;
+static struct clk_onecell_data clk_data;
+
+enum {
+       S2MPS11_CLK_AP = 0,
+       S2MPS11_CLK_CP,
+       S2MPS11_CLK_BT,
+       S2MPS11_CLKS_NUM,
+};
+
+struct s2mps11_clk {
+       struct sec_pmic_dev *iodev;
+       struct clk_hw hw;
+       struct clk *clk;
+       struct clk_lookup *lookup;
+       u32 mask;
+       bool enabled;
+};
+
+static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
+{
+       return container_of(hw, struct s2mps11_clk, hw);
+}
+
+static int s2mps11_clk_prepare(struct clk_hw *hw)
+{
+       struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+       int ret;
+
+       ret = regmap_update_bits(s2mps11->iodev->regmap,
+                               S2MPS11_REG_RTC_CTRL,
+                                s2mps11->mask, s2mps11->mask);
+       if (!ret)
+               s2mps11->enabled = true;
+
+       return ret;
+}
+
+static void s2mps11_clk_unprepare(struct clk_hw *hw)
+{
+       struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+       int ret;
+
+       ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
+                          s2mps11->mask, ~s2mps11->mask);
+
+       if (!ret)
+               s2mps11->enabled = false;
+}
+
+static int s2mps11_clk_is_enabled(struct clk_hw *hw)
+{
+       struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+
+       return s2mps11->enabled;
+}
+
+static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+       if (s2mps11->enabled)
+               return 32768;
+       else
+               return 0;
+}
+
+static struct clk_ops s2mps11_clk_ops = {
+       .prepare        = s2mps11_clk_prepare,
+       .unprepare      = s2mps11_clk_unprepare,
+       .is_enabled     = s2mps11_clk_is_enabled,
+       .recalc_rate    = s2mps11_clk_recalc_rate,
+};
+
+static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
+       [S2MPS11_CLK_AP] = {
+               .name = "s2mps11_ap",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [S2MPS11_CLK_CP] = {
+               .name = "s2mps11_cp",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [S2MPS11_CLK_BT] = {
+               .name = "s2mps11_bt",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+};
+
+static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev)
+{
+       struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct device_node *clk_np;
+       int i;
+
+       if (!iodev->dev->of_node)
+               return NULL;
+
+       clk_np = of_find_node_by_name(iodev->dev->of_node, "clocks");
+       if (!clk_np) {
+               dev_err(&pdev->dev, "could not find clock sub-node\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) *
+                                S2MPS11_CLKS_NUM, GFP_KERNEL);
+       if (!clk_table)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < S2MPS11_CLKS_NUM; i++)
+               of_property_read_string_index(clk_np, "clock-output-names", i,
+                               &s2mps11_clks_init[i].name);
+
+       return clk_np;
+}
+
+static int s2mps11_clk_probe(struct platform_device *pdev)
+{
+       struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
+       struct device_node *clk_np = NULL;
+       int i, ret = 0;
+       u32 val;
+
+       s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
+                                       S2MPS11_CLKS_NUM, GFP_KERNEL);
+       if (!s2mps11_clks)
+               return -ENOMEM;
+
+       s2mps11_clk = s2mps11_clks;
+
+       clk_np = s2mps11_clk_parse_dt(pdev);
+       if (IS_ERR(clk_np))
+               return PTR_ERR(clk_np);
+
+       for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
+               s2mps11_clk->iodev = iodev;
+               s2mps11_clk->hw.init = &s2mps11_clks_init[i];
+               s2mps11_clk->mask = 1 << i;
+
+               ret = regmap_read(s2mps11_clk->iodev->regmap,
+                                 S2MPS11_REG_RTC_CTRL, &val);
+               if (ret < 0)
+                       goto err_reg;
+
+               s2mps11_clk->enabled = val & s2mps11_clk->mask;
+
+               s2mps11_clk->clk = devm_clk_register(&pdev->dev,
+                                                       &s2mps11_clk->hw);
+               if (IS_ERR(s2mps11_clk->clk)) {
+                       dev_err(&pdev->dev, "Fail to register : %s\n",
+                                               s2mps11_name(s2mps11_clk));
+                       ret = PTR_ERR(s2mps11_clk->clk);
+                       goto err_reg;
+               }
+
+               s2mps11_clk->lookup = devm_kzalloc(&pdev->dev,
+                                       sizeof(struct clk_lookup), GFP_KERNEL);
+               if (!s2mps11_clk->lookup) {
+                       ret = -ENOMEM;
+                       goto err_lup;
+               }
+
+               s2mps11_clk->lookup->con_id = s2mps11_name(s2mps11_clk);
+               s2mps11_clk->lookup->clk = s2mps11_clk->clk;
+
+               clkdev_add(s2mps11_clk->lookup);
+       }
+
+       if (clk_table) {
+               for (i = 0; i < S2MPS11_CLKS_NUM; i++)
+                       clk_table[i] = s2mps11_clks[i].clk;
+
+               clk_data.clks = clk_table;
+               clk_data.clk_num = S2MPS11_CLKS_NUM;
+               of_clk_add_provider(clk_np, of_clk_src_onecell_get, &clk_data);
+       }
+
+       platform_set_drvdata(pdev, s2mps11_clks);
+
+       return ret;
+err_lup:
+       devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
+err_reg:
+       while (s2mps11_clk > s2mps11_clks) {
+               if (s2mps11_clk->lookup) {
+                       clkdev_drop(s2mps11_clk->lookup);
+                       devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
+               }
+               s2mps11_clk--;
+       }
+
+       return ret;
+}
+
+static int s2mps11_clk_remove(struct platform_device *pdev)
+{
+       struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < S2MPS11_CLKS_NUM; i++)
+               clkdev_drop(s2mps11_clks[i].lookup);
+
+       return 0;
+}
+
+static const struct platform_device_id s2mps11_clk_id[] = {
+       { "s2mps11-clk", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
+
+static struct platform_driver s2mps11_clk_driver = {
+       .driver = {
+               .name  = "s2mps11-clk",
+               .owner = THIS_MODULE,
+       },
+       .probe = s2mps11_clk_probe,
+       .remove = s2mps11_clk_remove,
+       .id_table = s2mps11_clk_id,
+};
+
+static int __init s2mps11_clk_init(void)
+{
+       return platform_driver_register(&s2mps11_clk_driver);
+}
+subsys_initcall(s2mps11_clk_init);
+
+static void __init s2mps11_clk_cleanup(void)
+{
+       platform_driver_unregister(&s2mps11_clk_driver);
+}
+module_exit(s2mps11_clk_cleanup);
+
+MODULE_DESCRIPTION("S2MPS11 Clock Driver");
+MODULE_AUTHOR("Yadwinder Singh Brar <[email protected]>");
+MODULE_LICENSE("GPL");
Signature · 1 line
1.7.0.4
#4 lore raw

Re: [PATCH 1/3] clk: s2mps11: Add support for s2mps11

Hi Mike,

Quoted 11 lines · Mike Turquette

Quoting Yadwinder Singh Brar (2013-07-07 04:44:20)

Quoted 4 lines

This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz outputs of mfd-s2mps11 with common clock framework.

Yadwinder,

Looks good to me with the exception of a binding description document. Can you provide one and squash it into this commit?

Binding description is provided in next patch :
[PATCH 2/3] mfd: sec: Add clock cell for s2mps11 :
https://lkml.org/lkml/2013/7/16/228

Since its a MFD, so i preferred to add documentation in same file under mfd, same was done for regulators also.
If its fine with you then, I think that patch can go through MFD tree as same file is touched in for-next of MFD tree.

Thanks,
Yadwinder

#5 lore raw

PATCH 1/3 clk: s2mps11: Add support for s2mps11

Quoting Yadwinder Singh Brar (2013-08-05 21:25:44)

Quoted 15 lines

Hi Mike,

Quoted 11 lines · Mike Turquette

Quoting Yadwinder Singh Brar (2013-07-07 04:44:20)

Quoted 4 lines

This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz outputs of mfd-s2mps11 with common clock framework.

Yadwinder,

Looks good to me with the exception of a binding description document. Can you provide one and squash it into this commit?

Quoted 8 lines

Binding description is provided in next patch :
[PATCH 2/3] mfd: sec: Add clock cell for s2mps11 :
https://lkml.org/lkml/2013/7/16/228

Since its a MFD, so i preferred to add documentation in same file under mfd, same was done for regulators also.
If its fine with you then, I think that patch can go through MFD tree as same file is touched in for-next of MFD tree.

I see. Ok I've taken patch #1 into clk-next.

Regards,
Mike

Quoted 4 lines

Thanks,
Yadwinder

#6 lore raw

Re: [PATCH 1/3] clk: s2mps11: Add support for s2mps11

Quoted 20 lines · Mike Turquette

Quoting Yadwinder Singh Brar (2013-08-05 21:25:44)

Quoted 19 lines

Hi Mike,

Quoted 11 lines · Mike Turquette

Quoting Yadwinder Singh Brar (2013-07-07 04:44:20)

Quoted 4 lines

This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz outputs of mfd-s2mps11 with common clock framework.

Yadwinder,

Looks good to me with the exception of a binding description document. Can you provide one and squash it into this commit?

Binding description is provided in next patch :
[PATCH 2/3] mfd: sec: Add clock cell for s2mps11 :
https://lkml.org/lkml/2013/7/16/228

Quoted 6 lines
Quoted 4 lines

Since its a MFD, so i preferred to add documentation in same file under mfd, same was done for regulators also.
If its fine with you then, I think that patch can go through MFD tree as same file is touched in for-next of MFD tree.

I see. Ok I've taken patch #1 into clk-next.

Can you review the bindings in:

mfd: sec: Add clock cell for s2mps11

... please Mike?

Signature · 4 lines
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
#7 lore raw

PATCH 2/3 mfd: sec: Add clock cell for s2mps11

In reply to Yadwinder Singh Brar

This patch adds clock to list of mfd cells for s2mps11 and DT documentation for clock part.

---
 Documentation/devicetree/bindings/mfd/s2mps11.txt |   20 ++++++++++++++++++++
 drivers/mfd/sec-core.c                            |    4 +++-
 2 files changed, 23 insertions(+), 1 deletions(-)
Documentation/devicetree/bindings/mfd/s2mps11.txt +20 -0
index 36269c4..e41dd16 100644
@@ -16,6 +16,21 @@ Optional properties:
 - interrupts: Interrupt specifiers for interrupt sources.
 
 Optional nodes:
+- clocks: s2mps11 provides three(AP/CP/BT) buffered 32.768 KHz outputs, so to
+  register these as clocks with common clock framework instantiate a sub-node
+  named "clocks". It uses the common clock binding documented in :
+  [Documentation/devicetree/bindings/clock/clock-bindings.txt]
+  - #clock-cells: should be 1.
+
+  - The following is the list of clocks generated by the controller. Each clock
+    is assigned an identifier and client nodes use this identifier to specify
+    the clock which they consume.
+    Clock               ID
+    ----------------------
+    32KhzAP		0
+    32KhzCP		1
+    32KhzBT		2
+
 - regulators: The regulators of s2mps11 that have to be instantiated should be
 included in a sub-node named 'regulators'. Regulator nodes included in this
 sub-node should be of the format as listed below.
@@ -55,6 +70,11 @@ Example:
 		compatible = "samsung,s2mps11-pmic";
 		reg = <0x66>;
 
+		s2m_osc: clocks{
+			#clock-cells = 1;
+			clock-output-names = "xx", "yy", "zz";
+		};
+
 		regulators {
 			ldo1_reg: LDO1 {
 				regulator-name = "VDD_ABB_3.3V";
drivers/mfd/sec-core.c +3 -1
index 760da8a..eaee5ec 100644
@@ -58,7 +58,9 @@ static struct mfd_cell s5m8767_devs[] = {
 static struct mfd_cell s2mps11_devs[] = {
 	{
 		.name = "s2mps11-pmic",
-	},
+	}, {
+		.name = "s2mps11-clk",
+	}
 };
 
 #ifdef CONFIG_OF
Signature · 1 line
1.7.0.4
Acked-by on v1 2/3
#8 lore raw

Re: [PATCH 2/3] mfd: sec: Add clock cell for s2mps11

Quoted 8 lines · Yadwinder Singh Brar

This patch adds clock to list of mfd cells for s2mps11 and DT documentation for clock part.

---
 Documentation/devicetree/bindings/mfd/s2mps11.txt |   20 ++++++++++++++++++++
 drivers/mfd/sec-core.c                            |    4 +++-
 2 files changed, 23 insertions(+), 1 deletions(-)

For drivers/mfd/sec-core.c:

Signature · 4 lines
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
Reviewed-by on v1 2/3
#9 lore raw

Re: [PATCH 2/3] mfd: sec: Add clock cell for s2mps11

In reply to Yadwinder Singh Brar

Quoting Yadwinder Singh Brar (2013-07-07 04:44:21)

Quoted 4 lines

This patch adds clock to list of mfd cells for s2mps11 and DT documentation for clock part.

Quoted 60 lines
---
 Documentation/devicetree/bindings/mfd/s2mps11.txt |   20 ++++++++++++++++++++
 drivers/mfd/sec-core.c                            |    4 +++-
 2 files changed, 23 insertions(+), 1 deletions(-)
Documentation/devicetree/bindings/mfd/s2mps11.txt +20 -0
index 36269c4..e41dd16 100644
@@ -16,6 +16,21 @@ Optional properties:
 - interrupts: Interrupt specifiers for interrupt sources.
 
 Optional nodes:
+- clocks: s2mps11 provides three(AP/CP/BT) buffered 32.768 KHz outputs, so to
+  register these as clocks with common clock framework instantiate a sub-node
+  named "clocks". It uses the common clock binding documented in :
+  [Documentation/devicetree/bindings/clock/clock-bindings.txt]
+  - #clock-cells: should be 1.
+
+  - The following is the list of clocks generated by the controller. Each clock
+    is assigned an identifier and client nodes use this identifier to specify
+    the clock which they consume.
+    Clock               ID
+    ----------------------
+    32KhzAP            0
+    32KhzCP            1
+    32KhzBT            2
+
 - regulators: The regulators of s2mps11 that have to be instantiated should be
 included in a sub-node named 'regulators'. Regulator nodes included in this
 sub-node should be of the format as listed below.
@@ -55,6 +70,11 @@ Example:
                compatible = "samsung,s2mps11-pmic";
                reg = <0x66>;
 
+               s2m_osc: clocks{
+                       #clock-cells = 1;
+                       clock-output-names = "xx", "yy", "zz";
+               };
+
                regulators {
                        ldo1_reg: LDO1 {
                                regulator-name = "VDD_ABB_3.3V";
drivers/mfd/sec-core.c +3 -1
index 760da8a..eaee5ec 100644
@@ -58,7 +58,9 @@ static struct mfd_cell s5m8767_devs[] = {
 static struct mfd_cell s2mps11_devs[] = {
        {
                .name = "s2mps11-pmic",
-       },
+       }, {
+               .name = "s2mps11-clk",
+       }
 };
 
 #ifdef CONFIG_OF
Signature · 1 line
1.7.0.4
#10 lore raw

Re: [PATCH 2/3] mfd: sec: Add clock cell for s2mps11

Quoted 7 lines · Mike Turquette

Quoting Yadwinder Singh Brar (2013-07-07 04:44:21)

Quoted 4 lines

This patch adds clock to list of mfd cells for s2mps11 and DT documentation for clock part.

Thanks Mike.

Patch applied, thanks.

Signature · 4 lines
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
#11 lore raw

PATCH 3/3 mfd: s2mps11: Remove clocks from regulators list

In reply to Yadwinder Singh Brar

Since these are fixed rate clocks which are registered with common clock framework so remove these from list of regulators which were unnecessarily incrementing the count(S2MPS11_REGULATOR_MAX) of regulators.

---
 include/linux/mfd/samsung/s2mps11.h |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)
include/linux/mfd/samsung/s2mps11.h +1 -5
index d0d52ea..b3ddf98 100644
@@ -167,11 +167,8 @@ enum s2mps11_regulators {
 	S2MPS11_BUCK8,
 	S2MPS11_BUCK9,
 	S2MPS11_BUCK10,
-	S2MPS11_AP_EN32KHZ,
-	S2MPS11_CP_EN32KHZ,
-	S2MPS11_BT_EN32KHZ,
 
-	S2MPS11_REG_MAX,
+	S2MPS11_REGULATOR_MAX,
 };
 
 #define S2MPS11_BUCK_MIN1	600000
@@ -203,6 +200,5 @@ enum s2mps11_regulators {
 #define S2MPS11_BUCK4_RAMP_EN_SHIFT	1
 #define S2MPS11_BUCK6_RAMP_EN_SHIFT	0
 #define S2MPS11_PMIC_EN_SHIFT	6
-#define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3)
 
 #endif /*  __LINUX_MFD_S2MPS11_H */
Signature · 1 line
1.7.0.4
#12 lore raw

Re: [PATCH 3/3] mfd: s2mps11: Remove clocks from regulators list

Quoted 14 lines · Yadwinder Singh Brar

Since these are fixed rate clocks which are registered with common clock framework so remove these from list of regulators which were unnecessarily incrementing the count(S2MPS11_REGULATOR_MAX) of regulators.

---
 include/linux/mfd/samsung/s2mps11.h |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)
include/linux/mfd/samsung/s2mps11.h +0 -0
index d0d52ea..b3ddf98 100644

include/linux/mfd/samsung/s2mps11.h enum s2mps11_regulators { · line 172

Quoted 6 lines
include/linux/mfd/samsung/s2mps11.h +0 -3
@@ -167,11 +167,8 @@ enum s2mps11_regulators {
 	S2MPS11_BUCK8,
 	S2MPS11_BUCK9,
 	S2MPS11_BUCK10,
-	S2MPS11_AP_EN32KHZ,
-	S2MPS11_CP_EN32KHZ,
-	S2MPS11_BT_EN32KHZ,

These aren't mentioned anywhere else in the kernel, so I'll just apply the patch.

Quoted 12 lines
include/linux/mfd/samsung/s2mps11.h +1 -2
-	S2MPS11_REG_MAX,
+	S2MPS11_REGULATOR_MAX,
 };
 
 #define S2MPS11_BUCK_MIN1	600000
@@ -203,6 +200,5 @@ enum s2mps11_regulators {
 #define S2MPS11_BUCK4_RAMP_EN_SHIFT	1
 #define S2MPS11_BUCK6_RAMP_EN_SHIFT	0
 #define S2MPS11_PMIC_EN_SHIFT	6
-#define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3)
 
 #endif /*  __LINUX_MFD_S2MPS11_H */
Signature · 4 lines
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog