Skip to content

Commit

Permalink
sh: clkfwk: Update SH7785 for refactored clock framework.
Browse files Browse the repository at this point in the history
This updates the SH7785 CPU code as well as the SH7785LCR board support
code for making use of the newly refactored clock framework. Support for
the legacy CPG clocks is dropped at this point, with the extal frequency
fed in from the board code.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
Paul Mundt committed May 13, 2009
1 parent 253b088 commit a77b5ac
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 104 deletions.
2 changes: 1 addition & 1 deletion arch/sh/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ config SH_PCLK_FREQ
platforms lacking an RTC.

config SH_CLK_CPG_LEGACY
def_bool y
def_bool y if !CPU_SUBTYPE_SH7785

config SH_CLK_MD
int "CPU Mode Pin Setting"
Expand Down
22 changes: 20 additions & 2 deletions arch/sh/boards/board-sh7785lcr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
* Renesas Technology Corp. R0P7785LC0011RL Support.
*
* Copyright (C) 2008 Yoshihiro Shimoda
* Copyright (C) 2009 Paul Mundt
*
* 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/init.h>
#include <linux/platform_device.h>
#include <linux/sm501.h>
Expand All @@ -19,8 +19,11 @@
#include <linux/i2c-pca-platform.h>
#include <linux/i2c-algo-pca.h>
#include <linux/irq.h>
#include <asm/heartbeat.h>
#include <linux/clk.h>
#include <linux/errno.h>
#include <mach/sh7785lcr.h>
#include <asm/heartbeat.h>
#include <asm/clock.h>

/*
* NOTE: This board has 2 physical memory maps.
Expand Down Expand Up @@ -273,6 +276,20 @@ void __init init_sh7785lcr_IRQ(void)
plat_irq_setup_pins(IRQ_MODE_IRQ3210);
}

static int sh7785lcr_clk_init(void)
{
struct clk *clk;
int ret;

clk = clk_get(NULL, "extal");
if (!clk || IS_ERR(clk))
return PTR_ERR(clk);
ret = clk_set_rate(clk, 33333333);
clk_put(clk);

return ret;
}

static void sh7785lcr_power_off(void)
{
unsigned char *p;
Expand Down Expand Up @@ -309,6 +326,7 @@ static void __init sh7785lcr_setup(char **cmdline_p)
static struct sh_machine_vector mv_sh7785lcr __initmv = {
.mv_name = "SH7785LCR",
.mv_setup = sh7785lcr_setup,
.mv_clk_init = sh7785lcr_clk_init,
.mv_init_irq = init_sh7785lcr_IRQ,
};

2 changes: 2 additions & 0 deletions arch/sh/include/asm/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ struct clk {

unsigned long rate;
unsigned long flags;

unsigned long arch_flags;
void *priv;
};

struct clk_lookup {
Expand Down
203 changes: 102 additions & 101 deletions arch/sh/kernel/cpu/sh4a/clock-sh7785.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,153 +3,154 @@
*
* SH7785 support for the clock framework
*
* Copyright (C) 2007 Paul Mundt
* Copyright (C) 2007 - 2009 Paul Mundt
*
* 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/init.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <asm/clock.h>
#include <asm/freq.h>
#include <asm/io.h>

static int ifc_divisors[] = { 1, 2, 4, 6 };
static int ufc_divisors[] = { 1, 1, 4, 6 };
static int sfc_divisors[] = { 1, 1, 4, 6 };
static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18,
24, 32, 36, 48, 1, 1, 1, 1 };
static int mfc_divisors[] = { 1, 1, 4, 6 };
static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18,
24, 32, 36, 48, 1, 1, 1, 1 };

static void master_clk_init(struct clk *clk)
{
clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
}

static struct clk_ops sh7785_master_clk_ops = {
.init = master_clk_init,
static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
24, 32, 36, 48 };
struct clk_priv {
unsigned int shift;
};

static unsigned long module_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inl(FRQMR1) & 0x000f);
return clk->parent->rate / pfc_divisors[idx];
}
#define FRQMR_CLK_DATA(_name, _shift) \
static struct clk_priv _name##_data = { .shift = _shift, }

static struct clk_ops sh7785_module_clk_ops = {
.recalc = module_clk_recalc,
};
FRQMR_CLK_DATA(pfc, 0);
FRQMR_CLK_DATA(s3fc, 4);
FRQMR_CLK_DATA(s2fc, 8);
FRQMR_CLK_DATA(mfc, 12);
FRQMR_CLK_DATA(bfc, 16);
FRQMR_CLK_DATA(sfc, 20);
FRQMR_CLK_DATA(ufc, 24);
FRQMR_CLK_DATA(ifc, 28);

static unsigned long bus_clk_recalc(struct clk *clk)
static unsigned long frqmr_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
return clk->parent->rate / bfc_divisors[idx];
}
struct clk_priv *data = clk->priv;
unsigned int idx;

static struct clk_ops sh7785_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f;

static unsigned long cpu_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
return clk->parent->rate / ifc_divisors[idx];
/*
* XXX: PLL1 multiplier is locked for the default clock mode,
* when mode pin detection and configuration support is added,
* select the multiplier dynamically.
*/
return clk->parent->rate * 36 / div2[idx];
}

static struct clk_ops sh7785_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
static struct clk_ops frqmr_clk_ops = {
.recalc = frqmr_clk_recalc,
};

static struct clk_ops *sh7785_clk_ops[] = {
&sh7785_master_clk_ops,
&sh7785_module_clk_ops,
&sh7785_bus_clk_ops,
&sh7785_cpu_clk_ops,
/*
* Default rate for the root input clock, reset this with clk_set_rate()
* from the platform code.
*/
static struct clk extal_clk = {
.name = "extal",
.id = -1,
.rate = 33333333,
};

void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7785_clk_ops))
*ops = sh7785_clk_ops[idx];
}

static unsigned long shyway_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
return clk->parent->rate / sfc_divisors[idx];
}

static struct clk_ops sh7785_shyway_clk_ops = {
.recalc = shyway_clk_recalc,
static struct clk cpu_clk = {
.name = "cpu_clk", /* Ick */
.id = -1,
.ops = &frqmr_clk_ops,
.parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT,
.priv = &ifc_data,
};

static struct clk sh7785_shyway_clk = {
.name = "shyway_clk",
static struct clk shyway_clk = {
.name = "shyway_clk", /* SHck */
.id = -1,
.ops = &frqmr_clk_ops,
.parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT,
.ops = &sh7785_shyway_clk_ops,
.priv = &sfc_data,
};

static unsigned long ddr_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
return clk->parent->rate / mfc_divisors[idx];
}
static struct clk peripheral_clk = {
.name = "peripheral_clk", /* Pck */
.id = -1,
.ops = &frqmr_clk_ops,
.parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT,
.priv = &pfc_data,
};

static struct clk_ops sh7785_ddr_clk_ops = {
.recalc = ddr_clk_recalc,
static struct clk ddr_clk = {
.name = "ddr_clk", /* DDRck */
.id = -1,
.ops = &frqmr_clk_ops,
.parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT,
.priv = &mfc_data,
};

static struct clk sh7785_ddr_clk = {
.name = "ddr_clk",
static struct clk bus_clk = {
.name = "bus_clk", /* Bck */
.id = -1,
.ops = &frqmr_clk_ops,
.parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT,
.ops = &sh7785_ddr_clk_ops,
.priv = &bfc_data,
};

static unsigned long ram_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQMR1) >> 24) & 0x0003);
return clk->parent->rate / ufc_divisors[idx];
}
static struct clk ga_clk = {
.name = "ga_clk", /* GAck */
.id = -1,
.ops = &frqmr_clk_ops,
.parent = &extal_clk,
.priv = &s2fc_data,
};

static struct clk_ops sh7785_ram_clk_ops = {
.recalc = ram_clk_recalc,
static struct clk du_clk = {
.name = "du_clk", /* DUck */
.id = -1,
.ops = &frqmr_clk_ops,
.parent = &extal_clk,
.priv = &s3fc_data,
};

static struct clk sh7785_ram_clk = {
.name = "ram_clk",
static struct clk umem_clk = {
.name = "umem_clk", /* uck */
.id = -1,
.ops = &frqmr_clk_ops,
.parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT,
.ops = &sh7785_ram_clk_ops,
.priv = &ufc_data,
};

/*
* Additional SH7785-specific on-chip clocks that aren't already part of the
* clock framework
*/
static struct clk *sh7785_onchip_clocks[] = {
&sh7785_shyway_clk,
&sh7785_ddr_clk,
&sh7785_ram_clk,
static struct clk *clks[] = {
&extal_clk,
&cpu_clk,
&shyway_clk,
&peripheral_clk,
&ddr_clk,
&bus_clk,
&ga_clk,
&du_clk,
&umem_clk,
};

int __init arch_clk_init(void)
{
struct clk *clk;
int i, ret = 0;

cpg_clk_init();

clk = clk_get(NULL, "master_clk");
for (i = 0; i < ARRAY_SIZE(sh7785_onchip_clocks); i++) {
struct clk *clkp = sh7785_onchip_clocks[i];

clkp->parent = clk;
ret |= clk_register(clkp);
}

clk_put(clk);
for (i = 0; i < ARRAY_SIZE(clks); i++)
ret |= clk_register(clks[i]);

return ret;
}

0 comments on commit a77b5ac

Please sign in to comment.