diff options
author | Mike Looijmans <mike.looijmans@topic.nl> | 2018-06-04 07:34:39 +0200 |
---|---|---|
committer | Stephen Boyd <sboyd@kernel.org> | 2018-06-29 19:59:40 +0200 |
commit | e8f127caf63ad29e2b4cb01894b97730384ad1ab (patch) | |
tree | 9507fd512e94d81abf542ec3b636c3c2b29e80d5 /drivers/clk/clk-si544.c | |
parent | Linux 4.18-rc1 (diff) | |
download | linux-e8f127caf63ad29e2b4cb01894b97730384ad1ab.tar.xz linux-e8f127caf63ad29e2b4cb01894b97730384ad1ab.zip |
clk-si514, clk-si544: Implement prepare/unprepare/is_prepared operations
This adds prepare/unprepare/is_prepared functionality to the drivers for
the SI544 and SI514 chips, allowing the clock output to be disabled when
the clock is not in use.
Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Diffstat (limited to 'drivers/clk/clk-si544.c')
-rw-r--r-- | drivers/clk/clk-si544.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c index 1e2a3b8f9454..64e607f3232a 100644 --- a/drivers/clk/clk-si544.c +++ b/drivers/clk/clk-si544.c @@ -86,6 +86,33 @@ static int si544_enable_output(struct clk_si544 *data, bool enable) SI544_OE_STATE_ODC_OE, enable ? SI544_OE_STATE_ODC_OE : 0); } +static int si544_prepare(struct clk_hw *hw) +{ + struct clk_si544 *data = to_clk_si544(hw); + + return si544_enable_output(data, true); +} + +static void si544_unprepare(struct clk_hw *hw) +{ + struct clk_si544 *data = to_clk_si544(hw); + + si544_enable_output(data, false); +} + +static int si544_is_prepared(struct clk_hw *hw) +{ + struct clk_si544 *data = to_clk_si544(hw); + unsigned int val; + int err; + + err = regmap_read(data->regmap, SI544_REG_OE_STATE, &val); + if (err < 0) + return err; + + return !!(val & SI544_OE_STATE_ODC_OE); +} + /* Retrieve clock multiplier and dividers from hardware */ static int si544_get_muldiv(struct clk_si544 *data, struct clk_si544_muldiv *settings) @@ -273,6 +300,7 @@ static int si544_set_rate(struct clk_hw *hw, unsigned long rate, { struct clk_si544 *data = to_clk_si544(hw); struct clk_si544_muldiv settings; + unsigned int old_oe_state; int err; if (!is_valid_frequency(data, rate)) @@ -282,6 +310,10 @@ static int si544_set_rate(struct clk_hw *hw, unsigned long rate, if (err) return err; + err = regmap_read(data->regmap, SI544_REG_OE_STATE, &old_oe_state); + if (err) + return err; + si544_enable_output(data, false); /* Allow FCAL for this frequency update */ @@ -303,12 +335,16 @@ static int si544_set_rate(struct clk_hw *hw, unsigned long rate, /* Applying a new frequency can take up to 10ms */ usleep_range(10000, 12000); - si544_enable_output(data, true); + if (old_oe_state & SI544_OE_STATE_ODC_OE) + si544_enable_output(data, true); return err; } static const struct clk_ops si544_clk_ops = { + .prepare = si544_prepare, + .unprepare = si544_unprepare, + .is_prepared = si544_is_prepared, .recalc_rate = si544_recalc_rate, .round_rate = si544_round_rate, .set_rate = si544_set_rate, |