linux/arch/arm/plat-s3c64xx/clock.c
<<
>>
Prefs
   1/* linux/arch/arm/plat-s3c64xx/clock.c
   2 *
   3 * Copyright 2008 Openmoko, Inc.
   4 * Copyright 2008 Simtec Electronics
   5 *      Ben Dooks <ben@simtec.co.uk>
   6 *      http://armlinux.simtec.co.uk/
   7 *
   8 * S3C64XX Base clock support
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13*/
  14
  15#include <linux/init.h>
  16#include <linux/module.h>
  17#include <linux/interrupt.h>
  18#include <linux/ioport.h>
  19#include <linux/io.h>
  20
  21#include <mach/hardware.h>
  22#include <mach/map.h>
  23
  24#include <plat/regs-sys.h>
  25#include <plat/regs-clock.h>
  26#include <plat/cpu.h>
  27#include <plat/devs.h>
  28#include <plat/clock.h>
  29
  30struct clk clk_h2 = {
  31        .name           = "hclk2",
  32        .id             = -1,
  33        .rate           = 0,
  34};
  35
  36struct clk clk_27m = {
  37        .name           = "clk_27m",
  38        .id             = -1,
  39        .rate           = 27000000,
  40};
  41
  42static int clk_48m_ctrl(struct clk *clk, int enable)
  43{
  44        unsigned long flags;
  45        u32 val;
  46
  47        /* can't rely on clock lock, this register has other usages */
  48        local_irq_save(flags);
  49
  50        val = __raw_readl(S3C64XX_OTHERS);
  51        if (enable)
  52                val |= S3C64XX_OTHERS_USBMASK;
  53        else
  54                val &= ~S3C64XX_OTHERS_USBMASK;
  55
  56        __raw_writel(val, S3C64XX_OTHERS);
  57        local_irq_restore(flags);
  58
  59        return 0;
  60}
  61
  62struct clk clk_48m = {
  63        .name           = "clk_48m",
  64        .id             = -1,
  65        .rate           = 48000000,
  66        .enable         = clk_48m_ctrl,
  67};
  68
  69static int inline s3c64xx_gate(void __iomem *reg,
  70                                struct clk *clk,
  71                                int enable)
  72{
  73        unsigned int ctrlbit = clk->ctrlbit;
  74        u32 con;
  75
  76        con = __raw_readl(reg);
  77
  78        if (enable)
  79                con |= ctrlbit;
  80        else
  81                con &= ~ctrlbit;
  82
  83        __raw_writel(con, reg);
  84        return 0;
  85}
  86
  87static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
  88{
  89        return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
  90}
  91
  92static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
  93{
  94        return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
  95}
  96
  97int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
  98{
  99        return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
 100}
 101
 102static struct clk init_clocks_disable[] = {
 103        {
 104                .name           = "nand",
 105                .id             = -1,
 106                .parent         = &clk_h,
 107        }, {
 108                .name           = "adc",
 109                .id             = -1,
 110                .parent         = &clk_p,
 111                .enable         = s3c64xx_pclk_ctrl,
 112                .ctrlbit        = S3C_CLKCON_PCLK_TSADC,
 113        }, {
 114                .name           = "i2c",
 115                .id             = -1,
 116                .parent         = &clk_p,
 117                .enable         = s3c64xx_pclk_ctrl,
 118                .ctrlbit        = S3C_CLKCON_PCLK_IIC,
 119        }, {
 120                .name           = "iis",
 121                .id             = 0,
 122                .parent         = &clk_p,
 123                .enable         = s3c64xx_pclk_ctrl,
 124                .ctrlbit        = S3C_CLKCON_PCLK_IIS0,
 125        }, {
 126                .name           = "iis",
 127                .id             = 1,
 128                .parent         = &clk_p,
 129                .enable         = s3c64xx_pclk_ctrl,
 130                .ctrlbit        = S3C_CLKCON_PCLK_IIS1,
 131        }, {
 132                .name           = "spi",
 133                .id             = 0,
 134                .parent         = &clk_p,
 135                .enable         = s3c64xx_pclk_ctrl,
 136                .ctrlbit        = S3C_CLKCON_PCLK_SPI0,
 137        }, {
 138                .name           = "spi",
 139                .id             = 1,
 140                .parent         = &clk_p,
 141                .enable         = s3c64xx_pclk_ctrl,
 142                .ctrlbit        = S3C_CLKCON_PCLK_SPI1,
 143        }, {
 144                .name           = "48m",
 145                .id             = 0,
 146                .parent         = &clk_48m,
 147                .enable         = s3c64xx_sclk_ctrl,
 148                .ctrlbit        = S3C_CLKCON_SCLK_MMC0_48,
 149        }, {
 150                .name           = "48m",
 151                .id             = 1,
 152                .parent         = &clk_48m,
 153                .enable         = s3c64xx_sclk_ctrl,
 154                .ctrlbit        = S3C_CLKCON_SCLK_MMC1_48,
 155        }, {
 156                .name           = "48m",
 157                .id             = 2,
 158                .parent         = &clk_48m,
 159                .enable         = s3c64xx_sclk_ctrl,
 160                .ctrlbit        = S3C_CLKCON_SCLK_MMC2_48,
 161        }, {
 162                .name           = "dma0",
 163                .id             = -1,
 164                .parent         = &clk_h,
 165                .enable         = s3c64xx_hclk_ctrl,
 166                .ctrlbit        = S3C_CLKCON_HCLK_DMA0,
 167        }, {
 168                .name           = "dma1",
 169                .id             = -1,
 170                .parent         = &clk_h,
 171                .enable         = s3c64xx_hclk_ctrl,
 172                .ctrlbit        = S3C_CLKCON_HCLK_DMA1,
 173        },
 174};
 175
 176static struct clk init_clocks[] = {
 177        {
 178                .name           = "lcd",
 179                .id             = -1,
 180                .parent         = &clk_h,
 181                .enable         = s3c64xx_hclk_ctrl,
 182                .ctrlbit        = S3C_CLKCON_HCLK_LCD,
 183        }, {
 184                .name           = "gpio",
 185                .id             = -1,
 186                .parent         = &clk_p,
 187                .enable         = s3c64xx_pclk_ctrl,
 188                .ctrlbit        = S3C_CLKCON_PCLK_GPIO,
 189        }, {
 190                .name           = "usb-host",
 191                .id             = -1,
 192                .parent         = &clk_h,
 193                .enable         = s3c64xx_hclk_ctrl,
 194                .ctrlbit        = S3C_CLKCON_HCLK_UHOST,
 195        }, {
 196                .name           = "hsmmc",
 197                .id             = 0,
 198                .parent         = &clk_h,
 199                .enable         = s3c64xx_hclk_ctrl,
 200                .ctrlbit        = S3C_CLKCON_HCLK_HSMMC0,
 201        }, {
 202                .name           = "hsmmc",
 203                .id             = 1,
 204                .parent         = &clk_h,
 205                .enable         = s3c64xx_hclk_ctrl,
 206                .ctrlbit        = S3C_CLKCON_HCLK_HSMMC1,
 207        }, {
 208                .name           = "hsmmc",
 209                .id             = 2,
 210                .parent         = &clk_h,
 211                .enable         = s3c64xx_hclk_ctrl,
 212                .ctrlbit        = S3C_CLKCON_HCLK_HSMMC2,
 213        }, {
 214                .name           = "timers",
 215                .id             = -1,
 216                .parent         = &clk_p,
 217                .enable         = s3c64xx_pclk_ctrl,
 218                .ctrlbit        = S3C_CLKCON_PCLK_PWM,
 219        }, {
 220                .name           = "uart",
 221                .id             = 0,
 222                .parent         = &clk_p,
 223                .enable         = s3c64xx_pclk_ctrl,
 224                .ctrlbit        = S3C_CLKCON_PCLK_UART0,
 225        }, {
 226                .name           = "uart",
 227                .id             = 1,
 228                .parent         = &clk_p,
 229                .enable         = s3c64xx_pclk_ctrl,
 230                .ctrlbit        = S3C_CLKCON_PCLK_UART1,
 231        }, {
 232                .name           = "uart",
 233                .id             = 2,
 234                .parent         = &clk_p,
 235                .enable         = s3c64xx_pclk_ctrl,
 236                .ctrlbit        = S3C_CLKCON_PCLK_UART2,
 237        }, {
 238                .name           = "uart",
 239                .id             = 3,
 240                .parent         = &clk_p,
 241                .enable         = s3c64xx_pclk_ctrl,
 242                .ctrlbit        = S3C_CLKCON_PCLK_UART3,
 243        }, {
 244                .name           = "rtc",
 245                .id             = -1,
 246                .parent         = &clk_p,
 247                .enable         = s3c64xx_pclk_ctrl,
 248                .ctrlbit        = S3C_CLKCON_PCLK_RTC,
 249        }, {
 250                .name           = "watchdog",
 251                .id             = -1,
 252                .parent         = &clk_p,
 253                .ctrlbit        = S3C_CLKCON_PCLK_WDT,
 254        }, {
 255                .name           = "ac97",
 256                .id             = -1,
 257                .parent         = &clk_p,
 258                .ctrlbit        = S3C_CLKCON_PCLK_AC97,
 259        }
 260};
 261
 262static struct clk *clks[] __initdata = {
 263        &clk_ext,
 264        &clk_epll,
 265        &clk_27m,
 266        &clk_48m,
 267        &clk_h2,
 268};
 269
 270void __init s3c64xx_register_clocks(void)
 271{
 272        struct clk *clkp;
 273        int ret;
 274        int ptr;
 275
 276        s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
 277
 278        clkp = init_clocks;
 279        for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
 280                ret = s3c24xx_register_clock(clkp);
 281                if (ret < 0) {
 282                        printk(KERN_ERR "Failed to register clock %s (%d)\n",
 283                               clkp->name, ret);
 284                }
 285        }
 286
 287        clkp = init_clocks_disable;
 288        for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
 289
 290                ret = s3c24xx_register_clock(clkp);
 291                if (ret < 0) {
 292                        printk(KERN_ERR "Failed to register clock %s (%d)\n",
 293                               clkp->name, ret);
 294                }
 295
 296                (clkp->enable)(clkp, 0);
 297        }
 298
 299        s3c_pwmclk_init();
 300}
 301
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.