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.

Linux/AM5726: Set Frequency in RT patched kernel

Part Number: AM5726
Other Parts Discussed in Thread: DRA752, AM5728, BEAGLEBOARD-X15

Tool/software: Linux

Hi all,

I have a Am572x IDK and got the latest linux source code from http://software-dl.ti.com/processor-sdk-linux-rt/esd/AM57X/latest/exports/am57xx-evm-linux-rt-sdk-src-03.03.00.04.tar.xz

Because DVFS is not a deterministic behavior I disabled CONFIG_CPU_FREQ and CONFIG_CPU_IDLE. As far as I understand is the CPU frequency set by the bootloader and wont be changed again. In the bootloaders menuconfig I saw that the MPU Voltage domain parameter is set to OPP_NOM and I assume that also the frequency is taken from this opp.

I want to set the frequency to 1.176 GHz so I just changed the lines of the opp_nom in the device tree from:

opp_table0 {
		compatible = "operating-points-v2";
		opp-shared;
		linux,phandle = <0x3>;
		phandle = <0x3>;

		opp_nom@1000000000 {
			opp-hz = <0x0 0x3b9aca00>;
			opp-microvolt = <0x102ca0 0xcf850 0x118c30>;
			opp-supported-hw = <0xff 0x1>;
			opp-suspend;
		};

  ... };

to

opp_table0 {
		compatible = "operating-points-v2";
		opp-shared;
		linux,phandle = <0x3>;
		phandle = <0x3>;

		opp_nom@1100000000 {
			opp-hz = <0x0 0x46185600>;
                        opp-microvolt = <0x11b340 0xd8108 0x11b340>;
			opp-supported-hw = <0xff 0x1>;
			opp-suspend;
		};

		...
	};


And I measure the frequency with the pert tool.
<sudo perf stat dd if=/dev/urandom of=/dev/null count=100000>

But unfortunately my sitara cpus still runs on 1.0 GHz. What am I doing wrong? What is the right way to set the frequency?

Regards,

Guy

  • Hi Guy,

    You can not run Cortex-A15 higher than 1GHz in OPP_NOM. If you need 1.176GHz, you should switch to OPP_OD.

    See AM572x DM, Table 5-8. Supported OPP vs Max Frequency

    Regards,
    Pavel
  • Hi Pavel,

    Thank you for your answer.
    Is there way to switch the frequency to OPP_OD with disabled CONFIG_CPU_FREQ parameter?

    Regards,
    Guy
  • Guy,

    The 1GHz OPP_NOM is set in u-boot first. You might try changing u-boot from OPP_NOM to OPP_OD, thus you will have OPP_OD in kernel by default. And you can disable DVFS/CPUFreq from menuconfig.

    u-boot-2016.05/arch/arm/include/asm/arch-omap5/clock.h - define CONFIG_DRA7_MPU_OPP_OD

    u-boot-2016.05/board/ti/am57xx/board.c - check get_voltrail_opp() and am572x_idk_volts

    Regards,
    Pavel
  • Hi Pavel,

    Thank you again :-)

    - So I set CONFIG_DRA7_MPU_OPP_OD. And added a debug() function to board/ti/am57xx/board.c:get_voltrail_opp() which is called three times for I assume it is the arch/arm/cpu/armv7/omap5/fdt.c:ft_opp_clock_fixups. But it is never called for the VOLT_MPU. Do I need also to adapt other sources files?

    - Anyhow I also got a strange output on the first lines of u-boot:

    U-Boot 2016.05-00319-ge811b89-dirty (Jun 06 2017 - 17:50:47 +0200)
    
    initcall: 8080f1fd
    U-Boot code: 80800000 -> 80864F50  BSS: -> 808B4554
    initcall: 80800b31
    CPU  : DRA752-GP ES2.0
    initcall: 8080f61d
    Model: TI AM5728 IDK
    Board: UNKNOWN(BeagleBoard X15?) REV UNKNOWN
    initcall: 8080f221
    DRAM:  initcall: 80800af5
    >>sdram_init()

    So it looks like the Board parameter is not set right. Do you know where I can change it?
    Just hardcoding it on line 76 of board.c seems for me not as the proper solution.

    - Also u-boot prints:

    bind node cpus
    Device 'cpus' has no compatible string

    Could this be a problem?

    - Are there any additional configuration needed? clock drivers? my config is based on the am57xx_evm_defconfig.

    Best regards,

    Guy

  • Hi Guy,

    Guy Bilgerig said:
    So I set CONFIG_DRA7_MPU_OPP_OD. And added a debug() function to board/ti/am57xx/board.c:get_voltrail_opp() which is called three times for I assume it is the arch/arm/cpu/armv7/omap5/fdt.c:ft_opp_clock_fixups. But it is never called for the VOLT_MPU. Do I need also to adapt other sources files?

    Actually I see that there is no option to set OPP_OD (or OPP_HIGH) in u-boot. To set OPP_OD we should use CTRL_CORE_STD_FUSE_OPP_VMIN_MPU_3/0x4A003B24 register, but I can not see this register usage in u-boot. We have only OPP_NOM:

    /* STD_FUSE_OPP_VMIN_MPU_2 */
    #define STD_FUSE_OPP_VMIN_MPU_NOM    (DRA752_EFUSE_BASE + 0x1B20)

    #define VDD_MPU_DRA7_NOM    1150

      struct vcores_data am572x_idk_volts = {
        .mpu.value[OPP_NOM]    = VDD_MPU_DRA7_NOM,
        .mpu.efuse.reg[OPP_NOM]    = STD_FUSE_OPP_VMIN_MPU_NOM,
        .mpu.efuse.reg_bits     = DRA752_EFUSE_REGBITS,

    This is done as we have the below requirement in AM572x DM:

    5.5.2 Voltage And Core Clock Specifications  - OPP_OD and OPP_HIGH are not applicable during boot (before AVS is enabled). OPP_OD and OPP_HIGH can be selected after AVS is enabled. For all OPPs, AVS must be enabled to avoid impact on device reliability, lifetime POH (Power on Hour), and device power.

    AVS is enabled in linux kernel, so you should switch to OPP_OD in linux kernel (after AVS is enabled) or in user space.


    Note also that AVS/SmartReflex usage is highly required, see the below e2e thread:

    I will also check regarding your other questions and come back to you when I have something.

    Regards,
    Pavel

  • Guy,

    In u-boot, Cortex-A15 MPU clock frequency (1000MHz) is setup in DPLL_MPU registers in below file and function:

    u-boot/arch/arm/cpu/armv7/omap-common/clocks-common.c -> configure_mpu_dpll()

    And the voltage that correspond to that 1000MHz frequency and OPP (OPP_NOM) is setup in below file and function:

    u-boot/arch/arm/cpu/armv7/omap-common/clocks-common.c -> scale_vcores()

    opp = get_voltrail_opp(VOLT_MPU);
    debug("mpu: %d\n", vcores->mpu.value[opp]);
    do_scale_vcore(vcores->mpu.addr, vcores->mpu.value[opp], vcores->mpu.pmic);
    /* Configure MPU ABB LDO after scale */
    abb_setup(vcores->mpu.efuse.reg[opp],
    (*ctrl)->control_wkup_ldovbb_mpu_voltage_ctrl,
    (*prcm)->prm_abbldo_mpu_setup,
    (*prcm)->prm_abbldo_mpu_ctrl,
    (*prcm)->prm_irqstatus_mpu_2,
    vcores->mpu.abb_tx_done_mask,
    OMAP_ABB_FAST_OPP);

    You might reuse that approach in linux kernel and/or user space. I think it will be more easy to apply these settings (change DPLL_MPU registers for 1176MHz and PMIC for OPP_OD) in user space with omapconf tool. See the below wiki for more info regarding omapconf tool:

    github.com/.../wiki

    Regards,
    Pavel
  • Guy Bilgerig said:

    - Anyhow I also got a strange output on the first lines of u-boot:

    U-Boot 2016.05-00319-ge811b89-dirty (Jun 06 2017 - 17:50:47 +0200)
    
    initcall: 8080f1fd
    U-Boot code: 80800000 -> 80864F50  BSS: -> 808B4554
    initcall: 80800b31
    CPU  : DRA752-GP ES2.0
    initcall: 8080f61d
    Model: TI AM5728 IDK
    Board: UNKNOWN(BeagleBoard X15?) REV UNKNOWN
    initcall: 8080f221
    DRAM:  initcall: 80800af5
    >>sdram_init()

    So it looks like the Board parameter is not set right. Do you know where I can change it?
    Just hardcoding it on line 76 of board.c seems for me not as the proper solution.

    There is EEPROM memory attached to I2C of AM572x GP EVM and IDK EVM. Each of the AM572x IDK EVMs has a unique serial number. This serial number is printed on a sticker attached to the IDK and it is programmed into a SEEPROM memory device connected to the AM5728 processor over the I2C bus. The SEEPROM also contains board details such as board type, version, configuration, and so on.

    In AM572x GP EVM I have:

    U-Boot 2016.05-g6c5519b6fc (Dec 14 2016 - 20:19:24 -0500)

    CPU  : DRA752-GP ES1.1
    Model: TI AM5728 BeagleBoard-X15
    Board: AM572x EVM REV A.20

    If you do not have EEPROM on your custom board, remove that functionality, see board.c do_board_detect() function. See also the below e2e threads:

    Regards,
    Pavel

  • Guy Bilgerig said:

    - Also u-boot prints:

    bind node cpus
    Device 'cpus' has no compatible string

    Can you provide me the full u-boot boot up log? I need to see at which stage exactly this message come up.

    Guy Bilgerig said:
    - Are there any additional configuration needed? clock drivers? my config is based on the am57xx_evm_defconfig.

    For building u-boot, am57xx_evm_defconfig is correct.

    Regards,
    Pavel

  • Hi,

    So omapconf tool looks pretty cool for validating and manipulating the values from the userspace.. As far as I could evaluate the tool. I can just change the frequency from the user space by i.e. omapconf write 0x4A00516C 0x81F409. Which is actually quite dirty because I haven't check the locking procedure.

    When I change CM_CLKSEL_DPLL_MPU in clocks-common.c and enable DCC_en to get higher frequencies than 1.4GHz  the kernel does not start anymore. Does setting DCC_EN requires some extra configurations before?

    Regards Guy

    (regarding the other issue.. I could solve the board detection and this solved also the bind node cpu issue.)

    omapconf write 0x4A00516C

  • Guy,

    For Cortex-A15 frequencies higher than 1.4GHz (also higher than 1.176GHz) you should switch to OPP_HIGH.

    Note also that when DCC_EN = 1, the DPLL output clock formula is different:

    Fdpll = Fref x (M/(N+1))

    when DCC_EN = 0 :

    Fdpll = Fref x 2 x M / (N+1)


    You can also see how DCC_EN is handled in GEL file:

    ccsv6/ccs_base/emulation/boards/am572x/gel/AM572x_prcm_config.gel

    /******************************************************************************
    * dpll_a15_opp_config() : Cortex A15 DPLL OPP configurations
    ******************************************************************************/
    dpll_a15_opp_config(uint32_t OPP, uint32_t DEVICE_TYPE)
    {
    uint32_t dpll_m, dpll_n, divm2, dcc_en;
    dcc_en = 0;

    GEL_TextOut("\tCortex A15 DPLL OPP %d clock config is in progress...\n",,,,, OPP);

    if(OPP_HIGH == OPP)
    {
    //1500MHz at 20MHz sys_clk
    dpll_m = 600;
    dpll_n = 7;
    divm2 = 1;
    dcc_en = 1;
    }
    .....


    Regards,
    Pavel
  • Hi Pavel,

    Ohh of course. I had to switch the OPP_HIGH. Thank you for all the help.

    For somebody who wants to know the final solution. I adapted the u-boot/arch/arm/cpu/armv7/omap-common/clocks-common.c – scale_vcores function (MPU beginning part):

    …
            //force OPP HIGH for MPU
            //opp = get_voltrail_opp(VOLT_MPU);
            opp = OPP_HIGH;
            debug("mpu: %d\n", vcores->mpu.value[opp]);
            do_scale_vcore(vcores->mpu.addr, vcores->mpu.value[opp],
                           vcores->mpu.pmic);
    …
    

    and u-boot/arch/arm/cpu/armv7/omap-common/clocks-common.c – configure_mpu_dpll function:

    …
    void configure_mpu_dpll(void)
    {
            struct dpll_params params;
            struct dpll_regs *mpu_dpll_regs;
    
            u32 omap_rev;
            omap_rev = omap_revision();
            debug("omap rev: %u\n",omap_rev);
    
            //activate bypass mode
            bypass_dpll((*prcm)->cm_clkmode_dpll_mpu);
    
            //set DCC_en in CM_CLKSEL_DPLL_MPU
            mpu_dpll_regs = (struct dpll_regs *)((*prcm)->cm_clkmode_dpll_mpu);
            setbits_le32(&mpu_dpll_regs->cm_clksel_dpll, CM_CLKSEL_DCC_EN_MASK);
    
            //set fdpll to 1.5 GHz = 20MHz * 600 / (7+1)
            //params = (dpll_params) {600, 7, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1};
            params.m = 600;
            params.n = 7;
            params.m2 = 1;
            params.m3 = 1;
            params.m4_h11 = -1;
            params.m5_h12 = -1;
            params.m6_h13 = -1;
            params.m7_h14 = -1;
            params.h21 = -1;
            params.h22 = -1;
            params.h23 = -1;
            params.h24 = -1;
    
            do_setup_dpll((*prcm)->cm_clkmode_dpll_mpu, &params, DPLL_LOCK, "mpu");
            debug("MPU DPLL locked\n");
    
    }
    …
    

    Best Regards,

    Guy