Linux内核时钟框架实例


今天想自己写个adc的驱动,发现不清楚系统各个模块的系统时钟如何使用。总不能自己想怎么弄,就怎么弄吧,还是学学框架吧——使用时钟的框架。
adc_clock = clk_get(NULL, "adc");

if (!adc_clock) {

printk(KERN_ERR
"failed to get adc clock source\n");

return -ENOENT;

}

clk_use(adc_clock);

clk_enable(adc_clock);

上面的这段代码是touchscreen的驱动中的一段,我不清楚,所以去学学系统各个模块时钟的使用方式。在系统的初始化的时候,看见过,但是忘了,再回顾一下。 那是在paging_init()中调用了 mdesc->map_io(),

 void __init sbc2440_map_io(void)

{

s3c24xx_init_io(sbc2440_iodesc, ARRAY_SIZE(sbc2440_iodesc));

s3c24xx_init_clocks(
12000000); //这个是系统各个部分始终初始化的起点

s3c24xx_init_uarts(sbc2440_uartcfgs, ARRAY_SIZE(sbc2440_uartcfgs));

s3c24xx_set_board(
&sbc2440_board);



s3c_device_nand.dev.platform_data
= &bit_nand_info;

}

跟 cpu_table 有关,拷贝过来 

/* table of supported CPUs */ 

static const char name_s3c2410[] = "S3C2410";

static const char name_s3c2440[] = "S3C2440";

static const char name_s3c2410a[] = "S3C2410A";

static const char name_s3c2440a[] = "S3C2440A";



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
= s3c2440_map_io,

.init_clocks
= s3c2440_init_clocks,

.init_uarts
= s3c2440_init_uarts,

.init
= s3c2440_init,

.name
= name_s3c2440

},

{

.idcode
= 0x32440001,

.idmask
= 0xffffffff,

.map_io
= s3c2440_map_io,

.init_clocks
= s3c2440_init_clocks,

.init_uarts
= s3c2440_init_uarts,

.init
= s3c2440_init,

.name
= name_s3c2440a

}

};

和时钟相关的调用路径: 在 s3c24xx_init_clocks() -> (cpu->init_clocks)(xtal)-> s3c24xx_setup_clocks()这个s3c24xx_setup_clocks()注册了系统的所有时钟,仔细看看它。 在这个函数被调用之前,代码已经根据3C2410_MPLLCON,S3C2410_CLKDIVN寄存器和晶振的频率计算出了fclk,hclk,pclk,他们应该分别是400M,100M,50M。

struct clk 

{

struct list_head list;

struct module *owner;

struct clk *parent;

const char *name;

int id;

atomic_t used;

unsigned
long rate;

unsigned
long ctrlbit;

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

};

clk数据结构是系统中时钟的抽象,它用list串成一个双向链表,在这个clocks链表里的clk结构,说明是系统中已经注册的,parent表示他的来源,f,h,p之一,name是寻找到某个clk的唯一标识��enable是面向对象的思想的体现,不过,这里没有用到,只是全部被填充为 s3c24xx_clkcon_enable()。

/* clock information */

static LIST_HEAD(clocks);

static DECLARE_MUTEX(clocks_sem);

/* clock definitions */

static struct clk init_clocks[] =

{

{

.name
= "nand",

.id
= -1,

.parent
= &clk_h,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_NAND

},

{

.name
= "lcd",

.id
= -1,

.parent
= &clk_h,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_LCDC

},

{

.name
= "usb-host",

.id
= -1,

.parent
= &clk_h,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_USBH

},

{

.name
= "usb-device",

.id
= -1,

/*.parent = &clk_h, */

.parent
= &clk_xtal,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_USBD

},

{

.name
= "timers",

.id
= -1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_PWMT

},

{

.name
= "sdi",

.id
= -1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_SDI

},

{

.name
= "uart",

.id
= 0,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_UART0

},

{

.name
= "uart",

.id
= 1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_UART1

},

{

.name
= "uart",

.id
= 2,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_UART2

},

{

.name
= "gpio",

.id
= -1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_GPIO

},

{

.name
= "rtc",

.id
= -1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_RTC

},

{

.name
= "adc",

.id
= -1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_ADC

},

{

.name
= "i2c",

.id
= -1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_IIC

},

{

.name
= "iis",

.id
= -1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_IIS

},

{

.name
= "spi",

.id
= -1,

.parent
= &clk_p,

.enable
= s3c24xx_clkcon_enable,

.ctrlbit
= S3C2410_CLKCON_SPI

},

{

.name
= "watchdog",

.id
= -1,

.parent
= &clk_p,

.ctrlbit
= 0

}

};
  • 1
  • 2
  • 3
  • 下一页

相关内容