Linux 时钟模块分析2

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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值