Skip to contentSkip to conversation

clk: palmas: add clock driver for palmas

PATCH Superseded Laxman Dewangan 3 participants 5 messages Oct 7, 2013 – Oct 8, 2013

Subsystems (2)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 clk: palmas: add clock driver for palmas

Palmas devices has two clock output CLK32K_KG and CLK32K_KG_AUDIO which can be nebale/disable through software.

Add clock driver support for the Palmas 32k clocks.

---
Changes from V1:
- Call prepare if the clk is needed for boot-enable or sleep control.
- change is_enabled to is_prepared.
- Added ops palmas_clks_recalc_rate.
- Added of_clk_add_provider().

 .../devicetree/bindings/clock/clk-palmas.txt       |   45 +++
 drivers/clk/Kconfig                                |    7 +
 drivers/clk/Makefile                               |    2 +
 drivers/clk/clk-palmas.c                           |  336 ++++++++++++++++++++
 4 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/clk-palmas.txt
 create mode 100644 drivers/clk/clk-palmas.c
Documentation/devicetree/bindings/clock/clk-palmas.txt new file +45 -0
new file mode 100644
index 0000000..c247538
@@ -0,0 +1,45 @@
+* Palmas 32KHz clocks *
+
+Palmas device has two clock output pins for 32KHz, KG and KG_AUDIO.
+
+This binding uses the common clock binding ./clock-bindings.txt.
+
+Clock 32KHz KG is output 0 of the driver and clock 32KHz is output 1.
+
+Required properties:
+- compatible : shall be "ti,palmas-clk".
+- #clock-cells : from common clock binding; shall be set to 1.
+
+Optional subnode:
+	The clock node has optional subnode to provide the init configuration of
+	clocks like boot enable, sleep control.
+
+	The subnode name is fixed and it should be
+		clk32k_kg for the 32KHz KG clock.
+		clk32k_kg_audio for the 32KHz KG_AUDIO clock.
+
+	Optional subnode properties:
+	ti,clock-boot-enable: Enable clock at the time of booting.
+	ti,external-sleep-control: The clock is enable/disabled by state
+		of external enable input pins ENABLE, ENABLE2 and NSLEEP.
+		The valid value for the external pins are:
+			1 for ENABLE1
+			2 for ENABLE2
+			3 for NSLEEP.
+		Option 0 or missing this property means the clock is
+		enabled/disabled via register access and these pins do
+		not have any control.
+
+Example:
+	clock {
+		compatible = "ti,palmas-clk";
+		#clock-cells = <1>;
+		clk32k_kg {
+			ti,clock-boot-enable;
+			ti,external-sleep-control = <3>;
+		};
+
+		clk32k_kg_audio {
+			ti,clock-boot-enable;
+		};
+	};
drivers/clk/Kconfig +7 -0
index 279407a..6b8c233 100644
@@ -93,6 +93,13 @@ config CLK_PPC_CORENET
 	  This adds the clock driver support for Freescale PowerPC corenet
 	  platforms using common clock framework.
 
+config COMMON_CLK_PALMAS
+	tristate "Clock driver for TI Palmas devices"
+	depends on MFD_PALMAS
+	---help---
+	  This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO
+	  using common clock framework.
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
drivers/clk/Makefile +2 -0
index 7b11106..f168ff7 100644
@@ -43,3 +43,5 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
 obj-$(CONFIG_CLK_TWL6040)	+= clk-twl6040.o
 obj-$(CONFIG_CLK_PPC_CORENET)	+= clk-ppc-corenet.o
+obj-$(CONFIG_COMMON_CLK_PALMAS)	+= clk-palmas.o
+obj-y += clk-test.o
drivers/clk/clk-palmas.c new file +336 -0

336 lines not on this page · raw message

Signature · 1 line
1.7.1.1
#1 lore raw

drivers/clk/Makefile obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o · line 47

Quoted 9 lines · Laxman Dewangan
drivers/clk/Makefile +2 -0
@@ -43,3 +43,5 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
  obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
  obj-$(CONFIG_CLK_TWL6040)	+= clk-twl6040.o
  obj-$(CONFIG_CLK_PPC_CORENET)	+= clk-ppc-corenet.o
+obj-$(CONFIG_COMMON_CLK_PALMAS)	+= clk-palmas.o
+obj-y += clk-test.o

Sorry, silly mistake, the line

+obj-y += clk-test.o

is not require. This was done for testing only.

I will respin the patch but wait for some more feedback if any to add on next version.

Thanks,
Laxman

#2 lore raw

PATCH v2 1/1 clk: palmas: add clock driver for palmas

In reply to Laxman Dewangan

Quoting Laxman Dewangan (2013-10-07 07:05:51)

Quoted 300 lines

Palmas devices has two clock output CLK32K_KG and CLK32K_KG_AUDIO which can be nebale/disable through software.

Add clock driver support for the Palmas 32k clocks.

---
Changes from V1:
- Call prepare if the clk is needed for boot-enable or sleep control.
- change is_enabled to is_prepared.
- Added ops palmas_clks_recalc_rate.
- Added of_clk_add_provider().

 .../devicetree/bindings/clock/clk-palmas.txt       |   45 +++
 drivers/clk/Kconfig                                |    7 +
 drivers/clk/Makefile                               |    2 +
 drivers/clk/clk-palmas.c                           |  336 ++++++++++++++++++++
 4 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/clk-palmas.txt
 create mode 100644 drivers/clk/clk-palmas.c
Documentation/devicetree/bindings/clock/clk-palmas.txt new file +45 -0
new file mode 100644
index 0000000..c247538
@@ -0,0 +1,45 @@
+* Palmas 32KHz clocks *
+
+Palmas device has two clock output pins for 32KHz, KG and KG_AUDIO.
+
+This binding uses the common clock binding ./clock-bindings.txt.
+
+Clock 32KHz KG is output 0 of the driver and clock 32KHz is output 1.
+
+Required properties:
+- compatible : shall be "ti,palmas-clk".
+- #clock-cells : from common clock binding; shall be set to 1.
+
+Optional subnode:
+       The clock node has optional subnode to provide the init configuration of
+       clocks like boot enable, sleep control.
+
+       The subnode name is fixed and it should be
+               clk32k_kg for the 32KHz KG clock.
+               clk32k_kg_audio for the 32KHz KG_AUDIO clock.
+
+       Optional subnode properties:
+       ti,clock-boot-enable: Enable clock at the time of booting.
+       ti,external-sleep-control: The clock is enable/disabled by state
+               of external enable input pins ENABLE, ENABLE2 and NSLEEP.
+               The valid value for the external pins are:
+                       1 for ENABLE1
+                       2 for ENABLE2
+                       3 for NSLEEP.
+               Option 0 or missing this property means the clock is
+               enabled/disabled via register access and these pins do
+               not have any control.
+
+Example:
+       clock {
+               compatible = "ti,palmas-clk";
+               #clock-cells = <1>;
+               clk32k_kg {
+                       ti,clock-boot-enable;
+                       ti,external-sleep-control = <3>;
+               };
+
+               clk32k_kg_audio {
+                       ti,clock-boot-enable;
+               };
+       };
drivers/clk/Kconfig +7 -0
index 279407a..6b8c233 100644
@@ -93,6 +93,13 @@ config CLK_PPC_CORENET
          This adds the clock driver support for Freescale PowerPC corenet
          platforms using common clock framework.
 
+config COMMON_CLK_PALMAS
+       tristate "Clock driver for TI Palmas devices"
+       depends on MFD_PALMAS
+       ---help---
+         This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO
+         using common clock framework.
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
drivers/clk/Makefile +2 -0
index 7b11106..f168ff7 100644
@@ -43,3 +43,5 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
 obj-$(CONFIG_CLK_TWL6040)      += clk-twl6040.o
 obj-$(CONFIG_CLK_PPC_CORENET)  += clk-ppc-corenet.o
+obj-$(CONFIG_COMMON_CLK_PALMAS)        += clk-palmas.o
+obj-y += clk-test.o
drivers/clk/clk-palmas.c new file +194 -0
new file mode 100644
index 0000000..804c76e
@@ -0,0 +1,336 @@
+/*
+ * Clock driver for Palmas device.
+ *
+ * Copyright (c) 2013, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <[email protected]>
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; 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/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/palmas.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+enum PALMAS_CLOCK32K {
+       PALMAS_CLOCK32KG,
+       PALMAS_CLOCK32KG_AUDIO,
+
+       /* Last entry */
+       PALMAS_CLOCK32K_NR,
+};
+
+struct palmas_clks;
+
+struct palmas_clk32k_desc {
+       const char *clk_name;
+       unsigned int control_reg;
+       unsigned int enable_mask;
+       unsigned int sleep_mask;
+       unsigned int sleep_reqstr_id;
+};
+
+struct palmas_clock_info {
+       struct clk *clk;
+       struct clk_hw hw;
+       struct palmas_clk32k_desc *clk_desc;
+       struct palmas_clks *palmas_clk;
+       int ext_control_pin;
+       bool boot_enable;
+};
+
+struct palmas_clks {
+       struct device *dev;
+       struct palmas *palmas;
+       struct clk_onecell_data clk_data;
+       struct palmas_clock_info clk_info[PALMAS_CLOCK32K_NR];
+};
+
+static struct palmas_clk32k_desc palmas_clk32k_descs[] = {
+       {
+               .clk_name = "clk32k_kg",
+               .control_reg = PALMAS_CLK32KG_CTRL,
+               .enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE,
+               .sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP,
+               .sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KG,
+       }, {
+               .clk_name = "clk32k_kg_audio",
+               .control_reg = PALMAS_CLK32KGAUDIO_CTRL,
+               .enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE,
+               .sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP,
+               .sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KGAUDIO,
+       },
+};
+
+static inline struct palmas_clock_info *to_palmas_clks_info(struct clk_hw *hw)
+{
+       return container_of(hw, struct palmas_clock_info, hw);
+}
+
+static unsigned long palmas_clks_recalc_rate(struct clk_hw *hw,
+       unsigned long parent_rate)
+{
+       return 32768;
+}
+
+static int palmas_clks_prepare(struct clk_hw *hw)
+{
+       struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+       struct palmas_clks *palmas_clks = cinfo->palmas_clk;
+       int ret;
+
+       ret = palmas_update_bits(palmas_clks->palmas, PALMAS_RESOURCE_BASE,
+                       cinfo->clk_desc->control_reg,
+                       cinfo->clk_desc->enable_mask,
+                       cinfo->clk_desc->enable_mask);
+       if (ret < 0)
+               dev_err(palmas_clks->dev, "Reg 0x%02x update failed, %d\n",
+                       cinfo->clk_desc->control_reg, ret);
+
+       return ret;
+}
+
+static void palmas_clks_unprepare(struct clk_hw *hw)
+{
+       struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+       struct palmas_clks *palmas_clks = cinfo->palmas_clk;
+       int ret;
+
+       /*
+        * Clock can be disabled through external pin if it is externally
+        * controlled.
+        */
+       if (cinfo->ext_control_pin)
+               return;
+
+       ret = palmas_update_bits(palmas_clks->palmas, PALMAS_RESOURCE_BASE,
+                       cinfo->clk_desc->control_reg,
+                       cinfo->clk_desc->enable_mask, 0);
+       if (ret < 0)
+               dev_err(palmas_clks->dev, "Reg 0x%02x update failed, %d\n",
+                       cinfo->clk_desc->control_reg, ret);
+
+}
+
+static int palmas_clks_is_prepared(struct clk_hw *hw)
+{
+       struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+       struct palmas_clks *palmas_clks = cinfo->palmas_clk;
+       int ret;
+       u32 val;
+
+       if (cinfo->ext_control_pin)
+               return 1;
+
+       ret = palmas_read(palmas_clks->palmas, PALMAS_RESOURCE_BASE,
+                       cinfo->clk_desc->control_reg, &val);
+       if (ret < 0) {
+               dev_err(palmas_clks->dev, "Reg 0x%02x read failed, %d\n",
+                               cinfo->clk_desc->control_reg, ret);
+               return ret;
+       }
+       return !!(val & cinfo->clk_desc->enable_mask);
+}
+
+static struct clk_ops palmas_clks_ops = {
+       .prepare        = palmas_clks_prepare,
+       .unprepare      = palmas_clks_unprepare,
+       .is_prepared    = palmas_clks_is_prepared,
+       .recalc_rate    = palmas_clks_recalc_rate,
+};
+
+static struct clk_init_data palmas_clks_hw_init[PALMAS_CLOCK32K_NR] = {
+       [PALMAS_CLOCK32KG] = {
+               .name = "clk32k_kg",
+               .ops = &palmas_clks_ops,
+               .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+       },
+       [PALMAS_CLOCK32KG_AUDIO] = {
+               .name = "clk32k_kg_audio",
+               .ops = &palmas_clks_ops,
+               .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static int palmas_clks_get_clk_data(struct platform_device *pdev,
+       struct palmas_clks *palmas_clks)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct device_node *child;
+       struct palmas_clock_info *cinfo;
+       unsigned int prop;
+       int ret;
+       int i;
+
+       for (i = 0; i < PALMAS_CLOCK32K_NR; ++i) {
+               child = of_get_child_by_name(node,
+                               palmas_clk32k_descs[i].clk_name);
+               if (!child)
+                       continue;
+
+               cinfo = &palmas_clks->clk_info[i];
+               cinfo->boot_enable = of_property_read_bool(child,
+                                               "ti,clock-boot-enable");
+               ret = of_property_read_u32(child, "ti,external-sleep-control",
+                                       &prop);
+               if (!ret) {

drivers/clk/clk-palmas.c line 204

Quoted 10 lines
drivers/clk/clk-palmas.c new file +10 -0
+                       switch (prop) {
+                       case 1:
+                               prop = PALMAS_EXT_CONTROL_ENABLE1;
+                               break;
+                       case 2:
+                               prop = PALMAS_EXT_CONTROL_ENABLE2;
+                               break;
+                       case 3:
+                               prop = PALMAS_EXT_CONTROL_NSLEEP;
+                               break;

Can magic numbers be replaced with defines?

Quoted 22 lines
drivers/clk/clk-palmas.c new file +22 -0
+                       default:
+                               WARN_ON(1);
+                               dev_warn(&pdev->dev,
+                                       "%s: Invalid ext control option: %u\n",
+                                       child->name, prop);
+                               prop = 0;
+                               break;
+                       }
+                       cinfo->ext_control_pin = prop;
+               }
+       }
+
+       return 0;
+}
+
+static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
+{
+       struct palmas_clks *palmas_clks = cinfo->palmas_clk;
+       int ret;
+
+       if (cinfo->boot_enable || cinfo->ext_control_pin) {
+               ret = clk_prepare(cinfo->clk);

drivers/clk/clk-palmas.c line 236

Quoted 10 lines
drivers/clk/clk-palmas.c new file +10 -0
+               if (ret < 0) {
+                       dev_err(palmas_clks->dev,
+                               "Clock prep failed, %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = palmas_update_bits(palmas_clks->palmas, PALMAS_RESOURCE_BASE,
+                       cinfo->clk_desc->control_reg,
+                       cinfo->clk_desc->sleep_mask, 0);

What does this call to palmas_update_bits do?

Quoted 65 lines
drivers/clk/clk-palmas.c new file +65 -0
+       if (ret < 0) {
+               dev_err(palmas_clks->dev, "Reg 0x%02x update failed, %d\n",
+                       cinfo->clk_desc->control_reg, ret);
+               return ret;
+       }
+
+       if (cinfo->ext_control_pin) {
+               ret = palmas_ext_control_req_config(palmas_clks->palmas,
+                               cinfo->clk_desc->sleep_reqstr_id,
+                               cinfo->ext_control_pin, true);
+               if (ret < 0) {
+                       dev_err(palmas_clks->dev,
+                               "Ext config for %s failed, %d\n",
+                               cinfo->clk_desc->clk_name, ret);
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static int palmas_clks_probe(struct platform_device *pdev)
+{
+       struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+       struct palmas_clock_info *cinfo;
+       struct palmas_clks *palmas_clks;
+       struct clk *clk;
+       int i, ret;
+
+       palmas_clks = devm_kzalloc(&pdev->dev, sizeof(*palmas_clks),
+                               GFP_KERNEL);
+       if (!palmas_clks)
+               return -ENOMEM;
+
+       palmas_clks->clk_data.clks = devm_kzalloc(&pdev->dev,
+                       PALMAS_CLOCK32K_NR * sizeof(palmas_clks->clk_data.clks),
+                       GFP_KERNEL);
+       if (!palmas_clks->clk_data.clks)
+               return -ENOMEM;
+
+       palmas_clks_get_clk_data(pdev, palmas_clks);
+       platform_set_drvdata(pdev, palmas_clks);
+
+       palmas_clks->dev = &pdev->dev;
+       palmas_clks->palmas = palmas;
+
+       for (i = 0; i < PALMAS_CLOCK32K_NR; i++) {
+               cinfo = &palmas_clks->clk_info[i];
+               cinfo->clk_desc = &palmas_clk32k_descs[i];
+               cinfo->hw.init = &palmas_clks_hw_init[i];
+               cinfo->palmas_clk = palmas_clks;
+               clk = devm_clk_register(&pdev->dev, &cinfo->hw);
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err(&pdev->dev, "Fail to register clock %s, %d\n",
+                               palmas_clk32k_descs[i].clk_name, ret);
+                       return ret;
+               }
+
+               cinfo->clk = clk;
+               palmas_clks->clk_data.clks[i] = clk;
+               palmas_clks->clk_data.clk_num++;
+               palmas_clks_init_configure(cinfo);
+       }
+

drivers/clk/clk-palmas.c line 311

Quoted 10 lines
drivers/clk/clk-palmas.c new file +10 -0
+       ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get,
+                       &palmas_clks->clk_data);
+       if (ret < 0)
+               dev_err(&pdev->dev, "Fail to add clock driver, %d\n", ret);
+       return ret;
+}
+
+static int palmas_clks_remove(struct platform_device *pdev)
+{
+       of_clk_del_provider(pdev->dev.of_node);

I'll be taking Sylwester's clock deregistration series after he publishes the next version, so if you want to call clk_unregister here (based on the new call) you could.

If you want to add that in a later patch it is OK.

Regards,
Mike

Quoted 27 lines
drivers/clk/clk-palmas.c new file +25 -0
+       return 0;
+}
+
+static struct of_device_id of_palmas_clks_match_tbl[] = {
+       { .compatible = "ti,palmas-clk", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, of_palmas_clks_match_tbl);
+
+static struct platform_driver palmas_clks_driver = {
+       .driver = {
+               .name = "palmas-clk",
+               .owner = THIS_MODULE,
+               .of_match_table = of_palmas_clks_match_tbl,
+       },
+       .probe = palmas_clks_probe,
+       .remove = palmas_clks_remove,
+};
+
+module_platform_driver(palmas_clks_driver);
+
+MODULE_DESCRIPTION("Clock driver for Palmas Series Devices");
+MODULE_ALIAS("platform:palmas-clk");
+MODULE_AUTHOR("Laxman Dewangan <[email protected]>");
+MODULE_LICENSE("GPL v2");
Signature · 1 line
1.7.1.1
#3 lore raw
Quoted 12 lines · Mike Turquette

Quoting Laxman Dewangan (2013-10-07 07:05:51)

drivers/clk/clk-palmas.c line 204

Quoted 11 lines
drivers/clk/clk-palmas.c new file +11 -0
+               if (!ret) {
+                       switch (prop) {
+                       case 1:
+                               prop = PALMAS_EXT_CONTROL_ENABLE1;
+                               break;
+                       case 2:
+                               prop = PALMAS_EXT_CONTROL_ENABLE2;
+                               break;
+                       case 3:
+                               prop = PALMAS_EXT_CONTROL_NSLEEP;
+                               break;
Quoted 1 line

Can magic numbers be replaced with defines?

Fine, will do in V3.

Quoted 7 lines
drivers/clk/clk-palmas.c new file +4 -0
+
+       ret = palmas_update_bits(palmas_clks->palmas, PALMAS_RESOURCE_BASE,
+                       cinfo->clk_desc->control_reg,
+                       cinfo->clk_desc->sleep_mask, 0);

What does this call to palmas_update_bits do?

This APIs update the selected bits based on mask. This is wrapper over the regmap_update_bits() to provide the interface at the Palmas register access. The palmas registers are paged on different i2c address and offset. The i2c address and offset is decided based on base_address and offset. This APIs does all calculation to get the correct i2c slave address and offset address based on argument.

Quoted 8 lines

drivers/clk/clk-palmas.c line 311

Quoted 3 lines
drivers/clk/clk-palmas.c new file +3 -0
+static int palmas_clks_remove(struct platform_device *pdev)
+{
+       of_clk_del_provider(pdev->dev.of_node);

I'll be taking Sylwester's clock deregistration series after he publishes the next version, so if you want to call clk_unregister here (based on the new call) you could.

If you want to add that in a later patch it is OK.

Thanks for pointing me this changes. I like to add this on my follow on (later) patch, not on this. -- 1.7.1.1

#4 lore raw
In reply to Laxman Dewangan
Quoted 28 lines · Laxman Dewangan

Palmas devices has two clock output CLK32K_KG and CLK32K_KG_AUDIO which can be nebale/disable through software.

Add clock driver support for the Palmas 32k clocks.

---
Changes from V1:
- Call prepare if the clk is needed for boot-enable or sleep control.
- change is_enabled to is_prepared.
- Added ops palmas_clks_recalc_rate.
- Added of_clk_add_provider().

 .../devicetree/bindings/clock/clk-palmas.txt       |   45 +++
 drivers/clk/Kconfig                                |    7 +
 drivers/clk/Makefile                               |    2 +
 drivers/clk/clk-palmas.c                           |  336 ++++++++++++++++++++
 4 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/clk-palmas.txt
 create mode 100644 drivers/clk/clk-palmas.c
Documentation/devicetree/bindings/clock/clk-palmas.txt new file +1 -0
new file mode 100644
index 0000000..c247538
@@ -0,0 +1,45 @@
+* Palmas 32KHz clocks *

Documentation/devicetree/bindings/clock/clk-palmas.txt line 11

Quoted 10 lines
Documentation/devicetree/bindings/clock/clk-palmas.txt new file +10 -0
+
+Palmas device has two clock output pins for 32KHz, KG and KG_AUDIO.
+
+This binding uses the common clock binding ./clock-bindings.txt.
+
+Clock 32KHz KG is output 0 of the driver and clock 32KHz is output 1.
+
+Required properties:
+- compatible : shall be "ti,palmas-clk".
+- #clock-cells : from common clock binding; shall be set to 1.

It would make sense to describe the value values here, rather than above.

Documentation/devicetree/bindings/clock/clk-palmas.txt line 22

Quoted 11 lines
Documentation/devicetree/bindings/clock/clk-palmas.txt new file +11 -0
+
+Optional subnode:
+       The clock node has optional subnode to provide the init configuration of
+       clocks like boot enable, sleep control.
+
+       The subnode name is fixed and it should be
+               clk32k_kg for the 32KHz KG clock.
+               clk32k_kg_audio for the 32KHz KG_AUDIO clock.
+
+       Optional subnode properties:
+       ti,clock-boot-enable: Enable clock at the time of booting.

Why is this needed?

If drivers need clocks, they should request them. If they don't currently, that's a bug in the driver.

Documentation/devicetree/bindings/clock/clk-palmas.txt line 31

Quoted 9 lines
Documentation/devicetree/bindings/clock/clk-palmas.txt new file +9 -0
+       ti,external-sleep-control: The clock is enable/disabled by state
+               of external enable input pins ENABLE, ENABLE2 and NSLEEP.
+               The valid value for the external pins are:
+                       1 for ENABLE1
+                       2 for ENABLE2
+                       3 for NSLEEP.
+               Option 0 or missing this property means the clock is
+               enabled/disabled via register access and these pins do
+               not have any control.

What actually drives these pins to control the clock?

Quoted 4 lines
Documentation/devicetree/bindings/clock/clk-palmas.txt new file +4 -0
+
+Example:
+       clock {
+               compatible = "ti,palmas-clk";

Documentation/devicetree/bindings/clock/clk-palmas.txt line 45

Quoted 10 lines
Documentation/devicetree/bindings/clock/clk-palmas.txt new file +10 -0
+               #clock-cells = <1>;
+               clk32k_kg {
+                       ti,clock-boot-enable;
+                       ti,external-sleep-control = <3>;
+               };
+
+               clk32k_kg_audio {
+                       ti,clock-boot-enable;
+               };
+       };

How does the palmas-clk driver control these? No description of registers, gpio, or any other component that could be used for control is dfined.

Is the palmas-clk intended to be a subnode of the palmas mfd (the palmas-rtc binding example suggests this)? It seems odd to describe components of a device separately with no linkage between them.

I also note that the palmas MFD appears to be an I2C slave, but the binding doesn't define that (which makes it somewhat confuding for someone unfamiliar with the hardware).

Thanks,
Mark.