aboutsummaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7778.c149
1 files changed, 136 insertions, 13 deletions
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index cd6855290b1f..5cc271ecb5d9 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -23,9 +23,23 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*
+ * MD MD MD MD PLLA PLLB EXTAL clki clkz
+ * 19 18 12 11 (HMz) (MHz) (MHz)
+ *----------------------------------------------------------------------------
+ * 1 0 0 0 x21 x21 38.00 800 800
+ * 1 0 0 1 x24 x24 33.33 800 800
+ * 1 0 1 0 x28 x28 28.50 800 800
+ * 1 0 1 1 x32 x32 25.00 800 800
+ * 1 1 0 1 x24 x21 33.33 800 700
+ * 1 1 1 0 x28 x21 28.50 800 600
+ * 1 1 1 1 x32 x24 25.00 800 600
+ */
+
#include <linux/io.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
+#include <mach/clock.h>
#include <mach/common.h>
#define MSTPCR0 IOMEM(0xffc80030)
@@ -37,6 +51,9 @@
#define MSTPCR4 IOMEM(0xffc80050)
#define MSTPCR5 IOMEM(0xffc80054)
#define MSTPCR6 IOMEM(0xffc80058)
+#define MODEMR 0xFFCC0020
+
+#define MD(nr) BIT(nr)
/* ioremap() through clock mapping mandatory to avoid
* collision with ARM coherent DMA virtual memory range.
@@ -47,14 +64,42 @@ static struct clk_mapping cpg_mapping = {
.len = 0x80,
};
-static struct clk clkp = {
- .rate = 62500000, /* FIXME: shortcut */
- .flags = CLK_ENABLE_ON_INIT,
+static struct clk extal_clk = {
+ /* .rate will be updated on r8a7778_clock_init() */
.mapping = &cpg_mapping,
};
+/*
+ * clock ratio of these clock will be updated
+ * on r8a7778_clock_init()
+ */
+SH_FIXED_RATIO_CLK_SET(plla_clk, extal_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(pllb_clk, extal_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(i_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(s_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(s1_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(s3_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(s4_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(b_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(out_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(p_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(g_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(z_clk, pllb_clk, 1, 1);
+
static struct clk *main_clks[] = {
- &clkp,
+ &extal_clk,
+ &plla_clk,
+ &pllb_clk,
+ &i_clk,
+ &s_clk,
+ &s1_clk,
+ &s3_clk,
+ &s4_clk,
+ &b_clk,
+ &out_clk,
+ &p_clk,
+ &g_clk,
+ &z_clk,
};
enum {
@@ -64,15 +109,15 @@ enum {
MSTP_NR };
static struct clk mstp_clks[MSTP_NR] = {
- [MSTP114] = SH_CLK_MSTP32(&clkp, MSTPCR1, 14, 0), /* Ether */
- [MSTP026] = SH_CLK_MSTP32(&clkp, MSTPCR0, 26, 0), /* SCIF0 */
- [MSTP025] = SH_CLK_MSTP32(&clkp, MSTPCR0, 25, 0), /* SCIF1 */
- [MSTP024] = SH_CLK_MSTP32(&clkp, MSTPCR0, 24, 0), /* SCIF2 */
- [MSTP023] = SH_CLK_MSTP32(&clkp, MSTPCR0, 23, 0), /* SCIF3 */
- [MSTP022] = SH_CLK_MSTP32(&clkp, MSTPCR0, 22, 0), /* SCIF4 */
- [MSTP021] = SH_CLK_MSTP32(&clkp, MSTPCR0, 21, 0), /* SCIF5 */
- [MSTP016] = SH_CLK_MSTP32(&clkp, MSTPCR0, 16, 0), /* TMU0 */
- [MSTP015] = SH_CLK_MSTP32(&clkp, MSTPCR0, 15, 0), /* TMU1 */
+ [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
+ [MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */
+ [MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */
+ [MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */
+ [MSTP023] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 23, 0), /* SCIF3 */
+ [MSTP022] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 22, 0), /* SCIF4 */
+ [MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */
+ [MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */
+ [MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */
};
static struct clk_lookup lookups[] = {
@@ -90,8 +135,86 @@ static struct clk_lookup lookups[] = {
void __init r8a7778_clock_init(void)
{
+ void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
+ u32 mode;
int k, ret = 0;
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+
+ switch (mode & (MD(19) | MD(18) | MD(12) | MD(11))) {
+ case MD(19):
+ extal_clk.rate = 38000000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 21, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1);
+ break;
+ case MD(19) | MD(11):
+ extal_clk.rate = 33333333;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 24, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 24, 1);
+ break;
+ case MD(19) | MD(12):
+ extal_clk.rate = 28500000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 28, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 28, 1);
+ break;
+ case MD(19) | MD(12) | MD(11):
+ extal_clk.rate = 25000000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 32, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 32, 1);
+ break;
+ case MD(19) | MD(18) | MD(11):
+ extal_clk.rate = 33333333;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 24, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1);
+ break;
+ case MD(19) | MD(18) | MD(12):
+ extal_clk.rate = 28500000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 28, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1);
+ break;
+ case MD(19) | MD(18) | MD(12) | MD(11):
+ extal_clk.rate = 25000000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 32, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 24, 1);
+ break;
+ default:
+ BUG();
+ }
+
+ if (mode & MD(1)) {
+ SH_CLK_SET_RATIO(&i_clk_ratio, 1, 1);
+ SH_CLK_SET_RATIO(&s_clk_ratio, 1, 3);
+ SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 6);
+ SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
+ SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&p_clk_ratio, 1, 12);
+ SH_CLK_SET_RATIO(&g_clk_ratio, 1, 12);
+ if (mode & MD(2)) {
+ SH_CLK_SET_RATIO(&b_clk_ratio, 1, 18);
+ SH_CLK_SET_RATIO(&out_clk_ratio, 1, 18);
+ } else {
+ SH_CLK_SET_RATIO(&b_clk_ratio, 1, 12);
+ SH_CLK_SET_RATIO(&out_clk_ratio, 1, 12);
+ }
+ } else {
+ SH_CLK_SET_RATIO(&i_clk_ratio, 1, 1);
+ SH_CLK_SET_RATIO(&s_clk_ratio, 1, 4);
+ SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
+ SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&p_clk_ratio, 1, 16);
+ SH_CLK_SET_RATIO(&g_clk_ratio, 1, 12);
+ if (mode & MD(2)) {
+ SH_CLK_SET_RATIO(&b_clk_ratio, 1, 16);
+ SH_CLK_SET_RATIO(&out_clk_ratio, 1, 16);
+ } else {
+ SH_CLK_SET_RATIO(&b_clk_ratio, 1, 12);
+ SH_CLK_SET_RATIO(&out_clk_ratio, 1, 12);
+ }
+ }
+
for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
ret = clk_register(main_clks[k]);