This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

how to make AM572x PCIe PHY refer clock out ?

Expert 1385 points

I use the kernel is 4.1.13,  and  I want to make ljcb_clkp and ljcb_clkn as output as the follow:

but I can't find the the device tree configuration for set these pins output, can you give me some help?

I have seen that this driver seems dosen't support this function, but what should i do for this ?

Thank you very much!

Best Regards

Qing 

  • anybody here?
  • Hi,

    Those pins (ljcb_clkp & ljcb_clkn) do not seem to have a padconf register. So they are set as described in AM572x Data manual, as I/O (input/output) pins.

    Best Regards,
    Yordan
  • Hi, Yordan:

    First of all, thanks for  you reply!

    I want to make ljcb_clkp and ljcb_clkn output 100MHz clock for other pcie device, but  i can't find device tree configuration about this.

    I have seen the $(kernel)/driver/phy/phy-ti-pipe3.c .  and found that the dpll_ref clock has been enabled in probe,

    static int ti_pipe3_probe(struct platform_device *pdev)
    {
    	............................
    /* This function enabled the dpll_ref clock, it's means that DPLL 
    has output 100MHz clock So, in theory, we just need to enable 
    ref clock buffer as out. is right?  */
    	ret = ti_pipe3_get_clk(phy); 
    	if (ret)
    		return ret;
    
    	if (of_property_read_bool(node, "ti,configure-as-pcie"))
    		phy->flags |= CONFIGURE_AS_PCIE;
    
    	platform_set_drvdata(pdev, phy);
    	pm_runtime_enable(dev);
    
            /* Enable the clock buffer as transmit*/
           reg =  CTRL_CORE_SMA_SW_6;
           reg &=~(3 << 16);
          reg | = (1<<16);
            while(1);
    
    	........................
    }

  • after that, no clock singnal is outputed, and could you tell me why ? 
  • Hi,

    Do you use the default dts file? Is this a custom board or the reference TI AM572x GP EVM?

    Have a look at Documentation/devicetree/bindings/pci/ti-pci.txt & Documentation/devicetree/bindings/pci/designware-pci.txt:

    - clocks: Must contain an entry for each entry in clock-names.
    See ../clocks/clock-bindings.txt for details.

    So, in your dra7.dtsi file, check if you have the correct entry for ljcb_clkp & ljcb_clkn:
    clocks = <&dpll_pcie_ref_ck>,
    <&dpll_pcie_ref_m2ldo_ck>,
    <&optfclk_pciephy1_32khz>,
    <&optfclk_pciephy1_clk>,
    <&optfclk_pciephy1_div_clk>,
    <&optfclk_pciephy_div>,
    <&sys_clkin1>;
    clock-names = "dpll_ref", "dpll_ref_m2",
    "wkupclk", "refclk",
    "div-clk", "phy-div", "sysclk";

    I think you need to add the ACS PCIE ref clocks for apll, that is you need additional entry in clocks & clock-names. As per dra7xx-clocks.dtsi, the clock for acs pcie ref clock is
    pciesref_acs_clk_ck: pciesref_acs_clk_ck {
    #clock-cells = <0>;
    compatible = "fixed-clock";
    clock-frequency = <100000000>;
    };
    So you may need &pciesref_acs_clk_ck & something like pciesref_acs_clk as a name.

    Best Regards,
    Yordan
  • Hi, Yordan:

    Thank you!

    1. Yes ,  I use the default dts file,  and  reference TI AM572x GP EVM.

    2.  I have seen the ti-pci.txt  and the driver only support 7 kinds of clock. and  ti-pci.txt content as follow:

    TI PIPE3 PHY
    Required properties:
     - compatible: Should be "ti,phy-usb3", "ti,phy-pipe3-sata" or "ti,phy-pipe3-pcie. "ti,omap-usb3" is deprecated.
     - reg : Address and length of the register set for the device.
     - reg-names: The names of the register addresses corresponding to the registers filled in "reg".
     - #phy-cells: determine the number of cells that should be given in the phandle while referencing this phy.
     - clocks: a list of phandles and clock-specifier pairs, one for each entry in clock-names.
     - clock-names: should include:
       * "wkupclk" - wakeup clock.
       * "sysclk" - system clock.
       * "refclk" - reference clock.
       * "dpll_ref" - external dpll ref clk
       * "dpll_ref_m2" - external dpll ref clk
       * "phy-div" - divider for apll
       * "div-clk" - apll clock 

    And no clock name for pciesref_acs_clk_ck.  About the other clock, the phy-ti_pipe3.c  seem no support. 

  • Hi, Yordan

    I can't undertand the clock configuration for in phy-ti-pipe3.c driver for DPLL_REF_CLK CLKOUTLDO.

    then I follow the Figure 26-21. DPLL_PCIE_REF Programming Sequence to program by raw code. 

    But I can't find the appropriate  frequecy value(20MHz)  according to the table 26-49 &26-50. and what should I do?

    Best Regards

    Qing

  • Hi Qing,

    Qing said:
    But I can't find the appropriate frequecy value(20MHz) according to the table 26-49 &26-50. and what should I do?


    You can use the Clock Tree Tool to generate the needed register values to reach the 20MHz frequency. Link to CTT download page is:
    www.ti.com/.../clocktreetool

    As for the acs ref clk, try adding the &pciesref_acs_clk_ck in the clocks parameter in your dts, i.e. replace the current refclock source with &pciesref_acs_clk_ck and see if you'll get the acs ref clk working. Have in mind that you may need to modify the driver source (phy-ti_pipe3.c) as well.

    Also you need to verify if the clock is present on the device pin, upon PCI transaction, I don't believe you'll have an active clock on the ljcb_clkp/ljcb_clkn pin, if the PCIe is not performing any transaction.

    Best Regards,
    Yordan
  • Hi, Yordan:

    I have wrtie a code in dsp side to Pcie clock out(follow the pcie driver), But it's still no signal.

    Can you give me some advice about the code :

    pcie.c
    typedef unsigned int  uint32_t;
    #define HW_WR_REG32(addr, data)   *(unsigned int*)(addr) =(unsigned int)(data)
    #define HW_RD_REG32(x)             (*((volatile uint32_t *)(x)))
    
    
    #define SOC_OCP2SCP3_BASE (0x4a090000U)
    #define SOC_CKGEN_CM_CORE_BASE	(0x4a008100U)
    #define CM_CLKSEL_DPLL_PCIE_REF (0x4A00820CU)
    #define CM_CLKSEL_DPLL_PCIE_REF_DPLL_DIV  (0xFF)
    #define CM_CLKSEL_DPLL_PCIE_REF_DPLL_MULT (0xFFF<<8) 
    #define CM_CLKSEL_DPLL_PCIE_REF_DPLL_SD_DIV (0xFF<<24)
    #define CM_DIV_M2_DPLL_PCIE_REF  	(0x4A008210)
    #define CM_DIV_M2_DPLL_PCIE_REF_DIVHS  (0x7F) 
    #define CM_CLKMODE_DPLL_PCIE_REF   (0x4A008200) 
    #define CM_CLKMODE_DPLL_PCIE_REF_DPLL_EN_DPLL_LOCK_MODE  (0x00000007U)
    #define CM_IDLEST_DPLL_PCIE_REF (0x4A008204)
    #define CM_IDLEST_DPLL_PCIE_REF_ST_DPLL_CLK_MASK (0x00000001U)
    #define CM_IDLEST_DPLL_PCIE_REF_ST_DPLL_CLK_SHIFT	(0U)
    #define CM_IDLEST_DPLL_PCIE_REF_ST_DPLL_CLK_DPLL_LOCKED  (0x00000001U) 
    #define CTRL_CORE_SMA_SW_6 				(0x4A003C14) 
    #define CM_CLKMODE_APLL_PCIE			(0x4A00821C)
    #define CM_IDLEST_APLL_PCIE             (0x4A008220)
    #define CM_IDLEST_APLL_PCIE_ST_APLL_CLK_MASK  (0x00000001U)
    #define CM_IDLEST_APLL_PCIE_ST_APLL_CLK_SHIFT  (0U)
    #define CM_IDLEST_APLL_PCIE_ST_APLL_CLK_APLL_LOCKED  (0x00000001U)
    
    void PlatformPCIESS1PllConfig(void)
    {
        uint32_t regVal;
    
        /*OCP2SCP_SYSCONFIG[1] Soft Reset*/
        regVal = HW_RD_REG32(SOC_OCP2SCP3_BASE + 0x10U) & 0xFFFFFFFDU;
        regVal |= 0x02U;
        HW_WR_REG32(SOC_OCP2SCP3_BASE + 0x10U, regVal);
    
        /*OCP2SCP_SYSSTATUS[0] Reset Done*/
        while ((HW_RD_REG32(SOC_OCP2SCP3_BASE + 0x14U) & 0x01U) != 0x01U)
        {
            ;
        }
    
        /*OCP2SCP_TIMING[9:7] Division Ratio = 1*/
        regVal = HW_RD_REG32(SOC_OCP2SCP3_BASE + 0x18U) & 0xFFFFFC7FU;
        regVal |= (uint32_t) 0x8U << 4U;
        HW_WR_REG32(SOC_OCP2SCP3_BASE + 0x18U, regVal);
    
        /*OCP2SCP_TIMING[3:0] (SYNC2) = 0xF*/
        regVal = HW_RD_REG32(SOC_OCP2SCP3_BASE + 0x18U) & 0xFFFFFFF0U;
        regVal |= 0xFU;
        HW_WR_REG32(SOC_OCP2SCP3_BASE + 0x18U, regVal);
    
        /*PCIe DPLL - M&N programming; CLKSEL*/
        regVal = HW_RD_REG32(CM_CLKSEL_DPLL_PCIE_REF);
    	//DPLL_DIV	
    	regVal &= ~CM_CLKSEL_DPLL_PCIE_REF_DPLL_DIV;
    	regVal |= 0x09U;
    	//DPLL_MULT
        regVal &= ~CM_CLKSEL_DPLL_PCIE_REF_DPLL_MULT;
        regVal |= (0x2EEU<<8);
        HW_WR_REG32(CM_CLKSEL_DPLL_PCIE_REF, regVal);
    
        /*SigmaDelta SD DIV programming */
        regVal = HW_RD_REG32(CM_CLKSEL_DPLL_PCIE_REF);
    	//SD_DIV	
    	regVal &= ~CM_CLKSEL_DPLL_PCIE_REF_DPLL_SD_DIV;
    	regVal |= 0x06U;
        HW_WR_REG32(CM_CLKSEL_DPLL_PCIE_REF, regVal);
    
        /*PCIe DPLL - M2 programming*/
    	regVal = HW_RD_REG32(CM_DIV_M2_DPLL_PCIE_REF);
    	regVal &= ~CM_DIV_M2_DPLL_PCIE_REF_DIVHS;
    	regVal |= 0x0FU;
    	HW_WR_REG32(CM_DIV_M2_DPLL_PCIE_REF, regVal);
    
        /*DPLL Enable*/
    	regVal = HW_RD_REG32(CM_CLKMODE_DPLL_PCIE_REF);
        regVal &= ~3;
    	regVal |= CM_CLKMODE_DPLL_PCIE_REF_DPLL_EN_DPLL_LOCK_MODE;
    	HW_WR_REG32(CM_CLKMODE_DPLL_PCIE_REF, regVal);
    
        /* Check for DPLL lock status */
        while (((HW_RD_REG32(CM_IDLEST_DPLL_PCIE_REF) &
                 CM_IDLEST_DPLL_PCIE_REF_ST_DPLL_CLK_MASK) <<
                CM_IDLEST_DPLL_PCIE_REF_ST_DPLL_CLK_SHIFT) !=
               CM_IDLEST_DPLL_PCIE_REF_ST_DPLL_CLK_DPLL_LOCKED)
        {
            ;
        }
    
        /*PCIe Tx and Rx Control of ACSPCIe*/
    	regVal = HW_RD_REG32(CTRL_CORE_SMA_SW_6);
    	regVal &= ~(3<<16);
        regVal |= (0x01<<16); // TX mode.
    	HW_WR_REG32(CTRL_CORE_SMA_SW_6, regVal);
    
        /*Locking APLL to 2.5GHz with 100MHz input*/
        regVal = HW_RD_REG32(CM_CLKMODE_APLL_PCIE);
    	regVal &= ~(1<<8);
    	regVal |= (1<<8); 
    	regVal &= ~(1<<8);
    	HW_WR_REG32(CM_CLKMODE_APLL_PCIE, regVal);
    	
    
    	regVal = HW_RD_REG32(CM_CLKMODE_APLL_PCIE);
    	regVal &= ~3;
    	regVal |= 1; 
    	HW_WR_REG32(CM_CLKMODE_APLL_PCIE, regVal);
    
        /*Wait for APLL lock*/
        while (((HW_RD_REG32(CM_IDLEST_APLL_PCIE) &
                 CM_IDLEST_APLL_PCIE_ST_APLL_CLK_MASK) <<
                CM_IDLEST_APLL_PCIE_ST_APLL_CLK_SHIFT) !=
               CM_IDLEST_APLL_PCIE_ST_APLL_CLK_APLL_LOCKED)
        {
            ;
        }
    }
    
    #define  CM_L3INIT_OCP2SCP1_CLKCTRL  (0x4A0093E0)
    #define  CM_L3INIT_OCP2SCP1_CLKCTRL_MODULEMODE_AUTO  (0x00000001U)
    #define  CM_L3INIT_OCP2SCP3_CLKCTRL   (0x4A0093E8)
    #define  CM_L3INIT_OCP2SCP3_CLKCTRL_MODULEMODE_AUTO  (0x00000001U)
    #define  CM_PCIE_CLKSTCTRL	          (0x4A0093A0)
    #define  CM_PCIE_CLKSTCTRL_CLKTRCTRL_SW_WKUP  (0x00000002U)
    #define  CM_PCIE_PCIESS1_CLKCTRL   (0x4A0093B0)
    #define  CM_PCIE_PCIESS1_CLKCTRL_MODULEMODE_ENABLED  (0x00000002U)
    #define  CM_PCIE_PCIESS1_CLKCTRL_IDLEST_MASK         (0x00030000U)
    #define  CM_PCIE_PCIESS1_CLKCTRL_IDLEST_FUNC  		 (0x00000000U)
    #define  OPTFCLKEN_PCIEPHY_CLK_DIV_EN 			(1<<10)
    #define  OPTFCLKEN_PCIEPHY_CLK_EN					(1<<9)
    #define  OPTFCLKEN_32KHZ_EN				(1<<8)
    void PlatformPCIESS1ClockEnable(void)
    {
      uint32_t regVal;
    
      /*OCP2SCP1 enables accessing the PCIe PHY serial configuration*/ 	
      regVal = HW_RD_REG32(CM_L3INIT_OCP2SCP1_CLKCTRL);  	
      regVal |= CM_L3INIT_OCP2SCP1_CLKCTRL_MODULEMODE_AUTO;
      HW_WR_REG32(CM_L3INIT_OCP2SCP1_CLKCTRL, regVal);	
    
      /*OCP2SCP3 enables accessing the PCIe PHY serial configuration*/
      regVal = HW_RD_REG32(CM_L3INIT_OCP2SCP3_CLKCTRL);  	
      regVal |= CM_L3INIT_OCP2SCP3_CLKCTRL_MODULEMODE_AUTO;
      HW_WR_REG32(CM_L3INIT_OCP2SCP3_CLKCTRL, regVal);	
    
      /* PCIeSS CLKSTCTRL SW WakeUp */
      regVal = HW_RD_REG32(CM_PCIE_CLKSTCTRL);  	
      regVal |= CM_PCIE_CLKSTCTRL_CLKTRCTRL_SW_WKUP;
      HW_WR_REG32(CM_PCIE_CLKSTCTRL, regVal);
    
      /*L3 Init PCIeSS1 CLKCTRL SW Enable*/
      regVal = HW_RD_REG32(CM_PCIE_PCIESS1_CLKCTRL);  	
      regVal |= CM_PCIE_PCIESS1_CLKCTRL_MODULEMODE_ENABLED;
      HW_WR_REG32(CM_PCIE_PCIESS1_CLKCTRL, regVal);
    
      
      while ((HW_RD_REG32(CM_PCIE_PCIESS1_CLKCTRL) &
                CM_PCIE_PCIESS1_CLKCTRL_IDLEST_MASK) !=
               CM_PCIE_PCIESS1_CLKCTRL_IDLEST_FUNC)
      {
       ;
      }	
    
      /*Enable PCIe PHY optional clk*/
      regVal = HW_RD_REG32(CM_PCIE_PCIESS1_CLKCTRL);		
      regVal |= OPTFCLKEN_PCIEPHY_CLK_DIV_EN;
      regVal |= OPTFCLKEN_PCIEPHY_CLK_EN;	
      regVal |= OPTFCLKEN_32KHZ_EN;	 
      HW_WR_REG32(CM_PCIE_PCIESS1_CLKCTRL, regVal);			
    }
    

    I follow this step to setup the DPLL in CCS, but it's still no signal.  I hope you give me advice ?

    Thank you very much!

    Best Regards

    Qing

  • I have tried to modify the devicetree and relative driver, but can't work.
    I have refered the TRM for Pcie clock output, but it's still no work. I hope you can give me some important advice about where I am wrong !

    Thank you very much!


    Best Regards
    Qing
  • Hi Qing,

    I'd advise to check also the RTOS PCIe examples for reference on the clock configurations. RTOS download page is: software-dl.ti.com/.../index_FDS.html

    I've also consulted the PCIe designer. I'll get back with any feedback I have.

    Best Regards,
    Yordan
  • From TRM 26.4.4.4.3 ACSPCIE reference clock buffer, you need to set the Tx mode in CTRL_CORE_SMA_SW_6
    0x4A003C14, 17:16 PCIE_TX_RX_CONTROL. I saw your code already did this.

    In our RTOS example, there are functions:
    PlatformPCIESS1ClockEnable();
    PlatformPCIESS1PllConfig();
    PlatformPCIESS1CtrlConfig();
    PlatformPCIESS1Reset();
    PlatformPCIESS1PhyConfig();

    APLL part is not required, you need some trial to see if that works for you to output 100MHz differential clock.

    Regards, Eric
  • I saw you posted the same with e2e.ti.com/.../1962047 and already resolved (you original goal is using Linux, the RTOS function is only pointed out here for referece). So I am closing this ticket.

    Regards, Eric