diff options
Diffstat (limited to 'drivers/clk/clk-si5351.c')
-rw-r--r-- | drivers/clk/clk-si5351.c | 74 |
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 | ||
854 | static 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 | |||
854 | static int si5351_clkout_prepare(struct clk_hw *hw) | 889 | static 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 */ |