>From 3e7a1a8e1f3e472e473e5ab47329bb44a9ec24ba Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Sun, 17 Feb 2013 18:01:08 +0100 Subject: [PATCH] si5351: cache 'prepared' bits of clocks --- drivers/clk/clk-si5351.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index b526742..528f88a 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -54,6 +54,7 @@ struct si5351_hw_data { struct si5351_driver_data *drvdata; struct si5351_parameters params; unsigned char num; + bool prepared; }; struct si5351_driver_data { @@ -70,6 +71,9 @@ struct si5351_driver_data { struct si5351_hw_data pll[2]; struct si5351_hw_data *msynth; struct si5351_hw_data *clkout; + + bool xtal_prepared; + bool clkin_prepared; }; static const char const *si5351_input_names[] = { @@ -223,6 +227,8 @@ static int si5351_xtal_prepare(struct clk_hw *hw) container_of(hw, struct si5351_driver_data, xtal); si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE, SI5351_XTAL_ENABLE, SI5351_XTAL_ENABLE); + drvdata->xtal_prepared = true; + return 0; } @@ -232,15 +238,14 @@ static void si5351_xtal_unprepare(struct clk_hw *hw) container_of(hw, struct si5351_driver_data, xtal); si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE, SI5351_XTAL_ENABLE, 0); + drvdata->xtal_prepared = false; } static int si5351_xtal_is_enabled(struct clk_hw *hw) { struct si5351_driver_data *drvdata = container_of(hw, struct si5351_driver_data, xtal); - unsigned char reg; - reg = si5351_reg_read(drvdata, SI5351_FANOUT_ENABLE); - return (reg & SI5351_XTAL_ENABLE) ? 1 : 0; + return drvdata->xtal_prepared; } static const struct clk_ops si5351_xtal_ops = { @@ -258,7 +263,8 @@ static int si5351_clkin_prepare(struct clk_hw *hw) container_of(hw, struct si5351_driver_data, clkin); si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE, SI5351_CLKIN_ENABLE, SI5351_CLKIN_ENABLE); - return 0; + drvdata->clkin_prepared = true; + return 1; } static void si5351_clkin_unprepare(struct clk_hw *hw) @@ -267,15 +273,14 @@ static void si5351_clkin_unprepare(struct clk_hw *hw) container_of(hw, struct si5351_driver_data, clkin); si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE, SI5351_CLKIN_ENABLE, 0); + drvdata->clkin_prepared = false; } static int si5351_clkin_is_enabled(struct clk_hw *hw) { struct si5351_driver_data *drvdata = container_of(hw, struct si5351_driver_data, clkin); - unsigned char reg; - reg = si5351_reg_read(drvdata, SI5351_FANOUT_ENABLE); - return (reg & SI5351_CLKIN_ENABLE) ? 1 : 0; + return drvdata->clkin_prepared; } /* @@ -660,6 +665,7 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw, m += hwdata->params.p2; m += 512 * hwdata->params.p3; } +printk(" XXXX m %d (%d)\n", m, hwdata->num); do_div(rate, m); dev_dbg(&hwdata->drvdata->client->dev, @@ -887,6 +893,8 @@ static int si5351_clkout_prepare(struct clk_hw *hw) SI5351_CLK_POWERDOWN, 0); si5351_set_bits(hwdata->drvdata, SI5351_OUTPUT_ENABLE_CTRL, (1 << hwdata->num), 0); + hwdata->prepared = true; + return 0; } @@ -899,21 +907,28 @@ static void si5351_clkout_unprepare(struct clk_hw *hw) SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN); si5351_set_bits(hwdata->drvdata, SI5351_OUTPUT_ENABLE_CTRL, (1 << hwdata->num), (1 << hwdata->num)); + hwdata->prepared = false; } -static int si5351_clkout_is_enabled(struct clk_hw *hw) +static void __si5351_read_clkout_prepared(struct si5351_hw_data *hwdata) { - struct si5351_hw_data *hwdata = - container_of(hw, struct si5351_hw_data, hw); unsigned char val; val = si5351_reg_read(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num); if (val & SI5351_CLK_POWERDOWN) - return 0; + hwdata->prepared = false; val = si5351_reg_read(hwdata->drvdata, SI5351_OUTPUT_ENABLE_CTRL); if (val & (1 << hwdata->num)) - return 0; - return 1; + hwdata->prepared = false; + hwdata->prepared = true; +} + +static int si5351_clkout_is_enabled(struct clk_hw *hw) +{ + struct si5351_hw_data *hwdata = + container_of(hw, struct si5351_hw_data, hw); + + return hwdata->prepared; } static u8 si5351_clkout_get_parent(struct clk_hw *hw) @@ -1306,6 +1321,11 @@ static int si5351_i2c_probe( return -EINVAL; } + /* read current clock enable bits */ + ret = si5351_reg_read(drvdata, SI5351_FANOUT_ENABLE); + drvdata->xtal_prepared = !!(ret & SI5351_XTAL_ENABLE); + drvdata->clkin_prepared = !!(ret & SI5351_CLKIN_ENABLE); + /* register PLLB or VXCO (Si5351B) */ drvdata->pll[1].num = 1; drvdata->pll[1].drvdata = drvdata; @@ -1394,6 +1414,7 @@ static int si5351_i2c_probe( return -EINVAL; } drvdata->onecell.clks[n] = clk; + __si5351_read_clkout_prepared(&drvdata->clkout[n]); } /* setup clock setup from DT */ -- 1.8.1.2