mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
sh: SH7722 clock framework support.
This adds support for the SH7722 (MobileR) to the clock framework. Signed-off-by: dmitry pervushin <dimka@nomadgs.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
committed by
Paul Mundt
parent
34a780a0af
commit
1929cb340b
32
Documentation/sh/clk.txt
Normal file
32
Documentation/sh/clk.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
Clock framework on SuperH architecture
|
||||
|
||||
The framework on SH extends existing API by the function clk_set_rate_ex,
|
||||
which prototype is as follows:
|
||||
|
||||
clk_set_rate_ex (struct clk *clk, unsigned long rate, int algo_id)
|
||||
|
||||
The algo_id parameter is used to specify algorithm used to recalculate clocks,
|
||||
adjanced to clock, specified as first argument. It is assumed that algo_id==0
|
||||
means no changes to adjanced clock
|
||||
|
||||
Internally, the clk_set_rate_ex forwards request to clk->ops->set_rate method,
|
||||
if it is present in ops structure. The method should set the clock rate and adjust
|
||||
all needed clocks according to the passed algo_id.
|
||||
Exact values for algo_id are machine-dependend. For the sh7722, the following
|
||||
values are defined:
|
||||
|
||||
NO_CHANGE = 0,
|
||||
IUS_N1_N1, /* I:U = N:1, U:Sh = N:1 */
|
||||
IUS_322, /* I:U:Sh = 3:2:2 */
|
||||
IUS_522, /* I:U:Sh = 5:2:2 */
|
||||
IUS_N11, /* I:U:Sh = N:1:1 */
|
||||
SB_N1, /* Sh:B = N:1 */
|
||||
SB3_N1, /* Sh:B3 = N:1 */
|
||||
SB3_32, /* Sh:B3 = 3:2 */
|
||||
SB3_43, /* Sh:B3 = 4:3 */
|
||||
SB3_54, /* Sh:B3 = 5:4 */
|
||||
BP_N1, /* B:P = N:1 */
|
||||
IP_N1 /* I:P = N:1 */
|
||||
|
||||
Each of these constants means relation between clocks that can be set via the FRQCR
|
||||
register
|
||||
@@ -98,13 +98,14 @@ int __clk_enable(struct clk *clk)
|
||||
if (clk->ops && clk->ops->init)
|
||||
clk->ops->init(clk);
|
||||
|
||||
kref_get(&clk->kref);
|
||||
|
||||
if (clk->flags & CLK_ALWAYS_ENABLED)
|
||||
return 0;
|
||||
|
||||
if (likely(clk->ops && clk->ops->enable))
|
||||
clk->ops->enable(clk);
|
||||
|
||||
kref_get(&clk->kref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -127,10 +128,15 @@ static void clk_kref_release(struct kref *kref)
|
||||
|
||||
void __clk_disable(struct clk *clk)
|
||||
{
|
||||
int count = kref_put(&clk->kref, clk_kref_release);
|
||||
|
||||
if (clk->flags & CLK_ALWAYS_ENABLED)
|
||||
return;
|
||||
|
||||
kref_put(&clk->kref, clk_kref_release);
|
||||
if (!count) { /* count reaches zero, disable the clock */
|
||||
if (likely(clk->ops && clk->ops->disable))
|
||||
clk->ops->disable(clk);
|
||||
}
|
||||
}
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
@@ -151,6 +157,15 @@ int clk_register(struct clk *clk)
|
||||
|
||||
mutex_unlock(&clock_list_sem);
|
||||
|
||||
if (clk->flags & CLK_ALWAYS_ENABLED) {
|
||||
pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name);
|
||||
if (clk->ops && clk->ops->init)
|
||||
clk->ops->init(clk);
|
||||
if (clk->ops && clk->ops->enable)
|
||||
clk->ops->enable(clk);
|
||||
pr_debug( "Enabled.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -167,6 +182,11 @@ inline unsigned long clk_get_rate(struct clk *clk)
|
||||
}
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return clk_set_rate_ex(clk, rate, 0);
|
||||
}
|
||||
|
||||
int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
@@ -174,7 +194,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
ret = clk->ops->set_rate(clk, rate);
|
||||
ret = clk->ops->set_rate(clk, rate, algo_id);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
}
|
||||
|
||||
@@ -256,7 +276,6 @@ int __init clk_init(void)
|
||||
|
||||
arch_init_clk_ops(&clk->ops, i);
|
||||
ret |= clk_register(clk);
|
||||
clk_enable(clk);
|
||||
}
|
||||
|
||||
/* Kick the child clocks.. */
|
||||
@@ -298,3 +317,4 @@ EXPORT_SYMBOL_GPL(__clk_disable);
|
||||
EXPORT_SYMBOL_GPL(clk_get_rate);
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate);
|
||||
EXPORT_SYMBOL_GPL(clk_recalc_rate);
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate_ex);
|
||||
|
||||
@@ -82,7 +82,8 @@ static void shoc_clk_init(struct clk *clk)
|
||||
for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
|
||||
int divisor = frqcr3_divisors[i];
|
||||
|
||||
if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
|
||||
if (clk->ops->set_rate(clk, clk->parent->rate /
|
||||
divisor, 0) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,6 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7343.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
|
||||
|
||||
obj-y += $(clock-y)
|
||||
|
||||
600
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
Normal file
600
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@ struct clk_ops {
|
||||
void (*enable)(struct clk *clk);
|
||||
void (*disable)(struct clk *clk);
|
||||
void (*recalc)(struct clk *clk);
|
||||
int (*set_rate)(struct clk *clk, unsigned long rate);
|
||||
int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
|
||||
};
|
||||
|
||||
struct clk {
|
||||
@@ -50,4 +50,34 @@ void clk_unregister(struct clk *);
|
||||
|
||||
int show_clocks(struct seq_file *m);
|
||||
|
||||
/* the exported API, in addition to clk_set_rate */
|
||||
/**
|
||||
* clk_set_rate_ex - set the clock rate for a clock source, with additional parameter
|
||||
* @clk: clock source
|
||||
* @rate: desired clock rate in Hz
|
||||
* @algo_id: algorithm id to be passed down to ops->set_rate
|
||||
*
|
||||
* Returns success (0) or negative errno.
|
||||
*/
|
||||
int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id);
|
||||
|
||||
enum clk_sh_algo_id {
|
||||
NO_CHANGE = 0,
|
||||
|
||||
IUS_N1_N1,
|
||||
IUS_322,
|
||||
IUS_522,
|
||||
IUS_N11,
|
||||
|
||||
SB_N1,
|
||||
|
||||
SB3_N1,
|
||||
SB3_32,
|
||||
SB3_43,
|
||||
SB3_54,
|
||||
|
||||
BP_N1,
|
||||
|
||||
IP_N1,
|
||||
};
|
||||
#endif /* __ASM_SH_CLOCK_H */
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7722)
|
||||
#define FRQCR 0xa4150000
|
||||
#define VCLKCR 0xa4150004
|
||||
#define SCLKACR 0xa4150008
|
||||
#define SCLKBCR 0xa415000c
|
||||
#define IrDACLKCR 0xa4150010
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
|
||||
#define FRQCR 0xffc80000
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7785)
|
||||
|
||||
Reference in New Issue
Block a user