linux/arch/arm/plat-samsung/s5p-clock.c
<<
>>
Prefs
   1/*
   2 * Copyright 2009 Samsung Electronics Co., Ltd.
   3 *              http://www.samsung.com/
   4 *
   5 * S5P - Common clock support
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10*/
  11
  12#include <linux/init.h>
  13#include <linux/module.h>
  14#include <linux/kernel.h>
  15#include <linux/list.h>
  16#include <linux/errno.h>
  17#include <linux/err.h>
  18#include <linux/clk.h>
  19#include <linux/device.h>
  20#include <linux/io.h>
  21#include <asm/div64.h>
  22
  23#include <mach/regs-clock.h>
  24
  25#include <plat/clock.h>
  26#include <plat/clock-clksrc.h>
  27#include <plat/s5p-clock.h>
  28
  29/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
  30 * clk_ext_xtal_mux.
  31*/
  32struct clk clk_ext_xtal_mux = {
  33        .name           = "ext_xtal",
  34        .id             = -1,
  35};
  36
  37struct clk clk_xusbxti = {
  38        .name           = "xusbxti",
  39        .id             = -1,
  40        .rate           = 24000000,
  41};
  42
  43struct clk s5p_clk_27m = {
  44        .name           = "clk_27m",
  45        .id             = -1,
  46        .rate           = 27000000,
  47};
  48
  49/* 48MHz USB Phy clock output */
  50struct clk clk_48m = {
  51        .name           = "clk_48m",
  52        .id             = -1,
  53        .rate           = 48000000,
  54};
  55
  56/* APLL clock output
  57 * No need .ctrlbit, this is always on
  58*/
  59struct clk clk_fout_apll = {
  60        .name           = "fout_apll",
  61        .id             = -1,
  62};
  63
  64/* BPLL clock output */
  65
  66struct clk clk_fout_bpll = {
  67        .name           = "fout_bpll",
  68        .id             = -1,
  69};
  70
  71struct clk clk_fout_bpll_div2 = {
  72        .name           = "fout_bpll_div2",
  73        .id             = -1,
  74};
  75
  76/* CPLL clock output */
  77
  78struct clk clk_fout_cpll = {
  79        .name           = "fout_cpll",
  80        .id             = -1,
  81};
  82
  83/* MPLL clock output
  84 * No need .ctrlbit, this is always on
  85*/
  86struct clk clk_fout_mpll = {
  87        .name           = "fout_mpll",
  88        .id             = -1,
  89};
  90
  91struct clk clk_fout_mpll_div2 = {
  92        .name           = "fout_mpll_div2",
  93        .id             = -1,
  94};
  95
  96/* EPLL clock output */
  97struct clk clk_fout_epll = {
  98        .name           = "fout_epll",
  99        .id             = -1,
 100        .ctrlbit        = (1 << 31),
 101};
 102
 103/* DPLL clock output */
 104struct clk clk_fout_dpll = {
 105        .name           = "fout_dpll",
 106        .id             = -1,
 107        .ctrlbit        = (1 << 31),
 108};
 109
 110/* VPLL clock output */
 111struct clk clk_fout_vpll = {
 112        .name           = "fout_vpll",
 113        .id             = -1,
 114        .ctrlbit        = (1 << 31),
 115};
 116
 117/* Possible clock sources for APLL Mux */
 118static struct clk *clk_src_apll_list[] = {
 119        [0] = &clk_fin_apll,
 120        [1] = &clk_fout_apll,
 121};
 122
 123struct clksrc_sources clk_src_apll = {
 124        .sources        = clk_src_apll_list,
 125        .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
 126};
 127
 128/* Possible clock sources for BPLL Mux */
 129static struct clk *clk_src_bpll_list[] = {
 130        [0] = &clk_fin_bpll,
 131        [1] = &clk_fout_bpll,
 132};
 133
 134struct clksrc_sources clk_src_bpll = {
 135        .sources        = clk_src_bpll_list,
 136        .nr_sources     = ARRAY_SIZE(clk_src_bpll_list),
 137};
 138
 139static struct clk *clk_src_bpll_fout_list[] = {
 140        [0] = &clk_fout_bpll_div2,
 141        [1] = &clk_fout_bpll,
 142};
 143
 144struct clksrc_sources clk_src_bpll_fout = {
 145        .sources        = clk_src_bpll_fout_list,
 146        .nr_sources     = ARRAY_SIZE(clk_src_bpll_fout_list),
 147};
 148
 149/* Possible clock sources for CPLL Mux */
 150static struct clk *clk_src_cpll_list[] = {
 151        [0] = &clk_fin_cpll,
 152        [1] = &clk_fout_cpll,
 153};
 154
 155struct clksrc_sources clk_src_cpll = {
 156        .sources        = clk_src_cpll_list,
 157        .nr_sources     = ARRAY_SIZE(clk_src_cpll_list),
 158};
 159
 160/* Possible clock sources for MPLL Mux */
 161static struct clk *clk_src_mpll_list[] = {
 162        [0] = &clk_fin_mpll,
 163        [1] = &clk_fout_mpll,
 164};
 165
 166struct clksrc_sources clk_src_mpll = {
 167        .sources        = clk_src_mpll_list,
 168        .nr_sources     = ARRAY_SIZE(clk_src_mpll_list),
 169};
 170
 171static struct clk *clk_src_mpll_fout_list[] = {
 172        [0] = &clk_fout_mpll_div2,
 173        [1] = &clk_fout_mpll,
 174};
 175
 176struct clksrc_sources clk_src_mpll_fout = {
 177        .sources        = clk_src_mpll_fout_list,
 178        .nr_sources     = ARRAY_SIZE(clk_src_mpll_fout_list),
 179};
 180
 181/* Possible clock sources for EPLL Mux */
 182static struct clk *clk_src_epll_list[] = {
 183        [0] = &clk_fin_epll,
 184        [1] = &clk_fout_epll,
 185};
 186
 187struct clksrc_sources clk_src_epll = {
 188        .sources        = clk_src_epll_list,
 189        .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
 190};
 191
 192/* Possible clock sources for DPLL Mux */
 193static struct clk *clk_src_dpll_list[] = {
 194        [0] = &clk_fin_dpll,
 195        [1] = &clk_fout_dpll,
 196};
 197
 198struct clksrc_sources clk_src_dpll = {
 199        .sources        = clk_src_dpll_list,
 200        .nr_sources     = ARRAY_SIZE(clk_src_dpll_list),
 201};
 202
 203struct clk clk_vpll = {
 204        .name           = "vpll",
 205        .id             = -1,
 206};
 207
 208int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
 209{
 210        unsigned int ctrlbit = clk->ctrlbit;
 211        u32 con;
 212
 213        con = __raw_readl(reg);
 214        con = enable ? (con | ctrlbit) : (con & ~ctrlbit);
 215        __raw_writel(con, reg);
 216        return 0;
 217}
 218
 219int s5p_epll_enable(struct clk *clk, int enable)
 220{
 221        unsigned int ctrlbit = clk->ctrlbit;
 222        unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
 223
 224        if (enable)
 225                __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
 226        else
 227                __raw_writel(epll_con, S5P_EPLL_CON);
 228
 229        return 0;
 230}
 231
 232unsigned long s5p_epll_get_rate(struct clk *clk)
 233{
 234        return clk->rate;
 235}
 236
 237int s5p_spdif_set_rate(struct clk *clk, unsigned long rate)
 238{
 239        struct clk *pclk;
 240        int ret;
 241
 242        pclk = clk_get_parent(clk);
 243        if (IS_ERR(pclk))
 244                return -EINVAL;
 245
 246        ret = pclk->ops->set_rate(pclk, rate);
 247        clk_put(pclk);
 248
 249        return ret;
 250}
 251
 252unsigned long s5p_spdif_get_rate(struct clk *clk)
 253{
 254        struct clk *pclk;
 255        int rate;
 256
 257        pclk = clk_get_parent(clk);
 258        if (IS_ERR(pclk))
 259                return -EINVAL;
 260
 261        rate = pclk->ops->get_rate(pclk);
 262        clk_put(pclk);
 263
 264        return rate;
 265}
 266
 267struct clk_ops s5p_sclk_spdif_ops = {
 268        .set_rate       = s5p_spdif_set_rate,
 269        .get_rate       = s5p_spdif_get_rate,
 270};
 271
 272static struct clk *s5p_clks[] __initdata = {
 273        &clk_ext_xtal_mux,
 274        &clk_48m,
 275        &s5p_clk_27m,
 276        &clk_fout_apll,
 277        &clk_fout_mpll,
 278        &clk_fout_epll,
 279        &clk_fout_dpll,
 280        &clk_fout_vpll,
 281        &clk_vpll,
 282        &clk_xusbxti,
 283};
 284
 285void __init s5p_register_clocks(unsigned long xtal_freq)
 286{
 287        int ret;
 288
 289        clk_ext_xtal_mux.rate = xtal_freq;
 290
 291        ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks));
 292        if (ret > 0)
 293                printk(KERN_ERR "Failed to register s5p clocks\n");
 294}
 295