1/* 2 * SH7367 clock framework support 3 * 4 * Copyright (C) 2010 Magnus Damm 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19#include <linux/init.h> 20#include <linux/kernel.h> 21#include <linux/io.h> 22#include <linux/sh_clk.h> 23#include <linux/clkdev.h> 24#include <mach/common.h> 25 26/* SH7367 registers */ 27#define RTFRQCR 0xe6150000 28#define SYFRQCR 0xe6150004 29#define CMFRQCR 0xe61500E0 30#define VCLKCR1 0xe6150008 31#define VCLKCR2 0xe615000C 32#define VCLKCR3 0xe615001C 33#define SCLKACR 0xe6150010 34#define SCLKBCR 0xe6150014 35#define SUBUSBCKCR 0xe6158080 36#define SPUCKCR 0xe6150084 37#define MSUCKCR 0xe6150088 38#define MVI3CKCR 0xe6150090 39#define VOUCKCR 0xe6150094 40#define MFCK1CR 0xe6150098 41#define MFCK2CR 0xe615009C 42#define PLLC1CR 0xe6150028 43#define PLLC2CR 0xe615002C 44#define RTMSTPCR0 0xe6158030 45#define RTMSTPCR2 0xe6158038 46#define SYMSTPCR0 0xe6158040 47#define SYMSTPCR2 0xe6158048 48#define CMMSTPCR0 0xe615804c 49 50/* Fixed 32 KHz root clock from EXTALR pin */ 51static struct clk r_clk = { 52 .rate = 32768, 53}; 54 55/* 56 * 26MHz default rate for the EXTALB1 root input clock. 57 * If needed, reset this with clk_set_rate() from the platform code. 58 */ 59struct clk sh7367_extalb1_clk = { 60 .rate = 26666666, 61}; 62 63/* 64 * 48MHz default rate for the EXTAL2 root input clock. 65 * If needed, reset this with clk_set_rate() from the platform code. 66 */ 67struct clk sh7367_extal2_clk = { 68 .rate = 48000000, 69}; 70 71/* A fixed divide-by-2 block */ 72static unsigned long div2_recalc(struct clk *clk) 73{ 74 return clk->parent->rate / 2; 75} 76 77static struct sh_clk_ops div2_clk_ops = { 78 .recalc = div2_recalc, 79}; 80 81/* Divide extalb1 by two */ 82static struct clk extalb1_div2_clk = { 83 .ops = &div2_clk_ops, 84 .parent = &sh7367_extalb1_clk, 85}; 86 87/* Divide extal2 by two */ 88static struct clk extal2_div2_clk = { 89 .ops = &div2_clk_ops, 90 .parent = &sh7367_extal2_clk, 91}; 92 93/* PLLC1 */ 94static unsigned long pllc1_recalc(struct clk *clk) 95{ 96 unsigned long mult = 1; 97 98 if (__raw_readl(PLLC1CR) & (1 << 14)) 99 mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2; 100 101 return clk->parent->rate * mult; 102} 103 104static struct sh_clk_ops pllc1_clk_ops = { 105 .recalc = pllc1_recalc, 106}; 107 108static struct clk pllc1_clk = { 109 .ops = &pllc1_clk_ops, 110 .flags = CLK_ENABLE_ON_INIT, 111 .parent = &extalb1_div2_clk, 112}; 113 114/* Divide PLLC1 by two */ 115static struct clk pllc1_div2_clk = { 116 .ops = &div2_clk_ops, 117 .parent = &pllc1_clk, 118}; 119 120/* PLLC2 */ 121static unsigned long pllc2_recalc(struct clk *clk) 122{ 123 unsigned long mult = 1; 124 125 if (__raw_readl(PLLC2CR) & (1 << 31)) 126 mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2; 127 128 return clk->parent->rate * mult; 129} 130 131static struct sh_clk_ops pllc2_clk_ops = { 132 .recalc = pllc2_recalc, 133}; 134 135static struct clk pllc2_clk = { 136 .ops = &pllc2_clk_ops, 137 .flags = CLK_ENABLE_ON_INIT, 138 .parent = &extalb1_div2_clk, 139}; 140 141static struct clk *main_clks[] = { 142 &r_clk, 143 &sh7367_extalb1_clk, 144 &sh7367_extal2_clk, 145 &extalb1_div2_clk, 146 &extal2_div2_clk, 147 &pllc1_clk, 148 &pllc1_div2_clk, 149 &pllc2_clk, 150}; 151 152static void div4_kick(struct clk *clk) 153{ 154 unsigned long value; 155 156 /* set KICK bit in SYFRQCR to update hardware setting */ 157 value = __raw_readl(SYFRQCR); 158 value |= (1 << 31); 159 __raw_writel(value, SYFRQCR); 160} 161 162static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 163 24, 32, 36, 48, 0, 72, 0, 0 }; 164 165static struct clk_div_mult_table div4_div_mult_table = { 166 .divisors = divisors, 167 .nr_divisors = ARRAY_SIZE(divisors), 168}; 169 170static struct clk_div4_table div4_table = { 171 .div_mult_table = &div4_div_mult_table, 172 .kick = div4_kick, 173}; 174 175enum { DIV4_I, DIV4_G, DIV4_S, DIV4_B, 176 DIV4_ZX, DIV4_ZT, DIV4_Z, DIV4_ZD, DIV4_HP, 177 DIV4_ZS, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_NR }; 178 179#define DIV4(_reg, _bit, _mask, _flags) \ 180 SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags) 181 182static struct clk div4_clks[DIV4_NR] = { 183 [DIV4_I] = DIV4(RTFRQCR, 20, 0x6fff, CLK_ENABLE_ON_INIT), 184 [DIV4_G] = DIV4(RTFRQCR, 16, 0x6fff, CLK_ENABLE_ON_INIT), 185 [DIV4_S] = DIV4(RTFRQCR, 12, 0x6fff, CLK_ENABLE_ON_INIT), 186 [DIV4_B] = DIV4(RTFRQCR, 8, 0x6fff, CLK_ENABLE_ON_INIT), 187 [DIV4_ZX] = DIV4(SYFRQCR, 20, 0x6fff, 0), 188 [DIV4_ZT] = DIV4(SYFRQCR, 16, 0x6fff, 0), 189 [DIV4_Z] = DIV4(SYFRQCR, 12, 0x6fff, 0), 190 [DIV4_ZD] = DIV4(SYFRQCR, 8, 0x6fff, 0), 191 [DIV4_HP] = DIV4(SYFRQCR, 4, 0x6fff, 0), 192 [DIV4_ZS] = DIV4(CMFRQCR, 12, 0x6fff, 0), 193 [DIV4_ZB] = DIV4(CMFRQCR, 8, 0x6fff, 0), 194 [DIV4_ZB3] = DIV4(CMFRQCR, 4, 0x6fff, 0), 195 [DIV4_CP] = DIV4(CMFRQCR, 0, 0x6fff, 0), 196}; 197 198enum { DIV6_SUB, DIV6_SIUA, DIV6_SIUB, DIV6_MSU, DIV6_SPU, 199 DIV6_MVI3, DIV6_MF1, DIV6_MF2, 200 DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_VOU, 201 DIV6_NR }; 202 203static struct clk div6_clks[DIV6_NR] = { 204 [DIV6_SUB] = SH_CLK_DIV6(&sh7367_extal2_clk, SUBUSBCKCR, 0), 205 [DIV6_SIUA] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKACR, 0), 206 [DIV6_SIUB] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKBCR, 0), 207 [DIV6_MSU] = SH_CLK_DIV6(&pllc1_div2_clk, MSUCKCR, 0), 208 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0), 209 [DIV6_MVI3] = SH_CLK_DIV6(&pllc1_div2_clk, MVI3CKCR, 0), 210 [DIV6_MF1] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK1CR, 0), 211 [DIV6_MF2] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK2CR, 0), 212 [DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0), 213 [DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0), 214 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0), 215 [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0), 216}; 217 218enum { RTMSTP001, 219 RTMSTP231, RTMSTP230, RTMSTP229, RTMSTP228, RTMSTP226, 220 RTMSTP216, RTMSTP206, RTMSTP205, RTMSTP201, 221 SYMSTP023, SYMSTP007, SYMSTP006, SYMSTP004, 222 SYMSTP003, SYMSTP002, SYMSTP001, SYMSTP000, 223 SYMSTP231, SYMSTP229, SYMSTP225, SYMSTP223, SYMSTP222, 224 SYMSTP215, SYMSTP214, SYMSTP213, SYMSTP211, 225 CMMSTP003, 226 MSTP_NR }; 227 228#define MSTP(_parent, _reg, _bit, _flags) \ 229 SH_CLK_MSTP32(_parent, _reg, _bit, _flags) 230 231static struct clk mstp_clks[MSTP_NR] = { 232 [RTMSTP001] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR0, 1, 0), /* IIC2 */ 233 [RTMSTP231] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 31, 0), /* VEU3 */ 234 [RTMSTP230] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 30, 0), /* VEU2 */ 235 [RTMSTP229] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 29, 0), /* VEU1 */ 236 [RTMSTP228] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 28, 0), /* VEU0 */ 237 [RTMSTP226] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 26, 0), /* VEU2H */ 238 [RTMSTP216] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR2, 16, 0), /* IIC0 */ 239 [RTMSTP206] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 6, 0), /* JPU */ 240 [RTMSTP205] = MSTP(&div6_clks[DIV6_VOU], RTMSTPCR2, 5, 0), /* VOU */ 241 [RTMSTP201] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 1, 0), /* VPU */ 242 [SYMSTP023] = MSTP(&div6_clks[DIV6_SPU], SYMSTPCR0, 23, 0), /* SPU1 */ 243 [SYMSTP007] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 7, 0), /* SCIFA5 */ 244 [SYMSTP006] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 6, 0), /* SCIFB */ 245 [SYMSTP004] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 4, 0), /* SCIFA0 */ 246 [SYMSTP003] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 3, 0), /* SCIFA1 */ 247 [SYMSTP002] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 2, 0), /* SCIFA2 */ 248 [SYMSTP001] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 1, 0), /* SCIFA3 */ 249 [SYMSTP000] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 0, 0), /* SCIFA4 */ 250 [SYMSTP231] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 31, 0), /* SIU */ 251 [SYMSTP229] = MSTP(&r_clk, SYMSTPCR2, 29, 0), /* CMT10 */ 252 [SYMSTP225] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 25, 0), /* IRDA */ 253 [SYMSTP223] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 23, 0), /* IIC1 */ 254 [SYMSTP222] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 22, 0), /* USBHS */ 255 [SYMSTP215] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 15, 0), /* FLCTL */ 256 [SYMSTP214] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 14, 0), /* SDHI0 */ 257 [SYMSTP213] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 13, 0), /* SDHI1 */ 258 [SYMSTP211] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 11, 0), /* SDHI2 */ 259 [CMMSTP003] = MSTP(&r_clk, CMMSTPCR0, 3, 0), /* KEYSC */ 260}; 261 262static struct clk_lookup lookups[] = { 263 /* main clocks */ 264 CLKDEV_CON_ID("r_clk", &r_clk), 265 CLKDEV_CON_ID("extalb1", &sh7367_extalb1_clk), 266 CLKDEV_CON_ID("extal2", &sh7367_extal2_clk), 267 CLKDEV_CON_ID("extalb1_div2_clk", &extalb1_div2_clk), 268 CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk), 269 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), 270 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), 271 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk), 272 273 /* DIV4 clocks */ 274 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), 275 CLKDEV_CON_ID("g_clk", &div4_clks[DIV4_G]), 276 CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]), 277 CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]), 278 CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]), 279 CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]), 280 CLKDEV_CON_ID("zd_clk", &div4_clks[DIV4_ZD]), 281 CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]), 282 CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]), 283 CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]), 284 CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]), 285 CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]), 286 287 /* DIV6 clocks */ 288 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), 289 CLKDEV_CON_ID("siua_clk", &div6_clks[DIV6_SIUA]), 290 CLKDEV_CON_ID("siub_clk", &div6_clks[DIV6_SIUB]), 291 CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]), 292 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), 293 CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]), 294 CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]), 295 CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]), 296 CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]), 297 CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]), 298 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), 299 CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]), 300 301 /* MSTP32 clocks */ 302 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[RTMSTP001]), /* IIC2 */ 303 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[RTMSTP231]), /* VEU3 */ 304 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[RTMSTP230]), /* VEU2 */ 305 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[RTMSTP229]), /* VEU1 */ 306 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[RTMSTP228]), /* VEU0 */ 307 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[RTMSTP226]), /* VEU2H */ 308 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[RTMSTP216]), /* IIC0 */ 309 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[RTMSTP206]), /* JPU */ 310 CLKDEV_DEV_ID("sh-vou", &mstp_clks[RTMSTP205]), /* VOU */ 311 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[RTMSTP201]), /* VPU */ 312 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[SYMSTP023]), /* SPU1 */ 313 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[SYMSTP007]), /* SCIFA5 */ 314 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[SYMSTP006]), /* SCIFB */ 315 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[SYMSTP004]), /* SCIFA0 */ 316 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[SYMSTP003]), /* SCIFA1 */ 317 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[SYMSTP002]), /* SCIFA2 */ 318 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */ 319 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */ 320 CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */ 321 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[SYMSTP229]), /* CMT10 */ 322 CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */ 323 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */ 324 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */ 325 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[SYMSTP222]), /* USBHS */ 326 CLKDEV_DEV_ID("sh_flctl", &mstp_clks[SYMSTP215]), /* FLCTL */ 327 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[SYMSTP214]), /* SDHI0 */ 328 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[SYMSTP213]), /* SDHI1 */ 329 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[SYMSTP211]), /* SDHI2 */ 330 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[CMMSTP003]), /* KEYSC */ 331}; 332 333void __init sh7367_clock_init(void) 334{ 335 int k, ret = 0; 336 337 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) 338 ret = clk_register(main_clks[k]); 339 340 if (!ret) 341 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); 342 343 if (!ret) 344 ret = sh_clk_div6_register(div6_clks, DIV6_NR); 345 346 if (!ret) 347 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); 348 349 clkdev_add_table(lookups, ARRAY_SIZE(lookups)); 350 351 if (!ret) 352 shmobile_clk_init(); 353 else 354 panic("failed to setup sh7367 clocks\n"); 355} 356