时钟子系统的问题

1:时钟的分频和倍频在哪里设置,多会设置

解析设备树的时候,已经将倍频和分频系数给解析,但是没有设置到寄存器,

设置的时候是外设需要的时候,外设驱动做设置。

2:打开时钟也是在外设驱动中操作。

以一个具体驱动说明:以nand驱动时钟说明:

gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck");

struct clk *devm_clk_get(struct device *dev, const char *id)
{
	struct clk **ptr, *clk;

	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return ERR_PTR(-ENOMEM);

	clk = clk_get(dev, id);
	if (!IS_ERR(clk)) {
		*ptr = clk;
		devres_add(dev, ptr);
		printk("devres_add \n");
	} else {
		devres_free(ptr);
			printk("devresfree\n");
	}

	return clk;

           分析其主要代码:     clk = clk_get(dev, id);

struct clk *clk_get(struct device *dev, const char *con_id)
{
	const char *dev_id = dev ? dev_name(dev) : NULL;
	struct clk *clk;

	if (dev) {
		clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
		if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
			return clk;
	}
	
	return clk_get_sys(dev_id, con_id);
}
EXPORT_SYMBOL(clk_get);

主要代码:__of_clk_get_by_name(dev->of_node, dev_id, con_id);

所以咱们找到con_id =“fck”的时钟即可。

开始设备运行:

am33xx_init_early

        am33xx_hwmod_init

  577  int __init am33xx_hwmod_init(void)
   578  {
   579          printk("am33xx_hwmod_init \n");
   580          omap_hwmod_am33xx_reg();
   581          omap_hwmod_init();
   582          return omap_hwmod_register_links(am33xx_hwmod_ocp_ifs);
   583  }

           579行: omap_hwmod_am33xx_reg();

 1414  void omap_hwmod_am43xx_reg(void)
  1415  {
  1416          omap_hwmod_am43xx_clkctrl();
  1417          omap_hwmod_am43xx_rst();
  1418  }

1416行:omap_hwmod_am43xx_clkctrl();

static void omap_hwmod_am33xx_clkctrl(void)
{
	CLKCTRL(am33xx_uart2_hwmod, AM33XX_CM_PER_UART1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_uart3_hwmod, AM33XX_CM_PER_UART2_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_uart4_hwmod, AM33XX_CM_PER_UART3_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_uart5_hwmod, AM33XX_CM_PER_UART4_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_uart6_hwmod, AM33XX_CM_PER_UART5_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_dcan0_hwmod, AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_dcan1_hwmod, AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_elm_hwmod, AM33XX_CM_PER_ELM_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_epwmss0_hwmod, AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_epwmss1_hwmod, AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_epwmss2_hwmod, AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_gpio1_hwmod, AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_gpio2_hwmod, AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_gpio3_hwmod, AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_i2c2_hwmod, AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_i2c3_hwmod, AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_mailbox_hwmod, AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_mcasp0_hwmod, AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_mcasp1_hwmod, AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_mmc0_hwmod, AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_mmc1_hwmod, AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_spi0_hwmod, AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_spi1_hwmod, AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_spinlock_hwmod, AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_timer2_hwmod, AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_timer3_hwmod, AM33XX_CM_PER_TIMER3_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_timer4_hwmod, AM33XX_CM_PER_TIMER4_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_timer5_hwmod, AM33XX_CM_PER_TIMER5_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_timer6_hwmod, AM33XX_CM_PER_TIMER6_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_timer7_hwmod, AM33XX_CM_PER_TIMER7_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_smartreflex0_hwmod,
		AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_smartreflex1_hwmod,
		AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_uart1_hwmod, AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_timer1_hwmod, AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_i2c1_hwmod, AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_wd_timer1_hwmod, AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_rtc_hwmod, AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET);
	PRCM_FLAGS(am33xx_rtc_hwmod, HWMOD_OMAP4_ZERO_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_mmc2_hwmod, AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_gpmc_hwmod, AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_l4_ls_hwmod, AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_l4_wkup_hwmod, AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_l3_main_hwmod, AM33XX_CM_PER_L3_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_tpcc_hwmod, AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_tptc0_hwmod, AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_tptc1_hwmod, AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_tptc2_hwmod, AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_gfx_hwmod, AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_cpgmac0_hwmod, AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_pruss_hwmod, AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_mpu_hwmod , AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_l3_instr_hwmod , AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_ocmcram_hwmod , AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_sha0_hwmod , AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_aes0_hwmod , AM33XX_CM_PER_AES0_CLKCTRL_OFFSET);
	CLKCTRL(am33xx_rng_hwmod, AM33XX_CM_PER_RNG_CLKCTRL_OFFSET);
}

选取其中一个

struct omap_hwmod am33xx_gpmc_hwmod = {
	.name		= "gpmc",
	.class		= &am33xx_gpmc_hwmod_class,
	.clkdm_name	= "l3s_clkdm",
	/* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */
	.flags		= DEBUG_OMAP_GPMC_HWMOD_FLAGS | HWMOD_NEEDS_REIDLE,
	.main_clk	= "l3s_gclk",
	.prcm		= {
		.omap4	= {
			.modulemode	= MODULEMODE_SWCTRL,
		},
	},
};

重点关注.main_clk    = "l3s_gclk",

程序开始会调用初始化函数

static int __init omap_device_init(void)
{
	omap_hwmod_setup_reidle();
	bus_register_notifier(&platform_bus_type, &platform_nb);
	return 0;
}
omap_postcore_initcall(omap_device_init);

主要关注bus_register_notifier(&platform_bus_type, &platform_nb);

其中:

struct bus_type platform_bus_type = {
	.name		= "platform",
	.dev_groups	= platform_dev_groups,
	.match		= platform_match,
	.uevent		= platform_uevent,
	.pm		= &platform_dev_pm_ops,
};

另外一个参数

static struct notifier_block platform_nb = {
	.notifier_call = _omap_device_notifier_call,
};

这是一个内核通知链,也即当检测到platform设备接入时,总线上的设备队列状态发生变化,就会调用其回调函数来增加设备;当移除设备的时候,也会调用其回调函数来卸载设备。其目的就是将该设备驱动挂至platform总线上。

看到运行通知函数:_omap_device_notifier_call

---->omap_device_build_from_dt

        ->omap_device_alloc

                ->_add_hwmod_clocks_clkdev

                        ->_add_hwmod_clocks_clkdev

                                   ---> _add_clkdev(od, "fck", oh->main_clk);//以前面的例子main_clk    = "l3s_gclk",

 这个函数就是把前面生成的    con_id=  "l3s_gclk",获取创建   con_id=  "fck"时钟。进去函数最里面就是把    con_id=  "l3s_gclk" 替换成           con_id=  "fck";

时钟还是原来的时钟结构。

自此我们找到前面所需要con_id =“fck”的时钟       

时钟即可完成。

题外话

问:咱们注册里这个通知链:怎么会通知它启动了?

答:设备树生成平台设备中:前面设备树解析到了

of_platform_bus_create

        进入这个函数

        ----------------->of_platform_device_create_pdata

                                ------->of_device_add(dev)

                                        ------->device_add(&ofdev->dev);

                                                        ---->if (dev->bus)

                                                                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

                         BUS_NOTIFY_ADD_DEVICE, dev);

通知通知链运行。

                        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值