1. 数据结构
struct clk {
unsigned int rate;
};
struct nxp_clk_periph {
const char *dev_name;
int dev_id;
char periph_id;
void *base_addr;
bool enable;
/* clock config */
char level;
unsigned int clk_mask0;
unsigned int clk_mask1;
short clk_src0;
short clk_div0;
char clk_inv0;
short clk_src1;
short clk_div1;
char clk_inv1;
long clk_ext1;
long clk_ext2;
spinlock_t lock;
};
struct nxp_clk_dev {
struct clk clk;
struct clk *link;
const char *name;
struct nxp_clk_periph *peri;
};
struct clk_link_dev {
char *name;
int id;
};
struct clk_gen_reg {
volatile U32 CLKENB;
volatile U32 CLKGEN[4];
};
2.执行流程
定义15个clk_core
static struct clk_core {
int id;
const char *name;
struct list_head list;
} clk_core[] = {
[ 0] = { .id = 0, .name = CORECLK_NAME_PLL0, .list = LIST_INIT( 0), },
[ 1] = { .id = 1, .name = CORECLK_NAME_PLL1, .list = LIST_INIT( 1), },
[ 2] = { .id = 2, .name = CORECLK_NAME_PLL2, .list = LIST_INIT( 2), },
[ 3] = { .id = 3, .name = CORECLK_NAME_PLL3, .list = LIST_INIT( 3), },
[ 4] = { .id = 4, .name = CORECLK_NAME_FCLK, .list = LIST_INIT( 4), },
[ 5] = { .id = 5, .name = CORECLK_NAME_MCLK, .list = LIST_INIT( 5), },
[ 6] = { .id = 6, .name = CORECLK_NAME_BCLK, .list = LIST_INIT( 6), },
[ 7] = { .id = 7, .name = CORECLK_NAME_PCLK, .list = LIST_INIT( 7), },
[ 8] = { .id = 8, .name = CORECLK_NAME_HCLK, .list = LIST_INIT( 8), },
[ 9] = { .id = 9, .name = "memdclk" , .list = LIST_INIT( 9), },
[10] = { .id = 10, .name = "membclk" , .list = LIST_INIT(10), },
[11] = { .id = 11, .name = "mempclk" , .list = LIST_INIT(11), },
[12] = { .id = 12, .name = "g3dbclk" , .list = LIST_INIT(12), },
[13] = { .id = 13, .name = "mpegbclk" , .list = LIST_INIT(13), },
[14] = { .id = 14, .name = "mpegpclk" , .list = LIST_INIT(14), },
};
定义若干nxp_clk_periph 和 clk_link_dev
static struct nxp_clk_periph clk_periphs [] = {
CLK_PERI_1S(DEV_NAME_TIMER , 0, CLK_ID_TIMER_0 , PHY_BASEADDR_CLKGEN14, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_TIMER , 1, CLK_ID_TIMER_1 , PHY_BASEADDR_CLKGEN0 , (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_TIMER , 2, CLK_ID_TIMER_2 , PHY_BASEADDR_CLKGEN1 , (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_TIMER , 3, CLK_ID_TIMER_3 , PHY_BASEADDR_CLKGEN2 , (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_UART , 0, CLK_ID_UART_0 , PHY_BASEADDR_CLKGEN22, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_UART , 1, CLK_ID_UART_1 , PHY_BASEADDR_CLKGEN24, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_UART , 2, CLK_ID_UART_2 , PHY_BASEADDR_CLKGEN23, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_UART , 3, CLK_ID_UART_3 , PHY_BASEADDR_CLKGEN25, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_UART , 4, CLK_ID_UART_4 , PHY_BASEADDR_CLKGEN26, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_UART , 5, CLK_ID_UART_5 , PHY_BASEADDR_CLKGEN27, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_PWM , 0, CLK_ID_PWM_0 , PHY_BASEADDR_CLKGEN13, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_PWM , 1, CLK_ID_PWM_1 , PHY_BASEADDR_CLKGEN3 , (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_PWM , 2, CLK_ID_PWM_2 , PHY_BASEADDR_CLKGEN4 , (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_PWM , 3, CLK_ID_PWM_3 , PHY_BASEADDR_CLKGEN5 , (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_I2C , 0, CLK_ID_I2C_0 , PHY_BASEADDR_CLKGEN6 , (_GATE_PCLK_)),
CLK_PERI_1S(DEV_NAME_I2C , 1, CLK_ID_I2C_1 , PHY_BASEADDR_CLKGEN7 , (_GATE_PCLK_)),
CLK_PERI_1S(DEV_NAME_I2C , 2, CLK_ID_I2C_2 , PHY_BASEADDR_CLKGEN8 , (_GATE_PCLK_)),
CLK_PERI_2S(DEV_NAME_I2S , 0, CLK_ID_I2S_0 , PHY_BASEADDR_CLKGEN15, (_PLL_0_3_|_EXTCLK1_), (_CLKOUTn_)),
CLK_PERI_2S(DEV_NAME_I2S , 1, CLK_ID_I2S_1 , PHY_BASEADDR_CLKGEN16, (_PLL_0_3_|_EXTCLK1_), (_CLKOUTn_)),
CLK_PERI_2S(DEV_NAME_I2S , 2, CLK_ID_I2S_2 , PHY_BASEADDR_CLKGEN17, (_PLL_0_3_|_EXTCLK1_), (_CLKOUTn_)),
CLK_PERI_1S(DEV_NAME_SDHC , 0, CLK_ID_SDHC_0 , PHY_BASEADDR_CLKGEN18, (_PLL_0_2_|_GATE_PCLK_)),
CLK_PERI_1S(DEV_NAME_SDHC , 1, CLK_ID_SDHC_1 , PHY_BASEADDR_CLKGEN19, (_PLL_0_2_|_GATE_PCLK_)),
CLK_PERI_1S(DEV_NAME_SDHC , 2, CLK_ID_SDHC_2 , PHY_BASEADDR_CLKGEN20, (_PLL_0_2_|_GATE_PCLK_)),
CLK_PERI_1S(DEV_NAME_SPI , 0, CLK_ID_SPI_0 , PHY_BASEADDR_CLKGEN37, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_SPI , 1, CLK_ID_SPI_1 , PHY_BASEADDR_CLKGEN38, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_SPI , 2, CLK_ID_SPI_2 , PHY_BASEADDR_CLKGEN39, (_PLL_0_2_)),
#if 0
CLK_PERI_1S(DEV_NAME_VIP , 0, CLK_ID_VIP_0 , PHY_BASEADDR_CLKGEN30, (_PLL_0_3_|_EXTCLK1_|_GATE_BCLK_)),
CLK_PERI_1S(DEV_NAME_VIP , 1, CLK_ID_VIP_1 , PHY_BASEADDR_CLKGEN31, (_PLL_0_3_|_EXTCLK1_|_EXTCLK2_|_GATE_BCLK_)),
#endif
CLK_PERI_1S(DEV_NAME_MIPI , -1, CLK_ID_MIPI , PHY_BASEADDR_CLKGEN9 , (_PLL_0_2_)),
CLK_PERI_2S(DEV_NAME_GMAC , -1, CLK_ID_GMAC , PHY_BASEADDR_CLKGEN10, (_PLL_0_3_|_EXTCLK1_), (_CLKOUTn_)),
CLK_PERI_1S(DEV_NAME_SPDIF_TX , -1, CLK_ID_SPDIF_TX , PHY_BASEADDR_CLKGEN11, (_PLL_0_2_)),
CLK_PERI_1S(DEV_NAME_MPEGTSI , -1, CLK_ID_MPEGTSI , PHY_BASEADDR_CLKGEN12, (_GATE_BCLK_)),
#if 0
CLK_PERI_1S(DEV_NAME_MALI , -1, CLK_ID_MALI , PHY_BASEADDR_CLKGEN21, (_GATE_BCLK_)),
#endif
CLK_PERI_1S(DEV_NAME_DIT , -1, CLK_ID_DIT , PHY_BASEADDR_CLKGEN28, (_GATE_BCLK_)),
CLK_PERI_1S(DEV_NAME_PPM , -1, CLK_ID_PPM , PHY_BASEADDR_CLKGEN29, (_PLL_0_2_)),
#if 0
CLK_PERI_2S(DEV_NAME_USB2HOST , -1, CLK_ID_USB2HOST , PHY_BASEADDR_CLKGEN32, (_PLL_0_3_), (_PLL_0_3_|_EXTCLK1_)),
CLK_PERI_1S(DEV_NAME_CODA , -1, CLK_ID_CODA , PHY_BASEADDR_CLKGEN33, (_GATE_PCLK_|_GATE_BCLK_)),
#endif
CLK_PERI_1S(DEV_NAME_CRYPTO , -1, CLK_ID_CRYPTO , PHY_BASEADDR_CLKGEN34, (_GATE_PCLK_)),
CLK_PERI_1S(DEV_NAME_SCALER , -1, CLK_ID_SCALER , PHY_BASEADDR_CLKGEN35, (_GATE_BCLK_)),
CLK_PERI_1S(DEV_NAME_PDM , -1, CLK_ID_PDM , PHY_BASEADDR_CLKGEN36, (_GATE_PCLK_)),
#if 0
CLK_PERI_2S(DEV_NAME_USBOTG , -1, CLK_ID_USBOTG , PHY_BASEADDR_CLKGEN32, (_PLL_0_3_), (_PLL_0_3_|_EXTCLK1_)),
#endif
};
static struct clk_link_dev clk_link[] = {
{ .name = "uart-pl011.0", .id = CLK_ID_UART_0, },
{ .name = "uart-pl011.1", .id = CLK_ID_UART_1, },
{ .name = "uart-pl011.2", .id = CLK_ID_UART_2, },
{ .name = "uart-pl011.3", .id = CLK_ID_UART_3, },
{ .name = "uart-pl011.4", .id = CLK_ID_UART_4, },
{ .name = "uart-pl011.5", .id = CLK_ID_UART_5, },
{ .name = "ssp-pl022.0" , .id = CLK_ID_SPI_0 , },
{ .name = "ssp-pl022.1" , .id = CLK_ID_SPI_1 , },
{ .name = "ssp-pl022.2" , .id = CLK_ID_SPI_2 , },
};
#define CLK_PERI_NUM ((int)ARRAY_SIZE(clk_periphs))
#define CLK_CORE_NUM ((int)ARRAY_SIZE(clk_core))
#define CLK_LINK_NUM ((int)ARRAY_SIZE(clk_link))
#define CLK_DEVS_NUM (CLK_CORE_NUM + CLK_PERI_NUM + CLK_LINK_NUM)
#define MAX_DIVIDER ((1<<8) - 1) // 256, align 2
static void __init cpu_map_io(void)
{
.....................................
nxp_cpu_base_init();
nxp_board_base_init();
nxp_cpu_clock_init();
nxp_cpu_clock_print();
}
在cpu_map_iocpu_map_io最后调用nxp_cpu_clock_init 和 nxp_cpu_clock_print来初始化时钟模块和打印时钟信息
static int __init cpu_pll_sys_init(void)
{
struct kobject *kobj = NULL;
int ret = 0;
/* create attribute interface */
kobj = kobject_create_and_add("pll", &platform_bus.kobj);
if (!kobj) {
printk(KERN_ERR "Fail, create kobject for cpu\n");
return -ret;
}
ret = sysfs_create_group(kobj, &attr_group);
if (ret) {
printk(KERN_ERR "Fail, create sysfs group for pll ...\n");
kobject_del(kobj);
return -ret;
}
return ret;
}
module_init(cpu_pll_sys_init);
创建目录 /sys/bus/platform/pll 和文件 /sys/bus/platform/pl/pll.0 /sys/bus/platform/pl/pll.1 /sys/bus/platform/pl/pll.2 /sys/bus/platform/pl/pll.3