1/* 2 * SH7377 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; either 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <mach/common.h> 24#include <asm/clkdev.h> 25 26/* SH7377 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 FMSICKCR 0xe6150010 34#define FMSOCKCR 0xe6150014 35#define FSICKCR 0xe6150018 36#define PLLC1CR 0xe6150028 37#define PLLC2CR 0xe615002C 38#define SUBUSBCKCR 0xe6150080 39#define SPUCKCR 0xe6150084 40#define MSUCKCR 0xe6150088 41#define MVI3CKCR 0xe6150090 42#define HDMICKCR 0xe6150094 43#define MFCK1CR 0xe6150098 44#define MFCK2CR 0xe615009C 45#define DSITCKCR 0xe6150060 46#define DSIPCKCR 0xe6150064 47#define SMSTPCR0 0xe6150130 48#define SMSTPCR1 0xe6150134 49#define SMSTPCR2 0xe6150138 50#define SMSTPCR3 0xe615013C 51#define SMSTPCR4 0xe6150140 52 53/* Fixed 32 KHz root clock from EXTALR pin */ 54static struct clk r_clk = { 55 .rate = 32768, 56}; 57 58/* 59 * 26MHz default rate for the EXTALC1 root input clock. 60 * If needed, reset this with clk_set_rate() from the platform code. 61 */ 62struct clk sh7377_extalc1_clk = { 63 .rate = 26666666, 64}; 65 66/* 67 * 48MHz default rate for the EXTAL2 root input clock. 68 * If needed, reset this with clk_set_rate() from the platform code. 69 */ 70struct clk sh7377_extal2_clk = { 71 .rate = 48000000, 72}; 73 74/* A fixed divide-by-2 block */ 75static unsigned long div2_recalc(struct clk *clk) 76{ 77 return clk->parent->rate / 2; 78} 79 80static struct clk_ops div2_clk_ops = { 81 .recalc = div2_recalc, 82}; 83 84/* Divide extalc1 by two */ 85static struct clk extalc1_div2_clk = { 86 .ops = &div2_clk_ops, 87 .parent = &sh7377_extalc1_clk, 88}; 89 90/* Divide extal2 by two */ 91static struct clk extal2_div2_clk = { 92 .ops = &div2_clk_ops, 93 .parent = &sh7377_extal2_clk, 94}; 95 96/* Divide extal2 by four */ 97static struct clk extal2_div4_clk = { 98 .ops = &div2_clk_ops, 99 .parent = &extal2_div2_clk, 100}; 101 102/* PLLC1 */ 103static unsigned long pllc1_recalc(struct clk *clk) 104{ 105 unsigned long mult = 1; 106 107 if (__raw_readl(PLLC1CR) & (1 << 14)) 108 mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2; 109 110 return clk->parent->rate * mult; 111} 112 113static struct clk_ops pllc1_clk_ops = { 114 .recalc = pllc1_recalc, 115}; 116 117static struct clk pllc1_clk = { 118 .ops = &pllc1_clk_ops, 119 .flags = CLK_ENABLE_ON_INIT, 120 .parent = &extalc1_div2_clk, 121}; 122 123/* Divide PLLC1 by two */ 124static struct clk pllc1_div2_clk = { 125 .ops = &div2_clk_ops, 126 .parent = &pllc1_clk, 127}; 128 129/* PLLC2 */ 130static unsigned long pllc2_recalc(struct clk *clk) 131{ 132 unsigned long mult = 1; 133 134 if (__raw_readl(PLLC2CR) & (1 << 31)) 135 mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2; 136 137 return clk->parent->rate * mult; 138} 139 140static struct clk_ops pllc2_clk_ops = { 141 .recalc = pllc2_recalc, 142}; 143 144static struct clk pllc2_clk = { 145 .ops = &pllc2_clk_ops, 146 .flags = CLK_ENABLE_ON_INIT, 147 .parent = &extalc1_div2_clk, 148}; 149 150static struct clk *main_clks[] = { 151 &r_clk, 152 &sh7377_extalc1_clk, 153 &sh7377_extal2_clk, 154 &extalc1_div2_clk, 155 &extal2_div2_clk, 156 &extal2_div4_clk, 157 &pllc1_clk, 158 &pllc1_div2_clk, 159 &pllc2_clk, 160}; 161 162static void div4_kick(struct clk *clk) 163{ 164 unsigned long value; 165 166 /* set KICK bit in SYFRQCR to update hardware setting */ 167 value = __raw_readl(SYFRQCR); 168 value |= (1 << 31); 169 __raw_writel(value, SYFRQCR); 170} 171 172static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 173 24, 32, 36, 48, 0, 72, 96, 0 }; 174 175static struct clk_div_mult_table div4_div_mult_table = { 176 .divisors = divisors, 177 .nr_divisors = ARRAY_SIZE(divisors), 178}; 179 180static struct clk_div4_table div4_table = { 181 .div_mult_table = &div4_div_mult_table, 182 .kick = div4_kick, 183}; 184 185enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_CSIR, 186 DIV4_ZTR, DIV4_ZT, DIV4_Z, DIV4_HP, 187 DIV4_ZS, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_NR }; 188 189#define DIV4(_reg, _bit, _mask, _flags) \ 190 SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags) 191 192static struct clk div4_clks[DIV4_NR] = { 193 [DIV4_I] = DIV4(RTFRQCR, 20, 0x6fff, CLK_ENABLE_ON_INIT), 194 [DIV4_ZG] = DIV4(RTFRQCR, 16, 0x6fff, CLK_ENABLE_ON_INIT), 195 [DIV4_B] = DIV4(RTFRQCR, 8, 0x6fff, CLK_ENABLE_ON_INIT), 196 [DIV4_M1] = DIV4(RTFRQCR, 4, 0x6fff, CLK_ENABLE_ON_INIT), 197 [DIV4_CSIR] = DIV4(RTFRQCR, 0, 0x6fff, 0), 198 [DIV4_ZTR] = DIV4(SYFRQCR, 20, 0x6fff, 0), 199 [DIV4_ZT] = DIV4(SYFRQCR, 16, 0x6fff, 0), 200 [DIV4_Z] = DIV4(SYFRQCR, 12, 0x6fff, 0), 201 [DIV4_HP] = DIV4(SYFRQCR, 4, 0x6fff, 0), 202 [DIV4_ZS] = DIV4(CMFRQCR, 12, 0x6fff, 0), 203 [DIV4_ZB] = DIV4(CMFRQCR, 8, 0x6fff, 0), 204 [DIV4_ZB3] = DIV4(CMFRQCR, 4, 0x6fff, 0), 205 [DIV4_CP] = DIV4(CMFRQCR, 0, 0x6fff, 0), 206}; 207 208enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO, 209 DIV6_FSI, DIV6_SUB, DIV6_SPU, DIV6_MSU, DIV6_MVI3, DIV6_HDMI, 210 DIV6_MF1, DIV6_MF2, DIV6_DSIT, DIV6_DSIP, 211 DIV6_NR }; 212 213static struct clk div6_clks[] = { 214 [DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0), 215 [DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0), 216 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0), 217 [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0), 218 [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0), 219 [DIV6_FSI] = SH_CLK_DIV6(&pllc1_div2_clk, FSICKCR, 0), 220 [DIV6_SUB] = SH_CLK_DIV6(&sh7377_extal2_clk, SUBUSBCKCR, 0), 221 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0), 222 [DIV6_MSU] = SH_CLK_DIV6(&pllc1_div2_clk, MSUCKCR, 0), 223 [DIV6_MVI3] = SH_CLK_DIV6(&pllc1_div2_clk, MVI3CKCR, 0), 224 [DIV6_HDMI] = SH_CLK_DIV6(&pllc1_div2_clk, HDMICKCR, 0), 225 [DIV6_MF1] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK1CR, 0), 226 [DIV6_MF2] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK2CR, 0), 227 [DIV6_DSIT] = SH_CLK_DIV6(&pllc1_div2_clk, DSITCKCR, 0), 228 [DIV6_DSIP] = SH_CLK_DIV6(&pllc1_div2_clk, DSIPCKCR, 0), 229}; 230 231enum { MSTP001, 232 MSTP131, MSTP130, MSTP129, MSTP128, MSTP116, MSTP106, MSTP101, 233 MSTP223, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, 234 MSTP331, MSTP329, MSTP325, MSTP323, MSTP322, 235 MSTP315, MSTP314, MSTP313, 236 MSTP403, 237 MSTP_NR }; 238 239#define MSTP(_parent, _reg, _bit, _flags) \ 240 SH_CLK_MSTP32(_parent, _reg, _bit, _flags) 241 242static struct clk mstp_clks[] = { 243 [MSTP001] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 1, 0), /* IIC2 */ 244 [MSTP131] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 31, 0), /* VEU3 */ 245 [MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */ 246 [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */ 247 [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */ 248 [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ 249 [MSTP106] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 6, 0), /* JPU */ 250 [MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */ 251 [MSTP223] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR2, 23, 0), /* SPU2 */ 252 [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ 253 [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ 254 [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ 255 [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */ 256 [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */ 257 [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ 258 [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ 259 [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */ 260 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ 261 [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IRDA */ 262 [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ 263 [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */ 264 [MSTP315] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 15, 0), /* FLCTL */ 265 [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ 266 [MSTP313] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */ 267 [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ 268}; 269 270#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } 271#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } 272 273static struct clk_lookup lookups[] = { 274 /* main clocks */ 275 CLKDEV_CON_ID("r_clk", &r_clk), 276 CLKDEV_CON_ID("extalc1", &sh7377_extalc1_clk), 277 CLKDEV_CON_ID("extal2", &sh7377_extal2_clk), 278 CLKDEV_CON_ID("extalc1_div2_clk", &extalc1_div2_clk), 279 CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk), 280 CLKDEV_CON_ID("extal2_div4_clk", &extal2_div4_clk), 281 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), 282 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), 283 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk), 284 285 /* DIV4 clocks */ 286 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), 287 CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]), 288 CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]), 289 CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]), 290 CLKDEV_CON_ID("csir_clk", &div4_clks[DIV4_CSIR]), 291 CLKDEV_CON_ID("ztr_clk", &div4_clks[DIV4_ZTR]), 292 CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]), 293 CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]), 294 CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]), 295 CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]), 296 CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]), 297 CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]), 298 CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]), 299 300 /* DIV6 clocks */ 301 CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]), 302 CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]), 303 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), 304 CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]), 305 CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]), 306 CLKDEV_CON_ID("fsi_clk", &div6_clks[DIV6_FSI]), 307 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), 308 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), 309 CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]), 310 CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]), 311 CLKDEV_CON_ID("hdmi_clk", &div6_clks[DIV6_HDMI]), 312 CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]), 313 CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]), 314 CLKDEV_CON_ID("dsit_clk", &div6_clks[DIV6_DSIT]), 315 CLKDEV_CON_ID("dsip_clk", &div6_clks[DIV6_DSIP]), 316 317 /* MSTP32 clocks */ 318 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */ 319 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */ 320 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */ 321 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */ 322 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */ 323 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ 324 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */ 325 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */ 326 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[MSTP223]), /* SPU2DSP0 */ 327 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[MSTP223]), /* SPU2DSP1 */ 328 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */ 329 CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP206]), /* SCIFB */ 330 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */ 331 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */ 332 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */ 333 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ 334 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ 335 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ 336 CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */ 337 CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */ 338 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ 339 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */ 340 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USBHS */ 341 CLKDEV_DEV_ID("sh_flctl", &mstp_clks[MSTP315]), /* FLCTL */ 342 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ 343 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ 344 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ 345}; 346 347void __init sh7377_clock_init(void) 348{ 349 int k, ret = 0; 350 351 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) 352 ret = clk_register(main_clks[k]); 353 354 if (!ret) 355 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); 356 357 if (!ret) 358 ret = sh_clk_div6_register(div6_clks, DIV6_NR); 359 360 if (!ret) 361 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); 362 363 clkdev_add_table(lookups, ARRAY_SIZE(lookups)); 364 365 if (!ret) 366 clk_init(); 367 else 368 panic("failed to setup sh7377 clocks\n"); 369} 370