Merge branch 'sh/clkfwk'

This commit is contained in:
Paul Mundt 2010-05-13 17:45:44 +09:00
commit c5eb5b372e
23 changed files with 1693 additions and 1321 deletions

View File

@ -710,8 +710,6 @@ static struct clk_ops fsimck_clk_ops = {
}; };
static struct clk fsimckb_clk = { static struct clk fsimckb_clk = {
.name = "fsimckb_clk",
.id = -1,
.ops = &fsimck_clk_ops, .ops = &fsimck_clk_ops,
.enable_reg = (void __iomem *)FCLKBCR, .enable_reg = (void __iomem *)FCLKBCR,
.rate = 0, /* unknown */ .rate = 0, /* unknown */
@ -1138,16 +1136,20 @@ static int __init arch_setup(void)
/* set SPU2 clock to 83.4 MHz */ /* set SPU2 clock to 83.4 MHz */
clk = clk_get(NULL, "spu_clk"); clk = clk_get(NULL, "spu_clk");
clk_set_rate(clk, clk_round_rate(clk, 83333333)); if (clk) {
clk_put(clk); clk_set_rate(clk, clk_round_rate(clk, 83333333));
clk_put(clk);
}
/* change parent of FSI B */ /* change parent of FSI B */
clk = clk_get(NULL, "fsib_clk"); clk = clk_get(NULL, "fsib_clk");
clk_register(&fsimckb_clk); if (clk) {
clk_set_parent(clk, &fsimckb_clk); clk_register(&fsimckb_clk);
clk_set_rate(clk, 11000); clk_set_parent(clk, &fsimckb_clk);
clk_set_rate(&fsimckb_clk, 11000); clk_set_rate(clk, 11000);
clk_put(clk); clk_set_rate(&fsimckb_clk, 11000);
clk_put(clk);
}
gpio_request(GPIO_PTU0, NULL); gpio_request(GPIO_PTU0, NULL);
gpio_direction_output(GPIO_PTU0, 0); gpio_direction_output(GPIO_PTU0, 0);
@ -1159,8 +1161,10 @@ static int __init arch_setup(void)
/* set VPU clock to 166 MHz */ /* set VPU clock to 166 MHz */
clk = clk_get(NULL, "vpu_clk"); clk = clk_get(NULL, "vpu_clk");
clk_set_rate(clk, clk_round_rate(clk, 166000000)); if (clk) {
clk_put(clk); clk_set_rate(clk, clk_round_rate(clk, 166000000));
clk_put(clk);
}
/* enable IrDA */ /* enable IrDA */
gpio_request(GPIO_FN_IRDA_OUT, NULL); gpio_request(GPIO_FN_IRDA_OUT, NULL);

View File

@ -14,6 +14,7 @@
* for more details. * for more details.
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/ata_platform.h> #include <linux/ata_platform.h>
#include <linux/types.h> #include <linux/types.h>
@ -26,6 +27,7 @@
#include <net/ax88796.h> #include <net/ax88796.h>
#include <asm/machvec.h> #include <asm/machvec.h>
#include <mach/highlander.h> #include <mach/highlander.h>
#include <asm/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/heartbeat.h> #include <asm/heartbeat.h>
#include <asm/io.h> #include <asm/io.h>
@ -326,7 +328,6 @@ static struct clk_ops ivdr_clk_ops = {
}; };
static struct clk ivdr_clk = { static struct clk ivdr_clk = {
.name = "ivdr_clk",
.ops = &ivdr_clk_ops, .ops = &ivdr_clk_ops,
}; };
@ -334,6 +335,13 @@ static struct clk *r7780rp_clocks[] = {
&ivdr_clk, &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) static void r7780rp_power_off(void)
{ {
if (mach_is_r7780mp() || mach_is_r7785rp()) if (mach_is_r7780mp() || mach_is_r7785rp())
@ -370,6 +378,8 @@ static void __init highlander_setup(char **cmdline_p)
clk_enable(clk); clk_enable(clk);
} }
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
__raw_writew(0x0000, PA_OBLED); /* Clear LED. */ __raw_writew(0x0000, PA_OBLED); /* Clear LED. */
if (mach_is_r7780rp()) if (mach_is_r7780rp())

View File

@ -276,8 +276,6 @@ static struct clk_ops fsimck_clk_ops = {
}; };
static struct clk fsimcka_clk = { static struct clk fsimcka_clk = {
.name = "fsimcka_clk",
.id = -1,
.ops = &fsimck_clk_ops, .ops = &fsimck_clk_ops,
.enable_reg = (void __iomem *)FCLKACR, .enable_reg = (void __iomem *)FCLKACR,
.rate = 0, /* unknown */ .rate = 0, /* unknown */
@ -771,16 +769,20 @@ static int __init devices_setup(void)
/* set SPU2 clock to 83.4 MHz */ /* set SPU2 clock to 83.4 MHz */
clk = clk_get(NULL, "spu_clk"); clk = clk_get(NULL, "spu_clk");
clk_set_rate(clk, clk_round_rate(clk, 83333333)); if (clk) {
clk_put(clk); clk_set_rate(clk, clk_round_rate(clk, 83333333));
clk_put(clk);
}
/* change parent of FSI A */ /* change parent of FSI A */
clk = clk_get(NULL, "fsia_clk"); clk = clk_get(NULL, "fsia_clk");
clk_register(&fsimcka_clk); if (clk) {
clk_set_parent(clk, &fsimcka_clk); clk_register(&fsimcka_clk);
clk_set_rate(clk, 11000); clk_set_parent(clk, &fsimcka_clk);
clk_set_rate(&fsimcka_clk, 11000); clk_set_rate(clk, 11000);
clk_put(clk); clk_set_rate(&fsimcka_clk, 11000);
clk_put(clk);
}
/* SDHI0 connected to cn7 */ /* SDHI0 connected to cn7 */
gpio_request(GPIO_FN_SDHI0CD, NULL); gpio_request(GPIO_FN_SDHI0CD, NULL);

View File

@ -1,163 +1,16 @@
#ifndef __ASM_SH_CLOCK_H #ifndef __ASM_SH_CLOCK_H
#define __ASM_SH_CLOCK_H #define __ASM_SH_CLOCK_H
#include <linux/list.h> #include <linux/sh_clk.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)
/* Should be defined by processor-specific code */ /* Should be defined by processor-specific code */
void __deprecated arch_init_clk_ops(struct clk_ops **, int type); void __deprecated arch_init_clk_ops(struct clk_ops **, int type);
int __init arch_clk_init(void); 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 */ /* arch/sh/kernel/cpu/clock-cpg.c */
int __init __deprecated cpg_clk_init(void); int __init __deprecated cpg_clk_init(void);
/* the exported API, in addition to clk_set_rate */ /* arch/sh/kernel/cpu/clock.c */
/** int clk_init(void);
* 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);
#endif /* __ASM_SH_CLOCK_H */ #endif /* __ASM_SH_CLOCK_H */

View File

@ -16,7 +16,7 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/
# Common interfaces. # Common interfaces.
obj-$(CONFIG_SH_ADC) += adc.o 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) += fpu.o
obj-$(CONFIG_SH_FPU_EMU) += fpu.o obj-$(CONFIG_SH_FPU_EMU) += fpu.o

View File

@ -2,317 +2,25 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h>
#include <asm/clock.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 = { static struct clk master_clk = {
.name = "master_clk",
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
.rate = CONFIG_SH_PCLK_FREQ, .rate = CONFIG_SH_PCLK_FREQ,
}; };
static struct clk peripheral_clk = { static struct clk peripheral_clk = {
.name = "peripheral_clk",
.parent = &master_clk, .parent = &master_clk,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
}; };
static struct clk bus_clk = { static struct clk bus_clk = {
.name = "bus_clk",
.parent = &master_clk, .parent = &master_clk,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
}; };
static struct clk cpu_clk = { static struct clk cpu_clk = {
.name = "cpu_clk",
.parent = &master_clk, .parent = &master_clk,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
}; };
@ -327,6 +35,16 @@ static struct clk *onchip_clocks[] = {
&cpu_clk, &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 __init __deprecated cpg_clk_init(void)
{ {
int i, ret = 0; int i, ret = 0;
@ -338,6 +56,8 @@ int __init __deprecated cpg_clk_init(void)
ret |= clk_register(clk); ret |= clk_register(clk);
} }
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
clk_add_alias("tmu_fck", NULL, "peripheral_clk", NULL); clk_add_alias("tmu_fck", NULL, "peripheral_clk", NULL);
clk_add_alias("mtu2_fck", NULL, "peripheral_clk", NULL); clk_add_alias("mtu2_fck", NULL, "peripheral_clk", NULL);
clk_add_alias("cmt_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(); return cpg_clk_init();
} }
#endif /* CONFIG_SH_CPG_CLK_LEGACY */

View File

@ -16,500 +16,10 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.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/clk.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/machvec.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 __init clk_init(void)
{ {
int ret; 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; struct clk *clk_get(struct device *dev, const char *con_id)
static int clk_debugfs_register_one(struct clk *c)
{ {
int err; const char *dev_id = dev ? dev_name(dev) : NULL;
struct dentry *d, *child, *child_tmp;
struct clk *pa = c->parent;
char s[255];
char *p = s;
p += sprintf(p, "%s", c->name); return clk_get_sys(dev_id, con_id);
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;
} }
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);

View File

@ -12,9 +12,10 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h>
#include <asm/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
#include <asm/io.h>
#define CPG2_FRQCR3 0xfe0a0018 #define CPG2_FRQCR3 0xfe0a0018
@ -45,7 +46,6 @@ static struct clk_ops sh4202_emi_clk_ops = {
}; };
static struct clk sh4202_emi_clk = { static struct clk sh4202_emi_clk = {
.name = "emi_clk",
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
.ops = &sh4202_emi_clk_ops, .ops = &sh4202_emi_clk_ops,
}; };
@ -61,7 +61,6 @@ static struct clk_ops sh4202_femi_clk_ops = {
}; };
static struct clk sh4202_femi_clk = { static struct clk sh4202_femi_clk = {
.name = "femi_clk",
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
.ops = &sh4202_femi_clk_ops, .ops = &sh4202_femi_clk_ops,
}; };
@ -139,7 +138,6 @@ static struct clk_ops sh4202_shoc_clk_ops = {
}; };
static struct clk sh4202_shoc_clk = { static struct clk sh4202_shoc_clk = {
.name = "shoc_clk",
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
.ops = &sh4202_shoc_clk_ops, .ops = &sh4202_shoc_clk_ops,
}; };
@ -150,6 +148,15 @@ static struct clk *sh4202_onchip_clocks[] = {
&sh4202_shoc_clk, &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) int __init arch_clk_init(void)
{ {
struct clk *clk; struct clk *clk;
@ -167,5 +174,7 @@ int __init arch_clk_init(void)
clk_put(clk); clk_put(clk);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
return ret; return ret;
} }

View File

@ -37,8 +37,6 @@
/* Fixed 32 KHz root clock for RTC and Power Management purposes */ /* Fixed 32 KHz root clock for RTC and Power Management purposes */
static struct clk r_clk = { static struct clk r_clk = {
.name = "rclk",
.id = -1,
.rate = 32768, .rate = 32768,
}; };
@ -47,8 +45,6 @@ static struct clk r_clk = {
* from the platform code. * from the platform code.
*/ */
struct clk extal_clk = { struct clk extal_clk = {
.name = "extal",
.id = -1,
.rate = 33333333, .rate = 33333333,
}; };
@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = {
}; };
static struct clk dll_clk = { static struct clk dll_clk = {
.name = "dll_clk",
.id = -1,
.ops = &dll_clk_ops, .ops = &dll_clk_ops,
.parent = &r_clk, .parent = &r_clk,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
@ -92,8 +86,6 @@ static struct clk_ops pll_clk_ops = {
}; };
static struct clk pll_clk = { static struct clk pll_clk = {
.name = "pll_clk",
.id = -1,
.ops = &pll_clk_ops, .ops = &pll_clk_ops,
.flags = CLK_ENABLE_ON_INIT, .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, enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
DIV4_SIUA, DIV4_SIUB, DIV4_NR }; DIV4_SIUA, DIV4_SIUB, DIV4_NR };
#define DIV4(_str, _reg, _bit, _mask, _flags) \ #define DIV4(_reg, _bit, _mask, _flags) \
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
struct clk div4_clks[DIV4_NR] = { struct clk div4_clks[DIV4_NR] = {
[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_I] = DIV4(FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0), [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0), [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
}; };
enum { DIV6_V, DIV6_NR }; enum { DIV6_V, DIV6_NR };
@ -142,61 +134,148 @@ struct clk div6_clks[DIV6_NR] = {
[DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0), [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
}; };
#define MSTP(_str, _parent, _reg, _bit, _flags) \ #define MSTP(_parent, _reg, _bit, _flags) \
SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags) SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
static struct clk mstp_clks[] = { enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026,
MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016,
MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010,
MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), MSTP007, MSTP006, MSTP005, MSTP004, MSTP003, MSTP002, MSTP001,
MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), MSTP109, MSTP108, MSTP100,
MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), MSTP225, MSTP224, MSTP218, MSTP217, MSTP216,
MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0), MSTP214, MSTP213, MSTP212, MSTP211, MSTP208,
MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0), MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0), MSTP_NR };
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),
MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), static struct clk mstp_clks[MSTP_NR] = {
MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 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_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), [MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0), [MSTP108] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 8, 0),
MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0), [MSTP225] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 25, 0),
MSTP("sim0", &div4_clks[DIV4_P], MSTPCR2, 16, 0), [MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
MSTP("keysc0", &r_clk, MSTPCR2, 14, 0), [MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 13, 0), [MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
MSTP("s3d40", &div4_clks[DIV4_P], MSTPCR2, 12, 0), [MSTP216] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 16, 0),
MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), [MSTP214] = MSTP(&r_clk, MSTPCR2, 14, 0),
MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0), [MSTP213] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 13, 0),
MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT), [MSTP212] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 12, 0),
MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), [MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), [MSTP208] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 8, 0),
MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), [MSTP206] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), [MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), [MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 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 } #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
static struct clk_lookup lookups[] = { 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 */ /* DIV6 clocks */
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), 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) 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); ret = sh_clk_div6_register(div6_clks, DIV6_NR);
if (!ret) if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
return ret; return ret;
} }

View File

@ -37,8 +37,6 @@
/* Fixed 32 KHz root clock for RTC and Power Management purposes */ /* Fixed 32 KHz root clock for RTC and Power Management purposes */
static struct clk r_clk = { static struct clk r_clk = {
.name = "rclk",
.id = -1,
.rate = 32768, .rate = 32768,
}; };
@ -47,8 +45,6 @@ static struct clk r_clk = {
* from the platform code. * from the platform code.
*/ */
struct clk extal_clk = { struct clk extal_clk = {
.name = "extal",
.id = -1,
.rate = 33333333, .rate = 33333333,
}; };
@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = {
}; };
static struct clk dll_clk = { static struct clk dll_clk = {
.name = "dll_clk",
.id = -1,
.ops = &dll_clk_ops, .ops = &dll_clk_ops,
.parent = &r_clk, .parent = &r_clk,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
@ -95,8 +89,6 @@ static struct clk_ops pll_clk_ops = {
}; };
static struct clk pll_clk = { static struct clk pll_clk = {
.name = "pll_clk",
.id = -1,
.ops = &pll_clk_ops, .ops = &pll_clk_ops,
.flags = CLK_ENABLE_ON_INIT, .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, enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
DIV4_SIUA, DIV4_SIUB, DIV4_NR }; DIV4_SIUA, DIV4_SIUB, DIV4_NR };
#define DIV4(_str, _reg, _bit, _mask, _flags) \ #define DIV4(_reg, _bit, _mask, _flags) \
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
struct clk div4_clks[DIV4_NR] = { struct clk div4_clks[DIV4_NR] = {
[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT), [DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0), [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0), [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
}; };
enum { DIV6_V, DIV6_NR }; enum { DIV6_V, DIV6_NR };
@ -145,58 +137,134 @@ struct clk div6_clks[DIV6_NR] = {
[DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0), [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
}; };
#define MSTP(_str, _parent, _reg, _bit, _flags) \ #define MSTP(_parent, _reg, _bit, _flags) \
SH_CLK_MSTP32(_str, -1, _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 */ /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */
MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), [MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), [MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), [MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
MSTP("rsmem0", &div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT), [MSTP028] = MSTP(&div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), [MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0), [MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0), [MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0), [MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), [MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), [MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), [MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), [MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), [MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0),
MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), [MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0),
MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), [MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), [MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), [MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), [MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), [MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
MSTP("msiof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), [MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
MSTP("sbr0", &div4_clks[DIV4_P], MSTPCR0, 1, 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), [MSTP227] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 27, 0),
MSTP("meram0", &div4_clks[DIV4_P], MSTPCR2, 26, 0), [MSTP226] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 26, 0),
MSTP("dacy1", &div4_clks[DIV4_P], MSTPCR2, 24, 0), [MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
MSTP("dacy0", &div4_clks[DIV4_P], MSTPCR2, 23, 0), [MSTP223] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 23, 0),
MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 22, 0), [MSTP222] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 22, 0),
MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), [MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0), [MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), [MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0), [MSTP207] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT),
MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT), [MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), [MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), [MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), [MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), [MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
}; };
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
static struct clk_lookup lookups[] = { 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 */ /* DIV6 clocks */
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), 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) 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); ret = sh_clk_div6_register(div6_clks, DIV6_NR);
if (!ret) if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
return ret; return ret;
} }

View File

@ -37,8 +37,6 @@
/* Fixed 32 KHz root clock for RTC and Power Management purposes */ /* Fixed 32 KHz root clock for RTC and Power Management purposes */
static struct clk r_clk = { static struct clk r_clk = {
.name = "rclk",
.id = -1,
.rate = 32768, .rate = 32768,
}; };
@ -47,8 +45,6 @@ static struct clk r_clk = {
* from the platform code. * from the platform code.
*/ */
struct clk extal_clk = { struct clk extal_clk = {
.name = "extal",
.id = -1,
.rate = 33333333, .rate = 33333333,
}; };
@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = {
}; };
static struct clk dll_clk = { static struct clk dll_clk = {
.name = "dll_clk",
.id = -1,
.ops = &dll_clk_ops, .ops = &dll_clk_ops,
.parent = &r_clk, .parent = &r_clk,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
@ -95,8 +89,6 @@ static struct clk_ops pll_clk_ops = {
}; };
static struct clk pll_clk = { static struct clk pll_clk = {
.name = "pll_clk",
.id = -1,
.ops = &pll_clk_ops, .ops = &pll_clk_ops,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
}; };
@ -122,31 +114,31 @@ static struct clk_div4_table div4_table = {
.div_mult_table = &div4_div_mult_table, .div_mult_table = &div4_div_mult_table,
}; };
#define DIV4(_str, _reg, _bit, _mask, _flags) \ #define DIV4(_reg, _bit, _mask, _flags) \
SH_CLK_DIV4(_str, &pll_clk, _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 }; enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };
struct clk div4_clks[DIV4_NR] = { struct clk div4_clks[DIV4_NR] = {
[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT), [DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0), [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
}; };
enum { DIV4_IRDA, DIV4_ENABLE_NR }; enum { DIV4_IRDA, DIV4_ENABLE_NR };
struct clk div4_enable_clks[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 }; enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };
struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {
[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0), [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
}; };
enum { DIV6_V, DIV6_NR }; 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 } #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
static struct clk_lookup lookups[] = { 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 */ /* DIV6 clocks */
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),

View File

@ -38,8 +38,6 @@
/* Fixed 32 KHz root clock for RTC and Power Management purposes */ /* Fixed 32 KHz root clock for RTC and Power Management purposes */
static struct clk r_clk = { static struct clk r_clk = {
.name = "rclk",
.id = -1,
.rate = 32768, .rate = 32768,
}; };
@ -48,8 +46,6 @@ static struct clk r_clk = {
* from the platform code. * from the platform code.
*/ */
struct clk extal_clk = { struct clk extal_clk = {
.name = "extal",
.id = -1,
.rate = 33333333, .rate = 33333333,
}; };
@ -71,8 +67,6 @@ static struct clk_ops dll_clk_ops = {
}; };
static struct clk dll_clk = { static struct clk dll_clk = {
.name = "dll_clk",
.id = -1,
.ops = &dll_clk_ops, .ops = &dll_clk_ops,
.parent = &r_clk, .parent = &r_clk,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
@ -96,8 +90,6 @@ static struct clk_ops pll_clk_ops = {
}; };
static struct clk pll_clk = { static struct clk pll_clk = {
.name = "pll_clk",
.id = -1,
.ops = &pll_clk_ops, .ops = &pll_clk_ops,
.flags = CLK_ENABLE_ON_INIT, .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 }; enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };
#define DIV4(_str, _reg, _bit, _mask, _flags) \ #define DIV4(_reg, _bit, _mask, _flags) \
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
struct clk div4_clks[DIV4_NR] = { struct clk div4_clks[DIV4_NR] = {
[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x0dbf, CLK_ENABLE_ON_INIT), [DIV4_I] = DIV4(FRQCR, 20, 0x0dbf, CLK_ENABLE_ON_INIT),
[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x0dbf, CLK_ENABLE_ON_INIT), [DIV4_U] = DIV4(FRQCR, 16, 0x0dbf, CLK_ENABLE_ON_INIT),
[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x0dbf, CLK_ENABLE_ON_INIT), [DIV4_SH] = DIV4(FRQCR, 12, 0x0dbf, CLK_ENABLE_ON_INIT),
[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT), [DIV4_B] = DIV4(FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT),
[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT), [DIV4_B3] = DIV4(FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT),
[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x0dbf, 0), [DIV4_P] = DIV4(FRQCR, 0, 0x0dbf, 0),
}; };
enum { DIV4_IRDA, DIV4_ENABLE_NR }; enum { DIV4_IRDA, DIV4_ENABLE_NR };
struct clk div4_enable_clks[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 }; enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };
struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {
[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0), [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x0dbf, 0),
[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0), [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x0dbf, 0),
}; };
enum { DIV6_V, DIV6_NR }; 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 } #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
static struct clk_lookup lookups[] = { 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 */ /* DIV6 clocks */
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),

View File

@ -41,8 +41,6 @@
/* Fixed 32 KHz root clock for RTC and Power Management purposes */ /* Fixed 32 KHz root clock for RTC and Power Management purposes */
static struct clk r_clk = { static struct clk r_clk = {
.name = "rclk",
.id = -1,
.rate = 32768, .rate = 32768,
}; };
@ -51,8 +49,6 @@ static struct clk r_clk = {
* from the platform code. * from the platform code.
*/ */
struct clk extal_clk = { struct clk extal_clk = {
.name = "extal",
.id = -1,
.rate = 33333333, .rate = 33333333,
}; };
@ -76,8 +72,6 @@ static struct clk_ops fll_clk_ops = {
}; };
static struct clk fll_clk = { static struct clk fll_clk = {
.name = "fll_clk",
.id = -1,
.ops = &fll_clk_ops, .ops = &fll_clk_ops,
.parent = &r_clk, .parent = &r_clk,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
@ -98,8 +92,6 @@ static struct clk_ops pll_clk_ops = {
}; };
static struct clk pll_clk = { static struct clk pll_clk = {
.name = "pll_clk",
.id = -1,
.ops = &pll_clk_ops, .ops = &pll_clk_ops,
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
}; };
@ -115,8 +107,6 @@ static struct clk_ops div3_clk_ops = {
}; };
static struct clk div3_clk = { static struct clk div3_clk = {
.name = "div3_clk",
.id = -1,
.ops = &div3_clk_ops, .ops = &div3_clk_ops,
.parent = &pll_clk, .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 }; enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_P, DIV4_M1, DIV4_NR };
#define DIV4(_str, _reg, _bit, _mask, _flags) \ #define DIV4(_reg, _bit, _mask, _flags) \
SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
struct clk div4_clks[DIV4_NR] = { struct clk div4_clks[DIV4_NR] = {
[DIV4_I] = DIV4("cpu_clk", FRQCRA, 20, 0x2f7d, CLK_ENABLE_ON_INIT), [DIV4_I] = DIV4(FRQCRA, 20, 0x2f7d, CLK_ENABLE_ON_INIT),
[DIV4_SH] = DIV4("shyway_clk", FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT), [DIV4_SH] = DIV4(FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT),
[DIV4_B] = DIV4("bus_clk", FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT), [DIV4_B] = DIV4(FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT),
[DIV4_P] = DIV4("peripheral_clk", FRQCRA, 0, 0x2f7c, 0), [DIV4_P] = DIV4(FRQCRA, 0, 0x2f7c, 0),
[DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT), [DIV4_M1] = DIV4(FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT),
}; };
enum { DIV6_V, DIV6_FA, DIV6_FB, DIV6_I, DIV6_S, DIV6_NR }; 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 } #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
static struct clk_lookup lookups[] = { 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 */ /* DIV6 clocks */
CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FA]), CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FA]),

View File

@ -12,6 +12,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
@ -87,7 +88,6 @@ static struct clk_ops sh7757_shyway_clk_ops = {
}; };
static struct clk sh7757_shyway_clk = { static struct clk sh7757_shyway_clk = {
.name = "shyway_clk",
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
.ops = &sh7757_shyway_clk_ops, .ops = &sh7757_shyway_clk_ops,
}; };
@ -100,6 +100,13 @@ static struct clk *sh7757_onchip_clocks[] = {
&sh7757_shyway_clk, &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) static int __init sh7757_clk_init(void)
{ {
struct clk *clk = clk_get(NULL, "master_clk"); struct clk *clk = clk_get(NULL, "master_clk");
@ -123,6 +130,8 @@ static int __init sh7757_clk_init(void)
clk_put(clk); clk_put(clk);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
return 0; return 0;
} }

View File

@ -12,6 +12,8 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h>
#include <asm/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
#include <asm/io.h> #include <asm/io.h>
@ -77,7 +79,6 @@ static struct clk_ops sh7763_shyway_clk_ops = {
}; };
static struct clk sh7763_shyway_clk = { static struct clk sh7763_shyway_clk = {
.name = "shyway_clk",
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
.ops = &sh7763_shyway_clk_ops, .ops = &sh7763_shyway_clk_ops,
}; };
@ -90,6 +91,13 @@ static struct clk *sh7763_onchip_clocks[] = {
&sh7763_shyway_clk, &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) int __init arch_clk_init(void)
{ {
struct clk *clk; struct clk *clk;
@ -107,5 +115,7 @@ int __init arch_clk_init(void)
clk_put(clk); clk_put(clk);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
return ret; return ret;
} }

View File

@ -11,6 +11,8 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h>
#include <asm/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
#include <asm/io.h> #include <asm/io.h>
@ -83,7 +85,6 @@ static struct clk_ops sh7780_shyway_clk_ops = {
}; };
static struct clk sh7780_shyway_clk = { static struct clk sh7780_shyway_clk = {
.name = "shyway_clk",
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
.ops = &sh7780_shyway_clk_ops, .ops = &sh7780_shyway_clk_ops,
}; };
@ -96,6 +97,13 @@ static struct clk *sh7780_onchip_clocks[] = {
&sh7780_shyway_clk, &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) int __init arch_clk_init(void)
{ {
struct clk *clk; struct clk *clk;
@ -113,5 +121,7 @@ int __init arch_clk_init(void)
clk_put(clk); clk_put(clk);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
return ret; return ret;
} }

View File

@ -24,8 +24,6 @@
* from the platform code. * from the platform code.
*/ */
static struct clk extal_clk = { static struct clk extal_clk = {
.name = "extal",
.id = -1,
.rate = 33333333, .rate = 33333333,
}; };
@ -43,8 +41,6 @@ static struct clk_ops pll_clk_ops = {
}; };
static struct clk pll_clk = { static struct clk pll_clk = {
.name = "pll_clk",
.id = -1,
.ops = &pll_clk_ops, .ops = &pll_clk_ops,
.parent = &extal_clk, .parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT, .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, enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA,
DIV4_DU, DIV4_P, DIV4_NR }; DIV4_DU, DIV4_P, DIV4_NR };
#define DIV4(_str, _bit, _mask, _flags) \ #define DIV4(_bit, _mask, _flags) \
SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags) SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
struct clk div4_clks[DIV4_NR] = { struct clk div4_clks[DIV4_NR] = {
[DIV4_P] = DIV4("peripheral_clk", 0, 0x0f80, 0), [DIV4_P] = DIV4(0, 0x0f80, 0),
[DIV4_DU] = DIV4("du_clk", 4, 0x0ff0, 0), [DIV4_DU] = DIV4(4, 0x0ff0, 0),
[DIV4_GA] = DIV4("ga_clk", 8, 0x0030, 0), [DIV4_GA] = DIV4(8, 0x0030, 0),
[DIV4_DDR] = DIV4("ddr_clk", 12, 0x000c, CLK_ENABLE_ON_INIT), [DIV4_DDR] = DIV4(12, 0x000c, CLK_ENABLE_ON_INIT),
[DIV4_B] = DIV4("bus_clk", 16, 0x0fe0, CLK_ENABLE_ON_INIT), [DIV4_B] = DIV4(16, 0x0fe0, CLK_ENABLE_ON_INIT),
[DIV4_SH] = DIV4("shyway_clk", 20, 0x000c, CLK_ENABLE_ON_INIT), [DIV4_SH] = DIV4(20, 0x000c, CLK_ENABLE_ON_INIT),
[DIV4_U] = DIV4("umem_clk", 24, 0x000c, CLK_ENABLE_ON_INIT), [DIV4_U] = DIV4(24, 0x000c, CLK_ENABLE_ON_INIT),
[DIV4_I] = DIV4("cpu_clk", 28, 0x000e, CLK_ENABLE_ON_INIT), [DIV4_I] = DIV4(28, 0x000e, CLK_ENABLE_ON_INIT),
}; };
#define MSTPCR0 0xffc80030 #define MSTPCR0 0xffc80030
#define MSTPCR1 0xffc80034 #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 */ /* MSTPCR0 */
SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0),
SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), [MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0),
SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), [MSTP020] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), [MSTP017] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0),
SH_CLK_MSTP32("mmcif_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 13, 0), [MSTP013] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 13, 0),
SH_CLK_MSTP32("flctl_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 12, 0), [MSTP012] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 12, 0),
SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
SH_CLK_MSTP32("siof_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 3, 0), [MSTP003] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
/* MSTPCR1 */ /* MSTPCR1 */
SH_CLK_MSTP32("hudi_fck", -1, NULL, MSTPCR1, 19, 0), [MSTP119] = SH_CLK_MSTP32(NULL, MSTPCR1, 19, 0),
SH_CLK_MSTP32("ubc_fck", -1, NULL, MSTPCR1, 17, 0), [MSTP117] = SH_CLK_MSTP32(NULL, MSTPCR1, 17, 0),
SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
SH_CLK_MSTP32("gdta_fck", -1, NULL, MSTPCR1, 0, 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[] = { 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 */ /* TMU0 */
.dev_id = "sh_tmu.0", .dev_id = "sh_tmu.0",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[13], /* tmu012_fck */ .clk = &mstp_clks[MSTP008],
}, { }, {
/* TMU1 */ /* TMU1 */
.dev_id = "sh_tmu.1", .dev_id = "sh_tmu.1",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[13], .clk = &mstp_clks[MSTP008],
}, { }, {
/* TMU2 */ /* TMU2 */
.dev_id = "sh_tmu.2", .dev_id = "sh_tmu.2",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[13], .clk = &mstp_clks[MSTP008],
}, { }, {
/* TMU3 */ /* TMU3 */
.dev_id = "sh_tmu.3", .dev_id = "sh_tmu.3",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[12], /* tmu345_fck */ .clk = &mstp_clks[MSTP009],
}, { }, {
/* TMU4 */ /* TMU4 */
.dev_id = "sh_tmu.4", .dev_id = "sh_tmu.4",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[12], .clk = &mstp_clks[MSTP009],
}, { }, {
/* TMU5 */ /* TMU5 */
.dev_id = "sh_tmu.5", .dev_id = "sh_tmu.5",
.con_id = "tmu_fck", .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) 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), ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
&div4_table); &div4_table);
if (!ret) if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
return ret; return ret;
} }

View File

@ -23,8 +23,6 @@
* from the platform code. * from the platform code.
*/ */
static struct clk extal_clk = { static struct clk extal_clk = {
.name = "extal",
.id = -1,
.rate = 33333333, .rate = 33333333,
}; };
@ -46,8 +44,6 @@ static struct clk_ops pll_clk_ops = {
}; };
static struct clk pll_clk = { static struct clk pll_clk = {
.name = "pll_clk",
.id = -1,
.ops = &pll_clk_ops, .ops = &pll_clk_ops,
.parent = &extal_clk, .parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT, .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 }; enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR };
#define DIV4(_str, _bit, _mask, _flags) \ #define DIV4(_bit, _mask, _flags) \
SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags) SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
struct clk div4_clks[DIV4_NR] = { struct clk div4_clks[DIV4_NR] = {
[DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0), [DIV4_P] = DIV4(0, 0x0b40, 0),
[DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0), [DIV4_DU] = DIV4(4, 0x0010, 0),
[DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT), [DIV4_DDR] = DIV4(12, 0x0002, CLK_ENABLE_ON_INIT),
[DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT), [DIV4_B] = DIV4(16, 0x0360, CLK_ENABLE_ON_INIT),
[DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT), [DIV4_SH] = DIV4(20, 0x0002, CLK_ENABLE_ON_INIT),
[DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT), [DIV4_I] = DIV4(28, 0x0006, CLK_ENABLE_ON_INIT),
}; };
#define MSTPCR0 0xffc40030 #define MSTPCR0 0xffc40030
#define MSTPCR1 0xffc40034 #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 */ /* MSTPCR0 */
SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0),
SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), [MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0),
SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), [MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), [MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), [MSTP020] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), [MSTP017] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0),
SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0), [MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0), [MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0),
SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0), [MSTP011] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0), [MSTP010] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0), [MSTP005] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0), [MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
/* MSTPCR1 */ /* MSTPCR1 */
SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0), [MSTP112] = SH_CLK_MSTP32(NULL, MSTPCR1, 12, 0),
SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0), [MSTP110] = SH_CLK_MSTP32(NULL, MSTPCR1, 10, 0),
SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0), [MSTP109] = SH_CLK_MSTP32(NULL, MSTPCR1, 9, 0),
SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0), [MSTP108] = SH_CLK_MSTP32(NULL, MSTPCR1, 8, 0),
SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0), [MSTP103] = SH_CLK_MSTP32(NULL, MSTPCR1, 3, 0),
SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 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[] = { 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 */ /* TMU0 */
.dev_id = "sh_tmu.0", .dev_id = "sh_tmu.0",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[17], /* tmu012_fck */ .clk = &mstp_clks[MSTP008],
}, { }, {
/* TMU1 */ /* TMU1 */
.dev_id = "sh_tmu.1", .dev_id = "sh_tmu.1",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[17], .clk = &mstp_clks[MSTP008],
}, { }, {
/* TMU2 */ /* TMU2 */
.dev_id = "sh_tmu.2", .dev_id = "sh_tmu.2",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[17], .clk = &mstp_clks[MSTP008],
}, { }, {
/* TMU3 */ /* TMU3 */
.dev_id = "sh_tmu.3", .dev_id = "sh_tmu.3",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[16], /* tmu345_fck */ .clk = &mstp_clks[MSTP009],
}, { }, {
/* TMU4 */ /* TMU4 */
.dev_id = "sh_tmu.4", .dev_id = "sh_tmu.4",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[16], .clk = &mstp_clks[MSTP009],
}, { }, {
/* TMU5 */ /* TMU5 */
.dev_id = "sh_tmu.5", .dev_id = "sh_tmu.5",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[16], .clk = &mstp_clks[MSTP009],
}, { }, {
/* TMU6 */ /* TMU6 */
.dev_id = "sh_tmu.6", .dev_id = "sh_tmu.6",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[15], /* tmu678_fck */ .clk = &mstp_clks[MSTP010],
}, { }, {
/* TMU7 */ /* TMU7 */
.dev_id = "sh_tmu.7", .dev_id = "sh_tmu.7",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[15], .clk = &mstp_clks[MSTP010],
}, { }, {
/* TMU8 */ /* TMU8 */
.dev_id = "sh_tmu.8", .dev_id = "sh_tmu.8",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[15], .clk = &mstp_clks[MSTP010],
}, { }, {
/* TMU9 */ /* TMU9 */
.dev_id = "sh_tmu.9", .dev_id = "sh_tmu.9",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[14], /* tmu9_11_fck */ .clk = &mstp_clks[MSTP011],
}, { }, {
/* TMU10 */ /* TMU10 */
.dev_id = "sh_tmu.10", .dev_id = "sh_tmu.10",
.con_id = "tmu_fck", .con_id = "tmu_fck",
.clk = &mstp_clks[14], .clk = &mstp_clks[MSTP011],
}, { }, {
/* TMU11 */ /* TMU11 */
.dev_id = "sh_tmu.11", .dev_id = "sh_tmu.11",
.con_id = "tmu_fck", .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) 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), ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
&div4_table); &div4_table);
if (!ret) if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
return ret; return ret;
} }

View File

@ -13,9 +13,10 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h>
#include <asm/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
#include <asm/io.h>
static int ifc_divisors[] = { 1, 2, 4 ,6 }; static int ifc_divisors[] = { 1, 2, 4 ,6 };
static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 }; 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 = { static struct clk shx3_shyway_clk = {
.name = "shyway_clk",
.flags = CLK_ENABLE_ON_INIT, .flags = CLK_ENABLE_ON_INIT,
.ops = &shx3_shyway_clk_ops, .ops = &shx3_shyway_clk_ops,
}; };
@ -107,6 +107,13 @@ static struct clk *shx3_onchip_clocks[] = {
&shx3_shyway_clk, &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) int __init arch_clk_init(void)
{ {
struct clk *clk; struct clk *clk;
@ -124,5 +131,7 @@ int __init arch_clk_init(void)
clk_put(clk); clk_put(clk);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
return ret; return ret;
} }

View File

@ -4,4 +4,6 @@
obj-$(CONFIG_SUPERHYWAY) += superhyway/ obj-$(CONFIG_SUPERHYWAY) += superhyway/
obj-$(CONFIG_MAPLE) += maple/ obj-$(CONFIG_MAPLE) += maple/
obj-$(CONFIG_GENERIC_GPIO) += pfc.o obj-$(CONFIG_GENERIC_GPIO) += pfc.o
obj-$(CONFIG_SUPERH) += clk.o
obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o
obj-y += intc.o obj-y += intc.o

298
drivers/sh/clk-cpg.c Normal file
View File

@ -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);
}

545
drivers/sh/clk.c Normal file
View File

@ -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);

151
include/linux/sh_clk.h Normal file
View File

@ -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 */