Merge branch 'sh/clkfwk'
This commit is contained in:
commit
c5eb5b372e
|
@ -710,8 +710,6 @@ static struct clk_ops fsimck_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk fsimckb_clk = {
|
||||
.name = "fsimckb_clk",
|
||||
.id = -1,
|
||||
.ops = &fsimck_clk_ops,
|
||||
.enable_reg = (void __iomem *)FCLKBCR,
|
||||
.rate = 0, /* unknown */
|
||||
|
@ -1138,16 +1136,20 @@ static int __init arch_setup(void)
|
|||
|
||||
/* set SPU2 clock to 83.4 MHz */
|
||||
clk = clk_get(NULL, "spu_clk");
|
||||
clk_set_rate(clk, clk_round_rate(clk, 83333333));
|
||||
clk_put(clk);
|
||||
if (clk) {
|
||||
clk_set_rate(clk, clk_round_rate(clk, 83333333));
|
||||
clk_put(clk);
|
||||
}
|
||||
|
||||
/* change parent of FSI B */
|
||||
clk = clk_get(NULL, "fsib_clk");
|
||||
clk_register(&fsimckb_clk);
|
||||
clk_set_parent(clk, &fsimckb_clk);
|
||||
clk_set_rate(clk, 11000);
|
||||
clk_set_rate(&fsimckb_clk, 11000);
|
||||
clk_put(clk);
|
||||
if (clk) {
|
||||
clk_register(&fsimckb_clk);
|
||||
clk_set_parent(clk, &fsimckb_clk);
|
||||
clk_set_rate(clk, 11000);
|
||||
clk_set_rate(&fsimckb_clk, 11000);
|
||||
clk_put(clk);
|
||||
}
|
||||
|
||||
gpio_request(GPIO_PTU0, NULL);
|
||||
gpio_direction_output(GPIO_PTU0, 0);
|
||||
|
@ -1159,8 +1161,10 @@ static int __init arch_setup(void)
|
|||
|
||||
/* set VPU clock to 166 MHz */
|
||||
clk = clk_get(NULL, "vpu_clk");
|
||||
clk_set_rate(clk, clk_round_rate(clk, 166000000));
|
||||
clk_put(clk);
|
||||
if (clk) {
|
||||
clk_set_rate(clk, clk_round_rate(clk, 166000000));
|
||||
clk_put(clk);
|
||||
}
|
||||
|
||||
/* enable IrDA */
|
||||
gpio_request(GPIO_FN_IRDA_OUT, NULL);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ata_platform.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include <net/ax88796.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <mach/highlander.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/heartbeat.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -326,7 +328,6 @@ static struct clk_ops ivdr_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk ivdr_clk = {
|
||||
.name = "ivdr_clk",
|
||||
.ops = &ivdr_clk_ops,
|
||||
};
|
||||
|
||||
|
@ -334,6 +335,13 @@ static struct clk *r7780rp_clocks[] = {
|
|||
&ivdr_clk,
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("ivdr_clk", &ivdr_clk),
|
||||
};
|
||||
|
||||
static void r7780rp_power_off(void)
|
||||
{
|
||||
if (mach_is_r7780mp() || mach_is_r7785rp())
|
||||
|
@ -370,6 +378,8 @@ static void __init highlander_setup(char **cmdline_p)
|
|||
clk_enable(clk);
|
||||
}
|
||||
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
__raw_writew(0x0000, PA_OBLED); /* Clear LED. */
|
||||
|
||||
if (mach_is_r7780rp())
|
||||
|
|
|
@ -276,8 +276,6 @@ static struct clk_ops fsimck_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk fsimcka_clk = {
|
||||
.name = "fsimcka_clk",
|
||||
.id = -1,
|
||||
.ops = &fsimck_clk_ops,
|
||||
.enable_reg = (void __iomem *)FCLKACR,
|
||||
.rate = 0, /* unknown */
|
||||
|
@ -771,16 +769,20 @@ static int __init devices_setup(void)
|
|||
|
||||
/* set SPU2 clock to 83.4 MHz */
|
||||
clk = clk_get(NULL, "spu_clk");
|
||||
clk_set_rate(clk, clk_round_rate(clk, 83333333));
|
||||
clk_put(clk);
|
||||
if (clk) {
|
||||
clk_set_rate(clk, clk_round_rate(clk, 83333333));
|
||||
clk_put(clk);
|
||||
}
|
||||
|
||||
/* change parent of FSI A */
|
||||
clk = clk_get(NULL, "fsia_clk");
|
||||
clk_register(&fsimcka_clk);
|
||||
clk_set_parent(clk, &fsimcka_clk);
|
||||
clk_set_rate(clk, 11000);
|
||||
clk_set_rate(&fsimcka_clk, 11000);
|
||||
clk_put(clk);
|
||||
if (clk) {
|
||||
clk_register(&fsimcka_clk);
|
||||
clk_set_parent(clk, &fsimcka_clk);
|
||||
clk_set_rate(clk, 11000);
|
||||
clk_set_rate(&fsimcka_clk, 11000);
|
||||
clk_put(clk);
|
||||
}
|
||||
|
||||
/* SDHI0 connected to cn7 */
|
||||
gpio_request(GPIO_FN_SDHI0CD, NULL);
|
||||
|
|
|
@ -1,163 +1,16 @@
|
|||
#ifndef __ASM_SH_CLOCK_H
|
||||
#define __ASM_SH_CLOCK_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
struct clk;
|
||||
|
||||
struct clk_ops {
|
||||
void (*init)(struct clk *clk);
|
||||
int (*enable)(struct clk *clk);
|
||||
void (*disable)(struct clk *clk);
|
||||
unsigned long (*recalc)(struct clk *clk);
|
||||
int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
|
||||
int (*set_parent)(struct clk *clk, struct clk *parent);
|
||||
long (*round_rate)(struct clk *clk, unsigned long rate);
|
||||
};
|
||||
|
||||
struct clk {
|
||||
struct list_head node;
|
||||
const char *name;
|
||||
int id;
|
||||
struct module *owner;
|
||||
|
||||
struct clk *parent;
|
||||
struct clk_ops *ops;
|
||||
|
||||
struct list_head children;
|
||||
struct list_head sibling; /* node for children */
|
||||
|
||||
int usecount;
|
||||
|
||||
unsigned long rate;
|
||||
unsigned long flags;
|
||||
|
||||
void __iomem *enable_reg;
|
||||
unsigned int enable_bit;
|
||||
|
||||
unsigned long arch_flags;
|
||||
void *priv;
|
||||
struct dentry *dentry;
|
||||
struct cpufreq_frequency_table *freq_table;
|
||||
};
|
||||
|
||||
#define CLK_ENABLE_ON_INIT (1 << 0)
|
||||
#include <linux/sh_clk.h>
|
||||
|
||||
/* Should be defined by processor-specific code */
|
||||
void __deprecated arch_init_clk_ops(struct clk_ops **, int type);
|
||||
int __init arch_clk_init(void);
|
||||
|
||||
/* arch/sh/kernel/cpu/clock.c */
|
||||
int clk_init(void);
|
||||
unsigned long followparent_recalc(struct clk *);
|
||||
void recalculate_root_clocks(void);
|
||||
void propagate_rate(struct clk *);
|
||||
int clk_reparent(struct clk *child, struct clk *parent);
|
||||
int clk_register(struct clk *);
|
||||
void clk_unregister(struct clk *);
|
||||
|
||||
/* arch/sh/kernel/cpu/clock-cpg.c */
|
||||
int __init __deprecated cpg_clk_init(void);
|
||||
|
||||
/* 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,
|
||||
};
|
||||
|
||||
struct clk_div_mult_table {
|
||||
unsigned int *divisors;
|
||||
unsigned int nr_divisors;
|
||||
unsigned int *multipliers;
|
||||
unsigned int nr_multipliers;
|
||||
};
|
||||
|
||||
struct cpufreq_frequency_table;
|
||||
void clk_rate_table_build(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
int nr_freqs,
|
||||
struct clk_div_mult_table *src_table,
|
||||
unsigned long *bitmap);
|
||||
|
||||
long clk_rate_table_round(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
unsigned long rate);
|
||||
|
||||
int clk_rate_table_find(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
unsigned long rate);
|
||||
|
||||
#define SH_CLK_MSTP32(_name, _id, _parent, _enable_reg, \
|
||||
_enable_bit, _flags) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.id = _id, \
|
||||
.parent = _parent, \
|
||||
.enable_reg = (void __iomem *)_enable_reg, \
|
||||
.enable_bit = _enable_bit, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
int sh_clk_mstp32_register(struct clk *clks, int nr);
|
||||
|
||||
#define SH_CLK_DIV4(_name, _parent, _reg, _shift, _div_bitmap, _flags) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.parent = _parent, \
|
||||
.enable_reg = (void __iomem *)_reg, \
|
||||
.enable_bit = _shift, \
|
||||
.arch_flags = _div_bitmap, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
struct clk_div4_table {
|
||||
struct clk_div_mult_table *div_mult_table;
|
||||
void (*kick)(struct clk *clk);
|
||||
};
|
||||
|
||||
int sh_clk_div4_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table);
|
||||
int sh_clk_div4_enable_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table);
|
||||
int sh_clk_div4_reparent_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table);
|
||||
|
||||
#define SH_CLK_DIV6(_parent, _reg, _flags) \
|
||||
{ \
|
||||
.parent = _parent, \
|
||||
.enable_reg = (void __iomem *)_reg, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
int sh_clk_div6_register(struct clk *clks, int nr);
|
||||
/* arch/sh/kernel/cpu/clock.c */
|
||||
int clk_init(void);
|
||||
|
||||
#endif /* __ASM_SH_CLOCK_H */
|
||||
|
|
|
@ -16,7 +16,7 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/
|
|||
# Common interfaces.
|
||||
|
||||
obj-$(CONFIG_SH_ADC) += adc.o
|
||||
obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o
|
||||
obj-$(CONFIG_SH_CLK_CPG_LEGACY) += clock-cpg.o
|
||||
obj-$(CONFIG_SH_FPU) += fpu.o
|
||||
obj-$(CONFIG_SH_FPU_EMU) += fpu.o
|
||||
|
||||
|
|
|
@ -2,317 +2,25 @@
|
|||
#include <linux/compiler.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/clock.h>
|
||||
|
||||
static int sh_clk_mstp32_enable(struct clk *clk)
|
||||
{
|
||||
__raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
|
||||
clk->enable_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sh_clk_mstp32_disable(struct clk *clk)
|
||||
{
|
||||
__raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
|
||||
clk->enable_reg);
|
||||
}
|
||||
|
||||
static struct clk_ops sh_clk_mstp32_clk_ops = {
|
||||
.enable = sh_clk_mstp32_enable,
|
||||
.disable = sh_clk_mstp32_disable,
|
||||
.recalc = followparent_recalc,
|
||||
};
|
||||
|
||||
int __init sh_clk_mstp32_register(struct clk *clks, int nr)
|
||||
{
|
||||
struct clk *clkp;
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
for (k = 0; !ret && (k < nr); k++) {
|
||||
clkp = clks + k;
|
||||
clkp->ops = &sh_clk_mstp32_clk_ops;
|
||||
ret |= clk_register(clkp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return clk_rate_table_round(clk, clk->freq_table, rate);
|
||||
}
|
||||
|
||||
static int sh_clk_div6_divisors[64] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
||||
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
|
||||
};
|
||||
|
||||
static struct clk_div_mult_table sh_clk_div6_table = {
|
||||
.divisors = sh_clk_div6_divisors,
|
||||
.nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
|
||||
};
|
||||
|
||||
static unsigned long sh_clk_div6_recalc(struct clk *clk)
|
||||
{
|
||||
struct clk_div_mult_table *table = &sh_clk_div6_table;
|
||||
unsigned int idx;
|
||||
|
||||
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
|
||||
table, NULL);
|
||||
|
||||
idx = __raw_readl(clk->enable_reg) & 0x003f;
|
||||
|
||||
return clk->freq_table[idx].frequency;
|
||||
}
|
||||
|
||||
static int sh_clk_div6_set_rate(struct clk *clk,
|
||||
unsigned long rate, int algo_id)
|
||||
{
|
||||
unsigned long value;
|
||||
int idx;
|
||||
|
||||
idx = clk_rate_table_find(clk, clk->freq_table, rate);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value &= ~0x3f;
|
||||
value |= idx;
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_clk_div6_enable(struct clk *clk)
|
||||
{
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
|
||||
if (ret == 0) {
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value &= ~0x100; /* clear stop bit to enable clock */
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sh_clk_div6_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value |= 0x100; /* stop clock */
|
||||
value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
}
|
||||
|
||||
static struct clk_ops sh_clk_div6_clk_ops = {
|
||||
.recalc = sh_clk_div6_recalc,
|
||||
.round_rate = sh_clk_div_round_rate,
|
||||
.set_rate = sh_clk_div6_set_rate,
|
||||
.enable = sh_clk_div6_enable,
|
||||
.disable = sh_clk_div6_disable,
|
||||
};
|
||||
|
||||
int __init sh_clk_div6_register(struct clk *clks, int nr)
|
||||
{
|
||||
struct clk *clkp;
|
||||
void *freq_table;
|
||||
int nr_divs = sh_clk_div6_table.nr_divisors;
|
||||
int freq_table_size = sizeof(struct cpufreq_frequency_table);
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
freq_table_size *= (nr_divs + 1);
|
||||
freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
|
||||
if (!freq_table) {
|
||||
pr_err("sh_clk_div6_register: unable to alloc memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (k = 0; !ret && (k < nr); k++) {
|
||||
clkp = clks + k;
|
||||
|
||||
clkp->ops = &sh_clk_div6_clk_ops;
|
||||
clkp->id = -1;
|
||||
clkp->freq_table = freq_table + (k * freq_table_size);
|
||||
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
ret = clk_register(clkp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long sh_clk_div4_recalc(struct clk *clk)
|
||||
{
|
||||
struct clk_div4_table *d4t = clk->priv;
|
||||
struct clk_div_mult_table *table = d4t->div_mult_table;
|
||||
unsigned int idx;
|
||||
|
||||
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
|
||||
table, &clk->arch_flags);
|
||||
|
||||
idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
|
||||
|
||||
return clk->freq_table[idx].frequency;
|
||||
}
|
||||
|
||||
static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
struct clk_div4_table *d4t = clk->priv;
|
||||
struct clk_div_mult_table *table = d4t->div_mult_table;
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
if (!strcmp("pll_clk", parent->name))
|
||||
value = __raw_readl(clk->enable_reg) & ~(1 << 7);
|
||||
else
|
||||
value = __raw_readl(clk->enable_reg) | (1 << 7);
|
||||
|
||||
ret = clk_reparent(clk, parent);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
|
||||
/* Rebiuld the frequency table */
|
||||
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
|
||||
table, &clk->arch_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id)
|
||||
{
|
||||
struct clk_div4_table *d4t = clk->priv;
|
||||
unsigned long value;
|
||||
int idx = clk_rate_table_find(clk, clk->freq_table, rate);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value &= ~(0xf << clk->enable_bit);
|
||||
value |= (idx << clk->enable_bit);
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
|
||||
if (d4t->kick)
|
||||
d4t->kick(clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_clk_div4_enable(struct clk *clk)
|
||||
{
|
||||
__raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sh_clk_div4_disable(struct clk *clk)
|
||||
{
|
||||
__raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
|
||||
}
|
||||
|
||||
static struct clk_ops sh_clk_div4_clk_ops = {
|
||||
.recalc = sh_clk_div4_recalc,
|
||||
.set_rate = sh_clk_div4_set_rate,
|
||||
.round_rate = sh_clk_div_round_rate,
|
||||
};
|
||||
|
||||
static struct clk_ops sh_clk_div4_enable_clk_ops = {
|
||||
.recalc = sh_clk_div4_recalc,
|
||||
.set_rate = sh_clk_div4_set_rate,
|
||||
.round_rate = sh_clk_div_round_rate,
|
||||
.enable = sh_clk_div4_enable,
|
||||
.disable = sh_clk_div4_disable,
|
||||
};
|
||||
|
||||
static struct clk_ops sh_clk_div4_reparent_clk_ops = {
|
||||
.recalc = sh_clk_div4_recalc,
|
||||
.set_rate = sh_clk_div4_set_rate,
|
||||
.round_rate = sh_clk_div_round_rate,
|
||||
.enable = sh_clk_div4_enable,
|
||||
.disable = sh_clk_div4_disable,
|
||||
.set_parent = sh_clk_div4_set_parent,
|
||||
};
|
||||
|
||||
static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table, struct clk_ops *ops)
|
||||
{
|
||||
struct clk *clkp;
|
||||
void *freq_table;
|
||||
int nr_divs = table->div_mult_table->nr_divisors;
|
||||
int freq_table_size = sizeof(struct cpufreq_frequency_table);
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
freq_table_size *= (nr_divs + 1);
|
||||
freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
|
||||
if (!freq_table) {
|
||||
pr_err("sh_clk_div4_register: unable to alloc memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (k = 0; !ret && (k < nr); k++) {
|
||||
clkp = clks + k;
|
||||
|
||||
clkp->ops = ops;
|
||||
clkp->id = -1;
|
||||
clkp->priv = table;
|
||||
|
||||
clkp->freq_table = freq_table + (k * freq_table_size);
|
||||
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
ret = clk_register(clkp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __init sh_clk_div4_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table)
|
||||
{
|
||||
return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
|
||||
}
|
||||
|
||||
int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table)
|
||||
{
|
||||
return sh_clk_div4_register_ops(clks, nr, table,
|
||||
&sh_clk_div4_enable_clk_ops);
|
||||
}
|
||||
|
||||
int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table)
|
||||
{
|
||||
return sh_clk_div4_register_ops(clks, nr, table,
|
||||
&sh_clk_div4_reparent_clk_ops);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SH_CLK_CPG_LEGACY
|
||||
static struct clk master_clk = {
|
||||
.name = "master_clk",
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
.rate = CONFIG_SH_PCLK_FREQ,
|
||||
};
|
||||
|
||||
static struct clk peripheral_clk = {
|
||||
.name = "peripheral_clk",
|
||||
.parent = &master_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
};
|
||||
|
||||
static struct clk bus_clk = {
|
||||
.name = "bus_clk",
|
||||
.parent = &master_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
};
|
||||
|
||||
static struct clk cpu_clk = {
|
||||
.name = "cpu_clk",
|
||||
.parent = &master_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
};
|
||||
|
@ -327,6 +35,16 @@ static struct clk *onchip_clocks[] = {
|
|||
&cpu_clk,
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("master_clk", &master_clk),
|
||||
CLKDEV_CON_ID("peripheral_clk", &peripheral_clk),
|
||||
CLKDEV_CON_ID("bus_clk", &bus_clk),
|
||||
CLKDEV_CON_ID("cpu_clk", &cpu_clk),
|
||||
};
|
||||
|
||||
int __init __deprecated cpg_clk_init(void)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
@ -338,6 +56,8 @@ int __init __deprecated cpg_clk_init(void)
|
|||
ret |= clk_register(clk);
|
||||
}
|
||||
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
clk_add_alias("tmu_fck", NULL, "peripheral_clk", NULL);
|
||||
clk_add_alias("mtu2_fck", NULL, "peripheral_clk", NULL);
|
||||
clk_add_alias("cmt_fck", NULL, "peripheral_clk", NULL);
|
||||
|
@ -354,4 +74,3 @@ int __init __weak arch_clk_init(void)
|
|||
{
|
||||
return cpg_clk_init();
|
||||
}
|
||||
#endif /* CONFIG_SH_CPG_CLK_LEGACY */
|
||||
|
|
|
@ -16,500 +16,10 @@
|
|||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/machvec.h>
|
||||
|
||||
static LIST_HEAD(clock_list);
|
||||
static DEFINE_SPINLOCK(clock_lock);
|
||||
static DEFINE_MUTEX(clock_list_sem);
|
||||
|
||||
void clk_rate_table_build(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
int nr_freqs,
|
||||
struct clk_div_mult_table *src_table,
|
||||
unsigned long *bitmap)
|
||||
{
|
||||
unsigned long mult, div;
|
||||
unsigned long freq;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_freqs; i++) {
|
||||
div = 1;
|
||||
mult = 1;
|
||||
|
||||
if (src_table->divisors && i < src_table->nr_divisors)
|
||||
div = src_table->divisors[i];
|
||||
|
||||
if (src_table->multipliers && i < src_table->nr_multipliers)
|
||||
mult = src_table->multipliers[i];
|
||||
|
||||
if (!div || !mult || (bitmap && !test_bit(i, bitmap)))
|
||||
freq = CPUFREQ_ENTRY_INVALID;
|
||||
else
|
||||
freq = clk->parent->rate * mult / div;
|
||||
|
||||
freq_table[i].index = i;
|
||||
freq_table[i].frequency = freq;
|
||||
}
|
||||
|
||||
/* Termination entry */
|
||||
freq_table[i].index = i;
|
||||
freq_table[i].frequency = CPUFREQ_TABLE_END;
|
||||
}
|
||||
|
||||
long clk_rate_table_round(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long rate_error, rate_error_prev = ~0UL;
|
||||
unsigned long rate_best_fit = rate;
|
||||
unsigned long highest, lowest;
|
||||
int i;
|
||||
|
||||
highest = lowest = 0;
|
||||
|
||||
for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
unsigned long freq = freq_table[i].frequency;
|
||||
|
||||
if (freq == CPUFREQ_ENTRY_INVALID)
|
||||
continue;
|
||||
|
||||
if (freq > highest)
|
||||
highest = freq;
|
||||
if (freq < lowest)
|
||||
lowest = freq;
|
||||
|
||||
rate_error = abs(freq - rate);
|
||||
if (rate_error < rate_error_prev) {
|
||||
rate_best_fit = freq;
|
||||
rate_error_prev = rate_error;
|
||||
}
|
||||
|
||||
if (rate_error == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rate >= highest)
|
||||
rate_best_fit = highest;
|
||||
if (rate <= lowest)
|
||||
rate_best_fit = lowest;
|
||||
|
||||
return rate_best_fit;
|
||||
}
|
||||
|
||||
int clk_rate_table_find(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
unsigned long rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
unsigned long freq = freq_table[i].frequency;
|
||||
|
||||
if (freq == CPUFREQ_ENTRY_INVALID)
|
||||
continue;
|
||||
|
||||
if (freq == rate)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Used for clocks that always have same value as the parent clock */
|
||||
unsigned long followparent_recalc(struct clk *clk)
|
||||
{
|
||||
return clk->parent ? clk->parent->rate : 0;
|
||||
}
|
||||
|
||||
int clk_reparent(struct clk *child, struct clk *parent)
|
||||
{
|
||||
list_del_init(&child->sibling);
|
||||
if (parent)
|
||||
list_add(&child->sibling, &parent->children);
|
||||
child->parent = parent;
|
||||
|
||||
/* now do the debugfs renaming to reattach the child
|
||||
to the proper parent */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Propagate rate to children */
|
||||
void propagate_rate(struct clk *tclk)
|
||||
{
|
||||
struct clk *clkp;
|
||||
|
||||
list_for_each_entry(clkp, &tclk->children, sibling) {
|
||||
if (clkp->ops && clkp->ops->recalc)
|
||||
clkp->rate = clkp->ops->recalc(clkp);
|
||||
|
||||
propagate_rate(clkp);
|
||||
}
|
||||
}
|
||||
|
||||
static void __clk_disable(struct clk *clk)
|
||||
{
|
||||
if (clk->usecount == 0) {
|
||||
printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
|
||||
clk->name);
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(--clk->usecount)) {
|
||||
if (likely(clk->ops && clk->ops->disable))
|
||||
clk->ops->disable(clk);
|
||||
if (likely(clk->parent))
|
||||
__clk_disable(clk->parent);
|
||||
}
|
||||
}
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!clk)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
__clk_disable(clk);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_disable);
|
||||
|
||||
static int __clk_enable(struct clk *clk)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (clk->usecount++ == 0) {
|
||||
if (clk->parent) {
|
||||
ret = __clk_enable(clk->parent);
|
||||
if (unlikely(ret))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (clk->ops && clk->ops->enable) {
|
||||
ret = clk->ops->enable(clk);
|
||||
if (ret) {
|
||||
if (clk->parent)
|
||||
__clk_disable(clk->parent);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
err:
|
||||
clk->usecount--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!clk)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
ret = __clk_enable(clk);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_enable);
|
||||
|
||||
static LIST_HEAD(root_clks);
|
||||
|
||||
/**
|
||||
* recalculate_root_clocks - recalculate and propagate all root clocks
|
||||
*
|
||||
* Recalculates all root clocks (clocks with no parent), which if the
|
||||
* clock's .recalc is set correctly, should also propagate their rates.
|
||||
* Called at init.
|
||||
*/
|
||||
void recalculate_root_clocks(void)
|
||||
{
|
||||
struct clk *clkp;
|
||||
|
||||
list_for_each_entry(clkp, &root_clks, sibling) {
|
||||
if (clkp->ops && clkp->ops->recalc)
|
||||
clkp->rate = clkp->ops->recalc(clkp);
|
||||
propagate_rate(clkp);
|
||||
}
|
||||
}
|
||||
|
||||
int clk_register(struct clk *clk)
|
||||
{
|
||||
if (clk == NULL || IS_ERR(clk))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* trap out already registered clocks
|
||||
*/
|
||||
if (clk->node.next || clk->node.prev)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&clock_list_sem);
|
||||
|
||||
INIT_LIST_HEAD(&clk->children);
|
||||
clk->usecount = 0;
|
||||
|
||||
if (clk->parent)
|
||||
list_add(&clk->sibling, &clk->parent->children);
|
||||
else
|
||||
list_add(&clk->sibling, &root_clks);
|
||||
|
||||
list_add(&clk->node, &clock_list);
|
||||
if (clk->ops && clk->ops->init)
|
||||
clk->ops->init(clk);
|
||||
mutex_unlock(&clock_list_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register);
|
||||
|
||||
void clk_unregister(struct clk *clk)
|
||||
{
|
||||
mutex_lock(&clock_list_sem);
|
||||
list_del(&clk->sibling);
|
||||
list_del(&clk->node);
|
||||
mutex_unlock(&clock_list_sem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_unregister);
|
||||
|
||||
static void clk_enable_init_clocks(void)
|
||||
{
|
||||
struct clk *clkp;
|
||||
|
||||
list_for_each_entry(clkp, &clock_list, node)
|
||||
if (clkp->flags & CLK_ENABLE_ON_INIT)
|
||||
clk_enable(clkp);
|
||||
}
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
return clk->rate;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_get_rate);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return clk_set_rate_ex(clk, rate, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate);
|
||||
|
||||
int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
|
||||
if (likely(clk->ops && clk->ops->set_rate)) {
|
||||
ret = clk->ops->set_rate(clk, rate, algo_id);
|
||||
if (ret != 0)
|
||||
goto out_unlock;
|
||||
} else {
|
||||
clk->rate = rate;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (clk->ops && clk->ops->recalc)
|
||||
clk->rate = clk->ops->recalc(clk);
|
||||
|
||||
propagate_rate(clk);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate_ex);
|
||||
|
||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!parent || !clk)
|
||||
return ret;
|
||||
if (clk->parent == parent)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
if (clk->usecount == 0) {
|
||||
if (clk->ops->set_parent)
|
||||
ret = clk->ops->set_parent(clk, parent);
|
||||
else
|
||||
ret = clk_reparent(clk, parent);
|
||||
|
||||
if (ret == 0) {
|
||||
pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
|
||||
clk->name, clk->parent->name, clk->rate);
|
||||
if (clk->ops->recalc)
|
||||
clk->rate = clk->ops->recalc(clk);
|
||||
propagate_rate(clk);
|
||||
}
|
||||
} else
|
||||
ret = -EBUSY;
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_parent);
|
||||
|
||||
struct clk *clk_get_parent(struct clk *clk)
|
||||
{
|
||||
return clk->parent;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_get_parent);
|
||||
|
||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
if (likely(clk->ops && clk->ops->round_rate)) {
|
||||
unsigned long flags, rounded;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
rounded = clk->ops->round_rate(clk, rate);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return rounded;
|
||||
}
|
||||
|
||||
return clk_get_rate(clk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_round_rate);
|
||||
|
||||
/*
|
||||
* Returns a clock. Note that we first try to use device id on the bus
|
||||
* and clock name. If this fails, we try to use clock name only.
|
||||
*/
|
||||
struct clk *clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
const char *dev_id = dev ? dev_name(dev) : NULL;
|
||||
struct clk *p, *clk = ERR_PTR(-ENOENT);
|
||||
int idno;
|
||||
|
||||
clk = clk_get_sys(dev_id, id);
|
||||
if (clk && !IS_ERR(clk))
|
||||
return clk;
|
||||
|
||||
if (dev == NULL || dev->bus != &platform_bus_type)
|
||||
idno = -1;
|
||||
else
|
||||
idno = to_platform_device(dev)->id;
|
||||
|
||||
mutex_lock(&clock_list_sem);
|
||||
list_for_each_entry(p, &clock_list, node) {
|
||||
if (p->name && p->id == idno &&
|
||||
strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
|
||||
clk = p;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(p, &clock_list, node) {
|
||||
if (p->name &&
|
||||
strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
|
||||
clk = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
mutex_unlock(&clock_list_sem);
|
||||
|
||||
return clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_get);
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
if (clk && !IS_ERR(clk))
|
||||
module_put(clk->owner);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_put);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
static pm_message_t prev_state;
|
||||
struct clk *clkp;
|
||||
|
||||
switch (state.event) {
|
||||
case PM_EVENT_ON:
|
||||
/* Resumeing from hibernation */
|
||||
if (prev_state.event != PM_EVENT_FREEZE)
|
||||
break;
|
||||
|
||||
list_for_each_entry(clkp, &clock_list, node) {
|
||||
if (likely(clkp->ops)) {
|
||||
unsigned long rate = clkp->rate;
|
||||
|
||||
if (likely(clkp->ops->set_parent))
|
||||
clkp->ops->set_parent(clkp,
|
||||
clkp->parent);
|
||||
if (likely(clkp->ops->set_rate))
|
||||
clkp->ops->set_rate(clkp,
|
||||
rate, NO_CHANGE);
|
||||
else if (likely(clkp->ops->recalc))
|
||||
clkp->rate = clkp->ops->recalc(clkp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PM_EVENT_FREEZE:
|
||||
break;
|
||||
case PM_EVENT_SUSPEND:
|
||||
break;
|
||||
}
|
||||
|
||||
prev_state = state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clks_sysdev_resume(struct sys_device *dev)
|
||||
{
|
||||
return clks_sysdev_suspend(dev, PMSG_ON);
|
||||
}
|
||||
|
||||
static struct sysdev_class clks_sysdev_class = {
|
||||
.name = "clks",
|
||||
};
|
||||
|
||||
static struct sysdev_driver clks_sysdev_driver = {
|
||||
.suspend = clks_sysdev_suspend,
|
||||
.resume = clks_sysdev_resume,
|
||||
};
|
||||
|
||||
static struct sys_device clks_sysdev_dev = {
|
||||
.cls = &clks_sysdev_class,
|
||||
};
|
||||
|
||||
static int __init clk_sysdev_init(void)
|
||||
{
|
||||
sysdev_class_register(&clks_sysdev_class);
|
||||
sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver);
|
||||
sysdev_register(&clks_sysdev_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(clk_sysdev_init);
|
||||
#endif
|
||||
|
||||
int __init clk_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
@ -539,89 +49,19 @@ int __init clk_init(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* debugfs support to trace clock tree hierarchy and attributes
|
||||
* Returns a clock. Note that we first try to use device id on the bus
|
||||
* and clock name. If this fails, we try to use clock name only.
|
||||
*/
|
||||
static struct dentry *clk_debugfs_root;
|
||||
|
||||
static int clk_debugfs_register_one(struct clk *c)
|
||||
struct clk *clk_get(struct device *dev, const char *con_id)
|
||||
{
|
||||
int err;
|
||||
struct dentry *d, *child, *child_tmp;
|
||||
struct clk *pa = c->parent;
|
||||
char s[255];
|
||||
char *p = s;
|
||||
const char *dev_id = dev ? dev_name(dev) : NULL;
|
||||
|
||||
p += sprintf(p, "%s", c->name);
|
||||
if (c->id >= 0)
|
||||
sprintf(p, ":%d", c->id);
|
||||
d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
c->dentry = d;
|
||||
|
||||
d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
d = c->dentry;
|
||||
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
|
||||
debugfs_remove(child);
|
||||
debugfs_remove(c->dentry);
|
||||
return err;
|
||||
return clk_get_sys(dev_id, con_id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_get);
|
||||
|
||||
static int clk_debugfs_register(struct clk *c)
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
int err;
|
||||
struct clk *pa = c->parent;
|
||||
|
||||
if (pa && !pa->dentry) {
|
||||
err = clk_debugfs_register(pa);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!c->dentry && c->name) {
|
||||
err = clk_debugfs_register_one(c);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_put);
|
||||
|
||||
static int __init clk_debugfs_init(void)
|
||||
{
|
||||
struct clk *c;
|
||||
struct dentry *d;
|
||||
int err;
|
||||
|
||||
d = debugfs_create_dir("clock", NULL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
clk_debugfs_root = d;
|
||||
|
||||
list_for_each_entry(c, &clock_list, node) {
|
||||
err = clk_debugfs_register(c);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
return 0;
|
||||
err_out:
|
||||
debugfs_remove_recursive(clk_debugfs_root);
|
||||
return err;
|
||||
}
|
||||
late_initcall(clk_debugfs_init);
|
||||
|
|
|
@ -12,9 +12,10 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CPG2_FRQCR3 0xfe0a0018
|
||||
|
||||
|
@ -45,7 +46,6 @@ static struct clk_ops sh4202_emi_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk sh4202_emi_clk = {
|
||||
.name = "emi_clk",
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
.ops = &sh4202_emi_clk_ops,
|
||||
};
|
||||
|
@ -61,7 +61,6 @@ static struct clk_ops sh4202_femi_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk sh4202_femi_clk = {
|
||||
.name = "femi_clk",
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
.ops = &sh4202_femi_clk_ops,
|
||||
};
|
||||
|
@ -139,7 +138,6 @@ static struct clk_ops sh4202_shoc_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk sh4202_shoc_clk = {
|
||||
.name = "shoc_clk",
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
.ops = &sh4202_shoc_clk_ops,
|
||||
};
|
||||
|
@ -150,6 +148,15 @@ static struct clk *sh4202_onchip_clocks[] = {
|
|||
&sh4202_shoc_clk,
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("emi_clk", &sh4202_emi_clk),
|
||||
CLKDEV_CON_ID("femi_clk", &sh4202_femi_clk),
|
||||
CLKDEV_CON_ID("shoc_clk", &sh4202_shoc_clk),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
@ -167,5 +174,7 @@ int __init arch_clk_init(void)
|
|||
|
||||
clk_put(clk);
|
||||
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
/* Fixed 32 KHz root clock for RTC and Power Management purposes */
|
||||
static struct clk r_clk = {
|
||||
.name = "rclk",
|
||||
.id = -1,
|
||||
.rate = 32768,
|
||||
};
|
||||
|
||||
|
@ -47,8 +45,6 @@ static struct clk r_clk = {
|
|||
* from the platform code.
|
||||
*/
|
||||
struct clk extal_clk = {
|
||||
.name = "extal",
|
||||
.id = -1,
|
||||
.rate = 33333333,
|
||||
};
|
||||
|
||||
|
@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk dll_clk = {
|
||||
.name = "dll_clk",
|
||||
.id = -1,
|
||||
.ops = &dll_clk_ops,
|
||||
.parent = &r_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
|
@ -92,8 +86,6 @@ static struct clk_ops pll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk pll_clk = {
|
||||
.name = "pll_clk",
|
||||
.id = -1,
|
||||
.ops = &pll_clk_ops,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
};
|
||||
|
@ -122,18 +114,18 @@ static struct clk_div4_table div4_table = {
|
|||
enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
|
||||
DIV4_SIUA, DIV4_SIUB, DIV4_NR };
|
||||
|
||||
#define DIV4(_str, _reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
|
||||
#define DIV4(_reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
|
||||
|
||||
struct clk div4_clks[DIV4_NR] = {
|
||||
[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0),
|
||||
[DIV4_I] = DIV4(FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
|
||||
};
|
||||
|
||||
enum { DIV6_V, DIV6_NR };
|
||||
|
@ -142,61 +134,148 @@ struct clk div6_clks[DIV6_NR] = {
|
|||
[DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
|
||||
};
|
||||
|
||||
#define MSTP(_str, _parent, _reg, _bit, _flags) \
|
||||
SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
|
||||
#define MSTP(_parent, _reg, _bit, _flags) \
|
||||
SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
|
||||
|
||||
static struct clk mstp_clks[] = {
|
||||
MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
|
||||
MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
|
||||
MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
|
||||
MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
|
||||
MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
|
||||
MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0),
|
||||
MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0),
|
||||
MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0),
|
||||
MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0),
|
||||
MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0),
|
||||
MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0),
|
||||
MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
|
||||
MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0),
|
||||
MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
|
||||
MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0),
|
||||
MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 4, 0),
|
||||
MSTP("sio0", &div4_clks[DIV4_P], MSTPCR0, 3, 0),
|
||||
MSTP("siof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0),
|
||||
MSTP("siof1", &div4_clks[DIV4_P], MSTPCR0, 1, 0),
|
||||
enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026,
|
||||
MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016,
|
||||
MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010,
|
||||
MSTP007, MSTP006, MSTP005, MSTP004, MSTP003, MSTP002, MSTP001,
|
||||
MSTP109, MSTP108, MSTP100,
|
||||
MSTP225, MSTP224, MSTP218, MSTP217, MSTP216,
|
||||
MSTP214, MSTP213, MSTP212, MSTP211, MSTP208,
|
||||
MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
|
||||
MSTP_NR };
|
||||
|
||||
MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
|
||||
MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0),
|
||||
static struct clk mstp_clks[MSTP_NR] = {
|
||||
[MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
|
||||
[MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
|
||||
[MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
|
||||
[MSTP028] = MSTP(&div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
|
||||
[MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
|
||||
[MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
|
||||
[MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
|
||||
[MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
|
||||
[MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
|
||||
[MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
|
||||
[MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
|
||||
[MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
|
||||
[MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0),
|
||||
[MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0),
|
||||
[MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
|
||||
[MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
|
||||
[MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
|
||||
[MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
|
||||
[MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
|
||||
[MSTP004] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
|
||||
[MSTP003] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
|
||||
[MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
|
||||
[MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
|
||||
|
||||
MSTP("tpu0", &div4_clks[DIV4_P], MSTPCR2, 25, 0),
|
||||
MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0),
|
||||
MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
|
||||
MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0),
|
||||
MSTP("sim0", &div4_clks[DIV4_P], MSTPCR2, 16, 0),
|
||||
MSTP("keysc0", &r_clk, MSTPCR2, 14, 0),
|
||||
MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 13, 0),
|
||||
MSTP("s3d40", &div4_clks[DIV4_P], MSTPCR2, 12, 0),
|
||||
MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
|
||||
MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0),
|
||||
MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
|
||||
MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
|
||||
MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
|
||||
MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
|
||||
MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
|
||||
MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
|
||||
MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
|
||||
[MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
|
||||
[MSTP108] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 8, 0),
|
||||
|
||||
[MSTP225] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 25, 0),
|
||||
[MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
|
||||
[MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
|
||||
[MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
|
||||
[MSTP216] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 16, 0),
|
||||
[MSTP214] = MSTP(&r_clk, MSTPCR2, 14, 0),
|
||||
[MSTP213] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 13, 0),
|
||||
[MSTP212] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 12, 0),
|
||||
[MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
|
||||
[MSTP208] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 8, 0),
|
||||
[MSTP206] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
|
||||
[MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
|
||||
[MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
|
||||
[MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
|
||||
[MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
|
||||
[MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
|
||||
[MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("rclk", &r_clk),
|
||||
CLKDEV_CON_ID("extal", &extal_clk),
|
||||
CLKDEV_CON_ID("dll_clk", &dll_clk),
|
||||
CLKDEV_CON_ID("pll_clk", &pll_clk),
|
||||
|
||||
/* DIV4 clocks */
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
|
||||
CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
|
||||
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
|
||||
CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
|
||||
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
|
||||
CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]),
|
||||
CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]),
|
||||
|
||||
/* DIV6 clocks */
|
||||
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]),
|
||||
CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]),
|
||||
CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]),
|
||||
CLKDEV_CON_ID("uram0", &mstp_clks[MSTP028]),
|
||||
CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]),
|
||||
CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]),
|
||||
CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]),
|
||||
CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]),
|
||||
CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]),
|
||||
CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
|
||||
CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
|
||||
CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
|
||||
CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP014]),
|
||||
CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
|
||||
CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
|
||||
CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
|
||||
{
|
||||
/* SCIF0 */
|
||||
.dev_id = "sh-sci.0",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP007],
|
||||
}, {
|
||||
/* SCIF1 */
|
||||
.dev_id = "sh-sci.1",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP006],
|
||||
}, {
|
||||
/* SCIF2 */
|
||||
.dev_id = "sh-sci.2",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP005],
|
||||
}, {
|
||||
/* SCIF3 */
|
||||
.dev_id = "sh-sci.3",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP004],
|
||||
},
|
||||
CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]),
|
||||
CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]),
|
||||
CLKDEV_CON_ID("siof1", &mstp_clks[MSTP001]),
|
||||
CLKDEV_CON_ID("i2c0", &mstp_clks[MSTP109]),
|
||||
CLKDEV_CON_ID("i2c1", &mstp_clks[MSTP108]),
|
||||
CLKDEV_CON_ID("tpu0", &mstp_clks[MSTP225]),
|
||||
CLKDEV_CON_ID("irda0", &mstp_clks[MSTP224]),
|
||||
CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
|
||||
CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]),
|
||||
CLKDEV_CON_ID("sim0", &mstp_clks[MSTP216]),
|
||||
CLKDEV_CON_ID("keysc0", &mstp_clks[MSTP214]),
|
||||
CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP213]),
|
||||
CLKDEV_CON_ID("s3d40", &mstp_clks[MSTP212]),
|
||||
CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]),
|
||||
CLKDEV_CON_ID("siu0", &mstp_clks[MSTP208]),
|
||||
CLKDEV_CON_ID("jpu0", &mstp_clks[MSTP206]),
|
||||
CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]),
|
||||
CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]),
|
||||
CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]),
|
||||
CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]),
|
||||
CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]),
|
||||
CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
|
@ -221,7 +300,7 @@ int __init arch_clk_init(void)
|
|||
ret = sh_clk_div6_register(div6_clks, DIV6_NR);
|
||||
|
||||
if (!ret)
|
||||
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
|
||||
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
/* Fixed 32 KHz root clock for RTC and Power Management purposes */
|
||||
static struct clk r_clk = {
|
||||
.name = "rclk",
|
||||
.id = -1,
|
||||
.rate = 32768,
|
||||
};
|
||||
|
||||
|
@ -47,8 +45,6 @@ static struct clk r_clk = {
|
|||
* from the platform code.
|
||||
*/
|
||||
struct clk extal_clk = {
|
||||
.name = "extal",
|
||||
.id = -1,
|
||||
.rate = 33333333,
|
||||
};
|
||||
|
||||
|
@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk dll_clk = {
|
||||
.name = "dll_clk",
|
||||
.id = -1,
|
||||
.ops = &dll_clk_ops,
|
||||
.parent = &r_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
|
@ -95,8 +89,6 @@ static struct clk_ops pll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk pll_clk = {
|
||||
.name = "pll_clk",
|
||||
.id = -1,
|
||||
.ops = &pll_clk_ops,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
};
|
||||
|
@ -125,18 +117,18 @@ static struct clk_div4_table div4_table = {
|
|||
enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
|
||||
DIV4_SIUA, DIV4_SIUB, DIV4_NR };
|
||||
|
||||
#define DIV4(_str, _reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
|
||||
#define DIV4(_reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
|
||||
|
||||
struct clk div4_clks[DIV4_NR] = {
|
||||
[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0),
|
||||
[DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
|
||||
};
|
||||
|
||||
enum { DIV6_V, DIV6_NR };
|
||||
|
@ -145,58 +137,134 @@ struct clk div6_clks[DIV6_NR] = {
|
|||
[DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
|
||||
};
|
||||
|
||||
#define MSTP(_str, _parent, _reg, _bit, _flags) \
|
||||
SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
|
||||
#define MSTP(_parent, _reg, _bit, _flags) \
|
||||
SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
|
||||
|
||||
static struct clk mstp_clks[] = {
|
||||
enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026,
|
||||
MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016,
|
||||
MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010,
|
||||
MSTP007, MSTP006, MSTP005, MSTP002, MSTP001,
|
||||
MSTP109, MSTP100,
|
||||
MSTP227, MSTP226, MSTP224, MSTP223, MSTP222, MSTP218, MSTP217,
|
||||
MSTP211, MSTP207, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
|
||||
MSTP_NR };
|
||||
|
||||
static struct clk mstp_clks[MSTP_NR] = {
|
||||
/* See page 52 of Datasheet V0.40: Overview -> Block Diagram */
|
||||
MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
|
||||
MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
|
||||
MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
|
||||
MSTP("rsmem0", &div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
|
||||
MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
|
||||
MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0),
|
||||
MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0),
|
||||
MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0),
|
||||
MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0),
|
||||
MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0),
|
||||
MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0),
|
||||
MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
|
||||
MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0),
|
||||
MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
|
||||
MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0),
|
||||
MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0),
|
||||
MSTP("msiof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0),
|
||||
MSTP("sbr0", &div4_clks[DIV4_P], MSTPCR0, 1, 0),
|
||||
[MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
|
||||
[MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
|
||||
[MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
|
||||
[MSTP028] = MSTP(&div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
|
||||
[MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
|
||||
[MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
|
||||
[MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
|
||||
[MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
|
||||
[MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
|
||||
[MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
|
||||
[MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
|
||||
[MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
|
||||
[MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0),
|
||||
[MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0),
|
||||
[MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
|
||||
[MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
|
||||
[MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
|
||||
[MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
|
||||
[MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
|
||||
[MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
|
||||
[MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
|
||||
|
||||
MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
|
||||
[MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
|
||||
|
||||
MSTP("icb0", &div4_clks[DIV4_P], MSTPCR2, 27, 0),
|
||||
MSTP("meram0", &div4_clks[DIV4_P], MSTPCR2, 26, 0),
|
||||
MSTP("dacy1", &div4_clks[DIV4_P], MSTPCR2, 24, 0),
|
||||
MSTP("dacy0", &div4_clks[DIV4_P], MSTPCR2, 23, 0),
|
||||
MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 22, 0),
|
||||
MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
|
||||
MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0),
|
||||
MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
|
||||
MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0),
|
||||
MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT),
|
||||
MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
|
||||
MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
|
||||
MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
|
||||
MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
|
||||
MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
|
||||
MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
|
||||
[MSTP227] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 27, 0),
|
||||
[MSTP226] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 26, 0),
|
||||
[MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
|
||||
[MSTP223] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 23, 0),
|
||||
[MSTP222] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 22, 0),
|
||||
[MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
|
||||
[MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
|
||||
[MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
|
||||
[MSTP207] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT),
|
||||
[MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
|
||||
[MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
|
||||
[MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
|
||||
[MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
|
||||
[MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
|
||||
[MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("rclk", &r_clk),
|
||||
CLKDEV_CON_ID("extal", &extal_clk),
|
||||
CLKDEV_CON_ID("dll_clk", &dll_clk),
|
||||
CLKDEV_CON_ID("pll_clk", &pll_clk),
|
||||
|
||||
/* DIV4 clocks */
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
|
||||
CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
|
||||
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
|
||||
CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
|
||||
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
|
||||
CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]),
|
||||
CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]),
|
||||
|
||||
/* DIV6 clocks */
|
||||
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]),
|
||||
CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]),
|
||||
CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]),
|
||||
CLKDEV_CON_ID("rsmem0", &mstp_clks[MSTP028]),
|
||||
CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]),
|
||||
CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]),
|
||||
CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]),
|
||||
CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]),
|
||||
CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]),
|
||||
CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
|
||||
CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
|
||||
CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
|
||||
CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP014]),
|
||||
CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
|
||||
CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
|
||||
CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
|
||||
{
|
||||
/* SCIF0 */
|
||||
.dev_id = "sh-sci.0",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP007],
|
||||
}, {
|
||||
/* SCIF1 */
|
||||
.dev_id = "sh-sci.1",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP006],
|
||||
}, {
|
||||
/* SCIF2 */
|
||||
.dev_id = "sh-sci.2",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP005],
|
||||
},
|
||||
CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
|
||||
CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),
|
||||
CLKDEV_CON_ID("i2c0", &mstp_clks[MSTP109]),
|
||||
CLKDEV_CON_ID("icb0", &mstp_clks[MSTP227]),
|
||||
CLKDEV_CON_ID("meram0", &mstp_clks[MSTP226]),
|
||||
CLKDEV_CON_ID("dacy1", &mstp_clks[MSTP224]),
|
||||
CLKDEV_CON_ID("dacy0", &mstp_clks[MSTP223]),
|
||||
CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP222]),
|
||||
CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
|
||||
CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]),
|
||||
CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]),
|
||||
CLKDEV_CON_ID("veu1", &mstp_clks[MSTP207]),
|
||||
CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]),
|
||||
CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]),
|
||||
CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]),
|
||||
CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]),
|
||||
CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]),
|
||||
CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
|
@ -221,7 +289,7 @@ int __init arch_clk_init(void)
|
|||
ret = sh_clk_div6_register(div6_clks, DIV6_NR);
|
||||
|
||||
if (!ret)
|
||||
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
|
||||
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
/* Fixed 32 KHz root clock for RTC and Power Management purposes */
|
||||
static struct clk r_clk = {
|
||||
.name = "rclk",
|
||||
.id = -1,
|
||||
.rate = 32768,
|
||||
};
|
||||
|
||||
|
@ -47,8 +45,6 @@ static struct clk r_clk = {
|
|||
* from the platform code.
|
||||
*/
|
||||
struct clk extal_clk = {
|
||||
.name = "extal",
|
||||
.id = -1,
|
||||
.rate = 33333333,
|
||||
};
|
||||
|
||||
|
@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk dll_clk = {
|
||||
.name = "dll_clk",
|
||||
.id = -1,
|
||||
.ops = &dll_clk_ops,
|
||||
.parent = &r_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
|
@ -95,8 +89,6 @@ static struct clk_ops pll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk pll_clk = {
|
||||
.name = "pll_clk",
|
||||
.id = -1,
|
||||
.ops = &pll_clk_ops,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
};
|
||||
|
@ -122,31 +114,31 @@ static struct clk_div4_table div4_table = {
|
|||
.div_mult_table = &div4_div_mult_table,
|
||||
};
|
||||
|
||||
#define DIV4(_str, _reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
|
||||
#define DIV4(_reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
|
||||
|
||||
enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };
|
||||
|
||||
struct clk div4_clks[DIV4_NR] = {
|
||||
[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0),
|
||||
[DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
|
||||
};
|
||||
|
||||
enum { DIV4_IRDA, DIV4_ENABLE_NR };
|
||||
|
||||
struct clk div4_enable_clks[DIV4_ENABLE_NR] = {
|
||||
[DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x1fff, 0),
|
||||
[DIV4_IRDA] = DIV4(IRDACLKCR, 0, 0x1fff, 0),
|
||||
};
|
||||
|
||||
enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };
|
||||
|
||||
struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {
|
||||
[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
|
||||
[DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
|
||||
};
|
||||
|
||||
enum { DIV6_V, DIV6_NR };
|
||||
|
@ -186,6 +178,23 @@ static struct clk mstp_clks[HWBLK_NR] = {
|
|||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("rclk", &r_clk),
|
||||
CLKDEV_CON_ID("extal", &extal_clk),
|
||||
CLKDEV_CON_ID("dll_clk", &dll_clk),
|
||||
CLKDEV_CON_ID("pll_clk", &pll_clk),
|
||||
|
||||
/* DIV4 clocks */
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
|
||||
CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
|
||||
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
|
||||
CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
|
||||
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
|
||||
CLKDEV_CON_ID("irda_clk", &div4_enable_clks[DIV4_IRDA]),
|
||||
CLKDEV_CON_ID("siua_clk", &div4_reparent_clks[DIV4_SIUA]),
|
||||
CLKDEV_CON_ID("siub_clk", &div4_reparent_clks[DIV4_SIUB]),
|
||||
|
||||
/* DIV6 clocks */
|
||||
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
|
||||
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
|
||||
/* Fixed 32 KHz root clock for RTC and Power Management purposes */
|
||||
static struct clk r_clk = {
|
||||
.name = "rclk",
|
||||
.id = -1,
|
||||
.rate = 32768,
|
||||
};
|
||||
|
||||
|
@ -48,8 +46,6 @@ static struct clk r_clk = {
|
|||
* from the platform code.
|
||||
*/
|
||||
struct clk extal_clk = {
|
||||
.name = "extal",
|
||||
.id = -1,
|
||||
.rate = 33333333,
|
||||
};
|
||||
|
||||
|
@ -71,8 +67,6 @@ static struct clk_ops dll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk dll_clk = {
|
||||
.name = "dll_clk",
|
||||
.id = -1,
|
||||
.ops = &dll_clk_ops,
|
||||
.parent = &r_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
|
@ -96,8 +90,6 @@ static struct clk_ops pll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk pll_clk = {
|
||||
.name = "pll_clk",
|
||||
.id = -1,
|
||||
.ops = &pll_clk_ops,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
};
|
||||
|
@ -125,29 +117,29 @@ static struct clk_div4_table div4_table = {
|
|||
|
||||
enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };
|
||||
|
||||
#define DIV4(_str, _reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
|
||||
#define DIV4(_reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
|
||||
|
||||
struct clk div4_clks[DIV4_NR] = {
|
||||
[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x0dbf, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x0dbf, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x0dbf, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x0dbf, 0),
|
||||
[DIV4_I] = DIV4(FRQCR, 20, 0x0dbf, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4(FRQCR, 16, 0x0dbf, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4(FRQCR, 12, 0x0dbf, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4(FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B3] = DIV4(FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4(FRQCR, 0, 0x0dbf, 0),
|
||||
};
|
||||
|
||||
enum { DIV4_IRDA, DIV4_ENABLE_NR };
|
||||
|
||||
struct clk div4_enable_clks[DIV4_ENABLE_NR] = {
|
||||
[DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x0dbf, 0),
|
||||
[DIV4_IRDA] = DIV4(IRDACLKCR, 0, 0x0dbf, 0),
|
||||
};
|
||||
|
||||
enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };
|
||||
|
||||
struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {
|
||||
[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0),
|
||||
[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0),
|
||||
[DIV4_SIUA] = DIV4(SCLKACR, 0, 0x0dbf, 0),
|
||||
[DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x0dbf, 0),
|
||||
};
|
||||
enum { DIV6_V, DIV6_NR };
|
||||
|
||||
|
@ -211,6 +203,23 @@ static struct clk mstp_clks[] = {
|
|||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("rclk", &r_clk),
|
||||
CLKDEV_CON_ID("extal", &extal_clk),
|
||||
CLKDEV_CON_ID("dll_clk", &dll_clk),
|
||||
CLKDEV_CON_ID("pll_clk", &pll_clk),
|
||||
|
||||
/* DIV4 clocks */
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
|
||||
CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
|
||||
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
|
||||
CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
|
||||
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
|
||||
CLKDEV_CON_ID("irda_clk", &div4_enable_clks[DIV4_IRDA]),
|
||||
CLKDEV_CON_ID("siua_clk", &div4_reparent_clks[DIV4_SIUA]),
|
||||
CLKDEV_CON_ID("siub_clk", &div4_reparent_clks[DIV4_SIUB]),
|
||||
|
||||
/* DIV6 clocks */
|
||||
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
|
||||
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
|
||||
/* Fixed 32 KHz root clock for RTC and Power Management purposes */
|
||||
static struct clk r_clk = {
|
||||
.name = "rclk",
|
||||
.id = -1,
|
||||
.rate = 32768,
|
||||
};
|
||||
|
||||
|
@ -51,8 +49,6 @@ static struct clk r_clk = {
|
|||
* from the platform code.
|
||||
*/
|
||||
struct clk extal_clk = {
|
||||
.name = "extal",
|
||||
.id = -1,
|
||||
.rate = 33333333,
|
||||
};
|
||||
|
||||
|
@ -76,8 +72,6 @@ static struct clk_ops fll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk fll_clk = {
|
||||
.name = "fll_clk",
|
||||
.id = -1,
|
||||
.ops = &fll_clk_ops,
|
||||
.parent = &r_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
|
@ -98,8 +92,6 @@ static struct clk_ops pll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk pll_clk = {
|
||||
.name = "pll_clk",
|
||||
.id = -1,
|
||||
.ops = &pll_clk_ops,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
};
|
||||
|
@ -115,8 +107,6 @@ static struct clk_ops div3_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk div3_clk = {
|
||||
.name = "div3_clk",
|
||||
.id = -1,
|
||||
.ops = &div3_clk_ops,
|
||||
.parent = &pll_clk,
|
||||
};
|
||||
|
@ -153,15 +143,15 @@ static struct clk_div4_table div4_table = {
|
|||
|
||||
enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_P, DIV4_M1, DIV4_NR };
|
||||
|
||||
#define DIV4(_str, _reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
|
||||
#define DIV4(_reg, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
|
||||
|
||||
struct clk div4_clks[DIV4_NR] = {
|
||||
[DIV4_I] = DIV4("cpu_clk", FRQCRA, 20, 0x2f7d, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4("shyway_clk", FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4("bus_clk", FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4("peripheral_clk", FRQCRA, 0, 0x2f7c, 0),
|
||||
[DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_I] = DIV4(FRQCRA, 20, 0x2f7d, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4(FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4(FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4(FRQCRA, 0, 0x2f7c, 0),
|
||||
[DIV4_M1] = DIV4(FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT),
|
||||
};
|
||||
|
||||
enum { DIV6_V, DIV6_FA, DIV6_FB, DIV6_I, DIV6_S, DIV6_NR };
|
||||
|
@ -234,6 +224,20 @@ static struct clk mstp_clks[HWBLK_NR] = {
|
|||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("rclk", &r_clk),
|
||||
CLKDEV_CON_ID("extal", &extal_clk),
|
||||
CLKDEV_CON_ID("fll_clk", &fll_clk),
|
||||
CLKDEV_CON_ID("pll_clk", &pll_clk),
|
||||
CLKDEV_CON_ID("div3_clk", &div3_clk),
|
||||
|
||||
/* DIV4 clocks */
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
|
||||
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
|
||||
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
|
||||
CLKDEV_CON_ID("vpu_clk", &div4_clks[DIV4_M1]),
|
||||
|
||||
/* DIV6 clocks */
|
||||
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
|
||||
CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FA]),
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
|
||||
|
@ -87,7 +88,6 @@ static struct clk_ops sh7757_shyway_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk sh7757_shyway_clk = {
|
||||
.name = "shyway_clk",
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
.ops = &sh7757_shyway_clk_ops,
|
||||
};
|
||||
|
@ -100,6 +100,13 @@ static struct clk *sh7757_onchip_clocks[] = {
|
|||
&sh7757_shyway_clk,
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("shyway_clk", &sh7757_shyway_clk),
|
||||
};
|
||||
|
||||
static int __init sh7757_clk_init(void)
|
||||
{
|
||||
struct clk *clk = clk_get(NULL, "master_clk");
|
||||
|
@ -123,6 +130,8 @@ static int __init sh7757_clk_init(void)
|
|||
|
||||
clk_put(clk);
|
||||
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -77,7 +79,6 @@ static struct clk_ops sh7763_shyway_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk sh7763_shyway_clk = {
|
||||
.name = "shyway_clk",
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
.ops = &sh7763_shyway_clk_ops,
|
||||
};
|
||||
|
@ -90,6 +91,13 @@ static struct clk *sh7763_onchip_clocks[] = {
|
|||
&sh7763_shyway_clk,
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("shyway_clk", &sh7763_shyway_clk),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
@ -107,5 +115,7 @@ int __init arch_clk_init(void)
|
|||
|
||||
clk_put(clk);
|
||||
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -83,7 +85,6 @@ static struct clk_ops sh7780_shyway_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk sh7780_shyway_clk = {
|
||||
.name = "shyway_clk",
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
.ops = &sh7780_shyway_clk_ops,
|
||||
};
|
||||
|
@ -96,6 +97,13 @@ static struct clk *sh7780_onchip_clocks[] = {
|
|||
&sh7780_shyway_clk,
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("shyway_clk", &sh7780_shyway_clk),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
@ -113,5 +121,7 @@ int __init arch_clk_init(void)
|
|||
|
||||
clk_put(clk);
|
||||
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
* from the platform code.
|
||||
*/
|
||||
static struct clk extal_clk = {
|
||||
.name = "extal",
|
||||
.id = -1,
|
||||
.rate = 33333333,
|
||||
};
|
||||
|
||||
|
@ -43,8 +41,6 @@ static struct clk_ops pll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk pll_clk = {
|
||||
.name = "pll_clk",
|
||||
.id = -1,
|
||||
.ops = &pll_clk_ops,
|
||||
.parent = &extal_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
|
@ -70,82 +66,149 @@ static struct clk_div4_table div4_table = {
|
|||
enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA,
|
||||
DIV4_DU, DIV4_P, DIV4_NR };
|
||||
|
||||
#define DIV4(_str, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags)
|
||||
#define DIV4(_bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
|
||||
|
||||
struct clk div4_clks[DIV4_NR] = {
|
||||
[DIV4_P] = DIV4("peripheral_clk", 0, 0x0f80, 0),
|
||||
[DIV4_DU] = DIV4("du_clk", 4, 0x0ff0, 0),
|
||||
[DIV4_GA] = DIV4("ga_clk", 8, 0x0030, 0),
|
||||
[DIV4_DDR] = DIV4("ddr_clk", 12, 0x000c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4("bus_clk", 16, 0x0fe0, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4("shyway_clk", 20, 0x000c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4("umem_clk", 24, 0x000c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_I] = DIV4("cpu_clk", 28, 0x000e, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4(0, 0x0f80, 0),
|
||||
[DIV4_DU] = DIV4(4, 0x0ff0, 0),
|
||||
[DIV4_GA] = DIV4(8, 0x0030, 0),
|
||||
[DIV4_DDR] = DIV4(12, 0x000c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4(16, 0x0fe0, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4(20, 0x000c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_U] = DIV4(24, 0x000c, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_I] = DIV4(28, 0x000e, CLK_ENABLE_ON_INIT),
|
||||
};
|
||||
|
||||
#define MSTPCR0 0xffc80030
|
||||
#define MSTPCR1 0xffc80034
|
||||
|
||||
static struct clk mstp_clks[] = {
|
||||
enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024,
|
||||
MSTP021, MSTP020, MSTP017, MSTP016,
|
||||
MSTP013, MSTP012, MSTP009, MSTP008, MSTP003, MSTP002,
|
||||
MSTP119, MSTP117, MSTP105, MSTP104, MSTP100,
|
||||
MSTP_NR };
|
||||
|
||||
static struct clk mstp_clks[MSTP_NR] = {
|
||||
/* MSTPCR0 */
|
||||
SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0),
|
||||
SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0),
|
||||
SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0),
|
||||
SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0),
|
||||
SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0),
|
||||
SH_CLK_MSTP32("mmcif_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 13, 0),
|
||||
SH_CLK_MSTP32("flctl_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 12, 0),
|
||||
SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0),
|
||||
SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0),
|
||||
SH_CLK_MSTP32("siof_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 3, 0),
|
||||
SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0),
|
||||
[MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0),
|
||||
[MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0),
|
||||
[MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
|
||||
[MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
|
||||
[MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
|
||||
[MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
|
||||
[MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
|
||||
[MSTP020] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
|
||||
[MSTP017] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
|
||||
[MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0),
|
||||
[MSTP013] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 13, 0),
|
||||
[MSTP012] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 12, 0),
|
||||
[MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
|
||||
[MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
|
||||
[MSTP003] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
|
||||
[MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
|
||||
|
||||
/* MSTPCR1 */
|
||||
SH_CLK_MSTP32("hudi_fck", -1, NULL, MSTPCR1, 19, 0),
|
||||
SH_CLK_MSTP32("ubc_fck", -1, NULL, MSTPCR1, 17, 0),
|
||||
SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0),
|
||||
SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0),
|
||||
SH_CLK_MSTP32("gdta_fck", -1, NULL, MSTPCR1, 0, 0),
|
||||
[MSTP119] = SH_CLK_MSTP32(NULL, MSTPCR1, 19, 0),
|
||||
[MSTP117] = SH_CLK_MSTP32(NULL, MSTPCR1, 17, 0),
|
||||
[MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
|
||||
[MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
|
||||
[MSTP100] = SH_CLK_MSTP32(NULL, MSTPCR1, 0, 0),
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("extal", &extal_clk),
|
||||
CLKDEV_CON_ID("pll_clk", &pll_clk),
|
||||
|
||||
/* DIV4 clocks */
|
||||
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
|
||||
CLKDEV_CON_ID("du_clk", &div4_clks[DIV4_DU]),
|
||||
CLKDEV_CON_ID("ga_clk", &div4_clks[DIV4_GA]),
|
||||
CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]),
|
||||
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
|
||||
CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
|
||||
CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
{
|
||||
/* SCIF5 */
|
||||
.dev_id = "sh-sci.5",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP029],
|
||||
}, {
|
||||
/* SCIF4 */
|
||||
.dev_id = "sh-sci.4",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP028],
|
||||
}, {
|
||||
/* SCIF3 */
|
||||
.dev_id = "sh-sci.3",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP027],
|
||||
}, {
|
||||
/* SCIF2 */
|
||||
.dev_id = "sh-sci.2",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP026],
|
||||
}, {
|
||||
/* SCIF1 */
|
||||
.dev_id = "sh-sci.1",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP025],
|
||||
}, {
|
||||
/* SCIF0 */
|
||||
.dev_id = "sh-sci.0",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP024],
|
||||
},
|
||||
CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
|
||||
CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]),
|
||||
CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]),
|
||||
CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]),
|
||||
CLKDEV_CON_ID("mmcif_fck", &mstp_clks[MSTP013]),
|
||||
CLKDEV_CON_ID("flctl_fck", &mstp_clks[MSTP012]),
|
||||
{
|
||||
/* TMU0 */
|
||||
.dev_id = "sh_tmu.0",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[13], /* tmu012_fck */
|
||||
.clk = &mstp_clks[MSTP008],
|
||||
}, {
|
||||
/* TMU1 */
|
||||
.dev_id = "sh_tmu.1",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[13],
|
||||
.clk = &mstp_clks[MSTP008],
|
||||
}, {
|
||||
/* TMU2 */
|
||||
.dev_id = "sh_tmu.2",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[13],
|
||||
.clk = &mstp_clks[MSTP008],
|
||||
}, {
|
||||
/* TMU3 */
|
||||
.dev_id = "sh_tmu.3",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[12], /* tmu345_fck */
|
||||
.clk = &mstp_clks[MSTP009],
|
||||
}, {
|
||||
/* TMU4 */
|
||||
.dev_id = "sh_tmu.4",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[12],
|
||||
.clk = &mstp_clks[MSTP009],
|
||||
}, {
|
||||
/* TMU5 */
|
||||
.dev_id = "sh_tmu.5",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[12],
|
||||
.clk = &mstp_clks[MSTP009],
|
||||
},
|
||||
CLKDEV_CON_ID("siof_fck", &mstp_clks[MSTP003]),
|
||||
CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]),
|
||||
CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
|
||||
CLKDEV_CON_ID("ubc_fck", &mstp_clks[MSTP117]),
|
||||
CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
|
||||
CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
|
||||
CLKDEV_CON_ID("gdta_fck", &mstp_clks[MSTP100]),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
|
@ -161,7 +224,7 @@ int __init arch_clk_init(void)
|
|||
ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
|
||||
&div4_table);
|
||||
if (!ret)
|
||||
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
|
||||
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
* from the platform code.
|
||||
*/
|
||||
static struct clk extal_clk = {
|
||||
.name = "extal",
|
||||
.id = -1,
|
||||
.rate = 33333333,
|
||||
};
|
||||
|
||||
|
@ -46,8 +44,6 @@ static struct clk_ops pll_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk pll_clk = {
|
||||
.name = "pll_clk",
|
||||
.id = -1,
|
||||
.ops = &pll_clk_ops,
|
||||
.parent = &extal_clk,
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
|
@ -72,118 +68,191 @@ static struct clk_div4_table div4_table = {
|
|||
|
||||
enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR };
|
||||
|
||||
#define DIV4(_str, _bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags)
|
||||
#define DIV4(_bit, _mask, _flags) \
|
||||
SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
|
||||
|
||||
struct clk div4_clks[DIV4_NR] = {
|
||||
[DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0),
|
||||
[DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0),
|
||||
[DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_P] = DIV4(0, 0x0b40, 0),
|
||||
[DIV4_DU] = DIV4(4, 0x0010, 0),
|
||||
[DIV4_DDR] = DIV4(12, 0x0002, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_B] = DIV4(16, 0x0360, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_SH] = DIV4(20, 0x0002, CLK_ENABLE_ON_INIT),
|
||||
[DIV4_I] = DIV4(28, 0x0006, CLK_ENABLE_ON_INIT),
|
||||
};
|
||||
|
||||
#define MSTPCR0 0xffc40030
|
||||
#define MSTPCR1 0xffc40034
|
||||
|
||||
static struct clk mstp_clks[] = {
|
||||
enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024,
|
||||
MSTP023, MSTP022, MSTP021, MSTP020, MSTP017, MSTP016,
|
||||
MSTP015, MSTP014, MSTP011, MSTP010, MSTP009, MSTP008,
|
||||
MSTP005, MSTP004, MSTP002,
|
||||
MSTP112, MSTP110, MSTP109, MSTP108,
|
||||
MSTP105, MSTP104, MSTP103, MSTP102,
|
||||
MSTP_NR };
|
||||
|
||||
static struct clk mstp_clks[MSTP_NR] = {
|
||||
/* MSTPCR0 */
|
||||
SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0),
|
||||
SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0),
|
||||
SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0),
|
||||
SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0),
|
||||
SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0),
|
||||
SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0),
|
||||
SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0),
|
||||
SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0),
|
||||
SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0),
|
||||
SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0),
|
||||
SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0),
|
||||
SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0),
|
||||
SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0),
|
||||
SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0),
|
||||
SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0),
|
||||
SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0),
|
||||
SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0),
|
||||
[MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0),
|
||||
[MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0),
|
||||
[MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
|
||||
[MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
|
||||
[MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
|
||||
[MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
|
||||
[MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
|
||||
[MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
|
||||
[MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
|
||||
[MSTP020] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
|
||||
[MSTP017] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
|
||||
[MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0),
|
||||
[MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
|
||||
[MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0),
|
||||
[MSTP011] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
|
||||
[MSTP010] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
|
||||
[MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
|
||||
[MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
|
||||
[MSTP005] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
|
||||
[MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
|
||||
[MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
|
||||
|
||||
/* MSTPCR1 */
|
||||
SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0),
|
||||
SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0),
|
||||
SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0),
|
||||
SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0),
|
||||
SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0),
|
||||
SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0),
|
||||
SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0),
|
||||
SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0),
|
||||
[MSTP112] = SH_CLK_MSTP32(NULL, MSTPCR1, 12, 0),
|
||||
[MSTP110] = SH_CLK_MSTP32(NULL, MSTPCR1, 10, 0),
|
||||
[MSTP109] = SH_CLK_MSTP32(NULL, MSTPCR1, 9, 0),
|
||||
[MSTP108] = SH_CLK_MSTP32(NULL, MSTPCR1, 8, 0),
|
||||
[MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
|
||||
[MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
|
||||
[MSTP103] = SH_CLK_MSTP32(NULL, MSTPCR1, 3, 0),
|
||||
[MSTP102] = SH_CLK_MSTP32(NULL, MSTPCR1, 2, 0),
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("extal", &extal_clk),
|
||||
CLKDEV_CON_ID("pll_clk", &pll_clk),
|
||||
|
||||
/* DIV4 clocks */
|
||||
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
|
||||
CLKDEV_CON_ID("du_clk", &div4_clks[DIV4_DU]),
|
||||
CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]),
|
||||
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
|
||||
CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
|
||||
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
{
|
||||
/* SCIF5 */
|
||||
.dev_id = "sh-sci.5",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP029],
|
||||
}, {
|
||||
/* SCIF4 */
|
||||
.dev_id = "sh-sci.4",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP028],
|
||||
}, {
|
||||
/* SCIF3 */
|
||||
.dev_id = "sh-sci.3",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP027],
|
||||
}, {
|
||||
/* SCIF2 */
|
||||
.dev_id = "sh-sci.2",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP026],
|
||||
}, {
|
||||
/* SCIF1 */
|
||||
.dev_id = "sh-sci.1",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP025],
|
||||
}, {
|
||||
/* SCIF0 */
|
||||
.dev_id = "sh-sci.0",
|
||||
.con_id = "sci_fck",
|
||||
.clk = &mstp_clks[MSTP024],
|
||||
},
|
||||
CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]),
|
||||
CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]),
|
||||
CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
|
||||
CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]),
|
||||
CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]),
|
||||
CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]),
|
||||
CLKDEV_CON_ID("i2c1_fck", &mstp_clks[MSTP015]),
|
||||
CLKDEV_CON_ID("i2c0_fck", &mstp_clks[MSTP014]),
|
||||
{
|
||||
/* TMU0 */
|
||||
.dev_id = "sh_tmu.0",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[17], /* tmu012_fck */
|
||||
.clk = &mstp_clks[MSTP008],
|
||||
}, {
|
||||
/* TMU1 */
|
||||
.dev_id = "sh_tmu.1",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[17],
|
||||
.clk = &mstp_clks[MSTP008],
|
||||
}, {
|
||||
/* TMU2 */
|
||||
.dev_id = "sh_tmu.2",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[17],
|
||||
.clk = &mstp_clks[MSTP008],
|
||||
}, {
|
||||
/* TMU3 */
|
||||
.dev_id = "sh_tmu.3",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[16], /* tmu345_fck */
|
||||
.clk = &mstp_clks[MSTP009],
|
||||
}, {
|
||||
/* TMU4 */
|
||||
.dev_id = "sh_tmu.4",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[16],
|
||||
.clk = &mstp_clks[MSTP009],
|
||||
}, {
|
||||
/* TMU5 */
|
||||
.dev_id = "sh_tmu.5",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[16],
|
||||
.clk = &mstp_clks[MSTP009],
|
||||
}, {
|
||||
/* TMU6 */
|
||||
.dev_id = "sh_tmu.6",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[15], /* tmu678_fck */
|
||||
.clk = &mstp_clks[MSTP010],
|
||||
}, {
|
||||
/* TMU7 */
|
||||
.dev_id = "sh_tmu.7",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[15],
|
||||
.clk = &mstp_clks[MSTP010],
|
||||
}, {
|
||||
/* TMU8 */
|
||||
.dev_id = "sh_tmu.8",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[15],
|
||||
.clk = &mstp_clks[MSTP010],
|
||||
}, {
|
||||
/* TMU9 */
|
||||
.dev_id = "sh_tmu.9",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[14], /* tmu9_11_fck */
|
||||
.clk = &mstp_clks[MSTP011],
|
||||
}, {
|
||||
/* TMU10 */
|
||||
.dev_id = "sh_tmu.10",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[14],
|
||||
.clk = &mstp_clks[MSTP011],
|
||||
}, {
|
||||
/* TMU11 */
|
||||
.dev_id = "sh_tmu.11",
|
||||
.con_id = "tmu_fck",
|
||||
.clk = &mstp_clks[14],
|
||||
}
|
||||
.clk = &mstp_clks[MSTP011],
|
||||
},
|
||||
CLKDEV_CON_ID("sdif1_fck", &mstp_clks[MSTP005]),
|
||||
CLKDEV_CON_ID("sdif0_fck", &mstp_clks[MSTP004]),
|
||||
CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]),
|
||||
CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP112]),
|
||||
CLKDEV_CON_ID("pcie2_fck", &mstp_clks[MSTP110]),
|
||||
CLKDEV_CON_ID("pcie1_fck", &mstp_clks[MSTP109]),
|
||||
CLKDEV_CON_ID("pcie0_fck", &mstp_clks[MSTP108]),
|
||||
CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
|
||||
CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
|
||||
CLKDEV_CON_ID("du_fck", &mstp_clks[MSTP103]),
|
||||
CLKDEV_CON_ID("ether_fck", &mstp_clks[MSTP102]),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
|
@ -199,7 +268,7 @@ int __init arch_clk_init(void)
|
|||
ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
|
||||
&div4_table);
|
||||
if (!ret)
|
||||
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
|
||||
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/freq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static int ifc_divisors[] = { 1, 2, 4 ,6 };
|
||||
static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
|
||||
|
@ -94,7 +95,6 @@ static struct clk_ops shx3_shyway_clk_ops = {
|
|||
};
|
||||
|
||||
static struct clk shx3_shyway_clk = {
|
||||
.name = "shyway_clk",
|
||||
.flags = CLK_ENABLE_ON_INIT,
|
||||
.ops = &shx3_shyway_clk_ops,
|
||||
};
|
||||
|
@ -107,6 +107,13 @@ static struct clk *shx3_onchip_clocks[] = {
|
|||
&shx3_shyway_clk,
|
||||
};
|
||||
|
||||
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
/* main clocks */
|
||||
CLKDEV_CON_ID("shyway_clk", &shx3_shyway_clk),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
@ -124,5 +131,7 @@ int __init arch_clk_init(void)
|
|||
|
||||
clk_put(clk);
|
||||
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -4,4 +4,6 @@
|
|||
obj-$(CONFIG_SUPERHYWAY) += superhyway/
|
||||
obj-$(CONFIG_MAPLE) += maple/
|
||||
obj-$(CONFIG_GENERIC_GPIO) += pfc.o
|
||||
obj-$(CONFIG_SUPERH) += clk.o
|
||||
obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o
|
||||
obj-y += intc.o
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sh_clk.h>
|
||||
|
||||
static int sh_clk_mstp32_enable(struct clk *clk)
|
||||
{
|
||||
__raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
|
||||
clk->enable_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sh_clk_mstp32_disable(struct clk *clk)
|
||||
{
|
||||
__raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
|
||||
clk->enable_reg);
|
||||
}
|
||||
|
||||
static struct clk_ops sh_clk_mstp32_clk_ops = {
|
||||
.enable = sh_clk_mstp32_enable,
|
||||
.disable = sh_clk_mstp32_disable,
|
||||
.recalc = followparent_recalc,
|
||||
};
|
||||
|
||||
int __init sh_clk_mstp32_register(struct clk *clks, int nr)
|
||||
{
|
||||
struct clk *clkp;
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
for (k = 0; !ret && (k < nr); k++) {
|
||||
clkp = clks + k;
|
||||
clkp->ops = &sh_clk_mstp32_clk_ops;
|
||||
ret |= clk_register(clkp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return clk_rate_table_round(clk, clk->freq_table, rate);
|
||||
}
|
||||
|
||||
static int sh_clk_div6_divisors[64] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
||||
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
|
||||
};
|
||||
|
||||
static struct clk_div_mult_table sh_clk_div6_table = {
|
||||
.divisors = sh_clk_div6_divisors,
|
||||
.nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
|
||||
};
|
||||
|
||||
static unsigned long sh_clk_div6_recalc(struct clk *clk)
|
||||
{
|
||||
struct clk_div_mult_table *table = &sh_clk_div6_table;
|
||||
unsigned int idx;
|
||||
|
||||
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
|
||||
table, NULL);
|
||||
|
||||
idx = __raw_readl(clk->enable_reg) & 0x003f;
|
||||
|
||||
return clk->freq_table[idx].frequency;
|
||||
}
|
||||
|
||||
static int sh_clk_div6_set_rate(struct clk *clk,
|
||||
unsigned long rate, int algo_id)
|
||||
{
|
||||
unsigned long value;
|
||||
int idx;
|
||||
|
||||
idx = clk_rate_table_find(clk, clk->freq_table, rate);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value &= ~0x3f;
|
||||
value |= idx;
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_clk_div6_enable(struct clk *clk)
|
||||
{
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
|
||||
if (ret == 0) {
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value &= ~0x100; /* clear stop bit to enable clock */
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sh_clk_div6_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value |= 0x100; /* stop clock */
|
||||
value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
}
|
||||
|
||||
static struct clk_ops sh_clk_div6_clk_ops = {
|
||||
.recalc = sh_clk_div6_recalc,
|
||||
.round_rate = sh_clk_div_round_rate,
|
||||
.set_rate = sh_clk_div6_set_rate,
|
||||
.enable = sh_clk_div6_enable,
|
||||
.disable = sh_clk_div6_disable,
|
||||
};
|
||||
|
||||
int __init sh_clk_div6_register(struct clk *clks, int nr)
|
||||
{
|
||||
struct clk *clkp;
|
||||
void *freq_table;
|
||||
int nr_divs = sh_clk_div6_table.nr_divisors;
|
||||
int freq_table_size = sizeof(struct cpufreq_frequency_table);
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
freq_table_size *= (nr_divs + 1);
|
||||
freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
|
||||
if (!freq_table) {
|
||||
pr_err("sh_clk_div6_register: unable to alloc memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (k = 0; !ret && (k < nr); k++) {
|
||||
clkp = clks + k;
|
||||
|
||||
clkp->ops = &sh_clk_div6_clk_ops;
|
||||
clkp->id = -1;
|
||||
clkp->freq_table = freq_table + (k * freq_table_size);
|
||||
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
ret = clk_register(clkp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long sh_clk_div4_recalc(struct clk *clk)
|
||||
{
|
||||
struct clk_div4_table *d4t = clk->priv;
|
||||
struct clk_div_mult_table *table = d4t->div_mult_table;
|
||||
unsigned int idx;
|
||||
|
||||
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
|
||||
table, &clk->arch_flags);
|
||||
|
||||
idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
|
||||
|
||||
return clk->freq_table[idx].frequency;
|
||||
}
|
||||
|
||||
static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
struct clk_div4_table *d4t = clk->priv;
|
||||
struct clk_div_mult_table *table = d4t->div_mult_table;
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
/* we really need a better way to determine parent index, but for
|
||||
* now assume internal parent comes with CLK_ENABLE_ON_INIT set,
|
||||
* no CLK_ENABLE_ON_INIT means external clock...
|
||||
*/
|
||||
|
||||
if (parent->flags & CLK_ENABLE_ON_INIT)
|
||||
value = __raw_readl(clk->enable_reg) & ~(1 << 7);
|
||||
else
|
||||
value = __raw_readl(clk->enable_reg) | (1 << 7);
|
||||
|
||||
ret = clk_reparent(clk, parent);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
|
||||
/* Rebiuld the frequency table */
|
||||
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
|
||||
table, &clk->arch_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id)
|
||||
{
|
||||
struct clk_div4_table *d4t = clk->priv;
|
||||
unsigned long value;
|
||||
int idx = clk_rate_table_find(clk, clk->freq_table, rate);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value &= ~(0xf << clk->enable_bit);
|
||||
value |= (idx << clk->enable_bit);
|
||||
__raw_writel(value, clk->enable_reg);
|
||||
|
||||
if (d4t->kick)
|
||||
d4t->kick(clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_clk_div4_enable(struct clk *clk)
|
||||
{
|
||||
__raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sh_clk_div4_disable(struct clk *clk)
|
||||
{
|
||||
__raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
|
||||
}
|
||||
|
||||
static struct clk_ops sh_clk_div4_clk_ops = {
|
||||
.recalc = sh_clk_div4_recalc,
|
||||
.set_rate = sh_clk_div4_set_rate,
|
||||
.round_rate = sh_clk_div_round_rate,
|
||||
};
|
||||
|
||||
static struct clk_ops sh_clk_div4_enable_clk_ops = {
|
||||
.recalc = sh_clk_div4_recalc,
|
||||
.set_rate = sh_clk_div4_set_rate,
|
||||
.round_rate = sh_clk_div_round_rate,
|
||||
.enable = sh_clk_div4_enable,
|
||||
.disable = sh_clk_div4_disable,
|
||||
};
|
||||
|
||||
static struct clk_ops sh_clk_div4_reparent_clk_ops = {
|
||||
.recalc = sh_clk_div4_recalc,
|
||||
.set_rate = sh_clk_div4_set_rate,
|
||||
.round_rate = sh_clk_div_round_rate,
|
||||
.enable = sh_clk_div4_enable,
|
||||
.disable = sh_clk_div4_disable,
|
||||
.set_parent = sh_clk_div4_set_parent,
|
||||
};
|
||||
|
||||
static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table, struct clk_ops *ops)
|
||||
{
|
||||
struct clk *clkp;
|
||||
void *freq_table;
|
||||
int nr_divs = table->div_mult_table->nr_divisors;
|
||||
int freq_table_size = sizeof(struct cpufreq_frequency_table);
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
freq_table_size *= (nr_divs + 1);
|
||||
freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
|
||||
if (!freq_table) {
|
||||
pr_err("sh_clk_div4_register: unable to alloc memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (k = 0; !ret && (k < nr); k++) {
|
||||
clkp = clks + k;
|
||||
|
||||
clkp->ops = ops;
|
||||
clkp->id = -1;
|
||||
clkp->priv = table;
|
||||
|
||||
clkp->freq_table = freq_table + (k * freq_table_size);
|
||||
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
ret = clk_register(clkp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __init sh_clk_div4_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table)
|
||||
{
|
||||
return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
|
||||
}
|
||||
|
||||
int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table)
|
||||
{
|
||||
return sh_clk_div4_register_ops(clks, nr, table,
|
||||
&sh_clk_div4_enable_clk_ops);
|
||||
}
|
||||
|
||||
int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table)
|
||||
{
|
||||
return sh_clk_div4_register_ops(clks, nr, table,
|
||||
&sh_clk_div4_reparent_clk_ops);
|
||||
}
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* drivers/sh/clk.c - SuperH clock framework
|
||||
*
|
||||
* Copyright (C) 2005 - 2009 Paul Mundt
|
||||
*
|
||||
* This clock framework is derived from the OMAP version by:
|
||||
*
|
||||
* Copyright (C) 2004 - 2008 Nokia Corporation
|
||||
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
|
||||
*
|
||||
* Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/sh_clk.h>
|
||||
|
||||
static LIST_HEAD(clock_list);
|
||||
static DEFINE_SPINLOCK(clock_lock);
|
||||
static DEFINE_MUTEX(clock_list_sem);
|
||||
|
||||
void clk_rate_table_build(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
int nr_freqs,
|
||||
struct clk_div_mult_table *src_table,
|
||||
unsigned long *bitmap)
|
||||
{
|
||||
unsigned long mult, div;
|
||||
unsigned long freq;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_freqs; i++) {
|
||||
div = 1;
|
||||
mult = 1;
|
||||
|
||||
if (src_table->divisors && i < src_table->nr_divisors)
|
||||
div = src_table->divisors[i];
|
||||
|
||||
if (src_table->multipliers && i < src_table->nr_multipliers)
|
||||
mult = src_table->multipliers[i];
|
||||
|
||||
if (!div || !mult || (bitmap && !test_bit(i, bitmap)))
|
||||
freq = CPUFREQ_ENTRY_INVALID;
|
||||
else
|
||||
freq = clk->parent->rate * mult / div;
|
||||
|
||||
freq_table[i].index = i;
|
||||
freq_table[i].frequency = freq;
|
||||
}
|
||||
|
||||
/* Termination entry */
|
||||
freq_table[i].index = i;
|
||||
freq_table[i].frequency = CPUFREQ_TABLE_END;
|
||||
}
|
||||
|
||||
long clk_rate_table_round(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long rate_error, rate_error_prev = ~0UL;
|
||||
unsigned long rate_best_fit = rate;
|
||||
unsigned long highest, lowest;
|
||||
int i;
|
||||
|
||||
highest = lowest = 0;
|
||||
|
||||
for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
unsigned long freq = freq_table[i].frequency;
|
||||
|
||||
if (freq == CPUFREQ_ENTRY_INVALID)
|
||||
continue;
|
||||
|
||||
if (freq > highest)
|
||||
highest = freq;
|
||||
if (freq < lowest)
|
||||
lowest = freq;
|
||||
|
||||
rate_error = abs(freq - rate);
|
||||
if (rate_error < rate_error_prev) {
|
||||
rate_best_fit = freq;
|
||||
rate_error_prev = rate_error;
|
||||
}
|
||||
|
||||
if (rate_error == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rate >= highest)
|
||||
rate_best_fit = highest;
|
||||
if (rate <= lowest)
|
||||
rate_best_fit = lowest;
|
||||
|
||||
return rate_best_fit;
|
||||
}
|
||||
|
||||
int clk_rate_table_find(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
unsigned long rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
unsigned long freq = freq_table[i].frequency;
|
||||
|
||||
if (freq == CPUFREQ_ENTRY_INVALID)
|
||||
continue;
|
||||
|
||||
if (freq == rate)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Used for clocks that always have same value as the parent clock */
|
||||
unsigned long followparent_recalc(struct clk *clk)
|
||||
{
|
||||
return clk->parent ? clk->parent->rate : 0;
|
||||
}
|
||||
|
||||
int clk_reparent(struct clk *child, struct clk *parent)
|
||||
{
|
||||
list_del_init(&child->sibling);
|
||||
if (parent)
|
||||
list_add(&child->sibling, &parent->children);
|
||||
child->parent = parent;
|
||||
|
||||
/* now do the debugfs renaming to reattach the child
|
||||
to the proper parent */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Propagate rate to children */
|
||||
void propagate_rate(struct clk *tclk)
|
||||
{
|
||||
struct clk *clkp;
|
||||
|
||||
list_for_each_entry(clkp, &tclk->children, sibling) {
|
||||
if (clkp->ops && clkp->ops->recalc)
|
||||
clkp->rate = clkp->ops->recalc(clkp);
|
||||
|
||||
propagate_rate(clkp);
|
||||
}
|
||||
}
|
||||
|
||||
static void __clk_disable(struct clk *clk)
|
||||
{
|
||||
if (WARN(!clk->usecount, "Trying to disable clock %s with 0 usecount\n",
|
||||
clk->name))
|
||||
return;
|
||||
|
||||
if (!(--clk->usecount)) {
|
||||
if (likely(clk->ops && clk->ops->disable))
|
||||
clk->ops->disable(clk);
|
||||
if (likely(clk->parent))
|
||||
__clk_disable(clk->parent);
|
||||
}
|
||||
}
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!clk)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
__clk_disable(clk);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_disable);
|
||||
|
||||
static int __clk_enable(struct clk *clk)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (clk->usecount++ == 0) {
|
||||
if (clk->parent) {
|
||||
ret = __clk_enable(clk->parent);
|
||||
if (unlikely(ret))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (clk->ops && clk->ops->enable) {
|
||||
ret = clk->ops->enable(clk);
|
||||
if (ret) {
|
||||
if (clk->parent)
|
||||
__clk_disable(clk->parent);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
err:
|
||||
clk->usecount--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!clk)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
ret = __clk_enable(clk);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_enable);
|
||||
|
||||
static LIST_HEAD(root_clks);
|
||||
|
||||
/**
|
||||
* recalculate_root_clocks - recalculate and propagate all root clocks
|
||||
*
|
||||
* Recalculates all root clocks (clocks with no parent), which if the
|
||||
* clock's .recalc is set correctly, should also propagate their rates.
|
||||
* Called at init.
|
||||
*/
|
||||
void recalculate_root_clocks(void)
|
||||
{
|
||||
struct clk *clkp;
|
||||
|
||||
list_for_each_entry(clkp, &root_clks, sibling) {
|
||||
if (clkp->ops && clkp->ops->recalc)
|
||||
clkp->rate = clkp->ops->recalc(clkp);
|
||||
propagate_rate(clkp);
|
||||
}
|
||||
}
|
||||
|
||||
int clk_register(struct clk *clk)
|
||||
{
|
||||
if (clk == NULL || IS_ERR(clk))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* trap out already registered clocks
|
||||
*/
|
||||
if (clk->node.next || clk->node.prev)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&clock_list_sem);
|
||||
|
||||
INIT_LIST_HEAD(&clk->children);
|
||||
clk->usecount = 0;
|
||||
|
||||
if (clk->parent)
|
||||
list_add(&clk->sibling, &clk->parent->children);
|
||||
else
|
||||
list_add(&clk->sibling, &root_clks);
|
||||
|
||||
list_add(&clk->node, &clock_list);
|
||||
if (clk->ops && clk->ops->init)
|
||||
clk->ops->init(clk);
|
||||
mutex_unlock(&clock_list_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register);
|
||||
|
||||
void clk_unregister(struct clk *clk)
|
||||
{
|
||||
mutex_lock(&clock_list_sem);
|
||||
list_del(&clk->sibling);
|
||||
list_del(&clk->node);
|
||||
mutex_unlock(&clock_list_sem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_unregister);
|
||||
|
||||
void clk_enable_init_clocks(void)
|
||||
{
|
||||
struct clk *clkp;
|
||||
|
||||
list_for_each_entry(clkp, &clock_list, node)
|
||||
if (clkp->flags & CLK_ENABLE_ON_INIT)
|
||||
clk_enable(clkp);
|
||||
}
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
return clk->rate;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_get_rate);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return clk_set_rate_ex(clk, rate, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate);
|
||||
|
||||
int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
|
||||
if (likely(clk->ops && clk->ops->set_rate)) {
|
||||
ret = clk->ops->set_rate(clk, rate, algo_id);
|
||||
if (ret != 0)
|
||||
goto out_unlock;
|
||||
} else {
|
||||
clk->rate = rate;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (clk->ops && clk->ops->recalc)
|
||||
clk->rate = clk->ops->recalc(clk);
|
||||
|
||||
propagate_rate(clk);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate_ex);
|
||||
|
||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!parent || !clk)
|
||||
return ret;
|
||||
if (clk->parent == parent)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
if (clk->usecount == 0) {
|
||||
if (clk->ops->set_parent)
|
||||
ret = clk->ops->set_parent(clk, parent);
|
||||
else
|
||||
ret = clk_reparent(clk, parent);
|
||||
|
||||
if (ret == 0) {
|
||||
pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
|
||||
clk->name, clk->parent->name, clk->rate);
|
||||
if (clk->ops->recalc)
|
||||
clk->rate = clk->ops->recalc(clk);
|
||||
propagate_rate(clk);
|
||||
}
|
||||
} else
|
||||
ret = -EBUSY;
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_parent);
|
||||
|
||||
struct clk *clk_get_parent(struct clk *clk)
|
||||
{
|
||||
return clk->parent;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_get_parent);
|
||||
|
||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
if (likely(clk->ops && clk->ops->round_rate)) {
|
||||
unsigned long flags, rounded;
|
||||
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
rounded = clk->ops->round_rate(clk, rate);
|
||||
spin_unlock_irqrestore(&clock_lock, flags);
|
||||
|
||||
return rounded;
|
||||
}
|
||||
|
||||
return clk_get_rate(clk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_round_rate);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
static pm_message_t prev_state;
|
||||
struct clk *clkp;
|
||||
|
||||
switch (state.event) {
|
||||
case PM_EVENT_ON:
|
||||
/* Resumeing from hibernation */
|
||||
if (prev_state.event != PM_EVENT_FREEZE)
|
||||
break;
|
||||
|
||||
list_for_each_entry(clkp, &clock_list, node) {
|
||||
if (likely(clkp->ops)) {
|
||||
unsigned long rate = clkp->rate;
|
||||
|
||||
if (likely(clkp->ops->set_parent))
|
||||
clkp->ops->set_parent(clkp,
|
||||
clkp->parent);
|
||||
if (likely(clkp->ops->set_rate))
|
||||
clkp->ops->set_rate(clkp,
|
||||
rate, NO_CHANGE);
|
||||
else if (likely(clkp->ops->recalc))
|
||||
clkp->rate = clkp->ops->recalc(clkp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PM_EVENT_FREEZE:
|
||||
break;
|
||||
case PM_EVENT_SUSPEND:
|
||||
break;
|
||||
}
|
||||
|
||||
prev_state = state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clks_sysdev_resume(struct sys_device *dev)
|
||||
{
|
||||
return clks_sysdev_suspend(dev, PMSG_ON);
|
||||
}
|
||||
|
||||
static struct sysdev_class clks_sysdev_class = {
|
||||
.name = "clks",
|
||||
};
|
||||
|
||||
static struct sysdev_driver clks_sysdev_driver = {
|
||||
.suspend = clks_sysdev_suspend,
|
||||
.resume = clks_sysdev_resume,
|
||||
};
|
||||
|
||||
static struct sys_device clks_sysdev_dev = {
|
||||
.cls = &clks_sysdev_class,
|
||||
};
|
||||
|
||||
static int __init clk_sysdev_init(void)
|
||||
{
|
||||
sysdev_class_register(&clks_sysdev_class);
|
||||
sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver);
|
||||
sysdev_register(&clks_sysdev_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(clk_sysdev_init);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* debugfs support to trace clock tree hierarchy and attributes
|
||||
*/
|
||||
static struct dentry *clk_debugfs_root;
|
||||
|
||||
static int clk_debugfs_register_one(struct clk *c)
|
||||
{
|
||||
int err;
|
||||
struct dentry *d, *child, *child_tmp;
|
||||
struct clk *pa = c->parent;
|
||||
char s[255];
|
||||
char *p = s;
|
||||
|
||||
p += sprintf(p, "%s", c->name);
|
||||
if (c->id >= 0)
|
||||
sprintf(p, ":%d", c->id);
|
||||
d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
c->dentry = d;
|
||||
|
||||
d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
d = c->dentry;
|
||||
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
|
||||
debugfs_remove(child);
|
||||
debugfs_remove(c->dentry);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int clk_debugfs_register(struct clk *c)
|
||||
{
|
||||
int err;
|
||||
struct clk *pa = c->parent;
|
||||
|
||||
if (pa && !pa->dentry) {
|
||||
err = clk_debugfs_register(pa);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!c->dentry && c->name) {
|
||||
err = clk_debugfs_register_one(c);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init clk_debugfs_init(void)
|
||||
{
|
||||
struct clk *c;
|
||||
struct dentry *d;
|
||||
int err;
|
||||
|
||||
d = debugfs_create_dir("clock", NULL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
clk_debugfs_root = d;
|
||||
|
||||
list_for_each_entry(c, &clock_list, node) {
|
||||
err = clk_debugfs_register(c);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
return 0;
|
||||
err_out:
|
||||
debugfs_remove_recursive(clk_debugfs_root);
|
||||
return err;
|
||||
}
|
||||
late_initcall(clk_debugfs_init);
|
|
@ -0,0 +1,151 @@
|
|||
#ifndef __SH_CLOCK_H
|
||||
#define __SH_CLOCK_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
struct clk;
|
||||
|
||||
struct clk_ops {
|
||||
void (*init)(struct clk *clk);
|
||||
int (*enable)(struct clk *clk);
|
||||
void (*disable)(struct clk *clk);
|
||||
unsigned long (*recalc)(struct clk *clk);
|
||||
int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
|
||||
int (*set_parent)(struct clk *clk, struct clk *parent);
|
||||
long (*round_rate)(struct clk *clk, unsigned long rate);
|
||||
};
|
||||
|
||||
struct clk {
|
||||
struct list_head node;
|
||||
const char *name;
|
||||
int id;
|
||||
|
||||
struct clk *parent;
|
||||
struct clk_ops *ops;
|
||||
|
||||
struct list_head children;
|
||||
struct list_head sibling; /* node for children */
|
||||
|
||||
int usecount;
|
||||
|
||||
unsigned long rate;
|
||||
unsigned long flags;
|
||||
|
||||
void __iomem *enable_reg;
|
||||
unsigned int enable_bit;
|
||||
|
||||
unsigned long arch_flags;
|
||||
void *priv;
|
||||
struct dentry *dentry;
|
||||
struct cpufreq_frequency_table *freq_table;
|
||||
};
|
||||
|
||||
#define CLK_ENABLE_ON_INIT (1 << 0)
|
||||
|
||||
/* arch/sh/kernel/cpu/clock.c */
|
||||
unsigned long followparent_recalc(struct clk *);
|
||||
void recalculate_root_clocks(void);
|
||||
void propagate_rate(struct clk *);
|
||||
int clk_reparent(struct clk *child, struct clk *parent);
|
||||
int clk_register(struct clk *);
|
||||
void clk_unregister(struct clk *);
|
||||
void clk_enable_init_clocks(void);
|
||||
|
||||
/* 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,
|
||||
};
|
||||
|
||||
struct clk_div_mult_table {
|
||||
unsigned int *divisors;
|
||||
unsigned int nr_divisors;
|
||||
unsigned int *multipliers;
|
||||
unsigned int nr_multipliers;
|
||||
};
|
||||
|
||||
struct cpufreq_frequency_table;
|
||||
void clk_rate_table_build(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
int nr_freqs,
|
||||
struct clk_div_mult_table *src_table,
|
||||
unsigned long *bitmap);
|
||||
|
||||
long clk_rate_table_round(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
unsigned long rate);
|
||||
|
||||
int clk_rate_table_find(struct clk *clk,
|
||||
struct cpufreq_frequency_table *freq_table,
|
||||
unsigned long rate);
|
||||
|
||||
#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags) \
|
||||
{ \
|
||||
.parent = _parent, \
|
||||
.enable_reg = (void __iomem *)_enable_reg, \
|
||||
.enable_bit = _enable_bit, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
int sh_clk_mstp32_register(struct clk *clks, int nr);
|
||||
|
||||
#define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \
|
||||
{ \
|
||||
.parent = _parent, \
|
||||
.enable_reg = (void __iomem *)_reg, \
|
||||
.enable_bit = _shift, \
|
||||
.arch_flags = _div_bitmap, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
struct clk_div4_table {
|
||||
struct clk_div_mult_table *div_mult_table;
|
||||
void (*kick)(struct clk *clk);
|
||||
};
|
||||
|
||||
int sh_clk_div4_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table);
|
||||
int sh_clk_div4_enable_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table);
|
||||
int sh_clk_div4_reparent_register(struct clk *clks, int nr,
|
||||
struct clk_div4_table *table);
|
||||
|
||||
#define SH_CLK_DIV6(_parent, _reg, _flags) \
|
||||
{ \
|
||||
.parent = _parent, \
|
||||
.enable_reg = (void __iomem *)_reg, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
int sh_clk_div6_register(struct clk *clks, int nr);
|
||||
|
||||
#endif /* __SH_CLOCK_H */
|
Loading…
Reference in New Issue