LPC3250的时钟介绍


一、相关概念:

SYSCLK:系统时钟。它有两个来源,OSC_CLK(主振荡器时钟)和RTC_CLK(RTC时钟)。选择那个时钟源取决于SYSCLK_CTRL的控制。

ARM_CLK:在SYSCLK后有一个HCLKPLL用于将SYSCLK转换成ARM_CLK。ARM_CLK用于ARMCPU,MSSDCLK。在寄存器HCLK_CTRL中,ARM_CLK将会被分频成HCLK,PCLK和DDRAM_CLK。

HCLK:AHB总线时钟。用于AHB矩阵和USBAHB、AHB从机、FAB从机和APB从机

P_CLK:外设时钟。

CLK48MHz:USB48MHz时钟——基于OSC_CLK。

DDRAM_CLK:DDR SDRAM时钟

MSSDCLK:SD卡时钟。

二、clock.c中有关函数介绍

clk结构体定义

struct clk {

     structlist_head node;

     struct module*owner;

     const char*name;           /* Clock name */

     struct clk*parent;           /* Parent clock */

     u32 rate;                 /* Rate in Hz for the clock (0= disabled) */

     u32 flags;                /* Setup flags */

     s8 usecount;                   /* Number of users of thisclock */

     /* Requiredfunctions per clock */

     int(*set_rate) (struct clk *, u32);

     u32(*round_rate) (struct clk *, u32);

     int (*enable)(struct clk *clk, int);

     /* Optionalfunctions per clock */

     int(*set_parent) (struct clk * clk, struct clk * parent);

     u32(*get_rate) (struct clk *clk);

     /* Registerand mask for enablings/disabling the clock, only

        used when the CLK_FLAG_ST_ENAB flag is set*/

     u32enable_reg;               /* Register toenable and disable associated clock */

     u32enable_mask;            /* Or mask forenable, AND ~mask for disable */

};

 

 

static void clk_upate_children(struct clk *clk)

{

     local_update_armpll_rate();

     local_update_usbpll_rate();

}

这个函数作用就是根据输入的系统时钟SYSCLK和相关寄存器的设置来获得clk_armpll.rate和clk_usbpll.rate 的成员值。当然后面还有函数会根据这个值去设置相关寄存器。

 

local_update_armpll_rate()和local_update_usbpll_rate()实现过程相仿。只追踪第一个函数的实现过程。

static void local_update_armpll_rate(void)

{

     u32 clkin,pllreg;

 

     /* Get PLLinput clock rate */

获得系统时钟速率

     clkin =clk_armpll.parent->rate;

     /* Get ARMHCLKPLL register */

     pllreg =__raw_readl(CLKPWR_HCLKPLL_CTRL(CLKPWR_IOBASE)) & 0x1FFFF;

根据系统时钟速度,和一个配置项获得ARM_CLK的速率。

     clk_armpll.rate= local_clk_get_pllrate_from_reg(clkin, pllreg);

}

 

 

static u32 local_clk_find_pll_cfg(u32 pllin_freq,

                           u32 target_freq,

                          CLKPWR_HCLK_PLL_SETUP_T *pllsetup)

 

这个函数作用是根据目前的pllin_freq和target_freq为设定pllsetup 。即如果按照pllsetup的项去配置相关寄存器,即可实现由pllin_freq 到target_freq的目标。而函数

static u32local_clk_hclkpll_setup(CLKPWR_HCLK_PLL_SETUP_T *pHCLKPllSetup)就是做这个事情的。

 

static int local_armpll_set_rate(struct clk *clk, u32rate)封装上面介绍的两个函数。这函数很简单,给定一个时钟,然后再给定一个要设置的速率。就能实现目标。不看其具体的实现就知道,它先要根据rate和clk->parent.rate为自己找到一个合适的pllsetup,然后再将任务传给local_clk_hclkpll_setup()去实现。

 

static struct clk *chip_clks[] = {

     &osc_32KHz,

     &osc_pll397,

     &osc_main,

     &clk_sys,

     &clk_armpll,

     &clk_hclk,

     &clk_pclk,

     &clk_usbpll,

     &clk_timer0,

     &clk_timer1,

     &clk_timer2,

     &clk_timer3,

     &clk_vfp9,

     &clk_dma,

#if defined (CONFIG_LPC32XX_WATCHDOG)

     &clk_wdt,

#endif

#if defined (CONFIG_MACH_LPC32XX_UART3_ENABLE)

     &clk_uart3,

#endif

#if defined (CONFIG_MACH_LPC32XX_UART4_ENABLE)

     &clk_uart4,

#endif

#if defined (CONFIG_MACH_LPC32XX_UART5_ENABLE)

     &clk_uart5,

#endif

#if defined (CONFIG_MACH_LPC32XX_UART6_ENABLE)

     &clk_uart6,

#endif

#if defined (CONFIG_MACH_LPC32XX_I2C0_ENABLE)

     &clk_i2c0,

#endif

#if defined (CONFIG_MACH_LPC32XX_I2C1_ENABLE)

     &clk_i2c1,

#endif

#if defined (CONFIG_MACH_LPC32XX_USBOTG_I2C_ENABLE)

     &clk_i2c2,

#endif

#if defined(CONFIG_SPI_LPC32XX)

#if defined(CONFIG_MACH_LPC32XX_SSP0_ENABLE)

     &clk_ssp0,

#endif

#if defined(CONFIG_MACH_LPC32XX_SSP1_ENABLE)

     &clk_ssp1,

#endif

#endif

#if defined(CONFIG_KEYBOARD_LPC32XX)

     &clk_kscan,

#endif

#if defined(CONFIG_MTD_NAND_SLC_LPC32XX)

     &clk_nand,

#endif

#if defined(CONFIG_SND_LPC3XXX_SOC_I2S)

     &clk_i2s0,

     &clk_i2s1,

#endif

#if defined (CONFIG_TOUCHSCREEN_LPC32XX)

     &clk_tsc,

#endif

#if defined (CONFIG_MMC_ARMMMCI)

     &clk_mmc,

#endif

#if defined (CONFIG_LPC32XX_MII)

     &clk_net,

#endif

#if defined (CONFIG_FB_ARMCLCD)

     &clk_lcd,

#endif

#if defined (CONFIG_USB_GADGET_LPC32XX)

     &clk_usbd,

#endif

};

这个结构体列出了lpc3250可能用到的所有时钟,而时钟的具体实现就是利用前面介绍的函数。

 

struct clk *local_clk_get(struct device *dev, const char*id)这个函数一般是会在id的位置传入一个时钟名称。然后该函数返回这个时钟的结构体。第一个参数没什么用处。

static int local_clk_enable(struct clk *clk)这个函数只是根据具体的时钟,来调用clk->enable成员方法。

struct clk *clk_get(struct device *dev, const char *id)是对struct clk *local_clk_get()函数的封装。只是中间添加了这么一项:在获取时钟结构体期间禁能了中断

int clk_is_sysclk_mainosc(void)判断系统时钟是否是从OSC_CLK(主振荡器时钟)获取。

最后的int __initclk_init(void)函数,分别注册了lpc3250的时钟,确定了系统时钟源。增加引用计数。虽然这个函数将时钟注册进了linux系统,但是这配置都还是默认的配置。ARM_CLK和OSC_CLK还是一样的。所以时钟在具体使用的时候,还要再具体配置。

 

 


你可能感兴趣的:(c,linux,timer,struct,Module,keyboard)