Blame view
arch/arm/mach-s3c2443/clock.c
5.83 KB
e4d06e395 [ARM] 4198/2: S3C... |
1 2 |
/* linux/arch/arm/mach-s3c2443/clock.c * |
4bed36b2c ARM: S3C2443: Fur... |
3 |
* Copyright (c) 2007, 2010 Simtec Electronics |
e4d06e395 [ARM] 4198/2: S3C... |
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
* Ben Dooks <ben@simtec.co.uk> * * S3C2443 Clock control support * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/init.h> |
af337f3e6 ARM: S3C2443: Mov... |
24 |
|
e4d06e395 [ARM] 4198/2: S3C... |
25 26 27 28 29 |
#include <linux/module.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> |
edbaa603e driver-core: remo... |
30 |
#include <linux/device.h> |
e4d06e395 [ARM] 4198/2: S3C... |
31 32 |
#include <linux/clk.h> #include <linux/mutex.h> |
e4d06e395 [ARM] 4198/2: S3C... |
33 |
#include <linux/serial_core.h> |
fced80c73 [ARM] Convert asm... |
34 |
#include <linux/io.h> |
e4d06e395 [ARM] 4198/2: S3C... |
35 36 |
#include <asm/mach/map.h> |
a09e64fbc [ARM] Move includ... |
37 |
#include <mach/hardware.h> |
e4d06e395 [ARM] 4198/2: S3C... |
38 |
|
a09e64fbc [ARM] Move includ... |
39 |
#include <mach/regs-s3c2443-clock.h> |
e4d06e395 [ARM] 4198/2: S3C... |
40 |
|
e425382ed [ARM] S3C24XX: Up... |
41 |
#include <plat/cpu-freq.h> |
a2b7ba9ca [ARM] S3C24XX: Mo... |
42 |
#include <plat/s3c2443.h> |
d5120ae72 [ARM] S3C24XX: Ad... |
43 |
#include <plat/clock.h> |
9aa753c44 ARM: S3C2443: Cha... |
44 |
#include <plat/clock-clksrc.h> |
a2b7ba9ca [ARM] S3C24XX: Mo... |
45 |
#include <plat/cpu.h> |
e4d06e395 [ARM] 4198/2: S3C... |
46 47 48 49 50 51 52 53 54 |
/* We currently have to assume that the system is running * from the XTPll input, and that all ***REFCLKs are being * fed from it, as we cannot read the state of OM[4] from * software. * * It would be possible for each board initialisation to * set the correct muxing at initialisation */ |
e4d06e395 [ARM] 4198/2: S3C... |
55 |
/* clock selections */ |
ba7622a19 [ARM] S3C2443: Ad... |
56 57 58 59 |
/* armdiv * * this clock is sourced from msysclk and can have a number of * divider values applied to it to then be fed into armclk. |
aab08eebd ARM: S3C2443: Mov... |
60 61 |
* The real clock definition is done in s3c2443-clock.c, * only the armdiv divisor table must be defined here. |
ba7622a19 [ARM] S3C2443: Ad... |
62 |
*/ |
41f23a09f ARM: S3C2443: Add... |
63 64 65 66 67 68 69 70 71 72 |
static unsigned int armdiv[16] = { [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1, [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2, [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3, [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4, [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6, [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8, [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12, [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16, }; |
e4d06e395 [ARM] 4198/2: S3C... |
73 74 75 76 |
/* hsspi * * high-speed spi clock, sourced from esysclk */ |
9aa753c44 ARM: S3C2443: Cha... |
77 78 |
static struct clksrc_clk clk_hsspi = { .clk = { |
8b069b770 ARM: S3C2443: Add... |
79 |
.name = "hsspi-if", |
4bed36b2c ARM: S3C2443: Fur... |
80 |
.parent = &clk_esysclk.clk, |
9aa753c44 ARM: S3C2443: Cha... |
81 82 |
.ctrlbit = S3C2443_SCLKCON_HSSPICLK, .enable = s3c2443_clkcon_enable_s, |
b3bf41be0 ARM: SAMSUNG: Red... |
83 |
}, |
9aa753c44 ARM: S3C2443: Cha... |
84 |
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, |
e4d06e395 [ARM] 4198/2: S3C... |
85 |
}; |
e4d06e395 [ARM] 4198/2: S3C... |
86 87 88 89 90 91 92 |
/* clk_hsmcc_div * * this clock is sourced from epll, and is fed through a divider, * to a mux controlled by sclkcon where either it or a extclk can * be fed to the hsmmc block */ |
9aa753c44 ARM: S3C2443: Cha... |
93 94 95 |
static struct clksrc_clk clk_hsmmc_div = { .clk = { .name = "hsmmc-div", |
e83626f2f ARM: S3C24XX: Add... |
96 |
.devname = "s3c-sdhci.1", |
4bed36b2c ARM: S3C2443: Fur... |
97 |
.parent = &clk_esysclk.clk, |
b3bf41be0 ARM: SAMSUNG: Red... |
98 |
}, |
9aa753c44 ARM: S3C2443: Cha... |
99 |
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 }, |
e4d06e395 [ARM] 4198/2: S3C... |
100 101 102 103 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 |
}; static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent) { unsigned long clksrc = __raw_readl(S3C2443_SCLKCON); clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT | S3C2443_SCLKCON_HSMMCCLK_EPLL); if (parent == &clk_epll) clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL; else if (parent == &clk_ext) clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT; else return -EINVAL; if (clk->usage > 0) { __raw_writel(clksrc, S3C2443_SCLKCON); } clk->parent = parent; return 0; } static int s3c2443_enable_hsmmc(struct clk *clk, int enable) { return s3c2443_setparent_hsmmc(clk, clk->parent); } static struct clk clk_hsmmc = { .name = "hsmmc-if", |
e83626f2f ARM: S3C24XX: Add... |
131 |
.devname = "s3c-sdhci.1", |
9aa753c44 ARM: S3C2443: Cha... |
132 |
.parent = &clk_hsmmc_div.clk, |
e4d06e395 [ARM] 4198/2: S3C... |
133 |
.enable = s3c2443_enable_hsmmc, |
b3bf41be0 ARM: SAMSUNG: Red... |
134 135 136 |
.ops = &(struct clk_ops) { .set_parent = s3c2443_setparent_hsmmc, }, |
e4d06e395 [ARM] 4198/2: S3C... |
137 |
}; |
e4d06e395 [ARM] 4198/2: S3C... |
138 |
/* standard clock definitions */ |
4e04691bc ARM: SAMSUNG: Add... |
139 |
static struct clk init_clocks_off[] = { |
e4d06e395 [ARM] 4198/2: S3C... |
140 |
{ |
e4d06e395 [ARM] 4198/2: S3C... |
141 |
.name = "sdi", |
e4d06e395 [ARM] 4198/2: S3C... |
142 143 144 145 |
.parent = &clk_p, .enable = s3c2443_clkcon_enable_p, .ctrlbit = S3C2443_PCLKCON_SDI, }, { |
e4d06e395 [ARM] 4198/2: S3C... |
146 |
.name = "spi", |
e83626f2f ARM: S3C24XX: Add... |
147 |
.devname = "s3c2410-spi.0", |
e4d06e395 [ARM] 4198/2: S3C... |
148 149 150 151 152 |
.parent = &clk_p, .enable = s3c2443_clkcon_enable_p, .ctrlbit = S3C2443_PCLKCON_SPI0, }, { .name = "spi", |
e83626f2f ARM: S3C24XX: Add... |
153 |
.devname = "s3c2410-spi.1", |
e4d06e395 [ARM] 4198/2: S3C... |
154 155 156 157 158 |
.parent = &clk_p, .enable = s3c2443_clkcon_enable_p, .ctrlbit = S3C2443_PCLKCON_SPI1, } }; |
e4d06e395 [ARM] 4198/2: S3C... |
159 |
/* clocks to add straight away */ |
9aa753c44 ARM: S3C2443: Cha... |
160 |
static struct clksrc_clk *clksrcs[] __initdata = { |
e4d06e395 [ARM] 4198/2: S3C... |
161 162 |
&clk_hsspi, &clk_hsmmc_div, |
9aa753c44 ARM: S3C2443: Cha... |
163 164 165 |
}; static struct clk *clks[] __initdata = { |
e4d06e395 [ARM] 4198/2: S3C... |
166 167 |
&clk_hsmmc, }; |
e425382ed [ARM] S3C24XX: Up... |
168 |
void __init_or_cpufreq s3c2443_setup_clocks(void) |
e4d06e395 [ARM] 4198/2: S3C... |
169 |
{ |
33ccedfd1 ARM: S3C24XX: use... |
170 |
s3c2443_common_setup_clocks(s3c2443_get_mpll); |
e425382ed [ARM] S3C24XX: Up... |
171 172 173 174 |
} void __init s3c2443_init_clocks(int xtal) { |
e425382ed [ARM] S3C24XX: Up... |
175 |
unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); |
e425382ed [ARM] S3C24XX: Up... |
176 |
int ptr; |
af337f3e6 ARM: S3C2443: Mov... |
177 178 |
clk_epll.rate = s3c2443_get_epll(epllcon, xtal); clk_epll.parent = &clk_epllref.clk; |
33ccedfd1 ARM: S3C24XX: use... |
179 |
s3c2443_common_init_clocks(xtal, s3c2443_get_mpll, |
d9a3bfbd7 ARM: S3C24XX: Add... |
180 181 |
armdiv, ARRAY_SIZE(armdiv), S3C2443_CLKDIV0_ARMDIV_MASK); |
e425382ed [ARM] S3C24XX: Up... |
182 |
|
e425382ed [ARM] S3C24XX: Up... |
183 |
s3c2443_setup_clocks(); |
e4d06e395 [ARM] 4198/2: S3C... |
184 |
|
4e04691bc ARM: SAMSUNG: Add... |
185 |
s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); |
e4d06e395 [ARM] 4198/2: S3C... |
186 |
|
9aa753c44 ARM: S3C2443: Cha... |
187 188 |
for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_register_clksrc(clksrcs[ptr], 1); |
e4d06e395 [ARM] 4198/2: S3C... |
189 |
/* We must be careful disabling the clocks we are not intending to |
3a4fa0a25 Fix misspellings ... |
190 |
* be using at boot time, as subsystems such as the LCD which do |
e4d06e395 [ARM] 4198/2: S3C... |
191 192 193 194 195 196 197 198 199 |
* their own DMA requests to the bus can cause the system to lockup * if they where in the middle of requesting bus access. * * Disabling the LCD clock if the LCD is active is very dangerous, * and therefore the bootloader should be careful to not enable * the LCD clock if it is not needed. */ /* install (and disable) the clocks we do not need immediately */ |
4e04691bc ARM: SAMSUNG: Add... |
200 201 |
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); |
9d325f234 [ARM] S3C: Update... |
202 203 |
s3c_pwmclk_init(); |
e4d06e395 [ARM] 4198/2: S3C... |
204 |
} |