aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/clock/silabs,si5351.txt5
-rw-r--r--drivers/clk/clk-si5351.c74
-rw-r--r--drivers/clk/clk-si5351.h1
-rw-r--r--include/linux/platform_data/si5351.h18
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
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 */
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 */
90enum 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};