博主使用的是天嵌科技的IMX6Q_coreC板子。

使用的内核版本为3.0.35

现在有关项目需要clko2输出40M时钟。

记录调试过程:

板级代码中有:
         管脚复用以配置成 MX6Q_PAD_GPIO_3__CCM_CLKO2
 
 
     clko2 = clk_get(NULL, "clko2_clk");
     if (IS_ERR(clko2))
            pr_err("can't get CLKO2 clock.\n");
 
     new_parent = clk_get(NULL, "osc_clk");
     if (!IS_ERR(new_parent))
     {
            clk_set_parent(clko2, new_parent);
            clk_put(new_parent);
     }
     rate = clk_round_rate(clko2, 24000000);
     clk_set_rate(clko2, rate);
     clk_enable(clko2);
 
     /* Camera and audio use osc clock */
     clko = clk_get(NULL, "clko_clk");
     if (!IS_ERR(clko))
            clk_set_parent(clko, clko2);
就是clko是从clko2中分出来的,而clko2是从osc_clk中分出来的,osc_clk是24M,用示波器量clko(GPIO0)是有24M的, clko2应该也是有24M才对啊,但是量得clko2却没有时钟输出
 
 
后来我在板级代码上改成这样
     clko2 = clk_get(NULL, "clko2_clk");
     if (IS_ERR(clko2))
            pr_err("can't get CLKO2 clock.\n");
 
     new_parent = clk_get(NULL, "osc_clk");
     if (!IS_ERR(new_parent))
     {
            clk_set_parent(clko2, new_parent);
            clk_put(new_parent);
     }
     rate = clk_round_rate(clko2, 24000000);
     clk_set_rate(clko2, rate);
     clk_enable(clko2);
 
在声卡的代码 static int mxc_wm8960_init(void)中改成这样:
      clko2 = clk_get(NULL, "clko2_clk");
     if (IS_ERR(clko2))
            pr_err("can't get CLKO2 clock.\n");
 
     new_parent = clk_get(NULL, "osc_clk");
     if (!IS_ERR(new_parent))
     {
            clk_set_parent(clko2, new_parent);
            clk_put(new_parent);
     }
     rate = clk_round_rate(clko2, 24000000);
     clk_set_rate(clko2, rate);
     clk_enable(clko2);
 
不将clko2设置成clko的父时钟,用示波器测量clko2_clk(GPIO_3),同样没有24M输出。
 
后来又改成这样:
 
static int mxc_wm8960_init(void)中改成这样:
     clko2 = clk_get(NULL, "clko2_clk");
     if (IS_ERR(clko2))
            pr_err("can't get CLKO2 clock.\n");
     rate = clk_round_rate(clko2, 24000000);
     clk_set_rate(clko2, rate);
     
而  static int wm8960_clk_enable(int enable)
{
     if (enable)
            clk_enable(clko2);
     else
            clk_disable(clko2);
 
     return 0;
}
直接设置clko2,不将osc_clk设置成clko2的父时钟,用示波器测量clko2_clk(GPIO_3),同样没有24M输出。
 
 
后来我跟了一下代码:
 我跟了一下代码:static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
{
u32 sel, reg;
 
if (parent == &pll3_usb_otg_main_clk)
sel = 0;
else if (parent == &pll2_528_bus_main_clk)
sel = 1;
else if (parent == &pll1_sys_main_clk)
sel = 2;
else if (parent == &pll5_video_main_clk)
sel = 3;
else if (parent == &axi_clk)
sel = 5;
else if (parent == &enfc_clk)
sel = 6;
else if (parent == &ipu1_di_clk[0])
sel = 7;
else if (parent == &ipu1_di_clk[1])
sel = 8;
else if (parent == &ipu2_di_clk[0])
sel = 9;
else if (parent == &ipu2_di_clk[1])
sel = 10;
else if (parent == &ahb_clk)
sel = 11;
else if (parent == &ipg_clk)
sel = 12;
else if (parent == &ipg_perclk)
sel = 13;
else if (parent == &ckil_clk)
sel = 14;
else if (parent == &pll4_audio_main_clk)
sel = 15;
else if (parent == &clko2_clk) {
reg = __raw_readl(MXC_CCM_CCOSR);
reg |= MXC_CCM_CCOSR_CKOL_MIRROR_CKO2_MASK;
__raw_writel(reg, MXC_CCM_CCOSR);
return 0;
} else
return -EINVAL;
 
reg = __raw_readl(MXC_CCM_CCOSR);
reg &= ~(MXC_CCM_CCOSR_CKOL_MIRROR_CKO2_MASK |
MXC_CCM_CCOSR_CKOL_SEL_MASK);
reg |= sel << MXC_CCM_CCOSR_CKOL_SEL_OFFSET;
__raw_writel(reg, MXC_CCM_CCOSR);
return 0;
}
从这个函数中可以看出clko要获取 24M 只有选clko2上(parent),其他的选择基本都达不到24M
 
 
clko2 的话 :static int _clk_clko2_set_parent(struct clk *clk, struct clk *parent)
{
     u32 sel, reg;
 
     if (parent == &mmdc_ch0_axi_clk[0])
            sel = 0;
     else if (parent == &mmdc_ch1_axi_clk[0])
            sel = 1;
     else if (parent == &usdhc4_clk)
            sel = 2;
     else if (parent == &usdhc1_clk)
            sel = 3;
     else if (parent == &gpu2d_axi_clk)
            sel = 4;
     else if (parent == &ecspi_clk[0])
            sel = 6;
     else if (parent == &gpu3d_axi_clk)
            sel = 7;
     else if (parent == &usdhc3_clk)
            sel = 8;
     else if (parent == &pcie_clk[0])
            sel = 9;
     else if (parent == &ipu1_clk)
            sel = 11;
     else if (parent == &ipu2_clk)
            sel = 12;
     else if (parent == &vdo_axi_clk)
            sel = 13;
     else if (parent == &osc_clk)
            sel = 14;
     else if (parent == &gpu2d_core_clk[0])
            sel = 15;
     else if (parent == &gpu3d_core_clk[0])
            sel = 16;
     else if (parent == &usdhc2_clk)
            sel = 17;
     else if (parent == &ssi1_clk)
            sel = 18;
     else if (parent == &ssi2_clk)
            sel = 19;
     else if (parent == &ssi3_clk)
            sel = 20;
     else if (parent == &gpu3d_shader_clk)
            sel = 21;
     else if (parent == &can_clk_root)
            sel = 23;
     else if (parent == &ldb_di0_clk)
            sel = 24;
     else if (parent == &ldb_di1_clk)
            sel = 25;
     else if (parent == &esai_clk)
            sel = 26;
     else if (parent == &uart_clk[0])
            sel = 28;
     else if (parent == &spdif0_clk[0])
            sel = 29;
     else if (parent == &hsi_tx_clk[0])
            sel = 31;
     else
            return -EINVAL;
 
     reg = __raw_readl(MXC_CCM_CCOSR);
     reg &= ~MXC_CCM_CCOSR_CKO2_SEL_MASK;
     reg |= sel << MXC_CCM_CCOSR_CKO2_SEL_OFFSET;
     __raw_writel(reg, MXC_CCM_CCOSR);
     return 0;
}他的选择比较多, 在系统初始化的的时候,系统确实是选择了osc_clk
 
 
在mx6_clocks_init函数中会有以下的初始化佐证:
 
        /* PCLK camera - J5 */
     clk_set_parent(&clko2_clk, &osc_clk);
     clk_set_rate(&clko2_clk, 2400000);
 
     clk_set_parent(&clko_clk, &pll4_audio_main_clk);
 
但在板级代码中又重新了初始化的,就是前面提到的代码:
 
      clko2 = clk_get(NULL, "clko2_clk");
     if (IS_ERR(clko2))
            pr_err("can't get CLKO2 clock.\n");
 
     new_parent = clk_get(NULL, "osc_clk");
     if (!IS_ERR(new_parent))
     {
            clk_set_parent(clko2, new_parent);
            clk_put(new_parent);
     }
     rate = clk_round_rate(clko2, 24000000);
     clk_set_rate(clko2, rate);
     clk_enable(clko2);
 
     /* Camera and audio use osc clock */
     clko = clk_get(NULL, "clko_clk");
     if (!IS_ERR(clko))
            clk_set_parent(clko, clko2);
 
clko2还是选择了osc_clk 作为父时钟 ,  clko就选择了clko2作为父时钟。
 
另外还发现clko除了使用clko2(osc_clk )作为父时钟,使用其他时钟作为父时钟,clko也没有输出。

后来怀疑clko2端口到CPU没有通路,然后将该接口复用成GPIO进行检测,发现可控制高低电平,说明硬件上没有问题。

后面怀疑该管脚的复用寄存器有问题。

故分别读取寄存器的值:

 IOMUXC_SW_MUX_CTL_PAD_GPIO03       寄存器值为0x4    将该管脚复用成CCM_CLKO2
    
 IOMUXC_SW_PAD_CTL_PAD_GPIO03        寄存器值为1b8b1

极有可能是这个寄存器配置不正确了: IOMUXC_SW_PAD_CTL_PAD_GPIO03

查看datasheet:

IMX6Q,clko2无法输出时钟问题

可能是第11bit的或者第16bit导致,尝试改变这两位的测量波形。

发现将第11bit置0后有波形输出,即将 IOMUXC_SW_PAD_CTL_PAD_GPIO03值设置为1B0B1。

记录完毕

 

相关文章:

  • 2021-05-18
  • 2021-05-18
  • 2021-08-20
  • 2022-12-23
  • 2021-06-23
  • 2022-01-02
  • 2022-01-17
  • 2021-12-25
猜你喜欢
  • 2021-06-17
  • 2021-12-30
  • 2022-02-10
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案