Mainline:Broadcom Kona/Clocks: Difference between revisions

import from my personal docs
 
 
(3 intermediate revisions by the same user not shown)
Line 7: Line 7:
* Figure out how voltage and peripheral voltage settings work, and what they affect
* Figure out how voltage and peripheral voltage settings work, and what they affect
* Document connection to the power/PI manager
* Document connection to the power/PI manager


-----
-----
Line 41: Line 40:
=== Policies ===
=== Policies ===


Each CCU has 4 policies. Policies control whether specific clocks are enabled, as well as the frequencies of specific clocks and some voltages, as seen in the frequency/voltage control sections below.
Each CCU has 4 policies. Policies control whether specific clocks can be gated (enabled/disabled), as well as the frequencies of specific clocks and some voltages, as seen in the frequency/voltage control sections below.


According to the mainline driver, these policies are: "Deep Sleep", "Economy", "Normal" and "Turbo", where policy 2 is the default (question is, is it 2 counting from 1 or 0?).
According to the mainline driver, these policies are: "Deep Sleep", "Economy", "Normal" and "Turbo", where policy 2 is the default (question is, is it 2 counting from 1 or 0?).
Line 49: Line 48:
Before making any changes to the policy or one of the controls below, the policy engine must first be stopped. Restarting the policy engine will apply the changes to it.
Before making any changes to the policy or one of the controls below, the policy engine must first be stopped. Restarting the policy engine will apply the changes to it.


Starting the policy engine is done by writing to the policy control offset, either: * the ATL (active load) bit for synchronous requests (we wait for the frequency and voltage to stabilize); * or clearing it for asynchronous requests, going into target mode (where the voltage ramps in the background, then the target load is copied to the active load triggering a frequency change).
Starting the policy engine is done by writing to the policy control offset, either:
 
* the ATL (active load) bit for synchronous requests (we wait for the frequency and voltage to stabilize);
* or clearing it for asynchronous requests, going into target mode (where the voltage ramps in the background, then the target load is copied to the active load triggering a frequency change).


The above is more or less abridged from the mainline driver's docs:
The above is more or less abridged from the mainline driver's docs:


<source lang="c">        /*
<syntaxhighlight lang="c">        /*
         * If it's a synchronous request, we'll wait for the voltage
         * If it's a synchronous request, we'll wait for the voltage
         * and frequency of the active load to stabilize before
         * and frequency of the active load to stabilize before
Line 67: Line 69:
         *  
         *  
         * Note, we do NOT read-modify-write this register.  
         * Note, we do NOT read-modify-write this register.  
         */    </source>
         */    </syntaxhighlight>
and is somewhat related to downstream's <code>ccu_set_policy_ctrl</code>.
and is somewhat related to downstream's <code>ccu_set_policy_ctrl</code>.


Line 90: Line 92:
Effectively, a frequency table looks sort of like this (written in a simplified, Python-like syntax for easier understanding):
Effectively, a frequency table looks sort of like this (written in a simplified, Python-like syntax for easier understanding):


<source lang="python">ccu_freq_list0 = [26000000,26000000,26000000,26000000]
<syntaxhighlight lang="python">ccu_freq_list0 = [26000000,26000000,26000000,26000000]
ccu_freq_list1 = [52000000,52000000,52000000,5200000]
ccu_freq_list1 = [52000000,52000000,52000000,5200000]
...
...
Line 98: Line 100:
     ccu_freq_list0, ccu_freq_list1, ..., ccu_freq_list6
     ccu_freq_list0, ccu_freq_list1, ..., ccu_freq_list6
]
]
# actual number of frequencies in table is specific to each CCU</source>
# actual number of frequencies in table is specific to each CCU</syntaxhighlight>
This is used by bus clocks - which frequencies correspond to which clocks is shown by the <code>.freq_tbl_index</code> member of the clock info struct. Clocks that have this value set to >= 0 specify that they're connected to that specific frequency; clocks with a value of -1 use a source clock or internal dividers instead.
This is used by bus clocks - which frequencies correspond to which clocks is shown by the <code>.freq_tbl_index</code> member of the clock info struct. Clocks that have this value set to >= 0 specify that they're connected to that specific frequency; clocks with a value of -1 use a source clock or internal dividers instead.


<source lang="python"># A bus clock will perform an operation like so:
<syntaxhighlight lang="python"># A bus clock will perform an operation like so:


current_policy = ccu.get_active_policy()  # CCU policy ID, from 0 to 3
current_policy = ccu.get_active_policy()  # CCU policy ID, from 0 to 3
freq_id = ccu.get_freq_policy(current_policy)  # read frequency ID (aka which table to use) for the current policy
freq_id = ccu.get_freq_policy(current_policy)  # read frequency ID (aka which table to use) for the current policy
ccu.freq_table[freq_id][bus_clk.freq_tbl_index]</source>
ccu.freq_table[freq_id][bus_clk.freq_tbl_index]</syntaxhighlight>
 
=== Core clocks and freq policy ===
=== Core clocks and freq policy ===


The second user of this is core clocks - in the core CCU, the frequency policy is used to determine which clock source is used for the CPU - see "Core clocks" section for details. ### PI manager and freq policy
The second user of this is core clocks - in the core CCU, the frequency policy is used to determine which clock source is used for the CPU - see "Core clocks" section for details.
 
=== PI manager and freq policy ===


The PI manager is also able to set this through the <code>pi_set_ccu_freq</code> function, which is only used if <code>CONFIG_CHANGE_POLICY_FOR_DFS</code> is not defined (and it is not defined in the Grand Neo downstream kernel). See "Power Islands" section.
The PI manager is also able to set this through the <code>pi_set_ccu_freq</code> function, which is only used if <code>CONFIG_CHANGE_POLICY_FOR_DFS</code> is not defined (and it is not defined in the Grand Neo downstream kernel). See "Power Islands" section.
Line 139: Line 144:
* Every PI also has its own OPPs which get converted to CCU frequency IDs as per the <code>.opp_info</code> tables
* Every PI also has its own OPPs which get converted to CCU frequency IDs as per the <code>.opp_info</code> tables
* PI reset offsets are located in the root CCU
* PI reset offsets are located in the root CCU


-----
-----
Line 158: Line 162:
* <code>.trig</code>: <code>TRIGGER()</code>, in order: <code>.clk_div.div_trig_offset</code>, <code>.div_trig_mask</code> (->bit)
* <code>.trig</code>: <code>TRIGGER()</code>, in order: <code>.clk_div.div_trig_offset</code>, <code>.div_trig_mask</code> (->bit)
* <code>.policy</code>: <code>POLICY()</code>, in order: the CCU's <code>policy_mask{1/2}_offset</code> (depending on <code>.mask_set</code>), <code>.policy_bit_mask</code> (->bit)
* <code>.policy</code>: <code>POLICY()</code>, in order: the CCU's <code>policy_mask{1/2}_offset</code> (depending on <code>.mask_set</code>), <code>.policy_bit_mask</code> (->bit)


-----
-----


TPIU is some CoreSight thing. PTI is likely MIPS PTI (''Parallel Trace Interface'').
TPIU is some CoreSight thing. PTI is likely MIPS PTI (''Parallel Trace Interface'').