[PATCH] clk/arc: Add I2S PLL clock driver

Jose Abreu Jose.Abreu at synopsys.com
Tue Mar 29 10:51:34 PDT 2016


Hi Vineet,

On 29-03-2016 13:36, Vineet Gupta wrote:
> On Tuesday 29 March 2016 04:55 PM, Alexey Brodkin wrote:
>> Hi Jose,
>>
>> On Tue, 2016-03-29 at 11:56 +0100, Jose Abreu wrote:
>>> The ARC SDP I2S clock can be programmed using a
>>> specific PLL.
>>>
>>> This patch has the goal of adding a clock driver
>>> that programs this PLL.
>>>
>>> At this moment the rate values are hardcoded in
>>> a table but in the future it would be ideal to
>>> use a function which determines the PLL values
>>> given the desired rate.
>>>
>>> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
>>> ---
>> I believe these kind of patches worth sending to
>> linux-snps mailing list (at least add it in Cc) so
>> they won't be lost in time and could be used later as
>> useful references.
> Please do also CC the common clk maintainers
>
> COMMON CLK FRAMEWORK
> M:    Michael Turquette <mturquette at baylibre.com>
> M:    Stephen Boyd <sboyd at codeaurora.org>
> L:    linux-clk at vger.kernel.org

Well, this was just an experiment and I think this patch is still far from being
ready to go mainline, that's why I did not cc'ed the clk maintainers. I will
send a v2 soon so you can review and if you think its worth sending to mainline
I will do that.

>>>  arch/arc/boot/dts/axs10x_mb.dtsi |   5 ++
>>>  drivers/clk/Makefile             |   1 +
>>>  drivers/clk/arc/Makefile         |   1 +
>>>  drivers/clk/arc/i2s_pll_clock.c  | 143 +++++++++++++++++++++++++++++++++++++++
>>>  4 files changed, 150 insertions(+)
>>>  create mode 100644 drivers/clk/arc/Makefile
>>>  create mode 100644 drivers/clk/arc/i2s_pll_clock.c
>>>
>>> diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
>>> index ab5d570..9c68226 100644
>>> --- a/arch/arc/boot/dts/axs10x_mb.dtsi
>>> +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
>>> @@ -23,6 +23,11 @@
>>>  				#clock-cells = <0>;
>>>  			};
>>>  
>>> +			i2sclk: i2sclk {
>>> +				compatible = "snps,i2s-pll-clock";
>>> +				#clock-cells = <0>;
>>> +			};
>>> +
>>>  			apbclk: apbclk {
>>>  				compatible = "fixed-clock";
>>>  				clock-frequency = <50000000>;
>>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>>> index 46869d6..620e47f 100644
>>> --- a/drivers/clk/Makefile
>>> +++ b/drivers/clk/Makefile
>>> @@ -84,3 +84,4 @@ obj-$(CONFIG_X86)			+= x86/
>>>  obj-$(CONFIG_ARCH_ZX)			+= zte/
>>>  obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
>>>  obj-$(CONFIG_H8300)		+= h8300/
>>> +obj-$(CONFIG_ARC)		+= arc/
>> Two things here:
>>  [1] This clock is relevant to only one board but not SoC, CPU core
>>      or whole architecture, so it makes sense to make it dependent on
>>      the AXS platform, i.e. CONFIG_ARC_PLAT_AXS10X.
>>
>>  [2] Something similar is applicable to folder name, I would suggest to
>>      use "drivers/clk/axs10x"
>>
>>> diff --git a/drivers/clk/arc/Makefile b/drivers/clk/arc/Makefile
>>> new file mode 100644
>>> index 0000000..01996b8
>>> --- /dev/null
>>> +++ b/drivers/clk/arc/Makefile
>>> @@ -0,0 +1 @@
>>> +obj-y += i2s_pll_clock.o
>>> diff --git a/drivers/clk/arc/i2s_pll_clock.c b/drivers/clk/arc/i2s_pll_clock.c
>>> new file mode 100644
>>> index 0000000..8c401f1
>>> --- /dev/null
>>> +++ b/drivers/clk/arc/i2s_pll_clock.c
>>> @@ -0,0 +1,143 @@
>>> +/*
>>> + * Synopsys I2S PLL clock driver
>> Again that's not generic SNPS I2S clock but clock driver for a particular board.
>>
>>> + *
>>> + * drivers/clk/arc/i2s_pll_clock.c
>> BTW not sure why this path could be needed here.
>> IMHO that might be safely dropped.
>>
>>> + *
>>> + * Copyright (C) 2016 Synopsys
>>> + *
>>> + * This file is licensed under the terms of the GNU General Public
>>> + * License version 2. This program is licensed "as is" without any
>>> + * warranty of any kind, whether express or implied.
>>> + */
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/err.h>
>>> +#include <linux/device.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/slab.h>
>>> +
>>> +/* FPGA Version Info */
>>> +#define FPGA_VER_INFO	0xE0011230
>>> +#define FPGA_VER_27M	0x000FBED9
>> This is a little bit tricky.
>> We'll need to do that check in each and every clock driver for AXS10x
>> and so it worth putting this code in some common location (I mean common
>> for all axs10x clock drivers).
>>
>>> +/* PLL registers addresses */
>>> +#define PLL_IDIV_ADDR	0xE00100A0
>>> +#define PLL_FBDIV_ADDR	0xE00100A4
>>> +#define PLL_ODIV0_ADDR	0xE00100A8
>>> +#define PLL_ODIV1_ADDR	0xE00100AC
>>>
>>> +struct i2s_pll_clk {
>>> +	struct clk_hw hw;
>>> +};
>>> +
>>> +struct i2s_pll_cfg {
>>> +	unsigned int rate;
>>> +	unsigned int idiv;
>>> +	unsigned int fbdiv;
>>> +	unsigned int odiv0;
>>> +	unsigned int odiv1;
>>> +};
>>> +
>>> +static const struct i2s_pll_cfg i2s_pll_cfg_27m[] = {
>>> +	/* 27 Mhz */
>>> +	{ 1024000, 0x104, 0x451, 0x10E38, 0x2000 },
>>> +	{ 1411200, 0x104, 0x596, 0x10D35, 0x2000 },
>>> +	{ 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 },
>>> +	{ 2048000, 0x82, 0x451, 0x10E38, 0x2000 },
>>> +	{ 2822400, 0x82, 0x596, 0x10D35, 0x2000 },
>>> +	{ 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 },
>>> +	{ 0, 0, 0, 0, 0 },
>>> +};
>>> +
>>> +static const struct i2s_pll_cfg i2s_pll_cfg_28m[] = {
>>> +	/* 28.224 Mhz */
>>> +	{ 1024000, 0x82, 0x105, 0x107DF, 0x2000 },
>>> +	{ 1411200, 0x28A, 0x1, 0x10001, 0x2000 },
>>> +	{ 1536000, 0xA28, 0x187, 0x10042, 0x2000 },
>>> +	{ 2048000, 0x41, 0x105, 0x107DF, 0x2000 },
>>> +	{ 2822400, 0x145, 0x1, 0x10001, 0x2000 },
>>> +	{ 3072000, 0x514, 0x187, 0x10042, 0x2000 },
>>> +	{ 0, 0, 0, 0, 0 },
>>> +};
>>> +
>>> +static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
>>> +			unsigned long parent_rate)
>>> +{
>>> +	/* TODO */
>>> +	pr_info("%s: parent_rate=%ld\n", __func__, parent_rate);
>>> +	return parent_rate;
>>> +}
>>> +
>>> +static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
>>> +			unsigned long *prate)
>>> +{
>>> +	/* TODO: Round rate to nearest valid rate */
>>> +	*prate = rate;
>>> +	pr_info("%s: rate=%ld, prate=%ld\n", __func__, rate, *prate);
>>> +	return *prate;
>>> +}
>> These are now just dummy functions so probably they could be dropped.
>>
>>> +static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>>> +			unsigned long parent_rate)
>>> +{
>>> +	const struct i2s_pll_cfg *pll_cfg;
>>> +	int i;
>>> +
>>> +	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
>>> +		pll_cfg = i2s_pll_cfg_27m;
>>> +	else
>>> +		pll_cfg = i2s_pll_cfg_28m;
>> As I mentioned above we need to check board version in common place and then
>> just use some variable or structure member for comparison.
>>
>> Otherwise it looks pretty nice!
>>
>> -Alexey
>

Best regards,
Jose Miguel Abreu



More information about the linux-snps-arc mailing list