From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mike Turquette Subject: Re: [PATCH v2] clk: si5351: Allow user to define disabled state for every clock output Date: Tue, 14 May 2013 12:13:50 -0700 Message-ID: <20130514191350.10068.22100@quantum> References: <1367559207-20086-1-git-send-email-marek.belisko@streamunlimited.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1367559207-20086-1-git-send-email-marek.belisko-6oiIBCxl0MMjD8S081q9vkEOCMrvLtNR@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: devicetree-discuss-bounces+gldd-devicetree-discuss=m.gmane.org-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org Sender: "devicetree-discuss" To: Marek Belisko Cc: linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org, vladimir.koutny-6oiIBCxl0MMjD8S081q9vkEOCMrvLtNR@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, Marek Belisko , daniel-cYrQPVfZoowdnm+yROfE0A@public.gmane.org, Sebastian Hesselbarth List-Id: devicetree@vger.kernel.org Quoting Marek Belisko (2013-05-02 22:33:27) > From: Sebastian Hesselbarth > > 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 > Signed-off-by: Sebastian Hesselbarth Taken into clk-next. Thanks, Mike > --- > Changes from v1->v2: > Sebastian Hesselbarth send me updated version of patch which was based > on v1. Resending with updates. > > .../devicetree/bindings/clock/silabs,si5351.txt | 5 ++ > drivers/clk/clk-si5351.c | 74 +++++++++++++++++++- > drivers/clk/clk-si5351.h | 1 + > 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 cc37465..66c75b2 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: > - silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth > divider. > - 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== > > diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c > index 8323c31..098f28b 100644 > --- a/drivers/clk/clk-si5351.c > +++ b/drivers/clk/clk-si5351.c > @@ -851,6 +851,41 @@ static int _si5351_clkout_set_drive_strength( > 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) > { > 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)) > pdata->clkout[num].rate = val; > > @@ -1281,9 +1343,6 @@ static int si5351_i2c_probe(struct i2c_client *client, > > /* Disable interrupts */ > 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 */ > if (drvdata->variant != SI5351_VARIANT_C) > 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); > 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 */ > diff --git a/drivers/clk/clk-si5351.h b/drivers/clk/clk-si5351.h > index af41b50..c0dbf26 100644 > --- a/drivers/clk/clk-si5351.h > +++ b/drivers/clk/clk-si5351.h > @@ -81,6 +81,7 @@ > > #define SI5351_CLK3_0_DISABLE_STATE 24 > #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_HIGH 1 > #define SI5351_CLK_DISABLE_STATE_FLOAT 2 > diff --git a/include/linux/platform_data/si5351.h b/include/linux/platform_data/si5351.h > index 92dabca..5433439 100644 > --- a/include/linux/platform_data/si5351.h > +++ b/include/linux/platform_data/si5351.h > @@ -79,6 +79,23 @@ enum si5351_drive_strength { > }; > > /** > + * 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 > * @clkout: clkout number > * @multisynth_src: multisynth source clock > @@ -91,6 +108,7 @@ struct si5351_clkout_config { > enum si5351_multisynth_src multisynth_src; > enum si5351_clkout_src clkout_src; > enum si5351_drive_strength drive; > + enum si5351_disable_state disable_state; > bool pll_master; > unsigned long rate; > }; > -- > 1.7.9.5