diff mbox

[PATCHv4,09/33] CLK: omap: add omap4 clock init file

Message ID 1374564028-11352-10-git-send-email-t-kristo@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tero Kristo July 23, 2013, 7:20 a.m. UTC
clk-44xx.c now contains the clock init functionality for omap4, including
DT clock registration and adding of static clkdev entries.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/omap/clk-44xx.c |  118 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)
 create mode 100644 drivers/clk/omap/clk-44xx.c

Comments

Nishanth Menon July 30, 2013, 7:33 p.m. UTC | #1
On 07/23/2013 02:20 AM, Tero Kristo wrote:
> clk-44xx.c now contains the clock init functionality for omap4, including
> DT clock registration and adding of static clkdev entries.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>   drivers/clk/omap/clk-44xx.c |  118 +++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 118 insertions(+)
>   create mode 100644 drivers/clk/omap/clk-44xx.c
>
> diff --git a/drivers/clk/omap/clk-44xx.c b/drivers/clk/omap/clk-44xx.c
> new file mode 100644
> index 0000000..cc12134
> --- /dev/null
> +++ b/drivers/clk/omap/clk-44xx.c
> @@ -0,0 +1,118 @@
> +/*
> + * OMAP4 Clock data
> + *
> + * Copyright (C) 2009-2012 Texas Instruments, Inc.
> + * Copyright (C) 2009-2010 Nokia Corporation
> + *
> + * Paul Walmsley (paul@pwsan.com)
> + * Rajendra Nayak (rnayak@ti.com)
> + * Benoit Cousson (b-cousson@ti.com)
> + * Mike Turquette (mturquette@ti.com)
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * XXX Some of the ES1 clocks have been removed/changed; once support
> + * is added for discriminating clocks by ES level, these should be added back
> + * in.
> + *
> + * XXX All of the remaining MODULEMODE clock nodes should be removed
> + * once the drivers are updated to use pm_runtime or to use the appropriate
> + * upstream clock node for rate/parent selection.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/clk-private.h>
> +#include <linux/clkdev.h>
> +#include <linux/io.h>
> +#include <linux/clk/omap.h>
> +
> +/*
> + * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
> + * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
> + * must be set to 196.608 MHz" and hence, the DPLL locked frequency is
> + * half of this value.
> + */
> +#define OMAP4_DPLL_ABE_DEFFREQ				98304000
> +
> +/*
> + * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
> + * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
> + * locked frequency for the USB DPLL is 960MHz.
> + */
> +#define OMAP4_DPLL_USB_DEFFREQ				960000000
> +
> +static struct omap_dt_clk omap44xx_clks[] = {
> +	DT_CLK("smp_twd",	NULL,			"mpu_periphclk"),
> +	DT_CLK("omapdss_dss", "ick", "dss_fck"),
> +	DT_CLK("usbhs_omap", "fs_fck", "usb_host_fs_fck"),
> +	DT_CLK("usbhs_omap", "hs_fck", "usb_host_hs_fck"),
> +	DT_CLK("usbhs_omap", "usbtll_ick", "usb_tll_hs_ick"),
> +	DT_CLK("usbhs_tll", "usbtll_ick", "usb_tll_hs_ick"),
> +	DT_CLK(NULL,	"timer_32k_ck",	"sys_32k_ck"),
> +	/* TODO: Remove "omap_timer.X" aliases once DT migration is complete */
> +	DT_CLK("omap_timer.1",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("omap_timer.2",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("omap_timer.3",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("omap_timer.4",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("omap_timer.9",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("omap_timer.10",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("omap_timer.11",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("omap_timer.5",	"timer_sys_ck",	"syc_clk_div_ck"),
> +	DT_CLK("omap_timer.6",	"timer_sys_ck",	"syc_clk_div_ck"),
> +	DT_CLK("omap_timer.7",	"timer_sys_ck",	"syc_clk_div_ck"),
> +	DT_CLK("omap_timer.8",	"timer_sys_ck",	"syc_clk_div_ck"),
> +	DT_CLK("4a318000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("48032000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("48034000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("48036000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("4803e000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("48086000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("48088000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
> +	DT_CLK("40138000.timer",	"timer_sys_ck",	"syc_clk_div_ck"),
> +	DT_CLK("4013a000.timer",	"timer_sys_ck",	"syc_clk_div_ck"),
> +	DT_CLK("4013c000.timer",	"timer_sys_ck",	"syc_clk_div_ck"),
> +	DT_CLK("4013e000.timer",	"timer_sys_ck",	"syc_clk_div_ck"),

> +	DT_CLK(NULL,	"cpufreq_ck",	"dpll_mpu_ck"),
please remove cpufreq.

> +};
> +
> +int __init omap4xxx_clk_init(void)
> +{
> +	int rc;
> +	struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
> +
> +	/* FIXME register clocks from DT first */
> +	dt_omap_clk_init();
> +
> +	omap_dt_clocks_register(omap44xx_clks, ARRAY_SIZE(omap44xx_clks));
> +
> +	omap2_clk_disable_autoidle_all();
> +
> +	/*
> +	 * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
> +	 * state when turning the ABE clock domain. Workaround this by
> +	 * locking the ABE DPLL on boot.
> +	 * Lock the ABE DPLL in any case to avoid issues with audio.
> +	 */

But this code will be called for 4430 and 4460. if the requirement is 
only for 4460, then we are not adhering to the spec?

> +	abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck");
> +	sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
> +	rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
> +	abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
> +	if (!rc)
> +		rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ);
> +	if (rc)
> +		pr_err("%s: failed to configure ABE DPLL!\n", __func__);
> +
> +	/*
> +	 * Lock USB DPLL on OMAP4 devices so that the L3INIT power
> +	 * domain can transition to retention state when not in use.
> +	 */
> +	usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
> +	rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ);
> +	if (rc)
> +		pr_err("%s: failed to configure USB DPLL!\n", __func__);

^^^^ why cant we have a generic property that does this "automagically" 
from dts property to the node?
a) be able to select a parent
b) be able to set a frequency.
c) how do we ensure that CLK_SET_RATE_PARENT are setup for the clock 
nodes defined by dt?

> +
> +	return 0;
> +}
>
Tero Kristo July 31, 2013, 2:52 p.m. UTC | #2
On 07/30/2013 10:33 PM, Nishanth Menon wrote:
> On 07/23/2013 02:20 AM, Tero Kristo wrote:
>> clk-44xx.c now contains the clock init functionality for omap4, including
>> DT clock registration and adding of static clkdev entries.
>>
>> Signed-off-by: Tero Kristo <t-kristo@ti.com>
>> ---
>>   drivers/clk/omap/clk-44xx.c |  118
>> +++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 118 insertions(+)
>>   create mode 100644 drivers/clk/omap/clk-44xx.c
>>
>> diff --git a/drivers/clk/omap/clk-44xx.c b/drivers/clk/omap/clk-44xx.c
>> new file mode 100644
>> index 0000000..cc12134
>> --- /dev/null
>> +++ b/drivers/clk/omap/clk-44xx.c
>> @@ -0,0 +1,118 @@
>> +/*
>> + * OMAP4 Clock data
>> + *
>> + * Copyright (C) 2009-2012 Texas Instruments, Inc.
>> + * Copyright (C) 2009-2010 Nokia Corporation
>> + *
>> + * Paul Walmsley (paul@pwsan.com)
>> + * Rajendra Nayak (rnayak@ti.com)
>> + * Benoit Cousson (b-cousson@ti.com)
>> + * Mike Turquette (mturquette@ti.com)
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * XXX Some of the ES1 clocks have been removed/changed; once support
>> + * is added for discriminating clocks by ES level, these should be
>> added back
>> + * in.
>> + *
>> + * XXX All of the remaining MODULEMODE clock nodes should be removed
>> + * once the drivers are updated to use pm_runtime or to use the
>> appropriate
>> + * upstream clock node for rate/parent selection.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/list.h>
>> +#include <linux/clk-private.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/io.h>
>> +#include <linux/clk/omap.h>
>> +
>> +/*
>> + * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
>> + * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
>> + * must be set to 196.608 MHz" and hence, the DPLL locked frequency is
>> + * half of this value.
>> + */
>> +#define OMAP4_DPLL_ABE_DEFFREQ                98304000
>> +
>> +/*
>> + * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
>> + * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
>> + * locked frequency for the USB DPLL is 960MHz.
>> + */
>> +#define OMAP4_DPLL_USB_DEFFREQ                960000000
>> +
>> +static struct omap_dt_clk omap44xx_clks[] = {
>> +    DT_CLK("smp_twd",    NULL,            "mpu_periphclk"),
>> +    DT_CLK("omapdss_dss", "ick", "dss_fck"),
>> +    DT_CLK("usbhs_omap", "fs_fck", "usb_host_fs_fck"),
>> +    DT_CLK("usbhs_omap", "hs_fck", "usb_host_hs_fck"),
>> +    DT_CLK("usbhs_omap", "usbtll_ick", "usb_tll_hs_ick"),
>> +    DT_CLK("usbhs_tll", "usbtll_ick", "usb_tll_hs_ick"),
>> +    DT_CLK(NULL,    "timer_32k_ck",    "sys_32k_ck"),
>> +    /* TODO: Remove "omap_timer.X" aliases once DT migration is
>> complete */
>> +    DT_CLK("omap_timer.1",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("omap_timer.2",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("omap_timer.3",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("omap_timer.4",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("omap_timer.9",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("omap_timer.10",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("omap_timer.11",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("omap_timer.5",    "timer_sys_ck",    "syc_clk_div_ck"),
>> +    DT_CLK("omap_timer.6",    "timer_sys_ck",    "syc_clk_div_ck"),
>> +    DT_CLK("omap_timer.7",    "timer_sys_ck",    "syc_clk_div_ck"),
>> +    DT_CLK("omap_timer.8",    "timer_sys_ck",    "syc_clk_div_ck"),
>> +    DT_CLK("4a318000.timer",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("48032000.timer",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("48034000.timer",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("48036000.timer",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("4803e000.timer",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("48086000.timer",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("48088000.timer",    "timer_sys_ck",    "sys_clkin_ck"),
>> +    DT_CLK("40138000.timer",    "timer_sys_ck",    "syc_clk_div_ck"),
>> +    DT_CLK("4013a000.timer",    "timer_sys_ck",    "syc_clk_div_ck"),
>> +    DT_CLK("4013c000.timer",    "timer_sys_ck",    "syc_clk_div_ck"),
>> +    DT_CLK("4013e000.timer",    "timer_sys_ck",    "syc_clk_div_ck"),
>
>> +    DT_CLK(NULL,    "cpufreq_ck",    "dpll_mpu_ck"),
> please remove cpufreq.

Hmm why?

Because cpufreq is completely broken now and your current work on it? :)

>
>> +};
>> +
>> +int __init omap4xxx_clk_init(void)
>> +{
>> +    int rc;
>> +    struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
>> +
>> +    /* FIXME register clocks from DT first */
>> +    dt_omap_clk_init();
>> +
>> +    omap_dt_clocks_register(omap44xx_clks, ARRAY_SIZE(omap44xx_clks));
>> +
>> +    omap2_clk_disable_autoidle_all();
>> +
>> +    /*
>> +     * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
>> +     * state when turning the ABE clock domain. Workaround this by
>> +     * locking the ABE DPLL on boot.
>> +     * Lock the ABE DPLL in any case to avoid issues with audio.
>> +     */
>
> But this code will be called for 4430 and 4460. if the requirement is
> only for 4460, then we are not adhering to the spec?

This is copy pasted from existing cclock44xx_data.c file init function.

>
>> +    abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck");
>> +    sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
>> +    rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
>> +    abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
>> +    if (!rc)
>> +        rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ);
>> +    if (rc)
>> +        pr_err("%s: failed to configure ABE DPLL!\n", __func__);
>> +
>> +    /*
>> +     * Lock USB DPLL on OMAP4 devices so that the L3INIT power
>> +     * domain can transition to retention state when not in use.
>> +     */
>> +    usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
>> +    rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ);
>> +    if (rc)
>> +        pr_err("%s: failed to configure USB DPLL!\n", __func__);
>
> ^^^^ why cant we have a generic property that does this "automagically"
> from dts property to the node?
> a) be able to select a parent
> b) be able to set a frequency.
> c) how do we ensure that CLK_SET_RATE_PARENT are setup for the clock
> nodes defined by dt?

This is probably for Mike to answer, currently such mechanism does not 
exist.

>
>> +
>> +    return 0;
>> +}
>>
>
>
Nishanth Menon Aug. 1, 2013, 2:40 p.m. UTC | #3
On 07/31/2013 09:52 AM, Tero Kristo wrote:
> On 07/30/2013 10:33 PM, Nishanth Menon wrote:
[...]

>>
>>> +    DT_CLK(NULL,    "cpufreq_ck",    "dpll_mpu_ck"),
>> please remove cpufreq.
>
> Hmm why?
>
> Because cpufreq is completely broken now and your current work on it? :)

cpufreq fixing can be done separately and has abillity to pick up clock 
nodes by describing clocks=<&dpll_mpu_ck> in cpu0 node. absolutely no 
need to carry on this hack - See my comment on [1]

yes, I know I will have to redo my cpufreq series, but thanks to your 
work, it is a 10 min job to enable them back online :) dont worry about 
the broken cpufreq, we will fix it properly and it is not even needed 
for basic boot to shell (example omap2plus_defconfig does not even 
enable CONFIG_CPU_FREQ).


>>
>>> +    abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck");
>>> +    sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
>>> +    rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
>>> +    abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
>>> +    if (!rc)
>>> +        rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ);
>>> +    if (rc)
>>> +        pr_err("%s: failed to configure ABE DPLL!\n", __func__);
>>> +
>>> +    /*
>>> +     * Lock USB DPLL on OMAP4 devices so that the L3INIT power
>>> +     * domain can transition to retention state when not in use.
>>> +     */
>>> +    usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
>>> +    rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ);
>>> +    if (rc)
>>> +        pr_err("%s: failed to configure USB DPLL!\n", __func__);
>>
>> ^^^^ why cant we have a generic property that does this "automagically"
>> from dts property to the node?
>> a) be able to select a parent
>> b) be able to set a frequency.
>> c) how do we ensure that CLK_SET_RATE_PARENT are setup for the clock
>> nodes defined by dt?
>
> This is probably for Mike to answer, currently such mechanism does not
> exist.

I think you already dealt with (c). in the same vein, we can do (a) and 
(b). Dont think anyone else has gone about this to the extent we are 
attempting to do till date, so as pioneers, we might as well suggest 
with a patch :D ?

[1] http://marc.info/?l=linux-omap&m=137536714605620&w=2
Tero Kristo Aug. 1, 2013, 3:34 p.m. UTC | #4
On 08/01/2013 05:40 PM, Nishanth Menon wrote:
> On 07/31/2013 09:52 AM, Tero Kristo wrote:
>> On 07/30/2013 10:33 PM, Nishanth Menon wrote:
> [...]
>
>>>
>>>> +    DT_CLK(NULL,    "cpufreq_ck",    "dpll_mpu_ck"),
>>> please remove cpufreq.
>>
>> Hmm why?
>>
>> Because cpufreq is completely broken now and your current work on it? :)
>
> cpufreq fixing can be done separately and has abillity to pick up clock
> nodes by describing clocks=<&dpll_mpu_ck> in cpu0 node. absolutely no
> need to carry on this hack - See my comment on [1]
>
> yes, I know I will have to redo my cpufreq series, but thanks to your
> work, it is a 10 min job to enable them back online :) dont worry about
> the broken cpufreq, we will fix it properly and it is not even needed
> for basic boot to shell (example omap2plus_defconfig does not even
> enable CONFIG_CPU_FREQ).

Ok, I'll drop the cpufreq one out at least. :)

>
>
>>>
>>>> +    abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck");
>>>> +    sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
>>>> +    rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
>>>> +    abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
>>>> +    if (!rc)
>>>> +        rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ);
>>>> +    if (rc)
>>>> +        pr_err("%s: failed to configure ABE DPLL!\n", __func__);
>>>> +
>>>> +    /*
>>>> +     * Lock USB DPLL on OMAP4 devices so that the L3INIT power
>>>> +     * domain can transition to retention state when not in use.
>>>> +     */
>>>> +    usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
>>>> +    rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ);
>>>> +    if (rc)
>>>> +        pr_err("%s: failed to configure USB DPLL!\n", __func__);
>>>
>>> ^^^^ why cant we have a generic property that does this "automagically"
>>> from dts property to the node?
>>> a) be able to select a parent
>>> b) be able to set a frequency.
>>> c) how do we ensure that CLK_SET_RATE_PARENT are setup for the clock
>>> nodes defined by dt?
>>
>> This is probably for Mike to answer, currently such mechanism does not
>> exist.
>
> I think you already dealt with (c). in the same vein, we can do (a) and
> (b). Dont think anyone else has gone about this to the extent we are
> attempting to do till date, so as pioneers, we might as well suggest
> with a patch :D ?

Yea, for c I have a patch as that is clearly required. For a/b, we can 
currently workaround. Again, I don't want to implement everything in 
this set at once, as the result would be a huge behemoth (this is 
complicated enough as is imo.)

>
> [1] http://marc.info/?l=linux-omap&m=137536714605620&w=2
Nishanth Menon Aug. 1, 2013, 4:10 p.m. UTC | #5
On Thu, Aug 1, 2013 at 10:34 AM, Tero Kristo <t-kristo@ti.com> wrote:
>>
>> I think you already dealt with (c). in the same vein, we can do (a) and
>> (b). Dont think anyone else has gone about this to the extent we are
>> attempting to do till date, so as pioneers, we might as well suggest
>> with a patch :D ?
>
>
> Yea, for c I have a patch as that is clearly required. For a/b, we can
> currently workaround. Again, I don't want to implement everything in this
> set at once, as the result would be a huge behemoth (this is complicated
> enough as is imo.)
this series will be smaller if you do it, not larger. you would just
need to introduce those parameters and not have to deal with SoC
specific "hacky drivers".
Regards,
NM
diff mbox

Patch

diff --git a/drivers/clk/omap/clk-44xx.c b/drivers/clk/omap/clk-44xx.c
new file mode 100644
index 0000000..cc12134
--- /dev/null
+++ b/drivers/clk/omap/clk-44xx.c
@@ -0,0 +1,118 @@ 
+/*
+ * OMAP4 Clock data
+ *
+ * Copyright (C) 2009-2012 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley (paul@pwsan.com)
+ * Rajendra Nayak (rnayak@ti.com)
+ * Benoit Cousson (b-cousson@ti.com)
+ * Mike Turquette (mturquette@ti.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX Some of the ES1 clocks have been removed/changed; once support
+ * is added for discriminating clocks by ES level, these should be added back
+ * in.
+ *
+ * XXX All of the remaining MODULEMODE clock nodes should be removed
+ * once the drivers are updated to use pm_runtime or to use the appropriate
+ * upstream clock node for rate/parent selection.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk/omap.h>
+
+/*
+ * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
+ * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
+ * must be set to 196.608 MHz" and hence, the DPLL locked frequency is
+ * half of this value.
+ */
+#define OMAP4_DPLL_ABE_DEFFREQ				98304000
+
+/*
+ * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
+ * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
+ * locked frequency for the USB DPLL is 960MHz.
+ */
+#define OMAP4_DPLL_USB_DEFFREQ				960000000
+
+static struct omap_dt_clk omap44xx_clks[] = {
+	DT_CLK("smp_twd",	NULL,			"mpu_periphclk"),
+	DT_CLK("omapdss_dss", "ick", "dss_fck"),
+	DT_CLK("usbhs_omap", "fs_fck", "usb_host_fs_fck"),
+	DT_CLK("usbhs_omap", "hs_fck", "usb_host_hs_fck"),
+	DT_CLK("usbhs_omap", "usbtll_ick", "usb_tll_hs_ick"),
+	DT_CLK("usbhs_tll", "usbtll_ick", "usb_tll_hs_ick"),
+	DT_CLK(NULL,	"timer_32k_ck",	"sys_32k_ck"),
+	/* TODO: Remove "omap_timer.X" aliases once DT migration is complete */
+	DT_CLK("omap_timer.1",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("omap_timer.2",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("omap_timer.3",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("omap_timer.4",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("omap_timer.9",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("omap_timer.10",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("omap_timer.11",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("omap_timer.5",	"timer_sys_ck",	"syc_clk_div_ck"),
+	DT_CLK("omap_timer.6",	"timer_sys_ck",	"syc_clk_div_ck"),
+	DT_CLK("omap_timer.7",	"timer_sys_ck",	"syc_clk_div_ck"),
+	DT_CLK("omap_timer.8",	"timer_sys_ck",	"syc_clk_div_ck"),
+	DT_CLK("4a318000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("48032000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("48034000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("48036000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("4803e000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("48086000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("48088000.timer",	"timer_sys_ck",	"sys_clkin_ck"),
+	DT_CLK("40138000.timer",	"timer_sys_ck",	"syc_clk_div_ck"),
+	DT_CLK("4013a000.timer",	"timer_sys_ck",	"syc_clk_div_ck"),
+	DT_CLK("4013c000.timer",	"timer_sys_ck",	"syc_clk_div_ck"),
+	DT_CLK("4013e000.timer",	"timer_sys_ck",	"syc_clk_div_ck"),
+	DT_CLK(NULL,	"cpufreq_ck",	"dpll_mpu_ck"),
+};
+
+int __init omap4xxx_clk_init(void)
+{
+	int rc;
+	struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
+
+	/* FIXME register clocks from DT first */
+	dt_omap_clk_init();
+
+	omap_dt_clocks_register(omap44xx_clks, ARRAY_SIZE(omap44xx_clks));
+
+	omap2_clk_disable_autoidle_all();
+
+	/*
+	 * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
+	 * state when turning the ABE clock domain. Workaround this by
+	 * locking the ABE DPLL on boot.
+	 * Lock the ABE DPLL in any case to avoid issues with audio.
+	 */
+	abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck");
+	sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
+	rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
+	abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
+	if (!rc)
+		rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ);
+	if (rc)
+		pr_err("%s: failed to configure ABE DPLL!\n", __func__);
+
+	/*
+	 * Lock USB DPLL on OMAP4 devices so that the L3INIT power
+	 * domain can transition to retention state when not in use.
+	 */
+	usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
+	rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ);
+	if (rc)
+		pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
+	return 0;
+}