[RFC PATCH 2/2] clk: add accuracy support for fixed clock
This patch adds support for accuracy retrieval on fixed clocks. It also adds a new dt property called 'clock-accuracy' to define the clock accuracy. This can be usefull for oscillator (RC, crystal, ...) definitions which are always given an accuracy characteristic. --- .../devicetree/bindings/clock/fixed-clock.txt |3 ++ drivers/clk/clk-fixed-rate.c | 41 +--- include/linux/clk-provider.h |3 ++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/fixed-clock.txt b/Documentation/devicetree/bindings/clock/fixed-clock.txt index 0b1fe78..48ea0ad 100644 --- a/Documentation/devicetree/bindings/clock/fixed-clock.txt +++ b/Documentation/devicetree/bindings/clock/fixed-clock.txt @@ -10,6 +10,8 @@ Required properties: - clock-frequency : frequency of clock in Hz. Should be a single cell. Optional properties: +- clock-accuracy : accuracy of clock in ppb (parts per billion). + Should be a single cell. - gpios : From common gpio binding; gpio connection to clock enable pin. - clock-output-names : From common clock binding. @@ -18,4 +20,5 @@ Example: compatible = fixed-clock; #clock-cells = 0; clock-frequency = 10; + clock-accuracy = 100; }; diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index dc58fbd..f716bf3 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -34,22 +34,31 @@ static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, return to_clk_fixed_rate(hw)-fixed_rate; } +static unsigned long clk_fixed_rate_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_accuracy) +{ + return to_clk_fixed_rate(hw)-fixed_accuracy; +} + const struct clk_ops clk_fixed_rate_ops = { .recalc_rate = clk_fixed_rate_recalc_rate, + .recalc_accuracy = clk_fixed_rate_recalc_accuracy, }; EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); /** - * clk_register_fixed_rate - register fixed-rate clock with the clock framework + * clk_register_fixed_rate_with_accuracy - register fixed-rate clock with the + *clock framework * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of clock's parent * @flags: framework-specific flags * @fixed_rate: non-adjustable clock rate + * @fixed_accuracy: non-adjustable clock rate */ -struct clk *clk_register_fixed_rate(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, - unsigned long fixed_rate) +struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + unsigned long fixed_rate, unsigned long fixed_accuracy) { struct clk_fixed_rate *fixed; struct clk *clk; @@ -70,6 +79,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, /* struct clk_fixed_rate assignments */ fixed-fixed_rate = fixed_rate; + fixed-fixed_accuracy = fixed_accuracy; fixed-hw.init = init; /* register the clock */ @@ -81,6 +91,22 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, return clk; } +/** + * clk_register_fixed_rate - register fixed-rate clock with the clock framework + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_name: name of clock's parent + * @flags: framework-specific flags + * @fixed_rate: non-adjustable clock rate + */ +struct clk *clk_register_fixed_rate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + unsigned long fixed_rate) +{ + return clk_register_fixed_rate_with_accuracy(dev, name, parent_name, +flags, fixed_rate, 0); +} + #ifdef CONFIG_OF /** * of_fixed_clk_setup() - Setup function for simple fixed rate clock @@ -90,13 +116,18 @@ void of_fixed_clk_setup(struct device_node *node) struct clk *clk; const char *clk_name = node-name; u32 rate; + u32 accuracy = 0; if (of_property_read_u32(node, clock-frequency, rate)) return; + of_property_read_u32(node, clock-accuracy, accuracy); + of_property_read_string(node, clock-output-names, clk_name); - clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate); + clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL, + CLK_IS_ROOT, rate, + accuracy); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); } diff --git a/include/linux/clk-provider.h
[RFC PATCH 2/2] clk: add accuracy support for fixed clock
This patch adds support for accuracy retrieval on fixed clocks. It also adds a new dt property called 'clock-accuracy' to define the clock accuracy. This can be usefull for oscillator (RC, crystal, ...) definitions which are always given an accuracy characteristic. --- .../devicetree/bindings/clock/fixed-clock.txt |3 ++ drivers/clk/clk-fixed-rate.c | 41 +--- include/linux/clk-provider.h |3 ++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/fixed-clock.txt b/Documentation/devicetree/bindings/clock/fixed-clock.txt index 0b1fe78..48ea0ad 100644 --- a/Documentation/devicetree/bindings/clock/fixed-clock.txt +++ b/Documentation/devicetree/bindings/clock/fixed-clock.txt @@ -10,6 +10,8 @@ Required properties: - clock-frequency : frequency of clock in Hz. Should be a single cell. Optional properties: +- clock-accuracy : accuracy of clock in ppb (parts per billion). + Should be a single cell. - gpios : From common gpio binding; gpio connection to clock enable pin. - clock-output-names : From common clock binding. @@ -18,4 +20,5 @@ Example: compatible = fixed-clock; #clock-cells = 0; clock-frequency = 10; + clock-accuracy = 100; }; diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index dc58fbd..f716bf3 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -34,22 +34,31 @@ static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, return to_clk_fixed_rate(hw)-fixed_rate; } +static unsigned long clk_fixed_rate_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_accuracy) +{ + return to_clk_fixed_rate(hw)-fixed_accuracy; +} + const struct clk_ops clk_fixed_rate_ops = { .recalc_rate = clk_fixed_rate_recalc_rate, + .recalc_accuracy = clk_fixed_rate_recalc_accuracy, }; EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); /** - * clk_register_fixed_rate - register fixed-rate clock with the clock framework + * clk_register_fixed_rate_with_accuracy - register fixed-rate clock with the + *clock framework * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of clock's parent * @flags: framework-specific flags * @fixed_rate: non-adjustable clock rate + * @fixed_accuracy: non-adjustable clock rate */ -struct clk *clk_register_fixed_rate(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, - unsigned long fixed_rate) +struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + unsigned long fixed_rate, unsigned long fixed_accuracy) { struct clk_fixed_rate *fixed; struct clk *clk; @@ -70,6 +79,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, /* struct clk_fixed_rate assignments */ fixed-fixed_rate = fixed_rate; + fixed-fixed_accuracy = fixed_accuracy; fixed-hw.init = init; /* register the clock */ @@ -81,6 +91,22 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, return clk; } +/** + * clk_register_fixed_rate - register fixed-rate clock with the clock framework + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_name: name of clock's parent + * @flags: framework-specific flags + * @fixed_rate: non-adjustable clock rate + */ +struct clk *clk_register_fixed_rate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + unsigned long fixed_rate) +{ + return clk_register_fixed_rate_with_accuracy(dev, name, parent_name, +flags, fixed_rate, 0); +} + #ifdef CONFIG_OF /** * of_fixed_clk_setup() - Setup function for simple fixed rate clock @@ -90,13 +116,18 @@ void of_fixed_clk_setup(struct device_node *node) struct clk *clk; const char *clk_name = node-name; u32 rate; + u32 accuracy = 0; if (of_property_read_u32(node, clock-frequency, rate)) return; + of_property_read_u32(node, clock-accuracy, accuracy); + of_property_read_string(node, clock-output-names, clk_name); - clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate); + clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL, + CLK_IS_ROOT, rate, + accuracy); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); } diff --git a/include/linux/clk-provider.h
[RFC PATCH 1/2] clk: add clk accuracy retrieval support
The clock accuracy is expressed in ppb (parts per billion) and represents the possible clock drift. Say you have a clock (e.g. an oscillator) which provides a fixed clock of 20MHz with an accuracy of +- 20Hz. This accuracy expressed in ppb is 20Hz/20MHz = 1000 ppb (or 1 ppm). Clock users may need the clock accuracy information in order to choose the best clock (the one with the best accuracy) across several available clocks. This patch adds clk accuracy retrieval support for common clk framework by means of a new function called clk_get_accuracy. This function returns the given clock accuracy expressed in ppb. In order to get the clock accuracy, this implementation adds one callback called recalc_accuracy to the clk_ops structure. This callback is given the parent clock accuracy (if the clock is not a root clock) and should recalculate the given clock accuracy. This callback is optional and may be implemented if the clock is not a perfect clock (accuracy != 0 ppb). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- Documentation/clk.txt|4 ++ drivers/clk/Kconfig |4 ++ drivers/clk/clk.c| 91 -- include/linux/clk-private.h |1 + include/linux/clk-provider.h | 11 + include/linux/clk.h | 17 6 files changed, 124 insertions(+), 4 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 6f68ba0..869a4a3 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long); + unsigned long (*recalc_accuracy)(struct clk_hw *hw, + unsigned long parent_accuracy); void(*init)(struct clk_hw *hw); }; @@ -197,6 +199,8 @@ optional or must be evaluated on a case-by-case basis. .set_parent | | | n | y | n| .get_parent | | | n | y | n| | | | | | | +.recalc_rate | | | | | | + | | | | | | .init| | | | | | --- diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 51380d6..205a19b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -6,12 +6,16 @@ config CLKDEV_LOOKUP config HAVE_CLK_PREPARE bool +config HAVE_CLK_GET_ACCURACY + bool + config HAVE_MACH_CLKDEV bool config COMMON_CLK bool select HAVE_CLK_PREPARE + select HAVE_CLK_GET_ACCURACY select CLKDEV_LOOKUP ---help--- The common clock framework is a single definition of struct diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 54a191c..f8e68ca 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -104,10 +104,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) if (!c) return; - seq_printf(s, %*s%-*s %-11d %-12d %-10lu, + seq_printf(s, %*s%-*s %-11d %-12d %-10lu %-11lu, level * 3 + 1, , 30 - level * 3, c-name, - c-enable_count, c-prepare_count, clk_get_rate(c)); + c-enable_count, c-prepare_count, clk_get_rate(c), + clk_get_accuracy(c)); seq_printf(s, \n); } @@ -129,8 +130,8 @@ static int clk_summary_show(struct seq_file *s, void *data) { struct clk *c; - seq_printf(s,clockenable_cnt prepare_cnt rate\n); - seq_printf(s, -\n); + seq_printf(s,clockenable_cnt prepare_cnt rateaccuracy\n); + seq_printf(s, -\n); clk_prepare_lock(); @@ -167,6 +168,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level) seq_printf(s, \enable_count\: %d,, c-enable_count); seq_printf(s, \prepare_count\: %d,, c-prepare_count); seq_printf(s, \rate\: %lu, clk_get_rate(c)); + seq_printf(s, \accuracy\: %lu, clk_get_accuracy(c)); } static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) @@ -248,6 +250,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) if (!d) goto err_out; + d = debugfs_create_u32(clk_accuracy, S_IRUGO, clk-dentry
Re: [RFC PATCH 1/2] clk: add clk accuracy retrieval support
Sorry for the noise, I forgot to add --in-reply-to option. On 01/08/2013 17:02, Boris BREZILLON wrote: The clock accuracy is expressed in ppb (parts per billion) and represents the possible clock drift. Say you have a clock (e.g. an oscillator) which provides a fixed clock of 20MHz with an accuracy of +- 20Hz. This accuracy expressed in ppb is 20Hz/20MHz = 1000 ppb (or 1 ppm). Clock users may need the clock accuracy information in order to choose the best clock (the one with the best accuracy) across several available clocks. This patch adds clk accuracy retrieval support for common clk framework by means of a new function called clk_get_accuracy. This function returns the given clock accuracy expressed in ppb. In order to get the clock accuracy, this implementation adds one callback called recalc_accuracy to the clk_ops structure. This callback is given the parent clock accuracy (if the clock is not a root clock) and should recalculate the given clock accuracy. This callback is optional and may be implemented if the clock is not a perfect clock (accuracy != 0 ppb). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- Documentation/clk.txt|4 ++ drivers/clk/Kconfig |4 ++ drivers/clk/clk.c| 91 -- include/linux/clk-private.h |1 + include/linux/clk-provider.h | 11 + include/linux/clk.h | 17 6 files changed, 124 insertions(+), 4 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 6f68ba0..869a4a3 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long); + unsigned long (*recalc_accuracy)(struct clk_hw *hw, + unsigned long parent_accuracy); void(*init)(struct clk_hw *hw); }; @@ -197,6 +199,8 @@ optional or must be evaluated on a case-by-case basis. .set_parent | | | n | y | n| .get_parent | | | n | y | n| | | | | | | +.recalc_rate | | | | | | + | | | | | | .init| | | | | | --- diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 51380d6..205a19b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -6,12 +6,16 @@ config CLKDEV_LOOKUP config HAVE_CLK_PREPARE bool +config HAVE_CLK_GET_ACCURACY + bool + config HAVE_MACH_CLKDEV bool config COMMON_CLK bool select HAVE_CLK_PREPARE + select HAVE_CLK_GET_ACCURACY select CLKDEV_LOOKUP ---help--- The common clock framework is a single definition of struct diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 54a191c..f8e68ca 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -104,10 +104,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) if (!c) return; - seq_printf(s, %*s%-*s %-11d %-12d %-10lu, + seq_printf(s, %*s%-*s %-11d %-12d %-10lu %-11lu, level * 3 + 1, , 30 - level * 3, c-name, - c-enable_count, c-prepare_count, clk_get_rate(c)); + c-enable_count, c-prepare_count, clk_get_rate(c), + clk_get_accuracy(c)); seq_printf(s, \n); } @@ -129,8 +130,8 @@ static int clk_summary_show(struct seq_file *s, void *data) { struct clk *c; - seq_printf(s,clockenable_cnt prepare_cnt rate\n); - seq_printf(s, -\n); + seq_printf(s,clockenable_cnt prepare_cnt rate accuracy\n); + seq_printf(s, -\n); clk_prepare_lock(); @@ -167,6 +168,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level) seq_printf(s, \enable_count\: %d,, c-enable_count); seq_printf(s, \prepare_count\: %d,, c-prepare_count); seq_printf(s, \rate\: %lu, clk_get_rate(c)); + seq_printf(s, \accuracy\: %lu, clk_get_accuracy(c)); } static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) @@ -248,6 +250,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) if (!d
Re: [PATCH] USB: ohci-at91: add usb_clk for transition to common clk framework
On 01/08/2013 16:39, Alan Stern wrote: On Thu, 1 Aug 2013, Boris BREZILLON wrote: The AT91 PMC (Power Management Controller) provides an USB clock used by USB Full Speed host (ohci) and USB Full Speed device (udc). The usb drivers (ohci and udc) must configure this clock to 48Mhz. This configuration was formely done in mach-at91/clock.c, but this implementation will be removed when moving to common clk framework. This patch adds support for usb clock retrieval and configuration, and is backward compatible with the current at91 clk implementation (if usb clk is not found, it does not configure/enable it). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com @@ -163,6 +169,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, goto err5; } + uclk = clk_get(pdev-dev, usb_clk); What happens if uclk isn't found but it is needed? It will not fail but I guess the usb host won't work as the clock won't be correctly configured. I agree with you: this is not a good solution. Another option is to keep the previous version of this patch and put uclk handling in #ifdef CONFIG_COMMON_CLK #endif sections. Would this be acceptable ? Alan Stern -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] usb: gadget: at91_udc: add usb_clk for transition to common clk framework
The AT91 PMC (Power Management Controller) provides an USB clock used by USB Full Speed host (ohci) and USB Full Speed device (udc). The usb drivers (ohci and udc) must configure this clock to 48Mhz. This configuration was formely done in mach-at91/clock.c, but this implementation will be removed when moving to common clk framework. This patch adds support for usb clock retrieval and configuration, and is backward compatible with the current at91 clk implementation (if usb clk is not found, it does not configure/enable it). Changes since v1: - use IS_ENABLED(CONFIG_COMMON_CLK) to isolate new at91 clk support Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/usb/gadget/at91_udc.c | 21 +++-- drivers/usb/gadget/at91_udc.h |2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index fce8e4e..5c7c8bb 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -870,6 +870,11 @@ static void clk_on(struct at91_udc *udc) if (udc-clocked) return; udc-clocked = 1; + + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + clk_set_rate(udc-uclk, 4800); + clk_prepare_enable(udc-uclk); + } clk_prepare_enable(udc-iclk); clk_prepare_enable(udc-fclk); } @@ -882,6 +887,8 @@ static void clk_off(struct at91_udc *udc) udc-gadget.speed = USB_SPEED_UNKNOWN; clk_disable_unprepare(udc-fclk); clk_disable_unprepare(udc-iclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_disable_unprepare(udc-uclk); } /* @@ -1774,10 +1781,12 @@ static int at91udc_probe(struct platform_device *pdev) /* get interface and function clocks */ udc-iclk = clk_get(dev, udc_clk); udc-fclk = clk_get(dev, udpck); - if (IS_ERR(udc-iclk) || IS_ERR(udc-fclk)) { + if (IS_ENABLED(CONFIG_COMMON_CLK)) + udc-uclk = clk_get(dev, usb_clk); + if (IS_ERR(udc-iclk) || IS_ERR(udc-fclk) || + (IS_ENABLED(CONFIG_COMMON_CLK) IS_ERR(udc-uclk))) { DBG(clocks missing\n); retval = -ENODEV; - /* NOTE: we know here that refcounts on these are NOPs */ goto fail1; } @@ -1851,6 +1860,12 @@ fail3: fail2: free_irq(udc-udp_irq, udc); fail1: + if (IS_ENABLED(CONFIG_COMMON_CLK) !IS_ERR(udc-uclk)) + clk_put(udc-uclk); + if (!IS_ERR(udc-fclk)) + clk_put(udc-fclk); + if (!IS_ERR(udc-iclk)) + clk_put(udc-iclk); iounmap(udc-udp_baseaddr); fail0a: if (cpu_is_at91rm9200()) @@ -1894,6 +1909,8 @@ static int __exit at91udc_remove(struct platform_device *pdev) clk_put(udc-iclk); clk_put(udc-fclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_put(udc-uclk); return 0; } diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index e647d1c..0175246 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h @@ -126,7 +126,7 @@ struct at91_udc { unsignedactive_suspend:1; u8 addr; struct at91_udc_databoard; - struct clk *iclk, *fclk; + struct clk *iclk, *fclk, *uclk; struct platform_device *pdev; struct proc_dir_entry *pde; void __iomem*udp_baseaddr; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] USB: ohci-at91: add usb_clk for transition to common clk framework
The AT91 PMC (Power Management Controller) provides an USB clock used by USB Full Speed host (ohci) and USB Full Speed device (udc). The usb drivers (ohci and udc) must configure this clock to 48Mhz. This configuration was formely done in mach-at91/clock.c, but this implementation will be removed when moving to common clk framework. This patch adds support for usb clock retrieval and configuration, and is backward compatible with the current at91 clk implementation (if usb clk is not found, it does not configure/enable it). Changes since v1: - use IS_ENABLED(CONFIG_COMMON_CLK) to isolate new at91 clk support Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/usb/host/ohci-at91.c | 23 +-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 9677f68..db60048 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -31,8 +31,8 @@ #define at91_for_each_port(index) \ for ((index) = 0; (index) AT91_MAX_USBH_PORTS; (index)++) -/* interface and function clocks; sometimes also an AHB clock */ -static struct clk *iclk, *fclk, *hclk; +/* interface, function and usb clocks; sometimes also an AHB clock */ +static struct clk *iclk, *fclk, *uclk, *hclk; static int clocked; extern int usb_disabled(void); @@ -41,6 +41,10 @@ extern int usb_disabled(void); static void at91_start_clock(void) { + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + clk_set_rate(uclk, 4800); + clk_prepare_enable(uclk); + } clk_prepare_enable(hclk); clk_prepare_enable(iclk); clk_prepare_enable(fclk); @@ -52,6 +56,8 @@ static void at91_stop_clock(void) clk_disable_unprepare(fclk); clk_disable_unprepare(iclk); clk_disable_unprepare(hclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_disable_unprepare(uclk); clocked = 0; } @@ -162,6 +168,14 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, retval = PTR_ERR(hclk); goto err5; } + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + uclk = clk_get(pdev-dev, usb_clk); + if (IS_ERR(uclk)) { + dev_err(pdev-dev, failed to get uclk\n); + retval = PTR_ERR(uclk); + goto err6; + } + } at91_start_hc(pdev); ohci_hcd_init(hcd_to_ohci(hcd)); @@ -173,6 +187,9 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, /* Error handling */ at91_stop_hc(pdev); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_put(uclk); + err6: clk_put(hclk); err5: clk_put(fclk); @@ -212,6 +229,8 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd, release_mem_region(hcd-rsrc_start, hcd-rsrc_len); usb_put_hcd(hcd); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_put(uclk); clk_put(hclk); clk_put(fclk); clk_put(iclk); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 0/2] usb: gadget: at91_udc: add usb_clk for transition to common clk framework
Hello, This patch series prepare the at91 SoCs transition to common clk framework. This is done by adding a new clock (called usb clock or uclk) to at91_udc driver. This clock will be used to configure the usb port clock rate. Best Regards, Boris Changes since v2: - split the patch in 2 parts: * add missing clk_put for existing clk (fclk and uclk) * add usb clock (uclk) support Changes since v1: - use IS_ENABLED(CONFIG_COMMON_CLK) to isolate new at91 clk support Boris BREZILLON (2): usb: gadget: at91_udc: add missing clk_put on fclk and iclk usb: gadget: at91_udc: add usb_clk for transition to common clk framework drivers/usb/gadget/at91_udc.c | 21 +++-- drivers/usb/gadget/at91_udc.h |2 +- 2 files changed, 20 insertions(+), 3 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 2/2] usb: gadget: at91_udc: add usb_clk for transition to common clk framework
The AT91 PMC (Power Management Controller) provides an USB clock used by USB Full Speed host (ohci) and USB Full Speed device (udc). The usb drivers (ohci and udc) must configure this clock to 48Mhz. This configuration was formely done in mach-at91/clock.c, but this implementation will be removed when moving to common clk framework. This patch adds support for usb clock retrieval and configuration, and is backward compatible with the current at91 clk implementation (if usb clk is not found, it does not configure/enable it). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/usb/gadget/at91_udc.c | 17 +++-- drivers/usb/gadget/at91_udc.h |2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index d145cb78..5c7c8bb 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -870,6 +870,11 @@ static void clk_on(struct at91_udc *udc) if (udc-clocked) return; udc-clocked = 1; + + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + clk_set_rate(udc-uclk, 4800); + clk_prepare_enable(udc-uclk); + } clk_prepare_enable(udc-iclk); clk_prepare_enable(udc-fclk); } @@ -882,6 +887,8 @@ static void clk_off(struct at91_udc *udc) udc-gadget.speed = USB_SPEED_UNKNOWN; clk_disable_unprepare(udc-fclk); clk_disable_unprepare(udc-iclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_disable_unprepare(udc-uclk); } /* @@ -1774,10 +1781,12 @@ static int at91udc_probe(struct platform_device *pdev) /* get interface and function clocks */ udc-iclk = clk_get(dev, udc_clk); udc-fclk = clk_get(dev, udpck); - if (IS_ERR(udc-iclk) || IS_ERR(udc-fclk)) { + if (IS_ENABLED(CONFIG_COMMON_CLK)) + udc-uclk = clk_get(dev, usb_clk); + if (IS_ERR(udc-iclk) || IS_ERR(udc-fclk) || + (IS_ENABLED(CONFIG_COMMON_CLK) IS_ERR(udc-uclk))) { DBG(clocks missing\n); retval = -ENODEV; - /* NOTE: we know here that refcounts on these are NOPs */ goto fail1; } @@ -1851,6 +1860,8 @@ fail3: fail2: free_irq(udc-udp_irq, udc); fail1: + if (IS_ENABLED(CONFIG_COMMON_CLK) !IS_ERR(udc-uclk)) + clk_put(udc-uclk); if (!IS_ERR(udc-fclk)) clk_put(udc-fclk); if (!IS_ERR(udc-iclk)) @@ -1898,6 +1909,8 @@ static int __exit at91udc_remove(struct platform_device *pdev) clk_put(udc-iclk); clk_put(udc-fclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_put(udc-uclk); return 0; } diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index e647d1c..0175246 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h @@ -126,7 +126,7 @@ struct at91_udc { unsignedactive_suspend:1; u8 addr; struct at91_udc_databoard; - struct clk *iclk, *fclk; + struct clk *iclk, *fclk, *uclk; struct platform_device *pdev; struct proc_dir_entry *pde; void __iomem*udp_baseaddr; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 1/2] usb: gadget: at91_udc: add missing clk_put on fclk and iclk
This patch adds missing clk_put on fclk and iclk in case the probe function fails after these clocks have been retrieved. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/usb/gadget/at91_udc.c |4 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index fce8e4e..d145cb78 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1851,6 +1851,10 @@ fail3: fail2: free_irq(udc-udp_irq, udc); fail1: + if (!IS_ERR(udc-fclk)) + clk_put(udc-fclk); + if (!IS_ERR(udc-iclk)) + clk_put(udc-iclk); iounmap(udc-udp_baseaddr); fail0a: if (cpu_is_at91rm9200()) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/8] ARM: at91/dt: make use of periph id macros
Hello Richard, On 01/08/2013 09:37, Richard Genoud wrote: 2013/8/1 Boris BREZILLON b.brezil...@overkiz.com: Hello, This patch series move at91 SoCs peripheral id definitions from machine specific include dir to dt-bindings include dir. These macros are used to reference interrupts instead of peripheral numbers. This makes dt definitions cleaner and easier to debug (one can easily tell if the peripheral macro used to reference an interrupt line is not the good one). These macros will be used for clk definitions and references too. I am not sure 'include/dt-bindings/at91/xxx' is the best place to put these definitions as there are no soc specific directories in dt-bindings include dir right now. Maybe something like 'include/dt-bindings/soc/at91/xxx' or 'include/dt-bindings/peripherals/at91/xxx' would be better. What do you think ? Well, I'd rather use atmel than at91 because, AFAIK, this prefix has been dropped for new atmel SoCs (sama5 for instance). Should I do the same for at91 clk series (replace drivers/clk/at91 directory by drivers/clk/atmel and include/linux/clk/at91_pmc.h by include/linux/clk/atmel_pmc.h) ? my 2 cents... Richard. Best Regards, Boris -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC PATCH RESEND 1/2] clk: add clk accuracy retrieval support
Hello Mike, On 08/11/2013 01:51, Mike Turquette wrote: Quoting Boris BREZILLON (2013-10-13 10:17:10) The clock accuracy is expressed in ppb (parts per billion) and represents the possible clock drift. Say you have a clock (e.g. an oscillator) which provides a fixed clock of 20MHz with an accuracy of +- 20Hz. This accuracy expressed in ppb is 20Hz/20MHz = 1000 ppb (or 1 ppm). Clock users may need the clock accuracy information in order to choose the best clock (the one with the best accuracy) across several available clocks. This patch adds clk accuracy retrieval support for common clk framework by means of a new function called clk_get_accuracy. This function returns the given clock accuracy expressed in ppb. In order to get the clock accuracy, this implementation adds one callback called recalc_accuracy to the clk_ops structure. This callback is given the parent clock accuracy (if the clock is not a root clock) and should recalculate the given clock accuracy. This callback is optional and may be implemented if the clock is not a perfect clock (accuracy != 0 ppb). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- Documentation/clk.txt|4 ++ drivers/clk/Kconfig |4 ++ drivers/clk/clk.c| 92 -- include/linux/clk-private.h |1 + include/linux/clk-provider.h | 11 + include/linux/clk.h | 17 6 files changed, 125 insertions(+), 4 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 3aeb5c4..dc52da1 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -77,6 +77,8 @@ the operations defined in clk.h: int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long); + unsigned long (*recalc_accuracy)(struct clk_hw *hw, + unsigned long parent_accuracy); void(*init)(struct clk_hw *hw); }; @@ -202,6 +204,8 @@ optional or must be evaluated on a case-by-case basis. .set_parent | | | n | y | n| .get_parent | | | n | y | n| | | | | | | +.recalc_rate| | | | | | s/recalc_rate/recalc_accuracy/ Oops. I'll fix it :). +| | | | | | .init | | | | | | --- [1] either one of round_rate or determine_rate is required. diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 279407a..4d12ae7 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -6,12 +6,16 @@ config CLKDEV_LOOKUP config HAVE_CLK_PREPARE bool +config HAVE_CLK_GET_ACCURACY + bool + This sort of thing gets messy. For platforms converted to common struct clk we select HAVE_CLK_PREPARE and we let legacy platforms select it on a case-by-case basis. For something like HAVE_CLK_GET_ACCURACY I am inclined to only add it for platforms converted to the common struct clk and not even expose it to legacy clock framework implementations. In those cases the call to clk_get_accuracy would return -EINVAL or -EPERM or something. Okay. If Russell agrees, I'll define a static inline function returning an error (-ENOTSUPP ?) in case CONFIG_COMMON_CLK is not defined. Russell, any thoughts on that approach? config HAVE_MACH_CLKDEV bool config COMMON_CLK bool select HAVE_CLK_PREPARE + select HAVE_CLK_GET_ACCURACY select CLKDEV_LOOKUP ---help--- The common clock framework is a single definition of struct diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index a004769..6a8f3ef 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -104,10 +104,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) if (!c) return; - seq_printf(s, %*s%-*s %-11d %-12d %-10lu, + seq_printf(s, %*s%-*s %-11d %-12d %-10lu %-11lu, level * 3 + 1, , 30 - level * 3, c-name, - c-enable_count, c-prepare_count, clk_get_rate(c)); + c-enable_count, c-prepare_count, clk_get_rate(c), + clk_get_accuracy(c)); seq_printf(s, \n); } @@ -129,8 +130,8 @@ static int clk_summary_show(struct seq_file *s, void *data) { struct clk *c; - seq_printf(s,clockenable_cnt prepare_cnt rate\n); - seq_printf(s
[PATCH 2/3] ARM: at91/tc/clocksource: improve driver robustness
Check function return values to avoid false positive driver init. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/clocksource/tcb_clksrc.c | 33 - 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 0481562..10a5d9e 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -184,11 +184,18 @@ static struct irqaction tc_irqaction = { .handler= ch2_irq, }; -static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) +static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) { + int ret; struct clk *t2_clk = tc-clk[2]; int irq = tc-irq[2]; + /* try to enable t2 clk to avoid future errors in mode change */ + ret = clk_prepare_enable(t2_clk); + if (ret) + return ret; + clk_disable_unprepare(t2_clk); + clkevt.regs = tc-regs; clkevt.clk = t2_clk; tc_irqaction.dev_id = clkevt; @@ -197,16 +204,21 @@ static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) clkevt.clkevt.cpumask = cpumask_of(0); + ret = setup_irq(irq, tc_irqaction); + if (ret) + return ret; + clockevents_config_and_register(clkevt.clkevt, 32768, 1, 0x); - setup_irq(irq, tc_irqaction); + return ret; } #else /* !CONFIG_GENERIC_CLOCKEVENTS */ -static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) +static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) { /* NOTHING */ + return 0; } #endif @@ -328,13 +340,24 @@ static int __init tcb_clksrc_init(void) } /* and away we go! */ - clocksource_register_hz(clksrc, divided_rate); + ret = clocksource_register_hz(clksrc, divided_rate); + if (ret) + goto err_disable_t1; /* channel 2: periodic and oneshot timer support */ - setup_clkevents(tc, clk32k_divisor_idx); + ret = setup_clkevents(tc, clk32k_divisor_idx); + if (ret) + goto err_unregister_clksrc; return 0; +err_unregister_clksrc: + clocksource_unregister(clksrc); + +err_disable_t1: + if (!tc-tcb_config || tc-tcb_config-counter_width != 32) + clk_disable_unprepare(tc-clk[1]); + err_disable_t0: clk_disable_unprepare(t0_clk); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/3] ARM: at91/tc/clocksource: various robustness improvements
Hello, This series include several improvements regarding the at91 tc clocksource driver: - use clk_prepare/unprepare_enable/disable functions instead of the clk_enable/disable functions to prepare the transition to the common clk framework - check several function return values instead of considering these functions always suceed. - remove the deprecated IRQF_DISABLED flag Best Regards, Boris Boris BREZILLON (3): ARM: at91/tc/clocksource: replace clk_enable/disable with clk_prepare_enable/disable_unprepare ARM: at91/tc/clocksource: improve driver robustness ARM: at91/tc/clocksource: remove IRQF_DISABLED drivers/clocksource/tcb_clksrc.c | 61 +++--- 1 file changed, 50 insertions(+), 11 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/3] ARM: at91/tc/clocksource: remove IRQF_DISABLED
Remove the deprecated IRQF_DISABLED flag. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/clocksource/tcb_clksrc.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 10a5d9e..00fdd11 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -180,7 +180,7 @@ static irqreturn_t ch2_irq(int irq, void *handle) static struct irqaction tc_irqaction = { .name = tc_clkevt, - .flags = IRQF_TIMER | IRQF_DISABLED, + .flags = IRQF_TIMER, .handler= ch2_irq, }; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/3] ARM: at91/tc/clocksource: replace clk_enable/disable with clk_prepare_enable/disable_unprepare
Replace clk_enable/disable with clk_prepare_enable/disable_unprepare to avoid common clk framework warnings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clocksource/tcb_clksrc.c | 26 +- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 8a61872..0481562 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -100,7 +100,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) || tcd-clkevt.mode == CLOCK_EVT_MODE_ONESHOT) { __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); - clk_disable(tcd-clk); + clk_disable_unprepare(tcd-clk); } switch (m) { @@ -109,7 +109,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) * of oneshot, we get lower overhead and improved accuracy. */ case CLOCK_EVT_MODE_PERIODIC: - clk_enable(tcd-clk); + clk_prepare_enable(tcd-clk); /* slow clock, count up to RC, then irq and restart */ __raw_writel(timer_clock @@ -126,7 +126,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) break; case CLOCK_EVT_MODE_ONESHOT: - clk_enable(tcd-clk); + clk_prepare_enable(tcd-clk); /* slow clock, count up to RC, then irq and stop */ __raw_writel(timer_clock | ATMEL_TC_CPCSTOP @@ -265,6 +265,7 @@ static int __init tcb_clksrc_init(void) int best_divisor_idx = -1; int clk32k_divisor_idx = -1; int i; + int ret; tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name); if (!tc) { @@ -275,7 +276,11 @@ static int __init tcb_clksrc_init(void) pdev = tc-pdev; t0_clk = tc-clk[0]; - clk_enable(t0_clk); + ret = clk_prepare_enable(t0_clk); + if (ret) { + pr_debug(can't enable T0 clk\n); + goto err_free_tc; + } /* How fast will we be counting? Pick something over 5 MHz. */ rate = (u32) clk_get_rate(t0_clk); @@ -313,7 +318,11 @@ static int __init tcb_clksrc_init(void) /* tclib will give us three clocks no matter what the * underlying platform supports. */ - clk_enable(tc-clk[1]); + ret = clk_prepare_enable(tc-clk[1]); + if (ret) { + pr_debug(can't enable T1 clk\n); + goto err_disable_t0; + } /* setup both channel 0 1 */ tcb_setup_dual_chan(tc, best_divisor_idx); } @@ -325,5 +334,12 @@ static int __init tcb_clksrc_init(void) setup_clkevents(tc, clk32k_divisor_idx); return 0; + +err_disable_t0: + clk_disable_unprepare(t0_clk); + +err_free_tc: + atmel_tc_free(tc); + return ret; } arch_initcall(tcb_clksrc_init); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/3] ARM: at91/tc/clocksource: replace clk_enable/disable with clk_prepare_enable/disable_unprepare
Replace clk_enable/disable with clk_prepare_enable/disable_unprepare to avoid common clk framework warnings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clocksource/tcb_clksrc.c | 26 +- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 8a61872..0481562 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -100,7 +100,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) || tcd-clkevt.mode == CLOCK_EVT_MODE_ONESHOT) { __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); - clk_disable(tcd-clk); + clk_disable_unprepare(tcd-clk); } switch (m) { @@ -109,7 +109,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) * of oneshot, we get lower overhead and improved accuracy. */ case CLOCK_EVT_MODE_PERIODIC: - clk_enable(tcd-clk); + clk_prepare_enable(tcd-clk); /* slow clock, count up to RC, then irq and restart */ __raw_writel(timer_clock @@ -126,7 +126,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) break; case CLOCK_EVT_MODE_ONESHOT: - clk_enable(tcd-clk); + clk_prepare_enable(tcd-clk); /* slow clock, count up to RC, then irq and stop */ __raw_writel(timer_clock | ATMEL_TC_CPCSTOP @@ -265,6 +265,7 @@ static int __init tcb_clksrc_init(void) int best_divisor_idx = -1; int clk32k_divisor_idx = -1; int i; + int ret; tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name); if (!tc) { @@ -275,7 +276,11 @@ static int __init tcb_clksrc_init(void) pdev = tc-pdev; t0_clk = tc-clk[0]; - clk_enable(t0_clk); + ret = clk_prepare_enable(t0_clk); + if (ret) { + pr_debug(can't enable T0 clk\n); + goto err_free_tc; + } /* How fast will we be counting? Pick something over 5 MHz. */ rate = (u32) clk_get_rate(t0_clk); @@ -313,7 +318,11 @@ static int __init tcb_clksrc_init(void) /* tclib will give us three clocks no matter what the * underlying platform supports. */ - clk_enable(tc-clk[1]); + ret = clk_prepare_enable(tc-clk[1]); + if (ret) { + pr_debug(can't enable T1 clk\n); + goto err_disable_t0; + } /* setup both channel 0 1 */ tcb_setup_dual_chan(tc, best_divisor_idx); } @@ -325,5 +334,12 @@ static int __init tcb_clksrc_init(void) setup_clkevents(tc, clk32k_divisor_idx); return 0; + +err_disable_t0: + clk_disable_unprepare(t0_clk); + +err_free_tc: + atmel_tc_free(tc); + return ret; } arch_initcall(tcb_clksrc_init); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [v2,2/4] watchdog: at91sam9_wdt: update device tree doc
On 02/10/2013 17:51, Guenter Roeck wrote: On Fri, Jun 21, 2013 at 03:23:34PM -, Boris BREZILLON wrote: Add new at91sam9 watchdog properties to the documentation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Grant Likelygrant.lik...@linaro.org --- .../devicetree/bindings/watchdog/atmel-wdt.txt | 30 ++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt index fcdd48f..e043106 100644 --- a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt @@ -9,11 +9,37 @@ Required properties: Optional properties: - timeout-sec: contains the watchdog timeout in seconds. +- interrupts : Should contain WDT interrupt. +- atmel,max-heartbeat-sec : Should contain the maximum heartbeat value in + seconds. This value should be less than 16. It is used to compute the + WDV field. +- atmel,min-heartbeat-sec : Should contain the minimum heartbeat value in + seconds. This value should be less than 4 times the max-heartbeat-sec + value. It is used to compute the WDD field. I am a bit at loss about less than 4 times the max-heartbeat-sec value. Why would a min-timeout larger than the max-timeout make sense under any condition ? Do you mean to say that max-heartbeat should be at least four times the value of min-heartbeat (or that min-heartbeat should be less or equal to one-forth of max-heartbeat) ? That's exactely what I meant (should be less or equal to one-forth of max-heartbeat). I'll fix it. Guenter +- atmel,watchdog-type : Should be hardware or software. Hardware watchdog + use the at91 watchdog reset. Software watchdog use the watchdog + interrupt to trigger a software reset. +- atmel,reset-type : Should be proc or all. + all : assert peripherals and processor reset signals + proc : assert the processor reset signal + This is valid only when using hardware watchdog. +- atmel,disable : Should be present if you want to disable the watchdog. +- atmel,idle-halt : Should be present if you want to stop the watchdog when + entering idle state. +- atmel,dbg-halt : Should be present if you want to stop the watchdog when + entering debug state. Example: - watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; - timeout-sec = 10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + timeout-sec = 15; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; + atmel,max-heartbeat-sec = 16; + atmel,min-heartbeat-sec = 0; + status = okay; }; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [v2,1/4] watchdog: at91sam9_wdt: better watchdog support
Hello Guenter, Thanks for reviewing this patch. On 02/10/2013 18:12, Guenter Roeck wrote: On Fri, Jun 21, 2013 at 03:21:28PM -, Boris BREZILLON wrote: The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/watchdog/at91sam9_wdt.c | 319 +-- 1 file changed, 236 insertions(+), 83 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index be37dde..fb47ec5 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -19,11 +19,13 @@ #include linux/errno.h #include linux/init.h +#include linux/interrupt.h #include linux/io.h #include linux/kernel.h #include linux/module.h #include linux/moduleparam.h #include linux/platform_device.h +#include linux/reboot.h #include linux/types.h #include linux/watchdog.h #include linux/jiffies.h @@ -31,23 +33,32 @@ #include linux/bitops.h #include linux/uaccess.h #include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h #include at91sam9_wdt.h #define DRV_NAME AT91SAM9 Watchdog -#define wdt_read(field) \ - __raw_readl(at91wdt_private.base + field) -#define wdt_write(field, val) \ - __raw_writel((val), at91wdt_private.base + field) +#define wdt_read(wdt, field) \ + __raw_readl((wdt)-base + field) +#define wdt_write(wtd, field, val) \ + __raw_writel((val), (wdt)-base + field) /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, * use this to convert a watchdog * value from/to milliseconds. */ +#define hz_to_ticks(h) (((h 8) / HZ) - 1) Unused. I'll drop it. +#define ticks_to_hz(t) (((t + 1) * HZ) 8) #define ms_to_ticks(t)(((t 8) / 1000) - 1) #define ticks_to_ms(t)(((t + 1) * 1000) 8) You should put macro parameters in () to avoid undesired side effects. (h), (t), (field) Sure, some of them are old. No reason not to fix it, though. I'll fix it (I'll fix old macros in a separate patch) +#define WDT_MR_RESET 0x3FFF2FFF + +#define WDT_WDD_MAX0xFFF +#define WDT_WDV_MAX0xFFF What are the units ? ticks (slow clk cycles). I'll rename these macros: #define WDT_XXX_MAX_TICKS 0xFFF + /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 2 @@ -66,23 +77,41 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, Watchdog cannot be stopped once started (default= __MODULE_STRING(WATCHDOG_NOWAYOUT) )); -static struct watchdog_device at91_wdt_dev; -static void at91_ping(unsigned long data); - -static struct { +#define to_wdt(wdd) container_of(wdd, struct at91wdt, wdd) +struct at91wdt { + struct watchdog_device wdd; void __iomem *base; unsigned long next_heartbeat; /* the next_heartbeat for the timer */ struct timer_list timer;/* The timer that pings the watchdog */ -} at91wdt_private; + u32 mr; + u32 mr_mask; + unsigned long heartbeat;/* WDT heartbeat in jiffies */ + bool nowayout; + unsigned int irq; +}; /* . */ +static irqreturn_t wdt_interrupt(int irq, void *dev_id) +{ + struct at91wdt *wdt = (struct at91wdt *)dev_id; + + if (wdt_read(wdt, AT91_WDT_SR)) { + /* Reboot */ That is quite obvious, isn't it ? I'll drop the comment line. + pr_crit(at91sam9 WDT software reset\n); + emergency_restart(); + pr_crit(Reboot didn't ?\n); + } + + return IRQ_HANDLED; +} + /* * Reload the watchdog timer. (ie, pat the watchdog) */ -static inline void at91_wdt_reset(void) +static inline void at91_wdt_reset(struct at91wdt *wdt) { - wdt_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); + wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); } /* @@ -90,26 +119,20 @@ static inline void at91_wdt_reset(void) */ static void at91_ping(unsigned long data
Re: [v2,1/4] watchdog: at91sam9_wdt: better watchdog support
On 02/10/2013 21:34, Guenter Roeck wrote: On Wed, Oct 02, 2013 at 09:27:03PM +0200, boris brezillon wrote: Hello Guenter, Thanks for reviewing this patch. On 02/10/2013 18:12, Guenter Roeck wrote: On Fri, Jun 21, 2013 at 03:21:28PM -, Boris BREZILLON wrote: The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/watchdog/at91sam9_wdt.c | 319 +-- 1 file changed, 236 insertions(+), 83 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index be37dde..fb47ec5 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -19,11 +19,13 @@ #include linux/errno.h #include linux/init.h +#include linux/interrupt.h #include linux/io.h #include linux/kernel.h #include linux/module.h #include linux/moduleparam.h #include linux/platform_device.h +#include linux/reboot.h #include linux/types.h #include linux/watchdog.h #include linux/jiffies.h @@ -31,23 +33,32 @@ #include linux/bitops.h #include linux/uaccess.h #include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h #include at91sam9_wdt.h #define DRV_NAME AT91SAM9 Watchdog -#define wdt_read(field) \ - __raw_readl(at91wdt_private.base + field) -#define wdt_write(field, val) \ - __raw_writel((val), at91wdt_private.base + field) +#define wdt_read(wdt, field) \ + __raw_readl((wdt)-base + field) +#define wdt_write(wtd, field, val) \ + __raw_writel((val), (wdt)-base + field) /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, * use this to convert a watchdog * value from/to milliseconds. */ +#define hz_to_ticks(h) (((h 8) / HZ) - 1) Unused. I'll drop it. +#define ticks_to_hz(t) (((t + 1) * HZ) 8) #define ms_to_ticks(t)(((t 8) / 1000) - 1) #define ticks_to_ms(t)(((t + 1) * 1000) 8) You should put macro parameters in () to avoid undesired side effects. (h), (t), (field) Sure, some of them are old. No reason not to fix it, though. I'll fix it (I'll fix old macros in a separate patch) +#define WDT_MR_RESET 0x3FFF2FFF + +#define WDT_WDD_MAX0xFFF +#define WDT_WDV_MAX0xFFF What are the units ? ticks (slow clk cycles). I'll rename these macros: #define WDT_XXX_MAX_TICKS 0xFFF + /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 2 @@ -66,23 +77,41 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, Watchdog cannot be stopped once started (default= __MODULE_STRING(WATCHDOG_NOWAYOUT) )); -static struct watchdog_device at91_wdt_dev; -static void at91_ping(unsigned long data); - -static struct { +#define to_wdt(wdd) container_of(wdd, struct at91wdt, wdd) +struct at91wdt { + struct watchdog_device wdd; void __iomem *base; unsigned long next_heartbeat; /* the next_heartbeat for the timer */ struct timer_list timer;/* The timer that pings the watchdog */ -} at91wdt_private; + u32 mr; + u32 mr_mask; + unsigned long heartbeat;/* WDT heartbeat in jiffies */ + bool nowayout; + unsigned int irq; +}; /* . */ +static irqreturn_t wdt_interrupt(int irq, void *dev_id) +{ + struct at91wdt *wdt = (struct at91wdt *)dev_id; + + if (wdt_read(wdt, AT91_WDT_SR)) { + /* Reboot */ That is quite obvious, isn't it ? I'll drop the comment line. + pr_crit(at91sam9 WDT software reset\n); + emergency_restart(); + pr_crit(Reboot didn't ?\n); + } + + return IRQ_HANDLED; +} + /* * Reload the watchdog timer. (ie, pat the watchdog) */ -static inline void at91_wdt_reset(void) +static inline void at91_wdt_reset(struct at91wdt *wdt) { - wdt_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); + wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); } /* @@ -90,26 +119,20 @@ static inline void
Re: [PATCH v2 2/4] watchdog: at91sam9_wdt: update device tree doc
Hello Fabio, On 03/10/2013 10:08, Fabio Porcedda wrote: On Fri, Jun 21, 2013 at 9:23 AM, Boris BREZILLON b.brezil...@overkiz.com wrote: Add new at91sam9 watchdog properties to the documentation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- .../devicetree/bindings/watchdog/atmel-wdt.txt | 30 ++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt index fcdd48f..e043106 100644 --- a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt @@ -9,11 +9,37 @@ Required properties: Optional properties: - timeout-sec: contains the watchdog timeout in seconds. Why are you removing the documentation about this property? I'm not removing the property: this is an enumeration minus not a diff minus. Regards Regards, Boris -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 0/4] watchdog: at91sam9_wdt: handle already configured wdt
Hello, This patch series is a porposal to enhance the sam9 watchdog timer support. The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. I'm not sure this is the best solution, so please tell me if you prefer to keep static instance of watchdog. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Best Regards, Boris Changes since v2: - fix documentation - rework the heartbeat computation to get a more flexible behaviour - fix xx_to_yy macros - modify warning and error messages - remove unneeded parenthesis in arithmetic operations - use devm functions to map io memory - remove unneeded devm_kfree calls Change since v1: - fix typo in documentaion - fix irq dt definition for sama5d3 SoC Boris BREZILLON (4): watchdog: at91sam9_wdt: better watchdog support watchdog: at91sam9_wdt: update device tree doc ARM: at91/dt: add sam9 watchdog default options to SoCs ARM: at91/dt: add watchdog properties to kizbox board .../devicetree/bindings/watchdog/atmel-wdt.txt | 30 +- arch/arm/boot/dts/at91sam9260.dtsi |5 + arch/arm/boot/dts/at91sam9263.dtsi |5 + arch/arm/boot/dts/at91sam9g45.dtsi |5 + arch/arm/boot/dts/at91sam9n12.dtsi |5 + arch/arm/boot/dts/at91sam9x5.dtsi |5 + arch/arm/boot/dts/kizbox.dts |6 + arch/arm/boot/dts/sama5d3.dtsi |5 + drivers/watchdog/at91sam9_wdt.c| 301 ++-- 9 files changed, 282 insertions(+), 85 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/4] watchdog: at91sam9_wdt: better watchdog support
The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/watchdog/at91sam9_wdt.c | 300 --- 1 file changed, 217 insertions(+), 83 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index be37dde..8f44528 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -19,11 +19,13 @@ #include linux/errno.h #include linux/init.h +#include linux/interrupt.h #include linux/io.h #include linux/kernel.h #include linux/module.h #include linux/moduleparam.h #include linux/platform_device.h +#include linux/reboot.h #include linux/types.h #include linux/watchdog.h #include linux/jiffies.h @@ -31,22 +33,33 @@ #include linux/bitops.h #include linux/uaccess.h #include linux/of.h +#include linux/of_irq.h #include at91sam9_wdt.h #define DRV_NAME AT91SAM9 Watchdog -#define wdt_read(field) \ - __raw_readl(at91wdt_private.base + field) -#define wdt_write(field, val) \ - __raw_writel((val), at91wdt_private.base + field) +#define wdt_read(wdt, field) \ + __raw_readl((wdt)-base + (field)) +#define wdt_write(wtd, field, val) \ + __raw_writel((val), (wdt)-base + (field)) /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, * use this to convert a watchdog * value from/to milliseconds. */ -#define ms_to_ticks(t) (((t 8) / 1000) - 1) -#define ticks_to_ms(t) (((t + 1) * 1000) 8) +#define ticks_to_hz_rounddown(t) t) + 1) * HZ) 8) +#define ticks_to_hz_roundup(t) (t) + 1) * HZ) + 255) 8) +#define ticks_to_secs(t) (((t) + 1) 8) +#define secs_to_ticks(s) (((s) 8) - 1) + +#define WDT_MR_RESET 0x3FFF2FFF + +/* Watchdog max counter value in ticks */ +#define WDT_COUNTER_MAX_TICKS 0xFFF + +/* Watchdog max delta/value in secs */ +#define WDT_COUNTER_MAX_SECS ticks_to_secs(WDT_COUNTER_MAX_TICKS) /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 2 @@ -66,23 +79,40 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, Watchdog cannot be stopped once started (default= __MODULE_STRING(WATCHDOG_NOWAYOUT) )); -static struct watchdog_device at91_wdt_dev; -static void at91_ping(unsigned long data); - -static struct { +#define to_wdt(wdd) container_of(wdd, struct at91wdt, wdd) +struct at91wdt { + struct watchdog_device wdd; void __iomem *base; unsigned long next_heartbeat; /* the next_heartbeat for the timer */ struct timer_list timer;/* The timer that pings the watchdog */ -} at91wdt_private; + u32 mr; + u32 mr_mask; + unsigned long heartbeat;/* WDT heartbeat in jiffies */ + bool nowayout; + unsigned int irq; +}; /* . */ +static irqreturn_t wdt_interrupt(int irq, void *dev_id) +{ + struct at91wdt *wdt = (struct at91wdt *)dev_id; + + if (wdt_read(wdt, AT91_WDT_SR)) { + pr_crit(at91sam9 WDT software reset\n); + emergency_restart(); + pr_crit(Reboot didn't ?\n); + } + + return IRQ_HANDLED; +} + /* * Reload the watchdog timer. (ie, pat the watchdog) */ -static inline void at91_wdt_reset(void) +static inline void at91_wdt_reset(struct at91wdt *wdt) { - wdt_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); + wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); } /* @@ -90,26 +120,20 @@ static inline void at91_wdt_reset(void) */ static void at91_ping(unsigned long data) { - if (time_before(jiffies, at91wdt_private.next_heartbeat) || - (!watchdog_active(at91_wdt_dev))) { - at91_wdt_reset(); - mod_timer(at91wdt_private.timer, jiffies + WDT_TIMEOUT); + struct at91wdt *wdt = (struct at91wdt *)data; + if (time_before(jiffies, wdt-next_heartbeat) || + !watchdog_active(wdt-wdd)) { + at91_wdt_reset(wdt
[PATCH 2/4] watchdog: at91sam9_wdt: update device tree doc
Add new at91sam9 watchdog properties to the documentation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- .../devicetree/bindings/watchdog/atmel-wdt.txt | 30 ++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt index fcdd48f..f90e294 100644 --- a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt @@ -9,11 +9,37 @@ Required properties: Optional properties: - timeout-sec: contains the watchdog timeout in seconds. +- interrupts : Should contain WDT interrupt. +- atmel,max-heartbeat-sec : Should contain the maximum heartbeat value in + seconds. This value should be less or equal to 16. It is used to + compute the WDV field. +- atmel,min-heartbeat-sec : Should contain the minimum heartbeat value in + seconds. This value must be smaller than the max-heartbeat-sec value. + It is used to compute the WDD field. +- atmel,watchdog-type : Should be hardware or software. Hardware watchdog + use the at91 watchdog reset. Software watchdog use the watchdog + interrupt to trigger a software reset. +- atmel,reset-type : Should be proc or all. + all : assert peripherals and processor reset signals + proc : assert the processor reset signal + This is valid only when using hardware watchdog. +- atmel,disable : Should be present if you want to disable the watchdog. +- atmel,idle-halt : Should be present if you want to stop the watchdog when + entering idle state. +- atmel,dbg-halt : Should be present if you want to stop the watchdog when + entering debug state. Example: - watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; - timeout-sec = 10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + timeout-sec = 15; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; + atmel,max-heartbeat-sec = 16; + atmel,min-heartbeat-sec = 0; + status = okay; }; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 4/4] ARM: at91/dt: add watchdog properties to kizbox board
Add watchdog specific config for kizbox board. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/boot/dts/kizbox.dts |6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts index 02df191..928f6ee 100644 --- a/arch/arm/boot/dts/kizbox.dts +++ b/arch/arm/boot/dts/kizbox.dts @@ -53,6 +53,12 @@ status = okay; }; + watchdog@fd40 { + timeout-sec = 15; + atmel,max-heartbeat-sec = 16; + atmel,min-heartbeat-sec = 0; + status = okay; + }; }; nand0: nand@4000 { -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/4] ARM: at91/dt: add sam9 watchdog default options to SoCs
Set default watchdog options in every SoC compatible with the sam9 watchdog. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/boot/dts/at91sam9260.dtsi |5 + arch/arm/boot/dts/at91sam9263.dtsi |5 + arch/arm/boot/dts/at91sam9g45.dtsi |5 + arch/arm/boot/dts/at91sam9n12.dtsi |5 + arch/arm/boot/dts/at91sam9x5.dtsi |5 + arch/arm/boot/dts/sama5d3.dtsi |5 + 6 files changed, 30 insertions(+) diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index 56ee828..997901f 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi @@ -648,6 +648,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; }; diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi index d5bd65f..45fb0a4 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/at91sam9263.dtsi @@ -523,6 +523,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index c3e5148..16534c7 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -639,6 +639,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi index 9fb7ffd..eaef94b 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/at91sam9n12.dtsi @@ -537,6 +537,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; }; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index e74dc15..6d31fd7 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -820,6 +820,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index b7f4961..3a17a3e 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -891,6 +891,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 4 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled
Re: [PATCH 1/4] watchdog: at91sam9_wdt: better watchdog support
Hi Guenter, On 03/10/2013 19:31, Guenter Roeck wrote: On Thu, Oct 03, 2013 at 02:19:18PM +0200, Boris BREZILLON wrote: The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Hi Boris, deeper dive this time ... --- drivers/watchdog/at91sam9_wdt.c | 300 --- 1 file changed, 217 insertions(+), 83 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index be37dde..8f44528 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -19,11 +19,13 @@ #include linux/errno.h #include linux/init.h +#include linux/interrupt.h #include linux/io.h #include linux/kernel.h #include linux/module.h #include linux/moduleparam.h #include linux/platform_device.h +#include linux/reboot.h #include linux/types.h #include linux/watchdog.h #include linux/jiffies.h @@ -31,22 +33,33 @@ #include linux/bitops.h #include linux/uaccess.h #include linux/of.h +#include linux/of_irq.h #include at91sam9_wdt.h #define DRV_NAME AT91SAM9 Watchdog -#define wdt_read(field) \ - __raw_readl(at91wdt_private.base + field) -#define wdt_write(field, val) \ - __raw_writel((val), at91wdt_private.base + field) +#define wdt_read(wdt, field) \ + __raw_readl((wdt)-base + (field)) +#define wdt_write(wtd, field, val) \ + __raw_writel((val), (wdt)-base + (field)) /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, * use this to convert a watchdog * value from/to milliseconds. */ -#define ms_to_ticks(t) (((t 8) / 1000) - 1) -#define ticks_to_ms(t) (((t + 1) * 1000) 8) +#define ticks_to_hz_rounddown(t) t) + 1) * HZ) 8) +#define ticks_to_hz_roundup(t) (t) + 1) * HZ) + 255) 8) +#define ticks_to_secs(t) (((t) + 1) 8) +#define secs_to_ticks(s) (((s) 8) - 1) + +#define WDT_MR_RESET 0x3FFF2FFF + +/* Watchdog max counter value in ticks */ +#define WDT_COUNTER_MAX_TICKS 0xFFF + +/* Watchdog max delta/value in secs */ +#define WDT_COUNTER_MAX_SECS ticks_to_secs(WDT_COUNTER_MAX_TICKS) /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 2 @@ -66,23 +79,40 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, Watchdog cannot be stopped once started (default= __MODULE_STRING(WATCHDOG_NOWAYOUT) )); -static struct watchdog_device at91_wdt_dev; -static void at91_ping(unsigned long data); - -static struct { +#define to_wdt(wdd) container_of(wdd, struct at91wdt, wdd) +struct at91wdt { + struct watchdog_device wdd; void __iomem *base; unsigned long next_heartbeat; /* the next_heartbeat for the timer */ struct timer_list timer;/* The timer that pings the watchdog */ -} at91wdt_private; + u32 mr; + u32 mr_mask; + unsigned long heartbeat;/* WDT heartbeat in jiffies */ + bool nowayout; + unsigned int irq; +}; /* . */ +static irqreturn_t wdt_interrupt(int irq, void *dev_id) +{ + struct at91wdt *wdt = (struct at91wdt *)dev_id; + + if (wdt_read(wdt, AT91_WDT_SR)) { + pr_crit(at91sam9 WDT software reset\n); + emergency_restart(); + pr_crit(Reboot didn't ?\n); + } + + return IRQ_HANDLED; +} + /* * Reload the watchdog timer. (ie, pat the watchdog) */ -static inline void at91_wdt_reset(void) +static inline void at91_wdt_reset(struct at91wdt *wdt) { - wdt_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); + wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); } /* @@ -90,26 +120,20 @@ static inline void at91_wdt_reset(void) */ static void at91_ping(unsigned long data) { - if (time_before(jiffies, at91wdt_private.next_heartbeat) || - (!watchdog_active(at91_wdt_dev))) { - at91_wdt_reset(); - mod_timer(at91wdt_private.timer
Re: [PATCH 1/4] watchdog: at91sam9_wdt: better watchdog support
On 03/10/2013 19:55, boris brezillon wrote: Hi Guenter, On 03/10/2013 19:31, Guenter Roeck wrote: On Thu, Oct 03, 2013 at 02:19:18PM +0200, Boris BREZILLON wrote: The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Hi Boris, deeper dive this time ... --- drivers/watchdog/at91sam9_wdt.c | 300 --- 1 file changed, 217 insertions(+), 83 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index be37dde..8f44528 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -19,11 +19,13 @@ #include linux/errno.h #include linux/init.h +#include linux/interrupt.h #include linux/io.h #include linux/kernel.h #include linux/module.h #include linux/moduleparam.h #include linux/platform_device.h +#include linux/reboot.h #include linux/types.h #include linux/watchdog.h #include linux/jiffies.h @@ -31,22 +33,33 @@ #include linux/bitops.h #include linux/uaccess.h #include linux/of.h +#include linux/of_irq.h #include at91sam9_wdt.h #define DRV_NAME AT91SAM9 Watchdog -#define wdt_read(field) \ -__raw_readl(at91wdt_private.base + field) -#define wdt_write(field, val) \ -__raw_writel((val), at91wdt_private.base + field) +#define wdt_read(wdt, field) \ +__raw_readl((wdt)-base + (field)) +#define wdt_write(wtd, field, val) \ +__raw_writel((val), (wdt)-base + (field)) /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, * use this to convert a watchdog * value from/to milliseconds. */ -#define ms_to_ticks(t)(((t 8) / 1000) - 1) -#define ticks_to_ms(t)(((t + 1) * 1000) 8) +#define ticks_to_hz_rounddown(t)t) + 1) * HZ) 8) +#define ticks_to_hz_roundup(t)(t) + 1) * HZ) + 255) 8) +#define ticks_to_secs(t)(((t) + 1) 8) +#define secs_to_ticks(s)(((s) 8) - 1) + +#define WDT_MR_RESET0x3FFF2FFF + +/* Watchdog max counter value in ticks */ +#define WDT_COUNTER_MAX_TICKS0xFFF + +/* Watchdog max delta/value in secs */ +#define WDT_COUNTER_MAX_SECSticks_to_secs(WDT_COUNTER_MAX_TICKS) /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 2 @@ -66,23 +79,40 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, Watchdog cannot be stopped once started (default= __MODULE_STRING(WATCHDOG_NOWAYOUT) )); -static struct watchdog_device at91_wdt_dev; -static void at91_ping(unsigned long data); - -static struct { +#define to_wdt(wdd) container_of(wdd, struct at91wdt, wdd) +struct at91wdt { +struct watchdog_device wdd; void __iomem *base; unsigned long next_heartbeat;/* the next_heartbeat for the timer */ struct timer_list timer;/* The timer that pings the watchdog */ -} at91wdt_private; +u32 mr; +u32 mr_mask; +unsigned long heartbeat;/* WDT heartbeat in jiffies */ +bool nowayout; +unsigned int irq; +}; /* . */ +static irqreturn_t wdt_interrupt(int irq, void *dev_id) +{ +struct at91wdt *wdt = (struct at91wdt *)dev_id; + +if (wdt_read(wdt, AT91_WDT_SR)) { +pr_crit(at91sam9 WDT software reset\n); +emergency_restart(); +pr_crit(Reboot didn't ?\n); +} + +return IRQ_HANDLED; +} + /* * Reload the watchdog timer. (ie, pat the watchdog) */ -static inline void at91_wdt_reset(void) +static inline void at91_wdt_reset(struct at91wdt *wdt) { -wdt_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); +wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); } /* @@ -90,26 +120,20 @@ static inline void at91_wdt_reset(void) */ static void at91_ping(unsigned long data) { -if (time_before(jiffies, at91wdt_private.next_heartbeat) || -(!watchdog_active(at91_wdt_dev))) { -at91_wdt_reset(); -mod_timer(at91wdt_private.timer, jiffies + WDT_TIMEOUT); +struct at91wdt *wdt = (struct at91wdt *)data; +if (time_before(jiffies, wdt
[PATCH v4 0/4] watchdog: at91sam9_wdt: handle already configured wdt
Hello, This patch series is a porposal to enhance the sam9 watchdog timer support. The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. I'm not sure this is the best solution, so please tell me if you prefer to keep static instance of watchdog. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Best Regards, Boris Changes since v3: - fix a bug in heartbeat time computation - fix a bug in at91_wdt_set_timeout when new timeout is bigger than the old one - rename at91_wdt_ping into at91_wdt_start - remove unneeded ping callback assignment Changes since v2: - fix documentation - rework the heartbeat computation to get a more flexible behaviour - fix xx_to_yy macros - modify warning and error messages - remove unneeded parenthesis in arithmetic operations - use devm functions to map io memory - remove unneeded devm_kfree calls Change since v1: - fix typo in documentaion - fix irq dt definition for sama5d3 SoC Boris BREZILLON (4): watchdog: at91sam9_wdt: better watchdog support watchdog: at91sam9_wdt: update device tree doc ARM: at91/dt: add sam9 watchdog default options to SoCs ARM: at91/dt: add watchdog properties to kizbox board .../devicetree/bindings/watchdog/atmel-wdt.txt | 30 +- arch/arm/boot/dts/at91sam9260.dtsi |5 + arch/arm/boot/dts/at91sam9263.dtsi |5 + arch/arm/boot/dts/at91sam9g45.dtsi |5 + arch/arm/boot/dts/at91sam9n12.dtsi |5 + arch/arm/boot/dts/at91sam9x5.dtsi |5 + arch/arm/boot/dts/kizbox.dts |6 + arch/arm/boot/dts/sama5d3.dtsi |5 + drivers/watchdog/at91sam9_wdt.c| 305 ++-- 9 files changed, 285 insertions(+), 86 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 1/4] watchdog: at91sam9_wdt: better watchdog support
The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/watchdog/at91sam9_wdt.c | 305 --- 1 file changed, 221 insertions(+), 84 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index be37dde..85760ab 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -19,11 +19,13 @@ #include linux/errno.h #include linux/init.h +#include linux/interrupt.h #include linux/io.h #include linux/kernel.h #include linux/module.h #include linux/moduleparam.h #include linux/platform_device.h +#include linux/reboot.h #include linux/types.h #include linux/watchdog.h #include linux/jiffies.h @@ -31,22 +33,33 @@ #include linux/bitops.h #include linux/uaccess.h #include linux/of.h +#include linux/of_irq.h #include at91sam9_wdt.h #define DRV_NAME AT91SAM9 Watchdog -#define wdt_read(field) \ - __raw_readl(at91wdt_private.base + field) -#define wdt_write(field, val) \ - __raw_writel((val), at91wdt_private.base + field) +#define wdt_read(wdt, field) \ + __raw_readl((wdt)-base + (field)) +#define wdt_write(wtd, field, val) \ + __raw_writel((val), (wdt)-base + (field)) /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, * use this to convert a watchdog * value from/to milliseconds. */ -#define ms_to_ticks(t) (((t 8) / 1000) - 1) -#define ticks_to_ms(t) (((t + 1) * 1000) 8) +#define ticks_to_hz_rounddown(t) t) + 1) * HZ) 8) +#define ticks_to_hz_roundup(t) (t) + 1) * HZ) + 255) 8) +#define ticks_to_secs(t) (((t) + 1) 8) +#define secs_to_ticks(s) (((s) 8) - 1) + +#define WDT_MR_RESET 0x3FFF2FFF + +/* Watchdog max counter value in ticks */ +#define WDT_COUNTER_MAX_TICKS 0xFFF + +/* Watchdog max delta/value in secs */ +#define WDT_COUNTER_MAX_SECS ticks_to_secs(WDT_COUNTER_MAX_TICKS) /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 2 @@ -66,23 +79,40 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, Watchdog cannot be stopped once started (default= __MODULE_STRING(WATCHDOG_NOWAYOUT) )); -static struct watchdog_device at91_wdt_dev; -static void at91_ping(unsigned long data); - -static struct { +#define to_wdt(wdd) container_of(wdd, struct at91wdt, wdd) +struct at91wdt { + struct watchdog_device wdd; void __iomem *base; unsigned long next_heartbeat; /* the next_heartbeat for the timer */ struct timer_list timer;/* The timer that pings the watchdog */ -} at91wdt_private; + u32 mr; + u32 mr_mask; + unsigned long heartbeat;/* WDT heartbeat in jiffies */ + bool nowayout; + unsigned int irq; +}; /* . */ +static irqreturn_t wdt_interrupt(int irq, void *dev_id) +{ + struct at91wdt *wdt = (struct at91wdt *)dev_id; + + if (wdt_read(wdt, AT91_WDT_SR)) { + pr_crit(at91sam9 WDT software reset\n); + emergency_restart(); + pr_crit(Reboot didn't ?\n); + } + + return IRQ_HANDLED; +} + /* * Reload the watchdog timer. (ie, pat the watchdog) */ -static inline void at91_wdt_reset(void) +static inline void at91_wdt_reset(struct at91wdt *wdt) { - wdt_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); + wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); } /* @@ -90,26 +120,20 @@ static inline void at91_wdt_reset(void) */ static void at91_ping(unsigned long data) { - if (time_before(jiffies, at91wdt_private.next_heartbeat) || - (!watchdog_active(at91_wdt_dev))) { - at91_wdt_reset(); - mod_timer(at91wdt_private.timer, jiffies + WDT_TIMEOUT); + struct at91wdt *wdt = (struct at91wdt *)data; + if (time_before(jiffies, wdt-next_heartbeat) || + !watchdog_active(wdt-wdd)) { + at91_wdt_reset(wdt
[PATCH v4 2/4] watchdog: at91sam9_wdt: update device tree doc
Add new at91sam9 watchdog properties to the documentation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- .../devicetree/bindings/watchdog/atmel-wdt.txt | 30 ++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt index fcdd48f..f90e294 100644 --- a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt @@ -9,11 +9,37 @@ Required properties: Optional properties: - timeout-sec: contains the watchdog timeout in seconds. +- interrupts : Should contain WDT interrupt. +- atmel,max-heartbeat-sec : Should contain the maximum heartbeat value in + seconds. This value should be less or equal to 16. It is used to + compute the WDV field. +- atmel,min-heartbeat-sec : Should contain the minimum heartbeat value in + seconds. This value must be smaller than the max-heartbeat-sec value. + It is used to compute the WDD field. +- atmel,watchdog-type : Should be hardware or software. Hardware watchdog + use the at91 watchdog reset. Software watchdog use the watchdog + interrupt to trigger a software reset. +- atmel,reset-type : Should be proc or all. + all : assert peripherals and processor reset signals + proc : assert the processor reset signal + This is valid only when using hardware watchdog. +- atmel,disable : Should be present if you want to disable the watchdog. +- atmel,idle-halt : Should be present if you want to stop the watchdog when + entering idle state. +- atmel,dbg-halt : Should be present if you want to stop the watchdog when + entering debug state. Example: - watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; - timeout-sec = 10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + timeout-sec = 15; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; + atmel,max-heartbeat-sec = 16; + atmel,min-heartbeat-sec = 0; + status = okay; }; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 3/4] ARM: at91/dt: add sam9 watchdog default options to SoCs
Set default watchdog options in every SoC compatible with the sam9 watchdog. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/boot/dts/at91sam9260.dtsi |5 + arch/arm/boot/dts/at91sam9263.dtsi |5 + arch/arm/boot/dts/at91sam9g45.dtsi |5 + arch/arm/boot/dts/at91sam9n12.dtsi |5 + arch/arm/boot/dts/at91sam9x5.dtsi |5 + arch/arm/boot/dts/sama5d3.dtsi |5 + 6 files changed, 30 insertions(+) diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index 56ee828..997901f 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi @@ -648,6 +648,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; }; diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi index d5bd65f..45fb0a4 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/at91sam9263.dtsi @@ -523,6 +523,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index c3e5148..16534c7 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -639,6 +639,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi index 9fb7ffd..eaef94b 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/at91sam9n12.dtsi @@ -537,6 +537,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; }; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index e74dc15..6d31fd7 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -820,6 +820,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index b7f4961..3a17a3e 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -891,6 +891,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 4 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled
[PATCH v4 4/4] ARM: at91/dt: add watchdog properties to kizbox board
Add watchdog specific config for kizbox board. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/boot/dts/kizbox.dts |6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts index 02df191..928f6ee 100644 --- a/arch/arm/boot/dts/kizbox.dts +++ b/arch/arm/boot/dts/kizbox.dts @@ -53,6 +53,12 @@ status = okay; }; + watchdog@fd40 { + timeout-sec = 15; + atmel,max-heartbeat-sec = 16; + atmel,min-heartbeat-sec = 0; + status = okay; + }; }; nand0: nand@4000 { -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v5 1/4] watchdog: at91sam9_wdt: better watchdog support
The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/watchdog/at91sam9_wdt.c | 309 --- 1 file changed, 223 insertions(+), 86 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index be37dde..9bd089e 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -19,11 +19,13 @@ #include linux/errno.h #include linux/init.h +#include linux/interrupt.h #include linux/io.h #include linux/kernel.h #include linux/module.h #include linux/moduleparam.h #include linux/platform_device.h +#include linux/reboot.h #include linux/types.h #include linux/watchdog.h #include linux/jiffies.h @@ -31,22 +33,33 @@ #include linux/bitops.h #include linux/uaccess.h #include linux/of.h +#include linux/of_irq.h #include at91sam9_wdt.h #define DRV_NAME AT91SAM9 Watchdog -#define wdt_read(field) \ - __raw_readl(at91wdt_private.base + field) -#define wdt_write(field, val) \ - __raw_writel((val), at91wdt_private.base + field) +#define wdt_read(wdt, field) \ + __raw_readl((wdt)-base + (field)) +#define wdt_write(wtd, field, val) \ + __raw_writel((val), (wdt)-base + (field)) /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, * use this to convert a watchdog * value from/to milliseconds. */ -#define ms_to_ticks(t) (((t 8) / 1000) - 1) -#define ticks_to_ms(t) (((t + 1) * 1000) 8) +#define ticks_to_hz_rounddown(t) t) + 1) * HZ) 8) +#define ticks_to_hz_roundup(t) (t) + 1) * HZ) + 255) 8) +#define ticks_to_secs(t) (((t) + 1) 8) +#define secs_to_ticks(s) (((s) 8) - 1) + +#define WDT_MR_RESET 0x3FFF2FFF + +/* Watchdog max counter value in ticks */ +#define WDT_COUNTER_MAX_TICKS 0xFFF + +/* Watchdog max delta/value in secs */ +#define WDT_COUNTER_MAX_SECS ticks_to_secs(WDT_COUNTER_MAX_TICKS) /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 2 @@ -66,23 +79,40 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, Watchdog cannot be stopped once started (default= __MODULE_STRING(WATCHDOG_NOWAYOUT) )); -static struct watchdog_device at91_wdt_dev; -static void at91_ping(unsigned long data); - -static struct { +#define to_wdt(wdd) container_of(wdd, struct at91wdt, wdd) +struct at91wdt { + struct watchdog_device wdd; void __iomem *base; unsigned long next_heartbeat; /* the next_heartbeat for the timer */ struct timer_list timer;/* The timer that pings the watchdog */ -} at91wdt_private; + u32 mr; + u32 mr_mask; + unsigned long heartbeat;/* WDT heartbeat in jiffies */ + bool nowayout; + unsigned int irq; +}; /* . */ +static irqreturn_t wdt_interrupt(int irq, void *dev_id) +{ + struct at91wdt *wdt = (struct at91wdt *)dev_id; + + if (wdt_read(wdt, AT91_WDT_SR)) { + pr_crit(at91sam9 WDT software reset\n); + emergency_restart(); + pr_crit(Reboot didn't ?\n); + } + + return IRQ_HANDLED; +} + /* * Reload the watchdog timer. (ie, pat the watchdog) */ -static inline void at91_wdt_reset(void) +static inline void at91_wdt_reset(struct at91wdt *wdt) { - wdt_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); + wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); } /* @@ -90,26 +120,21 @@ static inline void at91_wdt_reset(void) */ static void at91_ping(unsigned long data) { - if (time_before(jiffies, at91wdt_private.next_heartbeat) || - (!watchdog_active(at91_wdt_dev))) { - at91_wdt_reset(); - mod_timer(at91wdt_private.timer, jiffies + WDT_TIMEOUT); - } else + struct at91wdt *wdt = (struct at91wdt *)data; + if (time_before(jiffies, wdt-next_heartbeat) || + !watchdog_active(wdt-wdd)) { + at91_wdt_reset
[PATCH v5 2/4] watchdog: at91sam9_wdt: update device tree doc
Add new at91sam9 watchdog properties to the documentation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- .../devicetree/bindings/watchdog/atmel-wdt.txt | 30 ++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt index fcdd48f..f90e294 100644 --- a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt @@ -9,11 +9,37 @@ Required properties: Optional properties: - timeout-sec: contains the watchdog timeout in seconds. +- interrupts : Should contain WDT interrupt. +- atmel,max-heartbeat-sec : Should contain the maximum heartbeat value in + seconds. This value should be less or equal to 16. It is used to + compute the WDV field. +- atmel,min-heartbeat-sec : Should contain the minimum heartbeat value in + seconds. This value must be smaller than the max-heartbeat-sec value. + It is used to compute the WDD field. +- atmel,watchdog-type : Should be hardware or software. Hardware watchdog + use the at91 watchdog reset. Software watchdog use the watchdog + interrupt to trigger a software reset. +- atmel,reset-type : Should be proc or all. + all : assert peripherals and processor reset signals + proc : assert the processor reset signal + This is valid only when using hardware watchdog. +- atmel,disable : Should be present if you want to disable the watchdog. +- atmel,idle-halt : Should be present if you want to stop the watchdog when + entering idle state. +- atmel,dbg-halt : Should be present if you want to stop the watchdog when + entering debug state. Example: - watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; - timeout-sec = 10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + timeout-sec = 15; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; + atmel,max-heartbeat-sec = 16; + atmel,min-heartbeat-sec = 0; + status = okay; }; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v5 3/4] ARM: at91/dt: add sam9 watchdog default options to SoCs
Set default watchdog options in every SoC compatible with the sam9 watchdog. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/boot/dts/at91sam9260.dtsi |5 + arch/arm/boot/dts/at91sam9263.dtsi |5 + arch/arm/boot/dts/at91sam9g45.dtsi |5 + arch/arm/boot/dts/at91sam9n12.dtsi |5 + arch/arm/boot/dts/at91sam9x5.dtsi |5 + arch/arm/boot/dts/sama5d3.dtsi |5 + 6 files changed, 30 insertions(+) diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index 56ee828..997901f 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi @@ -648,6 +648,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; }; diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi index d5bd65f..45fb0a4 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/at91sam9263.dtsi @@ -523,6 +523,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index c3e5148..16534c7 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -639,6 +639,11 @@ watchdog@fd40 { compatible = atmel,at91sam9260-wdt; reg = 0xfd40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi index 9fb7ffd..eaef94b 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/at91sam9n12.dtsi @@ -537,6 +537,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; }; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index e74dc15..6d31fd7 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -820,6 +820,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 1 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled; }; diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index b7f4961..3a17a3e 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -891,6 +891,11 @@ watchdog@fe40 { compatible = atmel,at91sam9260-wdt; reg = 0xfe40 0x10; + interrupts = 4 IRQ_TYPE_LEVEL_HIGH 7; + atmel,watchdog-type = hardware; + atmel,reset-type = all; + atmel,dbg-halt; + atmel,idle-halt; status = disabled
[PATCH v5 4/4] ARM: at91/dt: add watchdog properties to kizbox board
Add watchdog specific config for kizbox board. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/boot/dts/kizbox.dts |6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts index 02df191..928f6ee 100644 --- a/arch/arm/boot/dts/kizbox.dts +++ b/arch/arm/boot/dts/kizbox.dts @@ -53,6 +53,12 @@ status = okay; }; + watchdog@fd40 { + timeout-sec = 15; + atmel,max-heartbeat-sec = 16; + atmel,min-heartbeat-sec = 0; + status = okay; + }; }; nand0: nand@4000 { -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v5 0/4] watchdog: at91sam9_wdt: handle already configured wdt
Hello, This patch series is a porposal to enhance the sam9 watchdog timer support. The at91sam9 watchdog timer can only be configured once, and the current implementation tries to configure it in a static way: - 2 seconds timeout - wdt restart every 500ms If the timer has already been configured with different values, it returns an error and do not create any watchdog device. This is not critical if the watchdog is disabled, but if it has been enabled with different timeout values it will lead to a SoC reset. This patch series tries to address this issue by adapting the heartbeat value according the WDT timer config: - it first tries to configure the timer as requested. - if it fails it fallbacks to the current config, adapting its heartbeat timer to the needs This patch series also move to a dynamically allocated at91wdt device instead of the static instance. I'm not sure this is the best solution, so please tell me if you prefer to keep static instance of watchdog. It adds a new at91 wdt type: software. This new type make use of the at91 wdt interrupt to trigger a software reboot. Finally it adds several properties to the device tree bindings. Best Regards, Boris Changes since v4: - fix coding style issues - remove unneeded watchdog_active test Changes since v3: - fix a bug in heartbeat time computation - fix a bug in at91_wdt_set_timeout when new timeout is bigger than the old one - rename at91_wdt_ping into at91_wdt_start - remove unneeded ping callback assignment Changes since v2: - fix documentation - rework the heartbeat computation to get a more flexible behaviour - fix xx_to_yy macros - modify warning and error messages - remove unneeded parenthesis in arithmetic operations - use devm functions to map io memory - remove unneeded devm_kfree calls Change since v1: - fix typo in documentaion - fix irq dt definition for sama5d3 SoC Boris BREZILLON (4): watchdog: at91sam9_wdt: better watchdog support watchdog: at91sam9_wdt: update device tree doc ARM: at91/dt: add sam9 watchdog default options to SoCs ARM: at91/dt: add watchdog properties to kizbox board .../devicetree/bindings/watchdog/atmel-wdt.txt | 30 +- arch/arm/boot/dts/at91sam9260.dtsi |5 + arch/arm/boot/dts/at91sam9263.dtsi |5 + arch/arm/boot/dts/at91sam9g45.dtsi |5 + arch/arm/boot/dts/at91sam9n12.dtsi |5 + arch/arm/boot/dts/at91sam9x5.dtsi |5 + arch/arm/boot/dts/kizbox.dts |6 + arch/arm/boot/dts/sama5d3.dtsi |5 + drivers/watchdog/at91sam9_wdt.c| 309 ++-- 9 files changed, 287 insertions(+), 88 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC PATCH alt 4/4] pinctrl: at91: rework debounce configuration
Hello Stephen, Le 14/09/2013 00:40, Stephen Warren a écrit : On 09/13/2013 01:53 AM, Boris BREZILLON wrote: AT91 SoCs do not support per pin debounce time configuration. Instead you have to configure a debounce time which will be used for all pins of a given bank (PIOA, PIOB, ...). diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt +Optional properties for iomux controller: +- atmel,default-debounce-div: array of debounce divisors (one divisor per bank) + which describes the debounce timing in use for all pins of a given bank + configured with the DEBOUNCE option (see the following description). + Debounce timing is obtained with this formula: + Tdebounce = 2 * (debouncediv + 1) / Fslowclk + with Fslowclk = 32KHz + Required properties for pin configuration node: - atmel,pins: 4 integers array, represents a group of pins mux and config setting. The format is atmel,pins = PIN_BANK PIN_BANK_NUM PERIPH CONFIG. @@ -91,7 +99,6 @@ DEGLITCH (1 2): indicate this pin need deglitch. PULL_DOWN (1 3): indicate this pin need a pull down. DIS_SCHMIT(1 4): indicate this pin need to disable schmit trigger. DEBOUNCE (1 16): indicate this pin need debounce. -DEBOUNCE_VAL (0x3fff 17): debounce val. This change would break the DT ABI since it removes a feature that's already present. I missed this point in my cons list. This won't be an issue for in kernel DT definitions (nobody is currently using the DEBOUCE option), but may be for out-of-tree DT definitions. I suppose it's still up to the Atmel maintainers to decide whether this is appropriate, or whether the impact to out-of-tree DT files would be problematic. Assuming the DT ABI can be broken, I think I'd prefer to do so, rather than take non-alt patch 4/4, since a per-pin DEBOUNCE_VAL clearly doesn't correctly model the HW, assuming the patch description is correct. I don't think arguments re: the generic pinconf debounce property hold; if the Linux-specific/internal generic property doesn't apply, the DT binding should not be bent to adjust to it, but should rather still represent the HW itself. What about the last point in my list: reconfigure debounce after startup ? Here is an example that may be problematic: Let's say you have one device using multiple configuration of pins (default, xxx, yyy). The default config needs a particular debounce time on a given pin and the xxx and yyy configs need different debounce time on the same pin. How would you solve this with this patch approach ? Best Regards, Boris -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC PATCH alt 4/4] pinctrl: at91: rework debounce configuration
Hello Jean-Christophe, Le 14/09/2013 18:37, Jean-Christophe PLAGNIOL-VILLARD a écrit : On 09:53 Fri 13 Sep , Boris BREZILLON wrote: AT91 SoCs do not support per pin debounce time configuration. Instead you have to configure a debounce time which will be used for all pins of a given bank (PIOA, PIOB, ...). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- .../bindings/pinctrl/atmel,at91-pinctrl.txt|9 ++- drivers/pinctrl/pinctrl-at91.c | 79 include/dt-bindings/pinctrl/at91.h |1 - 3 files changed, 73 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt index cf7c7bc..8a4cdeb 100644 --- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt @@ -78,6 +78,14 @@ PA31 TXD4 = 0xffc00c3b +Optional properties for iomux controller: +- atmel,default-debounce-div: array of debounce divisors (one divisor per bank) + which describes the debounce timing in use for all pins of a given bank + configured with the DEBOUNCE option (see the following description). + Debounce timing is obtained with this formula: + Tdebounce = 2 * (debouncediv + 1) / Fslowclk + with Fslowclk = 32KHz I known that I put the div in the original binding but maybe we should just put the debounce timing in the DT and calculate the div in C Sure, I can do this: retrieve a debounce time (in usec ?) and compute the according div value. + Required properties for pin configuration node: - atmel,pins: 4 integers array, represents a group of pins mux and config setting. The format is atmel,pins = PIN_BANK PIN_BANK_NUM PERIPH CONFIG. @@ -91,7 +99,6 @@ DEGLITCH (1 2): indicate this pin need deglitch. PULL_DOWN (1 3): indicate this pin need a pull down. DIS_SCHMIT(1 4): indicate this pin need to disable schmit trigger. DEBOUNCE (1 16): indicate this pin need debounce. -DEBOUNCE_VAL (0x3fff 17): debounce val. NOTE: Some requirements for using atmel,at91rm9200-pinctrl binding: diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index ac9dbea..2903758 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -62,8 +62,6 @@ static int gpio_banks; #define PULL_DOWN (1 3) #define DIS_SCHMIT(1 4) #define DEBOUNCE (1 16) -#define DEBOUNCE_VAL_SHIFT 17 -#define DEBOUNCE_VAL (0x3fff DEBOUNCE_VAL_SHIFT) /** * struct at91_pmx_func - describes AT91 pinmux functions @@ -145,8 +143,10 @@ struct at91_pinctrl_mux_ops { void (*mux_D_periph)(void __iomem *pio, unsigned mask); bool (*get_deglitch)(void __iomem *pio, unsigned pin); void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on); - bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div); - void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div); + bool (*get_debounce)(void __iomem *pio, unsigned pin); + void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on); + u32 (*get_debounce_div)(void __iomem *pio); + void (*set_debounce_div)(void __iomem *pio, u32 div); why do you split it? if it's just get if on or not put NULL to div but do not add more function pointer I not sure I got your point. Are you suggesting we should store the default bank bebounce div values in struct at91_pinctrl (during probe process) and pass these values each time the set_debounce function is called ? IMHO if we split the logic (split debounce activation and debounce time definition) we should split these callbacks: - one callback to enable debounce option on a given pin - one callback to configure the debounce time for a given bank If you keep the div parameter in the debounce enable/disable callback you will reconfigure the div register (PIO_SCDR_DIV) each time you enable the debounce option, which is kind of useless because the div value will never change. bool (*get_pulldown)(void __iomem *pio, unsigned pin); void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on); bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin); @@ -432,25 +432,32 @@ static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is at91_mux_set_deglitch(pio, mask, is_on); } -static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div) +static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin) { - *div = __raw_readl(pio + PIO_SCDR); - return ((__raw_readl(pio + PIO_IFSR) pin) 0x1) ((__raw_readl(pio + PIO_IFSCSR) pin) 0x1); } static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask, - bool is_on, u32 div
Re: [RFC PATCH alt 4/4] pinctrl: at91: rework debounce configuration
Hello Stephen, On 16/09/2013 18:41, Stephen Warren wrote: On 09/14/2013 01:08 AM, boris brezillon wrote: Hello Stephen, Le 14/09/2013 00:40, Stephen Warren a écrit : On 09/13/2013 01:53 AM, Boris BREZILLON wrote: AT91 SoCs do not support per pin debounce time configuration. Instead you have to configure a debounce time which will be used for all pins of a given bank (PIOA, PIOB, ...). ... Required properties for pin configuration node: ... -DEBOUNCE_VAL(0x3fff 17): debounce val. This change would break the DT ABI since it removes a feature that's already present. ... I suppose it's still up to the Atmel maintainers to decide whether this is appropriate, or whether the impact to out-of-tree DT files would be problematic. Assuming the DT ABI can be broken, I think I'd prefer to do so, rather than take non-alt patch 4/4, since a per-pin DEBOUNCE_VAL clearly doesn't correctly model the HW, assuming the patch description is correct. I don't think arguments re: the generic pinconf debounce property hold; if the Linux-specific/internal generic property doesn't apply, the DT binding should not be bent to adjust to it, but should rather still represent the HW itself. What about the last point in my list: reconfigure debounce after startup ? Here is an example that may be problematic: Let's say you have one device using multiple configuration of pins (default, xxx, yyy). The default config needs a particular debounce time on a given pin and the xxx and yyy configs need different debounce time on the same pin. How would you solve this with this patch approach ? Each state has a different pin configuration node, and hence can specify a different debounce value. This patch has no impact on that (it just changes whether the state-specific node specifies the debounce value in a single standalone property, or encodes it into each entry in the pins property, all within the same node). Actually it does: this patch removes the debounce time setting option from the pin config description. The only thing you can do is enable or disable the debounce filter. The atmel,default-debounce-div property is not part of the pin group (or pin state) node, it is a global property you define for the whole pinctrl controller (pinctrl node property): pinctrl { atmel,default-debounce-div=100 /* PIOA div = ~3 ms */ 50 /* PIOB div */ ...; function { group { atmel,pins=...; }; }; }; I can get the debounce time option in a separate property (as you're suggesting): pinctrl { function { group { atmel,debounce=1000; /* debounce in usec */ atmel,pins=...; }; }; }; but it won't solve the primary issue, that is all the pin on a given bank (PIOA1 PIOA2, ...) share the same debounce time. Please tell me if I misunderstood your suggestion. Best Regards, Boris -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/2] pwm: atmel-tcb: config fixes
Hello, This patch series fix 2 bugs regarding the pwm configuration: - the clock source of the timer channel is never applied - the maximum time that can be represented when using the slow clock may be wrong if the tc block provide a 32 bits width counter Best Regards, Boris Boris BREZILLON (2): pwm: atmel-tcb: add missing clk source config pwm: atmel-tcb: fix max time computation for slow clk source drivers/pwm/pwm-atmel-tcb.c |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] pwm: atmel-tcb: fix max time computation for slow clk source
Use the the tcb counter width to compute the maximum time that can be represented using the slow clock source instead of the static 16 bit width. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/pwm/pwm-atmel-tcb.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 0266969..f3dcd02 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -307,7 +307,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, i = slowclk; rate = 32768; min = div_u64(NSEC_PER_SEC, rate); - max = min 16; + max = min tc-tcb_config-counter_width; /* If period is too big return ERANGE error */ if (max period_ns) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] pwm: atmel-tcb: add missing clk source config
Clock source changes are never applied to the CMR register. This may lead to wrong period/duty cycle configuration. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/pwm/pwm-atmel-tcb.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index ba6ce01..0266969 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -249,6 +249,8 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) } } + cmr |= (tcbpwm-div ATMEL_TC_TCCLKS); + __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR)); if (index == 0) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/2] pwm: atmel-tcb: config fixes
On 19/09/2013 14:06, Thierry Reding wrote: On Wed, Sep 18, 2013 at 05:05:20PM +0200, Boris BREZILLON wrote: Hello, This patch series fix 2 bugs regarding the pwm configuration: - the clock source of the timer channel is never applied - the maximum time that can be represented when using the slow clock may be wrong if the tc block provide a 32 bits width counter Best Regards, Boris Boris BREZILLON (2): pwm: atmel-tcb: add missing clk source config pwm: atmel-tcb: fix max time computation for slow clk source drivers/pwm/pwm-atmel-tcb.c |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) Both applied, with Nicolas' Acked-by. Thierry Thanks. Regards, Boris -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v5 13/17] clk: at91: add PMC usb clock
This patch adds new at91 usb clock implementation using common clk framework. This clock is used to clock usb ports (ohci, ehci and udc). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig | 11 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-usb.c | 400 drivers/clk/at91/pmc.c | 15 ++ drivers/clk/at91/pmc.h |9 + 5 files changed, 436 insertions(+) create mode 100644 drivers/clk/at91/clk-usb.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 6ad37da..b76dc4c 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -3,6 +3,9 @@ if ARCH_AT91 config HAVE_AT91_UTMI bool +config HAVE_AT91_USB_CLK + bool + config HAVE_AT91_DBGU0 bool @@ -82,6 +85,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -96,12 +100,14 @@ config SOC_AT91RM9200 select MULTI_IRQ_HANDLER select SPARSE_IRQ select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9260 bool AT91SAM9260, AT91SAM9XE or AT91SAM9G20 select HAVE_AT91_DBGU0 select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE or AT91SAM9G20 SoC. @@ -112,6 +118,7 @@ config SOC_AT91SAM9261 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. @@ -121,6 +128,7 @@ config SOC_AT91SAM9263 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9RL bool AT91SAM9RL @@ -137,6 +145,7 @@ config SOC_AT91SAM9G45 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -148,6 +157,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is @@ -161,6 +171,7 @@ config SOC_AT91SAM9N12 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using Atmel's AT91SAM9N12 SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index a824883..61db058 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -8,3 +8,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o +obj-$(CONFIG_HAVE_AT91_USB_CLK)+= clk-usb.o diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c new file mode 100644 index 000..0454555 --- /dev/null +++ b/drivers/clk/at91/clk-usb.c @@ -0,0 +1,400 @@ +/* + * drivers/clk/at91/clk-usb.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define USB_SOURCE_MAX 2 + +#define SAM9X5_USB_DIV_SHIFT 8 +#define SAM9X5_USB_MAX_DIV 0xf + +#define RM9200_USB_DIV_SHIFT 28 +#define RM9200_USB_DIV_TAB_SIZE4 + +struct at91sam9x5_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_usb(hw) \ + container_of(hw, struct at91sam9x5_clk_usb, hw) + +struct at91rm9200_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 divisors[4]; +}; + +#define to_at91rm9200_clk_usb(hw) \ + container_of(hw, struct at91rm9200_clk_usb, hw) + +static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 usbdiv; + struct
Re: [PATCH] USB: ehci-atmel: add usb_clk for transition to CCF
Hello Nicolas, This patch should fix the bug you were seeing with USB device enumaration after moving to CCF. Tell me if this solves the issue (it worked for me). Best Regards, Boris On 18/10/2013 21:26, Boris BREZILLON wrote: The AT91 PMC (Power Management Controller) provides a USB clock used by the different USB controllers (ehci, ohci and udc). The atmel-ehci driver must configure the usb clock rate to 48Mhz in order to get a fully functionnal USB host controller. This configuration was formely done in mach-at91/clock.c, but will be bypassed when moving to common clk framework. This patch adds support for usb clock retrieval and configuration only if CCF is enabled (CONFIG_COMMON_CLK). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/usb/host/ehci-atmel.c | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 3b645ff..f417526 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -30,13 +30,17 @@ static const char hcd_name[] = ehci-atmel; static struct hc_driver __read_mostly ehci_atmel_hc_driver; /* interface and function clocks */ -static struct clk *iclk, *fclk; +static struct clk *iclk, *fclk, *uclk; static int clocked; /*-*/ static void atmel_start_clock(void) { + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + clk_set_rate(uclk, 4800); + clk_prepare_enable(uclk); + } clk_prepare_enable(iclk); clk_prepare_enable(fclk); clocked = 1; @@ -46,6 +50,8 @@ static void atmel_stop_clock(void) { clk_disable_unprepare(fclk); clk_disable_unprepare(iclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_disable_unprepare(uclk); clocked = 0; } @@ -130,6 +136,14 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) retval = -ENOENT; goto fail_request_resource; } + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + uclk = devm_clk_get(pdev-dev, usb_clk); + if (IS_ERR(uclk)) { + dev_err(pdev-dev, failed to get uclk\n); + retval = PTR_ERR(uclk); + goto fail_request_resource; + } + } ehci = hcd_to_ehci(hcd); /* registers start at offset 0x0 */ -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] USB: ehci-atmel: add usb_clk for transition to CCF
The AT91 PMC (Power Management Controller) provides a USB clock used by the different USB controllers (ehci, ohci and udc). The atmel-ehci driver must configure the usb clock rate to 48Mhz in order to get a fully functionnal USB host controller. This configuration was formely done in mach-at91/clock.c, but will be bypassed when moving to common clk framework. This patch adds support for usb clock retrieval and configuration only if CCF is enabled (CONFIG_COMMON_CLK). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- drivers/usb/host/ehci-atmel.c | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 3b645ff..f417526 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -30,13 +30,17 @@ static const char hcd_name[] = ehci-atmel; static struct hc_driver __read_mostly ehci_atmel_hc_driver; /* interface and function clocks */ -static struct clk *iclk, *fclk; +static struct clk *iclk, *fclk, *uclk; static int clocked; /*-*/ static void atmel_start_clock(void) { + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + clk_set_rate(uclk, 4800); + clk_prepare_enable(uclk); + } clk_prepare_enable(iclk); clk_prepare_enable(fclk); clocked = 1; @@ -46,6 +50,8 @@ static void atmel_stop_clock(void) { clk_disable_unprepare(fclk); clk_disable_unprepare(iclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_disable_unprepare(uclk); clocked = 0; } @@ -130,6 +136,14 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) retval = -ENOENT; goto fail_request_resource; } + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + uclk = devm_clk_get(pdev-dev, usb_clk); + if (IS_ERR(uclk)) { + dev_err(pdev-dev, failed to get uclk\n); + retval = PTR_ERR(uclk); + goto fail_request_resource; + } + } ehci = hcd_to_ehci(hcd); /* registers start at offset 0x0 */ -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 4/7] ARM: at91/dt: define sama5d3 clocks
Define sama5d3 clocks in sama5d3 device tree. Add references to the appropriate clocks in each peripheral. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- Changes since v2: - add usb_clk to usb ehci controller node This new version (and the associated patch USB: ehci-atmel: add usb_clk for transition to CCF) fixes a bug in ehci clk initialization. arch/arm/boot/dts/sama5d3.dtsi | 331 ++- arch/arm/boot/dts/sama5d3_can.dtsi | 18 ++ arch/arm/boot/dts/sama5d3_emac.dtsi | 10 ++ arch/arm/boot/dts/sama5d3_gmac.dtsi | 10 ++ arch/arm/boot/dts/sama5d3_lcd.dtsi | 15 ++ arch/arm/boot/dts/sama5d3_mci2.dtsi | 11 ++ arch/arm/boot/dts/sama5d3_tcb1.dtsi | 12 ++ arch/arm/boot/dts/sama5d3_uart.dtsi | 19 ++ 8 files changed, 425 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 5cdaba4..20a6e4e 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -13,6 +13,7 @@ #include dt-bindings/pinctrl/at91.h #include dt-bindings/interrupt-controller/irq.h #include dt-bindings/gpio/gpio.h +#include dt-bindings/clk/at91.h / { model = Atmel SAMA5D3 family SoC; @@ -56,6 +57,14 @@ reg = 0x2000 0x800; }; + clocks { + adc_op_clk: adc_op_clk{ + compatible = fixed-clock; + #clock-cells = 0; + clock-frequency = 2000; + }; + }; + ahb { compatible = simple-bus; #address-cells = 1; @@ -79,6 +88,8 @@ status = disabled; #address-cells = 1; #size-cells = 0; + clocks = periph 21; + clock-names = mci_clk; }; spi0: spi@f0004000 { @@ -92,6 +103,8 @@ dma-names = tx, rx; pinctrl-names = default; pinctrl-0 = pinctrl_spi0; + clocks = periph 24; + clock-names = spi_clk; status = disabled; }; @@ -101,6 +114,8 @@ interrupts = 38 IRQ_TYPE_LEVEL_HIGH 4; pinctrl-names = default; pinctrl-0 = pinctrl_ssc0_tx pinctrl_ssc0_rx; + clocks = periph 38; + clock-names = pclk; status = disabled; }; @@ -108,6 +123,8 @@ compatible = atmel,at91sam9x5-tcb; reg = 0xf001 0x100; interrupts = 26 IRQ_TYPE_LEVEL_HIGH 0; + clocks = periph 26; + clock-names = t0_clk; }; i2c0: i2c@f0014000 { @@ -121,6 +138,7 @@ pinctrl-0 = pinctrl_i2c0; #address-cells = 1; #size-cells = 0; + clocks = periph 18; status = disabled; }; @@ -135,6 +153,7 @@ pinctrl-0 = pinctrl_i2c1; #address-cells = 1; #size-cells = 0; + clocks = periph 19; status = disabled; }; @@ -144,6 +163,8 @@ interrupts = 12 IRQ_TYPE_LEVEL_HIGH 5; pinctrl-names = default; pinctrl-0 = pinctrl_usart0; + clocks = periph 12; + clock-names = usart; status = disabled; }; @@ -153,6 +174,8 @@ interrupts = 13 IRQ_TYPE_LEVEL_HIGH 5; pinctrl-names = default; pinctrl-0 = pinctrl_usart1; + clocks = periph 13; + clock-names = usart; status = disabled; }; @@ -174,6 +197,8 @@ status = disabled; #address-cells = 1; #size-cells = 0; + clocks = periph 22; + clock-names = mci_clk; }; spi1: spi@f8008000 { @@ -187,6 +212,8 @@ dma-names = tx, rx
Re: [PATCH 5/9] ARM: at91/dt: add mmc0 slot0 support to at91rm9200ek board
Hello Linus, Sorry for the noise, my mail was filtered by several ML because of some HTML contents. Le 26/11/2013 14:46, Linus Walleij a écrit : On Thu, Nov 21, 2013 at 11:34 AM, boris brezillon b.brezil...@overkiz.com wrote: On 21/11/2013 10:48, Linus Walleij wrote: No matter whether it's a switch or a GPIO regulator it seems we are in violent agreement that it should not be controlled by the pin control states at least. Start with making it a GPIO then you can figure out whether a GPIO regulator or drivers/extcon/extcon-gpio.c should be used. Thanks for pointing this out. I wasn't aware of the extcon subsystem. Actually, I think it's a little bit more tricky. Hm, yeah extcon is for things like audio jacks on phones that userspace need to detect. drivers/input/keyboard/gpio_keys* is for things that actually input characters to userspace stuff. None of it is applicable here it seems ... The switch connected to gpio PB22 is used to enable one device or the other: - PB22 set to high level enables slot0 of mmc0 (connect mmc signals to the mmc connector) - PB22 set to low level enables the dataflash (connect to the SPI0 signals to the dataflash device) So this is something like a jumper of the old type, configuring the entire system? Something like that: http://www.mignonette-game.com/images/v2/21-arduino-com-jumper.jpg But in this case it is a mechanical switch rather than a jumper? Not exactly. The functionnaly selection (spi device or mmc slot) is done by the software using to the PB22 pin: - set PB22 pin to 1 if you want to enable the mmc slot - set PB22 pin to 0 if you want to enable the spi device This is the rm9200ek board datasheet http://www.alliedelec.com/images/products/datasheets/bm/ATMEL/70123901.pdf, and you'll find the switch schematic at page 26. Here is the switch datasheet : http://pdf1.alldatasheet.fr/datasheet-pdf/view/90971/PERICOM/PI5A100Q.html If I understand correctly, you're suggesting to retrieve the PB22 pin value to decide wether the mmc slot or the spi device is enabled. Is that right ? In this case the bootstrap and/or bootloader would have to properly configure the P22 pin before executing the linux kernel, and I'm pretty sure this is not the case. This is not much different from the GPIOs people use to e.g. encode the board type, just that it can change. Do people switch this thing at runtime? In the board version this was configured in the init_machine function (or board init function) depending on the MTD_AT91_DATAFLASH_CARD ( http://lxr.free-electrons.com/source/arch/arm/mach-at91/board-rm9200ek.c#L173). As a result it was not reconfigurable at runtime. But Jean-Christophe suggested to make it configurable at runtime (using dt fragments). The pinctrl approach has the benefit of providing a transparent way (no existing drivers modifications) to enable one device or the other. But if you think this is better done (or cleaner) with an extcon or a regulator device, I'll try to find a way to do it this way. I'm uncertain. If this is something that changes at runtime, the input from the switch should be read through GPIO and used to select the default state of one device and something like sleep on the other (I suspect more things than pin control may be affected by that!) If this is a switch that you want to take the simple shortcut of just reading at boot, the approach would still be similar, just less code. So use gpio_get() to read the value, and then select which *entire device* goes active depending on the setting would be the right approach I guess? I'm not sure these suggestions apply according to my previous answers, but tell me if I'm wrong. Thanks for your time and suggestions. Best Regards, Boris Yours, Linus Walleij -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 0/2] clk: add clk accuracy support
Hello, This patch series adds support for clock accuracy retrieval in the common clk framework. Best Regards, Boris Changes since v1: - remove HAVE_CLK_GET_ACCURACY option and enable clk accuracy support only when using the CCF - export __clk_get_accuracy (might be used by clk-providers) - fix documentation (s/recalc_rate/recalc_accuracy/) - move fixed_accuracy field addition (struct clk_fixed_rate) from the 1st patch to the 2nd patch of this series Boris BREZILLON (2): clk: add clk accuracy retrieval support clk: add accuracy support for fixed clock Documentation/clk.txt |4 + .../devicetree/bindings/clock/fixed-clock.txt |3 + drivers/clk/clk-fixed-rate.c | 43 ++-- drivers/clk/clk.c | 109 +++- include/linux/clk-private.h|1 + include/linux/clk-provider.h | 15 +++ include/linux/clk.h| 17 +++ 7 files changed, 182 insertions(+), 10 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 1/2] clk: add clk accuracy retrieval support
The clock accuracy is expressed in ppb (parts per billion) and represents the possible clock drift. Say you have a clock (e.g. an oscillator) which provides a fixed clock of 20MHz with an accuracy of +- 20Hz. This accuracy expressed in ppb is 20Hz/20MHz = 1000 ppb (or 1 ppm). Clock users may need the clock accuracy information in order to choose the best clock (the one with the best accuracy) across several available clocks. This patch adds clk accuracy retrieval support for common clk framework by means of a new function called clk_get_accuracy. This function returns the given clock accuracy expressed in ppb. In order to get the clock accuracy, this implementation adds one callback called recalc_accuracy to the clk_ops structure. This callback is given the parent clock accuracy (if the clock is not a root clock) and should recalculate the given clock accuracy. This callback is optional and may be implemented if the clock is not a perfect clock (accuracy != 0 ppb). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- Documentation/clk.txt|4 ++ drivers/clk/clk.c| 109 -- include/linux/clk-private.h |1 + include/linux/clk-provider.h | 11 + include/linux/clk.h | 17 +++ 5 files changed, 138 insertions(+), 4 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 3aeb5c4..eb20198 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -77,6 +77,8 @@ the operations defined in clk.h: int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long); + unsigned long (*recalc_accuracy)(struct clk_hw *hw, + unsigned long parent_accuracy); void(*init)(struct clk_hw *hw); }; @@ -202,6 +204,8 @@ optional or must be evaluated on a case-by-case basis. .set_parent | | | n | y | n| .get_parent | | | n | y | n| | | | | | | +.recalc_accuracy| | | | | | +| | | | | | .init | | | | | | --- [1] either one of round_rate or determine_rate is required. diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2cf2ea6..4b0c1bc 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -104,10 +104,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) if (!c) return; - seq_printf(s, %*s%-*s %-11d %-12d %-10lu, + seq_printf(s, %*s%-*s %-11d %-12d %-10lu %-11lu, level * 3 + 1, , 30 - level * 3, c-name, - c-enable_count, c-prepare_count, clk_get_rate(c)); + c-enable_count, c-prepare_count, clk_get_rate(c), + clk_get_accuracy(c)); seq_printf(s, \n); } @@ -129,8 +130,8 @@ static int clk_summary_show(struct seq_file *s, void *data) { struct clk *c; - seq_printf(s,clockenable_cnt prepare_cnt rate\n); - seq_printf(s, -\n); + seq_printf(s,clockenable_cnt prepare_cnt rateaccuracy\n); + seq_printf(s, -\n); clk_prepare_lock(); @@ -167,6 +168,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level) seq_printf(s, \enable_count\: %d,, c-enable_count); seq_printf(s, \prepare_count\: %d,, c-prepare_count); seq_printf(s, \rate\: %lu, clk_get_rate(c)); + seq_printf(s, \accuracy\: %lu, clk_get_accuracy(c)); } static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) @@ -248,6 +250,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) if (!d) goto err_out; + d = debugfs_create_u32(clk_accuracy, S_IRUGO, clk-dentry, + (u32 *)clk-accuracy); + if (!d) + goto err_out; + d = debugfs_create_x32(clk_flags, S_IRUGO, clk-dentry, (u32 *)clk-flags); if (!d) @@ -602,6 +609,28 @@ out: return ret; } +unsigned long __clk_get_accuracy(struct clk *clk) +{ + unsigned long ret; + + if (!clk) { + ret = 0; + goto out; + } + + ret = clk-accuracy; + + if (clk-flags CLK_IS_ROOT
[PATCH v2 2/2] clk: add accuracy support for fixed clock
This patch adds support for accuracy retrieval on fixed clocks. It also adds a new dt property called 'clock-accuracy' to define the clock accuracy. This can be usefull for oscillator (RC, crystal, ...) definitions which are always given an accuracy characteristic. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- .../devicetree/bindings/clock/fixed-clock.txt |3 ++ drivers/clk/clk-fixed-rate.c | 43 +--- include/linux/clk-provider.h |4 ++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/fixed-clock.txt b/Documentation/devicetree/bindings/clock/fixed-clock.txt index 0b1fe78..48ea0ad 100644 --- a/Documentation/devicetree/bindings/clock/fixed-clock.txt +++ b/Documentation/devicetree/bindings/clock/fixed-clock.txt @@ -10,6 +10,8 @@ Required properties: - clock-frequency : frequency of clock in Hz. Should be a single cell. Optional properties: +- clock-accuracy : accuracy of clock in ppb (parts per billion). + Should be a single cell. - gpios : From common gpio binding; gpio connection to clock enable pin. - clock-output-names : From common clock binding. @@ -18,4 +20,5 @@ Example: compatible = fixed-clock; #clock-cells = 0; clock-frequency = 10; + clock-accuracy = 100; }; diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index 1ed591a..0fc56ab 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -34,22 +34,31 @@ static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, return to_clk_fixed_rate(hw)-fixed_rate; } +static unsigned long clk_fixed_rate_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_accuracy) +{ + return to_clk_fixed_rate(hw)-fixed_accuracy; +} + const struct clk_ops clk_fixed_rate_ops = { .recalc_rate = clk_fixed_rate_recalc_rate, + .recalc_accuracy = clk_fixed_rate_recalc_accuracy, }; EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); /** - * clk_register_fixed_rate - register fixed-rate clock with the clock framework + * clk_register_fixed_rate_with_accuracy - register fixed-rate clock with the + *clock framework * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of clock's parent * @flags: framework-specific flags * @fixed_rate: non-adjustable clock rate + * @fixed_accuracy: non-adjustable clock rate */ -struct clk *clk_register_fixed_rate(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, - unsigned long fixed_rate) +struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + unsigned long fixed_rate, unsigned long fixed_accuracy) { struct clk_fixed_rate *fixed; struct clk *clk; @@ -70,16 +79,33 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, /* struct clk_fixed_rate assignments */ fixed-fixed_rate = fixed_rate; + fixed-fixed_accuracy = fixed_accuracy; fixed-hw.init = init; /* register the clock */ clk = clk_register(dev, fixed-hw); - if (IS_ERR(clk)) kfree(fixed); return clk; } +EXPORT_SYMBOL_GPL(clk_register_fixed_rate_with_accuracy); + +/** + * clk_register_fixed_rate - register fixed-rate clock with the clock framework + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_name: name of clock's parent + * @flags: framework-specific flags + * @fixed_rate: non-adjustable clock rate + */ +struct clk *clk_register_fixed_rate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + unsigned long fixed_rate) +{ + return clk_register_fixed_rate_with_accuracy(dev, name, parent_name, +flags, fixed_rate, 0); +} EXPORT_SYMBOL_GPL(clk_register_fixed_rate); #ifdef CONFIG_OF @@ -91,13 +117,18 @@ void of_fixed_clk_setup(struct device_node *node) struct clk *clk; const char *clk_name = node-name; u32 rate; + u32 accuracy = 0; if (of_property_read_u32(node, clock-frequency, rate)) return; + of_property_read_u32(node, clock-accuracy, accuracy); + of_property_read_string(node, clock-output-names, clk_name); - clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate); + clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL, + CLK_IS_ROOT, rate, + accuracy); if (!IS_ERR(clk
Re: [PATCH v2 2/2] clk: add accuracy support for fixed clock
Hi Jason, On 27/11/2013 15:56, Jason Cooper wrote: Boris, Thanks for posting this series. Bear with me as I'm attempting to give MikeT a hand. Nice to hear. Mike already took a look at this series, but I'm happy to get more feedbacks. Don't be afraid to tell me a question is stupid :-) Your questions are far from stupid ;-). On Wed, Nov 27, 2013 at 01:44:45PM +0100, Boris BREZILLON wrote: This patch adds support for accuracy retrieval on fixed clocks. It also adds a new dt property called 'clock-accuracy' to define the clock accuracy. This can be usefull for oscillator (RC, crystal, ...) definitions which are always given an accuracy characteristic. I think we need to be more explicit in the binding and the API, especially when providing a method to recalculate the accuracy. I presume this recalculated value would be relative against the root clock? Yes, indirectly. Actually the clk accuracy depends on the whole clock chain, and is calculated either by comparing the real clk rate to the theorical clk rate (accuracy = absolute_value((theorical_clk_rate - real_clk_rate)) / theorical_clk_rate), or by adding all the accuracies (expressed in ppm, ppb or ppt) of the clk chain (accuracy = current_clk_accuracy + parent_clk_accuracy). Say you have a root clk with a +-1 ppb accuracy, then a pll multiplying this root clk by 40 and introducing a possible drift of +- 1000 ppb and eventually a system clk based on this pll with a perfect div by 2 prescaler (accuracy = 0 ppb). If I understand correctly how accuracy propagates accross the clk tree, you'll end up with a system clk with a +- 11000 ppb accuracy. e.g.: root clk = 12MHz +- 1 ppb = 12 MHz * (1 - (1 / 10^9)) root clk 12 MHz * (1 + (1 / 10^9)) = 11,99988 MHz root clk 12,00012 MHz pll clk = ((root clk) * 40) +- 1000 ppb = (11,99988 MHz * 40) * (1 - (1000 / 10^9)) pll clk (12,00012 MHz * 40) * (1 + (1000 / 10^9)) = 479,994720005 MHz pll clk 480,005280005 MHz system clk = ((pll clk) / 2) +- XXX ppb = 479,994720005 MHz / 2 system clk 480,005280005 MHz / 2 = 239,997360002 MHz system clk 240,002640002 MHz = system clk accuracy = 0,002640002 / 240 = 11000 ppb Please tell me if my assumptions are false. There really needs to be two attributes here: the rated accuracy from the manufacturer, and the calculated accuracy wrt another clock in the system. We only need a binding for the manufacturer rating since the calculated accuracy is determined at runtime. Actually when I proposed this new functionnality I only had the theorical (or manufacturer rated) accuracy in mind. But providing an estimated accuracy (based on another clk) sounds interresting if your reference clk is an extremly accurate one. I would also prefer to see an unknown accuracy be -1. I decided to keep 0 as a default value for unimplemented recalc_accuracy (or unspecified fixed accuracy) to keep existing implementation coherent. 0 means the clk is perfect, and I thought it would be easier to handle a perfect clk (even if this is not really the case) than handling an error case. Another aspect is the propagation of the clk accuracy accross the clk tree. Returning -1 in the middle of the clk chain will drop the previous clk accuracy calculation. Anyway, I can change this if you think this is more appropriate. There are already clocks on the market (PPS reference clocks) with accuracies of 0.1ppb/day [1]. Obviously, these aren't system clocks. So the limit on accuracy may be a non-issue. However, it may be worth changing the binding property to express the units. Wow, 0.1 ppb, this is impressive :-). This needs more than changing the dt bindings: I currently store the accuracy value in an unsigned long field, and expressing this in ppt (parts per trillion) may implies storing this in an u64 field (or store a unit field). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- .../devicetree/bindings/clock/fixed-clock.txt |3 ++ drivers/clk/clk-fixed-rate.c | 43 +--- include/linux/clk-provider.h |4 ++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/fixed-clock.txt b/Documentation/devicetree/bindings/clock/fixed-clock.txt index 0b1fe78..48ea0ad 100644 --- a/Documentation/devicetree/bindings/clock/fixed-clock.txt +++ b/Documentation/devicetree/bindings/clock/fixed-clock.txt @@ -10,6 +10,8 @@ Required properties: - clock-frequency : frequency of clock in Hz. Should be a single cell. Optional properties: +- clock-accuracy : accuracy of clock in ppb (parts per billion). + Should be a single cell. I would prefer to call
Re: [PATCH v2 2/2] clk: add accuracy support for fixed clock
On 27/11/2013 19:10, Mike Turquette wrote: Quoting boris brezillon (2013-11-27 09:19:08) Hi Jason, On 27/11/2013 15:56, Jason Cooper wrote: Boris, Thanks for posting this series. Bear with me as I'm attempting to give MikeT a hand. Nice to hear. Mike already took a look at this series, but I'm happy to get more feedbacks. Don't be afraid to tell me a question is stupid :-) Your questions are far from stupid ;-). On Wed, Nov 27, 2013 at 01:44:45PM +0100, Boris BREZILLON wrote: This patch adds support for accuracy retrieval on fixed clocks. It also adds a new dt property called 'clock-accuracy' to define the clock accuracy. This can be usefull for oscillator (RC, crystal, ...) definitions which are always given an accuracy characteristic. I think we need to be more explicit in the binding and the API, especially when providing a method to recalculate the accuracy. I presume this recalculated value would be relative against the root clock? Yes, indirectly. Actually the clk accuracy depends on the whole clock chain, and is calculated either by comparing the real clk rate to the theorical clk rate (accuracy = absolute_value((theorical_clk_rate - real_clk_rate)) / theorical_clk_rate), or by adding all the accuracies (expressed in ppm, ppb or ppt) of the clk chain (accuracy = current_clk_accuracy + parent_clk_accuracy). Say you have a root clk with a +-1 ppb accuracy, then a pll multiplying this root clk by 40 and introducing a possible drift of +- 1000 ppb and eventually a system clk based on this pll with a perfect div by 2 prescaler (accuracy = 0 ppb). If I understand correctly how accuracy propagates accross the clk tree, you'll end up with a system clk with a +- 11000 ppb accuracy. e.g.: root clk = 12MHz +- 1 ppb = 12 MHz * (1 - (1 / 10^9)) root clk 12 MHz * (1 + (1 / 10^9)) = 11,99988 MHz root clk 12,00012 MHz pll clk = ((root clk) * 40) +- 1000 ppb = (11,99988 MHz * 40) * (1 - (1000 / 10^9)) pll clk (12,00012 MHz * 40) * (1 + (1000 / 10^9)) = 479,994720005 MHz pll clk 480,005280005 MHz system clk = ((pll clk) / 2) +- XXX ppb = 479,994720005 MHz / 2 system clk 480,005280005 MHz / 2 = 239,997360002 MHz system clk 240,002640002 MHz = system clk accuracy = 0,002640002 / 240 = 11000 ppb Please tell me if my assumptions are false. There really needs to be two attributes here: the rated accuracy from the manufacturer, and the calculated accuracy wrt another clock in the system. We only need a binding for the manufacturer rating since the calculated accuracy is determined at runtime. Actually when I proposed this new functionnality I only had the theorical (or manufacturer rated) accuracy in mind. But providing an estimated accuracy (based on another clk) sounds interresting if your reference clk is an extremly accurate one. Is there a need to model clock accuracy across the clock chain? I'm OK modeling it in DT, and the code to do it in the clk framework isn't very much ... but I also wonder if we're just adding complexity for no reason. AFAIK the most important node in the clock chain (regarding accuracy) is the root node. But some nodes (like PLLs) might introduce more innacuracy. This series propose a simple way (or at least tries to keep it simple :-)) to express accuracy over the whole clk chain by means of the recalc_accuracy. I'm not sure keeping the accuracy calculation (or retrieval) in the root clk node only will simplify the calculation (or retrieval) of a leaf clk node accuracy (you'd still have to walk over the clock chain to get the root clk accuracy). My primary goal with this series is to provide a simple way (for a clock user) to choose the most accurate clock among several available clocks. This is a real need on AT91 platforms which provides internal RC oscillators with a really poor accuracy (+- 5% = +- 5 ppm). I would also prefer to see an unknown accuracy be -1. I decided to keep 0 as a default value for unimplemented recalc_accuracy (or unspecified fixed accuracy) to keep existing implementation coherent. 0 means the clk is perfect, and I thought it would be easier to handle a perfect clk (even if this is not really the case) than handling an error case. Another aspect is the propagation of the clk accuracy accross the clk tree. Returning -1 in the middle of the clk chain will drop the previous clk accuracy calculation. Anyway, I can change this if you think this is more appropriate. What about the absence of the property? Instead of requiring a -1 value can we simply detect that the property does not exist? This is nicer for backwards compatibility with existing DTS. I already handle the absence of the clock-accuracy property. In this case the clock
Re: [PATCH v2 0/2] clk: add clk accuracy support
Hello, On 28/11/2013 00:11, co...@horizon.com wrote: Um, do you have a definition somewhere (like in comments) of the definition of the accuracy you're using? So multiple people can add consistent values? Is this the standard deviation (67% confidence), 2 standard deviations (95%), 3 (99%), or something else? What averaging time is this computed over? Usually clock stability (which I recognize is not accuracy) is expressed using the Allan deviation, http://tf.nist.gov/general/glossary.htm#allandeviation This is because real clocks have unbounded asymptotic error. Over long time intervals, have a random frequency walk characteristic, where the frequency error after time T is proportional to sqrt(T). So an oscillator which is stable to 1ppb over a T second interval will be stable to 2ppb over a 4T second interval, 3ppb over a 9T second interval, and so on. Since accuracy is limited by stability, and there's no upper bound on instability, there's actually no upper bound on inaccuracy, either. (Admittedly, your typical crystal oscillators have their stability limited by environmental instability, particularly temperature, which dwarfs the frequency flicker noise limit.) On the flip side, some systems are synchronized to UTC by various means. This means (if we either neglect UTC's far sub-ppb instability, or just define it as perfect) that the inaccuracy over a long enough averaging interval is zero. But if it only synchronizes once a day, there can be significant inaccuracy between synchronization. Should the accuracy specification reflect that shorter-term instability? Finally, you can't specify *too* short an interval, because clocks also have increasing error over small time intervals. Below 10 seconds or so, white noise cycle-to-cycle jitter dominates, and the fewer cycles you average over, the larger it appears to be. A clear definition would help people understand what numbers to put in. Thanks for these informations, it helped me understand the different sources of inaccuracies of a crystal. As I said earlier, I'm not an expert in this area, and all your comments and feedbacks are welcome. BTW does this apply to other clk generators (RC oscillators, PLLs, ...), or is this only applicable to crystal oscillators ? Regarding the exact definition of accuracy, I guess in case of crystals this has more to do with stability. I found something called Total stability in several datasheet (e.g. http://www.silabs.com/Support%20Documents/TechnicalDocs/si510-11.pdf). Is this something applicable to our case ? Keep in mind that the primary goal of the clk accuracy retrieval is to give a clock user a way to choose the most accurate clock among several available clocks. This means we don't need the value to be extremely precise, but at least (as you stated) these values should represent the same things. Best Regards, Boris -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v5 06/17] clk: at91: add PMC pll clocks
Hi Mike, On 27/11/2013 22:48, Mike Turquette wrote: Quoting Boris BREZILLON (2013-11-12 13:57:19) +static const struct clk_ops pll_ops = { + .prepare = clk_pll_prepare, + .is_prepared = clk_pll_is_ready, + .disable = clk_pll_disable, + .is_enabled = clk_pll_is_ready, + .recalc_rate = clk_pll_recalc_rate, + .round_rate = clk_pll_round_rate, + .set_rate = clk_pll_set_rate, +}; Hi Boris, It is a bit strange to see only a .prepare and .disable callback populated. What happens if a driver calls clk_disable and then clk_enable? You clock will still be disabled in hardware. Oops, I haven't thought about that. I did this because the clk_pll_disable does not sleep, but this is a big mistake :-(. I'll fix this. Thanks. Best Regards, Boris Regards, Mike -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v6 02/16] ARM: at91: add Kconfig options for common clk support
This patch adds the following Kconfig options to prepare the transition to common clk framework: - AT91_USE_OLD_CLK: this option is selected by every SoC which does not support new at91 clks based on common clk framework (SoC which does not define the clock tree in its device tree). This options is also selected when the user choose non dt boards support (new at91 clks can only be registered from a device tree definition). - COMMON_CLK_AT91: this option cannot be selected directly. Instead it is enabled if these 3 conditions are met: * at least one of the selected SoCs have a PMC (Power Management Controller) Unit * device tree support is enabled * the old at91 clk implementation is disabled (every selected SoC define its clks in its device tree and non dt boards support is disabled) - OLD_CLK_AT91: this option cannot be selected directly. Instead it is enabled if these 2 conditions are met: * at least one of the selected SoCs have a PMC (Power Management Controller) Unit * at least one of the selected SoCs does not define its clks in its device tree or non dt-boards support is enabled This patch selects AT91_USE_OLD_CLK in all currently supported SoCs. These selects will be removed after clk definitions are properly added in each soc's device tree. It also selects AT91_USE_OLD_CLK in all non-dt boards support. AT91_PMC_UNIT references are replaced by OLD_CLK_AT91, because PMC Unit is enabled for both old and common clk implementations, and old clk implementation should not be compiled if COMMON_CLK is enabled. To avoid future link errors, a new stub is created for at91_dt_clock_init function if OLD_CLK_AT91 is disabled. A new check is added in dt init functions (setup.c) to prepare for SoCs supporting new clk implementation. These SoCs won't setup the register_clocks callback (clk registration is done using of_clk_init). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig| 21 + arch/arm/mach-at91/Kconfig.non_dt |6 ++ arch/arm/mach-at91/Makefile |2 +- arch/arm/mach-at91/generic.h |3 ++- arch/arm/mach-at91/setup.c|6 -- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 699b71e..85b53a4 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -6,10 +6,22 @@ config HAVE_AT91_DBGU0 config HAVE_AT91_DBGU1 bool +config AT91_USE_OLD_CLK + bool + config AT91_PMC_UNIT bool default !ARCH_AT91X40 +config COMMON_CLK_AT91 + bool + default AT91_PMC_UNIT USE_OF !AT91_USE_OLD_CLK + select COMMON_CLK + +config OLD_CLK_AT91 + bool + default AT91_PMC_UNIT AT91_USE_OLD_CLK + config AT91_SAM9_ALT_RESET bool default !ARCH_AT91X40 @@ -65,6 +77,7 @@ config SOC_SAMA5D3 select SOC_SAMA5 select HAVE_FB_ATMEL select HAVE_AT91_DBGU1 + select AT91_USE_OLD_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -78,11 +91,13 @@ config SOC_AT91RM9200 select HAVE_AT91_DBGU0 select MULTI_IRQ_HANDLER select SPARSE_IRQ + select AT91_USE_OLD_CLK config SOC_AT91SAM9260 bool AT91SAM9260, AT91SAM9XE or AT91SAM9G20 select HAVE_AT91_DBGU0 select SOC_AT91SAM9 + select AT91_USE_OLD_CLK help Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE or AT91SAM9G20 SoC. @@ -92,6 +107,7 @@ config SOC_AT91SAM9261 select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK help Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. @@ -100,18 +116,21 @@ config SOC_AT91SAM9263 select HAVE_AT91_DBGU1 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK config SOC_AT91SAM9RL bool AT91SAM9RL select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK config SOC_AT91SAM9G45 bool AT91SAM9G45 or AT91SAM9M10 families select HAVE_AT91_DBGU1 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -121,6 +140,7 @@ config SOC_AT91SAM9X5 select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5
[PATCH v6 05/16] clk: at91: add PMC main clock
This patch adds new at91 main oscillator clock implementation using common clk framework. If rate is not provided during clock registration it is calculated using the slow clock (main clk parent in this case) rate and MCFR register. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-main.c | 187 +++ drivers/clk/at91/pmc.c |5 ++ drivers/clk/at91/pmc.h |3 + 4 files changed, 196 insertions(+) create mode 100644 drivers/clk/at91/clk-main.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 1d4fb21..44105bd 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,3 +3,4 @@ # obj-y += pmc.o +obj-y += clk-main.o diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c new file mode 100644 index 000..8e9e8cc --- /dev/null +++ b/drivers/clk/at91/clk-main.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/delay.h +#include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h +#include linux/io.h +#include linux/interrupt.h +#include linux/irq.h +#include linux/sched.h +#include linux/wait.h + +#include pmc.h + +#define SLOW_CLOCK_FREQ32768 +#define MAINF_DIV 16 +#define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \ +SLOW_CLOCK_FREQ) +#define MAINF_LOOP_MIN_WAIT(USEC_PER_SEC / SLOW_CLOCK_FREQ) +#define MAINF_LOOP_MAX_WAITMAINFRDY_TIMEOUT + +struct clk_main { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned long rate; + unsigned int irq; + wait_queue_head_t wait; +}; + +#define to_clk_main(hw) container_of(hw, struct clk_main, hw) + +static irqreturn_t clk_main_irq_handler(int irq, void *dev_id) +{ + struct clk_main *clkmain = (struct clk_main *)dev_id; + + wake_up(clkmain-wait); + disable_irq_nosync(clkmain-irq); + + return IRQ_HANDLED; +} + +static int clk_main_prepare(struct clk_hw *hw) +{ + struct clk_main *clkmain = to_clk_main(hw); + struct at91_pmc *pmc = clkmain-pmc; + unsigned long halt_time, timeout; + u32 tmp; + + while (!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_MOSCS)) { + enable_irq(clkmain-irq); + wait_event(clkmain-wait, + pmc_read(pmc, AT91_PMC_SR) AT91_PMC_MOSCS); + } + + if (clkmain-rate) + return 0; + + timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); + do { + halt_time = jiffies; + tmp = pmc_read(pmc, AT91_CKGR_MCFR); + if (tmp AT91_PMC_MAINRDY) + return 0; + usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); + } while (time_before(halt_time, timeout)); + + return 0; +} + +static int clk_main_is_prepared(struct clk_hw *hw) +{ + struct clk_main *clkmain = to_clk_main(hw); + + return !!(pmc_read(clkmain-pmc, AT91_PMC_SR) AT91_PMC_MOSCS); +} + +static unsigned long clk_main_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + struct clk_main *clkmain = to_clk_main(hw); + struct at91_pmc *pmc = clkmain-pmc; + + if (clkmain-rate) + return clkmain-rate; + + tmp = pmc_read(pmc, AT91_CKGR_MCFR) AT91_PMC_MAINF; + clkmain-rate = (tmp * parent_rate) / MAINF_DIV; + + return clkmain-rate; +} + +static const struct clk_ops main_ops = { + .prepare = clk_main_prepare, + .is_prepared = clk_main_is_prepared, + .recalc_rate = clk_main_recalc_rate, +}; + +static struct clk * __init +at91_clk_register_main(struct at91_pmc *pmc, + unsigned int irq, + const char *name, + const char *parent_name, + unsigned long rate) +{ + int ret; + struct clk_main *clkmain; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !irq || !name) + return ERR_PTR(-EINVAL); + + if (!rate !parent_name) + return ERR_PTR(-EINVAL); + + clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); + if (!clkmain) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = main_ops; + init.parent_names = parent_name ? parent_name : NULL; + init.num_parents = parent_name ? 1 : 0
[PATCH v6 07/16] clk: at91: add PMC master clock
This patch adds new at91 master clock implementation using common clk framework. The master clock layout describe the MCKR register layout. There are 2 master clock layouts: - at91rm9200 - at91sam9x5 Master clocks are given characteristics: - min/max clock output rate These characteristics are checked during rate change to avoid over/underclocking. These characteristics are described in atmel's SoC datasheet in Electrical Characteristics paragraph. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |2 +- drivers/clk/at91/clk-master.c | 270 + drivers/clk/at91/clk-pll.c| 10 +- drivers/clk/at91/pmc.c|9 ++ drivers/clk/at91/pmc.h|5 + 5 files changed, 287 insertions(+), 9 deletions(-) create mode 100644 drivers/clk/at91/clk-master.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 902bbf1..e28fb2b 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,4 +3,4 @@ # obj-y += pmc.o -obj-y += clk-main.o clk-pll.o clk-plldiv.o +obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c new file mode 100644 index 000..bd313f7 --- /dev/null +++ b/drivers/clk/at91/clk-master.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h +#include linux/io.h +#include linux/wait.h +#include linux/sched.h +#include linux/interrupt.h +#include linux/irq.h + +#include pmc.h + +#define MASTER_SOURCE_MAX 4 + +#define MASTER_PRES_MASK 0x7 +#define MASTER_PRES_MAXMASTER_PRES_MASK +#define MASTER_DIV_SHIFT 8 +#define MASTER_DIV_MASK0x3 + +struct clk_master_characteristics { + struct clk_range output; + u32 divisors[4]; + u8 have_div3_pres; +}; + +struct clk_master_layout { + u32 mask; + u8 pres_shift; +}; + +#define to_clk_master(hw) container_of(hw, struct clk_master, hw) + +struct clk_master { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + const struct clk_master_layout *layout; + const struct clk_master_characteristics *characteristics; +}; + +static irqreturn_t clk_master_irq_handler(int irq, void *dev_id) +{ + struct clk_master *master = (struct clk_master *)dev_id; + + wake_up(master-wait); + disable_irq_nosync(master-irq); + + return IRQ_HANDLED; +} +static int clk_master_prepare(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master-pmc; + + while (!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_MCKRDY)) { + enable_irq(master-irq); + wait_event(master-wait, + pmc_read(pmc, AT91_PMC_SR) AT91_PMC_MCKRDY); + } + + return 0; +} + +static int clk_master_is_prepared(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + + return !!(pmc_read(master-pmc, AT91_PMC_SR) AT91_PMC_MCKRDY); +} + +static unsigned long clk_master_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u8 pres; + u8 div; + unsigned long rate = parent_rate; + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master-pmc; + const struct clk_master_layout *layout = master-layout; + const struct clk_master_characteristics *characteristics = + master-characteristics; + u32 tmp; + + pmc_lock(pmc); + tmp = pmc_read(pmc, AT91_PMC_MCKR) layout-mask; + pmc_unlock(pmc); + + pres = (tmp layout-pres_shift) MASTER_PRES_MASK; + div = (tmp MASTER_DIV_SHIFT) MASTER_DIV_MASK; + + if (characteristics-have_div3_pres pres == MASTER_PRES_MAX) + rate /= 3; + else + rate = pres; + + rate /= characteristics-divisors[div]; + + if (rate characteristics-output.min) + pr_warn(master clk is underclocked); + else if (rate characteristics-output.max) + pr_warn(master clk is overclocked); + + return rate; +} + +static u8 clk_master_get_parent(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master-pmc; + + return pmc_read(pmc, AT91_PMC_MCKR) AT91_PMC_CSS
[PATCH v6 06/16] clk: at91: add PMC pll clocks
This patch adds new at91 pll clock implementation using common clk framework. The pll clock layout describe the PLLX register layout. There are four pll clock layouts: - at91rm9200 - at91sam9g20 - at91sam9g45 - sama5d3 PLL clocks are given characteristics: - min/max clock source rate - ranges of valid clock output rates - values to set in out and icpll fields for each supported output range These characteristics are checked during rate change to avoid over/underclocking. These characteristics are described in atmel's SoC datasheet in Electrical Characteristics paragraph. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |2 +- drivers/clk/at91/clk-pll.c| 537 + drivers/clk/at91/clk-plldiv.c | 135 +++ drivers/clk/at91/pmc.c| 21 ++ drivers/clk/at91/pmc.h| 11 + include/linux/clk/at91_pmc.h |2 + 6 files changed, 707 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/at91/clk-pll.c create mode 100644 drivers/clk/at91/clk-plldiv.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 44105bd..902bbf1 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,4 +3,4 @@ # obj-y += pmc.o -obj-y += clk-main.o +obj-y += clk-main.o clk-pll.o clk-plldiv.o diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c new file mode 100644 index 000..5e23ee4 --- /dev/null +++ b/drivers/clk/at91/clk-pll.c @@ -0,0 +1,537 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h +#include linux/io.h +#include linux/wait.h +#include linux/sched.h +#include linux/interrupt.h +#include linux/irq.h + +#include pmc.h + +#define PLL_STATUS_MASK(id)(1 (1 + (id))) +#define PLL_REG(id)(AT91_CKGR_PLLAR + ((id) * 4)) +#define PLL_DIV_MASK 0xff +#define PLL_DIV_MAXPLL_DIV_MASK +#define PLL_DIV(reg) ((reg) PLL_DIV_MASK) +#define PLL_MUL(reg, layout) (((reg) (layout)-mul_shift) \ +(layout)-mul_mask) +#define PLL_ICPR_SHIFT(id) ((id) * 16) +#define PLL_ICPR_MASK(id) (0x PLL_ICPR_SHIFT(id)) +#define PLL_MAX_COUNT 0x3ff +#define PLL_COUNT_SHIFT8 +#define PLL_OUT_SHIFT 14 +#define PLL_MAX_ID 1 + +struct clk_pll_characteristics { + struct clk_range input; + int num_output; + struct clk_range *output; + u16 *icpll; + u8 *out; +}; + +struct clk_pll_layout { + u32 pllr_mask; + u16 mul_mask; + u8 mul_shift; +}; + +#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw) + +struct clk_pll { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + u8 id; + u8 div; + u8 range; + u16 mul; + const struct clk_pll_layout *layout; + const struct clk_pll_characteristics *characteristics; +}; + +static irqreturn_t clk_pll_irq_handler(int irq, void *dev_id) +{ + struct clk_pll *pll = (struct clk_pll *)dev_id; + + wake_up(pll-wait); + disable_irq_nosync(pll-irq); + + return IRQ_HANDLED; +} + +static int clk_pll_prepare(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct at91_pmc *pmc = pll-pmc; + const struct clk_pll_layout *layout = pll-layout; + u8 id = pll-id; + u32 mask = PLL_STATUS_MASK(id); + int offset = PLL_REG(id); + u8 out = 0; + u32 pllr, icpr; + u8 div; + u16 mul; + + pllr = pmc_read(pmc, offset); + div = PLL_DIV(pllr); + mul = PLL_MUL(pllr, layout); + + if ((pmc_read(pmc, AT91_PMC_SR) mask) + (div == pll-div mul == pll-mul)) + return 0; + + if (characteristics-out) + out = characteristics-out[pll-range]; + if (characteristics-icpll) { + icpr = pmc_read(pmc, AT91_PMC_PLLICPR) ~PLL_ICPR_MASK(id); + icpr |= (characteristics-icpll[pll-range] + PLL_ICPR_SHIFT(id)); + pmc_write(pmc, AT91_PMC_PLLICPR, icpr); + } + + pllr = ~layout-pllr_mask; + pllr |= layout-pllr_mask + (pll-div | (PLL_MAX_COUNT PLL_COUNT_SHIFT) | + (out PLL_OUT_SHIFT) | + ((pll-mul layout-mul_mask) layout-mul_shift)); + pmc_write(pmc, offset, pllr); + + while (!(pmc_read(pmc, AT91_PMC_SR) mask
[PATCH v6 01/16] ARM: at91: move at91_pmc.h to include/linux/clk/at91_pmc.h
This patch moves at91_pmc.h header from machine specific directory (arch/arm/mach-at91/include/mach/at91_pmc.h) to clk include directory (include/linux/clk/at91_pmc.h). We need this to avoid reference to machine specific headers in clk drivers. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Felipe Balbi ba...@ti.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/at91rm9200.c|2 +- arch/arm/mach-at91/at91sam9260.c |2 +- arch/arm/mach-at91/at91sam9261.c |2 +- arch/arm/mach-at91/at91sam9263.c |2 +- arch/arm/mach-at91/at91sam9g45.c |2 +- arch/arm/mach-at91/at91sam9n12.c |2 +- arch/arm/mach-at91/at91sam9rl.c|2 +- arch/arm/mach-at91/at91sam9x5.c|2 +- arch/arm/mach-at91/clock.c |2 +- arch/arm/mach-at91/pm.c|2 +- arch/arm/mach-at91/pm_slowclock.S |2 +- arch/arm/mach-at91/sama5d3.c |2 +- arch/arm/mach-at91/setup.c |2 +- drivers/usb/gadget/atmel_usba_udc.c|2 +- .../include/mach = include/linux/clk}/at91_pmc.h |2 +- 15 files changed, 15 insertions(+), 15 deletions(-) rename {arch/arm/mach-at91/include/mach = include/linux/clk}/at91_pmc.h (99%) diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index 4aad93d..102dac6 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -12,13 +12,13 @@ #include linux/module.h #include linux/reboot.h +#include linux/clk/at91_pmc.h #include asm/irq.h #include asm/mach/arch.h #include asm/mach/map.h #include asm/system_misc.h #include mach/at91rm9200.h -#include mach/at91_pmc.h #include mach/at91_st.h #include mach/cpu.h diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 5de6074..16d7817 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -11,6 +11,7 @@ */ #include linux/module.h +#include linux/clk/at91_pmc.h #include asm/proc-fns.h #include asm/irq.h @@ -20,7 +21,6 @@ #include mach/cpu.h #include mach/at91_dbgu.h #include mach/at91sam9260.h -#include mach/at91_pmc.h #include at91_aic.h #include at91_rstc.h diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 0e07932..c8f5958 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -11,6 +11,7 @@ */ #include linux/module.h +#include linux/clk/at91_pmc.h #include asm/proc-fns.h #include asm/irq.h @@ -19,7 +20,6 @@ #include asm/system_misc.h #include mach/cpu.h #include mach/at91sam9261.h -#include mach/at91_pmc.h #include at91_aic.h #include at91_rstc.h diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 6ce7d18..cd8ad95 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -11,6 +11,7 @@ */ #include linux/module.h +#include linux/clk/at91_pmc.h #include asm/proc-fns.h #include asm/irq.h @@ -18,7 +19,6 @@ #include asm/mach/map.h #include asm/system_misc.h #include mach/at91sam9263.h -#include mach/at91_pmc.h #include at91_aic.h #include at91_rstc.h diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 474ee04..9794b20 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -12,13 +12,13 @@ #include linux/module.h #include linux/dma-mapping.h +#include linux/clk/at91_pmc.h #include asm/irq.h #include asm/mach/arch.h #include asm/mach/map.h #include asm/system_misc.h #include mach/at91sam9g45.h -#include mach/at91_pmc.h #include mach/cpu.h #include at91_aic.h diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c index 2d895a2..deafab2 100644 --- a/arch/arm/mach-at91/at91sam9n12.c +++ b/arch/arm/mach-at91/at91sam9n12.c @@ -8,12 +8,12 @@ #include linux/module.h #include linux/dma-mapping.h +#include linux/clk/at91_pmc.h #include asm/irq.h #include asm/mach/arch.h #include asm/mach/map.h #include mach/at91sam9n12.h -#include mach/at91_pmc.h #include mach/cpu.h #include board.h diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index d4ec0d9..947da95 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -10,6 +10,7 @@ */ #include linux/module.h +#include linux/clk/at91_pmc.h #include asm/proc-fns.h #include asm/irq.h @@ -19,7 +20,6 @@ #include mach/cpu.h #include mach/at91_dbgu.h #include mach/at91sam9rl.h -#include mach/at91_pmc.h #include at91_aic.h #include at91_rstc.h diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index 916e5a1..a930d73 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm
[PATCH v6 00/16] ARM: at91: move to common clk framework
Hello, This patch series is the 5th version of the at91 clk implementations using the Common Clk Framework. Most of the clock provided by the PMC (Power Management Controller) are implemented : - main clock (main oscillator) - pll clocks - master clock - programmable clocks - utmi clock - peripheral clocks - system clocks Actually some clk drivers are missing (slow clk, main clk and processor clk), and some drivers only implement a subset of the hardware capabilities (master clk rate change is missing). But this series implements all the already available clks, and I will hopefully add missing features in a near future. This implementation is only compatible with device tree definition. The goal is to define the whole clock tree using the device tree. Just a note to let you know these bindings are currently unstable and might change in the future. Best Regards, Boris Changes since v5: - remove peripheral divisors macros from dt binding include file - remove file path from comment blocks - replace pll and utmi disable function by unprepare function to avoid issue when disabling and reenabling a clk - fix programmable clk interrupt retrieval - fix OF_CLK_DECLARE names (xxx_clk_main - xxx_clk_pmc) - add missing comma in at91rm9200 main clk dt declaration - fix num_parents check in smd clk driver Changes since v4: - rework dt bindings: * replace atmel,clk-id property by the standard reg property * reference system, peripheral and programmable clks using the direct clk node instead of the parent node plus a clk id - provide a new helper function (of_at91_get_clk_range) to retrieve a clk range from the device tree Changes since v3: - simplify master clk implementation (drop set_rate/parent support) - fix bug in set_rate function of pll driver - fix coding style issues - define macros and constants where needed - remove peripheral id macro references - remove sam9g35 specific handling (sam9g35 = sam9x5) - rework main clk prepare function to handle automatic rate calculation Changes since v2: - fix several bugs in clk implementations - drop non-dt boards support - split the series to ease review and tests: * 1 patch series for new clk implementations (this series) * 1 patch series to move each at91 SoC to common clk framework (coming soon) - modify dt-bindings (add atmel,clk- prefix to atmel specific properties) - add clk macros for dt-bindings - add pmc framework (helper function to access pmc registers) - add interrupt support to enable passive wait in clk_prepare functions Changes since v1: - fix bugs in pll, programmable and system clock implementations (wrong bit position). - add usb clock configuration support (ohci and udc drivers + clk_lookup for non dt boards) - rework of the system clock interfaces (no need to define a parent clock, system clock is a gate with no rate info) - change system, peripheral and programmable clk dt bindings (1 master node and multiple child nodes each defining a system/peripheral or prog clock) - fix bugs in sama5 dt definition Boris BREZILLON (16): ARM: at91: move at91_pmc.h to include/linux/clk/at91_pmc.h ARM: at91: add Kconfig options for common clk support clk: at91: add PMC base support clk: at91: add PMC macro file for dt definitions clk: at91: add PMC main clock clk: at91: add PMC pll clocks clk: at91: add PMC master clock clk: at91: add PMC system clocks clk: at91: add PMC peripheral clocks clk: at91: add PMC programmable clocks clk: at91: add PMC utmi clock clk: at91: add PMC usb clock clk: at91: add PMC smd clock dt: binding: add at91 clks dt bindings documentation ARM: at91: move pit timer to common clk framework ARM: at91: add new compatible strings for pmc driver .../devicetree/bindings/clock/at91-clock.txt | 339 + arch/arm/mach-at91/Kconfig | 44 ++ arch/arm/mach-at91/Kconfig.non_dt |6 + arch/arm/mach-at91/Makefile|2 +- arch/arm/mach-at91/at91rm9200.c|2 +- arch/arm/mach-at91/at91sam9260.c |2 +- arch/arm/mach-at91/at91sam9261.c |2 +- arch/arm/mach-at91/at91sam9263.c |2 +- arch/arm/mach-at91/at91sam926x_time.c | 14 +- arch/arm/mach-at91/at91sam9g45.c |2 +- arch/arm/mach-at91/at91sam9n12.c |2 +- arch/arm/mach-at91/at91sam9rl.c|2 +- arch/arm/mach-at91/at91sam9x5.c|2 +- arch/arm/mach-at91/clock.c |7 +- arch/arm/mach-at91/generic.h |3 +- arch/arm/mach-at91/pm.c|2 +- arch/arm/mach-at91/pm_slowclock.S |2 +- arch/arm/mach-at91/sama5d3.c |2 +- arch/arm/mach-at91/setup.c |8 +- drivers/clk/Makefile
[PATCH v6 08/16] clk: at91: add PMC system clocks
This patch adds new at91 system clock implementation using common clk framework. Some peripherals need to enable a system clock in order to work properly. Each system clock is given an id based on the bit position in SCER/SCDR registers. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-system.c | 135 + drivers/clk/at91/pmc.c|5 ++ drivers/clk/at91/pmc.h|3 + 4 files changed, 144 insertions(+) create mode 100644 drivers/clk/at91/clk-system.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index e28fb2b..c2b7068 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -4,3 +4,4 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o +obj-y += clk-system.o diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c new file mode 100644 index 000..8f7c043 --- /dev/null +++ b/drivers/clk/at91/clk-system.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define SYSTEM_MAX_ID 31 + +#define SYSTEM_MAX_NAME_SZ 32 + +#define to_clk_system(hw) container_of(hw, struct clk_system, hw) +struct clk_system { + struct clk_hw hw; + struct at91_pmc *pmc; + u8 id; +}; + +static int clk_system_enable(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys-pmc; + + pmc_write(pmc, AT91_PMC_SCER, 1 sys-id); + return 0; +} + +static void clk_system_disable(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys-pmc; + + pmc_write(pmc, AT91_PMC_SCDR, 1 sys-id); +} + +static int clk_system_is_enabled(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys-pmc; + + return !!(pmc_read(pmc, AT91_PMC_SCSR) (1 sys-id)); +} + +static const struct clk_ops system_ops = { + .enable = clk_system_enable, + .disable = clk_system_disable, + .is_enabled = clk_system_is_enabled, +}; + +static struct clk * __init +at91_clk_register_system(struct at91_pmc *pmc, const char *name, +const char *parent_name, u8 id) +{ + struct clk_system *sys; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!parent_name || id SYSTEM_MAX_ID) + return ERR_PTR(-EINVAL); + + sys = kzalloc(sizeof(*sys), GFP_KERNEL); + if (!sys) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = system_ops; + init.parent_names = parent_name; + init.num_parents = 1; + /* +* CLK_IGNORE_UNUSED is used to avoid ddrck switch off. +* TODO : we should implement a driver supporting at91 ddr controller +* (see drivers/memory) which would request and enable the ddrck clock. +* When this is done we will be able to remove CLK_IGNORE_UNUSED flag. +*/ + init.flags = CLK_IGNORE_UNUSED; + + sys-id = id; + sys-hw.init = init; + sys-pmc = pmc; + + clk = clk_register(NULL, sys-hw); + if (IS_ERR(clk)) + kfree(sys); + + return clk; +} + +static void __init +of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) +{ + int num; + u32 id; + struct clk *clk; + const char *name; + struct device_node *sysclknp; + const char *parent_name; + + num = of_get_child_count(np); + if (num (SYSTEM_MAX_ID + 1)) + return; + + for_each_child_of_node(np, sysclknp) { + if (of_property_read_u32(sysclknp, reg, id)) + continue; + + if (of_property_read_string(np, clock-output-names, name)) + name = sysclknp-name; + + parent_name = of_clk_get_parent_name(sysclknp, 0); + + clk = at91_clk_register_system(pmc, name, parent_name, id); + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk); + } +} + +void __init of_at91rm9200_clk_sys_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_sys_setup(np, pmc); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index a311cf3..a97554f 100644
[PATCH v6 09/16] clk: at91: add PMC peripheral clocks
This patch adds new at91 peripheral clock implementation using common clk framework. Almost all peripherals provided by at91 SoCs need a clock to work properly. This clock is enabled/disabled using PCER/PCDR resgisters. Each peripheral is given an id (see atmel's datasheets) which is used to define and reference peripheral clocks. Some new SoCs (at91sam9x5 and sama5d3) provide a new register (PCR) where you can configure the peripheral clock as a division of the master clock. This will help reducing the peripherals power comsumption. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |2 +- drivers/clk/at91/clk-peripheral.c | 410 + drivers/clk/at91/pmc.c|9 + drivers/clk/at91/pmc.h|5 + 4 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/at91/clk-peripheral.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index c2b7068..04deba3 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -4,4 +4,4 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o -obj-y += clk-system.o +obj-y += clk-system.o clk-peripheral.o diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c new file mode 100644 index 000..597fed4 --- /dev/null +++ b/drivers/clk/at91/clk-peripheral.c @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define PERIPHERAL_MAX 64 + +#define PERIPHERAL_AT91RM9200 0 +#define PERIPHERAL_AT91SAM9X5 1 + +#define PERIPHERAL_ID_MIN 2 +#define PERIPHERAL_ID_MAX 31 +#define PERIPHERAL_MASK(id)(1 ((id) PERIPHERAL_ID_MAX)) + +#define PERIPHERAL_RSHIFT_MASK 0x3 +#define PERIPHERAL_RSHIFT(val) (((val) 16) PERIPHERAL_RSHIFT_MASK) + +#define PERIPHERAL_MAX_SHIFT 4 + +struct clk_peripheral { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 id; +}; + +#define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw) + +struct clk_sam9x5_peripheral { + struct clk_hw hw; + struct at91_pmc *pmc; + struct clk_range range; + u32 id; + u32 div; + bool auto_div; +}; + +#define to_clk_sam9x5_peripheral(hw) \ + container_of(hw, struct clk_sam9x5_peripheral, hw) + +static int clk_peripheral_enable(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph-pmc; + int offset = AT91_PMC_PCER; + u32 id = periph-id; + + if (id PERIPHERAL_ID_MIN) + return 0; + if (id PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCER1; + pmc_write(pmc, offset, PERIPHERAL_MASK(id)); + return 0; +} + +static void clk_peripheral_disable(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph-pmc; + int offset = AT91_PMC_PCDR; + u32 id = periph-id; + + if (id PERIPHERAL_ID_MIN) + return; + if (id PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCDR1; + pmc_write(pmc, offset, PERIPHERAL_MASK(id)); +} + +static int clk_peripheral_is_enabled(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph-pmc; + int offset = AT91_PMC_PCSR; + u32 id = periph-id; + + if (id PERIPHERAL_ID_MIN) + return 1; + if (id PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCSR1; + return !!(pmc_read(pmc, offset) PERIPHERAL_MASK(id)); +} + +static const struct clk_ops peripheral_ops = { + .enable = clk_peripheral_enable, + .disable = clk_peripheral_disable, + .is_enabled = clk_peripheral_is_enabled, +}; + +static struct clk * __init +at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, +const char *parent_name, u32 id) +{ + struct clk_peripheral *periph; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !name || !parent_name || id PERIPHERAL_ID_MAX) + return ERR_PTR(-EINVAL); + + periph = kzalloc(sizeof(*periph), GFP_KERNEL); + if (!periph) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = peripheral_ops; + init.parent_names = (parent_name ? parent_name : NULL); + init.num_parents
[PATCH v6 03/16] clk: at91: add PMC base support
This patch adds at91 PMC (Power Management Controller) base support. All at91 clocks managed by the PMC unit will use this framework. This framework provides the following fonctionalities: - define a new struct at91_pmc to hide PMC internals (lock, PMC memory mapping, irq domain, ...) - read/write helper functions (pmc_read/write) to access PMC registers - lock/unlock helper functions (pmc_lock/unlock) to lock/unlock access to pmc registers - a new irq domain and its associated irq chip to request PMC specific interrupts (useful for clk prepare callbacks) The PMC unit is declared as a dt clk provider (CLK_OF_DECLARE), and every clk using this framework will declare a table of of_at91_clk_init_cb_t and add it to the pmc_clk_ids table. When the pmc dt clock setup function is called (by of_clk_init function), it triggers the registration of every supported child clk (those matching the definitions in pmc_clk_ids). This patch copies at91_pmc_base (memory mapping) and at91sam9_idle (function) from arch/arm/mach-at91/clock.c (which is not compiled if COMMON_CLK_AT91 is enabled). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/Makefile |1 + drivers/clk/at91/Makefile |5 + drivers/clk/at91/pmc.c| 304 + drivers/clk/at91/pmc.h| 61 + 4 files changed, 371 insertions(+) create mode 100644 drivers/clk/at91/Makefile create mode 100644 drivers/clk/at91/pmc.c create mode 100644 drivers/clk/at91/pmc.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7b11106..28c2678 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_ARCH_ZYNQ)+= zynq/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ +obj-$(CONFIG_COMMON_CLK_AT91) += at91/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile new file mode 100644 index 000..1d4fb21 --- /dev/null +++ b/drivers/clk/at91/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for at91 specific clk +# + +obj-y += pmc.o diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c new file mode 100644 index 000..69c116a --- /dev/null +++ b/drivers/clk/at91/pmc.c @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h +#include linux/interrupt.h +#include linux/irq.h +#include linux/irqchip/chained_irq.h +#include linux/irqdomain.h +#include linux/of_irq.h + +#include asm/proc-fns.h + +#include pmc.h + +void __iomem *at91_pmc_base; +EXPORT_SYMBOL_GPL(at91_pmc_base); + +void at91sam9_idle(void) +{ + at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); + cpu_do_idle(); +} + +int of_at91_get_clk_range(struct device_node *np, const char *propname, + struct clk_range *range) +{ + u32 min, max; + int ret; + + ret = of_property_read_u32_index(np, propname, 0, min); + if (ret) + return ret; + + ret = of_property_read_u32_index(np, propname, 1, max); + if (ret) + return ret; + + if (range) { + range-min = min; + range-max = max; + } + + return 0; +} +EXPORT_SYMBOL_GPL(of_at91_get_clk_range); + +static void pmc_irq_mask(struct irq_data *d) +{ + struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); + + pmc_write(pmc, AT91_PMC_IDR, 1 d-hwirq); +} + +static void pmc_irq_unmask(struct irq_data *d) +{ + struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); + + pmc_write(pmc, AT91_PMC_IER, 1 d-hwirq); +} + +static int pmc_irq_set_type(struct irq_data *d, unsigned type) +{ + if (type != IRQ_TYPE_LEVEL_HIGH) { + pr_warn(PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n); + return -EINVAL; + } + + return 0; +} + +static struct irq_chip pmc_irq = { + .name = PMC, + .irq_disable = pmc_irq_mask, + .irq_mask = pmc_irq_mask, + .irq_unmask = pmc_irq_unmask, + .irq_set_type = pmc_irq_set_type, +}; + +static struct lock_class_key pmc_lock_class; + +static int pmc_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct at91_pmc *pmc = h-host_data; + + irq_set_lockdep_class(virq, pmc_lock_class); + + irq_set_chip_and_handler(virq, pmc_irq, +handle_level_irq
[PATCH v6 04/16] clk: at91: add PMC macro file for dt definitions
This patch adds a new macro file for PMC macros. This macro file includes the definitions of SR (status register) bit offsets and will be use to reference PMC irqs. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- include/dt-bindings/clk/at91.h | 22 ++ 1 file changed, 22 insertions(+) create mode 100644 include/dt-bindings/clk/at91.h diff --git a/include/dt-bindings/clk/at91.h b/include/dt-bindings/clk/at91.h new file mode 100644 index 000..0b4cb99 --- /dev/null +++ b/include/dt-bindings/clk/at91.h @@ -0,0 +1,22 @@ +/* + * This header provides constants for AT91 pmc status. + * + * The constants defined in this header are being used in dts. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _DT_BINDINGS_CLK_AT91_H +#define _DT_BINDINGS_CLK_AT91_H + +#define AT91_PMC_MOSCS 0 /* MOSCS Flag */ +#define AT91_PMC_LOCKA 1 /* PLLA Lock */ +#define AT91_PMC_LOCKB 2 /* PLLB Lock */ +#define AT91_PMC_MCKRDY3 /* Master Clock */ +#define AT91_PMC_LOCKU 6 /* UPLL Lock */ +#define AT91_PMC_PCKRDY(id)(8 + (id)) /* Programmable Clock */ +#define AT91_PMC_MOSCSELS 16 /* Main Oscillator Selection */ +#define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */ +#define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */ + +#endif -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v6 10/16] clk: at91: add PMC programmable clocks
This patch adds new at91 programmable clocks implementation using common clk framework. A programmable clock is a clock which can be exported on a given pin to clock external devices. Each programmable clock is given an id (from 0 to 8). The number of available programmable clocks depends on the SoC you're using. Programmable clock driver only implements the clock setting (clock rate and parent setting). It must be chained to a system clock in order to enable/disable the generated clock. The PCKX pins used to output the clock signals must be assigned to the appropriate peripheral (see atmel's datasheets). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |2 + drivers/clk/at91/clk-programmable.c | 366 +++ drivers/clk/at91/pmc.c | 15 ++ drivers/clk/at91/pmc.h |9 + 4 files changed, 392 insertions(+) create mode 100644 drivers/clk/at91/clk-programmable.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 04deba3..3873b62 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -5,3 +5,5 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o obj-y += clk-system.o clk-peripheral.o + +obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c new file mode 100644 index 000..fd792b2 --- /dev/null +++ b/drivers/clk/at91/clk-programmable.c @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h +#include linux/io.h +#include linux/wait.h +#include linux/sched.h +#include linux/interrupt.h +#include linux/irq.h + +#include pmc.h + +#define PROG_SOURCE_MAX5 +#define PROG_ID_MAX7 + +#define PROG_STATUS_MASK(id) (1 ((id) + 8)) +#define PROG_PRES_MASK 0x7 +#define PROG_MAX_RM9200_CSS3 + +struct clk_programmable_layout { + u8 pres_shift; + u8 css_mask; + u8 have_slck_mck; +}; + +struct clk_programmable { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + u8 id; + u8 css; + u8 pres; + u8 slckmck; + const struct clk_programmable_layout *layout; +}; + +#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw) + + +static irqreturn_t clk_programmable_irq_handler(int irq, void *dev_id) +{ + struct clk_programmable *prog = (struct clk_programmable *)dev_id; + + wake_up(prog-wait); + + return IRQ_HANDLED; +} + +static int clk_programmable_prepare(struct clk_hw *hw) +{ + u32 tmp; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog-pmc; + const struct clk_programmable_layout *layout = prog-layout; + u8 id = prog-id; + u32 mask = PROG_STATUS_MASK(id); + + tmp = prog-css | (prog-pres layout-pres_shift); + if (layout-have_slck_mck prog-slckmck) + tmp |= AT91_PMC_CSSMCK_MCK; + + pmc_write(pmc, AT91_PMC_PCKR(id), tmp); + + while (!(pmc_read(pmc, AT91_PMC_SR) mask)) + wait_event(prog-wait, pmc_read(pmc, AT91_PMC_SR) mask); + + return 0; +} + +static int clk_programmable_is_ready(struct clk_hw *hw) +{ + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog-pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_PCKR(prog-id)); +} + +static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog-pmc; + const struct clk_programmable_layout *layout = prog-layout; + + tmp = pmc_read(pmc, AT91_PMC_PCKR(prog-id)); + prog-pres = (tmp layout-pres_shift) PROG_PRES_MASK; + + return parent_rate prog-pres; +} + +static long clk_programmable_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long best_rate = *parent_rate; + unsigned long best_diff; + unsigned long new_diff; + unsigned long cur_rate; + int shift = shift; + + if (rate *parent_rate) + return *parent_rate; + else + best_diff = *parent_rate - rate
[PATCH v6 11/16] clk: at91: add PMC utmi clock
This adds new at91 utmi clock implementation using common clk framework. This clock is a pll with a fixed factor (x40). It is used as a source for usb clock. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig |7 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-utmi.c | 159 +++ drivers/clk/at91/pmc.c |7 ++ drivers/clk/at91/pmc.h |5 ++ 5 files changed, 179 insertions(+) create mode 100644 drivers/clk/at91/clk-utmi.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 85b53a4..6ad37da 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -1,5 +1,8 @@ if ARCH_AT91 +config HAVE_AT91_UTMI + bool + config HAVE_AT91_DBGU0 bool @@ -78,6 +81,7 @@ config SOC_SAMA5D3 select HAVE_FB_ATMEL select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -124,6 +128,7 @@ config SOC_AT91SAM9RL select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI config SOC_AT91SAM9G45 bool AT91SAM9G45 or AT91SAM9M10 families @@ -131,6 +136,7 @@ config SOC_AT91SAM9G45 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -141,6 +147,7 @@ config SOC_AT91SAM9X5 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 3873b62..a824883 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -7,3 +7,4 @@ obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o +obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c new file mode 100644 index 000..ae3263b --- /dev/null +++ b/drivers/clk/at91/clk-utmi.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/interrupt.h +#include linux/irq.h +#include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h +#include linux/io.h +#include linux/sched.h +#include linux/wait.h + +#include pmc.h + +#define UTMI_FIXED_MUL 40 + +struct clk_utmi { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; +}; + +#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) + +static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id) +{ + struct clk_utmi *utmi = (struct clk_utmi *)dev_id; + + wake_up(utmi-wait); + disable_irq_nosync(utmi-irq); + + return IRQ_HANDLED; +} + +static int clk_utmi_prepare(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi-pmc; + u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) | AT91_PMC_UPLLEN | + AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; + + pmc_write(pmc, AT91_CKGR_UCKR, tmp); + + while (!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_LOCKU)) { + enable_irq(utmi-irq); + wait_event(utmi-wait, + pmc_read(pmc, AT91_PMC_SR) AT91_PMC_LOCKU); + } + + return 0; +} + +static int clk_utmi_is_prepared(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi-pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_LOCKU); +} + +static void clk_utmi_unprepare(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi-pmc; + u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) ~AT91_PMC_UPLLEN; + + pmc_write(pmc, AT91_CKGR_UCKR, tmp); +} + +static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + /* UTMI clk is a fixed clk multiplier */ + return
[PATCH v6 12/16] clk: at91: add PMC usb clock
This patch adds new at91 usb clock implementation using common clk framework. This clock is used to clock usb ports (ohci, ehci and udc). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig | 11 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-usb.c | 398 drivers/clk/at91/pmc.c | 15 ++ drivers/clk/at91/pmc.h |9 + 5 files changed, 434 insertions(+) create mode 100644 drivers/clk/at91/clk-usb.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 6ad37da..b76dc4c 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -3,6 +3,9 @@ if ARCH_AT91 config HAVE_AT91_UTMI bool +config HAVE_AT91_USB_CLK + bool + config HAVE_AT91_DBGU0 bool @@ -82,6 +85,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -96,12 +100,14 @@ config SOC_AT91RM9200 select MULTI_IRQ_HANDLER select SPARSE_IRQ select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9260 bool AT91SAM9260, AT91SAM9XE or AT91SAM9G20 select HAVE_AT91_DBGU0 select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE or AT91SAM9G20 SoC. @@ -112,6 +118,7 @@ config SOC_AT91SAM9261 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. @@ -121,6 +128,7 @@ config SOC_AT91SAM9263 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9RL bool AT91SAM9RL @@ -137,6 +145,7 @@ config SOC_AT91SAM9G45 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -148,6 +157,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is @@ -161,6 +171,7 @@ config SOC_AT91SAM9N12 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using Atmel's AT91SAM9N12 SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index a824883..61db058 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -8,3 +8,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o +obj-$(CONFIG_HAVE_AT91_USB_CLK)+= clk-usb.o diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c new file mode 100644 index 000..7d1d26a --- /dev/null +++ b/drivers/clk/at91/clk-usb.c @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define USB_SOURCE_MAX 2 + +#define SAM9X5_USB_DIV_SHIFT 8 +#define SAM9X5_USB_MAX_DIV 0xf + +#define RM9200_USB_DIV_SHIFT 28 +#define RM9200_USB_DIV_TAB_SIZE4 + +struct at91sam9x5_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_usb(hw) \ + container_of(hw, struct at91sam9x5_clk_usb, hw) + +struct at91rm9200_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 divisors[4]; +}; + +#define to_at91rm9200_clk_usb(hw) \ + container_of(hw, struct at91rm9200_clk_usb, hw) + +static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 usbdiv; + struct at91sam9x5_clk_usb *usb
[PATCH v6 13/16] clk: at91: add PMC smd clock
This patch adds at91 smd (Soft Modem) clock implementation using common clk framework. Not used by any driver right now. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig |5 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-smd.c | 171 drivers/clk/at91/pmc.c |7 ++ drivers/clk/at91/pmc.h |5 ++ 5 files changed, 189 insertions(+) create mode 100644 drivers/clk/at91/clk-smd.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index b76dc4c..97033f7 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -39,6 +39,9 @@ config AT91_SAM9G45_RESET config AT91_SAM9_TIME bool +config HAVE_AT91_SMD + bool + config SOC_AT91SAM9 bool select AT91_SAM9_TIME @@ -85,6 +88,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_SMD select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. @@ -157,6 +161,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_SMD select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 61db058..0e92b71 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -9,3 +9,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o obj-$(CONFIG_HAVE_AT91_USB_CLK)+= clk-usb.o +obj-$(CONFIG_HAVE_AT91_SMD)+= clk-smd.o diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c new file mode 100644 index 000..144d47e --- /dev/null +++ b/drivers/clk/at91/clk-smd.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define SMD_SOURCE_MAX 2 + +#define SMD_DIV_SHIFT 8 +#define SMD_MAX_DIV0xf + +struct at91sam9x5_clk_smd { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_smd(hw) \ + container_of(hw, struct at91sam9x5_clk_smd, hw) + +static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 smddiv; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + tmp = pmc_read(pmc, AT91_PMC_SMD); + smddiv = (tmp AT91_PMC_SMD_DIV) SMD_DIV_SHIFT; + return parent_rate / (smddiv + 1); +} + +static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + unsigned long bestrate; + unsigned long tmp; + + if (rate = *parent_rate) + return *parent_rate; + + div = *parent_rate / rate; + if (div SMD_MAX_DIV) + return *parent_rate / (SMD_MAX_DIV + 1); + + bestrate = *parent_rate / div; + tmp = *parent_rate / (div + 1); + if (bestrate - rate rate - tmp) + bestrate = tmp; + + return bestrate; +} + +static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + if (index 1) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_SMD) ~AT91_PMC_SMDS; + if (index) + tmp |= AT91_PMC_SMDS; + pmc_write(pmc, AT91_PMC_SMD, tmp); + return 0; +} + +static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw) +{ + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + return pmc_read(pmc, AT91_PMC_SMD) AT91_PMC_SMDS; +} + +static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate || div
[PATCH v6 14/16] dt: binding: add at91 clks dt bindings documentation
This patch adds new at91 clks dt bindings documentation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- .../devicetree/bindings/clock/at91-clock.txt | 339 1 file changed, 339 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/at91-clock.txt diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt new file mode 100644 index 000..cd5e239 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt @@ -0,0 +1,339 @@ +Device Tree Clock bindings for arch-at91 + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible : shall be one of the following: + atmel,at91rm9200-pmc or + atmel,at91sam9g45-pmc or + atmel,at91sam9n12-pmc or + atmel,at91sam9x5-pmc or + atmel,sama5d3-pmc: + at91 PMC (Power Management Controller) + All at91 specific clocks (clocks defined below) must be child + node of the PMC node. + + atmel,at91rm9200-clk-main: + at91 main oscillator + + atmel,at91rm9200-clk-master or + atmel,at91sam9x5-clk-master: + at91 master clock + + atmel,at91sam9x5-clk-peripheral or + atmel,at91rm9200-clk-peripheral: + at91 peripheral clocks + + atmel,at91rm9200-clk-pll or + atmel,at91sam9g45-clk-pll or + atmel,at91sam9g20-clk-pllb or + atmel,sama5d3-clk-pll: + at91 pll clocks + + atmel,at91sam9x5-clk-plldiv: + at91 plla divisor + + atmel,at91rm9200-clk-programmable or + atmel,at91sam9g45-clk-programmable or + atmel,at91sam9x5-clk-programmable: + at91 programmable clocks + + atmel,at91sam9x5-clk-smd: + at91 SMD (Soft Modem) clock + + atmel,at91rm9200-clk-system: + at91 system clocks + + atmel,at91rm9200-clk-usb or + atmel,at91sam9x5-clk-usb or + atmel,at91sam9n12-clk-usb: + at91 usb clock + + atmel,at91sam9x5-clk-utmi: + at91 utmi clock + +Required properties for PMC node: +- reg : defines the IO memory reserved for the PMC. +- #size-cells : shall be 0 (reg is used to encode clk id). +- #address-cells : shall be 1 (reg is used to encode clk id). +- interrupts : shall be set to PMC interrupt line. +- interrupt-controller : tell that the PMC is an interrupt controller. +- #interrupt-cells : must be set to 1. The first cell encodes the interrupt id, + and reflect the bit position in the PMC_ER/DR/SR registers. + You can use the dt macros defined in dt-bindings/clk/at91.h. + 0 (AT91_PMC_MOSCS) - main oscillator ready + 1 (AT91_PMC_LOCKA) - PLL A ready + 2 (AT91_PMC_LOCKB) - PLL B ready + 3 (AT91_PMC_MCKRDY) - master clock ready + 6 (AT91_PMC_LOCKU) - UTMI PLL clock ready + 8 .. 15 (AT91_PMC_PCKRDY(id)) - programmable clock ready + 16 (AT91_PMC_MOSCSELS) - main oscillator selected + 17 (AT91_PMC_MOSCRCS) - RC main oscillator stabilized + 18 (AT91_PMC_CFDEV) - clock failure detected + +For example: + pmc: pmc@fc00 { + compatible = atmel,sama5d3-pmc; + interrupts = 1 4 7; + interrupt-controller; + #interrupt-cells = 2; + #size-cells = 0; + #address-cells = 1; + + /* put at91 clocks here */ + }; + +Required properties for main clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to 0. +- #clock-cells : from common clock binding; shall be set to 0. +- clocks (optional if clock-frequency is provided) : shall be the slow clock + phandle. This clock is used to calculate the main clock rate if + clock-frequency is not provided. +- clock-frequency : the main oscillator frequency.Prefer the use of + clock-frequency over automatic clock rate calculation. + +For example: + main: mainck { + compatible = atmel,at91rm9200-clk-main; + interrupt-parent = pmc; + interrupts = 0; + #clock-cells = 0; + clocks = ck32k; + clock-frequency = 18432000; + }; + +Required properties for master clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to 3. +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the master clock sources (see atmel datasheet) phandles. + e.g. ck32k, main, plla, pllb. +- atmel,clk-output-range : minimum and maximum clock frequency (two u32 + fields). + e.g. output = 0 13300; = 0 to 133MHz. +- atmel,clk-divisors : master clock divisors table (four u32 fields). + 0 = reserved
[PATCH v6 15/16] ARM: at91: move pit timer to common clk framework
Use device tree to get the source clock of the PIT (Periodic Interval Timer). If the clock is not found in device tree (or dt is not enabled) we'll try to get it using clk_lookup definitions. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/at91sam926x_time.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index bb39232..0f04ffe 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c @@ -39,6 +39,7 @@ static u32 pit_cycle; /* write-once */ static u32 pit_cnt;/* access only w/system irq blocked */ static void __iomem *pit_base_addr __read_mostly; +static struct clk *mck; static inline unsigned int pit_read(unsigned int reg_offset) { @@ -195,10 +196,14 @@ static int __init of_at91sam926x_pit_init(void) if (!pit_base_addr) goto node_err; + mck = of_clk_get(np, 0); + /* Get the interrupts property */ ret = irq_of_parse_and_map(np, 0); if (!ret) { pr_crit(AT91: PIT: Unable to get IRQ from DT\n); + if (!IS_ERR(mck)) + clk_put(mck); goto ioremap_err; } at91sam926x_pit_irq.irq = ret; @@ -230,6 +235,8 @@ void __init at91sam926x_pit_init(void) unsignedbits; int ret; + mck = ERR_PTR(-ENOENT); + /* For device tree enabled device: initialize here */ of_at91sam926x_pit_init(); @@ -237,7 +244,12 @@ void __init at91sam926x_pit_init(void) * Use our actual MCK to figure out how many MCK/16 ticks per * 1/HZ period (instead of a compile-time constant LATCH). */ - pit_rate = clk_get_rate(clk_get(NULL, mck)) / 16; + if (IS_ERR(mck)) + mck = clk_get(NULL, mck); + + if (IS_ERR(mck)) + panic(AT91: PIT: Unable to get mck clk\n); + pit_rate = clk_get_rate(mck) / 16; pit_cycle = (pit_rate + HZ/2) / HZ; WARN_ON(((pit_cycle - 1) ~AT91_PIT_PIV) != 0); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v6 16/16] ARM: at91: add new compatible strings for pmc driver
This patch adds new compatible string for PMC node to prepare the transition to common clk. These compatible string come from pmc driver in clk subsystem and are needed to provide new device tree compatibility with old at91 clks (device tree using common clks will use the new compatible strings). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/clock.c |5 + 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 5f02aea..72b2579 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -884,6 +884,11 @@ static int __init at91_pmc_init(unsigned long main_clock) #if defined(CONFIG_OF) static struct of_device_id pmc_ids[] = { { .compatible = atmel,at91rm9200-pmc }, + { .compatible = atmel,at91sam9260-pmc }, + { .compatible = atmel,at91sam9g45-pmc }, + { .compatible = atmel,at91sam9n12-pmc }, + { .compatible = atmel,at91sam9x5-pmc }, + { .compatible = atmel,sama5d3-pmc }, { /*sentinel*/ } }; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 1/6] ARM: at91: prepare sama5 dt boards transition to common clk
This patch prepare the transition to common clk for sama5 dt boards by replacing the timer init callback. Clocks registration cannot be done in early init callback (as formerly done by the old clk implementation) because it requires dynamic allocation which is not ready yet during early init. In the other hand, at91 clocks must be registered before at91sam926x_pit_init is called because PIT (Periodic Interval Timer) driver request the master clk (mck). A new function (at91sama5_dt_timer_init) is created to fullfil these needs. This function registers all at91 clks using the dt definition before calling the PIT init function. The device tree clock registration is enabled only if common clk is selected. Else the old clk registration is been done during at91_dt_initialize call. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/board-dt-sama5.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/board-dt-sama5.c index bf00d15..075ec05 100644 --- a/arch/arm/mach-at91/board-dt-sama5.c +++ b/arch/arm/mach-at91/board-dt-sama5.c @@ -16,6 +16,7 @@ #include linux/of_irq.h #include linux/of_platform.h #include linux/phy.h +#include linux/clk-provider.h #include asm/setup.h #include asm/irq.h @@ -26,6 +27,13 @@ #include at91_aic.h #include generic.h +static void __init sama5_dt_timer_init(void) +{ +#if defined(CONFIG_COMMON_CLK) + of_clk_init(NULL); +#endif + at91sam926x_pit_init(); +} static const struct of_device_id irq_of_match[] __initconst = { @@ -72,7 +80,7 @@ static const char *sama5_dt_board_compat[] __initdata = { DT_MACHINE_START(sama5_dt, Atmel SAMA5 (Device Tree)) /* Maintainer: Atmel */ - .init_time = at91sam926x_pit_init, + .init_time = sama5_dt_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic5_handle_irq, .init_early = at91_dt_initialize, -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 3/6] ARM: at91/dt: define sama5d3 clocks
Define sama5d3 clocks in sama5d3 device tree. Add references to the appropriate clocks in each peripheral. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/boot/dts/sama5d3.dtsi | 379 ++- arch/arm/boot/dts/sama5d3_can.dtsi | 20 ++ arch/arm/boot/dts/sama5d3_emac.dtsi | 11 + arch/arm/boot/dts/sama5d3_gmac.dtsi | 11 + arch/arm/boot/dts/sama5d3_lcd.dtsi | 17 ++ arch/arm/boot/dts/sama5d3_mci2.dtsi | 12 ++ arch/arm/boot/dts/sama5d3_tcb1.dtsi | 12 ++ arch/arm/boot/dts/sama5d3_uart.dtsi | 21 ++ 8 files changed, 482 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 5cdaba4..f0dbed0 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -13,6 +13,7 @@ #include dt-bindings/pinctrl/at91.h #include dt-bindings/interrupt-controller/irq.h #include dt-bindings/gpio/gpio.h +#include dt-bindings/clk/at91.h / { model = Atmel SAMA5D3 family SoC; @@ -56,6 +57,14 @@ reg = 0x2000 0x800; }; + clocks { + adc_op_clk: adc_op_clk{ + compatible = fixed-clock; + #clock-cells = 0; + clock-frequency = 2000; + }; + }; + ahb { compatible = simple-bus; #address-cells = 1; @@ -79,6 +88,8 @@ status = disabled; #address-cells = 1; #size-cells = 0; + clocks = mci0_clk; + clock-names = mci_clk; }; spi0: spi@f0004000 { @@ -92,6 +103,8 @@ dma-names = tx, rx; pinctrl-names = default; pinctrl-0 = pinctrl_spi0; + clocks = spi0_clk; + clock-names = spi_clk; status = disabled; }; @@ -101,6 +114,8 @@ interrupts = 38 IRQ_TYPE_LEVEL_HIGH 4; pinctrl-names = default; pinctrl-0 = pinctrl_ssc0_tx pinctrl_ssc0_rx; + clocks = ssc0_clk; + clock-names = pclk; status = disabled; }; @@ -108,6 +123,8 @@ compatible = atmel,at91sam9x5-tcb; reg = 0xf001 0x100; interrupts = 26 IRQ_TYPE_LEVEL_HIGH 0; + clocks = tcb0_clk; + clock-names = t0_clk; }; i2c0: i2c@f0014000 { @@ -121,6 +138,7 @@ pinctrl-0 = pinctrl_i2c0; #address-cells = 1; #size-cells = 0; + clocks = twi0_clk; status = disabled; }; @@ -135,6 +153,7 @@ pinctrl-0 = pinctrl_i2c1; #address-cells = 1; #size-cells = 0; + clocks = twi1_clk; status = disabled; }; @@ -144,6 +163,8 @@ interrupts = 12 IRQ_TYPE_LEVEL_HIGH 5; pinctrl-names = default; pinctrl-0 = pinctrl_usart0; + clocks = usart0_clk; + clock-names = usart; status = disabled; }; @@ -153,6 +174,8 @@ interrupts = 13 IRQ_TYPE_LEVEL_HIGH 5; pinctrl-names = default; pinctrl-0 = pinctrl_usart1; + clocks = usart1_clk; + clock-names = usart; status = disabled; }; @@ -174,6 +197,8 @@ status = disabled; #address-cells = 1; #size-cells = 0; + clocks = mci1_clk; + clock-names = mci_clk; }; spi1: spi@f8008000 { @@ -187,6 +212,8 @@ dma-names = tx, rx; pinctrl-names = default; pinctrl-0 = pinctrl_spi1; + clocks = spi1_clk
[PATCH v4 4/6] ARM: at91/dt: define sama5d3xek's main clk frequency
Define the main clock frequency for the new main clock node in sama5d3xcm.dtsi. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/boot/dts/sama5d3xcm.dtsi |6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi index 726a0f3..dce5419 100644 --- a/arch/arm/boot/dts/sama5d3xcm.dtsi +++ b/arch/arm/boot/dts/sama5d3xcm.dtsi @@ -38,6 +38,12 @@ macb0: ethernet@f0028000 { phy-mode = rgmii; }; + + pmc: pmc@fc00 { + main: mainck { + clock-frequency = 1200; + }; + }; }; nand0: nand@6000 { -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 6/6] ARM: at91/dt: remove old clk material
This patch removes the old main clk node which is now useless as sama5d3 SoCs and boards are no longer compatible with the old at91 clk implementations. It also remove old clock definitions (clock definitions using at91 old clk framework). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/boot/dts/sama5d3xcm.dtsi | 11 -- arch/arm/mach-at91/sama5d3.c | 346 - 2 files changed, 357 deletions(-) diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi index dce5419..f55ed07 100644 --- a/arch/arm/boot/dts/sama5d3xcm.dtsi +++ b/arch/arm/boot/dts/sama5d3xcm.dtsi @@ -18,17 +18,6 @@ reg = 0x2000 0x2000; }; - clocks { - #address-cells = 1; - #size-cells = 1; - ranges; - - main_clock: clock@0 { - compatible = atmel,osc, fixed-clock; - clock-frequency = 1200; - }; - }; - ahb { apb { spi0: spi@f0004000 { diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c index 3426098..ae58fea 100644 --- a/arch/arm/mach-at91/sama5d3.c +++ b/arch/arm/mach-at91/sama5d3.c @@ -21,349 +21,6 @@ #include generic.h #include sam9_smc.h -#if defined(CONFIG_OLD_CLK_AT91) -#include clock.h -/* - * Clocks - * */ - -/* - * The peripheral clocks. - */ - -static struct clk pioA_clk = { - .name = pioA_clk, - .pid= SAMA5D3_ID_PIOA, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk pioB_clk = { - .name = pioB_clk, - .pid= SAMA5D3_ID_PIOB, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk pioC_clk = { - .name = pioC_clk, - .pid= SAMA5D3_ID_PIOC, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk pioD_clk = { - .name = pioD_clk, - .pid= SAMA5D3_ID_PIOD, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk pioE_clk = { - .name = pioE_clk, - .pid= SAMA5D3_ID_PIOE, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk usart0_clk = { - .name = usart0_clk, - .pid= SAMA5D3_ID_USART0, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk usart1_clk = { - .name = usart1_clk, - .pid= SAMA5D3_ID_USART1, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk usart2_clk = { - .name = usart2_clk, - .pid= SAMA5D3_ID_USART2, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk usart3_clk = { - .name = usart3_clk, - .pid= SAMA5D3_ID_USART3, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk uart0_clk = { - .name = uart0_clk, - .pid= SAMA5D3_ID_UART0, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk uart1_clk = { - .name = uart1_clk, - .pid= SAMA5D3_ID_UART1, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk twi0_clk = { - .name = twi0_clk, - .pid= SAMA5D3_ID_TWI0, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk twi1_clk = { - .name = twi1_clk, - .pid= SAMA5D3_ID_TWI1, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk twi2_clk = { - .name = twi2_clk, - .pid= SAMA5D3_ID_TWI2, - .type = CLK_TYPE_PERIPHERAL, - .div= AT91_PMC_PCR_DIV2, -}; -static struct clk mmc0_clk = { - .name = mci0_clk, - .pid= SAMA5D3_ID_HSMCI0, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk mmc1_clk = { - .name = mci1_clk, - .pid= SAMA5D3_ID_HSMCI1, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk mmc2_clk = { - .name = mci2_clk, - .pid= SAMA5D3_ID_HSMCI2, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk spi0_clk = { - .name = spi0_clk, - .pid= SAMA5D3_ID_SPI0, - .type = CLK_TYPE_PERIPHERAL
[PATCH v4 2/6] ARM: at91: prepare common clk transition for sama5d3 SoC
This patch encloses sama5d3 old clk registration in #if defined(CONFIG_OLD_CLK_AT91) #endif sections. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/sama5d3.c |6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c index 0003949..3426098 100644 --- a/arch/arm/mach-at91/sama5d3.c +++ b/arch/arm/mach-at91/sama5d3.c @@ -19,9 +19,10 @@ #include soc.h #include generic.h -#include clock.h #include sam9_smc.h +#if defined(CONFIG_OLD_CLK_AT91) +#include clock.h /* * Clocks * */ @@ -361,6 +362,7 @@ static void __init sama5d3_register_clocks(void) clk_register(pck1); clk_register(pck2); } +#endif /* * AT91SAM9x5 processor initialization @@ -373,5 +375,7 @@ static void __init sama5d3_map_io(void) AT91_SOC_START(sama5d3) .map_io = sama5d3_map_io, +#if defined(CONFIG_OLD_CLK_AT91) .register_clocks = sama5d3_register_clocks, +#endif AT91_SOC_END -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 0/6] ARM: at91: use new at91 clks for samad3 SoCs
Hello, This patch series moves sama5d3 SoCs and boards to the new at91 clk framework (based on common clk framework). Best Regards, Boris Changes since v3: - fix prog clks declaration Changes since v2: - rework dt bindings: * replace atmel,clk-id property by the standard reg property * reference system, peripheral and programmable clks using the direct clk node instead of the parent node plus a clk id - add usb_clk to usb ehci controller node Changes since v1: - remove references to peripheral id macros - remove old clk definitions after moving to new clk framework Boris BREZILLON (6): ARM: at91: prepare sama5 dt boards transition to common clk ARM: at91: prepare common clk transition for sama5d3 SoC ARM: at91/dt: define sama5d3 clocks ARM: at91/dt: define sama5d3xek's main clk frequency ARM: at91: move sama5d3 SoC to common clk ARM: at91/dt: remove old clk material arch/arm/boot/dts/sama5d3.dtsi | 379 ++- arch/arm/boot/dts/sama5d3_can.dtsi | 20 ++ arch/arm/boot/dts/sama5d3_emac.dtsi | 11 + arch/arm/boot/dts/sama5d3_gmac.dtsi | 11 + arch/arm/boot/dts/sama5d3_lcd.dtsi | 17 ++ arch/arm/boot/dts/sama5d3_mci2.dtsi | 12 ++ arch/arm/boot/dts/sama5d3_tcb1.dtsi | 12 ++ arch/arm/boot/dts/sama5d3_uart.dtsi | 21 ++ arch/arm/boot/dts/sama5d3xcm.dtsi | 17 +- arch/arm/mach-at91/Kconfig |1 - arch/arm/mach-at91/board-dt-sama5.c | 10 +- arch/arm/mach-at91/sama5d3.c| 342 --- 12 files changed, 497 insertions(+), 356 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 5/6] ARM: at91: move sama5d3 SoC to common clk
This patch removes the selection of AT91_USE_OLD_CLK when selecting sama5d3 SoC support. This will enable automatically enable COMMON_CLK_AT91 option and add support for at91 common clk implementation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig |1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 97033f7..b4f7d6f 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -86,7 +86,6 @@ config SOC_SAMA5D3 select SOC_SAMA5 select HAVE_FB_ATMEL select HAVE_AT91_DBGU1 - select AT91_USE_OLD_CLK select HAVE_AT91_UTMI select HAVE_AT91_SMD select HAVE_AT91_USB_CLK -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 5/9] ARM: at91/dt: add mmc0 slot0 support to at91rm9200ek board
Hello Linus, On 29/11/2013 11:03, Linus Walleij wrote: På tisdag, 26 Nov, 2013 vid 6:11 PM, skrev boris brezillon b.brezil...@overkiz.com: Le 26/11/2013 14:46, Linus Walleij a écrit : But in this case it is a mechanical switch rather than a jumper? Not exactly. The functionnaly selection (spi device or mmc slot) is done by the software using to the PB22 pin: - set PB22 pin to 1 if you want to enable the mmc slot - set PB22 pin to 0 if you want to enable the spi device OK I got it wrong, I thought it was a mechanical switch. So this is a GPIO line somekindof, you control it like this, and it will have effects on the electronics. So to get the device running you need to both: - Switch the value of this GPIO line. - Switch pin control state. We are certain that the gpio_set_value() shall be used to set that GPIO line, because it does not control any pin control logic, it controls some electronics outside of the SoC, and that is outside the pin controller domain. I guess one way is to obtain this GPIO in board code and just flick it depending on which device you register. You can have GPIOs tied to the machine/board itself, see this fragment from arch/arm/boot/dts/ste-nomadik-s8815.dts: /* Custom board node with GPIO pins to active etc */ usb-s8815 { /* This will bias the MMC/SD card detect line */ mmcsd-gpio { gpios = gpio3 16 0x1; }; }; This GPIO needs to be driven high to bias the MMC/SD card. I solved it like this in the board code in arch/arm/mach-nomadik/cpu-8815.c: /* * This GPIO pin turns on a line that is used to detect card insertion * on this board. */ static int __init cpu8815_mmcsd_init(void) { struct device_node *cdbias; int gpio, err; cdbias = of_find_node_by_path(/usb-s8815/mmcsd-gpio); if (!cdbias) { pr_info(could not find MMC/SD card detect bias node\n); return 0; } gpio = of_get_gpio(cdbias, 0); if (gpio 0) { pr_info(could not obtain MMC/SD card detect bias GPIO\n); return 0; } err = gpio_request(gpio, card detect bias); if (err) { pr_info(failed to request card detect bias GPIO %d\n, gpio); return -ENODEV; } err = gpio_direction_output(gpio, 0); if (err){ pr_info(failed to set GPIO %d as output, low\n, gpio); return err; } pr_info(enabled USB-S8815 CD bias GPIO %d, low\n, gpio); return 0; } device_initcall(cpu8815_mmcsd_init); This is maybe not a perfect approach :-/ But you get the idea. You could set this up one way or another depending on whether this board is registering a device for SPI or MMC. The whole goal of moving from board files to dt is to drop all board specific processing or initialization and only keep a common description with generic drivers capable of handling common use cases. I'm not sure providing new board specific drivers is a good solution (even if it is the simplest way to achieve our goal). Could we have something similar to pinctrl but with gpios : when the device is probed the device/driver core code request the gpio configure it appropriately and set it to the requested value (if configured as output). Or even better, provide an external switch subsystem (with a gpio-switch driver) and automate switch request/config in device/driver core code (as done for the pinctrl config). These are just thoughts, and I guess introducing new code in the device/driver core code is not that easy, especially when this code is here to handle specific case like ours. Thanks for sharing your thoughts. Best Regards, Boris Probably Jean-Christophe has opinions on this so let's see what he says. If I understand correctly, you're suggesting to retrieve the PB22 pin value to decide wether the mmc slot or the spi device is enabled. Is that right ? Forget about this, I didn't understand the real problem. In the board version this was configured in the init_machine function (or board init function) depending on the MTD_AT91_DATAFLASH_CARD ( http://lxr.free-electrons.com/source/arch/arm/mach-at91/board-rm9200ek.c#L173). As a result it was not reconfigurable at runtime. But Jean-Christophe suggested to make it configurable at runtime (using dt fragments). It should definately be set up at runtime, just a matter where and how. Yours, Linus Walleij -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 5/9] ARM: at91/dt: add mmc0 slot0 support to at91rm9200ek board
On 29/11/2013 14:31, Linus Walleij wrote: On Fri, Nov 29, 2013 at 11:30 AM, boris brezillon b.brezil...@overkiz.com wrote: On 29/11/2013 11:03, Linus Walleij wrote: I guess one way is to obtain this GPIO in board code and just flick it depending on which device you register. (...) The whole goal of moving from board files to dt is to drop all board specific processing or initialization and only keep a common description with generic drivers capable of handling common use cases. I'm not sure providing new board specific drivers is a good solution (even if it is the simplest way to achieve our goal). Could we have something similar to pinctrl but with gpios : when the device is probed the device/driver core code request the gpio configure it appropriately and set it to the requested value (if configured as output). This has been suggested under the name GPIO hogs in the past. It would work similar to how pinctrl hogs work by associating the GPIO line the controller itself, using some specific string like gpio-input-hogs = ... / gpio-output-hogs = ...; The gpiolib core will then grab and set up these before returning from the registration call so noone ever gets a chance to use them. Ok, I'll take a look. Could you point me out a thread (or other documents) talking about gpio hogs. I found this one http://lists.infradead.org/pipermail/linux-arm-kernel/2013-April/162254.html. These are just thoughts, and I guess introducing new code in the device/driver core code is not that easy, especially when this code is here to handle specific case like ours. It is very easy, just write the patch, iterate it (these patches get a lot of scrutiny as it is core code, so expect some work and time to get it done), and then unless there is a blocker, I would merge it. The concept is entirely sound, just that someone needs to step up and do the work... Sure, I'll propose something (I guess your talking about GPIO hogs concept not gpio-switch driver). If you already thought a bit about GPIO hogs, I'd be interested to get some inputs (suggestions, ideas, code, ...). Anyway, thanks for taking time to answer my questions. Best Reagrds, Boris Yours, Linus Walleij -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: at91: add usart3 alias to dtsi
Hi Nicolas, Le 02/12/2013 11:13, Nicolas Ferre a écrit : Alias was missing for SoC of the at91sam9x5 familly that embed USART3. Preripheral node and pinctrl declarations are already in the at91sam9x5_usart3.dtsi file. Reported-by: Jiri Prchal jiri.prc...@aksignal.cz Signed-off-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/boot/dts/at91sam9g25.dtsi | 4 arch/arm/boot/dts/at91sam9x25.dtsi | 4 2 files changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/at91sam9g25.dtsi b/arch/arm/boot/dts/at91sam9g25.dtsi index 17b879990914..d4650b4e9ebb 100644 --- a/arch/arm/boot/dts/at91sam9g25.dtsi +++ b/arch/arm/boot/dts/at91sam9g25.dtsi @@ -14,6 +14,10 @@ model = Atmel AT91SAM9G25 SoC; compatible = atmel,at91sam9g25, atmel,at91sam9x5; + aliases { + serial4 = usart3; + }; + Shouldn't this go into at91sam9x5_usart3.dtsi ? This way you would have the same alias for all the SoCs supporting usart3. Best Regards, Boris ahb { apb { pinctrl@f400 { diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/at91sam9x25.dtsi index c2554219f7a4..aceee86f60eb 100644 --- a/arch/arm/boot/dts/at91sam9x25.dtsi +++ b/arch/arm/boot/dts/at91sam9x25.dtsi @@ -15,6 +15,10 @@ model = Atmel AT91SAM9X25 SoC; compatible = atmel,at91sam9x25, atmel,at91sam9x5; + aliases { + serial4 = usart3; + }; + ahb { apb { pinctrl@f400 { -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v6 00/16] ARM: at91: move to common clk framework
Hi Mike, Le 01/12/2013 00:05, Mike Turquette a écrit : Quoting Boris BREZILLON (2013-11-28 04:36:24) Hello, This patch series is the 5th version of the at91 clk implementations using the Common Clk Framework. Oops, I just replied to v5 of this series. Thanks for the fixes. Which tree do you want this to go through? I'm not sure: the ARM: at91: move to common clk framework series depends on this one. Nicolas, what do you think ? Do you want to take it into your tree ? Regards, Mike Most of the clock provided by the PMC (Power Management Controller) are implemented : - main clock (main oscillator) - pll clocks - master clock - programmable clocks - utmi clock - peripheral clocks - system clocks Actually some clk drivers are missing (slow clk, main clk and processor clk), and some drivers only implement a subset of the hardware capabilities (master clk rate change is missing). But this series implements all the already available clks, and I will hopefully add missing features in a near future. This implementation is only compatible with device tree definition. The goal is to define the whole clock tree using the device tree. Just a note to let you know these bindings are currently unstable and might change in the future. Best Regards, Boris Changes since v5: - remove peripheral divisors macros from dt binding include file - remove file path from comment blocks - replace pll and utmi disable function by unprepare function to avoid issue when disabling and reenabling a clk - fix programmable clk interrupt retrieval - fix OF_CLK_DECLARE names (xxx_clk_main - xxx_clk_pmc) - add missing comma in at91rm9200 main clk dt declaration - fix num_parents check in smd clk driver Changes since v4: - rework dt bindings: * replace atmel,clk-id property by the standard reg property * reference system, peripheral and programmable clks using the direct clk node instead of the parent node plus a clk id - provide a new helper function (of_at91_get_clk_range) to retrieve a clk range from the device tree Changes since v3: - simplify master clk implementation (drop set_rate/parent support) - fix bug in set_rate function of pll driver - fix coding style issues - define macros and constants where needed - remove peripheral id macro references - remove sam9g35 specific handling (sam9g35 = sam9x5) - rework main clk prepare function to handle automatic rate calculation Changes since v2: - fix several bugs in clk implementations - drop non-dt boards support - split the series to ease review and tests: * 1 patch series for new clk implementations (this series) * 1 patch series to move each at91 SoC to common clk framework (coming soon) - modify dt-bindings (add atmel,clk- prefix to atmel specific properties) - add clk macros for dt-bindings - add pmc framework (helper function to access pmc registers) - add interrupt support to enable passive wait in clk_prepare functions Changes since v1: - fix bugs in pll, programmable and system clock implementations (wrong bit position). - add usb clock configuration support (ohci and udc drivers + clk_lookup for non dt boards) - rework of the system clock interfaces (no need to define a parent clock, system clock is a gate with no rate info) - change system, peripheral and programmable clk dt bindings (1 master node and multiple child nodes each defining a system/peripheral or prog clock) - fix bugs in sama5 dt definition Boris BREZILLON (16): ARM: at91: move at91_pmc.h to include/linux/clk/at91_pmc.h ARM: at91: add Kconfig options for common clk support clk: at91: add PMC base support clk: at91: add PMC macro file for dt definitions clk: at91: add PMC main clock clk: at91: add PMC pll clocks clk: at91: add PMC master clock clk: at91: add PMC system clocks clk: at91: add PMC peripheral clocks clk: at91: add PMC programmable clocks clk: at91: add PMC utmi clock clk: at91: add PMC usb clock clk: at91: add PMC smd clock dt: binding: add at91 clks dt bindings documentation ARM: at91: move pit timer to common clk framework ARM: at91: add new compatible strings for pmc driver .../devicetree/bindings/clock/at91-clock.txt | 339 + arch/arm/mach-at91/Kconfig | 44 ++ arch/arm/mach-at91/Kconfig.non_dt |6 + arch/arm/mach-at91/Makefile|2 +- arch/arm/mach-at91/at91rm9200.c|2 +- arch/arm/mach-at91/at91sam9260.c |2 +- arch/arm/mach-at91/at91sam9261.c |2 +- arch/arm/mach-at91/at91sam9263.c |2 +- arch/arm/mach-at91/at91sam926x_time.c | 14 +- arch/arm/mach-at91/at91sam9g45.c |2 +- arch/arm/mach-at91/at91sam9n12.c |2 +- arch/arm/mach-at91/at91sam9rl.c|2 +- arch
Re: [PATCH v2 1/2] clk: add clk accuracy retrieval support
Hello Uwe, Le 02/12/2013 08:50, Uwe Kleine-König a écrit : Hello, On Wed, Nov 27, 2013 at 01:44:44PM +0100, Boris BREZILLON wrote: The clock accuracy is expressed in ppb (parts per billion) and represents the possible clock drift. Say you have a clock (e.g. an oscillator) which provides a fixed clock of 20MHz with an accuracy of +- 20Hz. This accuracy expressed in ppb is 20Hz/20MHz = 1000 ppb (or 1 ppm). Clock users may need the clock accuracy information in order to choose the best clock (the one with the best accuracy) across several available clocks. This patch adds clk accuracy retrieval support for common clk framework by means of a new function called clk_get_accuracy. This function returns the given clock accuracy expressed in ppb. In order to get the clock accuracy, this implementation adds one callback called recalc_accuracy to the clk_ops structure. This callback is given the parent clock accuracy (if the clock is not a root clock) and should recalculate the given clock accuracy. This callback is optional and may be implemented if the clock is not a perfect clock (accuracy != 0 ppb). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- Documentation/clk.txt|4 ++ drivers/clk/clk.c| 109 -- include/linux/clk-private.h |1 + include/linux/clk-provider.h | 11 + include/linux/clk.h | 17 +++ 5 files changed, 138 insertions(+), 4 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 3aeb5c4..eb20198 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -77,6 +77,8 @@ the operations defined in clk.h: int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long); + unsigned long (*recalc_accuracy)(struct clk_hw *hw, + unsigned long parent_accuracy); void(*init)(struct clk_hw *hw); }; @@ -202,6 +204,8 @@ optional or must be evaluated on a case-by-case basis. .set_parent | | | n | y | n| .get_parent | | | n | y | n| | | | | | | +.recalc_accuracy| | | | | | +| | | | | | .init | | | | | | --- [1] either one of round_rate or determine_rate is required. diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2cf2ea6..4b0c1bc 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -104,10 +104,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) if (!c) return; - seq_printf(s, %*s%-*s %-11d %-12d %-10lu, + seq_printf(s, %*s%-*s %-11d %-12d %-10lu %-11lu, level * 3 + 1, , 30 - level * 3, c-name, - c-enable_count, c-prepare_count, clk_get_rate(c)); + c-enable_count, c-prepare_count, clk_get_rate(c), + clk_get_accuracy(c)); seq_printf(s, \n); } @@ -129,8 +130,8 @@ static int clk_summary_show(struct seq_file *s, void *data) { struct clk *c; - seq_printf(s,clockenable_cnt prepare_cnt rate\n); - seq_printf(s, -\n); + seq_printf(s,clockenable_cnt prepare_cnt rate accuracy\n); + seq_printf(s, -\n); clk_prepare_lock(); @@ -167,6 +168,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level) seq_printf(s, \enable_count\: %d,, c-enable_count); seq_printf(s, \prepare_count\: %d,, c-prepare_count); seq_printf(s, \rate\: %lu, clk_get_rate(c)); + seq_printf(s, \accuracy\: %lu, clk_get_accuracy(c)); } static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) @@ -248,6 +250,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) if (!d) goto err_out; + d = debugfs_create_u32(clk_accuracy, S_IRUGO, clk-dentry, + (u32 *)clk-accuracy); + if (!d) + goto err_out; + d = debugfs_create_x32(clk_flags, S_IRUGO, clk-dentry, (u32 *)clk-flags); if (!d) @@ -602,6 +609,28 @@ out: return ret; } +unsigned long __clk_get_accuracy(struct clk *clk) +{ + unsigned long ret
Re: [PATCH v6 00/16] ARM: at91: move to common clk framework
On 02/12/2013 12:43, boris brezillon wrote: Hi Mike, Le 01/12/2013 00:05, Mike Turquette a écrit : Quoting Boris BREZILLON (2013-11-28 04:36:24) Hello, This patch series is the 5th version of the at91 clk implementations using the Common Clk Framework. Oops, I just replied to v5 of this series. Thanks for the fixes. Which tree do you want this to go through? I'm not sure: the ARM: at91: move to common clk framework series Oops. I meant ARM: at91: use new at91 clks for samad3 SoCs. depends on this one. Nicolas, what do you think ? Do you want to take it into your tree ? Regards, Mike Most of the clock provided by the PMC (Power Management Controller) are implemented : - main clock (main oscillator) - pll clocks - master clock - programmable clocks - utmi clock - peripheral clocks - system clocks Actually some clk drivers are missing (slow clk, main clk and processor clk), and some drivers only implement a subset of the hardware capabilities (master clk rate change is missing). But this series implements all the already available clks, and I will hopefully add missing features in a near future. This implementation is only compatible with device tree definition. The goal is to define the whole clock tree using the device tree. Just a note to let you know these bindings are currently unstable and might change in the future. Best Regards, Boris Changes since v5: - remove peripheral divisors macros from dt binding include file - remove file path from comment blocks - replace pll and utmi disable function by unprepare function to avoid issue when disabling and reenabling a clk - fix programmable clk interrupt retrieval - fix OF_CLK_DECLARE names (xxx_clk_main - xxx_clk_pmc) - add missing comma in at91rm9200 main clk dt declaration - fix num_parents check in smd clk driver Changes since v4: - rework dt bindings: * replace atmel,clk-id property by the standard reg property * reference system, peripheral and programmable clks using the direct clk node instead of the parent node plus a clk id - provide a new helper function (of_at91_get_clk_range) to retrieve a clk range from the device tree Changes since v3: - simplify master clk implementation (drop set_rate/parent support) - fix bug in set_rate function of pll driver - fix coding style issues - define macros and constants where needed - remove peripheral id macro references - remove sam9g35 specific handling (sam9g35 = sam9x5) - rework main clk prepare function to handle automatic rate calculation Changes since v2: - fix several bugs in clk implementations - drop non-dt boards support - split the series to ease review and tests: * 1 patch series for new clk implementations (this series) * 1 patch series to move each at91 SoC to common clk framework (coming soon) - modify dt-bindings (add atmel,clk- prefix to atmel specific properties) - add clk macros for dt-bindings - add pmc framework (helper function to access pmc registers) - add interrupt support to enable passive wait in clk_prepare functions Changes since v1: - fix bugs in pll, programmable and system clock implementations (wrong bit position). - add usb clock configuration support (ohci and udc drivers + clk_lookup for non dt boards) - rework of the system clock interfaces (no need to define a parent clock, system clock is a gate with no rate info) - change system, peripheral and programmable clk dt bindings (1 master node and multiple child nodes each defining a system/peripheral or prog clock) - fix bugs in sama5 dt definition Boris BREZILLON (16): ARM: at91: move at91_pmc.h to include/linux/clk/at91_pmc.h ARM: at91: add Kconfig options for common clk support clk: at91: add PMC base support clk: at91: add PMC macro file for dt definitions clk: at91: add PMC main clock clk: at91: add PMC pll clocks clk: at91: add PMC master clock clk: at91: add PMC system clocks clk: at91: add PMC peripheral clocks clk: at91: add PMC programmable clocks clk: at91: add PMC utmi clock clk: at91: add PMC usb clock clk: at91: add PMC smd clock dt: binding: add at91 clks dt bindings documentation ARM: at91: move pit timer to common clk framework ARM: at91: add new compatible strings for pmc driver .../devicetree/bindings/clock/at91-clock.txt | 339 + arch/arm/mach-at91/Kconfig | 44 ++ arch/arm/mach-at91/Kconfig.non_dt |6 + arch/arm/mach-at91/Makefile|2 +- arch/arm/mach-at91/at91rm9200.c|2 +- arch/arm/mach-at91/at91sam9260.c |2 +- arch/arm/mach-at91/at91sam9261.c |2 +- arch/arm/mach-at91/at91sam9263.c |2 +- arch/arm/mach-at91/at91sam926x_time.c | 14 +- arch/arm/mach-at91/at91sam9g45.c |2
Re: [PATCH v2] ARM: at91: add usart3 alias to dtsi
On 02/12/2013 13:53, Nicolas Ferre wrote: Alias was missing for SoC of the at91sam9x5 familly that embed USART3. Acked-by: Boris BREZILLON b.brezil...@overkiz.com Reported-by: Jiri Prchal jiri.prc...@aksignal.cz Signed-off-by: Nicolas Ferre nicolas.fe...@atmel.com Cc: Boris Brezillon b.brezil...@overkiz.com --- arch/arm/boot/dts/at91sam9x5_usart3.dtsi | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/at91sam9x5_usart3.dtsi b/arch/arm/boot/dts/at91sam9x5_usart3.dtsi index 2347e9563cef..6801106fa1f8 100644 --- a/arch/arm/boot/dts/at91sam9x5_usart3.dtsi +++ b/arch/arm/boot/dts/at91sam9x5_usart3.dtsi @@ -11,6 +11,10 @@ #include dt-bindings/interrupt-controller/irq.h / { + aliases { + serial4 = usart3; + }; + ahb { apb { pinctrl@f400 { -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: at91: add uart aliases to sama5d3 dtsi
On 02/12/2013 17:10, Nicolas Ferre wrote: Acked-by Boris BREZILLON b.brezil...@overkiz.com Signed-off-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/boot/dts/sama5d3_uart.dtsi | 5 + 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/sama5d3_uart.dtsi b/arch/arm/boot/dts/sama5d3_uart.dtsi index 49d4d76ca6f4..a9fa75e41652 100644 --- a/arch/arm/boot/dts/sama5d3_uart.dtsi +++ b/arch/arm/boot/dts/sama5d3_uart.dtsi @@ -12,6 +12,11 @@ #include dt-bindings/clk/at91.h / { + aliases { + serial5 = uart0; + serial6 = uart1; + }; + ahb { apb { pinctrl@f200 { -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: at91: add i2c2 pinctrl speficifation to sama5d3 DT
On 02/12/2013 17:18, Nicolas Ferre wrote: Acked-by: Boris BREZILLON b.brezil...@overkiz.com Signed-off-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/boot/dts/sama5d3.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index f520b0236671..f5fd111b5ee6 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -304,6 +304,8 @@ dmas = dma1 2 AT91_DMA_CFG_PER_ID(11), dma1 2 AT91_DMA_CFG_PER_ID(12); dma-names = tx, rx; + pinctrl-names = default; + pinctrl-0 = pinctrl_i2c2; #address-cells = 1; #size-cells = 0; clocks = twi2_clk; @@ -494,6 +496,14 @@ }; }; +i2c2 { + pinctrl_i2c2: i2c2-0 { + atmel,pins = + AT91_PIOA 18 AT91_PERIPH_B AT91_PINCTRL_NONE/* TWD2 pin, conflicts with LCDDAT18, ISI_D2 */ +AT91_PIOA 19 AT91_PERIPH_B AT91_PINCTRL_NONE; /* TWCK2 pin, conflicts with LCDDAT19, ISI_D3 */ + }; + }; + isi { pinctrl_isi: isi-0 { atmel,pins = -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 13/17] clk: at91: add PMC usb clock
This patch adds new at91 usb clock implementation using common clk framework. This clock is used to clock usb ports (ohci, ehci and udc). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/mach-at91/Kconfig | 11 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-usb.c | 400 drivers/clk/at91/pmc.c | 11 ++ drivers/clk/at91/pmc.h |9 + 5 files changed, 432 insertions(+) create mode 100644 drivers/clk/at91/clk-usb.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 6ad37da..b76dc4c 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -3,6 +3,9 @@ if ARCH_AT91 config HAVE_AT91_UTMI bool +config HAVE_AT91_USB_CLK + bool + config HAVE_AT91_DBGU0 bool @@ -82,6 +85,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -96,12 +100,14 @@ config SOC_AT91RM9200 select MULTI_IRQ_HANDLER select SPARSE_IRQ select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9260 bool AT91SAM9260, AT91SAM9XE or AT91SAM9G20 select HAVE_AT91_DBGU0 select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE or AT91SAM9G20 SoC. @@ -112,6 +118,7 @@ config SOC_AT91SAM9261 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. @@ -121,6 +128,7 @@ config SOC_AT91SAM9263 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9RL bool AT91SAM9RL @@ -137,6 +145,7 @@ config SOC_AT91SAM9G45 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -148,6 +157,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is @@ -161,6 +171,7 @@ config SOC_AT91SAM9N12 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using Atmel's AT91SAM9N12 SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index a824883..61db058 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -8,3 +8,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o +obj-$(CONFIG_HAVE_AT91_USB_CLK)+= clk-usb.o diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c new file mode 100644 index 000..0454555 --- /dev/null +++ b/drivers/clk/at91/clk-usb.c @@ -0,0 +1,400 @@ +/* + * drivers/clk/at91/clk-usb.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define USB_SOURCE_MAX 2 + +#define SAM9X5_USB_DIV_SHIFT 8 +#define SAM9X5_USB_MAX_DIV 0xf + +#define RM9200_USB_DIV_SHIFT 28 +#define RM9200_USB_DIV_TAB_SIZE4 + +struct at91sam9x5_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_usb(hw) \ + container_of(hw, struct at91sam9x5_clk_usb, hw) + +struct at91rm9200_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 divisors[4]; +}; + +#define to_at91rm9200_clk_usb(hw) \ + container_of(hw, struct at91rm9200_clk_usb, hw) + +static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 usbdiv; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb
[PATCH v4 15/17] clk: at91: add PMC clk device tree binding doc.
This patch adds new at91 clks dt bindings documentation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- .../devicetree/bindings/clock/at91-clock.txt | 328 1 file changed, 328 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/at91-clock.txt diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt new file mode 100644 index 000..360d8fe --- /dev/null +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt @@ -0,0 +1,328 @@ +Device Tree Clock bindings for arch-at91 + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible : shall be one of the following: + atmel,at91rm9200-pmc or + atmel,at91sam9g45-pmc or + atmel,at91sam9n12-pmc or + atmel,at91sam9x5-pmc or + atmel,sama5d3-pmc: + at91 PMC (Power Management Controller) + All at91 specific clocks (clocks defined below) must be child + node of the PMC node. + + atmel,at91rm9200-clk-main: + at91 main oscillator + + atmel,at91rm9200-clk-master or + atmel,at91sam9x5-clk-master: + at91 master clock + + atmel,at91sam9x5-clk-peripheral or + atmel,at91rm9200-clk-peripheral: + at91 peripheral clocks + + atmel,at91rm9200-clk-pll or + atmel,at91sam9g45-clk-pll or + atmel,at91sam9g20-clk-pllb or + atmel,sama5d3-clk-pll: + at91 pll clocks + + atmel,at91sam9x5-clk-plldiv: + at91 plla divisor + + atmel,at91rm9200-clk-programmable or + atmel,at91sam9g45-clk-programmable or + atmel,at91sam9x5-clk-programmable: + at91 programmable clocks + + atmel,at91sam9x5-clk-smd: + at91 SMD (Soft Modem) clock + + atmel,at91rm9200-clk-system: + at91 system clocks + + atmel,at91rm9200-clk-usb or + atmel,at91sam9x5-clk-usb or + atmel,at91sam9n12-clk-usb: + at91 usb clock + + atmel,at91sam9x5-clk-utmi: + at91 utmi clock + +Required properties for PMC node: +- reg : defines the IO memory reserved for the PMC. +- interrupts : shall be set to PMC interrupt line. +- interrupt-controller : tell that the PMC is an interrupt controller. +- #interrupt-cells : must be set to 1. The first cell encodes the interrupt id, + and reflect the bit position in the PMC_ER/DR/SR registers. + You can use the dt macros defined in dt-bindings/clk/at91.h. + 0 (AT91_PMC_MOSCS) - main oscillator ready + 1 (AT91_PMC_LOCKA) - PLL A ready + 2 (AT91_PMC_LOCKB) - PLL B ready + 3 (AT91_PMC_MCKRDY) - master clock ready + 6 (AT91_PMC_LOCKU) - UTMI PLL clock ready + 8 .. 15 (AT91_PMC_PCKRDY(id)) - programmable clock ready + 16 (AT91_PMC_MOSCSELS) - main oscillator selected + 17 (AT91_PMC_MOSCRCS) - RC main oscillator stabilized + 18 (AT91_PMC_CFDEV) - clock failure detected + +For example: + pmc: pmc@fc00 { + compatible = atmel,sama5d3-pmc; + interrupts = 1 4 7; + interrupt-controller; + #interrupt-cells = 2; + + /* put at91 clocks here */ + }; + +Required properties for main clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to 0. +- #clock-cells : from common clock binding; shall be set to 0. +- clocks (optional if clock-frequency is provided) : shall be the slow clock + phandle. This clock is used to calculate the main clock rate if + clock-frequency is not provided. +- clock-frequency : the main oscillator frequency.Prefer the use of + clock-frequency over automatic clock rate calculation. + +For example: + main: mainck { + compatible = atmel,at91rm9200-clk-main; + interrupt-parent = pmc; + interrupts = 0; + #clock-cells = 0; + clocks = ck32k; + clock-frequency = 18432000; + }; + +Required properties for master clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to 3. +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the master clock sources (see atmel datasheet) phandles. + e.g. ck32k, main, plla, pllb. +- atmel,clk-output-range : minimum and maximum clock frequency (two u32 + fields). + e.g. output = 0 13300; = 0 to 133MHz. +- atmel,clk-divisors : master clock divisors table (four u32 fields). + 0 = reserved value. + e.g. divisors = 1 2 4 6; +- atmel,master-clk-have-div3-pres : some SoC use the reserved value 7 in the + PRES field as CLOCK_DIV3 (e.g sam9x5). + +For example: + mck: mck
[PATCH v4 14/17] clk: at91: add PMC smd clock
This patch adds at91 smd (Soft Modem) clock implementation using common clk framework. Not used by any driver right now. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/mach-at91/Kconfig |5 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-smd.c | 173 drivers/clk/at91/pmc.c |7 ++ drivers/clk/at91/pmc.h |5 ++ 5 files changed, 191 insertions(+) create mode 100644 drivers/clk/at91/clk-smd.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index b76dc4c..97033f7 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -39,6 +39,9 @@ config AT91_SAM9G45_RESET config AT91_SAM9_TIME bool +config HAVE_AT91_SMD + bool + config SOC_AT91SAM9 bool select AT91_SAM9_TIME @@ -85,6 +88,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_SMD select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. @@ -157,6 +161,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_SMD select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 61db058..0e92b71 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -9,3 +9,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o obj-$(CONFIG_HAVE_AT91_USB_CLK)+= clk-usb.o +obj-$(CONFIG_HAVE_AT91_SMD)+= clk-smd.o diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c new file mode 100644 index 000..9f3fa39 --- /dev/null +++ b/drivers/clk/at91/clk-smd.c @@ -0,0 +1,173 @@ +/* + * drivers/clk/at91/clk-smd.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define SMD_SOURCE_MAX 2 + +#define SMD_DIV_SHIFT 8 +#define SMD_MAX_DIV0xf + +struct at91sam9x5_clk_smd { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_smd(hw) \ + container_of(hw, struct at91sam9x5_clk_smd, hw) + +static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 smddiv; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + tmp = pmc_read(pmc, AT91_PMC_SMD); + smddiv = (tmp AT91_PMC_SMD_DIV) SMD_DIV_SHIFT; + return parent_rate / (smddiv + 1); +} + +static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + unsigned long bestrate; + unsigned long tmp; + + if (rate = *parent_rate) + return *parent_rate; + + div = *parent_rate / rate; + if (div SMD_MAX_DIV) + return *parent_rate / (SMD_MAX_DIV + 1); + + bestrate = *parent_rate / div; + tmp = *parent_rate / (div + 1); + if (bestrate - rate rate - tmp) + bestrate = tmp; + + return bestrate; +} + +static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + if (index 1) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_SMD) ~AT91_PMC_SMDS; + if (index) + tmp |= AT91_PMC_SMDS; + pmc_write(pmc, AT91_PMC_SMD, tmp); + return 0; +} + +static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw) +{ + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + return pmc_read(pmc, AT91_PMC_SMD) AT91_PMC_SMDS; +} + +static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate || div 1 || div
[PATCH v4 16/17] ARM: at91: move pit timer to common clk framework
Use device tree to get the source clock of the PIT (Periodic Interval Timer). If the clock is not found in device tree (or dt is not enabled) we'll try to get it using clk_lookup definitions. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/at91sam926x_time.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index bb39232..0f04ffe 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c @@ -39,6 +39,7 @@ static u32 pit_cycle; /* write-once */ static u32 pit_cnt;/* access only w/system irq blocked */ static void __iomem *pit_base_addr __read_mostly; +static struct clk *mck; static inline unsigned int pit_read(unsigned int reg_offset) { @@ -195,10 +196,14 @@ static int __init of_at91sam926x_pit_init(void) if (!pit_base_addr) goto node_err; + mck = of_clk_get(np, 0); + /* Get the interrupts property */ ret = irq_of_parse_and_map(np, 0); if (!ret) { pr_crit(AT91: PIT: Unable to get IRQ from DT\n); + if (!IS_ERR(mck)) + clk_put(mck); goto ioremap_err; } at91sam926x_pit_irq.irq = ret; @@ -230,6 +235,8 @@ void __init at91sam926x_pit_init(void) unsignedbits; int ret; + mck = ERR_PTR(-ENOENT); + /* For device tree enabled device: initialize here */ of_at91sam926x_pit_init(); @@ -237,7 +244,12 @@ void __init at91sam926x_pit_init(void) * Use our actual MCK to figure out how many MCK/16 ticks per * 1/HZ period (instead of a compile-time constant LATCH). */ - pit_rate = clk_get_rate(clk_get(NULL, mck)) / 16; + if (IS_ERR(mck)) + mck = clk_get(NULL, mck); + + if (IS_ERR(mck)) + panic(AT91: PIT: Unable to get mck clk\n); + pit_rate = clk_get_rate(mck) / 16; pit_cycle = (pit_rate + HZ/2) / HZ; WARN_ON(((pit_cycle - 1) ~AT91_PIT_PIV) != 0); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 17/17] ARM: at91: add new compatible strings for pmc driver
This patch adds new compatible string for PMC node to prepare the transition to common clk. These compatible string come from pmc driver in clk subsystem and are needed to provide new device tree compatibility with old at91 clks (device tree using common clks will use the new compatible strings). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/clock.c |5 + 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 5f02aea..72b2579 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -884,6 +884,11 @@ static int __init at91_pmc_init(unsigned long main_clock) #if defined(CONFIG_OF) static struct of_device_id pmc_ids[] = { { .compatible = atmel,at91rm9200-pmc }, + { .compatible = atmel,at91sam9260-pmc }, + { .compatible = atmel,at91sam9g45-pmc }, + { .compatible = atmel,at91sam9n12-pmc }, + { .compatible = atmel,at91sam9x5-pmc }, + { .compatible = atmel,sama5d3-pmc }, { /*sentinel*/ } }; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 0/6] ARM: at91: use new at91 clks for samad3 SoCs
Hello, This patch series moves sama5d3 SoCs and boards to the new at91 clk framework (based on common clk framework). This patch series depends on following patch series: 1) ARM: at91/dt: split sama5d3 definition (v1) 3) ARM: at91: move to common clk framework (v4) Best Regards, Boris Changes since v1: - remove references to peripheral id macros - remove old clk definitions after moving to new clk framework Boris BREZILLON (6): ARM: at91: prepare sama5 dt boards transition to common clk ARM: at91: prepare common clk transition for sama5d3 SoC ARM: at91/dt: define sama5d3 clocks ARM: at91/dt: define sama5d3xek's main clk frequency ARM: at91: move sama5d3 SoC to common clk ARM: at91/dt: remove sama5 old clk material arch/arm/boot/dts/sama5d3.dtsi | 331 - arch/arm/boot/dts/sama5d3_can.dtsi | 18 ++ arch/arm/boot/dts/sama5d3_emac.dtsi | 10 + arch/arm/boot/dts/sama5d3_gmac.dtsi | 10 + arch/arm/boot/dts/sama5d3_lcd.dtsi | 15 ++ arch/arm/boot/dts/sama5d3_mci2.dtsi | 11 ++ arch/arm/boot/dts/sama5d3_tcb1.dtsi | 12 ++ arch/arm/boot/dts/sama5d3_uart.dtsi | 19 ++ arch/arm/boot/dts/sama5d3xcm.dtsi | 17 +- arch/arm/mach-at91/Kconfig |1 - arch/arm/mach-at91/board-dt-sama5.c | 10 +- arch/arm/mach-at91/sama5d3.c| 342 --- 12 files changed, 440 insertions(+), 356 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 1/6] ARM: at91: prepare sama5 dt boards transition to common clk
This patch prepare the transition to common clk for sama5 dt boards by replacing the timer init callback. Clocks registration cannot be done in early init callback (as formerly done by the old clk implementation) because it requires dynamic allocation which is not ready yet during early init. In the other hand, at91 clocks must be registered before at91sam926x_pit_init is called because PIT (Periodic Interval Timer) driver request the master clk (mck). A new function (at91sama5_dt_timer_init) is created to fullfil these needs. This function registers all at91 clks using the dt definition before calling the PIT init function. The device tree clock registration is enabled only if common clk is selected. Else the old clk registration is been done during at91_dt_initialize call. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/board-dt-sama5.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/board-dt-sama5.c index bf00d15..075ec05 100644 --- a/arch/arm/mach-at91/board-dt-sama5.c +++ b/arch/arm/mach-at91/board-dt-sama5.c @@ -16,6 +16,7 @@ #include linux/of_irq.h #include linux/of_platform.h #include linux/phy.h +#include linux/clk-provider.h #include asm/setup.h #include asm/irq.h @@ -26,6 +27,13 @@ #include at91_aic.h #include generic.h +static void __init sama5_dt_timer_init(void) +{ +#if defined(CONFIG_COMMON_CLK) + of_clk_init(NULL); +#endif + at91sam926x_pit_init(); +} static const struct of_device_id irq_of_match[] __initconst = { @@ -72,7 +80,7 @@ static const char *sama5_dt_board_compat[] __initdata = { DT_MACHINE_START(sama5_dt, Atmel SAMA5 (Device Tree)) /* Maintainer: Atmel */ - .init_time = at91sam926x_pit_init, + .init_time = sama5_dt_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic5_handle_irq, .init_early = at91_dt_initialize, -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 2/6] ARM: at91: prepare common clk transition for sama5d3 SoC
This patch encloses sama5d3 old clk registration in #if defined(CONFIG_OLD_CLK_AT91) #endif sections. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/sama5d3.c |6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c index 0003949..3426098 100644 --- a/arch/arm/mach-at91/sama5d3.c +++ b/arch/arm/mach-at91/sama5d3.c @@ -19,9 +19,10 @@ #include soc.h #include generic.h -#include clock.h #include sam9_smc.h +#if defined(CONFIG_OLD_CLK_AT91) +#include clock.h /* * Clocks * */ @@ -361,6 +362,7 @@ static void __init sama5d3_register_clocks(void) clk_register(pck1); clk_register(pck2); } +#endif /* * AT91SAM9x5 processor initialization @@ -373,5 +375,7 @@ static void __init sama5d3_map_io(void) AT91_SOC_START(sama5d3) .map_io = sama5d3_map_io, +#if defined(CONFIG_OLD_CLK_AT91) .register_clocks = sama5d3_register_clocks, +#endif AT91_SOC_END -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 3/6] ARM: at91/dt: define sama5d3 clocks
Define sama5d3 clocks in sama5d3 device tree. Add references to the appropriate clocks in each peripheral. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com --- arch/arm/boot/dts/sama5d3.dtsi | 331 ++- arch/arm/boot/dts/sama5d3_can.dtsi | 18 ++ arch/arm/boot/dts/sama5d3_emac.dtsi | 10 ++ arch/arm/boot/dts/sama5d3_gmac.dtsi | 10 ++ arch/arm/boot/dts/sama5d3_lcd.dtsi | 15 ++ arch/arm/boot/dts/sama5d3_mci2.dtsi | 11 ++ arch/arm/boot/dts/sama5d3_tcb1.dtsi | 12 ++ arch/arm/boot/dts/sama5d3_uart.dtsi | 19 ++ 8 files changed, 425 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 5cdaba4..c4dad3b 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -13,6 +13,7 @@ #include dt-bindings/pinctrl/at91.h #include dt-bindings/interrupt-controller/irq.h #include dt-bindings/gpio/gpio.h +#include dt-bindings/clk/at91.h / { model = Atmel SAMA5D3 family SoC; @@ -56,6 +57,14 @@ reg = 0x2000 0x800; }; + clocks { + adc_op_clk: adc_op_clk{ + compatible = fixed-clock; + #clock-cells = 0; + clock-frequency = 2000; + }; + }; + ahb { compatible = simple-bus; #address-cells = 1; @@ -79,6 +88,8 @@ status = disabled; #address-cells = 1; #size-cells = 0; + clocks = periph 21; + clock-names = mci_clk; }; spi0: spi@f0004000 { @@ -92,6 +103,8 @@ dma-names = tx, rx; pinctrl-names = default; pinctrl-0 = pinctrl_spi0; + clocks = periph 24; + clock-names = spi_clk; status = disabled; }; @@ -101,6 +114,8 @@ interrupts = 38 IRQ_TYPE_LEVEL_HIGH 4; pinctrl-names = default; pinctrl-0 = pinctrl_ssc0_tx pinctrl_ssc0_rx; + clocks = periph 38; + clock-names = pclk; status = disabled; }; @@ -108,6 +123,8 @@ compatible = atmel,at91sam9x5-tcb; reg = 0xf001 0x100; interrupts = 26 IRQ_TYPE_LEVEL_HIGH 0; + clocks = periph 26; + clock-names = t0_clk; }; i2c0: i2c@f0014000 { @@ -121,6 +138,7 @@ pinctrl-0 = pinctrl_i2c0; #address-cells = 1; #size-cells = 0; + clocks = periph 18; status = disabled; }; @@ -135,6 +153,7 @@ pinctrl-0 = pinctrl_i2c1; #address-cells = 1; #size-cells = 0; + clocks = periph 19; status = disabled; }; @@ -144,6 +163,8 @@ interrupts = 12 IRQ_TYPE_LEVEL_HIGH 5; pinctrl-names = default; pinctrl-0 = pinctrl_usart0; + clocks = periph 12; + clock-names = usart; status = disabled; }; @@ -153,6 +174,8 @@ interrupts = 13 IRQ_TYPE_LEVEL_HIGH 5; pinctrl-names = default; pinctrl-0 = pinctrl_usart1; + clocks = periph 13; + clock-names = usart; status = disabled; }; @@ -174,6 +197,8 @@ status = disabled; #address-cells = 1; #size-cells = 0; + clocks = periph 22; + clock-names = mci_clk; }; spi1: spi@f8008000 { @@ -187,6 +212,8 @@ dma-names = tx, rx; pinctrl-names = default; pinctrl-0 = pinctrl_spi1; + clocks = periph 25; + clock
[PATCH v2 4/6] ARM: at91/dt: define sama5d3xek's main clk frequency
Define the main clock frequency for the new main clock node in sama5d3xcm.dtsi. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/boot/dts/sama5d3xcm.dtsi |6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi index 726a0f3..dce5419 100644 --- a/arch/arm/boot/dts/sama5d3xcm.dtsi +++ b/arch/arm/boot/dts/sama5d3xcm.dtsi @@ -38,6 +38,12 @@ macb0: ethernet@f0028000 { phy-mode = rgmii; }; + + pmc: pmc@fc00 { + main: mainck { + clock-frequency = 1200; + }; + }; }; nand0: nand@6000 { -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/