summaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-si5351.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clk-si5351.c')
-rw-r--r--drivers/clk/clk-si5351.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index a9a0bc448a..4ce83c5265 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -506,6 +506,8 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct si5351_hw_data *hwdata =
container_of(hw, struct si5351_hw_data, hw);
+ struct si5351_platform_data *pdata =
+ hwdata->drvdata->client->dev.platform_data;
u8 reg = (hwdata->num == 0) ? SI5351_PLLA_PARAMETERS :
SI5351_PLLB_PARAMETERS;
@@ -518,9 +520,10 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
(hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0);
/* Do a pll soft reset on the affected pll */
- si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET,
- hwdata->num == 0 ? SI5351_PLL_RESET_A :
- SI5351_PLL_RESET_B);
+ if (pdata->pll_reset[hwdata->num])
+ si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET,
+ hwdata->num == 0 ? SI5351_PLL_RESET_A :
+ SI5351_PLL_RESET_B);
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
@@ -1222,6 +1225,44 @@ static int si5351_dt_parse(struct i2c_client *client,
}
}
+ /*
+ * Parse PLL reset mode. For compatibility with older device trees, the
+ * default is to always reset a PLL after setting its rate.
+ */
+ pdata->pll_reset[0] = true;
+ pdata->pll_reset[1] = true;
+
+ of_property_for_each_u32(np, "silabs,pll-reset-mode", prop, p, num) {
+ if (num >= 2) {
+ dev_err(&client->dev,
+ "invalid pll %d on pll-reset-mode prop\n", num);
+ return -EINVAL;
+ }
+
+ p = of_prop_next_u32(prop, p, &val);
+ if (!p) {
+ dev_err(&client->dev,
+ "missing pll-reset-mode for pll %d\n", num);
+ return -EINVAL;
+ }
+
+ switch (val) {
+ case 0:
+ /* Reset PLL whenever its rate is adjusted */
+ pdata->pll_reset[num] = true;
+ break;
+ case 1:
+ /* Don't reset PLL whenever its rate is adjusted */
+ pdata->pll_reset[num] = false;
+ break;
+ default:
+ dev_err(&client->dev,
+ "invalid pll-reset-mode %d for pll %d\n", val,
+ num);
+ return -EINVAL;
+ }
+ }
+
/* per clkout properties */
for_each_child_of_node(np, child) {
if (of_property_read_u32(child, "reg", &num)) {