Mainline:Broadcom Kona/Timers: Difference between revisions
Line 138: | Line 138: | ||
** Calls <code>timers_init</code>, which 1. sets up clock rates, 2. calls <code>kona_timer_config</code> on the GP timer from the struct; | ** Calls <code>timers_init</code>, which 1. sets up clock rates, 2. calls <code>kona_timer_config</code> on the GP timer from the struct; | ||
*** Sets a callback function, <code>gptimer_interrupt_cb</code> to call on timer interrupt. | *** Sets a callback function, <code>gptimer_interrupt_cb</code> to call on timer interrupt. | ||
Downstream driver: https://github.com/knuxdroid/android_kernel_samsung_baffinlite/blob/cm-12.1/arch/arm/plat-kona/kona_timer.c |
Revision as of 09:51, 21 January 2025
The Kona platform has three timers:
- HUB/AON
- Slave/Peripheral
- (BCM23550 only) Core
The driver for the timers is split up into three files:
arch/arm/plat-kona/kona_timer.c
arch/arm/plat-kona/timer.c
arch/arm/plat-kona/localtimer.c
- setup for the local tick timer (local, I assume, means "CPU-local" - meaning each channel belongs to a different CPU core)
All timers use the same driver.
Timer operation
Each timer device manages 4 channels. Each channel has its own separate IRQ.
The timer operates in oneshot mode, meaning that it can be programmed to generate a clock event once (as opposed to PERIODIC mode which generates periodical events). See https://elixir.bootlin.com/linux/v6.10.6/source/include/linux/clockchips.h#L22. Downstream has some code to emulate periodic timers.
Due to hardware limitations, there is a delay of 5 clock cycles when writing values to the timers. Downstream claims that this is only true for HUB timer, but applies the mitigation to all timers. (https://github.com/knuxdroid/android_kernel_samsung_baffinlite/blob/cm-12.1/arch/arm/plat-kona/localtimer.c#L176-L179)
Timer rate
The Hub/AON timer uses the TIMERS
clock, which can be set to either 32KHz or 1MHz. (Downstream also claims it can use 19.5MHz, but the clock doesn't have the setting for it; if it did, it would have the selector value of 2. I assume either kona_timer.c or clock driver is mistaken.)
Getting the counter value
In 64-bit mode: Read the value of KONA_GPTIMER_STCLO_OFFSET
(0x04
) to get the low 32 bits, and KONA_GPTIMER_STCHI_OFFSET
(0x08
) to get the high 32 bits, then combine to get the full value.
In 32-bit mode: Read the value of KONA_GPTIMER_STCLO_OFFSET
(0x04
).
It's worth noting that despite the timer being capable of counting to 64 bits, the downstream driver overrides this for the hub timer. The reasoning is that the match values used for each channel are 32-bit. (Slave/Peripheral does not use channels? TODO) (https://github.com/knuxdroid/android_kernel_samsung_baffinlite/blob/cm-12.1/arch/arm/plat-kona/timer.c#L137-L142)
Switching to 32-bit mode is done by writing to the CHIPREG register. For Rhea, Hawaii and Java, this is done as such: (https://github.com/knuxdroid/android_kernel_samsung_baffinlite/blob/cm-12.1/arch/arm/plat-kona/kona_timer.c#L322-L326)
/* Configure KONA Timer count in 32 bit mode */
writel(0x0, KONA_CHIPREG_VA + CHIPREG_HUB_TIMER_WIDTH_OFFSET);
For Capri, this is done as such: (https://github.com/ghsr/android_kernel_samsung_i9152/blob/android-7.1/arch/arm/plat-kona/kona_timer.c#L268-L271)
/* Use 32bit mode timer */
reg = readl(KONA_CHIPREG_VA + CHIPREG_ARM_PERI_CONTROL_OFFSET);
reg &= ~(CHIPREG_ARM_PERI_CONTROL_SLV_TIMER_64BITMODE_MASK |
CHIPREG_ARM_PERI_CONTROL_HUB_TIMER_64BITMODE_MASK);
writel(reg, KONA_CHIPREG_VA + CHIPREG_ARM_PERI_CONTROL_OFFSET);
Note that on Capri, it seems to set both the Hub and the Slave/Peripheral timer to 32-bit mode, whereas on Rhea/Hawaii/Java only Hub timer is configured (Slave/Peripheral timer has a separate width offset at CHIPREG_SLAVE_TIMER_WIDTH_OFFSET
).
Starting the counter
Local tick timer
The local tick timer refers to the timer the channels of which are used as CPU-local timers. In downstream, it's set up in arch/arm/plat-kona/localtimer.c
.
Timer regs
KONA_GPTIMER_STCS (0x00
)
Settings register. Contains controls for the timer's state.
Name | Bit | Description |
---|---|---|
STCS_TIMER_MATCH
|
3:0 | When the match registers STCM{0,3} match the counter, the interrupt for the matching channel is raised and a bit corresponding to the channel is set in this register. - 0b0001 - channel 0 matches- 0b0010 - channel 1 matches- 0b0100 - channel 2 matches- 0b1000 - channel 3 matches
|
STCS_COMPARE_ENABLE
|
7:4 | Enable compare (match) on the specified channel(s). When this bit is set, the value of the STCM{0,3} register will be used for a match. - 0b0001 - enable compare for channel 0- 0b0010 - enable compare for channel 1- 0b0100 - enable compare for channel 2- 0b1000 - enable compare for channel 3
|
STCS_COMPARE_ENABLE_SYNC
|
11:8 | Sync bit for COMPARE_ENABLE. Same layout as the above. |
STCM{0,3}_SYNC
|
15:12 | Sync bit for STCM{0,3} value being set. |
Reserved | 31:16 | Reserved |
KONA_GPTIMER_STCLO (0x04
)
Contains the lower 32 bits of the counter value.
Name | Bit | Description |
---|---|---|
STCLO | 31:0 | Lower 32 bits of the counter value. In 32-bit mode, this is the only register used for the counter value. |
KONA_GPTIMER_STCHI (0x08
)
Contains the upper 32 bits of the counter value.
Name | Bit | Description |
---|---|---|
STCHI | 31:0 | Upper 32 bits of the counter value. Only used in 64-bit mode. |
KONA_GPTIMER_STCM{0,3} (0x0c
, 0x10
, 0x14
, 0x18
)
Match registers for channels 0-3.
Name | Bit | Description |
---|---|---|
STCM{0,3} | 31:0 | 32-bit time value for timer match. When the counter matches this value, the interrupt for the channel is raised and the bit corresponding to the triggered timer number is set in STCS_TIMER_MATCH. |
Timer initialization in downstream
- Starts in
hawaii_timer_init
in hawaii.c (https://github.com/knuxdroid/android_kernel_samsung_baffinlite/blob/cm-12.1/arch/arm/mach-hawaii/hawaii.c#L176-L208) - This sets up a GP timer setup struct and calls
gp_timer_init
, which is placed inarch/arm/plat-kona/timer.c
(https://github.com/knuxdroid/android_kernel_samsung_baffinlite/blob/cm-12.1/arch/arm/plat-kona/timer.c#L262C1-L305C2)- Calls
timers_init
, which 1. sets up clock rates, 2. callskona_timer_config
on the GP timer from the struct;- Sets a callback function,
gptimer_interrupt_cb
to call on timer interrupt.
- Sets a callback function,
- Calls
Downstream driver: https://github.com/knuxdroid/android_kernel_samsung_baffinlite/blob/cm-12.1/arch/arm/plat-kona/kona_timer.c