[PATCHv5 16/31] CLK: TI: DRA7: Add APLL support
Mark Rutland
mark.rutland at arm.com
Tue Aug 13 07:14:49 EDT 2013
On Fri, Aug 02, 2013 at 05:25:35PM +0100, Tero Kristo wrote:
> From: Keerthy <j-keerthy at ti.com>
>
> The patch adds support for DRA7 PCIe APLL. The APLL
> sources the optional functional clocks for PCIe module.
>
> APLL stands for Analog PLL. This is different when comapred
> with DPLL meaning Digital PLL, the phase detection is done
> using an analog circuit.
>
> Signed-off-by: Keerthy <j-keerthy at ti.com>
> Signed-off-by: Tero Kristo <t-kristo at ti.com>
> ---
> .../devicetree/bindings/clock/ti/apll.txt | 32 +++
> arch/arm/mach-omap2/clock.h | 1 -
> drivers/clk/ti/Makefile | 2 +-
> drivers/clk/ti/apll.c | 209 ++++++++++++++++++++
> include/linux/clk/ti.h | 2 +
> 5 files changed, 244 insertions(+), 2 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/clock/ti/apll.txt
> create mode 100644 drivers/clk/ti/apll.c
>
> diff --git a/Documentation/devicetree/bindings/clock/ti/apll.txt b/Documentation/devicetree/bindings/clock/ti/apll.txt
> new file mode 100644
> index 0000000..f7a82e9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/ti/apll.txt
> @@ -0,0 +1,32 @@
> +Binding for Texas Instruments APLL clock.
> +
> +This binding uses the common clock binding[1]. It assumes a
> +register-mapped APLL with usually two selectable input clocks
> +(reference clock and bypass clock), with analog phase locked
> +loop logic for multiplying the input clock to a desired output
> +clock. This clock also typically supports different operation
> +modes (locked, low power stop etc.) APLL mostly behaves like
> +a subtype of a DPLL [2], although a simplified one at that.
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +[2] Documentation/devicetree/bindings/clock/ti/dpll.txt
> +
> +Required properties:
> +- compatible : shall be "ti,dra7-apll-clock"
> +- #clock-cells : from common clock binding; shall be set to 0.
> +- clocks : link phandles of parent clocks (clk-ref and clk-bypass)
> +- reg : array of register base addresses for controlling the APLL:
> + reg[0] = control register
> + reg[1] = idle status register
Using reg-names is likely a good idea here.
> +- ti,clk-ref : link phandle for the reference clock
> +- ti,clk-bypass : link phandle for the bypass clock
You don't need this. Use the clocks and clock-names properties.
[...]
> +static int dra7_apll_enable(struct clk_hw *hw)
> +{
> + struct clk_hw_omap *clk = to_clk_hw_omap(hw);
> + int r = 0, i = 0;
> + struct dpll_data *ad;
> + const char *clk_name;
> + u8 state = 1;
> + u32 v;
> +
> + ad = clk->dpll_data;
> + if (!ad)
> + return -EINVAL;
> +
> + clk_name = __clk_get_name(clk->hw.clk);
> +
> + state <<= __ffs(ad->idlest_mask);
> +
> + /* Check is already locked */
> + if ((__raw_readl(ad->idlest_reg) & ad->idlest_mask) == state)
> + return r;
Why __raw_readl rather than raw_readl?
> +
> + v = __raw_readl(ad->control_reg);
> + v &= ~ad->enable_mask;
> + v |= APLL_FORCE_LOCK << __ffs(ad->enable_mask);
> + __raw_writel(v, ad->control_reg);
Why not raw_writel? Do you not need the rmb() provided by writel, here
or anywhere else?
[...]
> +void __init of_dra7_apll_setup(struct device_node *node)
> +{
> + const struct clk_ops *ops;
> + struct clk *clk;
> + const char *clk_name = node->name;
> + int num_parents;
> + const char **parent_names = NULL;
> + struct of_phandle_args clkspec;
> + u8 apll_flags = 0;
> + struct dpll_data *ad;
> + u32 idlest_mask = 0x1;
> + u32 autoidle_mask = 0x3;
> + int i;
> +
> + ops = &apll_ck_ops;
> + ad = kzalloc(sizeof(*ad), GFP_KERNEL);
> + if (!ad) {
> + pr_err("%s: could not allocate dpll_data\n", __func__);
> + return;
> + }
> +
> + of_property_read_string(node, "clock-output-names", &clk_name);
> +
> + num_parents = of_clk_get_parent_count(node);
> + if (num_parents < 1) {
> + pr_err("%s: omap dpll %s must have parent(s)\n",
> + __func__, node->name);
> + goto cleanup;
> + }
> +
> + parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL);
> +
> + for (i = 0; i < num_parents; i++)
> + parent_names[i] = of_clk_get_parent_name(node, i);
> +
> + clkspec.np = of_parse_phandle(node, "ti,clk-ref", 0);
> + ad->clk_ref = of_clk_get_from_provider(&clkspec);
Use clocks, clock-names, and of_clk_get_by_name().
Thanks,
Mark.
More information about the linux-arm-kernel
mailing list