blob: 8894926479a614234302af0f7f51fbc3e9f56266 [file] [log] [blame]
Paul Mundt36ddf312006-01-16 22:14:17 -08001/*
Uwe Kleine-König58862692007-05-09 07:51:49 +02002 * arch/sh/kernel/cpu/sh4a/clock-sh7780.c
Paul Mundt36ddf312006-01-16 22:14:17 -08003 *
4 * SH7780 support for the clock framework
5 *
6 * Copyright (C) 2005 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/kernel.h>
Magnus Damm29497ec2010-05-11 09:36:24 +000014#include <linux/io.h>
Jean-Christop PLAGNIOL-VILLARD6d803ba2010-11-17 10:04:33 +010015#include <linux/clkdev.h>
Paul Mundt36ddf312006-01-16 22:14:17 -080016#include <asm/clock.h>
17#include <asm/freq.h>
18#include <asm/io.h>
19
20static int ifc_divisors[] = { 2, 4 };
21static int bfc_divisors[] = { 1, 1, 1, 8, 12, 16, 24, 1 };
22static int pfc_divisors[] = { 1, 24, 24, 1 };
23static int cfc_divisors[] = { 1, 1, 4, 1, 6, 1, 1, 1 };
24
25static void master_clk_init(struct clk *clk)
26{
Paul Mundt9d56dd32010-01-26 12:58:40 +090027 clk->rate *= pfc_divisors[__raw_readl(FRQCR) & 0x0003];
Paul Mundt36ddf312006-01-16 22:14:17 -080028}
29
30static struct clk_ops sh7780_master_clk_ops = {
31 .init = master_clk_init,
32};
33
Paul Mundtb68d82012009-05-12 03:45:08 +090034static unsigned long module_clk_recalc(struct clk *clk)
Paul Mundt36ddf312006-01-16 22:14:17 -080035{
Paul Mundt9d56dd32010-01-26 12:58:40 +090036 int idx = (__raw_readl(FRQCR) & 0x0003);
Paul Mundtb68d82012009-05-12 03:45:08 +090037 return clk->parent->rate / pfc_divisors[idx];
Paul Mundt36ddf312006-01-16 22:14:17 -080038}
39
40static struct clk_ops sh7780_module_clk_ops = {
41 .recalc = module_clk_recalc,
42};
43
Paul Mundtb68d82012009-05-12 03:45:08 +090044static unsigned long bus_clk_recalc(struct clk *clk)
Paul Mundt36ddf312006-01-16 22:14:17 -080045{
Paul Mundt9d56dd32010-01-26 12:58:40 +090046 int idx = ((__raw_readl(FRQCR) >> 16) & 0x0007);
Paul Mundtb68d82012009-05-12 03:45:08 +090047 return clk->parent->rate / bfc_divisors[idx];
Paul Mundt36ddf312006-01-16 22:14:17 -080048}
49
50static struct clk_ops sh7780_bus_clk_ops = {
51 .recalc = bus_clk_recalc,
52};
53
Paul Mundtb68d82012009-05-12 03:45:08 +090054static unsigned long cpu_clk_recalc(struct clk *clk)
Paul Mundt36ddf312006-01-16 22:14:17 -080055{
Paul Mundt9d56dd32010-01-26 12:58:40 +090056 int idx = ((__raw_readl(FRQCR) >> 24) & 0x0001);
Paul Mundtb68d82012009-05-12 03:45:08 +090057 return clk->parent->rate / ifc_divisors[idx];
Paul Mundt36ddf312006-01-16 22:14:17 -080058}
59
60static struct clk_ops sh7780_cpu_clk_ops = {
61 .recalc = cpu_clk_recalc,
62};
63
64static struct clk_ops *sh7780_clk_ops[] = {
65 &sh7780_master_clk_ops,
66 &sh7780_module_clk_ops,
67 &sh7780_bus_clk_ops,
68 &sh7780_cpu_clk_ops,
69};
70
71void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
72{
73 if (idx < ARRAY_SIZE(sh7780_clk_ops))
74 *ops = sh7780_clk_ops[idx];
75}
76
Paul Mundtb68d82012009-05-12 03:45:08 +090077static unsigned long shyway_clk_recalc(struct clk *clk)
Paul Mundt36ddf312006-01-16 22:14:17 -080078{
Paul Mundt9d56dd32010-01-26 12:58:40 +090079 int idx = ((__raw_readl(FRQCR) >> 20) & 0x0007);
Paul Mundtb68d82012009-05-12 03:45:08 +090080 return clk->parent->rate / cfc_divisors[idx];
Paul Mundt36ddf312006-01-16 22:14:17 -080081}
82
83static struct clk_ops sh7780_shyway_clk_ops = {
84 .recalc = shyway_clk_recalc,
85};
86
87static struct clk sh7780_shyway_clk = {
Paul Mundt4ff29ff2009-05-12 05:14:53 +090088 .flags = CLK_ENABLE_ON_INIT,
Paul Mundt36ddf312006-01-16 22:14:17 -080089 .ops = &sh7780_shyway_clk_ops,
90};
91
92/*
93 * Additional SH7780-specific on-chip clocks that aren't already part of the
94 * clock framework
95 */
96static struct clk *sh7780_onchip_clocks[] = {
97 &sh7780_shyway_clk,
98};
99
Magnus Damm29497ec2010-05-11 09:36:24 +0000100#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
101
102static struct clk_lookup lookups[] = {
103 /* main clocks */
104 CLKDEV_CON_ID("shyway_clk", &sh7780_shyway_clk),
105};
106
Paul Mundt9fe5ee02009-05-12 19:29:04 +0900107int __init arch_clk_init(void)
Paul Mundt36ddf312006-01-16 22:14:17 -0800108{
Paul Mundt253b0882009-05-13 17:38:11 +0900109 struct clk *clk;
Paul Mundtf5c84cf2009-05-12 05:59:27 +0900110 int i, ret = 0;
Paul Mundt36ddf312006-01-16 22:14:17 -0800111
Paul Mundt253b0882009-05-13 17:38:11 +0900112 cpg_clk_init();
113
114 clk = clk_get(NULL, "master_clk");
Paul Mundt36ddf312006-01-16 22:14:17 -0800115 for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) {
116 struct clk *clkp = sh7780_onchip_clocks[i];
117
118 clkp->parent = clk;
Paul Mundtf5c84cf2009-05-12 05:59:27 +0900119 ret |= clk_register(clkp);
Paul Mundt36ddf312006-01-16 22:14:17 -0800120 }
121
Paul Mundt36ddf312006-01-16 22:14:17 -0800122 clk_put(clk);
123
Magnus Damm29497ec2010-05-11 09:36:24 +0000124 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
125
Paul Mundtf5c84cf2009-05-12 05:59:27 +0900126 return ret;
Paul Mundt36ddf312006-01-16 22:14:17 -0800127}