aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2012-04-09 15:50:06 -0400
committerMike Turquette <mturquette@linaro.org>2012-07-11 20:58:45 -0400
commit766e6a4ec602d0c107553b91b3434fe9c03474f4 (patch)
treeaa9bbba36954d927e931cc50c6a28ef9cced571c /drivers/clk/clk.c
parenta613163dff04cbfcb7d66b06ef4a5f65498ee59b (diff)
clk: add DT clock binding support
Based on work 1st by Ben Herrenschmidt and Jeremy Kerr, then by Grant Likely, this patch adds support to clk_get to allow drivers to retrieve clock data from the device tree. Platforms scan for clocks in DT with of_clk_init and a match table, and the register a provider through of_clk_add_provider. The provider's clk_src_get function will be called when a device references the provider's OF node for a clock reference. v6 (Rob Herring): - Return error values instead of NULL to match clock framework expectations v5 (Rob Herring): - Move from drivers/of into common clock subsystem - Squashed "dt/clock: add a simple provider get function" and "dt/clock: add function to get parent clock name" - Rebase to 3.4-rc1 - Drop CONFIG_OF_CLOCK and just use CONFIG_OF - Add missing EXPORT_SYMBOL to various functions - s/clock-output-name/clock-output-names/ - Define that fixed-clock binding is a single output v4 (Rob Herring): - Rework for common clk subsystem - Add of_clk_get_parent_name function v3: - Clarified documentation v2: - fixed errant ';' causing compile error - Editorial fixes from Shawn Guo - merged in adding lookup to clkdev - changed property names to match established convention. After working with the binding a bit it really made more sense to follow the lead of 'reg', 'gpios' and 'interrupts' by making the input simply 'clocks' & 'clock-names' instead of 'clock-input-*', and to only use clock-output* for the producer nodes. (Sorry Shawn, this will mean you need to change some code, but it should be trivial) - Add ability to inherit clocks from parent nodes by using an empty 'clock-ranges' property. Useful for busses. I could use some feedback on the new property name, 'clock-ranges' doesn't feel right to me. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Rob Herring <rob.herring@calxeda.com> Reviewed-by: Shawn Guo <shawn.guo@freescale.com> Cc: Sascha Hauer <kernel@pengutronix.de> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r--drivers/clk/clk.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 46317cbc088f..c87fdd710560 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -16,6 +16,7 @@
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/list.h> 17#include <linux/list.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/of.h>
19 20
20static DEFINE_SPINLOCK(enable_lock); 21static DEFINE_SPINLOCK(enable_lock);
21static DEFINE_MUTEX(prepare_lock); 22static DEFINE_MUTEX(prepare_lock);
@@ -1550,3 +1551,142 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
1550 return ret; 1551 return ret;
1551} 1552}
1552EXPORT_SYMBOL_GPL(clk_notifier_unregister); 1553EXPORT_SYMBOL_GPL(clk_notifier_unregister);
1554
1555#ifdef CONFIG_OF
1556/**
1557 * struct of_clk_provider - Clock provider registration structure
1558 * @link: Entry in global list of clock providers
1559 * @node: Pointer to device tree node of clock provider
1560 * @get: Get clock callback. Returns NULL or a struct clk for the
1561 * given clock specifier
1562 * @data: context pointer to be passed into @get callback
1563 */
1564struct of_clk_provider {
1565 struct list_head link;
1566
1567 struct device_node *node;
1568 struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
1569 void *data;
1570};
1571
1572static LIST_HEAD(of_clk_providers);
1573static DEFINE_MUTEX(of_clk_lock);
1574
1575struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
1576 void *data)
1577{
1578 return data;
1579}
1580EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
1581
1582/**
1583 * of_clk_add_provider() - Register a clock provider for a node
1584 * @np: Device node pointer associated with clock provider
1585 * @clk_src_get: callback for decoding clock
1586 * @data: context pointer for @clk_src_get callback.
1587 */
1588int of_clk_add_provider(struct device_node *np,
1589 struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
1590 void *data),
1591 void *data)
1592{
1593 struct of_clk_provider *cp;
1594
1595 cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
1596 if (!cp)
1597 return -ENOMEM;
1598
1599 cp->node = of_node_get(np);
1600 cp->data = data;
1601 cp->get = clk_src_get;
1602
1603 mutex_lock(&of_clk_lock);
1604 list_add(&cp->link, &of_clk_providers);
1605 mutex_unlock(&of_clk_lock);
1606 pr_debug("Added clock from %s\n", np->full_name);
1607
1608 return 0;
1609}
1610EXPORT_SYMBOL_GPL(of_clk_add_provider);
1611
1612/**
1613 * of_clk_del_provider() - Remove a previously registered clock provider
1614 * @np: Device node pointer associated with clock provider
1615 */
1616void of_clk_del_provider(struct device_node *np)
1617{
1618 struct of_clk_provider *cp;
1619
1620 mutex_lock(&of_clk_lock);
1621 list_for_each_entry(cp, &of_clk_providers, link) {
1622 if (cp->node == np) {
1623 list_del(&cp->link);
1624 of_node_put(cp->node);
1625 kfree(cp);
1626 break;
1627 }
1628 }
1629 mutex_unlock(&of_clk_lock);
1630}
1631EXPORT_SYMBOL_GPL(of_clk_del_provider);
1632
1633struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
1634{
1635 struct of_clk_provider *provider;
1636 struct clk *clk = ERR_PTR(-ENOENT);
1637
1638 /* Check if we have such a provider in our array */
1639 mutex_lock(&of_clk_lock);
1640 list_for_each_entry(provider, &of_clk_providers, link) {
1641 if (provider->node == clkspec->np)
1642 clk = provider->get(clkspec, provider->data);
1643 if (!IS_ERR(clk))
1644 break;
1645 }
1646 mutex_unlock(&of_clk_lock);
1647
1648 return clk;
1649}
1650
1651const char *of_clk_get_parent_name(struct device_node *np, int index)
1652{
1653 struct of_phandle_args clkspec;
1654 const char *clk_name;
1655 int rc;
1656
1657 if (index < 0)
1658 return NULL;
1659
1660 rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
1661 &clkspec);
1662 if (rc)
1663 return NULL;
1664
1665 if (of_property_read_string_index(clkspec.np, "clock-output-names",
1666 clkspec.args_count ? clkspec.args[0] : 0,
1667 &clk_name) < 0)
1668 clk_name = clkspec.np->name;
1669
1670 of_node_put(clkspec.np);
1671 return clk_name;
1672}
1673EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
1674
1675/**
1676 * of_clk_init() - Scan and init clock providers from the DT
1677 * @matches: array of compatible values and init functions for providers.
1678 *
1679 * This function scans the device tree for matching clock providers and
1680 * calls their initialization functions
1681 */
1682void __init of_clk_init(const struct of_device_id *matches)
1683{
1684 struct device_node *np;
1685
1686 for_each_matching_node(np, matches) {
1687 const struct of_device_id *match = of_match_node(matches, np);
1688 of_clk_init_cb_t clk_init_cb = match->data;
1689 clk_init_cb(np);
1690 }
1691}
1692#endif