Clock control for HiKey960


I am trying to add new OPP entry (frequency and power supply) into OPP table in the device tree.
For example:

opp_table1 {
    compatible = "operating-points-v2";
    linux,phandle = <0x12>;
    phandle = <0x12>;
   opp132 {
	clock-latency-ns = <0x493e0>;
	opp-hz = <0x0 0x89544000>;
	opp-microvolt = <0x10c8e0>;

After kernel re-compilation the new frequency appears in the /sys/devices/system/cpu/cpufreq/policy2/scaling_available_frequencies but whenever I am trying to set the new frequency, the systems sets a different one (which is closer to the values provided by the original device tree).

So I am taking a look into clk-hi3660-stub.c to have more details about the driver. Unfortunately, the driver seems a bit black box as they use mailbox to set up the frequency value:

if (stub_clk->id < HI3660_CLK_STUB_NUM) {
	stub_clk->msg[0] = stub_clk->set_rate_cmd;
	stub_clk->msg[1] = rate / MHZ;

	pr_debug("%s: set_rate_cmd[0] %x [1] %x\n", __func__, stub_clk->msg[0], stub_clk->msg[1]);

	mbox_send_message(chan->mbox, stub_clk->msg);

Could someone confirm that the desire rate is sent by stub_clk->rate/MHz and then this value is processed by the hardware.

I am interested in the possible dividers or multipliers of the CPU frequency. If you can navigate me a bit this will be great.

Update 1: Using the mailbox mechanism I could set only 5 supported frequencies: 903, 1421, 1805, 2112, and 2362 MHz which are already defined in the OPP table.

Hi @Roman, I don’t think you can set different CPU OPPs, except the predefined OPP “903, 1421, 1805, 2112, and 2362 MHz”. The reason is, after kernel send OPP value from application processor (AP) to MCU, the MCU firmware calculates the one lowest OPP can meet the requirement from AP side.

After MCU set the CPU frequency, it writes back the real CPU frequency value into share memory and the stub clock driver read back with below code:

100 static unsigned long hi3660_stub_clk_recalc_rate(
101                 struct clk_hw *hw, unsigned long parent_rate)                                                                                                                                                                  
102 {
103         struct hi3660_stub_clk *stub_clk =     
104                 container_of(hw, struct hi3660_stub_clk, hw);                                                                                                                                                                  
106         if (stub_clk->id < HI3660_CLK_STUB_DDR_VOTE)
107                 stub_clk->rate = readl(freq_reg + (stub_clk->id << 2)) * MHZ;                                                                                                                                                  
109         pr_debug("get rate%d;%u\n", stub_clk->id, stub_clk->rate);                                                                                                                                                             
111         return stub_clk->rate;
112 }

The MCU has encapsulated the code for CPU clock divider/multiplier, I also don’t know the related info for this.

Hello and thank you for reply @leo-yan,

Do you know if there are any debug messages from MCU?
I was trying to see printing from MCU on UART6 or debugfs, but I could not find any.

Could you also give any indication what does this MCU do exactly and how I can find this information?