Welcome 微信登录

首页 / 操作系统 / Linux / Linux内核时钟框架实例

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

if (!adc_clock) {

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

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_headlist;

struct module *owner;

struct clk*parent;

const char *name;

intid;

atomic_tused;

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

}

};