diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2012-11-12 15:59:00 -0500 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2012-11-12 15:59:00 -0500 |
| commit | 94c78a55b8404396e3b8d9463c1b5c562664c893 (patch) | |
| tree | 4fc4371853788170e9e9523807cb8385df3acf40 /drivers/sh | |
| parent | fd2e1dd7bb2e4f19e063aff9194b795be8510464 (diff) | |
| parent | 2944628607f76e4755660cd710f22a4748ef88d8 (diff) | |
Merge branches 'depends/asoc', 'renesas/boards', 'renesas/soc' and 'renesas/soc2' into next/boards2
These are all dependencies for the next set of renesas shmobile board
changes.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/sh')
| -rw-r--r-- | drivers/sh/clk/cpg.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 07e9fb4f804..b3dc44146ca 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c | |||
| @@ -361,3 +361,89 @@ int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, | |||
| 361 | return sh_clk_div_register_ops(clks, nr, table, | 361 | return sh_clk_div_register_ops(clks, nr, table, |
| 362 | &sh_clk_div4_reparent_clk_ops); | 362 | &sh_clk_div4_reparent_clk_ops); |
| 363 | } | 363 | } |
| 364 | |||
| 365 | /* FSI-DIV */ | ||
| 366 | static unsigned long fsidiv_recalc(struct clk *clk) | ||
| 367 | { | ||
| 368 | u32 value; | ||
| 369 | |||
| 370 | value = __raw_readl(clk->mapping->base); | ||
| 371 | |||
| 372 | value >>= 16; | ||
| 373 | if (value < 2) | ||
| 374 | return clk->parent->rate; | ||
| 375 | |||
| 376 | return clk->parent->rate / value; | ||
| 377 | } | ||
| 378 | |||
| 379 | static long fsidiv_round_rate(struct clk *clk, unsigned long rate) | ||
| 380 | { | ||
| 381 | return clk_rate_div_range_round(clk, 1, 0xffff, rate); | ||
| 382 | } | ||
| 383 | |||
| 384 | static void fsidiv_disable(struct clk *clk) | ||
| 385 | { | ||
| 386 | __raw_writel(0, clk->mapping->base); | ||
| 387 | } | ||
| 388 | |||
| 389 | static int fsidiv_enable(struct clk *clk) | ||
| 390 | { | ||
| 391 | u32 value; | ||
| 392 | |||
| 393 | value = __raw_readl(clk->mapping->base) >> 16; | ||
| 394 | if (value < 2) | ||
| 395 | return 0; | ||
| 396 | |||
| 397 | __raw_writel((value << 16) | 0x3, clk->mapping->base); | ||
| 398 | |||
| 399 | return 0; | ||
| 400 | } | ||
| 401 | |||
| 402 | static int fsidiv_set_rate(struct clk *clk, unsigned long rate) | ||
| 403 | { | ||
| 404 | u32 val; | ||
| 405 | int idx; | ||
| 406 | |||
| 407 | idx = (clk->parent->rate / rate) & 0xffff; | ||
| 408 | if (idx < 2) | ||
| 409 | __raw_writel(0, clk->mapping->base); | ||
| 410 | else | ||
| 411 | __raw_writel(idx << 16, clk->mapping->base); | ||
| 412 | |||
| 413 | return 0; | ||
| 414 | } | ||
| 415 | |||
| 416 | static struct sh_clk_ops fsidiv_clk_ops = { | ||
| 417 | .recalc = fsidiv_recalc, | ||
| 418 | .round_rate = fsidiv_round_rate, | ||
| 419 | .set_rate = fsidiv_set_rate, | ||
| 420 | .enable = fsidiv_enable, | ||
| 421 | .disable = fsidiv_disable, | ||
| 422 | }; | ||
| 423 | |||
| 424 | int __init sh_clk_fsidiv_register(struct clk *clks, int nr) | ||
| 425 | { | ||
| 426 | struct clk_mapping *map; | ||
| 427 | int i; | ||
| 428 | |||
| 429 | for (i = 0; i < nr; i++) { | ||
| 430 | |||
| 431 | map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL); | ||
| 432 | if (!map) { | ||
| 433 | pr_err("%s: unable to alloc memory\n", __func__); | ||
| 434 | return -ENOMEM; | ||
| 435 | } | ||
| 436 | |||
| 437 | /* clks[i].enable_reg came from SH_CLK_FSIDIV() */ | ||
| 438 | map->phys = (phys_addr_t)clks[i].enable_reg; | ||
| 439 | map->len = 8; | ||
| 440 | |||
| 441 | clks[i].enable_reg = 0; /* remove .enable_reg */ | ||
| 442 | clks[i].ops = &fsidiv_clk_ops; | ||
| 443 | clks[i].mapping = map; | ||
| 444 | |||
| 445 | clk_register(&clks[i]); | ||
| 446 | } | ||
| 447 | |||
| 448 | return 0; | ||
| 449 | } | ||
