Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a0483d2 authored by Sebastian Hesselbarth's avatar Sebastian Hesselbarth Committed by Mike Turquette
Browse files

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: default avatarMarek Belisko <marek.belisko@streamunlimited.com>
Signed-off-by: default avatarSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: default avatarMike Turquette <mturquette@linaro.org>
parent 555eae97
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -44,6 +44,11 @@ Optional child node properties:
- silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth
- silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth
  divider.
  divider.
- silabs,pll-master: boolean, multisynth can change pll frequency.
- silabs,pll-master: boolean, multisynth can change pll frequency.
- silabs,disable-state : clock output disable state, shall be
  0 = clock output is driven LOW when disabled
  1 = clock output is driven HIGH when disabled
  2 = clock output is FLOATING (HIGH-Z) when disabled
  3 = clock output is NEVER disabled


==Example==
==Example==


+71 −3
Original line number Original line Diff line number Diff line
@@ -851,6 +851,41 @@ static int _si5351_clkout_set_drive_strength(
	return 0;
	return 0;
}
}


static int _si5351_clkout_set_disable_state(
	struct si5351_driver_data *drvdata, int num,
	enum si5351_disable_state state)
{
	u8 reg = (num < 4) ? SI5351_CLK3_0_DISABLE_STATE :
		SI5351_CLK7_4_DISABLE_STATE;
	u8 shift = (num < 4) ? (2 * num) : (2 * (num-4));
	u8 mask = SI5351_CLK_DISABLE_STATE_MASK << shift;
	u8 val;

	if (num > 8)
		return -EINVAL;

	switch (state) {
	case SI5351_DISABLE_LOW:
		val = SI5351_CLK_DISABLE_STATE_LOW;
		break;
	case SI5351_DISABLE_HIGH:
		val = SI5351_CLK_DISABLE_STATE_HIGH;
		break;
	case SI5351_DISABLE_FLOATING:
		val = SI5351_CLK_DISABLE_STATE_FLOAT;
		break;
	case SI5351_DISABLE_NEVER:
		val = SI5351_CLK_DISABLE_STATE_NEVER;
		break;
	default:
		return 0;
	}

	si5351_set_bits(drvdata, reg, mask, val << shift);

	return 0;
}

static int si5351_clkout_prepare(struct clk_hw *hw)
static int si5351_clkout_prepare(struct clk_hw *hw)
{
{
	struct si5351_hw_data *hwdata =
	struct si5351_hw_data *hwdata =
@@ -1225,6 +1260,33 @@ static int si5351_dt_parse(struct i2c_client *client)
			}
			}
		}
		}


		if (!of_property_read_u32(child, "silabs,disable-state",
					  &val)) {
			switch (val) {
			case 0:
				pdata->clkout[num].disable_state =
					SI5351_DISABLE_LOW;
				break;
			case 1:
				pdata->clkout[num].disable_state =
					SI5351_DISABLE_HIGH;
				break;
			case 2:
				pdata->clkout[num].disable_state =
					SI5351_DISABLE_FLOATING;
				break;
			case 3:
				pdata->clkout[num].disable_state =
					SI5351_DISABLE_NEVER;
				break;
			default:
				dev_err(&client->dev,
					"invalid disable state %d for clkout %d\n",
					val, num);
				return -EINVAL;
			}
		}

		if (!of_property_read_u32(child, "clock-frequency", &val))
		if (!of_property_read_u32(child, "clock-frequency", &val))
			pdata->clkout[num].rate = val;
			pdata->clkout[num].rate = val;


@@ -1281,9 +1343,6 @@ static int si5351_i2c_probe(struct i2c_client *client,


	/* Disable interrupts */
	/* Disable interrupts */
	si5351_reg_write(drvdata, SI5351_INTERRUPT_MASK, 0xf0);
	si5351_reg_write(drvdata, SI5351_INTERRUPT_MASK, 0xf0);
	/* Set disabled output drivers to drive low */
	si5351_reg_write(drvdata, SI5351_CLK3_0_DISABLE_STATE, 0x00);
	si5351_reg_write(drvdata, SI5351_CLK7_4_DISABLE_STATE, 0x00);
	/* Ensure pll select is on XTAL for Si5351A/B */
	/* Ensure pll select is on XTAL for Si5351A/B */
	if (drvdata->variant != SI5351_VARIANT_C)
	if (drvdata->variant != SI5351_VARIANT_C)
		si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE,
		si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE,
@@ -1327,6 +1386,15 @@ static int si5351_i2c_probe(struct i2c_client *client,
				n, pdata->clkout[n].drive);
				n, pdata->clkout[n].drive);
			return ret;
			return ret;
		}
		}

		ret = _si5351_clkout_set_disable_state(drvdata, n,
						pdata->clkout[n].disable_state);
		if (ret) {
			dev_err(&client->dev,
				"failed set disable state of clkout%d to %d\n",
				n, pdata->clkout[n].disable_state);
			return ret;
		}
	}
	}


	/* register xtal input clock gate */
	/* register xtal input clock gate */
+1 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,7 @@


#define SI5351_CLK3_0_DISABLE_STATE		24
#define SI5351_CLK3_0_DISABLE_STATE		24
#define SI5351_CLK7_4_DISABLE_STATE		25
#define SI5351_CLK7_4_DISABLE_STATE		25
#define  SI5351_CLK_DISABLE_STATE_MASK		3
#define  SI5351_CLK_DISABLE_STATE_LOW		0
#define  SI5351_CLK_DISABLE_STATE_LOW		0
#define  SI5351_CLK_DISABLE_STATE_HIGH		1
#define  SI5351_CLK_DISABLE_STATE_HIGH		1
#define  SI5351_CLK_DISABLE_STATE_FLOAT		2
#define  SI5351_CLK_DISABLE_STATE_FLOAT		2
+18 −0
Original line number Original line Diff line number Diff line
@@ -78,6 +78,23 @@ enum si5351_drive_strength {
	SI5351_DRIVE_8MA = 8,
	SI5351_DRIVE_8MA = 8,
};
};


/**
 * enum si5351_disable_state - Si5351 clock output disable state
 * @SI5351_DISABLE_DEFAULT: default, do not change eeprom config
 * @SI5351_DISABLE_LOW: CLKx is set to a LOW state when disabled
 * @SI5351_DISABLE_HIGH: CLKx is set to a HIGH state when disabled
 * @SI5351_DISABLE_FLOATING: CLKx is set to a FLOATING state when
 *				disabled
 * @SI5351_DISABLE_NEVER: CLKx is NEVER disabled
 */
enum si5351_disable_state {
	SI5351_DISABLE_DEFAULT = 0,
	SI5351_DISABLE_LOW,
	SI5351_DISABLE_HIGH,
	SI5351_DISABLE_FLOATING,
	SI5351_DISABLE_NEVER,
};

/**
/**
 * struct si5351_clkout_config - Si5351 clock output configuration
 * struct si5351_clkout_config - Si5351 clock output configuration
 * @clkout: clkout number
 * @clkout: clkout number
@@ -91,6 +108,7 @@ struct si5351_clkout_config {
	enum si5351_multisynth_src multisynth_src;
	enum si5351_multisynth_src multisynth_src;
	enum si5351_clkout_src clkout_src;
	enum si5351_clkout_src clkout_src;
	enum si5351_drive_strength drive;
	enum si5351_drive_strength drive;
	enum si5351_disable_state disable_state;
	bool pll_master;
	bool pll_master;
	unsigned long rate;
	unsigned long rate;
};
};