Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 316618
b: refs/heads/master
c: 766e6a4
h: refs/heads/master
v: v3
  • Loading branch information
Grant Likely authored and Mike Turquette committed Jul 12, 2012
1 parent 8bc6f2c commit 1e21792
Show file tree
Hide file tree
Showing 7 changed files with 389 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a613163dff04cbfcb7d66b06ef4a5f65498ee59b
refs/heads/master: 766e6a4ec602d0c107553b91b3434fe9c03474f4
117 changes: 117 additions & 0 deletions trunk/Documentation/devicetree/bindings/clock/clock-bindings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
This binding is a work-in-progress, and are based on some experimental
work by benh[1].

Sources of clock signal can be represented by any node in the device
tree. Those nodes are designated as clock providers. Clock consumer
nodes use a phandle and clock specifier pair to connect clock provider
outputs to clock inputs. Similar to the gpio specifiers, a clock
specifier is an array of one more more cells identifying the clock
output on a device. The length of a clock specifier is defined by the
value of a #clock-cells property in the clock provider node.

[1] http://patchwork.ozlabs.org/patch/31551/

==Clock providers==

Required properties:
#clock-cells: Number of cells in a clock specifier; Typically 0 for nodes
with a single clock output and 1 for nodes with multiple
clock outputs.

Optional properties:
clock-output-names: Recommended to be a list of strings of clock output signal
names indexed by the first cell in the clock specifier.
However, the meaning of clock-output-names is domain
specific to the clock provider, and is only provided to
encourage using the same meaning for the majority of clock
providers. This format may not work for clock providers
using a complex clock specifier format. In those cases it
is recommended to omit this property and create a binding
specific names property.

Clock consumer nodes must never directly reference
the provider's clock-output-names property.

For example:

oscillator {
#clock-cells = <1>;
clock-output-names = "ckil", "ckih";
};

- this node defines a device with two clock outputs, the first named
"ckil" and the second named "ckih". Consumer nodes always reference
clocks by index. The names should reflect the clock output signal
names for the device.

==Clock consumers==

Required properties:
clocks: List of phandle and clock specifier pairs, one pair
for each clock input to the device. Note: if the
clock provider specifies '0' for #clock-cells, then
only the phandle portion of the pair will appear.

Optional properties:
clock-names: List of clock input name strings sorted in the same
order as the clocks property. Consumers drivers
will use clock-names to match clock input names
with clocks specifiers.
clock-ranges: Empty property indicating that child nodes can inherit named
clocks from this node. Useful for bus nodes to provide a
clock to their children.

For example:

device {
clocks = <&osc 1>, <&ref 0>;
clock-names = "baud", "register";
};


This represents a device with two clock inputs, named "baud" and "register".
The baud clock is connected to output 1 of the &osc device, and the register
clock is connected to output 0 of the &ref.

==Example==

/* external oscillator */
osc: oscillator {
compatible = "fixed-clock";
#clock-cells = <1>;
clock-frequency = <32678>;
clock-output-names = "osc";
};

/* phase-locked-loop device, generates a higher frequency clock
* from the external oscillator reference */
pll: pll@4c000 {
compatible = "vendor,some-pll-interface"
#clock-cells = <1>;
clocks = <&osc 0>;
clock-names = "ref";
reg = <0x4c000 0x1000>;
clock-output-names = "pll", "pll-switched";
};

/* UART, using the low frequency oscillator for the baud clock,
* and the high frequency switched PLL output for register
* clocking */
uart@a000 {
compatible = "fsl,imx-uart";
reg = <0xa000 0x1000>;
interrupts = <33>;
clocks = <&osc 0>, <&pll 1>;
clock-names = "baud", "register";
};

This DT fragment defines three devices: an external oscillator to provide a
low-frequency reference clock, a PLL device to generate a higher frequency
clock signal, and a UART.

* The oscillator is fixed-frequency, and provides one clock output, named "osc".
* The PLL is both a clock provider and a clock consumer. It uses the clock
signal generated by the external oscillator, and provides two output signals
("pll" and "pll-switched").
* The UART has its baud clock connected the external oscillator and its
register clock connected to the PLL clock (the "pll-switched" signal)
21 changes: 21 additions & 0 deletions trunk/Documentation/devicetree/bindings/clock/fixed-clock.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Binding for simple fixed-rate clock sources.

This binding uses the common clock binding[1].

[1] Documentation/devicetree/bindings/clock/clock-bindings.txt

Required properties:
- compatible : shall be "fixed-clock".
- #clock-cells : from common clock binding; shall be set to 0.
- clock-frequency : frequency of clock in Hz. Should be a single cell.

Optional properties:
- gpios : From common gpio binding; gpio connection to clock enable pin.
- clock-output-names : From common clock binding.

Example:
clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000000>;
};
140 changes: 140 additions & 0 deletions trunk/drivers/clk/clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/err.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/of.h>

static DEFINE_SPINLOCK(enable_lock);
static DEFINE_MUTEX(prepare_lock);
Expand Down Expand Up @@ -1550,3 +1551,142 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
return ret;
}
EXPORT_SYMBOL_GPL(clk_notifier_unregister);

#ifdef CONFIG_OF
/**
* struct of_clk_provider - Clock provider registration structure
* @link: Entry in global list of clock providers
* @node: Pointer to device tree node of clock provider
* @get: Get clock callback. Returns NULL or a struct clk for the
* given clock specifier
* @data: context pointer to be passed into @get callback
*/
struct of_clk_provider {
struct list_head link;

struct device_node *node;
struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
void *data;
};

static LIST_HEAD(of_clk_providers);
static DEFINE_MUTEX(of_clk_lock);

struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
void *data)
{
return data;
}
EXPORT_SYMBOL_GPL(of_clk_src_simple_get);

/**
* of_clk_add_provider() - Register a clock provider for a node
* @np: Device node pointer associated with clock provider
* @clk_src_get: callback for decoding clock
* @data: context pointer for @clk_src_get callback.
*/
int of_clk_add_provider(struct device_node *np,
struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
void *data),
void *data)
{
struct of_clk_provider *cp;

cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
if (!cp)
return -ENOMEM;

cp->node = of_node_get(np);
cp->data = data;
cp->get = clk_src_get;

mutex_lock(&of_clk_lock);
list_add(&cp->link, &of_clk_providers);
mutex_unlock(&of_clk_lock);
pr_debug("Added clock from %s\n", np->full_name);

return 0;
}
EXPORT_SYMBOL_GPL(of_clk_add_provider);

/**
* of_clk_del_provider() - Remove a previously registered clock provider
* @np: Device node pointer associated with clock provider
*/
void of_clk_del_provider(struct device_node *np)
{
struct of_clk_provider *cp;

mutex_lock(&of_clk_lock);
list_for_each_entry(cp, &of_clk_providers, link) {
if (cp->node == np) {
list_del(&cp->link);
of_node_put(cp->node);
kfree(cp);
break;
}
}
mutex_unlock(&of_clk_lock);
}
EXPORT_SYMBOL_GPL(of_clk_del_provider);

struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
{
struct of_clk_provider *provider;
struct clk *clk = ERR_PTR(-ENOENT);

/* Check if we have such a provider in our array */
mutex_lock(&of_clk_lock);
list_for_each_entry(provider, &of_clk_providers, link) {
if (provider->node == clkspec->np)
clk = provider->get(clkspec, provider->data);
if (!IS_ERR(clk))
break;
}
mutex_unlock(&of_clk_lock);

return clk;
}

const char *of_clk_get_parent_name(struct device_node *np, int index)
{
struct of_phandle_args clkspec;
const char *clk_name;
int rc;

if (index < 0)
return NULL;

rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
&clkspec);
if (rc)
return NULL;

if (of_property_read_string_index(clkspec.np, "clock-output-names",
clkspec.args_count ? clkspec.args[0] : 0,
&clk_name) < 0)
clk_name = clkspec.np->name;

of_node_put(clkspec.np);
return clk_name;
}
EXPORT_SYMBOL_GPL(of_clk_get_parent_name);

/**
* of_clk_init() - Scan and init clock providers from the DT
* @matches: array of compatible values and init functions for providers.
*
* This function scans the device tree for matching clock providers and
* calls their initialization functions
*/
void __init of_clk_init(const struct of_device_id *matches)
{
struct device_node *np;

for_each_matching_node(np, matches) {
const struct of_device_id *match = of_match_node(matches, np);
of_clk_init_cb_t clk_init_cb = match->data;
clk_init_cb(np);
}
}
#endif
77 changes: 77 additions & 0 deletions trunk/drivers/clk/clkdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,80 @@
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/of.h>

static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);

#ifdef CONFIG_OF
struct clk *of_clk_get(struct device_node *np, int index)
{
struct of_phandle_args clkspec;
struct clk *clk;
int rc;

if (index < 0)
return ERR_PTR(-EINVAL);

rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
&clkspec);
if (rc)
return ERR_PTR(rc);

clk = of_clk_get_from_provider(&clkspec);
of_node_put(clkspec.np);
return clk;
}
EXPORT_SYMBOL(of_clk_get);

/**
* of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
* @np: pointer to clock consumer node
* @name: name of consumer's clock input, or NULL for the first clock reference
*
* This function parses the clocks and clock-names properties,
* and uses them to look up the struct clk from the registered list of clock
* providers.
*/
struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
{
struct clk *clk = ERR_PTR(-ENOENT);

/* Walk up the tree of devices looking for a clock that matches */
while (np) {
int index = 0;

/*
* For named clocks, first look up the name in the
* "clock-names" property. If it cannot be found, then
* index will be an error code, and of_clk_get() will fail.
*/
if (name)
index = of_property_match_string(np, "clock-names", name);
clk = of_clk_get(np, index);
if (!IS_ERR(clk))
break;
else if (name && index >= 0) {
pr_err("ERROR: could not get clock %s:%s(%i)\n",
np->full_name, name ? name : "", index);
return clk;
}

/*
* No matching clock found on this node. If the parent node
* has a "clock-ranges" property, then we can try one of its
* clocks.
*/
np = np->parent;
if (np && !of_get_property(np, "clock-ranges", NULL))
break;
}

return clk;
}
EXPORT_SYMBOL(of_clk_get_by_name);
#endif

/*
* Find the correct struct clk for the device and connection ID.
* We do slightly fuzzy matching here:
Expand Down Expand Up @@ -83,6 +153,13 @@ EXPORT_SYMBOL(clk_get_sys);
struct clk *clk_get(struct device *dev, const char *con_id)
{
const char *dev_id = dev ? dev_name(dev) : NULL;
struct clk *clk;

if (dev) {
clk = of_clk_get_by_name(dev->of_node, con_id);
if (clk && __clk_get(clk))
return clk;
}

return clk_get_sys(dev_id, con_id);
}
Expand Down
Loading

0 comments on commit 1e21792

Please sign in to comment.