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 add support for new am335x core frequency using Sitara SDK 7.0

Hey all,

I know it is possible to set the core clk frequency below the OPP50 spec, but I can not figure out how to do it.

Does anybody know where inside the omap/am335x linux "driver" source code (using SDK 7.0) these registers and values are being hard coded as OPP options? Or how to go about solving this in general?

I realize that it might be more complicated than changing the values of one or two #defines, but any help is appreciated.

Thanks,

Nolan

  • Hi Nolan,

    Please refer the AM335x SDK location for OPP definitions.

    ti-sdk-am335x-evm/board-support/linux-3.2.0-psp04.06.00.11/arch/arm/mach-omap2/opp3xxx_data.c

  • Hi Nolan,

    The OPP value is set during SPL (MLO) execution. Please check the am33xx_spl_board_init() function inside <u-boot_dir>/board/ti/am335x/board.c.

    Please also take a look at the StarterWare "demo" project for an example, more specifically the demoDvfs.c file.

    Best regards,
    Miroslav

  • Also check the <linux_dir>/arch/arm/mach-omap2/opp3xxx_data.c file where you can add your desired frequency:

    #define AM33XX_VDD_MPU_OPP50_UV4 910000
    static struct omap_opp_def __initdata am33xx_opp_def_list[] = {
    /* MPU OPP - 1MHz */
    OPP_INITIALIZER("mpu", true, 1000000, AM33XX_VDD_MPU_OPP50_UV),
    /* MPU OPP - 5MHz */
    OPP_INITIALIZER("mpu", true, 5000000, AM33XX_VDD_MPU_OPP50_UV),
    /* MPU OPP - 8MHz */
    OPP_INITIALIZER("mpu", true, 8000000, AM33XX_VDD_MPU_OPP50_UV),
    /* MPU OPP - 10MHz */
    OPP_INITIALIZER("mpu", true, 10000000, AM33XX_VDD_MPU_OPP50_UV),
    /* MPU OPP - 100MHz */
    OPP_INITIALIZER("mpu", true, 100000000, AM33XX_VDD_MPU_OPP50_UV),
    };

    Then you can use /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed to set the frequency.

    I know this is the case for kernel 3.2, but I'm not sure for 3.12, so I'll try to ask someone from the factory team to confirm this.

    Best regards,
    Miroslav

  • Thanks for your responses.

    See, I looked at opp3xxx_data.c and that's why I am confused. I don't actually think the tables defined in there are being used at all. Even when i completely empty the tables, my kernel builds and runs just the same. Also, the values I currently observe with "cat scaling_available_frequencies" are not listed in those tables. I'll keep searching.

    Thanks,

    Nolan

  • Nolan,

    I got a reply from the factory team that this has been moved to the device tree for the 3.12 kernel.

    Here is how to create custom OPPs:

    Edit these two structures inside <linux>/arch/arm/boot/dts/am33xx.dtsi:

    Add your custom OPP to the "operating-points" part of this structure:

        cpus {
            #address-cells = <1>;
            #size-cells = <0>;
            cpu@0 {
                compatible = "arm,cortex-a8";
                device_type = "cpu";
                reg = <0>;

                /*
                 * To consider voltage drop between PMIC and SoC,
                 * tolerance value is reduced to 2% from 4% and
                 * voltage value is increased as a precaution.
                 */
                operating-points = <
                    /* kHz    uV */
                    1000000 1351000
                    800000    1285000
                    720000  1285000
                    600000  1225000
                    500000  1125000
                    300000  1125000
                    275000  1125000
                >;

                voltage-tolerance = <2>; /* 2 percentage */

                platform-opp-modifier = <&mpu_opp_modifier>;

                clocks = <&dpll_mpu_ck>;
                clock-names = "cpu";

                clock-latency = <300000>; /* From omap-cpufreq driver */
            };
        };

    Add your custom OPP to the "opp-modifier" part of this structure:

            efuse_sma: efuse@0x44e107fc {
                compatible = "ti,opp-omap-am3352";
                reg = <0x44e107fc 0x04        /* EFUSE_SMA */
                       0x44e10600 0x04>;    /* DEVICE_ID */

                ti,efuse-bit-enable-low;

                mpu_opp_modifier: mpu_opp_modifier {
                    opp-modifier = <
                    /* kHz     Rev                offset    mask */
                    1000000     OPP_REV(2,1)            0    AM33XX_EFUSE_SMA_OPP_NITRO_1GHZ_BIT
                    800000     OPP_REV(2,1)            0    AM33XX_EFUSE_SMA_OPP_TURBO_800MHZ_BIT
                    720000     OPP_REV(2,1)            0    AM33XX_EFUSE_SMA_OPP_120_720MHZ_BIT
                    600000     OPP_REV(2,1)            0    AM33XX_EFUSE_SMA_OPP_100_600MHZ_BIT
                    300000     (OPP_REV(2,0) | OPP_REV(2,1))     0    0
                    1000000     OPP_REV(2,0)            0    0
                    800000     OPP_REV(2,0)            0    0
                    720000     (OPP_REV(1,0) | OPP_REV(2,0))     0    0
                    600000     (OPP_REV(1,0) | OPP_REV(2,0))    0    0
                    500000     (OPP_REV(1,0))            0    0
                    275000     (OPP_REV(1,0))            0    0
                    >;
                };
            };

    Please note that there is an efuse check to determine if the frequency is supported. You may need to use an already existing (defined inside <linux>/include/dt-bindings/opp/am33xx.h) EFUSE value (for example AM33XX_EFUSE_SMA_OPP_100_600MHZ_BIT) in order for the efuse check to pass. You may also try to use NULL for the efuse field, but I was told this doesn't always work.

    Best regards,
    Miroslav

  • Miroslav,


    Thank you. Even though I still am not sure how the kernel knows how to configure the actual clock frequency, this seems to work! Adding my new freq to the opp-modifier list doesn't seem to be necessary, though.

    Thanks,

    Nolan

  • Nolan, 

    What operating frequencies have achieved and what exactly did you add to the dtsi file? 

    Thanks,
    Matt S. 

  • Matthew,

    I  actually removed the opp-modifier table from my device tree for now. Along with doing that, I am able to add any opp tuple to the opp table in the device tree and the kernel seems to configure it. For example, running at 50MHZ draws less current than at 100MHZ , which draws less than at 150MHZ, and so on. (For testing, I'm using the same voltage values for each opp).

    Having said that, I'm not sure how the kernel is actually calculating the clock control register values. At first I assumed that discrete opp values were being defined somewhere, but that seems to not be the case. I even tested using an opp of 1 KHz just to see what would happen. The kernel struggled to finish booting and the uart interface was really delayed, but it worked. The point is, I'm not sure what kind of rounding is going on between user defined opp frequency values and the real mpu frequency that gets set. I wish I knew how to measure or locate the actual mpu frequency.

    Cheers,

    Nolan

  • Thanks for the info, but I'm not seeing much if any reduction in current when I change the clock rate, I am measuring when the kernel is at idle. What kind of changes are you seeing?

    Here is my opp table. 

    	cpus {
    		#address-cells = <1>;
    		#size-cells = <0>;
    		cpu@0 {
    			compatible = "arm,cortex-a8";
    			device_type = "cpu";
    			reg = <0>;
    
    			/*
    			 * To consider voltage drop between PMIC and SoC,
    			 * tolerance value is reduced to 2% from 4% and
    			 * voltage value is increased as a precaution.
    			 */
    			operating-points = <
    				/* kHz    uV */
    				1000000 1351000
    				800000	1285000
    				720000  1285000
    				600000  1225000
    				500000  1125000
    				300000  1125000
    				275000  1125000
    				100000  950000
                    50000   950000
    			>;
    
    			voltage-tolerance = <2>; /* 2 percentage */
    
    			platform-opp-modifier = <&mpu_opp_modifier>;
    
    			clocks = <&dpll_mpu_ck>;
    			clock-names = "cpu";
    
    			clock-latency = <300000>; /* From omap-cpufreq driver */
    		};
    	};
    

    I left the opp-modifier table in place and added new lines for the operating points, should I remove it? 
    I'm using /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed to change the clock rate, is that correct? I do see a reduction in speed (calculating Fibonacci series) when I change it so I assume it's working.

    I'm measuring total board power of a Beaglebone Black and looking to get down to around 550mW at idle with a connected Ethernet link.

    Thanks,
    Matt S. 

  • Matt,

    It sounds like it might be working. In idle mode I only observe a difference of about 0.2mA every 50MHz. I think this is because MPU PLL is being bypassed. When I disable idle mode, the differences are much greater.

    Cheers,

    Nolan