diff options
-rw-r--r-- | Documentation/devicetree/bindings/clock/silabs,si5351.txt | 5 | ||||
-rw-r--r-- | drivers/clk/clk-si5351.c | 74 | ||||
-rw-r--r-- | drivers/clk/clk-si5351.h | 1 | ||||
-rw-r--r-- | include/linux/platform_data/si5351.h | 18 |
4 files changed, 95 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/clock/silabs,si5351.txt b/Documentation/devicetree/bindings/clock/silabs,si5351.txt index cc374651662c..66c75b2d6158 100644 --- a/Documentation/devicetree/bindings/clock/silabs,si5351.txt +++ b/Documentation/devicetree/bindings/clock/silabs,si5351.txt | |||
@@ -44,6 +44,11 @@ Optional child node properties: | |||
44 | - silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth | 44 | - silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth |
45 | divider. | 45 | divider. |
46 | - silabs,pll-master: boolean, multisynth can change pll frequency. | 46 | - silabs,pll-master: boolean, multisynth can change pll frequency. |
47 | - silabs,disable-state : clock output disable state, shall be | ||
48 | 0 = clock output is driven LOW when disabled | ||
49 | 1 = clock output is driven HIGH when disabled | ||
50 | 2 = clock output is FLOATING (HIGH-Z) when disabled | ||
51 | 3 = clock output is NEVER disabled | ||
47 | 52 | ||
48 | ==Example== | 53 | ==Example== |
49 | 54 | ||
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 */ |
diff --git a/drivers/clk/clk-si5351.h b/drivers/clk/clk-si5351.h index af41b5080f43..c0dbf2676872 100644 --- a/drivers/clk/clk-si5351.h +++ b/drivers/clk/clk-si5351.h | |||
@@ -81,6 +81,7 @@ | |||
81 | 81 | ||
82 | #define SI5351_CLK3_0_DISABLE_STATE 24 | 82 | #define SI5351_CLK3_0_DISABLE_STATE 24 |
83 | #define SI5351_CLK7_4_DISABLE_STATE 25 | 83 | #define SI5351_CLK7_4_DISABLE_STATE 25 |
84 | #define SI5351_CLK_DISABLE_STATE_MASK 3 | ||
84 | #define SI5351_CLK_DISABLE_STATE_LOW 0 | 85 | #define SI5351_CLK_DISABLE_STATE_LOW 0 |
85 | #define SI5351_CLK_DISABLE_STATE_HIGH 1 | 86 | #define SI5351_CLK_DISABLE_STATE_HIGH 1 |
86 | #define SI5351_CLK_DISABLE_STATE_FLOAT 2 | 87 | #define SI5351_CLK_DISABLE_STATE_FLOAT 2 |
diff --git a/include/linux/platform_data/si5351.h b/include/linux/platform_data/si5351.h index 92dabcaf6499..54334393ab92 100644 --- a/include/linux/platform_data/si5351.h +++ b/include/linux/platform_data/si5351.h | |||
@@ -79,6 +79,23 @@ enum si5351_drive_strength { | |||
79 | }; | 79 | }; |
80 | 80 | ||
81 | /** | 81 | /** |
82 | * enum si5351_disable_state - Si5351 clock output disable state | ||
83 | * @SI5351_DISABLE_DEFAULT: default, do not change eeprom config | ||
84 | * @SI5351_DISABLE_LOW: CLKx is set to a LOW state when disabled | ||
85 | * @SI5351_DISABLE_HIGH: CLKx is set to a HIGH state when disabled | ||
86 | * @SI5351_DISABLE_FLOATING: CLKx is set to a FLOATING state when | ||
87 | * disabled | ||
88 | * @SI5351_DISABLE_NEVER: CLKx is NEVER disabled | ||
89 | */ | ||
90 | enum si5351_disable_state { | ||
91 | SI5351_DISABLE_DEFAULT = 0, | ||
92 | SI5351_DISABLE_LOW, | ||
93 | SI5351_DISABLE_HIGH, | ||
94 | SI5351_DISABLE_FLOATING, | ||
95 | SI5351_DISABLE_NEVER, | ||
96 | }; | ||
97 | |||
98 | /** | ||
82 | * struct si5351_clkout_config - Si5351 clock output configuration | 99 | * struct si5351_clkout_config - Si5351 clock output configuration |
83 | * @clkout: clkout number | 100 | * @clkout: clkout number |
84 | * @multisynth_src: multisynth source clock | 101 | * @multisynth_src: multisynth source clock |
@@ -91,6 +108,7 @@ struct si5351_clkout_config { | |||
91 | enum si5351_multisynth_src multisynth_src; | 108 | enum si5351_multisynth_src multisynth_src; |
92 | enum si5351_clkout_src clkout_src; | 109 | enum si5351_clkout_src clkout_src; |
93 | enum si5351_drive_strength drive; | 110 | enum si5351_drive_strength drive; |
111 | enum si5351_disable_state disable_state; | ||
94 | bool pll_master; | 112 | bool pll_master; |
95 | unsigned long rate; | 113 | unsigned long rate; |
96 | }; | 114 | }; |