免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1112 | 回复: 0
打印 上一主题 下一主题

2440 clock [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-04 16:52 |只看该作者 |倒序浏览

[/url]

static void __init smdk2440_map_io(void)
{
       s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
       s3c24xx_init_clocks(0);
       s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}


Arm/plat-s3c24xx/cpu.c
void __init s3c24xx_init_clocks(int xtal)
{
       if (xtal == 0)
              xtal = 12*1000*1000;

       if (cpu == NULL)
              panic("s3c24xx_init_clocks: no cpu setup?\n");

       if (cpu->init_clocks == NULL)
              panic("s3c24xx_init_clocks: cpu has no clock init\n");
       else
              (cpu->init_clocks)(xtal);
}

static struct cpu_table cpu_ids[] __initdata = {
       {
              .idcode           = 0x32410000,
              .idmask          = 0xffffffff,
              .map_io          = s3c2410_map_io,
              .init_clocks     = s3c2410_init_clocks,
              .init_uarts       = s3c2410_init_uarts,
              .init         = s3c2410_init,
              .name             = name_s3c2410
       },
       {
              .idcode           = 0x32410002,
              .idmask          = 0xffffffff,
              .map_io          = s3c2410_map_io,
              .init_clocks     = s3c2410_init_clocks,
              .init_uarts       = s3c2410_init_uarts,
              .init         = s3c2410_init,
              .name             = name_s3c2410a
       },
       {
              .idcode           = 0x32440000,
              .idmask          = 0xffffffff,
              .map_io          = s3c244x_map_io,
              .init_clocks    = s3c244x_init_clocks,
              .init_uarts       = s3c244x_init_uarts,
              .init         = s3c2440_init,
              .name             = name_s3c2440
       },
};

Arm/plat-s3c24xx/s3c244x.c
void __init s3c244x_init_clocks(int xtal)
{
       unsigned long clkdiv;
       unsigned long camdiv;
       unsigned long hclk, fclk, pclk;
       int hdiv = 1;
   
       /* now we've got our machine bits initialised, work out what
        * clocks we've got */

       unsigned long delay=0;
    __raw_writel(__raw_readl(S3C2410_UPLLCON),S3C2410_UPLLCON);
    while(delay
   
    delay=0;
   
    __raw_writel(S3C2410_PLLVAL(125,1,1),S3C2410_MPLLCON);
    while(delay
   
       fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;

       clkdiv = __raw_readl(S3C2410_CLKDIVN);
       camdiv = __raw_readl(S3C2440_CAMDIVN);

       /* work out clock scalings */

       switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
       case S3C2440_CLKDIVN_HDIVN_1:
              hdiv = 1;
              break;

       case S3C2440_CLKDIVN_HDIVN_2:
              hdiv = 2;
              break;

       case S3C2440_CLKDIVN_HDIVN_4_8:
              hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
              break;

       case S3C2440_CLKDIVN_HDIVN_3_6:
              hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
              break;
       }

       hclk = fclk / hdiv;
       pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);

       /* print brief summary of clocks, etc */

       printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
              print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));

       /* initialise the clocks here, to allow other things like the
        * console to use them, and to add new ones after the initialisation
        */

       s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
       s3c2410_baseclk_add();
}
Arm/plat-s3c24xx/clock.c

/* base clocks */

struct clk clk_xtal = {
       .name             = "xtal",
       .id           = -1,
       .rate        = 0,
       .parent           = NULL,
       .ctrlbit     = 0,
};

struct clk clk_mpll = {
       .name             = "mpll",
       .id           = -1,
};

struct clk clk_upll = {
       .name             = "upll",
       .id           = -1,
       .parent           = NULL,
       .ctrlbit     = 0,
};

struct clk clk_f = {
       .name             = "fclk",
       .id           = -1,
       .rate        = 0,
       .parent           = &clk_mpll,
       .ctrlbit     = 0,
};

struct clk clk_h = {
       .name             = "hclk",
       .id           = -1,
       .rate        = 0,
       .parent           = NULL,
       .ctrlbit     = 0,
};

struct clk clk_p = {
       .name             = "pclk",
       .id           = -1,
       .rate        = 0,
       .parent           = NULL,
       .ctrlbit     = 0,
};

struct clk clk_usb_bus = {
       .name             = "usb-bus",
       .id           = -1,
       .rate        = 0,
       .parent           = &clk_upll,
};

int s3c24xx_register_clock(struct clk *clk)
{
       clk->owner = THIS_MODULE;

       if (clk->enable == NULL)
              clk->enable = clk_null_enable;

       /* add to the list of available clocks */

       mutex_lock(&clocks_mutex);
       list_add(&clk->list, &clocks);
       mutex_unlock(&clocks_mutex);

       return 0;
}
int __init s3c24xx_setup_clocks(unsigned long xtal,
                      unsigned long fclk,
                      unsigned long hclk,
                      unsigned long pclk)
{
       printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");

       /* initialise the main system clocks */

       clk_xtal.rate = xtal;
       clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);

       clk_mpll.rate = fclk;
       clk_h.rate = hclk;
       clk_p.rate = pclk;
       clk_f.rate = fclk;

       /* assume uart clocks are correctly setup */

       /* register our clocks */

       if (s3c24xx_register_clock(&clk_xtal)
              printk(KERN_ERR "failed to register master xtal\n");

       if (s3c24xx_register_clock(&clk_mpll)
              printk(KERN_ERR "failed to register mpll clock\n");

       if (s3c24xx_register_clock(&clk_upll)
              printk(KERN_ERR "failed to register upll clock\n");

       if (s3c24xx_register_clock(&clk_f)
              printk(KERN_ERR "failed to register cpu fclk\n");

       if (s3c24xx_register_clock(&clk_h)
              printk(KERN_ERR "failed to register cpu hclk\n");

       if (s3c24xx_register_clock(&clk_p)
              printk(KERN_ERR "failed to register cpu pclk\n");

       return 0;
}
Arm/mack-s3c2410/clock.c
int s3c2410_clkcon_enable(struct clk *clk, int enable)
{
       unsigned int clocks = clk->ctrlbit;
       unsigned long clkcon;

       clkcon = __raw_readl(S3C2410_CLKCON);

       if (enable)
              clkcon |= clocks;
       else
              clkcon &= ~clocks;

       /* ensure none of the special function bits set */
       clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);

       __raw_writel(clkcon, S3C2410_CLKCON);

       return 0;
}

static int s3c2410_upll_enable(struct clk *clk, int enable)
{
       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
       unsigned long orig = clkslow;

       if (enable)
              clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
       else
              clkslow |= S3C2410_CLKSLOW_UCLK_OFF;

       __raw_writel(clkslow, S3C2410_CLKSLOW);

       /* if we started the UPLL, then allow to settle */

       if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
              udelay(200);

       return 0;
}

/* standard clock definitions */

static struct clk init_clocks_disable[] = {
       {
              .name             = "nand",
              .id           = -1,
              .parent           = &clk_h,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_NAND,
       }, {
              .name             = "sdi",
              .id           = -1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_SDI,
       }, {
              .name             = "adc",
              .id           = -1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_ADC,
       }, {
              .name             = "i2c",
              .id           = -1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_IIC,
       }, {
              .name             = "iis",
              .id           = -1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_IIS,
       }, {
              .name             = "spi",
              .id           = -1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_SPI,
       }
};

static struct clk init_clocks[] = {
       {
              .name             = "lcd",
              .id           = -1,
              .parent           = &clk_h,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_LCDC,
       }, {
              .name             = "gpio",
              .id           = -1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_GPIO,
       }, {
              .name             = "usb-host",
              .id           = -1,
              .parent           = &clk_h,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_USBH,
       }, {
              .name             = "usb-device",
              .id           = -1,
              .parent           = &clk_h,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_USBD,
       }, {
              .name             = "timers",
              .id           = -1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_PWMT,
       }, {
              .name             = "uart",
              .id           = 0,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_UART0,
       }, {
              .name             = "uart",
              .id           = 1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_UART1,
       }, {
              .name             = "uart",
              .id           = 2,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_UART2,
       }, {
              .name             = "rtc",
              .id           = -1,
              .parent           = &clk_p,
              .enable           = s3c2410_clkcon_enable,
              .ctrlbit     = S3C2410_CLKCON_RTC,
       }, {
              .name             = "watchdog",
              .id           = -1,
              .parent           = &clk_p,
              .ctrlbit     = 0,
       }, {
              .name             = "usb-bus-host",
              .id           = -1,
              .parent           = &clk_usb_bus,
       }, {
              .name             = "usb-bus-gadget",
              .id           = -1,
              .parent           = &clk_usb_bus,
       },
};

/* s3c2410_baseclk_add()
*
* Add all the clocks used by the s3c2410 or compatible CPUs
* such as the S3C2440 and S3C2442.
*
* We cannot use a system device as we are needed before any
* of the init-calls that initialise the devices are actually
* done.
*/

int __init s3c2410_baseclk_add(void)
{
       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
       unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
       struct clk *clkp;
       struct clk *xtal;
       int ret;
       int ptr;

       clk_upll.enable = s3c2410_upll_enable;

       if (s3c24xx_register_clock(&clk_usb_bus)
              printk(KERN_ERR "failed to register usb bus clock\n");

       /* register clocks from clock array */

       clkp = init_clocks;
       for (ptr = 0; ptr
              /* ensure that we note the clock state */

              clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;

              ret = s3c24xx_register_clock(clkp);
              if (ret
                     printk(KERN_ERR "Failed to register clock %s (%d)\n",
                            clkp->name, ret);
              }
       }

       /* We must be careful disabling the clocks we are not intending to
        * be using at boot time, as subsystems such as the LCD which do
        * their own DMA requests to the bus can cause the system to lockup
        * if they where in the middle of requesting bus access.
        *
        * Disabling the LCD clock if the LCD is active is very dangerous,
        * and therefore the bootloader should be careful to not enable
        * the LCD clock if it is not needed.
       */

       /* install (and disable) the clocks we do not need immediately */

       clkp = init_clocks_disable;
       for (ptr = 0; ptr

              ret = s3c24xx_register_clock(clkp);
              if (ret
                     printk(KERN_ERR "Failed to register clock %s (%d)\n",
                            clkp->name, ret);
              }

              s3c2410_clkcon_enable(clkp, 0);
       }

       /* show the clock-slow value */

       xtal = clk_get(NULL, "xtal");

       printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
              print_mhz(clk_get_rate(xtal) /
                      ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
              (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
              (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
              (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");

       return 0;
}
启动信息
CPU S3C2440A (id 0x32440001)
S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz
S3C24XX Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on



本文来自ChinaUnix博客,如果查看原文请点:[url]http://blog.chinaunix.net/u3/96265/showart_2139179.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP