Add AXS10X I2S PLL clock driver
Subsystems (5)
v6 cover Add AXS10X I2S PLL clock driver
The ARC SDP I2S clock can be programmed using a
specific PLL.
This patch series has the goal of adding a clock driver that programs this PLL.
----
Changes v5 -> v6:
* Use parent clock to determine PLL input rate instead of using hardcoded values
* Documentation update (added 'clocks' field)
* Device tree update (added 'clocks' field)
Changes v4 -> v5:
* Documentation update (as suggested by Alexey Brodkin)
* Changed compatible string to "snps,axs10x-i2s-pll-clock" (as suggested by Alexey Brodkin)
* Added DT bindings
Changes v3 -> v4:
* Added binding document (as suggested by Stephen Boyd)
* Minor code style fixes (as suggested by Stephen Boyd)
* Use ioremap (as suggested by Stephen Boyd)
* Implement round_rate (as suggested by Stephen Boyd)
* Change to platform driver (as suggested by Stephen Boyd)
* Use {readl/writel}_relaxed (as suggested by Vineet Gupta)
Changes v2 -> v3:
* Implemented recalc_rate
Changes v1 -> v2:
* Renamed folder to axs10x (as suggested by Alexey Brodkin)
* Added more supported rates
Jose Abreu (2):
clk/axs10x: Add I2S PLL clock driver
arc: axs10x: Add DT bindings for I2S PLL Clock
.../bindings/clock/axs10x-i2s-pll-clock.txt | 25 +++ arch/arc/boot/dts/axs10x_mb.dtsi | 13 ++ drivers/clk/Makefile | 1 + drivers/clk/axs10x/Makefile | 1 + drivers/clk/axs10x/i2s_pll_clock.c | 228 +++++++++++++++++++++ 5 files changed, 268 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt create mode 100644 drivers/clk/axs10x/Makefile create mode 100644 drivers/clk/axs10x/i2s_pll_clock.c
Signature · 1 line
1.9.1
PATCH v6 1/2 clk/axs10x: Add I2S PLL clock driver
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.
---
Changes v5 -> v6:
* Use parent clock to determine PLL input rate instead of using hardcoded values
* Documentation update (added 'clocks' field)
Changes v4 -> v5:
* Documentation update (as suggested by Alexey Brodkin)
* Changed compatible string to "snps,axs10x-i2s-pll-clock" (as suggested by Alexey Brodkin)
Changes v3 -> v4:
* Added binding document (as suggested by Stephen Boyd)
* Minor code style fixes (as suggested by Stephen Boyd)
* Use ioremap (as suggested by Stephen Boyd)
* Implement round_rate (as suggested by Stephen Boyd)
* Change to platform driver (as suggested by Stephen Boyd)
* Use {readl/writel}_relaxed (as suggested by Vineet Gupta)
Changes v2 -> v3:
* Implemented recalc_rate
Changes v1 -> v2:
* Renamed folder to axs10x (as suggested by Alexey Brodkin)
* Added more supported rates
.../bindings/clock/axs10x-i2s-pll-clock.txt | 25 +++ drivers/clk/Makefile | 1 + drivers/clk/axs10x/Makefile | 1 + drivers/clk/axs10x/i2s_pll_clock.c | 228 +++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt create mode 100644 drivers/clk/axs10x/Makefile create mode 100644 drivers/clk/axs10x/i2s_pll_clock.c
Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt new file +25 -0
@@ -0,0 +1,25 @@ +Binding for the AXS10X I2S PLL clock + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible: shall be "snps,axs10x-i2s-pll-clock" +- reg : address and length of the I2S PLL register set. +- clocks: shall be the input parent clock phandle for the PLL. +- #clock-cells: from common clock binding; Should always be set to 0. + +Example: + pll_clock: pll_clock { + compatible = "fixed-clock"; + clock-frequency = <27000000>; + #clock-cells = <0>; + }; + + i2s_clock at 100a0 { + compatible = "snps,axs10x-i2s-pll-clock"; + reg = <0x100a0 0x10>; + clocks = <&pll_clock>; + #clock-cells = <0>; + };
drivers/clk/Makefile +1 -0
@@ -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_PLAT_AXS10X) += axs10x/
drivers/clk/axs10x/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-y += i2s_pll_clock.o
drivers/clk/axs10x/i2s_pll_clock.c new file +228 -0
228 lines not on this page · raw message
Signature · 1 line
1.9.1
Re: [PATCH 1/2 v6] clk/axs10x: Add I2S PLL clock driver
Adding device tree mailing list and Rob Herring.
Quoted 327 lines · Jose Abreu
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 <[email protected]>---
Changes v5 -> v6:
* Use parent clock to determine PLL input rate instead of using hardcoded values
* Documentation update (added 'clocks' field)Changes v4 -> v5:
* Documentation update (as suggested by Alexey Brodkin)
* Changed compatible string to "snps,axs10x-i2s-pll-clock" (as suggested by Alexey Brodkin)Changes v3 -> v4:
* Added binding document (as suggested by Stephen Boyd)
* Minor code style fixes (as suggested by Stephen Boyd)
* Use ioremap (as suggested by Stephen Boyd)
* Implementround_rate(as suggested by Stephen Boyd)
* Change to platform driver (as suggested by Stephen Boyd)
* Use {readl/writel}_relaxed (as suggested by Vineet Gupta)Changes v2 -> v3:
* Implementedrecalc_rateChanges v1 -> v2:
* Renamed folder to axs10x (as suggested by Alexey Brodkin)
* Added more supported rates.../bindings/clock/axs10x-i2s-pll-clock.txt | 25 +++ drivers/clk/Makefile | 1 + drivers/clk/axs10x/Makefile | 1 + drivers/clk/axs10x/i2s_pll_clock.c | 228 +++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt create mode 100644 drivers/clk/axs10x/Makefile create mode 100644 drivers/clk/axs10x/i2s_pll_clock.cDocumentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt new file +25
-0@@ -0,0 +1,25 @@ +Binding for the AXS10X I2S PLL clock + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible: shall be "snps,axs10x-i2s-pll-clock" +- reg : address and length of the I2S PLL register set. +- clocks: shall be the input parent clock phandle for the PLL. +- #clock-cells: from common clock binding; Should always be set to 0. + +Example: + pll_clock: pll_clock { + compatible = "fixed-clock"; + clock-frequency = <27000000>; + #clock-cells = <0>; + }; + + i2s_clock@100a0 { + compatible = "snps,axs10x-i2s-pll-clock"; + reg = <0x100a0 0x10>; + clocks = <&pll_clock>; + #clock-cells = <0>; + };drivers/clk/Makefile +1
-0@@ -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_PLAT_AXS10X) += axs10x/drivers/clk/axs10x/Makefile new file +1
-0@@ -0,0 +1 @@ +obj-y += i2s_pll_clock.odrivers/clk/axs10x/i2s_pll_clock.c new file +228
-0@@ -0,0 +1,228 @@ +/* +* Synopsys AXS10X SDP I2S PLL clock driver +* +* 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/platform_device.h> +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/device.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/of.h> + +/* PLL registers addresses */ +#define PLL_IDIV_REG 0x0 +#define PLL_FBDIV_REG 0x4 +#define PLL_ODIV0_REG 0x8 +#define PLL_ODIV1_REG 0xC + +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 }, + {2116800 ,0x82 ,0x3CF ,0x10C30 ,0x2000 }, + {2304000 ,0x104 ,0x79E ,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 }, + {2116800 ,0x514 ,0x42 ,0x10001 ,0x2000 }, + {2304000 ,0x619 ,0x82 ,0x10001 ,0x2000 }, + {0 ,0 ,0 ,0 ,0 }, +}; + +struct i2s_pll_clk { +void __iomem *base; +struct clk_hw hw; +struct device *dev; +}; + +static inline void i2s_pll_write (struct i2s_pll_clk *clk,unsigned int reg, +unsigned int val) +{ +writel_relaxed (val, clk->base + reg); +} + +static inline unsigned int i2s_pll_read (struct i2s_pll_clk *clk, +unsigned int reg) +{ +return readl_relaxed (clk->base + reg); +} + +static inline struct i2s_pll_clk *to_i2s_pll_clk (struct clk_hw *hw) +{ + return container_of(hw, struct i2s_pll_clk, hw); +} + +static inline unsigned int i2s_pll_get_value (unsigned int val) +{ +return (val &0x3F ) + ((val >>6 ) &0x3F ); +} + +static const struct i2s_pll_cfg *i2s_pll_get_cfg (unsigned long prate) +{ +switch (prate) { +case 27000000 : +return i2s_pll_cfg_27m; +case 28224000 : +return i2s_pll_cfg_28m; +default : +return NULL ; + } +} + +static unsigned long i2s_pll_recalc_rate (struct clk_hw *hw, +unsigned long parent_rate) +{ +struct i2s_pll_clk *clk =to_i2s_pll_clk (hw); +unsigned int idiv, fbdiv, odiv; + + idiv =i2s_pll_get_value (i2s_pll_read (clk,PLL_IDIV_REG )); + fbdiv =i2s_pll_get_value (i2s_pll_read (clk,PLL_FBDIV_REG )); + odiv =i2s_pll_get_value (i2s_pll_read (clk,PLL_ODIV0_REG )); + +return ((parent_rate / idiv) * fbdiv) / odiv; +} + +static long i2s_pll_round_rate (struct clk_hw *hw,unsigned long rate, +unsigned long *prate) +{ +struct i2s_pll_clk *clk =to_i2s_pll_clk (hw); +const struct i2s_pll_cfg *pll_cfg =i2s_pll_get_cfg (*prate); +int i; + +if (!pll_cfg) { +dev_err (clk->dev,"invalid parent rate=%ld\n" , *prate); +return -EINVAL ; + } + +for (i =0 ; pll_cfg[i].rate !=0 ; i++) +if (pll_cfg[i].rate == rate) +return rate; + +return -EINVAL ; +} + +static int i2s_pll_set_rate (struct clk_hw *hw,unsigned long rate, +unsigned long parent_rate) +{ +struct i2s_pll_clk *clk =to_i2s_pll_clk (hw); +const struct i2s_pll_cfg *pll_cfg =i2s_pll_get_cfg (parent_rate); +int i; + +if (!pll_cfg) { +dev_err (clk->dev,"invalid parent rate=%ld\n" , parent_rate); +return -EINVAL ; + } + +for (i =0 ; pll_cfg[i].rate !=0 ; i++) { +if (pll_cfg[i].rate == rate) { +i2s_pll_write (clk,PLL_IDIV_REG , pll_cfg[i].idiv); +i2s_pll_write (clk,PLL_FBDIV_REG , pll_cfg[i].fbdiv); +i2s_pll_write (clk,PLL_ODIV0_REG , pll_cfg[i].odiv0); +i2s_pll_write (clk,PLL_ODIV1_REG , pll_cfg[i].odiv1); +return 0 ; + } + } + +dev_err (clk->dev,"invalid rate=%ld, parent_rate=%ld\n" , rate, + parent_rate); +return -EINVAL ; +} + +static const struct clk_ops i2s_pll_ops = { + .recalc_rate = i2s_pll_recalc_rate, + .round_rate = i2s_pll_round_rate, + .set_rate = i2s_pll_set_rate, +}; + +static int i2s_pll_clk_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct device_node *node = dev->of_node; +const char *clk_name; +const char *parent_name; +struct clk *clk; +struct i2s_pll_clk *pll_clk; +struct clk_init_data init; +struct resource *mem; + + pll_clk =devm_kzalloc (dev,sizeof (*pll_clk),GFP_KERNEL ); +if (!pll_clk) +return -ENOMEM ; + + mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + pll_clk->base =devm_ioremap_resource (dev, mem); +if (IS_ERR (pll_clk->base)) +return PTR_ERR (pll_clk->base); + + clk_name = node->name; + init.name = clk_name; + init.ops = &i2s_pll_ops; + parent_name =of_clk_get_parent_name (node,0 ); + init.parent_names = &parent_name; + init.num_parents =1 ; + pll_clk->hw.init = &init; + pll_clk->dev = dev; + + clk =devm_clk_register (dev, &pll_clk->hw); +if (IS_ERR (clk)) { +dev_err (dev,"failed to register %s clock (%ld)\n" , + clk_name,PTR_ERR (clk)); +return PTR_ERR (clk); + } + +return of_clk_add_provider (node, of_clk_src_simple_get, clk); +} + +static int i2s_pll_clk_remove (struct platform_device *pdev) +{ +of_clk_del_provider (pdev->dev.of_node); +return 0 ; +} + +static const struct of_device_id i2s_pll_clk_id[] = { + { .compatible ="snps,axs10x-i2s-pll-clock" , }, + { }, +}; +MODULE_DEVICE_TABLE (of, i2s_pll_clk_id); + +static struct platform_driver i2s_pll_clk_driver = { + .driver = { + .name ="axs10x-i2s-pll-clock" , + .of_match_table = i2s_pll_clk_id, + }, + .probe = i2s_pll_clk_probe, + .remove = i2s_pll_clk_remove, +}; +module_platform_driver (i2s_pll_clk_driver); + +MODULE_AUTHOR ("Jose Abreu <[email protected]>" ); +MODULE_DESCRIPTION ("Synopsys AXS10X SDP I2S PLL Clock Driver" ); +MODULE_LICENSE ("GPL v2" );
Re: [PATCH 1/2 v6] clk/axs10x: Add I2S PLL clock driver
Hi,
@Stephen: Is this version ok? The DT bindings were already acked by Vineet and Alexey.
@Rob: Is this version ok? You already acked the previous version[1], see the version log for differences. Please see also if [2] is ok.
[1] https://marc.info/?l=devicetree&m=146056894500509&w=2
[2] https://marc.info/?l=devicetree&m=146126139521541&w=2
Quoted 326 lines · Jose Abreu
Adding device tree mailing list and Rob Herring.
Quoted 323 lines · Jose Abreu
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 <[email protected]>---
Changes v5 -> v6:
* Use parent clock to determine PLL input rate instead of using hardcoded values
* Documentation update (added 'clocks' field)Changes v4 -> v5:
* Documentation update (as suggested by Alexey Brodkin)
* Changed compatible string to "snps,axs10x-i2s-pll-clock" (as suggested by Alexey Brodkin)Changes v3 -> v4:
* Added binding document (as suggested by Stephen Boyd)
* Minor code style fixes (as suggested by Stephen Boyd)
* Use ioremap (as suggested by Stephen Boyd)
* Implementround_rate(as suggested by Stephen Boyd)
* Change to platform driver (as suggested by Stephen Boyd)
* Use {readl/writel}_relaxed (as suggested by Vineet Gupta)Changes v2 -> v3:
* Implementedrecalc_rateChanges v1 -> v2:
* Renamed folder to axs10x (as suggested by Alexey Brodkin)
* Added more supported rates.../bindings/clock/axs10x-i2s-pll-clock.txt | 25 +++ drivers/clk/Makefile | 1 + drivers/clk/axs10x/Makefile | 1 + drivers/clk/axs10x/i2s_pll_clock.c | 228 +++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt create mode 100644 drivers/clk/axs10x/Makefile create mode 100644 drivers/clk/axs10x/i2s_pll_clock.cDocumentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt new file +25
-0@@ -0,0 +1,25 @@ +Binding for the AXS10X I2S PLL clock + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible: shall be "snps,axs10x-i2s-pll-clock" +- reg : address and length of the I2S PLL register set. +- clocks: shall be the input parent clock phandle for the PLL. +- #clock-cells: from common clock binding; Should always be set to 0. + +Example: + pll_clock: pll_clock { + compatible = "fixed-clock"; + clock-frequency = <27000000>; + #clock-cells = <0>; + }; + + i2s_clock@100a0 { + compatible = "snps,axs10x-i2s-pll-clock"; + reg = <0x100a0 0x10>; + clocks = <&pll_clock>; + #clock-cells = <0>; + };drivers/clk/Makefile +1
-0@@ -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_PLAT_AXS10X) += axs10x/drivers/clk/axs10x/Makefile new file +1
-0@@ -0,0 +1 @@ +obj-y += i2s_pll_clock.odrivers/clk/axs10x/i2s_pll_clock.c new file +224
-0@@ -0,0 +1,228 @@ +/* +* Synopsys AXS10X SDP I2S PLL clock driver +* +* 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/platform_device.h> +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/device.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/of.h> + +/* PLL registers addresses */ +#define PLL_IDIV_REG 0x0 +#define PLL_FBDIV_REG 0x4 +#define PLL_ODIV0_REG 0x8 +#define PLL_ODIV1_REG 0xC + +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 }, + {2116800 ,0x82 ,0x3CF ,0x10C30 ,0x2000 }, + {2304000 ,0x104 ,0x79E ,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 }, + {2116800 ,0x514 ,0x42 ,0x10001 ,0x2000 }, + {2304000 ,0x619 ,0x82 ,0x10001 ,0x2000 }, + {0 ,0 ,0 ,0 ,0 }, +}; + +struct i2s_pll_clk { +void __iomem *base; +struct clk_hw hw; +struct device *dev; +}; + +static inline void i2s_pll_write (struct i2s_pll_clk *clk,unsigned int reg, +unsigned int val) +{ +writel_relaxed (val, clk->base + reg); +} + +static inline unsigned int i2s_pll_read (struct i2s_pll_clk *clk, +unsigned int reg) +{ +return readl_relaxed (clk->base + reg); +} + +static inline struct i2s_pll_clk *to_i2s_pll_clk (struct clk_hw *hw) +{ + return container_of(hw, struct i2s_pll_clk, hw); +} + +static inline unsigned int i2s_pll_get_value (unsigned int val) +{ +return (val &0x3F ) + ((val >>6 ) &0x3F ); +} + +static const struct i2s_pll_cfg *i2s_pll_get_cfg (unsigned long prate) +{ +switch (prate) { +case 27000000 : +return i2s_pll_cfg_27m; +case 28224000 : +return i2s_pll_cfg_28m; +default : +return NULL ; + } +} + +static unsigned long i2s_pll_recalc_rate (struct clk_hw *hw, +unsigned long parent_rate) +{ +struct i2s_pll_clk *clk =to_i2s_pll_clk (hw); +unsigned int idiv, fbdiv, odiv; + + idiv =i2s_pll_get_value (i2s_pll_read (clk,PLL_IDIV_REG )); + fbdiv =i2s_pll_get_value (i2s_pll_read (clk,PLL_FBDIV_REG )); + odiv =i2s_pll_get_value (i2s_pll_read (clk,PLL_ODIV0_REG )); + +return ((parent_rate / idiv) * fbdiv) / odiv; +} + +static long i2s_pll_round_rate (struct clk_hw *hw,unsigned long rate, +unsigned long *prate) +{ +struct i2s_pll_clk *clk =to_i2s_pll_clk (hw); +const struct i2s_pll_cfg *pll_cfg =i2s_pll_get_cfg (*prate); +int i; + +if (!pll_cfg) { +dev_err (clk->dev,"invalid parent rate=%ld\n" , *prate); +return -EINVAL ; + } + +for (i =0 ; pll_cfg[i].rate !=0 ; i++) +if (pll_cfg[i].rate == rate) +return rate; + +return -EINVAL ; +} + +static int i2s_pll_set_rate (struct clk_hw *hw,unsigned long rate, +unsigned long parent_rate) +{ +struct i2s_pll_clk *clk =to_i2s_pll_clk (hw); +const struct i2s_pll_cfg *pll_cfg =i2s_pll_get_cfg (parent_rate); +int i; + +if (!pll_cfg) { +dev_err (clk->dev,"invalid parent rate=%ld\n" , parent_rate); +return -EINVAL ; + } + +for (i =0 ; pll_cfg[i].rate !=0 ; i++) { +if (pll_cfg[i].rate == rate) { +i2s_pll_write (clk,PLL_IDIV_REG , pll_cfg[i].idiv); +i2s_pll_write (clk,PLL_FBDIV_REG , pll_cfg[i].fbdiv); +i2s_pll_write (clk,PLL_ODIV0_REG , pll_cfg[i].odiv0); +i2s_pll_write (clk,PLL_ODIV1_REG , pll_cfg[i].odiv1); +return 0 ; + } + } + +dev_err (clk->dev,"invalid rate=%ld, parent_rate=%ld\n" , rate, + parent_rate); +return -EINVAL ; +} + +static const struct clk_ops i2s_pll_ops = { + .recalc_rate = i2s_pll_recalc_rate, + .round_rate = i2s_pll_round_rate, + .set_rate = i2s_pll_set_rate, +}; + +static int i2s_pll_clk_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct device_node *node = dev->of_node; +const char *clk_name; +const char *parent_name; +struct clk *clk; +struct i2s_pll_clk *pll_clk; +struct clk_init_data init; +struct resource *mem; + + pll_clk =devm_kzalloc (dev,sizeof (*pll_clk),GFP_KERNEL ); +if (!pll_clk) +return -ENOMEM ; + + mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + pll_clk->base =devm_ioremap_resource (dev, mem); +if (IS_ERR (pll_clk->base)) +return PTR_ERR (pll_clk->base); + + clk_name = node->name; + init.name = clk_name; + init.ops = &i2s_pll_ops; + parent_name =of_clk_get_parent_name (node,0 ); + init.parent_names = &parent_name; + init.num_parents =1 ; + pll_clk->hw.init = &init; + pll_clk->dev = dev; + + clk =devm_clk_register (dev, &pll_clk->hw); +if (IS_ERR (clk)) { +dev_err (dev,"failed to register %s clock (%ld)\n" , + clk_name,PTR_ERR (clk)); +return PTR_ERR (clk); + } + +return of_clk_add_provider (node, of_clk_src_simple_get, clk); +} + +static int i2s_pll_clk_remove (struct platform_device *pdev) +{ +of_clk_del_provider (pdev->dev.of_node); +return 0 ; +} + +static const struct of_device_id i2s_pll_clk_id[] = { + { .compatible ="snps,axs10x-i2s-pll-clock" , }, + { }, +}; +MODULE_DEVICE_TABLE (of, i2s_pll_clk_id); + +static struct platform_driver i2s_pll_clk_driver = { + .driver = { + .name ="axs10x-i2s-pll-clock" , + .of_match_table = i2s_pll_clk_id, + }, + .probe = i2s_pll_clk_probe, + .remove = i2s_pll_clk_remove, +}; +module_platform_driver (i2s_pll_clk_driver);
Quoted 8 lines
drivers/clk/axs10x/i2s_pll_clock.c line 228
Quoted 4 lines
drivers/clk/axs10x/i2s_pll_clock.c new file +4
-0+ +MODULE_AUTHOR ("Jose Abreu <[email protected]>" ); +MODULE_DESCRIPTION ("Synopsys AXS10X SDP I2S PLL Clock Driver" ); +MODULE_LICENSE ("GPL v2" );--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Best regards,
Jose Miguel Abreu
Re: [RESEND PATCH 1/2 v6] clk/axs10x: Add I2S PLL clock driver
In reply to Jose AbreuQuoted 52 lines · Jose Abreu
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 <[email protected]>---
Changes v5 -> v6:
* Use parent clock to determine PLL input rate instead of using hardcoded values
* Documentation update (added 'clocks' field)Changes v4 -> v5:
* Documentation update (as suggested by Alexey Brodkin)
* Changed compatible string to "snps,axs10x-i2s-pll-clock" (as suggested by Alexey Brodkin)Changes v3 -> v4:
* Added binding document (as suggested by Stephen Boyd)
* Minor code style fixes (as suggested by Stephen Boyd)
* Use ioremap (as suggested by Stephen Boyd)
* Implementround_rate(as suggested by Stephen Boyd)
* Change to platform driver (as suggested by Stephen Boyd)
* Use {readl/writel}_relaxed (as suggested by Vineet Gupta)Changes v2 -> v3:
* Implementedrecalc_rateChanges v1 -> v2:
* Renamed folder to axs10x (as suggested by Alexey Brodkin)
* Added more supported ratesCc Carlos Palminha <[email protected]>Cc Rob Herring <[email protected]>Cc Pawel Moll <[email protected]>Cc Mark Rutland <[email protected]>Cc Ian Campbell <[email protected]>Cc Kumar Gala <[email protected]>Cc Michael Turquette <[email protected]>Cc Stephen Boyd <[email protected]>Cc Alexey Brodkin <[email protected]>Cc Vineet Gupta <[email protected]>
Quoted 1 line
.../bindings/clock/axs10x-i2s-pll-clock.txt | 25 +++
Quoted 7 lines
drivers/clk/Makefile | 1 + drivers/clk/axs10x/Makefile | 1 + drivers/clk/axs10x/i2s_pll_clock.c | 228 +++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt create mode 100644 drivers/clk/axs10x/Makefile create mode 100644 drivers/clk/axs10x/i2s_pll_clock.c
Stephen Boyd
AppliedRe: [RESEND PATCH 1/2 v6] clk/axs10x: Add I2S PLL clock driver
In reply to Jose AbreuQuoted 6 lines · Jose Abreu
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.
Quoted 7 lines
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 <[email protected]>---
Applied to clk-next
I'm not applying the arc dts file (patch #2 in this series).
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v6 2/2 arc: axs10x: Add DT bindings for I2S PLL Clock
In reply to Jose AbreuAdd device tree bindings for AXS10X I2S PLL Clock driver.
---
Changes v5 -> v6:
* Added 'clocks' field
This patch was only introduced in v5.
arch/arc/boot/dts/axs10x_mb.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+)
arch/arc/boot/dts/axs10x_mb.dtsi +13 -0
@@ -16,7 +16,20 @@ ranges = <0x00000000 0xe0000000 0x10000000>; interrupt-parent = <&mb_intc>; + i2sclk: i2sclk at 100a0 { + compatible = "snps,axs10x-i2s-pll-clock"; + reg = <0x100a0 0x10>; + clocks = <&i2spll_clk>; + #clock-cells = <0>; + }; + clocks { + i2spll_clk: i2spll_clk { + compatible = "fixed-clock"; + clock-frequency = <27000000>; + #clock-cells = <0>; + }; + i2cclk: i2cclk { compatible = "fixed-clock"; clock-frequency = <50000000>;
Signature · 1 line
1.9.1
Re: [PATCH 2/2 v6] arc: axs10x: Add DT bindings for I2S PLL Clock
Adding device tree mailing list and Rob Herring.
Quoted 38 lines · Jose Abreu
Add device tree bindings for AXS10X I2S PLL Clock driver.
Signed-off-by Jose Abreu <[email protected]>---
Changes v5 -> v6:
* Added 'clocks' fieldThis patch was only introduced in v5.
arch/arc/boot/dts/axs10x_mb.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+)arch/arc/boot/dts/axs10x_mb.dtsi +13
-0@@ -16,7 +16,20 @@ ranges = <0x00000000 0xe0000000 0x10000000>; interrupt-parent = <&mb_intc>; + i2sclk: i2sclk@100a0 { + compatible = "snps,axs10x-i2s-pll-clock"; + reg = <0x100a0 0x10>; + clocks = <&i2spll_clk>; + #clock-cells = <0>; + }; + clocks { + i2spll_clk: i2spll_clk { + compatible = "fixed-clock"; + clock-frequency = <27000000>; + #clock-cells = <0>; + }; + i2cclk: i2cclk { compatible = "fixed-clock"; clock-frequency = <50000000>;
Re: [PATCH 2/2 v6] arc: axs10x: Add DT bindings for I2S PLL Clock
In reply to Jose AbreuHi Jose,
Quoted 11 lines · Jose Abreu
Add device tree bindings for AXS10X I2S PLL Clock driver. =20
Signed-off-by Jose Abreu <[email protected]>---
=20
Changes v5 -> v6:
* Added 'clocks' field
=20
This patch was only introduced in v5.
=20
arch/arc/boot/dts/axs10x_mb.dtsi | 13 +-+-+-+-+-+-+-+-+-=
+-+-+-+-
arch/arc/boot/dts=
Quoted 3 lines
1 file changed, 13 insertions(+-)=20
arch/arc/boot/dts= renamed from arch/arc/boot/dts/axs10x_mb.dtsi +0
-0
/axs10x_mb.dtsi
Quoted 21 lines
index ab5d570..5c6489e 100644
---a/arch/arc/boot/dts/axs10x_mb.dtsi
+-+-+-b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -16,7 +-16,20 @@
ranges = <0x000000000xe00000000x10000000>; interrupt-parent = <&mb_intc>;+- i2sclk: i2sclk@100a0 { +- compatible = "snps,axs10x-i2s-pll-clock"; +- reg = <0x100a0 0x10>; +- clocks = <&i2spll_clk>; +- #clock-cells = <0>; +- }; +- clocks { +- i2spll_clk: i2spll_clk { +- compatible = "fixed-clock"; +- clock-frequency = <27000000>; +- #clock-cells = <0>; +- }; +-
Quoted 3 lines
i2cclk: i2cclk {
compatible = "fixed-clock"; clock-frequency = <50000000>;
Re: [PATCH 2/2 v6] arc: axs10x: Add DT bindings for I2S PLL Clock
In reply to Jose AbreuOn Thursday 21 April 2016 10:49 PM, Jose Abreu wrote:=0A=
Quoted 3 lines
Add device tree bindings for AXS10X I2S PLL Clock driver.=0A= =0A=
Signed-off-by Jose Abreu <[email protected]>=0A=
=0A=
Lets worry about different firmware versions et all after basic patch is me= rged.=0A=
I presume this patch will be merged via clk tree ?=0A=
=0A=
=0A=
Re: [RESEND PATCH 2/2 v6] arc: axs10x: Add DT bindings for I2S PLL Clock
In reply to Jose AbreuHi Vineet,
Quoted 45 lines · Jose Abreu
Add device tree bindings for AXS10X I2S PLL Clock driver.
Signed-off-by Jose Abreu <[email protected]>Acked-by Alexey Brodkin <[email protected]>Acked-by Vineet Gupta <[email protected]>---
Changes v5 -> v6:
* Added 'clocks' fieldThis patch was only introduced in v5.
Cc Carlos Palminha <[email protected]>Cc Rob Herring <[email protected]>Cc Pawel Moll <[email protected]>Cc Mark Rutland <[email protected]>Cc Ian Campbell <[email protected]>Cc Kumar Gala <[email protected]>Cc Michael Turquette <[email protected]>Cc Stephen Boyd <[email protected]>Cc Alexey Brodkin <[email protected]>Cc Vineet Gupta <[email protected]>arch/arc/boot/dts/axs10x_mb.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+)arch/arc/boot/dts/axs10x_mb.dtsi +7
-0@@ -16,7 +16,20 @@ ranges = <0x00000000 0xe0000000 0x10000000>; interrupt-parent = <&mb_intc>; + i2sclk: i2sclk@100a0 { + compatible = "snps,axs10x-i2s-pll-clock"; + reg = <0x100a0 0x10>; + clocks = <&i2spll_clk>; + #clock-cells = <0>; + }; +
arch/arc/boot/dts/axs10x_mb.dtsi line 35
Quoted 10 lines
arch/arc/boot/dts/axs10x_mb.dtsi +6
-0clocks { + i2spll_clk: i2spll_clk { + compatible = "fixed-clock"; + clock-frequency = <27000000>; + #clock-cells = <0>; + }; + i2cclk: i2cclk { compatible = "fixed-clock"; clock-frequency = <50000000>;
Can you apply this to arc-next? Main driver was already merged into clk-next. We still have to check how to deal with the parent clock frequency that will change in the next firmware release.
Best regards,
Jose Miguel Abreu
Re: [RESEND PATCH 2/2 v6] arc: axs10x: Add DT bindings for I2S PLL Clock
Quoted 3 lines · Jose Abreu
Can you apply this to arc-next? Main driver was already merged into clk-next. We still have to check how to deal with the parent clock frequency that will change in the next firmware release.
Done ! although note that this might *not* be bisectable if this goes ahead of driver in 4.7-rc1 !
A message that is not in the archive (sent off-list or not yet received): cover.1461258787.git.joabreu-HKixBCOQz3hWk0Htik3J/[email protected]
PATCH RESEND v6 1/2 clk/axs10x: Add I2S PLL clock driver
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.
---
Changes v5 -> v6:
* Use parent clock to determine PLL input rate instead of using hardcoded values
* Documentation update (added 'clocks' field)
Changes v4 -> v5:
* Documentation update (as suggested by Alexey Brodkin)
* Changed compatible string to "snps,axs10x-i2s-pll-clock" (as suggested by Alexey Brodkin)
Changes v3 -> v4:
* Added binding document (as suggested by Stephen Boyd)
* Minor code style fixes (as suggested by Stephen Boyd)
* Use ioremap (as suggested by Stephen Boyd)
* Implement round_rate (as suggested by Stephen Boyd)
* Change to platform driver (as suggested by Stephen Boyd)
* Use {readl/writel}_relaxed (as suggested by Vineet Gupta)
Changes v2 -> v3:
* Implemented recalc_rate
Changes v1 -> v2:
* Renamed folder to axs10x (as suggested by Alexey Brodkin)
* Added more supported rates
.../bindings/clock/axs10x-i2s-pll-clock.txt | 25 +++ drivers/clk/Makefile | 1 + drivers/clk/axs10x/Makefile | 1 + drivers/clk/axs10x/i2s_pll_clock.c | 228 +++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt create mode 100644 drivers/clk/axs10x/Makefile create mode 100644 drivers/clk/axs10x/i2s_pll_clock.c
Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt new file +25 -0
@@ -0,0 +1,25 @@ +Binding for the AXS10X I2S PLL clock + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible: shall be "snps,axs10x-i2s-pll-clock" +- reg : address and length of the I2S PLL register set. +- clocks: shall be the input parent clock phandle for the PLL. +- #clock-cells: from common clock binding; Should always be set to 0. + +Example: + pll_clock: pll_clock { + compatible = "fixed-clock"; + clock-frequency = <27000000>; + #clock-cells = <0>; + }; + + i2s_clock@100a0 { + compatible = "snps,axs10x-i2s-pll-clock"; + reg = <0x100a0 0x10>; + clocks = <&pll_clock>; + #clock-cells = <0>; + };
drivers/clk/Makefile +1 -0
@@ -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_PLAT_AXS10X) += axs10x/
drivers/clk/axs10x/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-y += i2s_pll_clock.o
drivers/clk/axs10x/i2s_pll_clock.c new file +228 -0
228 lines not on this page · raw message
Signature · 7 lines
1.9.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH RESEND v6 2/2 arc: axs10x: Add DT bindings for I2S PLL Clock
In reply to a message not in the archiveAdd device tree bindings for AXS10X I2S PLL Clock driver.
---
Changes v5 -> v6:
* Added 'clocks' field
This patch was only introduced in v5.
arch/arc/boot/dts/axs10x_mb.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+)
arch/arc/boot/dts/axs10x_mb.dtsi +13 -0
@@ -16,7 +16,20 @@ ranges = <0x00000000 0xe0000000 0x10000000>; interrupt-parent = <&mb_intc>; + i2sclk: i2sclk@100a0 { + compatible = "snps,axs10x-i2s-pll-clock"; + reg = <0x100a0 0x10>; + clocks = <&i2spll_clk>; + #clock-cells = <0>; + }; + clocks { + i2spll_clk: i2spll_clk { + compatible = "fixed-clock"; + clock-frequency = <27000000>; + #clock-cells = <0>; + }; + i2cclk: i2cclk { compatible = "fixed-clock"; clock-frequency = <50000000>;
Signature · 7 lines
1.9.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html