Message ID | 87d1cjyeb4.wl%kuninori.morimoto.gx@renesas.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Hi Morimoto-san, On Tue, Apr 11, 2017 at 2:36 AM, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> wrote: > From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> > > Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> > Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com> > --- > .../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 AUX_OUT is an output pin? Hence, isn't this software configuration instead of hardware description? Selection of refclk vs. clk_in vs. pllclkout can be implemented as a mux clock driver with three parents. PLL Lock/Unlock Indication and its pinctrl are something different. How to support that? Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-clk" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Geert Thank you for your feedback > > +- 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 > > AUX_OUT is an output pin? > Hence, isn't this software configuration instead of hardware description? > > Selection of refclk vs. clk_in vs. pllclkout can be implemented as a mux clock > driver with three parents. > > PLL Lock/Unlock Indication and its pinctrl are something different. > How to support that? I think mux clock is nice idea. I will use this idea. Best regards --- Kuninori Morimoto -- To unsubscribe from this list: send the line "unsubscribe linux-clk" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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;