summary refs log tree commit diff
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2015-02-05 22:55:01 +0300
committerWolfram Sang <wsa@the-dreams.de>2015-02-05 22:29:23 +0100
commite961a094afe04c6c8ca1adac50c8d16513f31b93 (patch)
tree2b5d803d08e759fe7f8202e3a1d098a60436fbf2 /drivers/i2c/busses
parent181d9a07da1050d3da30c6936eb825724fefc18a (diff)
downloadlinux-e961a094afe04c6c8ca1adac50c8d16513f31b93.tar.gz
i2c: ocores: add common clock support
Allow bus clock specification as a common clock handle. This makes this
controller easier to use in a setup based on common clock framework.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r--drivers/i2c/busses/i2c-ocores.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 6cbbb134cfb7..3fc76b6ffcaa 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -12,6 +12,7 @@
  * kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -35,6 +36,7 @@ struct ocores_i2c {
 	int pos;
 	int nmsgs;
 	int state; /* see STATE_ */
+	struct clk *clk;
 	int ip_clock_khz;
 	int bus_clock_khz;
 	void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value);
@@ -339,7 +341,21 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
 							&clock_frequency);
 	i2c->bus_clock_khz = 100;
 
-	if (of_property_read_u32(np, "opencores,ip-clock-frequency", &val)) {
+	i2c->clk = devm_clk_get(&pdev->dev, NULL);
+
+	if (!IS_ERR(i2c->clk)) {
+		int ret = clk_prepare_enable(i2c->clk);
+
+		if (ret) {
+			dev_err(&pdev->dev,
+				"clk_prepare_enable failed: %d\n", ret);
+			return ret;
+		}
+		i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000;
+		if (clock_frequency_present)
+			i2c->bus_clock_khz = clock_frequency / 1000;
+	} else if (of_property_read_u32(np, "opencores,ip-clock-frequency",
+					&val)) {
 		if (!clock_frequency_present) {
 			dev_err(&pdev->dev,
 				"Missing required parameter 'opencores,ip-clock-frequency'\n");
@@ -477,6 +493,9 @@ static int ocores_i2c_remove(struct platform_device *pdev)
 	/* remove adapter & data */
 	i2c_del_adapter(&i2c->adap);
 
+	if (!IS_ERR(i2c->clk))
+		clk_disable_unprepare(i2c->clk);
+
 	return 0;
 }
 
@@ -489,6 +508,8 @@ static int ocores_i2c_suspend(struct device *dev)
 	/* make sure the device is disabled */
 	oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
 
+	if (!IS_ERR(i2c->clk))
+		clk_disable_unprepare(i2c->clk);
 	return 0;
 }
 
@@ -496,6 +517,16 @@ static int ocores_i2c_resume(struct device *dev)
 {
 	struct ocores_i2c *i2c = dev_get_drvdata(dev);
 
+	if (!IS_ERR(i2c->clk)) {
+		int ret = clk_prepare_enable(i2c->clk);
+
+		if (ret) {
+			dev_err(dev,
+				"clk_prepare_enable failed: %d\n", ret);
+			return ret;
+		}
+		i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000;
+	}
 	return ocores_init(dev, i2c);
 }