aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-si5351.c
diff options
context:
space:
mode:
authorSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>2013-05-03 01:33:27 -0400
committerMike Turquette <mturquette@linaro.org>2013-05-29 01:50:31 -0400
commit1a0483d2a4c2c5e218d415c90d1a62b3b917d34e (patch)
tree14f9c34645c52c16e1a0d32986629b0fdeb0f153 /drivers/clk/clk-si5351.c
parent555eae97358082be3a46572464829c27b96ed8f1 (diff)
clk: si5351: Allow user to define disabled state for every clock output
This patch adds platform data and DT bindings to allow to overwrite the stored disabled state for each clock output. Signed-off-by: Marek Belisko <marek.belisko@streamunlimited.com> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/clk-si5351.c')
-rw-r--r--drivers/clk/clk-si5351.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 892728412e9d..efc6d5e9268b 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -851,6 +851,41 @@ static int _si5351_clkout_set_drive_strength(
851 return 0; 851 return 0;
852} 852}
853 853
854static int _si5351_clkout_set_disable_state(
855 struct si5351_driver_data *drvdata, int num,
856 enum si5351_disable_state state)
857{
858 u8 reg = (num < 4) ? SI5351_CLK3_0_DISABLE_STATE :
859 SI5351_CLK7_4_DISABLE_STATE;
860 u8 shift = (num < 4) ? (2 * num) : (2 * (num-4));
861 u8 mask = SI5351_CLK_DISABLE_STATE_MASK << shift;
862 u8 val;
863
864 if (num > 8)
865 return -EINVAL;
866
867 switch (state) {
868 case SI5351_DISABLE_LOW:
869 val = SI5351_CLK_DISABLE_STATE_LOW;
870 break;
871 case SI5351_DISABLE_HIGH:
872 val = SI5351_CLK_DISABLE_STATE_HIGH;
873 break;
874 case SI5351_DISABLE_FLOATING:
875 val = SI5351_CLK_DISABLE_STATE_FLOAT;
876 break;
877 case SI5351_DISABLE_NEVER:
878 val = SI5351_CLK_DISABLE_STATE_NEVER;
879 break;
880 default:
881 return 0;
882 }
883
884 si5351_set_bits(drvdata, reg, mask, val << shift);
885
886 return 0;
887}
888
854static int si5351_clkout_prepare(struct clk_hw *hw) 889static int si5351_clkout_prepare(struct clk_hw *hw)
855{ 890{
856 struct si5351_hw_data *hwdata = 891 struct si5351_hw_data *hwdata =
@@ -1225,6 +1260,33 @@ static int si5351_dt_parse(struct i2c_client *client)
1225 } 1260 }
1226 } 1261 }
1227 1262
1263 if (!of_property_read_u32(child, "silabs,disable-state",
1264 &val)) {
1265 switch (val) {
1266 case 0:
1267 pdata->clkout[num].disable_state =
1268 SI5351_DISABLE_LOW;
1269 break;
1270 case 1:
1271 pdata->clkout[num].disable_state =
1272 SI5351_DISABLE_HIGH;
1273 break;
1274 case 2:
1275 pdata->clkout[num].disable_state =
1276 SI5351_DISABLE_FLOATING;
1277 break;
1278 case 3:
1279 pdata->clkout[num].disable_state =
1280 SI5351_DISABLE_NEVER;
1281 break;
1282 default:
1283 dev_err(&client->dev,
1284 "invalid disable state %d for clkout %d\n",
1285 val, num);
1286 return -EINVAL;
1287 }
1288 }
1289
1228 if (!of_property_read_u32(child, "clock-frequency", &val)) 1290 if (!of_property_read_u32(child, "clock-frequency", &val))
1229 pdata->clkout[num].rate = val; 1291 pdata->clkout[num].rate = val;
1230 1292
@@ -1281,9 +1343,6 @@ static int si5351_i2c_probe(struct i2c_client *client,
1281 1343
1282 /* Disable interrupts */ 1344 /* Disable interrupts */
1283 si5351_reg_write(drvdata, SI5351_INTERRUPT_MASK, 0xf0); 1345 si5351_reg_write(drvdata, SI5351_INTERRUPT_MASK, 0xf0);
1284 /* Set disabled output drivers to drive low */
1285 si5351_reg_write(drvdata, SI5351_CLK3_0_DISABLE_STATE, 0x00);
1286 si5351_reg_write(drvdata, SI5351_CLK7_4_DISABLE_STATE, 0x00);
1287 /* Ensure pll select is on XTAL for Si5351A/B */ 1346 /* Ensure pll select is on XTAL for Si5351A/B */
1288 if (drvdata->variant != SI5351_VARIANT_C) 1347 if (drvdata->variant != SI5351_VARIANT_C)
1289 si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE, 1348 si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE,
@@ -1327,6 +1386,15 @@ static int si5351_i2c_probe(struct i2c_client *client,
1327 n, pdata->clkout[n].drive); 1386 n, pdata->clkout[n].drive);
1328 return ret; 1387 return ret;
1329 } 1388 }
1389
1390 ret = _si5351_clkout_set_disable_state(drvdata, n,
1391 pdata->clkout[n].disable_state);
1392 if (ret) {
1393 dev_err(&client->dev,
1394 "failed set disable state of clkout%d to %d\n",
1395 n, pdata->clkout[n].disable_state);
1396 return ret;
1397 }
1330 } 1398 }
1331 1399
1332 /* register xtal input clock gate */ 1400 /* register xtal input clock gate */