[PATCH 2/2] clk: cs2000: add AUX_OUT pin select support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>
Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@xxxxxxxxxxx>
---
 .../devicetree/bindings/clock/cs2000-cp.txt        |  9 +++
 drivers/clk/clk-cs2000-cp.c                        | 73 +++++++++++++++++++++-
 2 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/cs2000-cp.txt b/Documentation/devicetree/bindings/clock/cs2000-cp.txt
index 54e6df0..4c2f9cb 100644
--- a/Documentation/devicetree/bindings/clock/cs2000-cp.txt
+++ b/Documentation/devicetree/bindings/clock/cs2000-cp.txt
@@ -8,6 +8,15 @@ Required properties:
 - clock-names:		CLK_IN : clk_in, XTI/REF_CLK : ref_clk
 - #clock-cells:		must be <0>
 
+Option properties:
+
+- auxoutsrc:		select AUX_OUT source from these.
+				refclk:		Timing Reference Clock
+				clk_in:		Frequency Reference Clock
+				pllclkout:	PLL Clock Output
+				push-pull:	PLL Lock/Unlock Indication
+				open-drain:	PLL Lock/Unlock Indication
+
 Example:
 
 &i2c2 {
diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c
index 4df38c5..234e3b4 100644
--- a/drivers/clk/clk-cs2000-cp.c
+++ b/drivers/clk/clk-cs2000-cp.c
@@ -42,6 +42,8 @@
 /* DEVICE_CFG1 */
 #define RSEL(x)		(((x) & 0x3) << 3)
 #define RSEL_MASK	RSEL(0x3)
+#define AUXOUTSRC(x)	(((x) & 0x3) << 1)
+#define AUXOUTSRC_MASK	AUXOUTSRC(0x3)
 #define ENDEV1		(0x1)
 
 /* DEVICE_CFG2 */
@@ -54,6 +56,8 @@
 #define ENDEV2		(0x1)
 
 /* FUNC_CFG1 */
+#define AUXLOCKCFG(x)	(((x) & 0x1) << 6)
+#define AUXLOCKCFG_MASK	AUXLOCKCFG(1)
 #define REFCLKDIV(x)	(((x) & 0x3) << 3)
 #define REFCLKDIV_MASK	REFCLKDIV(0x3)
 
@@ -66,11 +70,20 @@
 #define REF_CLK	1
 #define CLK_MAX 2
 
+enum auxoutsrc {
+	AUXSRC_REFCLK = 0,
+	AUXSRC_CLKIN,
+	AUXSRC_PLLCLKOUT,
+	AUXSRC_PUSHPULL,
+	AUXSRC_OPENDRAIN,
+};
+
 struct cs2000_priv {
 	struct clk_hw hw;
 	struct i2c_client *client;
 	struct clk *clk_in;
 	struct clk *ref_clk;
+	enum auxoutsrc auxoutsrc;
 
 	/* suspend/resume */
 	unsigned long saved_rate;
@@ -111,9 +124,27 @@ static int cs2000_bset(struct cs2000_priv *priv, u8 addr, u8 mask, u8 val)
 static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)
 {
 	int ret;
+	u8 dcfg1, fcfg1;
+
+	dcfg1 = 0;
+	fcfg1 = 0;
+	if (enable)
+		dcfg1 |= ENDEV1;
+	switch (priv->auxoutsrc) {
+	case AUXSRC_REFCLK:
+	case AUXSRC_CLKIN:
+	case AUXSRC_PLLCLKOUT:
+		dcfg1 |= AUXOUTSRC(priv->auxoutsrc);
+		break;
+	case AUXSRC_OPENDRAIN:
+		fcfg1 |= AUXLOCKCFG(1);
+		/* fall though */
+	case AUXSRC_PUSHPULL:
+		dcfg1 |= AUXOUTSRC(3);
+		break;
+	}
 
-	ret = cs2000_bset(priv, DEVICE_CFG1, ENDEV1,
-			  enable ? ENDEV1 : 0);
+	ret = cs2000_bset(priv, DEVICE_CFG1, (AUXOUTSRC_MASK | ENDEV1), dcfg1);
 	if (ret < 0)
 		return ret;
 
@@ -122,6 +153,10 @@ static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)
 	if (ret < 0)
 		return ret;
 
+	ret = cs2000_bset(priv, FUNC_CFG1, AUXLOCKCFG_MASK, fcfg1);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -479,6 +514,38 @@ static int cs2000_remove(struct i2c_client *client)
 	return 0;
 }
 
+static void cs2000_of_parse(struct cs2000_priv *priv)
+{
+	struct device *dev = priv_to_dev(priv);
+	struct device_node *np = dev->of_node;
+	const char *auxoutsrc;
+
+	auxoutsrc = of_get_property(np, "auxoutsrc", NULL);
+
+	if (auxoutsrc) {
+		int i;
+		struct {
+			char *name;
+			enum auxoutsrc val;
+		} of_table[] = {
+			{"refclk",	AUXSRC_REFCLK},
+			{"clk_in",	AUXSRC_CLKIN},
+			{"pllclkout",	AUXSRC_PLLCLKOUT},
+			{"push-pull",	AUXSRC_PUSHPULL},
+			{"open-drain",	AUXSRC_OPENDRAIN},
+		};
+
+		for (i = 0; i < ARRAY_SIZE(of_table); i++) {
+			if (strcmp(of_table[i].name, auxoutsrc) == 0) {
+				priv->auxoutsrc = of_table[i].val;
+				dev_dbg(dev, "%s was selected\n",
+					of_table[i].name);
+				break;
+			}
+		}
+	}
+}
+
 static int cs2000_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -493,6 +560,8 @@ static int cs2000_probe(struct i2c_client *client,
 	priv->client = client;
 	i2c_set_clientdata(client, priv);
 
+	cs2000_of_parse(priv);
+
 	ret = cs2000_clk_get(priv);
 	if (ret < 0)
 		return ret;
-- 
1.9.1




[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux