clock-sh7757.c 3.9 KB
Newer Older
1 2 3 4 5
/*
 * arch/sh/kernel/cpu/sh4/clock-sh7757.c
 *
 * SH7757 support for the clock framework
 *
6
 *  Copyright (C) 2009-2010  Renesas Solutions Corp.
7 8 9 10 11 12 13 14
 *
 * 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/io.h>
M
Magnus Damm 已提交
15
#include <asm/clkdev.h>
16 17 18
#include <asm/clock.h>
#include <asm/freq.h>

19 20 21 22 23 24 25
/*
 * Default rate for the root input clock, reset this with clk_set_rate()
 * from the platform code.
 */
static struct clk extal_clk = {
	.rate		= 48000000,
};
26

27
static unsigned long pll_recalc(struct clk *clk)
28
{
29
	int multiplier;
30

31
	multiplier = test_mode_pin(MODE_PIN0) ? 24 : 16;
32

33
	return clk->parent->rate * multiplier;
34 35
}

36 37
static struct clk_ops pll_clk_ops = {
	.recalc		= pll_recalc,
38 39
};

40 41 42 43 44
static struct clk pll_clk = {
	.ops		= &pll_clk_ops,
	.parent		= &extal_clk,
	.flags		= CLK_ENABLE_ON_INIT,
};
45

46 47 48
static struct clk *clks[] = {
	&extal_clk,
	&pll_clk,
49 50
};

51 52
static unsigned int div2[] = { 1, 1, 2, 1, 1, 4, 1, 6,
			       1, 1, 1, 16, 1, 24, 1, 1 };
53

54 55 56
static struct clk_div_mult_table div4_div_mult_table = {
	.divisors = div2,
	.nr_divisors = ARRAY_SIZE(div2),
57 58
};

59 60
static struct clk_div4_table div4_table = {
	.div_mult_table = &div4_div_mult_table,
61 62
};

63
enum { DIV4_I, DIV4_SH, DIV4_P, DIV4_NR };
64

65 66
#define DIV4(_bit, _mask, _flags) \
  SH_CLK_DIV4(&pll_clk, FRQCR, _bit, _mask, _flags)
67

68 69 70 71 72 73 74 75
struct clk div4_clks[DIV4_NR] = {
	/*
	 * P clock is always enable, because some P clock modules is used
	 * by Host PC.
	 */
	[DIV4_P] = DIV4(0, 0x2800, CLK_ENABLE_ON_INIT),
	[DIV4_SH] = DIV4(12, 0x00a0, CLK_ENABLE_ON_INIT),
	[DIV4_I] = DIV4(20, 0x0004, CLK_ENABLE_ON_INIT),
76 77
};

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#define MSTPCR0		0xffc80030
#define MSTPCR1		0xffc80034

enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112,
       MSTP111, MSTP110, MSTP103, MSTP102,
       MSTP_NR };

static struct clk mstp_clks[MSTP_NR] = {
	/* MSTPCR0 */
	[MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
	[MSTP000] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 0, 0),

	/* MSTPCR1 */
	[MSTP114] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 14, 0),
	[MSTP113] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 13, 0),
	[MSTP112] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 12, 0),
	[MSTP111] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 11, 0),
	[MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0),
	[MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
	[MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0),
98 99
};

M
Magnus Damm 已提交
100 101 102 103
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }

static struct clk_lookup lookups[] = {
	/* main clocks */
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
	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("shyway_clk", &div4_clks[DIV4_SH]),
	CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),

	/* MSTP32 clocks */
	CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
	CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]),
	{
		/* TMU0 */
		.dev_id		= "sh_tmu.0",
		.con_id		= "tmu_fck",
		.clk		= &mstp_clks[MSTP113],
	}, {
		/* TMU1 */
		.dev_id		= "sh_tmu.1",
		.con_id		= "tmu_fck",
		.clk		= &mstp_clks[MSTP114],
	},
	{
		/* SCIF4 (But, ID is 2) */
		.dev_id		= "sh-sci.2",
		.con_id		= "sci_fck",
		.clk		= &mstp_clks[MSTP112],
	}, {
		/* SCIF3 */
		.dev_id		= "sh-sci.1",
		.con_id		= "sci_fck",
		.clk		= &mstp_clks[MSTP111],
	}, {
		/* SCIF2 */
		.dev_id		= "sh-sci.0",
		.con_id		= "sci_fck",
		.clk		= &mstp_clks[MSTP110],
	},
	CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
M
Magnus Damm 已提交
143 144
};

145
int __init arch_clk_init(void)
146
{
147
	int i, ret = 0;
148

149 150 151 152
	for (i = 0; i < ARRAY_SIZE(clks); i++)
		ret |= clk_register(clks[i]);
	for (i = 0; i < ARRAY_SIZE(lookups); i++)
		clkdev_add(&lookups[i]);
153

154 155 156 157 158
	if (!ret)
		ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
					   &div4_table);
	if (!ret)
		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
159

160
	return ret;
161 162
}