Info |
---|
This page is a work in progress! |
...
Table of Contents | ||||
---|---|---|---|---|
|
Introduction
Device drivers (e.g: UART, I2C, Audio, etc.) need to know the input clock rate for the device to configure and function properly. Some device drivers only need to know the configured clock rate, while others (such as audio, display, etc) may need to change the clock rate based on the requirements, such as supporting different sampling rates, resolutions, etc.
Several Arm implementations provide the clock rate to the device drivers using non-standard AML methods, objects, and _DSD properties. The ACPI v6.5 specification. standardized this by introducing the ClockInput resource descriptor.
Code Block |
---|
ClockInput (FrequencyNumerator, FrequencyDivisor, Scale, FixedMode, ResourceSource, ˓ResourceSourceIndex) |
Examples from ACPI spec.
Case 1: Simple clock input descriptor, with a fixed frequency of 33 1/3 MHz and no Device shown as a clock source.
Code Block |
---|
ClockInput (100, 3, MHz, Fixed,,) |
Case 2: Clock input descriptor referencing a variable clock input of 19.2 kHz, with a source device and index.
...
This page captures our investigation and suggestions for using the ClockInput
resource.
Option 1: ClockInput resources and configurability with _PRS and _SRS
This approach leverages the existing _PRS and _SRS methods to get the possible clock input resources and set one of the resources based on device requirements.
An example AML implementation is given below
Code Block |
---|
Device(DEV) { ... // Possible resources for the device Name (_PRS, ResourceTemplate () { ClockInput(100000, 1, Hz, Variable, “\\_SB.PCI0.CLK4”, 3) |
SCMI Clock Driver with ClockInput resources
Code Block |
---|
Device (SCMI) { Name (_HID, "PNP####") ... } Device(I2C) { ... Name(_CLK, 13Fixed,,) // 100 KHz ClockInput(400000, 1, Hz, Fixed,,) // 400 KHz ClockInput(1000000, 1, Hz, Fixed,,) // SCMI1 clockMHz ID for I2C}) root clock Method (_CRS, 00x0, NotSerialized) { Name ( RBUF, ResourceTemplate () { ClockInput(100000, 1, Hz, Fixed,,) MEMORY32FIXED(ReadWrite, 0x30A400000x30A20000, 0x14, ) Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 67 } 69 }) // Update ClockInput with configured frequency CreateDWordField (24RBUF, 1, MHz, Variable, “\\_SB.SCMI”, _CLK) })0x08, FQN) FQN = CLK1.FQN CreateWordField (RBUF, 0x06, FQD) FQD = CLK1.FQD Return(RBUF) } Method (_SRS, 1, NotSerialized) { // only ClockInput is configurable, ignore the rest of the resources CreateDWordField (Arg0, 0x08, FQN) CLK1... }FQN = FQN CreateWordField (Arg0, 0x06, FQD) CLK1.FQD = FQD } |
ACPI ClockInput resources with variable clock rate would require support from the operating system. Clock drivers and clock framework support will be required from OS.
ClockInput resources with _PRS, SRS, and _CRS
Another approach is to support ClockInput resources from AML without requiring operating system infrastructures.
Code Block |
---|
CLK: Method(GCLK, ...)} |
Pros:
No extra AML methods are required to configure the clocks.
No additional OS infrastructure support is required (except support for ClockInput resources, _PRS, _SRS, etc.)
Cons:
_PRS and _SRS are generally used for full resource configuration at device enumeration and dynamic configuring clock input using _SRS might not be aligned with the original design intent.
ClockInput resource control with multiple clock inputs is tricky as we don’t have any unique identifier for clocks. (except resource label and index which are optional for Fixed clocks)
There are potentially a few extra changes required at the spec to support this.
Add clarification to spec. around the use of _SRS
Add identifier to ClockInput resource to support multiple clock inputs
Add descriptor name to ClockInput resource to select the resource from the resource buffer.
Linux Kernel Prototype
...
Option 1: Devices directly use the ACPI resources to get and set clock inputs.
Option 2: Add an
acpi-clk
device to the clock framework that uses the clock resources to get and set rates.
Kernel Changes
Adding ClockInput Resource support to Linux ACPICA
Support ClockInput Resources
Device driver could use the above framework to get and select the clock rate
Code Block |
---|
// get the current clock rate from _CRS
acpi_freq = acpi_dev_get_clock_input_rate(ACPI_COMPANION(&pdev->dev), 0);
// request 40KHz clock rate for the device
// acpi clock framework will first look for a matching clock input from _PRS and
// invokes _SRS to configure the clock
ret = acpi_dev_set_clock_input_rate(ACPI_COMPANION(&pdev->dev), 400000, 0); |
Option 2: ClockInput resources with a standard clock resource provider
This option uses a standard clock controller known to the kernel.
AML methods for the standard clock provider can be standardized and the kernel can use that to provide the clock bindings required for the devices.
Code Block |
---|
Device (CLK) { Name (_HID, "PNP####") // Standard clock device with defined AML interfaces ... // Get Clock Rate Method(SCLK, _GCR, ) { ...) } // Set Clock Rate DEV: _PRS: ClockInput(FREQ_1, 1, MHz, Variable, CLK,) ClockInput(FREQ_2, 1, MHz, Variable, CLK, )Method(_SCR, ) { ... } // Set State (enable/disable etc.) Method(_SET, ) { ... } } Device(DEV) { ... Method (_CRS, 0, NotSerialized) { ... ClockInput (FREQ_324, 1, MHz, Variable, CLK“\\_SB.CLK”, 1) } _CRS: freq_num, freq_div = CLK.GCLK(...) ClockInput(freq_num, freq_div, ... , Variable, "//SB.CLK", ) _SRS: ... local0 = decode(Arg0) CLK.SCLK(local0) |
Challenges
...
ClockInput resource doesn't have resource names so we cannot index them for modification.
...
...
} |
This option would be able to support multiple clock input resources and allows supporting other clock control methods beyond setting the clock rate.
Kernel only has to provide the AML binding for clock resources and the clock management will be done from AML.
Option 3: ClockInput resources with SCMI clock provider
The above two options used the AML-based approach to configure the clock to avoid adding overhead to the kernel. However, this option requires SCMI driver support at the kernel side and uses that to provide clock control.
Code Block |
---|
Device (SCMI) {
Name (_HID, "PNP####") // SCMI Device ID
...
// Objects and Methods to provide SCMI transport channel
// needs to be defined for the device
}
Device(DEV) {
...
Method (_CRS, 0, NotSerialized)
{
...
ClockInput (24, 1, MHz, Variable, “\\_SB.SCMI”, 1)
}
...
} |
SCMI supports multiple APIs for clock (e.g: enable/disable clock, get/set rate, get notification for clock change, etc.). See the SCMI specification here https://developer.arm.com/documentation/den0056/e/?lang=en
This approach would avoid having to implement the clock framework in AML and platform vendors can implement the clock control in the firmware that can be driven through the SCMI protocol.
Linux already has support for SCMI driver and adding the binding for ACPI support wouldn’t require significant changes.
Option 4: Clock Framework support at Kernel
This would require the kernel to provide a clock framework and platform vendors to provide clock drivers.
Code Block |
---|
Device (GCCP}) {
Name (_HID, "QCOMXXXX")
...
}
Device(DEV) {
...
Method (_CRS, 0, NotSerialized)
{
...
ClockInput (24, 1, MHz, Variable, “\\_SB.GCCP”, 1)
}
...
} |
ACPICA
ClockInput resource is supported by Intel ACPICA.